summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
Diffstat (limited to 'indra')
-rw-r--r--indra/CMakeLists.txt1
-rw-r--r--indra/cmake/00-Common.cmake29
-rw-r--r--indra/cmake/APR.cmake32
-rw-r--r--indra/cmake/Boost.cmake2
-rw-r--r--indra/cmake/CMakeLists.txt2
-rw-r--r--indra/cmake/DeploySharedLibs.cmake67
-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/GoogleMock.cmake27
-rw-r--r--indra/cmake/LLAddBuildTest.cmake46
-rw-r--r--indra/cmake/LLCommon.cmake4
-rw-r--r--indra/cmake/LLKDU.cmake4
-rw-r--r--indra/cmake/LLLogin.cmake7
-rw-r--r--indra/cmake/LLSharedLibs.cmake31
-rw-r--r--indra/cmake/LLTestCommand.cmake13
-rw-r--r--indra/cmake/LLWindow.cmake2
-rw-r--r--indra/cmake/Linking.cmake3
-rw-r--r--indra/cmake/Pth.cmake21
-rw-r--r--indra/cmake/Python.cmake4
-rw-r--r--indra/cmake/WebKitLibPlugin.cmake1
-rw-r--r--indra/cmake/run_build_test.py111
-rwxr-xr-xindra/develop.py1
-rw-r--r--indra/integration_tests/llui_libtest/llui_libtest.cpp4
-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/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/llaudio/llaudiodecodemgr.cpp35
-rw-r--r--indra/llaudio/llvorbisencode.cpp6
-rw-r--r--indra/llaudio/llvorbisencode.h11
-rw-r--r--indra/llcharacter/CMakeLists.txt10
-rw-r--r--indra/llcharacter/llbvhloader.cpp13
-rw-r--r--indra/llcharacter/llbvhloader.h7
-rw-r--r--indra/llcharacter/llcharacter.cpp28
-rw-r--r--indra/llcharacter/llcharacter.h21
-rw-r--r--indra/llcharacter/llgesture.cpp2
-rw-r--r--indra/llcharacter/lljointsolverrp3.cpp2
-rw-r--r--indra/llcharacter/llkeyframestandmotion.cpp2
-rw-r--r--indra/llcharacter/llvisualparam.cpp39
-rw-r--r--indra/llcharacter/llvisualparam.h16
-rw-r--r--indra/llcharacter/tests/lljoint_test.cpp246
-rw-r--r--indra/llcommon/CMakeLists.txt77
-rw-r--r--indra/llcommon/bitpack.cpp36
-rw-r--r--indra/llcommon/indra_constants.h4
-rw-r--r--indra/llcommon/linden_common.h8
-rw-r--r--indra/llcommon/llallocator.h2
-rw-r--r--indra/llcommon/llallocator_heap_profile.cpp1
-rw-r--r--indra/llcommon/llapp.h2
-rw-r--r--indra/llcommon/llapr.h20
-rw-r--r--indra/llcommon/llassettype.cpp155
-rw-r--r--indra/llcommon/llassettype.h65
-rw-r--r--indra/llcommon/llbase32.h4
-rw-r--r--indra/llcommon/llbase64.h4
-rw-r--r--indra/llcommon/llcommon.h2
-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.h2
-rw-r--r--indra/llcommon/lldate.h9
-rw-r--r--indra/llcommon/lldependencies.h2
-rw-r--r--indra/llcommon/llerror.h10
-rw-r--r--indra/llcommon/llerrorcontrol.h50
-rw-r--r--indra/llcommon/llerrorthread.h2
-rw-r--r--indra/llcommon/llevent.h10
-rw-r--r--indra/llcommon/lleventcoro.cpp129
-rw-r--r--indra/llcommon/lleventcoro.h549
-rw-r--r--indra/llcommon/lleventdispatcher.cpp133
-rw-r--r--indra/llcommon/lleventdispatcher.h130
-rw-r--r--indra/llcommon/lleventfilter.cpp149
-rw-r--r--indra/llcommon/lleventfilter.h186
-rw-r--r--indra/llcommon/llevents.cpp71
-rw-r--r--indra/llcommon/llevents.h212
-rw-r--r--indra/llcommon/llfasttimer.h143
-rw-r--r--indra/llcommon/llfile.h14
-rw-r--r--indra/llcommon/llfindlocale.h4
-rw-r--r--indra/llcommon/llfixedbuffer.h2
-rw-r--r--indra/llcommon/llfoldertype.cpp165
-rw-r--r--indra/llcommon/llfoldertype.h123
-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/llkeythrottle.h57
-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/llmd5.h2
-rw-r--r--indra/llcommon/llmemory.h2
-rw-r--r--indra/llcommon/llmemorystream.h4
-rw-r--r--indra/llcommon/llmemtype.h4
-rw-r--r--indra/llcommon/llmetrics.h2
-rw-r--r--indra/llcommon/llmortician.h2
-rw-r--r--indra/llcommon/llpreprocessor.h50
-rw-r--r--indra/llcommon/llprocesslauncher.h2
-rw-r--r--indra/llcommon/llqueuedthread.h5
-rw-r--r--indra/llcommon/llrand.h12
-rw-r--r--indra/llcommon/llrefcount.h4
-rw-r--r--indra/llcommon/llrun.h4
-rw-r--r--indra/llcommon/llsd.h4
-rw-r--r--indra/llcommon/llsdserialize.h28
-rw-r--r--indra/llcommon/llsdserialize_xml.cpp12
-rw-r--r--indra/llcommon/llsdutil.cpp355
-rw-r--r--indra/llcommon/llsdutil.h114
-rw-r--r--indra/llcommon/llsecondlifeurls.h30
-rw-r--r--indra/llcommon/llsimplehash.h2
-rw-r--r--indra/llcommon/llsingleton.cpp38
-rw-r--r--indra/llcommon/llsingleton.h47
-rw-r--r--indra/llcommon/llstacktrace.cpp1
-rw-r--r--indra/llcommon/llstacktrace.h2
-rw-r--r--indra/llcommon/llstat.cpp51
-rw-r--r--indra/llcommon/llstat.h35
-rw-r--r--indra/llcommon/llstreamtools.h36
-rw-r--r--indra/llcommon/llstring.cpp45
-rw-r--r--indra/llcommon/llstring.h121
-rw-r--r--indra/llcommon/llstringtable.h18
-rw-r--r--indra/llcommon/llsys.cpp45
-rw-r--r--indra/llcommon/llsys.h18
-rw-r--r--indra/llcommon/llthread.h10
-rw-r--r--indra/llcommon/lltimer.h28
-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.h2
-rw-r--r--indra/llcommon/llworkerthread.h4
-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/stringize.h73
-rw-r--r--indra/llcommon/tests/bitpack_test.cpp125
-rw-r--r--indra/llcommon/tests/listener.h139
-rw-r--r--indra/llcommon/tests/llbase64_test.cpp83
-rw-r--r--indra/llcommon/tests/lldate_test.cpp2
-rw-r--r--indra/llcommon/tests/lldependencies_test.cpp275
-rw-r--r--indra/llcommon/tests/llerror_test.cpp768
-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/llrand_test.cpp2
-rw-r--r--indra/llcommon/tests/llsdserialize_test.cpp76
-rw-r--r--indra/llcommon/tests/llstring_test.cpp1
-rw-r--r--indra/llcommon/tests/lltreeiterators_test.cpp1222
-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
-rw-r--r--indra/llimage/llimage.cpp33
-rw-r--r--indra/llimage/llimagej2c.cpp48
-rw-r--r--indra/llimage/llimagej2c.h4
-rw-r--r--indra/llinventory/CMakeLists.txt2
-rw-r--r--indra/llinventory/llinventory.cpp95
-rw-r--r--indra/llinventory/llinventory.h18
-rw-r--r--indra/llinventory/llinventorytype.cpp34
-rw-r--r--indra/llinventory/llinventorytype.h3
-rw-r--r--indra/llinventory/llparcel.cpp3
-rw-r--r--indra/llinventory/llparcel.h6
-rw-r--r--indra/llinventory/llpermissions.cpp13
-rw-r--r--indra/llinventory/llpermissions.h4
-rw-r--r--indra/llinventory/lltransactiontypes.h12
-rw-r--r--indra/llinventory/tests/inventorymisc_test.cpp4
-rw-r--r--indra/llinventory/tests/llparcel_test.cpp75
-rw-r--r--indra/llmath/CMakeLists.txt7
-rw-r--r--indra/llmath/llbbox.cpp2
-rw-r--r--indra/llmath/llmath.h1
-rw-r--r--indra/llmath/llmodularmath.cpp36
-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/llsdutil_math.cpp2
-rw-r--r--indra/llmath/llsdutil_math.h70
-rw-r--r--indra/llmath/llvolume.cpp2
-rw-r--r--indra/llmath/tests/llbbox_test.cpp4
-rw-r--r--indra/llmath/tests/llbboxlocal_test.cpp5
-rw-r--r--indra/llmath/tests/llmodularmath_test.cpp82
-rw-r--r--indra/llmath/tests/llquaternion_test.cpp2
-rw-r--r--indra/llmath/tests/llrect_test.cpp4
-rw-r--r--indra/llmath/tests/m3math_test.cpp327
-rw-r--r--indra/llmath/tests/v2math_test.cpp2
-rw-r--r--indra/llmath/tests/v3color_test.cpp2
-rw-r--r--indra/llmath/tests/v3dmath_test.cpp2
-rw-r--r--indra/llmath/tests/v3math_test.cpp2
-rw-r--r--indra/llmath/tests/v4color_test.cpp2
-rw-r--r--indra/llmath/tests/v4coloru_test.cpp2
-rw-r--r--indra/llmath/tests/v4math_test.cpp2
-rw-r--r--indra/llmath/tests/xform_test.cpp2
-rw-r--r--indra/llmessage/CMakeLists.txt15
-rw-r--r--indra/llmessage/llares.cpp8
-rw-r--r--indra/llmessage/llares.h12
-rw-r--r--indra/llmessage/llareslistener.cpp75
-rw-r--r--indra/llmessage/llareslistener.h37
-rw-r--r--indra/llmessage/llcachename.h7
-rw-r--r--indra/llmessage/llcurl.cpp13
-rw-r--r--indra/llmessage/llcurl.h6
-rw-r--r--indra/llmessage/llhttpclient.cpp5
-rw-r--r--indra/llmessage/llhttpclientadapter.cpp2
-rw-r--r--indra/llmessage/llhttpclientadapter.h2
-rw-r--r--indra/llmessage/llhttpclientinterface.h2
-rw-r--r--indra/llmessage/llinstantmessage.cpp2
-rw-r--r--indra/llmessage/lliohttpserver.cpp14
-rw-r--r--indra/llmessage/llmail.cpp18
-rw-r--r--indra/llmessage/llmessagesenderinterface.h2
-rw-r--r--indra/llmessage/llpartdata.cpp2
-rw-r--r--indra/llmessage/llregionpresenceverifier.cpp90
-rw-r--r--indra/llmessage/llregionpresenceverifier.h39
-rw-r--r--indra/llmessage/llsdmessage.cpp7
-rw-r--r--indra/llmessage/llsdmessage.h3
-rwxr-xr-xindra/llmessage/llsdmessagebuilder.cpp1
-rwxr-xr-xindra/llmessage/llsdmessagereader.cpp1
-rw-r--r--indra/llmessage/llstoredmessage.cpp2
-rw-r--r--indra/llmessage/llstoredmessage.h2
-rw-r--r--indra/llmessage/lltemplatemessagebuilder.cpp4
-rw-r--r--indra/llmessage/lltemplatemessagereader.cpp7
-rw-r--r--indra/llmessage/llthrottle.cpp25
-rw-r--r--indra/llmessage/llthrottle.h2
-rw-r--r--indra/llmessage/lltransfersourceasset.cpp2
-rw-r--r--indra/llmessage/llurlrequest.cpp54
-rw-r--r--indra/llmessage/llurlrequest.h8
-rw-r--r--indra/llmessage/llxfermanager.cpp36
-rw-r--r--indra/llmessage/tests/llareslistener_test.cpp200
-rw-r--r--indra/llmessage/tests/llcurl_stub.cpp1
-rw-r--r--indra/llmessage/tests/llhost_test.cpp256
-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.cpp2
-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.cpp2
-rw-r--r--indra/llmessage/tests/llxfer_file_test.cpp64
-rw-r--r--indra/llmessage/tests/test_llsdmessage_peer.py30
-rw-r--r--indra/llmessage/tests/testrunner.py53
-rw-r--r--indra/llplugin/llpluginclassmedia.cpp90
-rw-r--r--indra/llplugin/llpluginclassmedia.h11
-rw-r--r--indra/llplugin/llpluginclassmediaowner.h7
-rw-r--r--indra/llplugin/llpluginprocessparent.cpp64
-rw-r--r--indra/llplugin/llpluginprocessparent.h5
-rw-r--r--indra/llprimitive/llmediaentry.cpp1
-rw-r--r--indra/llprimitive/llprimitive.cpp193
-rw-r--r--indra/llprimitive/llprimitive.h4
-rw-r--r--indra/llprimitive/llprimtexturelist.cpp19
-rw-r--r--indra/llprimitive/lltextureentry.cpp8
-rw-r--r--indra/llprimitive/lltextureentry.h4
-rw-r--r--indra/llprimitive/tests/llmediaentry_test.cpp118
-rw-r--r--indra/llrender/CMakeLists.txt2
-rw-r--r--indra/llrender/llcubemap.cpp2
-rw-r--r--indra/llrender/llfontfreetype.cpp132
-rw-r--r--indra/llrender/llfontfreetype.h21
-rw-r--r--indra/llrender/llfontgl.cpp58
-rw-r--r--indra/llrender/llfontgl.h3
-rw-r--r--indra/llrender/llfontregistry.cpp5
-rw-r--r--indra/llrender/llgl.cpp2
-rw-r--r--indra/llrender/llglheaders.h4
-rw-r--r--indra/llrender/llimagegl.cpp2
-rw-r--r--indra/llrender/lltexture.h2
-rw-r--r--indra/llui/CMakeLists.txt6
-rw-r--r--indra/llui/llbutton.cpp40
-rw-r--r--indra/llui/llbutton.h14
-rw-r--r--indra/llui/llconsole.cpp5
-rw-r--r--indra/llui/lldockablefloater.cpp27
-rw-r--r--indra/llui/lldockablefloater.h2
-rw-r--r--indra/llui/lldockcontrol.cpp45
-rw-r--r--indra/llui/lldockcontrol.h6
-rw-r--r--indra/llui/lldraghandle.cpp9
-rw-r--r--indra/llui/llflatlistview.cpp32
-rw-r--r--indra/llui/llflatlistview.h4
-rw-r--r--indra/llui/llfloater.cpp305
-rw-r--r--indra/llui/llfloater.h30
-rw-r--r--indra/llui/llfloaterreg.cpp38
-rw-r--r--indra/llui/llfloaterreg.h5
-rw-r--r--indra/llui/llfloaterreglistener.cpp114
-rw-r--r--indra/llui/llfloaterreglistener.h36
-rw-r--r--indra/llui/llflyoutbutton.cpp1
-rw-r--r--indra/llui/llfunctorregistry.cpp1
-rw-r--r--indra/llui/llhandle.h14
-rw-r--r--indra/llui/lliconctrl.cpp23
-rw-r--r--indra/llui/lliconctrl.h13
-rw-r--r--indra/llui/lllayoutstack.cpp30
-rw-r--r--indra/llui/lllayoutstack.h3
-rw-r--r--indra/llui/lllineeditor.cpp106
-rw-r--r--indra/llui/lllineeditor.h18
-rw-r--r--indra/llui/lllocalcliprect.cpp3
-rw-r--r--indra/llui/llmenubutton.cpp2
-rw-r--r--indra/llui/llmenugl.cpp75
-rw-r--r--indra/llui/llmenugl.h2
-rw-r--r--indra/llui/llmodaldialog.cpp15
-rw-r--r--indra/llui/llmodaldialog.h3
-rw-r--r--indra/llui/llmultifloater.cpp12
-rw-r--r--indra/llui/llnotifications.cpp4
-rw-r--r--indra/llui/llnotifications.h20
-rw-r--r--indra/llui/llnotificationslistener.cpp55
-rw-r--r--indra/llui/llnotificationslistener.h34
-rw-r--r--indra/llui/llpanel.cpp95
-rw-r--r--indra/llui/llpanel.h31
-rw-r--r--indra/llui/llradiogroup.cpp2
-rw-r--r--indra/llui/llresmgr.cpp8
-rw-r--r--indra/llui/llrngwriter.cpp3
-rw-r--r--indra/llui/llscrollbar.cpp32
-rw-r--r--indra/llui/llscrollbar.h12
-rw-r--r--indra/llui/llscrollcontainer.cpp8
-rw-r--r--indra/llui/llscrollingpanellist.cpp4
-rw-r--r--indra/llui/llscrollingpanellist.h2
-rw-r--r--indra/llui/llscrolllistcolumn.cpp15
-rw-r--r--indra/llui/llscrolllistcolumn.h15
-rw-r--r--indra/llui/llslider.cpp2
-rw-r--r--indra/llui/llsliderctrl.cpp1
-rw-r--r--indra/llui/lltabcontainer.cpp155
-rw-r--r--indra/llui/lltabcontainer.h40
-rw-r--r--indra/llui/lltextbase.cpp402
-rw-r--r--indra/llui/lltextbase.h35
-rw-r--r--indra/llui/lltextbox.cpp26
-rw-r--r--indra/llui/lltextbox.h21
-rw-r--r--indra/llui/lltexteditor.cpp94
-rw-r--r--indra/llui/lltexteditor.h6
-rw-r--r--indra/llui/lltooltip.cpp135
-rw-r--r--indra/llui/lltooltip.h14
-rw-r--r--indra/llui/llui.cpp23
-rw-r--r--indra/llui/llui.h29
-rw-r--r--indra/llui/lluicolortable.cpp25
-rw-r--r--indra/llui/lluicolortable.h23
-rw-r--r--indra/llui/lluictrl.cpp47
-rw-r--r--indra/llui/lluictrl.h24
-rw-r--r--indra/llui/lluictrlfactory.cpp45
-rw-r--r--indra/llui/lluictrlfactory.h50
-rw-r--r--indra/llui/lluiimage.cpp3
-rw-r--r--indra/llui/lluiimage.h6
-rw-r--r--indra/llui/lluistring.cpp2
-rw-r--r--indra/llui/lluistring.h6
-rw-r--r--indra/llui/llurlaction.cpp12
-rw-r--r--indra/llui/llurlaction.h3
-rw-r--r--indra/llui/llurlentry.cpp172
-rw-r--r--indra/llui/llurlentry.h14
-rw-r--r--indra/llui/llurlregistry.cpp13
-rw-r--r--indra/llui/llurlregistry.h4
-rw-r--r--indra/llui/llview.cpp73
-rw-r--r--indra/llui/llview.h23
-rw-r--r--indra/llui/tests/llurlentry_test.cpp4
-rw-r--r--indra/llvfs/CMakeLists.txt15
-rw-r--r--indra/llvfs/lldir.cpp18
-rw-r--r--indra/llvfs/lldir.h1
-rw-r--r--indra/llvfs/lldir_linux.cpp14
-rw-r--r--indra/llvfs/lldir_mac.cpp3
-rw-r--r--indra/llvfs/lldir_win32.cpp21
-rw-r--r--indra/llvfs/lldirguard.h78
-rwxr-xr-xindra/llvfs/llpidlock.cpp2
-rw-r--r--indra/llvfs/tests/lldir_test.cpp266
-rw-r--r--indra/llwindow/llkeyboard.cpp69
-rw-r--r--indra/llwindow/llkeyboard.h9
-rw-r--r--indra/llwindow/llkeyboardwin32.cpp2
-rw-r--r--indra/llwindow/llwindowmacosx.cpp6
-rw-r--r--indra/llwindow/llwindowmesaheadless.cpp2
-rw-r--r--indra/llwindow/llwindowmesaheadless.h2
-rw-r--r--indra/llwindow/llwindowsdl.cpp19
-rw-r--r--indra/llxml/CMakeLists.txt22
-rw-r--r--indra/llxml/tests/llcontrol_test.cpp161
-rw-r--r--indra/llxuixml/llinitparam.cpp43
-rw-r--r--indra/llxuixml/llinitparam.h219
-rw-r--r--indra/llxuixml/lltrans.cpp4
-rw-r--r--indra/llxuixml/lltrans.h5
-rw-r--r--indra/llxuixml/lluicolor.cpp15
-rw-r--r--indra/llxuixml/lluicolor.h15
-rw-r--r--indra/llxuixml/llxuiparser.cpp12
-rw-r--r--indra/llxuixml/llxuiparser.h7
-rw-r--r--indra/lscript/lscript_byteformat.h2
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.cpp12
-rw-r--r--indra/lscript/lscript_compile/lscript_tree.h1
-rw-r--r--indra/lscript/lscript_execute.h3
-rw-r--r--indra/lscript/lscript_execute/llscriptresource.cpp2
-rw-r--r--indra/lscript/lscript_execute/lscript_execute.cpp122
-rw-r--r--indra/mac_crash_logger/CMakeLists.txt5
-rw-r--r--indra/mac_updater/CMakeLists.txt4
-rw-r--r--indra/media_plugins/CMakeLists.txt2
-rw-r--r--indra/media_plugins/base/media_plugin_base.cpp1
-rw-r--r--indra/media_plugins/base/media_plugin_base.h1
-rw-r--r--indra/media_plugins/example/CMakeLists.txt74
-rw-r--r--indra/media_plugins/example/media_plugin_example.cpp488
-rw-r--r--indra/media_plugins/gstreamer010/CMakeLists.txt6
-rw-r--r--indra/media_plugins/quicktime/CMakeLists.txt8
-rw-r--r--indra/media_plugins/quicktime/media_plugin_quicktime.cpp219
-rw-r--r--indra/media_plugins/webkit/CMakeLists.txt8
-rw-r--r--indra/media_plugins/webkit/media_plugin_webkit.cpp186
-rw-r--r--indra/newview/CMakeLists.txt351
-rw-r--r--indra/newview/English.lproj/InfoPlist.strings4
-rw-r--r--indra/newview/Info-SecondLife.plist2
-rw-r--r--indra/newview/app_settings/foldertypes.xml31
-rw-r--r--indra/newview/app_settings/ignorable_dialogs.xml582
-rw-r--r--indra/newview/app_settings/keywords.ini4
-rw-r--r--indra/newview/app_settings/settings.xml325
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl16
-rw-r--r--indra/newview/build_win32_appConfig.py28
-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.xml20291
-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/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
-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/installers/darwin/firstlook-dmg/_DS_Storebin12292 -> 12292 bytes
-rw-r--r--indra/newview/installers/darwin/publicnightly-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/FILES_ARE_UNICODE_UTF-16LE.txt12
-rw-r--r--indra/newview/installers/windows/lang_it.nsibin7438 -> 7438 bytes
-rw-r--r--indra/newview/licenses-mac.txt509
-rw-r--r--indra/newview/llagent.cpp62
-rw-r--r--indra/newview/llagent.h8
-rw-r--r--indra/newview/llagentlistener.cpp78
-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/llagentui.cpp8
-rw-r--r--indra/newview/llagentui.h5
-rw-r--r--indra/newview/llagentwearables.cpp399
-rw-r--r--indra/newview/llagentwearables.h22
-rw-r--r--indra/newview/llappearancemgr.cpp461
-rw-r--r--indra/newview/llappearancemgr.h29
-rw-r--r--indra/newview/llappviewer.cpp310
-rw-r--r--indra/newview/llappviewer.h20
-rw-r--r--indra/newview/llappviewerlinux.cpp26
-rw-r--r--indra/newview/llappviewerlinux.h5
-rw-r--r--indra/newview/llappviewerlinux_api_dbus.cpp6
-rw-r--r--indra/newview/llappviewerlistener.cpp40
-rw-r--r--indra/newview/llappviewerlistener.h37
-rw-r--r--indra/newview/llappviewermacosx.cpp19
-rw-r--r--indra/newview/llassetuploadresponders.cpp5
-rw-r--r--indra/newview/llavataractions.cpp9
-rw-r--r--indra/newview/llavatariconctrl.cpp180
-rw-r--r--indra/newview/llavatariconctrl.h45
-rw-r--r--indra/newview/llavatarlist.cpp188
-rw-r--r--indra/newview/llavatarlist.h36
-rw-r--r--indra/newview/llavatarlistitem.cpp168
-rw-r--r--indra/newview/llavatarlistitem.h44
-rw-r--r--indra/newview/llavatarpropertiesprocessor.cpp13
-rw-r--r--indra/newview/llavatarpropertiesprocessor.h4
-rw-r--r--indra/newview/llbottomtray.cpp242
-rw-r--r--indra/newview/llbottomtray.h23
-rw-r--r--indra/newview/llcallingcard.cpp58
-rw-r--r--indra/newview/llcallingcard.h10
-rw-r--r--indra/newview/llcapabilitylistener.cpp24
-rw-r--r--indra/newview/llcapabilitylistener.h23
-rw-r--r--indra/newview/llcapabilityprovider.h23
-rw-r--r--indra/newview/llchannelmanager.cpp17
-rw-r--r--indra/newview/llchathistory.cpp379
-rw-r--r--indra/newview/llchathistory.h132
-rw-r--r--indra/newview/llchiclet.cpp420
-rw-r--r--indra/newview/llchiclet.h161
-rw-r--r--indra/newview/llclassifiedinfo.cpp36
-rw-r--r--indra/newview/llclassifiedinfo.h3
-rw-r--r--indra/newview/llcolorswatch.cpp3
-rw-r--r--indra/newview/llconfirmationmanager.cpp1
-rw-r--r--indra/newview/llcurrencyuimanager.cpp14
-rw-r--r--indra/newview/lldebugmessagebox.cpp1
-rw-r--r--indra/newview/lldndbutton.cpp60
-rw-r--r--indra/newview/lldndbutton.h89
-rw-r--r--indra/newview/lldrawpool.cpp1
-rw-r--r--indra/newview/lldrawpoolbump.cpp2
-rw-r--r--indra/newview/lldrawpoolterrain.cpp4
-rw-r--r--indra/newview/lldrawpoolwater.cpp6
-rw-r--r--indra/newview/lldriverparam.cpp182
-rw-r--r--indra/newview/lldriverparam.h13
-rw-r--r--indra/newview/lleventinfo.cpp37
-rw-r--r--indra/newview/lleventinfo.h3
-rw-r--r--indra/newview/lleventnotifier.cpp83
-rw-r--r--indra/newview/lleventnotifier.h5
-rw-r--r--indra/newview/llexpandabletextbox.cpp38
-rw-r--r--indra/newview/llexpandabletextbox.h12
-rw-r--r--indra/newview/llface.cpp15
-rw-r--r--indra/newview/llface.h2
-rw-r--r--indra/newview/llface.inl7
-rw-r--r--indra/newview/llfasttimerview.cpp10
-rw-r--r--indra/newview/llfavoritesbar.cpp121
-rw-r--r--indra/newview/llfavoritesbar.h2
-rw-r--r--indra/newview/llfeaturemanager.cpp6
-rw-r--r--indra/newview/llfirstuse.cpp4
-rw-r--r--indra/newview/llflexibleobject.cpp2
-rw-r--r--indra/newview/llfloaterabout.cpp268
-rw-r--r--indra/newview/llfloateranimpreview.cpp12
-rw-r--r--indra/newview/llfloaterauction.cpp294
-rw-r--r--indra/newview/llfloaterauction.h16
-rw-r--r--indra/newview/llfloateravatarpicker.cpp74
-rw-r--r--indra/newview/llfloateravatarpicker.h3
-rw-r--r--indra/newview/llfloateravatartextures.cpp49
-rw-r--r--indra/newview/llfloaterbulkpermission.cpp9
-rw-r--r--indra/newview/llfloaterbulkpermission.h1
-rw-r--r--indra/newview/llfloaterbump.cpp1
-rw-r--r--indra/newview/llfloaterbuy.cpp3
-rw-r--r--indra/newview/llfloaterbuycontents.cpp5
-rw-r--r--indra/newview/llfloaterbuycurrency.cpp1
-rw-r--r--indra/newview/llfloaterbuyland.cpp16
-rw-r--r--indra/newview/llfloatercamera.cpp57
-rw-r--r--indra/newview/llfloatercamera.h18
-rw-r--r--indra/newview/llfloaterchat.cpp31
-rw-r--r--indra/newview/llfloaterchat.h2
-rw-r--r--indra/newview/llfloaterchatterbox.cpp2
-rw-r--r--indra/newview/llfloatercolorpicker.cpp6
-rw-r--r--indra/newview/llfloaterdaycycle.cpp12
-rw-r--r--indra/newview/llfloaterdaycycle.h3
-rw-r--r--indra/newview/llfloaterenvsettings.cpp6
-rw-r--r--indra/newview/llfloaterenvsettings.h3
-rw-r--r--indra/newview/llfloaterfriends.h3
-rw-r--r--indra/newview/llfloatergesture.cpp26
-rw-r--r--indra/newview/llfloatergroupinvite.cpp5
-rw-r--r--indra/newview/llfloatergroups.cpp23
-rw-r--r--indra/newview/llfloatergroups.h3
-rw-r--r--indra/newview/llfloaterhardwaresettings.cpp12
-rw-r--r--indra/newview/llfloaterhardwaresettings.h3
-rw-r--r--indra/newview/llfloaterinventory.cpp1774
-rw-r--r--indra/newview/llfloaterinventory.h321
-rw-r--r--indra/newview/llfloaterland.cpp69
-rw-r--r--indra/newview/llfloaterland.h2
-rw-r--r--indra/newview/llfloatermap.cpp8
-rw-r--r--indra/newview/llfloatermediasettings.cpp26
-rw-r--r--indra/newview/llfloatermediasettings.h2
-rw-r--r--indra/newview/llfloaternamedesc.cpp2
-rw-r--r--indra/newview/llfloaternotificationsconsole.cpp3
-rw-r--r--indra/newview/llfloateropenobject.cpp15
-rw-r--r--indra/newview/llfloateropenobject.h4
-rw-r--r--indra/newview/llfloaterpay.cpp6
-rw-r--r--indra/newview/llfloaterpreference.cpp28
-rw-r--r--indra/newview/llfloaterpreference.h1
-rw-r--r--indra/newview/llfloaterproperties.cpp1
-rw-r--r--indra/newview/llfloaterregioninfo.cpp205
-rw-r--r--indra/newview/llfloaterregioninfo.h27
-rw-r--r--indra/newview/llfloaterreporter.cpp7
-rw-r--r--indra/newview/llfloaterscriptdebug.cpp2
-rw-r--r--indra/newview/llfloatersearch.cpp127
-rw-r--r--indra/newview/llfloatersearch.h80
-rw-r--r--indra/newview/llfloatersellland.cpp2
-rw-r--r--indra/newview/llfloatersnapshot.cpp4
-rw-r--r--indra/newview/llfloatertools.cpp108
-rw-r--r--indra/newview/llfloatertools.h6
-rw-r--r--indra/newview/llfloatertos.cpp37
-rw-r--r--indra/newview/llfloatertos.h4
-rw-r--r--indra/newview/llfloateruipreview.cpp293
-rw-r--r--indra/newview/llfloateruipreview.h133
-rw-r--r--indra/newview/llfloatervoicedevicesettings.cpp19
-rw-r--r--indra/newview/llfloatervoicedevicesettings.h2
-rw-r--r--indra/newview/llfloaterwater.cpp27
-rw-r--r--indra/newview/llfloaterwater.h4
-rw-r--r--indra/newview/llfloaterwindlight.cpp40
-rw-r--r--indra/newview/llfloaterwindlight.h4
-rw-r--r--indra/newview/llfloaterworldmap.cpp74
-rw-r--r--indra/newview/llfloaterworldmap.h1
-rw-r--r--indra/newview/llfolderview.cpp51
-rw-r--r--indra/newview/llfolderview.h20
-rw-r--r--indra/newview/llfoldervieweventlistener.h5
-rw-r--r--indra/newview/llfolderviewitem.cpp67
-rw-r--r--indra/newview/llfolderviewitem.h3
-rw-r--r--indra/newview/llfriendcard.cpp166
-rw-r--r--indra/newview/llfriendcard.h19
-rw-r--r--indra/newview/llgroupactions.cpp68
-rw-r--r--indra/newview/llgroupactions.h7
-rw-r--r--indra/newview/llgrouplist.cpp11
-rw-r--r--indra/newview/llgrouplist.h1
-rw-r--r--indra/newview/llgroupmgr.cpp14
-rw-r--r--indra/newview/llhudview.cpp14
-rw-r--r--indra/newview/llhudview.h2
-rw-r--r--indra/newview/llimfloater.cpp551
-rw-r--r--indra/newview/llimfloater.h59
-rw-r--r--indra/newview/llimpanel.cpp1016
-rw-r--r--indra/newview/llimpanel.h141
-rw-r--r--indra/newview/llimview.cpp722
-rw-r--r--indra/newview/llimview.h162
-rw-r--r--indra/newview/llinspect.cpp97
-rw-r--r--indra/newview/llinspect.h61
-rw-r--r--indra/newview/llinspectavatar.cpp134
-rw-r--r--indra/newview/llinspectgroup.cpp330
-rw-r--r--indra/newview/llinspectgroup.h41
-rw-r--r--indra/newview/llinspectobject.cpp185
-rw-r--r--indra/newview/llinventoryactions.h47
-rw-r--r--indra/newview/llinventorybridge.cpp736
-rw-r--r--indra/newview/llinventorybridge.h41
-rw-r--r--indra/newview/llinventoryclipboard.cpp12
-rw-r--r--indra/newview/llinventoryclipboard.h3
-rw-r--r--indra/newview/llinventoryfilter.cpp7
-rw-r--r--indra/newview/llinventoryfunctions.cpp340
-rw-r--r--indra/newview/llinventoryfunctions.h136
-rw-r--r--indra/newview/llinventorymodel.cpp337
-rw-r--r--indra/newview/llinventorymodel.h34
-rw-r--r--indra/newview/llinventorypanel.cpp902
-rw-r--r--indra/newview/llinventorypanel.h206
-rw-r--r--indra/newview/lljoystickbutton.cpp29
-rw-r--r--indra/newview/lljoystickbutton.h2
-rw-r--r--indra/newview/lllandmarkactions.cpp132
-rw-r--r--indra/newview/lllandmarkactions.h35
-rw-r--r--indra/newview/lllandmarklist.cpp36
-rw-r--r--indra/newview/lllandmarklist.h5
-rw-r--r--indra/newview/lllocaltextureobject.cpp132
-rw-r--r--indra/newview/lllocaltextureobject.h26
-rw-r--r--indra/newview/lllocationinputctrl.cpp22
-rw-r--r--indra/newview/lllocationinputctrl.h1
-rw-r--r--indra/newview/lllogchat.cpp60
-rw-r--r--indra/newview/lllogchat.h11
-rw-r--r--indra/newview/llloginhandler.cpp31
-rw-r--r--indra/newview/llloginhandler.h6
-rw-r--r--indra/newview/lllogininstance.cpp475
-rw-r--r--indra/newview/lllogininstance.h114
-rw-r--r--indra/newview/llmaniprotate.cpp4
-rw-r--r--indra/newview/llmaniptranslate.cpp2
-rw-r--r--indra/newview/llmediactrl.cpp102
-rw-r--r--indra/newview/llmediactrl.h2
-rwxr-xr-xindra/newview/llmediadataclient.cpp384
-rwxr-xr-xindra/newview/llmediadataclient.h88
-rw-r--r--indra/newview/llmenucommands.cpp2
-rw-r--r--indra/newview/llmimetypes.cpp1
-rw-r--r--indra/newview/llmoveview.cpp18
-rw-r--r--indra/newview/llmoveview.h4
-rw-r--r--indra/newview/llmutelist.cpp3
-rw-r--r--indra/newview/llmutelist.h8
-rw-r--r--indra/newview/llnavigationbar.cpp58
-rw-r--r--indra/newview/llnavigationbar.h16
-rw-r--r--indra/newview/llnearbychat.cpp364
-rw-r--r--indra/newview/llnearbychat.h46
-rw-r--r--indra/newview/llnearbychatbar.cpp83
-rw-r--r--indra/newview/llnearbychatbar.h17
-rw-r--r--indra/newview/llnearbychathandler.cpp25
-rw-r--r--indra/newview/llnetmap.cpp27
-rw-r--r--indra/newview/llnetmap.h9
-rw-r--r--indra/newview/llnotificationhandler.h24
-rw-r--r--indra/newview/llnotificationmanager.cpp3
-rw-r--r--indra/newview/llnotificationofferhandler.cpp153
-rw-r--r--indra/newview/llnotificationscripthandler.cpp5
-rw-r--r--indra/newview/llnotificationtiphandler.cpp17
-rw-r--r--indra/newview/lloutputmonitorctrl.cpp12
-rw-r--r--indra/newview/lloutputmonitorctrl.h3
-rw-r--r--indra/newview/llpanelavatar.cpp26
-rw-r--r--indra/newview/llpanelavatar.h4
-rw-r--r--indra/newview/llpanelclassified.cpp8
-rw-r--r--indra/newview/llpanelcontents.cpp13
-rw-r--r--indra/newview/llpanelcontents.h11
-rw-r--r--indra/newview/llpaneleditwearable.cpp657
-rw-r--r--indra/newview/llpaneleditwearable.h114
-rw-r--r--indra/newview/llpanelgroup.cpp121
-rw-r--r--indra/newview/llpanelgroup.h11
-rw-r--r--indra/newview/llpanelgroupgeneral.cpp13
-rw-r--r--indra/newview/llpanelgrouplandmoney.cpp9
-rw-r--r--indra/newview/llpanelgrouplandmoney.h2
-rw-r--r--indra/newview/llpanelgroupnotices.cpp1
-rw-r--r--indra/newview/llpanelgrouproles.cpp14
-rw-r--r--indra/newview/llpanelgrouproles.h1
-rw-r--r--indra/newview/llpanelimcontrolpanel.cpp186
-rw-r--r--indra/newview/llpanelimcontrolpanel.h54
-rw-r--r--indra/newview/llpanelland.cpp6
-rw-r--r--indra/newview/llpanelland.h1
-rw-r--r--indra/newview/llpanellandmarkinfo.cpp420
-rw-r--r--indra/newview/llpanellandmarkinfo.h85
-rw-r--r--indra/newview/llpanellandmarks.cpp935
-rw-r--r--indra/newview/llpanellandmarks.h100
-rw-r--r--indra/newview/llpanellogin.cpp121
-rw-r--r--indra/newview/llpanellogin.h6
-rw-r--r--indra/newview/llpanelmaininventory.cpp818
-rw-r--r--indra/newview/llpanelmaininventory.h125
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.cpp47
-rw-r--r--indra/newview/llpanelmediasettingsgeneral.h4
-rw-r--r--indra/newview/llpanelmediasettingssecurity.cpp582
-rw-r--r--indra/newview/llpanelmediasettingssecurity.h7
-rw-r--r--indra/newview/llpanelobject.h1
-rw-r--r--indra/newview/llpanelobjectinventory.cpp1927
-rw-r--r--indra/newview/llpanelobjectinventory.h102
-rw-r--r--indra/newview/llpanelpeople.cpp247
-rw-r--r--indra/newview/llpanelpeople.h18
-rw-r--r--indra/newview/llpanelpeoplemenus.cpp104
-rw-r--r--indra/newview/llpanelpeoplemenus.h10
-rw-r--r--indra/newview/llpanelpick.cpp680
-rw-r--r--indra/newview/llpanelpick.h240
-rw-r--r--indra/newview/llpanelpicks.cpp242
-rw-r--r--indra/newview/llpanelpicks.h40
-rw-r--r--indra/newview/llpanelplace.cpp1
-rw-r--r--indra/newview/llpanelplaceinfo.cpp879
-rw-r--r--indra/newview/llpanelplaceinfo.h148
-rw-r--r--indra/newview/llpanelplaceprofile.cpp586
-rw-r--r--indra/newview/llpanelplaceprofile.h121
-rw-r--r--indra/newview/llpanelplaces.cpp280
-rw-r--r--indra/newview/llpanelplaces.h20
-rw-r--r--indra/newview/llpanelplacestab.cpp3
-rw-r--r--indra/newview/llpanelplacestab.h5
-rw-r--r--indra/newview/llpanelprimmediacontrols.cpp1112
-rw-r--r--indra/newview/llpanelprimmediacontrols.h148
-rw-r--r--indra/newview/llpanelprofile.cpp97
-rw-r--r--indra/newview/llpanelprofile.h4
-rw-r--r--indra/newview/llpanelprofileview.cpp56
-rw-r--r--indra/newview/llpanelprofileview.h23
-rw-r--r--indra/newview/llpanelteleporthistory.cpp362
-rw-r--r--indra/newview/llpanelteleporthistory.h17
-rw-r--r--indra/newview/llpanelvolume.cpp1
-rw-r--r--indra/newview/llpanelvolume.h1
-rw-r--r--indra/newview/llparticipantlist.cpp177
-rw-r--r--indra/newview/llparticipantlist.h111
-rw-r--r--indra/newview/llplacesinventorybridge.cpp201
-rw-r--r--indra/newview/llplacesinventorybridge.h91
-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.cpp33
-rw-r--r--indra/newview/llpreview.h1
-rw-r--r--indra/newview/llpreviewgesture.cpp6
-rw-r--r--indra/newview/llpreviewscript.cpp7
-rw-r--r--indra/newview/llpreviewtexture.cpp115
-rw-r--r--indra/newview/llpreviewtexture.h6
-rw-r--r--indra/newview/llresourcedata.h3
-rw-r--r--indra/newview/llrootview.h22
-rw-r--r--indra/newview/llscreenchannel.cpp57
-rw-r--r--indra/newview/llscreenchannel.h7
-rw-r--r--indra/newview/llscrollingpanelparam.cpp388
-rw-r--r--indra/newview/llscrollingpanelparam.h100
-rw-r--r--indra/newview/llsearchcombobox.cpp1
-rw-r--r--indra/newview/llselectmgr.cpp28
-rw-r--r--indra/newview/llselectmgr.h3
-rw-r--r--indra/newview/llsidepanelinventory.cpp244
-rw-r--r--indra/newview/llsidepanelinventory.h80
-rw-r--r--indra/newview/llsidetray.cpp256
-rw-r--r--indra/newview/llsidetray.h81
-rw-r--r--indra/newview/llsky.cpp3
-rw-r--r--indra/newview/llsky.h6
-rw-r--r--indra/newview/llspatialpartition.cpp9
-rw-r--r--indra/newview/llspeakbutton.cpp174
-rw-r--r--indra/newview/llspeakbutton.h82
-rw-r--r--indra/newview/llspeakers.cpp639
-rw-r--r--indra/newview/llspeakers.h172
-rw-r--r--indra/newview/llstartup.cpp1482
-rw-r--r--indra/newview/llstartup.h6
-rw-r--r--indra/newview/llstatusbar.cpp1
-rw-r--r--indra/newview/llsyswellwindow.cpp61
-rw-r--r--indra/newview/llsyswellwindow.h2
-rw-r--r--indra/newview/llteleporthistorystorage.cpp13
-rw-r--r--indra/newview/llteleporthistorystorage.h5
-rw-r--r--indra/newview/lltexglobalcolor.cpp13
-rw-r--r--indra/newview/lltexglobalcolor.h4
-rw-r--r--indra/newview/lltexlayer.cpp908
-rw-r--r--indra/newview/lltexlayer.h140
-rw-r--r--indra/newview/lltexlayerparams.cpp55
-rw-r--r--indra/newview/lltexlayerparams.h17
-rw-r--r--indra/newview/lltexturectrl.cpp12
-rw-r--r--indra/newview/lltexturefetch.cpp2
-rw-r--r--indra/newview/lltextureview.cpp2
-rw-r--r--indra/newview/lltoast.cpp72
-rw-r--r--indra/newview/lltoast.h57
-rw-r--r--indra/newview/lltoastalertpanel.cpp5
-rw-r--r--indra/newview/lltoastalertpanel.h16
-rw-r--r--indra/newview/lltoastgroupnotifypanel.cpp2
-rw-r--r--indra/newview/lltoastimpanel.cpp1
-rw-r--r--indra/newview/lltoastnotifypanel.cpp332
-rw-r--r--indra/newview/lltoastnotifypanel.h26
-rw-r--r--indra/newview/lltoastpanel.cpp20
-rw-r--r--indra/newview/lltoastpanel.h4
-rw-r--r--indra/newview/lltooldraganddrop.cpp23
-rw-r--r--indra/newview/lltoolpie.cpp272
-rw-r--r--indra/newview/lltoolpie.h4
-rw-r--r--indra/newview/lltracker.cpp6
-rw-r--r--indra/newview/lltransientdockablefloater.cpp96
-rw-r--r--indra/newview/lltransientdockablefloater.h57
-rw-r--r--indra/newview/lltransientfloatermgr.cpp110
-rw-r--r--indra/newview/lltransientfloatermgr.h63
-rw-r--r--indra/newview/lluilistener.cpp50
-rw-r--r--indra/newview/lluilistener.h29
-rw-r--r--indra/newview/llurldispatcher.cpp1
-rw-r--r--indra/newview/llviewerassettype.cpp114
-rw-r--r--indra/newview/llviewerassettype.h54
-rw-r--r--indra/newview/llviewercamera.cpp5
-rw-r--r--indra/newview/llviewercontrol.cpp27
-rw-r--r--indra/newview/llviewercontrol.h3
-rw-r--r--indra/newview/llviewercontrollistener.cpp102
-rw-r--r--indra/newview/llviewercontrollistener.h33
-rw-r--r--indra/newview/llviewerfloaterreg.cpp13
-rw-r--r--indra/newview/llviewerfoldertype.cpp263
-rw-r--r--indra/newview/llviewerfoldertype.h57
-rw-r--r--indra/newview/llviewerinventory.cpp159
-rw-r--r--indra/newview/llviewerinventory.h9
-rw-r--r--indra/newview/llviewerjointattachment.cpp247
-rw-r--r--indra/newview/llviewerjointattachment.h26
-rw-r--r--indra/newview/llviewerjointmesh.cpp2
-rw-r--r--indra/newview/llviewerjoystick.cpp87
-rw-r--r--indra/newview/llviewerjoystick.h5
-rw-r--r--indra/newview/llviewerkeyboard.cpp2
-rw-r--r--indra/newview/llviewermedia.cpp661
-rw-r--r--indra/newview/llviewermedia.h88
-rw-r--r--indra/newview/llviewermediafocus.cpp410
-rw-r--r--indra/newview/llviewermediafocus.h69
-rw-r--r--indra/newview/llviewermenu.cpp568
-rw-r--r--indra/newview/llviewermenu.h9
-rw-r--r--indra/newview/llviewermenufile.cpp18
-rw-r--r--indra/newview/llviewermenufile.h6
-rw-r--r--indra/newview/llviewermessage.cpp153
-rw-r--r--indra/newview/llviewermessage.h1
-rw-r--r--indra/newview/llviewernetwork.cpp6
-rw-r--r--indra/newview/llviewernetwork.h4
-rw-r--r--indra/newview/llviewerobject.cpp9
-rw-r--r--indra/newview/llviewerobject.h6
-rw-r--r--indra/newview/llviewerobjectlist.cpp125
-rw-r--r--indra/newview/llviewerparcelmedia.cpp18
-rw-r--r--indra/newview/llviewerparcelmgr.cpp15
-rw-r--r--indra/newview/llviewerparcelmgr.h2
-rw-r--r--indra/newview/llviewerprecompiledheaders.h1
-rw-r--r--indra/newview/llviewerstats.cpp3
-rw-r--r--indra/newview/llviewertexteditor.cpp111
-rw-r--r--indra/newview/llviewertexture.cpp129
-rw-r--r--indra/newview/llviewertexture.h40
-rw-r--r--indra/newview/llviewertexturelist.cpp86
-rw-r--r--indra/newview/llviewertexturelist.h18
-rw-r--r--indra/newview/llviewervisualparam.cpp15
-rw-r--r--indra/newview/llviewervisualparam.h9
-rw-r--r--indra/newview/llviewerwindow.cpp122
-rw-r--r--indra/newview/llviewerwindow.h5
-rw-r--r--indra/newview/llviewerwindowlistener.cpp87
-rw-r--r--indra/newview/llviewerwindowlistener.h35
-rw-r--r--indra/newview/llvoavatar.cpp721
-rw-r--r--indra/newview/llvoavatar.h34
-rw-r--r--indra/newview/llvoavatardefines.cpp26
-rw-r--r--indra/newview/llvoavatarself.cpp503
-rw-r--r--indra/newview/llvoavatarself.h54
-rw-r--r--indra/newview/llvograss.cpp2
-rw-r--r--indra/newview/llvoicechannel.cpp880
-rw-r--r--indra/newview/llvoicechannel.h179
-rw-r--r--indra/newview/llvoiceclient.cpp66
-rw-r--r--indra/newview/llvoiceclient.h5
-rw-r--r--indra/newview/llvoicevisualizer.cpp2
-rw-r--r--indra/newview/llvopartgroup.cpp6
-rw-r--r--indra/newview/llvosky.cpp10
-rw-r--r--indra/newview/llvosky.h2
-rw-r--r--indra/newview/llvotree.cpp2
-rw-r--r--indra/newview/llvovolume.cpp294
-rw-r--r--indra/newview/llvovolume.h19
-rw-r--r--indra/newview/llvowlsky.cpp4
-rw-r--r--indra/newview/llwaterparammanager.cpp2
-rw-r--r--indra/newview/llwearable.cpp542
-rw-r--r--indra/newview/llwearable.h45
-rw-r--r--indra/newview/llwearablelist.cpp43
-rw-r--r--indra/newview/llwearablelist.h3
-rw-r--r--indra/newview/llweb.cpp4
-rw-r--r--indra/newview/llwldaycycle.cpp1
-rw-r--r--indra/newview/llwlparammanager.cpp4
-rw-r--r--indra/newview/llworldmap.cpp15
-rw-r--r--indra/newview/llworldmap.h1
-rw-r--r--indra/newview/llworldmapview.cpp16
-rw-r--r--indra/newview/llxmlrpclistener.cpp496
-rw-r--r--indra/newview/llxmlrpclistener.h35
-rw-r--r--indra/newview/llxmlrpctransaction.cpp23
-rw-r--r--indra/newview/llxmlrpctransaction.h6
-rw-r--r--indra/newview/macview_Prefix.h1
-rw-r--r--indra/newview/pipeline.cpp77
-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/viewerRes.rc8
-rw-r--r--indra/newview/skins/default/colors.xml14
-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/loading/loading.html18
-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/bottomtray/Notices_Unread.pngbin0 -> 333 bytes
-rw-r--r--indra/newview/skins/default/textures/bottomtray/Snapshot_Off.pngbin332 -> 3204 bytes
-rw-r--r--indra/newview/skins/default/textures/containers/Accordion_Selected.pngbin0 -> 228 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/ForSale_Badge.pngbin0 -> 5727 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/Info_Over.pngbin0 -> 376 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Alpha.pngbin0 -> 253 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Animation.pngbin486 -> 496 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_BodyShape.pngbin571 -> 641 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Clothing.pngbin255 -> 253 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Eye.pngbin439 -> 491 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderClosed.pngbin215 -> 219 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_FolderOpen.pngbin351 -> 361 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gesture.pngbin413 -> 408 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Gloves.pngbin385 -> 366 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Hair.pngbin366 -> 377 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Jacket.pngbin573 -> 591 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Landmark.pngbin494 -> 532 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.pngbin238 -> 222 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Object.pngbin327 -> 333 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Pants.pngbin375 -> 377 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Script.pngbin463 -> 469 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shirt.pngbin397 -> 402 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Shoe.pngbin284 -> 276 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skin.pngbin382 -> 393 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Skirt.pngbin449 -> 494 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Snapshot.pngbin416 -> 535 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Socks.pngbin347 -> 358 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Sound.pngbin359 -> 404 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Tattoo.pngbin0 -> 253 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Texture.pngbin157 -> 157 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Underpants.pngbin397 -> 418 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/Inv_Undershirt.pngbin208 -> 208 bytes
-rw-r--r--indra/newview/skins/default/textures/icons/YouAreHere_Badge.pngbin0 -> 6143 bytes
-rw-r--r--indra/newview/skins/default/textures/inv_folder_inbox.tgabin0 -> 2085 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Over.pngbin2985 -> 2956 bytes
-rw-r--r--indra/newview/skins/default/textures/navbar/BuyArrow_Press.pngbin249 -> 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/Search.pngbin467 -> 3182 bytes
-rw-r--r--indra/newview/skins/default/textures/textures.xml189
-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/windows/Inspector_Background.pngbin400 -> 348 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Toast_Background.pngbin0 -> 349 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Background.pngbin950 -> 509 bytes
-rw-r--r--indra/newview/skins/default/textures/windows/Window_Foreground.pngbin959 -> 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/xui/da/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_avatar_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_build_options.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_bulk_perms.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_buy_object.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_customize.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_day_cycle_options.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_inspect.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_joystick.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_land_holdings.xml2
-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.xml2
-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_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_openobject.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_postcard.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_preferences.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_notecard.xml2
-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.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_snapshot.xml2
-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_telehub.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/da/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/da/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/da/notifications.xml2
-rw-r--r--indra/newview/skins/default/xui/da/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/da/panel_preferences_alerts.xml20
-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.xml40
-rw-r--r--indra/newview/skins/default/xui/da/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/de/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_avatar_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_build_options.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_bumps.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_contents.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_customize.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_env_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_god_tools.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_inspect.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory_item_properties.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_joystick.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_land_holdings.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_my_friends.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.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_openobject.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_postcard.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preferences.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_preview_notecard.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_region_info.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_report_abuse.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_script_search.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_snapshot.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_telehub.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/de/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/de/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/de/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/de/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_alerts.xml24
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_privacy.xml32
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_setup.xml30
-rw-r--r--indra/newview/skins/default/xui/de/panel_preferences_sound.xml73
-rw-r--r--indra/newview/skins/default/xui/de/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/en/favorites_bar_button.xml14
-rw-r--r--indra/newview/skins/default/xui/en/floater_aaa.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml113
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml71
-rw-r--r--indra/newview/skins/default/xui/en/floater_activeim.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_animation_preview.xml21
-rw-r--r--indra/newview/skins/default/xui/en/floater_auction.xml45
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_picker.xml51
-rw-r--r--indra/newview/skins/default/xui/en/floater_avatar_textures.xml108
-rw-r--r--indra/newview/skins/default/xui/en/floater_beacons.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_build_options.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_bulk_perms.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_bumps.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_contents.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_currency.xml69
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_land.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_buy_object.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_camera.xml178
-rw-r--r--indra/newview/skins/default/xui/en/floater_choose_group.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_color_picker.xml26
-rw-r--r--indra/newview/skins/default/xui/en/floater_critical.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml267
-rw-r--r--indra/newview/skins/default/xui/en/floater_day_cycle_options.xml13
-rw-r--r--indra/newview/skins/default/xui/en/floater_device_settings.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_env_settings.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_first_time_tip.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_font_test.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_gesture.xml12
-rw-r--r--indra/newview/skins/default/xui/en/floater_god_tools.xml43
-rw-r--r--indra/newview/skins/default/xui/en/floater_hardware_settings.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_help_browser.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_hud.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_im.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_im_session.xml51
-rw-r--r--indra/newview/skins/default/xui/en/floater_image_preview.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_incoming_call.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_inspect.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml414
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_joystick.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_lagmeter.xml28
-rw-r--r--indra/newview/skins/default/xui/en/floater_land_holdings.xml106
-rw-r--r--indra/newview/skins/default/xui/en/floater_live_lsleditor.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_lsl_guide.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_map.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_browser.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_media_settings.xml91
-rw-r--r--indra/newview/skins/default/xui/en/floater_mem_leaking.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_moveview.xml33
-rw-r--r--indra/newview/skins/default/xui/en/floater_mute_object.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_my_friends.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_nearby_chat.xml51
-rw-r--r--indra/newview/skins/default/xui/en/floater_notification.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_notifications_console.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_openobject.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay.xml8
-rw-r--r--indra/newview/skins/default/xui/en/floater_pay_object.xml37
-rw-r--r--indra/newview/skins/default/xui/en/floater_perm_prefs.xml17
-rw-r--r--indra/newview/skins/default/xui/en/floater_post_process.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_postcard.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_preferences.xml43
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_animation.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_classified.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_event.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture.xml341
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_notecard.xml11
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_sound.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_preview_texture.xml71
-rw-r--r--indra/newview/skins/default/xui/en/floater_region_info.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_report_abuse.xml106
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_debug_panel.xml5
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_preview.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_queue.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_search.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_search.xml61
-rw-r--r--indra/newview/skins/default/xui/en/floater_select_key.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_sell_land.xml70
-rw-r--r--indra/newview/skins/default/xui/en/floater_settings_debug.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_snapshot.xml7
-rw-r--r--indra/newview/skins/default/xui/en/floater_sound_preview.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_statistics.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_stats.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_sys_well.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_telehub.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_button.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_checkbox.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_combobox.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_inspectors.xml21
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_layout.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_line_editor.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_list_view.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_radiogroup.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_slider.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_spinner.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_textbox.xml68
-rw-r--r--indra/newview/skins/default/xui/en/floater_test_widgets.xml99
-rw-r--r--indra/newview/skins/default/xui/en/floater_texture_ctrl.xml109
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml491
-rw-r--r--indra/newview/skins/default/xui/en/floater_top_objects.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_tos.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_ui_preview.xml40
-rw-r--r--indra/newview/skins/default/xui/en/floater_url_entry.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_water.xml262
-rw-r--r--indra/newview/skins/default/xui/en/floater_wearable_save_as.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_whitelist_entry.xml1
-rw-r--r--indra/newview/skins/default/xui/en/floater_windlight_options.xml228
-rw-r--r--indra/newview/skins/default/xui/en/floater_world_map.xml12
-rw-r--r--indra/newview/skins/default/xui/en/fonts.xml21
-rw-r--r--indra/newview/skins/default/xui/en/inspect_avatar.xml22
-rw-r--r--indra/newview/skins/default/xui/en/inspect_group.xml109
-rw-r--r--indra/newview/skins/default/xui/en/inspect_object.xml63
-rw-r--r--indra/newview/skins/default/xui/en/menu_group_plus.xml2
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml26
-rw-r--r--indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml102
-rw-r--r--indra/newview/skins/default/xui/en/menu_inventory.xml13
-rw-r--r--indra/newview/skins/default/xui/en/menu_landmark.xml11
-rw-r--r--indra/newview/skins/default/xui/en/menu_login.xml53
-rw-r--r--indra/newview/skins/default/xui/en/menu_object_icon.xml27
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml42
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_groups_view_sort.xml13
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml47
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_nearby_view_sort.xml13
-rw-r--r--indra/newview/skins/default/xui/en/menu_people_recent_view_sort.xml39
-rw-r--r--indra/newview/skins/default/xui/en/menu_place.xml3
-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.xml127
-rw-r--r--indra/newview/skins/default/xui/en/menu_places_gear_landmark.xml177
-rw-r--r--indra/newview/skins/default/xui/en/menu_teleport_history_item.xml6
-rw-r--r--indra/newview/skins/default/xui/en/menu_text_editor.xml54
-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.xml7
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_parcel.xml9
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_slurl.xml7
-rw-r--r--indra/newview/skins/default/xui/en/menu_url_teleport.xml9
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml1033
-rw-r--r--indra/newview/skins/default/xui/en/mime_types.xml34
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml994
-rw-r--r--indra/newview/skins/default/xui/en/panel_activeim_row.xml43
-rw-r--r--indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml63
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_list_item.xml59
-rw-r--r--indra/newview/skins/default/xui/en/panel_avatar_tag.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_bars.xml67
-rw-r--r--indra/newview/skins/default/xui/en/panel_bottomtray.xml280
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_header.xml44
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_item.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_chat_separator.xml8
-rw-r--r--indra/newview/skins/default/xui/en/panel_classified.xml4
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_alpha.xml126
-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.xml65
-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.xml77
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pants.xml65
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_pick.xml93
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_profile.xml416
-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.xml65
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_shoes.xml65
-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.xml65
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_socks.xml65
-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.xml65
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_undershirt.xml65
-rw-r--r--indra/newview/skins/default/xui/en/panel_edit_wearable.xml364
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_control_panel.xml96
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_general.xml135
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml268
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_invite.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_land_money.xml239
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_list_item.xml56
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notices.xml253
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_notify.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_group_roles.xml616
-rw-r--r--indra/newview/skins/default/xui/en/panel_im_control_panel.xml127
-rw-r--r--indra/newview/skins/default/xui/en/panel_instant_message.xml43
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmark_info.xml256
-rw-r--r--indra/newview/skins/default/xui/en/panel_landmarks.xml145
-rw-r--r--indra/newview/skins/default/xui/en/panel_login.xml51
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml415
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_general.xml66
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml6
-rw-r--r--indra/newview/skins/default/xui/en/panel_media_settings_security.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_navigation_bar.xml38
-rw-r--r--indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml59
-rw-r--r--indra/newview/skins/default/xui/en/panel_notes.xml127
-rw-r--r--indra/newview/skins/default/xui/en/panel_notification.xml100
-rw-r--r--indra/newview/skins/default/xui/en/panel_notifications_channel.xml1
-rw-r--r--indra/newview/skins/default/xui/en/panel_people.xml295
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_info.xml79
-rw-r--r--indra/newview/skins/default/xui/en/panel_pick_list_item.xml70
-rw-r--r--indra/newview/skins/default/xui/en/panel_picks.xml88
-rw-r--r--indra/newview/skins/default/xui/en/panel_place_profile.xml919
-rw-r--r--indra/newview/skins/default/xui/en/panel_places.xml106
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_advanced.xml175
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_alerts.xml120
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_chat.xml31
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_general.xml81
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml69
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_privacy.xml219
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_setup.xml341
-rw-r--r--indra/newview/skins/default/xui/en/panel_preferences_sound.xml520
-rw-r--r--indra/newview/skins/default/xui/en/panel_prim_media_controls.xml580
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile.xml197
-rw-r--r--indra/newview/skins/default/xui/en/panel_profile_view.xml58
-rw-r--r--indra/newview/skins/default/xui/en/panel_progress.xml7
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_covenant.xml11
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_debug.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_estate.xml102
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general.xml110
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_general_layout.xml110
-rw-r--r--indra/newview/skins/default/xui/en/panel_region_terrain.xml80
-rw-r--r--indra/newview/skins/default/xui/en/panel_scrolling_param.xml2
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray.xml41
-rw-r--r--indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml15
-rw-r--r--indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml130
-rw-r--r--indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml10
-rw-r--r--indra/newview/skins/default/xui/en/panel_status_bar.xml156
-rw-r--r--indra/newview/skins/default/xui/en/panel_sys_well_item.xml69
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history.xml42
-rw-r--r--indra/newview/skins/default/xui/en/panel_teleport_history_item.xml35
-rw-r--r--indra/newview/skins/default/xui/en/panel_toast.xml63
-rw-r--r--indra/newview/skins/default/xui/en/sidepanel_inventory.xml122
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml290
-rw-r--r--indra/newview/skins/default/xui/en/widgets/accordion_tab.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/button.xml1
-rw-r--r--indra/newview/skins/default/xui/en/widgets/chat_history.xml18
-rw-r--r--indra/newview/skins/default/xui/en/widgets/combo_box.xml10
-rw-r--r--indra/newview/skins/default/xui/en/widgets/expandable_text.xml3
-rw-r--r--indra/newview/skins/default/xui/en/widgets/flat_list_view.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/floater.xml6
-rw-r--r--indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml13
-rw-r--r--indra/newview/skins/default/xui/en/widgets/location_input.xml7
-rw-r--r--indra/newview/skins/default/xui/en/widgets/menu.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/output_monitor.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/panel.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_combo_box.xml8
-rw-r--r--indra/newview/skins/default/xui/en/widgets/search_editor.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/split_button.xml23
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tab_container.xml24
-rw-r--r--indra/newview/skins/default/xui/en/widgets/talk_button.xml35
-rw-r--r--indra/newview/skins/default/xui/en/widgets/text.xml2
-rw-r--r--indra/newview/skins/default/xui/en/widgets/textbase.xml4
-rw-r--r--indra/newview/skins/default/xui/en/widgets/tool_tip.xml10
-rw-r--r--indra/newview/skins/default/xui/es/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_avatar_picker.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_buy_object.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_customize.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_day_cycle_options.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_god_tools.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_inspect.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_joystick.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_land_holdings.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_openobject.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_preferences.xml2
-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_notecard.xml2
-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.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_snapshot.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/es/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/es/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/es/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/es/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/es/panel_preferences_alerts.xml18
-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/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_avatar_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_avatar_textures.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_beacons.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_build_options.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_bulk_perms.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_bumps.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_buy_object.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_choose_group.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_color_picker.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_customize.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_env_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_god_tools.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inspect.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory_item_properties.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_joystick.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_land_holdings.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_my_friends.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.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_openobject.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preferences.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_classified.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_event.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_preview_notecard.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_queue.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_script_search.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_snapshot.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_telehub.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/fr/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/fr/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/fr/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml21
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml32
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_setup.xml30
-rw-r--r--indra/newview/skins/default/xui/fr/panel_preferences_sound.xml40
-rw-r--r--indra/newview/skins/default/xui/fr/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/it/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_avatar_picker.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_buy_object.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_customize.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_day_cycle_options.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_font_test.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_gesture.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_inspect.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_land_holdings.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_mute_object.xml2
-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_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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_preferences.xml2
-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_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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_snapshot.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/it/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/it/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/it/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/it/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/it/panel_preferences_alerts.xml18
-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/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/ja/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_device_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_script_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_sound_preview.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/floater_tools.xml2
-rw-r--r--indra/newview/skins/default/xui/ja/notifications.xml8
-rw-r--r--indra/newview/skins/default/xui/ja/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml21
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml32
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_setup.xml31
-rw-r--r--indra/newview/skins/default/xui/ja/panel_preferences_sound.xml77
-rw-r--r--indra/newview/skins/default/xui/ja/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/nl/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_about_land.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_buy_object.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_customize.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_env_settings.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_inventory.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_joystick.xml2
-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_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_openobject.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_perm_prefs.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_post_process.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_postcard.xml2
-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.xml2
-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_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_snapshot.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_statistics.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_telehub.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/nl/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/nl/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/nl/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/nl/strings.xml38
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_about_land.xml2
-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.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_land.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_buy_object.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_choose_group.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_color_picker.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_customize.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_day_cycle_options.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_device_settings.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_env_settings.xml2
-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.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_hardware_settings.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_hud.xml2
-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.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_inventory_view_finder.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_joystick.xml4
-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
-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_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.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/floater_perm_prefs.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_post_process.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_postcard.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_preferences.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_notecard.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_region_info.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_report_abuse.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_debug.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_preview.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_queue.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_script_search.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_sell_land.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_settings_debug.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_snapshot.xml2
-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.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_texture_ctrl.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_tools.xml4
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_top_objects.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_water.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_windlight_options.xml2
-rwxr-xr-xindra/newview/skins/default/xui/pl/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/pl/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/pl/panel_edit_profile.xml45
-rwxr-xr-xindra/newview/skins/default/xui/pl/panel_preferences_alerts.xml21
-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/strings.xml38
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_about_land.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_auction.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_avatar_picker.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_currency.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_land.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_buy_object.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_customize.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_day_cycle_options.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_hardware_settings.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_hud.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inspect.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_inventory_view_finder.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_joystick.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_lagmeter.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_land_holdings.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_live_lsleditor.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_lsl_guide.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_media_browser.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_mem_leaking.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_mute_object.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_my_friends.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_openobject.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_preferences.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_notecard.xml2
-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.xml2
-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.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_sell_land.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_settings_debug.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_snapshot.xml2
-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.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_texture_ctrl.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_tools.xml4
-rw-r--r--indra/newview/skins/default/xui/pt/floater_top_objects.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_water.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_windlight_options.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/floater_world_map.xml2
-rw-r--r--indra/newview/skins/default/xui/pt/notifications.xml6
-rw-r--r--indra/newview/skins/default/xui/pt/panel_edit_profile.xml45
-rw-r--r--indra/newview/skins/default/xui/pt/panel_preferences_alerts.xml18
-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/strings.xml38
-rw-r--r--indra/newview/tests/llagentaccess_test.cpp2
-rw-r--r--indra/newview/tests/llcapabilitylistener_test.cpp61
-rw-r--r--indra/newview/tests/lldateutil_test.cpp3
-rw-r--r--indra/newview/tests/lllogininstance_test.cpp423
-rw-r--r--indra/newview/tests/llmediadataclient_test.cpp501
-rw-r--r--indra/newview/tests/llviewerhelputil_test.cpp3
-rw-r--r--indra/newview/tests/llxmlrpclistener_test.cpp230
-rw-r--r--indra/newview/tests/test_llxmlrpc_peer.py59
-rwxr-xr-xindra/newview/viewer_manifest.py253
-rw-r--r--indra/test/CMakeLists.txt38
-rw-r--r--indra/test/debug.h68
-rw-r--r--indra/test/llevents_tut.cpp133
-rwxr-xr-xindra/test/llsdmessagebuilder_tut.cpp2
-rwxr-xr-xindra/test/llsdmessagereader_tut.cpp1
-rw-r--r--indra/test/llsdutil_tut.cpp235
-rw-r--r--indra/test/lltut.cpp12
-rw-r--r--indra/test/lltut.h5
-rw-r--r--indra/test/test.cpp12
-rw-r--r--indra/test_apps/llplugintest/CMakeLists.txt196
-rw-r--r--indra/test_apps/llplugintest/bookmarks.txt11
-rw-r--r--indra/test_apps/llplugintest/llmediaplugintest.cpp57
-rw-r--r--indra/tools/vstool/README.txt18
-rw-r--r--indra/tools/vstool/VSTool.csproj188
-rw-r--r--indra/tools/vstool/VSTool.sln38
-rw-r--r--indra/tools/vstool/main.cs1422
-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.cpp374
-rw-r--r--indra/viewer_components/login/lllogin.h133
-rw-r--r--indra/viewer_components/login/tests/lllogin_test.cpp417
1866 files changed, 77988 insertions, 35403 deletions
diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt
index 9418dbf271..261c0b17e2 100644
--- a/indra/CMakeLists.txt
+++ b/indra/CMakeLists.txt
@@ -66,6 +66,7 @@ if (VIEWER)
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)
diff --git a/indra/cmake/00-Common.cmake b/indra/cmake/00-Common.cmake
index 2a70263446..db5495091e 100644
--- a/indra/cmake/00-Common.cmake
+++ b/indra/cmake/00-Common.cmake
@@ -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 ${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} GREATER 429)
add_definitions(-Wno-parentheses)
set(CMAKE_CXX_FLAGS "-Wno-deprecated ${CMAKE_CXX_FLAGS}")
- endif (${CXX_VERSION} MATCHES "4.3")
+ endif (${CXX_VERSION} 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 -Woverloaded-virtual")
+ 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}")
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 3ce393b659..4563b59ad2 100644
--- a/indra/cmake/CMakeLists.txt
+++ b/indra/cmake/CMakeLists.txt
@@ -53,6 +53,7 @@ set(cmake_SOURCE_FILES
LLPrimitive.cmake
LLRender.cmake
LLScene.cmake
+ LLTestCommand.cmake
LLUI.cmake
LLVFS.cmake
LLWindow.cmake
@@ -69,7 +70,6 @@ set(cmake_SOURCE_FILES
PNG.cmake
Python.cmake
Prebuilt.cmake
- RunBuildTest.cmake
TemplateCheck.cmake
Tut.cmake
UI.cmake
diff --git a/indra/cmake/DeploySharedLibs.cmake b/indra/cmake/DeploySharedLibs.cmake
new file mode 100644
index 0000000000..a7e772bd75
--- /dev/null
+++ b/indra/cmake/DeploySharedLibs.cmake
@@ -0,0 +1,67 @@
+# 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.
+include(GetPrerequisites)
+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/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/LLAddBuildTest.cmake b/indra/cmake/LLAddBuildTest.cmake
index 008b277960..d8f64199cf 100644
--- a/indra/cmake/LLAddBuildTest.cmake
+++ b/indra/cmake/LLAddBuildTest.cmake
@@ -1,4 +1,6 @@
# -*- 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),
@@ -13,6 +15,8 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
#
# WARNING: do NOT modify this code without working with poppy -
# there is another branch that will conflict heavily with any changes here.
+INCLUDE(GoogleMock)
+
IF(LL_TEST_VERBOSE)
MESSAGE("LL_ADD_PROJECT_UNIT_TESTS UNITTEST_PROJECT_${project} sources: ${sources}")
@@ -41,8 +45,10 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${LLMATH_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${LIBS_OPEN_DIR}/test
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
SET(alltest_LIBRARIES
+ ${GOOGLEMOCK_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
)
@@ -51,6 +57,11 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
${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})
@@ -93,9 +104,9 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
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})
-
#
# Per-codefile additional / external project dep and lib dep property extraction
#
@@ -123,16 +134,20 @@ MACRO(LL_ADD_PROJECT_UNIT_TESTS project sources)
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
+
+ # 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)
- 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(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/usr/lib)
+ ENDIF(WINDOWS)
+
+ 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)
@@ -176,6 +191,7 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
SET(libraries
${library_dependencies}
+ ${GOOGLEMOCK_LIBRARIES}
${PTHREAD_LIBRARY}
)
@@ -212,12 +228,14 @@ FUNCTION(LL_ADD_INTEGRATION_TEST
LIST(INSERT test_command test_exe_pos "${TEST_EXE}")
ENDIF (test_exe_pos LESS 0)
- SET(TEST_SCRIPT_CMD
- ${CMAKE_COMMAND}
- -DLD_LIBRARY_PATH=${ARCH_PREBUILT_DIRS}:/usr/lib
- -DTEST_CMD:STRING="${test_command}"
- -P ${CMAKE_SOURCE_DIR}/cmake/RunBuildTest.cmake
- )
+ IF(WINDOWS)
+ set(LD_LIBRARY_PATH ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR})
+ ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/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}")
diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake
index ef202dd879..d1ab264a41 100644
--- a/indra/cmake/LLCommon.cmake
+++ b/indra/cmake/LLCommon.cmake
@@ -17,3 +17,7 @@ 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/LLSharedLibs.cmake b/indra/cmake/LLSharedLibs.cmake
new file mode 100644
index 0000000000..a8c81609bb
--- /dev/null
+++ b/indra/cmake/LLSharedLibs.cmake
@@ -0,0 +1,31 @@
+# ll_deploy_sharedlibs_command
+# target_exe: the cmake target of the executable for which the shared libs will be deployed.
+# search_dirs: a list of dirs to search for the dependencies
+# dst_path: path to copy deps to, relative to the output location of the target_exe
+macro(ll_deploy_sharedlibs_command target_exe search_dirs dst_path)
+ get_target_property(OUTPUT_LOCATION ${target_exe} LOCATION)
+
+ if(DARWIN)
+ get_target_property(IS_BUNDLE ${target_exe} MACOSX_BUNDLE)
+ if(IS_BUNDLE)
+ get_filename_component(TARGET_FILE ${OUTPUT_LOCATION} NAME)
+ set(OUTPUT_PATH ${OUTPUT_LOCATION}.app/Contents/MacOS)
+ set(OUTPUT_LOCATION ${OUTPUT_PATH}/${TARGET_FILE})
+ endif(IS_BUNDLE)
+ else(DARWIN)
+ message(FATAL_ERROR "Only darwin currently supported!")
+ endif(DARWIN)
+
+ add_custom_command(
+ TARGET ${target_exe} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ "-DBIN_NAME=\"${OUTPUT_LOCATION}\""
+ "-DSEARCH_DIRS=\"${search_dirs}\""
+ "-DDST_PATH=\"${OUTPUT_PATH}/${dst_path}\""
+ "-P"
+ "${CMAKE_SOURCE_DIR}/cmake/DeploySharedLibs.cmake"
+ )
+
+endmacro(ll_deploy_sharedlibs_command)
+
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/Linking.cmake b/indra/cmake/Linking.cmake
index eaa8a6dc29..1f3553539f 100644
--- a/indra/cmake/Linking.cmake
+++ b/indra/cmake/Linking.cmake
@@ -5,6 +5,7 @@ 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")
elseif (LINUX)
if (VIEWER)
set(ARCH_PREBUILT_DIRS ${LIBS_PREBUILT_DIR}/${LL_ARCH_DIR}/lib_release_client)
@@ -13,10 +14,12 @@ 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 CACHE FILEPATH "Location of staged .sos")
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")
endif (WINDOWS)
endif (NOT STANDALONE)
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/WebKitLibPlugin.cmake b/indra/cmake/WebKitLibPlugin.cmake
index 9ec23e80ca..1c572ab27f 100644
--- a/indra/cmake/WebKitLibPlugin.cmake
+++ b/indra/cmake/WebKitLibPlugin.cmake
@@ -51,6 +51,7 @@ elseif (LINUX)
QtGui
QtCore
+ jpeg
fontconfig
X11
Xrender
diff --git a/indra/cmake/run_build_test.py b/indra/cmake/run_build_test.py
new file mode 100644
index 0000000000..fff78ecbe3
--- /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 b2b494d1b3..7836c97473 100755
--- a/indra/develop.py
+++ b/indra/develop.py
@@ -439,7 +439,6 @@ class DarwinSetup(UnixSetup):
)
if self.universal == 'ON':
args['universal'] = '-DCMAKE_OSX_ARCHITECTURES:STRING=\'i386;ppc\''
- pass
#if simple:
# return 'cmake %(opts)s %(dir)r' % args
return ('cmake -G %(generator)r '
diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp
index 3631761c93..abd8f7dbde 100644
--- a/indra/integration_tests/llui_libtest/llui_libtest.cpp
+++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp
@@ -84,12 +84,12 @@ class LLTexture ;
class TestImageProvider : public LLImageProviderInterface
{
public:
- /*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name)
+ /*virtual*/ LLPointer<LLUIImage> getUIImage(const std::string& name, S32 priority)
{
return makeImage();
}
- /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id)
+ /*virtual*/ LLPointer<LLUIImage> getUIImageByID(const LLUUID& id, S32 priority)
{
return makeImage();
}
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/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/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp
index 099c4eba40..ae959eaa81 100644
--- a/indra/llaudio/llaudiodecodemgr.cpp
+++ b/indra/llaudio/llaudiodecodemgr.cpp
@@ -43,6 +43,8 @@
#include "llassetstorage.h"
#include "llrefcount.h"
+#include "llvorbisencode.h"
+
#include "vorbis/codec.h"
#include "vorbis/vorbisfile.h"
@@ -218,11 +220,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/llvorbisencode.cpp b/indra/llaudio/llvorbisencode.cpp
index 8ee082a245..0c1ad8191c 100644
--- a/indra/llaudio/llvorbisencode.cpp
+++ b/indra/llaudio/llvorbisencode.cpp
@@ -162,13 +162,13 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
return(LLVORBISENC_PCM_FORMAT_ERR);
}
- if ((num_channels < 1) || (num_channels > 2))
+ if ((num_channels < 1) || (num_channels > LLVORBIS_CLIP_MAX_CHANNELS))
{
error_msg = "SoundFileInvalidChannelCount";
return(LLVORBISENC_MULTICHANNEL_ERR);
}
- if (sample_rate != 44100)
+ if (sample_rate != LLVORBIS_CLIP_SAMPLE_RATE)
{
error_msg = "SoundFileInvalidSampleRate";
return(LLVORBISENC_UNSUPPORTED_SAMPLE_RATE);
@@ -188,7 +188,7 @@ S32 check_for_invalid_wav_formats(const std::string& in_fname, std::string& erro
F32 clip_length = (F32)raw_data_length/(F32)bytes_per_sec;
- if (clip_length > 10.0f)
+ if (clip_length > LLVORBIS_CLIP_MAX_TIME)
{
error_msg = "SoundFileInvalidTooLong";
return(LLVORBISENC_CLIP_TOO_LONG);
diff --git a/indra/llaudio/llvorbisencode.h b/indra/llaudio/llvorbisencode.h
index ff5ce3a053..6531c1919e 100644
--- a/indra/llaudio/llvorbisencode.h
+++ b/indra/llaudio/llvorbisencode.h
@@ -45,6 +45,17 @@ const S32 LLVORBISENC_UNSUPPORTED_SAMPLE_RATE = 8; // unsupported sample ra
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);
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 24391eb8f3..3dd54b4760 100644
--- a/indra/llcharacter/llbvhloader.cpp
+++ b/indra/llcharacter/llbvhloader.cpp
@@ -91,7 +91,9 @@ 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()
//------------------------------------------------------------------------
@@ -777,6 +779,17 @@ ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &
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
//----------------------------------------------------------------
diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h
index ecdfc95478..85ab035e61 100644
--- a/indra/llcharacter/llbvhloader.h
+++ b/indra/llcharacter/llbvhloader.h
@@ -216,7 +216,8 @@ typedef enum e_load_status
E_ST_NO_XLT_EASEIN,
E_ST_NO_XLT_EASEOUT,
E_ST_NO_XLT_HAND,
- E_ST_NO_XLT_EMOTE
+ E_ST_NO_XLT_EMOTE,
+ E_ST_BAD_ROOT
} ELoadStatus;
//------------------------------------------------------------------------
@@ -235,7 +236,7 @@ public:
/*
// 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;
@@ -267,6 +268,7 @@ 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.
ELoadStatus loadTranslationTable(const char *fileName);
@@ -325,6 +327,7 @@ protected:
BOOL mInitialized;
ELoadStatus mStatus;
+
// computed values
F32 mDuration;
};
diff --git a/indra/llcharacter/llcharacter.cpp b/indra/llcharacter/llcharacter.cpp
index 20ff7bab34..e68672d46f 100644
--- a/indra/llcharacter/llcharacter.cpp
+++ b/indra/llcharacter/llcharacter.cpp
@@ -276,7 +276,7 @@ void LLCharacter::removeAnimationData(std::string name)
BOOL LLCharacter::setVisualParamWeight(LLVisualParam* which_param, F32 weight, BOOL set_by_user)
{
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);
@@ -293,7 +293,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
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);
@@ -308,7 +308,7 @@ BOOL LLCharacter::setVisualParamWeight(const char* param_name, F32 weight, BOOL
//-----------------------------------------------------------------------------
BOOL LLCharacter::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user)
{
- 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);
@@ -324,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();
@@ -344,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();
@@ -358,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();
@@ -415,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;
@@ -430,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;
@@ -457,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;
}
@@ -473,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 cd8f9e63fb..cb44a32e8a 100644
--- a/indra/llcharacter/llcharacter.h
+++ b/indra/llcharacter/llcharacter.h
@@ -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 set_by_user = FALSE );
+ virtual BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
+ virtual BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = FALSE );
// get visual param weight by param or name
F32 getVisualParamWeight(LLVisualParam *distortion);
@@ -233,12 +233,12 @@ public:
LLVisualParam* getVisualParam(S32 id) const
{
- VisualParamIndexMap_t::const_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)
@@ -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/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/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/llvisualparam.cpp b/indra/llcharacter/llvisualparam.cpp
index d7a144e00c..6232c7588b 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)
{
}
@@ -236,6 +252,13 @@ void LLVisualParam::setWeight(F32 weight, BOOL set_by_user)
//-----------------------------------------------------------------------------
void LLVisualParam::setAnimationTarget(F32 target_value, BOOL set_by_user)
{
+ // don't animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, set_by_user);
+ return;
+ }
+
if (mInfo)
{
if (getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE)
@@ -288,3 +311,17 @@ void LLVisualParam::stopAnimating(BOOL set_by_user)
setWeight(mTargetWeight, set_by_user);
}
}
+
+//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 25c41e8509..eec56d7844 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();
@@ -111,6 +118,9 @@ public:
virtual void animate(F32 delta, BOOL set_by_user);
virtual void stopAnimating(BOOL set_by_user);
+ virtual BOOL linkDrivenParams(visual_param_mapper mapper, BOOL only_cross_params);
+ virtual void resetDrivenParams();
+
// Interface methods
S32 getID() const { return mID; }
void setID(S32 id) { llassert(!mInfo); mID = id; }
@@ -138,15 +148,19 @@ public:
LLVisualParam* getNextParam() { return mNext; }
void setNextParam( LLVisualParam *next );
- virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; }
+ 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
F32 mLastWeight; // last weight
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 48e053b8ee..f785698612 100644
--- a/indra/llcommon/CMakeLists.txt
+++ b/indra/llcommon/CMakeLists.txt
@@ -4,12 +4,19 @@ project(llcommon)
include(00-Common)
include(LLCommon)
+include(Linking)
include(Boost)
+include (Pth)
+
+if (WINDOWS)
+ include(CopyWinLibs)
+endif (WINDOWS)
include_directories(
${EXPAT_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
${ZLIB_INCLUDE_DIRS}
+ ${PTH_INCLUDE_DIRS}
)
# add_executable(lltreeiterators lltreeiterators.cpp)
@@ -26,6 +33,7 @@ set(llcommon_SOURCE_FILES
llbase32.cpp
llbase64.cpp
llcommon.cpp
+ llcoros.cpp
llcrc.cpp
llcriticaldamp.cpp
llcursortypes.cpp
@@ -34,11 +42,15 @@ set(llcommon_SOURCE_FILES
llerror.cpp
llerrorthread.cpp
llevent.cpp
+ lleventcoro.cpp
+ lleventdispatcher.cpp
+ lleventfilter.cpp
llevents.cpp
llfasttimer.cpp
llfile.cpp
llfindlocale.cpp
llfixedbuffer.cpp
+ llfoldertype.cpp
llformat.cpp
llframetimer.cpp
llheartbeat.cpp
@@ -64,6 +76,7 @@ set(llcommon_SOURCE_FILES
llsdserialize_xml.cpp
llsdutil.cpp
llsecondlifeurls.cpp
+ llsingleton.cpp
llstat.cpp
llstacktrace.cpp
llstreamtools.cpp
@@ -106,6 +119,7 @@ set(llcommon_HEADER_FILES
llchat.h
llclickaction.h
llcommon.h
+ llcoros.h
llcrc.h
llcriticaldamp.h
llcursortypes.h
@@ -127,6 +141,9 @@ set(llcommon_HEADER_FILES
llerrorlegacy.h
llerrorthread.h
llevent.h
+ lleventcoro.h
+ lleventdispatcher.h
+ lleventfilter.h
llevents.h
lleventemitter.h
llextendedstatus.h
@@ -134,6 +151,7 @@ set(llcommon_HEADER_FILES
llfile.h
llfindlocale.h
llfixedbuffer.h
+ llfoldertype.h
llformat.h
llframetimer.h
llhash.h
@@ -141,6 +159,7 @@ set(llcommon_HEADER_FILES
llhttpstatuscodes.h
llindexedqueue.h
llinstancetracker.h
+ llinstancetracker.h
llkeythrottle.h
lllazy.h
lllinkedqueue.h
@@ -222,33 +241,81 @@ set_source_files_properties(${llcommon_HEADER_FILES}
list(APPEND llcommon_SOURCE_FILES ${llcommon_HEADER_FILES})
-add_library (llcommon ${llcommon_SOURCE_FILES})
-target_link_libraries(llcommon
+if(LLCOMMON_LINK_SHARED)
+ add_library (llcommon SHARED ${llcommon_SOURCE_FILES})
+
+ if(SHARED_LIB_STAGING_DIR)
+ # *FIX:Mani ---
+ # llcommon.dll get written to the DLL staging directory.
+ # Also this directory is shared with RunBuildTest.cmake, y'know, for the tests.
+ set_target_properties(llcommon PROPERTIES RUNTIME_OUTPUT_DIRECTORY ${SHARED_LIB_STAGING_DIR})
+ if(NOT WINDOWS)
+ get_target_property(LLCOMMON_PATH llcommon LOCATION)
+ get_filename_component(LLCOMMON_FILE ${LLCOMMON_PATH} NAME)
+ add_custom_command(
+ TARGET llcommon POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ copy_if_different
+ ${LLCOMMON_PATH}
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}/${LLCOMMON_FILE}
+ COMMENT "Copying llcommon to the staging folder."
+ )
+ endif(NOT WINDOWS)
+ endif(SHARED_LIB_STAGING_DIR)
+
+ if (DARWIN)
+ set_target_properties(llcommon PROPERTIES
+ BUILD_WITH_INSTALL_RPATH 1
+ INSTALL_NAME_DIR "@executable_path/../Resources"
+ )
+ endif(DARWIN)
+
+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}
)
-#add unit tests
-INCLUDE(LLAddBuildTest)
+add_dependencies(llcommon stage_third_party_libs)
+
+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})
+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(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)
+
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/indra_constants.h b/indra/llcommon/indra_constants.h
index 4836d41fb3..6b75a720af 100644
--- a/indra/llcommon/indra_constants.h
+++ b/indra/llcommon/indra_constants.h
@@ -253,6 +253,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;
diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h
index 8687a24655..c2eb867795 100644
--- a/indra/llcommon/linden_common.h
+++ b/indra/llcommon/linden_common.h
@@ -72,13 +72,7 @@
#ifdef LL_WINDOWS
// Reenable warnings we disabled above
#pragma warning (3 : 4702) // unreachable code, 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)) )
+// 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
diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h
index 2b70fee0b8..50129b4526 100644
--- a/indra/llcommon/llallocator.h
+++ b/indra/llcommon/llallocator.h
@@ -38,7 +38,7 @@
#include "llmemtype.h"
#include "llallocator_heap_profile.h"
-class LLAllocator {
+class LL_COMMON_API LLAllocator {
friend class LLMemoryView;
friend class LLMemType;
diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp
index d82ee9ed81..0a807702d0 100644
--- a/indra/llcommon/llallocator_heap_profile.cpp
+++ b/indra/llcommon/llallocator_heap_profile.cpp
@@ -38,6 +38,7 @@
// 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>
diff --git a/indra/llcommon/llapp.h b/indra/llcommon/llapp.h
index e32a293f1c..1a052ce62d 100644
--- a/indra/llcommon/llapp.h
+++ b/indra/llcommon/llapp.h
@@ -62,7 +62,7 @@ public:
};
#endif
-class LLApp : public LLOptionInterface
+class LL_COMMON_API LLApp : public LLOptionInterface
{
friend class LLErrorThread;
public:
diff --git a/indra/llcommon/llapr.h b/indra/llcommon/llapr.h
index 63130a89fc..a1fcd2cf8d 100644
--- a/indra/llcommon/llapr.h
+++ b/indra/llcommon/llapr.h
@@ -48,25 +48,25 @@
#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) ;
@@ -92,7 +92,7 @@ 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);
@@ -118,7 +118,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,7 +192,7 @@ 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
{
private:
apr_file_t* mFile ;
@@ -250,10 +250,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 5d7672b378..6d5b12d840 100644
--- a/indra/llcommon/llassettype.cpp
+++ b/indra/llcommon/llassettype.cpp
@@ -43,30 +43,21 @@
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
- const char *category_name, // used by llinventorymodel when creating new categories
- EDragAndDropType dad_type,
- bool can_link, // can you create a link to this type?
- bool is_protected) // can the viewer change categories of this type?
+ 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),
- mCategoryName(category_name),
- mDadType(dad_type),
- mCanLink(can_link),
- mIsProtected(is_protected)
+ mCanLink(can_link)
{
llassert(strlen(mTypeName) <= 8);
}
const char *mTypeName;
const char *mHumanName;
- const char *mCategoryName;
- EDragAndDropType mDadType;
bool mCanLink;
- bool mIsProtected;
};
class LLAssetDictionary : public LLSingleton<LLAssetDictionary>,
@@ -78,48 +69,32 @@ public:
LLAssetDictionary::LLAssetDictionary()
{
- // DESCRIPTION TYPE NAME HUMAN NAME CATEGORY NAME DRAG&DROP CAN LINK? PROTECTED?
- // |--------------------|-----------|-------------------|-------------------|---------------|-----------|-----------|
- addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE, TRUE, TRUE));
- addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND, TRUE, TRUE));
- addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD, TRUE, TRUE));
- addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK, TRUE, TRUE));
- addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING, TRUE, TRUE));
- addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT, TRUE, TRUE));
- addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD, TRUE, TRUE));
- addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY, TRUE, TRUE));
- addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY, TRUE, TRUE));
- addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT, TRUE, TRUE));
- addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART, TRUE, TRUE));
- addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed SoundS", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE, TRUE, TRUE));
- addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION, TRUE, TRUE));
- addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE, TRUE, TRUE));
- addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE, FALSE, TRUE));
- addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE, FALSE, TRUE));
-
- addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "Link", DAD_LINK, FALSE, TRUE));
- addEntry(LLAssetType::AT_LINK_FOLDER, new AssetEntry("FOLDER_LINK", "link_f", "symbolic folder link", "New Folder", DAD_LINK, FALSE, TRUE));
-
- for (S32 ensemble_num = S32(LLAssetType::AT_FOLDER_ENSEMBLE_START);
- ensemble_num <= S32(LLAssetType::AT_FOLDER_ENSEMBLE_END);
- ensemble_num++)
- {
- addEntry(LLAssetType::EType(ensemble_num), new AssetEntry("ENSEMBLE", "ensemble", "ensemble", "New Folder", DAD_CATEGORY, TRUE, FALSE));
- }
-
- addEntry(LLAssetType::AT_CURRENT_OUTFIT, new AssetEntry("CURRENT", "current", "current outfit", "Current Outfit", DAD_CATEGORY, FALSE, TRUE));
- addEntry(LLAssetType::AT_OUTFIT, new AssetEntry("OUTFIT", "outfit", "outfit", "New Outfit", DAD_CATEGORY, TRUE, FALSE));
- addEntry(LLAssetType::AT_MY_OUTFITS, new AssetEntry("MY_OUTFITS", "my_otfts", "my outfits", "My Outfits", DAD_CATEGORY, FALSE, TRUE));
-
- addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE, FALSE, FALSE));
+ // 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));
};
// static
@@ -140,8 +115,7 @@ const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type)
}
else
{
- static const std::string error_string = "BAD TYPE";
- return error_string;
+ return badLookup();
}
}
@@ -156,7 +130,7 @@ const char *LLAssetType::lookup(LLAssetType::EType asset_type)
}
else
{
- return "-1";
+ return badLookup().c_str();
}
}
@@ -166,6 +140,7 @@ LLAssetType::EType LLAssetType::lookup(const char* name)
return lookup(ll_safe_string(name));
}
+// static
LLAssetType::EType LLAssetType::lookup(const std::string& type_name)
{
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
@@ -193,7 +168,7 @@ const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type)
}
else
{
- return NULL;
+ return badLookup().c_str();
}
}
@@ -203,6 +178,7 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const char* name)
return lookupHumanReadable(ll_safe_string(name));
}
+// static
LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name)
{
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
@@ -211,7 +187,7 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_
iter++)
{
const AssetEntry *entry = iter->second;
- if (readable_name == entry->mHumanName)
+ if (entry->mHumanName && (readable_name == entry->mHumanName))
{
return iter->first;
}
@@ -220,32 +196,6 @@ LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_
}
// static
-const char *LLAssetType::lookupCategoryName(LLAssetType::EType asset_type)
-{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mCategoryName;
- }
- else
- {
- return "New Folder";
- }
-}
-
-// static
-EDragAndDropType LLAssetType::lookupDragAndDropType(EType asset_type)
-{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- return entry->mDadType;
- else
- return DAD_NONE;
-}
-
-// static
bool LLAssetType::lookupCanLink(EType asset_type)
{
const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
@@ -269,36 +219,9 @@ bool LLAssetType::lookupIsLinkType(EType asset_type)
}
// static
-// Only ensembles and plain folders aren't protected. "Protected" means
-// you can't change certain properties such as their type.
-bool LLAssetType::lookupIsProtectedCategoryType(EType asset_type)
+const std::string &LLAssetType::badLookup()
{
- const LLAssetDictionary *dict = LLAssetDictionary::getInstance();
- const AssetEntry *entry = dict->lookup(asset_type);
- if (entry)
- {
- return entry->mIsProtected;
- }
- return true;
-}
+ static const std::string sBadLookup = "llassettype_bad_lookup";
+ return sBadLookup;
-// static
-bool LLAssetType::lookupIsEnsembleCategoryType(EType asset_type)
-{
- return (asset_type >= AT_FOLDER_ENSEMBLE_START &&
- asset_type <= AT_FOLDER_ENSEMBLE_END);
-}
-
-// static. Generate a good default description
-void LLAssetType::generateDescriptionFor(LLAssetType::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/llcommon/llassettype.h b/indra/llcommon/llassettype.h
index 5e51188541..ec2290d30e 100644
--- a/indra/llcommon/llassettype.h
+++ b/indra/llcommon/llassettype.h
@@ -37,7 +37,7 @@
#include "stdenums.h" // for EDragAndDropType
-class LLAssetType
+class LL_COMMON_API LLAssetType
{
public:
enum EType
@@ -94,18 +94,6 @@ public:
AT_BODYPART = 13,
// A collection of textures and parameters that can be worn by an avatar.
- AT_TRASH = 14,
- // Only to be used as a marker for a category preferred type.
- // Using this, we can throw things in the trash before completely deleting.
-
- AT_SNAPSHOT_CATEGORY = 15,
- // 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_LOST_AND_FOUND = 16,
- // Used to stuff lost&found items into.
-
AT_SOUND_WAV = 17,
// Uncompressed sound.
@@ -126,37 +114,22 @@ public:
AT_SIMSTATE = 22,
// Simstate file.
- AT_FAVORITE = 23,
- // favorite items
-
AT_LINK = 24,
// Inventory symbolic link
AT_LINK_FOLDER = 25,
// Inventory folder link
-
- AT_FOLDER_ENSEMBLE_START = 26,
- AT_FOLDER_ENSEMBLE_END = 45,
- // This range is reserved for special clothing folder types.
-
- AT_CURRENT_OUTFIT = 46,
- // Current outfit
-
- AT_OUTFIT = 47,
- // Predefined outfit ("look")
-
- AT_MY_OUTFITS = 48,
- // Folder that holds your outfits.
-
- AT_COUNT = 49,
+ AT_COUNT = 26,
+
// +*********************************************************+
// | TO ADD AN ELEMENT TO THIS ENUM: |
// +*********************************************************+
// | 1. INSERT BEFORE AT_COUNT |
// | 2. INCREMENT AT_COUNT BY 1 |
- // | 3. ADD TO LLAssetDictionary in LLAssetType.cpp |
- // | 3. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
+ // | 3. ADD TO LLAssetType.cpp |
+ // | 4. ADD TO LLViewerAssetType.cpp |
+ // | 5. ADD TO DEFAULT_ASSET_FOR_INV in LLInventoryType.cpp |
// +*********************************************************+
AT_NONE = -1
@@ -172,33 +145,17 @@ public:
static EType lookupHumanReadable(const std::string& readable_name);
static const char* lookupHumanReadable(EType asset_type);
- // 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 asset_type,
- std::string& description);
-
static EType getType(const std::string& desc_name);
static const std::string& getDesc(EType asset_type);
- static EDragAndDropType lookupDragAndDropType(EType asset_type);
static bool lookupCanLink(EType asset_type);
static bool lookupIsLinkType(EType asset_type);
- static const char* lookupCategoryName(EType asset_type);
- static bool lookupIsProtectedCategoryType(EType asset_type);
- static bool lookupIsEnsembleCategoryType(EType asset_type);
-
- /* TODO: Change return types from "const char *" to "const std::string &".
- This is fairly straightforward, but requires changing some calls to use .c_str().
- e.g.:
- - fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType));
- + fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType).c_str());
- */
-
-private:
- // don't instantiate or derive one of these objects
- LLAssetType( void ) {}
- ~LLAssetType( void ) {}
+ static const std::string& badLookup(); // error string when a lookup fails
+
+protected:
+ LLAssetType() {}
+ ~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/llcommon.h b/indra/llcommon/llcommon.h
index a1808e8a6c..b36471f9f8 100644
--- a/indra/llcommon/llcommon.h
+++ b/indra/llcommon/llcommon.h
@@ -37,7 +37,7 @@
#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.h b/indra/llcommon/llcursortypes.h
index 35dbeaf16e..a1b8178bfe 100644
--- a/indra/llcommon/llcursortypes.h
+++ b/indra/llcommon/llcursortypes.h
@@ -71,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.h b/indra/llcommon/lldate.h
index 2655a2d283..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:
/**
@@ -156,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/lldependencies.h b/indra/llcommon/lldependencies.h
index 82f53c6e17..e6229db834 100644
--- a/indra/llcommon/lldependencies.h
+++ b/indra/llcommon/lldependencies.h
@@ -81,7 +81,7 @@ struct instance_from_range: public TYPE
* LLDependencies components that should not be reinstantiated for each KEY,
* NODE specialization
*/
-class LLDependenciesBase
+class LL_COMMON_API LLDependenciesBase
{
public:
virtual ~LLDependenciesBase() {}
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 fab0a1ef9f..233e9d3389 100644
--- a/indra/llcommon/llerrorcontrol.h
+++ b/indra/llcommon/llerrorcontrol.h
@@ -63,12 +63,12 @@ public:
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
@@ -79,14 +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);
- void setTagLevel(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
@@ -96,21 +96,21 @@ namespace LLError
*/
typedef boost::function<void(const std::string&)> FatalFunction;
- void crashAndLoop(const std::string& message);
+ LL_COMMON_API void crashAndLoop(const std::string& message);
// Default fatal function: access null pointer and loops forever
- void setFatalFunction(const 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.
- FatalFunction getFatalFunction();
+ 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 OverrideFatalFunction
+ class LL_COMMON_API OverrideFatalFunction
{
public:
OverrideFatalFunction(const FatalFunction& func):
@@ -128,15 +128,15 @@ namespace LLError
};
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:
@@ -150,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(LLLineBuffer*);
+ 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
@@ -169,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/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.h b/indra/llcommon/llevent.h
index 2cc8577219..0ea7cf4ae8 100644
--- a/indra/llcommon/llevent.h
+++ b/indra/llcommon/llevent.h
@@ -47,7 +47,7 @@ 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();
@@ -75,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();
@@ -92,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();
@@ -117,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();
@@ -160,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
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..c6d9de171d
--- /dev/null
+++ b/indra/llcommon/lleventcoro.h
@@ -0,0 +1,549 @@
+/**
+ * @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()
+ << ": " << 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..6b1413d054
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.cpp
@@ -0,0 +1,133 @@
+/**
+ * @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 Callable& callable, const LLSD& required)
+{
+ mDispatch[name] = DispatchMap::mapped_type(callable, 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.second, 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.first)(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.first;
+}
+
+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..5a86b90bff
--- /dev/null
+++ b/indra/llcommon/lleventdispatcher.h
@@ -0,0 +1,130 @@
+/**
+ * @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 <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 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, void (CLASS::*method)(const LLSD&),
+ const LLSD& required=LLSD())
+ {
+ addMethod<CLASS>(name, method, required);
+ }
+
+ /// Overload for both const and non-const methods
+ template <class CLASS>
+ void add(const std::string& name, void (CLASS::*method)(const LLSD&) const,
+ const LLSD& required=LLSD())
+ {
+ addMethod<CLASS>(name, method, 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;
+
+ /// Fetch the Callable for the specified name. If no such name was
+ /// registered, return an empty() Callable.
+ Callable get(const std::string& name) const;
+
+private:
+ template <class CLASS, typename METHOD>
+ void addMethod(const std::string& name, const METHOD& method, const LLSD& required)
+ {
+ CLASS* downcast = dynamic_cast<CLASS*>(this);
+ if (! downcast)
+ {
+ addFail(name, typeid(CLASS).name());
+ }
+ else
+ {
+ add(name, 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;
+ typedef std::map<std::string, std::pair<Callable, LLSD> > DispatchMap;
+ DispatchMap mDispatch;
+};
+
+/**
+ * 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
index eb380ba7c8..4bdfe5a867 100644
--- a/indra/llcommon/llevents.cpp
+++ b/indra/llcommon/llevents.cpp
@@ -38,6 +38,12 @@
#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
@@ -56,14 +62,12 @@ const char* queue_names[] =
/*****************************************************************************
* If there's a "mainloop" pump, listen on that to flush all LLEventQueues
*****************************************************************************/
-struct RegisterFlush
+struct RegisterFlush : public LLEventTrackable
{
RegisterFlush():
- pumps(LLEventPumps::instance()),
- mainloop(pumps.obtain("mainloop")),
- name("flushLLEventQueues")
+ pumps(LLEventPumps::instance())
{
- mainloop.listen(name, boost::bind(&RegisterFlush::flush, this, _1));
+ pumps.obtain("mainloop").listen("flushLLEventQueues", boost::bind(&RegisterFlush::flush, this, _1));
}
bool flush(const LLSD&)
{
@@ -72,11 +76,9 @@ struct RegisterFlush
}
~RegisterFlush()
{
- mainloop.stopListening(name);
+ // LLEventTrackable handles stopListening for us.
}
LLEventPumps& pumps;
- LLEventPump& mainloop;
- const std::string name;
};
static RegisterFlush registerFlush;
@@ -124,6 +126,16 @@ void LLEventPumps::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 =
@@ -240,6 +252,7 @@ LLEventPumps::~LLEventPumps()
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)
{}
@@ -256,6 +269,19 @@ LLEventPump::~LLEventPump()
// 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)
@@ -397,7 +423,7 @@ LLBoundListener LLEventPump::listen_impl(const std::string& name, const LLEventL
}
// Now that newNode has a value that places it appropriately in mSignal,
// connect it.
- LLBoundListener bound = mSignal.connect(newNode, listener);
+ LLBoundListener bound = mSignal->connect(newNode, listener);
mConnections[name] = bound;
return bound;
}
@@ -437,7 +463,7 @@ bool LLEventStream::post(const LLSD& event)
// 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 mSignal(event);
+ return (*mSignal)(event);
}
/*****************************************************************************
@@ -468,7 +494,7 @@ void LLEventQueue::flush()
mEventQueue.clear();
for ( ; ! queue.empty(); queue.pop_front())
{
- mSignal(queue.front());
+ (*mSignal)(queue.front());
}
}
@@ -499,3 +525,26 @@ bool LLListenerOrPumpName::operator()(const LLSD& event) const
}
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
index 240adcdd41..192d79b27d 100644
--- a/indra/llcommon/llevents.h
+++ b/indra/llcommon/llevents.h
@@ -19,7 +19,6 @@
#include <map>
#include <set>
#include <vector>
-#include <list>
#include <deque>
#include <stdexcept>
#if LL_WINDOWS
@@ -37,13 +36,9 @@
#include <boost/enable_shared_from_this.hpp>
#include <boost/utility.hpp> // noncopyable
#include <boost/optional/optional.hpp>
-#include <boost/ptr_container/ptr_vector.hpp>
#include <boost/visit_each.hpp>
#include <boost/ref.hpp> // reference_wrapper
#include <boost/type_traits/is_pointer.hpp>
-#include <boost/utility/addressof.hpp>
-#include <boost/preprocessor/repetition/enum_params.hpp>
-#include <boost/preprocessor/iteration/local.hpp>
#include <boost/function.hpp>
#include <boost/static_assert.hpp>
#include "llsd.h"
@@ -120,6 +115,9 @@ 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 --
@@ -136,7 +134,7 @@ typedef boost::signals2::connection LLBoundListener;
* LLListenerOrPumpName::Empty. Test for this condition beforehand using
* either <tt>if (param)</tt> or <tt>if (! param)</tt>.
*/
-class LLListenerOrPumpName
+class LL_COMMON_API LLListenerOrPumpName
{
public:
/// passing string name of LLEventPump
@@ -189,7 +187,7 @@ class LLEventPump;
* LLEventPumps is a Singleton manager through which one typically accesses
* this subsystem.
*/
-class LLEventPumps: public LLSingleton<LLEventPumps>
+class LL_COMMON_API LLEventPumps: public LLSingleton<LLEventPumps>
{
friend class LLSingleton<LLEventPumps>;
public:
@@ -204,6 +202,12 @@ public:
*/
void flush();
+ /**
+ * Reset all known LLEventPump instances
+ * workaround for DEV-35406 crash on shutdown
+ */
+ void reset();
+
private:
friend class LLEventPump;
/**
@@ -264,13 +268,61 @@ namespace LLEventDetail
} // 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 LLEventPump: boost::noncopyable
+class LL_COMMON_API LLEventPump: public LLEventTrackable
{
public:
/**
@@ -373,10 +425,22 @@ public:
* themselves. listen() can throw any ListenError; see ListenError
* subclasses.
*
- * If (as is typical) you pass a <tt>boost::bind()</tt> expression,
- * 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.
+ * 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
@@ -438,11 +502,16 @@ public:
/// 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,
@@ -451,7 +520,8 @@ private:
protected:
/// implement the dispatching
- LLStandardSignal mSignal;
+ boost::scoped_ptr<LLStandardSignal> mSignal;
+
/// valve open?
bool mEnabled;
/// Map of named listeners. This tracks the listeners that actually exist
@@ -476,7 +546,7 @@ protected:
* LLEventStream is a thin wrapper around LLStandardSignal. Posting an
* event immediately calls all registered listeners.
*/
-class LLEventStream: public LLEventPump
+class LL_COMMON_API LLEventStream: public LLEventPump
{
public:
LLEventStream(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
@@ -493,7 +563,7 @@ public:
* LLEventQueue isa LLEventPump whose post() method defers calling registered
* listeners until flush() is called.
*/
-class LLEventQueue: public LLEventPump
+class LL_COMMON_API LLEventQueue: public LLEventPump
{
public:
LLEventQueue(const std::string& name, bool tweak=false): LLEventPump(name, tweak) {}
@@ -512,47 +582,89 @@ private:
};
/*****************************************************************************
-* LLEventTrackable and underpinnings
+* LLReqID
*****************************************************************************/
/**
- * 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.
+ * 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
- * 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.
+ * 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.
*/
-typedef boost::signals2::trackable LLEventTrackable;
+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;
+};
+
+/*****************************************************************************
+* Underpinnings
+*****************************************************************************/
/**
* We originally provided a suite of overloaded
* LLEventTrackable::listenTo(LLEventPump&, ...) methods that would call
diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h
index c2f23f6ff6..45b84ea3ea 100644
--- a/indra/llcommon/llfasttimer.h
+++ b/indra/llcommon/llfasttimer.h
@@ -37,7 +37,75 @@
#define FAST_TIMER_ON 1
-U64 get_cpu_clock_count();
+#if LL_WINDOWS
+
+// 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 get_cpu_clock_count_32()
+{
+ U32 ret_val;
+ __asm
+ {
+ _emit 0x0f
+ _emit 0x31
+ shr eax,8
+ shl edx,24
+ or eax, edx
+ mov dword ptr [ret_val], eax
+ }
+ return ret_val;
+}
+
+// return full timer value, still shifted by 8 bits
+inline U64 get_cpu_clock_count_64()
+{
+ U64 ret_val;
+ __asm
+ {
+ _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 >> 8;
+}
+
+#endif // LL_WINDOWS
+
+#if (LL_LINUX || LL_SOLARIS || LL_DARWIN) && (defined(__i386__) || defined(__amd64__))
+inline U32 get_cpu_clock_count_32()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return (U32)x >> 8;
+}
+
+inline U32 get_cpu_clock_count_64()
+{
+ U64 x;
+ __asm__ volatile (".byte 0x0f, 0x31": "=A"(x));
+ return x >> 8;
+}
+#endif
+
+#if ( LL_DARWIN && !(defined(__i386__) || defined(__amd64__))) || (LL_SOLARIS && defined(__sparc__))
+//
+// Mac PPC (deprecated) & Solaris SPARC implementation of CPU clock
+//
+// Just use gettimeofday implementation for now
+
+inline U32 get_cpu_clock_count_32()
+{
+ return (U32)get_clock_count();
+}
+
+inline U32 get_cpu_clock_count_64()
+{
+ return get_clock_count();
+}
+#endif
class LLMutex;
@@ -45,20 +113,21 @@ class LLMutex;
#include "llsd.h"
-class LLFastTimer
+class LL_COMMON_API LLFastTimer
{
public:
// stores a "named" timer instance to be reused via multiple LLFastTimer stack instances
- class NamedTimer
+ class LL_COMMON_API NamedTimer
: public LLInstanceTracker<NamedTimer>
{
+ friend class DeclareTimer;
public:
~NamedTimer();
enum { HISTORY_NUM = 60 };
- const std::string& getName() { return mName; }
- NamedTimer* getParent() { return mParent; }
+ 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);
@@ -71,11 +140,11 @@ public:
void setCollapsed(bool collapsed) { mCollapsed = collapsed; }
bool getCollapsed() const { return mCollapsed; }
- U64 getCountAverage() const { return mCountAverage; }
- U64 getCallAverage() const { return mCallAverage; }
+ U32 getCountAverage() const { return mCountAverage; }
+ U32 getCallAverage() const { return mCallAverage; }
- U64 getHistoricalCount(S32 history_index = 0) const;
- U64 getHistoricalCalls(S32 history_index = 0) const;
+ U32 getHistoricalCount(S32 history_index = 0) const;
+ U32 getHistoricalCalls(S32 history_index = 0) const;
static NamedTimer& getRootNamedTimer();
@@ -83,8 +152,7 @@ public:
{
FrameState(NamedTimer* timerp);
- U64 mSelfTimeCounter;
- U64 mLastStartTime; // most recent time when this timer was started
+ U32 mSelfTimeCounter;
U32 mCalls;
FrameState* mParent; // info for caller timer
FrameState* mLastCaller; // used to bootstrap tree construction
@@ -93,11 +161,6 @@ public:
bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame
};
- FrameState& getFrameStateFast() const
- {
- return (*sTimerInfos)[mFrameStateIndex];
- }
-
S32 getFrameStateIndex() const { return mFrameStateIndex; }
FrameState& getFrameState() const;
@@ -122,10 +185,7 @@ public:
static void resetFrame();
static void reset();
- typedef std::vector<FrameState> info_list_t;
- static info_list_t& getFrameStateList();
- static void createFrameStateList(); // must call before any call to getFrameStateList()
-
+
//
// members
//
@@ -133,13 +193,13 @@ public:
std::string mName;
- U64 mTotalTimeCounter;
+ U32 mTotalTimeCounter;
- U64 mCountAverage;
- U64 mCallAverage;
+ U32 mCountAverage;
+ U32 mCallAverage;
- U64* mCountHistory;
- U64* mCallHistory;
+ U32* mCountHistory;
+ U32* mCallHistory;
// tree structure
NamedTimer* mParent; // NamedTimer of caller(parent)
@@ -147,41 +207,46 @@ public:
bool mCollapsed; // don't show children
bool mNeedsSorting; // sort children whenever child added
- static info_list_t* sTimerInfos;
};
// used to statically declare a new named timer
- class DeclareTimer
+ class LL_COMMON_API DeclareTimer
+ : public LLInstanceTracker<DeclareTimer>
{
public:
DeclareTimer(const std::string& name, bool open);
DeclareTimer(const std::string& name);
+ static void updateCachedPointers();
+
// convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer)
- operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); }
+ operator NamedTimer::FrameState&() { return *mFrameState; }
private:
- NamedTimer& mNamedTimer;
+ NamedTimer& mTimer;
+ NamedTimer::FrameState* mFrameState;
};
public:
- enum RootTimerMarker { ROOT };
-
static LLMutex* sLogLock;
static std::queue<LLSD> sLogQueue;
static BOOL sLog;
static BOOL sMetricLog;
+ typedef std::vector<NamedTimer::FrameState> info_list_t;
+ static info_list_t& getFrameStateList();
+
+ enum RootTimerMarker { ROOT };
LLFastTimer(RootTimerMarker);
LLFastTimer(NamedTimer::FrameState& timer)
: mFrameState(&timer)
{
#if FAST_TIMER_ON
- NamedTimer::FrameState* frame_state = mFrameState;
- U64 cur_time = get_cpu_clock_count();
- frame_state->mLastStartTime = cur_time;
+ NamedTimer::FrameState* frame_state = &timer;
+ U32 cur_time = get_cpu_clock_count_32();
mStartSelfTime = cur_time;
+ mStartTotalTime = cur_time;
frame_state->mActiveCount++;
frame_state->mCalls++;
@@ -197,7 +262,7 @@ public:
{
#if FAST_TIMER_ON
NamedTimer::FrameState* frame_state = mFrameState;
- U64 cur_time = get_cpu_clock_count();
+ U32 cur_time = get_cpu_clock_count_32();
frame_state->mSelfTimeCounter += cur_time - mStartSelfTime;
frame_state->mActiveCount--;
@@ -208,7 +273,7 @@ public:
frame_state->mLastCaller = last_timer->mFrameState;
// we are only tracking self time, so subtract our total time delta from parents
- U64 total_time = cur_time - frame_state->mLastStartTime;
+ U32 total_time = cur_time - mStartTotalTime;
last_timer->mStartSelfTime += total_time;
#endif
}
@@ -240,9 +305,11 @@ private:
static LLFastTimer* sCurTimer;
static S32 sCurFrameIndex;
static S32 sLastFrameIndex;
+ static U64 sLastFrameTime;
+ static info_list_t* sTimerInfos;
- static F64 sCPUClockFrequency;
- U64 mStartSelfTime; // start time + time of all child timers
+ U32 mStartSelfTime; // start time + time of all child timers
+ U32 mStartTotalTime; // start time + time of all child timers
NamedTimer::FrameState* mFrameState;
LLFastTimer* mLastTimer;
};
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.h b/indra/llcommon/llfixedbuffer.h
index 01b46d327a..17fdef27d7 100644
--- a/indra/llcommon/llfixedbuffer.h
+++ b/indra/llcommon/llfixedbuffer.h
@@ -41,7 +41,7 @@
#include "llerrorcontrol.h"
// fixed buffer implementation
-class LLFixedBuffer : public LLLineBuffer
+class LL_COMMON_API LLFixedBuffer : public LLLineBuffer
{
public:
LLFixedBuffer(const U32 max_lines = 20);
diff --git a/indra/llcommon/llfoldertype.cpp b/indra/llcommon/llfoldertype.cpp
new file mode 100644
index 0000000000..9107b11597
--- /dev/null
+++ b/indra/llcommon/llfoldertype.cpp
@@ -0,0 +1,165 @@
+/**
+ * @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();
+};
+
+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_CATEGORY, new FolderEntry("category", TRUE));
+ addEntry(LLFolderType::FT_ROOT_CATEGORY, new FolderEntry("root", 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..5374ffd829
--- /dev/null
+++ b/indra/llcommon/llfoldertype.h
@@ -0,0 +1,123 @@
+/**
+ * @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_SCRIPT = 4,
+
+ FT_CLOTHING = 5,
+
+ FT_OBJECT = 6,
+
+ FT_NOTECARD = 7,
+
+ FT_CATEGORY = 8,
+
+ FT_ROOT_CATEGORY = 9,
+
+ FT_LSL_TEXT = 10,
+
+ // FT_LSL_BYTECODE = 11,
+ // FT_TEXTURE_TGA = 12,
+
+ FT_BODYPART = 13,
+
+ FT_TRASH = 14,
+
+ FT_SNAPSHOT_CATEGORY = 15,
+
+ FT_LOST_AND_FOUND = 16,
+
+ // FT_SOUND_WAV = 17,
+ // FT_IMAGE_TGA = 18,
+ // FT_IMAGE_JPEG = 19,
+
+ FT_ANIMATION = 20,
+
+ FT_GESTURE = 21,
+
+ // FT_SIMSTATE = 22,
+
+ 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/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/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/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.h b/indra/llcommon/llmemory.h
index f41da37ba6..1c6f64dd8b 100644
--- a/indra/llcommon/llmemory.h
+++ b/indra/llcommon/llmemory.h
@@ -41,7 +41,7 @@ extern S32 gDACount;
extern void* ll_allocate (size_t size);
extern void ll_release (void *p);
-class LLMemory
+class LL_COMMON_API LLMemory
{
public:
static void initClass();
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.h b/indra/llcommon/llmemtype.h
index 12310fcdb4..677fad3034 100644
--- a/indra/llcommon/llmemtype.h
+++ b/indra/llcommon/llmemtype.h
@@ -48,14 +48,14 @@
#define MEM_TYPE_NEW(T)
-class LLMemType
+class LL_COMMON_API LLMemType
{
public:
// class we'll initialize all instances of as
// static members of MemType. Then use
// to construct any new mem type.
- class DeclareMemType
+ class LL_COMMON_API DeclareMemType
{
public:
DeclareMemType(char const * st);
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/llpreprocessor.h b/indra/llcommon/llpreprocessor.h
index bb598a2be1..48244480b1 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
@@ -137,6 +126,43 @@ using snprintf_hack::snprintf;
#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
+
+// 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.h b/indra/llcommon/llprocesslauncher.h
index a1b8e22691..880562157f 100644
--- a/indra/llcommon/llprocesslauncher.h
+++ b/indra/llcommon/llprocesslauncher.h
@@ -42,7 +42,7 @@
It also keeps track of whether the process is still running, and can kill it if required.
*/
-class LLProcessLauncher
+class LL_COMMON_API LLProcessLauncher
{
LOG_CLASS(LLProcessLauncher);
public:
diff --git a/indra/llcommon/llqueuedthread.h b/indra/llcommon/llqueuedthread.h
index 3ba43e1e07..8bfa5632a1 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:
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.h b/indra/llcommon/llrefcount.h
index d3597b454c..9ab844eb22 100644
--- a/indra/llcommon/llrefcount.h
+++ b/indra/llcommon/llrefcount.h
@@ -39,9 +39,9 @@
// see llthread.h for LLThreadSafeRefCount
//----------------------------------------------------------------------------
-class LLRefCount
+class LL_COMMON_API LLRefCount
{
-protected:
+private:
LLRefCount(const LLRefCount& other); // no implementation
private:
LLRefCount& operator=(const LLRefCount&); // no implementation
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/llsd.h b/indra/llcommon/llsd.h
index d2845a3757..552bb57498 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
@@ -387,7 +387,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.h b/indra/llcommon/llsdserialize.h
index 7463d1e5dd..2f2b292189 100644
--- a/indra/llcommon/llsdserialize.h
+++ b/indra/llcommon/llsdserialize.h
@@ -44,7 +44,7 @@
* @class LLSDParser
* @brief Abstract base class for LLSD parsers.
*/
-class LLSDParser : public LLRefCount
+class LL_COMMON_API LLSDParser : public LLRefCount
{
protected:
/**
@@ -221,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:
/**
@@ -294,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:
/**
@@ -342,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:
/**
@@ -407,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:
/**
@@ -479,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:
/**
@@ -520,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:
/**
@@ -588,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:
/**
@@ -638,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:
/**
@@ -661,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;
}
@@ -677,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 0202a033c3..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)
@@ -313,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 501600f1d9..6a6c396687 100644
--- a/indra/llcommon/llsdutil.h
+++ b/indra/llcommon/llsdutil.h
@@ -35,62 +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_ptr(const LLSD* sd);
-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
@@ -99,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.h b/indra/llcommon/llsecondlifeurls.h
index a2e5f0b9c6..bd2f9f7604 100644
--- a/indra/llcommon/llsecondlifeurls.h
+++ b/indra/llcommon/llsecondlifeurls.h
@@ -34,49 +34,49 @@
#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;
+LL_COMMON_API extern const std::string MANAGE_ACCOUNT;
-extern const std::string AUCTION_URL;
+LL_COMMON_API extern const std::string AUCTION_URL;
-extern const std::string EVENTS_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
-extern const std::string DIRECTX_9_URL;
+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;
// 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
index 2e7d845bf7..f55fafadd8 100644
--- a/indra/llcommon/llsingleton.h
+++ b/indra/llcommon/llsingleton.h
@@ -33,7 +33,41 @@
#include "llerror.h" // *TODO: eliminate this
+#include <typeinfo>
#include <boost/noncopyable.hpp>
+#include <boost/any.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
@@ -107,8 +141,17 @@ public:
static SingletonInstanceData& getData()
{
- static SingletonInstanceData data;
- return data;
+ // 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()
diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp
index 4be91b5b11..6558df70a4 100644
--- a/indra/llcommon/llstacktrace.cpp
+++ b/indra/llcommon/llstacktrace.cpp
@@ -30,6 +30,7 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
#include "llstacktrace.h"
#ifdef LL_WINDOWS
diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h
index 609b934a97..9f857f0fd3 100644
--- a/indra/llcommon/llstacktrace.h
+++ b/indra/llcommon/llstacktrace.h
@@ -38,7 +38,7 @@
#include <vector>
#include <string>
-bool ll_get_stack_trace(std::vector<std::string>& lines);
+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 90dae11793..0bd2609f4a 100644
--- a/indra/llcommon/llstat.cpp
+++ b/indra/llcommon/llstat.cpp
@@ -43,7 +43,7 @@
// 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;
@@ -130,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))
@@ -141,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 )
@@ -254,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();
}
@@ -269,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);
}
}
@@ -612,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 (!sStatsEnabled) return;
+ 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 ((sStatsFlags & flags) == 0)
+ {
+ return;
+ }
if (NULL == key2 || strlen(key2) == 0)
{
@@ -630,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
diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h
index bad18f46a0..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,7 +265,7 @@ private:
};
// ----------------------------------------------------------------------------
-class LLStat
+class LL_COMMON_API LLStat
{
private:
typedef std::multimap<std::string, LLStat*> stat_map_t;
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 f2edd5c559..c027aa7bdd 100644
--- a/indra/llcommon/llstring.cpp
+++ b/indra/llcommon/llstring.cpp
@@ -671,9 +671,9 @@ std::string ll_convert_wide_to_string(const wchar_t* in)
}
#endif // LL_WINDOWS
-long LLStringOps::sltOffset;
-long LLStringOps::localTimeOffset;
-bool LLStringOps::daylightSavings;
+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)
@@ -700,11 +700,11 @@ void LLStringOps::setupDatetimeInfo (bool daylight)
tmpT = gmtime (&nowT);
gmtT = mktime (tmpT);
- localTimeOffset = (long) (gmtT - localT);
+ sLocalTimeOffset = (long) (gmtT - localT);
- daylightSavings = daylight;
- sltOffset = (daylightSavings? 7 : 8 ) * 60 * 60;
+ sPacificDaylightTime = daylight;
+ sPacificTimeOffset = (sPacificDaylightTime? 7 : 8 ) * 60 * 60;
datetimeToCodes["wkday"] = "%a"; // Thu
datetimeToCodes["weekday"] = "%A"; // Thursday
@@ -957,36 +957,35 @@ bool LLStringUtil::formatDatetime(std::string& replacement, std::string token,
}
else if (param != "utc") // slt
{
- secFromEpoch -= LLStringOps::getSltOffset();
+ secFromEpoch -= LLStringOps::getPacificTimeOffset();
}
// if never fell into those two ifs above, param must be utc
if (secFromEpoch < 0) secFromEpoch = 0;
- LLDate * datetime = new LLDate((F64)secFromEpoch);
+ 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 == "slt")
- replacement = "SLT";
- else if (param != "local") // *TODO Vadim: not local? then what?
- replacement = LLStringOps::getDaylightSavings() ? "PDT" : "PST";
-
- return true;
- }
- replacement = datetime->toHTTPDateString(code);
-
- if (code.empty())
- {
- return false;
- }
- else
- {
+ }
+ 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);
+ return !code.empty();
}
// LLStringUtil::format recogizes the following patterns.
diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h
index 8f70726a9e..31e70e0fe4 100644
--- a/indra/llcommon/llstring.h
+++ b/indra/llcommon/llstring.h
@@ -34,6 +34,7 @@
#define LL_LLSTRING_H
#include <string>
+#include <cstdio>
#include <locale>
#include <iomanip>
#include "llsd.h"
@@ -147,12 +148,12 @@ struct char_traits<U16>
};
#endif
-class LLStringOps
+class LL_COMMON_API LLStringOps
{
private:
- static long sltOffset;
- static long localTimeOffset;
- static bool daylightSavings;
+ static long sPacificTimeOffset;
+ static long sLocalTimeOffset;
+ static bool sPacificDaylightTime;
static std::map<std::string, std::string> datetimeToCodes;
public:
@@ -183,10 +184,13 @@ 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 daylight);
- static long getSltOffset (void) {return sltOffset;}
- static long getLocalTimeOffset (void) {return localTimeOffset;}
- static bool getDaylightSavings (void) {return daylightSavings;}
+ 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);
};
@@ -194,8 +198,8 @@ public:
* @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
@@ -230,13 +234,13 @@ public:
static std::basic_string<T> null;
typedef std::map<LLFormatMapString, LLFormatMapString> format_map_t;
- static void getTokens(const std::basic_string<T>& instr, std::vector<std::basic_string<T> >& tokens, const std::basic_string<T>& delims);
- static void formatNumber(std::basic_string<T>& numStr, std::basic_string<T> decimals);
- static bool formatDatetime(std::basic_string<T>& replacement, std::basic_string<T> token, std::basic_string<T> param, S32 secFromEpoch);
- static S32 format(std::basic_string<T>& s, const format_map_t& substitutions);
- static S32 format(std::basic_string<T>& s, const LLSD& substitutions);
- static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const format_map_t& substitutions);
- static bool simpleReplacement(std::basic_string<T>& replacement, std::basic_string<T> token, const LLSD& substitutions);
+ 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;};
@@ -342,11 +346,11 @@ public:
#ifdef _DEBUG
- static void testHarness();
+ LL_COMMON_API static void testHarness();
#endif
private:
- static size_type getSubstitution(const std::basic_string<T>& instr, size_type& start, std::vector<std::basic_string<T> >& tokens);
+ 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;
@@ -400,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.
@@ -411,8 +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);
-bool iswindividual(llwchar elem);
+LL_COMMON_API bool _read_file_into_string(std::string& str, const std::string& filename);
+LL_COMMON_API bool iswindividual(llwchar elem);
/**
* Unicode support
@@ -421,52 +425,52 @@ bool iswindividual(llwchar elem);
// 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.
@@ -478,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);
@@ -493,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
@@ -528,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
@@ -558,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);
@@ -572,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);
@@ -581,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);
/**
@@ -592,7 +603,7 @@ 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);
}
diff --git a/indra/llcommon/llstringtable.h b/indra/llcommon/llstringtable.h
index 888361b0b9..d40c9d8dfd 100644
--- a/indra/llcommon/llstringtable.h
+++ b/indra/llcommon/llstringtable.h
@@ -48,15 +48,17 @@
//# 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);
@@ -69,7 +71,7 @@ public:
S32 mCount;
};
-class LLStringTable
+class LL_COMMON_API LLStringTable
{
public:
LLStringTable(int tablesize);
@@ -103,7 +105,7 @@ public:
#endif
};
-extern LLStringTable gStringTable;
+extern LL_COMMON_API LLStringTable gStringTable;
//============================================================================
@@ -113,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..3652eeba72 100644
--- a/indra/llcommon/llsys.cpp
+++ b/indra/llcommon/llsys.cpp
@@ -124,12 +124,53 @@ LLOSInfo::LLOSInfo() :
}
else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 0)
{
+ ///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
+ {
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows Vista 64-bit ";
+ else
+ mOSStringSimple = "Microsoft Windows Vista Server 64-bit ";
+ }
+ else if (si.wProcessorArchitecture==PROCESSOR_ARCHITECTURE_INTEL )
+ {
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows Vista 32-bit ";
+ else
+ mOSStringSimple = "Microsoft Windows Vista Server 32-bit ";
+ }
+ else // PROCESSOR_ARCHITECTURE_IA64 || PROCESSOR_ARCHITECTURE_UNKNOWN not checked
+ {
+ if(osvi.wProductType == VER_NT_WORKSTATION)
+ mOSStringSimple = "Microsoft Windows Vista ";
+ else
+ mOSStringSimple = "Microsoft Windows Vista Server ";
+ }
+ }
+ else if(osvi.dwMajorVersion == 6 && osvi.dwMinorVersion == 1)
+ {
if(osvi.wProductType == VER_NT_WORKSTATION)
- mOSStringSimple = "Microsoft Windows Vista ";
- else mOSStringSimple = "Microsoft Windows Vista Server ";
+ mOSStringSimple = "Microsoft Windows 7 ";
+ else mOSStringSimple = "Microsoft Windows 7 Server ";
}
else // Use the registry on early versions of Windows NT.
{
+ mOSStringSimple = "Microsoft Windows (unrecognized) ";
+
HKEY hKey;
WCHAR szProductType[80];
DWORD dwBufLen;
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.h b/indra/llcommon/llthread.h
index f25339f48d..c3d7650bd9 100644
--- a/indra/llcommon/llthread.h
+++ b/indra/llcommon/llthread.h
@@ -42,7 +42,7 @@ class LLThread;
class LLMutex;
class LLCondition;
-class LLThread
+class LL_COMMON_API LLThread
{
public:
typedef enum e_thread_status
@@ -130,7 +130,7 @@ protected:
//============================================================================
-class LLMutex
+class LL_COMMON_API LLMutex
{
public:
LLMutex(apr_pool_t *apr_poolp); // NULL pool constructs a new pool for the mutex
@@ -147,7 +147,7 @@ protected:
};
// 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.
@@ -194,7 +194,7 @@ void LLThread::unlockData()
// see llmemory.h for LLPointer<> definition
-class LLThreadSafeRefCount
+class LL_COMMON_API LLThreadSafeRefCount
{
public:
static void initThreadSafeRefCount(); // creates sMutex
@@ -246,7 +246,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.h b/indra/llcommon/lltimer.h
index 0319bec45b..d009c0f5f7 100644
--- a/indra/llcommon/lltimer.h
+++ b/indra/llcommon/lltimer.h
@@ -55,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
@@ -114,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()
{
@@ -155,24 +155,24 @@ 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 : protected LLInstanceTracker<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
@@ -190,4 +190,6 @@ protected:
F32 mPeriod;
};
+U64 LL_COMMON_API totalTime(); // Returns current system time in microseconds
+
#endif
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 23e39ceb08..71c6fc0591 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 = 0;
+const S32 LL_VERSION_BUILD = 3256;
const char * const LL_CHANNEL = "Second Life Server";
diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h
index 2c3e9c7333..082d054ba2 100644
--- a/indra/llcommon/llversionviewer.h
+++ b/indra/llcommon/llversionviewer.h
@@ -36,7 +36,7 @@
const S32 LL_VERSION_MAJOR = 2;
const S32 LL_VERSION_MINOR = 0;
const S32 LL_VERSION_PATCH = 0;
-const S32 LL_VERSION_BUILD = 0;
+const S32 LL_VERSION_BUILD = 3256;
const char * const LL_CHANNEL = "Second Life Developer";
diff --git a/indra/llcommon/llworkerthread.h b/indra/llcommon/llworkerthread.h
index 19407f4463..a12bd52a64 100644
--- a/indra/llcommon/llworkerthread.h
+++ b/indra/llcommon/llworkerthread.h
@@ -50,7 +50,7 @@ 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
{
public:
class WorkRequest : public LLQueuedThread::QueuedRequest
@@ -113,7 +113,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/stringize.h b/indra/llcommon/stringize.h
index 1b2958020f..6399547f5e 100644
--- a/indra/llcommon/stringize.h
+++ b/indra/llcommon/stringize.h
@@ -13,6 +13,7 @@
#define LL_STRINGIZE_H
#include <sstream>
+#include <boost/lambda/lambda.hpp>
/**
* stringize(item) encapsulates an idiom we use constantly, using
@@ -28,6 +29,17 @@ std::string stringize(const T& item)
}
/**
+ * 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
@@ -36,40 +48,43 @@ std::string stringize(const T& item)
* return out.str();
* @endcode
*/
-#define STRINGIZE(EXPRESSION) (static_cast<std::ostringstream&>(Stringize() << EXPRESSION).str())
+#define STRINGIZE(EXPRESSION) (stringize_f(boost::lambda::_1 << EXPRESSION))
+
/**
- * Helper class for STRINGIZE() macro. Ideally the body of
- * STRINGIZE(EXPRESSION) would look something like this:
+ * 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::ostringstream() << EXPRESSION).str()
+ * std::istringstream in(str);
+ * in >> item1 >> item2 >> item3 ... ;
* @endcode
- * That doesn't work because each of the relevant operator<<() functions
- * accepts a non-const std::ostream&, to which you can't pass a temp instance
- * of std::ostringstream. Stringize plays the necessary const tricks to make
- * the whole thing work.
*/
-class Stringize
-{
-public:
- /**
- * This is the essence of Stringize. The leftmost << operator (the one
- * coded in the STRINGIZE() macro) engages this operator<<() const method
- * on the temp Stringize instance. Every other << operator (ones embedded
- * in EXPRESSION) simply sees the std::ostream& returned by the first one.
- *
- * Finally, the STRINGIZE() macro downcasts that std::ostream& to
- * std::ostringstream&.
- */
- template <typename T>
- std::ostream& operator<<(const T& item) const
- {
- mOut << item;
- return mOut;
- }
+#define DESTRINGIZE(STR, EXPRESSION) (destringize_f((STR), (boost::lambda::_1 >> EXPRESSION)))
-private:
- mutable std::ostringstream mOut;
-};
#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/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/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
index 1e36fdd119..c31259227a 100644
--- a/indra/llcommon/tests/lldate_test.cpp
+++ b/indra/llcommon/tests/lldate_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file lldate_tut.cpp
+ * @file lldate_test.cpp
* @author Adroit
* @date 2007-02
* @brief LLDate test cases.
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..1558df231a
--- /dev/null
+++ b/indra/llcommon/tests/llerror_test.cpp
@@ -0,0 +1,768 @@
+/**
+ * @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>()
+ {
+ 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/llrand_test.cpp b/indra/llcommon/tests/llrand_test.cpp
index e5100e51dc..1f178d6fc9 100644
--- a/indra/llcommon/tests/llrand_test.cpp
+++ b/indra/llcommon/tests/llrand_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llrandom_tut.cpp
+ * @file llrandom_test.cpp
* @author Phoenix
* @date 2007-01-25
*
diff --git a/indra/llcommon/tests/llsdserialize_test.cpp b/indra/llcommon/tests/llsdserialize_test.cpp
index 662b599c55..6ab48ec34a 100644
--- a/indra/llcommon/tests/llsdserialize_test.cpp
+++ b/indra/llcommon/tests/llsdserialize_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llsdserialize_tut.cpp
+ * @file llsdserialize_test.cpp
* @date 2006-04
* @brief LLSDSerialize unit tests
*
@@ -48,6 +48,18 @@
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
@@ -107,7 +119,16 @@ namespace tut
expected = "<llsd><date>2006-04-24T16:11:33Z</date></llsd>\n";
xml_test("date", expected);
- // *FIX: test binary
+ // 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<>
@@ -199,6 +220,21 @@ namespace tut
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
{
@@ -637,6 +673,42 @@ namespace tut
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
diff --git a/indra/llcommon/tests/llstring_test.cpp b/indra/llcommon/tests/llstring_test.cpp
index 6a2ebc61f5..beba55416a 100644
--- a/indra/llcommon/tests/llstring_test.cpp
+++ b/indra/llcommon/tests/llstring_test.cpp
@@ -32,6 +32,7 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
#include "../test/lltut.h"
#include "../llstring.h"
diff --git a/indra/llcommon/tests/lltreeiterators_test.cpp b/indra/llcommon/tests/lltreeiterators_test.cpp
new file mode 100644
index 0000000000..d6d9f68110
--- /dev/null
+++ b/indra/llcommon/tests/lltreeiterators_test.cpp
@@ -0,0 +1,1222 @@
+/**
+ * @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"
+
+#if LL_WINDOWS
+#pragma warning (disable : 4180) // qualifier applied to function type has no meaning; ignored
+#endif
+
+// 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/llimage/llimage.cpp b/indra/llimage/llimage.cpp
index 488f3bf78d..73c23fa8d8 100644
--- a/indra/llimage/llimage.cpp
+++ b/indra/llimage/llimage.cpp
@@ -159,7 +159,7 @@ U8* LLImageBase::allocateData(S32 size)
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))
@@ -1223,25 +1223,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/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp
index 363486fb9c..2352c8edd7 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
@@ -367,9 +373,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)
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/llinventory/CMakeLists.txt b/indra/llinventory/CMakeLists.txt
index e3dd24ad02..b358f0a013 100644
--- a/indra/llinventory/CMakeLists.txt
+++ b/indra/llinventory/CMakeLists.txt
@@ -68,3 +68,5 @@ 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/llinventory.cpp b/indra/llinventory/llinventory.cpp
index e2a77f1d1e..d665deb605 100644
--- a/indra/llinventory/llinventory.cpp
+++ b/indra/llinventory/llinventory.cpp
@@ -458,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
{
@@ -1291,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)
@@ -1299,7 +1332,7 @@ LLInventoryCategory::LLInventoryCategory(
}
LLInventoryCategory::LLInventoryCategory() :
- mPreferredType(LLAssetType::AT_NONE)
+ mPreferredType(LLFolderType::FT_NONE)
{
mType = LLAssetType::AT_CATEGORY;
}
@@ -1321,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;
}
@@ -1372,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;
@@ -1400,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, ' ');
}
@@ -1449,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))
{
@@ -1481,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;
@@ -1528,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))
{
@@ -1560,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;
@@ -1596,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;
@@ -1642,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::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ if(LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
rv[INV_PREFERRED_TYPE_LABEL] =
- LLAssetType::lookup(cat->getPreferredType());
+ LLFolderType::lookup(cat->getPreferredType()).c_str();
}
return rv;
}
@@ -1659,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 64af6c94f5..3de9d14f54 100644
--- a/indra/llinventory/llinventory.h
+++ b/indra/llinventory/llinventory.h
@@ -37,6 +37,7 @@
#include "llassetstorage.h"
#include "lldarray.h"
+#include "llfoldertype.h"
#include "llinventorytype.h"
#include "llmemtype.h"
#include "llpermissions.h"
@@ -93,7 +94,6 @@ public:
virtual const LLUUID& getUUID() const;
const LLUUID& getParentUUID() 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
@@ -263,6 +263,10 @@ public:
void setInventoryType(LLInventoryType::EType inv_type);
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.
@@ -318,15 +322,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);
@@ -342,10 +346,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;
};
diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp
index a445466b26..0e71c0d12d 100644
--- a/indra/llinventory/llinventorytype.cpp
+++ b/indra/llinventory/llinventorytype.cpp
@@ -79,24 +79,16 @@ LLInventoryDictionary::LLInventoryDictionary()
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_SCRIPT, new InventoryEntry(NULL,NULL));
- //addEntry(LLInventoryType::IT_CLOTHING, new InventoryEntry(NULL,NULL));
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_LSL_BYTECODE, new InventoryEntry(NULL,NULL));
- //addEntry(LLInventoryType::IT_TEXTURE_TGA, new InventoryEntry(NULL,NULL));
- //addEntry(LLInventoryType::IT_BODYPART, new InventoryEntry(NULL,NULL));
- //addEntry(LLInventoryType::IT_TRASH, new InventoryEntry(NULL,NULL));
addEntry(LLInventoryType::IT_SNAPSHOT, new InventoryEntry("snapshot", "snapshot", 1, LLAssetType::AT_TEXTURE));
- //addEntry(LLInventoryType::IT_LOST_AND_FOUND, new InventoryEntry(NULL,NULL, ));
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));
- addEntry(LLInventoryType::IT_FAVORITE, new InventoryEntry("favorite", "favorite", 1, LLAssetType::AT_FAVORITE));
}
@@ -128,35 +120,9 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] =
LLInventoryType::IT_ANIMATION, // AT_ANIMATION
LLInventoryType::IT_GESTURE, // AT_GESTURE
LLInventoryType::IT_NONE, // AT_SIMSTATE
- LLInventoryType::IT_FAVORITE, // AT_FAVORITE
LLInventoryType::IT_NONE, // AT_LINK
LLInventoryType::IT_NONE, // AT_LINK_FOLDER
-
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
- LLInventoryType::IT_CATEGORY, // AT_ENSEMBLE
-
- LLInventoryType::IT_CATEGORY, // AT_CURRENT_OUTFIT
- LLInventoryType::IT_CATEGORY, // AT_OUTFIT
- LLInventoryType::IT_CATEGORY, // AT_MY_OUTFITS
};
// static
diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h
index 14b28bfe4b..e515b8a304 100644
--- a/indra/llinventory/llinventorytype.h
+++ b/indra/llinventory/llinventorytype.h
@@ -67,8 +67,7 @@ public:
IT_WEARABLE = 18,
IT_ANIMATION = 19,
IT_GESTURE = 20,
- IT_FAVORITE = 21,
- IT_COUNT = 22,
+ IT_COUNT = 21,
IT_NONE = -1
};
diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp
index e48690908e..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"
@@ -706,7 +706,6 @@ void LLParcel::packMessage(LLSD& msg)
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;
diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h
index aa8391230c..2a9a596912 100644
--- a/indra/llinventory/llparcel.h
+++ b/indra/llinventory/llparcel.h
@@ -136,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;
diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp
index 0babf26457..d2e5034734 100644
--- a/indra/llinventory/llpermissions.cpp
+++ b/indra/llinventory/llpermissions.cpp
@@ -288,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
@@ -895,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 864088148f..d5a0881c8f 100644
--- a/indra/llinventory/llpermissions.h
+++ b/indra/llinventory/llpermissions.h
@@ -232,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
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
index 770594dc9d..c797a70c50 100644
--- a/indra/llinventory/tests/inventorymisc_test.cpp
+++ b/indra/llinventory/tests/inventorymisc_test.cpp
@@ -94,7 +94,7 @@ LLPointer<LLInventoryCategory> create_random_inventory_cat()
LLPointer<LLInventoryCategory> cat = new LLInventoryCategory(
item_id,
parent_id,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
std::string("Sample category"));
return cat;
}
@@ -452,7 +452,7 @@ namespace tut
ensure_equals("4.type::getType() failed", dst->getType(), src->getType());
ensure_equals("5.preferred type::getPreferredType() failed", dst->getPreferredType(), src->getPreferredType());
- src->setPreferredType( LLAssetType::AT_TEXTURE);
+ 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());
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 e8b84eeabd..7957c32be2 100644
--- a/indra/llmath/CMakeLists.txt
+++ b/indra/llmath/CMakeLists.txt
@@ -15,6 +15,7 @@ set(llmath_SOURCE_FILES
llcamera.cpp
llcoordframe.cpp
llline.cpp
+ llmodularmath.cpp
llperlin.cpp
llquaternion.cpp
llrect.cpp
@@ -48,6 +49,7 @@ set(llmath_HEADER_FILES
llinterp.h
llline.h
llmath.h
+ llmodularmath.h
lloctree.h
llperlin.h
llplane.h
@@ -62,6 +64,7 @@ set(llmath_HEADER_FILES
llv4vector3.h
llvolume.h
llvolumemgr.h
+ llsdutil_math.h
m3math.h
m4math.h
raytrace.h
@@ -87,6 +90,7 @@ include(LLAddBuildTest)
# UNIT TESTS
SET(llmath_TEST_SOURCE_FILES
llbboxlocal.cpp
+ llmodularmath.cpp
llrect.cpp
v2math.cpp
v3color.cpp
@@ -99,8 +103,9 @@ LL_ADD_PROJECT_UNIT_TESTS(llmath "${llmath_TEST_SOURCE_FILES}")
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(mathmisc "" "${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}")
diff --git a/indra/llmath/llbbox.cpp b/indra/llmath/llbbox.cpp
index acf93a2a38..914cbfdc12 100644
--- a/indra/llmath/llbbox.cpp
+++ b/indra/llmath/llbbox.cpp
@@ -30,6 +30,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
// self include
#include "llbbox.h"
diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h
index f85c4f39f4..7a5d51ff76 100644
--- a/indra/llmath/llmath.h
+++ b/indra/llmath/llmath.h
@@ -35,6 +35,7 @@
#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
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/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/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp
index c5176681ce..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"
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 5cc0a596fd..b8ef92f9a9 100644
--- a/indra/llmath/llvolume.cpp
+++ b/indra/llmath/llvolume.cpp
@@ -4273,7 +4273,7 @@ LLFaceID LLVolume::generateFaceMask()
}
break;
default:
- llerrs << "Unknown profile!" << llendl
+ llerrs << "Unknown profile!" << llendl;
break;
}
diff --git a/indra/llmath/tests/llbbox_test.cpp b/indra/llmath/tests/llbbox_test.cpp
index 2cfdd8b36d..3031310a5d 100644
--- a/indra/llmath/tests/llbbox_test.cpp
+++ b/indra/llmath/tests/llbbox_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llbbox_tut.cpp
+ * @file llbbox_test.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llbbox.cpp.
@@ -32,6 +32,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "../test/lltut.h"
#include "../llbbox.h"
diff --git a/indra/llmath/tests/llbboxlocal_test.cpp b/indra/llmath/tests/llbboxlocal_test.cpp
index 92cdf1c8a2..fb51deab4a 100644
--- a/indra/llmath/tests/llbboxlocal_test.cpp
+++ b/indra/llmath/tests/llbboxlocal_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llbboxlocal_tut.cpp
+ * @file llbboxlocal_test.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llbboxlocal.cpp.
@@ -32,11 +32,10 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
#include "../test/lltut.h"
-
#include "../llbboxlocal.h"
-
namespace tut
{
struct LLBBoxLocalData
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
index bfa475d91b..2d27d1eb32 100644
--- a/indra/llmath/tests/llquaternion_test.cpp
+++ b/indra/llmath/tests/llquaternion_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llquaternion_tut.cpp
+ * @file llquaternion_test.cpp
* @author Adroit
* @date 2007-03
* @brief Test cases of llquaternion.h
diff --git a/indra/llmath/tests/llrect_test.cpp b/indra/llmath/tests/llrect_test.cpp
index b16716a72c..c5e9e425bb 100644
--- a/indra/llmath/tests/llrect_test.cpp
+++ b/indra/llmath/tests/llrect_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llrect_tut.cpp
+ * @file llrect_test.cpp
* @author Martin Reddy
* @date 2009-06-25
* @brief Test for llrect.cpp.
@@ -32,8 +32,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
#include "../test/lltut.h"
-
#include "../llrect.h"
namespace tut
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/v2math_test.cpp b/indra/llmath/tests/v2math_test.cpp
index 456faf7c0c..4660fcb955 100644
--- a/indra/llmath/tests/v2math_test.cpp
+++ b/indra/llmath/tests/v2math_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v2math_tut.cpp
+ * @file v2math_test.cpp
* @author Adroit
* @date 2007-02
* @brief v2math test cases.
diff --git a/indra/llmath/tests/v3color_test.cpp b/indra/llmath/tests/v3color_test.cpp
index bb6e234fd6..316b6e392f 100644
--- a/indra/llmath/tests/v3color_test.cpp
+++ b/indra/llmath/tests/v3color_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v3color_tut.cpp
+ * @file v3color_test.cpp
* @author Adroit
* @date 2007-03
* @brief v3color test cases.
diff --git a/indra/llmath/tests/v3dmath_test.cpp b/indra/llmath/tests/v3dmath_test.cpp
index 780495e53d..e7c949186c 100644
--- a/indra/llmath/tests/v3dmath_test.cpp
+++ b/indra/llmath/tests/v3dmath_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v3dmath_tut.cpp
+ * @file v3dmath_test.cpp
* @author Adroit
* @date 2007-03
* @brief v3dmath test cases.
diff --git a/indra/llmath/tests/v3math_test.cpp b/indra/llmath/tests/v3math_test.cpp
index 14159974a3..7faf076243 100644
--- a/indra/llmath/tests/v3math_test.cpp
+++ b/indra/llmath/tests/v3math_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v3math_tut.cpp
+ * @file v3math_test.cpp
* @author Adroit
* @date 2007-02
* @brief v3math test cases.
diff --git a/indra/llmath/tests/v4color_test.cpp b/indra/llmath/tests/v4color_test.cpp
index cebb026ce6..33921e0f0f 100644
--- a/indra/llmath/tests/v4color_test.cpp
+++ b/indra/llmath/tests/v4color_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v4color_tut.cpp
+ * @file v4color_test.cpp
* @author Adroit
* @date 2007-03
* @brief v4color test cases.
diff --git a/indra/llmath/tests/v4coloru_test.cpp b/indra/llmath/tests/v4coloru_test.cpp
index 00515893da..9f71cfc8cc 100644
--- a/indra/llmath/tests/v4coloru_test.cpp
+++ b/indra/llmath/tests/v4coloru_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v4coloru_tut.cpp
+ * @file v4coloru_test.cpp
* @author Adroit
* @date 2007-03
* @brief v4coloru test cases.
diff --git a/indra/llmath/tests/v4math_test.cpp b/indra/llmath/tests/v4math_test.cpp
index e020038ae5..fe051c27e9 100644
--- a/indra/llmath/tests/v4math_test.cpp
+++ b/indra/llmath/tests/v4math_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file v4math_tut.cpp
+ * @file v4math_test.cpp
* @author Adroit
* @date 2007-03
* @brief v4math test cases.
diff --git a/indra/llmath/tests/xform_test.cpp b/indra/llmath/tests/xform_test.cpp
index 81116a58f0..e697a0b7a1 100644
--- a/indra/llmath/tests/xform_test.cpp
+++ b/indra/llmath/tests/xform_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file xform_tut.cpp
+ * @file xform_test.cpp
* @author Adroit
* @date March 2007
* @brief Test cases for LLXform
diff --git a/indra/llmessage/CMakeLists.txt b/indra/llmessage/CMakeLists.txt
index 31ea747f52..a611de0cda 100644
--- a/indra/llmessage/CMakeLists.txt
+++ b/indra/llmessage/CMakeLists.txt
@@ -3,6 +3,7 @@
project(llmessage)
include(00-Common)
+include(GoogleMock)
include(LLAddBuildTest)
include(LLCommon)
include(LLMath)
@@ -22,6 +23,7 @@ include_directories(
set(llmessage_SOURCE_FILES
llares.cpp
+ llareslistener.cpp
llassetstorage.cpp
llblowfishcipher.cpp
llbuffer.cpp
@@ -104,6 +106,7 @@ set(llmessage_HEADER_FILES
CMakeLists.txt
llares.h
+ llareslistener.h
llassetstorage.h
llblowfishcipher.h
llbuffer.h
@@ -213,12 +216,18 @@ target_link_libraries(
${XMLRPCEPI_LIBRARIES}
)
+# 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}
@@ -226,6 +235,7 @@ set(test_libs
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(
@@ -236,4 +246,7 @@ LL_ADD_INTEGRATION_TEST(
"${CMAKE_CURRENT_SOURCE_DIR}/tests/test_llsdmessage_peer.py"
)
-LL_ADD_PROJECT_UNIT_TESTS(llmessage "${llmessage_TEST_SOURCE_FILES}")
+LL_ADD_INTEGRATION_TEST(llhost "" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llpartdata "" "${test_libs}")
+LL_ADD_INTEGRATION_TEST(llxfer_file "" "${test_libs}")
+
diff --git a/indra/llmessage/llares.cpp b/indra/llmessage/llares.cpp
index fe37fe8142..acbf51d75c 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("LLAres", this))
{
if (ares_init(&chan_) != ARES_SUCCESS)
{
diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h
index c709a08499..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
@@ -49,7 +55,10 @@
#include "llrefcount.h"
#include "lluri.h"
+#include <boost/shared_ptr.hpp>
+
class LLQueryResponder;
+class LLAresListener;
/**
* @brief Supported DNS RR types.
@@ -444,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..a8beb8cbde
--- /dev/null
+++ b/indra/llmessage/llareslistener.cpp
@@ -0,0 +1,75 @@
+/**
+ * @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(const std::string& pumpname, LLAres* llares):
+ LLDispatchListener(pumpname, "op"),
+ mAres(llares)
+{
+ // add() every method we want to be able to invoke via this event API.
+ // Optional third parameter validates expected LLSD request structure.
+ add("rewriteURI", &LLAresListener::rewriteURI,
+ LLSD().insert("uri", LLSD()).insert("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..bf093b3d3d
--- /dev/null
+++ b/indra/llmessage/llareslistener.h
@@ -0,0 +1,37 @@
+/**
+ * @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 "lleventdispatcher.h"
+
+class LLAres;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAres request events.
+class LLAresListener: public LLDispatchListener
+{
+public:
+ /// Specify the pump name on which to listen, and bind the LLAres instance
+ /// to use (e.g. gAres)
+ LLAresListener(const std::string& pumpname, LLAres* llares);
+
+private:
+ /// command["op"] == "rewriteURI"
+ void rewriteURI(const LLSD& data);
+
+ LLAres* mAres;
+};
+
+#endif /* ! defined(LL_LLARESLISTENER_H) */
diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h
index 47d49076f4..8641437d86 100644
--- a/indra/llmessage/llcachename.h
+++ b/indra/llmessage/llcachename.h
@@ -42,9 +42,9 @@ class LLUUID;
typedef boost::signals2::signal<void (const LLUUID& id,
- const std::string& first_name,
- const std::string& last_name,
- BOOL is_group)> LLCacheNameSignal;
+ 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
@@ -100,7 +100,6 @@ public:
// LEGACY
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();
diff --git a/indra/llmessage/llcurl.cpp b/indra/llmessage/llcurl.cpp
index a4af8e989b..5ff41322b7 100644
--- a/indra/llmessage/llcurl.cpp
+++ b/indra/llmessage/llcurl.cpp
@@ -131,7 +131,7 @@ void LLCurl::Responder::errorWithContent(
// virtual
void LLCurl::Responder::error(U32 status, const std::string& reason)
{
- llinfos << status << ": " << reason << llendl;
+ llinfos << mURL << " [" << status << "]: " << reason << llendl;
}
// virtual
@@ -139,6 +139,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 +153,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);
}
diff --git a/indra/llmessage/llcurl.h b/indra/llmessage/llcurl.h
index fbd3077cbf..0b58e7c4a5 100644
--- a/indra/llmessage/llcurl.h
+++ b/indra/llmessage/llcurl.h
@@ -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;
diff --git a/indra/llmessage/llhttpclient.cpp b/indra/llmessage/llhttpclient.cpp
index 8b90a4c5ca..12ecbb36eb 100644
--- a/indra/llmessage/llhttpclient.cpp
+++ b/indra/llmessage/llhttpclient.cpp
@@ -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 b6988224ce..9d3c83f828 100644
--- a/indra/llmessage/llhttpclientadapter.cpp
+++ b/indra/llmessage/llhttpclientadapter.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadapter.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h
index 7f76390d0c..a205a2f260 100644
--- a/indra/llmessage/llhttpclientadapter.h
+++ b/indra/llmessage/llhttpclientadapter.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientadepter.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h
index 42a8e5cd0a..085a59cf27 100644
--- a/indra/llmessage/llhttpclientinterface.h
+++ b/indra/llmessage/llhttpclientinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llhttpclientinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp
index 7c63625004..3da41939fa 100644
--- a/indra/llmessage/llinstantmessage.cpp
+++ b/indra/llmessage/llinstantmessage.cpp
@@ -40,7 +40,7 @@
#include "lluuid.h"
#include "llsd.h"
#include "llsdserialize.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llpointer.h"
#include "message.h"
diff --git a/indra/llmessage/lliohttpserver.cpp b/indra/llmessage/lliohttpserver.cpp
index a00dbd1809..97134bd336 100644
--- a/indra/llmessage/lliohttpserver.cpp
+++ b/indra/llmessage/lliohttpserver.cpp
@@ -521,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,
@@ -592,7 +592,7 @@ LLHTTPResponder::~LLHTTPResponder()
//lldebugs << "destroying LLHTTPResponder" << llendl;
}
-bool LLHTTPResponder::readLine(
+bool LLHTTPResponder::readHeaderLine(
const LLChannelDescriptors& channels,
buffer_ptr_t buffer,
U8* dest,
@@ -670,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;
@@ -734,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/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 119eb1d7f7..af6733fa05 100644
--- a/indra/llmessage/llmessagesenderinterface.h
+++ b/indra/llmessage/llmessagesenderinterface.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llmessagesenderinterface.h
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
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/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp
index 0527d5cb8d..b1868e6a00 100644
--- a/indra/llmessage/llregionpresenceverifier.cpp
+++ b/indra/llmessage/llregionpresenceverifier.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -30,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::RegionResponder::RegionResponder(ResponsePtr data) : mSharedData(data)
+LLRegionPresenceVerifier::Response::~Response()
{
}
+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)
{
@@ -49,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)
{
@@ -87,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();
}
}
@@ -101,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 54ad6226d6..f57a62a731 100644
--- a/indra/llmessage/llregionpresenceverifier.h
+++ b/indra/llmessage/llregionpresenceverifier.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llregionpresenceverifier.cpp
* @brief
*
* $LicenseInfo:firstyear=2008&license=viewergpl$
@@ -37,7 +37,7 @@
#include "llhttpclient.h"
#include <string>
#include "llsd.h"
-#include <boost/shared_ptr.hpp>
+#include <boost/intrusive_ptr.hpp>
class LLHTTPClientInterface;
@@ -47,49 +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/llsdmessage.cpp b/indra/llmessage/llsdmessage.cpp
index 9967a6197f..2cb742e261 100644
--- a/indra/llmessage/llsdmessage.cpp
+++ b/indra/llmessage/llsdmessage.cpp
@@ -68,6 +68,7 @@ bool LLSDMessage::httpListener(const LLSD& request)
}
LLHTTPClient::post(url, payload,
new LLSDMessage::EventResponder(LLEventPumps::instance(),
+ request,
url, "POST", reply, error),
LLSD(), // headers
timeout);
@@ -81,7 +82,9 @@ void LLSDMessage::EventResponder::result(const LLSD& data)
// to the pump whose name is "".
if (! mReplyPump.empty())
{
- mPumps.obtain(mReplyPump).post(data);
+ LLSD response(data);
+ mReqID.stamp(response);
+ mPumps.obtain(mReplyPump).post(response);
}
else // default success handling
{
@@ -98,7 +101,7 @@ void LLSDMessage::EventResponder::errorWithContent(U32 status, const std::string
// explicit pump name.
if (! mErrorPump.empty())
{
- LLSD info;
+ LLSD info(mReqID.makeResponse());
info["target"] = mTarget;
info["message"] = mMessage;
info["status"] = LLSD::Integer(status);
diff --git a/indra/llmessage/llsdmessage.h b/indra/llmessage/llsdmessage.h
index 65503756a8..6ee00fd41d 100644
--- a/indra/llmessage/llsdmessage.h
+++ b/indra/llmessage/llsdmessage.h
@@ -121,9 +121,11 @@ private:
* (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),
@@ -135,6 +137,7 @@ private:
private:
LLEventPumps& mPumps;
+ LLReqID mReqID;
const std::string mTarget, mMessage, mReplyPump, mErrorPump;
};
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 32cbb15cb3..d6b2f45d04 100644
--- a/indra/llmessage/llstoredmessage.cpp
+++ b/indra/llmessage/llstoredmessage.cpp
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.cpp
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h
index 5069c2cb2e..359e4c5aea 100644
--- a/indra/llmessage/llstoredmessage.h
+++ b/indra/llmessage/llstoredmessage.h
@@ -1,5 +1,5 @@
/**
- * @file
+ * @file llstoredmessage.h
* @brief
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
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/lltemplatemessagereader.cpp b/indra/llmessage/lltemplatemessagereader.cpp
index 8c9eb7ed42..6682575ca5 100644
--- a/indra/llmessage/lltemplatemessagereader.cpp
+++ b/indra/llmessage/lltemplatemessagereader.cpp
@@ -678,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());
}
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 5a1cd95ffc..7332f5c954 100644
--- a/indra/llmessage/lltransfersourceasset.cpp
+++ b/indra/llmessage/lltransfersourceasset.cpp
@@ -270,7 +270,6 @@ bool is_asset_fetch_by_id_allowed(LLAssetType::EType type)
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_GESTURE:
- case LLAssetType::AT_FAVORITE:
rv = true;
break;
default:
@@ -293,7 +292,6 @@ bool is_asset_id_knowable(LLAssetType::EType type)
case LLAssetType::AT_BODYPART:
case LLAssetType::AT_ANIMATION:
case LLAssetType::AT_GESTURE:
- case LLAssetType::AT_FAVORITE:
case LLAssetType::AT_LINK:
case LLAssetType::AT_LINK_FOLDER:
rv = true;
diff --git a/indra/llmessage/llurlrequest.cpp b/indra/llmessage/llurlrequest.cpp
index 3ab8057abb..81b7761ed5 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);
@@ -247,7 +248,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 +309,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 +363,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 +385,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 +489,7 @@ size_t LLURLRequest::downCallback(
req->mDetail->mChannels.out(),
(U8*)data,
bytes);
+ req->mResponseTransferedBytes += bytes;
req->mDetail->mByteAccumulator += bytes;
return bytes;
}
@@ -494,6 +513,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/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 5dc5932fde..e6a5ad9946 100644
--- a/indra/llmessage/tests/llcurl_stub.cpp
+++ b/indra/llmessage/tests/llcurl_stub.cpp
@@ -22,6 +22,7 @@
#include "linden_common.h"
LLCurl::Responder::Responder()
+ : mReferenceCount(0)
{
}
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/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
index 3146e7f979..bef4c06334 100644
--- a/indra/llmessage/tests/llnamevalue_test.cpp
+++ b/indra/llmessage/tests/llnamevalue_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llnamevalue_tut.cpp
+ * @file llnamevalue_test.cpp
* @author Adroit
* @date 2007-02
* @brief LLNameValue unit test
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
index 2957d7cc4f..9b018d685b 100644
--- a/indra/llmessage/tests/llsdmessage_test.cpp
+++ b/indra/llmessage/tests/llsdmessage_test.cpp
@@ -1,5 +1,5 @@
/**
- * @file llsdmessage_tut.cpp
+ * @file llsdmessage_test.cpp
* @author Nat Goodspeed
* @date 2008-12-22
* @brief Test of llsdmessage.h
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/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/llpluginclassmedia.cpp b/indra/llplugin/llpluginclassmedia.cpp
index 7299ede22d..457c074ef1 100644
--- a/indra/llplugin/llpluginclassmedia.cpp
+++ b/indra/llplugin/llpluginclassmedia.cpp
@@ -112,6 +112,8 @@ void LLPluginClassMedia::reset()
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;
@@ -133,6 +135,7 @@ void LLPluginClassMedia::reset()
mCurrentTime = 0.0f;
mDuration = 0.0f;
mCurrentRate = 0.0f;
+ mLoadedDuration = 0.0f;
}
void LLPluginClassMedia::idle(void)
@@ -411,8 +414,20 @@ std::string LLPluginClassMedia::translateModifiers(MASK modifiers)
return result;
}
-void LLPluginClassMedia::mouseEvent(EMouseEventType type, int x, int y, MASK modifiers)
+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)
@@ -424,6 +439,8 @@ void LLPluginClassMedia::mouseEvent(EMouseEventType type, int x, int y, MASK mod
}
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.
@@ -514,11 +531,12 @@ void LLPluginClassMedia::scrollEvent(int x, int y, MASK modifiers)
sendMessage(message);
}
-bool LLPluginClassMedia::textInput(const std::string &text)
+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);
@@ -534,6 +552,23 @@ void LLPluginClassMedia::loadURI(const std::string &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)
@@ -542,35 +577,28 @@ void LLPluginClassMedia::setPriority(EPriority priority)
LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "set_priority");
- std::string priority_string;
+ std::string priority_string = priorityToString(priority);
switch(priority)
{
case PRIORITY_UNLOADED:
- priority_string = "unloaded";
mSleepTime = 1.0f;
break;
case PRIORITY_STOPPED:
- priority_string = "stopped";
mSleepTime = 1.0f;
break;
case PRIORITY_HIDDEN:
- priority_string = "hidden";
mSleepTime = 1.0f;
break;
case PRIORITY_SLIDESHOW:
- priority_string = "slideshow";
mSleepTime = 1.0f;
break;
case PRIORITY_LOW:
- priority_string = "low";
mSleepTime = 1.0f / 50.0f;
break;
case PRIORITY_NORMAL:
- priority_string = "normal";
mSleepTime = 1.0f / 100.0f;
break;
case PRIORITY_HIGH:
- priority_string = "high";
mSleepTime = 1.0f / 100.0f;
break;
}
@@ -705,6 +733,7 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
bool time_duration_updated = false;
+ int previous_percent = mProgressPercent;
if(message.hasValue("current_time"))
{
@@ -722,11 +751,32 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
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")
{
@@ -754,6 +804,10 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
{
mStatus = LLPluginClassMediaOwner::MEDIA_PAUSED;
}
+ else if(status == "done")
+ {
+ mStatus = LLPluginClassMediaOwner::MEDIA_DONE;
+ }
else
{
// empty string or any unknown string
@@ -812,6 +866,11 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
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;
@@ -884,6 +943,12 @@ void LLPluginClassMedia::receivePluginMessage(const LLPluginMessage &message)
}
/* virtual */
+void LLPluginClassMedia::pluginLaunchFailed()
+{
+ mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED_LAUNCH);
+}
+
+/* virtual */
void LLPluginClassMedia::pluginDied()
{
mediaEvent(LLPluginClassMediaOwner::MEDIA_EVENT_PLUGIN_FAILED);
@@ -1078,6 +1143,11 @@ void LLPluginClassMedia::setVolume(float volume)
}
}
+float LLPluginClassMedia::getVolume()
+{
+ return mRequestedVolume;
+}
+
void LLPluginClassMedia::initializeUrlHistory(const LLSD& url_history)
{
// Send URL history to plugin
diff --git a/indra/llplugin/llpluginclassmedia.h b/indra/llplugin/llpluginclassmedia.h
index 331ca5f6dc..90ecd1e073 100644
--- a/indra/llplugin/llpluginclassmedia.h
+++ b/indra/llplugin/llpluginclassmedia.h
@@ -101,7 +101,7 @@ public:
MOUSE_EVENT_DOUBLE_CLICK
}EMouseEventType;
- void mouseEvent(EMouseEventType type, int x, int y, MASK modifiers);
+ void mouseEvent(EMouseEventType type, int button, int x, int y, MASK modifiers);
typedef enum
{
@@ -115,7 +115,7 @@ public:
void scrollEvent(int x, int y, MASK modifiers);
// Text may be unicode (utf8 encoded)
- bool textInput(const std::string &text);
+ bool textInput(const std::string &text, MASK modifiers);
void loadURI(const std::string &uri);
@@ -135,6 +135,7 @@ public:
// Inherited from LLPluginProcessParentOwner
/* virtual */ void receivePluginMessage(const LLPluginMessage &message);
+ /* virtual */ void pluginLaunchFailed();
/* virtual */ void pluginDied();
@@ -149,6 +150,7 @@ public:
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);
@@ -226,10 +228,12 @@ public:
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
@@ -308,6 +312,8 @@ protected:
std::string translateModifiers(MASK modifiers);
std::string mCursorName;
+ int mLastMouseX;
+ int mLastMouseY;
LLPluginClassMediaOwner::EMediaStatus mStatus;
@@ -338,6 +344,7 @@ protected:
F64 mCurrentTime;
F64 mDuration;
F64 mCurrentRate;
+ F64 mLoadedDuration;
};
diff --git a/indra/llplugin/llpluginclassmediaowner.h b/indra/llplugin/llpluginclassmediaowner.h
index df6de0925e..c798af29ca 100644
--- a/indra/llplugin/llpluginclassmediaowner.h
+++ b/indra/llplugin/llpluginclassmediaowner.h
@@ -52,11 +52,13 @@ public:
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 // The plugin failed to launch or died unexpectedly
+ MEDIA_EVENT_PLUGIN_FAILED_LAUNCH, // The plugin failed to launch
+ MEDIA_EVENT_PLUGIN_FAILED // The plugin died unexpectedly
} EMediaEvent;
@@ -68,7 +70,8 @@ public:
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() {};
diff --git a/indra/llplugin/llpluginprocessparent.cpp b/indra/llplugin/llpluginprocessparent.cpp
index 41784a713c..39f9438fb3 100644
--- a/indra/llplugin/llpluginprocessparent.cpp
+++ b/indra/llplugin/llpluginprocessparent.cpp
@@ -55,6 +55,11 @@ LLPluginProcessParent::LLPluginProcessParent(LLPluginProcessParentOwner *owner)
mBoundPort = 0;
mState = STATE_UNINITIALIZED;
mDisableTimeout = false;
+
+ // initialize timer - heartbeat test (mHeartbeat.hasExpired())
+ // can sometimes return true immediately otherwise and plugins
+ // fail immediately because it looks like
+ mHeartbeat.setTimerExpirySec(PLUGIN_LOCKED_UP_SECONDS);
}
LLPluginProcessParent::~LLPluginProcessParent()
@@ -83,6 +88,14 @@ void LLPluginProcessParent::killSockets(void)
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)
{
mProcess.setExecutable(launcher_filename);
@@ -132,7 +145,7 @@ bool LLPluginProcessParent::accept()
ll_apr_warn_status(status);
// Some other error.
- setState(STATE_ERROR);
+ errorState();
}
return result;
@@ -150,15 +163,15 @@ void LLPluginProcessParent::idle(void)
if(!mMessagePipe->pump())
{
// LL_WARNS("Plugin") << "Message pipe hit an error state" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
- if((mSocketError != APR_SUCCESS) && (mState < STATE_ERROR))
+ 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;
- setState(STATE_ERROR);
+ 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().
@@ -191,7 +204,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -202,7 +215,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -212,7 +225,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(apr_socket_addr_get(&bound_addr, APR_LOCAL, mListenSocket->getSocket())))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
mBoundPort = bound_addr->port;
@@ -222,7 +235,7 @@ void LLPluginProcessParent::idle(void)
LL_WARNS("Plugin") << "Bound port number unknown, bailing out." << LL_ENDL;
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
}
@@ -234,7 +247,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -242,7 +255,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -255,7 +268,7 @@ void LLPluginProcessParent::idle(void)
if(ll_apr_warn_status(status))
{
killSockets();
- setState(STATE_ERROR);
+ errorState();
break;
}
@@ -274,7 +287,7 @@ void LLPluginProcessParent::idle(void)
mProcess.addArgument(stream.str());
if(mProcess.launch() != 0)
{
- setState(STATE_ERROR);
+ errorState();
}
else
{
@@ -290,7 +303,7 @@ void LLPluginProcessParent::idle(void)
// waiting for the plugin to connect
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
else
{
@@ -309,7 +322,7 @@ void LLPluginProcessParent::idle(void)
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
@@ -330,14 +343,14 @@ void LLPluginProcessParent::idle(void)
// The load_plugin_response message will kick us from here into STATE_RUNNING
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
case STATE_RUNNING:
if(pluginLockedUpOrQuit())
{
- setState(STATE_ERROR);
+ errorState();
}
break;
@@ -349,10 +362,18 @@ void LLPluginProcessParent::idle(void)
else if(pluginLockedUp())
{
LL_WARNS("Plugin") << "timeout in exiting state, bailing out" << llendl;
- setState(STATE_ERROR);
+ errorState();
}
break;
+ case STATE_LAUNCH_FAILURE:
+ if(mOwner != NULL)
+ {
+ mOwner->pluginLaunchFailed();
+ }
+ setState(STATE_CLEANUP);
+ break;
+
case STATE_ERROR:
if(mOwner != NULL)
{
@@ -467,7 +488,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
else
{
LL_WARNS("Plugin") << "received hello message in wrong state -- bailing out" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
@@ -477,6 +498,9 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
{
// 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?
@@ -487,8 +511,6 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
LL_INFOS("Plugin") << "message class: " << iter->first << " -> version: " << iter->second.asString() << LL_ENDL;
}
- mPluginVersionString = message.getValue("plugin_version");
-
// Send initial sleep time
setSleepTime(mSleepTime, true);
@@ -497,7 +519,7 @@ void LLPluginProcessParent::receiveMessage(const LLPluginMessage &message)
else
{
LL_WARNS("Plugin") << "received load_plugin_response message in wrong state -- bailing out" << LL_ENDL;
- setState(STATE_ERROR);
+ errorState();
}
}
else if(message_name == "heartbeat")
diff --git a/indra/llplugin/llpluginprocessparent.h b/indra/llplugin/llpluginprocessparent.h
index 0d0b047c88..754ebeb946 100644
--- a/indra/llplugin/llpluginprocessparent.h
+++ b/indra/llplugin/llpluginprocessparent.h
@@ -45,6 +45,7 @@ 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() {};
};
@@ -68,6 +69,9 @@ public:
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; };
@@ -110,6 +114,7 @@ private:
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
diff --git a/indra/llprimitive/llmediaentry.cpp b/indra/llprimitive/llmediaentry.cpp
index fa04bf80e7..701300163a 100644
--- a/indra/llprimitive/llmediaentry.cpp
+++ b/indra/llprimitive/llmediaentry.cpp
@@ -164,6 +164,7 @@ void LLMediaEntry::asLLSD(LLSD& sd) const
// "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]);
diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp
index b102254b62..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"
/**
@@ -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;
}
@@ -1715,10 +1900,10 @@ LLSD LLLightImageParams::asLLSD() const
bool LLLightImageParams::fromLLSD(LLSD& sd)
{
- if (sd.has("texture") && sd.has("params") && sd["params"].size() == 3)
+ if (sd.has("texture"))
{
setLightTexture( sd["texture"] );
- setParams( LLVector3(sd["params"][0].asReal(), sd["params"][1].asReal(), sd["params"][2].asReal()) );
+ setParams( LLVector3( sd["params"] ) );
return true;
}
diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h
index 53095cc925..4f828186cb 100644
--- a/indra/llprimitive/llprimitive.h
+++ b/indra/llprimitive/llprimitive.h
@@ -263,9 +263,9 @@ 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
diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp
index d03150fc78..1c7de95975 100644
--- a/indra/llprimitive/llprimtexturelist.cpp
+++ b/indra/llprimitive/llprimtexturelist.cpp
@@ -135,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)
@@ -387,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/lltextureentry.cpp b/indra/llprimitive/lltextureentry.cpp
index b534939dfc..f75f1d9b8c 100644
--- a/indra/llprimitive/lltextureentry.cpp
+++ b/indra/llprimitive/lltextureentry.cpp
@@ -35,7 +35,7 @@
#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
@@ -646,3 +646,9 @@ LLUUID LLTextureEntry::getAgentIDFromMediaVersionString(const std::string &versi
}
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 8d2834f78c..d6366b9bb2 100644
--- a/indra/llprimitive/lltextureentry.h
+++ b/indra/llprimitive/lltextureentry.h
@@ -171,7 +171,9 @@ public:
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_HAS_MEDIA = 0x1 };
diff --git a/indra/llprimitive/tests/llmediaentry_test.cpp b/indra/llprimitive/tests/llmediaentry_test.cpp
index 72478d0459..cd9608d56b 100644
--- a/indra/llprimitive/tests/llmediaentry_test.cpp
+++ b/indra/llprimitive/tests/llmediaentry_test.cpp
@@ -157,7 +157,7 @@ namespace tut
void ensure_llsd_equals(const std::string& msg, const LLSD& expected, const LLSD& actual)
{
- if (! llsd_equals(expected, actual))
+ if (!tut::llsd_equals(expected, actual))
{
std::string message = msg;
message += ": actual: ";
@@ -223,8 +223,7 @@ namespace tut
{
set_test_name("Test LLMediaEntry Instantiation");
LLMediaEntry entry;
- ensure_llsd_equals(get_test_name(), defaultMediaEntryLLSD, entry.asLLSD());
-
+ ensure_llsd_equals(get_test_name() + " failed", defaultMediaEntryLLSD, entry.asLLSD());
}
template<> template<>
@@ -251,12 +250,27 @@ namespace tut
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);
+ }
+
// 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<4>()
+ void object::test<5>()
{
set_test_name("Test Limits on setting current URL");
LLMediaEntry entry;
@@ -267,7 +281,7 @@ namespace tut
}
template<> template<>
- void object::test<5>()
+ void object::test<6>()
{
set_test_name("Test Limits on setting home URL");
LLMediaEntry entry;
@@ -278,7 +292,7 @@ namespace tut
}
template<> template<>
- void object::test<6>()
+ void object::test<7>()
{
set_test_name("Test Limits on setting whitelist");
@@ -292,7 +306,7 @@ namespace tut
}
template<> template<>
- void object::test<7>()
+ void object::test<8>()
{
set_test_name("Test Limits on setting whitelist too big");
@@ -307,7 +321,7 @@ namespace tut
}
template<> template<>
- void object::test<8>()
+ void object::test<9>()
{
set_test_name("Test Limits on setting whitelist too many");
@@ -323,7 +337,7 @@ namespace tut
}
template<> template<>
- void object::test<9>()
+ void object::test<10>()
{
set_test_name("Test to make sure both setWhiteList() functions behave the same");
@@ -341,7 +355,7 @@ namespace tut
}
template<> template<>
- void object::test<10>()
+ void object::test<11>()
{
set_test_name("Test to make sure both setWhiteList() functions behave the same");
@@ -362,7 +376,7 @@ namespace tut
}
template<> template<>
- void object::test<11>()
+ void object::test<12>()
{
set_test_name("Test to make sure both setWhiteList() functions behave the same");
@@ -386,99 +400,99 @@ namespace tut
// Check the "empty whitelist" case
template<> template<>
- void object::test<12>() { whitelist_test("", "http://www.example.com", true); }
+ void object::test<13>() { whitelist_test("", "http://www.example.com", true); }
// Check the "missing scheme" case
template<> template<>
- void object::test<13>() { whitelist_test("www.example.com", "http://www.example.com", true); }
+ void object::test<14>() { whitelist_test("www.example.com", "http://www.example.com", true); }
// Check the "exactly the same" case
template<> template<>
- void object::test<14>() { whitelist_test("http://example.com", "http://example.com", true); }
+ void object::test<15>() { whitelist_test("http://example.com", "http://example.com", true); }
// Check the enable flag
template<> template<>
- void object::test<15>() { whitelist_test(false, "www.example.com", "http://www.secondlife.com", true); }
+ void object::test<16>() { whitelist_test(false, "www.example.com", "http://www.secondlife.com", true); }
template<> template<>
- void object::test<16>() { whitelist_test(true, "www.example.com", "http://www.secondlife.com", false); }
+ void object::test<17>() { whitelist_test(true, "www.example.com", "http://www.secondlife.com", false); }
// Check permutations of trailing slash:
template<> template<>
- void object::test<17>() { whitelist_test("http://www.example.com", "http://www.example.com/", true); }
+ void object::test<18>() { whitelist_test("http://www.example.com", "http://www.example.com/", true); }
template<> template<>
- void object::test<18>() { whitelist_test("http://www.example.com/", "http://www.example.com/", true); }
+ void object::test<19>() { whitelist_test("http://www.example.com/", "http://www.example.com/", true); }
template<> template<>
- void object::test<19>() { whitelist_test("http://www.example.com/", "http://www.example.com", false); }
+ void object::test<20>() { whitelist_test("http://www.example.com/", "http://www.example.com", false); }
template<> template<>
- void object::test<20>() { whitelist_test("http://www.example.com", "http://www.example.com/foobar", true); }
+ void object::test<21>() { whitelist_test("http://www.example.com", "http://www.example.com/foobar", true); }
template<> template<>
- void object::test<21>() { whitelist_test("http://www.example.com/", "http://www.example.com/foobar", false); }
+ void object::test<22>() { whitelist_test("http://www.example.com/", "http://www.example.com/foobar", false); }
// More cases...
template<> template<>
- void object::test<22>() { whitelist_test("http://example.com", "http://example.com/wiki", true); }
+ void object::test<23>() { whitelist_test("http://example.com", "http://example.com/wiki", true); }
template<> template<>
- void object::test<23>() { whitelist_test("www.example.com", "http://www.example.com/help", true); }
+ void object::test<24>() { whitelist_test("www.example.com", "http://www.example.com/help", true); }
template<> template<>
- void object::test<24>() { whitelist_test("http://www.example.com", "http://wwwexample.com", false); }
+ void object::test<25>() { whitelist_test("http://www.example.com", "http://wwwexample.com", false); }
template<> template<>
- void object::test<25>() { whitelist_test("http://www.example.com", "http://www.example.com/wiki", true); }
+ void object::test<26>() { whitelist_test("http://www.example.com", "http://www.example.com/wiki", true); }
template<> template<>
- void object::test<26>() { whitelist_test("example.com", "http://wwwexample.com", false); }
+ void object::test<27>() { whitelist_test("example.com", "http://wwwexample.com", false); }
template<> template<>
- void object::test<27>() { whitelist_test("http://www.example.com/", "http://www.amazon.com/wiki", false); }
+ void object::test<28>() { whitelist_test("http://www.example.com/", "http://www.amazon.com/wiki", false); }
template<> template<>
- void object::test<28>() { whitelist_test("www.example.com", "http://www.amazon.com", false); }
+ void object::test<29>() { whitelist_test("www.example.com", "http://www.amazon.com", false); }
// regexp cases
template<> template<>
- void object::test<29>() { whitelist_test("*.example.com", "http://www.example.com", true); }
+ void object::test<30>() { whitelist_test("*.example.com", "http://www.example.com", true); }
template<> template<>
- void object::test<30>() { whitelist_test("*.example.com", "http://www.amazon.com", false); }
+ void object::test<31>() { whitelist_test("*.example.com", "http://www.amazon.com", false); }
template<> template<>
- void object::test<31>() { whitelist_test("*.example.com", "http://www.example.com/foo/bar", true); }
+ void object::test<32>() { whitelist_test("*.example.com", "http://www.example.com/foo/bar", true); }
template<> template<>
- void object::test<32>() { whitelist_test("*.example.com", "http:/example.com/foo/bar", false); }
+ void object::test<33>() { whitelist_test("*.example.com", "http:/example.com/foo/bar", false); }
template<> template<>
- void object::test<33>() { whitelist_test("*example.com", "http://example.com/foo/bar", true); }
+ void object::test<34>() { whitelist_test("*example.com", "http://example.com/foo/bar", true); }
template<> template<>
- void object::test<34>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?example.com", false); }
+ void object::test<35>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?example.com", false); }
template<> template<>
- void object::test<35>() { whitelist_test("example.com", "http://my.virus.com/foo/bar?example.com", false); }
+ void object::test<36>() { whitelist_test("example.com", "http://my.virus.com/foo/bar?example.com", false); }
template<> template<>
- void object::test<36>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?*example.com", false); }
+ void object::test<37>() { whitelist_test("*example.com", "http://my.virus.com/foo/bar?*example.com", false); }
template<> template<>
- void object::test<37>() { whitelist_test("http://*example.com", "http://www.example.com", true); }
+ void object::test<38>() { whitelist_test("http://*example.com", "http://www.example.com", true); }
template<> template<>
- void object::test<38>() { whitelist_test("http://*.example.com", "http://www.example.com", true); }
+ void object::test<39>() { whitelist_test("http://*.example.com", "http://www.example.com", true); }
template<> template<>
- void object::test<39>() { whitelist_test("http://*.e$?^.com", "http://www.e$?^.com", true); }
+ void object::test<40>() { whitelist_test("http://*.e$?^.com", "http://www.e$?^.com", true); }
template<> template<>
- void object::test<40>() { whitelist_test("*.example.com/foo/bar", "http://www.example.com/", false); }
+ void object::test<41>() { whitelist_test("*.example.com/foo/bar", "http://www.example.com/", false); }
template<> template<>
- void object::test<41>() { whitelist_test("*.example.com/foo/bar", "http://example.com/foo/bar", false); }
+ void object::test<42>() { whitelist_test("*.example.com/foo/bar", "http://example.com/foo/bar", false); }
template<> template<>
- void object::test<42>() { whitelist_test("http://*.example.com/foo/bar", "http://www.example.com", false); }
+ void object::test<43>() { whitelist_test("http://*.example.com/foo/bar", "http://www.example.com", false); }
template<> template<>
- void object::test<43>() { whitelist_test("http://*.example.com", "https://www.example.com", false); }
+ void object::test<44>() { whitelist_test("http://*.example.com", "https://www.example.com", false); }
template<> template<>
- void object::test<44>() { whitelist_test("http*://*.example.com", "rtsp://www.example.com", false); }
+ void object::test<45>() { whitelist_test("http*://*.example.com", "rtsp://www.example.com", false); }
template<> template<>
- void object::test<45>() { whitelist_test("http*://*.example.com", "https://www.example.com", true); }
+ void object::test<46>() { whitelist_test("http*://*.example.com", "https://www.example.com", true); }
template<> template<>
- void object::test<46>() { whitelist_test("example.com", "http://www.example.com", false); }
+ void object::test<47>() { whitelist_test("example.com", "http://www.example.com", false); }
template<> template<>
- void object::test<47>() { whitelist_test("www.example.com", "http://www.example.com:80", false); }
+ void object::test<48>() { whitelist_test("www.example.com", "http://www.example.com:80", false); }
template<> template<>
- void object::test<48>() { whitelist_test("www.example.com", "http://www.example.com", true); }
+ void object::test<49>() { whitelist_test("www.example.com", "http://www.example.com", true); }
template<> template<>
- void object::test<49>() { whitelist_test("www.example.com/", "http://www.example.com", false); }
+ void object::test<50>() { whitelist_test("www.example.com/", "http://www.example.com", false); }
template<> template<>
- void object::test<50>() { whitelist_test("www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true); }
+ void object::test<51>() { whitelist_test("www.example.com/foo/bar/*", "http://www.example.com/foo/bar/baz", true); }
// Path only
template<> template<>
- void object::test<51>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/baz", true); }
+ void object::test<52>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/baz", true); }
template<> template<>
- void object::test<52>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/", false); }
+ void object::test<53>() { whitelist_test("/foo/*/baz", "http://www.example.com/foo/bar/", false); }
}
diff --git a/indra/llrender/CMakeLists.txt b/indra/llrender/CMakeLists.txt
index aac650bec9..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}
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/llfontfreetype.cpp b/indra/llrender/llfontfreetype.cpp
index 44e997340e..786dc64452 100644
--- a/indra/llrender/llfontfreetype.cpp
+++ b/indra/llrender/llfontfreetype.cpp
@@ -98,9 +98,7 @@ LLFontGlyphInfo::LLFontGlyphInfo(U32 index)
mWidth(0), // In pixels
mHeight(0), // In pixels
mXAdvance(0.f), // In pixels
- mYAdvance(0.f), // In pixels
- mIsRendered(FALSE),
- mMetricsValid(FALSE)
+ mYAdvance(0.f) // In pixels
{
}
@@ -199,7 +197,7 @@ BOOL LLFontFreetype::loadFace(const std::string& filename, F32 point_size, F32 v
if (!mIsFallback)
{
// Add the default glyph
- addGlyph(0, 0);
+ addGlyphFromFont(this, 0, 0);
}
mName = filename;
@@ -251,57 +249,10 @@ F32 LLFontFreetype::getXAdvance(llwchar wch) const
if (mFTFace == NULL)
return 0.0;
- //llassert(!mIsFallback);
- U32 glyph_index;
-
// Return existing info only if it is current
LLFontGlyphInfo* gi = getGlyphInfo(wch);
- if (gi && gi->mMetricsValid)
- {
- return gi->mXAdvance;
- }
-
- const LLFontFreetype* fontp = this;
-
- // Initialize char to glyph map
- glyph_index = FT_Get_Char_Index(mFTFace, wch);
- if (glyph_index == 0)
- {
- font_vector_t::const_iterator iter;
- for(iter = mFallbackFonts.begin(); (iter != mFallbackFonts.end()) && (glyph_index == 0); iter++)
- {
- glyph_index = FT_Get_Char_Index((*iter)->mFTFace, wch);
- if(glyph_index)
- {
- fontp = *iter;
- }
- }
- }
-
- if (glyph_index)
+ if (gi)
{
- // This font has this glyph
- fontp->renderGlyph(glyph_index);
-
- // Create the entry if it's not there
- char_glyph_info_map_t::iterator iter2 = mCharGlyphInfoMap.find(wch);
- if (iter2 == mCharGlyphInfoMap.end())
- {
- gi = new LLFontGlyphInfo(glyph_index);
- insertGlyphInfo(wch, gi);
- }
- else
- {
- gi = iter2->second;
- }
-
- gi->mWidth = fontp->mFTFace->glyph->bitmap.width;
- gi->mHeight = fontp->mFTFace->glyph->bitmap.rows;
-
- // 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;
- gi->mMetricsValid = TRUE;
return gi->mXAdvance;
}
else
@@ -323,10 +274,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
return 0.0;
//llassert(!mIsFallback);
- LLFontGlyphInfo* left_glyph_info = get_if_there(mCharGlyphInfoMap, char_left, (LLFontGlyphInfo*)NULL);
+ 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 = get_if_there(mCharGlyphInfoMap, char_right, (LLFontGlyphInfo*)NULL);
+ LLFontGlyphInfo* right_glyph_info = getGlyphInfo(char_right);
U32 right_glyph = right_glyph_info ? right_glyph_info->mGlyphIndex : 0;
FT_Vector delta;
@@ -339,18 +290,10 @@ F32 LLFontFreetype::getXKerning(llwchar char_left, llwchar char_right) const
BOOL LLFontFreetype::hasGlyph(llwchar wch) const
{
llassert(!mIsFallback);
- const LLFontGlyphInfo* gi = getGlyphInfo(wch);
- if (gi && gi->mIsRendered)
- {
- return TRUE;
- }
- else
- {
- return FALSE;
- }
+ return(mCharGlyphInfoMap.find(wch) != mCharGlyphInfoMap.end());
}
-BOOL LLFontFreetype::addChar(llwchar wch) const
+LLFontGlyphInfo* LLFontFreetype::addGlyph(llwchar wch) const
{
if (mFTFace == NULL)
return FALSE;
@@ -364,37 +307,30 @@ BOOL LLFontFreetype::addChar(llwchar wch) const
glyph_index = FT_Get_Char_Index(mFTFace, wch);
if (glyph_index == 0)
{
- //llinfos << "Trying to add glyph from fallback font!" << llendl
+ //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)
{
- addGlyphFromFont(*iter, wch, glyph_index);
- return TRUE;
+ return addGlyphFromFont(*iter, wch, glyph_index);
}
}
}
char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.find(wch);
- if (iter == mCharGlyphInfoMap.end() || !(iter->second->mIsRendered))
+ if (iter == mCharGlyphInfoMap.end())
{
- BOOL result = addGlyph(wch, glyph_index);
- return result;
+ return addGlyphFromFont(this, wch, glyph_index);
}
- return FALSE;
-}
-
-BOOL LLFontFreetype::addGlyph(llwchar wch, U32 glyph_index) const
-{
- return addGlyphFromFont(this, wch, glyph_index);
+ return NULL;
}
-BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
+LLFontGlyphInfo* LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch, U32 glyph_index) const
{
if (mFTFace == NULL)
- return FALSE;
+ return NULL;
llassert(!mIsFallback);
fontp->renderGlyph(glyph_index);
@@ -417,8 +353,6 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch,
// 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;
- gi->mIsRendered = TRUE;
- gi->mMetricsValid = TRUE;
insertGlyphInfo(wch, gi);
@@ -489,7 +423,11 @@ BOOL LLFontFreetype::addGlyphFromFont(const LLFontFreetype *fontp, llwchar wch,
// omit it from the font-image.
}
- return TRUE;
+ 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
@@ -499,7 +437,11 @@ LLFontGlyphInfo* LLFontFreetype::getGlyphInfo(llwchar wch) const
{
return iter->second;
}
- return NULL;
+ 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
@@ -534,11 +476,10 @@ void LLFontFreetype::renderGlyph(U32 glyph_index) const
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.
- loadFace(mName, mPointSize, vert_dpi ,horz_dpi, mFontBitmapCachep->getNumComponents(), mIsFallback);
-
if (mFallbackFonts.empty())
{
llwarns << "LLFontGL::reset(), no fallback fonts present" << llendl;
@@ -557,19 +498,12 @@ void LLFontFreetype::reset(F32 vert_dpi, F32 horz_dpi)
void LLFontFreetype::resetBitmapCache()
{
- // Iterate through glyphs and clear the mIsRendered flag
- for (char_glyph_info_map_t::iterator iter = mCharGlyphInfoMap.begin();
- iter != mCharGlyphInfoMap.end(); ++iter)
- {
- iter->second->mIsRendered = FALSE;
- //FIXME: this is only strictly necessary when resetting the entire font,
- //not just flushing the bitmap
- iter->second->mMetricsValid = FALSE;
- }
+ for_each(mCharGlyphInfoMap.begin(), mCharGlyphInfoMap.end(), DeletePairedPointer());
+ mCharGlyphInfoMap.clear();
mFontBitmapCachep->reset();
// Add the empty glyph
- addGlyph(0, 0);
+ addGlyphFromFont(this, 0, 0);
}
void LLFontFreetype::destroyGL()
@@ -577,21 +511,11 @@ void LLFontFreetype::destroyGL()
mFontBitmapCachep->destroyGL();
}
-BOOL LLFontFreetype::getIsFallback() const
-{
- return mIsFallback;
-}
-
const std::string &LLFontFreetype::getName() const
{
return mName;
}
-F32 LLFontFreetype::getPointSize() const
-{
- return mPointSize;
-}
-
const LLPointer<LLFontBitmapCache> LLFontFreetype::getFontBitmapCache() const
{
return mFontBitmapCachep;
diff --git a/indra/llrender/llfontfreetype.h b/indra/llrender/llfontfreetype.h
index 5adaab3a88..1325b4995b 100644
--- a/indra/llrender/llfontfreetype.h
+++ b/indra/llrender/llfontfreetype.h
@@ -70,10 +70,8 @@ public:
S32 mHeight; // In pixels
F32 mXAdvance; // In pixels
F32 mYAdvance; // In pixels
- BOOL mMetricsValid; // We have up-to-date metrics for this glyph
// Information for actually rendering
- BOOL mIsRendered; // We actually have rendered this glyph
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
@@ -133,34 +131,27 @@ public:
F32 getXAdvance(llwchar wc) const;
F32 getXKerning(llwchar char_left, llwchar char_right) const; // Get the kerning between the two characters
- BOOL hasGlyph(llwchar wch) const; // Has a glyph for this character
- BOOL addChar(llwchar wch) const; // Add a new character to the font if necessary
- BOOL addGlyph(llwchar wch, U32 glyph_index) const; // Add a new glyph to the existing font
- BOOL 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)
-
LLFontGlyphInfo* getGlyphInfo(llwchar wch) const;
- void insertGlyphInfo(llwchar wch, LLFontGlyphInfo* gi) const;
- void renderGlyph(U32 glyph_index) const;
-
void reset(F32 vert_dpi, F32 horz_dpi);
- void resetBitmapCache();
void destroyGL();
- BOOL getIsFallback() const;
-
const std::string& getName() const;
- F32 getPointSize() 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;
diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp
index f7bab3de67..793a526c26 100644
--- a/indra/llrender/llfontgl.cpp
+++ b/indra/llrender/llfontgl.cpp
@@ -44,6 +44,7 @@
#include "llstl.h"
#include "v4color.h"
#include "lltexture.h"
+#include "lldir.h"
// Third party library includes
#include <boost/tokenizer.hpp>
@@ -251,11 +252,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
{
llwchar wch = wstr[i];
- if (!mFontFreetype->hasGlyph(wch))
- {
- addChar(wch);
- }
-
const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
if (!fgi)
{
@@ -298,10 +294,6 @@ S32 LLFontGL::render(const LLWString &wstr, S32 begin_offset, F32 x, F32 y, cons
if (next_char && (next_char < LAST_CHARACTER))
{
// Kern this puppy.
- if (!mFontFreetype->hasGlyph(next_char))
- {
- addChar(next_char);
- }
cur_x += mFontFreetype->getXKerning(wch, next_char);
}
@@ -441,15 +433,22 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
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++)
{
llwchar wch = wchars[i];
- if (wch == 0)
- {
- break; // done
- }
- cur_x += mFontFreetype->getXAdvance(wch);
+ const LLFontGlyphInfo* fgi= mFontFreetype->getGlyphInfo(wch);
+
+ 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, (F32)fgi->mWidth - advance);
+
+ cur_x += advance;
llwchar next_char = wchars[i+1];
if (((i + 1) < begin_offset + max_chars)
@@ -463,6 +462,9 @@ F32 LLFontGL::getWidthF32(const llwchar* wchars, S32 begin_offset, S32 max_chars
cur_x = (F32)llfloor(cur_x + 0.5f);
}
+ // add in extra pixels for last character's width past its xadvance
+ cur_x += width_padding;
+
return cur_x / sScaleX;
}
@@ -662,25 +664,6 @@ S32 LLFontGL::charFromPixelOffset(const llwchar* wchars, S32 begin_offset, F32 t
return llmin(max_chars, pos - begin_offset);
}
-BOOL LLFontGL::addChar(llwchar wch) const
-{
- if (!mFontFreetype->addChar(wch))
- {
- return FALSE;
- }
-
- stop_glerror();
-
- LLFontGlyphInfo *glyph_info = mFontFreetype->getGlyphInfo(wch);
- U32 bitmap_num = glyph_info->mBitmapNum;
-
- const LLFontBitmapCache* font_bitmap_cache = mFontFreetype->getFontBitmapCache();
- LLImageGL *image_gl = font_bitmap_cache->getImageGL(bitmap_num);
- LLImageRaw *image_raw = font_bitmap_cache->getImageRaw(bitmap_num);
- image_gl->setSubImage(image_raw, 0, 0, image_gl->getWidth(), image_gl->getHeight());
- return TRUE;
-}
-
const LLFontDescriptor& LLFontGL::getFontDesc() const
{
return mFontDescriptor;
@@ -910,6 +893,13 @@ LLFontGL* LLFontGL::getFontByName(const std::string& name)
}
}
+//static
+LLFontGL* LLFontGL::getFontDefault()
+{
+ return getFontSansSerif(); // Fallback to sans serif as default font
+}
+
+
// static
std::string LLFontGL::getFontPathSystem()
{
diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h
index ad84b6d641..5f2c86c6c1 100644
--- a/indra/llrender/llfontgl.h
+++ b/indra/llrender/llfontgl.h
@@ -131,8 +131,6 @@ public:
// Returns the index of the character closest to pixel position x (ignoring text to the right of max_pixels and max_chars)
S32 charFromPixelOffset(const llwchar* wchars, S32 char_offset, F32 x, F32 max_pixels=F32_MAX, S32 max_chars = S32_MAX, BOOL round = TRUE) const;
- BOOL addChar(const llwchar wch) const;
-
const LLFontDescriptor& getFontDesc() const;
@@ -167,6 +165,7 @@ public:
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();
diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp
index 45573cd817..7a3d6ec4f2 100644
--- a/indra/llrender/llfontregistry.cpp
+++ b/indra/llrender/llfontregistry.cpp
@@ -380,7 +380,10 @@ 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;
diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp
index 10315bacf1..3400a72385 100644
--- a/indra/llrender/llgl.cpp
+++ b/indra/llrender/llgl.cpp
@@ -593,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
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/llimagegl.cpp b/indra/llrender/llimagegl.cpp
index dd64d753c7..e5fea5b995 100644
--- a/indra/llrender/llimagegl.cpp
+++ b/indra/llrender/llimagegl.cpp
@@ -428,7 +428,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)
diff --git a/indra/llrender/lltexture.h b/indra/llrender/lltexture.h
index c18917b663..0cd9667644 100644
--- a/indra/llrender/lltexture.h
+++ b/indra/llrender/lltexture.h
@@ -61,6 +61,8 @@ public:
//
//interfaces to access LLViewerTexture
//
+ virtual S8 getType() const = 0 ;
+ virtual void setKnownDrawSize(S32 width, S32 height) = 0 ;
virtual bool bindDefaultImage(const S32 stage = 0) const = 0 ;
virtual void forceImmediateUpdate() = 0 ;
virtual void setActive() = 0 ;
diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt
index d9169f57f9..f0b4436df5 100644
--- a/indra/llui/CMakeLists.txt
+++ b/indra/llui/CMakeLists.txt
@@ -43,6 +43,7 @@ set(llui_SOURCE_FILES
llflatlistview.cpp
llfloater.cpp
llfloaterreg.cpp
+ llfloaterreglistener.cpp
llflyoutbutton.cpp
llfocusmgr.cpp
llfunctorregistry.cpp
@@ -58,6 +59,7 @@ set(llui_SOURCE_FILES
llmultislider.cpp
llmultisliderctrl.cpp
llnotifications.cpp
+ llnotificationslistener.cpp
llpanel.cpp
llprogressbar.cpp
llradiogroup.cpp
@@ -86,7 +88,6 @@ set(llui_SOURCE_FILES
lltextbox.cpp
lltexteditor.cpp
lltextparser.cpp
- lltransientfloatermgr.cpp
lltransutil.cpp
lltoggleablemenu.cpp
lltooltip.cpp
@@ -128,6 +129,7 @@ set(llui_HEADER_FILES
llflatlistview.h
llfloater.h
llfloaterreg.h
+ llfloaterreglistener.h
llflyoutbutton.h
llfocusmgr.h
llfunctorregistry.h
@@ -146,6 +148,7 @@ set(llui_HEADER_FILES
llmultisliderctrl.h
llmultislider.h
llnotifications.h
+ llnotificationslistener.h
llpanel.h
llprogressbar.h
llradiogroup.h
@@ -176,7 +179,6 @@ set(llui_HEADER_FILES
lltextparser.h
lltoggleablemenu.h
lltooltip.h
- lltransientfloatermgr.h
lltransutil.h
lluicolortable.h
lluiconstants.h
diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp
index f28fca35c5..bbaf908d2e 100644
--- a/indra/llui/llbutton.cpp
+++ b/indra/llui/llbutton.cpp
@@ -95,8 +95,7 @@ LLButton::Params::Params()
is_toggle("is_toggle", false),
scale_image("scale_image", true),
hover_glow_amount("hover_glow_amount"),
- commit_on_return("commit_on_return", true),
- picture_style("picture_style", false)
+ commit_on_return("commit_on_return", true)
{
addSynonym(is_toggle, "toggle");
held_down_delay.seconds = 0.5f;
@@ -147,22 +146,15 @@ LLButton::LLButton(const LLButton::Params& p)
mHoverGlowStrength(p.hover_glow_amount),
mCommitOnReturn(p.commit_on_return),
mFadeWhenDisabled(FALSE),
- mForcePressedState(FALSE)
+ mForcePressedState(FALSE),
+ mLastDrawCharsCount(0)
{
static LLUICachedControl<S32> llbutton_orig_h_pad ("UIButtonOrigHPad", 0);
static Params default_params(LLUICtrlFactory::getDefaultParams<LLButton>());
- //if we aren't a picture_style button set label as name if not provided
- if (!p.picture_style.isProvided() || !p.picture_style)
+ if (!p.label_selected.isProvided())
{
- if (!p.label.isProvided())
- {
- mUnselectedLabel = p.name();
- }
- if (!p.label_selected.isProvided())
- {
- mSelectedLabel = mUnselectedLabel.getString();
- }
+ mSelectedLabel = mUnselectedLabel;
}
// Hack to make sure there is space for at least one character
@@ -485,6 +477,11 @@ void LLButton::onMouseLeave(S32 x, S32 y, MASK mask)
mNeedsHighlight = FALSE;
}
+void LLButton::setHighlight(bool b)
+{
+ mNeedsHighlight = b;
+}
+
BOOL LLButton::handleHover(S32 x, S32 y, MASK mask)
{
if (!childrenHandleHover(x, y, mask))
@@ -814,7 +811,7 @@ void LLButton::draw()
// 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.
- mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
+ mLastDrawCharsCount = mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset),
label_color % alpha,
mHAlign, LLFontGL::BOTTOM,
LLFontGL::NORMAL,
@@ -1094,18 +1091,3 @@ void LLButton::resetMouseDownTimer()
mMouseDownTimer.stop();
mMouseDownTimer.reset();
}
-
-
-// *TODO: Remove this function after the initial XUI XML re-export pass.
-// static
-void LLButton::setupParamsForExport(Params& p, LLView* parent)
-{
- std::string label = p.label;
- if (label.empty())
- {
- //if our label is empty this is a picture style button
- p.picture_style = true;
- }
-
- LLUICtrl::setupParamsForExport(p, parent);
-}
diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h
index 7ca520b935..08f289092f 100644
--- a/indra/llui/llbutton.h
+++ b/indra/llui/llbutton.h
@@ -115,8 +115,7 @@ public:
// misc
Optional<bool> is_toggle,
scale_image,
- commit_on_return,
- picture_style; //if true, don't display label
+ commit_on_return;
Optional<F32> hover_glow_amount;
Optional<TimeIntervalParam> held_down_delay;
@@ -176,6 +175,7 @@ public:
BOOL getToggleState() const;
void setToggleState(BOOL b);
+ void setHighlight(bool b);
void setFlashing( BOOL b );
BOOL getFlashing() const { return mFlashing; }
@@ -210,6 +210,9 @@ public:
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; }
@@ -238,13 +241,11 @@ public:
void setForcePressedState(BOOL b) { mForcePressedState = b; }
protected:
- 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;
- // If the label is empty, set the picture_style attribute
- static void setupParamsForExport(Params& p, LLView* parent);
private:
void drawBorder(LLUIImage* imagep, const LLColor4& color, S32 size);
void resetMouseDownTimer();
@@ -260,6 +261,7 @@ private:
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> mImageOverlay;
LLFontGL::HAlign mImageOverlayAlignment;
diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp
index 285ce82d2d..e0053b4cc7 100644
--- a/indra/llui/llconsole.cpp
+++ b/indra/llui/llconsole.cpp
@@ -120,6 +120,11 @@ void LLConsole::setFontSize(S32 size_index)
{
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++)
{
diff --git a/indra/llui/lldockablefloater.cpp b/indra/llui/lldockablefloater.cpp
index 228d0e701f..f56cb2eee7 100644
--- a/indra/llui/lldockablefloater.cpp
+++ b/indra/llui/lldockablefloater.cpp
@@ -99,7 +99,7 @@ void LLDockableFloater::toggleInstance(const LLSD& sdname)
{
instance->setMinimized(FALSE);
instance->setVisible(TRUE);
- instance->setFocus(TRUE);
+ gFloaterView->bringToFront(instance);
}
}
@@ -136,11 +136,29 @@ void LLDockableFloater::setMinimized(BOOL minimize)
{
setVisible(FALSE);
}
- setCanDock(!minimize);
+
+ if (minimize)
+ {
+ setCanDock(false);
+ }
+ else if (!minimize && mDockControl.get() != NULL && mDockControl.get()->isDockVisible())
+ {
+ setCanDock(true);
+ }
LLFloater::setMinimized(minimize);
}
+LLView * LLDockableFloater::getDockWidget()
+{
+ LLView * res = NULL;
+ if (getDockControl() != NULL) {
+ res = getDockControl()->getDock();
+ }
+
+ return res;
+}
+
void LLDockableFloater::onDockHidden()
{
setCanDock(FALSE);
@@ -148,7 +166,10 @@ void LLDockableFloater::onDockHidden()
void LLDockableFloater::onDockShown()
{
- setCanDock(TRUE);
+ if (!isMinimized())
+ {
+ setCanDock(TRUE);
+ }
}
void LLDockableFloater::setDocked(bool docked, bool pop_on_undock)
diff --git a/indra/llui/lldockablefloater.h b/indra/llui/lldockablefloater.h
index 499ce9ae8d..46491d8a29 100644
--- a/indra/llui/lldockablefloater.h
+++ b/indra/llui/lldockablefloater.h
@@ -78,6 +78,8 @@ public:
*/
/*virtual*/ void setMinimized(BOOL minimize);
+ LLView * getDockWidget();
+
virtual void onDockHidden();
virtual void onDockShown();
diff --git a/indra/llui/lldockcontrol.cpp b/indra/llui/lldockcontrol.cpp
index cdcd823b1c..35a854267a 100644
--- a/indra/llui/lldockcontrol.cpp
+++ b/indra/llui/lldockcontrol.cpp
@@ -37,7 +37,7 @@
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)
+ mDockWidget(dockWidget), mDockableFloater(dockableFloater), mDockTongue(dockTongue)
{
mDockAt = dockAt;
@@ -63,6 +63,15 @@ LLDockControl::LLDockControl(LLView* dockWidget, LLFloater* dockableFloater,
{
repositionDockable();
}
+
+ if (mDockWidget != NULL)
+ {
+ mDockWidgetVisible = isDockVisible();
+ }
+ else
+ {
+ mDockWidgetVisible = false;
+ }
}
LLDockControl::~LLDockControl()
@@ -75,6 +84,11 @@ void LLDockControl::setDock(LLView* dockWidget)
if (mDockWidget != NULL)
{
repositionDockable();
+ mDockWidgetVisible = isDockVisible();
+ }
+ else
+ {
+ mDockWidgetVisible = false;
}
}
@@ -88,11 +102,10 @@ void LLDockControl::repositionDockable()
LLRect dockRect = mDockWidget->calcScreenRect();
LLRect rootRect;
mGetAllowedRectCallback(rootRect);
- static BOOL prev_visibility = !mDockWidget->getVisible();
// recalculate dockable position if dock position changed, dock visibility changed,
// root view rect changed or recalculation is forced
- if (mPrevDockRect != dockRect || prev_visibility != mDockWidget->getVisible()
+ if (mPrevDockRect != dockRect || mDockWidgetVisible != isDockVisible()
|| mRootRect != rootRect || mRecalculateDocablePosition)
{
// undock dockable and off() if dock not visible
@@ -125,7 +138,7 @@ void LLDockControl::repositionDockable()
mPrevDockRect = dockRect;
mRootRect = rootRect;
mRecalculateDocablePosition = false;
- prev_visibility = mDockWidget->getVisible();
+ mDockWidgetVisible = isDockVisible();
}
}
@@ -143,6 +156,8 @@ bool LLDockControl::isDockVisible()
switch (mDockAt)
{
+ case LEFT: // to keep compiler happy
+ break;
case TOP:
// check is dock inside parent rect
LLRect dockParentRect =
@@ -170,8 +185,27 @@ void LLDockControl::moveDockable()
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 + mDockTongue->getHeight() + dockableRect.getHeight();
@@ -187,8 +221,7 @@ void LLDockControl::moveDockable()
// calculate dock tongue position
- LLRect dockParentRect =
- mDockWidget->getParent()->calcScreenRect();
+ dockParentRect = mDockWidget->getParent()->calcScreenRect();
if (dockRect.getCenterX() < dockParentRect.mLeft)
{
mDockTongueX = dockParentRect.mLeft - mDockTongue->getWidth() / 2;
diff --git a/indra/llui/lldockcontrol.h b/indra/llui/lldockcontrol.h
index e8ffcac0ac..eaedb4c307 100644
--- a/indra/llui/lldockcontrol.h
+++ b/indra/llui/lldockcontrol.h
@@ -48,6 +48,7 @@ public:
enum DocAt
{
TOP
+ ,LEFT
};
public:
@@ -63,6 +64,10 @@ public:
void on();
void off();
void setDock(LLView* dockWidget);
+ LLView* getDock()
+ {
+ return mDockWidget;
+ }
void repositionDockable();
void drawToungue();
bool isDockVisible();
@@ -76,6 +81,7 @@ private:
get_allowed_rect_callback_t mGetAllowedRectCallback;
bool mEnabled;
bool mRecalculateDocablePosition;
+ bool mDockWidgetVisible;
DocAt mDockAt;
LLView* mDockWidget;
LLRect mPrevDockRect;
diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp
index 8eccd709ce..d9b98b1c28 100644
--- a/indra/llui/lldraghandle.cpp
+++ b/indra/llui/lldraghandle.cpp
@@ -49,9 +49,9 @@
#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;
@@ -240,19 +240,20 @@ void LLDragHandleLeft::draw()
void LLDragHandleTop::reshapeTitleBox()
{
+ static LLUICachedControl<S32> title_vpad("UIFloaterTitleVPad", 0);
if( ! mTitleBox)
{
return;
}
const LLFontGL* font = LLFontGL::getFontSansSerif();
- S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD;
+ 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);
diff --git a/indra/llui/llflatlistview.cpp b/indra/llui/llflatlistview.cpp
index e9df361472..19f203b80c 100644
--- a/indra/llui/llflatlistview.cpp
+++ b/indra/llui/llflatlistview.cpp
@@ -44,6 +44,9 @@ const LLSD UNSELECTED_EVENT = LLSD().insert("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"),
@@ -89,7 +92,7 @@ bool LLFlatListView::addItem(LLPanel * item, const LLSD& value /*= LLUUID::null*
//_4 is for MASK
item->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
- item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
rearrangeItems();
notifyParentItemsRectChanged();
@@ -134,7 +137,7 @@ bool LLFlatListView::insertItemAfter(LLPanel* after_item, LLPanel* item_to_add,
//_4 is for MASK
item_to_add->setMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
- item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemMouseClick, this, new_pair, _4));
+ item_to_add->setRightMouseDownCallback(boost::bind(&LLFlatListView::onItemRightMouseClick, this, new_pair, _4));
rearrangeItems();
notifyParentItemsRectChanged();
@@ -333,6 +336,17 @@ void LLFlatListView::sort()
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
@@ -445,6 +459,20 @@ void LLFlatListView::onItemMouseClick(item_pair_t* item_pair, MASK mask)
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);
+}
+
LLFlatListView::item_pair_t* LLFlatListView::getItemPair(LLPanel* item) const
{
llassert(item);
diff --git a/indra/llui/llflatlistview.h b/indra/llui/llflatlistview.h
index af5a9cfa9b..97772bc677 100644
--- a/indra/llui/llflatlistview.h
+++ b/indra/llui/llflatlistview.h
@@ -273,6 +273,8 @@ public:
void setComparator(const ItemComparator* comp) { mItemComparator = comp; }
void sort();
+ bool updateValue(const LLSD& old_value, const LLSD& new_value);
+
protected:
/** Pairs LLpanel representing a single item LLPanel and LLSD associated with it */
@@ -302,6 +304,8 @@ protected:
/** 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.
diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp
index 8d2783db20..aac27e6562 100644
--- a/indra/llui/llfloater.cpp
+++ b/indra/llui/llfloater.cpp
@@ -61,6 +61,7 @@
#include "lltrans.h"
#include "llhelp.h"
#include "llmultifloater.h"
+#include "llsdutil.h"
// use this to control "jumping" behavior when Ctrl-Tabbing
const S32 TABBED_FLOATER_OFFSET = 0;
@@ -132,6 +133,16 @@ LLFloater::handle_map_t LLFloater::sFloaterMap;
LLFloaterView* gFloaterView = NULL;
+/*==========================================================================*|
+// 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)
{
@@ -159,32 +170,11 @@ bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b)
else
return false; // no valid operation for Binary
}
+|*==========================================================================*/
bool LLFloater::KeyCompare::equate(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 true;
- 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
+ return llsd_equals(a, b);
}
//************************************
@@ -199,11 +189,14 @@ LLFloater::Params::Params()
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),
open_callback("open_callback"),
- close_callback("close_callback"),
- can_dock("can_dock", false)
+ close_callback("close_callback")
{
visible = false;
}
@@ -229,7 +222,7 @@ void LLFloater::initClass()
static LLWidgetNameRegistry::StaticRegistrar sRegisterFloaterParams(&typeid(LLFloater::Params), "floater");
LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
-: LLPanel(),
+: LLPanel(), // intentionally do not pass params here, see initFromParams
mDragHandle(NULL),
mTitle(p.title),
mShortTitle(p.short_title),
@@ -243,6 +236,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
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),
@@ -273,11 +268,8 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
mButtonsEnabled[i] = FALSE;
mButtons[i] = NULL;
}
- for (S32 i = 0; i < 4; i++)
- {
- mResizeBar[i] = NULL;
- mResizeHandle[i] = NULL;
- }
+ addDragHandle();
+ addResizeCtrls();
initFromParams(p);
@@ -290,10 +282,6 @@ LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p)
// Note: Floaters constructed from XML call init() twice!
void LLFloater::initFloater()
{
- addDragHandle();
-
- addResizeCtrls();
-
// Close button.
if (mCanClose)
{
@@ -333,9 +321,6 @@ void LLFloater::initFloater()
void LLFloater::addDragHandle()
{
- static LLUICachedControl<S32> floater_close_box_size ("UIFloaterCloseBoxSize", 0);
- S32 close_box_size = mCanClose ? floater_close_box_size : 0;
-
if (!mDragHandle)
{
if (mDragOnLeft)
@@ -356,6 +341,14 @@ void LLFloater::addDragHandle()
}
addChild(mDragHandle);
}
+ layoutDragHandle();
+}
+
+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)
{
@@ -371,40 +364,17 @@ void LLFloater::addDragHandle()
}
void LLFloater::addResizeCtrls()
-{
- for (S32 i = 0; i < 4; i++)
- {
- if (mResizeBar[i])
- {
- removeChild(mResizeBar[i]);
- delete mResizeBar[i];
- mResizeBar[i] = NULL;
- }
- if (mResizeHandle[i])
- {
- removeChild(mResizeHandle[i]);
- delete mResizeHandle[i];
- mResizeHandle[i] = NULL;
- }
- }
- if( !mResizable )
- {
- return;
- }
-
+{
// Resize bars (sides)
- const S32 RESIZE_BAR_THICKNESS = 3;
LLResizeBar::Params p;
p.name("resizebar_left");
p.resizing_view(this);
- p.rect(LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0));
p.min_size(mMinWidth);
p.side(LLResizeBar::LEFT);
mResizeBar[LLResizeBar::LEFT] = LLUICtrlFactory::create<LLResizeBar>(p);
addChild( mResizeBar[LLResizeBar::LEFT] );
p.name("resizebar_top");
- p.rect(LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS));
p.min_size(mMinHeight);
p.side(LLResizeBar::TOP);
@@ -412,15 +382,12 @@ void LLFloater::addResizeCtrls()
addChild( mResizeBar[LLResizeBar::TOP] );
p.name("resizebar_right");
- p.rect(LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0));
p.min_size(mMinWidth);
- p.side(LLResizeBar::RIGHT);
-
+ p.side(LLResizeBar::RIGHT);
mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create<LLResizeBar>(p);
addChild( mResizeBar[LLResizeBar::RIGHT] );
p.name("resizebar_bottom");
- p.rect(LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0));
p.min_size(mMinHeight);
p.side(LLResizeBar::BOTTOM);
mResizeBar[LLResizeBar::BOTTOM] = LLUICtrlFactory::create<LLResizeBar>(p);
@@ -431,27 +398,69 @@ void LLFloater::addResizeCtrls()
// 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.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0));
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.rect(LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT));
handle_p.corner(LLResizeHandle::RIGHT_TOP);
mResizeHandle[1] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
addChild(mResizeHandle[1]);
- handle_p.rect(LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ));
handle_p.corner(LLResizeHandle::LEFT_BOTTOM);
mResizeHandle[2] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
addChild(mResizeHandle[2]);
- handle_p.rect(LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ));
handle_p.corner(LLResizeHandle::LEFT_TOP);
mResizeHandle[3] = LLUICtrlFactory::create<LLResizeHandle>(handle_p);
addChild(mResizeHandle[3]);
+
+ layoutResizeCtrls();
+}
+
+void LLFloater::layoutResizeCtrls()
+{
+ LLRect rect;
+
+ // Resize bars (sides)
+ const S32 RESIZE_BAR_THICKNESS = 3;
+ rect = LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0);
+ mResizeBar[LLResizeBar::LEFT]->setRect(rect);
+
+ rect = LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS);
+ mResizeBar[LLResizeBar::TOP]->setRect(rect);
+
+ rect = LLRect(getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0);
+ mResizeBar[LLResizeBar::RIGHT]->setRect(rect);
+
+ rect = LLRect(0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0);
+ mResizeBar[LLResizeBar::BOTTOM]->setRect(rect);
+
+ // Resize handles (corners)
+ rect = LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0);
+ mResizeHandle[0]->setRect(rect);
+
+ 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);
+
+ 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)
+ {
+ mResizeBar[i]->setVisible(enable);
+ mResizeBar[i]->setEnabled(enable);
+
+ mResizeHandle[i]->setVisible(enable);
+ mResizeHandle[i]->setEnabled(enable);
+ }
}
// virtual
@@ -493,6 +502,7 @@ LLFloater::~LLFloater()
storeRectControl();
setVisible(false); // We're not visible if we're destroyed
storeVisibilityControl();
+ storeDockStateControl();
}
void LLFloater::storeRectControl()
@@ -511,6 +521,15 @@ void LLFloater::storeVisibilityControl()
}
}
+void LLFloater::storeDockStateControl()
+{
+ if( !sQuitting && mDocStateControl.size() > 1 )
+ {
+ LLUI::sSettingGroups["floater"]->setBOOL( mDocStateControl, isDocked() );
+ }
+}
+
+
void LLFloater::setVisible( BOOL visible )
{
LLPanel::setVisible(visible); // calls handleVisibilityChange()
@@ -753,6 +772,12 @@ LLMultiFloater* LLFloater::getHost()
return (LLMultiFloater*)mHostHandle.get();
}
+void LLFloater::applySavedVariables()
+{
+ applyRectControl();
+ applyDockState();
+}
+
void LLFloater::applyRectControl()
{
if (mRectControl.size() > 1)
@@ -769,6 +794,16 @@ void LLFloater::applyRectControl()
}
}
+void LLFloater::applyDockState()
+{
+ if (mDocStateControl.size() > 1)
+ {
+ bool dockState = LLUI::sSettingGroups["floater"]->getBOOL(mDocStateControl);
+ setDocked(dockState);
+ }
+
+}
+
void LLFloater::applyTitle()
{
if (!mDragHandle)
@@ -919,7 +954,8 @@ void LLFloater::handleReshape(const LLRect& new_rect, bool by_user)
void LLFloater::setMinimized(BOOL minimize)
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ 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;
@@ -1092,7 +1128,8 @@ void LLFloater::setFocus( BOOL b )
void LLFloater::setRect(const LLRect &rect)
{
LLPanel::setRect(rect);
- addDragHandle(); // re-add drag handle, sized based on rect
+ layoutDragHandle();
+ layoutResizeCtrls();
}
// virtual
@@ -1262,6 +1299,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)
{
@@ -1380,7 +1423,10 @@ void LLFloater::setDocked(bool docked, bool pop_on_undock)
mButtonsEnabled[BUTTON_DOCK] = !mDocked;
mButtonsEnabled[BUTTON_UNDOCK] = mDocked;
updateButtons();
+
+ storeDockStateControl();
}
+
}
// static
@@ -1393,9 +1439,9 @@ void LLFloater::onClickMinimize(LLFloater* self)
void LLFloater::onClickTearOff(LLFloater* self)
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
if (!self)
return;
+ S32 floater_header_size = self->mHeaderHeight;
LLMultiFloater* host_floater = self->getHost();
if (host_floater) //Tear off
{
@@ -1443,7 +1489,12 @@ void LLFloater::onClickHelp( LLFloater* self )
{
if (self && LLUI::sHelpImpl)
{
- LLUI::sHelpImpl->showTopic(self->getHelpTopic());
+ // find the current help context for this floater
+ std::string help_topic;
+ if (self->findHelpTopic(help_topic))
+ {
+ LLUI::sHelpImpl->showTopic(help_topic);
+ }
}
}
@@ -1547,26 +1598,42 @@ void LLFloater::draw()
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() % alpha );
+ // NOTE: image may not be set
+ image = getBackgroundImage();
+ color = getBackgroundColor();
}
else
{
- gl_rect_2d( left, top, right, bottom, getTransparentColor() % alpha );
+ image = getTransparentImage();
+ color = getTransparentColor();
}
- if(hasFocus()
- && !getIsChrome()
- && !getCurrentTitle().empty())
+ if (image)
+ {
+ // We're using images for this floater's backgrounds
+ image->draw(getLocalRect(), UI_VERTEX_COLOR % alpha);
+ }
+ else
{
- static LLUIColor titlebar_focus_color = LLUIColorTable::instance().getColor("TitleBarFocusColor");
+ // 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 = 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);
+ 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);
+ }
}
}
@@ -1616,18 +1683,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
- static LLUIColor focus_border_color = LLUIColorTable::instance().getColor("FloaterFocusBorderColor");
- static LLUIColor unfocus_border_color = LLUIColorTable::instance().getColor("FloaterUnfocusBorderColor");
- LLUI::setLineWidth(1.5f);
- LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? focus_border_color : unfocus_border_color;
- gl_rect_2d_offset_local(0, getRect().getHeight() + 1, getRect().getWidth() + 1, 0, outlineColor % alpha, -LLPANEL_BORDER_WIDTH, FALSE);
- LLUI::setLineWidth(1.f);
- }
-
// update tearoff button for torn off floaters
// when last host goes away
if (mCanTearOff && !getHost())
@@ -1676,7 +1731,7 @@ void LLFloater::setCanTearOff(BOOL can_tear_off)
void LLFloater::setCanResize(BOOL can_resize)
{
mResizable = can_resize;
- addResizeCtrls();
+ enableResizeCtrls(can_resize);
}
void LLFloater::setCanDrag(BOOL can_drag)
@@ -1777,7 +1832,6 @@ void LLFloater::buildButtons()
LLButton::Params p;
p.name(sButtonNames[i]);
p.rect(btn_rect);
- p.label("");
p.image_unselected.name(sButtonActiveImageNames[i]);
// Selected, no matter if hovered or not, is "pressed"
p.image_selected.name(sButtonPressedImageNames[i]);
@@ -1790,6 +1844,7 @@ void LLFloater::buildButtons()
p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT);
p.tool_tip(sButtonToolTips[i]);
p.scale_image(true);
+ p.chrome(true);
LLButton* buttonp = LLUICtrlFactory::create<LLButton>(p);
addChild(buttonp);
@@ -2112,7 +2167,8 @@ void LLFloaterView::focusFrontFloater()
void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom)
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
static LLUICachedControl<S32> minimized_width ("UIMinimizedWidth", 0);
S32 col = 0;
LLRect snap_rect_local = getLocalSnapRect();
@@ -2487,6 +2543,11 @@ void LLFloater::setInstanceName(const std::string& name)
{
mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName);
}
+ if(!mDocStateControl.empty())
+ {
+ mDocStateControl = LLFloaterReg::declareDockStateControl(mInstanceName);
+ }
+
}
}
@@ -2527,6 +2588,9 @@ void LLFloater::setupParamsForExport(Params& p, LLView* parent)
void LLFloater::initFromParams(const LLFloater::Params& p)
{
+ // *NOTE: We have too many classes derived from LLFloater to retrofit them
+ // all to pass in params via constructors. So we use this method.
+
// control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible
LLPanel::initFromParams(p);
@@ -2538,11 +2602,12 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
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;
- mResizable = p.can_resize;
- mMinWidth = p.min_width;
- mMinHeight = p.min_height;
+ mHeaderHeight = p.header_height;
+ mLegacyHeaderHeight = p.legacy_header_height;
mSingleInstance = p.single_instance;
mAutoTile = p.auto_tile;
@@ -2554,6 +2619,11 @@ void LLFloater::initFromParams(const LLFloater::Params& p)
{
mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set
}
+
+ if(p.save_dock_state)
+ {
+ mDocStateControl = "t"; // flag to build mDocStateControl name once mInstanceName is set
+ }
// open callback
if (p.open_callback.isProvided())
@@ -2598,6 +2668,23 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
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;
+
+ // This will also update drag handle, title bar, close box, etc.
+ setRect(rect);
+ }
+
BOOL result;
{
LLFastTimer ft(POST_BUILD);
@@ -2615,6 +2702,18 @@ bool LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr o
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 7a6c3f6863..95c8dd84f6 100644
--- a/indra/llui/llfloater.h
+++ b/indra/llui/llfloater.h
@@ -87,12 +87,14 @@ friend class LLMultiFloater;
public:
struct KeyCompare
{
- static bool compare(const LLSD& a, const LLSD& b);
+// 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 EFloaterButtons
@@ -122,7 +124,10 @@ public:
can_tear_off,
save_rect,
save_visibility,
+ save_dock_state,
can_dock;
+ Optional<S32> header_height,
+ legacy_header_height; // HACK see initFromXML()
Optional<CommitCallbackParam> open_callback,
close_callback;
@@ -183,7 +188,13 @@ 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 isFrontmost();
BOOL isDependent() { return !mDependeeHandle.isDead(); }
void setCanMinimize(BOOL can_minimize);
@@ -201,11 +212,15 @@ public:
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(const LLSD& key) {}
@@ -265,9 +280,14 @@ public:
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);
@@ -291,7 +311,10 @@ private:
void buildButtons();
BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index);
void addResizeCtrls();
+ void layoutResizeCtrls();
+ void enableResizeCtrls(bool enable);
void addDragHandle();
+ void layoutDragHandle(); // repair layout
public:
// Called when floater is opened, passes mKey
@@ -305,6 +328,7 @@ public:
protected:
std::string mRectControl;
std::string mVisibilityControl;
+ std::string mDocStateControl;
LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg
LLDragHandle* mDragHandle;
@@ -329,6 +353,8 @@ private:
S32 mMinWidth;
S32 mMinHeight;
+ S32 mHeaderHeight; // height in pixels of header for title, drag bar
+ S32 mLegacyHeaderHeight;// HACK see initFloaterXML()
BOOL mMinimized;
BOOL mForeground;
diff --git a/indra/llui/llfloaterreg.cpp b/indra/llui/llfloaterreg.cpp
index 815260dff3..03925f922c 100644
--- a/indra/llui/llfloaterreg.cpp
+++ b/indra/llui/llfloaterreg.cpp
@@ -36,6 +36,7 @@
#include "llfloater.h"
#include "llmultifloater.h"
+#include "llfloaterreglistener.h"
//*******************************************************
@@ -45,6 +46,8 @@ LLFloaterReg::instance_map_t LLFloaterReg::sInstanceMap;
LLFloaterReg::build_map_t LLFloaterReg::sBuildMap;
std::map<std::string,std::string> LLFloaterReg::sGroupMap;
+static LLFloaterRegListener sFloaterRegListener("LLFloaterReg");
+
//*******************************************************
//static
@@ -124,14 +127,14 @@ LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key)
bool success = LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, NULL);
if (!success)
{
- llwarns << "Failed to buid floater type: '" << name << "'." << llendl;
+ 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->applyRectControl(); // Can't apply rect control until setting instance 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();
@@ -249,7 +252,7 @@ bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key)
bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
{
LLFloater* instance = findInstance(name, key);
- if (instance && !instance->isMinimized() && instance->isInVisibleChain())
+ if (LLFloater::isShown(instance))
{
// When toggling *visibility*, close the host instead of the floater when hosted
if (instance->getHost())
@@ -269,14 +272,7 @@ bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key)
bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key)
{
LLFloater* instance = findInstance(name, key);
- if (instance && !instance->isMinimized() && instance->isInVisibleChain())
- {
- return true;
- }
- else
- {
- return false;
- }
+ return LLFloater::isShown(instance);
}
//static
@@ -368,6 +364,26 @@ std::string LLFloaterReg::declareVisibilityControl(const std::string& name)
}
//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
diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h
index 7edac43c96..634a235926 100644
--- a/indra/llui/llfloaterreg.h
+++ b/indra/llui/llfloaterreg.h
@@ -70,6 +70,7 @@ public:
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;
@@ -120,6 +121,10 @@ public:
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
diff --git a/indra/llui/llfloaterreglistener.cpp b/indra/llui/llfloaterreglistener.cpp
new file mode 100644
index 0000000000..57d148b5af
--- /dev/null
+++ b/indra/llui/llfloaterreglistener.cpp
@@ -0,0 +1,114 @@
+/**
+ * @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(const std::string& pumpName):
+ LLDispatchListener(pumpName, "op")
+{
+ add("getBuildMap", &LLFloaterRegListener::getBuildMap, LLSD().insert("reply", LLSD()));
+ LLSD requiredName;
+ requiredName["name"] = LLSD();
+ add("showInstance", &LLFloaterRegListener::showInstance, requiredName);
+ add("hideInstance", &LLFloaterRegListener::hideInstance, requiredName);
+ add("toggleInstance", &LLFloaterRegListener::toggleInstance, requiredName);
+ LLSD requiredNameButton;
+ requiredNameButton["name"] = LLSD();
+ requiredNameButton["button"] = LLSD();
+ add("clickButton", &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..304ecd1090
--- /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 "lleventdispatcher.h"
+#include <string>
+
+class LLSD;
+
+/// Event API wrapper for LLFloaterReg
+class LLFloaterRegListener: public LLDispatchListener
+{
+public:
+ /// As all public LLFloaterReg methods are static, there's no point in
+ /// binding an LLFloaterReg instance.
+ LLFloaterRegListener(const std::string& pumpName);
+
+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
index 3483bac782..abb0b869eb 100644
--- a/indra/llui/llflyoutbutton.cpp
+++ b/indra/llui/llflyoutbutton.cpp
@@ -48,6 +48,7 @@ LLFlyoutButton::LLFlyoutButton(const Params& p)
// 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);
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/llhandle.h b/indra/llui/llhandle.h
index 10a7fd4544..899f6b9326 100644
--- a/indra/llui/llhandle.h
+++ b/indra/llui/llhandle.h
@@ -60,7 +60,7 @@ template <typename T>
class LLHandle
{
public:
- LLHandle() : mTombStone(sDefaultTombStone) {}
+ LLHandle() : mTombStone(getDefaultTombStone()) {}
const LLHandle<T>& operator =(const LLHandle<T>& other)
{
mTombStone = other.mTombStone;
@@ -74,7 +74,7 @@ public:
void markDead()
{
- mTombStone = sDefaultTombStone;
+ mTombStone = getDefaultTombStone();
}
T* get() const
@@ -104,13 +104,13 @@ protected:
LLPointer<LLTombStone<T> > mTombStone;
private:
- static LLPointer<LLTombStone<T> > sDefaultTombStone;
+ static LLPointer<LLTombStone<T> >& getDefaultTombStone()
+ {
+ static LLPointer<LLTombStone<T> > sDefaultTombStone = new LLTombStone<T>;
+ return 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>
{
diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp
index 0330a2b374..b1bd2b89a9 100644
--- a/indra/llui/lliconctrl.cpp
+++ b/indra/llui/lliconctrl.cpp
@@ -56,7 +56,10 @@ LLIconCtrl::Params::Params()
LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p)
: LLUICtrl(p),
mColor(p.color()),
- mImagep(p.image)
+ mImagep(p.image),
+ mPriority(0),
+ mDrawWidth(0),
+ mDrawHeight(0)
{
if (mImagep.notNull())
{
@@ -93,12 +96,14 @@ void LLIconCtrl::setValue(const LLSD& value )
LLUICtrl::setValue(tvalue);
if (tvalue.isUUID())
{
- mImagep = LLUI::getUIImageByID(tvalue.asUUID());
+ mImagep = LLUI::getUIImageByID(tvalue.asUUID(), mPriority);
}
else
{
- mImagep = LLUI::getUIImage(tvalue.asString());
+ mImagep = LLUI::getUIImage(tvalue.asString(), mPriority);
}
+
+ setIconImageDrawSize();
}
std::string LLIconCtrl::getImageName() const
@@ -108,3 +113,15 @@ std::string LLIconCtrl::getImageName() const
else
return std::string();
}
+
+void LLIconCtrl::setIconImageDrawSize()
+{
+ if(mImagep.notNull() && mDrawWidth && mDrawHeight)
+ {
+ if(mImagep->getImage().notNull())
+ {
+ mImagep->getImage()->setKnownDrawSize(mDrawWidth, mDrawHeight) ;
+ }
+ }
+}
+
diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h
index ff25b0d53e..66368f979b 100644
--- a/indra/llui/lliconctrl.h
+++ b/indra/llui/lliconctrl.h
@@ -60,6 +60,7 @@ public:
protected:
LLIconCtrl(const Params&);
friend class LLUICtrlFactory;
+
public:
virtual ~LLIconCtrl();
@@ -72,10 +73,20 @@ public:
std::string getImageName() const;
void setColor(const LLColor4& color) { mColor = color; }
+
+private:
+ void setIconImageDrawSize() ;
+
+protected:
+ S32 mPriority;
+
+ //the output size of the icon image if set.
+ S32 mDrawWidth ;
+ S32 mDrawHeight ;
private:
LLUIColor mColor;
- LLPointer<LLUIImage> mImagep;
+ LLPointer<LLUIImage> mImagep;
};
#endif
diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp
index 5eade72b61..bac5491943 100644
--- a/indra/llui/lllayoutstack.cpp
+++ b/indra/llui/lllayoutstack.cpp
@@ -229,7 +229,7 @@ static void get_attribute_bool_and_write(LLXMLNodePtr node,
LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams<LLLayoutStack>());
- LLXUIParser::instance().readXUI(node, p);
+ 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
@@ -401,6 +401,16 @@ void LLLayoutStack::collapsePanel(LLPanel* panel, BOOL collapsed)
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::updateLayout(BOOL force_resize)
{
static LLUICachedControl<S32> resize_bar_overlap ("UIResizeBarOverlap", 0);
@@ -713,6 +723,24 @@ LLLayoutStack::LayoutPanel* LLLayoutStack::findEmbeddedPanel(LLPanel* panelp) co
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()
{
diff --git a/indra/llui/lllayoutstack.h b/indra/llui/lllayoutstack.h
index 49cbe7270f..9ded48ef6a 100644
--- a/indra/llui/lllayoutstack.h
+++ b/indra/llui/lllayoutstack.h
@@ -80,6 +80,7 @@ public:
void collapsePanel(LLPanel* panel, BOOL collapsed = TRUE);
S32 getNumPanels() { return mPanels.size(); }
+ void updatePanelAutoResize(const std::string& panel_name, BOOL auto_resize);
protected:
LLLayoutStack(const Params&);
friend class LLUICtrlFactory;
@@ -96,7 +97,9 @@ private:
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
diff --git a/indra/llui/lllineeditor.cpp b/indra/llui/lllineeditor.cpp
index 693ea5bb45..75905d0927 100644
--- a/indra/llui/lllineeditor.cpp
+++ b/indra/llui/lllineeditor.cpp
@@ -148,6 +148,7 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
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()),
@@ -164,13 +165,8 @@ LLLineEditor::LLLineEditor(const LLLineEditor::Params& p)
mTripleClickTimer.reset();
setText(p.default_text());
- // 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;
+ // Initialize current history line iterator
+ mCurrentHistoryLine = mLineHistory.begin();
LLRect border_rect(getLocalRect());
// adjust for gl line drawing glitch
@@ -278,16 +274,31 @@ 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() )
{
- mLineHistory.pop_back();
+ // 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.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;
}
}
@@ -357,11 +368,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;
}
@@ -1254,9 +1262,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
@@ -1271,9 +1279,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
@@ -1536,18 +1544,24 @@ void LLLineEditor::drawBackground()
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(),
- gFocusMgr.getFocusColor(),
+ tmp_color,
gFocusMgr.getFocusFlashWidth());
}
- image->draw(getLocalRect());
+ 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<S32> lineeditor_v_pad ("UILineEditorVPad", 0);
@@ -1600,8 +1614,10 @@ void LLLineEditor::draw()
{
text_color = mReadOnlyFgColor.get();
}
+ 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.
@@ -1624,7 +1640,7 @@ void LLLineEditor::draw()
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(1.0f));
+ + mPreeditBgColor * (1 - preedit_standout_brightness)).setAlpha(alpha/*1.0f*/));
}
else
{
@@ -1633,7 +1649,7 @@ void LLLineEditor::draw()
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(1.0f));
+ + mPreeditBgColor * (1 - preedit_marker_brightness)).setAlpha(alpha/*1.0f*/));
}
}
}
@@ -1676,15 +1692,17 @@ void LLLineEditor::draw()
if( (rendered_pixels_right < (F32)mMaxHPixels) && (rendered_text < text_len) )
{
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));
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,
0,
LLFontGL::NO_SHADOW,
@@ -1750,8 +1768,9 @@ void LLLineEditor::draw()
cursor_right, cursor_bottom, text_color);
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
+ 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,
- 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,
0,
LLFontGL::NO_SHADOW,
@@ -2291,14 +2310,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);
@@ -2500,20 +2525,3 @@ LLWString LLLineEditor::getConvertedText() const
}
return text;
}
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLLinePrevalidateFunc>::equals(const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b)
- {
- return false;
- }
-
- template<>
- bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
- const boost::function<void (LLLineEditor *)> &a,
- const boost::function<void (LLLineEditor *)> &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/lllineeditor.h b/indra/llui/lllineeditor.h
index 48d68b9935..d3daa941cf 100644
--- a/indra/llui/lllineeditor.h
+++ b/indra/llui/lllineeditor.h
@@ -172,6 +172,8 @@ public:
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(); }
@@ -286,8 +288,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;
@@ -390,15 +393,4 @@ private:
}; // end class LLLineEditor
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLLinePrevalidateFunc>::equals(
- const LLLinePrevalidateFunc &a, const LLLinePrevalidateFunc &b);
-
- template<>
- bool ParamCompare<boost::function<void (LLLineEditor *)> >::equals(
- const boost::function<void (LLLineEditor *)> &a, const boost::function<void (LLLineEditor *)> &b);
-}
-
#endif // LL_LINEEDITOR_
diff --git a/indra/llui/lllocalcliprect.cpp b/indra/llui/lllocalcliprect.cpp
index 058b6ae178..43c21e250c 100644
--- a/indra/llui/lllocalcliprect.cpp
+++ b/indra/llui/lllocalcliprect.cpp
@@ -113,6 +113,9 @@ 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;
diff --git a/indra/llui/llmenubutton.cpp b/indra/llui/llmenubutton.cpp
index 8dbcd6e229..a657ed039a 100644
--- a/indra/llui/llmenubutton.cpp
+++ b/indra/llui/llmenubutton.cpp
@@ -85,6 +85,8 @@ void LLMenuButton::toggleMenu()
void LLMenuButton::hideMenu()
{
+ if(!mMenu)
+ return;
mMenu->setVisible(FALSE);
}
diff --git a/indra/llui/llmenugl.cpp b/indra/llui/llmenugl.cpp
index 14bee0465c..956e843987 100644
--- a/indra/llui/llmenugl.cpp
+++ b/indra/llui/llmenugl.cpp
@@ -279,47 +279,7 @@ 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( "Ctrl-" );
- }
- else
- {
- st.append( "Cmd-" ); // Symbol would be "\xE2\x8C\x98"
- }
- }
- if( mAcceleratorMask & MASK_ALT )
- st.append( "Opt-" ); // Symbol would be "\xE2\x8C\xA5"
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( "Shift-" ); // Symbol would be "\xE2\x8C\xA7"
-#else
- if( mAcceleratorMask & MASK_CONTROL )
- st.append( "Ctrl-" );
- if( mAcceleratorMask & MASK_ALT )
- st.append( "Alt-" );
- if( mAcceleratorMask & MASK_SHIFT )
- st.append( "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;
}
@@ -499,12 +459,6 @@ void LLMenuItemGL::draw( void )
LLColor4 color;
- LLFontGL::ShadowType shadow_style = LLFontGL::NO_SHADOW;
- if (getEnabled() && !mDrawTextDisabled )
- {
- shadow_style = LLFontGL::DROP_SHADOW_SOFT;
- }
-
if ( getEnabled() && getHighlight() )
{
color = mHighlightForeground.get();
@@ -522,26 +476,26 @@ void LLMenuItemGL::draw( void )
if (mBriefItem)
{
mFont->render( mLabel, 0, BRIEF_PAD_PIXELS / 2, 0, color,
- LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_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, LLFontGL::NORMAL, shadow_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, LLFontGL::NORMAL, shadow_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, LLFontGL::NORMAL, shadow_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, LLFontGL::NORMAL, shadow_style, S32_MAX, S32_MAX, NULL, FALSE );
+ LLFontGL::RIGHT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE );
}
}
@@ -1500,12 +1454,6 @@ void LLMenuItemBranchDownGL::draw( void )
gl_rect_2d( 0, getRect().getHeight(), getRect().getWidth(), 0 );
}
- LLFontGL::ShadowType shadow_style = LLFontGL::NO_SHADOW;
- if (getEnabled() && !getDrawTextDisabled() )
- {
- shadow_style = LLFontGL::DROP_SHADOW_SOFT;
- }
-
LLColor4 color;
if (getHighlight())
{
@@ -1520,7 +1468,7 @@ void LLMenuItemBranchDownGL::draw( void )
color = mDisabledColor.get();
}
getFont()->render( mLabel.getWString(), 0, (F32)getRect().getWidth() / 2.f, (F32)LABEL_BOTTOM_PAD_PIXELS, color,
- LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL, shadow_style );
+ LLFontGL::HCENTER, LLFontGL::BOTTOM, LLFontGL::NORMAL);
// underline navigation key only when keyboard navigation has been initiated
@@ -1595,8 +1543,6 @@ LLMenuScrollItem::LLMenuScrollItem(const Params& p)
}
LLButton::Params bparams;
- bparams.label("");
- bparams.label_selected("");
bparams.mouse_opaque(true);
bparams.scale_image(false);
bparams.click_callback(p.scroll_callback);
@@ -2934,8 +2880,8 @@ void hide_top_view( LLView* view )
}
-// x and y are the desired location for the popup, NOT necessarily the
-// mouse location
+// 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)
{
@@ -3475,7 +3421,7 @@ void LLMenuHolderGL::setActivatedItem(LLMenuItemGL* item)
LLTearOffMenu::LLTearOffMenu(LLMenuGL* menup) :
LLFloater(LLSD())
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ S32 floater_header_size = getHeaderHeight();
setName(menup->getName());
setTitle(menup->getLabel());
@@ -3519,7 +3465,6 @@ LLTearOffMenu::~LLTearOffMenu()
void LLTearOffMenu::draw()
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
mMenu->setBackgroundVisible(isBackgroundOpaque());
mMenu->needsArrange();
diff --git a/indra/llui/llmenugl.h b/indra/llui/llmenugl.h
index 48887ec352..09d9e407c7 100644
--- a/indra/llui/llmenugl.h
+++ b/indra/llui/llmenugl.h
@@ -505,7 +505,7 @@ public:
void buildDrawLabels();
void createJumpKeys();
- // 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
diff --git a/indra/llui/llmodaldialog.cpp b/indra/llui/llmodaldialog.cpp
index f77ec5f4c7..387af05935 100644
--- a/indra/llui/llmodaldialog.cpp
+++ b/indra/llui/llmodaldialog.cpp
@@ -297,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 9d716a1880..863572fb5a 100644
--- a/indra/llui/llmodaldialog.h
+++ b/indra/llui/llmodaldialog.h
@@ -73,7 +73,8 @@ public:
static void onAppFocusGained();
static S32 activeCount() { return sModalStack.size(); }
-
+ static void shutdownModals();
+
protected:
void centerOnScreen();
diff --git a/indra/llui/llmultifloater.cpp b/indra/llui/llmultifloater.cpp
index e8ce1a8d97..78738c826d 100644
--- a/indra/llui/llmultifloater.cpp
+++ b/indra/llui/llmultifloater.cpp
@@ -54,7 +54,8 @@ LLMultiFloater::LLMultiFloater(const LLSD& key, const LLFloater::Params& params)
void LLMultiFloater::buildTabContainer()
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ const LLFloater::Params& default_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = default_params.header_height;
LLTabContainer::Params p;
p.name(std::string("Preview Tabs"));
@@ -131,7 +132,8 @@ BOOL LLMultiFloater::closeAllFloaters()
void LLMultiFloater::growToFit(S32 content_width, S32 content_height)
{
static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 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);
@@ -432,6 +434,7 @@ void LLMultiFloater::onTabSelected()
void LLMultiFloater::setCanResize(BOOL can_resize)
{
LLFloater::setCanResize(can_resize);
+ if (!mTabContainer) return;
if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM)
{
mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH);
@@ -455,13 +458,16 @@ BOOL LLMultiFloater::postBuild()
}
mTabContainer = getChild<LLTabContainer>("Preview Tabs");
+
+ setCanResize(mResizable);
return TRUE;
}
void LLMultiFloater::updateResizeLimits()
{
static LLUICachedControl<S32> tabcntr_close_btn_size ("UITabCntrCloseBtnSize", 0);
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 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;
diff --git a/indra/llui/llnotifications.cpp b/indra/llui/llnotifications.cpp
index 25e2475f59..ef222bad60 100644
--- a/indra/llui/llnotifications.cpp
+++ b/indra/llui/llnotifications.cpp
@@ -34,11 +34,13 @@
#include "llnotifications.h"
+#include "llxmlnode.h"
#include "lluictrl.h"
#include "lluictrlfactory.h"
#include "lldir.h"
#include "llsdserialize.h"
#include "lltrans.h"
+#include "llnotificationslistener.h"
#include <algorithm>
#include <boost/regex.hpp>
@@ -944,6 +946,8 @@ LLNotifications::LLNotifications() : LLNotificationChannelBase(LLNotificationFil
mIgnoreAllNotifications(false)
{
LLUICtrl::CommitCallbackRegistry::currentRegistrar().add("Notification.Show", boost::bind(&LLNotifications::addFromCallback, this, _2));
+
+ mListener.reset(new LLNotificationsListener(*this));
}
diff --git a/indra/llui/llnotifications.h b/indra/llui/llnotifications.h
index 19895c3293..0d7cb74f70 100644
--- a/indra/llui/llnotifications.h
+++ b/indra/llui/llnotifications.h
@@ -102,7 +102,7 @@
#include "llfunctorregistry.h"
#include "llpointer.h"
#include "llinitparam.h"
-#include "llxmlnode.h"
+#include "llnotificationslistener.h"
class LLNotification;
typedef boost::shared_ptr<LLNotification> LLNotificationPtr;
@@ -160,7 +160,7 @@ public:
LLNotificationForm();
LLNotificationForm(const LLSD& sd);
LLNotificationForm(const std::string& name,
- const LLPointer<LLXMLNode> xml_node);
+ const LLPointer<class LLXMLNode> xml_node);
LLSD asLLSD() const;
@@ -813,9 +813,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
{
@@ -839,7 +849,7 @@ public:
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);
@@ -918,6 +928,8 @@ private:
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..75f4d6177d
--- /dev/null
+++ b/indra/llui/llnotificationslistener.cpp
@@ -0,0 +1,55 @@
+/**
+ * @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"
+
+LLNotificationsListener::LLNotificationsListener(LLNotifications & notifications) :
+ LLDispatchListener("LLNotifications", "op"),
+ mNotifications(notifications)
+{
+ add("requestAdd", &LLNotificationsListener::requestAdd);
+}
+
+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);
+}
diff --git a/indra/llui/llnotificationslistener.h b/indra/llui/llnotificationslistener.h
new file mode 100644
index 0000000000..6f71a7c781
--- /dev/null
+++ b/indra/llui/llnotificationslistener.h
@@ -0,0 +1,34 @@
+/**
+ * @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 "lleventdispatcher.h"
+
+class LLNotifications;
+class LLSD;
+
+class LLNotificationsListener : public LLDispatchListener
+{
+public:
+ LLNotificationsListener(LLNotifications & notifications);
+
+ void requestAdd(LLSD const & event_data) const;
+
+private:
+ void NotificationResponder(const std::string& replypump,
+ const LLSD& notification,
+ const LLSD& response) const;
+ LLNotifications & mNotifications;
+};
+
+#endif // LL_LLNOTIFICATIONSLISTENER_H
diff --git a/indra/llui/llpanel.cpp b/indra/llui/llpanel.cpp
index 69ff3dddc3..07c0f3ce84 100644
--- a/indra/llui/llpanel.cpp
+++ b/indra/llui/llpanel.cpp
@@ -71,10 +71,12 @@ const LLPanel::Params& LLPanel::getDefaultParams()
LLPanel::Params::Params()
: has_border("border", false),
border(""),
- bg_opaque_color("bg_opaque_color"),
- bg_alpha_color("bg_alpha_color"),
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"),
@@ -92,10 +94,12 @@ LLPanel::Params::Params()
LLPanel::LLPanel(const LLPanel::Params& p)
: LLUICtrl(p),
- mBgColorAlpha(p.bg_alpha_color()),
- mBgColorOpaque(p.bg_opaque_color()),
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),
@@ -103,9 +107,9 @@ LLPanel::LLPanel(const LLPanel::Params& p)
mCommitCallbackRegistrar(false),
mEnableCallbackRegistrar(false),
mXMLFilename(p.filename)
+ // *NOTE: Be sure to also change LLPanel::initFromParams(). We have too
+ // many classes derived from LLPanel to retrofit them all to pass in params.
{
- setIsChrome(FALSE);
-
if (p.has_border)
{
addBorder(p.border);
@@ -178,19 +182,31 @@ void LLPanel::draw()
// 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.get() % alpha);
+ // 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.get() % alpha);
+ // transparent, in-back look
+ if (mBgAlphaImage.notNull())
+ {
+ mBgAlphaImage->draw( local_rect, UI_VERTEX_COLOR % alpha );
+ }
+ else
+ {
+ gl_rect_2d( local_rect, mBgAlphaColor.get() % alpha );
+ }
}
}
@@ -443,7 +459,8 @@ void LLPanel::initFromParams(const LLPanel::Params& p)
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();
}
static LLFastTimer::DeclareTimer FTM_PANEL_SETUP("Panel Setup");
@@ -474,7 +491,7 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
{
//if we are exporting, we want to export the current xml
//not the referenced xml
- LLXUIParser::instance().readXUI(node, params);
+ LLXUIParser::instance().readXUI(node, params, xml_filename);
Params output_params(params);
setupParamsForExport(output_params, parent);
output_node->setName(node->getName()->mString);
@@ -490,14 +507,15 @@ BOOL LLPanel::initPanelXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr outpu
return FALSE;
}
- LLXUIParser::instance().readXUI(referenced_xml, params);
+ LLXUIParser::instance().readXUI(referenced_xml, params, xml_filename);
// add children using dimensions from referenced xml for consistent layout
setShape(params.rect);
LLUICtrlFactory::createChildren(this, referenced_xml, child_registry_t::instance());
}
- LLXUIParser::instance().readXUI(node, params);
+ // ask LLUICtrlFactory for filename, since xml_filename might be empty
+ LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
if (output_node)
{
@@ -810,6 +828,47 @@ LLPanel *LLPanel::childGetVisibleTab(const std::string& id) const
return NULL;
}
+static LLPanel *childGetVisibleTabWithHelp(LLView *parent)
+{
+ LLView *child;
+
+ // look through immediate children first for an active tab with help
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ {
+ LLTabContainer *tab = dynamic_cast<LLTabContainer *>(child);
+ if (tab && tab->getVisible())
+ {
+ LLPanel *curTabPanel = tab->getCurrentPanel();
+ if (curTabPanel && !curTabPanel->getHelpTopic().empty())
+ {
+ return curTabPanel;
+ }
+ }
+ }
+
+ // then try a bit harder and recurse through all children
+ for (child = parent->getFirstChild(); child; child = parent->findNextSibling(child))
+ {
+ if (child->getVisible())
+ {
+ LLPanel* tab = ::childGetVisibleTabWithHelp(child);
+ if (tab)
+ {
+ return tab;
+ }
+ }
+ }
+
+ // couldn't find any active tabs with a help topic string
+ return NULL;
+}
+
+LLPanel *LLPanel::childGetVisibleTabWithHelp()
+{
+ // find a visible tab with a help topic (to determine help context)
+ return ::childGetVisibleTabWithHelp(this);
+}
+
void LLPanel::childSetPrevalidate(const std::string& id, BOOL (*func)(const LLWString &) )
{
LLLineEditor* child = findChild<LLLineEditor>(id);
diff --git a/indra/llui/llpanel.h b/indra/llui/llpanel.h
index 0594762333..c213809d68 100644
--- a/indra/llui/llpanel.h
+++ b/indra/llui/llpanel.h
@@ -48,6 +48,7 @@ const BOOL BORDER_YES = TRUE;
const BOOL BORDER_NO = FALSE;
class LLButton;
+class LLUIImage;
/*
* General purpose concrete view base class.
@@ -72,12 +73,15 @@ public:
Optional<bool> has_border;
Optional<LLViewBorder::Params> border;
- Optional<LLUIColor> bg_opaque_color,
- bg_alpha_color;
-
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;
@@ -127,10 +131,12 @@ public:
BOOL hasBorder() const { return mBorder != NULL; }
void setBorderVisible( BOOL b );
- 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; }
@@ -208,6 +214,7 @@ public:
// LLTabContainer
void childShowTab(const std::string& id, const std::string& tabname, bool visible = true);
LLPanel *childGetVisibleTab(const std::string& id) const;
+ LLPanel *childGetVisibleTabWithHelp();
// LLTextBox/LLTextEditor/LLLineEditor
void childSetText(const std::string& id, const LLStringExplicit& text) { childSetValue(id, LLSD(text)); }
@@ -247,10 +254,12 @@ protected:
std::string mHelpTopic; // the name of this panel's help topic to display in the Help Viewer
private:
- LLUIColor mBgColorAlpha;
- LLUIColor mBgColorOpaque;
- 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;
LLUIString mLabel;
diff --git a/indra/llui/llradiogroup.cpp b/indra/llui/llradiogroup.cpp
index f9f0307d17..86bd2f05ce 100644
--- a/indra/llui/llradiogroup.cpp
+++ b/indra/llui/llradiogroup.cpp
@@ -106,7 +106,7 @@ void LLRadioGroup::setIndexEnabled(S32 index, BOOL enabled)
child->setEnabled(enabled);
if (index == mSelectedIndex && enabled == FALSE)
{
- mSelectedIndex = -1;
+ setSelectedIndex(-1);
}
break;
}
diff --git a/indra/llui/llresmgr.cpp b/indra/llui/llresmgr.cpp
index a4e23a605b..ed870d46d5 100644
--- a/indra/llui/llresmgr.cpp
+++ b/indra/llui/llresmgr.cpp
@@ -279,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;
diff --git a/indra/llui/llrngwriter.cpp b/indra/llui/llrngwriter.cpp
index cf23e3af15..7e3d4b92d3 100644
--- a/indra/llui/llrngwriter.cpp
+++ b/indra/llui/llrngwriter.cpp
@@ -108,7 +108,8 @@ void LLRNGWriter::addDefinition(const std::string& type_name, const LLInitParam:
LLXMLNodePtr old_element_node = mElementNode;
LLXMLNodePtr old_child_node = mChildrenNode;
- addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))());
+ //FIXME: add LLDefaultParamBlockRegistry back when working on schema generation
+ //addDefinition(child_name, (*LLDefaultParamBlockRegistry::instance().getValue(type))());
mElementNode = old_element_node;
mChildrenNode = old_child_node;
diff --git a/indra/llui/llscrollbar.cpp b/indra/llui/llscrollbar.cpp
index 7db34a0608..dfd315d451 100644
--- a/indra/llui/llscrollbar.cpp
+++ b/indra/llui/llscrollbar.cpp
@@ -149,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)
@@ -166,7 +167,9 @@ void LLScrollbar::setDocPos(S32 pos, BOOL update_thumb)
{
updateThumbRect();
}
+ return true;
}
+ return false;
}
void LLScrollbar::setDocSize(S32 size)
@@ -409,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,
@@ -452,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;
@@ -566,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)
@@ -640,15 +650,3 @@ void LLScrollbar::onLineDownBtnPressed( const LLSD& data )
{
changeLine( mStepSize, TRUE );
}
-
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
- const boost::function<void (S32, LLScrollbar*)> &a,
- const boost::function<void (S32, LLScrollbar*)> &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/llscrollbar.h b/indra/llui/llscrollbar.h
index e4c5712fb7..a9f028f9ae 100644
--- a/indra/llui/llscrollbar.h
+++ b/indra/llui/llscrollbar.h
@@ -93,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,
@@ -108,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();
@@ -132,7 +133,7 @@ public:
private:
void updateThumbRect();
- void changeLine(S32 delta, BOOL update_thumb );
+ bool changeLine(S32 delta, BOOL update_thumb );
callback_t mChangeCallback;
@@ -167,11 +168,4 @@ private:
};
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<boost::function<void (S32, LLScrollbar*)> >::equals(
- const boost::function<void (S32, LLScrollbar*)> &a, const boost::function<void (S32, LLScrollbar*)> &b);
-}
-
#endif // LL_SCROLLBAR_H
diff --git a/indra/llui/llscrollcontainer.cpp b/indra/llui/llscrollcontainer.cpp
index 5597d494fe..5e17372fe9 100644
--- a/indra/llui/llscrollcontainer.cpp
+++ b/indra/llui/llscrollcontainer.cpp
@@ -235,6 +235,8 @@ BOOL LLScrollContainer::handleKeyHere(KEY key, MASK mask)
BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
{
+ if(LLUICtrl::handleScrollWheel(x,y,clicks))
+ return TRUE;
for( S32 i = 0; i < SCROLLBAR_COUNT; i++ )
{
// Note: tries vertical and then horizontal
@@ -246,9 +248,7 @@ BOOL LLScrollContainer::handleScrollWheel( S32 x, S32 y, S32 clicks )
return TRUE;
}
}
-
- // Eat scroll wheel event (to avoid scrolling nested containers?)
- return TRUE;
+ return FALSE;
}
BOOL LLScrollContainer::handleDragAndDrop(S32 x, S32 y, MASK mask,
@@ -432,7 +432,7 @@ void LLScrollContainer::draw()
LLLocalClipRect clip(LLRect(mInnerRect.mLeft,
mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0) + visible_height,
- visible_width,
+ mInnerRect.mRight - (show_v_scrollbar ? scrollbar_size: 0),
mInnerRect.mBottom + (show_h_scrollbar ? scrollbar_size : 0)
));
drawChild(mScrolledView);
diff --git a/indra/llui/llscrollingpanellist.cpp b/indra/llui/llscrollingpanellist.cpp
index 13fbe1d576..4f55c0507c 100644
--- a/indra/llui/llscrollingpanellist.cpp
+++ b/indra/llui/llscrollingpanellist.cpp
@@ -50,7 +50,7 @@ void LLScrollingPanelList::clearPanels()
reshape( 1, 1, FALSE );
}
-void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
+S32 LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
{
addChildInBack( panel );
mPanelList.push_front( panel );
@@ -79,6 +79,8 @@ void LLScrollingPanelList::addPanel( LLScrollingPanel* panel )
childp->translate( -childp->getRect().mLeft, cur_y - childp->getRect().mBottom);
cur_y -= GAP_BETWEEN_PANELS;
}
+
+ return total_height;
}
void LLScrollingPanelList::removePanel(LLScrollingPanel* panel)
diff --git a/indra/llui/llscrollingpanellist.h b/indra/llui/llscrollingpanellist.h
index 9da15822d0..3abfbcbbe7 100644
--- a/indra/llui/llscrollingpanellist.h
+++ b/indra/llui/llscrollingpanellist.h
@@ -77,7 +77,7 @@ public:
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);
diff --git a/indra/llui/llscrolllistcolumn.cpp b/indra/llui/llscrolllistcolumn.cpp
index 073e14386f..ba53f84877 100644
--- a/indra/llui/llscrolllistcolumn.cpp
+++ b/indra/llui/llscrolllistcolumn.cpp
@@ -47,6 +47,21 @@ const S32 MIN_COLUMN_WIDTH = 20;
//---------------------------------------------------------------------------
// LLScrollColumnHeader
//---------------------------------------------------------------------------
+LLScrollColumnHeader::Params::Params()
+: column("column")
+{
+ name = "column_header";
+ image_unselected.name("square_btn_32x128.tga");
+ image_selected.name("square_btn_selected_32x128.tga");
+ image_disabled.name("square_btn_32x128.tga");
+ image_disabled_selected.name("square_btn_selected_32x128.tga");
+ image_overlay.name("combobox_arrow.tga");
+ image_overlay_alignment("right");
+ font_halign = LLFontGL::LEFT;
+ tab_stop(false);
+ scale_image(true);
+}
+
LLScrollColumnHeader::LLScrollColumnHeader(const LLScrollColumnHeader::Params& p)
: LLButton(p), // use combobox params to steal images
diff --git a/indra/llui/llscrolllistcolumn.h b/indra/llui/llscrolllistcolumn.h
index 23318fd7c4..5aef6e8e94 100644
--- a/indra/llui/llscrolllistcolumn.h
+++ b/indra/llui/llscrolllistcolumn.h
@@ -50,20 +50,7 @@ public:
{
Mandatory<LLScrollListColumn*> column;
- Params()
- : column("column")
- {
- name = "column_header";
- image_unselected.name("square_btn_32x128.tga");
- image_selected.name("square_btn_selected_32x128.tga");
- image_disabled.name("square_btn_32x128.tga");
- image_disabled_selected.name("square_btn_selected_32x128.tga");
- image_overlay.name("combobox_arrow.tga");
- image_overlay_alignment("right");
- font_halign = LLFontGL::LEFT;
- tab_stop(false);
- scale_image(true);
- }
+ Params();
};
LLScrollColumnHeader(const Params&);
~LLScrollColumnHeader();
diff --git a/indra/llui/llslider.cpp b/indra/llui/llslider.cpp
index 07b6895378..f86776384a 100644
--- a/indra/llui/llslider.cpp
+++ b/indra/llui/llslider.cpp
@@ -43,6 +43,8 @@
#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()
: track_color("track_color"),
diff --git a/indra/llui/llsliderctrl.cpp b/indra/llui/llsliderctrl.cpp
index 3ecf629082..ed22c0a47f 100644
--- a/indra/llui/llsliderctrl.cpp
+++ b/indra/llui/llsliderctrl.cpp
@@ -396,4 +396,3 @@ void LLSliderCtrl::reportInvalidData()
make_ui_sound("UISndBadKeystroke");
}
-
diff --git a/indra/llui/lltabcontainer.cpp b/indra/llui/lltabcontainer.cpp
index b1067ad6f3..b67f753d39 100644
--- a/indra/llui/lltabcontainer.cpp
+++ b/indra/llui/lltabcontainer.cpp
@@ -44,6 +44,7 @@
#include "lluictrlfactory.h"
#include "llrender.h"
#include "llfloater.h"
+#include "lltrans.h"
//----------------------------------------------------------------------------
@@ -105,19 +106,26 @@ struct LLPlaceHolderPanel : public LLPanel
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_position("tab_position"),
tab_min_width("tab_min_width"),
tab_max_width("tab_max_width"),
+ tab_height("tab_height"),
+ tab_position("tab_position"),
hide_tabs("hide_tabs", false),
tab_padding_right("tab_padding_right"),
- 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")
+ first_tab("first_tab"),
+ middle_tab("middle_tab"),
+ last_tab("last_tab")
{
name(std::string("tab_container"));
mouse_opaque = false;
@@ -136,6 +144,7 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mLockedTabCount(0),
mMinTabWidth(0),
mMaxTabWidth(p.tab_max_width),
+ mTabHeight(p.tab_height),
mPrevArrowBtn(NULL),
mNextArrowBtn(NULL),
mIsVertical( p.tab_position == LEFT ),
@@ -145,12 +154,11 @@ LLTabContainer::LLTabContainer(const LLTabContainer::Params& p)
mRightTabBtnOffset(p.tab_padding_right),
mTotalTabWidth(0),
mTabPosition(p.tab_position),
- mImageTopUnselected(p.tab_top_image_unselected),
- mImageTopSelected(p.tab_top_image_selected),
- mImageBottomUnselected(p.tab_bottom_image_unselected),
- mImageBottomSelected(p.tab_bottom_image_selected),
- mImageLeftUnselected(p.tab_left_image_unselected),
- mImageLeftSelected(p.tab_left_image_selected)
+ 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);
@@ -396,12 +404,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++;
}
@@ -636,12 +638,6 @@ BOOL LLTabContainer::handleToolTip( S32 x, S32 y, MASK mask)
}
}
}
-
- for(tuple_list_t::iterator iter = mTabList.begin(); iter != mTabList.end(); ++iter)
- {
- LLTabTuple* tuple = *iter;
- tuple->mButton->setVisible( FALSE );
- }
}
return handled;
}
@@ -789,6 +785,29 @@ 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();
@@ -802,15 +821,12 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
static LLUICachedControl<S32> tabcntrv_pad ("UITabCntrvPad", 0);
static LLUICachedControl<S32> tabcntr_button_panel_overlap ("UITabCntrButtonPanelOverlap", 0);
- static LLUICachedControl<S32> tabcntr_tab_height ("UITabCntrTabHeight", 0);
static LLUICachedControl<S32> tab_padding ("UITabPadding", 0);
if (child->getParent() == this)
{
// already a child of mine
return;
}
- const LLFontGL* font =
- (mIsVertical ? LLFontGL::getFontSansSerif() : LLFontGL::getFontSansSerifSmall());
// Store the original label for possible xml export.
child->setLabel(label);
@@ -820,7 +836,7 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
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
@@ -830,14 +846,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
{
if( getTabPosition() == LLTabContainer::TOP )
{
- S32 tab_height = mIsVertical ? BTN_HEIGHT : tabcntr_tab_height;
+ 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 = (tabcntr_tab_height - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
+ tab_panel_bottom = (mTabHeight - tabcntr_button_panel_overlap); // Run to the edge, covering up the border
}
}
else
@@ -886,15 +902,15 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else if( getTabPosition() == LLTabContainer::TOP )
{
- btn_rect.setLeftTopAndSize( 0, getRect().getHeight() - getTopBorderHeight() + tab_fudge, button_width, tabcntr_tab_height );
- tab_img = mImageTopUnselected.get();
- tab_selected_img = mImageTopSelected.get();
+ 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 = mImageBottomUnselected.get();
- tab_selected_img = mImageBottomSelected.get();
+ 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;
@@ -907,11 +923,11 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
params.name(trimmed_label);
params.rect(btn_rect);
params.initial_value(trimmed_label);
- params.font(font);
+ params.font(mFont);
textbox = LLUICtrlFactory::create<LLTextBox> (params);
LLButton::Params p;
- p.name("");
+ p.name("placeholder");
btn = LLUICtrlFactory::create<LLButton>(p);
}
else
@@ -923,13 +939,14 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.rect(btn_rect);
p.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT);
p.click_callback.function(boost::bind(&LLTabContainer::onTabBtn, this, _2, child));
- p.font(font);
+ p.font(mFont);
p.label(trimmed_label);
- p.image_unselected(mImageLeftUnselected);
- p.image_selected(mImageLeftSelected);
+ p.image_unselected(mMiddleTabParams.tab_left_image_unselected);
+ p.image_selected(mMiddleTabParams.tab_left_image_selected);
p.scale_image(true);
- p.font_halign = LLFontGL::LEFT;
+ p.font_halign = mFontHalign;
p.tab_stop(false);
+ p.label_shadow(false);
if (indent)
{
p.pad_left(indent);
@@ -938,26 +955,22 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
}
else
{
- std::string tooltip = trimmed_label;
- tooltip += "\nAlt-Left arrow for previous tab";
- tooltip += "\nAlt-Right arrow for next tab";
-
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(font);
+ p.font(mFont);
p.label(trimmed_label);
p.visible(false);
- p.tool_tip(tooltip);
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
p.pad_left(4);
p.pad_right(2);
- p.font_halign = LLFontGL::LEFT;
+ p.font_halign = mFontHalign;
p.follows.flags = FOLLOWS_LEFT;
p.follows.flags = FOLLOWS_LEFT;
@@ -975,13 +988,38 @@ void LLTabContainer::addTabPanel(const TabPanelParams& panel)
p.follows.flags = p.follows.flags() | FOLLOWS_BOTTOM;
}
- btn = LLUICtrlFactory::create<LLButton>(p);
+++ btn = LLUICtrlFactory::create<LLButton>(p);
}
}
LLTabTuple* tuple = new LLTabTuple( this, child, btn, textbox );
insertTuple( tuple, insertion_point );
+ // 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())
+ {
+ update_images(tuple, mLastTabParams, getTabPosition());
+
+ if (mTabList.size() > 2)
+ {
+ update_images(mTabList[mTabList.size()-2], mMiddleTabParams, getTabPosition());
+ }
+ }
+
//Don't add button and textbox if tab buttons are invisible(EXT - 576)
if (!getTabsHidden())
{
@@ -1063,7 +1101,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 );
@@ -1443,7 +1491,6 @@ void LLTabContainer::setTabImage(LLPanel* child, std::string image_name, const L
if (!mIsVertical)
{
- const LLFontGL* fontp = LLFontGL::getFontSansSerifSmall();
// remove current width from total tab strip width
mTotalTabWidth -= tuple->mButton->getRect().getWidth();
@@ -1454,7 +1501,7 @@ 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();
diff --git a/indra/llui/lltabcontainer.h b/indra/llui/lltabcontainer.h
index 7bbecc1abc..be9c6c7d06 100644
--- a/indra/llui/lltabcontainer.h
+++ b/indra/llui/lltabcontainer.h
@@ -61,22 +61,32 @@ public:
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_max_width,
+ tab_height;
+
Optional<bool> hide_tabs;
Optional<S32> tab_padding_right;
- 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;
+ Optional<TabParams> first_tab,
+ middle_tab,
+ last_tab;
Params();
};
@@ -213,6 +223,9 @@ 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;
@@ -246,15 +259,16 @@ private:
S32 mMaxTabWidth;
S32 mTotalTabWidth;
+ S32 mTabHeight;
LLFrameTimer mDragAndDropDelayTimer;
+
+ LLFontGL::HAlign mFontHalign;
+ const LLFontGL* mFont;
- LLPointer<LLUIImage> mImageTopUnselected;
- LLPointer<LLUIImage> mImageTopSelected;
- LLPointer<LLUIImage> mImageBottomUnselected;
- LLPointer<LLUIImage> mImageBottomSelected;
- LLPointer<LLUIImage> mImageLeftUnselected;
- LLPointer<LLUIImage> mImageLeftSelected;
+ TabParams mFirstTabParams;
+ TabParams mMiddleTabParams;
+ TabParams mLastTabParams;
};
#endif // LL_TABCONTAINER_H
diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp
index e85bee7775..97ba691341 100644
--- a/indra/llui/lltextbase.cpp
+++ b/indra/llui/lltextbase.cpp
@@ -210,8 +210,6 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
scroll_params.mouse_opaque = false;
scroll_params.min_auto_scroll_rate = 200;
scroll_params.max_auto_scroll_rate = 800;
- // all text widgets only show scrollbar on demand
- scroll_params.hide_scrollbar = true;
scroll_params.border_visible = p.border_visible;
mScroller = LLUICtrlFactory::create<LLScrollContainer>(scroll_params);
addChild(mScroller);
@@ -234,7 +232,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p)
createDefaultSegment();
- updateTextRect();
+ updateRects();
}
LLTextBase::~LLTextBase()
@@ -342,11 +340,14 @@ void LLTextBase::drawSelectionBackground()
S32 segment_line_start = segmentp->getStart() + segment_offset;
S32 segment_line_end = llmin(segmentp->getEnd(), line_iter->mDocIndexEnd);
+ S32 segment_width, segment_height;
+
// if selection after beginning of segment
if(selection_left >= segment_line_start)
{
S32 num_chars = llmin(selection_left, segment_line_end) - segment_line_start;
- selection_rect.mLeft += segmentp->getWidth(segment_offset, num_chars);
+ segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
+ selection_rect.mLeft += segment_width;
}
// if selection spans end of current segment...
@@ -354,13 +355,16 @@ void LLTextBase::drawSelectionBackground()
{
// extend selection slightly beyond end of line
// to indicate selection of newline character (use "n" character to determine width)
- selection_rect.mRight += segmentp->getWidth(segment_offset, segment_line_end - segment_line_start);
+ 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;
- selection_rect.mRight += segmentp->getWidth(segment_offset, num_chars);
+ segmentp->getDimensions(segment_offset, num_chars, segment_width, segment_height);
+ selection_rect.mRight += segment_width;
break;
}
@@ -415,9 +419,6 @@ void LLTextBase::drawCursor()
return;
}
- if (!mTextRect.contains(cursor_rect))
- return;
-
// Draw the cursor
// (Flash the cursor every half second starting a fixed time after the last keystroke)
F32 elapsed = mCursorBlinkTimer.getElapsedTimeF32();
@@ -426,7 +427,9 @@ void LLTextBase::drawCursor()
if (LL_KIM_OVERWRITE == gKeyboard->getInsertMode() && !hasSelection())
{
- S32 width = llmax(CURSOR_THICKNESS, segmentp->getWidth(mCursorPos - segmentp->getStart(), 1));
+ S32 segment_width, segment_height;
+ 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
@@ -532,10 +535,6 @@ void LLTextBase::drawText()
next_start = getLineStart(cur_line + 1);
line_end = next_start;
}
- if ( text[line_end-1] == '\n' )
- {
- --line_end;
- }
LLRect text_rect(line.mRect.mLeft + mTextRect.mLeft - scrolled_view_rect.mLeft,
line.mRect.mTop - scrolled_view_rect.mBottom + mTextRect.mBottom,
@@ -934,13 +933,16 @@ BOOL LLTextBase::handleToolTip(S32 x, S32 y, MASK mask)
void LLTextBase::reshape(S32 width, S32 height, BOOL called_from_parent)
{
- LLUICtrl::reshape( width, height, 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 mTextRect
- updateTextRect();
-
- needsReflow();
+ // do this first after reshape, because other things depend on
+ // up-to-date mTextRect
+ updateRects();
+
+ needsReflow();
+ }
}
void LLTextBase::draw()
@@ -951,17 +953,27 @@ void LLTextBase::draw()
// then update scroll position, as cursor may have moved
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(getLocalRect(), mScroller != NULL);
+ LLLocalClipRect clip(doc_rect, mScroller != NULL);
LLColor4 bg_color = mReadOnly
? mReadOnlyBgColor.get()
: hasFocus()
? mFocusBgColor.get()
: mWriteableBgColor.get();
- gl_rect_2d(mDocumentView->getRect(), bg_color, TRUE);
+ gl_rect_2d(mTextRect, bg_color, TRUE);
}
// draw document view
@@ -969,7 +981,7 @@ void LLTextBase::draw()
{
// only clip if we support scrolling (mScroller != NULL)
- LLLocalClipRect clip(mTextRect, mScroller != NULL);
+ LLLocalClipRect clip(doc_rect, mScroller != NULL);
drawSelectionBackground();
drawText();
drawCursor();
@@ -1022,13 +1034,13 @@ S32 LLTextBase::getLeftOffset(S32 width)
switch (mHAlign)
{
case LLFontGL::LEFT:
- return 0;
+ return mHPad;
case LLFontGL::HCENTER:
- return (mTextRect.getWidth() - width) / 2;
+ return mHPad + (mTextRect.getWidth() - width - mHPad) / 2;
case LLFontGL::RIGHT:
return mTextRect.getWidth() - width;
default:
- return 0;
+ return mHPad;
}
}
@@ -1036,8 +1048,6 @@ S32 LLTextBase::getLeftOffset(S32 width)
static LLFastTimer::DeclareTimer FTM_TEXT_REFLOW ("Text Reflow");
void LLTextBase::reflow(S32 start_index)
{
- if (!mReflowNeeded) return;
-
LLFastTimer ft(FTM_TEXT_REFLOW);
updateSegments();
@@ -1066,7 +1076,7 @@ void LLTextBase::reflow(S32 start_index)
segment_set_t::iterator seg_iter = mSegments.begin();
S32 seg_offset = 0;
S32 line_start_index = 0;
- const S32 text_width = mTextRect.getWidth(); // optionally reserve room for margin
+ const S32 text_width = mTextRect.getWidth() - mHPad; // reserve room for margin
S32 remaining_pixels = text_width;
LLWString text(getWText());
S32 line_count = 0;
@@ -1089,59 +1099,44 @@ void LLTextBase::reflow(S32 start_index)
LLTextSegmentPtr segment = *seg_iter;
// track maximum height of any segment on this line
- line_height = llmax(line_height, segment->getMaxHeight());
S32 cur_index = segment->getStart() + seg_offset;
- // find run of text from this segment that we can display on one line
- S32 end_index = cur_index;
- while(end_index < segment->getEnd() && text[end_index] != '\n')
- {
- ++end_index;
- }
// ask segment how many character fit in remaining space
- S32 max_characters = end_index - cur_index;
S32 character_count = segment->getNumChars(getWordWrap() ? llmax(0, remaining_pixels) : S32_MAX,
seg_offset,
cur_index - line_start_index,
- max_characters);
-
+ S32_MAX);
- S32 segment_width = segment->getWidth(seg_offset, character_count);
+ 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;
- S32 text_left = getLeftOffset(text_width - remaining_pixels);
seg_offset += character_count;
S32 last_segment_char_on_line = segment->getStart() + seg_offset;
+ S32 text_left = getLeftOffset(text_width - remaining_pixels);
+ LLRect line_rect(text_left,
+ cur_top,
+ text_left + (text_width - remaining_pixels),
+ cur_top - line_height);
+
// if we didn't finish the current segment...
if (last_segment_char_on_line < segment->getEnd())
{
- // set up index for next line
- // ...skip newline, we don't want to draw
- S32 next_line_count = line_count;
- if (text[last_segment_char_on_line] == '\n')
- {
- seg_offset++;
- last_segment_char_on_line++;
- next_line_count++;
- }
-
// add line info and keep going
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
+ line_rect,
line_count));
line_start_index = segment->getStart() + seg_offset;
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
remaining_pixels = text_width;
line_height = 0;
- line_count = next_line_count;
}
// ...just consumed last segment..
else if (++segment_set_t::iterator(seg_iter) == mSegments.end())
@@ -1149,77 +1144,34 @@ void LLTextBase::reflow(S32 start_index)
mLineInfoList.push_back(line_info(
line_start_index,
last_segment_char_on_line,
- LLRect(text_left,
- cur_top,
- text_left + (text_width - remaining_pixels),
- cur_top - line_height),
+ line_rect,
line_count));
cur_top -= llround((F32)line_height * mLineSpacingMult) + mLineSpacingPixels;
break;
}
- // finished a segment and there are segments remaining on this line
+ // ...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_width;
+ }
++seg_iter;
seg_offset = 0;
}
}
- if (mLineInfoList.empty())
- {
- mContentsRect = LLRect(0, mVPad, mHPad, 0);
- }
- else
- {
-
- mContentsRect = mLineInfoList.begin()->mRect;
- for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
- line_iter != mLineInfoList.end();
- ++line_iter)
- {
- mContentsRect.unionWith(line_iter->mRect);
- }
-
- mContentsRect.mRight += mHPad;
- mContentsRect.mTop += mVPad;
- // get around rounding errors when clipping text against rectangle
- mContentsRect.stretch(1);
- }
-
- // change mDocumentView size to accomodate reflowed text
- LLRect document_rect;
- if (mScroller)
- {
- // document is size of scroller or size of text contents, whichever is larger
- document_rect.setOriginAndSize(0, 0,
- mScroller->getContentWindowRect().getWidth(),
- llmax(mScroller->getContentWindowRect().getHeight(), mContentsRect.getHeight()));
- }
- else
- {
- // document size is just extents of reflowed text, reset to origin 0,0
- document_rect.set(0,
- getLocalRect().getHeight(),
- getLocalRect().getWidth(),
- llmin(0, getLocalRect().getHeight() - mContentsRect.getHeight()));
- }
- mDocumentView->setShape(document_rect);
-
- // after making document big enough to hold all the text, move the text to fit in the document
- if (!mLineInfoList.empty())
- {
- S32 delta_pos = mDocumentView->getRect().getHeight() - mLineInfoList.begin()->mRect.mTop - mVPad;
- // 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);
- }
- mContentsRect.translate(0, delta_pos);
- }
-
// calculate visible region for diplaying text
- updateTextRect();
+ updateRects();
for (segment_set_t::iterator segment_it = mSegments.begin();
segment_it != mSegments.end();
@@ -1256,11 +1208,10 @@ void LLTextBase::reflow(S32 start_index)
//llassert_always(getLocalRectFromDocIndex(mScrollIndex).mBottom == first_char_rect.mBottom);
}
}
- }
-
- // reset desired x cursor position
- updateCursorXPos();
+ // reset desired x cursor position
+ updateCursorXPos();
+ }
}
LLRect LLTextBase::getContentsRect()
@@ -1480,6 +1431,7 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_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));
@@ -1511,9 +1463,7 @@ void LLTextBase::setText(const LLStringExplicit &utf8str)
appendText(text, false);
- //resetDirty();
onValueChange(0, getLength());
- needsReflow();
}
//virtual
@@ -1691,8 +1641,6 @@ void LLTextBase::appendAndHighlightText(const std::string &new_text, bool prepen
insertStringNoUndo(getLength(), wide_text, &segments);
}
- needsReflow();
-
// Set the cursor and scroll position
if( selection_start != selection_end )
{
@@ -1804,7 +1752,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
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 = segmentp->getWidth(line_seg_offset, segment_line_length);
+ 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
{
@@ -1812,7 +1761,8 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
S32 offset;
if (!segmentp->canEdit())
{
- S32 segment_width = segmentp->getWidth(0, segmentp->getEnd() - segmentp->getStart());
+ 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;
@@ -1835,27 +1785,26 @@ S32 LLTextBase::getDocIndexFromLocalCoord( S32 local_x, S32 local_y, BOOL round
return pos;
}
-LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
+// returns rectangle of insertion caret
+// in document coordinate frame from given index into text
+LLRect LLTextBase::getDocRectFromDocIndex(S32 pos) const
{
- LLRect local_rect;
if (mLineInfoList.empty())
{
- local_rect = mTextRect;
- local_rect.mBottom = local_rect.mTop - (S32)(mDefaultFont->getLineHeight());
- return local_rect;
+ 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());
- LLRect scrolled_view_rect = getVisibleDocumentRect();
- local_rect.mLeft = mTextRect.mLeft - scrolled_view_rect.mLeft + line_iter->mRect.mLeft;
- local_rect.mBottom = mTextRect.mBottom + (line_iter->mRect.mBottom - scrolled_view_rect.mBottom);
- local_rect.mTop = mTextRect.mBottom + (line_iter->mRect.mTop - scrolled_view_rect.mBottom);
+ 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;
@@ -1871,14 +1820,18 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
if (line_seg_iter == cursor_seg_iter)
{
// cursor advanced to right based on difference in offset of cursor to start of line
- local_rect.mLeft += segmentp->getWidth(line_seg_offset, cursor_seg_offset - line_seg_offset);
+ 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
- local_rect.mLeft += segmentp->getWidth(line_seg_offset, (segmentp->getEnd() - segmentp->getStart()) - line_seg_offset);
+ 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
@@ -1886,7 +1839,31 @@ LLRect LLTextBase::getLocalRectFromDocIndex(S32 pos) const
}
}
- local_rect.mRight = local_rect.mLeft;
+ // 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 = mTextRect;
+ 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(mTextRect.mLeft - scrolled_view_rect.mLeft,
+ mTextRect.mBottom - scrolled_view_rect.mBottom);
return local_rect;
}
@@ -2058,8 +2035,44 @@ S32 LLTextBase::getEditableIndex(S32 index, bool increasing_direction)
}
}
-void LLTextBase::updateTextRect()
+void LLTextBase::updateRects()
{
+ if (mLineInfoList.empty())
+ {
+ mContentsRect = LLRect(0, mVPad, mHPad, 0);
+ }
+ else
+ {
+ mContentsRect = mLineInfoList.begin()->mRect;
+ for (line_list_t::const_iterator line_iter = ++mLineInfoList.begin();
+ line_iter != mLineInfoList.end();
+ ++line_iter)
+ {
+ mContentsRect.unionWith(line_iter->mRect);
+ }
+
+ mContentsRect.mLeft = 0;
+ mContentsRect.mTop += mVPad;
+
+ S32 delta_pos = -mContentsRect.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);
+ }
+ mContentsRect.translate(0, delta_pos);
+ }
+
+ // update document container dimensions according to text contents
+ LLRect doc_rect = mContentsRect;
+ // use old mTextRect constraint document to width of viewable region
+ doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+
+ mDocumentView->setShape(doc_rect);
+
+ //update mTextRect *after* mDocumentView has been resized
+ // so that scrollbars are added if document needs to scroll
+ // since mTextRect does not include scrollbars
LLRect old_text_rect = mTextRect;
mTextRect = mScroller ? mScroller->getContentWindowRect() : getLocalRect();
//FIXME: replace border with image?
@@ -2067,12 +2080,14 @@ void LLTextBase::updateTextRect()
{
mTextRect.stretch(-1);
}
- mTextRect.mLeft += mHPad;
- mTextRect.mTop -= mVPad;
if (mTextRect != old_text_rect)
{
needsReflow();
}
+
+ // update document container again, using new mTextRect
+ doc_rect.mRight = doc_rect.mLeft + mTextRect.getWidth();
+ mDocumentView->setShape(doc_rect);
}
@@ -2104,9 +2119,12 @@ LLRect LLTextBase::getVisibleDocumentRect() const
}
else
{
- // entire document rect when not scrolling
+ // entire document rect is visible when not scrolling
+ // but offset according to height of widget
LLRect doc_rect = mDocumentView->getLocalRect();
- doc_rect.translate(-mDocumentView->getRect().mLeft, -mDocumentView->getRect().mBottom);
+ doc_rect.mLeft -= mDocumentView->getRect().mLeft;
+ // adjust for height of text above widget baseline
+ doc_rect.mBottom = doc_rect.getHeight() - mTextRect.getHeight();
return doc_rect;
}
}
@@ -2118,12 +2136,11 @@ LLRect LLTextBase::getVisibleDocumentRect() const
LLTextSegment::~LLTextSegment()
{}
-S32 LLTextSegment::getWidth(S32 first_char, S32 num_chars) const { return 0; }
+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; }
-S32 LLTextSegment::getMaxHeight() const { return 0; }
bool LLTextSegment::canEdit() const { return false; }
void LLTextSegment::unlinkFromDocument(LLTextBase*) {}
void LLTextSegment::linkToDocument(LLTextBase*) {}
@@ -2161,7 +2178,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLStyleSP& style, S32 start, S32
mToken(NULL),
mEditor(editor)
{
- mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = llceil(mStyle->getFont()->getLineHeight());
}
LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32 end, LLTextBase& editor, BOOL is_visible)
@@ -2171,7 +2188,7 @@ LLNormalTextSegment::LLNormalTextSegment( const LLColor4& color, S32 start, S32
{
mStyle = new LLStyle(LLStyle::Params().visible(is_visible).color(color));
- mMaxHeight = llceil(mStyle->getFont()->getLineHeight());
+ mFontHeight = llceil(mStyle->getFont()->getLineHeight());
}
F32 LLNormalTextSegment::draw(S32 start, S32 end, S32 selection_start, S32 selection_end, const LLRect& draw_rect)
@@ -2202,6 +2219,11 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
const LLWString &text = mEditor.getWText();
+ if ( text[seg_end-1] == '\n' )
+ {
+ --seg_end;
+ }
+
F32 right_x = rect.mLeft;
if (!mStyle->isVisible())
{
@@ -2269,11 +2291,6 @@ F32 LLNormalTextSegment::drawClippedSegment(S32 seg_start, S32 seg_end, S32 sele
return right_x;
}
-S32 LLNormalTextSegment::getMaxHeight() const
-{
- return mMaxHeight;
-}
-
BOOL LLNormalTextSegment::handleHover(S32 x, S32 y, MASK mask)
{
if (getStyle() && getStyle()->isLink())
@@ -2294,6 +2311,17 @@ BOOL LLNormalTextSegment::handleRightMouseDown(S32 x, S32 y, MASK mask)
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())
@@ -2336,10 +2364,13 @@ void LLNormalTextSegment::setToolTip(const std::string& tooltip)
mTooltip = tooltip;
}
-S32 LLNormalTextSegment::getWidth(S32 first_char, S32 num_chars) const
+bool LLNormalTextSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
LLWString text = mEditor.getWText();
- return mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
+
+ height = mFontHeight;
+ width = mStyle->getFont()->getWidth(text.c_str(), mStart + first_char, num_chars);
+ return num_chars >= 1 && text[mStart + num_chars - 1] == '\n';
}
S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset, S32 num_chars, bool round) const
@@ -2355,6 +2386,20 @@ S32 LLNormalTextSegment::getOffset(S32 segment_local_x_coord, S32 start_offset,
S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 line_offset, S32 max_chars) const
{
LLWString text = mEditor.getWText();
+
+ // 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));
+
S32 num_chars = mStyle->getFont()->maxDrawableChars(text.c_str() + segment_offset + mStart,
(F32)num_pixels,
max_chars,
@@ -2367,9 +2412,15 @@ S32 LLNormalTextSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
// If at the beginning of a line, and a single character won't fit, draw it anyway
num_chars = 1;
}
- if (mStart + segment_offset + num_chars == mEditor.getLength())
+
+ // 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'))
{
- // include terminating NULL
num_chars++;
}
return num_chars;
@@ -2391,9 +2442,14 @@ void LLNormalTextSegment::dump() const
// LLInlineViewSegment
//
-LLInlineViewSegment::LLInlineViewSegment(LLView* view, S32 start, S32 end)
+LLInlineViewSegment::LLInlineViewSegment(const Params& p, S32 start, S32 end)
: LLTextSegment(start, end),
- mView(view)
+ mView(p.view),
+ mForceNewLine(p.force_newline),
+ mLeftPad(p.left_pad),
+ mRightPad(p.right_pad),
+ mTopPad(p.top_pad),
+ mBottomPad(p.bottom_pad)
{
}
@@ -2402,21 +2458,31 @@ LLInlineViewSegment::~LLInlineViewSegment()
mView->die();
}
-S32 LLInlineViewSegment::getWidth(S32 first_char, S32 num_chars) const
+bool LLInlineViewSegment::getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
if (first_char == 0 && num_chars == 0)
{
- return 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
{
- return mView->getRect().getWidth();
+ 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 (line_offset != 0 && num_pixels < mView->getRect().getWidth())
+ // 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;
}
@@ -2428,19 +2494,15 @@ S32 LLInlineViewSegment::getNumChars(S32 num_pixels, S32 segment_offset, S32 lin
void LLInlineViewSegment::updateLayout(const LLTextBase& editor)
{
- LLRect start_rect = editor.getLocalRectFromDocIndex(mStart);
- LLRect doc_rect = editor.getDocumentView()->getRect();
- mView->setOrigin(doc_rect.mLeft + start_rect.mLeft, doc_rect.mBottom + start_rect.mBottom);
+ 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 (F32)(draw_rect.mLeft + mView->getRect().getWidth());
-}
-
-S32 LLInlineViewSegment::getMaxHeight() const
-{
- return mView->getRect().getHeight();
+ // 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)
diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h
index 903396c78a..8cae8fde22 100644
--- a/indra/llui/lltextbase.h
+++ b/indra/llui/lltextbase.h
@@ -154,9 +154,13 @@ public:
LLRect getContentsRect();
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; }
@@ -293,7 +297,7 @@ protected:
void endSelection();
// misc
- void updateTextRect();
+ void updateRects();
void needsReflow() { mReflowNeeded = TRUE; }
void needsScroll() { mScrollNeeded = TRUE; }
void replaceUrlLabel(const std::string &url, const std::string &label);
@@ -366,12 +370,11 @@ public:
LLTextSegment(S32 start, S32 end) : mStart(start), mEnd(end){};
virtual ~LLTextSegment();
- virtual S32 getWidth(S32 first_char, S32 num_chars) const;
+ 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 S32 getMaxHeight() const;
virtual bool canEdit() const;
virtual void unlinkFromDocument(class LLTextBase* editor);
virtual void linkToDocument(class LLTextBase* editor);
@@ -418,11 +421,10 @@ 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);
- /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const;
+ /*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*/ S32 getMaxHeight() const;
/*virtual*/ bool canEdit() const { return true; }
/*virtual*/ const LLColor4& getColor() const { return mStyle->getColor(); }
/*virtual*/ void setColor(const LLColor4 &color) { mStyle->setColor(color); }
@@ -436,6 +438,7 @@ public:
/*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);
@@ -445,7 +448,7 @@ protected:
protected:
class LLTextBase& mEditor;
LLStyleSP mStyle;
- S32 mMaxHeight;
+ S32 mFontHeight;
LLKeywordToken* mToken;
std::string mTooltip;
};
@@ -459,19 +462,33 @@ public:
class LLInlineViewSegment : public LLTextSegment
{
public:
- LLInlineViewSegment(LLView* widget, S32 start, S32 end);
+ 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*/ S32 getWidth(S32 first_char, S32 num_chars) const;
+ /*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*/ S32 getMaxHeight() const;
/*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;
};
diff --git a/indra/llui/lltextbox.cpp b/indra/llui/lltextbox.cpp
index 20bceb4675..00f1d833a3 100644
--- a/indra/llui/lltextbox.cpp
+++ b/indra/llui/lltextbox.cpp
@@ -45,6 +45,9 @@ LLTextBox::LLTextBox(const LLTextBox::Params& p)
mClickedCallback(NULL)
{}
+LLTextBox::~LLTextBox()
+{}
+
BOOL LLTextBox::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = LLTextBase::handleMouseDown(x, y, mask);
@@ -97,6 +100,18 @@ BOOL LLTextBox::handleMouseUp(S32 x, S32 y, MASK mask)
return handled;
}
+BOOL LLTextBox::handleHover(S32 x, S32 y, MASK mask)
+{
+ BOOL handled = LLTextBase::handleHover(x, y, mask);
+ if (!handled && mClickedCallback)
+ {
+ // Clickable text boxes change the cursor to a hand
+ LLUI::getWindow()->setCursor(UI_CURSOR_HAND);
+ return TRUE;
+ }
+ return handled;
+}
+
void LLTextBox::setText(const LLStringExplicit& text)
{
// does string argument insertion
@@ -105,6 +120,11 @@ void LLTextBox::setText(const LLStringExplicit& text)
LLTextBase::setText(mText.getString());
}
+void LLTextBox::setClickedCallback( boost::function<void (void*)> cb, void* userdata /*= NULL */ )
+{
+ mClickedCallback = boost::bind(cb, userdata);
+}
+
S32 LLTextBox::getTextPixelWidth()
{
return getContentsRect().getWidth();
@@ -115,6 +135,12 @@ S32 LLTextBox::getTextPixelHeight()
return getContentsRect().getHeight();
}
+
+LLSD LLTextBox::getValue() const
+{
+ return LLSD(getText());
+}
+
BOOL LLTextBox::setTextArg( const std::string& key, const LLStringExplicit& text )
{
mText.setArg(key, text);
diff --git a/indra/llui/lltextbox.h b/indra/llui/lltextbox.h
index da0bcbe972..73f8a7c299 100644
--- a/indra/llui/lltextbox.h
+++ b/indra/llui/lltextbox.h
@@ -33,8 +33,6 @@
#ifndef LL_LLTEXTBOX_H
#define LL_LLTEXTBOX_H
-#include "v4color.h"
-#include "llstring.h"
#include "lluistring.h"
#include "lltextbase.h"
@@ -54,28 +52,25 @@ protected:
friend class LLUICtrlFactory;
public:
- virtual ~LLTextBox() {}
+ virtual ~LLTextBox();
- virtual BOOL handleMouseDown(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 handleMouseUp(S32 x, S32 y, MASK mask);
+ /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
- /*virtual*/ void setText( const LLStringExplicit& text );
+ /*virtual*/ void setText( const LLStringExplicit& text );
void setRightAlign() { mHAlign = LLFontGL::RIGHT; }
void setHAlign( LLFontGL::HAlign align ) { mHAlign = align; }
- void setClickedCallback( boost::function<void (void*)> cb, void* userdata = NULL ){ mClickedCallback = boost::bind(cb, userdata); } // mouse down and up within button
-
- //const LLFontGL* getFont() const { return mDefaultFont; }
- //void setFont(const LLFontGL* font) { mDefaultFont = font; }
+ 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 LLSD getValue() const { return LLSD(getText()); }
- virtual BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
+ /*virtual*/ LLSD getValue() const;
+ /*virtual*/ BOOL setTextArg( const std::string& key, const LLStringExplicit& text );
protected:
void onUrlLabelUpdated(const std::string &url, const std::string &label);
diff --git a/indra/llui/lltexteditor.cpp b/indra/llui/lltexteditor.cpp
index 74373e7803..3ce5a0320b 100644
--- a/indra/llui/lltexteditor.cpp
+++ b/indra/llui/lltexteditor.cpp
@@ -63,6 +63,7 @@
#include "llpanel.h"
#include "llurlregistry.h"
#include "lltooltip.h"
+#include "llmenugl.h"
#include <queue>
#include "llcombobox.h"
@@ -252,7 +253,8 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
mHandleEditKeysDirectly( p.handle_edit_keys_directly ),
mMouseDownX(0),
mMouseDownY(0),
- mTabsToNextField(p.ignore_tab)
+ mTabsToNextField(p.ignore_tab),
+ mContextMenu(NULL)
{
mDefaultFont = p.font;
@@ -273,7 +275,7 @@ LLTextEditor::LLTextEditor(const LLTextEditor::Params& p) :
if (mShowLineNumbers)
{
mHPad += UI_TEXTEDITOR_LINE_NUMBER_MARGIN;
- updateTextRect();
+ updateRects();
}
}
@@ -301,6 +303,8 @@ LLTextEditor::~LLTextEditor()
// Scrollbar is deleted by LLView
std::for_each(mUndoStack.begin(), mUndoStack.end(), DeletePointer());
+
+ delete mContextMenu;
}
////////////////////////////////////////////////////////////
@@ -648,6 +652,13 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
+ // set focus first, in case click callbacks want to change it
+ // RN: do we really need to have a tab stop?
+ if (hasTabStop())
+ {
+ setFocus( TRUE );
+ }
+
// Let scrollbar have first dibs
handled = LLTextBase::handleMouseDown(x, y, mask);
@@ -690,30 +701,40 @@ BOOL LLTextEditor::handleMouseDown(S32 x, S32 y, MASK mask)
handled = TRUE;
}
- if (hasTabStop())
- {
- setFocus( TRUE );
- handled = TRUE;
- }
-
// Delay cursor flashing
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)
{
- BOOL handled = FALSE;
- handled = LLTextBase::handleMouseDown(x, y, mask);
+ if (hasTabStop())
+ {
+ setFocus(TRUE);
+ }
- if (!handled)
+ if (!LLTextBase::handleMouseDown(x, y, mask))
{
- setFocus( TRUE );
if( canPastePrimary() )
{
setCursorAtLocalPos( x, y, true );
+ // does not rely on focus being set
pastePrimary();
}
}
@@ -736,7 +757,6 @@ BOOL LLTextEditor::handleHover(S32 x, S32 y, MASK mask)
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;
@@ -990,7 +1010,7 @@ void LLTextEditor::removeChar()
// Add a single character to the text
S32 LLTextEditor::addChar(S32 pos, llwchar wc)
{
- if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) >= mMaxTextByteLength)
+ if ( (wstring_utf8_length( getWText() ) + wchar_utf8_length( wc )) > mMaxTextByteLength)
{
make_ui_sound("UISndBadKeystroke");
return 0;
@@ -1991,6 +2011,21 @@ void LLTextEditor::setEnabled(BOOL enabled)
}
}
+void LLTextEditor::showContextMenu(S32 x, S32 y)
+{
+ if (!mContextMenu)
+ {
+ mContextMenu = LLUICtrlFactory::instance().createFromFile<LLContextMenu>("menu_text_editor.xml",
+ LLMenuGL::sMenuContainer,
+ LLMenuHolderGL::child_registry_t::instance());
+ }
+
+ 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);
@@ -2276,7 +2311,7 @@ void LLTextEditor::insertText(const std::string &new_text)
setEnabled( enabled );
}
-void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline)
+void LLTextEditor::appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo)
{
// Save old state
S32 selection_start = mSelectionStart;
@@ -2290,20 +2325,9 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
setCursorPos(old_length);
- LLWString widget_wide_text;
-
- // Add carriage return if not first line
- if (getLength() != 0
- && prepend_newline)
- {
- widget_wide_text = utf8str_to_wstring(std::string("\n") + widget_text);
- }
- else
- {
- widget_wide_text = utf8str_to_wstring(widget_text);
- }
+ LLWString widget_wide_text = utf8str_to_wstring(text);
- LLTextSegmentPtr segment = new LLInlineViewSegment(widget, old_length, old_length + widget_text.size());
+ LLTextSegmentPtr segment = new LLInlineViewSegment(params, old_length, old_length + widget_wide_text.size());
insert(getLength(), widget_wide_text, FALSE, segment);
needsReflow();
@@ -2326,7 +2350,7 @@ void LLTextEditor::appendWidget(LLView* widget, const std::string &widget_text,
setCursorPos(cursor_pos);
}
- if( !allow_undo )
+ if (!allow_undo)
{
blockUndo();
}
@@ -2505,6 +2529,8 @@ void LLTextEditor::updateSegments()
void LLTextEditor::updateLinkSegments()
{
+ LLWString wtext = getWText();
+
// update any segments that contain a link
for (segment_set_t::iterator it = mSegments.begin(); it != mSegments.end(); ++it)
{
@@ -2514,13 +2540,13 @@ void LLTextEditor::updateLinkSegments()
// 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.
- LLUrlMatch match;
LLStyleSP style = static_cast<LLStyleSP>(segment->getStyle());
- std::string url_label = getText().substr(segment->getStart(), segment->getEnd()-segment->getStart());
- if (LLUrlRegistry::instance().findUrl(url_label, match))
+ LLWString url_label = wtext.substr(segment->getStart(), segment->getEnd()-segment->getStart());
+ if (LLUrlRegistry::instance().hasUrl(url_label))
{
- LLStringUtil::trim(url_label);
- style->setLinkHREF(url_label);
+ std::string new_url = wstring_to_utf8str(url_label);
+ LLStringUtil::trim(new_url);
+ style->setLinkHREF(new_url);
}
}
}
diff --git a/indra/llui/lltexteditor.h b/indra/llui/lltexteditor.h
index e232efbfb3..10fc94dedc 100644
--- a/indra/llui/lltexteditor.h
+++ b/indra/llui/lltexteditor.h
@@ -99,6 +99,7 @@ public:
// 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 handleDoubleClick(S32 x, S32 y, MASK mask );
virtual BOOL handleMiddleMouseDown(S32 x,S32 y,MASK mask);
@@ -165,7 +166,7 @@ public:
// inserts text at cursor
void insertText(const std::string &text);
- void appendWidget(LLView* widget, const std::string &widget_text, bool allow_undo, bool prepend_newline);
+ void appendWidget(const LLInlineViewSegment::Params& params, const std::string& text, bool allow_undo);
// Non-undoable
void setText(const LLStringExplicit &utf8str);
@@ -201,6 +202,7 @@ public:
void getSelectedSegments(segment_vec_t& segments) const;
protected:
+ void showContextMenu(S32 x, S32 y);
void drawPreeditMarker();
void assignEmbedded(const std::string &s);
@@ -328,6 +330,8 @@ private:
LLCoordGL mLastIMEPosition; // Last position of the IME editor
keystroke_signal_t mKeystrokeSignal;
+
+ LLContextMenu* mContextMenu;
}; // end class LLTextEditor
diff --git a/indra/llui/lltooltip.cpp b/indra/llui/lltooltip.cpp
index f30e56b907..4bc9a9c042 100644
--- a/indra/llui/lltooltip.cpp
+++ b/indra/llui/lltooltip.cpp
@@ -38,10 +38,11 @@
// 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
//
@@ -155,19 +156,23 @@ LLToolTip::Params::Params()
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")
+ image("image"),
+ time_based_media("time_based_media", false),
+ web_based_media("web_based_media", false),
+ media_playing("media_playing", false)
{
- name = "tooltip";
- font = LLFontGL::getFontSansSerif();
- bg_opaque_color = LLUIColorTable::instance().getColor( "ToolTipBgColor" );
- background_visible = true;
+ chrome = true;
}
LLToolTip::LLToolTip(const LLToolTip::Params& p)
: LLPanel(p),
mMaxWidth(p.max_width),
mHasClickCallback(p.click_callback.isProvided()),
- mPadding(p.padding)
+ mPadding(p.padding),
+ mTextBox(NULL),
+ mInfoButton(NULL),
+ mPlayMediaButton(NULL),
+ mHomePageButton(NULL)
{
LLTextBox::Params params;
params.initial_value = "tip_text";
@@ -183,27 +188,87 @@ LLToolTip::LLToolTip(const LLToolTip::Params& p)
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())
{
- LLIconCtrl::Params icon_params;
- icon_params.name = "tooltip_icon";
+ 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;
- const S32 TOOLTIP_ICON_SIZE = (imagep ? imagep->getWidth() : 16);
+ 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.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
- icon_params.image = p.image;
- icon_params.mouse_opaque = false;
- addChild(LLUICtrlFactory::create<LLIconCtrl>(icon_params));
-
+ //icon_params.follows.flags = FOLLOWS_LEFT | FOLLOWS_BOTTOM;
+ 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(""); // 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_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()));
@@ -254,6 +319,10 @@ void LLToolTip::setVisible(BOOL visible)
BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
{
+ //mInfoButton->setFlashing(true);
+ if(mInfoButton)
+ mInfoButton->setHighlight(true);
+
LLPanel::handleHover(x, y, mask);
if (mHasClickCallback)
{
@@ -262,6 +331,14 @@ BOOL LLToolTip::handleHover(S32 x, S32 y, MASK mask)
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;
@@ -319,9 +396,16 @@ void LLToolTipMgr::createToolTip(const LLToolTip::Params& params)
LLToolTip::Params tooltip_params(params);
// block mouse events if there is a click handler registered (specifically, hover)
- tooltip_params.mouse_opaque = params.click_callback.isProvided();
+ 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);
mToolTip->setValue(params.message());
gToolTipView->addChild(mToolTip);
@@ -370,7 +454,10 @@ void LLToolTipMgr::show(const std::string& msg)
void LLToolTipMgr::show(const LLToolTip::Params& params)
{
- if (!params.validateBlock())
+ // 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;
@@ -382,10 +469,12 @@ void LLToolTipMgr::show(const LLToolTip::Params& params)
// are we ready to show the tooltip?
if (!mToolTipsBlocked // we haven't hit a key, moved the mouse, etc.
- && LLUI::getMouseIdleTime() > params.delay_time) // the mouse has been still long enough
+ && LLUI::getMouseIdleTime() > params_with_defaults.delay_time) // the mouse has been still long enough
{
- bool tooltip_changed = mLastToolTipParams.message() != params.message()
- || mLastToolTipParams.pos() != params.pos();
+ 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()
@@ -393,7 +482,7 @@ void LLToolTipMgr::show(const LLToolTip::Params& params)
mNeedsToolTip = tooltip_changed || !tooltip_shown;
// store description of tooltip for later creation
- mNextToolTipParams = params;
+ mNextToolTipParams = params_with_defaults;
}
}
diff --git a/indra/llui/lltooltip.h b/indra/llui/lltooltip.h
index 63e7249a12..30d251266c 100644
--- a/indra/llui/lltooltip.h
+++ b/indra/llui/lltooltip.h
@@ -78,9 +78,13 @@ public:
visible_time_far; // time for which tooltip is visible while mouse moved away
Optional<LLRect> sticky_rect;
Optional<const LLFontGL*> font;
-
- Optional<click_callback_t> click_callback;
Optional<LLUIImage*> image;
+ 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;
Optional<S32> padding;
Optional<bool> wrap;
@@ -89,7 +93,7 @@ public:
};
/*virtual*/ void draw();
/*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask);
-
+ /*virtual*/ void onMouseLeave(S32 x, S32 y, MASK mask);
/*virtual*/ void setValue(const LLSD& value);
/*virtual*/ void setVisible(BOOL visible);
@@ -101,6 +105,10 @@ public:
private:
class LLTextBox* mTextBox;
+ class LLButton* mInfoButton;
+ class LLButton* mPlayMediaButton;
+ class LLButton* mHomePageButton;
+
LLFrameTimer mFadeTimer;
LLFrameTimer mVisibleTimer;
S32 mMaxWidth;
diff --git a/indra/llui/llui.cpp b/indra/llui/llui.cpp
index 9a90ee267e..a82e6eb372 100644
--- a/indra/llui/llui.cpp
+++ b/indra/llui/llui.cpp
@@ -1807,11 +1807,11 @@ void LLUI::glRectToScreen(const LLRect& gl, LLRect *screen)
}
//static
-LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id)
+LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id, S32 priority)
{
if (sImageProvider)
{
- return sImageProvider->getUIImageByID(image_id);
+ return sImageProvider->getUIImageByID(image_id, priority);
}
else
{
@@ -1820,10 +1820,10 @@ LLPointer<LLUIImage> LLUI::getUIImageByID(const LLUUID& image_id)
}
//static
-LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name)
+LLPointer<LLUIImage> LLUI::getUIImage(const std::string& name, S32 priority)
{
if (!name.empty() && sImageProvider)
- return sImageProvider->getUIImage(name);
+ return sImageProvider->getUIImage(name, priority);
else
return NULL;
}
@@ -1918,16 +1918,11 @@ namespace LLInitParam
declare("blue", LLColor4::blue);
}
- template<>
- class ParamCompare<const LLFontGL*>
+ bool ParamCompare<const LLFontGL*, false>::equals(const LLFontGL* a, const LLFontGL* b)
{
- public:
- static bool equals(const LLFontGL* a, const LLFontGL* b)
- {
- return !(a->getFontDesc() < b->getFontDesc())
- && !(b->getFontDesc() < a->getFontDesc());
- }
- };
+ return !(a->getFontDesc() < b->getFontDesc())
+ && !(b->getFontDesc() < a->getFontDesc());
+ }
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),
@@ -1957,7 +1952,7 @@ namespace LLInitParam
return fontp;
}
}
-
+
// default to current value
return mData.mValue;
}
diff --git a/indra/llui/llui.h b/indra/llui/llui.h
index f071e8dc47..5ec07f1941 100644
--- a/indra/llui/llui.h
+++ b/indra/llui/llui.h
@@ -195,8 +195,8 @@ public:
static void getMousePositionLocal(const LLView* viewp, S32 *x, S32 *y);
static void setScaleFactor(const LLVector2& scale_factor);
static void setLineWidth(F32 width);
- static LLPointer<LLUIImage> getUIImageByID(const LLUUID& image_id);
- static LLPointer<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);
@@ -241,8 +241,8 @@ protected:
LLImageProviderInterface() {};
virtual ~LLImageProviderInterface() {};
public:
- virtual LLPointer<LLUIImage> getUIImage(const std::string& name) = 0;
- virtual LLPointer<LLUIImage> getUIImageByID(const LLUUID& id) = 0;
+ 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;
};
@@ -404,6 +404,20 @@ namespace LLInitParam
LLUIColor getValueFromBlock() const;
};
+ // 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;
+ }
+ };
+
+
template<>
class TypedParam<const LLFontGL*>
: public BlockValue<const LLFontGL*>
@@ -437,6 +451,13 @@ namespace LLInitParam
};
template<>
+ struct ParamCompare<const LLFontGL*, false>
+ {
+ static bool equals(const LLFontGL* a, const LLFontGL* b);
+ };
+
+
+ template<>
class TypedParam<LLCoordGL>
: public BlockValue<LLCoordGL>
{
diff --git a/indra/llui/lluicolortable.cpp b/indra/llui/lluicolortable.cpp
index 087a99c2b0..851091f0ca 100644
--- a/indra/llui/lluicolortable.cpp
+++ b/indra/llui/lluicolortable.cpp
@@ -3,7 +3,30 @@
* @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$
*/
@@ -278,7 +301,7 @@ bool LLUIColorTable::loadFromFilename(const std::string& filename)
}
Params params;
- LLXUIParser::instance().readXUI(root, params);
+ LLXUIParser::instance().readXUI(root, params, filename);
if(params.validateBlock())
{
diff --git a/indra/llui/lluicolortable.h b/indra/llui/lluicolortable.h
index f102a573b8..59be0c4f9a 100644
--- a/indra/llui/lluicolortable.h
+++ b/indra/llui/lluicolortable.h
@@ -3,7 +3,30 @@
* @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$
*/
diff --git a/indra/llui/lluictrl.cpp b/indra/llui/lluictrl.cpp
index 5b72f87a78..08fc8fb784 100644
--- a/indra/llui/lluictrl.cpp
+++ b/indra/llui/lluictrl.cpp
@@ -42,6 +42,7 @@ static LLDefaultChildRegistry::Register<LLUICtrl> r("ui_ctrl");
LLUICtrl::Params::Params()
: tab_stop("tab_stop", true),
+ chrome("chrome", false),
label("label"),
initial_value("value"),
init_callback("init_callback"),
@@ -86,6 +87,7 @@ void LLUICtrl::initFromParams(const Params& p)
{
LLView::initFromParams(p);
+ setIsChrome(p.chrome);
setControlName(p.control_name);
if(p.enabled_controls.isProvided())
{
@@ -582,7 +584,6 @@ void LLUICtrl::setIsChrome(BOOL is_chrome)
// virtual
BOOL LLUICtrl::getIsChrome() const
{
-
LLView* parent_ctrl = getParent();
while(parent_ctrl)
{
@@ -795,16 +796,29 @@ bool LLUICtrl::findHelpTopic(std::string& help_topic_out)
LLUICtrl* ctrl = this;
// search back through the control's parents for a panel
- // with a help_topic string defined
+ // or tab with a help_topic string defined
while (ctrl)
{
LLPanel *panel = dynamic_cast<LLPanel *>(ctrl);
- if (panel && !panel->getHelpTopic().empty())
+
+ if (panel)
{
- help_topic_out = panel->getHelpTopic();
- return true; // success
+ // 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();
}
@@ -836,24 +850,3 @@ BOOL LLUICtrl::getTentative() const
// virtual
void LLUICtrl::setColor(const LLColor4& color)
{ }
-
-
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLUICtrl::commit_callback_t>::equals(
- const LLUICtrl::commit_callback_t &a,
- const LLUICtrl::commit_callback_t &b)
- {
- return false;
- }
-
-
- template<>
- bool ParamCompare<LLUICtrl::enable_callback_t>::equals(
- const LLUICtrl::enable_callback_t &a,
- const LLUICtrl::enable_callback_t &b)
- {
- return false;
- }
-}
diff --git a/indra/llui/lluictrl.h b/indra/llui/lluictrl.h
index 69207eb8ea..dd22851100 100644
--- a/indra/llui/lluictrl.h
+++ b/indra/llui/lluictrl.h
@@ -126,7 +126,8 @@ public:
struct Params : public LLInitParam::Block<Params, LLView::Params>
{
Optional<std::string> label;
- Optional<bool> tab_stop;
+ Optional<bool> tab_stop,
+ chrome;
Optional<LLSD> initial_value;
Optional<CommitCallbackParam> init_callback,
@@ -228,7 +229,11 @@ public:
// 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 setColor(const LLColor4& color);
BOOL focusNextItem(BOOL text_entry_only);
@@ -323,21 +328,4 @@ private:
class DefaultTabGroupFirstSorter;
};
-namespace LLInitParam
-{
- template<>
- bool ParamCompare<LLUICtrl::commit_callback_t>::equals(
- const LLUICtrl::commit_callback_t &a,
- const LLUICtrl::commit_callback_t &b);
-
- template<>
- bool ParamCompare<LLUICtrl::enable_callback_t>::equals(
- const LLUICtrl::enable_callback_t &a,
- const LLUICtrl::enable_callback_t &b);
-
- template<>
- bool ParamCompare<LLLazyValue<LLColor4> >::equals(
- const LLLazyValue<LLColor4> &a, const LLLazyValue<LLColor4> &b);
-}
-
#endif // LL_LLUICTRL_H
diff --git a/indra/llui/lluictrlfactory.cpp b/indra/llui/lluictrlfactory.cpp
index 209ee76940..c3c0daed0f 100644
--- a/indra/llui/lluictrlfactory.cpp
+++ b/indra/llui/lluictrlfactory.cpp
@@ -34,6 +34,8 @@
#include "lluictrlfactory.h"
+#include "llxmlnode.h"
+
#include <fstream>
#include <boost/tokenizer.hpp>
@@ -83,8 +85,9 @@ LLUICtrlFactory::LLUICtrlFactory()
LLUICtrlFactory::~LLUICtrlFactory()
{
- delete mDummyPanel;
- mDummyPanel = NULL;
+ // go ahead and leak mDummyPanel since this is static destructor time
+ //delete mDummyPanel;
+ //mDummyPanel = NULL;
}
void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block)
@@ -94,7 +97,7 @@ void LLUICtrlFactory::loadWidgetTemplate(const std::string& widget_tag, LLInitPa
if (LLUICtrlFactory::getLayeredXMLNode(filename, root_node))
{
- LLXUIParser::instance().readXUI(root_node, block);
+ LLXUIParser::instance().readXUI(root_node, block, filename);
}
}
@@ -410,3 +413,39 @@ void LLUICtrlFactory::popFactoryFunctions()
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);
+ LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type);
+ //FIXME: comment this in when working on schema generation
+ //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 5e6dad312c..17e32dc7a9 100644
--- a/indra/llui/lluictrlfactory.h
+++ b/indra/llui/lluictrlfactory.h
@@ -36,7 +36,7 @@
#include "llcallbackmap.h"
#include "llinitparam.h"
#include "llregistry.h"
-#include "llxmlnode.h"
+#include "v4color.h"
#include "llfasttimer.h"
#include "llxuiparser.h"
@@ -98,10 +98,11 @@ class LLDefaultWidgetRegistry
{};
// lookup function for generating empty param block by widget type
-typedef const LLInitParam::BaseBlock& (*empty_param_block_func_t)();
-class LLDefaultParamBlockRegistry
-: public LLRegistrySingleton<const std::type_info*, empty_param_block_func_t, LLDefaultParamBlockRegistry, LLCompareTypeID>
-{};
+// 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;
@@ -124,7 +125,7 @@ private:
// 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
- std::string* param_block_tag = LLWidgetNameRegistry::instance().getValue(&typeid(PARAM_BLOCK));
+ const std::string* param_block_tag = getWidgetTag(&typeid(PARAM_BLOCK));
if (param_block_tag)
{
LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype);
@@ -241,7 +242,7 @@ fail:
template<class T>
static T* getDefaultWidget(const std::string& name)
{
- dummy_widget_creator_func_t* dummy_func = LLDefaultWidgetRegistry::instance().getValue(&typeid(T));
+ dummy_widget_creator_func_t* dummy_func = getDefaultWidgetFunc(&typeid(T));
return dummy_func ? dynamic_cast<T*>((*dummy_func)(name)) : NULL;
}
@@ -254,6 +255,8 @@ fail:
return create<T>(params);
}
+ static void copyName(LLXMLNodePtr src, LLXMLNodePtr dest);
+
template<typename T>
static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node)
{
@@ -262,7 +265,7 @@ fail:
//#pragma message("Generating LLUICtrlFactory::defaultBuilder")
typename T::Params params(getDefaultParams<T>());
- LLXUIParser::instance().readXUI(node, params);
+ LLXUIParser::instance().readXUI(node, params, LLUICtrlFactory::getInstance()->getCurFileName());
if (output_node)
{
@@ -271,7 +274,7 @@ fail:
T::setupParamsForExport(output_params, parent);
// Export only the differences between this any default params
typename T::Params default_params(getDefaultParams<T>());
- output_node->setName(node->getName()->mString);
+ copyName(node, output_node);
LLXUIParser::instance().writeXUI(
output_node, output_params, &default_params);
}
@@ -320,7 +323,15 @@ fail:
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:
+ // 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);
@@ -347,23 +358,12 @@ template<typename T>
LLChildRegistry<DERIVED>::Register<T>::Register(const char* tag, LLWidgetCreatorFunc func)
: LLChildRegistry<DERIVED>::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder<T> : func)
{
- const std::type_info* widget_type_infop = &typeid(T);
- // associate parameter block type with template .xml file
- std::string* existing_tag = LLWidgetNameRegistry ::instance().getValue(&typeid(typename T::Params));
- if (existing_tag != NULL && *existing_tag != tag)
- {
- // duplicate entry for T::Params
- // try creating empty param block in derived classes that inherit T::Params
- int* crash = 0;
- *crash = 0;
- }
- LLWidgetNameRegistry ::instance().defaultRegistrar().add(&typeid(typename T::Params), tag);
- // associate widget type with factory function
- LLDefaultWidgetRegistry::instance().defaultRegistrar().add(widget_type_infop, &LLUICtrlFactory::createDefaultWidget<T>);
- LLWidgetTypeRegistry::instance().defaultRegistrar().add(tag, widget_type_infop);
- LLDefaultParamBlockRegistry::instance().defaultRegistrar().add(widget_type_infop, &getEmptyParamBlock<T>);
+ // 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(widget_type_infop, registry_t::instance());
+ LLChildRegistryRegistry::instance().defaultRegistrar().add(&typeid(T), registry_t::instance());
}
diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp
index ab0d65e731..6c1a32722f 100644
--- a/indra/llui/lluiimage.cpp
+++ b/indra/llui/lluiimage.cpp
@@ -152,8 +152,7 @@ namespace LLInitParam
}
- template<>
- bool ParamCompare<LLUIImage*>::equals(
+ bool ParamCompare<LLUIImage*, false>::equals(
LLUIImage* const &a,
LLUIImage* const &b)
{
diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h
index 4ec24e98dc..9d734bcfdf 100644
--- a/indra/llui/lluiimage.h
+++ b/indra/llui/lluiimage.h
@@ -108,8 +108,10 @@ namespace LLInitParam
// Need custom comparison function for our test app, which only loads
// LLUIImage* as NULL.
template<>
- bool ParamCompare<LLUIImage*>::equals(
- LLUIImage* const &a, LLUIImage* const &b);
+ struct ParamCompare<LLUIImage*, false>
+ {
+ static bool equals(LLUIImage* const &a, LLUIImage* const &b);
+ };
}
typedef LLPointer<LLUIImage> LLUIImagePtr;
diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp
index 20ff71378e..3a1e656364 100644
--- a/indra/llui/lluistring.cpp
+++ b/indra/llui/lluistring.cpp
@@ -35,8 +35,6 @@
#include "llsd.h"
#include "lltrans.h"
-const LLStringUtil::format_map_t LLUIString::sNullArgs;
-
LLFastTimer::DeclareTimer FTM_UI_STRING("UI String");
diff --git a/indra/llui/lluistring.h b/indra/llui/lluistring.h
index aedeca27cb..763de4d6a3 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
@@ -95,8 +95,6 @@ public:
void insert(S32 charidx, const LLWString& wchars);
void replace(S32 charidx, llwchar wc);
- static const LLStringUtil::format_map_t sNullArgs;
-
private:
void format();
diff --git a/indra/llui/llurlaction.cpp b/indra/llui/llurlaction.cpp
index f3401f91f7..679db5e39b 100644
--- a/indra/llui/llurlaction.cpp
+++ b/indra/llui/llurlaction.cpp
@@ -121,6 +121,18 @@ void LLUrlAction::teleportToLocation(std::string url)
}
}
+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));
diff --git a/indra/llui/llurlaction.h b/indra/llui/llurlaction.h
index 6b9d565b44..4830cf27ef 100644
--- a/indra/llui/llurlaction.h
+++ b/indra/llui/llurlaction.h
@@ -67,6 +67,9 @@ public:
/// 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);
diff --git a/indra/llui/llurlentry.cpp b/indra/llui/llurlentry.cpp
index c1da73fa83..dae4b512d1 100644
--- a/indra/llui/llurlentry.cpp
+++ b/indra/llui/llurlentry.cpp
@@ -145,6 +145,18 @@ void LLUrlEntryBase::callObservers(const std::string &id, const std::string &lab
}
}
+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
//
@@ -154,7 +166,6 @@ LLUrlEntryHTTP::LLUrlEntryHTTP()
boost::regex::perl|boost::regex::icase);
mMenuName = "menu_url_http.xml";
mTooltip = LLTrans::getString("TooltipHttpUrl");
- //mIcon = "gear.tga";
}
std::string LLUrlEntryHTTP::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
@@ -280,36 +291,52 @@ void LLUrlEntryAgent::onAgentNameReceived(const LLUUID& id,
std::string LLUrlEntryAgent::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
- std::string id = getIDStringFromUrl(url);
- if (gCacheName && ! id.empty())
+ if (!gCacheName)
{
- LLUUID uuid(id);
- std::string full_name;
- if (gCacheName->getFullName(uuid, full_name))
- {
- return full_name;
- }
- else
- {
- gCacheName->get(uuid, FALSE, boost::bind(&LLUrlEntryAgent::onAgentNameReceived, this, _1, _2, _3, _4));
- addObserver(id, url, cb);
- }
+ // probably at the login screen, use short string for layout
+ return LLTrans::getString("LoadingData");
}
- return LLTrans::getString("LoadingData");//unescapeUrl(url);
+ 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-]+/about",
+ 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,
@@ -323,23 +350,37 @@ void LLUrlEntryGroup::onGroupNameReceived(const LLUUID& id,
std::string LLUrlEntryGroup::getLabel(const std::string &url, const LLUrlLabelCallback &cb)
{
- std::string id = getIDStringFromUrl(url);
- if (gCacheName && ! id.empty())
+ if (!gCacheName)
{
- LLUUID uuid(id);
- std::string group_name;
- if (gCacheName->getGroupName(uuid, group_name))
- {
- return group_name;
- }
- else
- {
- gCacheName->get(uuid, TRUE, boost::bind(&LLUrlEntryGroup::onGroupNameReceived, this, _1, _2, _3, _4));
- addObserver(id, url, cb);
- }
+ // probably at login screen, give something short for layout
+ return LLTrans::getString("LoadingData");
}
- return unescapeUrl(url);
+ 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");
+ }
}
///
@@ -360,7 +401,7 @@ std::string LLUrlEntryParcel::getLabel(const std::string &url, const LLUrlLabelC
}
//
-// LLUrlEntryPlace Describes secondlife:///<location> URLs
+// LLUrlEntryPlace Describes secondlife://<location> URLs
//
LLUrlEntryPlace::LLUrlEntryPlace()
{
@@ -403,15 +444,7 @@ std::string LLUrlEntryPlace::getLabel(const std::string &url, const LLUrlLabelCa
std::string LLUrlEntryPlace::getLocation(const std::string &url) const
{
// return the part of the Url after secondlife:// part
- const std::string search_string = "://";
- size_t pos = url.find(search_string);
- if (pos == std::string::npos)
- {
- return "";
- }
-
- pos += search_string.size();
- return url.substr(pos, url.size() - pos);
+ return ::getStringAfterToken(url, "://");
}
//
@@ -438,6 +471,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
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
@@ -445,7 +479,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
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 "Teleport to " + location + " (" + x + "," + y + "," + z + ")";
+ return label + " " + location + " (" + x + "," + y + "," + z + ")";
}
else if (path_parts == 5)
{
@@ -453,20 +487,20 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
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 "Teleport to " + location + " (" + x + "," + y + ")";
+ 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 "Teleport to " + location + " (" + x + ")";
+ 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 "Teleport to " + location;
+ return label + " " + location;
}
return url;
@@ -475,15 +509,7 @@ std::string LLUrlEntryTeleport::getLabel(const std::string &url, const LLUrlLabe
std::string LLUrlEntryTeleport::getLocation(const std::string &url) const
{
// return the part of the Url after ///app/teleport
- const std::string search_string = "teleport";
- 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);
+ return ::getStringAfterToken(url, "app/teleport/");
}
///
@@ -569,3 +595,43 @@ 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
index afb2fdcde9..4507572b1e 100644
--- a/indra/llui/llurlentry.h
+++ b/indra/llui/llurlentry.h
@@ -186,7 +186,7 @@ public:
///
/// LLUrlEntryPlace Describes a Second Life location Url, e.g.,
-/// secondlife:///Ahern/50/50/50
+/// secondlife://Ahern/50/50/50
///
class LLUrlEntryPlace : public LLUrlEntryBase
{
@@ -243,4 +243,16 @@ public:
/*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/llurlregistry.cpp b/indra/llui/llurlregistry.cpp
index 8413de0837..60275b60bc 100644
--- a/indra/llui/llurlregistry.cpp
+++ b/indra/llui/llurlregistry.cpp
@@ -51,6 +51,7 @@ LLUrlRegistry::LLUrlRegistry()
registerUrl(new LLUrlEntryGroup());
registerUrl(new LLUrlEntryParcel());
registerUrl(new LLUrlEntryTeleport());
+ registerUrl(new LLUrlEntryWorldMap());
registerUrl(new LLUrlEntryObjectIM());
registerUrl(new LLUrlEntryPlace());
registerUrl(new LLUrlEntrySL());
@@ -192,3 +193,15 @@ bool LLUrlRegistry::findUrl(const LLWString &text, LLUrlMatch &match, const LLUr
}
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);
+}
diff --git a/indra/llui/llurlregistry.h b/indra/llui/llurlregistry.h
index 85e934e4b5..d7800d8cfc 100644
--- a/indra/llui/llurlregistry.h
+++ b/indra/llui/llurlregistry.h
@@ -81,6 +81,10 @@ public:
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);
+
private:
LLUrlRegistry();
friend class LLSingleton<LLUrlRegistry>;
diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp
index 1df8838738..fe7fd59de8 100644
--- a/indra/llui/llview.cpp
+++ b/indra/llui/llview.cpp
@@ -57,14 +57,13 @@
#include "lltexteditor.h"
#include "lltextbox.h"
-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;
@@ -439,6 +438,18 @@ void LLView::setEnabled(BOOL enabled)
}
//virtual
+bool LLView::isAvailable() const
+{
+ return isInEnabledChain() && isInVisibleChain();
+}
+
+//static
+bool LLView::isAvailable(const LLView* view)
+{
+ return view && view->isAvailable();
+}
+
+//virtual
BOOL LLView::setLabelArg( const std::string& key, const LLStringExplicit& text )
{
return FALSE;
@@ -656,7 +667,7 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
@@ -673,6 +684,26 @@ LLView* LLView::childrenHandleToolTip(S32 x, S32 y, MASK mask)
}
+LLView* LLView::childFromPoint(S32 x, S32 y)
+{
+ 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->getRect().mLeft;
+ S32 local_y = y - viewp->getRect().mBottom;
+ if (!viewp->pointInView(local_x, local_y)
+ || !viewp->getVisible() )
+ {
+ continue;
+ }
+ return viewp;
+
+ }
+ return 0;
+}
+
BOOL LLView::handleToolTip(S32 x, S32 y, MASK mask)
{
BOOL handled = FALSE;
@@ -896,18 +927,12 @@ LLView* LLView::childrenHandleScrollWheel(S32 x, S32 y, S32 clicks)
{
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;
@@ -934,7 +959,7 @@ LLView* LLView::childrenHandleHover(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
@@ -1024,7 +1049,7 @@ LLView* LLView::childrenHandleMouseDown(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1062,7 +1087,7 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
@@ -1101,7 +1126,7 @@ LLView* LLView::childrenHandleMiddleMouseDown(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1140,7 +1165,7 @@ LLView* LLView::childrenHandleDoubleClick(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1177,7 +1202,7 @@ LLView* LLView::childrenHandleMouseUp(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1214,7 +1239,7 @@ LLView* LLView::childrenHandleRightMouseUp(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1251,7 +1276,7 @@ LLView* LLView::childrenHandleMiddleMouseUp(S32 x, S32 y, MASK mask)
{
if (sDebugMouseHandling)
{
- sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage;
+ sMouseHandlerMessage = std::string("/") + viewp->mName + sMouseHandlerMessage;
}
handled_view = viewp;
break;
@@ -1353,7 +1378,7 @@ 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);
+ LLColor4 border_color(0.25f, 0.25f, 0.25f, 1.f);
if(preview_iter != sPreviewHighlightedElements.end())
{
if(LLView::sPreviewClickedElement && this == sPreviewClickedElement)
@@ -1388,7 +1413,9 @@ void LLView::drawDebugRect()
gGL.end();
// Draw the name if it's not a leaf node or not in editing or preview mode
- if (mChildList.size() && preview_iter == sPreviewHighlightedElements.end())
+ if (mChildList.size()
+ && preview_iter == sPreviewHighlightedElements.end()
+ && sDebugRectsShowNames)
{
//char temp[256];
S32 x, y;
diff --git a/indra/llui/llview.h b/indra/llui/llview.h
index 7ddff2bd9e..c3b442e022 100644
--- a/indra/llui/llview.h
+++ b/indra/llui/llview.h
@@ -304,6 +304,11 @@ 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 );
@@ -445,6 +450,8 @@ public:
/*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 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);
@@ -586,14 +593,20 @@ private:
default_widget_map_t& getDefaultWidgetMap() const;
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
diff --git a/indra/llui/tests/llurlentry_test.cpp b/indra/llui/tests/llurlentry_test.cpp
index 468fae2ec5..128cd134c1 100644
--- a/indra/llui/tests/llurlentry_test.cpp
+++ b/indra/llui/tests/llurlentry_test.cpp
@@ -308,6 +308,10 @@ namespace tut
"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");
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 745e53c980..c0c6e592d5 100644
--- a/indra/llvfs/lldir.cpp
+++ b/indra/llvfs/lldir.cpp
@@ -404,6 +404,12 @@ std::string LLDir::getExpandedFilename(ELLPath location, const std::string& subd
prefix = getExecutableDir();
break;
+ case LL_PATH_FONTS:
+ prefix = getAppRODataDir();
+ prefix += mDirDelimiter;
+ prefix += "fonts";
+ break;
+
default:
llassert(0);
}
@@ -419,6 +425,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())
{
@@ -569,7 +580,7 @@ void LLDir::setLindenUserDir(const std::string &first, const std::string &last)
}
else
{
- llerrs << "Invalid name for LLDir::setLindenUserDir" << llendl;
+ llerrs << "Invalid name for LLDir::setLindenUserDir(first='" << first << "', last='" << last << "')" << llendl;
}
dumpCurrentDirectories();
@@ -673,11 +684,6 @@ void LLDir::dumpCurrentDirectories()
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 6c9fea6b6a..07c814769e 100644
--- a/indra/llvfs/lldir.h
+++ b/indra/llvfs/lldir.h
@@ -60,6 +60,7 @@ typedef enum ELLPath
// LL_PATH_HTML = 16,
LL_PATH_EXECUTABLE = 16,
LL_PATH_DEFAULT_SKIN = 17,
+ LL_PATH_FONTS = 18,
LL_PATH_LAST
} ELLPath;
diff --git a/indra/llvfs/lldir_linux.cpp b/indra/llvfs/lldir_linux.cpp
index 7a531e0fbf..08c993ed2a 100644
--- a/indra/llvfs/lldir_linux.cpp
+++ b/indra/llvfs/lldir_linux.cpp
@@ -99,7 +99,19 @@ LLDir_Linux::LLDir_Linux()
#else
mAppRODataDir = tmp_str;
#endif
- mSkinBaseDir = mAppRODataDir + mDirDelimiter + "skins";
+ 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;
diff --git a/indra/llvfs/lldir_mac.cpp b/indra/llvfs/lldir_mac.cpp
index 346f7dd8ed..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))
diff --git a/indra/llvfs/lldir_win32.cpp b/indra/llvfs/lldir_win32.cpp
index 3e302764de..4c376f11a5 100644
--- a/indra/llvfs/lldir_win32.cpp
+++ b/indra/llvfs/lldir_win32.cpp
@@ -121,17 +121,22 @@ 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();
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/llpidlock.cpp b/indra/llvfs/llpidlock.cpp
index 93ac120302..315baa001d 100755
--- a/indra/llvfs/llpidlock.cpp
+++ b/indra/llvfs/llpidlock.cpp
@@ -62,7 +62,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/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/llkeyboard.cpp b/indra/llwindow/llkeyboard.cpp
index f0f618aef1..16cbf815e0 100644
--- a/indra/llwindow/llkeyboard.cpp
+++ b/indra/llwindow/llkeyboard.cpp
@@ -36,7 +36,6 @@
#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/llkeyboardwin32.cpp b/indra/llwindow/llkeyboardwin32.cpp
index ea11e0537e..35a3e7621a 100644
--- a/indra/llwindow/llkeyboardwin32.cpp
+++ b/indra/llwindow/llkeyboardwin32.cpp
@@ -65,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));
}
diff --git a/indra/llwindow/llwindowmacosx.cpp b/indra/llwindow/llwindowmacosx.cpp
index 7137c93476..96e5a1b7ca 100644
--- a/indra/llwindow/llwindowmacosx.cpp
+++ b/indra/llwindow/llwindowmacosx.cpp
@@ -1389,11 +1389,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();
@@ -1411,7 +1411,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;
diff --git a/indra/llwindow/llwindowmesaheadless.cpp b/indra/llwindow/llwindowmesaheadless.cpp
index 7ee09f4a24..48736d9207 100644
--- a/indra/llwindow/llwindowmesaheadless.cpp
+++ b/indra/llwindow/llwindowmesaheadless.cpp
@@ -45,7 +45,7 @@ U16 *gMesaBuffer = NULL;
// LLWindowMesaHeadless
//
LLWindowMesaHeadless::LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+ 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(callbacks, fullscreen, flags)
diff --git a/indra/llwindow/llwindowmesaheadless.h b/indra/llwindow/llwindowmesaheadless.h
index 22e0ec126d..46b62b914c 100644
--- a/indra/llwindow/llwindowmesaheadless.h
+++ b/indra/llwindow/llwindowmesaheadless.h
@@ -99,7 +99,7 @@ public:
/*virtual*/ void bringToFront() {};
LLWindowMesaHeadless(LLWindowCallbacks* callbacks,
- const std::string& title, const std::string& name, S32 x, S32 y, S32 width, S32 height,
+ 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 00a8d429ba..e671fc8a83 100644
--- a/indra/llwindow/llwindowsdl.cpp
+++ b/indra/llwindow/llwindowsdl.cpp
@@ -70,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
@@ -219,8 +219,7 @@ LLWindowSDL::LLWindowSDL(LLWindowCallbacks* callbacks,
#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();
@@ -419,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;
@@ -674,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;
@@ -2252,6 +2250,7 @@ BOOL LLWindowSDL::dialogColorPicker( 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);
diff --git a/indra/llxml/CMakeLists.txt b/indra/llxml/CMakeLists.txt
index 3f7714f505..fbcfade383 100644
--- a/indra/llxml/CMakeLists.txt
+++ b/indra/llxml/CMakeLists.txt
@@ -44,3 +44,25 @@ target_link_libraries( llxml
llmath
${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/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/llinitparam.cpp b/indra/llxuixml/llinitparam.cpp
index 1b867b79c9..318a0348a2 100644
--- a/indra/llxuixml/llinitparam.cpp
+++ b/indra/llxuixml/llinitparam.cpp
@@ -38,8 +38,6 @@
namespace LLInitParam
{
- BlockDescriptor BaseBlock::sBlockDescriptor;
-
//
// Param
//
@@ -127,7 +125,7 @@ namespace LLInitParam
bool BaseBlock::submitValue(const Parser::name_stack_t& name_stack, Parser& p, bool silent)
{
- if (!deserializeBlock(p, boost::make_iterator_range(name_stack.begin(), name_stack.end())))
+ if (!deserializeBlock(p, std::make_pair(name_stack.begin(), name_stack.end())))
{
if (!silent)
{
@@ -304,11 +302,11 @@ namespace LLInitParam
bool BaseBlock::deserializeBlock(Parser& p, Parser::name_stack_range_t name_stack)
{
BlockDescriptor& block_data = getBlockDescriptor();
- bool names_left = !name_stack.empty();
+ bool names_left = name_stack.first != name_stack.second;
if (names_left)
{
- const std::string& top_name = name_stack.front().first;
+ const std::string& top_name = name_stack.first->first;
ParamDescriptor::deserialize_func_t deserialize_func = NULL;
Param* paramp = NULL;
@@ -331,10 +329,11 @@ namespace LLInitParam
}
}
- Parser::name_stack_range_t new_name_stack(++name_stack.begin(), name_stack.end());
+ 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.empty() ? -1 : name_stack.front().second);
+ return deserialize_func(*paramp, p, new_name_stack, name_stack.first == name_stack.second ? -1 : name_stack.first->second);
}
}
@@ -346,7 +345,7 @@ namespace LLInitParam
Param* paramp = getParamFromHandle((*it)->mParamHandle);
ParamDescriptor::deserialize_func_t deserialize_func = (*it)->mDeserializeFunc;
- if (deserialize_func && deserialize_func(*paramp, p, name_stack, name_stack.empty() ? -1 : name_stack.front().second))
+ 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;
@@ -499,33 +498,7 @@ namespace LLInitParam
return param_changed;
}
-
- template<>
- bool ParamCompare<boost::function<void (const std::string &,void *)> >::equals(
- const boost::function<void (const std::string &,void *)> &a,
- const boost::function<void (const std::string &,void *)> &b)
- {
- return false;
- }
-
- template<>
- bool ParamCompare<boost::function<void (const LLSD &,const LLSD &)> >::equals(
- const boost::function<void (const LLSD &,const LLSD &)> &a,
- const boost::function<void (const LLSD &,const LLSD &)> &b)
- {
- return false;
- }
-
- template<>
- bool ParamCompare<boost::function<void (void)> >::equals(
- const boost::function<void (void)> &a,
- const boost::function<void (void)> &b)
- {
- return false;
- }
-
- template<>
- bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b)
+ 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
index 88bc430504..9fb464ca7b 100644
--- a/indra/llxuixml/llinitparam.h
+++ b/indra/llxuixml/llinitparam.h
@@ -39,25 +39,32 @@
#include <stddef.h>
#include <boost/function.hpp>
#include <boost/bind.hpp>
-#include <boost/range/iterator_range.hpp>
+#include <boost/type_traits/is_convertible.hpp>
#include "llregistry.h"
#include "llmemory.h"
namespace LLInitParam
{
- template <typename T>
- class ParamCompare {
- public:
- static bool equals(const T &a, const T &b);
+
+ 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;
+ }
};
- template<class T>
- bool ParamCompare<T>::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
@@ -192,7 +199,7 @@ namespace LLInitParam
};
typedef std::vector<std::pair<std::string, S32> > name_stack_t;
- typedef boost::iterator_range<name_stack_t::const_iterator> name_stack_range_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;
@@ -468,7 +475,11 @@ namespace LLInitParam
BlockDescriptor* mBlockDescriptor; // most derived block descriptor
- static BlockDescriptor sBlockDescriptor;
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
private:
const std::string& getParamName(const BlockDescriptor& block_data, const Param* paramp) const;
@@ -485,23 +496,25 @@ namespace LLInitParam
// 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 the ilk
+ // this is supposedly faster than boost::is_convertible and its ilk
template<typename T, typename Void = void>
- struct is_BaseBlock
- : boost::false_type
- {};
+ struct IsBaseBlock
+ {
+ static const bool value = false;
+ };
template<typename T>
- struct is_BaseBlock<T, typename T::baseblock_base_class_t>
- : boost::true_type
- {};
+ 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,
- typename VALUE_IS_BLOCK = typename is_BaseBlock<T>::type>
+ bool VALUE_IS_BLOCK = IsBaseBlock<T>::value>
class TypedParam
: public Param
{
@@ -535,7 +548,7 @@ namespace LLInitParam
{
self_t& typed_param = static_cast<self_t&>(param);
// no further names in stack, attempt to parse value now
- if (name_stack.empty())
+ if (name_stack.first == name_stack.second)
{
if (parser.readValue<T>(typed_param.mData.mValue))
{
@@ -661,17 +674,17 @@ namespace LLInitParam
// parameter that is a block
template <typename T, typename NAME_VALUE_LOOKUP>
- class TypedParam<T, NAME_VALUE_LOOKUP, false, boost::true_type>
+ 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, boost::true_type> self_t;
+ 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),
@@ -847,19 +860,19 @@ namespace LLInitParam
// container of non-block parameters
template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, boost::false_type>
+ class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, false>
: public Param
{
public:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, boost::false_type> self_t;
- typedef typename std::vector<VALUE_TYPE> container_t;
- typedef const container_t& value_assignment_t;
+ 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 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;
+ 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),
@@ -886,7 +899,7 @@ namespace LLInitParam
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.empty())
+ if (name_stack.first == name_stack.second)
{
// attempt to read value directly
if (parser.readValue<value_t>(value))
@@ -998,9 +1011,9 @@ namespace LLInitParam
// explicit conversion
value_assignment_t operator()() const { return get(); }
- bool hasNValidElements(S32 n) const
+ U32 numValidElements() const
{
- return mValues.size() >= n;
+ return mValues.size();
}
protected:
@@ -1029,19 +1042,19 @@ namespace LLInitParam
// container of block parameters
template <typename VALUE_TYPE, typename NAME_VALUE_LOOKUP>
- class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, boost::true_type>
+ class TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, true>
: public Param
{
public:
- typedef TypedParam<VALUE_TYPE, NAME_VALUE_LOOKUP, true, boost::true_type> self_t;
- typedef typename std::vector<VALUE_TYPE> container_t;
- typedef const container_t& value_assignment_t;
+ 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 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;
+ 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),
@@ -1238,7 +1251,7 @@ namespace LLInitParam
bool overwriteFrom(const self_t& other)
{
mCurChoice = other.mCurChoice;
- return BaseBlock::overwriteFromImpl(sBlockDescriptor, other);
+ return BaseBlock::overwriteFromImpl(blockDescriptor(), other);
}
// take all provided params that are not already provided, and apply to self
@@ -1269,7 +1282,7 @@ namespace LLInitParam
Choice()
: mCurChoice(0)
{
- BaseBlock::init(sBlockDescriptor, BaseBlock::sBlockDescriptor, sizeof(DERIVED_BLOCK));
+ BaseBlock::init(blockDescriptor(), BaseBlock::blockDescriptor(), sizeof(DERIVED_BLOCK));
}
// Alternatives are mutually exclusive wrt other Alternatives in the same block.
@@ -1281,17 +1294,17 @@ namespace LLInitParam
public:
friend class Choice<DERIVED_BLOCK>;
- typedef Alternative<T, NAME_VALUE_LOOKUP> self_t;
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
+ 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::sBlockDescriptor, name, val, NULL, 0, 1),
+ : 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::sBlockDescriptor.mCurrentBlockPtr);
- if (DERIVED_BLOCK::sBlockDescriptor.mInitializationState == BlockDescriptor::INITIALIZING
+ 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);
@@ -1337,7 +1350,11 @@ namespace LLInitParam
};
protected:
- static BlockDescriptor sBlockDescriptor;
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
private:
param_handle_t mCurChoice;
@@ -1348,15 +1365,6 @@ namespace LLInitParam
}
};
- template<typename DERIVED_BLOCK>
- BlockDescriptor
- Choice<DERIVED_BLOCK>::sBlockDescriptor;
-
- //struct CardinalityConstraint
- //{
- // virtual std::pair<S32, S32> getRange() = 0;
- //};
-
struct AnyAmount
{
static U32 minCount() { return 0; }
@@ -1404,19 +1412,19 @@ namespace LLInitParam
// take all provided params from other and apply to self
bool overwriteFrom(const self_t& other)
{
- return BaseBlock::overwriteFromImpl(sBlockDescriptor, 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(sBlockDescriptor, other);
+ return BaseBlock::fillFromImpl(blockDescriptor(), other);
}
protected:
Block()
{
//#pragma message("Parsing LLInitParam::Block")
- BaseBlock::init(sBlockDescriptor, BASE_BLOCK::sBlockDescriptor, sizeof(DERIVED_BLOCK));
+ BaseBlock::init(blockDescriptor(), BASE_BLOCK::blockDescriptor(), sizeof(DERIVED_BLOCK));
}
//
@@ -1426,11 +1434,11 @@ namespace LLInitParam
class Optional : public TypedParam<T, NAME_VALUE_LOOKUP, false>
{
public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
+ 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::sBlockDescriptor, name, val, NULL, 0, 1)
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, NULL, 0, 1)
{
//#pragma message("Parsing LLInitParam::Block::Optional")
}
@@ -1453,13 +1461,13 @@ namespace LLInitParam
class Mandatory : public TypedParam<T, NAME_VALUE_LOOKUP, false>
{
public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, false> super_t;
- typedef Mandatory<T, NAME_VALUE_LOOKUP> self_t;
- typedef typename super_t::value_assignment_t value_assignment_t;
+ 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::sBlockDescriptor, name, val, &validate, 1, 1)
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, 1, 1)
{}
Mandatory& operator=(value_assignment_t val)
@@ -1487,15 +1495,15 @@ namespace LLInitParam
class Multiple : public TypedParam<T, NAME_VALUE_LOOKUP, true>
{
public:
- typedef TypedParam<T, NAME_VALUE_LOOKUP, true> 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;
+ 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::sBlockDescriptor, name, val, &validate, RANGE::minCount(), RANGE::maxCount())
+ : super_t(DERIVED_BLOCK::blockDescriptor(), name, val, &validate, RANGE::minCount(), RANGE::maxCount())
{}
using super_t::operator();
@@ -1523,9 +1531,9 @@ namespace LLInitParam
{
public:
explicit Deprecated(const char* name)
- : Param(DERIVED_BLOCK::sBlockDescriptor.mCurrentBlockPtr)
+ : Param(DERIVED_BLOCK::blockDescriptor().mCurrentBlockPtr)
{
- BlockDescriptor& block_descriptor = DERIVED_BLOCK::sBlockDescriptor;
+ BlockDescriptor& block_descriptor = DERIVED_BLOCK::blockDescriptor();
if (block_descriptor.mInitializationState == BlockDescriptor::INITIALIZING)
{
ParamDescriptor param_descriptor(block_descriptor.mCurrentBlockPtr->getHandleFromParam(this),
@@ -1541,7 +1549,7 @@ namespace LLInitParam
static bool deserializeParam(Param& param, Parser& parser, const Parser::name_stack_range_t& name_stack, S32 generation)
{
- if (name_stack.empty())
+ if (name_stack.first == name_stack.second)
{
//std::string message = llformat("Deprecated value %s ignored", getName().c_str());
//parser.parserWarning(message);
@@ -1555,13 +1563,13 @@ namespace LLInitParam
typedef Deprecated Ignored;
protected:
- static BlockDescriptor sBlockDescriptor;
+ static BlockDescriptor& blockDescriptor()
+ {
+ static BlockDescriptor sBlockDescriptor;
+ return sBlockDescriptor;
+ }
};
- template<typename DERIVED_BLOCK, typename BASE_BLOCK>
- BlockDescriptor
- Block<DERIVED_BLOCK, BASE_BLOCK>::sBlockDescriptor;
-
template<typename T, typename DERIVED = TypedParam<T> >
class BlockValue
: public Block<TypedParam<T, TypeValues<T>, false> >,
@@ -1600,7 +1608,7 @@ namespace LLInitParam
{
self_t& typed_param = static_cast<self_t&>(param);
// type to apply parse direct value T
- if (name_stack.empty())
+ if (name_stack.first == name_stack.second)
{
if(parser.readValue<T>(typed_param.mData.mValue))
{
@@ -1795,11 +1803,11 @@ namespace LLInitParam
// assign individual parameters
if (overwrite)
{
- dst_typed_param.BaseBlock::overwriteFromImpl(block_t::sBlockDescriptor, src_param);
+ dst_typed_param.BaseBlock::overwriteFromImpl(block_t::blockDescriptor(), src_param);
}
else
{
- dst_typed_param.BaseBlock::fillFromImpl(block_t::sBlockDescriptor, src_param);
+ dst_typed_param.BaseBlock::fillFromImpl(block_t::blockDescriptor(), src_param);
}
// then copy actual value
dst_typed_param.mData.mValue = src_param.get();
@@ -1811,24 +1819,11 @@ namespace LLInitParam
}
};
- template<>
- bool ParamCompare<boost::function<void (const std::string &,void *)> >::equals(
- const boost::function<void (const std::string &,void *)> &a,
- const boost::function<void (const std::string &,void *)> &b);
-
- template<>
- bool ParamCompare<boost::function<void (const LLSD &,const LLSD &)> >::equals(
- const boost::function<void (const LLSD &,const LLSD &)> &a,
- const boost::function<void (const LLSD &,const LLSD &)> &b);
-
- template<>
- bool ParamCompare<boost::function<void (void)> >::equals(
- const boost::function<void (void)> &a,
- const boost::function<void (void)> &b);
-
-
- template<>
- bool ParamCompare<LLSD>::equals(const LLSD &a, const LLSD &b);
+ template<>
+ struct ParamCompare<LLSD, false>
+ {
+ static bool equals(const LLSD &a, const LLSD &b);
+ };
}
#endif // LL_LLPARAM_H
diff --git a/indra/llxuixml/lltrans.cpp b/indra/llxuixml/lltrans.cpp
index e974dbd0ba..4c800a502d 100644
--- a/indra/llxuixml/lltrans.cpp
+++ b/indra/llxuixml/lltrans.cpp
@@ -72,7 +72,7 @@ bool LLTrans::parseStrings(LLXMLNodePtr &root, const std::set<std::string>& defa
}
StringTable string_table;
- LLXUIParser::instance().readXUI(root, string_table);
+ LLXUIParser::instance().readXUI(root, string_table, xml_filename);
if (!string_table.validateBlock())
{
@@ -115,7 +115,7 @@ bool LLTrans::parseLanguageStrings(LLXMLNodePtr &root)
}
StringTable string_table;
- LLXUIParser::instance().readXUI(root, string_table);
+ LLXUIParser::instance().readXUI(root, string_table, xml_filename);
if (!string_table.validateBlock())
{
diff --git a/indra/llxuixml/lltrans.h b/indra/llxuixml/lltrans.h
index 79df5802e5..856b9e04fc 100644
--- a/indra/llxuixml/lltrans.h
+++ b/indra/llxuixml/lltrans.h
@@ -103,6 +103,11 @@ public:
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()
diff --git a/indra/llxuixml/lluicolor.cpp b/indra/llxuixml/lluicolor.cpp
index ef0fa5d634..424d878a6b 100644
--- a/indra/llxuixml/lluicolor.cpp
+++ b/indra/llxuixml/lluicolor.cpp
@@ -7,6 +7,8 @@
* $/LicenseInfo$
*/
+#include "linden_common.h"
+
#include "lluicolor.h"
LLUIColor::LLUIColor()
@@ -58,14 +60,9 @@ bool LLUIColor::isReference() const
namespace LLInitParam
{
// used to detect equivalence with default values on export
- template<>
- class ParamCompare<LLUIColor>
+ bool ParamCompare<LLUIColor, false>::equals(const LLUIColor &a, const LLUIColor &b)
{
- public:
- static bool 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);
- }
- };
+ // 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
index 365f61003b..bb0f786326 100644
--- a/indra/llxuixml/lluicolor.h
+++ b/indra/llxuixml/lluicolor.h
@@ -14,8 +14,8 @@
namespace LLInitParam
{
- template<typename T>
- class ParamCompare;
+ template<typename T, bool>
+ struct ParamCompare;
}
class LLUIColor
@@ -36,10 +36,19 @@ public:
bool isReference() const;
private:
- friend class LLInitParam::ParamCompare<LLUIColor>;
+ 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
index e28e52fd16..17399865e5 100644
--- a/indra/llxuixml/llxuiparser.cpp
+++ b/indra/llxuixml/llxuiparser.cpp
@@ -34,6 +34,7 @@
#include "llxuiparser.h"
+#include "llxmlnode.h"
#include <fstream>
#include <boost/tokenizer.hpp>
@@ -401,10 +402,11 @@ LLXUIParser::LLXUIParser()
static LLFastTimer::DeclareTimer FTM_PARSE_XUI("XUI Parsing");
-void LLXUIParser::readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent)
+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);
@@ -946,9 +948,9 @@ bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack)
void LLXUIParser::parserWarning(const std::string& message)
{
-#if 0 //#ifdef LL_WINDOWS
+#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", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+ 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
@@ -958,8 +960,8 @@ void LLXUIParser::parserWarning(const std::string& message)
void LLXUIParser::parserError(const std::string& message)
{
-#if 0 //#ifdef LL_WINDOWS
- llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str());
+#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
diff --git a/indra/llxuixml/llxuiparser.h b/indra/llxuixml/llxuiparser.h
index 6f000f2422..884f4f7578 100644
--- a/indra/llxuixml/llxuiparser.h
+++ b/indra/llxuixml/llxuiparser.h
@@ -34,9 +34,9 @@
#define LLXUIPARSER_H
#include "llinitparam.h"
-#include "llxmlnode.h"
#include "llfasttimer.h"
#include "llregistry.h"
+#include "llpointer.h"
#include <boost/function.hpp>
#include <iosfwd>
@@ -48,6 +48,8 @@
class LLView;
+typedef LLPointer<class LLXMLNode> LLXMLNodePtr;
+
// lookup widget type by name
class LLWidgetTypeRegistry
@@ -114,7 +116,7 @@ public:
/*virtual*/ void parserWarning(const std::string& message);
/*virtual*/ void parserError(const std::string& message);
- void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent=false);
+ 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:
@@ -168,6 +170,7 @@ private:
S32 mLastWriteGeneration;
LLXMLNodePtr mLastWrittenChild;
S32 mCurReadDepth;
+ std::string mCurFileName;
};
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/lscript_tree.cpp b/indra/lscript/lscript_compile/lscript_tree.cpp
index 98146d6f2b..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:
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 245fc320d1..96855abea0 100644
--- a/indra/lscript/lscript_execute.h
+++ b/indra/lscript/lscript_execute.h
@@ -371,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 2fd81210c0..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 >= (U8)gScriptLibrary.mFunctions.size())
+ 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,23 +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("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
+ // Actually execute the function call
+ function.mExecFunc(returnvalue, arguments, id);
- {
- 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);
}
@@ -4304,71 +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 >= (U16)gScriptLibrary.mFunctions.size())
+ 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("See LSLTipText_%s in strings.xml for usage\n", gScriptLibrary.mFunctions[arg].mName);
- }
-
- {
- 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/mac_crash_logger/CMakeLists.txt b/indra/mac_crash_logger/CMakeLists.txt
index daf3e10857..1d6494fecf 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,7 @@ 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
+ "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR};${ARCH_PREBUILT_DIRS}"
+ "../Resources")
diff --git a/indra/mac_updater/CMakeLists.txt b/indra/mac_updater/CMakeLists.txt
index 0eac76fa69..d7bd6f993c 100644
--- a/indra/mac_updater/CMakeLists.txt
+++ b/indra/mac_updater/CMakeLists.txt
@@ -77,3 +77,7 @@ add_custom_command(
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/mac-updater.app/Contents/Resources/AutoUpdater.nib
)
+ll_deploy_sharedlibs_command(
+ mac-updater
+ "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR};${ARCH_PREBUILT_DIRS}"
+ "../Resources")
diff --git a/indra/media_plugins/CMakeLists.txt b/indra/media_plugins/CMakeLists.txt
index d35afd8cbd..cc03d9cb72 100644
--- a/indra/media_plugins/CMakeLists.txt
+++ b/indra/media_plugins/CMakeLists.txt
@@ -9,3 +9,5 @@ add_subdirectory(gstreamer010)
if (WINDOWS OR DARWIN)
add_subdirectory(quicktime)
endif (WINDOWS OR DARWIN)
+
+add_subdirectory(example)
diff --git a/indra/media_plugins/base/media_plugin_base.cpp b/indra/media_plugins/base/media_plugin_base.cpp
index 0b7092fad6..6acac07423 100644
--- a/indra/media_plugins/base/media_plugin_base.cpp
+++ b/indra/media_plugins/base/media_plugin_base.cpp
@@ -64,6 +64,7 @@ std::string MediaPluginBase::statusString()
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;
diff --git a/indra/media_plugins/base/media_plugin_base.h b/indra/media_plugins/base/media_plugin_base.h
index 8f600cb8d6..f1e96335f9 100644
--- a/indra/media_plugins/base/media_plugin_base.h
+++ b/indra/media_plugins/base/media_plugin_base.h
@@ -56,6 +56,7 @@ protected:
STATUS_ERROR,
STATUS_PLAYING,
STATUS_PAUSED,
+ STATUS_DONE
} EStatus;
class SharedSegmentInfo
diff --git a/indra/media_plugins/example/CMakeLists.txt b/indra/media_plugins/example/CMakeLists.txt
new file mode 100644
index 0000000000..4d82f2747c
--- /dev/null
+++ b/indra/media_plugins/example/CMakeLists.txt
@@ -0,0 +1,74 @@
+# -*- 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
+
+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..99e0199a29
--- /dev/null
+++ b/indra/media_plugins/example/media_plugin_example.cpp
@@ -0,0 +1,488 @@
+/**
+ * @file media_plugin_example.cpp
+ * @brief Example plugin for LLMedia API 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 "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
index 5c0ce3ee17..a9f7938b41 100644
--- a/indra/media_plugins/gstreamer010/CMakeLists.txt
+++ b/indra/media_plugins/gstreamer010/CMakeLists.txt
@@ -42,12 +42,12 @@ set(media_plugin_gstreamer010_HEADER_FILES
llmediaimplgstreamertriviallogging.h
)
-if (${CXX_VERSION} MATCHES "4.[23]")
+if (${CXX_VERSION} 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-error=write-strings)
-endif (${CXX_VERSION} MATCHES "4.[23]")
+ COMPILE_FLAGS -Wno-write-strings)
+endif (${CXX_VERSION} MATCHES "4[23].")
add_library(media_plugin_gstreamer010
SHARED
diff --git a/indra/media_plugins/quicktime/CMakeLists.txt b/indra/media_plugins/quicktime/CMakeLists.txt
index db11c9ae21..f0b8f0d167 100644
--- a/indra/media_plugins/quicktime/CMakeLists.txt
+++ b/indra/media_plugins/quicktime/CMakeLists.txt
@@ -56,6 +56,14 @@ add_dependencies(media_plugin_quicktime
${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)
diff --git a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
index fbda65120d..de927de1cd 100644
--- a/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
+++ b/indra/media_plugins/quicktime/media_plugin_quicktime.cpp
@@ -1,4 +1,4 @@
-/**
+/**
* @file media_plugin_quicktime.cpp
* @brief QuickTime plugin for LLMedia API plugin system
*
@@ -48,6 +48,7 @@
#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
@@ -71,11 +72,14 @@ private:
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,
@@ -97,14 +101,14 @@ private:
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);
}
@@ -112,16 +116,16 @@ private:
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;
@@ -140,25 +144,27 @@ private:
{
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);
@@ -174,6 +180,11 @@ private:
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 );
@@ -192,12 +203,15 @@ private:
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 );
@@ -226,7 +240,7 @@ private:
DisposeGWorld( mGWorldHandle );
mGWorldHandle = NULL;
};
-
+
setStatus(STATUS_NONE);
return true;
@@ -236,7 +250,7 @@ private:
{
unload();
load( url );
-
+
return true;
};
@@ -244,7 +258,7 @@ private:
{
if ( ! mMovieHandle )
return false;
-
+
// Check to see whether the movie's natural size has updated
{
int width, height;
@@ -262,14 +276,14 @@ private:
//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)
@@ -301,7 +315,7 @@ private:
{
DisposeGWorld( old_gworld_handle );
}
-
+
// Set up the movie display matrix
{
// scale movie to fit rect and invert vertically to match opengl image format
@@ -314,7 +328,7 @@ private:
ScaleMatrix( &transform, X2Fix( scaleX ), X2Fix( scaleY ), X2Fix( centerX ), X2Fix( centerY ) );
SetMovieMatrix( mMovieHandle, &transform );
}
-
+
// update movie controller
if ( mMovieController )
{
@@ -332,7 +346,6 @@ private:
return true;
}
-
static Boolean mcActionFilterCallBack( MovieController mc, short action, void *params, long ref )
{
Boolean result = false;
@@ -342,9 +355,9 @@ private:
switch( action )
{
// handle window resizing
- case mcActionControllerSizeChanged:
+ case mcActionControllerSizeChanged:
// Ensure that the movie draws correctly at the new size
- self->sizeChanged();
+ self->sizeChanged();
break;
// Block any movie controller actions that open URLs.
@@ -373,6 +386,7 @@ private:
// self->updateQuickTime();
// TODO ^^^
+
if ( self->mWidth > 0 && self->mHeight > 0 )
self->setDirty( 0, 0, self->mWidth, self->mHeight );
@@ -381,11 +395,18 @@ private:
static void moviePrePrerollCompleteCallback( Movie movie, OSErr preroll_err, void *ref )
{
- //MediaPluginQuickTime* self = ( MediaPluginQuickTime* )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);
};
@@ -399,7 +420,7 @@ private:
{
if ( mCommand == COMMAND_PLAY )
{
- if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING )
+ if ( mStatus == STATUS_LOADED || mStatus == STATUS_PAUSED || mStatus == STATUS_PLAYING || mStatus == STATUS_DONE )
{
long state = GetMovieLoadState( mMovieHandle );
@@ -414,7 +435,7 @@ private:
MCDoAction( mMovieController, mcActionPlay, (void*)rate );
rewind();
};
-
+
MCDoAction( mMovieController, mcActionPrerollAndPlay, (void*)getPlayRate() );
MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
setStatus(STATUS_PLAYING);
@@ -425,7 +446,7 @@ private:
else
if ( mCommand == COMMAND_STOP )
{
- if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED )
+ if ( mStatus == STATUS_PLAYING || mStatus == STATUS_PAUSED || mStatus == STATUS_DONE )
{
if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
{
@@ -442,7 +463,7 @@ private:
if ( mCommand == COMMAND_PAUSE )
{
if ( mStatus == STATUS_PLAYING )
- {
+ {
if ( GetMovieLoadState( mMovieHandle ) >= kMovieLoadStatePlaythroughOK )
{
Fixed rate = X2Fix( 0.0 );
@@ -475,7 +496,7 @@ private:
void getMovieNaturalSize(int *movie_width, int *movie_height)
{
Rect rect;
-
+
GetMovieNaturalBoundsRect( mMovieHandle, &rect );
int width = ( rect.right - rect.left );
@@ -498,7 +519,7 @@ private:
*movie_width = width;
*movie_height = height;
}
-
+
void updateQuickTime(int milliseconds)
{
if ( ! mMovieHandle )
@@ -524,11 +545,14 @@ private:
// update state machine
processState();
- // special code for looping - need to rewind at the end of the movie
- if ( mIsLooping )
+ // 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 ) )
{
- // 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();
@@ -541,8 +565,16 @@ private:
// set the volume
MCDoAction( mMovieController, mcActionSetVolume, (void*)mCurVolume );
};
- };
- };
+ }
+ else
+ {
+ if(mStatus == STATUS_PLAYING)
+ {
+ setStatus(STATUS_DONE);
+ }
+ }
+ }
+
};
int getDataWidth() const
@@ -585,6 +617,19 @@ private:
};
};
+ 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 );
@@ -642,6 +687,71 @@ private:
{
};
+ ////////////////////////////////////////////////////////////////////////////////
+ // 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 )
+ return false;
+
+ // allocate some space and grab it
+ UInt8* item_data = new UInt8( size );
+ memset( item_data, 0, size * sizeof( UInt8* ) );
+ result = QTMetaDataGetItemValue( media_data_ref, item, item_data, size, NULL );
+ if ( noErr != result )
+ return false;
+
+ // save it
+ mMovieTitle = std::string( (char* )item_data );
+
+ // 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(
@@ -663,6 +773,8 @@ MediaPluginQuickTime::MediaPluginQuickTime(
mCurVolume = 0x99;
mMediaSizeChanging = false;
mIsLooping = false;
+ mMovieTitle = std::string();
+ mReceivedTitle = false;
mCommand = COMMAND_NONE;
mPlayRate = 0.0f;
mStatus = STATUS_NONE;
@@ -699,22 +811,29 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
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_BROWSER] = LLPLUGIN_MESSAGE_CLASS_MEDIA_BROWSER_VERSION;
versions[LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME] = LLPLUGIN_MESSAGE_CLASS_MEDIA_TIME_VERSION;
message.setValueLLSD("versions", versions);
#ifdef LL_WINDOWS
- if ( InitializeQTML( 0L ) != noErr )
+
+ // 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.
- //return false;
}
else
{
-// std::cerr << "QuickTime initialized" << std::endl;
+ //std::cerr << "QuickTime initialized" << std::endl;
};
#endif
+ // required for both Windows and Mac
EnterMovies();
std::string plugin_version = "QuickTime media plugin, QuickTime version ";
@@ -731,7 +850,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
message.setMessage(LLPLUGIN_MESSAGE_CLASS_MEDIA, "texture_params");
#if defined(LL_WINDOWS)
// Values for Windows
- mDepth = 3;
+ mDepth = 3;
message.setValueU32("format", GL_RGB);
message.setValueU32("type", GL_UNSIGNED_BYTE);
@@ -740,7 +859,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
message.setValueU32("padding", 32 * 3);
#else
// Values for Mac
- mDepth = 4;
+ mDepth = 4;
message.setValueU32("format", GL_BGRA_EXT);
#ifdef __BIG_ENDIAN__
message.setValueU32("type", GL_UNSIGNED_INT_8_8_8_8_REV );
@@ -761,7 +880,7 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
{
// no response is necessary here.
F64 time = message_in.getValueReal("time");
-
+
// Convert time to milliseconds for update()
update((int)(time * 1000.0f));
}
@@ -775,8 +894,6 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
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
@@ -799,9 +916,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
// 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();
+ sizeChanged();
}
mSharedSegments.erase(iter);
}
@@ -858,9 +975,9 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
mTextureHeight = texture_height;
mMediaSizeChanging = false;
-
+
sizeChanged();
-
+
update();
};
};
@@ -869,14 +986,14 @@ void MediaPluginQuickTime::receiveMessage(const char *message_string)
{
std::string uri = message_in.getValue("uri");
load( uri );
- sendStatus();
+ 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);
@@ -969,7 +1086,7 @@ MediaPluginQuickTime::~MediaPluginQuickTime()
void MediaPluginQuickTime::receiveMessage(const char *message_string)
{
- // no-op
+ // no-op
}
// We're building without quicktime enabled. Just refuse to initialize.
diff --git a/indra/media_plugins/webkit/CMakeLists.txt b/indra/media_plugins/webkit/CMakeLists.txt
index d96477279d..5bccd589d8 100644
--- a/indra/media_plugins/webkit/CMakeLists.txt
+++ b/indra/media_plugins/webkit/CMakeLists.txt
@@ -52,6 +52,14 @@ add_dependencies(media_plugin_webkit
${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(
diff --git a/indra/media_plugins/webkit/media_plugin_webkit.cpp b/indra/media_plugins/webkit/media_plugin_webkit.cpp
index eb2457744a..3ce8ff3deb 100644
--- a/indra/media_plugins/webkit/media_plugin_webkit.cpp
+++ b/indra/media_plugins/webkit/media_plugin_webkit.cpp
@@ -48,6 +48,18 @@
#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 :
@@ -69,6 +81,9 @@ private:
bool mCanCut;
bool mCanCopy;
bool mCanPaste;
+ int mLastMouseX;
+ int mLastMouseY;
+ bool mFirstFocus;
////////////////////////////////////////////////////////////////////////////////
//
@@ -126,7 +141,31 @@ private:
return false;
}
std::string application_dir = std::string( cwd );
+
+#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
std::string profileDir = application_dir + "/" + "browser_profile"; // cross platform?
// window handle - needed on Windows and must be app window.
@@ -147,7 +186,7 @@ private:
#if LL_WINDOWS
// Enable plugins
- LLQtWebKit::getInstance()->enablePlugins(false);
+ LLQtWebKit::getInstance()->enablePlugins(true);
#elif LL_DARWIN
// Disable plugins
LLQtWebKit::getInstance()->enablePlugins(false);
@@ -168,14 +207,13 @@ private:
// don't flip bitmap
LLQtWebKit::getInstance()->flipWindow( mBrowserWindowId, true );
- // Set the background color to black
- LLQtWebKit::getInstance()->
// set background color to be black - mostly for initial login page
LLQtWebKit::getInstance()->setBackgroundColor( mBrowserWindowId, 0x00, 0x00, 0x00 );
- // go to the "home page"
// Don't do this here -- it causes the dreaded "white flash" when loading a browser instance.
-// LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
+ // 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.
+ LLQtWebKit::getInstance()->navigateTo( mBrowserWindowId, "about:blank" );
// set flag so we don't do this again
mBrowserInitialized = true;
@@ -272,7 +310,16 @@ private:
message.setValue("status", event.getStringValue());
sendMessage(message);
}
-
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // virtual
+ void onTitleChange(const EventType& event)
+ {
+ LLPluginMessage message(LLPLUGIN_MESSAGE_CLASS_MEDIA, "name_text");
+ message.setValue("name", event.getStringValue());
+ sendMessage(message);
+ }
+
////////////////////////////////////////////////////////////////////////////////
// virtual
void onLocationChange(const EventType& event)
@@ -300,33 +347,30 @@ private:
message.setValue("uri", event.getStringValue());
sendMessage(message);
}
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseDown( int x, int y )
- {
- LLQtWebKit::getInstance()->mouseDown( mBrowserWindowId, x, y );
- };
-
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseUp( int x, int y )
+
+ LLQtWebKit::EKeyboardModifier decodeModifiers(std::string &modifiers)
{
- LLQtWebKit::getInstance()->mouseUp( mBrowserWindowId, x, y );
- LLQtWebKit::getInstance()->focusBrowser( mBrowserWindowId, true );
- checkEditState();
- };
+ int result = 0;
+
+ if(modifiers.find("shift") != std::string::npos)
+ result |= LLQtWebKit::KM_MODIFIER_SHIFT;
- ////////////////////////////////////////////////////////////////////////////////
- //
- void mouseMove( int x, int y )
- {
- LLQtWebKit::getInstance()->mouseMove( mBrowserWindowId, x, y );
- };
+ 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 keyPress( int key )
+ void keyEvent(LLQtWebKit::EKeyEvent key_event, int key, LLQtWebKit::EKeyboardModifier modifiers)
{
int llqt_key;
@@ -380,7 +424,7 @@ private:
if(llqt_key != 0)
{
- LLQtWebKit::getInstance()->keyPress( mBrowserWindowId, llqt_key );
+ LLQtWebKit::getInstance()->keyEvent( mBrowserWindowId, key_event, llqt_key, modifiers);
}
checkEditState();
@@ -388,7 +432,7 @@ private:
////////////////////////////////////////////////////////////////////////////////
//
- void unicodeInput( const std::string &utf8str )
+ void unicodeInput( const std::string &utf8str, LLQtWebKit::EKeyboardModifier modifiers)
{
LLWString wstr = utf8str_to_wstring(utf8str);
@@ -397,7 +441,7 @@ private:
{
// std::cerr << "unicode input, code = 0x" << std::hex << (unsigned long)(wstr[i]) << std::dec << std::endl;
- LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i]);
+ LLQtWebKit::getInstance()->unicodeInput(mBrowserWindowId, wstr[i], modifiers);
}
checkEditState();
@@ -449,6 +493,9 @@ MediaPluginWebKit::MediaPluginWebKit(LLPluginInstance::sendMessageFunction host_
mCanCut = false;
mCanCopy = false;
mCanPaste = false;
+ mLastMouseX = 0;
+ mLastMouseY = 0;
+ mFirstFocus = true;
}
MediaPluginWebKit::~MediaPluginWebKit()
@@ -633,66 +680,84 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
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");
- // std::string modifiers = message.getValue("modifiers");
-
+ 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")
{
- mouseDown(x, y);
- //std::cout << "Mouse down at " << x << " x " << y << std::endl;
+ mouse_event = LLQtWebKit::ME_MOUSE_DOWN;
}
else if(event == "up")
{
- mouseUp(x, y);
- //std::cout << "Mouse up at " << x << " x " << y << std::endl;
+ mouse_event = LLQtWebKit::ME_MOUSE_UP;
}
- else if(event == "move")
+ else if(event == "double_click")
{
- mouseMove(x, y);
- //std::cout << ">>>>>>>>>>>>>>>>>>>> Mouse move at " << x << " x " << y << std::endl;
+ 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 x = message_in.getValueS32("x");
S32 y = message_in.getValueS32("y");
- // std::string modifiers = message.getValue("modifiers");
+ 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.
- // We currently ignore horizontal scrolling.
- // The scroll values are roughly 1 per wheel click, so we need to magnify them by some factor.
- // Arbitrarily, I choose 16.
- y *= 16;
- LLQtWebKit::getInstance()->scrollByLines(mBrowserWindowId, y);
+ 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");
-
- // act on "key down" or "key repeat"
- if ( (event == "down") || (event == "repeat") )
+ 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")
{
- S32 key = message_in.getValueS32("key");
- keyPress( key );
- };
+ 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);
+ 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
{
@@ -705,6 +770,15 @@ void MediaPluginWebKit::receiveMessage(const char *message_string)
{
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")
{
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index b9e5664ff7..cba9b09dc0 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -36,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}
@@ -61,23 +59,27 @@ include_directories(
${LLXUIXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
+ ${LLLOGIN_INCLUDE_DIRS}
)
set(viewer_SOURCE_FILES
- llaccordionctrltab.cpp
llaccordionctrl.cpp
+ llaccordionctrltab.cpp
llagent.cpp
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
llavataractions.cpp
llavatariconctrl.cpp
@@ -93,6 +95,7 @@ set(viewer_SOURCE_FILES
llcaphttpsender.cpp
llchannelmanager.cpp
llchatbar.cpp
+ llchathistory.cpp
llchatitemscontainerctrl.cpp
llchatmsgbox.cpp
llchiclet.cpp
@@ -111,11 +114,12 @@ set(viewer_SOURCE_FILES
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
@@ -147,8 +151,8 @@ set(viewer_SOURCE_FILES
llfloaterbuildoptions.cpp
llfloaterbulkpermission.cpp
llfloaterbump.cpp
- llfloaterbuycontents.cpp
llfloaterbuy.cpp
+ llfloaterbuycontents.cpp
llfloaterbuycurrency.cpp
llfloaterbuyland.cpp
llfloatercall.cpp
@@ -158,10 +162,9 @@ set(viewer_SOURCE_FILES
llfloatercolorpicker.cpp
llfloatercustomize.cpp
llfloaterdaycycle.cpp
- llfloaterdirectory.cpp
llfloaterenvsettings.cpp
- llfloaterfriends.cpp
llfloaterfonttest.cpp
+ llfloaterfriends.cpp
llfloatergesture.cpp
llfloatergodtools.cpp
llfloatergroupinvite.cpp
@@ -169,8 +172,6 @@ set(viewer_SOURCE_FILES
llfloaterhandler.cpp
llfloaterhardwaresettings.cpp
llfloaterhelpbrowser.cpp
- llfloatermediabrowser.cpp
- llfloatermediasettings.cpp
llfloaterhud.cpp
llfloaterimagepreview.cpp
llfloaterinspect.cpp
@@ -180,8 +181,11 @@ set(viewer_SOURCE_FILES
llfloaterland.cpp
llfloaterlandholdings.cpp
llfloatermap.cpp
+ llfloatermediabrowser.cpp
+ llfloatermediasettings.cpp
llfloatermemleak.cpp
llfloaternamedesc.cpp
+ llfloaternearbymedia.cpp
llfloaternotificationsconsole.cpp
llfloateropenobject.cpp
llfloaterparcel.cpp
@@ -194,6 +198,7 @@ set(viewer_SOURCE_FILES
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
+ llfloatersearch.cpp
llfloatersellland.cpp
llfloatersettingsdebug.cpp
llfloatersnapshot.cpp
@@ -211,7 +216,6 @@ set(viewer_SOURCE_FILES
llfloaterwhitelistentry.cpp
llfloaterwindlight.cpp
llfloaterworldmap.cpp
- llfoldertype.cpp
llfolderview.cpp
llfolderviewitem.cpp
llfollowcam.cpp
@@ -223,8 +227,8 @@ set(viewer_SOURCE_FILES
llgroupmgr.cpp
llgroupnotify.cpp
llhomelocationresponder.cpp
- llhudeffectbeam.cpp
llhudeffect.cpp
+ llhudeffectbeam.cpp
llhudeffectlookat.cpp
llhudeffectpointat.cpp
llhudeffecttrail.cpp
@@ -238,13 +242,17 @@ set(viewer_SOURCE_FILES
llimhandler.cpp
llimpanel.cpp
llimview.cpp
- llimcontrolpanel.cpp
+ llinspect.cpp
llinspectavatar.cpp
+ llinspectgroup.cpp
llinspectobject.cpp
llinventorybridge.cpp
llinventoryclipboard.cpp
llinventoryfilter.cpp
+ llinventoryfunctions.cpp
llinventorymodel.cpp
+ llinventorypanel.cpp
+ llinventorysubtreepanel.cpp
lljoystickbutton.cpp
lllandmarkactions.cpp
lllandmarklist.cpp
@@ -253,9 +261,9 @@ set(viewer_SOURCE_FILES
lllocaltextureobject.cpp
lllocationhistory.cpp
lllocationinputctrl.cpp
- llurllineeditorctrl.cpp
lllogchat.cpp
llloginhandler.cpp
+ lllogininstance.cpp
llmanip.cpp
llmaniprotate.cpp
llmanipscale.cpp
@@ -282,6 +290,7 @@ set(viewer_SOURCE_FILES
llnotificationalerthandler.cpp
llnotificationgrouphandler.cpp
llnotificationmanager.cpp
+ llnotificationofferhandler.cpp
llnotificationscripthandler.cpp
llnotificationtiphandler.cpp
llnotify.cpp
@@ -295,14 +304,7 @@ set(viewer_SOURCE_FILES
llpanelblockedlist.cpp
llpanelclassified.cpp
llpanelcontents.cpp
- llpaneldirbrowser.cpp
- llpaneldirclassified.cpp
- llpaneldirevents.cpp
- llpaneldirfind.cpp
- llpaneldirgroups.cpp
- llpaneldirland.cpp
- llpaneldirpeople.cpp
- llpaneldirplaces.cpp
+ llpaneleditwearable.cpp
llpanelevent.cpp
llpanelface.cpp
llpanelgroup.cpp
@@ -311,22 +313,22 @@ set(viewer_SOURCE_FILES
llpanelgrouplandmoney.cpp
llpanelgroupnotices.cpp
llpanelgrouproles.cpp
- llpanelinventory.cpp
llpanelimcontrolpanel.cpp
llpanelland.cpp
llpanellandaudio.cpp
+ llpanellandmarkinfo.cpp
llpanellandmarks.cpp
llpanellandmedia.cpp
llpanellogin.cpp
llpanellookinfo.cpp
llpanellooks.cpp
- llpanelmedia.cpp
- llpanelmediahud.cpp
- llpanelmeprofile.cpp
+ llpanelmaininventory.cpp
llpanelmediasettingsgeneral.cpp
- llpanelmediasettingssecurity.cpp
llpanelmediasettingspermissions.cpp
+ llpanelmediasettingssecurity.cpp
+ llpanelmeprofile.cpp
llpanelobject.cpp
+ llpanelobjectinventory.cpp
llpanelpeople.cpp
llpanelpeoplemenus.cpp
llpanelpermissions.cpp
@@ -334,18 +336,23 @@ set(viewer_SOURCE_FILES
llpanelpicks.cpp
llpanelplace.cpp
llpanelplaceinfo.cpp
+ llpanelplaceprofile.cpp
llpanelplaces.cpp
llpanelplacestab.cpp
+ llpanelprimmediacontrols.cpp
llpanelprofile.cpp
llpanelprofileview.cpp
+ llpanelshower.cpp
llpanelteleporthistory.cpp
llpanelvolume.cpp
llparcelselection.cpp
+ llparticipantlist.cpp
llpatchvertexarray.cpp
+ llplacesinventorybridge.cpp
llpolymesh.cpp
llpolymorph.cpp
- llpreviewanim.cpp
llpreview.cpp
+ llpreviewanim.cpp
llpreviewgesture.cpp
llpreviewnotecard.cpp
llpreviewscript.cpp
@@ -358,17 +365,21 @@ set(viewer_SOURCE_FILES
llremoteparcelrequest.cpp
llsavedsettingsglue.cpp
llscreenchannel.cpp
+ llscrollingpanelparam.cpp
llsearchcombobox.cpp
llsearchhistory.cpp
llselectmgr.cpp
+ llsidepanelinventory.cpp
+ llsidepanelobjectinfo.cpp
llsidetray.cpp
llsidetraypanelcontainer.cpp
llsky.cpp
llslurl.cpp
llspatialpartition.cpp
+ llspeakbutton.cpp
+ llspeakers.cpp
llsplitbutton.cpp
llsprite.cpp
- llsrv.cpp
llstartup.cpp
llstatusbar.cpp
llstylemap.cpp
@@ -393,10 +404,10 @@ set(viewer_SOURCE_FILES
lltoastimpanel.cpp
lltoastnotifypanel.cpp
lltoastpanel.cpp
+ lltool.cpp
lltoolbar.cpp
lltoolbrush.cpp
lltoolcomp.cpp
- lltool.cpp
lltooldraganddrop.cpp
lltoolface.cpp
lltoolfocus.cpp
@@ -413,38 +424,44 @@ set(viewer_SOURCE_FILES
lltoolselectland.cpp
lltoolselectrect.cpp
lltracker.cpp
+ lltransientdockablefloater.cpp
+ lltransientfloatermgr.cpp
+ lluilistener.cpp
lluploaddialog.cpp
llurl.cpp
llurldispatcher.cpp
llurlhistory.cpp
+ llurllineeditorctrl.cpp
llurlsimstring.cpp
llurlwhitelist.cpp
- lluserauth.cpp
llvectorperfoptions.cpp
llviewchildren.cpp
llviewerassetstorage.cpp
+ llviewerassettype.cpp
llvieweraudio.cpp
llviewercamera.cpp
llviewercontrol.cpp
+ llviewercontrollistener.cpp
llviewerdisplay.cpp
llviewerfloaterreg.cpp
+ llviewerfoldertype.cpp
llviewergenericmessage.cpp
llviewergesture.cpp
llviewerhelp.cpp
llviewerhelputil.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
- llviewermediafocus.cpp
llviewermedia_streamingaudio.cpp
+ llviewermediafocus.cpp
llviewermenu.cpp
llviewermenufile.cpp
llviewermessage.cpp
@@ -467,6 +484,7 @@ set(viewer_SOURCE_FILES
llviewerthrottle.cpp
llviewervisualparam.cpp
llviewerwindow.cpp
+ llviewerwindowlistener.cpp
llvlcomposition.cpp
llvlmanager.cpp
llvoavatar.cpp
@@ -476,10 +494,11 @@ set(viewer_SOURCE_FILES
llvoclouds.cpp
llvograss.cpp
llvoground.cpp
+ llvoicechannel.cpp
llvoiceclient.cpp
+ llvoicecontrolpanel.cpp
llvoiceremotectrl.cpp
llvoicevisualizer.cpp
- llvoicecontrolpanel.cpp
llvoinventorylistener.cpp
llvopartgroup.cpp
llvosky.cpp
@@ -504,6 +523,7 @@ set(viewer_SOURCE_FILES
llworld.cpp
llworldmap.cpp
llworldmapview.cpp
+ llxmlrpclistener.cpp
llxmlrpctransaction.cpp
noise.cpp
pipeline.cpp
@@ -529,22 +549,25 @@ endif (LINUX)
set(viewer_HEADER_FILES
CMakeLists.txt
ViewerInstall.cmake
- llaccordionctrltab.h
llaccordionctrl.h
+ llaccordionctrltab.h
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
- llappearancemgr.h
llavataractions.h
llavatariconctrl.h
llavatarlist.h
@@ -560,6 +583,7 @@ set(viewer_HEADER_FILES
llcaphttpsender.h
llchannelmanager.h
llchatbar.h
+ llchathistory.h
llchatitemscontainerctrl.h
llchatmsgbox.h
llchiclet.h
@@ -578,6 +602,7 @@ set(viewer_HEADER_FILES
lldebugview.h
lldelayedgestureerror.h
lldirpicker.h
+ lldndbutton.h
lldrawable.h
lldrawpool.h
lldrawpoolalpha.h
@@ -626,7 +651,6 @@ set(viewer_HEADER_FILES
llfloatercolorpicker.h
llfloatercustomize.h
llfloaterdaycycle.h
- llfloaterdirectory.h
llfloaterenvsettings.h
llfloaterfonttest.h
llfloaterfriends.h
@@ -637,8 +661,6 @@ set(viewer_HEADER_FILES
llfloaterhandler.h
llfloaterhardwaresettings.h
llfloaterhelpbrowser.h
- llfloatermediabrowser.h
- llfloatermediasettings.h
llfloaterhud.h
llfloaterimagepreview.h
llfloaterinspect.h
@@ -648,20 +670,24 @@ set(viewer_HEADER_FILES
llfloaterland.h
llfloaterlandholdings.h
llfloatermap.h
+ llfloatermediabrowser.h
+ llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
+ llfloaternearbymedia.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
llfloaterpay.h
+ llfloaterperms.h
llfloaterpostcard.h
llfloaterpostprocess.h
llfloaterpreference.h
- llfloaterperms.h
llfloaterproperties.h
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
+ llfloatersearch.h
llfloatersellland.h
llfloatersettingsdebug.h
llfloatersnapshot.h
@@ -679,7 +705,6 @@ set(viewer_HEADER_FILES
llfloaterwhitelistentry.h
llfloaterwindlight.h
llfloaterworldmap.h
- llfoldertype.h
llfolderview.h
llfoldervieweventlistener.h
llfolderviewitem.h
@@ -705,13 +730,17 @@ set(viewer_HEADER_FILES
llimfloater.h
llimpanel.h
llimview.h
- llimcontrolpanel.h
+ llinspect.h
llinspectavatar.h
+ llinspectgroup.h
llinspectobject.h
llinventorybridge.h
llinventoryclipboard.h
llinventoryfilter.h
+ llinventoryfunctions.h
llinventorymodel.h
+ llinventorypanel.h
+ llinventorysubtreepanel.h
lljoystickbutton.h
lllandmarkactions.h
lllandmarklist.h
@@ -721,14 +750,15 @@ set(viewer_HEADER_FILES
lllocaltextureobject.h
lllocationhistory.h
lllocationinputctrl.h
- llurllineeditorctrl.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
@@ -759,14 +789,7 @@ set(viewer_HEADER_FILES
llpanelblockedlist.h
llpanelclassified.h
llpanelcontents.h
- llpaneldirbrowser.h
- llpaneldirclassified.h
- llpaneldirevents.h
- llpaneldirfind.h
- llpaneldirgroups.h
- llpaneldirland.h
- llpaneldirpeople.h
- llpaneldirplaces.h
+ llpaneleditwearable.h
llpanelevent.h
llpanelface.h
llpanelgroup.h
@@ -775,22 +798,22 @@ set(viewer_HEADER_FILES
llpanelgrouplandmoney.h
llpanelgroupnotices.h
llpanelgrouproles.h
- llpanelinventory.h
llpanelimcontrolpanel.h
llpanelland.h
llpanellandaudio.h
+ llpanellandmarkinfo.h
llpanellandmarks.h
llpanellandmedia.h
llpanellogin.h
llpanellookinfo.h
llpanellooks.h
- llpanelmedia.h
- llpanelmediahud.h
- llpanelmeprofile.h
+ llpanelmaininventory.h
llpanelmediasettingsgeneral.h
- llpanelmediasettingssecurity.h
llpanelmediasettingspermissions.h
+ llpanelmediasettingssecurity.h
+ llpanelmeprofile.h
llpanelobject.h
+ llpanelobjectinventory.h
llpanelpeople.h
llpanelpeoplemenus.h
llpanelpermissions.h
@@ -798,14 +821,19 @@ set(viewer_HEADER_FILES
llpanelpicks.h
llpanelplace.h
llpanelplaceinfo.h
+ llpanelplaceprofile.h
llpanelplaces.h
llpanelplacestab.h
+ llpanelprimmediacontrols.h
llpanelprofile.h
llpanelprofileview.h
+ llpanelshower.h
llpanelteleporthistory.h
llpanelvolume.h
llparcelselection.h
+ llparticipantlist.h
llpatchvertexarray.h
+ llplacesinventorybridge.h
llpolymesh.h
llpolymorph.h
llpreview.h
@@ -822,19 +850,23 @@ set(viewer_HEADER_FILES
llremoteparcelrequest.h
llresourcedata.h
llrootview.h
- llscreenchannel.h
llsavedsettingsglue.h
+ llscreenchannel.h
+ llscrollingpanelparam.h
llsearchcombobox.h
llsearchhistory.h
llselectmgr.h
+ llsidepanelinventory.h
+ llsidepanelobjectinfo.h
llsidetray.h
llsidetraypanelcontainer.h
llsky.h
llslurl.h
llspatialpartition.h
+ llspeakbutton.h
+ llspeakers.h
llsplitbutton.h
llsprite.h
- llsrv.h
llstartup.h
llstatusbar.h
llstylemap.h
@@ -880,23 +912,29 @@ set(viewer_HEADER_FILES
lltoolselectland.h
lltoolselectrect.h
lltracker.h
+ lltransientdockablefloater.h
+ lltransientfloatermgr.h
lluiconstants.h
+ lluilistener.h
lluploaddialog.h
llurl.h
llurldispatcher.h
llurlhistory.h
+ llurllineeditorctrl.h
llurlsimstring.h
llurlwhitelist.h
- lluserauth.h
llvectorperfoptions.h
llviewchildren.h
llviewerassetstorage.h
+ llviewerassettype.h
llvieweraudio.h
llviewerbuild.h
llviewercamera.h
llviewercontrol.h
+ llviewercontrollistener.h
llviewerdisplay.h
llviewerfloaterreg.h
+ llviewerfoldertype.h
llviewergenericmessage.h
llviewergesture.h
llviewerhelp.h
@@ -908,8 +946,8 @@ set(viewer_HEADER_FILES
llviewerkeyboard.h
llviewerlayer.h
llviewermedia.h
- llviewermediaobserver.h
llviewermediafocus.h
+ llviewermediaobserver.h
llviewermenu.h
llviewermenufile.h
llviewermessage.h
@@ -933,6 +971,7 @@ set(viewer_HEADER_FILES
llviewerthrottle.h
llviewervisualparam.h
llviewerwindow.h
+ llviewerwindowlistener.h
llvlcomposition.h
llvlmanager.h
llvoavatar.h
@@ -942,10 +981,11 @@ set(viewer_HEADER_FILES
llvoclouds.h
llvograss.h
llvoground.h
+ llvoicechannel.h
llvoiceclient.h
+ llvoicecontrolpanel.h
llvoiceremotectrl.h
llvoicevisualizer.h
- llvoicecontrolpanel.h
llvoinventorylistener.h
llvopartgroup.h
llvosky.h
@@ -963,7 +1003,6 @@ set(viewer_HEADER_FILES
llwearabledictionary.h
llwearablelist.h
llweb.h
- llmediactrl.h
llwind.h
llwindebug.h
llwlanimator.h
@@ -973,6 +1012,7 @@ set(viewer_HEADER_FILES
llworld.h
llworldmap.h
llworldmapview.h
+ llxmlrpclistener.h
llxmlrpctransaction.h
macmain.h
noise.h
@@ -1025,7 +1065,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
@@ -1113,7 +1153,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})
@@ -1127,7 +1169,6 @@ if (WINDOWS)
comdlg32
${DINPUT_LIBRARY}
${DXGUID_LIBRARY}
- fmodvc
kernel32
odbc32
odbccp32
@@ -1171,6 +1212,15 @@ 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(SORT viewer_XUI_FILES)
source_group("XUI Files" FILES ${viewer_XUI_FILES})
@@ -1223,8 +1273,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)
@@ -1244,23 +1295,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}")
@@ -1281,6 +1332,11 @@ if (LLKDU_LIBRARY)
add_dependencies(${VIEWER_BINARY_NAME} ${LLKDU_LIBRARY})
endif (LLKDU_LIBRARY)
+# 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 OFF CACHE BOOL
"Add a package target that builds an installer package.")
@@ -1337,7 +1393,28 @@ if (WINDOWS)
COMMENT "Copying message.xml to the runtime folder."
)
- add_dependencies(${VIEWER_BINARY_NAME} copy_win_libs)
+ if(WINDOWS)
+ # Copy Win Libs...
+ # This happens at build time, not config time. We can't glob files in this cmake.
+ # *FIX:Mani Write a sub script to glob the files...
+ # *FIX:Mani Use actually dependencies rather than bulk copy.
+ add_custom_command(
+ TARGET ${VIEWER_BINARY_NAME} PRE_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ copy_directory
+ ${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}
+ COMMENT "Copying staged dlls."
+ )
+
+ add_dependencies(${VIEWER_BINARY_NAME} stage_third_party_libs llcommon)
+ if(LLKDU_LIBRARY)
+ # kdu may not exist!
+ add_dependencies(${VIEWER_BINARY_NAME} llkdu)
+ endif(LLKDU_LIBRARY)
+ endif(WINDOWS)
if (EXISTS ${CMAKE_SOURCE_DIR}/copy_win_scripts)
add_dependencies(${VIEWER_BINARY_NAME} copy_win_scripts)
@@ -1363,8 +1440,29 @@ if (WINDOWS)
add_dependencies(${VIEWER_BINARY_NAME} SLPlugin media_plugin_quicktime media_plugin_webkit)
if (PACKAGE)
- add_custom_target(package ALL DEPENDS ${CMAKE_CFG_INTDIR}/touched.bat)
+ add_custom_command(
+ OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/event_host.tar.bz2
+ COMMAND ${PYTHON_EXECUTABLE}
+ ARGS
+ ${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_custom_target(package ALL
+ DEPENDS
+ ${CMAKE_CFG_INTDIR}/touched.bat)
+ # 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)
add_dependencies(package windows-updater windows-crash-logger)
+
+
endif (PACKAGE)
endif (WINDOWS)
@@ -1401,6 +1499,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${WINDOWS_LIBRARIES}
${XMLRPCEPI_LIBRARIES}
${ELFIO_LIBRARIES}
+ ${LLLOGIN_LIBRARIES}
${GOOGLE_PERFTOOLS_LIBRARIES}
)
@@ -1534,7 +1633,9 @@ include(LLAddBuildTest)
SET(viewer_TEST_SOURCE_FILES
llagentaccess.cpp
lldateutil.cpp
+ llmediadataclient.cpp
llviewerhelputil.cpp
+ lllogininstance.cpp
)
set_source_files_properties(
${viewer_TEST_SOURCE_FILES}
@@ -1551,6 +1652,7 @@ set(test_libs
${LLVFS_LIBRARIES}
${LLMATH_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
)
LL_ADD_INTEGRATION_TEST(llcapabilitylistener
@@ -1565,6 +1667,16 @@ LL_ADD_INTEGRATION_TEST(llcapabilitylistener
# Don't do these for DARWIN or LINUX here -- they're taken care of by viewer_manifest.py
if (WINDOWS)
+ add_custom_command(
+ TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ make_directory
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
+ COMMENT "Creating llplugin dir."
+ )
+
get_target_property(BUILT_SLPLUGIN SLPlugin LOCATION)
add_custom_command(
TARGET ${VIEWER_BINARY_NAME} POST_BUILD
@@ -1600,5 +1712,72 @@ if (WINDOWS)
${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin
COMMENT "Copying Quicktime Plugin to the runtime folder."
)
+
+ #*******************************
+ # Copy media plugin support dlls
+ # Debug config runtime files required for the plugins
+ set(plugins_debug_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug")
+ set(plugins_debug_files
+ libeay32.dll
+ qtcored4.dll
+ qtguid4.dll
+ qtnetworkd4.dll
+ qtopengld4.dll
+ qtwebkitd4.dll
+ ssleay32.dll
+ )
+ copy_if_different(
+ ${plugins_debug_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Debug/llplugin"
+ out_targets
+ ${plugins_debug_files}
+ )
+ set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+
+ # Release & ReleaseDebInfo config runtime files required for the plugins
+ set(plugins_release_src_dir "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release")
+ set(plugins_release_files
+ libeay32.dll
+ qtcore4.dll
+ qtgui4.dll
+ qtnetwork4.dll
+ qtopengl4.dll
+ qtwebkit4.dll
+ ssleay32.dll
+ )
+ copy_if_different(
+ ${plugins_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/Release/llplugin"
+ out_targets
+ ${plugins_release_files}
+ )
+ set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+
+ copy_if_different(
+ ${plugins_release_src_dir}
+ "${CMAKE_CURRENT_BINARY_DIR}/RelWithDebInfo/llplugin"
+ out_targets
+ ${plugins_release_files}
+ )
+ set(media_plugin_targets ${media_plugin_targets} ${out_targets})
+
+ add_custom_target(copy_media_plugin_libs ALL
+ DEPENDS
+ ${media_plugin_targets}
+ )
+
+ add_custom_command(
+ TARGET ${VIEWER_BINARY_NAME} POST_BUILD
+ COMMAND ${CMAKE_COMMAND}
+ ARGS
+ -E
+ copy_directory
+ ${CMAKE_BINARY_DIR}/test_apps/llplugintest/${CMAKE_CFG_INTDIR}/imageformats
+ ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/llplugin/imageformats
+ COMMENT "Copying llpluging imageformat libs."
+ )
+
+ add_dependencies(${VIEWER_BINARY_NAME} llmediaplugintest copy_media_plugin_libs)
+
endif (WINDOWS)
diff --git a/indra/newview/English.lproj/InfoPlist.strings b/indra/newview/English.lproj/InfoPlist.strings
index 735424c647..dceaba9a43 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 2.0.0.0";
-CFBundleGetInfoString = "Second Life version 2.0.0.0, Copyright 2004-2009 Linden Research, Inc.";
+CFBundleShortVersionString = "Second Life version 2.0.0.3256";
+CFBundleGetInfoString = "Second Life version 2.0.0.3256, Copyright 2004-2009 Linden Research, Inc.";
diff --git a/indra/newview/Info-SecondLife.plist b/indra/newview/Info-SecondLife.plist
index 7264044d37..7aec8a343d 100644
--- a/indra/newview/Info-SecondLife.plist
+++ b/indra/newview/Info-SecondLife.plist
@@ -32,7 +32,7 @@
</dict>
</array>
<key>CFBundleVersion</key>
- <string>2.0.0.0</string>
+ <string>2.0.0.3256</string>
<key>CSResourcesFileMapped</key>
<true/>
</dict>
diff --git a/indra/newview/app_settings/foldertypes.xml b/indra/newview/app_settings/foldertypes.xml
index 698158308e..0d539177f3 100644
--- a/indra/newview/app_settings/foldertypes.xml
+++ b/indra/newview/app_settings/foldertypes.xml
@@ -1,74 +1,63 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<ensemble_defs>
<ensemble
- asset_num="-1"
- xui_name="default"
- icon_name="inv_plain_closed.tga"
- />
- <ensemble
- asset_num="27"
+ foldertype_num="27"
xui_name="head"
icon_name="inv_folder_outfit_head.tga"
allowed="hair,eyes"
/>
<ensemble
- asset_num="28"
+ foldertype_num="28"
xui_name="gloves"
icon_name="inv_folder_outfit_gloves.tga"
allowed="gloves"
/>
<ensemble
- asset_num="29"
+ foldertype_num="29"
xui_name="jacket"
icon_name="inv_folder_outfit_jacket.tga"
allowed="jacket"
/>
<ensemble
- asset_num="30"
+ foldertype_num="30"
xui_name="pants"
icon_name="inv_folder_outfit_pants.tga"
allowed="pants,underpants"
/>
<ensemble
- asset_num="31"
+ foldertype_num="31"
xui_name="shape"
icon_name="inv_folder_outfit_shape.tga"
allowed="shape,skin,hair,eyes"
/>
<ensemble
- asset_num="32"
+ foldertype_num="32"
xui_name="shoes"
icon_name="inv_folder_outfit_shoes.tga"
allowed="shoes,socks"
/>
<ensemble
- asset_num="33"
+ foldertype_num="33"
xui_name="shirt"
icon_name="inv_folder_outfit_shirt.tga"
allowed="shirt,undershirt"
/>
<ensemble
- asset_num="34"
+ foldertype_num="34"
xui_name="skirt"
icon_name="inv_folder_outfit_skirt.tga"
allowed=""
/>
<ensemble
- asset_num="35"
+ foldertype_num="35"
xui_name="underpants"
icon_name="inv_folder_outfit_underpants.tga"
allowed="underpants"
/>
<ensemble
- asset_num="36"
+ foldertype_num="36"
xui_name="undershirt"
icon_name="inv_folder_outfit_undershirt.tga"
allowed="undershirt"
/>
- <ensemble
- asset_num="47"
- xui_name="outfit"
- icon_name="inv_folder_outfit.tga"
- allowed="outfit"
- />
</ensemble_defs>
diff --git a/indra/newview/app_settings/ignorable_dialogs.xml b/indra/newview/app_settings/ignorable_dialogs.xml
index 669235af1b..ab18febccc 100644
--- a/indra/newview/app_settings/ignorable_dialogs.xml
+++ b/indra/newview/app_settings/ignorable_dialogs.xml
@@ -1,291 +1,291 @@
-<?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>FirstStreamingMusic</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>FirstStreamingVideo</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>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>
+<?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>FirstStreamingMusic</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>FirstStreamingVideo</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>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 5d52158298..5f6fd6e4a7 100644
--- a/indra/newview/app_settings/keywords.ini
+++ b/indra/newview/app_settings/keywords.ini
@@ -459,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
@@ -559,7 +560,8 @@ STATUS_WHITELIST_FAILED URL failed to pass whitelist
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/settings.xml b/indra/newview/app_settings/settings.xml
index be48ebdf67..e8af26c743 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -133,7 +133,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>
@@ -142,7 +142,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>1</integer>
+ <integer>0</integer>
</map>
<key>AskedAboutCrashReports</key>
<map>
@@ -375,6 +375,17 @@
<key>Value</key>
<integer>0</integer>
</map>
+ <key>AutoPlayMedia</key>
+ <map>
+ <key>Comment</key>
+ <string>Allow media objects to automatically play or navigate?</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>AutoSnapshot</key>
<map>
<key>Comment</key>
@@ -1599,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>
@@ -3620,6 +3631,17 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>IMShowControlPanel</key>
+ <map>
+ <key>Comment</key>
+ <string>Show IM Control Panel</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
<key>IgnoreAllNotifications</key>
<map>
<key>Comment</key>
@@ -3851,6 +3873,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>
@@ -4158,7 +4191,7 @@
<key>Type</key>
<string>Boolean</string>
<key>Value</key>
- <integer>0</integer>
+ <integer>1</integer>
</map>
<key>LipSyncOoh</key>
<map>
@@ -4831,10 +4864,10 @@
<key>Value</key>
<integer>350</integer>
</map>
- <key>NotificationToastTime</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>
@@ -4842,21 +4875,55 @@
<key>Value</key>
<integer>5</integer>
</map>
- <key>ToastOpaqueTime</key>
+ <key>NotificationTipToastLifeTime</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <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>4</integer>
+ <integer>10</integer>
</map>
- <key>StartUpToastTime</key>
+ <key>ToastFadingTime</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <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>StartUpToastLifeTime</key>
+ <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>
@@ -4864,10 +4931,10 @@
<key>Value</key>
<integer>5</integer>
</map>
- <key>ToastMargin</key>
+ <key>ToastGap</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <string>Gap between toasts on a screen</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -4878,7 +4945,7 @@
<key>ChannelBottomPanelMargin</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <string>Space from a lower toast to the Bottom Tray</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -4889,7 +4956,7 @@
<key>NotificationChannelRightMargin</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <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>
@@ -4900,7 +4967,7 @@
<key>OverflowToastHeight</key>
<map>
<key>Comment</key>
- <string>Width of notification messages</string>
+ <string>Height of an overflow toast</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
@@ -5227,7 +5294,6 @@
<key>Value</key>
<integer>1</integer>
</map>
-
<key>PluginInstancesCPULimit</key>
<map>
<key>Comment</key>
@@ -5294,6 +5360,28 @@
<key>Value</key>
<integer>13</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>PrimMediaMaxRetries</key>
+ <map>
+ <key>Comment</key>
+ <string>Maximum number of retries for media queries.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>4</integer>
+ </map>
<key>PrimMediaRequestQueueDelay</key>
<map>
<key>Comment</key>
@@ -5382,6 +5470,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>
@@ -5459,6 +5569,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>
@@ -7285,17 +7406,6 @@
<key>Value</key>
<integer>0</integer>
</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>
@@ -7610,6 +7720,28 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>ShowScriptErrors</key>
+ <map>
+ <key>Comment</key>
+ <string>Show script errors</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>Boolean</string>
+ <key>Value</key>
+ <integer>1</integer>
+ </map>
+ <key>ShowScriptErrorsLocation</key>
+ <map>
+ <key>Comment</key>
+ <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>
@@ -7676,6 +7808,72 @@
<key>Value</key>
<integer>1</integer>
</map>
+ <key>FriendsListShowIcons</key>
+ <map>
+ <key>Comment</key>
+ <string>Show/hide online and all friends icons in the friend list</string>
+ <key>Persist</key>
+ <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>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>
@@ -8493,13 +8691,13 @@
<key>ToolTipVisibleTimeNear</key>
<map>
<key>Comment</key>
- <string>Fade tooltip after after time passes (seconds) while mouse near tooltip</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>F32</string>
<key>Value</key>
- <real>5.0</real>
+ <real>10.0</real>
</map>
<key>ToolTipVisibleTimeOver</key>
<map>
@@ -8680,13 +8878,13 @@
<key>UICloseBoxFromTop</key>
<map>
<key>Comment</key>
- <string>Size of UI floater close box from top</string>
+ <string>Distance from top of floater to top of close box icon, pixels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <real>1</real>
+ <real>5</real>
</map>
<key>UIExtraTriangleHeight</key>
<map>
@@ -8721,17 +8919,6 @@
<key>Value</key>
<real>16</real>
</map>
- <key>UIFloaterHeaderSize</key>
- <map>
- <key>Comment</key>
- <string>Size of UI floater header size</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <real>18</real>
- </map>
<key>UIFloaterHPad</key>
<map>
<key>Comment</key>
@@ -8754,16 +8941,16 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>UIFloaterVPad</key>
+ <key>UIFloaterTitleVPad</key>
<map>
<key>Comment</key>
- <string>Size of UI floater vertical pad</string>
+ <string>Distance from top of floater to top of title string, pixels</string>
<key>Persist</key>
<integer>1</integer>
<key>Type</key>
<string>S32</string>
<key>Value</key>
- <real>6</real>
+ <real>7</real>
</map>
<key>UIImgDefaultEyesUUID</key>
<map>
@@ -8875,17 +9062,6 @@
<key>Value</key>
<string>5748decc-f629-461c-9a36-a35a221fe21f</string>
</map>
- <key>UIImgDefaultTattooUUID</key>
- <map>
- <key>Comment</key>
- <string />
- <key>Persist</key>
- <integer>0</integer>
- <key>Type</key>
- <string>String</string>
- <key>Value</key>
- <string>5748decc-f629-461c-9a36-a35a221fe21f</string>
- </map>
<key>UIImgDefaultUnderwearUUID</key>
<map>
<key>Comment</key>
@@ -9645,17 +9821,6 @@
<key>Value</key>
<integer>16</integer>
</map>
- <key>UITabCntrTabHeight</key>
- <map>
- <key>Comment</key>
- <string>UI Tab Container Tab Height</string>
- <key>Persist</key>
- <integer>1</integer>
- <key>Type</key>
- <string>S32</string>
- <key>Value</key>
- <integer>16</integer>
- </map>
<key>UITabCntrTabHPad</key>
<map>
<key>Comment</key>
@@ -9970,7 +10135,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>
@@ -10372,6 +10537,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>
@@ -10471,6 +10647,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>
diff --git a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
index 8bd702a8da..28908a311d 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/blurLightF.glsl
@@ -46,11 +46,15 @@ void main()
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 defined_weight = kern[0].xy; // special case the kern[0] (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;
+
+ float center_e = 1.0 - (texture2DRect(edgeMap, vary_fragcoord.xy).a+
+ texture2DRect(edgeMap, vary_fragcoord.xy+dlt*0.333).a+
+ texture2DRect(edgeMap, vary_fragcoord.xy-dlt*0.333).a);
- float e = 1.0;
- for (int i = 0; i < 4; i++)
+ float e = center_e;
+ for (int i = 1; i < 4; i++)
{
vec2 tc = vary_fragcoord.xy + kern[i].z*dlt;
@@ -67,10 +71,8 @@ void main()
texture2DRect(edgeMap, tc.xy-dlt*0.333).a;
}
-
- e = 1.0;
-
- for (int i = 0; i < 4; i++)
+ e = center_e;
+ for (int i = 1; i < 4; i++)
{
vec2 tc = vary_fragcoord.xy - kern[i].z*dlt;
diff --git a/indra/newview/build_win32_appConfig.py b/indra/newview/build_win32_appConfig.py
index fb6a0258bc..8eadf0068f 100644
--- a/indra/newview/build_win32_appConfig.py
+++ b/indra/newview/build_win32_appConfig.py
@@ -31,11 +31,7 @@
import sys, os, re
from xml.dom.minidom import parse
-def main():
- src_manifest_name = sys.argv[1]
- src_config_name = sys.argv[2]
- dst_config_name = sys.argv[3]
-
+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')
@@ -47,11 +43,31 @@ def main():
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__":
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 c943c57fdb..10c197d09e 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="24">
+ <!-- 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,10899 +403,10966 @@
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"
+ 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="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="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"
+ id="1016"
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="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"
+ id="600"
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"
+ 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"
+ id="832"
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"
+ 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_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 alpha"
- visibility_mask="TRUE">
+ name="lower_clothes_shadow">
<texture
- local_texture="hair_alpha" />
- </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">
-
- <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
- 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="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_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="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" />
-
- <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
- 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="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_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="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" />
-
- <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
- name="lower alpha"
- visibility_mask="TRUE">
- <texture
- local_texture="lower_alpha" />
- </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
- name="eyes alpha"
- visibility_mask="TRUE">
- <texture
- local_texture="eyes_alpha" />
- </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>
+
+ <layer
+ name="eyes alpha"
+ visibility_mask="TRUE">
+ <texture
+ local_texture="eyes_alpha" />
+ </layer>
- <driven
- id="635" />
+ </layer_set>
- <driven
- id="851" />
- </param_driver>
- </param>
+ <!-- =========================================================== -->
+ <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"
+ id="858"
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"
- 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"
- 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"
+ id="859"
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>
-
- <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_alpha
+ tga_file="skirt_slit_left_alpha.tga"
+ multiply_blend="true"
+ domain="0" />
</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"
+ id="862"
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"
- 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
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/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/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/installers/darwin/firstlook-dmg/_DS_Store b/indra/newview/installers/darwin/firstlook-dmg/_DS_Store
index 6c5a3f3452..408a4d4992 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/publicnightly-dmg/_DS_Store b/indra/newview/installers/darwin/publicnightly-dmg/_DS_Store
index 6a91b38d6d..b901e46b65 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/releasecandidate-dmg/_DS_Store b/indra/newview/installers/darwin/releasecandidate-dmg/_DS_Store
index a8b757372e..309c8adaaa 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/FILES_ARE_UNICODE_UTF-16LE.txt b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt
index 185c0180fb..30f9349111 100644
--- a/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt
+++ b/indra/newview/installers/windows/FILES_ARE_UNICODE_UTF-16LE.txt
@@ -1,6 +1,6 @@
-The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE.
-
-This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details.
-
-James Cook
-September 2008
+The language files in this directory are Unicode (Little-Endian) format, also known as UTF-16 LE.
+
+This is the format required for NSIS Unicode. See http://www.scratchpaper.com/ for details.
+
+James Cook
+September 2008
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/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/llagent.cpp b/indra/newview/llagent.cpp
index 08681db6cb..75a72e5b17 100644
--- a/indra/newview/llagent.cpp
+++ b/indra/newview/llagent.cpp
@@ -35,16 +35,16 @@
#include "llagent.h"
#include "llagentwearables.h"
+#include "llagentlistener.h"
#include "llanimationstates.h"
#include "llcallingcard.h"
#include "llconsole.h"
#include "lldrawable.h"
#include "llfirstuse.h"
#include "llfloaterreg.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
#include "llfloatercamera.h"
#include "llfloatercustomize.h"
-#include "llfloaterdirectory.h"
#include "llfloaterland.h"
#include "llfloatersnapshot.h"
@@ -256,6 +256,7 @@ LLAgent::LLAgent() :
mHUDTargetZoom(1.f),
mHUDCurZoom(1.f),
mInitialized(FALSE),
+ mListener(),
mForceMouselook(FALSE),
mDoubleTapRunTimer(),
@@ -330,7 +331,7 @@ LLAgent::LLAgent() :
mLeftKey(0),
mUpKey(0),
mYawKey(0.f),
- mPitchKey(0),
+ mPitchKey(0.f),
mOrbitLeftKey(0.f),
mOrbitRightKey(0.f),
@@ -384,6 +385,8 @@ LLAgent::LLAgent() :
}
mFollowCam.setMaxCameraDistantFromSubject( MAX_CAMERA_DISTANCE_FROM_AGENT );
+
+ mListener.reset(new LLAgentListener(*this));
}
// Requires gSavedSettings to be initialized.
@@ -723,15 +726,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);
}
@@ -2509,10 +2512,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())
@@ -2537,7 +2540,7 @@ void LLAgent::propagate(const F32 dt)
mLeftKey = 0;
mUpKey = 0;
mYawKey = 0.f;
- mPitchKey = 0;
+ mPitchKey = 0.f;
}
//-----------------------------------------------------------------------------
@@ -3168,6 +3171,7 @@ void LLAgent::updateCamera()
mFollowCam.copyParams(*current_cam);
mFollowCam.setSubjectPositionAndRotation( mAvatarObject->getRenderPosition(), avatarRotationForFollowCam );
mFollowCam.update();
+ LLViewerJoystick::getInstance()->setCameraNeedsUpdate(true);
}
else
{
@@ -3377,13 +3381,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();
+ }
}
}
@@ -4245,7 +4254,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL avatar_animate, BOOL camera_ani
{
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();
@@ -5382,12 +5391,6 @@ void update_group_floaters(const LLUUID& group_id)
//*TODO Implement group update for Profile View
// still actual as of July 31, 2009 (DZ)
- if (gIMMgr)
- {
- // update the talk view
- gIMMgr->refresh();
- }
-
gAgent.fireEvent(new LLOldEvents::LLEvent(&gAgent, "new group"), "");
}
@@ -5427,8 +5430,6 @@ void LLAgent::processAgentDropGroup(LLMessageSystem *msg, void **)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
LLGroupActions::closeGroup(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
}
else
{
@@ -5506,9 +5507,6 @@ class LLAgentDropGroupViewerNode : public LLHTTPNode
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
LLGroupActions::closeGroup(group_id);
- // refresh the group panel of the search window,
- //if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
}
else
{
@@ -5971,7 +5969,7 @@ bool LLAgent::teleportCore(bool is_local)
LLFloaterReg::hideInstance("about_land");
LLViewerParcelMgr::getInstance()->deselectLand();
- LLViewerMediaFocus::getInstance()->setFocusFace(false, NULL, 0, NULL);
+ LLViewerMediaFocus::getInstance()->clearFocus();
// Close all pie menus, deselect land, etc.
// Don't change the camera until we know teleport succeeded. JC
@@ -6319,8 +6317,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;
diff --git a/indra/newview/llagent.h b/indra/newview/llagent.h
index 5ca630f8d1..99a9bdd8e6 100644
--- a/indra/newview/llagent.h
+++ b/indra/newview/llagent.h
@@ -105,6 +105,8 @@ struct LLGroupData
std::string mName;
};
+class LLAgentListener;
+
//------------------------------------------------------------------------
// LLAgent
//------------------------------------------------------------------------
@@ -142,6 +144,8 @@ public:
BOOL mInitialized;
BOOL mFirstLogin;
std::string mMOTD; // Message of the day
+private:
+ boost::shared_ptr<LLAgentListener> mListener;
//--------------------------------------------------------------------
// Session
@@ -471,7 +475,7 @@ private:
S32 mLeftKey;
S32 mUpKey;
F32 mYawKey;
- S32 mPitchKey;
+ F32 mPitchKey;
//--------------------------------------------------------------------
// Movement from user input
@@ -486,7 +490,7 @@ public:
void moveLeftNudge(S32 direction);
void moveUp(S32 direction);
void moveYaw(F32 mag, bool reset_view = true);
- void movePitch(S32 direction);
+ void movePitch(F32 mag);
//--------------------------------------------------------------------
// Orbit
diff --git a/indra/newview/llagentlistener.cpp b/indra/newview/llagentlistener.cpp
new file mode 100644
index 0000000000..0f00078b33
--- /dev/null
+++ b/indra/newview/llagentlistener.cpp
@@ -0,0 +1,78 @@
+/**
+ * @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)
+ : LLDispatchListener("LLAgent", "op"),
+ mAgent(agent)
+{
+ add("requestTeleport", &LLAgentListener::requestTeleport);
+ add("requestSit", &LLAgentListener::requestSit);
+ add("requestStand", &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", "objectim", "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..6f0b5a54c5
--- /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 "lleventdispatcher.h"
+
+class LLAgent;
+class LLSD;
+
+class LLAgentListener : public LLDispatchListener
+{
+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/llagentui.cpp b/indra/newview/llagentui.cpp
index 1a69f1d975..2911a35581 100644
--- a/indra/newview/llagentui.cpp
+++ b/indra/newview/llagentui.cpp
@@ -89,6 +89,14 @@ std::string LLAgentUI::buildSLURL(const bool escaped /*= true*/)
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();
diff --git a/indra/newview/llagentui.h b/indra/newview/llagentui.h
index 47ecb04547..c7aafb71e7 100644
--- a/indra/newview/llagentui.h
+++ b/indra/newview/llagentui.h
@@ -52,6 +52,11 @@ public:
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
index 2cfa8d2a54..3fc1055acd 100644
--- a/indra/newview/llagentwearables.cpp
+++ b/indra/newview/llagentwearables.cpp
@@ -39,6 +39,7 @@
#include "llfloaterinventory.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llnotify.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
@@ -46,6 +47,7 @@
#include "llwearablelist.h"
#include "llgesturemgr.h"
#include "llappearancemgr.h"
+#include "lltexlayer.h"
#include <boost/scoped_ptr.hpp>
@@ -65,11 +67,13 @@ public:
struct InitialWearableData
{
EWearableType mType;
- U32 mIndex;
LLUUID mItemID;
LLUUID mAssetID;
- InitialWearableData(EWearableType type, U32 index, LLUUID itemID, LLUUID assetID) :
- mType(type), mIndex(index), mItemID(itemID), mAssetID(assetID) { }
+ InitialWearableData(EWearableType type, LLUUID& itemID, LLUUID& assetID) :
+ mType(type),
+ mItemID(itemID),
+ mAssetID(assetID)
+ {}
};
typedef std::vector<InitialWearableData> initial_wearable_data_vec_t;
@@ -139,11 +143,6 @@ LLAgentWearables::LLAgentWearables() :
mWearablesLoaded(FALSE),
mAvatarObject(NULL)
{
- // MULTI-WEARABLE: TODO remove null entries.
- for (U32 i = 0; i < WT_COUNT; i++)
- {
- mWearableDatas[(EWearableType)i].push_back(NULL);
- }
}
LLAgentWearables::~LLAgentWearables()
@@ -237,10 +236,16 @@ void LLAgentWearables::addWearabletoAgentInventoryDone(const S32 type,
{
wearable->setItemID(item_id);
}
- setWearable((EWearableType)type,index,wearable);
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)
@@ -260,11 +265,11 @@ void LLAgentWearables::sendAgentWearablesUpdate()
{
// MULTI-WEARABLE: call i "type" or something.
// First make sure that we have inventory items for each wearable
- for (S32 i=0; i < WT_COUNT; ++i)
+ for (S32 type=0; type < WT_COUNT; ++type)
{
- for (U32 j=0; j < getWearableCount((EWearableType)i); j++)
+ for (U32 j=0; j < getWearableCount((EWearableType)type); ++j)
{
- LLWearable* wearable = getWearable((EWearableType)i,j);
+ LLWearable* wearable = getWearable((EWearableType)type,j);
if (wearable)
{
if (wearable->getItemID().isNull())
@@ -272,7 +277,7 @@ void LLAgentWearables::sendAgentWearablesUpdate()
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
LLPointer<LLRefCount>(NULL),
- i,
+ type,
j,
wearable,
addWearableToAgentInventoryCallback::CALL_NONE);
@@ -299,15 +304,15 @@ void LLAgentWearables::sendAgentWearablesUpdate()
lldebugs << "sendAgentWearablesUpdate()" << llendl;
// MULTI-WEARABLE: update for multi-wearables after server-side support is in.
- for (S32 i=0; i < WT_COUNT; ++i)
+ for (S32 type=0; type < WT_COUNT; ++type)
{
gMessageSystem->nextBlockFast(_PREHASH_WearableData);
- U8 type_u8 = (U8)i;
+ 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)i, 0);
+ LLWearable* wearable = getWearable((EWearableType)type, 0);
if (wearable)
{
//llinfos << "Sending wearable " << wearable->getName() << llendl;
@@ -327,19 +332,18 @@ void LLAgentWearables::sendAgentWearablesUpdate()
gMessageSystem->addUUIDFast(_PREHASH_ItemID, LLUUID::null);
}
- lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)i) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
+ lldebugs << " " << LLWearableDictionary::getTypeLabel((EWearableType)type) << ": " << (wearable ? wearable->getAssetID() : LLUUID::null) << llendl;
}
gAgent.sendReliableMessage();
}
-// MULTI-WEARABLE: add index.
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().createCopyFromAvatar(old_wearable);
+ 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);
@@ -391,7 +395,6 @@ void LLAgentWearables::saveWearable(const EWearableType type, const U32 index, B
}
}
-// MULTI-WEARABLE: add index
void LLAgentWearables::saveWearableAs(const EWearableType type,
const U32 index,
const std::string& new_name,
@@ -417,7 +420,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
}
std::string trunc_name(new_name);
LLStringUtil::truncate(trunc_name, DB_INV_ITEM_NAME_STR_LEN);
- LLWearable* new_wearable = LLWearableList::instance().createCopyFromAvatar(
+ LLWearable* new_wearable = LLWearableList::instance().createCopy(
old_wearable,
trunc_name);
LLPointer<LLInventoryCallback> cb =
@@ -431,7 +434,7 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
if (save_in_lost_and_found)
{
category_id = gInventory.findCategoryUUIDForType(
- LLAssetType::AT_LOST_AND_FOUND);
+ LLFolderType::FT_LOST_AND_FOUND);
}
else
{
@@ -451,10 +454,8 @@ void LLAgentWearables::saveWearableAs(const EWearableType type,
void LLAgentWearables::revertWearable(const EWearableType type, const U32 index)
{
LLWearable* wearable = getWearable(type, index);
- if (wearable)
- {
- wearable->writeToAvatar(TRUE);
- }
+ wearable->revertValues();
+
gAgent.sendAgentSetAppearance();
}
@@ -604,13 +605,10 @@ void LLAgentWearables::sendAgentWearablesRequest()
gAgent.sendReliableMessage();
}
-// MULTI-WEARABLE: update for multiple items per type.
-// Used to enable/disable menu items.
// static
BOOL LLAgentWearables::selfHasWearable(EWearableType type)
{
- // MULTI-WEARABLE: TODO could be getWearableCount > 0, once null entries have been eliminated.
- return gAgentWearables.getWearable(type,0) != NULL;
+ return (gAgentWearables.getWearableCount(type) > 0);
}
LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
@@ -633,6 +631,11 @@ LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 index)
void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearable *wearable)
{
+ if (!getWearable(type,index))
+ {
+ pushWearable(type,wearable);
+ return;
+ }
wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
if (wearable_iter == mWearableDatas.end())
{
@@ -647,7 +650,78 @@ void LLAgentWearables::setWearable(const EWearableType type, U32 index, LLWearab
else
{
wearable_vec[index] = wearable;
+ mAvatarObject->wearableUpdated(wearable->getType());
+ }
+}
+
+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);
+ mAvatarObject->wearableUpdated(wearable->getType());
+ return mWearableDatas[type].size()-1;
+ }
+ return MAX_WEARABLES_PER_TYPE;
+}
+
+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());
+ }
+}
+
+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
@@ -668,7 +742,17 @@ const LLWearable* LLAgentWearables::getWearable(const EWearableType type, U32 in
}
}
-//MULTI-WEARABLE: this will give wrong values until we get rid of the "always one empty object" scheme.
+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);
@@ -680,6 +764,13 @@ U32 LLAgentWearables::getWearableCount(const EWearableType type) const
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();
@@ -708,22 +799,12 @@ const LLUUID LLAgentWearables::getWearableAssetID(EWearableType type, U32 index)
return LLUUID();
}
-// Warning: include_linked_items = TRUE makes this operation expensive.
-BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id, BOOL include_linked_items) const
+BOOL LLAgentWearables::isWearingItem(const LLUUID& item_id) const
{
- if (getWearableFromItemID(item_id) != NULL) return TRUE;
- if (include_linked_items)
+ const LLUUID& base_item_id = gInventory.getLinkedItemID(item_id);
+ if (getWearableFromItemID(base_item_id) != NULL)
{
- LLInventoryModel::item_array_t item_array;
- gInventory.collectLinkedItems(item_id, item_array);
- for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- LLViewerInventoryItem *linked_item = (*iter);
- const LLUUID &linked_item_id = linked_item->getUUID();
- if (getWearableFromItemID(linked_item_id) != NULL) return TRUE;
- }
+ return TRUE;
}
return FALSE;
}
@@ -759,7 +840,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
}
// Get the UUID of the current outfit folder (will be created if it doesn't exist)
- LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
LLInitialWearablesFetch* outfit = new LLInitialWearablesFetch();
@@ -798,7 +879,7 @@ void LLAgentWearables::processAgentInitialWearablesUpdate(LLMessageSystem* mesgs
// 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, 0, item_id, asset_id); // MULTI-WEARABLE: update
+ LLInitialWearablesFetch::InitialWearableData wearable_data(type, item_id, asset_id); // MULTI-WEARABLE: update
outfit->mAgentInitialWearables.push_back(wearable_data);
}
@@ -832,7 +913,7 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void*
{
boost::scoped_ptr<LLInitialWearablesFetch::InitialWearableData> wear_data((LLInitialWearablesFetch::InitialWearableData*)userdata);
const EWearableType type = wear_data->mType;
- const U32 index = wear_data->mIndex;
+ U32 index = 0;
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if (!avatar)
@@ -843,22 +924,19 @@ void LLAgentWearables::onInitialWearableAssetArrived(LLWearable* wearable, void*
if (wearable)
{
llassert(type == wearable->getType());
- // MULTI-WEARABLE: is this always zeroth element? Change sometime.
wearable->setItemID(wear_data->mItemID);
- gAgentWearables.setWearable(type, index, wearable);
+ index = gAgentWearables.pushWearable(type, wearable);
gAgentWearables.mItemsAwaitingWearableUpdate.erase(wear_data->mItemID);
// disable composites if initial textures are baked
avatar->setupComposites();
- wearable->writeToAvatar(FALSE);
avatar->setCompositeUpdatesEnabled(TRUE);
gInventory.addChangedMask(LLInventoryObserver::LABEL, wearable->getItemID());
}
else
{
// Somehow the asset doesn't exist in the database.
- // MULTI-WEARABLE: assuming zeroth elt
gAgentWearables.recoverMissingWearable(type,index);
}
@@ -898,13 +976,12 @@ void LLAgentWearables::recoverMissingWearable(const EWearableType type, U32 inde
S32 type_s32 = (S32) type;
setWearable(type,index,new_wearable);
- new_wearable->writeToAvatar(TRUE);
+ //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);
+ const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
LLPointer<LLRefCount>(NULL),
@@ -938,8 +1015,8 @@ void LLAgentWearables::addLocalTextureObject(const EWearableType wearable_type,
{
llerrs << "Tried to add local texture object to invalid wearable with type " << wearable_type << " and index " << wearable_index << llendl;
}
-
- wearable->setLocalTextureObject(texture_type, new LLLocalTextureObject());
+ LLLocalTextureObject* lto = new LLLocalTextureObject();
+ wearable->setLocalTextureObject(texture_type, lto);
}
void LLAgentWearables::createStandardWearables(BOOL female)
@@ -982,17 +1059,15 @@ void LLAgentWearables::createStandardWearables(BOOL female)
once = true;
donecb = new createStandardWearablesAllDoneCallback;
}
- // MULTI_WEARABLE: only elt 0, may be the right thing?
- llassert(getWearable((EWearableType)i,0) == NULL);
+ llassert(getWearableCount((EWearableType)i) == 0);
LLWearable* wearable = LLWearableList::instance().createNewWearable((EWearableType)i);
- setWearable((EWearableType)i,0,wearable);
+ U32 index = pushWearable((EWearableType)i,wearable);
// no need to update here...
- // MULTI_WEARABLE: hardwired index = 0 here.
LLPointer<LLInventoryCallback> cb =
new addWearableToAgentInventoryCallback(
donecb,
i,
- 0,
+ index,
wearable,
addWearableToAgentInventoryCallback::CALL_CREATESTANDARDDONE);
addWearableToAgentInventory(cb, wearable, LLUUID::null, FALSE);
@@ -1002,11 +1077,9 @@ void LLAgentWearables::createStandardWearables(BOOL female)
void LLAgentWearables::createStandardWearablesDone(S32 type, U32 index)
{
- LLWearable* wearable = getWearable((EWearableType)type, index);
-
- if (wearable)
+ if (mAvatarObject)
{
- wearable->writeToAvatar(TRUE);
+ mAvatarObject->updateVisualParams();
}
}
@@ -1023,12 +1096,12 @@ void LLAgentWearables::createStandardWearablesAllDone()
mAvatarObject->onFirstTEMessageReceived();
}
+// MULTI-WEARABLE: Properly handle multiwearables later.
void LLAgentWearables::getAllWearablesArray(LLDynamicArray<S32>& wearables)
{
for( S32 i = 0; i < WT_COUNT; ++i )
{
- // MULTI-WEARABLE: Properly handle multiwearables later.
- if (getWearable( (EWearableType) i, 0 ) != NULL)
+ if (getWearableCount((EWearableType) i) != 0)
{
wearables.push_back(i);
}
@@ -1049,8 +1122,8 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
// First, make a folder in the Clothes directory.
LLUUID folder_id = gInventory.createNewCategory(
- gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING),
- LLAssetType::AT_NONE,
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING),
+ LLFolderType::FT_NONE,
new_folder_name);
bool found_first_item = false;
@@ -1141,25 +1214,30 @@ void LLAgentWearables::makeNewOutfit(const std::string& new_folder_name,
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)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- 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);
+ 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());
}
- msg->nextBlock("ObjectData");
- msg->addUUID("OldItemID", item_id);
- msg->addUUID("OldFolderID", item->getParentUUID());
}
if (msg_started)
@@ -1178,10 +1256,10 @@ LLUUID LLAgentWearables::makeNewOutfitLinks(const std::string& new_folder_name)
}
// First, make a folder in the My Outfits directory.
- LLUUID parent_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_MY_OUTFITS);
+ const LLUUID parent_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_MY_OUTFITS);
LLUUID folder_id = gInventory.createNewCategory(
parent_id,
- LLAssetType::AT_OUTFIT,
+ LLFolderType::FT_OUTFIT,
new_folder_name);
LLAppearanceManager::shallowCopyCategory(LLAppearanceManager::getCOF(),folder_id, NULL);
@@ -1233,6 +1311,18 @@ void LLAgentWearables::addWearableToAgentInventory(LLPointer<LLInventoryCallback
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)
{
@@ -1240,16 +1330,8 @@ void LLAgentWearables::removeWearable(const EWearableType type, bool do_remove_a
}
else
{
-// MULTI_WEARABLE: handle vector changes from arbitrary removal.
LLWearable* old_wearable = getWearable(type,index);
- 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())
@@ -1307,27 +1389,27 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
for (S32 i=max_entry; i>=0; i--)
{
LLWearable* old_wearable = getWearable(type,i);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,i));
- setWearable(type,i,NULL);
+ const LLUUID &item_id = getWearableItemID(type,i);
+ popWearable(type,i);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ LLAppearanceManager::removeItemLinks(item_id,false);
//queryWearableCache(); // moved below
- // MULTI_WEARABLE: FIXME - currently we keep a null entry, so can't delete the last one.
- if (i>0)
- {
- mWearableDatas[type].pop_back();
- }
if (old_wearable)
{
old_wearable->removeFromAvatar(TRUE);
}
}
+ mWearableDatas[type].clear();
}
else
{
LLWearable* old_wearable = getWearable(type, index);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID(type,index));
- setWearable(type,index,NULL);
+ const LLUUID &item_id = getWearableItemID(type,index);
+ popWearable(type, index);
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ LLAppearanceManager::removeItemLinks(item_id,false);
//queryWearableCache(); // moved below
@@ -1335,16 +1417,6 @@ void LLAgentWearables::removeWearableFinal(const EWearableType type, bool do_rem
{
old_wearable->removeFromAvatar(TRUE);
}
-
- // MULTI_WEARABLE: logic changes if null entries go away
- if (getWearableCount(type)>1)
- {
- // Have to shrink the vector and clean up the item.
- wearableentry_map_t::iterator wearable_iter = mWearableDatas.find(type);
- llassert_always(wearable_iter != mWearableDatas.end());
- wearableentry_vec_t& wearable_vec = wearable_iter->second;
- wearable_vec.erase( wearable_vec.begin() + index );
- }
}
queryWearableCache();
@@ -1376,6 +1448,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
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);
@@ -1402,7 +1477,6 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
gInventory.addChangedMask(LLInventoryObserver::LABEL, old_item_id);
-
// Assumes existing wearables are not dirty.
if (old_wearable->isDirty())
{
@@ -1424,12 +1498,13 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
{
// MULTI_WEARABLE: assuming 0th
LLWearable* wearable = getWearable((EWearableType)i, 0);
- gInventory.addChangedMask(LLInventoryObserver::LABEL, getWearableItemID((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);
}
- setWearable((EWearableType)i,0,NULL);
+ removeWearable((EWearableType)i,true,0);
}
}
@@ -1450,9 +1525,9 @@ void LLAgentWearables::setWearableOutfit(const LLInventoryItem::item_array_t& it
}
}
- for (i = 0; i < count; i++)
+ if (mAvatarObject)
{
- wearables[i]->writeToAvatar(TRUE);
+ mAvatarObject->updateVisualParams();
}
// Start rendering & update the server
@@ -1578,7 +1653,7 @@ void LLAgentWearables::setWearableFinal(LLInventoryItem* new_item, LLWearable* n
//llinfos << "LLVOAvatar::setWearableItem()" << llendl;
queryWearableCache();
- new_wearable->writeToAvatar(TRUE);
+ //new_wearable->writeToAvatar(TRUE);
updateServer();
}
@@ -1612,13 +1687,16 @@ void LLAgentWearables::queryWearableCache()
LLUUID hash;
for (U8 i=0; i < baked_dict->mWearables.size(); i++)
{
- // EWearableType baked_type = gBakedWearableMap[baked_index][baked_num];
const EWearableType baked_type = baked_dict->mWearables[i];
- // MULTI_WEARABLE: assuming 0th
- const LLWearable* wearable = getWearable(baked_type,0);
- if (wearable)
+ // MULTI_WEARABLE: not order-dependent
+ const U32 num_wearables = getWearableCount(baked_type);
+ for (U32 index = 0; index < num_wearables; ++index)
{
- hash ^= wearable->getAssetID();
+ const LLWearable* wearable = getWearable(baked_type,index);
+ if (wearable)
+ {
+ hash ^= wearable->getAssetID();
+ }
}
}
if (hash.notNull())
@@ -1645,10 +1723,8 @@ void LLAgentWearables::queryWearableCache()
// 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(void* userdata)
+void LLAgentWearables::userRemoveWearable(EWearableType& type)
{
- EWearableType type = (EWearableType)(intptr_t)userdata;
-
if (!(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR)) //&&
//!((!gAgent.isTeen()) && (type==WT_UNDERPANTS || type==WT_UNDERSHIRT)))
{
@@ -1658,7 +1734,7 @@ void LLAgentWearables::userRemoveWearable(void* userdata)
}
// static
-void LLAgentWearables::userRemoveAllClothes(void* userdata)
+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)
@@ -1672,7 +1748,6 @@ void LLAgentWearables::userRemoveAllClothes(void* userdata)
}
// static
-// MULTI_WEARABLE: removing all here.
void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
{
if (proceed)
@@ -1686,6 +1761,8 @@ void LLAgentWearables::userRemoveAllClothesStep2(BOOL proceed)
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);
}
}
@@ -1717,20 +1794,25 @@ void LLAgentWearables::userUpdateAttachments(LLInventoryModel::item_array_t& obj
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject* objectp = attachment->getObject();
- if (objectp)
+ for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin();
+ attachment_iter != attachment->mAttachedObjects.end();
+ ++attachment_iter)
{
- LLUUID object_item_id = attachment->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
+ LLViewerObject *objectp = (*attachment_iter);
+ if (objectp)
{
- // object currently worn, not requested.
- objects_to_remove.push_back(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);
+ }
}
}
}
@@ -1806,9 +1888,16 @@ void LLAgentWearables::userRemoveAllAttachments()
{
LLVOAvatar::attachment_map_t::iterator curiter = iter++;
LLViewerJointAttachment* attachment = curiter->second;
- LLViewerObject* objectp = attachment->getObject();
- if (objectp)
- objects_to_remove.push_back(objectp);
+ 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);
}
@@ -1896,6 +1985,17 @@ bool LLAgentWearables::canWearableBeRemoved(const LLWearable* wearable) const
return !(((type == WT_SHAPE) || (type == WT_SKIN) || (type == WT_HAIR) || (type == WT_EYES))
&& (getWearableCount(type) <= 1) );
}
+void LLAgentWearables::animateAllWearableParams(F32 delta, BOOL set_by_user)
+{
+ 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, set_by_user);
+ }
+ }
+}
void LLAgentWearables::updateServer()
{
@@ -1914,7 +2014,8 @@ void LLInitialWearablesFetch::done()
LLFindWearables is_wearable;
gInventory.collectDescendentsIf(mCompleteFolders.front(), cat_array, wearable_array,
LLInventoryModel::EXCLUDE_TRASH, is_wearable);
-
+
+ LLAppearanceManager::setAttachmentInvLinkEnable(true);
if (wearable_array.count() > 0)
{
LLAppearanceManager::instance().updateAppearanceFromCOF();
@@ -1930,7 +2031,7 @@ void LLInitialWearablesFetch::processWearablesMessage()
{
if (!mAgentInitialWearables.empty()) // We have an empty current outfit folder, use the message data instead.
{
- LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
for (U8 i = 0; i < mAgentInitialWearables.size(); ++i)
{
// Populate the current outfit folder with links to the wearables passed in the message
diff --git a/indra/newview/llagentwearables.h b/indra/newview/llagentwearables.h
index 8b9d29342a..317f4a7e4f 100644
--- a/indra/newview/llagentwearables.h
+++ b/indra/newview/llagentwearables.h
@@ -45,6 +45,7 @@ class LLVOAvatarSelf;
class LLWearable;
class LLInitialWearablesFetch;
class LLViewerObject;
+class LLTexLayerTemplate;
class LLAgentWearables
{
@@ -69,7 +70,7 @@ protected:
// Queries
//--------------------------------------------------------------------
public:
- BOOL isWearingItem(const LLUUID& item_id, const BOOL include_linked_items = FALSE) const;
+ 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;
@@ -79,6 +80,7 @@ public:
// 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 set_by_user);
//--------------------------------------------------------------------
// Accessors
@@ -93,8 +95,9 @@ public:
static BOOL selfHasWearable(EWearableType type);
LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/);
const LLWearable* getWearable(const EWearableType type, U32 index /*= 0*/) const;
- U32 getWearableCount(const EWearableType type) const;
-
+ LLWearable* getTopWearable(const EWearableType type);
+ U32 getWearableCount(const EWearableType type) const;
+ U32 getWearableCount(const U32 tex_index) const;
//--------------------------------------------------------------------
// Setters
@@ -103,12 +106,17 @@ public:
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 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);
@@ -183,9 +191,9 @@ public:
//--------------------------------------------------------------------
public:
// MULTI-WEARABLE: assuming one wearable per type. Need upstream changes.
- static void userRemoveWearable(void* userdata); // userdata is EWearableType
- static void userRemoveAllClothes(void* userdata); // userdata is NULL
-
+ 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);
@@ -252,6 +260,8 @@ private:
LLPointer<LLRefCount> mCB;
};
+ static const U32 MAX_WEARABLES_PER_TYPE = 1;
+
}; // LLAgentWearables
extern LLAgentWearables gAgentWearables;
diff --git a/indra/newview/llappearancemgr.cpp b/indra/newview/llappearancemgr.cpp
index cf8d852dfe..41cd77b45d 100644
--- a/indra/newview/llappearancemgr.cpp
+++ b/indra/newview/llappearancemgr.cpp
@@ -130,11 +130,11 @@ void LLOutfitObserver::done()
{
if(LLInventoryType::IT_GESTURE == item->getInventoryType())
{
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
+ pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_GESTURE);
}
else
{
- pid = gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ pid = gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
}
break;
}
@@ -146,7 +146,7 @@ void LLOutfitObserver::done()
LLUUID cat_id = gInventory.createNewCategory(
pid,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
name);
mCatID = cat_id;
LLPointer<LLInventoryCallback> cb = new LLWearInventoryCategoryCallback(mCatID, mAppend);
@@ -296,15 +296,39 @@ struct LLWearableHoldingPattern
bool append;
};
+/* 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;
+}
void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventoryModel::item_array_t& src)
{
LLInventoryModel::item_array_t new_dst;
std::set<LLUUID> mark_inventory;
- std::set<LLUUID> mark_asset;
S32 inventory_dups = 0;
- S32 asset_dups = 0;
for (LLInventoryModel::item_array_t::const_iterator src_pos = src.begin();
src_pos != src.end();
@@ -312,8 +336,6 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
{
LLUUID src_item_id = (*src_pos)->getLinkedUUID();
mark_inventory.insert(src_item_id);
- LLUUID src_asset_id = (*src_pos)->getAssetUUID();
- mark_asset.insert(src_asset_id);
}
for (LLInventoryModel::item_array_t::const_iterator dst_pos = dst.begin();
@@ -324,43 +346,37 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
if (mark_inventory.find(dst_item_id) == mark_inventory.end())
{
- }
- else
- {
- inventory_dups++;
- }
-
- LLUUID dst_asset_id = (*dst_pos)->getAssetUUID();
-
- if (mark_asset.find(dst_asset_id) == mark_asset.end())
- {
// Item is not already present in COF.
new_dst.put(*dst_pos);
- mark_asset.insert(dst_item_id);
+ mark_inventory.insert(dst_item_id);
}
else
{
- asset_dups++;
+ inventory_dups++;
}
}
llinfos << "removeDups, original " << dst.count() << " final " << new_dst.count()
- << " inventory dups " << inventory_dups << " asset_dups " << asset_dups << llendl;
+ << " inventory dups " << inventory_dups << llendl;
dst = new_dst;
}
-
-/* static */ LLUUID LLAppearanceManager::getCOF()
+/* static */
+LLUUID LLAppearanceManager::getCOF()
{
- return gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ return gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
}
// Update appearance from outfit folder.
-/* static */ void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append)
+/* static */
+void LLAppearanceManager::changeOutfit(bool proceed, const LLUUID& category, bool append)
{
if (!proceed)
return;
+#if 1
+ updateCOF(category,append);
+#else
if (append)
{
updateCOFFromCategory(category, append); // append is true - add non-duplicates to COF.
@@ -368,20 +384,22 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
else
{
LLViewerInventoryCategory* catp = gInventory.getCategory(category);
- if (catp->getPreferredType() == LLAssetType::AT_NONE ||
- LLAssetType::lookupIsEnsembleCategoryType(catp->getPreferredType()))
+ if (catp->getPreferredType() == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(catp->getPreferredType()))
{
updateCOFFromCategory(category, append); // append is false - rebuild COF.
}
- else if (catp->getPreferredType() == LLAssetType::AT_OUTFIT)
+ else if (catp->getPreferredType() == LLFolderType::FT_OUTFIT)
{
rebuildCOFFromOutfit(category);
}
}
+#endif
}
// Append to current COF contents by recursively traversing a folder.
-/* static */ void LLAppearanceManager::updateCOFFromCategory(const LLUUID& category, bool append)
+/* static */
+void LLAppearanceManager::updateCOFFromCategory(const LLUUID& category, bool append)
{
// BAP consolidate into one "get all 3 types of descendents" function, use both places.
LLInventoryModel::item_array_t wear_items;
@@ -398,7 +416,7 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
return;
}
- const LLUUID &current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ const LLUUID current_outfit_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
// Processes that take time should show the busy cursor
//inc_busy_count();
@@ -418,11 +436,7 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
if (!append && total_links > 0)
{
- for (S32 i = 0; i < cof_items.count(); ++i)
- {
- gInventory.purgeObject(cof_items.get(i)->getUUID());
- }
- gInventory.notifyObservers();
+ purgeCOFBeforeRebuild(category);
}
LLPointer<LLUpdateAppearanceOnDestroy> link_waiter = new LLUpdateAppearanceOnDestroy;
@@ -477,8 +491,9 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
}
}
-/* static */ void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
- LLPointer<LLInventoryCallback> cb)
+/* static */
+void LLAppearanceManager::shallowCopyCategory(const LLUUID& src_id, const LLUUID& dst_id,
+ LLPointer<LLInventoryCallback> cb)
{
LLInventoryModel::cat_array_t cats;
LLInventoryModel::item_array_t items;
@@ -499,7 +514,7 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
{
LLViewerInventoryCategory *catp = item->getLinkedCategory();
// Skip copying outfit links.
- if (catp && catp->getPreferredType() != LLAssetType::AT_OUTFIT)
+ if (catp && catp->getPreferredType() != LLFolderType::FT_OUTFIT)
{
link_inventory_item(gAgent.getID(),
item->getLinkedUUID(),
@@ -520,9 +535,199 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
}
}
}
+/* static */ 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;
+ 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.
+/* static */ 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.
+/* static */ 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);
+ }
+}
+
+/* static */ void LLAppearanceManager::updateCOF(const LLUUID& category, bool append)
+{
+ const LLUUID cof = getCOF();
+
+ // 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.
+ LLViewerInventoryCategory* catp = gInventory.getCategory(category);
+ if (!append && catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
+ {
+ link_inventory_item(gAgent.getID(), category, cof, catp->getName(),
+ LLAssetType::AT_LINK_FOLDER, link_waiter);
+ }
+
+}
+
+/* static */
+bool LLAppearanceManager::isMandatoryWearableType(EWearableType type)
+{
+ return (type==WT_SHAPE) || (type==WT_SKIN) || (type== WT_HAIR) || (type==WT_EYES);
+}
+
+// For mandatory body parts.
+/* static */
+void LLAppearanceManager::checkMandatoryWearableTypes(const LLUUID& category, std::set<EWearableType>& types_found)
+{
+ LLInventoryModel::cat_array_t new_cats;
+ LLInventoryModel::item_array_t new_items;
+ gInventory.collectDescendents(category, new_cats, new_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ std::set<EWearableType> wt_types_found;
+ for (S32 i = 0; i < new_items.count(); ++i)
+ {
+ LLViewerInventoryItem *itemp = new_items.get(i);
+ if (itemp->isWearableType())
+ {
+ EWearableType type = itemp->getWearableType();
+ if (isMandatoryWearableType(type))
+ {
+ types_found.insert(type);
+ }
+ }
+ }
+}
+
+// Remove everything from the COF that we safely can before replacing
+// with contents of new category. This means preserving any mandatory
+// body parts that aren't present in the new category, and getting rid
+// of everything else.
+/* static */
+void LLAppearanceManager::purgeCOFBeforeRebuild(const LLUUID& category)
+{
+ // See which mandatory body types are present in the new category.
+ std::set<EWearableType> wt_types_found;
+ checkMandatoryWearableTypes(category,wt_types_found);
+
+ LLInventoryModel::cat_array_t cof_cats;
+ LLInventoryModel::item_array_t cof_items;
+ gInventory.collectDescendents(getCOF(), cof_cats, cof_items,
+ LLInventoryModel::EXCLUDE_TRASH);
+ for (S32 i = 0; i < cof_items.count(); ++i)
+ {
+ LLViewerInventoryItem *itemp = cof_items.get(i);
+ if (itemp->isWearableType())
+ {
+ EWearableType type = itemp->getWearableType();
+ if (!isMandatoryWearableType(type) || (wt_types_found.find(type) != wt_types_found.end()))
+ {
+ // Not mandatory or supplied by the new category - OK to delete
+ gInventory.purgeObject(cof_items.get(i)->getUUID());
+ }
+ }
+ else
+ {
+ // Not a wearable - always purge
+ gInventory.purgeObject(cof_items.get(i)->getUUID());
+ }
+ }
+ gInventory.notifyObservers();
+}
// Replace COF contents from a given outfit folder.
-/* static */ void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category)
+/* static */
+void LLAppearanceManager::rebuildCOFFromOutfit(const LLUUID& category)
{
lldebugs << "rebuildCOFFromOutfit()" << llendl;
@@ -538,37 +743,25 @@ void removeDuplicateItems(LLInventoryModel::item_array_t& dst, const LLInventory
LLNotifications::instance().add("CouldNotPutOnOutfit");
return;
}
-
- const LLUUID &current_outfit_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+
// Processes that take time should show the busy cursor
//inc_busy_count();
- LLInventoryModel::cat_array_t cof_cats;
- LLInventoryModel::item_array_t cof_items;
- gInventory.collectDescendents(current_outfit_id, cof_cats, cof_items,
- LLInventoryModel::EXCLUDE_TRASH);
-
//dumpCat(current_outfit_id,"COF before remove:");
- if (items.count() > 0)
- {
- for (S32 i = 0; i < cof_items.count(); ++i)
- {
- gInventory.purgeObject(cof_items.get(i)->getUUID());
- }
- gInventory.notifyObservers();
- }
-
//dumpCat(current_outfit_id,"COF after remove:");
+ purgeCOFBeforeRebuild(category);
+
LLPointer<LLInventoryCallback> link_waiter = new LLUpdateAppearanceOnDestroy;
+ LLUUID current_outfit_id = getCOF();
LLAppearanceManager::shallowCopyCategory(category, current_outfit_id, link_waiter);
//dumpCat(current_outfit_id,"COF after shallow copy:");
// Create a link to the outfit that we wore.
LLViewerInventoryCategory* catp = gInventory.getCategory(category);
- if (catp && catp->getPreferredType() == LLAssetType::AT_OUTFIT)
+ if (catp && catp->getPreferredType() == LLFolderType::FT_OUTFIT)
{
link_inventory_item(gAgent.getID(), category, current_outfit_id, catp->getName(),
LLAssetType::AT_LINK_FOLDER, link_waiter);
@@ -642,7 +835,8 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
// dec_busy_count();
}
-/* static */ void LLAppearanceManager::updateAppearanceFromCOF()
+/* static */
+void LLAppearanceManager::updateAppearanceFromCOF()
{
dumpCat(getCOF(),"COF, start");
@@ -693,7 +887,7 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
LLDynamicArray<LLFoundData*> found_container;
for(S32 i = 0; i < wear_items.count(); ++i)
{
- found = new LLFoundData(wear_items.get(i)->getUUID(),
+ found = new LLFoundData(wear_items.get(i)->getLinkedUUID(), // Wear the base item, not the link
wear_items.get(i)->getAssetUUID(),
wear_items.get(i)->getName(),
wear_items.get(i)->getType());
@@ -724,7 +918,7 @@ void LLAppearanceManager::updateAgentWearables(LLWearableHoldingPattern* holder,
/* static */
void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category,
- LLInventoryModel::item_array_t& items)
+ LLInventoryModel::item_array_t& items)
{
LLInventoryModel::cat_array_t cats;
LLFindCOFValidItems is_cof_valid;
@@ -737,11 +931,28 @@ void LLAppearanceManager::getCOFValidDescendents(const LLUUID& category,
follow_folder_links);
}
-/* static */ 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)
+/* static */
+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);
+}
+
+/* static */
+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;
@@ -868,9 +1079,21 @@ void LLAppearanceManager::wearOutfitByName(const std::string& name)
//dec_busy_count();
}
+bool areMatchingWearables(const LLViewerInventoryItem *a, const LLViewerInventoryItem *b)
+{
+ return (a->isWearableType() && b->isWearableType() &&
+ (a->getWearableType() == b->getWearableType()));
+}
/* static */
void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
{
+ LLViewerInventoryItem *vitem = dynamic_cast<LLViewerInventoryItem*>(item);
+ if (!vitem)
+ {
+ llwarns << "not an llviewerinventoryitem, failed" << llendl;
+ return;
+ }
+
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
gInventory.collectDescendents(LLAppearanceManager::getCOF(),
@@ -880,11 +1103,20 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
bool linked_already = false;
for (S32 i=0; i<item_array.count(); i++)
{
- const LLInventoryItem* inv_item = item_array.get(i).get();
+ // Are these links to the same object?
+ const LLViewerInventoryItem* inv_item = item_array.get(i).get();
if (inv_item->getLinkedUUID() == item->getLinkedUUID())
{
linked_already = true;
- break;
+ }
+ // 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);
+ gInventory.purgeObject(inv_item->getUUID());
+ gInventory.notifyObservers();
}
}
if (linked_already)
@@ -896,9 +1128,9 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
{
LLPointer<LLInventoryCallback> cb = do_update ? new ModifiedCOFCallback : 0;
link_inventory_item( gAgent.getID(),
- item->getLinkedUUID(),
+ vitem->getLinkedUUID(),
getCOF(),
- item->getName(),
+ vitem->getName(),
LLAssetType::AT_LINK,
cb);
}
@@ -907,6 +1139,7 @@ void LLAppearanceManager::wearItem( LLInventoryItem* item, bool do_update )
/* static */
void LLAppearanceManager::wearEnsemble( 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(),
@@ -915,10 +1148,11 @@ void LLAppearanceManager::wearEnsemble( LLInventoryCategory* cat, bool do_update
cat->getName(),
LLAssetType::AT_LINK_FOLDER,
cb);
+#endif
}
/* static */
-void LLAppearanceManager::removeItemLinks(LLUUID& item_id, bool do_update)
+void LLAppearanceManager::removeItemLinks(const LLUUID& item_id, bool do_update)
{
LLInventoryModel::cat_array_t cat_array;
LLInventoryModel::item_array_t item_array;
@@ -940,14 +1174,16 @@ void LLAppearanceManager::removeItemLinks(LLUUID& item_id, bool do_update)
}
}
+//#define DUMP_CAT_VERBOSE
+
/* static */
-void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str)
+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);
-#if 0
+#ifdef DUMP_CAT_VERBOSE
llinfos << llendl;
llinfos << str << llendl;
S32 hitcount = 0;
@@ -959,6 +1195,89 @@ void LLAppearanceManager::dumpCat(const LLUUID& cat_id, std::string str)
llinfos << i <<" "<< item->getName() <<llendl;
}
#endif
- llinfos << str << " count " << items.count() << llendl;
+ llinfos << msg << " count " << items.count() << llendl;
+}
+
+/* static */
+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;
+}
+
+
+std::set<LLUUID> LLAppearanceManager::sRegisteredAttachments;
+bool LLAppearanceManager::sAttachmentInvLinkEnabled(false);
+
+/* static */
+void LLAppearanceManager::setAttachmentInvLinkEnable(bool val)
+{
+ llinfos << "setAttachmentInvLinkEnable => " << (int) val << llendl;
+ sAttachmentInvLinkEnabled = 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;
+}
+
+/* static */
+void LLAppearanceManager::registerAttachment(const LLUUID& item_id)
+{
+ sRegisteredAttachments.insert(item_id);
+ dumpAttachmentSet(sRegisteredAttachments,"after register:");
+
+ if (sAttachmentInvLinkEnabled)
+ {
+ LLViewerInventoryItem *item = gInventory.getItem(item_id);
+ if (item)
+ {
+ LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:");
+ LLAppearanceManager::wearItem(item,false); // Add COF link for item.
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ gInventory.notifyObservers();
+ }
+ }
+ else
+ {
+ llinfos << "no link changes, inv link not enabled" << llendl;
+ }
+}
+
+/* static */
+void LLAppearanceManager::unregisterAttachment(const LLUUID& item_id)
+{
+ sRegisteredAttachments.erase(item_id);
+ dumpAttachmentSet(sRegisteredAttachments,"after unregister:");
+
+ if (sAttachmentInvLinkEnabled)
+ {
+ LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:");
+ LLAppearanceManager::removeItemLinks(item_id, false);
+ // BAP - needs to change for label to track link.
+ gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
+ gInventory.notifyObservers();
+ }
+ else
+ {
+ llinfos << "no link changes, inv link not enabled" << llendl;
+ }
+}
diff --git a/indra/newview/llappearancemgr.h b/indra/newview/llappearancemgr.h
index fe24696182..56f54dfc23 100644
--- a/indra/newview/llappearancemgr.h
+++ b/indra/newview/llappearancemgr.h
@@ -46,6 +46,7 @@ public:
static void updateAppearanceFromCOF();
static bool needToSaveCOF();
static void changeOutfit(bool proceed, const LLUUID& category, bool append);
+ static void updateCOF(const LLUUID& category, bool append = false);
static void updateCOFFromCategory(const LLUUID& category, bool append);
static void rebuildCOFFromOutfit(const LLUUID& category);
static void wearInventoryCategory(LLInventoryCategory* category, bool copy, bool append);
@@ -62,12 +63,26 @@ public:
static LLUUID getCOF();
// Remove COF entries
- static void removeItemLinks(LLUUID& item_id, bool do_update = true);
+ static void removeItemLinks(const LLUUID& item_id, bool do_update = true);
// For debugging - could be moved elsewhere.
- static void dumpCat(const LLUUID& cat_id, std::string str);
+ static void dumpCat(const LLUUID& cat_id, const std::string& msg);
+ static void dumpItemArray(const LLInventoryModel::item_array_t& items, const std::string& msg);
+ static void unregisterAttachment(const LLUUID& item_id);
+ static void registerAttachment(const LLUUID& item_id);
+ static void setAttachmentInvLinkEnable(bool val);
private:
+ static void filterWearableItems(LLInventoryModel::item_array_t& items, S32 max_per_type);
+ static void linkAll(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLPointer<LLInventoryCallback> cb);
+
+ static void getDescendentsOfAssetType(const LLUUID& category,
+ LLInventoryModel::item_array_t& items,
+ LLAssetType::EType type,
+ bool follow_folder_links);
+
static void getCOFValidDescendents(const LLUUID& category,
LLInventoryModel::item_array_t& items);
@@ -78,6 +93,16 @@ private:
bool follow_folder_links);
static void onWearableAssetFetch(LLWearable* wearable, void* data);
static void updateAgentWearables(LLWearableHoldingPattern* holder, bool append);
+ static bool isMandatoryWearableType(EWearableType type);
+ static void checkMandatoryWearableTypes(const LLUUID& category, std::set<EWearableType>& types_found);
+ static void purgeCOFBeforeRebuild(const LLUUID& category);
+ static void purgeCategory(const LLUUID& category, bool keep_outfit_links);
+
+ static std::set<LLUUID> sRegisteredAttachments;
+ static bool sAttachmentInvLinkEnabled;
+
};
+#define SUPPORT_ENSEMBLES 0
+
#endif
diff --git a/indra/newview/llappviewer.cpp b/indra/newview/llappviewer.cpp
index d47b994322..e95eec4741 100644
--- a/indra/newview/llappviewer.cpp
+++ b/indra/newview/llappviewer.cpp
@@ -49,7 +49,6 @@
#include "llviewerstats.h"
#include "llmd5.h"
#include "llpumpio.h"
-#include "llimpanel.h"
#include "llmimetypes.h"
#include "llslurl.h"
#include "llstartup.h"
@@ -73,8 +72,10 @@
#include "llurlhistory.h"
#include "llfirstuse.h"
#include "llrender.h"
+#include "llteleporthistory.h"
#include "lllocationhistory.h"
#include "llfasttimerview.h"
+#include "llvoicechannel.h"
#include "llweb.h"
#include "llsecondlifeurls.h"
@@ -91,14 +92,15 @@
#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 "llapr.h"
+#include "apr_dso.h"
+#include <boost/lexical_cast.hpp>
+
#include "llnotify.h"
#include "llviewerkeyboard.h"
#include "lllfsthread.h"
@@ -154,7 +156,6 @@
#include "llfolderview.h"
#include "lltoolbar.h"
#include "llagentpilot.h"
-#include "llsrv.h"
#include "llvovolume.h"
#include "llflexibleobject.h"
#include "llvosurfacepatch.h"
@@ -179,6 +180,7 @@
#include "llimview.h"
#include "llviewerthrottle.h"
#include "llparcel.h"
+#include "llavatariconctrl.h"
// *FIX: These extern globals should be cleaned up.
// The globals either represent state/config/resource-storage of either
@@ -191,7 +193,19 @@
//----------------------------------------------------------------------------
// 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
+
+#if LL_MSVC
+// disable boost::lexical_cast warning
+#pragma warning (disable:4702)
+#endif
+static LLAppViewerListener sAppViewerListener("LLAppViewer", LLAppViewer::instance);
////// Windows-specific includes to the bottom - nasty defines in these pollute the preprocessor
//
@@ -213,13 +227,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;
@@ -228,8 +238,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;
@@ -410,7 +418,6 @@ static void settings_to_globals()
gAgent.setHideGroupTitle(gSavedSettings.getBOOL("RenderHideGroupTitle"));
gDebugWindowProc = gSavedSettings.getBOOL("DebugWindowProc");
- gAllowTapTapHoldRun = gSavedSettings.getBOOL("AllowTapTapHoldRun");
gShowObjectUpdates = gSavedSettings.getBOOL("ShowObjectUpdates");
gMapScale = gSavedSettings.getF32("MapScale");
@@ -564,9 +571,9 @@ LLAppViewer::LLAppViewer() :
mYieldTime(-1),
mMainloopTimeout(NULL),
mAgentRegionLastAlive(false),
- mFastTimerLogThread(NULL),
mRandomizeFramerate(LLCachedControl<bool>(gSavedSettings,"Randomize Framerate", FALSE)),
- mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE))
+ mPeriodicSlowFrame(LLCachedControl<bool>(gSavedSettings,"Periodic Slow Frame", FALSE)),
+ mFastTimerLogThread(NULL)
{
if(NULL != sInstance)
{
@@ -613,7 +620,19 @@ bool LLAppViewer::init()
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.
@@ -686,8 +705,12 @@ bool LLAppViewer::init()
LLUI::setupPaths();
LLTransUtil::parseStrings("strings.xml", default_trans_args);
LLTransUtil::parseLanguageStrings("language_settings.xml");
- LLWeb::initClass(); // do this after LLUI
+
+ // LLKeyboard relies on LLUI to know what some accelerator keys are called.
+ LLKeyboard::setStringTranslatorFunc( LLTrans::getKeyboardString );
+ LLWeb::initClass(); // do this after LLUI
+
// Provide the text fields with callbacks for opening Urls
LLUrlAction::setOpenURLCallback(&LLWeb::loadURL);
LLUrlAction::setOpenURLInternalCallback(&LLWeb::loadURLInternal);
@@ -872,6 +895,11 @@ bool LLAppViewer::init()
LLViewerJoystick::getInstance()->init(false);
gGLActive = FALSE;
+ if (gSavedSettings.getBOOL("QAMode") && gSavedSettings.getS32("QAModeEventHostPort") > 0)
+ {
+ loadEventHostModule(gSavedSettings.getS32("QAModeEventHostPort"));
+ }
+
return true;
}
@@ -1186,6 +1214,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
@@ -1315,7 +1358,11 @@ bool LLAppViewer::cleanup()
// Destroy the UI
if( gViewerWindow)
gViewerWindow->shutdownViews();
-
+
+ // Cleanup Inventory after the UI since it will delete any remaining observers
+ // (Deleted observers should have already removed themselves)
+ gInventory.cleanupInventory();
+
// 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();
@@ -1463,6 +1510,9 @@ bool LLAppViewer::cleanup()
sImageDecodeThread = NULL;
LLLocationHistory::getInstance()->save();
+
+ LLAvatarIconIDCache::getInstance()->save();
+
delete mFastTimerLogThread;
mFastTimerLogThread = NULL;
@@ -1490,7 +1540,6 @@ bool LLAppViewer::cleanup()
//Note:
//LLViewerMedia::cleanupClass() has to be put before gTextureList.shutdown()
//because some new image might be generated during cleaning up media. --bao
- LLViewerMediaFocus::cleanupClass();
LLViewerMedia::cleanupClass();
LLViewerParcelMedia::cleanupClass();
gTextureList.shutdown(); // shutdown again in case a callback added something
@@ -1628,7 +1677,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");
@@ -1802,8 +1851,18 @@ bool LLAppViewer::initConfiguration()
gSavedSettings.setString("VersionChannelName", LL_CHANNEL);
#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
@@ -2353,7 +2412,6 @@ void LLAppViewer::cleanupSavedSettings()
gSavedSettings.setBOOL("DebugWindowProc", gDebugWindowProc);
- gSavedSettings.setBOOL("AllowTapTapHoldRun", gAllowTapTapHoldRun);
gSavedSettings.setBOOL("ShowObjectUpdates", gShowObjectUpdates);
if (!gNoRender)
@@ -3676,6 +3734,17 @@ void LLAppViewer::idleShutdown()
{
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)
@@ -3970,7 +4039,7 @@ void LLAppViewer::forceErrorBadMemoryAccess()
return;
}
-void LLAppViewer::forceErrorInifiniteLoop()
+void LLAppViewer::forceErrorInfiniteLoop()
{
while(true)
{
@@ -4091,3 +4160,198 @@ void LLAppViewer::handleLoginComplete()
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 == "")
+ {
+ llwarns << "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)
+ {
+ llwarns << "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 646b677264..73256a8fe6 100644
--- a/indra/newview/llappviewer.h
+++ b/indra/newview/llappviewer.h
@@ -47,6 +47,8 @@ class LLVFS;
class LLWatchdogTimeout;
class LLWorkerThread;
+struct apr_dso_handle_t;
+
class LLAppViewer : public LLApp
{
@@ -124,7 +126,7 @@ public:
virtual void forceErrorLLError();
virtual void forceErrorBreakpoint();
virtual void forceErrorBadMemoryAccess();
- virtual void forceErrorInifiniteLoop();
+ virtual void forceErrorInfiniteLoop();
virtual void forceErrorSoftwareException();
virtual void forceErrorDriverCrash();
@@ -210,6 +212,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;
@@ -255,6 +259,8 @@ private:
LLAllocator mAlloc;
+ std::set<struct apr_dso_handle_t*> mPlugins;
+
public:
//some information for updater
typedef struct
@@ -263,6 +269,8 @@ public:
std::ostringstream mParams;
}LLUpdaterInfo ;
static LLUpdaterInfo *sUpdaterInfo ;
+
+ void launchUpdater();
};
// consts from viewer.h
@@ -274,14 +282,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,
@@ -299,10 +301,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
diff --git a/indra/newview/llappviewerlinux.cpp b/indra/newview/llappviewerlinux.cpp
index ed291c16a8..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;
}
@@ -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..3259309eee
--- /dev/null
+++ b/indra/newview/llappviewerlistener.cpp
@@ -0,0 +1,40 @@
+/**
+ * @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 std::string& pumpname,
+ const LLAppViewerGetter& getter):
+ LLDispatchListener(pumpname, "op"),
+ mAppViewerGetter(getter)
+{
+ // add() every method we want to be able to invoke via this event API.
+ add("requestQuit", &LLAppViewerListener::requestQuit);
+ add("forceQuit", &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..73227cb95a
--- /dev/null
+++ b/indra/newview/llappviewerlistener.h
@@ -0,0 +1,37 @@
+/**
+ * @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 "lleventdispatcher.h"
+#include <boost/function.hpp>
+
+class LLAppViewer;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLAppViewer request events.
+class LLAppViewerListener: public LLDispatchListener
+{
+public:
+ typedef boost::function<LLAppViewer*(void)> LLAppViewerGetter;
+ /// Specify the pump name on which to listen, and bind the LLAppViewer
+ /// instance to use (e.g. LLAppViewer::instance()).
+ LLAppViewerListener(const std::string& pumpname, 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 2b3939d92f..1282e437f2 100644
--- a/indra/newview/llappviewermacosx.cpp
+++ b/indra/newview/llappviewermacosx.cpp
@@ -159,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())
@@ -180,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
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 827ae5855b..d4df6dfbe7 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -41,6 +41,7 @@
#include "llfilepicker.h"
#include "llnotify.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llfloaterinventory.h"
#include "llpermissionsflags.h"
#include "llpreviewnotecard.h"
@@ -333,7 +334,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);
@@ -539,7 +540,7 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
gVFS->removeFile(content["new_asset"].asUUID(),
LLAssetType::AT_NOTECARD);
}
-
+ nc->setAssetId(content["new_asset"].asUUID());
nc->refreshFromInventory();
}
break;
diff --git a/indra/newview/llavataractions.cpp b/indra/newview/llavataractions.cpp
index 2b5e2369bb..67ffe54b7e 100644
--- a/indra/newview/llavataractions.cpp
+++ b/indra/newview/llavataractions.cpp
@@ -57,6 +57,7 @@
#include "llviewerobjectlist.h"
#include "llviewermessage.h" // for handle_lure
#include "llviewerregion.h"
+#include "llimfloater.h"
// static
@@ -176,7 +177,8 @@ void LLAvatarActions::startIM(const LLUUID& id)
std::string name;
gCacheName->getFullName(id, name);
- gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ LLUUID session_id = gIMMgr->addSession(name, IM_NOTHING_SPECIAL, id);
+ LLIMFloater::show(session_id);
make_ui_sound("UISndStartIM");
}
@@ -255,6 +257,7 @@ void LLAvatarActions::inviteToGroup(const LLUUID& id)
LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(id));
if (widget)
{
+ widget->removeNoneOption();
widget->center();
widget->setPowersMask(GP_MEMBER_INVITE);
widget->setSelectGroupCallback(boost::bind(callback_invite_to_group, _1, id));
@@ -342,7 +345,7 @@ bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& re
// 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);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
std::string message = calling_card_folder_id.asString();
requestFriendship(notification["payload"]["id"].asUUID(),
notification["payload"]["name"].asString(),
@@ -354,7 +357,7 @@ bool LLAvatarActions::callbackAddFriend(const LLSD& notification, const LLSD& re
// static
void LLAvatarActions::requestFriendship(const LLUUID& target_id, const std::string& target_name, const std::string& message)
{
- LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+ const LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
send_improved_im(target_id,
target_name,
message,
diff --git a/indra/newview/llavatariconctrl.cpp b/indra/newview/llavatariconctrl.cpp
index 1d5fa9ffa7..b56e8d1ec2 100644
--- a/indra/newview/llavatariconctrl.cpp
+++ b/indra/newview/llavatariconctrl.cpp
@@ -50,7 +50,94 @@
static LLDefaultChildRegistry::Register<LLAvatarIconCtrl> r("avatar_icon");
-LLAvatarIconCtrl::avatar_image_map_t LLAvatarIconCtrl::sImagesCache;
+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_PER_SL_ACCOUNT, 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_PER_SL_ACCOUNT, 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()
@@ -65,7 +152,11 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
: LLIconCtrl(p),
mDrawTooltip(p.draw_tooltip)
{
+ 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);
@@ -94,16 +185,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
rect.setOriginAndSize(left, bottom, llavatariconctrl_symbol_size, llavatariconctrl_symbol_size);
- LLIconCtrl::Params icparams;
- icparams.name ("Status Symbol");
- icparams.follows.flags (FOLLOWS_RIGHT | FOLLOWS_BOTTOM);
- icparams.rect (rect);
- mStatusSymbol = LLUICtrlFactory::create<LLIconCtrl> (icparams);
- mStatusSymbol->setValue("circle.tga");
- mStatusSymbol->setColor(LLColor4::grey);
-
- addChild(mStatusSymbol);
-
if (p.avatar_id.isProvided())
{
LLSD value(p.avatar_id);
@@ -114,7 +195,6 @@ LLAvatarIconCtrl::LLAvatarIconCtrl(const LLAvatarIconCtrl::Params& p)
LLIconCtrl::setValue("default_profile_picture.j2c");
}
-
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
registrar.add("AvatarIcon.Action", boost::bind(&LLAvatarIconCtrl::onAvatarIconContextMenuItemClicked, this, _2));
@@ -152,27 +232,19 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
mAvatarId = value.asUUID();
// *BUG: This will return stale icons if a user changes their
- // profile picture. Also, the online/offline tooltips will be
- // out of date. However, otherwise we send too many upstream
+ // profile picture. However, otherwise we send too many upstream
// AvatarPropertiesRequest messages.
- //
- // *TODO: Implement a timeout on the icon cache, perhaps a day?,
- // and make the cache update if a user views the full-profile for
- // an avatar.
+
+ // to get fresh avatar icon use
+ // LLAvatarIconIDCache::getInstance()->remove(avatar_id);
// Check if cache already contains image_id for that avatar
- avatar_image_map_t::iterator it = sImagesCache.find(mAvatarId);
- if (it != sImagesCache.end())
+ if (!updateFromCache())
{
- updateFromCache(it->second);
- }
- else
- {
- app->addObserver(value.asUUID(), this);
- app->sendAvatarPropertiesRequest(value.asUUID());
+ app->addObserver(mAvatarId, this);
+ app->sendAvatarPropertiesRequest(mAvatarId);
}
}
-
}
else
{
@@ -182,48 +254,25 @@ void LLAvatarIconCtrl::setValue(const LLSD& value)
gCacheName->get(mAvatarId, FALSE, boost::bind(&LLAvatarIconCtrl::nameUpdatedCallback, this, _1, _2, _3, _4));
}
-void LLAvatarIconCtrl::updateFromCache(LLAvatarIconCtrl::LLImagesCacheItem data)
+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 (data.image_id.notNull())
+ if (icon_id.notNull())
{
- LLIconCtrl::setValue(data.image_id);
+ LLIconCtrl::setValue(icon_id);
}
else
{
LLIconCtrl::setValue("default_profile_picture.j2c");
}
- // Can only see online status of friends
- if (LLAvatarTracker::instance().isBuddy(mAvatarId))
- {
- if (LLAvatarTracker::instance().isBuddyOnline(mAvatarId))
- {
- // Update color of status symbol and tool tip
- mStatusSymbol->setColor(LLColor4::green);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"Online");
- }
- }
- else
- {
- mStatusSymbol->setColor(LLColor4::grey);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"Offline");
- }
- }
- }
- else
- {
- // Not a buddy, no information
- mStatusSymbol->setColor(LLColor4::grey);
- if (mDrawTooltip)
- {
- setToolTip((LLStringExplicit)"");
- }
- }
+ return true;
}
//virtual
@@ -239,10 +288,8 @@ void LLAvatarIconCtrl::processProperties(void* data, EAvatarProcessorType type)
return;
}
- LLAvatarIconCtrl::LLImagesCacheItem data(avatar_data->image_id, avatar_data->flags);
-
- updateFromCache(data);
- sImagesCache.insert(std::pair<LLUUID, LLAvatarIconCtrl::LLImagesCacheItem>(mAvatarId, data));
+ LLAvatarIconIDCache::getInstance()->add(mAvatarId,avatar_data->image_id);
+ updateFromCache();
}
}
}
@@ -283,6 +330,11 @@ void LLAvatarIconCtrl::nameUpdatedCallback(
{
mFirstName = first;
mLastName = last;
+
+ if (mDrawTooltip)
+ {
+ setToolTip(mFirstName + " " + mLastName);
+ }
}
}
diff --git a/indra/newview/llavatariconctrl.h b/indra/newview/llavatariconctrl.h
index 49e304a521..65b5c86ed5 100644
--- a/indra/newview/llavatariconctrl.h
+++ b/indra/newview/llavatariconctrl.h
@@ -37,6 +37,35 @@
#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
{
@@ -74,27 +103,17 @@ public:
const std::string& getFirstName() const { return mFirstName; }
const std::string& getLastName() const { return mLastName; }
+ void setDrawTooltip(bool value) { mDrawTooltip = value;}
+
protected:
- LLIconCtrl* mStatusSymbol;
LLUUID mAvatarId;
std::string mFirstName;
std::string mLastName;
LLHandle<LLView> mPopupMenuHandle;
bool mDrawTooltip;
- struct LLImagesCacheItem
- {
- LLUUID image_id;
- U32 flags;
-
- LLImagesCacheItem(LLUUID image_id_, U32 flags_) : image_id(image_id_), flags(flags_) {}
- };
-
- typedef std::map<LLUUID, LLAvatarIconCtrl::LLImagesCacheItem> avatar_image_map_t;
-
- static avatar_image_map_t sImagesCache;
- void updateFromCache(LLAvatarIconCtrl::LLImagesCacheItem data);
+ bool updateFromCache();
};
#endif // LL_LLAVATARICONCTRL_H
diff --git a/indra/newview/llavatarlist.cpp b/indra/newview/llavatarlist.cpp
index 36f9780ad0..bb03f47f46 100644
--- a/indra/newview/llavatarlist.cpp
+++ b/indra/newview/llavatarlist.cpp
@@ -37,14 +37,48 @@
// 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;
+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)->setSpeakingIndicatorVisible(mShowSpeakingIndicator);
+ }
+}
+
static bool findInsensitive(std::string haystack, const std::string& needle_upper)
{
LLStringUtil::toUpper(haystack);
@@ -57,33 +91,66 @@ static const LLAvatarItemNameComparator NAME_COMPARATOR;
static const LLFlatListView::ItemReverseComparator REVERSE_NAME_COMPARATOR(NAME_COMPARATOR);
LLAvatarList::Params::Params()
-:
-volume_column_width("volume_column_width", 0)
-, online_go_first("online_go_first", true)
+: 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)
-, mOnlineGoFirst(p.online_go_first)
+, 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();
- LLFlatListView::draw();
+ if (mShowLastInteractionTime && mLITUpdateTimer->hasExpired())
+ {
+ updateLastInteractionTimes();
+ mLITUpdateTimer->setTimerExpirySec(LIT_UPDATE_PERIOD); // restart the timer
+ }
}
void LLAvatarList::setNameFilter(const std::string& filter)
@@ -188,27 +255,80 @@ void LLAvatarList::refresh()
bool dirty = add_limit_exceeded || (have_filter && !have_names);
setDirty(dirty);
+ // Refreshed all items, lets send refresh_complete signal.
+ if(!dirty)
+ {
+ 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();
-void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos)
+ 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);
+}
+
+void LLAvatarList::addNewItem(const LLUUID& id, const std::string& name, BOOL is_online, EAddPosition pos)
{
LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(false);
item->showInfoBtn(true);
item->showSpeakingIndicator(true);
item->setName(name);
- item->setAvatarId(id);
+ item->setAvatarId(id, mIgnoreOnlineStatus);
+ item->setOnline(mIgnoreOnlineStatus ? true : is_online);
+ item->showLastInteractionTime(mShowLastInteractionTime);
item->setContextMenu(mContextMenu);
item->childSetVisible("info_btn", false);
+ item->setAvatarIconVisible(mShowIcons);
+ item->setShowInfoBtn(mShowInfoBtn);
+ item->setShowProfileBtn(mShowProfileBtn);
+ item->setSpeakingIndicatorVisible(mShowSpeakingIndicator);
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,
@@ -243,6 +363,54 @@ void LLAvatarList::computeDifference(
vadded.erase(it, vadded.end());
}
+static std::string format_secs(S32 secs)
+{
+ // *TODO: reinventing the wheel?
+ // *TODO: i18n
+ static const int LL_AL_MIN = 60;
+ static const int LL_AL_HOUR = LL_AL_MIN * 60;
+ static const int LL_AL_DAY = LL_AL_HOUR * 24;
+ static const int LL_AL_WEEK = LL_AL_DAY * 7;
+ static const int LL_AL_MONTH = LL_AL_DAY * 31;
+ static const int LL_AL_YEAR = LL_AL_DAY * 365;
+
+ std::string s;
+
+ if (secs >= LL_AL_YEAR)
+ s = llformat("%dy", secs / LL_AL_YEAR);
+ else if (secs >= LL_AL_MONTH)
+ s = llformat("%dmon", secs / LL_AL_MONTH);
+ else if (secs >= LL_AL_WEEK)
+ s = llformat("%dw", secs / LL_AL_WEEK);
+ else if (secs >= LL_AL_DAY)
+ s = llformat("%dd", secs / LL_AL_DAY);
+ else if (secs >= LL_AL_HOUR)
+ s = llformat("%dh", secs / LL_AL_HOUR);
+ else if (secs >= LL_AL_MIN)
+ s = llformat("%dm", secs / LL_AL_MIN);
+ else
+ s = llformat("%ds", secs);
+
+ return s;
+}
+
+// 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(format_secs(secs_since));
+ }
+}
+
bool LLAvatarItemComparator::compare(const LLPanel* item1, const LLPanel* item2) const
{
const LLAvatarListItem* avatar_item1 = dynamic_cast<const LLAvatarListItem*>(item1);
diff --git a/indra/newview/llavatarlist.h b/indra/newview/llavatarlist.h
index ec801645fe..490f93e501 100644
--- a/indra/newview/llavatarlist.h
+++ b/indra/newview/llavatarlist.h
@@ -37,6 +37,8 @@
#include "llavatarlistitem.h"
+class LLTimer;
+
/**
* Generic list of avatars.
*
@@ -55,13 +57,16 @@ public:
struct Params : public LLInitParam::Block<Params, LLFlatListView::Params>
{
- Optional<S32> volume_column_width;
- Optional<bool> online_go_first;
+ 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 ~LLAvatarList();
virtual void draw(); // from LLView
@@ -71,26 +76,47 @@ public:
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);
protected:
void refresh();
- void addNewItem(const LLUUID& id, const std::string& name, BOOL is_bold, EAddPosition pos = ADD_BOTTOM);
+ 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();
private:
- bool mOnlineGoFirst;
+ 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;
};
/** Abstract comparator for avatar items */
diff --git a/indra/newview/llavatarlistitem.cpp b/indra/newview/llavatarlistitem.cpp
index 51545bcc07..7df278d887 100644
--- a/indra/newview/llavatarlistitem.cpp
+++ b/indra/newview/llavatarlistitem.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
+#include "llavataractions.h"
#include "llavatarlistitem.h"
#include "llfloaterreg.h"
@@ -41,32 +42,51 @@
#include "llavatariconctrl.h"
#include "llbutton.h"
-
LLAvatarListItem::LLAvatarListItem()
: LLPanel(),
mAvatarIcon(NULL),
mAvatarName(NULL),
- mStatus(NULL),
+ mLastInteractionTime(NULL),
mSpeakingIndicator(NULL),
mInfoBtn(NULL),
+ mProfileBtn(NULL),
mContextMenu(NULL),
- mAvatarId(LLUUID::null)
+ mOnlineStatus(E_UNKNOWN),
+ mShowInfoBtn(true),
+ mShowProfileBtn(true)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_avatar_list_item.xml");
+ // Remember avatar icon width including its padding from the name text box,
+ // so that we can hide and show the icon again later.
+
+ mIconWidth = mAvatarName->getRect().mLeft - mAvatarIcon->getRect().mLeft;
+ mInfoBtnWidth = mInfoBtn->getRect().mRight - mSpeakingIndicator->getRect().mRight;
+ mProfileBtnWidth = mProfileBtn->getRect().mRight - mInfoBtn->getRect().mRight;
+ mSpeakingIndicatorWidth = mSpeakingIndicator->getRect().mRight - mAvatarName->getRect().mRight;
+}
+
+LLAvatarListItem::~LLAvatarListItem()
+{
+ if (mAvatarId.notNull())
+ LLAvatarTracker::instance().removeParticularFriendObserver(mAvatarId, this);
}
BOOL LLAvatarListItem::postBuild()
{
mAvatarIcon = getChild<LLAvatarIconCtrl>("avatar_icon");
mAvatarName = getChild<LLTextBox>("avatar_name");
- mStatus = getChild<LLTextBox>("avatar_status");
-
+ 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(!p.buttons.profile)
{
@@ -78,12 +98,6 @@ BOOL LLAvatarListItem::postBuild()
rect.setLeftTopAndSize(mName->getRect().mLeft, mName->getRect().mTop, mName->getRect().getWidth() + 30, mName->getRect().getHeight());
mName->setRect(rect);
- if(mStatus)
- {
- rect.setLeftTopAndSize(mStatus->getRect().mLeft + 30, mStatus->getRect().mTop, mStatus->getRect().getWidth(), mStatus->getRect().getHeight());
- mStatus->setRect(rect);
- }
-
if(mLocator)
{
rect.setLeftTopAndSize(mLocator->getRect().mLeft + 30, mLocator->getRect().mTop, mLocator->getRect().getWidth(), mLocator->getRect().getHeight());
@@ -103,7 +117,8 @@ BOOL LLAvatarListItem::postBuild()
void LLAvatarListItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", true);
- mInfoBtn->setVisible(true);
+ mInfoBtn->setVisible(mShowInfoBtn);
+ mProfileBtn->setVisible(mShowProfileBtn);
LLPanel::onMouseEnter(x, y, mask);
}
@@ -112,22 +127,39 @@ void LLAvatarListItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", false);
mInfoBtn->setVisible(false);
+ mProfileBtn->setVisible(false);
LLPanel::onMouseLeave(x, y, mask);
}
-// virtual
-BOOL LLAvatarListItem::handleRightMouseDown(S32 x, S32 y, MASK mask)
+// virtual, called by LLAvatarTracker
+void LLAvatarListItem::changed(U32 mask)
{
- if (mContextMenu)
- mContextMenu->show(this, const_cast<const LLUUID&>(mAvatarId), x, y);
-
- return LLPanel::handleRightMouseDown(x, y, mask);
+ // no need to check mAvatarId for null in this case
+ setOnline(LLAvatarTracker::instance().isBuddyOnline(mAvatarId));
}
-void LLAvatarListItem::setStatus(const std::string& status)
+void LLAvatarListItem::setOnline(bool online)
{
- mStatus->setValue(status);
+ // *FIX: setName() overrides font style set by setOnline(). Not an issue ATM.
+ // *TODO: Make the colors configurable via XUI.
+
+ if (mOnlineStatus != E_UNKNOWN && (bool) mOnlineStatus == online)
+ return;
+
+ mOnlineStatus = (EOnlineStatus) online;
+
+ // Change avatar name font style depending on the new online status.
+ LLStyle::Params style_params;
+ style_params.color = online ? LLColor4::white : LLColor4::grey;
+
+ // Rebuild the text to change its style.
+ std::string text = mAvatarName->getText();
+ mAvatarName->setText(LLStringUtil::null);
+ mAvatarName->appendText(text, false, style_params);
+
+ // Make the icon fade if the avatar goes offline.
+ mAvatarIcon->setColor(online ? LLColor4::white : LLColor4::smoke);
}
void LLAvatarListItem::setName(const std::string& name)
@@ -136,16 +168,96 @@ void LLAvatarListItem::setName(const std::string& name)
mAvatarName->setToolTip(name);
}
-void LLAvatarListItem::setAvatarId(const LLUUID& id)
+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;
+
+ LLRect name_rect = mAvatarName->getRect();
+ LLRect time_rect = mLastInteractionTime->getRect();
+
+ mLastInteractionTime->setVisible(false);
+ name_rect.mRight += (time_rect.mRight - name_rect.mRight);
+ mAvatarName->setRect(name_rect);
+}
+
+void LLAvatarListItem::setLastInteractionTime(const std::string& val)
+{
+ mLastInteractionTime->setValue(val);
+}
+
+void LLAvatarListItem::setShowInfoBtn(bool show)
+{
+ // Already done? Then do nothing.
+ if(mShowInfoBtn == show)
+ return;
+ mShowInfoBtn = show;
+ S32 width_delta = show ? - mInfoBtnWidth : mInfoBtnWidth;
+
+ //Translating speaking indicator
+ mSpeakingIndicator->translate(width_delta, 0);
+ //Reshaping avatar name
+ mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
+void LLAvatarListItem::setShowProfileBtn(bool show)
+{
+ // Already done? Then do nothing.
+ if(mShowProfileBtn == show)
+ return;
+ mShowProfileBtn = show;
+ S32 width_delta = show ? - mProfileBtnWidth : mProfileBtnWidth;
+
+ //Translating speaking indicator
+ mSpeakingIndicator->translate(width_delta, 0);
+ //Reshaping avatar name
+ mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
+void LLAvatarListItem::setSpeakingIndicatorVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mSpeakingIndicator->getVisible() == (BOOL)visible)
+ return;
+ mSpeakingIndicator->setVisible(visible);
+ S32 width_delta = visible ? - mSpeakingIndicatorWidth : mSpeakingIndicatorWidth;
+
+ //Reshaping avatar name
+ mAvatarName->reshape(mAvatarName->getRect().getWidth() + width_delta, mAvatarName->getRect().getHeight());
+}
+
+void LLAvatarListItem::setAvatarIconVisible(bool visible)
+{
+ // Already done? Then do nothing.
+ if (mAvatarIcon->getVisible() == (BOOL)visible)
+ return;
+
+ // Show/hide avatar icon.
+ mAvatarIcon->setVisible(visible);
+
+ // Move the avatar name horizontally by icon size + its distance from the avatar name.
+ LLRect name_rect = mAvatarName->getRect();
+ name_rect.mLeft += visible ? mIconWidth : -mIconWidth;
+ mAvatarName->setRect(name_rect);
+}
+
void LLAvatarListItem::onInfoBtnClick()
{
LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarId));
@@ -171,19 +283,9 @@ void LLAvatarListItem::onInfoBtnClick()
*/
}
-void LLAvatarListItem::showStatus(bool show_status)
+void LLAvatarListItem::onProfileBtnClick()
{
- // *HACK: dirty hack until we can determine correct avatar status (EXT-1076).
-
- if (show_status)
- return;
-
- LLRect name_rect = mAvatarName->getRect();
- LLRect status_rect = mStatus->getRect();
-
- mStatus->setVisible(show_status);
- name_rect.mRight += (status_rect.mRight - name_rect.mRight);
- mAvatarName->setRect(name_rect);
+ LLAvatarActions::showProfile(mAvatarId);
}
void LLAvatarListItem::setValue( const LLSD& value )
diff --git a/indra/newview/llavatarlistitem.h b/indra/newview/llavatarlistitem.h
index bde9250e4a..d379797a46 100644
--- a/indra/newview/llavatarlistitem.h
+++ b/indra/newview/llavatarlistitem.h
@@ -38,53 +38,79 @@
#include "llbutton.h"
#include "lltextbox.h"
+#include "llcallingcard.h" // for LLFriendObserver
+
class LLAvatarIconCtrl;
-class LLAvatarListItem : public LLPanel
+class LLAvatarListItem : public LLPanel, public LLFriendObserver
{
public:
class ContextMenu
{
public:
- virtual void show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y) = 0;
+ virtual void show(LLView* spawning_view, const std::vector<LLUUID>& selected_uuids, S32 x, S32 y) = 0;
};
LLAvatarListItem();
- virtual ~LLAvatarListItem() {};
+ virtual ~LLAvatarListItem();
virtual BOOL postBuild();
virtual void onMouseLeave(S32 x, S32 y, MASK mask);
virtual void onMouseEnter(S32 x, S32 y, MASK mask);
- virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
virtual void setValue(const LLSD& value);
+ virtual void changed(U32 mask); // from LLFriendObserver
- void setStatus(const std::string& status);
+ void setOnline(bool online);
void setName(const std::string& name);
- void setAvatarId(const LLUUID& id);
+ void setAvatarId(const LLUUID& id, bool ignore_status_changes = false);
+ void setLastInteractionTime(const std::string& val);
+ //Show/hide profile/info btn, translating speaker indicator and avatar name coordinates accordingly
+ void setShowProfileBtn(bool show);
+ void setShowInfoBtn(bool show);
+ void setSpeakingIndicatorVisible(bool visible);
+ void setAvatarIconVisible(bool visible);
const LLUUID& getAvatarId() const;
const std::string getAvatarName() const;
void onInfoBtnClick();
+ void onProfileBtnClick();
void showSpeakingIndicator(bool show) { mSpeakingIndicator->setVisible(show); }
void showInfoBtn(bool show_info_btn) {mInfoBtn->setVisible(show_info_btn); }
- void showStatus(bool show_status);
+ void showLastInteractionTime(bool show);
void setContextMenu(ContextMenu* menu) { mContextMenu = menu; }
private:
+
+ typedef enum e_online_status {
+ E_OFFLINE,
+ E_ONLINE,
+ E_UNKNOWN,
+ } EOnlineStatus;
+
void onNameCache(const std::string& first_name, const std::string& last_name);
- LLAvatarIconCtrl*mAvatarIcon;
+ LLAvatarIconCtrl* mAvatarIcon;
LLTextBox* mAvatarName;
- LLTextBox* mStatus;
+ LLTextBox* mLastInteractionTime;
LLOutputMonitorCtrl* mSpeakingIndicator;
LLButton* mInfoBtn;
+ LLButton* mProfileBtn;
ContextMenu* mContextMenu;
LLUUID mAvatarId;
+ 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;
+ S32 mIconWidth; // icon width + padding
+ S32 mInfoBtnWidth; //info btn width + padding
+ S32 mProfileBtnWidth; //profile btn width + padding
+ S32 mSpeakingIndicatorWidth; //speaking indicator width + padding
};
#endif //LL_LLAVATARLISTITEM_H
diff --git a/indra/newview/llavatarpropertiesprocessor.cpp b/indra/newview/llavatarpropertiesprocessor.cpp
index f58c85d8c5..73e24ca8e7 100644
--- a/indra/newview/llavatarpropertiesprocessor.cpp
+++ b/indra/newview/llavatarpropertiesprocessor.cpp
@@ -36,6 +36,7 @@
// Viewer includes
#include "llagent.h"
+#include "llagentpicksinfo.h"
#include "llviewergenericmessage.h"
// Linden library includes
@@ -150,6 +151,13 @@ void LLAvatarPropertiesProcessor::sendAvatarGroupsRequest(const LLUUID& avatar_i
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::sendAvatarPropertiesUpdate(const LLAvatarData* avatar_props)
{
llinfos << "Sending avatarinfo update" << llendl;
@@ -438,6 +446,9 @@ void LLAvatarPropertiesProcessor::sendPickDelete( const LLUUID& pick_id )
msg->nextBlock(_PREHASH_Data);
msg->addUUID(_PREHASH_PickID, pick_id);
gAgent.sendReliableMessage();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
+ LLAgentPicksInfo::getInstance()->decrementNumberOfPicks();
}
void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
@@ -470,6 +481,8 @@ void LLAvatarPropertiesProcessor::sendPickInfoUpdate(const LLPickData* new_pick)
msg->addBOOL(_PREHASH_Enabled, new_pick->enabled);
gAgent.sendReliableMessage();
+
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
}
void LLAvatarPropertiesProcessor::sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id)
diff --git a/indra/newview/llavatarpropertiesprocessor.h b/indra/newview/llavatarpropertiesprocessor.h
index ea80c3d4f8..e6563024b2 100644
--- a/indra/newview/llavatarpropertiesprocessor.h
+++ b/indra/newview/llavatarpropertiesprocessor.h
@@ -52,7 +52,8 @@ enum EAvatarProcessorType
APT_NOTES,
APT_GROUPS,
APT_PICKS,
- APT_PICK_INFO
+ APT_PICK_INFO,
+ APT_TEXTURES
};
struct LLAvatarData
@@ -160,6 +161,7 @@ public:
void sendAvatarPicksRequest(const LLUUID& avatar_id);
void sendAvatarNotesRequest(const LLUUID& avatar_id);
void sendAvatarGroupsRequest(const LLUUID& avatar_id);
+ void sendAvatarTexturesRequest(const LLUUID& avatar_id);
// Duplicate pick info requests are not suppressed.
void sendPickInfoRequest(const LLUUID& creator_id, const LLUUID& pick_id);
diff --git a/indra/newview/llbottomtray.cpp b/indra/newview/llbottomtray.cpp
index 0ff8ca7d26..a17ba79078 100644
--- a/indra/newview/llbottomtray.cpp
+++ b/indra/newview/llbottomtray.cpp
@@ -47,7 +47,7 @@
LLBottomTray::LLBottomTray(const LLSD&)
: mChicletPanel(NULL),
mSysWell(NULL),
- mTalkBtn(NULL),
+ mSpeakBtn(NULL),
mNearbyChatBar(NULL),
mToolbarStack(NULL)
@@ -65,7 +65,7 @@ LLBottomTray::LLBottomTray(const LLSD&)
mChicletPanel->setChicletClickedCallback(boost::bind(&LLBottomTray::onChicletClick,this,_1));
- LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView",&LLFloaterCameraPresets::onClickCameraPresets);
+ LLUICtrl::CommitCallbackRegistry::defaultRegistrar().add("CameraPresets.ChangeView", boost::bind(&LLFloaterCamera::onClickCameraPresets, _2));
LLIMMgr::getInstance()->addSessionObserver(this);
//this is to fix a crash that occurs because LLBottomTray is a singleton
@@ -77,22 +77,6 @@ LLBottomTray::LLBottomTray(const LLSD&)
setFocusRoot(TRUE);
}
-BOOL LLBottomTray::postBuild()
-{
- 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");
- mGestureCombo = getChild<LLComboBox>("Gesture");
- mCamPanel = getChild<LLPanel>("cam_panel");
- mSnapshotPanel = getChild<LLPanel>("snapshot_panel");
- setRightMouseDownCallback(boost::bind(&LLBottomTray::showBottomTrayContextMenu,this, _2, _3,_4));
-
- return TRUE;
-}
-
LLBottomTray::~LLBottomTray()
{
if (!LLSingleton<LLIMMgr>::destroyed())
@@ -134,8 +118,9 @@ LLIMChiclet* LLBottomTray::createIMChiclet(const LLUUID& session_id)
case LLIMChiclet::TYPE_IM:
return getChicletPanel()->createChiclet<LLIMP2PChiclet>(session_id);
case LLIMChiclet::TYPE_GROUP:
- case LLIMChiclet::TYPE_AD_HOC:
return getChicletPanel()->createChiclet<LLIMGroupChiclet>(session_id);
+ case LLIMChiclet::TYPE_AD_HOC:
+ return getChicletPanel()->createChiclet<LLAdHocChiclet>(session_id);
case LLIMChiclet::TYPE_UNKNOWN:
break;
}
@@ -185,6 +170,18 @@ void LLBottomTray::sessionRemoved(const LLUUID& 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);
+ }
+}
+
//virtual
void LLBottomTray::onFocusLost()
{
@@ -238,24 +235,7 @@ void LLBottomTray::showBottomTrayContextMenu(S32 x, S32 y, MASK mask)
void LLBottomTray::showGestureButton(BOOL visible)
{
- if (visible != mGestureCombo->getVisible())
- {
- LLRect r = mNearbyChatBar->getRect();
-
- mGestureCombo->setVisible(visible);
-
- if (!visible)
- {
- LLFloaterReg::hideFloaterInstance("gestures");
- r.mRight -= mGestureCombo->getRect().getWidth();
- }
- else
- {
- r.mRight += mGestureCombo->getRect().getWidth();
- }
-
- mNearbyChatBar->setRect(r);
- }
+ mGesturePanel->setVisible(visible);
}
void LLBottomTray::showMoveButton(BOOL visible)
@@ -272,3 +252,191 @@ void LLBottomTray::showSnapshotButton(BOOL visible)
{
mSnapshotPanel->setVisible(visible);
}
+
+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";
+}
+
+BOOL LLBottomTray::postBuild()
+{
+ 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));
+
+ if (mChicletPanel && mToolbarStack && mNearbyChatBar)
+ {
+ verifyChildControlsSizes();
+ }
+
+ return TRUE;
+}
+
+void LLBottomTray::verifyChildControlsSizes()
+{
+ LLRect rect = mChicletPanel->getRect();
+ if (rect.getWidth() < mChicletPanel->getMinWidth())
+ {
+ mChicletPanel->reshape(mChicletPanel->getMinWidth(), rect.getHeight());
+ }
+
+ rect = mNearbyChatBar->getRect();
+ if (rect.getWidth() < mNearbyChatBar->getMinWidth())
+ {
+ mNearbyChatBar->reshape(mNearbyChatBar->getMinWidth(), rect.getHeight());
+ }
+ else if (rect.getWidth() > mNearbyChatBar->getMaxWidth())
+ {
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, mNearbyChatBar->getMaxWidth(), rect.getHeight());
+ mNearbyChatBar->reshape(mNearbyChatBar->getMaxWidth(), rect.getHeight());
+ mNearbyChatBar->setRect(rect);
+ }
+}
+
+void LLBottomTray::reshape(S32 width, S32 height, BOOL called_from_parent)
+{
+
+ if (mChicletPanel && mToolbarStack && mNearbyChatBar)
+ {
+#ifdef __FEATURE_EXT_991__
+ BOOL shrink = width < getRect().getWidth();
+ const S32 MIN_RENDERED_CHARS = 3;
+#endif
+
+ verifyChildControlsSizes();
+ updateResizeState(width, height);
+
+ switch (mResizeState)
+ {
+ case STATE_CHICLET_PANEL:
+ mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, TRUE);
+
+ mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE);
+ mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE);
+ mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE);
+
+ break;
+ case STATE_CHATBAR_INPUT:
+ mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, TRUE);
+
+ mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE);
+ mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, FALSE);
+ mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, FALSE);
+
+ break;
+
+#ifdef __FEATURE_EXT_991__
+
+ case STATE_BUTTONS:
+ mToolbarStack->updatePanelAutoResize(PANEL_CAMERA_NAME, TRUE);
+ mToolbarStack->updatePanelAutoResize(PANEL_MOVEMENT_NAME, TRUE);
+
+ mToolbarStack->updatePanelAutoResize(PANEL_CHICLET_NAME, FALSE);
+ mToolbarStack->updatePanelAutoResize(PANEL_CHATBAR_NAME, FALSE);
+
+ if (shrink)
+ {
+
+ if (mSnapshotPanel->getVisible())
+ {
+ showSnapshotButton(FALSE);
+ }
+
+ if (mCamPanel->getVisible() && mCamButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS)
+ {
+ showCameraButton(FALSE);
+ }
+
+ if (mMovementPanel->getVisible() && mMovementButton->getLastDrawCharsCount() < MIN_RENDERED_CHARS)
+ {
+ showMoveButton(FALSE);
+ }
+
+ }
+ else
+ {
+ showMoveButton(TRUE);
+ mMovementPanel->draw();
+
+ if (mMovementButton->getLastDrawCharsCount() >= MIN_RENDERED_CHARS)
+ {
+ showMoveButton(TRUE);
+ }
+ else
+ {
+ showMoveButton(FALSE);
+ }
+ }
+ break;
+#endif
+
+ default:
+ break;
+ }
+ }
+
+ LLPanel::reshape(width, height, called_from_parent);
+}
+
+void LLBottomTray::updateResizeState(S32 width, S32 height)
+{
+ mResizeState = STATE_BUTTONS;
+
+ const S32 chiclet_panel_width = mChicletPanel->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();
+
+ // bottom tray is narrowed
+ if (width < getRect().getWidth())
+ {
+ if (chiclet_panel_width > chiclet_panel_min_width)
+ {
+ mResizeState = STATE_CHICLET_PANEL;
+ }
+ else if (chatbar_panel_width > chatbar_panel_min_width)
+ {
+ mResizeState = STATE_CHATBAR_INPUT;
+ }
+ else
+ {
+ mResizeState = STATE_BUTTONS;
+ }
+ }
+ // bottom tray is widen
+ else
+ {
+#ifdef __FEATURE_EXT_991__
+ if (!mMovementPanel->getVisible())
+ {
+ mResizeState = STATE_BUTTONS;
+ }
+ else
+#endif
+ if (chatbar_panel_width < chatbar_panel_max_width)
+ {
+ mResizeState = STATE_CHATBAR_INPUT;
+ }
+ else
+ {
+ mResizeState = STATE_CHICLET_PANEL;
+ }
+ }
+
+
+ // TODO: finish implementation
+}
diff --git a/indra/newview/llbottomtray.h b/indra/newview/llbottomtray.h
index 4724c5ecef..02588a1975 100644
--- a/indra/newview/llbottomtray.h
+++ b/indra/newview/llbottomtray.h
@@ -43,7 +43,7 @@ class LLChicletPanel;
class LLLineEditor;
class LLLayoutStack;
class LLNotificationChiclet;
-class LLTalkButton;
+class LLSpeakButton;
class LLNearbyChatBar;
class LLIMChiclet;
@@ -67,6 +67,9 @@ public:
// 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);
+
+ virtual void reshape(S32 width, S32 height, BOOL called_from_parent);
virtual void onFocusLost();
virtual void setVisible(BOOL visible);
@@ -80,6 +83,18 @@ public:
private:
+ enum EResizeState
+ {
+ STATE_CHICLET_PANEL = 1,
+ STATE_CHATBAR_INPUT,
+ STATE_BUTTONS
+ };
+
+ void updateResizeState(S32 width, S32 height);
+ void verifyChildControlsSizes();
+
+ EResizeState mResizeState;
+
protected:
LLBottomTray(const LLSD& key = LLSD());
@@ -95,14 +110,16 @@ protected:
LLChicletPanel* mChicletPanel;
LLNotificationChiclet* mSysWell;
- LLTalkButton* mTalkBtn;
+ LLSpeakButton* mSpeakBtn;
LLNearbyChatBar* mNearbyChatBar;
LLLayoutStack* mToolbarStack;
LLMenuGL* mBottomTrayContextMenu;
LLPanel* mMovementPanel;
LLPanel* mCamPanel;
LLPanel* mSnapshotPanel;
- LLComboBox* mGestureCombo;
+ LLPanel* mGesturePanel;
+ LLButton* mCamButton;
+ LLButton* mMovementButton;
};
#endif // LL_LLBOTTOMPANEL_H
diff --git a/indra/newview/llcallingcard.cpp b/indra/newview/llcallingcard.cpp
index e3440ee779..e8812d87ee 100644
--- a/indra/newview/llcallingcard.cpp
+++ b/indra/newview/llcallingcard.cpp
@@ -62,7 +62,6 @@
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llimview.h"
-#include "llimpanel.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -260,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()
@@ -333,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
@@ -488,10 +487,52 @@ 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)
@@ -610,8 +651,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg)
}
}
}
- mModifyMask |= LLFriendObserver::POWERS;
+ addChangedMask(LLFriendObserver::POWERS, agent_id);
notifyObservers();
}
@@ -677,13 +718,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online)
// 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,LLUIColorTable::instance().getColor("SystemChatColor"));
- }
+ std::string notify_msg = notification->getMessage();
+ LLIMModel::instance().proccessOnlineOfflineNotification(session_id, notify_msg);
}
mModifyMask |= LLFriendObserver::ONLINE;
diff --git a/indra/newview/llcallingcard.h b/indra/newview/llcallingcard.h
index 228239b5ba..bd58b2fbe6 100644
--- a/indra/newview/llcallingcard.h
+++ b/indra/newview/llcallingcard.h
@@ -150,6 +150,12 @@ 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
*
@@ -199,6 +205,10 @@ protected:
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
index 4134e9e0a4..ed9613c1bc 100644
--- a/indra/newview/llcapabilitylistener.cpp
+++ b/indra/newview/llcapabilitylistener.cpp
@@ -5,7 +5,30 @@
* @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$
*/
@@ -91,6 +114,7 @@ bool LLCapabilityListener::capListener(const LLSD& request)
// 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
diff --git a/indra/newview/llcapabilitylistener.h b/indra/newview/llcapabilitylistener.h
index ce16b7da5d..be51cf1b8c 100644
--- a/indra/newview/llcapabilitylistener.h
+++ b/indra/newview/llcapabilitylistener.h
@@ -5,7 +5,30 @@
* @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$
*/
diff --git a/indra/newview/llcapabilityprovider.h b/indra/newview/llcapabilityprovider.h
index 0ddb2b6cb9..3d07904775 100644
--- a/indra/newview/llcapabilityprovider.h
+++ b/indra/newview/llcapabilityprovider.h
@@ -6,7 +6,30 @@
* 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$
*/
diff --git a/indra/newview/llchannelmanager.cpp b/indra/newview/llchannelmanager.cpp
index c4619dc57a..6427422572 100644
--- a/indra/newview/llchannelmanager.cpp
+++ b/indra/newview/llchannelmanager.cpp
@@ -39,6 +39,9 @@
#include "llimview.h"
#include "llbottomtray.h"
#include "llviewerwindow.h"
+#include "llrootview.h"
+#include "llsyswellwindow.h"
+#include "llfloaterreg.h"
#include <algorithm>
@@ -121,14 +124,16 @@ void LLChannelManager::onLoginCompleted()
return;
}
+ gViewerWindow->getRootView()->addChild(mStartUpChannel);
+
// init channel's position and size
S32 channel_right_bound = gViewerWindow->getWorldViewRect().mRight - gSavedSettings.getS32("NotificationChannelRightMargin");
S32 channel_width = gSavedSettings.getS32("NotifyBoxWidth");
mStartUpChannel->init(channel_right_bound - channel_width, channel_right_bound);
- mStartUpChannel->setShowToasts(true);
+ mStartUpChannel->setMouseDownCallback(boost::bind(&LLSysWellWindow::onStartUpToastClick, LLFloaterReg::getTypedInstance<LLSysWellWindow>("syswell_window"), _2, _3, _4));
mStartUpChannel->setCommitCallback(boost::bind(&LLChannelManager::onStartUpToastClose, this));
- mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("ChannelBottomPanelMargin"), gSavedSettings.getS32("StartUpToastTime"));
+ mStartUpChannel->createStartUpToast(away_notifications, gSavedSettings.getS32("StartUpToastLifeTime"));
}
//--------------------------------------------------------------------------
@@ -139,19 +144,11 @@ void LLChannelManager::onStartUpToastClose()
mStartUpChannel->setVisible(FALSE);
mStartUpChannel->closeStartUpToast();
removeChannelByID(LLUUID(gSavedSettings.getString("StartUpChannelUUID")));
- delete mStartUpChannel;
mStartUpChannel = NULL;
}
// set StartUp Toast Flag to allow all other channels to show incoming toasts
LLScreenChannel::setStartUpToastShown();
-
- // force NEARBY CHAT CHANNEL to repost all toasts if present
- //LLScreenChannelBase* nearby_channel = findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
- //!!!!!!!!!!!!!!
- //FIXME
- //nearby_channel->loadStoredToastsToChannel();
- //nearby_channel->setCanStoreToasts(false);
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp
new file mode 100644
index 0000000000..2ccd6b7d35
--- /dev/null
+++ b/indra/newview/llchathistory.cpp
@@ -0,0 +1,379 @@
+/**
+ * @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 "llchathistory.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lluictrlfactory.h"
+#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
+
+#include "llimview.h"
+#include "llcallingcard.h" //for LLAvatarTracker
+#include "llagentdata.h"
+#include "llavataractions.h"
+#include "lltrans.h"
+#include "llfloaterreg.h"
+#include "llmutelist.h"
+
+static LLDefaultChildRegistry::Register<LLChatHistory> r("chat_history");
+static const std::string MESSAGE_USERNAME_DATE_SEPARATOR(" ----- ");
+
+std::string formatCurrentTime()
+{
+ 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;
+}
+
+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")
+ {
+ }
+ else if (level == "block")
+ {
+ LLMuteList::getInstance()->add(LLMute(getAvatarId(), mFrom, LLMute::OBJECT));
+ }
+ }
+
+ 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();
+
+ setMouseDownCallback(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)
+ {
+ LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("avatar_id", mAvatarID));
+ }
+
+ 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)
+ {
+ 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;
+ }
+
+
+ LLTextBox* userName = getChild<LLTextBox>("user_name");
+
+ if(!chat.mFromName.empty())
+ {
+ userName->setValue(chat.mFromName);
+ mFrom = chat.mFromName;
+ }
+ else
+ {
+ std::string SL = LLTrans::getString("SECOND_LIFE");
+ userName->setValue(SL);
+ }
+
+ LLTextBox* timeBox = getChild<LLTextBox>("time_box");
+ timeBox->setValue(formatCurrentTime());
+
+ LLAvatarIconCtrl* icon = getChild<LLAvatarIconCtrl>("avatar_icon");
+
+ if(mSourceType != CHAT_SOURCE_AGENT)
+ icon->setDrawTooltip(false);
+
+ if(!chat.mFromID.isNull())
+ {
+ icon->setValue(chat.mFromID);
+ }
+
+ }
+
+ 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:
+ 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);
+ }
+ }
+
+
+
+protected:
+ LLHandle<LLView> mPopupMenuHandleAvatar;
+ LLHandle<LLView> mPopupMenuHandleObject;
+
+ LLUUID mAvatarID;
+ EChatSourceType mSourceType;
+ std::string mFirstName;
+ std::string mLastName;
+ std::string mFrom;
+
+};
+
+
+LLChatHistory::LLChatHistory(const LLChatHistory::Params& p)
+: LLTextEditor(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)
+{
+}
+
+LLChatHistory::~LLChatHistory()
+{
+ this->clear();
+}
+
+/*void LLChatHistory::updateTextRect()
+{
+ static LLUICachedControl<S32> texteditor_border ("UITextEditorBorder", 0);
+
+ LLRect old_text_rect = mTextRect;
+ mTextRect = mScroller->getContentWindowRect();
+ mTextRect.stretch(-texteditor_border);
+ mTextRect.mLeft += mLeftTextPad;
+ mTextRect.mRight -= mRightTextPad;
+ if (mTextRect != 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)
+{
+ LLChatHistoryHeader* header = LLChatHistoryHeader::createInstance(mMessageHeaderFilename);
+ header->setup(chat);
+ return header;
+}
+
+void LLChatHistory::appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params)
+{
+ LLView* view = NULL;
+ std::string view_text;
+
+ LLInlineViewSegment::Params p;
+ p.force_newline = true;
+ p.left_pad = mLeftWidgetPad;
+ p.right_pad = mRightWidgetPad;
+
+ if (mLastFromName == chat.mFromName)
+ {
+ view = getSeparator();
+ view_text = "\n";
+ p.top_pad = mTopSeparatorPad;
+ p.bottom_pad = mBottomSeparatorPad;
+ }
+ else
+ {
+ view = getHeader(chat);
+ view_text = chat.mFromName + MESSAGE_USERNAME_DATE_SEPARATOR + formatCurrentTime() + '\n';
+ if (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 = getDocumentView()->getRect();
+ // squeeze down the widget by subtracting padding off left and right
+ target_rect.mLeft += mLeftWidgetPad + mHPad;
+ target_rect.mRight -= mRightWidgetPad;
+ view->reshape(target_rect.getWidth(), view->getRect().getHeight());
+ view->setOrigin(target_rect.mLeft, view->getRect().mBottom);
+
+ appendWidget(p, view_text, false);
+
+ //Append the text message
+ std::string message = chat.mText + '\n';
+ appendText(message, FALSE, style_params);
+
+ mLastFromName = chat.mFromName;
+ blockUndo();
+ setCursorAndScrollToEnd();
+}
diff --git a/indra/newview/llchathistory.h b/indra/newview/llchathistory.h
new file mode 100644
index 0000000000..3789ebff4e
--- /dev/null
+++ b/indra/newview/llchathistory.h
@@ -0,0 +1,132 @@
+/**
+ * @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 "llchat.h"
+
+//Chat log widget allowing addition of a message as a widget
+class LLChatHistory : public LLTextEditor
+{
+ 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;
+
+ 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")
+ {
+ }
+
+ };
+ protected:
+ LLChatHistory(const Params&);
+ friend class LLUICtrlFactory;
+
+ /**
+ * 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.
+ * @param from owner of a message.
+ * @param time time of a message.
+ * @return pointer to LLView header object.
+ */
+ LLView* getHeader(const LLChat& chat);
+
+ public:
+ ~LLChatHistory();
+
+ /**
+ * 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 time time of a message.
+ * @param message message itself.
+ */
+ void appendWidgetMessage(const LLChat& chat, LLStyle::Params& style_params);
+
+ private:
+ std::string mLastFromName;
+ std::string mMessageHeaderFilename;
+ std::string mMessageSeparatorFilename;
+
+ S32 mLeftTextPad;
+ S32 mRightTextPad;
+
+ S32 mLeftWidgetPad;
+ S32 mRightWidgetPad;
+
+ S32 mTopSeparatorPad;
+ S32 mBottomSeparatorPad;
+ S32 mTopHeaderPad;
+ S32 mBottomHeaderPad;
+};
+#endif /* LLCHATHISTORY_H_ */
diff --git a/indra/newview/llchiclet.cpp b/indra/newview/llchiclet.cpp
index 23664fa6d6..53c4bb32ca 100644
--- a/indra/newview/llchiclet.cpp
+++ b/indra/newview/llchiclet.cpp
@@ -37,7 +37,6 @@
#include "llbottomtray.h"
#include "llgroupactions.h"
#include "lliconctrl.h"
-#include "llimpanel.h" // LLFloaterIMPanel
#include "llimfloater.h"
#include "llimview.h"
#include "llfloaterreg.h"
@@ -52,14 +51,11 @@
#include "lltransientfloatermgr.h"
static LLDefaultChildRegistry::Register<LLChicletPanel> t1("chiclet_panel");
-static LLDefaultChildRegistry::Register<LLTalkButton> t2("chiclet_talk");
-static LLDefaultChildRegistry::Register<LLNotificationChiclet> t3("chiclet_notification");
-static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t4("chiclet_im_p2p");
-static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t5("chiclet_im_group");
+static LLDefaultChildRegistry::Register<LLNotificationChiclet> t2("chiclet_notification");
+static LLDefaultChildRegistry::Register<LLIMP2PChiclet> t3("chiclet_im_p2p");
+static LLDefaultChildRegistry::Register<LLIMGroupChiclet> t4("chiclet_im_group");
S32 LLNotificationChiclet::mUreadSystemNotifications = 0;
-S32 LLNotificationChiclet::mUreadIMNotifications = 0;
-
boost::signals2::signal<LLChiclet* (const LLUUID&),
LLIMChiclet::CollectChicletCombiner<std::list<LLChiclet*> > >
@@ -100,7 +96,6 @@ LLNotificationChiclet::LLNotificationChiclet(const Params& p)
// connect counter handlers to the signals
connectCounterUpdatersToSignal("notify");
connectCounterUpdatersToSignal("groupnotify");
- connectCounterUpdatersToSignal("notifytoast");
}
LLNotificationChiclet::~LLNotificationChiclet()
@@ -114,16 +109,8 @@ void LLNotificationChiclet::connectCounterUpdatersToSignal(std::string notificat
LLNotificationsUI::LLEventHandler* n_handler = manager->getHandlerForNotification(notification_type);
if(n_handler)
{
- if(notification_type == "notifytoast")
- {
- n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this));
- n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::updateUreadIMNotifications, this));
- }
- else
- {
- n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
- n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
- }
+ n_handler->setNewNotificationCallback(boost::bind(&LLNotificationChiclet::incUreadSystemNotifications, this));
+ n_handler->setDelNotification(boost::bind(&LLNotificationChiclet::decUreadSystemNotifications, this));
}
}
@@ -148,12 +135,6 @@ void LLNotificationChiclet::setToggleState(BOOL toggled) {
mButton->setToggleState(toggled);
}
-void LLNotificationChiclet::updateUreadIMNotifications()
-{
- mUreadIMNotifications = gIMMgr->getNumberOfUnreadIM();
- setCounter(mUreadSystemNotifications + mUreadIMNotifications);
-}
-
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
@@ -216,9 +197,38 @@ void LLChiclet::setValue(const LLSD& value)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
-LLIMChiclet::LLIMChiclet(const LLChiclet::Params& p)
+LLIMChiclet::LLIMChiclet(const LLIMChiclet::Params& p)
: LLChiclet(p)
+, mNewMessagesIcon(NULL)
+, mCounterCtrl(NULL)
{
+ // initialize an overlay icon for new messages
+ LLIconCtrl::Params icon_params;
+ icon_params.visible = false;
+ icon_params.image = LLUI::getUIImage(p.new_messages_icon_name);
+ mNewMessagesIcon = LLUICtrlFactory::create<LLIconCtrl>(icon_params);
+ // adjust size and position of an icon
+ LLRect chiclet_rect = p.rect;
+ LLRect overlay_icon_rect = LLRect(chiclet_rect.getWidth()/2, chiclet_rect.mTop, chiclet_rect.mRight, chiclet_rect.getHeight()/2);
+ // shift an icon a little bit to the right and up corner of a chiclet
+ overlay_icon_rect.translate(overlay_icon_rect.getWidth()/5, overlay_icon_rect.getHeight()/5);
+ mNewMessagesIcon->setRect(overlay_icon_rect);
+ addChild(mNewMessagesIcon);
+
+ setShowCounter(false);
+}
+
+void LLIMChiclet::setShowNewMessagesIcon(bool show)
+{
+ if(mNewMessagesIcon)
+ {
+ mNewMessagesIcon->setVisible(show);
+ }
+}
+
+bool LLIMChiclet::getShowNewMessagesIcon()
+{
+ return mNewMessagesIcon->getVisible();
}
void LLIMChiclet::onMouseDown()
@@ -236,8 +246,6 @@ BOOL LLIMChiclet::handleMouseDown(S32 x, S32 y, MASK mask)
void LLIMChiclet::draw()
{
LLUICtrl::draw();
-
- gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.0f,0.0f,0.0f,1.f), FALSE);
}
// static
@@ -292,7 +300,7 @@ LLIMP2PChiclet::Params::Params()
, show_speaker("show_speaker")
{
// *TODO Vadim: Get rid of hardcoded values.
- rect(LLRect(0, 25, 45, 0));
+ rect(LLRect(0, 25, 25, 0));
avatar_icon.name("avatar_icon");
avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
@@ -311,6 +319,7 @@ LLIMP2PChiclet::Params::Params()
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
unread_notifications.mouse_opaque(false);
+ unread_notifications.visible(false);
speaker.name("speaker");
speaker.rect(LLRect(45, 25, 65, 0));
@@ -321,7 +330,6 @@ LLIMP2PChiclet::Params::Params()
LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
: LLIMChiclet(p)
, mChicletIconCtrl(NULL)
-, mCounterCtrl(NULL)
, mSpeakerCtrl(NULL)
, mPopupMenu(NULL)
{
@@ -340,28 +348,14 @@ LLIMP2PChiclet::LLIMP2PChiclet(const Params& p)
mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
addChild(mSpeakerCtrl);
+ sendChildToFront(mNewMessagesIcon);
setShowSpeaker(p.show_speaker);
}
void LLIMP2PChiclet::setCounter(S32 counter)
{
mCounterCtrl->setCounter(counter);
-
- if(getShowCounter())
- {
- LLRect counter_rect = mCounterCtrl->getRect();
- LLRect required_rect = mCounterCtrl->getRequiredRect();
- bool needs_resize = required_rect.getWidth() != counter_rect.getWidth();
-
- if(needs_resize)
- {
- counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth();
- mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight());
- mCounterCtrl->setRect(counter_rect);
-
- onChicletSizeChanged();
- }
- }
+ setShowNewMessagesIcon(counter);
}
LLRect LLIMP2PChiclet::getRequiredRect()
@@ -468,10 +462,109 @@ void LLIMP2PChiclet::setShowSpeaker(bool show)
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
+LLAdHocChiclet::Params::Params()
+: avatar_icon("avatar_icon")
+, unread_notifications("unread_notifications")
+, speaker("speaker")
+, show_speaker("show_speaker")
+, avatar_icon_color("avatar_icon_color", LLColor4::green)
+{
+ // *TODO Vadim: Get rid of hardcoded values.
+ rect(LLRect(0, 25, 25, 0));
+
+ avatar_icon.name("avatar_icon");
+ avatar_icon.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP | FOLLOWS_BOTTOM);
+
+ // *NOTE dzaporozhan
+ // Changed icon height from 25 to 24 to fix ticket EXT-794.
+ // In some cases(after changing UI scale) 25 pixel height icon was
+ // drawn incorrectly, i'm not sure why.
+ avatar_icon.rect(LLRect(0, 24, 25, 0));
+ avatar_icon.mouse_opaque(false);
+
+ unread_notifications.name("unread");
+ unread_notifications.rect(LLRect(25, 25, 45, 0));
+ unread_notifications.font(LLFontGL::getFontSansSerif());
+ unread_notifications.font_halign(LLFontGL::HCENTER);
+ unread_notifications.v_pad(5);
+ unread_notifications.text_color(LLColor4::white);
+ unread_notifications.mouse_opaque(false);
+ unread_notifications.visible(false);
+
+
+ speaker.name("speaker");
+ speaker.rect(LLRect(45, 25, 65, 0));
+
+ show_speaker = false;
+}
+
+LLAdHocChiclet::LLAdHocChiclet(const Params& p)
+: LLIMChiclet(p)
+, mChicletIconCtrl(NULL)
+, mSpeakerCtrl(NULL)
+, mPopupMenu(NULL)
+{
+ 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::setCounter(S32 counter)
+{
+ mCounterCtrl->setCounter(counter);
+ setShowNewMessagesIcon(counter);
+}
+
+LLRect LLAdHocChiclet::getRequiredRect()
+{
+ LLRect rect(0, 0, mChicletIconCtrl->getRect().getWidth(), 0);
+ if(getShowCounter())
+ {
+ rect.mRight += mCounterCtrl->getRequiredRect().getWidth();
+ }
+ if(getShowSpeaker())
+ {
+ rect.mRight += mSpeakerCtrl->getRect().getWidth();
+ }
+ return rect;
+}
+
+BOOL LLAdHocChiclet::handleRightMouseDown(S32 x, S32 y, MASK mask)
+{
+ return TRUE;
+}
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
LLIMGroupChiclet::Params::Params()
: group_icon("group_icon")
{
- rect(LLRect(0, 25, 45, 0));
+ rect(LLRect(0, 25, 25, 0));
group_icon.name("group_icon");
@@ -487,6 +580,7 @@ LLIMGroupChiclet::Params::Params()
unread_notifications.font_halign(LLFontGL::HCENTER);
unread_notifications.v_pad(5);
unread_notifications.text_color(LLColor4::white);
+ unread_notifications.visible(false);
speaker.name("speaker");
speaker.rect(LLRect(45, 25, 65, 0));
@@ -498,7 +592,6 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
: LLIMChiclet(p)
, LLGroupMgrObserver(LLUUID::null)
, mChicletIconCtrl(NULL)
-, mCounterCtrl(NULL)
, mSpeakerCtrl(NULL)
, mPopupMenu(NULL)
{
@@ -517,6 +610,7 @@ LLIMGroupChiclet::LLIMGroupChiclet(const Params& p)
mSpeakerCtrl = LLUICtrlFactory::create<LLChicletSpeakerCtrl>(speaker_params);
addChild(mSpeakerCtrl);
+ sendChildToFront(mNewMessagesIcon);
setShowSpeaker(p.show_speaker);
}
@@ -528,22 +622,7 @@ LLIMGroupChiclet::~LLIMGroupChiclet()
void LLIMGroupChiclet::setCounter(S32 counter)
{
mCounterCtrl->setCounter(counter);
-
- if(getShowCounter())
- {
- LLRect counter_rect = mCounterCtrl->getRect();
- LLRect required_rect = mCounterCtrl->getRequiredRect();
- bool needs_resize = required_rect.getWidth() != counter_rect.getWidth();
-
- if(needs_resize)
- {
- counter_rect.mRight = counter_rect.mLeft + required_rect.getWidth();
- mCounterCtrl->reshape(counter_rect.getWidth(), counter_rect.getHeight());
- mCounterCtrl->setRect(counter_rect);
-
- onChicletSizeChanged();
- }
- }
+ setShowNewMessagesIcon(counter);
}
LLRect LLIMGroupChiclet::getRequiredRect()
@@ -669,7 +748,12 @@ LLChicletPanel::Params::Params()
{
chiclet_padding = 3;
scrolling_offset = 40;
- min_width = 70;
+
+ if (!min_width.isProvided())
+ {
+ // min_width = 4 chiclets + 3 paddings
+ min_width = 179 + 3*chiclet_padding;
+ }
LLRect scroll_button_rect(0, 25, 19, 5);
@@ -704,6 +788,7 @@ LLChicletPanel::LLChicletPanel(const Params&p)
mLeftScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params);
addChild(mLeftScrollButton);
+ LLTransientFloaterMgr::getInstance()->addControlView(mLeftScrollButton);
mLeftScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onLeftScrollClick,this));
mLeftScrollButton->setEnabled(false);
@@ -711,6 +796,7 @@ LLChicletPanel::LLChicletPanel(const Params&p)
scroll_button_params = p.right_scroll_button;
mRightScrollButton = LLUICtrlFactory::create<LLButton>(scroll_button_params);
addChild(mRightScrollButton);
+ LLTransientFloaterMgr::getInstance()->addControlView(mRightScrollButton);
mRightScrollButton->setClickedCallback(boost::bind(&LLChicletPanel::onRightScrollClick,this));
mRightScrollButton->setEnabled(false);
@@ -732,13 +818,21 @@ LLChicletPanel::~LLChicletPanel()
void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
LLUUID session_id = data["session_id"].asUUID();
+ S32 unread = data["num_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(data["num_unread"].asInteger());
+ chiclet->setCounter(unread);
}
else
{
@@ -752,26 +846,36 @@ void im_chiclet_callback(LLChicletPanel* panel, const LLSD& data){
BOOL LLChicletPanel::postBuild()
{
LLPanel::postBuild();
- LLIMModel::instance().addChangedCallback(boost::bind(im_chiclet_callback, this, _1));
+ LLIMModel::instance().addNewMsgCallback(boost::bind(im_chiclet_callback, this, _1));
+ LLIMModel::instance().addNoUnreadMsgsCallback(boost::bind(im_chiclet_callback, this, _1));
LLIMChiclet::sFindChicletsSignal.connect(boost::bind(&LLChicletPanel::findChiclet<LLChiclet>, this, _1));
return TRUE;
}
+S32 LLChicletPanel::calcChickletPanleWidth()
+{
+ S32 res = 0;
+
+ for (chiclet_list_t::iterator it = mChicletList.begin(); it
+ != mChicletList.end(); it++)
+ {
+ res = (*it)->getRect().getWidth() + getChicletPadding();
+ }
+ return res;
+}
+
bool LLChicletPanel::addChiclet(LLChiclet* chiclet, S32 index)
{
if(mScrollArea->addChild(chiclet))
{
+ // chicklets should be aligned to right edge of scroll panel
S32 offset = 0;
- // Do not scroll chiclets if chiclets are scrolled right and new
- // chiclet is added to the beginning of the list
- if(canScrollLeft())
+
+ if (!canScrollLeft())
{
- offset = - (chiclet->getRequiredRect().getWidth() + getChicletPadding());
- if(0 == index)
- {
- offset += getChiclet(0)->getRect().mLeft;
- }
+ offset = mScrollArea->getRect().getWidth()
+ - chiclet->getRect().getWidth() - calcChickletPanleWidth();
}
mChicletList.insert(mChicletList.begin() + index, chiclet);
@@ -964,25 +1068,16 @@ void LLChicletPanel::arrange()
void LLChicletPanel::trimChiclets()
{
// trim right
- if(canScrollLeft() && !canScrollRight())
+ 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)
+ if(last_chiclet_right < scroll_width || first_chiclet_left > 0)
{
shiftChiclets(scroll_width - last_chiclet_right);
}
}
-
- // trim left
- if(!mChicletList.empty())
- {
- LLRect first_chiclet_rect = getChiclet(0)->getRect();
- if(first_chiclet_rect.mLeft > 0)
- {
- shiftChiclets( - first_chiclet_rect.mLeft);
- }
- }
}
void LLChicletPanel::showScrollButtonsIfNeeded()
@@ -1128,150 +1223,23 @@ BOOL LLChicletPanel::handleScrollWheel(S32 x, S32 y, S32 clicks)
return TRUE;
}
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-//////////////////////////////////////////////////////////////////////////
-
-// *TODO Vadim: Move this out of llchiclet.cpp.
-
-LLTalkButton::Params::Params()
- : speak_button("speak_button")
- , show_button("show_button")
- , monitor("monitor")
-{
- // *TODO Vadim: move hardcoded labels (!) and other params to XUI.
- speak_button.name("left");
- speak_button.label("Speak");
- speak_button.label_selected("Speak");
- speak_button.font(LLFontGL::getFontSansSerifSmall());
- speak_button.tab_stop(false);
- speak_button.is_toggle(true);
- speak_button.picture_style(true);
- // Use default button art. JC
- //speak_button.image_selected(LLUI::getUIImage("SegmentedBtn_Left_Selected"));
- //speak_button.image_unselected(LLUI::getUIImage("SegmentedBtn_Left_Off"));
-
- show_button.name("right");
- show_button.label(LLStringUtil::null);
- show_button.rect(LLRect(0, 0, 20, 0));
- show_button.tab_stop(false);
- show_button.is_toggle(true);
- show_button.picture_style(true);
- show_button.image_selected(LLUI::getUIImage("ComboButton_Selected"));
- show_button.image_unselected(LLUI::getUIImage("ComboButton_Off"));
-
- monitor.name("monitor");
- // *TODO: Make this data driven.
- monitor.rect(LLRect(0, 18, 18, 0));
-}
-
-LLTalkButton::LLTalkButton(const Params& p)
-: LLUICtrl(p)
-, mPrivateCallPanel(NULL)
-, mOutputMonitor(NULL)
-, mSpeakBtn(NULL)
-, mShowBtn(NULL)
+bool LLChicletPanel::isAnyIMFloaterDoked()
{
- 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->setClickedCallback(boost::bind(&LLTalkButton::onClick_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(&LLTalkButton::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);
-}
-
-LLTalkButton::~LLTalkButton()
-{
-}
-
-void LLTalkButton::setSpeakBtnToggleState(bool state)
-{
- mSpeakBtn->setToggleState(state);
-}
-
-void LLTalkButton::onClick_SpeakBtn()
-{
- bool speaking = mSpeakBtn->getToggleState();
- gVoiceClient->setUserPTTState(speaking);
-}
-
-void LLTalkButton::onClick_ShowBtn()
-{
- if(!mShowBtn->getToggleState())
+ bool res = false;
+ for (chiclet_list_t::iterator it = mChicletList.begin(); it
+ != mChicletList.end(); it++)
{
- mPrivateCallPanel->onClickClose(mPrivateCallPanel);
- delete mPrivateCallPanel;
- mPrivateCallPanel = NULL;
- mShowBtn->setToggleState(FALSE);
- return;
+ 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;
+ }
}
- S32 x = mSpeakBtn->getRect().mLeft;
- S32 y = 0;
-
- localPointToScreen(x, y, &x, &y);
-
- mPrivateCallPanel = new LLVoiceControlPanel;
- getRootView()->addChild(mPrivateCallPanel);
-
- y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight();
-
- LLRect rect;
- rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight());
- mPrivateCallPanel->setRect(rect);
-
-
- LLAvatarListItem* item = new LLAvatarListItem();
- item->showStatus(true);
- item->showInfoBtn(true);
- item->showSpeakingIndicator(true);
- item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE);
-
- mPrivateCallPanel->addItem(item);
- mPrivateCallPanel->setVisible(TRUE);
- mPrivateCallPanel->setFrontmost(TRUE);
-
- mShowBtn->setToggleState(TRUE);
+ return res;
}
//////////////////////////////////////////////////////////////////////////
diff --git a/indra/newview/llchiclet.h b/indra/newview/llchiclet.h
index ef47b54333..b50702205c 100644
--- a/indra/newview/llchiclet.h
+++ b/indra/newview/llchiclet.h
@@ -278,6 +278,14 @@ public:
TYPE_GROUP,
TYPE_AD_HOC
};
+ struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ {
+ Optional<std::string> new_messages_icon_name;
+
+ Params() : new_messages_icon_name("new_messages_icon_name", "icn_voice-localchat.tga")
+ {}
+ };
+
/*virtual*/ ~LLIMChiclet() {};
@@ -308,6 +316,16 @@ public:
virtual bool getShowSpeaker() {return mShowSpeaker;};
/*
+ * 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();
+
+ /*
* Draws border around chiclet.
*/
/*virtual*/ void draw();
@@ -335,7 +353,7 @@ public:
protected:
- LLIMChiclet(const LLChiclet::Params& p);
+ LLIMChiclet(const LLIMChiclet::Params& p);
/*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask);
@@ -343,6 +361,9 @@ protected:
bool mShowSpeaker;
+ LLIconCtrl* mNewMessagesIcon;
+ LLChicletNotificationCounterCtrl* mCounterCtrl;
+
/** the id of another participant, either an avatar id or a group id*/
LLUUID mOtherParticipantId;
@@ -374,7 +395,7 @@ public:
class LLIMP2PChiclet : public LLIMChiclet
{
public:
- struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
{
Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
@@ -436,7 +457,66 @@ protected:
private:
LLChicletAvatarIconCtrl* mChicletIconCtrl;
- LLChicletNotificationCounterCtrl* mCounterCtrl;
+ LLChicletSpeakerCtrl* mSpeakerCtrl;
+ LLMenuGL* mPopupMenu;
+};
+
+/**
+ * Implements AD-HOC chiclet.
+ */
+class LLAdHocChiclet : public LLIMChiclet
+{
+public:
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
+ {
+ Optional<LLChicletAvatarIconCtrl::Params> avatar_icon;
+
+ Optional<LLChicletNotificationCounterCtrl::Params> unread_notifications;
+
+ Optional<LLChicletSpeakerCtrl::Params> speaker;
+
+ 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);
+
+ /*
+ * 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);
+
+ /*
+ * Returns number of unread messages.
+ */
+ /*virtual*/ S32 getCounter() { return mCounterCtrl->getCounter(); }
+
+ /*
+ * Returns rect, required to display chiclet.
+ * Width is the only valid value.
+ */
+ /*virtual*/ LLRect getRequiredRect();
+
+protected:
+ LLAdHocChiclet(const Params& p);
+ friend class LLUICtrlFactory;
+
+ /*
+ * Displays popup menu.
+ */
+ virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
+
+private:
+
+ LLChicletAvatarIconCtrl* mChicletIconCtrl;
LLChicletSpeakerCtrl* mSpeakerCtrl;
LLMenuGL* mPopupMenu;
};
@@ -448,7 +528,7 @@ class LLIMGroupChiclet : public LLIMChiclet, public LLGroupMgrObserver
{
public:
- struct Params : public LLInitParam::Block<Params, LLChiclet::Params>
+ struct Params : public LLInitParam::Block<Params, LLIMChiclet::Params>
{
Optional<LLChicletGroupIconCtrl::Params> group_icon;
@@ -517,7 +597,6 @@ protected:
private:
LLChicletGroupIconCtrl* mChicletIconCtrl;
- LLChicletNotificationCounterCtrl* mCounterCtrl;
LLChicletSpeakerCtrl* mSpeakerCtrl;
LLMenuGL* mPopupMenu;
};
@@ -549,10 +628,9 @@ public:
/*virtual*/ ~ LLNotificationChiclet();
- // methods for updating a number of unread System or IM notifications
- void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications + mUreadIMNotifications); }
- void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications + mUreadIMNotifications); }
- void updateUreadIMNotifications();
+ // methods for updating a number of unread System notifications
+ void incUreadSystemNotifications() { setCounter(++mUreadSystemNotifications); }
+ void decUreadSystemNotifications() { setCounter(--mUreadSystemNotifications); }
void setToggleState(BOOL toggled);
protected:
@@ -563,7 +641,6 @@ protected:
friend class LLUICtrlFactory;
static S32 mUreadSystemNotifications;
- static S32 mUreadIMNotifications;
protected:
LLButton* mButton;
@@ -594,9 +671,14 @@ public:
virtual ~LLChicletPanel();
/*
- * Creates chiclet and adds it to chiclet list.
+ * Creates chiclet and adds it to chiclet list at specified index.
*/
- template<class T> T* createChiclet(const LLUUID& session_id = LLUUID::null, S32 index = 0);
+ 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.
@@ -660,10 +742,14 @@ public:
/*virtual*/ void draw();
+ S32 getMinWidth() const { return mMinWidth; }
+
protected:
LLChicletPanel(const Params&p);
friend class LLUICtrlFactory;
+ S32 calcChickletPanleWidth();
+
/*
* Adds chiclet to list and rearranges all chiclets.
*/
@@ -752,6 +838,8 @@ protected:
S32 getScrollingOffset() { return mScrollingOffset; }
+ bool isAnyIMFloaterDoked();
+
protected:
chiclet_list_t mChicletList;
@@ -765,44 +853,8 @@ protected:
bool mShowControls;
};
-/*
- * Button displaying voice chat status. Displays voice chat options When clicked.
-*/
-class LLTalkButton : public LLUICtrl
-{
-public:
-
- struct Params : public LLInitParam::Block<Params, LLUICtrl::Params>
- {
- Optional<LLButton::Params> speak_button,
- show_button;
-
- Optional<LLOutputMonitorCtrl::Params> monitor;
-
- Params();
- };
-
- /*virtual*/ ~LLTalkButton();
-
- void setSpeakBtnToggleState(bool state);
-
-protected:
- friend class LLUICtrlFactory;
- LLTalkButton(const Params& p);
-
- void onClick_SpeakBtn();
-
- void onClick_ShowBtn();
-
-private:
- LLButton* mSpeakBtn;
- LLButton* mShowBtn;
- LLVoiceControlPanel* mPrivateCallPanel;
- LLOutputMonitorCtrl* mOutputMonitor;
-};
-
template<class T>
-T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S32 index /*= 0*/)
+T* LLChicletPanel::createChiclet(const LLUUID& session_id, S32 index)
{
typename T::Params params;
T* chiclet = LLUICtrlFactory::create<T>(params);
@@ -818,7 +870,10 @@ T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S3
return NULL;
}
- scrollToChiclet(chiclet);
+ if (!isAnyIMFloaterDoked())
+ {
+ scrollToChiclet(chiclet);
+ }
chiclet->setSessionId(session_id);
@@ -826,6 +881,12 @@ T* LLChicletPanel::createChiclet(const LLUUID& session_id /*= LLUUID::null*/, S3
}
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())
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/llcolorswatch.cpp b/indra/newview/llcolorswatch.cpp
index 7b75c77a1e..ed304bdd34 100644
--- a/indra/newview/llcolorswatch.cpp
+++ b/indra/newview/llcolorswatch.cpp
@@ -228,7 +228,8 @@ void LLColorSwatchCtrl::draw()
{
if (!mFallbackImageName.empty())
{
- LLPointer<LLViewerTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ LLPointer<LLViewerTexture> fallback_image = LLViewerTextureManager::getFetchedTextureFromFile(mFallbackImageName, TRUE,
+ LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if( fallback_image->getComponents() == 4 )
{
gl_rect_2d_checkerboard( interior );
diff --git a/indra/newview/llconfirmationmanager.cpp b/indra/newview/llconfirmationmanager.cpp
index 225f177546..5813943ad3 100644
--- a/indra/newview/llconfirmationmanager.cpp
+++ b/indra/newview/llconfirmationmanager.cpp
@@ -39,6 +39,7 @@
// viewer includes
#include "llnotifications.h"
#include "llstring.h"
+#include "llxmlnode.h"
LLConfirmationManager::ListenerBase::~ListenerBase()
{
diff --git a/indra/newview/llcurrencyuimanager.cpp b/indra/newview/llcurrencyuimanager.cpp
index 979a1a9a60..c4bfd71999 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 "llversionviewer.h"
#include "llcurrencyuimanager.h"
@@ -156,6 +158,11 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo()
"secureSessionId",
gAgent.getSecureSessionID().asString());
keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy);
+ keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR);
+ keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR);
+ keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH);
+ keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD);
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
@@ -209,7 +216,12 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password)
{
keywordArgs.appendString("password", password);
}
-
+ keywordArgs.appendString("viewerChannel", gSavedSettings.getString("VersionChannelName"));
+ keywordArgs.appendInt("viewerMajorVersion", LL_VERSION_MAJOR);
+ keywordArgs.appendInt("viewerMinorVersion", LL_VERSION_MINOR);
+ keywordArgs.appendInt("viewerPatchVersion", LL_VERSION_PATCH);
+ keywordArgs.appendInt("viewerBuildVersion", LL_VERSION_BUILD);
+
LLXMLRPCValue params = LLXMLRPCValue::createArray();
params.append(keywordArgs);
diff --git a/indra/newview/lldebugmessagebox.cpp b/indra/newview/lldebugmessagebox.cpp
index 29e375c9fa..7814e94dfd 100644
--- a/indra/newview/lldebugmessagebox.cpp
+++ b/indra/newview/lldebugmessagebox.cpp
@@ -124,6 +124,7 @@ LLDebugVarMessageBox::LLDebugVarMessageBox(const std::string& title, EDebugVarTy
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);
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/lldrawpool.cpp b/indra/newview/lldrawpool.cpp
index 976f02eeb7..d8c34581d5 100644
--- a/indra/newview/lldrawpool.cpp
+++ b/indra/newview/lldrawpool.cpp
@@ -442,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;
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index e087feeaec..5f845c3721 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -144,7 +144,7 @@ void LLStandardBumpmap::restoreGL()
gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage =
LLViewerTextureManager::getFetchedTexture(LLUUID(bump_image_id),
TRUE,
- FALSE,
+ LLViewerTexture::BOOST_NONE,
LLViewerTexture::LOD_TEXTURE,
0,
0);
diff --git a/indra/newview/lldrawpoolterrain.cpp b/indra/newview/lldrawpoolterrain.cpp
index 790e75cfaa..9dc22cddcd 100644
--- a/indra/newview/lldrawpoolterrain.cpp
+++ b/indra/newview/lldrawpoolterrain.cpp
@@ -72,7 +72,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
sDetailScale = 1.f/gSavedSettings.getF32("RenderTerrainScale");
sDetailMode = gSavedSettings.getS32("RenderTerrainDetail");
mAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient.tga",
- TRUE, TRUE,
+ TRUE, LLViewerTexture::BOOST_UI,
LLViewerTexture::FETCHED_TEXTURE,
GL_ALPHA8, GL_ALPHA,
LLUUID("e97cf410-8e61-7005-ec06-629eba4cd1fb"));
@@ -81,7 +81,7 @@ LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerTexture *texturep) :
mAlphaRampImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
m2DAlphaRampImagep = LLViewerTextureManager::getFetchedTextureFromFile("alpha_gradient_2d.j2c",
- TRUE, TRUE,
+ TRUE, LLViewerTexture::BOOST_UI,
LLViewerTexture::FETCHED_TEXTURE,
GL_ALPHA8, GL_ALPHA,
LLUUID("38b86f85-2575-52a9-a531-23108d8da837"));
diff --git a/indra/newview/lldrawpoolwater.cpp b/indra/newview/lldrawpoolwater.cpp
index f56359afc3..107de934df 100644
--- a/indra/newview/lldrawpoolwater.cpp
+++ b/indra/newview/lldrawpoolwater.cpp
@@ -69,11 +69,11 @@ LLVector3 LLDrawPoolWater::sLightDir;
LLDrawPoolWater::LLDrawPoolWater() :
LLFacePool(POOL_WATER)
{
- mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE);
+ mHBTex[0] = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
gGL.getTexUnit(0)->bind(mHBTex[0]) ;
mHBTex[0]->setAddressMode(LLTexUnit::TAM_CLAMP);
- mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE);
+ mHBTex[1] = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
gGL.getTexUnit(0)->bind(mHBTex[1]);
mHBTex[1]->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -369,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();
diff --git a/indra/newview/lldriverparam.cpp b/indra/newview/lldriverparam.cpp
index 55b3ab796e..45f4b4fbd0 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
@@ -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,set_by_user);
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,set_by_user);
continue;
}
}
driven_weight = getDrivenWeight(driven, mCurWeight);
- driven->mParam->setWeight( driven_weight, set_by_user );
+ setDrivenWeight(driven,driven_weight,set_by_user);
}
}
@@ -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 set_by_user)
+{
+ 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, set_by_user );
+ }
+ else
+ {
+ driven->mParam->setWeight( driven_weight, set_by_user );
+ }
+}
diff --git a/indra/newview/lldriverparam.h b/indra/newview/lldriverparam.h
index 7bc0c15448..069e71a2cb 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*/ 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 set_by_user);
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/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 2c52cf9565..da20766e7e 100644
--- a/indra/newview/lleventnotifier.cpp
+++ b/indra/newview/lleventnotifier.cpp
@@ -39,7 +39,6 @@
#include "llnotify.h"
#include "lleventinfo.h"
#include "llfloaterreg.h"
-#include "llfloaterdirectory.h"
#include "llfloaterworldmap.h"
#include "llagent.h"
@@ -95,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;
@@ -199,8 +196,7 @@ bool LLEventNotification::handleResponse(const LLSD& notification, const LLSD& r
break;
}
case 1:
- gDisplayEventHack = TRUE;
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "event").insert("id", S32(getEventID())));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "events").insert("id", S32(getEventID())));
break;
case 2:
break;
@@ -210,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
{
@@ -264,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/llexpandabletextbox.cpp b/indra/newview/llexpandabletextbox.cpp
index 2467356018..424d635321 100644
--- a/indra/newview/llexpandabletextbox.cpp
+++ b/indra/newview/llexpandabletextbox.cpp
@@ -48,16 +48,31 @@ public:
mExpanderLabel(more_text)
{}
- /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
// more label always spans width of text box
- return mEditor.getTextRect().getWidth();
+ width = mEditor.getTextRect().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 { return getEnd() - getStart(); }
+ /*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;
@@ -72,8 +87,9 @@ public:
mEditor.getUseEllipses());
return right_x;
}
- /*virtual*/ S32 getMaxHeight() const { return llceil(mStyle->getFont()->getLineHeight()); }
/*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)
{
@@ -113,9 +129,12 @@ void LLExpandableTextBox::LLTextBoxEx::reshape(S32 width, S32 height, BOOL calle
}
}
-void LLExpandableTextBox::LLTextBoxEx::setValue(const LLSD& value)
+void LLExpandableTextBox::LLTextBoxEx::setText(const LLStringExplicit& text)
{
- LLTextBox::setValue(value);
+ // LLTextBox::setText will obliterate the expander segment, so make sure
+ // we generate it again by clearing mExpanderVisible
+ mExpanderVisible = false;
+ LLTextBox::setText(text);
// text contents have changed, segments are cleared out
// so hide the expander and determine if we need it
@@ -135,6 +154,11 @@ 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;
@@ -382,7 +406,6 @@ void LLExpandableTextBox::onTopLost()
void LLExpandableTextBox::setValue(const LLSD& value)
{
collapseTextBox();
-
mText = value.asString();
mTextBox->setValue(value);
}
@@ -390,7 +413,6 @@ void LLExpandableTextBox::setValue(const LLSD& value)
void LLExpandableTextBox::setText(const std::string& str)
{
collapseTextBox();
-
mText = str;
mTextBox->setText(str);
}
diff --git a/indra/newview/llexpandabletextbox.h b/indra/newview/llexpandabletextbox.h
index d6401e224f..3fe646c29c 100644
--- a/indra/newview/llexpandabletextbox.h
+++ b/indra/newview/llexpandabletextbox.h
@@ -60,7 +60,7 @@ protected:
// adds or removes "More" link as needed
/*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE);
- /*virtual*/ void setValue(const LLSD& value);
+ /*virtual*/ void setText(const LLStringExplicit& text);
/**
* Returns difference between text box height and text height.
@@ -69,16 +69,6 @@ protected:
virtual S32 getVerticalTextDelta();
/**
- * Returns text vertical padding
- */
- virtual S32 getVPad() { return mVPad; }
-
- /**
- * Returns text horizontal padding
- */
- virtual S32 getHPad() { return mHPad; }
-
- /**
* Shows "More" link
*/
void showExpandText();
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index 4246cbc27f..8ec448e281 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -515,8 +515,8 @@ void LLFace::renderSelected(LLViewerTexture *imagep, const LLColor4& color)
/* removed in lieu of raycast uv detection
void LLFace::renderSelectedUV()
{
- LLViewerTexture* red_blue_imagep = LLViewerTextureManager::getFetchedTextureFromFile("uv_test1.j2c", TRUE, TRUE);
- LLViewerTexture* green_imagep = LLViewerTextureManager::getFetchedTextureFromFile("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;
@@ -856,6 +856,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();
@@ -864,7 +865,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;
}
diff --git a/indra/newview/llface.h b/indra/newview/llface.h
index d734b327d9..2b134c8c31 100644
--- a/indra/newview/llface.h
+++ b/indra/newview/llface.h
@@ -246,7 +246,7 @@ protected:
//atlas
LLPointer<LLTextureAtlasSlot> mAtlasInfop ;
- BOOL mUsingAtlas ;
+ BOOL mUsingAtlas ;
protected:
static BOOL sSafeRenderSelect;
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 0bd4389b50..2ab17d6220 100644
--- a/indra/newview/llfasttimerview.cpp
+++ b/indra/newview/llfasttimerview.cpp
@@ -496,7 +496,7 @@ void LLFastTimerView::draw()
// Draw the history bars
if (LLFastTimer::getLastFrameIndex() >= 0)
{
- LLLocalClipRect clip(LLRect(xleft, ytop - margin, getRect().getWidth() - margin, margin));
+ LLLocalClipRect clip(LLRect(xleft, ytop, getRect().getWidth() - margin, margin));
U64 totalticks;
if (!LLFastTimer::sPauseHistory)
@@ -996,8 +996,12 @@ LLSD LLFastTimerView::analyzePerformanceLogDefault(std::istream& is)
std::string label = iter->first;
F64 time = iter->second["Time"].asReal();
-
- total_time += time;
+
+ // Skip the total figure
+ if(label.compare("Total") != 0)
+ {
+ total_time += time;
+ }
if (time > 0.0)
{
diff --git a/indra/newview/llfavoritesbar.cpp b/indra/newview/llfavoritesbar.cpp
index 007c6b2c4c..18135fc558 100644
--- a/indra/newview/llfavoritesbar.cpp
+++ b/indra/newview/llfavoritesbar.cpp
@@ -66,29 +66,46 @@ const S32 DROP_DOWN_MENU_WIDTH = 250;
* Helper for LLFavoriteLandmarkButton and LLFavoriteLandmarkMenuItem.
* Performing requests for SLURL for given Landmark ID
*/
-class LLSLURLGetter
+class LLLandmarkInfoGetter
{
public:
- LLSLURLGetter()
- : mLandmarkID(LLUUID::null)
- , mSLURL("(Loading...)")
- , mLoaded(false) {}
+ LLLandmarkInfoGetter()
+ : mLandmarkID(LLUUID::null),
+ mName("(Loading...)"),
+ mPosX(0),
+ mPosY(0),
+ mLoaded(false)
+ {}
void setLandmarkID(const LLUUID& id) { mLandmarkID = id; }
const LLUUID& getLandmarkId() const { return mLandmarkID; }
- const std::string& getSLURL()
+ const std::string& getName()
{
if(!mLoaded)
- requestSLURL();
+ requestNameAndPos();
- return mSLURL;
+ return mName;
+ }
+
+ S32 getPosX()
+ {
+ if (!mLoaded)
+ requestNameAndPos();
+ return mPosX;
+ }
+
+ S32 getPosY()
+ {
+ if (!mLoaded)
+ requestNameAndPos();
+ return mPosY;
}
private:
/**
* Requests landmark data from server.
*/
- void requestSLURL()
+ void requestNameAndPos()
{
if (mLandmarkID.isNull())
return;
@@ -96,19 +113,23 @@ private:
LLVector3d g_pos;
if(LLLandmarkActions::getLandmarkGlobalPos(mLandmarkID, g_pos))
{
- LLLandmarkActions::getSLURLfromPosGlobal(g_pos,
- boost::bind(&LLSLURLGetter::landmarkNameCallback, this, _1), false);
+ LLLandmarkActions::getRegionNameAndCoordsFromPosGlobal(g_pos,
+ boost::bind(&LLLandmarkInfoGetter::landmarkNameCallback, this, _1, _2, _3));
}
}
- void landmarkNameCallback(const std::string& name)
+ void landmarkNameCallback(const std::string& name, S32 x, S32 y)
{
- mSLURL = name;
+ mPosX = x;
+ mPosY = y;
+ mName = name;
mLoaded = true;
}
LLUUID mLandmarkID;
- std::string mSLURL;
+ std::string mName;
+ S32 mPosX;
+ S32 mPosY;
bool mLoaded;
};
@@ -125,7 +146,15 @@ public:
BOOL handleToolTip(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
+ std::string region_name = mLandmarkInfoGetter.getName();
+
+ if (!region_name.empty())
+ {
+ LLToolTip::Params params;
+ params.message = llformat("%s\n%s (%d, %d)", getLabelSelected().c_str(), region_name.c_str(), mLandmarkInfoGetter.getPosX(), mLandmarkInfoGetter.getPosY());
+ params.sticky_rect = calcScreenRect();
+ LLToolTipMgr::instance().show(params);
+ }
return TRUE;
}
@@ -141,8 +170,8 @@ public:
return LLButton::handleHover(x, y, mask);
}
- void setLandmarkID(const LLUUID& id){ mUrlGetter.setLandmarkID(id); }
- const LLUUID& getLandmarkId() const { return mUrlGetter.getLandmarkId(); }
+ void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
+ const LLUUID& getLandmarkId() const { return mLandmarkInfoGetter.getLandmarkId(); }
void onMouseEnter(S32 x, S32 y, MASK mask)
{
@@ -161,7 +190,7 @@ protected:
friend class LLUICtrlFactory;
private:
- LLSLURLGetter mUrlGetter;
+ LLLandmarkInfoGetter mLandmarkInfoGetter;
};
/**
@@ -176,11 +205,18 @@ class LLFavoriteLandmarkMenuItem : public LLMenuItemCallGL
public:
BOOL handleToolTip(S32 x, S32 y, MASK mask)
{
- LLToolTipMgr::instance().show(mUrlGetter.getSLURL());
+ 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){ mUrlGetter.setLandmarkID(id); }
+ void setLandmarkID(const LLUUID& id){ mLandmarkInfoGetter.setLandmarkID(id); }
virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask)
{
@@ -212,7 +248,7 @@ protected:
friend class LLUICtrlFactory;
private:
- LLSLURLGetter mUrlGetter;
+ LLLandmarkInfoGetter mLandmarkInfoGetter;
LLFavoritesBarCtrl* fb;
};
@@ -401,7 +437,7 @@ BOOL LLFavoritesBarCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
}
else
{
- LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ 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;
@@ -467,13 +503,15 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
return;
}
+ LLPointer<LLViewerInventoryItem> viewer_item = new LLViewerInventoryItem(item);
+
if (dest)
{
- insertBeforeItem(mItems, dest->getLandmarkId(), item->getUUID());
+ insertBeforeItem(mItems, dest->getLandmarkId(), viewer_item);
}
else
{
- mItems.push_back(gInventory.getItem(item->getUUID()));
+ mItems.push_back(viewer_item);
}
int sortField = 0;
@@ -498,13 +536,22 @@ void LLFavoritesBarCtrl::handleNewFavoriteDragAndDrop(LLInventoryItem *item, con
}
}
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- favorites_id,
- std::string(),
- cb);
+ 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;
}
@@ -514,7 +561,7 @@ void LLFavoritesBarCtrl::changed(U32 mask)
{
if (mFavoriteFolderId.isNull())
{
- mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ mFavoriteFolderId = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if (mFavoriteFolderId.notNull())
{
@@ -590,8 +637,6 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
buttonXMLNode->getAttributeS32("width", buttonWidth);
S32 buttonHGap = 2; // default value
buttonXMLNode->getAttributeS32("left", buttonHGap);
-
- const S32 buttonVGap = 2;
S32 count = mItems.count();
@@ -677,7 +722,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
if (chevron_button)
{
LLRect rect;
- rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap);
+ rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, 0, chevron_button_width, getRect().getHeight());
chevron_button->setRect(rect);
chevron_button->setVisible(TRUE);
mChevronRect = rect;
@@ -692,7 +737,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
LLButton::Params bparams;
LLRect rect;
- rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, buttonVGap, chevron_button_width, getRect().getHeight()-buttonVGap);
+ rect.setOriginAndSize(bar_width - chevron_button_width - buttonHGap, 0, chevron_button_width, getRect().getHeight());
bparams.follows.flags (FOLLOWS_LEFT | FOLLOWS_BOTTOM);
bparams.image_unselected.name(flat_icon);
@@ -705,6 +750,7 @@ void LLFavoritesBarCtrl::updateButtons(U32 bar_width)
bparams.tab_stop(false);
bparams.font(mFont);
bparams.name(">>");
+ bparams.label(">>");
bparams.tool_tip(mChevronButtonToolTip);
bparams.click_callback.function(boost::bind(&LLFavoritesBarCtrl::showDropDownMenu, this));
@@ -1229,10 +1275,9 @@ void LLFavoritesBarCtrl::updateItemsOrder(LLInventoryModel::item_array_t& items,
items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
}
-void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, const LLUUID& insertedItemId)
+void LLFavoritesBarCtrl::insertBeforeItem(LLInventoryModel::item_array_t& items, const LLUUID& beforeItemId, LLViewerInventoryItem* insertedItem)
{
LLViewerInventoryItem* beforeItem = gInventory.getItem(beforeItemId);
- LLViewerInventoryItem* insertedItem = gInventory.getItem(insertedItemId);
items.insert(findItemByUUID(items, beforeItem->getUUID()), insertedItem);
}
diff --git a/indra/newview/llfavoritesbar.h b/indra/newview/llfavoritesbar.h
index ea2a3d08e2..e90d13f9d5 100644
--- a/indra/newview/llfavoritesbar.h
+++ b/indra/newview/llfavoritesbar.h
@@ -141,7 +141,7 @@ private:
* 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, const LLUUID& insertedItemId);
+ 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);
diff --git a/indra/newview/llfeaturemanager.cpp b/indra/newview/llfeaturemanager.cpp
index 2a8365b3f0..fb724f30e0 100644
--- a/indra/newview/llfeaturemanager.cpp
+++ b/indra/newview/llfeaturemanager.cpp
@@ -44,6 +44,7 @@
#include "llgl.h"
#include "llsecondlifeurls.h"
+#include "llappviewer.h"
#include "llviewercontrol.h"
#include "llworld.h"
#include "lldrawpoolterrain.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";
diff --git a/indra/newview/llfirstuse.cpp b/indra/newview/llfirstuse.cpp
index de079b7123..893b12ec35 100644
--- a/indra/newview/llfirstuse.cpp
+++ b/indra/newview/llfirstuse.cpp
@@ -272,6 +272,8 @@ void LLFirstUse::useMedia()
{
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
+ //LLNotifications::instance().add("FirstMedia");
}
}
diff --git a/indra/newview/llflexibleobject.cpp b/indra/newview/llflexibleobject.cpp
index 216bca8262..fc8790c172 100644
--- a/indra/newview/llflexibleobject.cpp
+++ b/indra/newview/llflexibleobject.cpp
@@ -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/llfloaterabout.cpp b/indra/newview/llfloaterabout.cpp
index a4c38d03aa..b01293d17c 100644
--- a/indra/newview/llfloaterabout.cpp
+++ b/indra/newview/llfloaterabout.cpp
@@ -39,6 +39,7 @@
#include "llagent.h"
#include "llappviewer.h"
#include "llsecondlifeurls.h"
+#include "llvoiceclient.h"
#include "lluictrlfactory.h"
#include "llviewertexteditor.h"
#include "llviewercontrol.h"
@@ -61,12 +62,14 @@
#include "lluri.h"
#include "v3dmath.h"
#include "llwindow.h"
+#include "stringize.h"
+#include "llsdutil_math.h"
+#include "lleventdispatcher.h"
#if LL_WINDOWS
#include "lldxhardware.h"
#endif
-extern LLCPUInfo gSysCPU;
extern LLMemoryInfo gSysMemory;
extern U32 gPacketsIn;
@@ -86,6 +89,10 @@ private:
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();
};
@@ -115,25 +122,117 @@ BOOL LLFloaterAbout::postBuild()
getChild<LLUICtrl>("copy_btn")->setCommitCallback(
boost::bind(&LLFloaterAbout::onClickCopyToClipboard, this));
- // Version string
- std::string version = LLTrans::getString("APP_NAME")
- + 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());
+#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::string support;
- support.append(version);
- support.append("[" + get_viewer_release_notes_url() + " " +
- LLTrans::getString("ReleaseNotes") + "]");
- support.append("\n\n");
+ std::ostringstream support;
-#if LL_MSVC
- support.append(llformat("Built with MSVC version %d\n\n", _MSC_VER));
-#endif
+ // 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();
+ }
+ }
+ }
+
+ // Now build the various pieces
+ support << getString("AboutHeader", args);
+ if (info.has("COMPILER"))
+ {
+ support << "\n\n" << getString("AboutCompiler", args);
+ }
+ if (info.has("REGION"))
+ {
+ support << "\n\n" << getString("AboutPosition", args);
+ }
+ support << "\n\n" << getString("AboutSystem", args);
+ if (info.has("GRAPHICS_DRIVER_VERSION"))
+ {
+ support << "\n\n" << getString("AboutDriver", args);
+ }
+ support << "\n\n" << getString("AboutLibs", args);
+ if (info.has("PACKETS_IN"))
+ {
+ support << '\n' << getString("AboutTraffic", args);
+ }
-#if LL_GNUC
- support.append(llformat("Built with GCC version %d\n\n", GCC_VERSION));
+ support_widget->appendText(support.str(),
+ FALSE,
+ LLStyle::Params()
+ .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
+ support_widget->blockUndo();
+
+ // Fix views
+ support_widget->setCursorPos(0);
+ support_widget->setEnabled(FALSE);
+
+ credits_widget->setCursorPos(0);
+ credits_widget->setEnabled(FALSE);
+
+ return TRUE;
+}
+
+// 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(LL_VERSION_MAJOR);
+ version.append(LL_VERSION_MINOR);
+ version.append(LL_VERSION_PATCH);
+ version.append(LL_VERSION_BUILD);
+ info["VIEWER_VERSION"] = version;
+ info["VIEWER_VERSION_STR"] = STRINGIZE(version[0].asInteger() << '.' <<
+ version[1].asInteger() << '.' <<
+ version[2].asInteger() << '.' <<
+ version[3].asInteger());
+ 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_MSVC
+ info["COMPILER"] = "MSVC";
+ info["COMPILER_VERSION"] = _MSC_VER;
+#elif LL_GNUC
+ info["COMPILER"] = "GCC";
+ info["COMPILER_VERSION"] = GCC_VERSION;
#endif
// Position
@@ -141,120 +240,50 @@ BOOL LLFloaterAbout::postBuild()
if (region)
{
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);
-
- LLUIString region_text = getString ("in_region") + " ";
- region_text.setArg("[REGION]", llformat ("%s", 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.append("[" + LLWeb::escapeURL(region->getCapability("ServerReleaseNotes")) +
- " " + LLTrans::getString("ReleaseNotes") + "]");
- support.append("\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(getString("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
-
- LLStringUtil::format_map_t args;
- args["[MEM]"] = llformat ("%u", memory);
- support.append(getString("Memory", args) + "\n");
-
- support.append(getString("OSVersion") + " ");
- support.append( LLAppViewer::instance()->getOSInfo().getOSString() );
- support.append("\n");
-
- support.append(getString("GraphicsCardVendor") + " ");
- support.append( (const char*) glGetString(GL_VENDOR) );
- support.append("\n");
-
- support.append(getString("GraphicsCard") + " ");
- 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(getString("OpenGLVersion") + " ");
- support.append( (const char*) glGetString(GL_VERSION) );
- support.append("\n");
-
- support.append("\n");
-
- support.append(getString("LibCurlVersion") + " ");
- support.append( LLCurl::getVersionString() );
- support.append("\n");
-
- support.append(getString("J2CDecoderVersion") + " ");
- support.append( LLImageJ2C::getEngineInfo() );
- support.append("\n");
-
- support.append(getString("AudioDriverVersion") + " ");
+ 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) : getString("none") );
- support.append("\n");
+ info["AUDIO_DRIVER_VERSION"] = gAudiop ? LLSD(gAudiop->getDriverName(want_fullname)) : LLSD();
+ info["VIVOX_VERSION"] = gVoiceClient ? gVoiceClient->getAPIVersion() : "Unknown";
// TODO: Implement media plugin version query
-
- support.append(getString("LLQtWebkitVersion") + " ");
- support.append("\n");
+ info["QT_WEBKIT_VERSION"] = "4.5.2";
if (gPacketsIn > 0)
{
- args["[LOST]"] = llformat ("%.0f", LLViewerStats::getInstance()->mPacketsLostStat.getCurrent());
- args["[IN]"] = llformat ("%.0f", F32(gPacketsIn));
- args["[PCT]"] = llformat ("%.1f", 100.f*LLViewerStats::getInstance()->mPacketsLostStat.getCurrent() / F32(gPacketsIn) );
- support.append(getString ("PacketsLost", args) + "\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->appendText(support,
- FALSE,
- LLStyle::Params()
- .color(LLUIColorTable::instance().getColor("TextFgReadOnlyColor")));
- support_widget->blockUndo();
-
- // Fix views
- support_widget->setCursorPos(0);
- support_widget->setEnabled(FALSE);
-
- credits_widget->setCursorPos(0);
- credits_widget->setEnabled(FALSE);
-
- return TRUE;
+ return info;
}
-
static std::string get_viewer_release_notes_url()
{
std::ostringstream version;
@@ -273,6 +302,27 @@ static std::string get_viewer_release_notes_url()
return LLWeb::escapeURL(url.str());
}
+class LLFloaterAboutListener: public LLDispatchListener
+{
+public:
+ LLFloaterAboutListener():
+ LLDispatchListener("LLFloaterAbout", "op")
+ {
+ add("getInfo", &LLFloaterAboutListener::getInfo, LLSD().insert("reply", LLSD()));
+ }
+
+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;
+
void LLFloaterAbout::onClickCopyToClipboard()
{
LLViewerTextEditor *support_widget =
diff --git a/indra/newview/llfloateranimpreview.cpp b/indra/newview/llfloateranimpreview.cpp
index c062e6ccf2..095fe0a220 100644
--- a/indra/newview/llfloateranimpreview.cpp
+++ b/indra/newview/llfloateranimpreview.cpp
@@ -426,8 +426,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
@@ -638,10 +638,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();
@@ -989,7 +989,7 @@ void LLFloaterAnimPreview::onBtnOK(void* userdata)
name,
desc,
0,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
LLInventoryType::IT_ANIMATION,
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
name,
diff --git a/indra/newview/llfloaterauction.cpp b/indra/newview/llfloaterauction.cpp
index da2a4d9d93..262dc1804d 100644
--- a/indra/newview/llfloaterauction.cpp
+++ b/indra/newview/llfloaterauction.cpp
@@ -33,6 +33,7 @@
#include "llviewerprecompiledheaders.h"
#include "llfloaterauction.h"
+#include "llfloaterregioninfo.h"
#include "lldir.h"
#include "llgl.h"
@@ -56,6 +57,8 @@
#include "llviewercontrol.h"
#include "llui.h"
#include "llrender.h"
+#include "llsdutil.h"
+#include "llsdutil_math.h"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -77,7 +80,9 @@ LLFloaterAuction::LLFloaterAuction(const LLSD& key)
{
// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_auction.xml");
mCommitCallbackRegistrar.add("ClickSnapshot", boost::bind(&LLFloaterAuction::onClickSnapshot, this));
- mCommitCallbackRegistrar.add("ClickOK", boost::bind(&LLFloaterAuction::onClickOK, 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
@@ -97,6 +102,8 @@ void LLFloaterAuction::onOpen(const LLSD& key)
void LLFloaterAuction::initialize()
{
+ mParcelUpdateCapUrl.clear();
+
mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection();
LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
LLParcel* parcelp = mParcelp->getParcel();
@@ -104,10 +111,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
{
@@ -122,8 +142,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;
}
@@ -205,7 +228,7 @@ void LLFloaterAuction::onClickSnapshot(void* data)
}
// static
-void LLFloaterAuction::onClickOK(void* data)
+void LLFloaterAuction::onClickStartAuction(void* data)
{
LLFloaterAuction* self = (LLFloaterAuction*)(data);
@@ -244,11 +267,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->closeFloater();
+ 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 = LLNotification::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();
+ }
}
diff --git a/indra/newview/llfloaterauction.h b/indra/newview/llfloaterauction.h
index 1acc08057c..c599af782d 100644
--- a/indra/newview/llfloaterauction.h
+++ b/indra/newview/llfloaterauction.h
@@ -45,6 +45,8 @@
// Class which holds the functionality to start auctions.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
class LLParcelSelection;
+class LLParcel;
+class LLViewerRegion;
class LLFloaterAuction : public LLFloater
{
@@ -62,16 +64,28 @@ private:
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);
/*virtual*/ BOOL postBuild();
+
+ void doResetParcel();
+ void doSellToAnyone();
+ void clearParcelAccessLists( LLParcel* parcel, LLViewerRegion* region );
+ void cleanupAndClose();
+
private:
+
LLTransactionID mTransactionID;
LLAssetID mImageID;
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 890d863db7..8ac7f3fd7e 100644
--- a/indra/newview/llfloateravatarpicker.cpp
+++ b/indra/newview/llfloateravatarpicker.cpp
@@ -35,6 +35,7 @@
// Viewer includes
#include "llagent.h"
+#include "llcallingcard.h"
#include "llfocusmgr.h"
#include "llfloaterreg.h"
#include "llviewercontrol.h"
@@ -69,13 +70,14 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback,
// Default constructor
LLFloaterAvatarPicker::LLFloaterAvatarPicker(const LLSD& key)
: LLFloater(key),
- mResultsReturned(FALSE),
+ mNumResultsReturned(0),
mCallback(NULL),
mCallbackUserdata(NULL),
mNearMeListComplete(FALSE),
mCloseOnSelect(FALSE)
{
// LLUICtrlFactory::getInstance()->buildFloater(this, "floater_avatar_picker.xml");
+ mCommitCallbackRegistrar.add("Refresh.FriendList", boost::bind(&LLFloaterAvatarPicker::populateFriend, this));
}
BOOL LLFloaterAvatarPicker::postBuild()
@@ -95,7 +97,11 @@ BOOL LLFloaterAvatarPicker::postBuild()
LLScrollListCtrl* nearme = getChild<LLScrollListCtrl>("NearMe");
nearme->setDoubleClickCallback(onBtnSelect, this);
childSetCommitCallback("NearMe", onList, this);
-
+
+ LLScrollListCtrl* friends = getChild<LLScrollListCtrl>("Friends");
+ friends->setDoubleClickCallback(onBtnSelect, this);
+ childSetCommitCallback("Friends", onList, this);
+
childSetAction("Select", onBtnSelect, this);
childDisable("Select");
@@ -119,6 +125,8 @@ BOOL LLFloaterAvatarPicker::postBuild()
center();
+ populateFriend();
+
return TRUE;
}
@@ -159,25 +167,37 @@ void LLFloaterAvatarPicker::onBtnSelect(void* userdata)
if(self->mCallback)
{
+ std::string acvtive_panel_name;
+ LLScrollListCtrl* list = NULL;
LLPanel* active_panel = self->childGetVisibleTab("ResidentChooserTabs");
-
- if(active_panel == self->getChild<LLPanel>("SearchPanel"))
+ if(active_panel)
{
- 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);
+ acvtive_panel_name = active_panel->getName();
}
- else if(active_panel == self->getChild<LLPanel>("NearMePanel"))
+ if(acvtive_panel_name == "SearchPanel")
+ {
+ list = self->getChild<LLScrollListCtrl>("SearchResults");
+ }
+ else if(acvtive_panel_name == "NearMePanel")
+ {
+ list =self->getChild<LLScrollListCtrl>("NearMe");
+ }
+ else if (acvtive_panel_name == "FriendsPanel")
+ {
+ list =self->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);
+ getSelectedAvatarData(list, avatar_names, avatar_ids);
self->mCallback(avatar_names, avatar_ids, self->mCallbackUserdata);
}
}
self->getChild<LLScrollListCtrl>("SearchResults")->deselectAllItems(TRUE);
self->getChild<LLScrollListCtrl>("NearMe")->deselectAllItems(TRUE);
+ self->getChild<LLScrollListCtrl>("Friends")->deselectAllItems(TRUE);
if(self->mCloseOnSelect)
{
self->mCloseOnSelect = FALSE;
@@ -268,6 +288,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();
@@ -289,6 +329,10 @@ BOOL LLFloaterAvatarPicker::visibleItemsSelected() const
{
return getChild<LLScrollListCtrl>("NearMe")->getFirstSelectedIndex() >= 0;
}
+ else if(active_panel == getChild<LLPanel>("FriendsPanel"))
+ {
+ return getChild<LLScrollListCtrl>("Friends")->getFirstSelectedIndex() >= 0;
+ }
return FALSE;
}
@@ -314,13 +358,14 @@ void LLFloaterAvatarPicker::find()
getChild<LLScrollListCtrl>("SearchResults")->setCommentText(getString("searching"));
childSetEnabled("Select", FALSE);
- mResultsReturned = FALSE;
+ mNumResultsReturned = 0;
}
void LLFloaterAvatarPicker::setAllowMultiple(BOOL allow_multiple)
{
getChild<LLScrollListCtrl>("SearchResults")->setAllowMultipleSelection(allow_multiple);
getChild<LLScrollListCtrl>("NearMe")->setAllowMultipleSelection(allow_multiple);
+ getChild<LLScrollListCtrl>("Friends")->setAllowMultipleSelection(allow_multiple);
}
// static
@@ -349,9 +394,10 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void*
LLScrollListCtrl* search_results = floater->getChild<LLScrollListCtrl>("SearchResults");
// clear "Searching" label on first results
- search_results->deleteAllItems();
-
- floater->mResultsReturned = TRUE;
+ if (floater->mNumResultsReturned++ == 0)
+ {
+ search_results->deleteAllItems();
+ }
BOOL found_one = FALSE;
S32 num_new_rows = msg->getNumberOfBlocks("Data");
diff --git a/indra/newview/llfloateravatarpicker.h b/indra/newview/llfloateravatarpicker.h
index f3b9aefb9c..b8ace985d9 100644
--- a/indra/newview/llfloateravatarpicker.h
+++ b/indra/newview/llfloateravatarpicker.h
@@ -67,6 +67,7 @@ private:
void onTabChanged();
void populateNearMe();
+ void populateFriend();
BOOL visibleItemsSelected() const; // Returns true if any items in the current tab are selected.
void find();
@@ -76,7 +77,7 @@ private:
virtual BOOL handleKeyHere(KEY key, MASK mask);
LLUUID mQueryID;
- BOOL mResultsReturned;
+ int mNumResultsReturned;
BOOL mNearMeListComplete;
BOOL mCloseOnSelect;
diff --git a/indra/newview/llfloateravatartextures.cpp b/indra/newview/llfloateravatartextures.cpp
index 3976e25ba4..8c7899af3e 100644
--- a/indra/newview/llfloateravatartextures.cpp
+++ b/indra/newview/llfloateravatartextures.cpp
@@ -39,6 +39,7 @@
#include "lluictrlfactory.h"
#include "llviewerobjectlist.h"
#include "llvoavatar.h"
+#include "llagentwearables.h"
using namespace LLVOAvatarDefines;
@@ -79,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);
@@ -152,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/llfloaterbulkpermission.cpp b/indra/newview/llfloaterbulkpermission.cpp
index a73ebf4e06..538b44c056 100644
--- a/indra/newview/llfloaterbulkpermission.cpp
+++ b/indra/newview/llfloaterbulkpermission.cpp
@@ -72,8 +72,6 @@ LLFloaterBulkPermission::LLFloaterBulkPermission(const LLSD& seed)
BOOL LLFloaterBulkPermission::postBuild()
{
-// childSetAction("help", onHelpBtn, this); // this is not in use
-
return TRUE;
}
@@ -157,12 +155,6 @@ void LLFloaterBulkPermission::onApplyBtn()
doApply();
}
-// angela -- this is not in use
-//void LLFloaterBulkPermission::onHelpBtn(void* user_data)
-//{
-// LLNotifications::instance().add("HelpBulkPermission");
-//}
-
void LLFloaterBulkPermission::onCloseBtn()
{
closeFloater();
@@ -272,7 +264,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_FAVORITE && gSavedSettings.getBOOL("BulkChangeIncludeFavourite" )) ||
( asstype == LLAssetType::AT_NOTECARD && gSavedSettings.getBOOL("BulkChangeIncludeNotecards" )) ||
( asstype == LLAssetType::AT_OBJECT && gSavedSettings.getBOOL("BulkChangeIncludeObjects" )) ||
( asstype == LLAssetType::AT_LSL_TEXT && gSavedSettings.getBOOL("BulkChangeIncludeScripts" )) ||
diff --git a/indra/newview/llfloaterbulkpermission.h b/indra/newview/llfloaterbulkpermission.h
index c34e4413cc..31f4f5c3e1 100644
--- a/indra/newview/llfloaterbulkpermission.h
+++ b/indra/newview/llfloaterbulkpermission.h
@@ -79,7 +79,6 @@ private:
U8 key,
bool is_new);
-// static void onHelpBtn(void* user_data);
void onCloseBtn();
void onApplyBtn();
void onCommitCopy();
diff --git a/indra/newview/llfloaterbump.cpp b/indra/newview/llfloaterbump.cpp
index 8b64f913e0..68f06b1e5b 100644
--- a/indra/newview/llfloaterbump.cpp
+++ b/indra/newview/llfloaterbump.cpp
@@ -40,7 +40,6 @@
#include "llsd.h"
#include "lluictrlfactory.h"
#include "llviewermessage.h"
-#include "llappviewer.h" // gPacificDaylightTime
///----------------------------------------------------------------------------
/// Class LLFloaterBump
diff --git a/indra/newview/llfloaterbuy.cpp b/indra/newview/llfloaterbuy.cpp
index 9d07362edc..cefd7a3808 100644
--- a/indra/newview/llfloaterbuy.cpp
+++ b/indra/newview/llfloaterbuy.cpp
@@ -45,6 +45,7 @@
#include "llinventorymodel.h" // for gInventory
#include "llfloaterreg.h"
#include "llfloaterinventory.h" // for get_item_icon
+#include "llinventoryfunctions.h"
#include "llselectmgr.h"
#include "llscrolllistctrl.h"
#include "llviewerobject.h"
@@ -292,7 +293,7 @@ void LLFloaterBuy::onClickBuy()
{
// 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
diff --git a/indra/newview/llfloaterbuycontents.cpp b/indra/newview/llfloaterbuycontents.cpp
index 3a4171c6be..32802f6a20 100644
--- a/indra/newview/llfloaterbuycontents.cpp
+++ b/indra/newview/llfloaterbuycontents.cpp
@@ -45,6 +45,7 @@
#include "llagent.h" // for agent id
#include "llalertdialog.h"
#include "llcheckboxctrl.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h" // for gInventory
#include "llfloaterreg.h"
#include "llfloaterinventory.h" // for get_item_icon
@@ -280,12 +281,12 @@ void LLFloaterBuyContents::onClickBuy()
// We may want to wear this item
if (childGetValue("wear_check"))
{
- LLFloaterInventory::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_CATEGORY);
// *NOTE: doesn't work for multiple object buy, which UI does not
// currently support sale info is used for verification only, if
diff --git a/indra/newview/llfloaterbuycurrency.cpp b/indra/newview/llfloaterbuycurrency.cpp
index e160cd01be..651122f20a 100644
--- a/indra/newview/llfloaterbuycurrency.cpp
+++ b/indra/newview/llfloaterbuycurrency.cpp
@@ -152,6 +152,7 @@ void LLFloaterBuyCurrencyUI::draw()
{
if (mManager.bought())
{
+ LLNotifications::instance().add("BuyLindenDollarSuccess");
closeFloater();
return;
}
diff --git a/indra/newview/llfloaterbuyland.cpp b/indra/newview/llfloaterbuyland.cpp
index 2c2a5107f5..36f0315790 100644
--- a/indra/newview/llfloaterbuyland.cpp
+++ b/indra/newview/llfloaterbuyland.cpp
@@ -81,6 +81,8 @@ public:
LLFloaterBuyLandUI(const LLSD& key);
virtual ~LLFloaterBuyLandUI();
+ /*virtual*/ void onClose(bool app_quitting);
+
private:
class SelectionObserver : public LLParcelObserver
{
@@ -300,11 +302,21 @@ LLFloaterBuyLandUI::LLFloaterBuyLandUI(const LLSD& key)
LLFloaterBuyLandUI::~LLFloaterBuyLandUI()
{
LLViewerParcelMgr::getInstance()->removeObserver(&mParcelSelectionObserver);
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
delete mTransaction;
}
+// 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()
{
if (LLViewerParcelMgr::getInstance()->selectionEmpty())
@@ -756,7 +768,7 @@ void LLFloaterBuyLandUI::sendBuyLand()
if (mParcelBuyInfo)
{
LLViewerParcelMgr::getInstance()->sendParcelBuy(mParcelBuyInfo);
- LLViewerParcelMgr::getInstance()->deleteParcelBuy(mParcelBuyInfo);
+ LLViewerParcelMgr::getInstance()->deleteParcelBuy(&mParcelBuyInfo);
mBought = true;
}
}
diff --git a/indra/newview/llfloatercamera.cpp b/indra/newview/llfloatercamera.cpp
index db20b11efd..d1317f7c36 100644
--- a/indra/newview/llfloatercamera.cpp
+++ b/indra/newview/llfloatercamera.cpp
@@ -50,6 +50,8 @@ 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"
@@ -125,9 +127,15 @@ void LLFloaterCamera::onOpen(const LLSD& key)
}
+void LLFloaterCamera::onClose(bool app_quitting)
+{
+ //We don't care of camera mode if app is quitting
+ if(!app_quitting)
+ switchMode(CAMERA_CTRL_MODE_ORBIT);
+}
LLFloaterCamera::LLFloaterCamera(const LLSD& val)
-: LLDockableFloater(NULL, val),
+: LLTransientDockableFloater(NULL, true, val),
mCurrMode(CAMERA_CTRL_MODE_ORBIT),
mPrevMode(CAMERA_CTRL_MODE_ORBIT)
{
@@ -139,7 +147,7 @@ BOOL LLFloaterCamera::postBuild()
setIsChrome(TRUE);
mRotate = getChild<LLJoystickCameraRotate>(ORBIT);
- mZoom = getChild<LLJoystickCameraZoom>("zoom");
+ mZoom = getChild<LLJoystickCameraZoom>(ZOOM);
mTrack = getChild<LLJoystickCameraTrack>(PAN);
assignButton2Mode(CAMERA_CTRL_MODE_ORBIT, "orbit_btn");
@@ -210,7 +218,6 @@ void LLFloaterCamera::switchMode(ECameraControlMode mode)
break;
case CAMERA_CTRL_MODE_AVATAR_VIEW:
- gAgent.changeCameraToMouselook();
break;
default:
@@ -246,15 +253,13 @@ void LLFloaterCamera::updateState()
iter->second->setToggleState(iter->first == mCurrMode);
}
- //updating controls
- bool isOrbitMode = CAMERA_CTRL_MODE_ORBIT == mCurrMode;
- bool isPanMode = CAMERA_CTRL_MODE_PAN == mCurrMode;
-
- childSetVisible(ORBIT, isOrbitMode);
- childSetVisible(PAN, isPanMode);
+ 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 = isOrbitMode || isPanMode;
+ bool showControls = CAMERA_CTRL_MODE_FREE_CAMERA != mCurrMode;
if (showControls == childIsVisible(CONTROLS)) return;
childSetVisible(CONTROLS, showControls);
@@ -263,8 +268,8 @@ void LLFloaterCamera::updateState()
LLRect controls_rect;
if (childGetRect(CONTROLS, controls_rect))
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
- static S32 height = controls_rect.getHeight() - floater_header_size;
+ S32 floater_header_size = getHeaderHeight();
+ S32 height = controls_rect.getHeight() - floater_header_size;
S32 newHeight = rect.getHeight();
if (showControls)
@@ -283,29 +288,7 @@ void LLFloaterCamera::updateState()
}
}
-//-------------LLFloaterCameraPresets------------------------
-
-LLFloaterCameraPresets::LLFloaterCameraPresets(const LLSD& key):
-LLDockableFloater(NULL, key)
-{}
-
-BOOL LLFloaterCameraPresets::postBuild()
-{
- setIsChrome(TRUE);
-
- //build dockTongue
- LLDockableFloater::postBuild();
-
- LLButton *anchor_btn = LLBottomTray::getInstance()->getChild<LLButton>("camera_presets_btn");
-
- setDockControl(new LLDockControl(
- anchor_btn, this,
- getDockTongue(), LLDockControl::TOP));
- return TRUE;
-}
-
-/*static*/
-void LLFloaterCameraPresets::onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param)
+void LLFloaterCamera::onClickCameraPresets(const LLSD& param)
{
std::string name = param.asString();
@@ -321,5 +304,9 @@ void LLFloaterCameraPresets::onClickCameraPresets(LLUICtrl* ctrl, const LLSD& pa
{
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 69df861a20..583f279e62 100644
--- a/indra/newview/llfloatercamera.h
+++ b/indra/newview/llfloatercamera.h
@@ -33,7 +33,7 @@
#ifndef LLFLOATERCAMERA_H
#define LLFLOATERCAMERA_H
-#include "lldockablefloater.h"
+#include "lltransientdockablefloater.h"
class LLJoystickCameraRotate;
class LLJoystickCameraZoom;
@@ -49,7 +49,7 @@ enum ECameraControlMode
};
class LLFloaterCamera
- : public LLDockableFloater
+ : public LLTransientDockableFloater
{
friend class LLFloaterReg;
@@ -57,6 +57,8 @@ public:
/* whether in free camera mode */
static bool inFreeCameraMode();
+ /* callback for camera presets changing */
+ static void onClickCameraPresets(const LLSD& param);
static void toPrevModeIfInAvatarViewMode();
@@ -69,6 +71,7 @@ public:
static void updateIfNotInAvatarViewMode();
virtual void onOpen(const LLSD& key);
+ virtual void onClose(bool app_quitting);
LLJoystickCameraRotate* mRotate;
LLJoystickCameraZoom* mZoom;
@@ -111,15 +114,4 @@ private:
};
-class LLFloaterCameraPresets : public LLDockableFloater
-{
- friend class LLFloaterReg;
-public:
- static void onClickCameraPresets(LLUICtrl* ctrl, const LLSD& param);
-private:
- LLFloaterCameraPresets(const LLSD&);
- ~LLFloaterCameraPresets(){}
- /*virtual*/ BOOL postBuild();
-
-};
#endif
diff --git a/indra/newview/llfloaterchat.cpp b/indra/newview/llfloaterchat.cpp
index 6d2e959352..ed14079ae9 100644
--- a/indra/newview/llfloaterchat.cpp
+++ b/indra/newview/llfloaterchat.cpp
@@ -182,13 +182,7 @@ void add_timestamped_line(LLViewerTextEditor* edit, LLChat chat, const LLColor4&
void log_chat_text(const LLChat& chat)
{
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + chat.mText;
- else
- histstr = chat.mText;
-
- LLLogChat::saveHistory(std::string("chat"),histstr);
+ LLLogChat::saveHistory(std::string("chat"), chat.mFromName, chat.mFromID, chat.mText);
}
// static
void LLFloaterChat::addChatHistory(const LLChat& chat, bool log_to_file)
@@ -204,12 +198,14 @@ 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;
}
}
@@ -315,9 +311,9 @@ void LLFloaterChat::addChat(const LLChat& chat,
{
LLColor4 text_color = get_text_color(chat);
- BOOL invisible_script_debug_chat =
- chat.mChatType == CHAT_TYPE_DEBUG_MSG
- && !gSavedSettings.getBOOL("ScriptErrorsAsChat");
+ BOOL invisible_script_debug_chat = ((gSavedSettings.getBOOL("ShowScriptErrors") == FALSE) ||
+ (chat.mChatType == CHAT_TYPE_DEBUG_MSG
+ && (gSavedSettings.getS32("ShowScriptErrorsLocation") == 1)));
if (!invisible_script_debug_chat
&& !chat.mMuted
@@ -474,7 +470,7 @@ void LLFloaterChat::loadHistory()
}
//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)
{
@@ -483,9 +479,10 @@ 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);
}
diff --git a/indra/newview/llfloaterchat.h b/indra/newview/llfloaterchat.h
index 6ba3165d6a..aed82a6781 100644
--- a/indra/newview/llfloaterchat.h
+++ b/indra/newview/llfloaterchat.h
@@ -78,7 +78,7 @@ public:
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);
diff --git a/indra/newview/llfloaterchatterbox.cpp b/indra/newview/llfloaterchatterbox.cpp
index dea656b0e4..fbf09207fe 100644
--- a/indra/newview/llfloaterchatterbox.cpp
+++ b/indra/newview/llfloaterchatterbox.cpp
@@ -42,7 +42,7 @@
#include "llfloaterfriends.h"
#include "llfloatergroups.h"
#include "llviewercontrol.h"
-#include "llimview.h"
+#include "llvoicechannel.h"
#include "llimpanel.h"
//
diff --git a/indra/newview/llfloatercolorpicker.cpp b/indra/newview/llfloatercolorpicker.cpp
index 8e385fca78..73b79d8e13 100644
--- a/indra/newview/llfloatercolorpicker.cpp
+++ b/indra/newview/llfloatercolorpicker.cpp
@@ -561,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 );
@@ -591,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 );
@@ -607,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 );
diff --git a/indra/newview/llfloaterdaycycle.cpp b/indra/newview/llfloaterdaycycle.cpp
index 7f3b988dfe..48d552022f 100644
--- a/indra/newview/llfloaterdaycycle.cpp
+++ b/indra/newview/llfloaterdaycycle.cpp
@@ -105,20 +105,8 @@ LLFloaterDayCycle::~LLFloaterDayCycle()
{
}
-void LLFloaterDayCycle::onClickHelp(std::string xml_alert)
-{
- LLNotifications::instance().add(contextualNotification(xml_alert));
-}
-
-void LLFloaterDayCycle::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- getChild<LLButton>(name)->setClickedCallback(boost::bind(&LLFloaterDayCycle::onClickHelp, this, xml_alert));
-}
-
void LLFloaterDayCycle::initCallbacks(void)
{
- initHelpBtn("WLDayCycleHelp", "HelpDayCycle");
-
// WL Day Cycle
getChild<LLUICtrl>("WLTimeSlider")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onTimeSliderMoved, this, _1));
getChild<LLUICtrl>("WLDayCycleKeys")->setCommitCallback(boost::bind(&LLFloaterDayCycle::onKeyTimeMoved, this, _1));
diff --git a/indra/newview/llfloaterdaycycle.h b/indra/newview/llfloaterdaycycle.h
index 43c347d4f2..c250902b65 100644
--- a/indra/newview/llfloaterdaycycle.h
+++ b/indra/newview/llfloaterdaycycle.h
@@ -59,9 +59,6 @@ public:
LLFloaterDayCycle(const LLSD& key);
virtual ~LLFloaterDayCycle();
/*virtual*/ BOOL postBuild();
- /// help button stuff
- void onClickHelp(std::string xml_alert);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
/// initialize all
void initCallbacks(void);
diff --git a/indra/newview/llfloaterenvsettings.cpp b/indra/newview/llfloaterenvsettings.cpp
index a520df36de..2fffa6eece 100644
--- a/indra/newview/llfloaterenvsettings.cpp
+++ b/indra/newview/llfloaterenvsettings.cpp
@@ -70,10 +70,6 @@ BOOL LLFloaterEnvSettings::postBuild()
syncMenu();
return TRUE;
}
-void LLFloaterEnvSettings::onClickHelp()
-{
- LLNotifications::instance().add(contextualNotification("EnvSettingsHelpButton"));
-}
void LLFloaterEnvSettings::initCallbacks(void)
{
@@ -89,10 +85,8 @@ void LLFloaterEnvSettings::initCallbacks(void)
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));
- getChild<LLUICtrl>("EnvSettingsHelpButton")->setCommitCallback(boost::bind(&LLFloaterEnvSettings::onClickHelp, this));
}
-
// menu maintenance functions
void LLFloaterEnvSettings::syncMenu()
diff --git a/indra/newview/llfloaterenvsettings.h b/indra/newview/llfloaterenvsettings.h
index 083e3636d1..02bc502120 100644
--- a/indra/newview/llfloaterenvsettings.h
+++ b/indra/newview/llfloaterenvsettings.h
@@ -53,9 +53,6 @@ public:
/// initialize all the callbacks for the menu
void initCallbacks(void);
- /// callback for the menus help button
- void onClickHelp();
-
/// handle if time of day is changed
void onChangeDayTime(LLUICtrl* ctrl);
diff --git a/indra/newview/llfloaterfriends.h b/indra/newview/llfloaterfriends.h
index 9242f00c91..9c6660c0dc 100644
--- a/indra/newview/llfloaterfriends.h
+++ b/indra/newview/llfloaterfriends.h
@@ -74,6 +74,9 @@ public:
virtual BOOL postBuild();
+ // *HACK Made public to remove friends from LLAvatarIconCtrl context menu
+ static bool handleRemove(const LLSD& notification, const LLSD& response);
+
private:
enum FRIENDS_COLUMN_ORDER
diff --git a/indra/newview/llfloatergesture.cpp b/indra/newview/llfloatergesture.cpp
index e0fe87f9ae..c114eed4a2 100644
--- a/indra/newview/llfloatergesture.cpp
+++ b/indra/newview/llfloatergesture.cpp
@@ -44,6 +44,7 @@
#include "llcombobox.h"
#include "llgesturemgr.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llfloaterinventory.h"
#include "llkeyboard.h"
#include "lllineeditor.h"
@@ -211,25 +212,16 @@ void LLFloaterGesture::buildGestureList()
std::string key_string = LLKeyboard::stringFromKey(gesture->mKey);
std::string buffer;
+ if (gesture->mKey == KEY_NONE)
{
- 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);
- }
+ buffer = "---";
+ key_string = "~~~"; // alphabetize to end
}
+ else
+ {
+ buffer = LLKeyboard::stringFromAccelerator( gesture->mMask, gesture->mKey );
+ }
+
element["columns"][1]["column"] = "shortcut";
element["columns"][1]["value"] = buffer;
element["columns"][1]["font"]["name"] = "SANSSERIF";
diff --git a/indra/newview/llfloatergroupinvite.cpp b/indra/newview/llfloatergroupinvite.cpp
index 3598479305..bf484c6343 100644
--- a/indra/newview/llfloatergroupinvite.cpp
+++ b/indra/newview/llfloatergroupinvite.cpp
@@ -81,7 +81,7 @@ void LLFloaterGroupInvite::impl::closeFloater(void* data)
LLFloaterGroupInvite::LLFloaterGroupInvite(const LLUUID& group_id)
: LLFloater(group_id)
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ S32 floater_header_size = getHeaderHeight();
LLRect contents;
mImpl = new impl(group_id);
@@ -114,7 +114,8 @@ LLFloaterGroupInvite::~LLFloaterGroupInvite()
// static
void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id, std::vector<LLUUID> *agent_ids)
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
LLRect contents;
// Make sure group_id isn't null
diff --git a/indra/newview/llfloatergroups.cpp b/indra/newview/llfloatergroups.cpp
index 3648898f28..45af515a86 100644
--- a/indra/newview/llfloatergroups.cpp
+++ b/indra/newview/llfloatergroups.cpp
@@ -89,15 +89,6 @@ BOOL LLFloaterGroupPicker::postBuild()
list_ctrl->setContextMenu(LLScrollListCtrl::MENU_GROUP);
}
- // 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 = list_ctrl->getListInterface();
- if(group_list)
- {
- group_list->selectByValue(LLUUID::null);
- group_list->operateOnSelection(LLCtrlListInterface::OP_DELETE);
- }
childSetAction("OK", onBtnOK, this);
@@ -110,6 +101,20 @@ BOOL LLFloaterGroupPicker::postBuild()
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;
diff --git a/indra/newview/llfloatergroups.h b/indra/newview/llfloatergroups.h
index 489238356d..ce3a470a23 100644
--- a/indra/newview/llfloatergroups.h
+++ b/indra/newview/llfloatergroups.h
@@ -72,6 +72,9 @@ 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:
void ok();
static void onBtnOK(void* userdata);
diff --git a/indra/newview/llfloaterhardwaresettings.cpp b/indra/newview/llfloaterhardwaresettings.cpp
index 3c3508b65c..31b494b590 100644
--- a/indra/newview/llfloaterhardwaresettings.cpp
+++ b/indra/newview/llfloaterhardwaresettings.cpp
@@ -47,7 +47,7 @@
#include "llradiogroup.h"
#include "lluictrlfactory.h"
#include "llwindow.h"
-#include "llslider.h"
+#include "llsliderctrl.h"
LLFloaterHardwareSettings::LLFloaterHardwareSettings(const LLSD& key)
: LLFloater(key)
@@ -59,12 +59,6 @@ LLFloaterHardwareSettings::~LLFloaterHardwareSettings()
{
}
-void LLFloaterHardwareSettings::onClickHelp(void* data)
-{
- const char* xml_alert = "HardwareSettingsHelpButton";
- LLNotifications::instance().add(xml_alert);
-}
-
void LLFloaterHardwareSettings::initCallbacks(void)
{
}
@@ -91,8 +85,8 @@ void LLFloaterHardwareSettings::refreshEnabledState()
{
S32 min_tex_mem = LLViewerTextureList::getMinVideoRamSetting();
S32 max_tex_mem = LLViewerTextureList::getMaxVideoRamSetting();
- getChild<LLSlider>("GrapicsCardTextureMemory")->setMinValue(min_tex_mem);
- getChild<LLSlider>("GrapicsCardTextureMemory")->setMinValue(max_tex_mem);
+ getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMinValue(min_tex_mem);
+ getChild<LLSliderCtrl>("GraphicsCardTextureMemory")->setMaxValue(max_tex_mem);
if (!LLFeatureManager::getInstance()->isFeatureAvailable("RenderVBOEnable") ||
!gGLManager.mHasVertexBufferObject)
diff --git a/indra/newview/llfloaterhardwaresettings.h b/indra/newview/llfloaterhardwaresettings.h
index 3f19d89cbb..ef0b0c905e 100644
--- a/indra/newview/llfloaterhardwaresettings.h
+++ b/indra/newview/llfloaterhardwaresettings.h
@@ -50,9 +50,6 @@ public:
/// initialize all the callbacks for the menu
void initCallbacks(void);
- /// callback for the menus help button
- static void onClickHelp(void* data);
-
/// OK button
static void onBtnOK( void* userdata );
diff --git a/indra/newview/llfloaterinventory.cpp b/indra/newview/llfloaterinventory.cpp
index d9cd929606..92778510e7 100644
--- a/indra/newview/llfloaterinventory.cpp
+++ b/indra/newview/llfloaterinventory.cpp
@@ -32,538 +32,35 @@
#include "llviewerprecompiledheaders.h"
-#include <utility> // for std::pair<>
-
#include "llfloaterinventory.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 "llappviewer.h"
#include "llfirstuse.h"
-#include "llfloaterchat.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 "llfloaterreg.h"
#include "llinventorymodel.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 "llpanelmaininventory.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"
-
-static LLDefaultChildRegistry::Register<LLInventoryPanel> r("inventory_panel");
-
-//BOOL LLFloaterInventory::sOpenNextNewItem = FALSE;
-BOOL LLFloaterInventory::sWearNewClothing = FALSE;
-LLUUID LLFloaterInventory::sWearNewClothingTransactionID;
-
-///----------------------------------------------------------------------------
-/// LLFloaterInventoryFinder
-///----------------------------------------------------------------------------
-
-LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLFloaterInventory* inventory_view)
-: LLFloater(LLSD()),
- mFloaterInventory(inventory_view),
- mFilter(inventory_view->mActivePanel->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 = mFloaterInventory->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->getFilterTypes();
- std::string filter_string = mFilter->getFilterSubString();
- LLInventoryFilter::EFolderShow show_folders = mFilter->getShowFolderState();
- U32 hours = mFilter->getHoursAgo();
-
- // update the ui elements
- LLFloater::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
- mFloaterInventory->mActivePanel->setShowFolderState(getCheckShowEmpty() ?
- LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mFloaterInventory->mActivePanel->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;
- mFloaterInventory->mActivePanel->setHoursAgo(hours);
- mFloaterInventory->mActivePanel->setSinceLogoff(getCheckSinceLogoff());
- mFloaterInventory->setFilterTextFromFilter();
-
- LLFloater::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);
-
-/*
- self->mCheckCallingCard->set(TRUE);
- self->mCheckClothing->set(TRUE);
- self->mCheckGesture->set(TRUE);
- self->mCheckLandmark->set(TRUE);
- self->mCheckNotecard->set(TRUE);
- self->mCheckObject->set(TRUE);
- self->mCheckScript->set(TRUE);
- self->mCheckSound->set(TRUE);
- self->mCheckTexture->set(TRUE);
- self->mCheckSnapshot->set(TRUE);*/
-}
-
-//static
-void LLFloaterInventoryFinder::selectNoTypes(void* user_data)
-{
- LLFloaterInventoryFinder* self = (LLFloaterInventoryFinder*)user_data;
- if(!self) return;
-
- /*
- self->childSetValue("check_animation", FALSE);
- self->mCheckCallingCard->set(FALSE);
- self->mCheckClothing->set(FALSE);
- self->mCheckGesture->set(FALSE);
- self->mCheckLandmark->set(FALSE);
- self->mCheckNotecard->set(FALSE);
- self->mCheckObject->set(FALSE);
- self->mCheckScript->set(FALSE);
- self->mCheckSound->set(FALSE);
- self->mCheckTexture->set(FALSE);
- self->mCheckSnapshot->set(FALSE);*/
-
-
- 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);
-}
-
+#include "llviewerfoldertype.h"
///----------------------------------------------------------------------------
/// LLFloaterInventory
///----------------------------------------------------------------------------
-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());
- }
- }
-}
LLFloaterInventory::LLFloaterInventory(const LLSD& key)
: LLFloater(key)
{
- LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_INIT);
- // Menu Callbacks (non contex menus)
- mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLFloaterInventory::doToSelected, this, _2));
- mCommitCallbackRegistrar.add("Inventory.CloseAllFolders", boost::bind(&LLFloaterInventory::closeAllFolders, this));
- mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH));
- mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_LOST_AND_FOUND));
- mCommitCallbackRegistrar.add("Inventory.DoCreate", boost::bind(&LLFloaterInventory::doCreate, this, _2));
-// mCommitCallbackRegistrar.add("Inventory.NewWindow", boost::bind(&LLFloaterInventory::newWindow, this));
- mCommitCallbackRegistrar.add("Inventory.ShowFilters", boost::bind(&LLFloaterInventory::toggleFindOptions, this));
- mCommitCallbackRegistrar.add("Inventory.ResetFilters", boost::bind(&LLFloaterInventory::resetFilters, this));
- mCommitCallbackRegistrar.add("Inventory.SetSortBy", boost::bind(&LLFloaterInventory::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);
+}
- //Called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_inventory.xml");
+LLFloaterInventory::~LLFloaterInventory()
+{
}
BOOL LLFloaterInventory::postBuild()
{
- gInventory.addObserver(this);
-
- mFilterTabs = getChild<LLTabContainer>("inventory filter tabs");
- mFilterTabs->setCommitCallback(boost::bind(&LLFloaterInventory::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(&LLInventoryPanel::onSelectionChange, 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(&LLInventoryPanel::onSelectionChange, 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.xml");
- llinfos << "LLFloaterInventory::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(&LLFloaterInventory::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);
-
+ mPanelMainInventory = getChild<LLPanelMainInventory>("Inventory Panel");
return TRUE;
}
-// Destroys the object
-LLFloaterInventory::~LLFloaterInventory( 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();
- 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();
- LLSD filterState;
- filter->toLLSD(filterState);
- filterRoot[filter->getName()] = filterState;
- }
-
- std::ostringstream filterSaveName;
- filterSaveName << gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "filters.xml");
- 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 LLFloaterInventory::draw()
{
@@ -574,113 +71,6 @@ void LLFloaterInventory::draw()
LLFloater::draw();
}
-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);
- }
-}
-
-void LLFloaterInventory::startSearch()
-{
- // this forces focus to line editor portion of search editor
- if (mFilterEditor)
- {
- mFilterEditor->focusFirstItem(TRUE);
- }
-}
-
-void LLFloaterInventory::onOpen(const LLSD& key)
-{
- LLFirstUse::useInventory();
-}
-
-BOOL LLFloaterInventory::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 LLFloater::handleKeyHere(key, mask);
-
-}
-
void LLFloaterInventory::updateTitle()
{
LLLocale locale(LLLocale::USER_LOCALE);
@@ -689,7 +79,7 @@ void LLFloaterInventory::updateTitle()
LLStringUtil::format_map_t string_args;
string_args["[ITEM_COUNT]"] = item_count_string;
- string_args["[FILTER]"] = mFilterText;
+ string_args["[FILTER]"] = mPanelMainInventory->getFilterText();
if (LLInventoryModel::backgroundFetchActive())
{
@@ -698,102 +88,21 @@ void LLFloaterInventory::updateTitle()
else
{
setTitle(getString("TitleCompleted", string_args));
- }
+ }
}
-
void LLFloaterInventory::changed(U32 mask)
{
updateTitle();
}
-//----------------------------------------------------------------------------
-// menu callbacks
-
-void LLFloaterInventory::doToSelected(const LLSD& userdata)
-{
- getPanel()->getRootFolder()->doToSelected(&gInventory, userdata);
-}
-
-void LLFloaterInventory::closeAllFolders()
-{
- getPanel()->getRootFolder()->closeAllFolders();
-}
-
-void LLFloaterInventory::doCreate(const LLSD& userdata)
+LLInventoryPanel* LLFloaterInventory::getPanel()
{
- menu_create_inventory_item(getPanel()->getRootFolder(), NULL, userdata);
+ if (mPanelMainInventory)
+ return mPanelMainInventory->getPanel();
+ return NULL;
}
-void LLFloaterInventory::resetFilters()
-{
- LLFloaterInventoryFinder *finder = getFinder();
- getActivePanel()->getFilter()->resetDefault();
- if (finder)
- {
- finder->updateElementsFromFilter();
- }
-
- setFilterTextFromFilter();
-}
-
-void LLFloaterInventory::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
LLFloaterInventory* LLFloaterInventory::showAgentInventory()
{
@@ -841,1060 +150,7 @@ void LLFloaterInventory::cleanup()
}
}
-void LLFloaterInventory::toggleFindOptions()
-{
- LLMemType mt(LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE);
- LLFloater *floater = getFinder();
- if (!floater)
- {
- LLFloaterInventoryFinder * finder = new LLFloaterInventoryFinder(this);
- mFinderHandle = finder->getHandle();
- finder->openFloater();
- addDependentFloater(mFinderHandle);
-
- // start background fetch of folders
- gInventory.startBackgroundFetch();
- }
- else
- {
- floater->closeFloater();
- }
-}
-
-// static
-BOOL LLFloaterInventory::filtersVisible(void* user_data)
-{
- LLFloaterInventory* self = (LLFloaterInventory*)user_data;
- if(!self) return FALSE;
-
- return self->getFinder() != NULL;
-}
-
-void LLFloaterInventory::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();
- }
-}
-
-void LLFloaterInventory::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);
- 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(uppercase_search_string);
-}
-
-
- //static
- BOOL LLFloaterInventory::incrementalFind(LLFolderViewItem* first_item, const char *find_text, BOOL backward)
- {
- LLFloaterInventory* 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)
- {
- LLFloaterInventory* iv = dynamic_cast<LLFloaterInventory*>(*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->mActivePanel &&
- active_view->mActivePanel->getRootFolder()->search(first_item, search_string, backward))
- {
- return TRUE;
- }
-
- return FALSE;
- }
-
-void LLFloaterInventory::onFilterSelected()
-{
- // Find my index
- mActivePanel = (LLInventoryPanel*)childGetVisibleTab("inventory filter tabs");
-
- if (!mActivePanel)
- {
- return;
- }
- 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();
-}
-
-BOOL LLFloaterInventory::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 = LLFloater::handleDragAndDrop(x, y, mask, drop, cargo_type, cargo_data, accept, tooltip_msg);
-
- return handled;
-}
-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_FAVORITE:
- //TODO - need bette idx
- idx = LANDMARK_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);
-}
-
-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("");
-
-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),
- mHasInventoryConnection(false)
-{
- // contex menu callbacks
- mCommitCallbackRegistrar.add("Inventory.DoToSelected", boost::bind(&LLInventoryPanel::doToSelected, this, _2));
- mCommitCallbackRegistrar.add("Inventory.EmptyTrash", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyTrash", LLAssetType::AT_TRASH));
- mCommitCallbackRegistrar.add("Inventory.EmptyLostAndFound", boost::bind(&LLInventoryModel::emptyFolderType, &gInventory, "ConfirmEmptyLostAndFound", LLAssetType::AT_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));
-
- setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor"));
- setBackgroundVisible(TRUE);
- setBackgroundOpaque(TRUE);
-}
-
-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;
- 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 inventory ready, otherwise wait for modelChanged() callback
- if (mInventory->isInventoryUsable() && !mHasInventoryConnection)
- {
- rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
- mHasInventoryConnection = true;
- }
-
- // bit of a hack to make sure the inventory is open.
- mFolders->openFolder(std::string("My Inventory"));
-
- if (mSortOrderSetting != INHERIT_SORT_ORDER)
- {
- setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
- }
- else
- {
- setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
- }
- mFolders->setSortOrder(mFolders->getFilter()->getSortOrder());
-
- return TRUE;
-}
-
-LLInventoryPanel::~LLInventoryPanel()
-{
- // should this be a global setting?
- 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;
-}
-
- LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML);
-void LLInventoryPanel::draw()
-{
- // select the desired item (in case it wasn't loaded when the selection was requested)
- mFolders->updateSelection();
- LLPanel::draw();
-}
-
-void LLInventoryPanel::setFilterTypes(U64 filter_types, BOOL filter_for_categories)
-{
- mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories);
-}
-
-void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
-{
- mFolders->getFilter()->setFilterPermissions(filter_perm_mask);
-}
-
-void LLInventoryPanel::setFilterSubString(const std::string& string)
-{
- mFolders->getFilter()->setFilterSubString(string);
-}
-
-void LLInventoryPanel::setSortOrder(U32 order)
-{
- mFolders->getFilter()->setSortOrder(order);
- if (mFolders->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)
-{
- mFolders->getFilter()->setDateRangeLastLogoff(sl);
-}
-
-void LLInventoryPanel::setHoursAgo(U32 hours)
-{
- mFolders->getFilter()->setHoursAgo(hours);
-}
-
-void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
-{
- mFolders->getFilter()->setShowFolderState(show);
-}
-
-LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
-{
- return mFolders->getFilter()->getShowFolderState();
-}
-
-static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
-
-void LLInventoryPanel::modelChanged(U32 mask)
-{
- LLFastTimer t2(FTM_REFRESH);
-
- bool handled = false;
-
- // inventory just initialized, do complete build
- if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
- {
- rebuildViewsFor(LLUUID::null, LLInventoryObserver::ADD);
- mHasInventoryConnection = true;
- return;
- }
-
- if(mask & LLInventoryObserver::LABEL)
- {
- handled = true;
- // label change - empty out the display name for each object
- // in this change set.
- const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
- std::set<LLUUID>::const_iterator id_it = changed_items.begin();
- std::set<LLUUID>::const_iterator id_end = changed_items.end();
- LLFolderViewItem* view = NULL;
- LLInvFVBridge* bridge = NULL;
- for (;id_it != id_end; ++id_it)
- {
- view = mFolders->getItemByID(*id_it);
- if(view)
- {
- // request refresh on this item (also flags for filtering)
- bridge = (LLInvFVBridge*)view->getListener();
- if(bridge)
- { // Clear the display name first, so it gets properly re-built during refresh()
- bridge->clearDisplayName();
- }
- view->refresh();
- }
- }
- }
- if((mask & (LLInventoryObserver::STRUCTURE
- | LLInventoryObserver::ADD
- | LLInventoryObserver::REMOVE)) != 0)
- {
- handled = true;
- // Record which folders are open by uuid.
- LLInventoryModel* model = getModel();
- if (model)
- {
- const std::set<LLUUID>& changed_items = gInventory.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)
- {
- // sync view with model
- LLInventoryObject* model_item = model->getObject(*id_it);
- LLFolderViewItem* view_item = mFolders->getItemByID(*id_it);
-
- if (model_item)
- {
- if (!view_item)
- {
- // this object was just created, need to build a view for it
- if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD)
- {
- llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl;
- }
- buildNewViews(*id_it);
-
- // select any newly created object
- // that has the auto rename at top of folder
- // root set
- if(mFolders->getRoot()->needsAutoRename())
- {
- setSelection(*id_it, FALSE);
- }
- }
- else
- {
- // this object was probably moved, check its parent
- if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE)
- {
- llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl;
- }
-
- LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
- if (view_item->getParentFolder() != new_parent)
- {
- view_item->getParentFolder()->extractItem(view_item);
- view_item->addToFolder(new_parent, mFolders);
- }
- }
- }
- else
- {
- if (view_item)
- {
- if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE)
- {
- llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl;
- }
- // item in view but not model, need to delete view
- view_item->destroyView();
- }
- else
- {
- llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl;
- }
- }
- }
- }
- }
-
- if (!handled)
- {
- // it's a small change that only requires a refresh.
- // *TODO: figure out a more efficient way to do the refresh
- // since it is expensive on large inventories
- mFolders->refresh();
- }
-}
-
-void LLInventoryPanel::rebuildViewsFor(const LLUUID& id, U32 mask)
-{
- LLFolderViewItem* old_view = NULL;
-
- // get old 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)
- {
- if (objectp->getType() <= LLAssetType::AT_NONE ||
- objectp->getType() >= LLAssetType::AT_COUNT)
- {
- llwarns << "LLInventoryPanel::buildNewViews called with objectp->mType == "
- << ((S32) objectp->getType())
- << " (shouldn't happen)" << llendl;
- }
- else if (objectp->getType() == LLAssetType::AT_CATEGORY &&
- objectp->getActualType() != LLAssetType::AT_LINK_FOLDER)
- {
- LLInvFVBridge* new_listener = LLInvFVBridge::createBridge(objectp->getType(),
- objectp->getType(),
- LLInventoryType::IT_CATEGORY,
- this,
- objectp->getUUID());
-
- if (new_listener)
- {
- LLFolderViewFolder::Params p;
- p.name = new_listener->getDisplayName();
- p.icon = LLUI::getUIImage("Inv_FolderClosed");
- p.icon_open = LLUI::getUIImage("Inv_FolderOpen");
- p.root = mFolders;
- p.listener = new_listener;
- LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p);
-
- folderp->setItemSortOrder(mFolders->getSortOrder());
- itemp = folderp;
- }
- }
- else
- {
- // Build new view for item
- LLInventoryItem* item = (LLInventoryItem*)objectp;
- LLInvFVBridge* new_listener = LLInvFVBridge::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.creation_date(new_listener->getCreationDate());
- params.root(mFolders);
- params.listener(new_listener);
- params.rect(LLRect (0, 0, 0, 0));
- itemp = LLUICtrlFactory::create<LLFolderViewItem> (params);
- }
- }
-
- LLFolderViewFolder* parent_folder = (LLFolderViewFolder*)mFolders->getItemByID(objectp->getParentUUID());
-
- if (itemp)
- {
- if (parent_folder)
- {
- itemp->addToFolder(parent_folder, mFolders);
- }
- else
- {
- llwarns << "Couldn't find parent folder for child " << itemp->getLabel() << llendl;
- delete itemp;
- }
- }
- }
- if ((id.isNull() ||
- (objectp && objectp->getType() == LLAssetType::AT_CATEGORY)))
- {
- LLViewerInventoryCategory::cat_array_t* categories;
- LLViewerInventoryItem::item_array_t* items;
-
- mInventory->lockDirectDescendentArrays(id, categories, items);
- if(categories)
- {
- S32 count = categories->count();
- for(S32 i = 0; i < count; ++i)
- {
- LLInventoryCategory* cat = categories->get(i);
- buildNewViews(cat->getUUID());
- }
- }
- if(items)
- {
- S32 count = items->count();
- for(S32 i = 0; i < count; ++i)
- {
- LLInventoryItem* item = items->get(i);
- buildNewViews(item->getUUID());
- }
- }
- mInventory->unlockDirectDescendentArrays(id);
- }
-}
-
-struct LLConfirmPurgeData
-{
- LLUUID mID;
- LLInventoryModel* mModel;
-};
-
-class LLIsNotWorn : public LLInventoryCollectFunctor
-{
-public:
- LLIsNotWorn() {}
- virtual ~LLIsNotWorn() {}
- virtual bool operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
- {
- return !gAgentWearables.isWearingItem(item->getUUID());
- }
-};
-
-class LLOpenFolderByID : public LLFolderViewFunctor
-{
-public:
- LLOpenFolderByID(const LLUUID& id) : mID(id) {}
- virtual ~LLOpenFolderByID() {}
- virtual void doFolder(LLFolderViewFolder* folder)
- {
- if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
- }
- virtual void doItem(LLFolderViewItem* item) {}
-protected:
- const LLUUID& mID;
-};
-
-
-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 (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::openDefaultFolderForType(LLAssetType::EType type)
-{
- LLUUID category_id = mInventory->findCategoryUUIDForType(type);
- LLOpenFolderByID opener(category_id);
- mFolders->applyFunctorRecursively(opener);
-}
-
-void LLInventoryPanel::setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus)
-{
- mFolders->setSelectionByID(obj_id, take_keyboard_focus);
-}
-
-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++);
- }
-
- gIMMgr->addSession(name, type, members[0], members);
-
- return true;
-}
-
-bool LLInventoryPanel::attachObject(const LLSD& userdata)
-{
- std::set<LLUUID> selected_items;
- mFolders->getSelectionList(selected_items);
- LLUUID id = *selected_items.begin();
-
- 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;
- }
- 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;
-}
-
-
-//----------------------------------------------------------------------------
-
-// static DEBUG ONLY:
-void LLInventoryPanel::dumpSelectionInformation(void* user_data)
-{
- LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
- iv->mFolders->dumpSelectionInformation();
-}
-
-BOOL LLInventoryPanel::getSinceLogoff()
-{
- return mFolders->getFilter()->isSinceLogoff();
-}
-
-void example_param_block_usage()
+void LLFloaterInventory::onOpen(const LLSD& key)
{
- LLInventoryPanel::Params param_block;
- param_block.name(std::string("inventory"));
-
- param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER);
- param_block.allow_multi_select(true);
- param_block.filter(LLInventoryPanel::Filter()
- .sort_order(1)
- .types(0xffff0000));
- param_block.inventory(&gInventory);
- param_block.has_border(true);
-
- LLUICtrlFactory::create<LLInventoryPanel>(param_block);
-
- param_block = LLInventoryPanel::Params();
- param_block.name(std::string("inventory"));
-
- //LLSD param_block_sd;
- //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER;
- //param_block_sd["allow_multi_select"] = true;
- //param_block_sd["filter"]["sort_order"] = 1;
- //param_block_sd["filter"]["types"] = (S32)0xffff0000;
- //param_block_sd["has_border"] = true;
-
- //LLInitParam::LLSDParser(param_block_sd).parse(param_block);
-
- LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+ LLFirstUse::useInventory();
}
diff --git a/indra/newview/llfloaterinventory.h b/indra/newview/llfloaterinventory.h
index 1aaac74c87..c0de89bff2 100644
--- a/indra/newview/llfloaterinventory.h
+++ b/indra/newview/llfloaterinventory.h
@@ -31,336 +31,55 @@
* $/LicenseInfo$
*/
-#ifndef LL_LLINVENTORYVIEW_H
-#define LL_LLINVENTORYVIEW_H
+#ifndef LL_LLFLOATERINVENTORY_H
+#define LL_LLFLOATERINVENTORY_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>
+#include "llfoldertype.h"
+class LLInventoryPanel;
+class LLPanelMainInventory;
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLFloaterInventory
//
-// This is the agent inventory _floater_.
-// It deals with the buttons and views used to navigate as
-// well as controls the behavior of the overall object.
+// This deals with the buttons and views used to navigate as
+// well as controlling the behavior of the overall object.
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLFolderViewItem;
-class LLInventoryFilter;
-class LLInventoryModel;
-class LLInvFVBridge;
-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;
-
- Params()
- : sort_order_setting("sort_order_setting"),
- inventory("", &gInventory),
- allow_multi_select("allow_multi_select", true),
- filter("filter")
- {}
- };
-
-protected:
- LLInventoryPanel(const Params&);
- friend class LLUICtrlFactory;
-
-public:
- ~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 openDefaultFolderForType(LLAssetType::EType);
- void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
- void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); }
- void clearSelection();
- LLInventoryFilter* getFilter() { return mFolders->getFilter(); }
- void setFilterTypes(U64 filter, BOOL filter_for_categories = FALSE); // if filter_for_categories is true, operate on folder preferred asset type
- U32 getFilterTypes() const { return mFolders->getFilterTypes(); }
- 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); }
-
-protected:
- // Given the id and the parent, build all of the folder views.
- void rebuildViewsFor(const LLUUID& id, U32 mask);
- void buildNewViews(const LLUUID& id);
-
-protected:
- LLInventoryModel* mInventory;
- LLInventoryObserver* mInventoryObserver;
- LLFolderView* mFolders;
- LLScrollContainer* mScroller;
- BOOL mAllowMultiSelect;
- std::string mSortOrderSetting;
- bool mHasInventoryConnection;
-};
-
-class LLFloaterInventory;
-
-class LLFloaterInventoryFinder : public LLFloater
+class LLFloaterInventory : public LLFloater
{
public:
- LLFloaterInventoryFinder( LLFloaterInventory* 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);
-
-protected:
- LLFloaterInventory* mFloaterInventory;
- LLSpinCtrl* mSpinSinceDays;
- LLSpinCtrl* mSpinSinceHours;
- LLInventoryFilter* mFilter;
-};
-
-class LLFloaterInventory : public LLFloater, LLInventoryObserver
-{
-friend class LLFloaterInventoryFinder;
-
-public:
LLFloaterInventory(const LLSD& key);
~LLFloaterInventory();
- /*virtual*/ void changed(U32 mask);
-
- BOOL postBuild();
-
- //
- // Misc functions
- //
- void setFilterTextFromFilter() { mFilterText = mActivePanel->getFilter()->getFilterText(); }
- void startSearch();
-
- // This method makes sure that an inventory view exists, is
- // visible, and has focus. The view chosen is returned.
- static LLFloaterInventory* showAgentInventory();
+ BOOL postBuild();
// Return the active inventory view if there is one. Active is
// defined as the inventory that is the closest to the front, and
// is visible.
static LLFloaterInventory* getActiveInventory();
- // This method calls showAgentInventory() if no views are visible,
- // or hides/destroyes them all if any are visible.
- static void toggleVisibility();
- static void toggleVisibility(void*) { toggleVisibility(); }
+ // 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();
- // LLView & LLFloater functionality
- virtual void onOpen(const LLSD& key);
- virtual void draw();
- virtual BOOL handleKeyHere(KEY key, MASK mask);
-
- BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data,
- EAcceptance* accept,
- std::string& tooltip_msg);
-
-
- LLInventoryPanel* getPanel() { return mActivePanel; }
- LLInventoryPanel* getActivePanel() { return mActivePanel; }
-
- 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() { return mActivePanel->getFilterSubString(); }
- void setFilterSubString(const std::string& string) { mActivePanel->setFilterSubString(string); }
-
- // menu callbacks
- void doToSelected(const LLSD& userdata);
- void closeAllFolders();
- void doCreate(const LLSD& userdata);
- void resetFilters();
- void setSortBy(const LLSD& userdata);
-
- // HACK: Until we can route this info through the instant message hierarchy
- static BOOL sWearNewClothing;
- static LLUUID sWearNewClothingTransactionID; // wear all clothing in this transaction
-
- void toggleFindOptions();
-
- LLFloaterInventoryFinder* getFinder() { return (LLFloaterInventoryFinder*)mFinderHandle.get(); }
+ // Inherited functionality
+ /*virtual*/ void changed(U32 mask);
+ /*virtual*/ void draw();
+ /*virtual*/ void onOpen(const LLSD& key);
+ LLInventoryPanel* getPanel();
protected:
- LLFilterEditor* mFilterEditor;
- LLTabContainer* mFilterTabs;
- LLHandle<LLFloater> mFinderHandle;
- LLInventoryPanel* mActivePanel;
- LLSaveFolderState* mSavedFolderState;
-
- std::string mFilterText;
-
-private:
void updateTitle();
+private:
+ LLPanelMainInventory* mPanelMainInventory;
};
-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);
-};
-
-///----------------------------------------------------------------------------
-/// Function declarations, constants, enums, and typedefs
-///----------------------------------------------------------------------------
-
-// useful functions with the inventory view
-
-class LLInventoryCategory;
-class LLInventoryItem;
-
-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 );
-
-#endif // LL_LLINVENTORYVIEW_H
+#endif // LL_LLFLOATERINVENTORY_H
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index a378a511b5..015a947d91 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -105,7 +105,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;
@@ -123,7 +123,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.
@@ -744,6 +744,7 @@ void LLPanelLandGeneral::refreshNames()
if (!parcel)
{
mTextOwner->setText(LLStringUtil::null);
+ mTextGroup->setText(LLStringUtil::null);
return;
}
@@ -764,6 +765,13 @@ void LLPanelLandGeneral::refreshNames()
}
mTextOwner->setText(owner);
+ std::string group;
+ if (!parcel->getGroupID().isNull())
+ {
+ group = LLSLURL::buildCommand("group", parcel->getGroupID(), "inspect");
+ }
+ mTextGroup->setText(group);
+
const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
if(auth_buyer_id.notNull())
{
@@ -781,20 +789,6 @@ void LLPanelLandGeneral::refreshNames()
// virtual
void LLPanelLandGeneral::draw()
{
- LLParcel *parcel = mParcel->getParcel();
- if (parcel)
- {
- std::string group;
- if (!parcel->getGroupID().isNull())
- {
- // *TODO: Change to "inspect" when we have group inspectors and
- // move into refreshNames() above
- // group = LLSLURL::buildCommand("group", parcel->getGroupID(), "inspect");
- gCacheName->getGroupName(parcel->getGroupID(), group);
- }
- mTextGroup->setText(group);
- }
-
LLPanel::draw();
}
@@ -1060,9 +1054,9 @@ 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);
@@ -1525,7 +1519,9 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo
}
// Placeholder for name.
- item_params.columns.add().font(FONT).column("name");
+ 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);
item_params.columns.add().value(object_count_str).font(FONT).column("count");
@@ -1749,7 +1745,6 @@ LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel)
mClearBtn(NULL),
mMatureCtrl(NULL),
mPushRestrictionCtrl(NULL),
- mPublishHelpButton(NULL),
mParcel(parcel)
{
}
@@ -1818,14 +1813,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);
}
@@ -1918,7 +1908,6 @@ void LLPanelLandOptions::refresh()
mClearBtn->setEnabled(FALSE);
mMatureCtrl->setEnabled(FALSE);
- mPublishHelpButton->setEnabled(FALSE);
}
else
{
@@ -1994,13 +1983,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);
}
@@ -2253,28 +2238,6 @@ 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
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index 749c395147..f7fb978c2a 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -320,7 +320,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;
@@ -345,7 +344,6 @@ private:
LLCheckBoxCtrl *mMatureCtrl;
LLCheckBoxCtrl *mPushRestrictionCtrl;
- LLButton *mPublishHelpButton;
LLSafeHandle<LLParcelSelection>& mParcel;
};
diff --git a/indra/newview/llfloatermap.cpp b/indra/newview/llfloatermap.cpp
index eac1b65f7d..0c9a759f32 100644
--- a/indra/newview/llfloatermap.cpp
+++ b/indra/newview/llfloatermap.cpp
@@ -30,7 +30,6 @@
* $/LicenseInfo$
*/
-#include <string>
#include "llviewerprecompiledheaders.h"
// self include
@@ -52,13 +51,6 @@
#include "llviewermenu.h"
//
-// Constants
-//
-const F32 MAP_SCALE_MIN = 64;
-const F32 MAP_SCALE_MID = 172;
-const F32 MAP_SCALE_MAX = 512;
-
-//
// Member functions
//
diff --git a/indra/newview/llfloatermediasettings.cpp b/indra/newview/llfloatermediasettings.cpp
index aa457de2d8..d941f24f49 100644
--- a/indra/newview/llfloatermediasettings.cpp
+++ b/indra/newview/llfloatermediasettings.cpp
@@ -118,6 +118,7 @@ BOOL LLFloaterMediaSettings::postBuild()
mTabContainer->addTabPanel(
LLTabContainer::TabPanelParams().
panel(mPanelMediaSettingsSecurity));
+ mPanelMediaSettingsSecurity->setParent( this );
// restore the last tab viewed from persistance variable storage
if (!mTabContainer->selectTab(gSavedSettings.getS32("LastMediaSettingsTab")))
@@ -248,3 +249,28 @@ void LLFloaterMediaSettings::enableOkApplyBtns( bool enable )
childSetEnabled( "OK", enable );
childSetEnabled( "Apply", enable );
}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLFloaterMediaSettings::getHomeUrl()
+{
+ if ( mPanelMediaSettingsGeneral )
+ return mPanelMediaSettingsGeneral->getHomeUrl();
+ else
+ return std::string( "" );
+}
+
+
+////////////////////////////////////////////////////////////////////////////////
+//
+bool LLFloaterMediaSettings::passesWhiteList( const std::string& test_url )
+{
+ // sanity check - don't think this can happen
+ if ( mPanelMediaSettingsSecurity )
+ // version in security dialog code is specialized so we pass in
+ // empty string for first parameter since it's not used
+ return mPanelMediaSettingsSecurity->passesWhiteList( "", test_url );
+ else
+ // this is all we can do
+ return false;
+}
diff --git a/indra/newview/llfloatermediasettings.h b/indra/newview/llfloatermediasettings.h
index e2683039cc..17a47cb0f5 100644
--- a/indra/newview/llfloatermediasettings.h
+++ b/indra/newview/llfloatermediasettings.h
@@ -56,6 +56,8 @@ public:
static void clearValues( bool editable);
void enableOkApplyBtns( bool enable );
LLPanelMediaSettingsSecurity* getPanelSecurity(){return mPanelMediaSettingsSecurity;};
+ const std::string getHomeUrl();
+ bool passesWhiteList( const std::string& test_url );
bool mIdenticalHasMediaInfo;
bool mMultipleMedia;
diff --git a/indra/newview/llfloaternamedesc.cpp b/indra/newview/llfloaternamedesc.cpp
index ed7d2c71ea..b7296518d4 100644
--- a/indra/newview/llfloaternamedesc.cpp
+++ b/indra/newview/llfloaternamedesc.cpp
@@ -176,7 +176,7 @@ void LLFloaterNameDesc::onBtnOK( )
upload_new_resource(mFilenameAndPath, // file
childGetValue("name_form").asString(),
childGetValue("description_form").asString(),
- 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE,
+ 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
display_name, callback, expected_upload_cost, nruserdata);
closeFloater(false);
diff --git a/indra/newview/llfloaternotificationsconsole.cpp b/indra/newview/llfloaternotificationsconsole.cpp
index f2dff55044..f20fca1258 100644
--- a/indra/newview/llfloaternotificationsconsole.cpp
+++ b/indra/newview/llfloaternotificationsconsole.cpp
@@ -221,7 +221,8 @@ void LLFloaterNotificationConsole::removeChannel(const std::string& name)
//static
void LLFloaterNotificationConsole::updateResizeLimits()
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ const LLFloater::Params& floater_params = LLFloater::getDefaultParams();
+ S32 floater_header_size = floater_params.header_height;
LLLayoutStack& stack = getChildRef<LLLayoutStack>("notification_channels");
setResizeLimits(getMinWidth(), floater_header_size + HEADER_PADDING + ((NOTIFICATION_PANEL_HEADER_HEIGHT + 3) * stack.getNumPanels()));
diff --git a/indra/newview/llfloateropenobject.cpp b/indra/newview/llfloateropenobject.cpp
index aa82dc34b7..e277aba493 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"
@@ -47,7 +47,8 @@
#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"
@@ -58,7 +59,7 @@
LLFloaterOpenObject::LLFloaterOpenObject(const LLSD& key)
: LLFloater(key),
- mPanelInventory(NULL),
+ mPanelInventoryObject(NULL),
mDirty(TRUE)
{
// LLUICtrlFactory::getInstance()->buildFloater(this,"floater_openobject.xml");
@@ -74,7 +75,7 @@ LLFloaterOpenObject::~LLFloaterOpenObject()
BOOL LLFloaterOpenObject::postBuild()
{
childSetTextArg("object_name", "[DESC]", std::string("Object") ); // *Note: probably do not want to translate this
- mPanelInventory = getChild<LLPanelInventory>("object_contents");
+ mPanelInventoryObject = getChild<LLPanelObjectInventory>("object_contents");
return TRUE;
}
@@ -96,7 +97,7 @@ void LLFloaterOpenObject::onOpen(const LLSD& key)
}
void LLFloaterOpenObject::refresh()
{
- mPanelInventory->refresh();
+ mPanelInventoryObject->refresh();
std::string name;
BOOL enabled;
@@ -157,14 +158,14 @@ void LLFloaterOpenObject::moveToInventory(bool wear)
if (wear)
{
parent_category_id = gInventory.findCategoryUUIDForType(
- LLAssetType::AT_CLOTHING);
+ LLFolderType::FT_CLOTHING);
}
else
{
parent_category_id = gInventory.getRootFolderID();
}
LLUUID category_id = gInventory.createNewCategory(parent_category_id,
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
name);
LLCatAndWear* data = new LLCatAndWear;
diff --git a/indra/newview/llfloateropenobject.h b/indra/newview/llfloateropenobject.h
index a61cc04941..10d96b7ea3 100644
--- a/indra/newview/llfloateropenobject.h
+++ b/indra/newview/llfloateropenobject.h
@@ -41,7 +41,7 @@
#include "llfloater.h"
class LLObjectSelection;
-class LLPanelInventory;
+class LLPanelObjectInventory;
class LLFloaterOpenObject
: public LLFloater
@@ -77,7 +77,7 @@ private:
protected:
- LLPanelInventory* mPanelInventory;
+ LLPanelObjectInventory* mPanelInventoryObject;
LLSafeHandle<LLObjectSelection> mObjectSelection;
BOOL mDirty;
};
diff --git a/indra/newview/llfloaterpay.cpp b/indra/newview/llfloaterpay.cpp
index 88811d06fe..c2389e73a0 100644
--- a/indra/newview/llfloaterpay.cpp
+++ b/indra/newview/llfloaterpay.cpp
@@ -444,13 +444,11 @@ void LLFloaterPay::onCacheOwnerName(const LLUUID& owner_id,
{
if (is_group)
{
- childSetVisible("payee_group",true);
- childSetVisible("payee_resident",false);
+ setTitle(getString("payee_group"));
}
else
{
- childSetVisible("payee_group",false);
- childSetVisible("payee_resident",true);
+ setTitle(getString("payee_resident"));
}
childSetTextArg("payee_name", "[FIRST]", firstname);
diff --git a/indra/newview/llfloaterpreference.cpp b/indra/newview/llfloaterpreference.cpp
index dbee9ea309..2af1313db4 100644
--- a/indra/newview/llfloaterpreference.cpp
+++ b/indra/newview/llfloaterpreference.cpp
@@ -339,7 +339,6 @@ LLFloaterPreference::LLFloaterPreference(const LLSD& key)
mCommitCallbackRegistrar.add("Pref.ClickDisablePopup", boost::bind(&LLFloaterPreference::onClickDisablePopup, this));
mCommitCallbackRegistrar.add("Pref.LogPath", boost::bind(&LLFloaterPreference::onClickLogPath, this));
mCommitCallbackRegistrar.add("Pref.Logging", boost::bind(&LLFloaterPreference::onCommitLogging, this));
- mCommitCallbackRegistrar.add("Pref.OpenHelp", boost::bind(&LLFloaterPreference::onOpenHelp, 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));
@@ -608,12 +607,6 @@ void LLFloaterPreference::onBtnOK()
LLPanelLogin::refreshLocation( false );
}
-void LLFloaterPreference::onOpenHelp()
-{
- const char* xml_alert = "GraphicsPreferencesHelp";
- LLNotifications::instance().add(this->contextualNotification(xml_alert));
-}
-
// static
void LLFloaterPreference::onBtnApply( )
{
@@ -843,10 +836,7 @@ void LLFloaterPreference::refreshEnabledState()
bool bumpshiny = gGLManager.mHasCubeMap && LLCubeMap::sUseCubeMaps && LLFeatureManager::getInstance()->isFeatureAvailable("RenderObjectBump");
getChild<LLCheckBoxCtrl>("BumpShiny")->setEnabled(bumpshiny ? TRUE : FALSE);
- for (S32 i = 0; i < radio_reflection_detail->getItemCount(); ++i)
- {
- radio_reflection_detail->setIndexEnabled(i, ctrl_reflections->get() && reflections);
- }
+ radio_reflection_detail->setEnabled(ctrl_reflections->get() && reflections);
// Avatar Mode
// Enable Avatar Shaders
@@ -880,20 +870,10 @@ void LLFloaterPreference::refreshEnabledState()
{
mRadioTerrainDetail->setValue(1);
mRadioTerrainDetail->setEnabled(FALSE);
- for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
- {
- mRadioTerrainDetail->setIndexEnabled(i, FALSE);
- }
}
else
{
- mRadioTerrainDetail->setEnabled(TRUE);
-
- for (S32 i = 0; i < mRadioTerrainDetail->getItemCount(); ++i)
- {
- mRadioTerrainDetail->setIndexEnabled(i, TRUE);
- }
-
+ mRadioTerrainDetail->setEnabled(TRUE);
}
// WindLight
@@ -1056,11 +1036,15 @@ void LLFloaterPreference::onClickSetKey()
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()
diff --git a/indra/newview/llfloaterpreference.h b/indra/newview/llfloaterpreference.h
index 34723b8c7e..b1ad0348c0 100644
--- a/indra/newview/llfloaterpreference.h
+++ b/indra/newview/llfloaterpreference.h
@@ -84,7 +84,6 @@ protected:
void onBtnOK();
void onBtnCancel();
void onBtnApply();
- void onOpenHelp();
// void onClickClearCache();
void onClickBrowserClearCache();
diff --git a/indra/newview/llfloaterproperties.cpp b/indra/newview/llfloaterproperties.cpp
index 091debe95e..4375787ea2 100644
--- a/indra/newview/llfloaterproperties.cpp
+++ b/indra/newview/llfloaterproperties.cpp
@@ -586,7 +586,6 @@ void LLFloaterProperties::onCommitName()
{
new_item->updateServer(FALSE);
gInventory.updateItem(new_item);
- gInventory.updateLinkedObjects(new_item->getUUID());
gInventory.notifyObservers();
}
else
diff --git a/indra/newview/llfloaterregioninfo.cpp b/indra/newview/llfloaterregioninfo.cpp
index 0330a8c692..32229bd850 100644
--- a/indra/newview/llfloaterregioninfo.cpp
+++ b/indra/newview/llfloaterregioninfo.cpp
@@ -179,6 +179,8 @@ 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(LLTabContainer::TabPanelParams().panel(panel).select_tab(true));
@@ -442,52 +444,43 @@ LLPanelRegionInfo::LLPanelRegionInfo()
{
}
-// static
-void LLPanelRegionInfo::onBtnSet(void* user_data)
+void LLPanelRegionInfo::onBtnSet()
{
- LLPanelRegionInfo* panel = (LLPanelRegionInfo*)user_data;
- if(!panel) return;
- if (panel->sendUpdate())
+ if (sendUpdate())
{
- panel->disableButton("apply_btn");
+ disableButton("apply_btn");
}
}
-//static
-void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl, void* user_data)
+void LLPanelRegionInfo::onChangeChildCtrl(LLUICtrl* ctrl)
{
- if (ctrl)
- {
- LLPanelRegionInfo* panel = (LLPanelRegionInfo*) ctrl->getParent();
- panel->updateChild(ctrl);
- }
+ updateChild(ctrl); // virtual function
}
-// static
// 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;
@@ -550,19 +543,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");
}
/////////////////////////////////////////////////////////////////////////////
@@ -600,22 +587,10 @@ 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_all_btn", onClickKickAll, this);
childSetAction("im_btn", onClickMessage, this);
// childSetAction("manage_telehub_btn", onClickManageTelehub, this);
- mCommitCallbackRegistrar.add("RegionInfo.Cancel", boost::bind(&LLPanelRegionGeneralInfo::onClickManageTelehub, this));
return LLPanelRegionInfo::postBuild();
}
@@ -723,11 +698,7 @@ bool LLPanelRegionGeneralInfo::onMessageCommit(const LLSD& notification, const L
return false;
}
-void LLPanelRegionGeneralInfo::onClickManageTelehub()
-{
- LLFloaterReg::hideInstance("region_info");
- LLFloaterReg::showInstance("telehubs");
-}
+
// setregioninfo
// strings[0] = 'Y' - block terraform, 'N' - not
@@ -820,13 +791,6 @@ 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("return_btn", onClickReturn, this);
childSetAction("top_colliders_btn", onClickTopColliders, this);
@@ -1193,23 +1157,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);
@@ -1292,39 +1247,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
@@ -1420,32 +1365,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");
}
@@ -1522,6 +1458,7 @@ bool LLPanelEstateInfo::addAllowedGroup(const LLSD& notification, const LLSD& re
LLFloaterGroupPicker* widget = LLFloaterReg::showTypedInstance<LLFloaterGroupPicker>("group_picker", LLSD(gAgent.getID()));
if (widget)
{
+ widget->removeNoneOption();
widget->setSelectGroupCallback(boost::bind(&LLPanelEstateInfo::addAllowedGroup2, this, _1));
if (parent_floater)
{
@@ -2129,29 +2066,15 @@ BOOL LLPanelEstateInfo::postBuild()
initCtrl("limit_payment");
initCtrl("limit_age_verified");
initCtrl("voice_chat_check");
- childSetCommitCallback("abuse_email_address", onChangeAnything, this);
+ getChild<LLUICtrl>("abuse_email_address")->setCommitCallback(boost::bind(&LLPanelEstateInfo::onChangeAnything, this));
getChild<LLLineEditor>("abuse_email_address")->setKeystrokeCallback(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)
{
@@ -2162,7 +2085,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)
{
@@ -2173,7 +2096,7 @@ BOOL LLPanelEstateInfo::postBuild()
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)
{
@@ -2184,7 +2107,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)
{
@@ -2298,13 +2221,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
@@ -2314,7 +2242,7 @@ public:
<< status << ": " << reason << llendl;
}
private:
- LLPanelEstateInfo* mpPanel;
+ LLHandle<LLPanel> mpPanel;
};
// tries to send estate info using a cap; returns true if it succeeded
@@ -2352,7 +2280,7 @@ bool LLPanelEstateInfo::commitEstateInfoCaps()
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;
}
@@ -2718,7 +2646,6 @@ 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");
diff --git a/indra/newview/llfloaterregioninfo.h b/indra/newview/llfloaterregioninfo.h
index 68ed4e0c89..a3b91223b7 100644
--- a/indra/newview/llfloaterregioninfo.h
+++ b/indra/newview/llfloaterregioninfo.h
@@ -109,9 +109,9 @@ class LLPanelRegionInfo : public LLPanel
public:
LLPanelRegionInfo();
- static void onBtnSet(void* user_data);
- static void onChangeChildCtrl(LLUICtrl* ctrl, void* user_data);
- static void onChangeAnything(LLUICtrl* ctrl, void* user_data);
+ void onBtnSet();
+ void onChangeChildCtrl(LLUICtrl* ctrl);
+ void onChangeAnything();
static void onChangeText(LLLineEditor* caller, void* user_data);
virtual bool refreshFromRegion(LLViewerRegion* region);
@@ -123,12 +123,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.
@@ -152,6 +150,7 @@ protected:
class LLPanelRegionGeneralInfo : public LLPanelRegionInfo
{
+
public:
LLPanelRegionGeneralInfo()
: LLPanelRegionInfo() {}
@@ -161,16 +160,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);
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);
- void onClickManageTelehub();
+
};
/////////////////////////////////////////////////////////////////////////////
@@ -239,9 +238,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*);
@@ -256,8 +255,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);
diff --git a/indra/newview/llfloaterreporter.cpp b/indra/newview/llfloaterreporter.cpp
index 1ec869da73..0f4d6e33a3 100644
--- a/indra/newview/llfloaterreporter.cpp
+++ b/indra/newview/llfloaterreporter.cpp
@@ -143,6 +143,7 @@ BOOL LLFloaterReporter::postBuild()
LLViewerRegion *regionp = gAgent.getRegion();
if (regionp)
{
+ childSetText("sim_field", regionp->getName());
pos -= regionp->getOriginGlobal();
}
setPosBox(pos);
@@ -769,7 +770,7 @@ void LLFloaterReporter::takeScreenshot()
if (COMPLAINT_REPORT == mReportType)
{
mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE;
- mResourceDatap->mPreferredLocation = LLAssetType::EType(-2);
+ mResourceDatap->mPreferredLocation = LLFolderType::EType(LLResourceData::INVALID_LOCATION);
}
else
{
@@ -788,7 +789,7 @@ void LLFloaterReporter::takeScreenshot()
// store in the image list so it doesn't try to fetch from the server
LLPointer<LLViewerFetchedTexture> image_in_list =
- LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, FALSE, LLViewerTexture::FETCHED_TEXTURE);
+ LLViewerTextureManager::getFetchedTexture(mResourceDatap->mAssetInfo.mUuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::FETCHED_TEXTURE);
image_in_list->createGLTexture(0, raw);
// the texture picker then uses that texture
@@ -837,7 +838,7 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data,
}
EReportType report_type = UNKNOWN_REPORT;
- if (data->mPreferredLocation == -2)
+ if (data->mPreferredLocation == LLResourceData::INVALID_LOCATION)
{
report_type = COMPLAINT_REPORT;
}
diff --git a/indra/newview/llfloaterscriptdebug.cpp b/indra/newview/llfloaterscriptdebug.cpp
index 3bf1848efb..eeea71cc4c 100644
--- a/indra/newview/llfloaterscriptdebug.cpp
+++ b/indra/newview/llfloaterscriptdebug.cpp
@@ -106,7 +106,7 @@ void LLFloaterScriptDebug::addScriptLine(const std::string &utf8mesg, const std:
if (objectp)
{
- objectp->setIcon(LLViewerTextureManager::getFetchedTextureFromFile("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
diff --git a/indra/newview/llfloatersearch.cpp b/indra/newview/llfloatersearch.cpp
new file mode 100644
index 0000000000..97c573ddea
--- /dev/null
+++ b/indra/newview/llfloatersearch.cpp
@@ -0,0 +1,127 @@
+/**
+ * @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 "llfloatersearch.h"
+#include "llmediactrl.h"
+#include "lllogininstance.h"
+#include "lluri.h"
+
+LLFloaterSearch::LLFloaterSearch(const LLSD& key) :
+ LLFloater(key),
+ mBrowser(NULL)
+{
+ // 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);
+ mBrowser->setHomePageUrl(getString("search_url"));
+ }
+
+ return TRUE;
+}
+
+void LLFloaterSearch::onOpen(const LLSD& key)
+{
+ search(key);
+}
+
+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::search(const LLSD &key)
+{
+ if (! mBrowser)
+ {
+ return;
+ }
+
+ // get the URL for the search page
+ std::string url = getString("search_url");
+ if (! LLStringUtil::endsWith(url, "/"))
+ {
+ url += "/";
+ }
+
+ // work out the subdir to use based on the requested category
+ std::string category = key.has("category") ? key["category"].asString() : "";
+ if (mCategoryPaths.has(category))
+ {
+ url += mCategoryPaths[category].asString();
+ }
+ else
+ {
+ url += mCategoryPaths["all"].asString();
+ }
+
+ // append the search query string
+ std::string search_text = key.has("id") ? key["id"].asString() : "";
+ url += std::string("?q=") + LLURI::escape(search_text);
+
+ // append the permissions token that login.cgi gave us
+ LLSD search_token = LLLoginInstance::getInstance()->getResponse("search_token");
+ url += "&p=" + search_token.asString();
+
+ // 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..743107484f
--- /dev/null
+++ b/indra/newview/llfloatersearch.h
@@ -0,0 +1,80 @@
+/**
+ * @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);
+
+ /// 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);
+
+private:
+ /*virtual*/ BOOL postBuild();
+
+ // inherited from LLViewerMediaObserver
+ /*virtual*/ void handleMediaEvent(LLPluginClassMedia *self, EMediaEvent event);
+
+ LLMediaCtrl *mBrowser;
+ LLSD mCategoryPaths;
+};
+
+#endif // LL_LLFLOATERSEARCH_H
+
diff --git a/indra/newview/llfloatersellland.cpp b/indra/newview/llfloatersellland.cpp
index 43d31aa30a..2d8ccd1aef 100644
--- a/indra/newview/llfloatersellland.cpp
+++ b/indra/newview/llfloatersellland.cpp
@@ -47,7 +47,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 };
diff --git a/indra/newview/llfloatersnapshot.cpp b/indra/newview/llfloatersnapshot.cpp
index 235e819218..fd2e7b3487 100644
--- a/indra/newview/llfloatersnapshot.cpp
+++ b/indra/newview/llfloatersnapshot.cpp
@@ -980,7 +980,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
@@ -1373,8 +1373,10 @@ void LLFloaterSnapshot::Impl::checkAutoSnapshot(LLSnapshotLivePreview* previewp,
void LLFloaterSnapshot::Impl::onClickDiscard(void* data)
{
LLFloaterSnapshot *view = (LLFloaterSnapshot *)data;
+
if (view)
{
+ view->getParent()->setMouseOpaque(FALSE);
view->closeFloater();
}
}
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index b64d8ab334..3aef15a35c 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -49,11 +49,12 @@
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llmediaentry.h"
+#include "llmediactrl.h"
#include "llmenugl.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"
@@ -221,6 +222,7 @@ BOOL LLFloaterTools::postBuild()
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"));
@@ -304,6 +306,7 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mCheckSnapToGrid(NULL),
mBtnGridOptions(NULL),
+ mTitleMedia(NULL),
mTextGridMode(NULL),
mComboGridMode(NULL),
mCheckStretchUniform(NULL),
@@ -335,7 +338,8 @@ LLFloaterTools::LLFloaterTools(const LLSD& key)
mPanelLandInfo(NULL),
mTabLand(NULL),
- mDirty(TRUE)
+ mDirty(TRUE),
+ mNeedMediaTitle(TRUE)
{
gFloaterTools = this;
@@ -417,6 +421,11 @@ void LLFloaterTools::refresh()
LLResMgr::getInstance()->getIntegerString(prim_count_string, LLSelectMgr::getInstance()->getSelection()->getObjectCount());
childSetTextArg("prim_count", "[COUNT]", prim_count_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);
+
// Refresh child tabs
mPanelPermissions->refresh();
mPanelObject->refresh();
@@ -435,6 +444,9 @@ void LLFloaterTools::draw()
mDirty = FALSE;
}
+ // grab media name/title and update the UI widget
+ updateMediaTitle();
+
// mCheckSelectIndividual->set(gSavedSettings.getBOOL("EditLinkedParts"));
LLFloater::draw();
}
@@ -731,6 +743,10 @@ void LLFloaterTools::onClose(bool app_quitting)
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"));
@@ -1033,12 +1049,13 @@ void LLFloaterTools::getMediaState()
&&first_object->permModify()
))
{
- childSetEnabled("media_tex", FALSE);
+ childSetEnabled("Add_Media", FALSE);
+/* childSetEnabled("media_tex", FALSE);
childSetEnabled("add_media", FALSE);
childSetEnabled("delete_media", FALSE);
childSetEnabled("edit_media", FALSE);
childSetEnabled("media_info", FALSE);
- media_info->setEnabled(FALSE);
+ media_info->setEnabled(FALSE);*/
media_info->clear();
clearMediaSettings();
return;
@@ -1049,13 +1066,14 @@ void LLFloaterTools::getMediaState()
if(!has_media_capability)
{
- childSetEnabled("media_tex", FALSE);
+ childSetEnabled("Add_Media", FALSE);
+ /* childSetEnabled("media_tex", FALSE);
childSetEnabled("add_media", FALSE);
childSetEnabled("delete_media", FALSE);
childSetEnabled("edit_media", FALSE);
childSetEnabled("media_info", FALSE);
media_info->setEnabled(FALSE);
- media_info->clear();
+ media_info->clear();*/
clearMediaSettings();
return;
}
@@ -1076,6 +1094,7 @@ void LLFloaterTools::getMediaState()
LLFloaterMediaSettings::getInstance()->mIdenticalHasMediaInfo = selected_objects->getSelectedTEValue( &func, has_media );
bool bool_has_media = (has_media & LLTextureEntry::MF_HAS_MEDIA);
+
const LLMediaEntry default_media_data;
struct functor_getter_media_data : public LLSelectedTEGetFunctor< LLMediaEntry>
@@ -1100,9 +1119,11 @@ void LLFloaterTools::getMediaState()
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 )
{
@@ -1114,25 +1135,26 @@ void LLFloaterTools::getMediaState()
// Media data is valid
if(media_data_get!=default_media_data)
{
- //TODO: get media title
- //media_title = media_data_get->getTile();
- //LLFloaterMediaSettings::getInstance()->mIdenticalValidMedia = true;
+ // 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 & editable );
childSetEnabled( "delete_media", bool_has_media & editable );
childSetEnabled( "add_media", ( ! bool_has_media ) & editable );
- media_info->setEnabled(bool_has_media & editable);
+ media_info->setEnabled(false);
// TODO: display a list of all media on the face - use 'identical' flag
}
else // not all face has media but at least one does.
@@ -1143,20 +1165,23 @@ void LLFloaterTools::getMediaState()
if(LLFloaterMediaSettings::getInstance()->mMultipleValidMedia)
{
media_title = multi_media_info_str;
+ mNeedMediaTitle = false;
}
else
{
// Media data is valid
if(media_data_get!=default_media_data)
{
- //TODO: get media title
- //media_title = media_data_get->getTile();
+ // 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;
}
-
}
- media_info->setEnabled(TRUE);
+ media_info->setEnabled(false);
media_info->setTentative(true);
childSetEnabled("media_tex", TRUE);
childSetEnabled( "edit_media", TRUE);
@@ -1244,12 +1269,63 @@ bool LLFloaterTools::deleteMediaConfirm(const LLSD& notification, const LLSD& re
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
+ LLLineEditor* media_title_field = getChild<LLLineEditor>("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()
diff --git a/indra/newview/llfloatertools.h b/indra/newview/llfloatertools.h
index 59acef6071..a3e0cac034 100644
--- a/indra/newview/llfloatertools.h
+++ b/indra/newview/llfloatertools.h
@@ -51,6 +51,7 @@ class LLRadioGroup;
class LLSlider;
class LLTabContainer;
class LLTextBox;
+class LLMediaCtrl;
class LLTool;
class LLParcelSelection;
class LLObjectSelection;
@@ -107,6 +108,8 @@ public:
void onClickBtnAddMedia();
void onClickBtnEditMedia();
void clearMediaSettings();
+ void updateMediaTitle();
+ void navigateToTitleMedia( const std::string url );
bool selectedMediaEditable();
private:
@@ -182,6 +185,9 @@ public:
LLParcelSelectionHandle mParcelSelection;
LLObjectSelectionHandle mObjectSelection;
+ LLMediaCtrl *mTitleMedia;
+ bool mNeedMediaTitle;
+
private:
BOOL mDirty;
diff --git a/indra/newview/llfloatertos.cpp b/indra/newview/llfloatertos.cpp
index 1c3443ae80..8d2d48f1af 100644
--- a/indra/newview/llfloatertos.cpp
+++ b/indra/newview/llfloatertos.cpp
@@ -35,8 +35,6 @@
#include "llfloatertos.h"
// viewer includes
-#include "llappviewer.h"
-#include "llstartup.h"
#include "llviewerstats.h"
#include "llviewerwindow.h"
@@ -50,13 +48,15 @@
#include "lluictrlfactory.h"
#include "llvfile.h"
#include "message.h"
+#include "llstartup.h" // login_alert_done
-LLFloaterTOS::LLFloaterTOS(const LLSD& message)
-: LLModalDialog( message ),
- mMessage(message.asString()),
+LLFloaterTOS::LLFloaterTOS(const LLSD& data)
+: LLModalDialog( data["message"].asString() ),
+ mMessage(data["message"].asString()),
mWebBrowserWindowId( 0 ),
- mLoadCompleteCount( 0 )
+ mLoadCompleteCount( 0 ),
+ mReplyPumpName(data["reply_pump"].asString())
{
}
@@ -193,25 +193,12 @@ void LLFloaterTOS::onContinue( void* userdata )
{
LLFloaterTOS* self = (LLFloaterTOS*) userdata;
llinfos << "User agrees with TOS." << llendl;
- if (self->getInstanceName() == "message_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->closeFloater(); // destroys this object
}
@@ -221,7 +208,12 @@ 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 );
+
+ if(self->mReplyPumpName != "")
+ {
+ LLEventPumps::instance().obtain(self->mReplyPumpName).post(LLSD(false));
+ }
+
self->mLoadCompleteCount = 0; // reset counter for next time we come to TOS
self->closeFloater(); // destroys this object
}
@@ -241,3 +233,4 @@ void LLFloaterTOS::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent ev
}
}
}
+
diff --git a/indra/newview/llfloatertos.h b/indra/newview/llfloatertos.h
index 49f982aa80..1d573e8170 100644
--- a/indra/newview/llfloatertos.h
+++ b/indra/newview/llfloatertos.h
@@ -36,6 +36,7 @@
#include "llmodaldialog.h"
#include "llassetstorage.h"
#include "llmediactrl.h"
+#include <boost/function.hpp>
class LLButton;
class LLRadioGroup;
@@ -48,7 +49,7 @@ class LLFloaterTOS :
public LLViewerMediaObserver
{
public:
- LLFloaterTOS(const LLSD& message);
+ LLFloaterTOS(const LLSD& data);
virtual ~LLFloaterTOS();
BOOL postBuild();
@@ -68,6 +69,7 @@ private:
std::string mMessage;
int mWebBrowserWindowId;
int mLoadCompleteCount;
+ std::string mReplyPumpName;
};
#endif // LL_LLFLOATERTOS_H
diff --git a/indra/newview/llfloateruipreview.cpp b/indra/newview/llfloateruipreview.cpp
index 98ca33c9cc..2fe21f28de 100644
--- a/indra/newview/llfloateruipreview.cpp
+++ b/indra/newview/llfloateruipreview.cpp
@@ -56,8 +56,13 @@
#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>
@@ -65,6 +70,8 @@
// External utility
#include <string>
+#include <list>
+#include <map>
#if LL_DARWIN
#include <CoreFoundation/CFURL.h>
@@ -74,6 +81,7 @@
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()
@@ -82,6 +90,134 @@ static std::string get_xui_dir()
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,
@@ -137,11 +273,17 @@ public:
}
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
@@ -257,7 +399,6 @@ LLFloaterUIPreview::LLFloaterUIPreview(const LLSD& key)
mHighlightingOverlaps(FALSE),
mLastDisplayedX(0),
mLastDisplayedY(0)
-
{
// called from floater reg: LLUICtrlFactory::getInstance()->buildFloater(this, "floater_ui_preview.xml");
}
@@ -317,6 +458,8 @@ BOOL LLFloaterUIPreview::postBuild()
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");
@@ -410,34 +553,39 @@ void LLFloaterUIPreview::onLanguageComboSelect(LLUICtrl* ctrl)
void LLFloaterUIPreview::onClickExportSchema()
{
- 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);
+ //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)
@@ -717,7 +865,8 @@ void LLFloaterUIPreview::displayFloater(BOOL click, S32 ID, bool save)
}
else // if it is a panel...
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ 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
@@ -1357,6 +1506,73 @@ void LLFloaterUIPreview::onClickCloseDisplayedFloater(S32 caller_id)
}
+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);
@@ -1415,7 +1631,22 @@ void LLPreviewedFloater::draw()
{
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;
@@ -1635,3 +1866,9 @@ void LLOverlapPanel::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
index 2a98c90727..2a31b2df59 100644
--- a/indra/newview/llfloateruipreview.h
+++ b/indra/newview/llfloateruipreview.h
@@ -37,137 +37,10 @@
#ifndef LL_LLUIPREVIEW_H
#define LL_LLUIPREVIEW_H
-#include "llfloater.h" // superclass
-#include "llscrollcontainer.h" // scroll container for overlapping elements
-#include "lllivefile.h" // live file poll/stat/reload
-#include <list>
-#include <map>
-
-// 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
+namespace LLFloaterUIPreviewUtil
{
-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);
+ void registerFloater();
+}
- // 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();
-};
#endif // LL_LLUIPREVIEW_H
diff --git a/indra/newview/llfloatervoicedevicesettings.cpp b/indra/newview/llfloatervoicedevicesettings.cpp
index b64257b11d..bbeb287171 100644
--- a/indra/newview/llfloatervoicedevicesettings.cpp
+++ b/indra/newview/llfloatervoicedevicesettings.cpp
@@ -43,12 +43,15 @@
#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()
{
@@ -82,8 +85,22 @@ BOOL LLPanelVoiceDeviceSettings::postBuild()
return TRUE;
}
+// virtual
+void LLPanelVoiceDeviceSettings::handleVisibilityChange ( BOOL new_visibility )
+{
+ if (new_visibility)
+ {
+ initialize();
+ }
+ else
+ {
+ cleanup();
+ }
+}
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);
diff --git a/indra/newview/llfloatervoicedevicesettings.h b/indra/newview/llfloatervoicedevicesettings.h
index f1603dc414..d67283d0a2 100644
--- a/indra/newview/llfloatervoicedevicesettings.h
+++ b/indra/newview/llfloatervoicedevicesettings.h
@@ -50,6 +50,8 @@ public:
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);
diff --git a/indra/newview/llfloaterwater.cpp b/indra/newview/llfloaterwater.cpp
index 72c82c178b..a0fe42bf61 100644
--- a/indra/newview/llfloaterwater.cpp
+++ b/indra/newview/llfloaterwater.cpp
@@ -110,23 +110,6 @@ BOOL LLFloaterWater::postBuild()
}
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();
getChild<LLUICtrl>("WaterFogColor")->setCommitCallback(boost::bind(&LLFloaterWater::onWaterFogColorMoved, this, _1, &param_mgr->mFogColor));
@@ -173,16 +156,6 @@ void LLFloaterWater::initCallbacks(void) {
getChild<LLUICtrl>("WaterNormalMap")->setCommitCallback(boost::bind(&LLFloaterWater::onNormalMapPicked, this, _1));
}
-void LLFloaterWater::onClickHelp(std::string xml_alert)
-{
- LLNotifications::instance().add(contextualNotification(xml_alert));
-}
-
-void LLFloaterWater::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- getChild<LLButton>(name)->setClickedCallback(boost::bind(&LLFloaterWater::onClickHelp, this, xml_alert));
-}
-
bool LLFloaterWater::newPromptCallback(const LLSD& notification, const LLSD& response)
{
std::string text = response["message"].asString();
diff --git a/indra/newview/llfloaterwater.h b/indra/newview/llfloaterwater.h
index 08c630c69e..0ea2436dbe 100644
--- a/indra/newview/llfloaterwater.h
+++ b/indra/newview/llfloaterwater.h
@@ -59,10 +59,6 @@ public:
/// initialize all
void initCallbacks(void);
- // help button stuff
- void onClickHelp(std::string xml_alert);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
-
bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
diff --git a/indra/newview/llfloaterwindlight.cpp b/indra/newview/llfloaterwindlight.cpp
index 02979acdd7..60494f3cce 100644
--- a/indra/newview/llfloaterwindlight.cpp
+++ b/indra/newview/llfloaterwindlight.cpp
@@ -119,36 +119,6 @@ BOOL LLFloaterWindLight::postBuild()
}
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
@@ -237,16 +207,6 @@ void LLFloaterWindLight::initCallbacks(void) {
getChild<LLUICtrl>("WLStarAlpha")->setCommitCallback(boost::bind(&LLFloaterWindLight::onStarAlphaMoved, this, _1));
}
-void LLFloaterWindLight::onClickHelp(std::string xml_alert)
-{
- LLNotifications::instance().add(contextualNotification(xml_alert));
-}
-
-void LLFloaterWindLight::initHelpBtn(const std::string& name, const std::string& xml_alert)
-{
- getChild<LLButton>(name)->setClickedCallback(boost::bind(&LLFloaterWindLight::onClickHelp, this, xml_alert));
-}
-
bool LLFloaterWindLight::newPromptCallback(const LLSD& notification, const LLSD& response)
{
std::string text = response["message"].asString();
diff --git a/indra/newview/llfloaterwindlight.h b/indra/newview/llfloaterwindlight.h
index 56c2c6623b..ed9322c450 100644
--- a/indra/newview/llfloaterwindlight.h
+++ b/indra/newview/llfloaterwindlight.h
@@ -57,10 +57,6 @@ public:
/// initialize all
void initCallbacks(void);
- // help button stuff
- void onClickHelp(std::string alert);
- void initHelpBtn(const std::string& name, const std::string& xml_alert);
-
bool newPromptCallback(const LLSD& notification, const LLSD& response);
/// general purpose callbacks for dealing with color controllers
diff --git a/indra/newview/llfloaterworldmap.cpp b/indra/newview/llfloaterworldmap.cpp
index d653d44f8c..412011e76a 100644
--- a/indra/newview/llfloaterworldmap.cpp
+++ b/indra/newview/llfloaterworldmap.cpp
@@ -45,10 +45,12 @@
#include "llcallingcard.h"
#include "llcombobox.h"
#include "llviewercontrol.h"
+#include "llcommandhandler.h"
#include "lldraghandle.h"
#include "llfirstuse.h"
#include "llfloaterreg.h" // getTypedInstance()
#include "llfocusmgr.h"
+#include "llinventorymodel.h"
#include "lllandmarklist.h"
#include "lllineeditor.h"
#include "llregionhandle.h"
@@ -57,7 +59,7 @@
#include "lltabcontainer.h"
#include "lltextbox.h"
#include "lltracker.h"
-#include "llinventorymodel.h"
+#include "lltrans.h"
#include "llviewerinventory.h" // LLViewerInventoryItem
#include "llviewermenu.h"
#include "llviewerregion.h"
@@ -95,6 +97,35 @@ static const F32 SIM_COORD_DEFAULT = 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)
+ {
+ return false;
+ }
+
+ 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
@@ -151,7 +182,6 @@ LLFloaterWorldMap::LLFloaterWorldMap(const LLSD& key)
mFriendObserver(NULL),
mCompletingRegionName(""),
mWaitingForTracker(FALSE),
- mExactMatch(FALSE),
mIsClosing(FALSE),
mSetToUserPosition(TRUE),
mTrackedLocation(0,0,0),
@@ -297,7 +327,7 @@ void LLFloaterWorldMap::onOpen(const LLSD& key)
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);
childSetFocus("location", TRUE);
@@ -427,7 +457,7 @@ 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);
}
@@ -903,7 +933,6 @@ void LLFloaterWorldMap::clearLocationSelection(BOOL clear_ui)
}
LLWorldMap::getInstance()->mIsTrackingCommit = FALSE;
mCompletingRegionName = "";
- mExactMatch = FALSE;
}
@@ -1163,7 +1192,6 @@ void LLFloaterWorldMap::onLocationCommit()
LLStringUtil::toLower(str);
mCompletingRegionName = str;
LLWorldMap::getInstance()->mIsTrackingCommit = TRUE;
- mExactMatch = FALSE;
if (str.length() >= 3)
{
LLWorldMap::getInstance()->sendNamedRegionRequest(str);
@@ -1418,11 +1446,10 @@ 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)
@@ -1434,15 +1461,11 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
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 = sim_name;
}
-
+
LLSD value;
value["id"] = sim_name;
value["columns"][0]["column"] = "sim_name";
@@ -1451,29 +1474,24 @@ void LLFloaterWorldMap::updateSims(bool found_null_sim)
num_results++;
}
}
-
- list->selectByValue(selected_value);
if (found_null_sim)
{
mCompletingRegionName = "";
}
- if (match_found)
- {
- mExactMatch = TRUE;
- childSetFocus("search_results");
- onCommitSearchResult();
- }
- 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();
}
- else if (num_results == 0)
+
+ // if we found nothing, say "none"
+ if (num_results == 0)
{
- list->setCommentText(std::string("None found."));
+ list->setCommentText(LLTrans::getString("worldmap_results_none_found"));
list->operateOnAll(LLCtrlListInterface::OP_DESELECT);
}
}
diff --git a/indra/newview/llfloaterworldmap.h b/indra/newview/llfloaterworldmap.h
index 6d5b7543d4..20a8e6d321 100644
--- a/indra/newview/llfloaterworldmap.h
+++ b/indra/newview/llfloaterworldmap.h
@@ -174,7 +174,6 @@ protected:
std::string mCompletingRegionName;
std::string mLastRegionName;
BOOL mWaitingForTracker;
- BOOL mExactMatch;
BOOL mIsClosing;
BOOL mSetToUserPosition;
diff --git a/indra/newview/llfolderview.cpp b/indra/newview/llfolderview.cpp
index 3fd0875709..7863c373c6 100644
--- a/indra/newview/llfolderview.cpp
+++ b/indra/newview/llfolderview.cpp
@@ -38,6 +38,7 @@
#include "llinventorybridge.h"
#include "llinventoryclipboard.h" // *TODO: remove this once hack below gone.
#include "llinventoryfilter.h"
+#include "llinventoryfunctions.h"
#include "llfoldertype.h"
#include "llfloaterinventory.h"// hacked in for the bonus context menu items.
#include "llkeyboard.h"
@@ -54,6 +55,7 @@
#include "llviewermenu.h"
#include "lluictrlfactory.h"
#include "llviewercontrol.h"
+#include "llviewerfoldertype.h"
#include "llviewerwindow.h"
#include "llvoavatar.h"
#include "llfloaterproperties.h"
@@ -189,7 +191,9 @@ LLFolderView::LLFolderView(const Params& p)
mMinWidth(0),
mDragAndDropThisFrame(FALSE),
mCallbackRegistrar(NULL),
- mParentPanel(p.parent_panel)
+ 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);
@@ -481,6 +485,11 @@ void LLFolderView::reshape(S32 width, S32 height, BOOL called_from_parent)
scroll_rect = mScrollContainer->getContentWindowRect();
}
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);
@@ -1100,7 +1109,7 @@ void LLFolderView::propertiesSelectedItems( void )
}
}
-void LLFolderView::changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type)
+void LLFolderView::changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type)
{
LLFolderBridge *folder_bridge = LLFolderBridge::sSelf;
@@ -1224,12 +1233,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
@@ -1918,7 +1959,7 @@ bool LLFolderView::doToSelected(LLInventoryModel* model, const LLSD& userdata)
if (action.length() > change_folder_string.length() &&
(action.compare(0,change_folder_string.length(),"change_folder_type_") == 0))
{
- LLAssetType::EType new_folder_type = LLFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
+ LLFolderType::EType new_folder_type = LLViewerFolderType::lookupTypeFromXUIName(action.substr(change_folder_string.length()));
changeType(model, new_folder_type);
return true;
}
diff --git a/indra/newview/llfolderview.h b/indra/newview/llfolderview.h
index 69c0c5b132..0bd65b5f90 100644
--- a/indra/newview/llfolderview.h
+++ b/indra/newview/llfolderview.h
@@ -104,8 +104,6 @@ public:
Mandatory<LLPanel*> parent_panel;
Optional<LLUUID> task_id;
};
- LLFolderView( const std::string& name, LLUIImagePtr root_folder_icon, const LLRect& rect,
- const LLUUID& source_id, LLPanel *parent_view );
LLFolderView(const Params&);
virtual ~LLFolderView( void );
@@ -182,6 +180,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();
@@ -191,7 +192,7 @@ public:
void propertiesSelectedItems( void );
// change the folder type
- void changeType(LLInventoryModel *model, LLAssetType::EType new_folder_type);
+ void changeType(LLInventoryModel *model, LLFolderType::EType new_folder_type);
void autoOpenItem(LLFolderViewFolder* item);
void closeAutoOpenedFolders();
@@ -250,6 +251,8 @@ 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);
@@ -329,6 +332,17 @@ protected:
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:
diff --git a/indra/newview/llfoldervieweventlistener.h b/indra/newview/llfoldervieweventlistener.h
index 254ce4062a..60ece75cea 100644
--- a/indra/newview/llfoldervieweventlistener.h
+++ b/indra/newview/llfoldervieweventlistener.h
@@ -32,6 +32,7 @@
#define LLFOLDERVIEWEVENTLISTENER_H
#include "lldarray.h" // JAMESDEBUG convert to std::vector
+#include "llfoldertype.h"
#include "llfontgl.h" // just for StyleFlags enum
#include "llpointer.h"
@@ -57,7 +58,7 @@ public:
virtual const LLUUID& getUUID() const = 0;
virtual time_t getCreationDate() const = 0; // UTC seconds
virtual PermissionMask getPermissionMask() const = 0;
- virtual LLAssetType::EType getPreferredType() const = 0;
+ virtual LLFolderType::EType getPreferredType() const = 0;
virtual LLPointer<LLUIImage> getIcon() const = 0;
virtual LLFontGL::StyleFlags getLabelStyle() const = 0;
virtual std::string getLabelSuffix() const = 0;
@@ -68,7 +69,7 @@ public:
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 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;
diff --git a/indra/newview/llfolderviewitem.cpp b/indra/newview/llfolderviewitem.cpp
index 2b1dd83d72..6fdaefd21a 100644
--- a/indra/newview/llfolderviewitem.cpp
+++ b/indra/newview/llfolderviewitem.cpp
@@ -36,6 +36,7 @@
// 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 "llinventorymodel.h" // *TODO: make it take a pointer to an inventory-model interface
#include "llviewercontrol.h" // gSavedSettings
@@ -70,6 +71,10 @@ LLFontGL* LLFolderViewItem::getLabelFontForStyle(U8 style)
{
LLFontDescriptor labelfontdesc("SansSerif", "Small", style);
rtn = LLFontGL::getFont(labelfontdesc);
+ if (!rtn)
+ {
+ rtn = LLFontGL::getFontDefault();
+ }
sFonts[style] = rtn;
}
return rtn;
@@ -130,6 +135,7 @@ LLFolderViewItem::LLFolderViewItem(LLFolderViewItem::Params p)
mListener(p.listener),
mArrowImage(p.folder_arrow_image),
mBoxImage(p.selection_image)
+, mDontShowInHierarhy(false)
{
refresh();
}
@@ -242,13 +248,13 @@ void LLFolderViewItem::refreshFromListener()
if(mListener)
{
mLabel = mListener->getDisplayName();
- LLAssetType::EType preferred_type = mListener->getPreferredType();
+ 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 (LLAssetType::lookupIsProtectedCategoryType(preferred_type))
+ if (LLFolderType::lookupIsProtectedType(preferred_type))
{
LLTrans::findString(mLabel, "InvFolder " + mLabel);
};
@@ -312,7 +318,12 @@ void LLFolderViewItem::arrangeFromRoot()
S32 height = 0;
S32 width = 0;
- root->arrange( &width, &height, 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
@@ -385,12 +396,22 @@ S32 LLFolderViewItem::arrange( S32* width, S32* height, S32 filter_generation)
}
*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 (mDontShowInHierarhy) return 0;
+
S32 icon_height = mIcon->getHeight();
S32 label_height = llround(getLabelFontForStyle(mLabelStyle)->getLineHeight());
return llmax( icon_height, label_height ) + ICON_PAD;
@@ -781,7 +802,10 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
}
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)
{
@@ -794,6 +818,8 @@ BOOL LLFolderViewItem::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
void LLFolderViewItem::draw()
{
+ if (mDontShowInHierarhy) 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);
@@ -864,11 +890,11 @@ void LLFolderViewItem::draw()
llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD),
sHighlightFgColor, FALSE);
}
- if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 2)
+ if (getRect().getHeight() > llround(font->getLineHeight()) + ICON_PAD + 4)
{
gl_rect_2d(
0,
- llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2,
+ llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4,
getRect().getWidth() - 2,
2,
sHighlightFgColor, FALSE);
@@ -876,7 +902,7 @@ void LLFolderViewItem::draw()
{
gl_rect_2d(
0,
- llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 2,
+ llfloor(getRect().getHeight() - font->getLineHeight() - ICON_PAD) - 4,
getRect().getWidth() - 2,
2,
sHighlightBgColor, TRUE);
@@ -948,7 +974,8 @@ void LLFolderViewItem::draw()
font->renderUTF8( mLabel, 0, text_left, y, color,
LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::NORMAL, LLFontGL::NO_SHADOW,
- S32_MAX, S32_MAX, &right_x, FALSE );
+ S32_MAX, getRect().getWidth() - (S32) text_left, &right_x, TRUE);
+
if (!mLabelSuffix.empty())
{
font->renderUTF8( mLabelSuffix, 0, right_x, y, sSuffixColor,
@@ -1726,7 +1753,7 @@ bool LLFolderViewFolder::isTrash() const
{
if (mAmTrash == LLFolderViewFolder::UNKNOWN)
{
- mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
+ mAmTrash = mListener->getUUID() == gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH, false) ? LLFolderViewFolder::TRASH : LLFolderViewFolder::NOT_TRASH;
}
return mAmTrash == LLFolderViewFolder::TRASH;
}
@@ -2140,7 +2167,7 @@ BOOL LLFolderViewFolder::handleDoubleClick( S32 x, S32 y, MASK mask )
{
const LLUUID &cat_uuid = getListener()->getUUID();
const LLViewerInventoryCategory *cat = gInventory.getCategory(cat_uuid);
- if (cat && cat->getPreferredType() == LLAssetType::AT_OUTFIT)
+ if (cat && cat->getPreferredType() == LLFolderType::FT_OUTFIT)
{
getListener()->performAction(NULL, NULL,"replaceoutfit");
return TRUE;
@@ -2456,6 +2483,28 @@ bool LLInventorySort::updateSort(U32 order)
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);
+
+ 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)
+ {
+ // *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
diff --git a/indra/newview/llfolderviewitem.h b/indra/newview/llfolderviewitem.h
index 09c97662d9..62a4b9a187 100644
--- a/indra/newview/llfolderviewitem.h
+++ b/indra/newview/llfolderviewitem.h
@@ -158,6 +158,7 @@ protected:
LLUIImagePtr mBoxImage;
BOOL mIsLoading;
LLTimer mTimeSinceRequestStart;
+ bool mDontShowInHierarhy;
// helper function to change the selection from the root.
void changeSelectionFromRoot(LLFolderViewItem* selection, BOOL selected);
@@ -200,6 +201,8 @@ public:
// 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();
+ void setDontShowInHierarchy(bool dont_show) { mDontShowInHierarhy = dont_show; }
+ bool getDontShowInHierarchy() { return mDontShowInHierarhy; }
// applies filters to control visibility of inventory items
virtual void filter( LLInventoryFilter& filter);
diff --git a/indra/newview/llfriendcard.cpp b/indra/newview/llfriendcard.cpp
index 97b7f3e9ad..c956657825 100644
--- a/indra/newview/llfriendcard.cpp
+++ b/indra/newview/llfriendcard.cpp
@@ -91,8 +91,44 @@ const LLUUID& get_folder_uuid(const LLUUID& parentFolderUUID, LLInventoryCollect
return LLUUID::null;
}
+
+// LLViewerInventoryCategory::fetchDescendents has it own period of fetching.
+// for now it is FETCH_TIMER_EXPIRY = 10.0f; So made our period a bit more.
+const F32 FETCH_FRIENDS_DESCENDENTS_PERIOD = 11.0f;
+
+
+/**
+ * Intended to call passed callback after the specified period of time.
+ *
+ * Implemented to fix an issue when Inventory folders are in incomplete state. See EXT-2061, EXT-1935, EXT-813.
+ * For now it uses to periodically sync Inventory Friends/All folder with a Agent's Friends List
+ * until it is complete.
+ */
+class FriendListUpdater : public LLEventTimer
+{
+public:
+ typedef boost::function<bool()> callback_t;
+
+ FriendListUpdater(callback_t cb, F32 period)
+ : LLEventTimer(period)
+ , mCallback(cb)
+ {
+ mEventTimer.start();
+ }
+
+ virtual BOOL tick() // from LLEventTimer
+ {
+ return mCallback();
+ }
+
+private:
+ callback_t mCallback;
+};
+
+
// LLFriendCardsManager Constructor / Destructor
LLFriendCardsManager::LLFriendCardsManager()
+: mFriendsAllFolderCompleted(true)
{
LLAvatarTracker::instance().addObserver(this);
}
@@ -135,14 +171,14 @@ const LLUUID LLFriendCardsManager::extractAvatarID(const LLUUID& avatarID)
// and this method must be called before any actions with friend list
void LLFriendCardsManager::ensureFriendFoldersExist()
{
- LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+ const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
LLUUID friendFolderUUID = findFriendFolderUUIDImpl();
if (friendFolderUUID.isNull())
{
friendFolderUUID = gInventory.createNewCategory(callingCardsFolderID,
- LLAssetType::AT_CALLINGCARD, get_friend_folder_name());
+ LLFolderType::FT_CALLINGCARD, get_friend_folder_name());
}
LLUUID friendAllSubfolderUUID = findFriendAllSubfolderUUIDImpl();
@@ -150,7 +186,7 @@ void LLFriendCardsManager::ensureFriendFoldersExist()
if (friendAllSubfolderUUID.isNull())
{
friendAllSubfolderUUID = gInventory.createNewCategory(friendFolderUUID,
- LLAssetType::AT_CALLINGCARD, get_friend_all_subfolder_name());
+ LLFolderType::FT_CALLINGCARD, get_friend_all_subfolder_name());
}
}
@@ -166,6 +202,93 @@ bool LLFriendCardsManager::isItemInAnyFriendsList(const LLViewerInventoryItem* i
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)
@@ -182,7 +305,7 @@ bool LLFriendCardsManager::isAnyFriendCategory(const LLUUID& catID) const
return TRUE == gInventory.isObjectDescendentOf(catID, friendFolderID);
}
-void LLFriendCardsManager::syncFriendsFolder()
+bool LLFriendCardsManager::syncFriendsFolder()
{
//lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" if they are absent
LLFriendCardsManager::instance().ensureFriendFoldersExist();
@@ -210,11 +333,35 @@ void LLFriendCardsManager::syncFriendsFolder()
// 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;
+ mFriendsAllFolderCompleted = true;
for(; buddy_it != all_buddies.end(); ++buddy_it)
{
const LLUUID& buddy_id = (*buddy_it).first;
addFriendCardToInventory(buddy_id);
}
+
+ if (!mFriendsAllFolderCompleted)
+ {
+ forceFriendListIsLoaded(findFriendAllSubfolderUUIDImpl());
+
+ static bool timer_started = false;
+ if (!timer_started)
+ {
+ lldebugs << "Create and start timer to sync Inventory Friends All folder with Friends list" << llendl;
+
+ // do not worry about destruction of the FriendListUpdater.
+ // It will be deleted by LLEventTimer::updateClass when FriendListUpdater::tick() returns true.
+ new FriendListUpdater(boost::bind(&LLFriendCardsManager::syncFriendsFolder, this),
+ FETCH_FRIENDS_DESCENDENTS_PERIOD);
+ }
+ timer_started = true;
+ }
+ else
+ {
+ lldebugs << "Friends/All Inventory folder is synchronized with the Agent's Friends List" << llendl;
+ }
+
+ return mFriendsAllFolderCompleted;
}
void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBuddiesMap) const
@@ -264,7 +411,7 @@ void LLFriendCardsManager::collectFriendsLists(folderid_buddies_map_t& folderBud
/************************************************************************/
const LLUUID& LLFriendCardsManager::findFriendFolderUUIDImpl() const
{
- LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD);
+ const LLUUID callingCardsFolderID = gInventory.findCategoryUUIDForType(LLFolderType::FT_CALLINGCARD);
std::string friendFolderName = get_friend_folder_name();
@@ -374,7 +521,9 @@ bool LLFriendCardsManager::addFriendCardToInventory(const LLUUID& avatarID)
LLUUID friendListFolderID = findFriendAllSubfolderUUIDImpl();
if (shouldBeAdded && !invModel->isCategoryComplete(friendListFolderID))
{
+ mFriendsAllFolderCompleted = false;
shouldBeAdded = false;
+ lldebugs << "Friends/All category is not completed" << llendl;
}
if (shouldBeAdded)
{
@@ -433,4 +582,11 @@ void LLFriendCardsManager::onFriendListUpdate(U32 changed_mask)
}
}
+void LLFriendCardsManager::forceFriendListIsLoaded(const LLUUID& folder_id) const
+{
+ bool fetching_inventory = gInventory.fetchDescendentsOf(folder_id);
+ lldebugs << "Trying to fetch descendants of Friends/All Inventory folder, fetched: "
+ << fetching_inventory << llendl;
+}
+
// EOF
diff --git a/indra/newview/llfriendcard.h b/indra/newview/llfriendcard.h
index aa391ce2c1..feea05bc1d 100644
--- a/indra/newview/llfriendcard.h
+++ b/indra/newview/llfriendcard.h
@@ -72,6 +72,12 @@ public:
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;
@@ -83,8 +89,10 @@ public:
/**
* Synchronizes content of the Calling Card/Friends/All Global Inventory folder with Agent's Friend List
+ *
+ * @return true - if folder is already synchronized, false otherwise.
*/
- void syncFriendsFolder();
+ bool syncFriendsFolder();
/*!
* \brief
@@ -138,11 +146,20 @@ private:
void onFriendListUpdate(U32 changed_mask);
+ /**
+ * Force fetching of the Inventory folder specified by passed folder's LLUUID.
+ *
+ * It only sends request to server, server reply should be processed in other place.
+ * Because request can be sent via UDP we need to periodically check if request was completed with success.
+ */
+ void forceFriendListIsLoaded(const LLUUID& folder_id) const;
+
private:
typedef std::set<LLUUID> avatar_uuid_set_t;
avatar_uuid_set_t mBuddyIDSet;
+ bool mFriendsAllFolderCompleted;
};
#endif // LL_LLFRIENDCARD_H
diff --git a/indra/newview/llgroupactions.cpp b/indra/newview/llgroupactions.cpp
index d1cbe96906..c46eedbef2 100644
--- a/indra/newview/llgroupactions.cpp
+++ b/indra/newview/llgroupactions.cpp
@@ -35,13 +35,14 @@
#include "llgroupactions.h"
+// Viewer includes
#include "llagent.h"
+#include "llcommandhandler.h"
#include "llfloaterreg.h"
#include "llgroupmgr.h"
#include "llimview.h" // for gIMMgr
#include "llsidetray.h"
-
-#include "llcommandhandler.h"
+#include "llstatusbar.h" // can_afford_transaction()
//
// Globals
@@ -96,6 +97,13 @@ public:
return true;
}
+ if (tokens[1].asString() == "inspect")
+ {
+ LLSD key;
+ key["group_id"] = group_id;
+ LLFloaterReg::showInstance("inspect_group", key);
+ return true;
+ }
return false;
}
};
@@ -104,7 +112,53 @@ LLGroupHandler gGroupHandler;
// static
void LLGroupActions::search()
{
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "group"));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "groups"));
+}
+
+// static
+void LLGroupActions::join(const LLUUID& group_id)
+{
+ 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))
+ {
+ LLNotifications::instance().add("JoinGroupCanAfford", args, payload, onJoinGroup);
+ }
+ else
+ {
+ LLNotifications::instance().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 = LLNotification::getSelectedOption(notification, response);
+
+ if (option == 1)
+ {
+ // user clicked cancel
+ return false;
+ }
+
+ LLGroupMgr::getInstance()->
+ sendGroupMemberJoin(notification["payload"]["group_id"].asUUID());
+ return false;
}
// static
@@ -240,6 +294,14 @@ void LLGroupActions::startChat(const LLUUID& group_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())
diff --git a/indra/newview/llgroupactions.h b/indra/newview/llgroupactions.h
index 9fe1da8af2..74c84d1561 100644
--- a/indra/newview/llgroupactions.h
+++ b/indra/newview/llgroupactions.h
@@ -47,6 +47,9 @@ public:
*/
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.
*/
@@ -87,6 +90,9 @@ public:
*/
static void startChat(const LLUUID& group_id);
+ /// Returns if the current user is a member of the group
+ static bool isInGroup(const LLUUID& group_id);
+
/**
* Returns true if avatar is in group.
*
@@ -97,6 +103,7 @@ public:
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);
};
diff --git a/indra/newview/llgrouplist.cpp b/indra/newview/llgrouplist.cpp
index 4caef8e000..2e2b2d5101 100644
--- a/indra/newview/llgrouplist.cpp
+++ b/indra/newview/llgrouplist.cpp
@@ -43,6 +43,7 @@
// newview
#include "llagent.h"
#include "llgroupactions.h"
+#include "llfloaterreg.h"
#include "llviewercontrol.h" // for gSavedSettings
static LLDefaultChildRegistry::Register<LLGroupList> r("group_list");
@@ -231,6 +232,8 @@ BOOL LLGroupListItem::postBuild()
mInfoBtn = getChild<LLButton>("info_btn");
mInfoBtn->setClickedCallback(boost::bind(&LLGroupListItem::onInfoBtnClick, this));
+ childSetAction("profile_btn", boost::bind(&LLGroupListItem::onProfileBtnClick, this));
+
return TRUE;
}
@@ -315,12 +318,18 @@ void LLGroupListItem::setActive(bool active)
// rebuild the text. This will cause problems if the text contains
// hyperlinks, as their styles will be wrong.
std::string text = mGroupNameBox->getText();
- mGroupNameBox->clear();
+ mGroupNameBox->setText(LLStringUtil::null);
mGroupNameBox->appendText(text, false, style_params);
}
void LLGroupListItem::onInfoBtnClick()
{
+ LLFloaterReg::showInstance("inspect_group", LLSD().insert("group_id", mGroupID));
+}
+
+void LLGroupListItem::onProfileBtnClick()
+{
LLGroupActions::show(mGroupID);
}
+
//EOF
diff --git a/indra/newview/llgrouplist.h b/indra/newview/llgrouplist.h
index 9c3ab88901..8dbc13997c 100644
--- a/indra/newview/llgrouplist.h
+++ b/indra/newview/llgrouplist.h
@@ -98,6 +98,7 @@ public:
private:
void setActive(bool active);
void onInfoBtnClick();
+ void onProfileBtnClick();
LLTextBox* mGroupNameBox;
LLUUID mGroupID;
diff --git a/indra/newview/llgroupmgr.cpp b/indra/newview/llgroupmgr.cpp
index 5e50fad008..0626a5c3d3 100644
--- a/indra/newview/llgroupmgr.cpp
+++ b/indra/newview/llgroupmgr.cpp
@@ -50,7 +50,6 @@
#include "llstatusbar.h"
#include "lleconomy.h"
#include "llviewerwindow.h"
-#include "llfloaterdirectory.h"
#include "llpanelgroup.h"
#include "llgroupactions.h"
#include "lluictrlfactory.h"
@@ -1232,8 +1231,6 @@ void LLGroupMgr::processJoinGroupReply(LLMessageSystem* msg, void ** data)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// refresh the floater for this group, if any.
LLGroupActions::refresh(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
}
}
@@ -1254,8 +1251,6 @@ void LLGroupMgr::processLeaveGroupReply(LLMessageSystem* msg, void ** data)
LLGroupMgr::getInstance()->clearGroupData(group_id);
// close the floater for this group, if any.
LLGroupActions::closeGroup(group_id);
- // refresh the group panel of the search window, if necessary.
- LLFloaterDirectory::refreshGroup(group_id);
}
}
@@ -1325,11 +1320,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/llhudview.cpp b/indra/newview/llhudview.cpp
index 027cd2ab07..261d9f1df7 100644
--- a/indra/newview/llhudview.cpp
+++ b/indra/newview/llhudview.cpp
@@ -71,20 +71,6 @@ void LLHUDView::draw()
LLView::draw();
}
-
-// public
-const LLColor4& LLHUDView::colorFromType(S32 type)
-{
- switch (type)
- {
- case 0:
- return LLColor4::green;
- default:
- return LLColor4::black;
- }
-}
-
-
/*virtual*/
BOOL LLHUDView::handleMouseDown(S32 x, S32 y, MASK mask)
{
diff --git a/indra/newview/llhudview.h b/indra/newview/llhudview.h
index 05ff9c8596..0946e2c5c8 100644
--- a/indra/newview/llhudview.h
+++ b/indra/newview/llhudview.h
@@ -47,8 +47,6 @@ public:
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
index 680106c7bb..85863ed85b 100644
--- a/indra/newview/llimfloater.cpp
+++ b/indra/newview/llimfloater.cpp
@@ -42,54 +42,74 @@
#include "llchiclet.h"
#include "llfloaterchat.h"
#include "llfloaterreg.h"
-#include "llimview.h"
#include "lllineeditor.h"
#include "lllogchat.h"
#include "llpanelimcontrolpanel.h"
#include "llscreenchannel.h"
#include "lltrans.h"
-#include "llviewertexteditor.h"
+#include "llchathistory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lltransientfloatermgr.h"
+#include "llinventorymodel.h"
LLIMFloater::LLIMFloater(const LLUUID& session_id)
- : LLDockableFloater(NULL, session_id),
+ : LLTransientDockableFloater(NULL, true, session_id),
mControlPanel(NULL),
mSessionID(session_id),
mLastMessageIndex(-1),
- mLastFromName(),
mDialog(IM_NOTHING_SPECIAL),
- mHistoryEditor(NULL),
- mInputEditor(NULL),
- mPositioned(false)
+ mChatHistory(NULL),
+ mInputEditor(NULL),
+ mSavedTitle(),
+ mTypingStart(),
+ mShouldSendTypingState(false),
+ mMeTyping(false),
+ mOtherTyping(false),
+ mTypingTimer(),
+ mTypingTimeoutTimer(),
+ mPositioned(false),
+ mSessionInitialized(false)
{
- EInstantMessage type = LLIMModel::getInstance()->getType(session_id);
- if(IM_COUNT != type)
+ LLIMModel::LLIMSession* im_session = LLIMModel::getInstance()->findIMSession(mSessionID);
+ if (im_session)
{
- mDialog = type;
-
- if (IM_NOTHING_SPECIAL == mDialog || IM_SESSION_P2P_INVITE == mDialog)
- {
+ 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);
- }
- else
- {
+ break;
+ case IM_SESSION_CONFERENCE_START:
+ mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelAdHocControl, this);
+ break;
+ default:
mFactoryMap["panel_im_control_panel"] = LLCallbackMap(createPanelGroupControl, this);
}
}
+}
- LLTransientFloaterMgr::getInstance()->registerTransientFloater(this);
+void LLIMFloater::onFocusLost()
+{
+ LLIMModel::getInstance()->resetActiveSessionID();
+}
+
+void LLIMFloater::onFocusReceived()
+{
+ LLIMModel::getInstance()->setActiveSessionID(mSessionID);
}
// virtual
void LLIMFloater::onClose(bool app_quitting)
{
- LLIMModel::instance().sendLeaveSession(mSessionID, mOtherParticipantUUID);
-
- //*TODO - move to the IMModel::sendLeaveSession() for the integrity (IB)
- gIMMgr->removeSession(mSessionID);
+ if (!gIMMgr->hasSession(mSessionID)) return;
+
+ setTyping(false);
+ gIMMgr->leaveSession(mSessionID);
}
/* static */
@@ -114,10 +134,28 @@ void LLIMFloater::newIMCallback(const LLSD& data){
}
}
+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()
@@ -139,10 +177,16 @@ void LLIMFloater::sendMsg()
std::string utf8_text = wstring_to_utf8str(text);
utf8_text = utf8str_truncate(utf8_text, MAX_MSG_BUF_SIZE - 1);
- LLIMModel::sendMessage(utf8_text,
- mSessionID,
- mOtherParticipantUUID,
- mDialog);
+ 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);
@@ -155,7 +199,6 @@ void LLIMFloater::sendMsg()
LLIMFloater::~LLIMFloater()
{
- LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this);
}
//virtual
@@ -165,9 +208,10 @@ BOOL LLIMFloater::postBuild()
if (other_party_id.notNull())
{
mOtherParticipantUUID = other_party_id;
- mControlPanel->setID(mOtherParticipantUUID);
}
+ mControlPanel->setSessionId(mSessionID);
+
LLButton* slide_left = getChild<LLButton>("slide_left_btn");
slide_left->setVisible(mControlPanel->getVisible());
slide_left->setClickedCallback(boost::bind(&LLIMFloater::onSlide, this));
@@ -181,6 +225,7 @@ BOOL LLIMFloater::postBuild()
// 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 );
@@ -188,22 +233,50 @@ BOOL LLIMFloater::postBuild()
mInputEditor->setRevertOnEsc( FALSE );
mInputEditor->setReplaceNewlinesWithSpaces( FALSE );
+ std::string session_name(LLIMModel::instance().getName(mSessionID));
+
+ mInputEditor->setLabel(mInputEditor->getLabel() + " " + session_name);
+
+ LLStringUtil::toUpper(session_name);
+ setTitle(session_name);
+
childSetCommitCallback("chat_editor", onSendMsg, this);
- mHistoryEditor = getChild<LLViewerTextEditor>("im_text");
-
- setTitle(LLIMModel::instance().getName(mSessionID));
+ mChatHistory = getChild<LLChatHistory>("chat_history");
+
setDocked(true);
-
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+
+ 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 )
{
- LLLogChat::loadHistory(getTitle(), &chatFromLogFile, (void *)this);
+ 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)
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
@@ -220,16 +293,27 @@ void* LLIMFloater::createPanelIMControl(void* userdata)
void* LLIMFloater::createPanelGroupControl(void* userdata)
{
LLIMFloater *self = (LLIMFloater*)userdata;
- self->mControlPanel = new LLPanelGroupControlPanel();
+ 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()
{
LLPanel* im_control_panel = getChild<LLPanel>("panel_im_control_panel");
im_control_panel->setVisible(!im_control_panel->getVisible());
+ gSavedSettings.setBOOL("IMShowControlPanel", im_control_panel->getVisible());
+
getChild<LLButton>("slide_left_btn")->setVisible(im_control_panel->getVisible());
getChild<LLButton>("slide_right_btn")->setVisible(!im_control_panel->getVisible());
}
@@ -272,6 +356,8 @@ LLIMFloater* LLIMFloater::show(const LLUUID& session_id)
LLDockControl::TOP, boost::bind(&LLIMFloater::getAllowedRect, floater, _1)));
}
+ floater->childSetVisible("panel_im_control_panel", gSavedSettings.getBOOL("IMShowControlPanel"));
+
return floater;
}
@@ -286,8 +372,10 @@ void LLIMFloater::setDocked(bool docked, bool pop_on_undock)
LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
(LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
+
+ setCanResize(!docked);
- LLDockableFloater::setDocked(docked, pop_on_undock);
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
// update notification channel state
if(channel)
@@ -301,7 +389,7 @@ void LLIMFloater::setVisible(BOOL visible)
LLNotificationsUI::LLScreenChannel* channel = dynamic_cast<LLNotificationsUI::LLScreenChannel*>
(LLNotificationsUI::LLChannelManager::getInstance()->
findChannelByID(LLUUID(gSavedSettings.getString("NotificationChannelUUID"))));
- LLDockableFloater::setVisible(visible);
+ LLTransientDockableFloater::setVisible(visible);
// update notification channel state
if(channel)
@@ -331,55 +419,74 @@ bool LLIMFloater::toggle(const LLUUID& session_id)
{
// ensure the list of messages is updated when floater is made visible
show(session_id);
- // update number of unread notifications in the SysWell
- LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
return true;
}
}
-void LLIMFloater::updateMessages()
+//static
+LLIMFloater* LLIMFloater::findInstance(const LLUUID& session_id)
{
- std::list<LLSD> messages = LLIMModel::instance().getMessages(mSessionID, mLastMessageIndex+1);
- std::string agent_name;
+ return LLFloaterReg::findTypedInstance<LLIMFloater>("impanel", session_id);
+}
+
+void LLIMFloater::sessionInitReplyReceived(const LLUUID& im_session_id)
+{
+ mSessionInitialized = true;
- gCacheName->getFullName(gAgentID, agent_name);
+ //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()
+{
+ std::list<LLSD> messages;
+ LLIMModel::instance().getMessages(mSessionID, messages, mLastMessageIndex+1);
if (messages.size())
{
- LLUIColor divider_color = LLUIColorTable::instance().getColor("LtGray_50");
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)
+ for (; iter != iter_end; ++iter)
{
LLSD msg = *iter;
- const bool prepend_newline = true;
- std::string from = msg["from"].asString();
- if (from == agent_name)
- from = LLTrans::getString("You");
- if (mLastFromName != from)
- {
- message << from << " ----- " << msg["time"].asString();
- mHistoryEditor->appendText(message.str(),
- prepend_newline, LLStyle::Params().color(divider_color) );
- message.str("");
- mLastFromName = from;
- }
+ std::string time = msg["time"].asString();
+ LLUUID from_id = msg["from_id"].asUUID();
+ std::string from = from_id != gAgentID ? msg["from"].asString() : LLTrans::getString("You");
+ std::string message = msg["message"].asString();
+ LLStyle::Params style_params;
+ style_params.color(chat_color);
+
+ LLChat chat(message);
+ chat.mFromID = from_id;
+ chat.mFromName = from;
- message << msg["message"].asString();
- mHistoryEditor->appendText(message.str(),
- prepend_newline,
- LLStyle::Params().color(chat_color) );
- message.str("");
+ mChatHistory->appendWidgetMessage(chat, style_params);
mLastMessageIndex = msg["index"].asInteger();
}
- mHistoryEditor->blockUndo();
-
- mHistoryEditor->setCursorAndScrollToEnd();
}
}
@@ -388,17 +495,22 @@ void LLIMFloater::onInputEditorFocusReceived( LLFocusableElement* caller, void*
{
LLIMFloater* self= (LLIMFloater*) userdata;
- //in disconnected state IM input editor should be disabled
- self->mInputEditor->setEnabled(!gDisconnected);
-
- self->mHistoryEditor->setCursorAndScrollToEnd();
+ // Allow enabling the LLIMFloater input editor only if session can accept text
+ LLIMModel::LLIMSession* im_session =
+ LLIMModel::instance().findIMSession(self->mSessionID);
+ if( im_session && im_session->mTextIMPossible )
+ {
+ //in disconnected state IM input editor should be disabled
+ self->mInputEditor->setEnabled(!gDisconnected);
+ }
+ self->mChatHistory->setCursorAndScrollToEnd();
}
// static
void LLIMFloater::onInputEditorFocusLost(LLFocusableElement* caller, void* userdata)
{
LLIMFloater* self = (LLIMFloater*) userdata;
- self->setTyping(FALSE);
+ self->setTyping(false);
}
// static
@@ -408,52 +520,297 @@ void LLIMFloater::onInputEditorKeystroke(LLLineEditor* caller, void* userdata)
std::string text = self->mInputEditor->getText();
if (!text.empty())
{
- self->setTyping(TRUE);
+ self->setTyping(true);
}
else
{
// Deleting all text counts as stopping typing.
- self->setTyping(FALSE);
+ 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::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);
-//just a stub for now
-void LLIMFloater::setTyping(BOOL typing)
+ 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;
}
-void LLIMFloater::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
+BOOL LLIMFloater::dropCallingCard(LLInventoryItem* item, BOOL drop)
{
- if (!userdata) return;
+ 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;
+}
- LLIMFloater* self = (LLIMFloater*) userdata;
- std::string message = line;
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- switch (type)
+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)
{
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (im_log_option!=LOG_CHAT)
+ 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++)
{
- message = LLTrans::getString("IM_logging_string");
+ data["params"].append(ids[i]);
}
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (im_log_option!=LOG_CHAT)
+
+ 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 )
{
- message = LLTrans::getString("IM_logging_string");
+ speaker_mgr->setSpeakerTyping(im_info->mFromID, TRUE);
}
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
}
+}
+
+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);
+ }
+ }
- self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
- self->mHistoryEditor->blockUndo();
+ }
}
+
diff --git a/indra/newview/llimfloater.h b/indra/newview/llimfloater.h
index 5276013568..f5edb3188a 100644
--- a/indra/newview/llimfloater.h
+++ b/indra/newview/llimfloater.h
@@ -33,19 +33,21 @@
#ifndef LL_IMFLOATER_H
#define LL_IMFLOATER_H
-#include "lldockablefloater.h"
+#include "lltransientdockablefloater.h"
#include "lllogchat.h"
+#include "lltooldraganddrop.h"
class LLLineEditor;
class LLPanelChatControlPanel;
-class LLViewerTextEditor;
-
+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 LLDockableFloater
+class LLIMFloater : public LLTransientDockableFloater
{
public:
LLIMFloater(const LLUUID& session_id);
@@ -55,6 +57,8 @@ public:
// 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);
@@ -68,6 +72,10 @@ public:
// Returns true iff panel became visible
static bool toggle(const LLUUID& session_id);
+ static LLIMFloater* findInstance(const LLUUID& session_id);
+
+ void sessionInitReplyReceived(const LLUUID& im_session_id);
+
// get new messages from LLIMModel
void updateMessages();
static void onSendMsg( LLUICtrl*, void*);
@@ -80,34 +88,63 @@ public:
// 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 processSessionUpdate(const LLSD& session_update);
+
+ BOOL handleDragAndDrop(S32 x, S32 y, MASK mask,
+ BOOL drop, EDragAndDropType cargo_type,
+ void *cargo_data, EAcceptance *accept,
+ std::string& tooltip_msg);
+
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 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);
- static void chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata);
+ // 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;
- // username of last user who added text to this conversation, used to
- // suppress duplicate username divider bars
- std::string mLastFromName;
-
EInstantMessage mDialog;
LLUUID mOtherParticipantUUID;
- LLViewerTextEditor* mHistoryEditor;
+ 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;
};
diff --git a/indra/newview/llimpanel.cpp b/indra/newview/llimpanel.cpp
index 99f331d087..7399f1e1b3 100644
--- a/indra/newview/llimpanel.cpp
+++ b/indra/newview/llimpanel.cpp
@@ -54,6 +54,7 @@
#include "llconsole.h"
#include "llgroupactions.h"
#include "llfloater.h"
+#include "llfloateractivespeakers.h"
#include "llfloatercall.h"
#include "llavataractions.h"
#include "llimview.h"
@@ -69,6 +70,7 @@
#include "llpanelimcontrolpanel.h"
#include "llrecentpeople.h"
#include "llresmgr.h"
+#include "lltooldraganddrop.h"
#include "lltrans.h"
#include "lltabcontainer.h"
#include "llviewertexteditor.h"
@@ -77,6 +79,7 @@
#include "llviewercontrol.h"
#include "lluictrlfactory.h"
#include "llviewerwindow.h"
+#include "llvoicechannel.h"
#include "lllogchat.h"
#include "llweb.h"
#include "llhttpclient.h"
@@ -90,7 +93,6 @@
const S32 LINE_HEIGHT = 16;
const S32 MIN_WIDTH = 200;
const S32 MIN_HEIGHT = 130;
-const U32 DEFAULT_RETRIES_COUNT = 3;
//
// Statics
@@ -100,831 +102,6 @@ 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;
-
-
-
-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;
-}
-
-void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
-{
- if (state == STATE_CONNECTED)
- {
- LLFloaterReg::showInstance("voice_call", mSessionID);
- }
- // By checking that current state is CONNECTED we make sure that the call window
- // has been shown, hence there's something to hide. This helps when user presses
- // the "End call" button right after initiating the call.
- // *TODO: move this check to LLFloaterCall?
- else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
- {
- LLFloaterReg::hideInstance("voice_call", mSessionID);
- }
-}
-
-//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);
-
-#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
- }
-}
-
-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)
-{
- // HACK: Open/close the call window if needed.
- toggleCallWindowIfNeeded(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();
- }
-
- // Add the party to the list of people with which we've recently interacted.
- LLRecentPeople::instance().add(mOtherUserID);
- }
-}
-
-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)
-{
- // HACK: Open/close the call window if needed.
- toggleCallWindowIfNeeded(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
@@ -951,7 +128,6 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
mSentTypingState(TRUE),
mNumUnreadMessages(0),
mShowSpeakersOnConnect(TRUE),
- mAutoConnect(FALSE),
mTextIMPossible(TRUE),
mProfileButtonEnabled(TRUE),
mCallBackEnabled(TRUE),
@@ -1006,40 +182,28 @@ LLFloaterIMPanel::LLFloaterIMPanel(const std::string& session_label,
// 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 ( !LLIMModel::instance().sendStartSession(
- 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,
- LLUIColorTable::instance().getColor("SystemChatColor"),
- false);
- }
+ addHistoryLine(
+ session_start,
+ LLUIColorTable::instance().getColor("SystemChatColor"),
+ false);
}
}
@@ -1184,12 +348,6 @@ 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 && voice_channel->isActive())
{
@@ -1346,25 +504,6 @@ void LLFloaterIMPanel::addHistoryLine(const std::string &utf8msg, const LLColor4
mHistoryEditor->appendText(utf8msg, prepend_newline, LLStyle::Params().color(color));
mHistoryEditor->blockUndo();
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- if (log_to_file && (im_log_option!=LOG_CHAT))
- {
- std::string histstr;
- if (gSavedPerAccountSettings.getBOOL("LogTimestamp"))
- histstr = LLLogChat::timestamp(gSavedPerAccountSettings.getBOOL("LogTimestampDate")) + name + separator_string + utf8msg;
- else
- histstr = name + separator_string + utf8msg;
-
- if(im_log_option==LOG_BOTH_TOGETHER)
- {
- LLLogChat::saveHistory(std::string("chat"),histstr);
- }
- else
- {
- LLLogChat::saveHistory(getTitle(),histstr);
- }
- }
-
if (!isInVisibleChain())
{
mNumUnreadMessages++;
@@ -1549,7 +688,7 @@ void LLFloaterIMPanel::onClickStartCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->activate();
+ gIMMgr->startCall(self->mSessionUUID);
}
// static
@@ -1557,7 +696,7 @@ void LLFloaterIMPanel::onClickEndCall(void* userdata)
{
LLFloaterIMPanel* self = (LLFloaterIMPanel*) userdata;
- LLIMModel::getInstance()->getVoiceChannel(self->mSessionUUID)->deactivate();
+ gIMMgr->endCall(self->mSessionUUID);
}
// static
@@ -1617,9 +756,7 @@ void LLFloaterIMPanel::onClose(bool app_quitting)
{
setTyping(FALSE);
- LLIMModel::instance().sendLeaveSession(mSessionUUID, mOtherParticipantUUID);
-
- gIMMgr->removeSession(mSessionUUID);
+ gIMMgr->leaveSession(mSessionUUID);
// *HACK hide the voice floater
LLFloaterReg::hideInstance("voice_call", mSessionUUID);
@@ -1654,6 +791,8 @@ 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);
@@ -1734,11 +873,6 @@ void LLFloaterIMPanel::sessionInitReplyReceived(const LLUUID& session_id)
}
}
-void LLFloaterIMPanel::requestAutoConnect()
-{
- mAutoConnect = TRUE;
-}
-
void LLFloaterIMPanel::setTyping(BOOL typing)
{
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(mSessionUUID);
@@ -1837,110 +971,8 @@ void LLFloaterIMPanel::removeTypingIndicator(const LLIMInfo* im_info)
}
}
-//static
-void LLFloaterIMPanel::chatFromLogFile(LLLogChat::ELogLineType type, std::string line, void* userdata)
-{
- LLFloaterIMPanel* self = (LLFloaterIMPanel*)userdata;
- std::string message = line;
- S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
- switch (type)
- {
- case LLLogChat::LOG_EMPTY:
- // add warning log enabled message
- if (im_log_option!=LOG_CHAT)
- {
- message = LLTrans::getString("IM_logging_string");
- }
- break;
- case LLLogChat::LOG_END:
- // add log end message
- if (im_log_option!=LOG_CHAT)
- {
- message = LLTrans::getString("IM_logging_string");
- }
- break;
- case LLLogChat::LOG_LINE:
- // just add normal lines from file
- break;
- default:
- // nothing
- break;
- }
-
- //self->addHistoryLine(line, LLColor4::grey, FALSE);
- self->mHistoryEditor->appendText(message, true, LLStyle::Params().color(LLUIColorTable::instance().getColor("ChatHistoryTextColor")));
- self->mHistoryEditor->blockUndo();
-}
-
-void LLFloaterIMPanel::showSessionStartError(
- const std::string& error_string)
-{
- LLSD args;
- args["REASON"] = LLTrans::getString(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"] =
- LLTrans::getString(error_string);
- args["EVENT"] =
- LLTrans::getString(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"] = LLTrans::getString(reason_string);
-
- LLSD payload;
- payload["session_id"] = mSessionUUID;
-
- LLNotifications::instance().add(
- "ForceCloseChatterBoxSession",
- args,
- payload,
- LLFloaterIMPanel::onConfirmForceCloseError);
-
-}
-
//static
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->closeFloater(FALSE);
- }
- return false;
-}
diff --git a/indra/newview/llimpanel.h b/indra/newview/llimpanel.h
index 57379b2c0d..b8f99d45c9 100644
--- a/indra/newview/llimpanel.h
+++ b/indra/newview/llimpanel.h
@@ -50,133 +50,6 @@ class LLIMSpeakerMgr;
class LLPanelActiveSpeakers;
class LLPanelChatControlPanel;
-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 std::string& getSessionName() const { return mSessionName; }
-
- 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 toggleCallWindowIfNeeded(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 LLFloaterIMPanel : public LLFloater
{
public:
@@ -250,22 +123,10 @@ public:
EInstantMessage getDialogType() const { return mDialog; }
void setDialogType(EInstantMessage dialog) { mDialog = dialog; }
- void requestAutoConnect();
-
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 UI methods.
@@ -336,8 +197,6 @@ private:
BOOL mShowSpeakersOnConnect;
- BOOL mAutoConnect;
-
BOOL mTextIMPossible;
BOOL mProfileButtonEnabled;
BOOL mCallBackEnabled;
diff --git a/indra/newview/llimview.cpp b/indra/newview/llimview.cpp
index 6b947b2503..7e8701bf21 100644
--- a/indra/newview/llimview.cpp
+++ b/indra/newview/llimview.cpp
@@ -40,7 +40,7 @@
#include "llerror.h"
#include "llbutton.h"
#include "llhttpclient.h"
-#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llstring.h"
#include "lluictrlfactory.h"
@@ -70,6 +70,7 @@
#include "llviewerwindow.h"
#include "llnotify.h"
#include "llviewerregion.h"
+#include "llvoicechannel.h"
#include "lltrans.h"
#include "llrecentpeople.h"
@@ -86,47 +87,70 @@ LLIMMgr* gIMMgr = NULL;
//
// *FIXME: make these all either UIStrings or Strings
-
-std::map<LLUUID, LLIMModel::LLIMSession*> LLIMModel::sSessionsMap;
-
+const static std::string IM_SEPARATOR(": ");
void toast_callback(const LLSD& msg){
- // do not show toast in busy mode
- if (gAgent.getBusy())
+ // do not show toast in busy mode or it goes from agent
+ if (gAgent.getBusy() || gAgent.getID() == msg["from_id"])
{
return;
}
-
- //we send notifications to reset counter also
- if (msg["num_unread"].asInteger())
+
+ // check whether incoming IM belongs to an active session or not
+ if (LLIMModel::getInstance()->getActiveSessionID() == msg["session_id"])
{
- 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"];
+ return;
+ }
- LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
+ // Skip toasting for system messages
+ if (msg["from_id"].asUUID() == LLUUID::null)
+ {
+ 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"];
+
+ LLNotifications::instance().add("IMToast", args, LLSD(), boost::bind(&LLIMFloater::show, msg["session_id"].asUUID()));
}
-LLIMModel::LLIMModel()
+void LLIMModel::setActiveSessionID(const LLUUID& session_id)
{
- addChangedCallback(LLIMFloater::newIMCallback);
- addChangedCallback(toast_callback);
+ // 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);
+ addNoUnreadMsgsCallback(LLIMFloater::newIMCallback);
+ addNewMsgCallback(toast_callback);
+}
-LLIMModel::LLIMSession::LLIMSession( const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id )
+LLIMModel::LLIMSession::LLIMSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
: mSessionID(session_id),
mName(name),
mType(type),
mNumUnread(0),
mOtherParticipantID(other_participant_id),
+ mInitialTargetIDs(ids),
mVoiceChannel(NULL),
- mSpeakers(NULL)
+ mSpeakers(NULL),
+ mSessionInitialized(false),
+ mCallBackEnabled(true),
+ mTextIMPossible(true),
+ mOtherParticipantIsAvatar(true)
{
if (IM_NOTHING_SPECIAL == type || IM_SESSION_P2P_INVITE == type)
{
@@ -140,6 +164,26 @@ LLIMModel::LLIMSession::LLIMSession( const LLUUID& session_id, const std::string
// All participants will be added to the list of people we've recently interacted with.
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);
+ mOtherParticipantIsAvatar = LLVoiceClient::getInstance()->isParticipantAvatar(mSessionID);
+ }
+
+ if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
+ LLLogChat::loadHistory(mName, &chatFromLogFile, (void *)this);
}
LLIMModel::LLIMSession::~LLIMSession()
@@ -170,26 +214,84 @@ LLIMModel::LLIMSession::~LLIMSession()
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);
+ }
+}
+
+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(LLIMModel::instance().sSessionsMap, session_id,
+ return get_if_there(mId2SessionMap, session_id,
(LLIMModel::LLIMSession*) NULL);
}
-void LLIMModel::updateSessionID(const LLUUID& old_session_id, const LLUUID& new_session_id)
+void LLIMModel::processSessionInitializedReply(const LLUUID& old_session_id, const LLUUID& new_session_id)
{
- if (new_session_id == old_session_id) return;
-
LLIMSession* session = findIMSession(old_session_id);
if (session)
{
- session->mSessionID = new_session_id;
- session->mVoiceChannel->updateSessionID(new_session_id);
+ session->sessionInitReplyReceived(new_session_id);
- //*TODO set session initialized flag here? (IB)
+ if (old_session_id != new_session_id)
+ {
+ mId2SessionMap.erase(old_session_id);
+ mId2SessionMap[new_session_id] = session;
- sSessionsMap.erase(old_session_id);
- sSessionsMap[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);
+ }
+ }
+
+ //*TODO remove this "floater" stuff when Communicate Floater is gone
+ LLFloaterIMPanel* floater = gIMMgr->findFloaterBySession(old_session_id);
+ if (floater)
+ {
+ floater->sessionInitReplyReceived(new_session_id);
}
}
@@ -219,16 +321,17 @@ void LLIMModel::testMessages()
}
-bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id)
+bool LLIMModel::newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type,
+ const LLUUID& other_participant_id, const std::vector<LLUUID>& ids)
{
- if (is_in_map(sSessionsMap, session_id))
+ 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);
- sSessionsMap[session_id] = session;
+ LLIMSession* session = new LLIMSession(session_id, name, type, other_participant_id, ids);
+ mId2SessionMap[session_id] = session;
LLIMMgr::getInstance()->notifyObserverSessionAdded(session_id, name, other_participant_id);
@@ -236,24 +339,21 @@ bool LLIMModel::newSession(LLUUID session_id, std::string name, EInstantMessage
}
-bool LLIMModel::clearSession(LLUUID session_id)
+bool LLIMModel::clearSession(const LLUUID& session_id)
{
- if (sSessionsMap.find(session_id) == sSessionsMap.end()) return false;
- delete (sSessionsMap[session_id]);
- sSessionsMap.erase(session_id);
+ if (mId2SessionMap.find(session_id) == mId2SessionMap.end()) return false;
+ delete (mId2SessionMap[session_id]);
+ mId2SessionMap.erase(session_id);
return true;
}
-//*TODO remake it, instead of returing the list pass it as as parameter (IB)
-std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
+void LLIMModel::getMessages(const LLUUID& session_id, std::list<LLSD>& messages, int start_index)
{
- std::list<LLSD> return_list;
-
LLIMSession* session = findIMSession(session_id);
if (!session)
{
llwarns << "session " << session_id << "does not exist " << llendl;
- return return_list;
+ return;
}
int i = session->mMsgs.size() - start_index;
@@ -264,7 +364,7 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
{
LLSD msg;
msg = *iter;
- return_list.push_back(*iter);
+ messages.push_back(*iter);
i--;
}
@@ -273,15 +373,10 @@ std::list<LLSD> LLIMModel::getMessages(LLUUID session_id, int start_index)
LLSD arg;
arg["session_id"] = session_id;
arg["num_unread"] = 0;
- mChangedSignal(arg);
-
- // TODO: in the future is there a more efficient way to return these
- //of course there is - return as parameter (IB)
- return return_list;
-
+ mNoUnreadMsgsSignal(arg);
}
-bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string utf8_text) {
+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);
@@ -291,21 +386,49 @@ bool LLIMModel::addToHistory(LLUUID session_id, std::string from, std::string ut
return false;
}
- LLSD message;
- message["from"] = from;
- message["message"] = utf8_text;
- message["time"] = LLLogChat::timestamp(false); //might want to add date separately
- message["index"] = (LLSD::Integer)session->mMsgs.size();
-
- session->mMsgs.push_front(message);
+ session->addMessage(from, from_id, utf8_text, LLLogChat::timestamp(false)); //might want to add date separately
return true;
+}
+bool LLIMModel::logToFile(const LLUUID& session_id, const std::string& from, const LLUUID& from_id, const std::string& utf8_text)
+{
+ S32 im_log_option = gSavedPerAccountSettings.getS32("IMLogOptions");
+ if (im_log_option != LOG_CHAT)
+ {
+ if(im_log_option == LOG_BOTH_TOGETHER)
+ {
+ LLLogChat::saveHistory(std::string("chat"), from, from_id, utf8_text);
+ return true;
+ }
+ else
+ {
+ LLLogChat::saveHistory(LLIMModel::getInstance()->getName(session_id), from, from_id, utf8_text);
+ return true;
+ }
+ }
+ return false;
}
-
-bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id, std::string 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 = findIMSession(session_id);
if (!session)
@@ -314,11 +437,9 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
return false;
}
- addToHistory(session_id, from, utf8_text);
+ addToHistory(session_id, from, from_id, utf8_text);
+ if (log2file) logToFile(session_id, from, from_id, utf8_text);
- std::string agent_name;
- LLAgentUI::buildFullname(agent_name);
-
session->mNumUnread++;
// notify listeners
@@ -329,7 +450,7 @@ bool LLIMModel::addMessage(LLUUID session_id, std::string from, LLUUID from_id,
arg["from"] = from;
arg["from_id"] = from_id;
arg["time"] = LLLogChat::timestamp(false);
- mChangedSignal(arg);
+ mNewMsgSignal(arg);
return true;
}
@@ -429,7 +550,7 @@ void LLIMModel::sendTypingState(LLUUID session_id, LLUUID other_participant_id,
gAgent.sendReliableMessage();
}
-void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id)
+void LLIMModel::sendLeaveSession(const LLUUID& session_id, const LLUUID& other_participant_id)
{
if(session_id.notNull())
{
@@ -450,8 +571,7 @@ void LLIMModel::sendLeaveSession(LLUUID session_id, LLUUID other_participant_id)
}
}
-
-//*TODO update list of messages in a LLIMSession (IB)
+//*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,
@@ -527,7 +647,7 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
// Do we have to replace the /me's here?
std::string from;
LLAgentUI::buildFullname(from);
- LLIMModel::instance().addToHistory(im_session_id, from, utf8_text);
+ LLIMModel::getInstance()->addMessage(im_session_id, from, gAgentID, utf8_text);
//local echo for the legacy communicate panel
std::string history_echo;
@@ -559,14 +679,8 @@ void LLIMModel::sendMessage(const std::string& utf8_text,
}
// Add the recipient to the recent people list.
- //*TODO should be deleted, because speaker manager updates through callback the recent list
LLRecentPeople::instance().add(other_participant_id);
}
-
-boost::signals2::connection LLIMModel::addChangedCallback( boost::function<void (const LLSD& data)> cb )
-{
- return mChangedSignal.connect(cb);
-}
void session_starter_helper(
const LLUUID& temp_session_id,
@@ -695,18 +809,10 @@ bool LLIMModel::sendStartSession(
temp_session_id,
other_participant_id,
dialog);
-
- switch(dialog)
- {
- case IM_SESSION_GROUP_START:
- gMessageSystem->addBinaryDataFast(
+ gMessageSystem->addBinaryDataFast(
_PREHASH_BinaryBucket,
EMPTY_BINARY_BUCKET,
EMPTY_BINARY_BUCKET_SIZE);
- break;
- default:
- break;
- }
gAgent.sendReliableMessage();
return true;
@@ -748,6 +854,9 @@ bool LLIMModel::sendStartSession(
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;
@@ -798,23 +907,18 @@ public:
//in case of race conditions
speaker_mgr->updateSpeakers(gIMMgr->getPendingAgentListUpdates(mSessionID));
}
-
- LLFloaterIMPanel* floaterp =
- gIMMgr->findFloaterBySession(mSessionID);
- if (floaterp)
+ if (LLIMMgr::INVITATION_TYPE_VOICE == mInvitiationType)
{
- if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE )
- {
- floaterp->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(floaterp);
- // always open IM window when connecting to voice
- LLFloaterReg::showInstance("communicate", LLSD(), TRUE);
- }
- else if ( mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE )
- {
- LLFloaterReg::showInstance("communicate", LLSD(), TRUE);
- }
+ gIMMgr->startCall(mSessionID);
+ }
+
+ if ((mInvitiationType == LLIMMgr::INVITATION_TYPE_VOICE
+ || mInvitiationType == LLIMMgr::INVITATION_TYPE_IMMEDIATE)
+ && LLIMModel::getInstance()->findIMSession(mSessionID))
+ {
+ // always open IM window when connecting to voice
+ LLIMFloater::show(mSessionID);
}
gIMMgr->clearPendingAgentListUpdates(mSessionID);
@@ -829,20 +933,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 = "does not exist";
+ gIMMgr->showSessionStartError(error_string, mSessionID);
}
}
}
@@ -894,6 +989,106 @@ 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;
+
+ LLNotifications::instance().add(
+ "ChatterBoxSessionStartError",
+ args,
+ payload,
+ LLIMMgr::onConfirmForceCloseError);
+}
+
+void
+LLIMMgr::showSessionEventError(
+ const std::string& event_string,
+ 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["EVENT"] =
+ LLTrans::getString(event_string);
+ args["RECIPIENT"] = floater->getTitle();
+
+ LLNotifications::instance().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;
+
+ LLNotifications::instance().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;
+}
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLIncomingCallDialog
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -985,20 +1180,13 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
if (voice)
{
- LLFloaterIMPanel* im_floater =
- gIMMgr->findFloaterBySession(
- session_id);
-
- if (im_floater)
+ if (gIMMgr->startCall(session_id))
{
- im_floater->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(im_floater);
+ // always open IM window when connecting to voice
+ LLIMFloater::show(session_id);
}
}
- // always open IM window when connecting to voice
- LLFloaterReg::showInstance("communicate", session_id);
-
gIMMgr->clearPendingAgentListUpdates(session_id);
gIMMgr->clearPendingInvitation(session_id);
}
@@ -1060,29 +1248,6 @@ void LLIncomingCallDialog::processCallResponse(S32 response)
}
}
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLIMViewFriendObserver
-//
-// Bridge to suport knowing when the inventory has changed.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-
-class LLIMViewFriendObserver : public LLFriendObserver
-{
-public:
- LLIMViewFriendObserver(LLIMMgr* tv) : mTV(tv) {}
- virtual ~LLIMViewFriendObserver() {}
- virtual void changed(U32 mask)
- {
- if(mask & (LLFriendObserver::ADD | LLFriendObserver::REMOVE | LLFriendObserver::ONLINE))
- {
- mTV->refresh();
- }
- }
-protected:
- LLIMMgr* mTV;
-};
-
-
bool inviteUserResponse(const LLSD& notification, const LLSD& response)
{
const LLSD& payload = notification["payload"];
@@ -1103,15 +1268,10 @@ 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)
+ if (gIMMgr->startCall(session_id))
{
- im_floater->requestAutoConnect();
- LLFloaterIMPanel::onClickStartCall(im_floater);
// always open IM window when connecting to voice
- LLFloaterReg::showInstance("communicate", session_id, TRUE);
+ LLIMFloater::show(session_id);
}
gIMMgr->clearPendingAgentListUpdates(session_id);
@@ -1188,7 +1348,6 @@ bool inviteUserResponse(const LLSD& notification, const LLSD& response)
//
LLIMMgr::LLIMMgr() :
- mFriendObserver(NULL),
mIMReceived(FALSE)
{
static bool registered_dialog = false;
@@ -1197,21 +1356,11 @@ LLIMMgr::LLIMMgr() :
LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
registered_dialog = true;
}
-
- mFriendObserver = new LLIMViewFriendObserver(this);
- LLAvatarTracker::instance().addObserver(mFriendObserver);
mPendingInvitations = LLSD::emptyMap();
mPendingAgentListUpdates = LLSD::emptyMap();
}
-LLIMMgr::~LLIMMgr()
-{
- LLAvatarTracker::instance().removeObserver(mFriendObserver);
- delete mFriendObserver;
- // Children all cleaned up by default view destructor.
-}
-
// Add a message to a session.
void LLIMMgr::addMessage(
const LLUUID& session_id,
@@ -1235,13 +1384,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())
@@ -1250,9 +1392,17 @@ void LLIMMgr::addMessage(
new_session_id = computeSessionID(dialog, other_participant_id);
}
- if (!LLIMModel::getInstance()->findIMSession(new_session_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)
{
- LLIMModel::instance().newSession(session_id, session_name, dialog, other_participant_id);
+ 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);
@@ -1269,20 +1419,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.
@@ -1292,7 +1438,7 @@ void LLIMMgr::addMessage(
std::ostringstream bonus_info;
bonus_info << LLTrans::getString("***")+ " "+ LLTrans::getString("IMParentEstate") + ":" + " "
<< parent_estate_id
- << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
+ << ((parent_estate_id == 1) ? "," + LLTrans::getString("IMMainland") : "")
<< ((parent_estate_id == 5) ? "," + LLTrans::getString ("IMTeen") : "");
// once we have web-services (or something) which returns
@@ -1320,14 +1466,6 @@ void LLIMMgr::addMessage(
else
{
floater->addHistoryLine(msg, color, true, other_participant_id, from); // Insert linked name to front of message
-
- //*TODO consider moving that speaker management stuff into model (IB)
- LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(new_session_id);
- if (speaker_mgr)
- {
- speaker_mgr->speakerChatted(gAgentID);
- speaker_mgr->setSpeakerTyping(gAgentID, FALSE);
- }
}
LLIMModel::instance().addMessage(new_session_id, from, other_participant_id, msg);
@@ -1371,12 +1509,10 @@ void LLIMMgr::addSystemMessage(const LLUUID& session_id, const std::string& mess
}
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());
}
}
@@ -1395,12 +1531,9 @@ S32 LLIMMgr::getNumberOfUnreadIM()
std::map<LLUUID, LLIMModel::LLIMSession*>::iterator it;
S32 num = 0;
- for(it = LLIMModel::sSessionsMap.begin(); it != LLIMModel::sSessionsMap.end(); ++it)
+ for(it = LLIMModel::getInstance()->mId2SessionMap.begin(); it != LLIMModel::getInstance()->mId2SessionMap.end(); ++it)
{
- if((*it).first != mBeingRemovedSessionID)
- {
- num += (*it).second->mNumUnread;
- }
+ num += (*it).second->mNumUnread;
}
return num;
@@ -1416,15 +1549,6 @@ 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)
-{
- LLFloaterIMPanel* floater = findFloaterBySession(uuid);
- if(floater) return TRUE;
- return FALSE;
-}
-
LLUUID LLIMMgr::addP2PSession(const std::string& name,
const LLUUID& other_participant_id,
const std::string& voice_session_handle,
@@ -1473,11 +1597,15 @@ LLUUID LLIMMgr::addSession(
LLUUID session_id = computeSessionID(dialog,other_participant_id);
- if (!LLIMModel::getInstance()->findIMSession(session_id))
+ bool new_session = !LLIMModel::getInstance()->findIMSession(session_id);
+
+ if (new_session)
{
- LLIMModel::instance().newSession(session_id, name, dialog, other_participant_id);
+ LLIMModel::getInstance()->newSession(session_id, name, dialog, other_participant_id, ids);
}
+
+ //*TODO remove this "floater" thing when Communicate Floater's gone
LLFloaterIMPanel* floater = findFloaterBySession(session_id);
if(!floater)
{
@@ -1490,58 +1618,51 @@ LLUUID LLIMMgr::addSession(
dialog,
TRUE,
ids);
+ }
- if ( !floater ) return LLUUID::null;
-
- noteOfflineUsers(floater, ids);
+ //we don't need to show notes about online/offline, mute/unmute users' statuses for existing sessions
+ if (!new_session) return session_id;
+
+ noteOfflineUsers(session_id, floater, ids);
- // Only warn for regular IMs - not group IMs
- if( dialog == IM_NOTHING_SPECIAL )
- {
- noteMutedUsers(floater, ids);
- }
+ // Only warn for regular IMs - not group IMs
+ if( dialog == IM_NOTHING_SPECIAL )
+ {
+ noteMutedUsers(session_id, floater, ids);
}
- floater->setInputFocus(TRUE);
- LLIMFloater::show(session_id);
return session_id;
}
-// This removes the panel referenced by the uuid, and then restores
-// internal consistency. The internal pointer is not deleted? Did you mean
-// a pointer to the corresponding LLIMSession? Session data is cleared now.
-// Put a copy of UUID to avoid problem when passed reference becames invalid
-// if it has been come from the object removed in observer.
-void LLIMMgr::removeSession(LLUUID session_id)
+bool LLIMMgr::leaveSession(const LLUUID& session_id)
{
- if (mBeingRemovedSessionID == session_id)
- {
- return;
- }
+ 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;
+}
+
+// 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()->removeFloater(floater);
- //mTabContainer->removeTabPanel(floater);
-
- clearPendingInvitation(session_id);
- clearPendingAgentListUpdates(session_id);
}
- // for some purposes storing ID of a sessios that is being removed
- mBeingRemovedSessionID = session_id;
- notifyObserverSessionRemoved(session_id);
+ clearPendingInvitation(session_id);
+ clearPendingAgentListUpdates(session_id);
- //if we don't clear session data on removing the session
- //we can't use LLBottomTray as observer of session creation/delettion and
- //creating chiclets only on session created even, we need to handle chiclets creation
- //the same way as LLFloaterIMPanels were managed.
LLIMModel::getInstance()->clearSession(session_id);
- // now this session is completely removed
- mBeingRemovedSessionID.setNull();
+ notifyObserverSessionRemoved(session_id);
}
void LLIMMgr::inviteToSession(
@@ -1670,10 +1791,6 @@ void LLIMMgr::onInviteNameLookup(LLSD payload, const LLUUID& id, const std::stri
}
}
-void LLIMMgr::refresh()
-{
-}
-
void LLIMMgr::disconnectAllSessions()
{
LLFloaterIMPanel* floater = NULL;
@@ -1720,7 +1837,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)
@@ -1827,6 +1944,15 @@ void LLIMMgr::notifyObserverSessionRemoved(const LLUUID& 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);
@@ -1837,6 +1963,24 @@ void LLIMMgr::removeSessionObserver(LLIMSessionObserver *observer)
mSessionObservers.remove(observer);
}
+bool LLIMMgr::startCall(const LLUUID& session_id)
+{
+ LLVoiceChannel* voice_channel = LLIMModel::getInstance()->getVoiceChannel(session_id);
+ if (!voice_channel) return false;
+
+ 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;
+}
+
// 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
@@ -1868,18 +2012,25 @@ LLFloaterIMPanel* LLIMMgr::createFloater(
}
void LLIMMgr::noteOfflineUsers(
+ const LLUUID& session_id,
LLFloaterIMPanel* floater,
const LLDynamicArray<LLUUID>& ids)
{
S32 count = ids.count();
if(count == 0)
{
- floater->addHistoryLine(LLTrans::getString("only_user_message"), LLUIColorTable::instance().getColor("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));
@@ -1890,13 +2041,13 @@ void LLIMMgr::noteOfflineUsers(
LLUIString offline = LLTrans::getString("offline_message");
offline.setArg("[FIRST]", first);
offline.setArg("[LAST]", last);
- floater->addHistoryLine(offline, LLUIColorTable::instance().getColor("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.
@@ -1909,12 +2060,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 = 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;
}
}
@@ -1939,16 +2096,11 @@ 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);
}
}
@@ -1980,11 +2132,8 @@ public:
if ( success )
{
session_id = body["session_id"].asUUID();
- gIMMgr->updateFloaterSessionID(
- temp_session_id,
- session_id);
- LLIMModel::getInstance()->updateSessionID(temp_session_id, session_id);
+ LLIMModel::getInstance()->processSessionInitializedReply(temp_session_id, session_id);
LLIMSpeakerMgr* speaker_mgr = LLIMModel::getInstance()->getSpeakerManager(session_id);
if (speaker_mgr)
@@ -2002,19 +2151,21 @@ public:
}
}
+ 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);
@@ -2047,15 +2198,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);
}
}
};
@@ -2073,13 +2219,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);
}
};
@@ -2117,11 +2257,17 @@ 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"]);
+ }
}
};
diff --git a/indra/newview/llimview.h b/indra/newview/llimview.h
index 9a94d01bb2..f986d9dcdb 100644
--- a/indra/newview/llimview.h
+++ b/indra/newview/llimview.h
@@ -34,12 +34,13 @@
#define LL_LLIMVIEW_H
#include "lldarray.h"
-#include "llfloateractivespeakers.h" //for LLIMSpeakerMgr
+#include "llspeakers.h" //for LLIMSpeakerMgr
#include "llimpanel.h" //for voice channels
#include "llmodaldialog.h"
#include "llinstantmessage.h"
#include "lluuid.h"
#include "llmultifloater.h"
+#include "lllogchat.h"
class LLFloaterChatterBox;
class LLUUID;
@@ -53,27 +54,51 @@ public:
struct LLIMSession
{
LLIMSession(const LLUUID& session_id, const std::string& name,
- const EInstantMessage& type, const LLUUID& other_participant_id);
+ const EInstantMessage& type, const LLUUID& other_participant_id, const std::vector<LLUUID>& ids);
virtual ~LLIMSession();
+ void sessionInitReplyReceived(const LLUUID& new_session_id);
+ void addMessage(const std::string& from, const LLUUID& from_id, const std::string& utf8_text, const std::string& time);
+ static void chatFromLogFile(LLLogChat::ELogLineType type, const LLSD& msg, void* userdata);
+
LLUUID mSessionID;
std::string mName;
EInstantMessage mType;
LLUUID mOtherParticipantID;
+ std::vector<LLUUID> mInitialTargetIDs;
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;
};
LLIMModel();
- //*TODO make it non-static as LLIMMOdel is a singleton (IB)
- static std::map<LLUUID, LLIMSession*> sSessionsMap; //mapping session_id to session
- boost::signals2::signal<void(const LLSD&)> mChangedSignal;
+ //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
@@ -84,17 +109,45 @@ public:
/**
* Rebind session data to a new session id.
*/
- void updateSessionID(const LLUUID& old_session_id, const LLUUID& 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
+ */
+ bool newSession(const LLUUID& session_id, const std::string& name, const EInstantMessage& type, const LLUUID& other_participant_id,
+ const std::vector<LLUUID>& ids = std::vector<LLUUID>());
+
+ /**
+ * 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);
- boost::signals2::connection addChangedCallback( boost::function<void (const LLSD& data)> cb );
+ /**
+ * Add a system message to an IM Model
+ */
+ bool proccessOnlineOfflineNotification(const LLUUID& session_id, const std::string& utf8_text);
- bool newSession(LLUUID session_id, std::string name, EInstantMessage type, LLUUID other_participant_id);
- bool clearSession(LLUUID session_id);
- std::list<LLSD> getMessages(LLUUID session_id, int start_index = 0);
- bool addMessage(LLUUID session_id, std::string from, LLUUID other_participant_id, std::string utf8_text);
- bool addToHistory(LLUUID session_id, std::string from, std::string utf8_text);
- //used to get the name of the session, for use as the title
- //currently just the other avatar name
+ /**
+ * 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;
/**
@@ -129,7 +182,7 @@ public:
*/
LLIMSpeakerMgr* getSpeakerManager(const LLUUID& session_id) const;
- static void sendLeaveSession(LLUUID session_id, LLUUID other_participant_id);
+ 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);
@@ -137,6 +190,18 @@ public:
const LLUUID& other_participant_id, EInstantMessage dialog);
void testMessages();
+
+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
@@ -145,6 +210,7 @@ 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;
};
@@ -161,7 +227,7 @@ public:
};
LLIMMgr();
- virtual ~LLIMMgr();
+ virtual ~LLIMMgr() {};
// Add a message to a session. The session can keyed to sesion id
// or agent id.
@@ -178,11 +244,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
@@ -208,10 +269,12 @@ public:
const std::string& voice_session_handle,
const std::string& caller_uri = LLStringUtil::null);
- // This removes the panel referenced by the uuid, and then
- // restores internal consistency. The internal pointer is not
- // deleted.
- void removeSession(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,
@@ -223,18 +286,9 @@ 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();
@@ -250,10 +304,6 @@ public:
// good connection.
void disconnectAllSessions();
- // 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
@@ -272,12 +322,37 @@ 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);
+
+ /**
+ * End call in a session
+ * @return false if voice channel doesn't exist
+ **/
+ bool endCall(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
@@ -293,8 +368,8 @@ private:
// 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);
@@ -302,10 +377,12 @@ private:
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;
@@ -315,9 +392,6 @@ private:
LLSD mPendingInvitations;
LLSD mPendingAgentListUpdates;
- // ID of a session that is being removed: observers are already told
- // that this session is being removed, but it is still present in the sessions' map
- LLUUID mBeingRemovedSessionID;
};
class LLIncomingCallDialog : public LLModalDialog
diff --git a/indra/newview/llinspect.cpp b/indra/newview/llinspect.cpp
new file mode 100644
index 0000000000..aa299014ee
--- /dev/null
+++ b/indra/newview/llinspect.cpp
@@ -0,0 +1,97 @@
+/**
+ * @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);
+ if (mOpenTimer.getStarted())
+ {
+ F32 alpha = clamp_rescale(mOpenTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 0.f, 1.f);
+ LLViewDrawContext context(alpha);
+ LLFloater::draw();
+ if (alpha == 1.f)
+ {
+ mOpenTimer.stop();
+ }
+
+ }
+ 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();
+}
diff --git a/indra/newview/llinspect.h b/indra/newview/llinspect.h
new file mode 100644
index 0000000000..a461c2fa16
--- /dev/null
+++ b/indra/newview/llinspect.h
@@ -0,0 +1,61 @@
+/**
+ * @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();
+
+ /// Start open animation
+ /*virtual*/ void onOpen(const LLSD& avatar_id);
+
+ /// Inspectors close themselves when they lose focus
+ /*virtual*/ void onFocusLost();
+
+private:
+ LLFrameTimer mCloseTimer;
+ LLFrameTimer mOpenTimer;
+};
+
+#endif
+
diff --git a/indra/newview/llinspectavatar.cpp b/indra/newview/llinspectavatar.cpp
index 261d0836a0..9989a3b473 100644
--- a/indra/newview/llinspectavatar.cpp
+++ b/indra/newview/llinspectavatar.cpp
@@ -39,22 +39,24 @@
#include "llavataractions.h"
#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
-#include "lldateutil.h" // ageFromDate()
#include "llfloaterreporter.h"
#include "llfloaterworldmap.h"
+#include "llinspect.h"
#include "llmutelist.h"
#include "llpanelblockedlist.h"
+#include "llstartup.h"
#include "llviewermenu.h"
#include "llvoiceclient.h"
// Linden libraries
-#include "llcontrol.h" // LLCachedControl
#include "llfloater.h"
#include "llfloaterreg.h"
#include "llmenubutton.h"
#include "lltooltip.h" // positionViewNearMouse()
#include "lluictrl.h"
+#include "llavatariconctrl.h"
+
class LLFetchAvatarData;
@@ -65,7 +67,7 @@ class LLFetchAvatarData;
// 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 LLFloater
+class LLInspectAvatar : public LLInspect
{
friend class LLFloaterReg;
@@ -76,7 +78,6 @@ public:
virtual ~LLInspectAvatar();
/*virtual*/ BOOL postBuild(void);
- /*virtual*/ void draw();
// Because floater is single instance, need to re-parse data on each spawn
// (for example, inspector about same avatar but in different position)
@@ -85,9 +86,6 @@ public:
// When closing they should close their gear menu
/*virtual*/ void onClose(bool app_quitting);
- // Inspectors close themselves when they lose focus
- /*virtual*/ void onFocusLost();
-
// Update view based on information from avatar properties processor
void processAvatarData(LLAvatarData* data);
@@ -109,10 +107,12 @@ private:
void onClickPay();
void onClickBlock();
void onClickReport();
+ void onClickFreeze();
+ void onClickEject();
void onClickZoomIn();
void onClickFindOnMap();
bool onVisibleFindOnMap();
- bool onVisibleGodMode();
+ bool onVisibleFreezeEject();
void onClickMuteVolume();
void onVolumeChange(const LLSD& data);
@@ -131,8 +131,6 @@ private:
// an in-flight request for avatar properties from LLAvatarPropertiesProcessor
// is represented by this object
LLFetchAvatarData* mPropertiesRequest;
- LLFrameTimer mCloseTimer;
- LLFrameTimer mOpenTimer;
};
//////////////////////////////////////////////////////////////////////////////
@@ -182,26 +180,30 @@ public:
};
LLInspectAvatar::LLInspectAvatar(const LLSD& sd)
-: LLFloater( LLSD() ), // single_instance, doesn't really need key
+: LLInspect( LLSD() ), // single_instance, doesn't really need key
mAvatarID(), // set in onOpen()
mPartnerID(),
mAvatarName(),
- mPropertiesRequest(NULL),
- mCloseTimer()
+ 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.IM",
+ boost::bind(&LLInspectAvatar::onClickIM, 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.Block", boost::bind(&LLInspectAvatar::onClickBlock, 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));
mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFindOnMap", boost::bind(&LLInspectAvatar::onVisibleFindOnMap, this));
- mVisibleCallbackRegistrar.add("InspectAvatar.VisibleGodMode", boost::bind(&LLInspectAvatar::onVisibleGodMode, this));
-
+ mVisibleCallbackRegistrar.add("InspectAvatar.VisibleFreezeEject",
+ boost::bind(&LLInspectAvatar::onVisibleFreezeEject, this));
// can't make the properties request until the widgets are constructed
// as it might return immediately, so do it in postBuild.
@@ -233,35 +235,7 @@ BOOL LLInspectAvatar::postBuild(void)
return TRUE;
}
-void LLInspectAvatar::draw()
-{
- static LLCachedControl<F32> FADE_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
- if (mOpenTimer.getStarted())
- {
- F32 alpha = clamp_rescale(mOpenTimer.getElapsedTimeF32(), 0.f, FADE_TIME, 0.f, 1.f);
- LLViewDrawContext context(alpha);
- LLFloater::draw();
- if (alpha == 1.f)
- {
- mOpenTimer.stop();
- }
- }
- 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();
- }
-}
// Multiple calls to showInstance("inspect_avatar", foo) will provide different
@@ -269,8 +243,8 @@ void LLInspectAvatar::draw()
//virtual
void LLInspectAvatar::onOpen(const LLSD& data)
{
- mCloseTimer.stop();
- mOpenTimer.start();
+ // Start open animation
+ LLInspect::onOpen(data);
// Extract appropriate avatar id
mAvatarID = data["avatar_id"];
@@ -305,26 +279,18 @@ void LLInspectAvatar::onClose(bool app_quitting)
getChild<LLMenuButton>("gear_btn")->hideMenu();
}
-//virtual
-void LLInspectAvatar::onFocusLost()
-{
- // Start closing when we lose focus
- mCloseTimer.start();
- mOpenTimer.stop();
-}
-
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())
{
- getChild<LLUICtrl>("user_subtitle")->
- setValue("Test subtitle");
- getChild<LLUICtrl>("user_details")->
- setValue("Test details");
- getChild<LLUICtrl>("user_partner")->
- setValue("Test partner");
+ 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;
}
@@ -341,13 +307,31 @@ void LLInspectAvatar::requestUpdate()
// 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);
- childSetEnabled("add_friend_btn", !is_friend && !is_self);
+ 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,
@@ -359,7 +343,7 @@ void LLInspectAvatar::processAvatarData(LLAvatarData* data)
{
LLStringUtil::format_map_t args;
args["[BORN_ON]"] = data->born_on;
- args["[AGE]"] = LLDateUtil::ageFromDate(data->born_on);
+ args["[AGE]"] = data->born_on;
args["[SL_PROFILE]"] = data->about_text;
args["[RW_PROFILE"] = data->fl_about_text;
args["[ACCTTYPE]"] = LLAvatarPropertiesProcessor::accountType(data);
@@ -476,13 +460,13 @@ void LLInspectAvatar::nameUpdatedCallback(
void LLInspectAvatar::onClickAddFriend()
{
LLAvatarActions::requestFriendshipDialog(mAvatarID, mAvatarName);
+ closeFloater();
}
void LLInspectAvatar::onClickViewProfile()
{
- // hide inspector when showing profile
- setFocus(FALSE);
LLAvatarActions::showProfile(mAvatarID);
+ closeFloater();
}
bool LLInspectAvatar::onVisibleFindOnMap()
@@ -490,29 +474,33 @@ bool LLInspectAvatar::onVisibleFindOnMap()
return gAgent.isGodlike() || is_agent_mappable(mAvatarID);
}
-bool LLInspectAvatar::onVisibleGodMode()
+bool LLInspectAvatar::onVisibleFreezeEject()
{
- return gAgent.isGodlike();
+ return enable_freeze_eject( LLSD(mAvatarID) );
}
void LLInspectAvatar::onClickIM()
{
LLAvatarActions::startIM(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::onClickBlock()
@@ -520,11 +508,25 @@ void LLInspectAvatar::onClickBlock()
LLMute mute(mAvatarID, mAvatarName, LLMute::AGENT);
LLMuteList::getInstance()->add(mute);
LLPanelBlockedList::showPanelAndSelect(mute.mID);
+ closeFloater();
}
void LLInspectAvatar::onClickReport()
{
LLFloaterReporter::showFromObject(mAvatarID);
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickFreeze()
+{
+ handle_avatar_freeze( LLSD(mAvatarID) );
+ closeFloater();
+}
+
+void LLInspectAvatar::onClickEject()
+{
+ handle_avatar_eject( LLSD(mAvatarID) );
+ closeFloater();
}
void LLInspectAvatar::onClickZoomIn()
diff --git a/indra/newview/llinspectgroup.cpp b/indra/newview/llinspectgroup.cpp
new file mode 100644
index 0000000000..c78bcd6afe
--- /dev/null
+++ b/indra/newview/llinspectgroup.cpp
@@ -0,0 +1,330 @@
+/**
+ * @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>("leave_btn")->setVisible(true);
+ 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
index cdb3a10dfc..e3780f93ff 100644
--- a/indra/newview/llinspectobject.cpp
+++ b/indra/newview/llinspectobject.cpp
@@ -34,17 +34,18 @@
#include "llinspectobject.h"
// Viewer
+#include "llinspect.h"
+#include "llmediaentry.h"
#include "llnotifications.h" // *TODO: Eliminate, add LLNotificationsUtil wrapper
#include "llselectmgr.h"
#include "llslurl.h"
#include "llviewermenu.h" // handle_object_touch(), handle_buy()
+#include "llviewermedia.h"
#include "llviewerobjectlist.h" // to select the requested object
// Linden libraries
#include "llbutton.h" // setLabel(), not virtual!
#include "llclickaction.h"
-#include "llcontrol.h" // LLCachedControl
-#include "llfloater.h"
#include "llfloaterreg.h"
#include "llmenubutton.h"
#include "llresmgr.h" // getMonetaryString
@@ -56,15 +57,13 @@
class LLViewerObject;
-// *TODO: Abstract out base class for LLInspectObject and LLInspectObject
-
//////////////////////////////////////////////////////////////////////////////
// LLInspectObject
//////////////////////////////////////////////////////////////////////////////
// Object Inspector, a small information window used when clicking
// in the ambient inspector widget for objects in the 3D world.
-class LLInspectObject : public LLFloater
+class LLInspectObject : public LLInspect
{
friend class LLFloaterReg;
@@ -75,7 +74,6 @@ public:
virtual ~LLInspectObject();
/*virtual*/ BOOL postBuild(void);
- /*virtual*/ void draw();
// Because floater is single instance, need to re-parse data on each spawn
// (for example, inspector about same avatar but in different position)
@@ -84,9 +82,6 @@ public:
// Release the selection and do other cleanup
/*virtual*/ void onClose(bool app_quitting);
- // Inspectors close themselves when they lose focus
- /*virtual*/ void onFocusLost();
-
private:
// Refresh displayed data with information from selection manager
void update();
@@ -99,8 +94,10 @@ private:
void updateName(LLSelectNode* nodep);
void updateDescription(LLSelectNode* nodep);
void updatePrice(LLSelectNode* nodep);
-
void updateCreator(LLSelectNode* nodep);
+
+ void updateMediaCurrentURL();
+ void updateSecureBrowsing();
void onClickBuy();
void onClickPay();
@@ -113,16 +110,19 @@ private:
private:
LLUUID mObjectID;
- LLFrameTimer mOpenTimer;
- LLFrameTimer mCloseTimer;
+ S32 mObjectFace;
+ viewer_media_t mMediaImpl;
+ LLMediaEntry* mMediaEntry;
LLSafeHandle<LLObjectSelection> mObjectSelection;
};
LLInspectObject::LLInspectObject(const LLSD& sd)
-: LLFloater( LLSD() ), // single_instance, doesn't really need key
- mObjectID(), // set in onOpen()
- mCloseTimer(),
- mOpenTimer()
+: 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.
@@ -149,7 +149,7 @@ BOOL LLInspectObject::postBuild(void)
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();
@@ -181,43 +181,22 @@ BOOL LLInspectObject::postBuild(void)
return TRUE;
}
-void LLInspectObject::draw()
-{
- static LLCachedControl<F32> FADE_OUT_TIME(*LLUI::sSettingGroups["config"], "InspectorFadeTime", 1.f);
- if (mOpenTimer.getStarted())
- {
- F32 alpha = clamp_rescale(mOpenTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 0.f, 1.f);
- LLViewDrawContext context(alpha);
- LLFloater::draw();
- }
- else if (mCloseTimer.getStarted())
- {
- F32 alpha = clamp_rescale(mCloseTimer.getElapsedTimeF32(), 0.f, FADE_OUT_TIME, 1.f, 0.f);
- LLViewDrawContext context(alpha);
- LLFloater::draw();
- if (mCloseTimer.getElapsedTimeF32() > FADE_OUT_TIME)
- {
- closeFloater(false);
- }
- }
- else
- {
- LLFloater::draw();
- }
-}
-
// 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)
{
- mCloseTimer.stop();
- mOpenTimer.start();
+ // 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
@@ -248,6 +227,17 @@ void LLInspectObject::onOpen(const LLSD& data)
}
} 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());
}
}
@@ -260,14 +250,6 @@ void LLInspectObject::onClose(bool app_quitting)
getChild<LLMenuButton>("gear_btn")->hideMenu();
}
-//virtual
-void LLInspectObject::onFocusLost()
-{
- // Start closing when we lose focus
- mCloseTimer.start();
- mOpenTimer.stop();
-}
-
void LLInspectObject::update()
{
@@ -286,6 +268,30 @@ void LLInspectObject::update()
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()
@@ -424,6 +430,45 @@ void LLInspectObject::updateDescription(LLSelectNode* nodep)
}
}
+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
@@ -496,6 +541,40 @@ void LLInspectObject::updatePrice(LLSelectNode* nodep)
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);
+}
+
+
void LLInspectObject::onClickBuy()
{
handle_buy();
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 d4a9324208..b9a25d5dc7 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.
@@ -62,7 +62,9 @@
#include "llavataractions.h"
#include "llgesturemgr.h"
#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llinventoryclipboard.h"
#include "lllineeditor.h"
#include "llmenugl.h"
@@ -76,6 +78,7 @@
#include "llscrollcontainer.h"
#include "llimview.h"
#include "lltooldraganddrop.h"
+#include "llviewerfoldertype.h"
#include "llviewertexturelist.h"
#include "llviewerinventory.h"
#include "llviewerobjectlist.h"
@@ -83,7 +86,8 @@
#include "llvoavatar.h"
#include "llwearable.h"
#include "llwearablelist.h"
-#include "llviewermessage.h"
+#include "llviewerassettype.h"
+#include "llviewermessage.h"
#include "llviewerregion.h"
#include "llvoavatarself.h"
#include "lltabcontainer.h"
@@ -147,8 +151,8 @@ std::string ICON_NAME[ICON_NAME_COUNT] =
"Inv_Undershirt",
"Inv_Underpants",
"Inv_Skirt",
- "inv_item_alpha.tga",
- "inv_item_tattoo.tga",
+ "Inv_Alpha",
+ "Inv_Tattoo",
"Inv_Animation",
"Inv_Gesture",
@@ -200,9 +204,9 @@ PermissionMask LLInvFVBridge::getPermissionMask() const
}
// virtual
-LLAssetType::EType LLInvFVBridge::getPreferredType() const
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
{
- return LLAssetType::AT_NONE;
+ return LLFolderType::FT_NONE;
}
@@ -237,16 +241,15 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
{
return;
}
-
- LLInventoryModel::item_array_t item_array;
- model->collectLinkedItems(item_id, item_array);
+
+ LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
iter != item_array.end();
iter++)
{
LLViewerInventoryItem *linked_item = (*iter);
if (linked_item->getUUID() == item_id) continue;
-
+
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
new_item->rename(new_name);
new_item->updateServer(FALSE);
@@ -257,15 +260,30 @@ void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string&
}
// 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()
{
- LLFloaterReg::showInstance("properties", mUUID);
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // LLFloaterReg::showInstance("properties", mUUID);
}
void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
@@ -280,7 +298,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());
@@ -293,7 +311,7 @@ void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batc
}
}
for(i = 0; i < count; ++i)
- {
+ {
bridge = (LLInvFVBridge*)(batch.get(i));
if(!bridge || !bridge->isItemRemovable()) continue;
cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
@@ -323,7 +341,7 @@ void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*
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;
@@ -487,11 +505,16 @@ BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
return FALSE;
}
}
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return FALSE;
+ }
}
return TRUE;
}
-void hideContextEntries(LLMenuGL& menu,
+void hide_context_entries(LLMenuGL& menu,
const std::vector<std::string> &entries_to_show,
const std::vector<std::string> &disabled_entries)
{
@@ -506,10 +529,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)
@@ -537,8 +560,8 @@ void hideContextEntries(LLMenuGL& menu,
}
// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
- std::vector<std::string> &items,
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
std::vector<std::string> &disabled_items, U32 flags)
{
items.push_back(std::string("Rename"));
@@ -550,7 +573,7 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
if (show_asset_id)
{
items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
|| (flags & FIRST_SELECTED_ITEM) == 0)
{
disabled_items.push_back(std::string("Copy Asset UUID"));
@@ -583,6 +606,12 @@ void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
{
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)
@@ -606,7 +635,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
@@ -618,12 +647,12 @@ BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
if(obj)
{
- *type = LLAssetType::lookupDragAndDropType(obj->getActualType());
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
if(*type == DAD_NONE)
{
return FALSE;
}
-
+
*id = obj->getUUID();
//object_ids.put(obj->getUUID());
@@ -659,7 +688,7 @@ BOOL LLInvFVBridge::isInTrash() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return model->isObjectDescendentOf(mUUID, trash_id);
}
@@ -672,7 +701,7 @@ BOOL LLInvFVBridge::isLinkedObjectInTrash() const
{
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
}
return FALSE;
@@ -690,7 +719,7 @@ BOOL LLInvFVBridge::isCOFFolder() const
{
const LLInventoryModel* model = getInventoryModel();
if(!model) return TRUE;
- const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
{
return TRUE;
@@ -793,7 +822,7 @@ LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
}
new_listener = new LLLandmarkBridge(inventory, uuid, flags);
break;
-
+
case LLAssetType::AT_CALLINGCARD:
if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
{
@@ -907,6 +936,24 @@ void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
}
// +=================================================+
+// | 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 |
// +=================================================+
@@ -999,7 +1046,7 @@ void LLItemBridge::restoreItem()
if(item)
{
LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(item->getType());
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
// do not restamp on restore.
LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
}
@@ -1032,7 +1079,7 @@ void LLItemBridge::restoreToWorld()
}
// Check if it's in the trash. (again similar to the normal rez logic)
- const LLUUID 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;
@@ -1067,7 +1114,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());
@@ -1093,9 +1140,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
{
@@ -1104,9 +1151,9 @@ void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
}
LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{
+{
U8 font = LLFontGL::NORMAL;
-
+
if( gAgentWearables.isWearingItem( mUUID ) )
{
// llinfos << "BOLD" << llendl;
@@ -1132,7 +1179,7 @@ std::string LLItemBridge::getLabelSuffix() const
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()
@@ -1208,7 +1255,6 @@ BOOL LLItemBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
- model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
}
@@ -1228,7 +1274,7 @@ BOOL LLItemBridge::removeItem()
LLPreview::hide(mUUID, TRUE);
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
@@ -1258,13 +1304,13 @@ BOOL LLItemBridge::isItemCopyable() const
return FALSE;
}
- if( avatarp->isWearingAttachment( mUUID, TRUE ) )
+ if(avatarp->isWearingAttachment(mUUID))
{
return FALSE;
}
-
+
// All items can be copied, not all can be pasted.
- // The only time an item can't be copied is if it's a link
+ // The only time an item can't be copied is if it's a link
// return (item->getPermissions().allowCopyBy(gAgent.getID()));
if (item->getIsLinkType())
{
@@ -1316,12 +1362,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::lookupIsProtectedCategoryType(((LLInventoryCategory*)obj)->getPreferredType()));
+ return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
}
return FALSE;
}
@@ -1335,7 +1381,7 @@ void LLFolderBridge::selectItem()
BOOL LLFolderBridge::isItemRemovable()
{
LLInventoryModel* model = getInventoryModel();
- if(!model)
+ if(!model)
{
return FALSE;
}
@@ -1357,7 +1403,7 @@ BOOL LLFolderBridge::isItemRemovable()
return FALSE;
}
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
return FALSE;
}
@@ -1370,7 +1416,7 @@ BOOL LLFolderBridge::isItemRemovable()
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(category->getPreferredType()))
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
{
return FALSE;
}
@@ -1382,7 +1428,7 @@ BOOL LLFolderBridge::isItemRemovable()
if( (item->getType() == LLAssetType::AT_CLOTHING) ||
(item->getType() == LLAssetType::AT_BODYPART) )
{
- if( gAgentWearables.isWearingItem( item->getUUID(), TRUE ) )
+ if(gAgentWearables.isWearingItem(item->getUUID()))
{
return FALSE;
}
@@ -1390,7 +1436,7 @@ BOOL LLFolderBridge::isItemRemovable()
else
if( item->getType() == LLAssetType::AT_OBJECT )
{
- if( avatar->isWearingAttachment( item->getUUID(), TRUE ) )
+ if(avatar->isWearingAttachment(item->getUUID()))
{
return FALSE;
}
@@ -1428,6 +1474,39 @@ BOOL LLFolderBridge::copyToClipboard() const
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 )
+ {
+ return FALSE;
+ }
+
+ 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)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+
+ }
+ return TRUE;
+}
+
BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
// Check normal paste-as-link permissions
@@ -1435,7 +1514,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
{
return FALSE;
}
-
+
const LLInventoryModel* model = getInventoryModel();
if (!model)
{
@@ -1445,23 +1524,36 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
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 LLInventoryCategory *cat = model->getCategory(objects.get(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) ||
+ 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;
@@ -1471,7 +1563,7 @@ BOOL LLFolderBridge::isClipboardPasteableAsLink() const
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;
@@ -1501,18 +1593,24 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
const LLUUID& cat_id = inv_cat->getUUID();
// Is the destination the trash?
- const 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);
- BOOL is_movable = (!LLAssetType::lookupIsProtectedCategoryType(inv_cat->getPreferredType()));
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ 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()==LLAssetType::AT_OUTFIT);
+ 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 );
@@ -1520,14 +1618,14 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
for( i = 0; i < descendent_categories.count(); i++ )
{
LLInventoryCategory* category = descendent_categories[i];
- if(LLAssetType::lookupIsProtectedCategoryType(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 )
@@ -1558,7 +1656,7 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
-
+
accept = is_movable
&& (mUUID != cat_id) // Can't move a folder into itself
&& (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
@@ -1579,8 +1677,9 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
}
}
// if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
+ if (move_is_into_current_outfit || move_is_into_outfit)
{
+#if SUPPORT_ENSEMBLES
// BAP - should skip if dup.
if (move_is_into_current_outfit)
{
@@ -1597,10 +1696,11 @@ BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
LLAssetType::AT_LINK_FOLDER,
cb);
}
+#endif
}
else
{
-
+
// Reparent the folder and restamp children if it's moving
// into trash.
LLInvFVBridge::changeCategoryParent(
@@ -1637,7 +1737,7 @@ void warn_move_inventory(LLViewerObject* object, LLMoveInv* 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*),
@@ -1664,7 +1764,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;
@@ -1750,9 +1850,9 @@ bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
{
LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
// BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
- ((linked_category->getPreferredType() == LLAssetType::AT_NONE) ||
- (LLAssetType::lookupIsEnsembleCategoryType(linked_category->getPreferredType()))));
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
+ (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
}
}
@@ -1792,7 +1892,7 @@ public:
gInventory.removeObserver(this);
delete this;
}
-
+
protected:
LLUUID mCatID;
@@ -1887,7 +1987,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
@@ -1909,7 +2009,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
{
if((mask & (LLInventoryObserver::ADD)) != 0)
{
- if (!mFolderAdded)
+ if (!mFolderAdded)
{
const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
@@ -1917,7 +2017,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;
@@ -1925,7 +2025,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
}
}
- if (mFolderAdded)
+ if (mFolderAdded)
{
LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
@@ -1943,7 +2043,7 @@ void LLInventoryCopyAndWearObserver::changed(U32 mask)
LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
delete this;
}
- }
+ }
}
}
@@ -1978,6 +2078,7 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
modifyOutfit(FALSE);
return;
}
+#if SUPPORT_ENSEMBLES
else if ("wearasensemble" == action)
{
LLInventoryModel* model = getInventoryModel();
@@ -1987,6 +2088,7 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
LLAppearanceManager::wearEnsemble(cat,true);
return;
}
+#endif
else if ("addtooutfit" == action)
{
modifyOutfit(TRUE);
@@ -2003,12 +2105,12 @@ void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
+
remove_inventory_category_from_avatar ( cat );
return;
- }
+ }
else if ("purge" == action)
- {
+ {
purgeItem(model, mUUID);
return;
}
@@ -2052,7 +2154,7 @@ void LLFolderBridge::determineFolderType()
BOOL LLFolderBridge::isItemRenameable() const
{
LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && !LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())
+ if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
&& (cat->getOwnerID() == gAgent.getID()))
{
return TRUE;
@@ -2067,15 +2169,15 @@ void LLFolderBridge::restoreItem()
if(cat)
{
LLInventoryModel* model = getInventoryModel();
- LLUUID new_parent = model->findCategoryUUIDForType(cat->getType());
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
// do not restamp children on restore
LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
}
}
-LLAssetType::EType LLFolderBridge::getPreferredType() const
+LLFolderType::EType LLFolderBridge::getPreferredType() const
{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
@@ -2088,7 +2190,7 @@ LLAssetType::EType LLFolderBridge::getPreferredType() const
// Icons for folders are based on the preferred type
LLUIImagePtr LLFolderBridge::getIcon() const
{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
LLViewerInventoryCategory* cat = getCategory();
if(cat)
{
@@ -2097,7 +2199,7 @@ LLUIImagePtr LLFolderBridge::getIcon() const
return getIcon(preferred_type);
}
-LLUIImagePtr LLFolderBridge::getIcon(LLAssetType::EType preferred_type)
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
{
// we only have one folder image now
return LLUI::getUIImage("Inv_FolderClosed");
@@ -2117,7 +2219,6 @@ BOOL LLFolderBridge::renameItem(const std::string& new_name)
new_cat->rename(new_name);
new_cat->updateServer(FALSE);
model->updateCategory(new_cat);
- model->updateLinkedObjects(cat->getUUID());
model->notifyObservers();
}
@@ -2137,7 +2238,7 @@ BOOL LLFolderBridge::removeItem()
LLInventoryModel* model = getInventoryModel();
if(!model) return FALSE;
- LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
// Look for any gestures and deactivate them
LLInventoryModel::cat_array_t descendent_categories;
@@ -2175,19 +2276,28 @@ void LLFolderBridge::pasteFromClipboard()
LLDynamicArray<LLUUID> objects;
LLInventoryClipboard::instance().retrieve(objects);
S32 count = objects.count();
- LLUUID parent_id(mUUID);
+ const LLUUID parent_id(mUUID);
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));
+ 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));
+ }
}
}
}
@@ -2205,6 +2315,7 @@ void LLFolderBridge::pasteLinkFromClipboard()
for(S32 i = 0; i < count; i++)
{
const LLUUID &object_id = objects.get(i);
+#if SUPPORT_ENSEMBLES
if (LLInventoryCategory *cat = model->getCategory(object_id))
{
link_inventory_item(
@@ -2215,7 +2326,9 @@ void LLFolderBridge::pasteLinkFromClipboard()
LLAssetType::AT_LINK_FOLDER,
LLPointer<LLInventoryCallback>(NULL));
}
- else if (LLInventoryItem *item = model->getItem(object_id))
+ else
+#endif
+ if (LLInventoryItem *item = model->getItem(object_id))
{
link_inventory_item(
gAgent.getID(),
@@ -2243,12 +2356,12 @@ void LLFolderBridge::folderOptionsMenu()
if(!model) return;
const LLInventoryCategory* category = model->getCategory(mUUID);
- LLAssetType::EType type = category->getPreferredType();
- const bool is_default_folder = category && LLAssetType::lookupIsProtectedCategoryType(type);
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type);
// BAP change once we're no longer treating regular categories as ensembles.
- const bool is_ensemble = category && (type == LLAssetType::AT_NONE ||
- LLAssetType::lookupIsEnsembleCategoryType(type));
-
+ 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.
@@ -2262,7 +2375,7 @@ void LLFolderBridge::folderOptionsMenu()
mItems.push_back(std::string("IM All Contacts In Folder"));
}
}
-
+
// wearables related functionality for folders.
//is_wearable
LLFindWearables is_wearable;
@@ -2288,7 +2401,7 @@ void LLFolderBridge::folderOptionsMenu()
}
mItems.push_back(std::string("Take Off Items"));
}
- hideContextEntries(*mMenu, mItems, disabled_items);
+ hide_context_entries(*mMenu, mItems, disabled_items);
}
BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
@@ -2313,9 +2426,11 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// std::vector<std::string> disabled_items;
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);
+ mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
+ mDisabledItems.clear(); //adding code to clear out disabled members from previous
if (lost_and_found_id == mUUID)
{
// This is the lost+found folder.
@@ -2342,7 +2457,6 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
else if(isAgentInventory()) // do not allow creating in library
{
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 /*&&
@@ -2357,19 +2471,19 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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 && LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType()))
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
{
mDisabledItems.push_back(std::string("Change Type"));
}
-
+
getClipboardEntries(false, mItems, mDisabledItems, flags);
}
else
{
// Want some but not all of the items from getClipboardEntries for outfits.
- if (cat && cat->getPreferredType()==LLAssetType::AT_OUTFIT)
+ if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
{
mItems.push_back(std::string("Rename"));
mItems.push_back(std::string("Delete"));
@@ -2378,24 +2492,24 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
//Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
mCallingCards = mWearables = FALSE;
-
+
LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
if (checkFolderForContentsOfType(model, is_callingcard))
{
mCallingCards=TRUE;
}
-
+
LLFindWearables is_wearable;
LLIsType is_object( LLAssetType::AT_OBJECT );
LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
+
if (checkFolderForContentsOfType(model, is_wearable) ||
checkFolderForContentsOfType(model, is_object) ||
checkFolderForContentsOfType(model, is_gesture) )
{
mWearables=TRUE;
}
-
+
mMenu = &menu;
sSelf = this;
LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
@@ -2425,7 +2539,7 @@ 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);
+ hide_context_entries(menu, mItems, mDisabledItems);
}
BOOL LLFolderBridge::hasChildren() const
@@ -2505,7 +2619,7 @@ void LLFolderBridge::createNewCategory(void* user_data)
if(!model) return;
LLUUID id;
id = model->createNewCategory(bridge->getUUID(),
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
LLStringUtil::null);
model->notifyObservers();
@@ -2590,7 +2704,7 @@ 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 = LLWearableList::instance().createNewWearable(type);
LLAssetType::EType asset_type = wearable->getAssetType();
@@ -2608,7 +2722,7 @@ void LLFolderBridge::modifyOutfit(BOOL append)
if(!model) return;
LLViewerInventoryCategory* cat = getCategory();
if(!cat) return;
-
+
// BAP - was:
// wear_inventory_category_on_avatar( cat, append );
LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
@@ -2634,8 +2748,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);
@@ -2654,6 +2768,56 @@ bool move_task_inventory_callback(const LLSD& notification, const LLSD& response
return false;
}
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator 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 updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
BOOL drop)
{
@@ -2683,36 +2847,50 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
break;
case LLAssetType::AT_CATEGORY:
- is_movable = !LLAssetType::lookupIsProtectedCategoryType(((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);
- LLUUID current_outfit_id = model->findCategoryUUIDForType(LLAssetType::AT_CURRENT_OUTFIT);
+ 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()==LLAssetType::AT_OUTFIT);
-
+ 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 = !gAgentWearables.isWearingItem(inv_item->getUUID(), TRUE);
+ is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
break;
case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID(), TRUE);
+ is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
break;
default:
break;
}
}
-
- accept = is_movable && (mUUID != inv_item->getParentUUID());
+
+ 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());
+ }
+
+ const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
if(accept && drop)
{
if (inv_item->getType() == LLAssetType::AT_GESTURE
@@ -2734,8 +2912,28 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
}
}
- LLUUID favorites_id = model->findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
- if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ 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();
+
+ // update order
+ updateItemsOrder(items, srcItemId, destItemId);
+
+ saveItemsOrder(items);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
{
copy_inventory_item(
gAgent.getID(),
@@ -2794,7 +2992,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
&& perm.allowTransferTo(gAgent.getID())))
// || gAgent.isGodlike())
-
+
{
accept = TRUE;
}
@@ -2825,7 +3023,7 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
LLNotifications::instance().forceResponse(params, 0);
}
}
-
+
}
else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
{
@@ -2878,11 +3076,11 @@ 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());
@@ -2901,7 +3099,7 @@ LLUIImagePtr LLSoundBridge::getIcon() const
void LLSoundBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -2962,7 +3160,7 @@ 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);
}
// +=================================================+
@@ -2970,7 +3168,7 @@ void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// +=================================================+
LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid)
+LLItemBridge(inventory, uuid)
{
mVisited = FALSE;
if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
@@ -3009,17 +3207,17 @@ 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"));
// 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("Teleport To Landmark"));
+ disabled_items.push_back(std::string("About Landmark"));
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// Convenience function for the two functions below.
@@ -3059,7 +3257,7 @@ void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
LLSideTray::getInstance()->showPanel("panel_places", key);
}
}
- else
+ else
{
LLItemBridge::performAction(folder, model, action);
}
@@ -3083,7 +3281,7 @@ static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFro
void LLLandmarkBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3191,7 +3389,7 @@ std::string LLCallingCardBridge::getLabelSuffix() const
void LLCallingCardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3248,7 +3446,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,
@@ -3330,7 +3528,7 @@ BOOL LLCallingCardBridge::removeItem()
LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
return FALSE;
}
- else
+ else
{
return LLItemBridge::removeItem();
}
@@ -3347,7 +3545,7 @@ LLUIImagePtr LLNotecardBridge::getIcon() const
void LLNotecardBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3429,7 +3627,7 @@ void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* mode
void LLGestureBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3477,7 +3675,7 @@ void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Activate"));
items.push_back(std::string("Deactivate"));
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
// +=================================================+
@@ -3517,7 +3715,7 @@ 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);
}
@@ -3531,7 +3729,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
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)
{
@@ -3548,7 +3746,7 @@ void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* mo
void LLAnimationBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3581,7 +3779,7 @@ BOOL LLObjectBridge::isItemRemovable()
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if(!avatar) return FALSE;
- if(avatar->isWearingAttachment(mUUID, TRUE)) return FALSE;
+ if(avatar->isWearingAttachment(mUUID)) return FALSE;
return LLInvFVBridge::isItemRemovable();
}
@@ -3630,14 +3828,13 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
else if ("detach" == 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 =
@@ -3657,19 +3854,23 @@ void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model
void LLObjectBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
}
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
/*
LLFloaterReg::showInstance("properties", mUUID);
*/
}
LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
+{
U8 font = LLFontGL::NORMAL;
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
@@ -3683,7 +3884,7 @@ LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
{
font |= LLFontGL::ITALIC;
}
-
+
return (LLFontGL::StyleFlags)font;
}
@@ -3694,7 +3895,10 @@ std::string LLObjectBridge::getLabelSuffix() const
{
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(")");
+
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
}
else
{
@@ -3723,11 +3927,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);
}
else
+#endif
{
LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
}
@@ -3735,11 +3941,21 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach
bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
{
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0/*YES*/)
{
LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
+
if (itemp)
{
LLMessageSystem* msg = gMessageSystem;
@@ -3750,7 +3966,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());
@@ -3796,7 +4016,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
{
return;
}
-
+
if( avatarp->isWearingAttachment( mUUID ) )
{
items.push_back(std::string("Detach From Yourself"));
@@ -3811,16 +4031,22 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
// commented out for DEV-32347
//items.push_back(std::string("Restore to Last Position"));
+ 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)
+ 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++;
@@ -3849,7 +4075,7 @@ void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
}
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
BOOL LLObjectBridge::renameItem(const std::string& new_name)
@@ -3868,7 +4094,6 @@ BOOL LLObjectBridge::renameItem(const std::string& new_name)
buildDisplayName(new_item, mDisplayName);
new_item->updateServer(FALSE);
model->updateItem(new_item);
- model->updateLinkedObjects(item->getUUID());
model->notifyObservers();
@@ -3902,7 +4127,7 @@ LLUIImagePtr LLLSLTextBridge::getIcon() const
void LLLSLTextBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -3938,7 +4163,7 @@ void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
{
lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
<< " )" << llendl;
-
+
LLWearableList::instance().getAsset(item->getAssetUUID(),
item->getName(),
item->getType(),
@@ -3952,8 +4177,8 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
if(!category) return;
lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
<< " )" << llendl;
-
-
+
+
if( gFloaterCustomize )
{
gFloaterCustomize->askToSaveIfDirty(
@@ -3968,10 +4193,8 @@ void remove_inventory_category_from_avatar( LLInventoryCategory* category )
struct OnRemoveStruct
{
LLUUID mUUID;
- LLFolderView *mFolderToDeleteSelected;
- OnRemoveStruct(const LLUUID& uuid, LLFolderView *fv = NULL):
- mUUID(uuid),
- mFolderToDeleteSelected(fv)
+ OnRemoveStruct(const LLUUID& uuid):
+ mUUID(uuid)
{
}
};
@@ -4030,8 +4253,8 @@ void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_
}
}
}
-
-
+
+
if (obj_count > 0)
{
for(i = 0; i < obj_count; ++i)
@@ -4083,7 +4306,7 @@ BOOL LLWearableBridge::renameItem(const std::string& new_name)
BOOL LLWearableBridge::isItemRemovable()
{
- if (gAgentWearables.isWearingItem(mUUID, TRUE)) return FALSE;
+ if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
return LLInvFVBridge::isItemRemovable();
}
@@ -4091,7 +4314,7 @@ std::string LLWearableBridge::getLabelSuffix() const
{
if( gAgentWearables.isWearingItem( mUUID ) )
{
- return LLItemBridge::getLabelSuffix() + " (worn)";
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
}
else
{
@@ -4126,25 +4349,12 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
{
LLViewerInventoryItem* item = getItem();
if (item)
- {
- if (item->getIsLinkType() &&
- model->isObjectDescendentOf(mUUID,LLAppearanceManager::getCOF()))
- {
- // Delete link after item has been taken off.
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID, folder));
- }
- else
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID));
- }
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID));
}
}
}
@@ -4154,7 +4364,7 @@ void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* mod
void LLWearableBridge::openItem()
{
LLViewerInventoryItem* item = getItem();
-
+
if (item)
{
LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
@@ -4238,7 +4448,7 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
getClipboardEntries(true, items, disabled_items, flags);
items.push_back(std::string("Wearable Separator"));
-
+
items.push_back(std::string("Wearable Wear"));
items.push_back(std::string("Wearable Add"));
items.push_back(std::string("Wearable Edit"));
@@ -4255,12 +4465,30 @@ void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
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"));
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ case LLAssetType::AT_BODYPART:
+ if (gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ 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
@@ -4290,7 +4518,7 @@ void LLWearableBridge::wearOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4321,7 +4549,7 @@ void LLWearableBridge::wearAddOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4409,7 +4637,7 @@ BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
return (gAgentWearables.isWearingItem(self->mUUID));
}
-// static
+// static
void LLWearableBridge::onEditOnAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4447,7 +4675,7 @@ BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
return FALSE;
}
-// static
+// static
void LLWearableBridge::onRemoveFromAvatar(void* user_data)
{
LLWearableBridge* self = (LLWearableBridge*)user_data;
@@ -4472,13 +4700,13 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
void* userdata)
{
OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
- LLUUID item_id = on_remove_struct->mUUID;
+ const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
if(wearable)
{
if( gAgentWearables.isWearingItem( 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 )) )
{
@@ -4488,10 +4716,20 @@ void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
}
}
}
- if (on_remove_struct->mFolderToDeleteSelected)
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::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)
{
- on_remove_struct->mFolderToDeleteSelected->removeSelectedItems();
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
}
+ gInventory.notifyObservers();
+
delete on_remove_struct;
}
@@ -4512,7 +4750,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
case LLAssetType::AT_LANDMARK:
action = new LLLandmarkBridgeAction(uuid,model);
break;
-
+
case LLAssetType::AT_CALLINGCARD:
action = new LLCallingCardBridgeAction(uuid,model);
break;
@@ -4549,7 +4787,7 @@ LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_
return action;
}
-//static
+//static
void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
const LLUUID& uuid,LLInventoryModel* model)
{
@@ -4561,7 +4799,7 @@ void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
}
}
-//static
+//static
void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
{
LLAssetType::EType asset_type = model->getItem(uuid)->getType();
@@ -4580,8 +4818,8 @@ LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
return NULL;
}
-//virtual
-void LLTextureBridgeAction::doIt()
+//virtual
+void LLTextureBridgeAction::doIt()
{
if (getItem())
{
@@ -4592,20 +4830,20 @@ void LLTextureBridgeAction::doIt()
}
//virtual
-void LLSoundBridgeAction::doIt()
+void LLSoundBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if(item)
{
LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
}
-
+
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLLandmarkBridgeAction::doIt()
+//virtual
+void LLLandmarkBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if( item )
@@ -4621,8 +4859,8 @@ void LLLandmarkBridgeAction::doIt()
}
-//virtual
-void LLCallingCardBridgeAction::doIt()
+//virtual
+void LLCallingCardBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if(item && item->getCreatorUUID().notNull())
@@ -4633,9 +4871,9 @@ void LLCallingCardBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void
-LLNotecardBridgeAction::doIt()
+//virtual
+void
+LLNotecardBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4646,8 +4884,8 @@ LLNotecardBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLGestureBridgeAction::doIt()
+//virtual
+void LLGestureBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4659,8 +4897,8 @@ void LLGestureBridgeAction::doIt()
LLInvFVBridgeAction::doIt();
}
-//virtual
-void LLAnimationBridgeAction::doIt()
+//virtual
+void LLAnimationBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4672,7 +4910,7 @@ void LLAnimationBridgeAction::doIt()
}
-//virtual
+//virtual
void LLObjectBridgeAction::doIt()
{
LLFloaterReg::showInstance("properties", mUUID);
@@ -4681,8 +4919,8 @@ void LLObjectBridgeAction::doIt()
}
-//virtual
-void LLLSLTextBridgeAction::doIt()
+//virtual
+void LLLSLTextBridgeAction::doIt()
{
LLViewerInventoryItem* item = getItem();
if (item)
@@ -4697,7 +4935,7 @@ void LLLSLTextBridgeAction::doIt()
BOOL LLWearableBridgeAction::isInTrash() const
{
if(!mModel) return FALSE;
- LLUUID trash_id = mModel->findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
return mModel->isObjectDescendentOf(mUUID, trash_id);
}
@@ -4712,7 +4950,7 @@ void LLWearableBridgeAction::wearOnAvatar()
{
// Don't wear anything until initial wearables are loaded, can
// destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
+ if (!gAgentWearables.areWearablesLoaded())
{
LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
return;
@@ -4739,7 +4977,7 @@ void LLWearableBridgeAction::wearOnAvatar()
}
}
-//virtual
+//virtual
void LLWearableBridgeAction::doIt()
{
if(isInTrash())
@@ -4815,14 +5053,14 @@ void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Restore Item"));
}
else
- {
+ {
items.push_back(std::string("Delete"));
if (!isItemRemovable())
{
disabled_items.push_back(std::string("Delete"));
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
@@ -4836,7 +5074,7 @@ std::string LLLinkFolderBridge::sPrefix("Link: ");
LLUIImagePtr LLLinkFolderBridge::getIcon() const
{
- LLAssetType::EType preferred_type = LLAssetType::AT_NONE;
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
if (LLViewerInventoryItem *item = getItem())
{
if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
@@ -4865,7 +5103,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
items.push_back(std::string("Restore Item"));
}
else
- {
+ {
items.push_back(std::string("Goto Link"));
items.push_back(std::string("Delete"));
if (!isItemRemovable())
@@ -4873,7 +5111,7 @@ void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
disabled_items.push_back(std::string("Delete"));
}
}
- hideContextEntries(menu, items, disabled_items);
+ hide_context_entries(menu, items, disabled_items);
}
void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index bc950520aa..f95e8f9361 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -41,6 +41,7 @@
#include "llfoldervieweventlistener.h"
class LLInventoryPanel;
+class LLMenuGL;
enum EInventoryIcon
{
@@ -120,6 +121,11 @@ 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)
//
@@ -153,7 +159,7 @@ public:
virtual const std::string& getName() const;
virtual const std::string& getDisplayName() const;
virtual PermissionMask getPermissionMask() const;
- virtual LLAssetType::EType getPreferredType() const;
+ virtual LLFolderType::EType getPreferredType() const;
virtual time_t getCreationDate() const;
virtual LLFontGL::StyleFlags getLabelStyle() const
{
@@ -168,13 +174,13 @@ public:
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() {}
@@ -221,6 +227,22 @@ protected:
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;
+};
+
class LLItemBridge : public LLInvFVBridge
{
@@ -276,9 +298,9 @@ public:
virtual void selectItem();
virtual void restoreItem();
- virtual LLAssetType::EType getPreferredType() const;
+ virtual LLFolderType::EType getPreferredType() const;
virtual LLUIImagePtr getIcon() const;
- static LLUIImagePtr getIcon(LLAssetType::EType asset_type);
+ static LLUIImagePtr getIcon(LLFolderType::EType preferred_type);
virtual BOOL renameItem(const std::string& new_name);
virtual BOOL removeItem();
@@ -291,14 +313,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;
@@ -785,5 +808,9 @@ BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
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
index b4d3f4575b..7ec8d3d003 100644
--- a/indra/newview/llinventoryfilter.cpp
+++ b/indra/newview/llinventoryfilter.cpp
@@ -131,6 +131,13 @@ BOOL LLInventoryFilter::check(LLFolderViewItem* item)
&& (mFilterSubString.size() == 0 || mSubStringMatchOffset != std::string::npos)
&& ((listener->getPermissionMask() & mFilterOps.mPermissions) == mFilterOps.mPermissions)
&& (listener->getCreationDate() >= earliest && listener->getCreationDate() <= mFilterOps.mMaxDate);
+
+ BOOL is_folder = (dynamic_cast<LLFolderViewFolder*>(item) != NULL);
+ if (is_folder && mFilterOps.mShowFolderState == LLInventoryFilter::SHOW_ALL_FOLDERS)
+ {
+ passed = TRUE;
+ }
+
return passed;
}
diff --git a/indra/newview/llinventoryfunctions.cpp b/indra/newview/llinventoryfunctions.cpp
new file mode 100644
index 0000000000..75218e98e0
--- /dev/null
+++ b/indra/newview/llinventoryfunctions.cpp
@@ -0,0 +1,340 @@
+/**
+ * @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 "llfloaterchat.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);
+}
diff --git a/indra/newview/llinventoryfunctions.h b/indra/newview/llinventoryfunctions.h
new file mode 100644
index 0000000000..95cc68ddbe
--- /dev/null
+++ b/indra/newview/llinventoryfunctions.h
@@ -0,0 +1,136 @@
+/**
+ * @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 "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 LLInventoryPanel;
+class LLInvFVBridge;
+class LLInventoryFVBridgeBuilder;
+class LLMenuBarGL;
+class LLCheckBoxCtrl;
+class LLSpinCtrl;
+class LLScrollContainer;
+class LLTextBox;
+class LLIconCtrl;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+//
+// This is a collection of miscellaneous functions and classes
+// that don't fit cleanly into any other class header.
+//
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+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 );
+
+#endif // LL_LLINVENTORYFUNCTIONS_H
+
+
+
diff --git a/indra/newview/llinventorymodel.cpp b/indra/newview/llinventorymodel.cpp
index 2f3171a868..baf34b42ff 100644
--- a/indra/newview/llinventorymodel.cpp
+++ b/indra/newview/llinventorymodel.cpp
@@ -46,7 +46,10 @@
#include "llfloater.h"
#include "llfocusmgr.h"
#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
#include "llfloaterinventory.h"
+#include "llviewerfoldertype.h"
#include "llviewerinventory.h"
#include "llviewermessage.h"
#include "llviewerwindow.h"
@@ -176,12 +179,21 @@ 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
@@ -305,7 +317,7 @@ 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)
{
const LLUUID &rv = findCatUUID(t);
if(rv.isNull() && isInventoryUsable() && create_folder)
@@ -321,10 +333,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.
-const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) const
+const LLUUID &LLInventoryModel::findCatUUID(LLFolderType::EType preferred_type) const
{
const LLUUID &root_id = gInventory.getRootFolderID();
- if(LLAssetType::AT_CATEGORY == preferred_type)
+ if(LLFolderType::FT_CATEGORY == preferred_type)
{
return root_id;
}
@@ -352,7 +364,7 @@ const LLUUID &LLInventoryModel::findCatUUID(LLAssetType::EType preferred_type) c
// 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;
@@ -362,9 +374,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;
}
@@ -376,7 +388,7 @@ LLUUID LLInventoryModel::createNewCategory(const LLUUID& parent_id,
}
else
{
- name.assign(LLAssetType::lookupCategoryName(preferred_type));
+ name.assign(LLViewerFolderType::lookupNewCategoryName(preferred_type));
}
// Add the category to the internal representation
@@ -440,7 +452,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
// Start with categories
if(!include_trash)
{
- const LLUUID trash_id = findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = findCategoryUUIDForType(LLFolderType::FT_TRASH);
if(trash_id.notNull() && (trash_id == id))
return;
}
@@ -474,7 +486,7 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
if (item->getActualType() == LLAssetType::AT_LINK_FOLDER)
{
LLViewerInventoryCategory *linked_cat = item->getLinkedCategory();
- if (linked_cat && linked_cat->getPreferredType() != LLAssetType::AT_OUTFIT)
+ if (linked_cat && linked_cat->getPreferredType() != LLFolderType::FT_OUTFIT)
// BAP - was
// LLAssetType::lookupIsEnsembleCategoryType(linked_cat->getPreferredType()))
// Change back once ensemble typing is in place.
@@ -507,8 +519,12 @@ void LLInventoryModel::collectDescendentsIf(const LLUUID& id,
}
}
-void LLInventoryModel::updateLinkedObjects(const LLUUID& object_id)
+void LLInventoryModel::updateLinkedItems(const LLUUID& object_id)
{
+ 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);
@@ -536,16 +552,31 @@ void LLInventoryModel::updateLinkedObjects(const LLUUID& object_id)
notifyObservers();
}
-void LLInventoryModel::collectLinkedItems(const LLUUID& id,
- item_array_t& items)
+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(gInventory.getRootFolderID(),
+ 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
@@ -635,7 +666,7 @@ U32 LLInventoryModel::updateItem(const LLViewerInventoryItem* 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 )
@@ -659,7 +690,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);
@@ -672,7 +703,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)
@@ -909,8 +940,7 @@ void LLInventoryModel::purgeLinkedObjects(const LLUUID &id)
return;
}
- LLInventoryModel::item_array_t item_array;
- collectLinkedItems(id, item_array);
+ LLInventoryModel::item_array_t item_array = collectLinkedItems(id);
for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
iter != item_array.end();
@@ -1131,6 +1161,13 @@ void LLInventoryModel::addChangedMask(U32 mask, const LLUUID& referent)
{
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)
+ {
+ updateLinkedItems(referent);
+ }
}
// This method to prepares a set of mock inventory which provides
@@ -1148,7 +1185,7 @@ void LLInventoryModel::mock(const LLUUID& root_id)
root_id,
LLUUID::null,
LLAssetType::AT_CATEGORY,
- LLAssetType::lookupCategoryName(LLAssetType::AT_ROOT_CATEGORY),
+ LLFolderType::lookupNewCategoryName(LLFolderType::FT_ROOT_CATEGORY),
gAgent.getID());
addCategory(cat);
gInventory.buildParentChildMap();
@@ -1306,7 +1343,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;
@@ -1985,63 +2022,56 @@ 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.
@@ -2216,85 +2246,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;
}
@@ -2372,12 +2401,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_CATEGORY == pref)
{
// it's the root
cat->setParent(LLUUID::null);
@@ -2436,7 +2465,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();
@@ -2457,7 +2486,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)
@@ -2910,7 +2939,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());
@@ -3148,13 +3177,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 (LLFloaterInventory::sWearNewClothing)
+ if (LLInventoryState::sWearNewClothing)
{
- LLFloaterInventory::sWearNewClothingTransactionID = tid;
- LLFloaterInventory::sWearNewClothing = FALSE;
+ LLInventoryState::sWearNewClothingTransactionID = tid;
+ LLInventoryState::sWearNewClothing = FALSE;
}
- if (tid == LLFloaterInventory::sWearNewClothingTransactionID)
+ if (tid == LLInventoryState::sWearNewClothingTransactionID)
{
count = wearable_ids.size();
for (i = 0; i < count; ++i)
@@ -3297,31 +3326,31 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**)
//----------------------------------------------------------------------------
-// Trash: LLAssetType::AT_TRASH, "ConfirmEmptyTrash"
-// Lost&Found: LLAssetType::AT_LOST_AND_FOUND, "ConfirmEmptyLostAndFound"
+// Trash: LLFolderType::FT_TRASH, "ConfirmEmptyTrash"
+// Lost&Found: LLFolderType::FT_LOST_AND_FOUND, "ConfirmEmptyLostAndFound"
-bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLAssetType::EType folder_type)
+bool LLInventoryModel::callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLFolderType::EType preferred_type)
{
S32 option = LLNotification::getSelectedOption(notification, response);
if (option == 0) // YES
{
- LLUUID folder_id = findCategoryUUIDForType(folder_type);
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
purgeDescendentsOf(folder_id);
notifyObservers();
}
return false;
}
-void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetType::EType folder_type)
+void LLInventoryModel::emptyFolderType(const std::string notification, LLFolderType::EType preferred_type)
{
if (!notification.empty())
{
LLNotifications::instance().add(notification, LLSD(), LLSD(),
- boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, folder_type));
+ boost::bind(&LLInventoryModel::callbackEmptyFolderType, this, _1, _2, preferred_type));
}
else
{
- LLUUID folder_id = findCategoryUUIDForType(folder_type);
+ const LLUUID folder_id = findCategoryUUIDForType(preferred_type);
purgeDescendentsOf(folder_id);
notifyObservers();
}
@@ -3332,7 +3361,7 @@ void LLInventoryModel::emptyFolderType(const std::string notification, LLAssetTy
void LLInventoryModel::removeItem(const LLUUID& item_id)
{
LLViewerInventoryItem* item = getItem(item_id);
- const LLUUID new_parent = findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID new_parent = findCategoryUUIDForType(LLFolderType::FT_TRASH);
if (item && item->getParentUUID() != new_parent)
{
LLInventoryModel::update_list_t update;
diff --git a/indra/newview/llinventorymodel.h b/indra/newview/llinventorymodel.h
index 91a1906fab..aba0a619db 100644
--- a/indra/newview/llinventorymodel.h
+++ b/indra/newview/llinventorymodel.h
@@ -34,6 +34,7 @@
#define LL_LLINVENTORYMODEL_H
#include "llassettype.h"
+#include "llfoldertype.h"
#include "lldarray.h"
#include "llframetimer.h"
#include "llhttpclient.h"
@@ -112,7 +113,9 @@ public:
// construction & destruction
LLInventoryModel();
~LLInventoryModel();
-
+
+ void cleanupInventory();
+
class fetchInventoryResponder : public LLHTTPClient::Responder
{
public:
@@ -190,10 +193,13 @@ public:
// Collect all items in inventory that are linked to item_id.
// Assumes item_id is itself not a linked item.
- void collectLinkedItems(const LLUUID& item_id,
- item_array_t& items);
- // Updates all linked objects pointing to this id.
- void updateLinkedObjects(const LLUUID& object_id);
+ item_array_t collectLinkedItems(const LLUUID& item_id,
+ const LLUUID& start_folder_id = LLUUID::null);
+ // Updates all linked items pointing to this id.
+ void updateLinkedItems(const LLUUID& object_id);
+
+ // Get the inventoryID that this item points to, else just return item_id
+ const LLUUID& getLinkedItemID(const LLUUID& object_id) const;
// The inventory model usage is sensitive to the initial construction of the
// model.
@@ -275,7 +281,7 @@ public:
// 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);
// Call this method when it's time to update everyone on a new
// state, by default, the inventory model will not update
@@ -324,15 +330,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.
@@ -382,9 +386,9 @@ public:
bool isCategoryComplete(const LLUUID& cat_id) const;
// callbacks
- // Trigger a notification and empty the folder type (AT_TRASH or AT_LOST_AND_FOUND) if confirmed
- void emptyFolderType(const std::string notification, LLAssetType::EType folder_type);
- bool callbackEmptyFolderType(const LLSD& notification, const LLSD& response, LLAssetType::EType folder_type);
+ // 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);
// Utility Functions
void removeItem(const LLUUID& item_id);
@@ -428,7 +432,7 @@ protected:
//
// Internal method which looks for a category with the specified
// preferred type. Returns LLUUID::null if not found
- const LLUUID &findCatUUID(LLAssetType::EType preferred_type) const;
+ const LLUUID &findCatUUID(LLFolderType::EType preferred_type) const;
// Empty the entire contents
void empty();
diff --git a/indra/newview/llinventorypanel.cpp b/indra/newview/llinventorypanel.cpp
new file mode 100644
index 0000000000..178e7d0823
--- /dev/null
+++ b/indra/newview/llinventorypanel.cpp
@@ -0,0 +1,902 @@
+/**
+ * @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 "llinventorypanel.h"
+
+// Seraph TODO: Remove unnecessary headers
+
+// 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 "llfloaterchat.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 "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 "llviewerfoldertype.h"
+#include "llviewerinventory.h"
+#include "llviewermessage.h"
+#include "llviewerobjectlist.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llvoavatarself.h"
+#include "llwearablelist.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;
+
+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),
+ mHasInventoryConnection(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));
+
+ setBackgroundColor(LLUIColorTable::instance().getColor("InventoryBackgroundColor"));
+ setBackgroundVisible(TRUE);
+ setBackgroundOpaque(TRUE);
+}
+
+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;
+ 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);
+
+ // determine the root folder, if any, so inventory contents show just the children
+ // of that folder (i.e. not including the folder itself).
+ const LLFolderType::EType preferred_type = LLViewerFolderType::lookupTypeFromNewCategoryName(mStartFolderString);
+
+ if ("INVENTORY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getRootFolderID();
+ }
+ else if ("LIBRARY" == mStartFolderString)
+ {
+ mStartFolderID = gInventory.getLibraryRootFolderID();
+ }
+ else
+ {
+ mStartFolderID = (preferred_type != LLFolderType::FT_NONE ? gInventory.findCategoryUUIDForType(preferred_type) : LLUUID::null);
+ }
+
+ // build view of inventory if we need default full hierarchy and inventory ready, otherwise wait for modelChanged() callback
+ if (mBuildDefaultHierarchy && mInventory->isInventoryUsable() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ }
+
+ // bit of a hack to make sure the inventory is open.
+ mFolders->openFolder(preferred_type != LLFolderType::FT_NONE ? LLViewerFolderType::lookupNewCategoryName(preferred_type) : "My Inventory");
+
+ if (mSortOrderSetting != INHERIT_SORT_ORDER)
+ {
+ setSortOrder(gSavedSettings.getU32(mSortOrderSetting));
+ }
+ else
+ {
+ setSortOrder(gSavedSettings.getU32(DEFAULT_SORT_ORDER));
+ }
+ mFolders->setSortOrder(mFolders->getFilter()->getSortOrder());
+
+ return TRUE;
+}
+
+LLInventoryPanel::~LLInventoryPanel()
+{
+ // should this be a global setting?
+ 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;
+}
+
+LLMemType mt(LLMemType::MTYPE_INVENTORY_FROM_XML); // ! BUG ! Should this be removed?
+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 filter_types, BOOL filter_for_categories)
+{
+ mFolders->getFilter()->setFilterTypes(filter_types, filter_for_categories);
+}
+
+void LLInventoryPanel::setFilterPermMask(PermissionMask filter_perm_mask)
+{
+ mFolders->getFilter()->setFilterPermissions(filter_perm_mask);
+}
+
+void LLInventoryPanel::setFilterSubString(const std::string& string)
+{
+ mFolders->getFilter()->setFilterSubString(string);
+}
+
+void LLInventoryPanel::setSortOrder(U32 order)
+{
+ mFolders->getFilter()->setSortOrder(order);
+ if (mFolders->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)
+{
+ mFolders->getFilter()->setDateRangeLastLogoff(sl);
+}
+
+void LLInventoryPanel::setHoursAgo(U32 hours)
+{
+ mFolders->getFilter()->setHoursAgo(hours);
+}
+
+void LLInventoryPanel::setShowFolderState(LLInventoryFilter::EFolderShow show)
+{
+ mFolders->getFilter()->setShowFolderState(show);
+}
+
+LLInventoryFilter::EFolderShow LLInventoryPanel::getShowFolderState()
+{
+ return mFolders->getFilter()->getShowFolderState();
+}
+
+static LLFastTimer::DeclareTimer FTM_REFRESH("Inventory Refresh");
+
+void LLInventoryPanel::modelChanged(U32 mask)
+{
+ LLFastTimer t2(FTM_REFRESH);
+
+ bool handled = false;
+
+ // inventory just initialized, do complete build
+ if ((mask & LLInventoryObserver::ADD) && gInventory.getChangedIDs().empty() && !mHasInventoryConnection)
+ {
+ rebuildViewsFor(mStartFolderID);
+ mHasInventoryConnection = true;
+ return;
+ }
+
+ if(mask & LLInventoryObserver::LABEL)
+ {
+ handled = true;
+ // label change - empty out the display name for each object
+ // in this change set.
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ LLFolderViewItem* view = NULL;
+ LLInvFVBridge* bridge = NULL;
+ for (;id_it != id_end; ++id_it)
+ {
+ view = mFolders->getItemByID(*id_it);
+ if(view)
+ {
+ // request refresh on this item (also flags for filtering)
+ bridge = (LLInvFVBridge*)view->getListener();
+ if(bridge)
+ { // Clear the display name first, so it gets properly re-built during refresh()
+ bridge->clearDisplayName();
+ }
+ view->refresh();
+ }
+ }
+ }
+ if((mask & (LLInventoryObserver::STRUCTURE
+ | LLInventoryObserver::ADD
+ | LLInventoryObserver::REMOVE)) != 0)
+ {
+ handled = true;
+ // Record which folders are open by uuid.
+ LLInventoryModel* model = getModel();
+ if (model)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.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)
+ {
+ // sync view with model
+ LLInventoryObject* model_item = model->getObject(*id_it);
+ LLFolderViewItem* view_item = mFolders->getItemByID(*id_it);
+
+ if (model_item)
+ {
+ if (!view_item)
+ {
+ // this object was just created, need to build a view for it
+ if ((mask & LLInventoryObserver::ADD) != LLInventoryObserver::ADD)
+ {
+ llwarns << *id_it << " is in model but not in view, but ADD flag not set" << llendl;
+ }
+ buildNewViews(*id_it);
+
+ // select any newly created object
+ // that has the auto rename at top of folder
+ // root set
+ if(mFolders->getRoot()->needsAutoRename())
+ {
+ setSelection(*id_it, FALSE);
+ }
+ }
+ else
+ {
+ // this object was probably moved, check its parent
+ if ((mask & LLInventoryObserver::STRUCTURE) != LLInventoryObserver::STRUCTURE)
+ {
+ llwarns << *id_it << " is in model and in view, but STRUCTURE flag not set" << llendl;
+ }
+
+ LLFolderViewFolder* new_parent = (LLFolderViewFolder*)mFolders->getItemByID(model_item->getParentUUID());
+
+ // added check against NULL for cases when Inventory panel contains startFolder.
+ // in this case parent is LLFolderView (LLInventoryPanel::mFolders) itself.
+ // this check is a fix for bug EXT-1859.
+ if (NULL != new_parent && view_item->getParentFolder() != new_parent)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ view_item->addToFolder(new_parent, mFolders);
+ }
+/*
+ on the other side in case Inventory Panel has content of the any folder
+ it is possible that item moved to some folder which is absent in current
+ Panel. For ex. removing item (via moving to trash).
+ In this case we need to check if new parent is other then inventory start folder
+ and simply remove its View from the hierarchy.
+ See details in EXT-2098.
+*/
+ // So, let check if item was moved into folder out of this Inventory Panel.
+ else if (mStartFolderID.notNull() && NULL == new_parent && model_item->getParentUUID() != mStartFolderID)
+ {
+ view_item->getParentFolder()->extractItem(view_item);
+ }
+ }
+ }
+ else
+ {
+ if (view_item)
+ {
+ if ((mask & LLInventoryObserver::REMOVE) != LLInventoryObserver::REMOVE)
+ {
+ llwarns << *id_it << " is not in model but in view, but REMOVE flag not set" << llendl;
+ }
+ // item in view but not model, need to delete view
+ view_item->destroyView();
+ }
+ else
+ {
+ llwarns << *id_it << "Item does not exist in either view or model, but notification triggered" << llendl;
+ }
+ }
+ }
+ }
+ }
+
+ if (!handled)
+ {
+ // it's a small change that only requires a refresh.
+ // *TODO: figure out a more efficient way to do the refresh
+ // since it is expensive on large inventories
+ mFolders->refresh();
+ }
+}
+
+
+void LLInventoryPanel::rebuildViewsFor(const LLUUID& id)
+{
+ LLFolderViewItem* old_view = NULL;
+
+ // get old 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 = NULL;
+
+ // Don't add the start folder (the inventory panel will show contents
+ // beginning with the children of the starting folder, excluding the starting folder itself).
+ if (id != mStartFolderID)
+ {
+ objectp = gInventory.getObject(id);
+ if (objectp)
+ {
+ const LLUUID &parent_id = objectp->getParentUUID();
+ // If this item's parent is the starting folder, then just add it to the top level (recall that
+ // the starting folder isn't actually represented in the view, parent_folder would be NULL in
+ // this case otherwise).
+ LLFolderViewFolder* parent_folder = (parent_id == mStartFolderID ?
+ mFolders : (LLFolderViewFolder*)mFolders->getItemByID(parent_id));
+
+ // This item exists outside the inventory's hierarchy, so don't add it.
+ if (!parent_folder)
+ {
+ return;
+ }
+
+ if (objectp->getType() <= LLAssetType::AT_NONE ||
+ objectp->getType() >= LLAssetType::AT_COUNT)
+ {
+ llwarns << "LLInventoryPanel::buildNewViews called with invalid objectp->mType : " <<
+ ((S32) objectp->getType()) << 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 p;
+ p.name = new_listener->getDisplayName();
+ p.icon = new_listener->getIcon();
+ p.root = mFolders;
+ p.listener = new_listener;
+ LLFolderViewFolder* folderp = LLUICtrlFactory::create<LLFolderViewFolder>(p);
+
+ folderp->setItemSortOrder(mFolders->getSortOrder());
+ itemp = folderp;
+ }
+ }
+ 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.creation_date(new_listener->getCreationDate());
+ params.root(mFolders);
+ params.listener(new_listener);
+ params.rect(LLRect (0, 0, 0, 0));
+ 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)
+ {
+ S32 count = categories->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryCategory* cat = categories->get(i);
+ buildNewViews(cat->getUUID());
+ }
+ }
+ if(items)
+ {
+ S32 count = items->count();
+ for(S32 i = 0; i < count; ++i)
+ {
+ LLInventoryItem* item = items->get(i);
+ buildNewViews(item->getUUID());
+ }
+ }
+ mInventory->unlockDirectDescendentArrays(id);
+ }
+}
+
+struct LLConfirmPurgeData
+{
+ LLUUID mID;
+ LLInventoryModel* mModel;
+};
+
+class LLIsNotWorn : public LLInventoryCollectFunctor
+{
+public:
+ LLIsNotWorn() {}
+ virtual ~LLIsNotWorn() {}
+ virtual bool operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+ {
+ return !gAgentWearables.isWearingItem(item->getUUID());
+ }
+};
+
+class LLOpenFolderByID : public LLFolderViewFunctor
+{
+public:
+ LLOpenFolderByID(const LLUUID& id) : mID(id) {}
+ virtual ~LLOpenFolderByID() {}
+ virtual void doFolder(LLFolderViewFolder* folder)
+ {
+ if (folder->getListener() && folder->getListener()->getUUID() == mID) folder->setOpenArrangeRecursively(TRUE, LLFolderViewFolder::RECURSE_UP);
+ }
+ virtual void doItem(LLFolderViewItem* item) {}
+protected:
+ const LLUUID& mID;
+};
+
+
+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 (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::openDefaultFolderForType(LLFolderType::EType type)
+{
+ LLUUID category_id = mInventory->findCategoryUUIDForType(type);
+ LLOpenFolderByID opener(category_id);
+ mFolders->applyFunctorRecursively(opener);
+}
+
+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::getCOF())
+ {
+ return;
+ }
+ mFolders->setSelectionByID(obj_id, take_keyboard_focus);
+}
+
+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++);
+ }
+
+ gIMMgr->addSession(name, type, members[0], members);
+
+ 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;
+}
+
+
+//----------------------------------------------------------------------------
+
+// static DEBUG ONLY:
+void LLInventoryPanel::dumpSelectionInformation(void* user_data)
+{
+ LLInventoryPanel* iv = (LLInventoryPanel*)user_data;
+ iv->mFolders->dumpSelectionInformation();
+}
+
+BOOL LLInventoryPanel::getSinceLogoff()
+{
+ return mFolders->getFilter()->isSinceLogoff();
+}
+
+void example_param_block_usage()
+{
+ LLInventoryPanel::Params param_block;
+ param_block.name(std::string("inventory"));
+
+ param_block.sort_order_setting(LLInventoryPanel::RECENTITEMS_SORT_ORDER);
+ param_block.allow_multi_select(true);
+ param_block.filter(LLInventoryPanel::Filter()
+ .sort_order(1)
+ .types(0xffff0000));
+ param_block.inventory(&gInventory);
+ param_block.has_border(true);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+
+ param_block = LLInventoryPanel::Params();
+ param_block.name(std::string("inventory"));
+
+ //LLSD param_block_sd;
+ //param_block_sd["sort_order_setting"] = LLInventoryPanel::RECENTITEMS_SORT_ORDER;
+ //param_block_sd["allow_multi_select"] = true;
+ //param_block_sd["filter"]["sort_order"] = 1;
+ //param_block_sd["filter"]["types"] = (S32)0xffff0000;
+ //param_block_sd["has_border"] = true;
+
+ //LLInitParam::LLSDParser(param_block_sd).parse(param_block);
+
+ LLUICtrlFactory::create<LLInventoryPanel>(param_block);
+}
diff --git a/indra/newview/llinventorypanel.h b/indra/newview/llinventorypanel.h
new file mode 100644
index 0000000000..9f74fad5c1
--- /dev/null
+++ b/indra/newview/llinventorypanel.h
@@ -0,0 +1,206 @@
+/**
+ * @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 openDefaultFolderForType(LLFolderType::EType);
+ void setSelection(const LLUUID& obj_id, BOOL take_keyboard_focus);
+ void setSelectCallback(const LLFolderView::signal_t::slot_type& cb) { if (mFolders) mFolders->setSelectCallback(cb); }
+ void clearSelection();
+ LLInventoryFilter* getFilter();
+ void setFilterTypes(U64 filter, BOOL filter_for_categories = FALSE); // if filter_for_categories is true, operate on folder preferred asset type
+ U32 getFilterTypes() const { return mFolders->getFilterTypes(); }
+ 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); }
+
+protected:
+ // Given the id and the parent, build all of the folder views.
+ void rebuildViewsFor(const LLUUID& id);
+ virtual void buildNewViews(const LLUUID& id); // made virtual to support derived classes. EXT-719
+
+protected:
+ LLInventoryModel* mInventory;
+ LLInventoryObserver* mInventoryObserver;
+ BOOL mAllowMultiSelect;
+ std::string mSortOrderSetting;
+
+//private: // Can not make these private - needed by llinventorysubtreepanel
+ LLFolderView* mFolders;
+ std::string mStartFolderString;
+
+ /**
+ * Contains UUID of Inventory item from which hierarchy should be built.
+ * Can be set with the "start_folder" xml property.
+ * Default is LLUUID::null that means total Inventory hierarchy.
+ */
+ LLUUID mStartFolderID;
+ LLScrollContainer* mScroller;
+ bool mHasInventoryConnection;
+
+ /**
+ * Flag specified if default inventory hierarchy should be created in postBuild()
+ */
+ bool mBuildDefaultHierarchy;
+
+ LLUUID mRootInventoryItemUUID;
+
+ /**
+ * 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;
+
+};
+
+#endif // LL_LLINVENTORYPANEL_H
diff --git a/indra/newview/lljoystickbutton.cpp b/indra/newview/lljoystickbutton.cpp
index 4fd3b7bddc..bd6702a0b2 100644
--- a/indra/newview/lljoystickbutton.cpp
+++ b/indra/newview/lljoystickbutton.cpp
@@ -517,43 +517,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 );
+ drawRotatedImage( getImageSelected(), 3 );
}
}
// Draws image rotated by multiples of 90 degrees
-void LLJoystickCameraRotate::drawRotatedImage( LLTexture* 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);
diff --git a/indra/newview/lljoystickbutton.h b/indra/newview/lljoystickbutton.h
index 8caef30fa4..4c657913b8 100644
--- a/indra/newview/lljoystickbutton.h
+++ b/indra/newview/lljoystickbutton.h
@@ -150,7 +150,7 @@ public:
protected:
F32 getOrbitRate();
virtual void updateSlop();
- void drawRotatedImage( LLTexture* image, S32 rotations );
+ void drawRotatedImage( LLPointer<LLUIImage> image, S32 rotations );
protected:
BOOL mInLeft;
diff --git a/indra/newview/lllandmarkactions.cpp b/indra/newview/lllandmarkactions.cpp
index 7c759e22a8..b1829b3945 100644
--- a/indra/newview/lllandmarkactions.cpp
+++ b/indra/newview/lllandmarkactions.cpp
@@ -42,16 +42,18 @@
#include "llnotifications.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 "llviewerwindow.h"
+#include "llwindow.h"
#include "llworldmap.h"
-#include "lllandmark.h"
-#include "llinventorymodel.h"
-#include "llagentui.h"
+void copy_slurl_to_clipboard_callback(const std::string& slurl);
class LLFetchlLandmarkByPos : public LLInventoryCollectFunctor
{
@@ -131,13 +133,39 @@ public:
}
};
+// 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"
- LLUUID favorites_folder_id =
- gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ const LLUUID favorites_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
gInventory.collectDescendentsIf(favorites_folder_id,
cats,
items,
@@ -145,8 +173,7 @@ static void fetch_landmarks(LLInventoryModel::cat_array_t& cats,
add);
// Look in "Landmarks"
- LLUUID landmarks_folder_id =
- gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+ const LLUUID landmarks_folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
gInventory.collectDescendentsIf(landmarks_folder_id,
cats,
items,
@@ -170,6 +197,16 @@ bool LLLandmarkActions::landmarkAlreadyExists()
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
@@ -248,7 +285,7 @@ void LLLandmarkActions::createLandmarkHere()
LLAgentUI::buildLocationString(landmark_name, LLAgentUI::LOCATION_FORMAT_LANDMARK);
LLAgentUI::buildLocationString(landmark_desc, LLAgentUI::LOCATION_FORMAT_FULL);
- LLUUID folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK);
+ const LLUUID folder_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LANDMARK);
createLandmarkHere(landmark_name, landmark_desc, folder_id);
}
@@ -268,23 +305,42 @@ void LLLandmarkActions::getSLURLfromPosGlobal(const LLVector3d& global_pos, slur
{
U64 new_region_handle = to_region_handle(global_pos);
- LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponse,
+ LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseSLURL,
cb,
global_pos,
escaped,
- _1, _2, _3, _4);
+ _2);
+
+ LLWorldMap::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);
+ cb(sim_infop->mName, llround(pos.mV[VX]), llround(pos.mV[VY]));
+ }
+ else
+ {
+ U64 new_region_handle = to_region_handle(global_pos);
+
+ LLWorldMap::url_callback_t url_cb = boost::bind(&LLLandmarkActions::onRegionResponseNameAndCoords,
+ cb,
+ global_pos,
+ _1);
LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, url_cb, std::string("unused"), false);
}
}
-void LLLandmarkActions::onRegionResponse(slurl_callback_t cb,
+void LLLandmarkActions::onRegionResponseSLURL(slurl_callback_t cb,
const LLVector3d& global_pos,
bool escaped,
- U64 region_handle,
- const std::string& url,
- const LLUUID& snapshot_id,
- bool teleport)
+ const std::string& url)
{
std::string sim_name;
std::string slurl;
@@ -301,17 +357,53 @@ void LLLandmarkActions::onRegionResponse(slurl_callback_t cb,
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);
+ cb(sim_infop->mName, llround(local_pos.mV[VX]), llround(local_pos.mV[VY]));
+ }
+}
+
bool LLLandmarkActions::getLandmarkGlobalPos(const LLUUID& landmarkInventoryItemID, LLVector3d& posGlobal)
{
+ LLLandmark* landmark = LLLandmarkActions::getLandmark(landmarkInventoryItemID);
+
+ if (NULL == landmark)
+ return false;
+
+ return landmark->getGlobalPos(posGlobal);
+}
+
+LLLandmark* LLLandmarkActions::getLandmark(const LLUUID& landmarkInventoryItemID)
+{
LLViewerInventoryItem* item = gInventory.getItem(landmarkInventoryItemID);
if (NULL == item)
- return false;
+ return NULL;
const LLUUID& asset_id = item->getAssetUUID();
- LLLandmark* landmark = gLandmarkList.getAsset(asset_id, NULL);
+ return gLandmarkList.getAsset(asset_id, NULL);
+}
- if (NULL == landmark)
- return false;
+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);
+ }
+}
- return landmark->getGlobalPos(posGlobal);
+void copy_slurl_to_clipboard_callback(const std::string& slurl)
+{
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(slurl));
+ LLSD args;
+ args["SLURL"] = slurl;
+ LLNotifications::instance().add("CopySLURL", args);
}
diff --git a/indra/newview/lllandmarkactions.h b/indra/newview/lllandmarkactions.h
index ab8cc4d6a5..1c524c820c 100644
--- a/indra/newview/lllandmarkactions.h
+++ b/indra/newview/lllandmarkactions.h
@@ -35,6 +35,7 @@
#include "llinventorymodel.h"
+class LLLandmark;
/**
* @brief Provides helper functions to manage landmarks
*/
@@ -42,15 +43,21 @@ class LLLandmarkActions
{
public:
typedef boost::function<void(std::string& slurl)> slurl_callback_t;
+ typedef boost::function<void(std::string& slurl, S32 x, S32 y)> 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 parcel.
+ * @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.
@@ -91,6 +98,8 @@ public:
*/
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.
@@ -101,17 +110,31 @@ public:
// *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
+ *
+ * @return pointer to loaded landmark from gLandmarkList or NULL if landmark does not exist or wasn't loaded.
+ */
+ static LLLandmark* getLandmark(const LLUUID& landmarkInventoryItemID);
+
+ /**
+ * @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 onRegionResponse(slurl_callback_t cb,
+ static void onRegionResponseSLURL(slurl_callback_t cb,
const LLVector3d& global_pos,
bool escaped,
- U64 region_handle,
- const std::string& url,
- const LLUUID& snapshot_id,
- bool teleport);
+ 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 2e8084759a..83e694951b 100644
--- a/indra/newview/lllandmarklist.cpp
+++ b/indra/newview/lllandmarklist.cpp
@@ -37,6 +37,7 @@
#include "message.h"
#include "llassetstorage.h"
+#include "llappviewer.h"
#include "llagent.h"
#include "llnotify.h"
#include "llvfile.h"
@@ -63,20 +64,32 @@ LLLandmark* LLLandmarkList::getAsset(const LLUUID& asset_uuid, loaded_callback_t
}
else
{
- if ( gLandmarkList.mBadList.find(asset_uuid) == gLandmarkList.mBadList.end() )
+ if ( mBadList.find(asset_uuid) != mBadList.end() )
{
- if (cb)
+ 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)
{
- loaded_callback_map_t::value_type vt(asset_uuid, cb);
- mLoadedCallbackMap.insert(vt);
+ return NULL;
}
-
- gAssetStorage->getAssetData(
- asset_uuid,
- LLAssetType::AT_LANDMARK,
- LLLandmarkList::processGetAssetReply,
- 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;
}
@@ -103,7 +116,8 @@ void LLLandmarkList::processGetAssetReply(
if (landmark)
{
gLandmarkList.mList[ uuid ] = landmark;
-
+ gLandmarkList.mRequestedList.erase(uuid);
+
LLVector3d pos;
if(!landmark->getGlobalPos(pos))
{
diff --git a/indra/newview/lllandmarklist.h b/indra/newview/lllandmarklist.h
index ebf1b65e97..d9c3267142 100644
--- a/indra/newview/lllandmarklist.h
+++ b/indra/newview/lllandmarklist.h
@@ -74,7 +74,10 @@ protected:
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;
diff --git a/indra/newview/lllocaltextureobject.cpp b/indra/newview/lllocaltextureobject.cpp
index e4a20aea68..6bcbe6f58c 100644
--- a/indra/newview/lllocaltextureobject.cpp
+++ b/indra/newview/lllocaltextureobject.cpp
@@ -37,6 +37,7 @@
#include "llviewertexture.h"
#include "lltextureentry.h"
#include "lluuid.h"
+#include "llwearable.h"
LLLocalTextureObject::LLLocalTextureObject() :
@@ -46,31 +47,33 @@ LLLocalTextureObject::LLLocalTextureObject() :
mImage = NULL;
}
-LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture *image, LLTextureEntry *entry, LLTexLayer *layer, LLUUID id)
+LLLocalTextureObject::LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id)
{
- if (entry)
- {
- LLTextureEntry * te = new LLTextureEntry(*entry);
- mTexEntry = boost::shared_ptr<LLTextureEntry>(te);
- }
-
- if (layer)
- {
- LLTexLayer *texLayer = new LLTexLayer(*layer);
- mTexLayer = boost::shared_ptr<LLTexLayer>(texLayer);
- }
mImage = image;
+ gGL.getTexUnit(0)->bind(mImage);
mID = id;
}
-LLLocalTextureObject::LLLocalTextureObject(const LLLocalTextureObject &lto) :
-mImage(lto.mImage),
-mTexEntry(lto.mTexEntry),
-mTexLayer(lto.mTexLayer),
-mID(lto.mID),
-mIsBakedReady(lto.mIsBakedReady),
-mDiscard(lto.mDiscard)
+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()
@@ -82,14 +85,33 @@ LLViewerFetchedTexture* LLLocalTextureObject::getImage() const
return mImage;
}
-LLTextureEntry* LLLocalTextureObject::getTexEntry() const
+LLTexLayer* LLLocalTextureObject::getTexLayer(U32 index) const
{
- return mTexEntry.get();
+ if (index >= getNumTexLayers())
+ {
+ return NULL;
+ }
+
+ return mTexLayers[index];
}
-LLTexLayer* LLLocalTextureObject::getTexLayer() const
+LLTexLayer* LLLocalTextureObject::getTexLayer(const std::string &name)
{
- return mTexLayer.get();
+ 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
@@ -112,24 +134,68 @@ void LLLocalTextureObject::setImage(LLViewerFetchedTexture* new_image)
mImage = new_image;
}
-void LLLocalTextureObject::setTexEntry(LLTextureEntry *new_te)
+BOOL LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer, U32 index)
{
- LLTextureEntry *ptr = NULL;
- if (new_te)
+ if (index >= getNumTexLayers() )
+ {
+ return FALSE;
+ }
+
+ if (new_tex_layer == NULL)
{
- ptr = new LLTextureEntry(*new_te);
+ return removeTexLayer(index);
}
- mTexEntry = boost::shared_ptr<LLTextureEntry>(ptr);
+
+ 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;
}
-void LLLocalTextureObject::setTexLayer(LLTexLayer *new_tex_layer)
+BOOL LLLocalTextureObject::addTexLayer(LLTexLayerTemplate *new_tex_layer, LLWearable *wearable)
{
- LLTexLayer *ptr = NULL;
- if (new_tex_layer)
+ if (new_tex_layer == NULL)
{
- ptr = new LLTexLayer(*new_tex_layer);
+ return FALSE;
}
- mTexLayer = boost::shared_ptr<LLTexLayer>(ptr);
+
+ 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)
diff --git a/indra/newview/lllocaltextureobject.h b/indra/newview/lllocaltextureobject.h
index 79e1562dce..c8b8aa924b 100644
--- a/indra/newview/lllocaltextureobject.h
+++ b/indra/newview/lllocaltextureobject.h
@@ -35,10 +35,13 @@
#include <boost/shared_ptr.hpp>
-class LLViewerFetchedTexture;
+#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 -
@@ -47,20 +50,24 @@ class LLLocalTextureObject
{
public:
LLLocalTextureObject();
- LLLocalTextureObject(LLViewerFetchedTexture *image, LLTextureEntry *entry, LLTexLayer *layer, LLUUID id);
- LLLocalTextureObject(const LLLocalTextureObject &lto);
+ LLLocalTextureObject(LLViewerFetchedTexture* image, const LLUUID& id);
+ LLLocalTextureObject(const LLLocalTextureObject& lto);
~LLLocalTextureObject();
LLViewerFetchedTexture* getImage() const;
- LLTextureEntry* getTexEntry() const;
- LLTexLayer* getTexLayer() 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);
- void setTexEntry(LLTextureEntry *new_te);
- void setTexLayer(LLTexLayer *new_tex_layer);
+ 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);
@@ -73,8 +80,9 @@ private:
// 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
- boost::shared_ptr<LLTextureEntry> mTexEntry;
- boost::shared_ptr<LLTexLayer> mTexLayer;
+ typedef std::vector<LLTexLayer*> tex_layer_vec_t;
+ tex_layer_vec_t mTexLayers;
+
LLUUID mID;
BOOL mIsBakedReady;
diff --git a/indra/newview/lllocationinputctrl.cpp b/indra/newview/lllocationinputctrl.cpp
index 16a10dc502..8fe317a292 100644
--- a/indra/newview/lllocationinputctrl.cpp
+++ b/indra/newview/lllocationinputctrl.cpp
@@ -261,9 +261,11 @@ LLLocationInputCtrl::LLLocationInputCtrl(const LLLocationInputCtrl::Params& p)
mAddLandmarkObserver = new LLAddLandmarkObserver(this);
gInventory.addObserver(mRemoveLandmarkObserver);
gInventory.addObserver(mAddLandmarkObserver);
-
- mAddLandmarkTooltip = LLTrans::getString("location_ctrl_add_landmark");
- mEditLandmarkTooltip = LLTrans::getString("location_ctrl_edit_landmark");
+
+ 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()
@@ -292,6 +294,11 @@ void LLLocationInputCtrl::hideList()
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))
{
@@ -600,11 +607,12 @@ void LLLocationInputCtrl::enableAddLandmarkButton(bool val)
// depending on whether current parcel has been landmarked.
void LLLocationInputCtrl::updateAddLandmarkButton()
{
- bool landmark_exists = LLLandmarkActions::landmarkAlreadyExists();
- enableAddLandmarkButton(!landmark_exists);
-
+ enableAddLandmarkButton(LLLandmarkActions::hasParcelLandmark());
+}
+void LLLocationInputCtrl::updateAddLandmarkTooltip()
+{
std::string tooltip;
- if(landmark_exists)
+ if(LLLandmarkActions::landmarkAlreadyExists())
{
tooltip = mEditLandmarkTooltip;
}
diff --git a/indra/newview/lllocationinputctrl.h b/indra/newview/lllocationinputctrl.h
index c74a294ca3..44dc0cb251 100644
--- a/indra/newview/lllocationinputctrl.h
+++ b/indra/newview/lllocationinputctrl.h
@@ -107,6 +107,7 @@ private:
bool findTeleportItemsByTitle(const LLTeleportHistoryItem& item, const std::string& filter);
void setText(const LLStringExplicit& text);
void updateAddLandmarkButton();
+ void updateAddLandmarkTooltip();
void updateContextMenu();
void updateWidgetlayout();
void changeLocationPresentation();
diff --git a/indra/newview/lllogchat.cpp b/indra/newview/lllogchat.cpp
index 69214b5cab..a16ffe19c6 100644
--- a/indra/newview/lllogchat.cpp
+++ b/indra/newview/lllogchat.cpp
@@ -36,6 +36,8 @@
#include "llappviewer.h"
#include "llfloaterchat.h"
#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "llsdserialize.h"
const S32 LOG_RECALL_SIZE = 2048;
@@ -89,41 +91,53 @@ std::string LLLogChat::timestamp(bool withdate)
//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 (!gSavedPerAccountSettings.getBOOL("LogInstantMessages"))
+ return;
+
if(!filename.size())
{
llinfos << "Filename is Empty!" << llendl;
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 << LLSDOStreamer <LLSDNotationFormatter>(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 = LLTrans::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,6 +157,9 @@ void LLLogChat::loadHistory(std::string filename , void (*callback)(ELogLineType
}
}
+ // the parser's destructor is protected so we cannot create in the stack.
+ LLPointer<LLSDParser> parser = new LLSDNotationParser();
+
while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) )
{
len = strlen(buffer) - 1; /*Flawfinder: ignore*/
@@ -150,14 +167,25 @@ 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 (parser->parse(iss, item, line.length()) == LLSDParser::PARSE_FAILURE)
+ {
+ 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);
}
diff --git a/indra/newview/lllogchat.h b/indra/newview/lllogchat.h
index ad903b66fe..e252cd7d41 100644
--- a/indra/newview/lllogchat.h
+++ b/indra/newview/lllogchat.h
@@ -41,13 +41,18 @@ 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);
+
+ static void loadHistory(const std::string& filename,
+ void (*callback)(ELogLineType, const LLSD&, void*),
void* userdata);
private:
static std::string cleanFileName(std::string filename);
diff --git a/indra/newview/llloginhandler.cpp b/indra/newview/llloginhandler.cpp
index 6f0b8a3c1e..2a1f42c3c4 100644
--- a/indra/newview/llloginhandler.cpp
+++ b/indra/newview/llloginhandler.cpp
@@ -56,7 +56,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 +71,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();
@@ -165,7 +165,15 @@ void LLLoginHandler::parse(const LLSD& queryMap)
bool LLLoginHandler::handle(const LLSD& tokens,
const LLSD& query_map,
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;
+ }
+
parse(query_map);
//if we haven't initialized stuff yet, this is
@@ -200,14 +208,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 d36ceaf3cc..ac4648761b 100644
--- a/indra/newview/llloginhandler.h
+++ b/indra/newview/llloginhandler.h
@@ -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..e5f347ddc4
--- /dev/null
+++ b/indra/newview/lllogininstance.cpp
@@ -0,0 +1,475 @@
+/**
+ * @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));
+}
+
+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;
+}
+
+bool LLLoginInstance::handleLoginEvent(const LLSD& event)
+{
+ std::cout << "LoginListener called!: \n";
+ std::cout << event << "\n";
+
+ 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
+}
+
+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));
+ }
+
+ /* *NOTE:Mani Experiment with Event API interface.
+ if(!mUpdateAppResponse)
+ {
+ bool make_unique = true;
+ mUpdateAppResponse.reset(new LLEventStream("logininstance_updateapp", make_unique));
+ mUpdateAppResponse->listen("diaupdateDialogCallback",
+ boost::bind(&LLLoginInstance::updateDialogCallback,
+ this, _1
+ )
+ );
+ }
+
+ LLSD event;
+ event["op"] = "requestAdd";
+ event["name"] = notification_name;
+ event["substitutions"] = args;
+ event["payload"] = payload;
+ event["reply"] = mUpdateAppResponse->getName();
+
+ LLEventPumps::getInstance()->obtain("LLNotifications").post(event);
+ */
+}
+
+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..19d7449bc1
--- /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);
+
+ 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;
+ boost::scoped_ptr<LLEventStream> mUpdateAppResponse;
+ LLEventDispatcher mDispatcher;
+};
+
+#endif
diff --git a/indra/newview/llmaniprotate.cpp b/indra/newview/llmaniprotate.cpp
index 14a8b7cb59..c99e67be3f 100644
--- a/indra/newview/llmaniprotate.cpp
+++ b/indra/newview/llmaniprotate.cpp
@@ -1234,9 +1234,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;
}
diff --git a/indra/newview/llmaniptranslate.cpp b/indra/newview/llmaniptranslate.cpp
index 2153f77336..f1b3a37677 100644
--- a/indra/newview/llmaniptranslate.cpp
+++ b/indra/newview/llmaniptranslate.cpp
@@ -163,7 +163,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)
diff --git a/indra/newview/llmediactrl.cpp b/indra/newview/llmediactrl.cpp
index 4fa7f62c68..8f29f908e5 100644
--- a/indra/newview/llmediactrl.cpp
+++ b/indra/newview/llmediactrl.cpp
@@ -51,6 +51,7 @@
#include "llpluginclassmedia.h"
#include "llslurl.h"
#include "lluictrlfactory.h" // LLDefaultChildRegistry
+#include "llkeyboard.h"
// linden library includes
#include "llfocusmgr.h"
@@ -193,7 +194,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
if (mMediaSource)
{
- mMediaSource->mouseMove(x, y);
+ mMediaSource->mouseMove(x, y, mask);
gViewerWindow->setCursor(mMediaSource->getLastSetCursor());
}
@@ -205,7 +206,7 @@ BOOL LLMediaCtrl::handleHover( S32 x, S32 y, MASK mask )
BOOL LLMediaCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks )
{
if (mMediaSource && mMediaSource->hasMedia())
- mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, MASK_NONE);
+ mMediaSource->getMediaPlugin()->scrollEvent(0, clicks, gKeyboard->currentMask(TRUE));
return TRUE;
}
@@ -218,7 +219,7 @@ BOOL LLMediaCtrl::handleMouseUp( S32 x, S32 y, MASK mask )
if (mMediaSource)
{
- mMediaSource->mouseUp(x, y);
+ mMediaSource->mouseUp(x, y, mask);
// *HACK: LLMediaImplLLMozLib automatically takes focus on mouseup,
// in addition to the onFocusReceived() call below. Undo this. JC
@@ -241,7 +242,50 @@ BOOL LLMediaCtrl::handleMouseDown( S32 x, S32 y, MASK mask )
convertInputCoords(x, y);
if (mMediaSource)
- mMediaSource->mouseDown(x, y);
+ 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 );
@@ -260,7 +304,7 @@ BOOL LLMediaCtrl::handleDoubleClick( S32 x, S32 y, MASK mask )
convertInputCoords(x, y);
if (mMediaSource)
- mMediaSource->mouseLeftDoubleClick( x, y );
+ mMediaSource->mouseDoubleClick( x, y, mask);
gFocusMgr.setMouseCapture( this );
@@ -321,36 +365,9 @@ BOOL LLMediaCtrl::handleKeyHere( KEY key, MASK mask )
{
BOOL result = FALSE;
- // 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 (mMediaSource)
{
- 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->handleKeyHere(key, mask);
- }
+ result = mMediaSource->handleKeyHere(key, mask);
}
return result;
@@ -373,12 +390,9 @@ BOOL LLMediaCtrl::handleUnicodeCharHere(llwchar uni_char)
{
BOOL result = FALSE;
- // only accept 'printable' characters, sigh...
- if (uni_char >= 32 // discard 'control' characters
- && uni_char != 127) // SDL thinks this is 'delete' - yuck.
+ if (mMediaSource)
{
- if (mMediaSource)
- result = mMediaSource->handleUnicodeCharHere(uni_char);
+ result = mMediaSource->handleUnicodeCharHere(uni_char);
}
return result;
@@ -905,6 +919,18 @@ void LLMediaCtrl::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event)
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.
diff --git a/indra/newview/llmediactrl.h b/indra/newview/llmediactrl.h
index 5ea03f1e6c..76ddc61ebf 100644
--- a/indra/newview/llmediactrl.h
+++ b/indra/newview/llmediactrl.h
@@ -86,6 +86,8 @@ public:
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 );
diff --git a/indra/newview/llmediadataclient.cpp b/indra/newview/llmediadataclient.cpp
index 6a932d76bf..512104a2f4 100755
--- a/indra/newview/llmediadataclient.cpp
+++ b/indra/newview/llmediadataclient.cpp
@@ -34,15 +34,18 @@
#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 "llnotifications.h"
#include "llsdutil.h"
#include "llmediaentry.h"
#include "lltextureentry.h"
#include "llviewerregion.h"
-#include "llvovolume.h"
//
// When making a request
@@ -55,7 +58,9 @@
// - Any request that gets a 503 still goes through the retry logic
//
-// Some helpful logging macros
+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;
//////////////////////////////////////////////////////////////////////////////////////
//
@@ -66,7 +71,7 @@
LLMediaDataClient::Request::Request(const std::string &cap_name,
const LLSD& sd_payload,
- LLVOVolume *obj,
+ LLMediaDataClientObject *obj,
LLMediaDataClient *mdc)
: mCapName(cap_name),
mPayload(sd_payload),
@@ -79,38 +84,39 @@ LLMediaDataClient::Request::Request(const std::string &cap_name,
LLMediaDataClient::Request::~Request()
{
+ LL_DEBUGS("LLMediaDataClient") << "~Request" << (*this) << LL_ENDL;
mMDC = NULL;
- mObject = NULL;
+ mObject = NULL;
}
std::string LLMediaDataClient::Request::getCapability() const
{
- return getObject()->getRegion()->getCapability(getCapName());
+ 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 (mCapName == "ObjectMediaNavigate")
- {
- return NAVIGATE;
- }
- else if (mCapName == "ObjectMedia")
- {
- const std::string &verb = mPayload["verb"];
- if (verb == "GET")
- {
- return GET;
- }
- else if (verb == "UPDATE")
- {
- return UPDATE;
- }
- }
- llassert(false);
- return GET;
+ if (mCapName == "ObjectMediaNavigate")
+ {
+ return NAVIGATE;
+ }
+ else if (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
@@ -138,6 +144,17 @@ void LLMediaDataClient::Request::reEnqueue() const
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;
+}
+
std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::Request &r)
{
s << "<request>"
@@ -164,15 +181,21 @@ LLMediaDataClient::Responder::RetryTimer::RetryTimer(F32 time, Responder *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()
{
- // 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();
// Don't fire again
return TRUE;
}
@@ -191,35 +214,35 @@ LLMediaDataClient::Responder::Responder(const request_ptr_t &request)
LLMediaDataClient::Responder::~Responder()
{
- mRequest = NULL;
+ LL_DEBUGS("LLMediaDataClient") << "~Responder" << *(getRequest()) << LL_ENDL;
+ mRequest = NULL;
}
/*virtual*/
void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
{
- extern LLControlGroup gSavedSettings;
-
if (status == HTTP_SERVICE_UNAVAILABLE)
{
- F32 retry_timeout = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
- if (retry_timeout <= 0.0)
- {
- retry_timeout = (F32)UNAVAILABLE_RETRY_TIMER_DELAY;
- }
- LL_INFOS("LLMediaDataClient") << *mRequest << "got SERVICE_UNAVAILABLE...retrying in " << retry_timeout << " seconds" << LL_ENDL;
+ F32 retry_timeout = mRequest->getRetryTimerDelay();
mRequest->incRetryCount();
- // Start timer (instances are automagically tracked by
- // InstanceTracker<> and LLEventTimer)
- new RetryTimer(F32(retry_timeout/*secs*/), this);
+ 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_INFOS("LLMediaDataClient") << *mRequest << " error(" << msg << ")" << LL_ENDL;
- LLSD args;
- args["ERROR"] = msg;
- LLNotifications::instance().add("ObjectMediaFailure", args);
+ LL_WARNS("LLMediaDataClient") << *mRequest << " http error(" << msg << ")" << LL_ENDL;
}
}
@@ -227,7 +250,7 @@ void LLMediaDataClient::Responder::error(U32 status, const std::string& reason)
/*virtual*/
void LLMediaDataClient::Responder::result(const LLSD& content)
{
- LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_pretty_print_sd(content) << LL_ENDL;
+ LL_INFOS("LLMediaDataClient") << *mRequest << "result : " << ll_print_sd(content) << LL_ENDL;
}
@@ -256,29 +279,25 @@ bool LLMediaDataClient::Comparator::operator() (const request_ptr_t &o1, const r
// Calculate the scores for each.
F64 o1_score = Comparator::getObjectScore(o1->getObject());
F64 o2_score = Comparator::getObjectScore(o2->getObject());
-
- return ( o1_score > o2_score );
+
+ // XXX Weird: a higher score should go earlier, but by observation I notice
+ // that this causes further-away objects load first. This is counterintuitive
+ // to the priority_queue Comparator, which states that this function should
+ // return 'true' if o1 should be *before* o2.
+ // In other words, I'd have expected that the following should return
+ // ( o1_score > o2_score).
+ return ( o1_score < o2_score );
}
// static
-F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj)
+F64 LLMediaDataClient::Comparator::getObjectScore(const LLMediaDataClientObject::ptr_t &obj)
{
// *TODO: make this less expensive?
- F32 dist = obj->getRenderPosition().length() + 0.1; // avoids div by 0
+ F64 dist = obj->getDistanceFromAvatar() + 0.1; // avoids div by 0
// square the distance so that they are in the same "unit magnitude" as
// the interest (which is an area)
dist *= dist;
- F64 interest = (F64)1;
- int i = 0;
- int end = obj->getNumTEs();
- for ( ; i < end; ++i)
- {
- const viewer_media_t &impl = obj->getMediaImpl(i);
- if (!impl.isNull())
- {
- interest += impl->getInterest();
- }
- }
+ F64 interest = obj->getTotalMediaInterest() + 1.0;
return interest/dist;
}
@@ -286,7 +305,7 @@ F64 LLMediaDataClient::Comparator::getObjectScore(const ll_vo_volume_ptr_t &obj)
//////////////////////////////////////////////////////////////////////////////////////
//
// LLMediaDataClient::PriorityQueue
-// Queue of LLVOVolume smart pointers to request media for.
+// Queue of LLMediaDataClientObject smart pointers to request media for.
//
//////////////////////////////////////////////////////////////////////////////////////
@@ -308,7 +327,7 @@ std::ostream& operator<<(std::ostream &s, const LLMediaDataClient::PriorityQueue
//////////////////////////////////////////////////////////////////////////////////////
//
// LLMediaDataClient::QueueTimer
-// Queue of LLVOVolume smart pointers to request media for.
+// Queue of LLMediaDataClientObject smart pointers to request media for.
//
//////////////////////////////////////////////////////////////////////////////////////
@@ -320,6 +339,7 @@ LLMediaDataClient::QueueTimer::QueueTimer(F32 time, LLMediaDataClient *mdc)
LLMediaDataClient::QueueTimer::~QueueTimer()
{
+ LL_DEBUGS("LLMediaDataClient") << "~QueueTimer" << LL_ENDL;
mMDC->setIsRunning(false);
mMDC = NULL;
}
@@ -342,15 +362,16 @@ BOOL LLMediaDataClient::QueueTimer::tick()
return TRUE;
}
- LL_DEBUGS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
+ LL_INFOS("LLMediaDataClient") << "QueueTimer::tick() started, queue is: " << queue << LL_ENDL;
// Peel one off of the items from the queue, and execute request
request_ptr_t request = queue.top();
llassert(!request.isNull());
- const ll_vo_volume_ptr_t &object = request->getObject();
+ const LLMediaDataClientObject *object = (request.isNull()) ? NULL : request->getObject();
bool performed_request = false;
- llassert(!object.isNull());
- if (!object.isNull() && object->hasMedia())
+ bool error = false;
+ llassert(NULL != object);
+ if (NULL != object && object->hasMedia())
{
std::string url = request->getCapability();
if (!url.empty())
@@ -367,17 +388,27 @@ BOOL LLMediaDataClient::QueueTimer::tick()
}
}
else {
- if (!object->hasMedia())
+ if (request.isNull())
+ {
+ LL_WARNS("LLMediaDataClient") << "Not Sending request: NULL request!" << LL_ENDL;
+ }
+ else if (NULL == object)
{
- LL_INFOS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
+ LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " NULL object!" << LL_ENDL;
}
+ else if (!object->hasMedia())
+ {
+ LL_WARNS("LLMediaDataClient") << "Not Sending request for " << *request << " hasMedia() is false!" << LL_ENDL;
+ }
+ error = true;
}
- bool exceeded_retries = request->getRetryCount() > LLMediaDataClient::MAX_RETRIES;
- if (performed_request || exceeded_retries) // Try N times before giving up
+ bool exceeded_retries = request->getRetryCount() > mMDC->mMaxNumRetries;
+ if (performed_request || exceeded_retries || error) // Try N times before giving up
{
if (exceeded_retries)
{
- LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for " << LLMediaDataClient::MAX_RETRIES << " tries...popping object id " << object->getID() << LL_ENDL;
+ LL_WARNS("LLMediaDataClient") << "Could not send request " << *request << " for "
+ << mMDC->mMaxNumRetries << " tries...popping object id " << object->getID() << LL_ENDL;
// XXX Should we bring up a warning dialog??
}
queue.pop();
@@ -394,15 +425,12 @@ void LLMediaDataClient::startQueueTimer()
{
if (! mQueueTimerIsRunning)
{
- extern LLControlGroup gSavedSettings;
- F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
- if (queue_timer_delay <= 0.0f)
- {
- queue_timer_delay = (F32)LLMediaDataClient::QUEUE_TIMER_DELAY;
- }
- LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << queue_timer_delay << " seconds)" << LL_ENDL;
+ LL_INFOS("LLMediaDataClient") << "starting queue timer (delay=" << mQueueTimerDelay << " seconds)" << LL_ENDL;
// LLEventTimer automagically takes care of the lifetime of this object
- new QueueTimer(queue_timer_delay, this);
+ new QueueTimer(mQueueTimerDelay, this);
+ }
+ else {
+ LL_DEBUGS("LLMediaDataClient") << "not starting queue timer (it's already running, right???)" << LL_ENDL;
}
}
@@ -411,9 +439,9 @@ void LLMediaDataClient::stopQueueTimer()
mQueueTimerIsRunning = false;
}
-void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload)
+void LLMediaDataClient::request(const LLMediaDataClientObject::ptr_t &object, const LLSD &payload)
{
- if (NULL == object || ! object->hasMedia()) return;
+ if (object.isNull() || ! object->hasMedia()) return;
// Push the object on the priority queue
enqueue(new Request(getCapabilityName(), payload, object, this));
@@ -422,8 +450,8 @@ void LLMediaDataClient::request(LLVOVolume *object, const LLSD &payload)
void LLMediaDataClient::enqueue(const Request *request)
{
LL_INFOS("LLMediaDataClient") << "Queuing request for " << *request << LL_ENDL;
- // Push the request on the priority queue
- // Sadly, we have to const-cast because items put into the queue are not const
+ // Push the request on the priority queue
+ // Sadly, we have to const-cast because items put into the queue are not const
pRequestQueue->push(const_cast<LLMediaDataClient::Request*>(request));
LL_DEBUGS("LLMediaDataClient") << "Queue:" << (*pRequestQueue) << LL_ENDL;
// Start the timer if not already running
@@ -436,21 +464,31 @@ void LLMediaDataClient::enqueue(const Request *request)
//
//////////////////////////////////////////////////////////////////////////////////////
-LLMediaDataClient::LLMediaDataClient()
+LLMediaDataClient::LLMediaDataClient(F32 queue_timer_delay,
+ F32 retry_timer_delay,
+ U32 max_retries)
+ : mQueueTimerDelay(queue_timer_delay),
+ mRetryTimerDelay(retry_timer_delay),
+ mMaxNumRetries(max_retries),
+ mQueueTimerIsRunning(false)
{
pRequestQueue = new PriorityQueue();
}
-
LLMediaDataClient::~LLMediaDataClient()
{
stopQueueTimer();
-
+
// This should clear the queue, and hopefully call all the destructors.
- while (! pRequestQueue->empty()) pRequestQueue->pop();
-
+ LL_DEBUGS("LLMediaDataClient") << "~LLMediaDataClient destructor: queue: " <<
+ (pRequestQueue->empty() ? "<empty> " : "<not empty> ") << (*pRequestQueue) << LL_ENDL;
delete pRequestQueue;
- pRequestQueue = NULL;
+ pRequestQueue = NULL;
+}
+
+bool LLMediaDataClient::isEmpty() const
+{
+ return (NULL == pRequestQueue) ? true : pRequestQueue->empty();
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -462,79 +500,78 @@ LLMediaDataClient::~LLMediaDataClient()
LLMediaDataClient::Responder *LLObjectMediaDataClient::createResponder(const request_ptr_t &request) const
{
- return new LLObjectMediaDataClient::Responder(request);
+ return new LLObjectMediaDataClient::Responder(request);
}
const char *LLObjectMediaDataClient::getCapabilityName() const
{
- return "ObjectMedia";
+ return "ObjectMedia";
}
-void LLObjectMediaDataClient::fetchMedia(LLVOVolume *object)
+void LLObjectMediaDataClient::fetchMedia(LLMediaDataClientObject *object)
{
- LLSD sd_payload;
- sd_payload["verb"] = "GET";
- sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
- request(object, sd_payload);
+ LLSD sd_payload;
+ sd_payload["verb"] = "GET";
+ sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ request(object, sd_payload);
}
-void LLObjectMediaDataClient::updateMedia(LLVOVolume *object)
+void LLObjectMediaDataClient::updateMedia(LLMediaDataClientObject *object)
{
- LLSD sd_payload;
- sd_payload["verb"] = "UPDATE";
- sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
- LLSD object_media_data;
- for (int i=0; i < object->getNumTEs(); i++) {
- LLTextureEntry *texture_entry = object->getTE(i);
- llassert((texture_entry->getMediaData() != NULL) == texture_entry->hasMedia());
- const LLSD &media_data =
- (texture_entry->getMediaData() == NULL) ? LLSD() : texture_entry->getMediaData()->asLLSD();
- object_media_data.append(media_data);
- }
- sd_payload[LLTextureEntry::OBJECT_MEDIA_DATA_KEY] = object_media_data;
-
- LL_INFOS("LLMediaDataClient") << "update media data: " << object->getID() << " " << ll_pretty_print_sd(sd_payload) << LL_ENDL;
-
- request(object, sd_payload);
+ 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_INFOS("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_INFOS("LLMediaDataClient") << *(getRequest()) << "GET returned: " << ll_pretty_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=" <<
+ const LLMediaDataClient::Request::Type type = getRequest()->getType();
+ llassert(type == LLMediaDataClient::Request::GET || type == LLMediaDataClient::Request::UPDATE)
+ if (type == LLMediaDataClient::Request::GET)
+ {
+ LL_INFOS("LLMediaDataClient") << *(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]);
- }
- }
- else if (type == LLMediaDataClient::Request::UPDATE)
- {
- // just do what our superclass does
- LLMediaDataClient::Responder::result(content);
- }
+
+ // 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]);
+ }
+ }
+ else if (type == LLMediaDataClient::Request::UPDATE)
+ {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
}
//////////////////////////////////////////////////////////////////////////////////////
@@ -545,21 +582,21 @@ void LLObjectMediaDataClient::Responder::result(const LLSD& content)
//////////////////////////////////////////////////////////////////////////////////////
LLMediaDataClient::Responder *LLObjectMediaNavigateClient::createResponder(const request_ptr_t &request) const
{
- return new LLObjectMediaNavigateClient::Responder(request);
+ return new LLObjectMediaNavigateClient::Responder(request);
}
const char *LLObjectMediaNavigateClient::getCapabilityName() const
{
- return "ObjectMediaNavigate";
+ return "ObjectMediaNavigate";
}
-void LLObjectMediaNavigateClient::navigate(LLVOVolume *object, U8 texture_index, const std::string &url)
+void LLObjectMediaNavigateClient::navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url)
{
- LLSD sd_payload;
- sd_payload[LLTextureEntry::OBJECT_ID_KEY] = object->getID();
+ 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;
- request(object, sd_payload);
+ request(object, sd_payload);
}
/*virtual*/
@@ -573,16 +610,18 @@ void LLObjectMediaNavigateClient::Responder::error(U32 status, const std::string
}
else {
// bounce the face back
- bounceBack();
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_DEBUGS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_pretty_print_sd(content) << LL_ENDL;
-
+ LL_INFOS("LLMediaDataClient") << *(getRequest()) << " NAVIGATE returned " << ll_print_sd(content) << LL_ENDL;
+
if (content.has("error"))
{
const LLSD &error = content["error"];
@@ -590,38 +629,19 @@ void LLObjectMediaNavigateClient::Responder::result(const LLSD& content)
if (ERROR_PERMISSION_DENIED_CODE == error_code)
{
- LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+ LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Navigation denied: bounce back" << LL_ENDL;
+ const LLSD &payload = getRequest()->getPayload();
// bounce the face back
- bounceBack();
+ getRequest()->getObject()->mediaNavigateBounceBack((LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY]);
}
else {
- LL_WARNS("LLMediaDataClient") << *(getRequest()) << " Error navigating: code=" <<
+ 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);
- }
-}
-
-
-void LLObjectMediaNavigateClient::Responder::bounceBack()
-{
- const LLSD &payload = getRequest()->getPayload();
- U8 texture_index = (U8)(LLSD::Integer)payload[LLTextureEntry::TEXTURE_INDEX_KEY];
- viewer_media_t impl = getRequest()->getObject()->getMediaImpl(texture_index);
- // Find the media entry for this navigate
- LLMediaEntry* mep = NULL;
- LLTextureEntry *te = getRequest()->getObject()->getTE(texture_index);
- if(te)
- {
- mep = te->getMediaData();
- }
-
- if (mep && impl)
- {
-// impl->navigateTo(mep->getCurrentURL());
- }
+ else {
+ // just do what our superclass does
+ LLMediaDataClient::Responder::result(content);
+ }
}
diff --git a/indra/newview/llmediadataclient.h b/indra/newview/llmediadataclient.h
index 59c4334251..9d0aa0981e 100755
--- a/indra/newview/llmediadataclient.h
+++ b/indra/newview/llmediadataclient.h
@@ -36,12 +36,36 @@
#include "llhttpclient.h"
#include <queue>
#include "llrefcount.h"
+#include "llpointer.h"
#include "lltimer.h"
-// Forward decls
-class LLVOVolume;
-typedef LLPointer<LLVOVolume> ll_vo_volume_ptr_t;
+// 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) = 0;
+ // Return the distance from the object to the avatar
+ virtual F64 getDistanceFromAvatar() const = 0;
+ // Return the total "interest" of the media (on-screen area)
+ virtual F64 getTotalMediaInterest() const = 0;
+ // Return the given cap url
+ virtual std::string getCapabilityUrl(const std::string &name) 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
@@ -50,15 +74,23 @@ class LLMediaDataClient : public LLRefCount
public:
LOG_CLASS(LLMediaDataClient);
- const static int QUEUE_TIMER_DELAY = 1; // seconds(s)
- const static int MAX_RETRIES = 4;
+ 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;
// Constructor
- LLMediaDataClient();
+ LLMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES);
// Make the request
- void request(LLVOVolume *object, const LLSD &payload);
-
+ 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;
+
protected:
// Destructor
virtual ~LLMediaDataClient(); // use unref
@@ -73,10 +105,10 @@ protected:
NAVIGATE
};
- Request(const std::string &cap_name, const LLSD& sd_payload, LLVOVolume *obj, LLMediaDataClient *mdc);
+ Request(const std::string &cap_name, const LLSD& sd_payload, LLMediaDataClientObject *obj, LLMediaDataClient *mdc);
const std::string &getCapName() const { return mCapName; }
const LLSD &getPayload() const { return mPayload; }
- LLVOVolume *getObject() const { return mObject; }
+ LLMediaDataClientObject *getObject() const { return mObject; }
U32 getNum() const { return mNum; }
@@ -92,6 +124,9 @@ protected:
// Re-enqueue thyself
void reEnqueue() const;
+ F32 getRetryTimerDelay() const;
+ U32 getMaxNumRetries() const;
+
public:
friend std::ostream& operator<<(std::ostream &s, const Request &q);
@@ -101,7 +136,7 @@ protected:
private:
std::string mCapName;
LLSD mPayload;
- ll_vo_volume_ptr_t mObject;
+ LLMediaDataClientObject::ptr_t mObject;
// Simple tracking
const U32 mNum;
static U32 sNum;
@@ -115,8 +150,6 @@ protected:
// Responder
class Responder : public LLHTTPClient::Responder
{
- static const int UNAVAILABLE_RETRY_TIMER_DELAY = 5; // secs
-
public:
Responder(const request_ptr_t &request);
//If we get back an error (not found, etc...), handle it here
@@ -163,9 +196,10 @@ private:
public:
bool operator() (const request_ptr_t &o1, const request_ptr_t &o2) const;
private:
- static F64 getObjectScore(const ll_vo_volume_ptr_t &obj);
+ static F64 getObjectScore(const LLMediaDataClientObject::ptr_t &obj);
};
+ // PriorityQueue
class PriorityQueue : public std::priority_queue<
request_ptr_t,
std::vector<request_ptr_t>,
@@ -193,6 +227,10 @@ private:
void startQueueTimer();
void stopQueueTimer();
void setIsRunning(bool val) { mQueueTimerIsRunning = val; }
+
+ const F32 mQueueTimerDelay;
+ const F32 mRetryTimerDelay;
+ const U32 mMaxNumRetries;
bool mQueueTimerIsRunning;
@@ -204,11 +242,15 @@ private:
class LLObjectMediaDataClient : public LLMediaDataClient
{
public:
- LLObjectMediaDataClient() {}
+ LLObjectMediaDataClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
~LLObjectMediaDataClient() {}
- void fetchMedia(LLVOVolume *object);
- void updateMedia(LLVOVolume *object);
+ void fetchMedia(LLMediaDataClientObject *object);
+ void updateMedia(LLMediaDataClientObject *object);
protected:
// Subclasses must override this factory method to return a new responder
@@ -230,14 +272,18 @@ protected:
// MediaDataResponder specific for the ObjectMediaNavigate cap
class LLObjectMediaNavigateClient : public LLMediaDataClient
{
+public:
// NOTE: from llmediaservice.h
static const int ERROR_PERMISSION_DENIED_CODE = 8002;
-public:
- LLObjectMediaNavigateClient() {}
+ LLObjectMediaNavigateClient(F32 queue_timer_delay = QUEUE_TIMER_DELAY,
+ F32 retry_timer_delay = UNAVAILABLE_RETRY_TIMER_DELAY,
+ U32 max_retries = MAX_RETRIES)
+ : LLMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries)
+ {}
~LLObjectMediaNavigateClient() {}
- void navigate(LLVOVolume *object, U8 texture_index, const std::string &url);
+ void navigate(LLMediaDataClientObject *object, U8 texture_index, const std::string &url);
protected:
// Subclasses must override this factory method to return a new responder
@@ -254,7 +300,7 @@ protected:
virtual void error(U32 status, const std::string& reason);
virtual void result(const LLSD &content);
private:
- void bounceBack();
+ void mediaNavigateBounceBack();
};
};
diff --git a/indra/newview/llmenucommands.cpp b/indra/newview/llmenucommands.cpp
index f61177d581..28ddaa61c4 100644
--- a/indra/newview/llmenucommands.cpp
+++ b/indra/newview/llmenucommands.cpp
@@ -47,7 +47,6 @@
#include "llviewercontrol.h"
#include "llfirstuse.h"
#include "llfloaterchat.h"
-#include "llfloaterdirectory.h"
#include "llfloaterworldmap.h"
#include "lllineeditor.h"
#include "llnotify.h"
@@ -67,7 +66,6 @@
#include "llfocusmgr.h"
#include "llnearbychatbar.h"
-
void handle_mouselook(void*)
{
gAgent.changeCameraToMouselook();
diff --git a/indra/newview/llmimetypes.cpp b/indra/newview/llmimetypes.cpp
index 525e89cdff..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"
diff --git a/indra/newview/llmoveview.cpp b/indra/newview/llmoveview.cpp
index 1bbcc3f98e..14da35594f 100644
--- a/indra/newview/llmoveview.cpp
+++ b/indra/newview/llmoveview.cpp
@@ -70,7 +70,7 @@ const std::string BOTTOM_TRAY_BUTTON_NAME = "movement_btn";
// protected
LLFloaterMove::LLFloaterMove(const LLSD& key)
-: LLDockableFloater(NULL, key),
+: LLTransientDockableFloater(NULL, true, key),
mForwardButton(NULL),
mBackwardButton(NULL),
mTurnLeftButton(NULL),
@@ -280,6 +280,14 @@ 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:
@@ -498,7 +506,13 @@ void LLFloaterMove::setDocked(bool docked, bool pop_on_undock/* = true*/)
{
LLDockableFloater::setDocked(docked, pop_on_undock);
bool show_mode_buttons = isDocked() || !gAgent.getFlying();
- updateHeight(show_mode_buttons);
+
+ if (!isMinimized())
+ {
+ updateHeight(show_mode_buttons);
+ }
+
+ LLTransientDockableFloater::setDocked(docked, pop_on_undock);
}
void LLFloaterMove::setModeButtonToggleState(const EMovementMode mode)
diff --git a/indra/newview/llmoveview.h b/indra/newview/llmoveview.h
index cbed36f10d..cee6078ee9 100644
--- a/indra/newview/llmoveview.h
+++ b/indra/newview/llmoveview.h
@@ -34,7 +34,7 @@
#define LL_LLMOVEVIEW_H
// Library includes
-#include "lldockablefloater.h"
+#include "lltransientdockablefloater.h"
class LLButton;
class LLJoystickAgentTurn;
@@ -44,7 +44,7 @@ class LLJoystickAgentSlide;
// Classes
//
class LLFloaterMove
-: public LLDockableFloater
+: public LLTransientDockableFloater
{
friend class LLFloaterReg;
diff --git a/indra/newview/llmutelist.cpp b/indra/newview/llmutelist.cpp
index b47d6f4214..36cf2c1aa8 100644
--- a/indra/newview/llmutelist.cpp
+++ b/indra/newview/llmutelist.cpp
@@ -65,7 +65,6 @@
#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"
@@ -530,6 +529,8 @@ void notify_automute_callback(const LLUUID& agent_id, const std::string& first_n
{
timp->addHistoryLine(message);
}
+
+ LLIMModel::getInstance()->addMessage(agent_id, SYSTEM_FROM, LLUUID::null, message);
}
LLChat auto_chat(message);
diff --git a/indra/newview/llmutelist.h b/indra/newview/llmutelist.h
index dec8d7576e..409b637bf2 100644
--- a/indra/newview/llmutelist.h
+++ b/indra/newview/llmutelist.h
@@ -153,7 +153,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
diff --git a/indra/newview/llnavigationbar.cpp b/indra/newview/llnavigationbar.cpp
index 19fee20740..4f145891ea 100644
--- a/indra/newview/llnavigationbar.cpp
+++ b/indra/newview/llnavigationbar.cpp
@@ -50,6 +50,7 @@
#include "llslurl.h"
#include "llurlsimstring.h"
#include "llviewerinventory.h"
+#include "llviewermenu.h"
#include "llviewerparcelmgr.h"
#include "llworldmap.h"
#include "llappviewer.h"
@@ -164,17 +165,6 @@ TODO:
- Load navbar height from saved settings (as it's done for status bar) or think of a better way.
*/
-S32 NAVIGATION_BAR_HEIGHT = 60; // *HACK
-LLNavigationBar* LLNavigationBar::sInstance = 0;
-
-LLNavigationBar* LLNavigationBar::getInstance()
-{
- if (!sInstance)
- sInstance = new LLNavigationBar();
-
- return sInstance;
-}
-
LLNavigationBar::LLNavigationBar()
: mTeleportHistoryMenu(NULL),
mBtnBack(NULL),
@@ -184,8 +174,6 @@ LLNavigationBar::LLNavigationBar()
mSearchComboBox(NULL),
mPurgeTPHistoryItems(false)
{
- setIsChrome(TRUE);
-
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_navigation_bar.xml");
// set a listener function for LoginComplete event
@@ -198,8 +186,6 @@ LLNavigationBar::LLNavigationBar()
LLNavigationBar::~LLNavigationBar()
{
mTeleportFinishConnection.disconnect();
- sInstance = 0;
-
LLSearchHistory::getInstance()->save();
}
@@ -272,9 +258,30 @@ void LLNavigationBar::draw()
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();
@@ -521,8 +528,8 @@ void LLNavigationBar::showTeleportHistoryMenu()
// *TODO: why to draw/update anything before showing the menu?
mTeleportHistoryMenu->buildDrawLabels();
mTeleportHistoryMenu->updateParent(LLMenuGL::sMenuContainer);
- LLRect btnBackRect = mBtnBack->getRect();
- LLMenuGL::showPopup(this, mTeleportHistoryMenu, btnBackRect.mLeft, btnBackRect.mBottom);
+ 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 );
@@ -535,7 +542,7 @@ void LLNavigationBar::handleLoginComplete()
void LLNavigationBar::invokeSearch(std::string search_text)
{
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "all").insert("id", LLSD(search_text)));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "all").insert("id", LLSD(search_text)));
}
void LLNavigationBar::clearHistoryCache()
@@ -547,6 +554,15 @@ void LLNavigationBar::clearHistoryCache()
mPurgeTPHistoryItems= true;
}
+int LLNavigationBar::getDefNavBarHeight()
+{
+ return mDefaultNbRect.getHeight();
+}
+int LLNavigationBar::getDefFavBarHeight()
+{
+ return mDefaultFpRect.getHeight();
+}
+
void LLNavigationBar::showNavigationPanel(BOOL visible)
{
bool fpVisible = gSavedSettings.getBOOL("ShowNavbarFavoritesPanel");
@@ -613,6 +629,9 @@ void LLNavigationBar::showNavigationPanel(BOOL visible)
}
}
+ childSetVisible("bg_icon", fpVisible);
+ childSetVisible("bg_icon_no_fav", !fpVisible);
+
if(LLSideTray::instanceCreated())
{
LLSideTray::getInstance()->resetPanelRect();
@@ -677,6 +696,9 @@ void LLNavigationBar::showFavoritesPanel(BOOL visible)
setRect(nbRect);
}
+ childSetVisible("bg_icon", visible);
+ childSetVisible("bg_icon_no_fav", !visible);
+
fb->setVisible(visible);
if(LLSideTray::instanceCreated())
{
diff --git a/indra/newview/llnavigationbar.h b/indra/newview/llnavigationbar.h
index 8a65cd24fa..52f5a827e4 100644
--- a/indra/newview/llnavigationbar.h
+++ b/indra/newview/llnavigationbar.h
@@ -35,8 +35,6 @@
#include "llpanel.h"
-extern S32 NAVIGATION_BAR_HEIGHT;
-
class LLButton;
class LLLocationInputCtrl;
class LLMenuGL;
@@ -47,15 +45,16 @@ class LLSearchComboBox;
* Web browser-like navigation bar.
*/
class LLNavigationBar
-: public LLPanel
+ : public LLPanel, public LLSingleton<LLNavigationBar>
{
LOG_CLASS(LLNavigationBar);
-
+
public:
- static LLNavigationBar* getInstance();
+ LLNavigationBar();
virtual ~LLNavigationBar();
/*virtual*/ void draw();
+ /*virtual*/ BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
/*virtual*/ BOOL postBuild();
void handleLoginComplete();
@@ -63,9 +62,11 @@ public:
void showNavigationPanel(BOOL visible);
void showFavoritesPanel(BOOL visible);
+
+ int getDefNavBarHeight();
+ int getDefFavBarHeight();
private:
- LLNavigationBar();
void rebuildTeleportHistoryMenu();
void showTeleportHistoryMenu();
@@ -77,7 +78,6 @@ private:
void onBackOrForwardButtonHeldDown(const LLSD& param);
void onForwardButtonClicked();
void onHomeButtonClicked();
- void onHelpButtonClicked();
void onLocationSelection();
void onLocationPrearrange(const LLSD& data);
void onSearchCommit();
@@ -91,8 +91,6 @@ private:
void fillSearchComboBox();
- static LLNavigationBar *sInstance;
-
LLMenuGL* mTeleportHistoryMenu;
LLButton* mBtnBack;
LLButton* mBtnForward;
diff --git a/indra/newview/llnearbychat.cpp b/indra/newview/llnearbychat.cpp
index 91862112a0..974291a54e 100644
--- a/indra/newview/llnearbychat.cpp
+++ b/indra/newview/llnearbychat.cpp
@@ -48,25 +48,23 @@
#include "llnearbychathandler.h"
#include "llchannelmanager.h"
-//for LLViewerTextEditor support
#include "llagent.h" // gAgent
#include "llfloaterscriptdebug.h"
-#include "llslurl.h"
-#include "llviewertexteditor.h"
+#include "llchathistory.h"
#include "llstylemap.h"
#include "lldraghandle.h"
-
+#include "lltrans.h"
+#include "llbottomtray.h"
+#include "llnearbychatbar.h"
static const S32 RESIZE_BAR_THICKNESS = 3;
-LLNearbyChat::LLNearbyChat(const LLSD& key) :
- LLFloater(key),
- mEChatTearofState(CHAT_PINNED),
- mChatCaptionPanel(NULL),
- mChatHistoryEditor(NULL)
+LLNearbyChat::LLNearbyChat(const LLSD& key)
+ : LLDockableFloater(NULL, false, key)
+ ,mChatHistory(NULL)
{
- m_isDirty = false;
+
}
LLNearbyChat::~LLNearbyChat()
@@ -75,25 +73,6 @@ LLNearbyChat::~LLNearbyChat()
BOOL LLNearbyChat::postBuild()
{
- //resize bars
- setCanResize(true);
-
- mResizeBar[LLResizeBar::BOTTOM]->setVisible(false);
- mResizeBar[LLResizeBar::LEFT]->setVisible(false);
- mResizeBar[LLResizeBar::RIGHT]->setVisible(false);
-
- mResizeBar[LLResizeBar::BOTTOM]->setResizeLimits(120,500);
- mResizeBar[LLResizeBar::TOP]->setResizeLimits(120,500);
- mResizeBar[LLResizeBar::LEFT]->setResizeLimits(220,600);
- mResizeBar[LLResizeBar::RIGHT]->setResizeLimits(220,600);
-
- mResizeHandle[0]->setVisible(false);
- mResizeHandle[1]->setVisible(false);
- mResizeHandle[2]->setVisible(false);
- mResizeHandle[3]->setVisible(false);
-
- getDragHandle()->setVisible(false);
-
//menu
LLUICtrl::CommitCallbackRegistry::ScopedRegistrar registrar;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
@@ -103,21 +82,56 @@ BOOL LLNearbyChat::postBuild()
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);
- mChatCaptionPanel = getChild<LLPanel>("chat_caption", false);
- mChatHistoryEditor = getChild<LLViewerTextEditor>("Chat History Editor");
+ mChatHistory = getChild<LLChatHistory>("chat_history");
- reshape(getRect().getWidth(), getRect().getHeight(), FALSE);
-
- return LLFloater::postBuild();
+ setCanResize(true);
+
+ if(!LLDockableFloater::postBuild())
+ return false;
+
+ if (getDockControl() == NULL)
+ {
+ setDockControl(new LLDockControl(
+ LLBottomTray::getInstance()->getNearbyChatBar(), this,
+ getDockTongue(), LLDockControl::LEFT, boost::bind(&LLNearbyChat::getAllowedRect, this, _1)));
+ }
+
+ 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);
+ }
+ }
+}
+
LLColor4 nearbychat_get_text_color(const LLChat& chat)
{
LLColor4 text_color;
@@ -185,44 +199,6 @@ LLColor4 nearbychat_get_text_color(const LLChat& chat)
void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& color)
{
- std::string line = chat.mText;
-
- //chat.mText starts with Avatar Name if entered message was "/me <action>".
- // In this case output chat message should be "<Avatar Name> <action>". See EXT-656
- // See also process_chat_from_simulator() in the llviewermessage.cpp where ircstyle = TRUE;
- if (CHAT_STYLE_IRC != chat.mChatStyle)
- line = chat.mFromName + ": " + line;
-
- bool prepend_newline = true;
- if (gSavedSettings.getBOOL("ChatShowTimestamps"))
- {
- mChatHistoryEditor->appendTime(prepend_newline);
- prepend_newline = false;
- }
-
- // If the msg is from an agent (not yourself though),
- // extract out the sender name and replace it with the hotlinked name.
-
- std::string str_URL = chat.mURL;
-
- if (chat.mSourceType == CHAT_SOURCE_AGENT &&
- chat.mFromID != LLUUID::null)
- {
- str_URL = LLSLURL::buildCommand("agent", chat.mFromID, "inspect");
- }
-
- // If the chat line has an associated url, link it up to the name.
- if (!str_URL.empty()
- && (line.length() > chat.mFromName.length() && line.find(chat.mFromName,0) == 0))
- {
- std::string start_line = line.substr(0, chat.mFromName.length() + 1);
- line = line.substr(chat.mFromName.length() + 1);
- mChatHistoryEditor->appendText(start_line, prepend_newline,
- LLStyleMap::instance().lookup(chat.mFromID,str_URL));
- mChatHistoryEditor->blockUndo();
- prepend_newline = false;
- }
-
S32 font_size = gSavedSettings.getS32("ChatFontSize");
const LLFontGL* fontp = NULL;
@@ -240,23 +216,29 @@ void LLNearbyChat::add_timestamped_line(const LLChat& chat, const LLColor4& colo
break;
}
- mChatHistoryEditor->appendText(line, prepend_newline, LLStyle::Params().color(color).font(fontp));
- mChatHistoryEditor->blockUndo();
+ LLStyle::Params style_params;
+ style_params.color(color);
+ style_params.font(fontp);
+ LLUUID uuid = chat.mFromID;
+ std::string from = chat.mFromName;
+ std::string message = chat.mText;
+ mChatHistory->appendWidgetMessage(chat, style_params);
}
void LLNearbyChat::addMessage(const LLChat& chat)
{
LLColor4 color = nearbychat_get_text_color(chat);
-
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)// show error in window //("ScriptErrorsAsChat"))
{
+ LLFloaterScriptDebug::addScriptLine(chat.mText,
+ chat.mFromName,
+ color,
+ chat.mFromID);
return;
}
}
@@ -273,193 +255,6 @@ void LLNearbyChat::onNearbySpeakers()
LLSideTray::getInstance()->showPanel("panel_people",param);
}
-void LLNearbyChat::onTearOff()
-{
- if(mEChatTearofState == CHAT_PINNED)
- float_panel();
- else
- pinn_panel();
-}
-
-void LLNearbyChat::reshape(S32 width, S32 height, BOOL called_from_parent)
-{
-
- LLFloater::reshape(width, height, called_from_parent);
-
- LLRect resize_rect;
- resize_rect.setLeftTopAndSize( 0, height, width, RESIZE_BAR_THICKNESS);
- if (mResizeBar[LLResizeBar::TOP])
- {
- mResizeBar[LLResizeBar::TOP]->reshape(width,RESIZE_BAR_THICKNESS);
- mResizeBar[LLResizeBar::TOP]->setRect(resize_rect);
- }
-
- resize_rect.setLeftTopAndSize( 0, RESIZE_BAR_THICKNESS, width, RESIZE_BAR_THICKNESS);
- if (mResizeBar[LLResizeBar::BOTTOM])
- {
- mResizeBar[LLResizeBar::BOTTOM]->reshape(width,RESIZE_BAR_THICKNESS);
- mResizeBar[LLResizeBar::BOTTOM]->setRect(resize_rect);
- }
-
- resize_rect.setLeftTopAndSize( 0, height, RESIZE_BAR_THICKNESS, height);
- if (mResizeBar[LLResizeBar::LEFT])
- {
- mResizeBar[LLResizeBar::LEFT]->reshape(RESIZE_BAR_THICKNESS,height);
- mResizeBar[LLResizeBar::LEFT]->setRect(resize_rect);
- }
-
- resize_rect.setLeftTopAndSize( width - RESIZE_BAR_THICKNESS, height, RESIZE_BAR_THICKNESS, height);
- if (mResizeBar[LLResizeBar::RIGHT])
- {
- mResizeBar[LLResizeBar::RIGHT]->reshape(RESIZE_BAR_THICKNESS,height);
- mResizeBar[LLResizeBar::RIGHT]->setRect(resize_rect);
- }
-
- // *NOTE: we must check mChatCaptionPanel and mChatHistoryEditor against NULL because reshape is called from the
- // LLView::initFromParams BEFORE postBuild is called and child controls are not exist yet
- LLRect caption_rect;
- if (NULL != mChatCaptionPanel)
- {
- caption_rect = mChatCaptionPanel->getRect();
- caption_rect.setLeftTopAndSize( 2, height - RESIZE_BAR_THICKNESS, width - 4, caption_rect.getHeight());
- mChatCaptionPanel->reshape( width - 4, caption_rect.getHeight(), 1);
- mChatCaptionPanel->setRect(caption_rect);
- }
-
- if (NULL != mChatHistoryEditor)
- {
- LLRect scroll_rect = mChatHistoryEditor->getRect();
- scroll_rect.setLeftTopAndSize( 2, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS, width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2);
- mChatHistoryEditor->reshape( width - 4, height - caption_rect.getHeight() - RESIZE_BAR_THICKNESS*2, 1);
- mChatHistoryEditor->setRect(scroll_rect);
- }
-
- //
- if(mEChatTearofState == CHAT_PINNED)
- {
- const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
-
- LLRect panel_rect;
- panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+height+4, width, height);
- setRect(panel_rect);
- }
- else
- {
- LLRect panel_rect;
- panel_rect.setLeftTopAndSize( getRect().mLeft, getRect().mTop, width, height);
- setRect(panel_rect);
- }
-
-}
-
-BOOL LLNearbyChat::handleMouseDown (S32 x, S32 y, MASK mask)
-{
- LLUICtrl* nearby_speakers_btn = mChatCaptionPanel->getChild<LLUICtrl>("nearby_speakers_btn");
- LLUICtrl* tearoff_btn = mChatCaptionPanel->getChild<LLUICtrl>("tearoff_btn");
- LLUICtrl* close_btn = mChatCaptionPanel->getChild<LLUICtrl>("close_btn");
-
- S32 caption_local_x = x - mChatCaptionPanel->getRect().mLeft;
- S32 caption_local_y = y - mChatCaptionPanel->getRect().mBottom;
-
- S32 local_x = caption_local_x - nearby_speakers_btn->getRect().mLeft;
- S32 local_y = caption_local_y - nearby_speakers_btn->getRect().mBottom;
- if(nearby_speakers_btn->pointInView(local_x, local_y))
- {
-
- onNearbySpeakers();
- bringToFront( x, y );
- return true;
- }
- local_x = caption_local_x - tearoff_btn->getRect().mLeft;
- local_y = caption_local_y- tearoff_btn->getRect().mBottom;
- if(tearoff_btn->pointInView(local_x, local_y))
- {
- onTearOff();
- bringToFront( x, y );
- return true;
- }
-
- local_x = caption_local_x - close_btn->getRect().mLeft;
- local_y = caption_local_y - close_btn->getRect().mBottom;
- if(close_btn->pointInView(local_x, local_y))
- {
- setVisible(false);
- bringToFront( x, y );
- return true;
- }
-
- if(mEChatTearofState == CHAT_UNPINNED && mChatCaptionPanel->pointInView(caption_local_x, caption_local_y) )
- {
- //start draggind
- gFocusMgr.setMouseCapture(this);
- mStart_Y = y;
- mStart_X = x;
- bringToFront( x, y );
- return true;
- }
-
- return LLFloater::handleMouseDown(x,y,mask);
-}
-
-BOOL LLNearbyChat::handleMouseUp(S32 x, S32 y, MASK mask)
-{
- if( hasMouseCapture() )
- {
- // Release the mouse
- gFocusMgr.setMouseCapture( NULL );
- mStart_X = 0;
- mStart_Y = 0;
- return true;
- }
-
- return LLFloater::handleMouseUp(x,y,mask);
-}
-
-BOOL LLNearbyChat::handleHover(S32 x, S32 y, MASK mask)
-{
- if( hasMouseCapture() )
- {
- translate(x-mStart_X,y-mStart_Y);
- return true;
- }
- return LLFloater::handleHover(x,y,mask);
-}
-
-void LLNearbyChat::pinn_panel()
-{
- mEChatTearofState = CHAT_PINNED;
- LLIconCtrl* tearoff_btn = mChatCaptionPanel->getChild<LLIconCtrl>("tearoff_btn",false);
-
- tearoff_btn->setValue("Inv_Landmark");
-
- const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
-
- LLRect panel_rect;
- panel_rect.setLeftTopAndSize( parent_rect.mLeft+2, parent_rect.mBottom+getRect().getHeight()+4, getRect().getWidth(), getRect().getHeight());
- setRect(panel_rect);
-
- mResizeBar[LLResizeBar::BOTTOM]->setVisible(false);
- mResizeBar[LLResizeBar::LEFT]->setVisible(false);
- mResizeBar[LLResizeBar::RIGHT]->setVisible(false);
-
- getDragHandle()->setVisible(false);
-
-}
-
-void LLNearbyChat::float_panel()
-{
- mEChatTearofState = CHAT_UNPINNED;
- LLIconCtrl* tearoff_btn = mChatCaptionPanel->getChild<LLIconCtrl>("tearoff_btn", false);
-
- tearoff_btn->setValue("Inv_Landmark");
- mResizeBar[LLResizeBar::BOTTOM]->setVisible(true);
- mResizeBar[LLResizeBar::LEFT]->setVisible(true);
- mResizeBar[LLResizeBar::RIGHT]->setVisible(true);
-
- getDragHandle()->setVisible(true);
-
- translate(4,4);
-}
void LLNearbyChat::onNearbyChatContextMenuItemClicked(const LLSD& userdata)
{
@@ -472,23 +267,6 @@ bool LLNearbyChat::onNearbyChatCheckContextMenuItem(const LLSD& userdata)
return false;
}
-BOOL LLNearbyChat::handleRightMouseDown(S32 x, S32 y, MASK mask)
-{
- if(mChatCaptionPanel->pointInView(x - mChatCaptionPanel->getRect().mLeft, y - mChatCaptionPanel->getRect().mBottom) )
- {
- LLMenuGL* menu = (LLMenuGL*)mPopupMenuHandle.get();
-
- if(menu)
- {
- menu->buildDrawLabels();
- menu->updateParent(LLMenuGL::sMenuContainer);
- LLMenuGL::showPopup(this, menu, x, y);
- }
- return true;
- }
- return LLFloater::handleRightMouseDown(x, y, mask);
-}
-
void LLNearbyChat::onOpen(const LLSD& key )
{
LLNotificationsUI::LLScreenChannelBase* chat_channel = LLNotificationsUI::LLChannelManager::getInstance()->findChannelByID(LLUUID(gSavedSettings.getString("NearByChatChannelUUID")));
@@ -498,9 +276,21 @@ void LLNearbyChat::onOpen(const LLSD& key )
}
}
-void LLNearbyChat::draw ()
+void LLNearbyChat::setDocked (bool docked, bool pop_on_undock)
+{
+ LLDockableFloater::setDocked(docked, pop_on_undock);
+
+ setCanResize(!docked);
+}
+
+void LLNearbyChat::setRect (const LLRect &rect)
+{
+ LLDockableFloater::setRect(rect);
+}
+
+void LLNearbyChat::getAllowedRect(LLRect& rect)
{
- LLFloater::draw();
+ rect = gViewerWindow->getWorldViewRect();
}
diff --git a/indra/newview/llnearbychat.h b/indra/newview/llnearbychat.h
index 7c8ffa3b94..cb4654654a 100644
--- a/indra/newview/llnearbychat.h
+++ b/indra/newview/llnearbychat.h
@@ -33,65 +33,43 @@
#ifndef LL_LLNEARBYCHAT_H_
#define LL_LLNEARBYCHAT_H_
-#include "llfloater.h"
+#include "lldockablefloater.h"
#include "llscrollbar.h"
#include "llchat.h"
class LLResizeBar;
-class LLViewerTextEditor;
+class LLChatHistory;
-class LLNearbyChat: public LLFloater
+class LLNearbyChat: public LLDockableFloater
{
public:
- // enumerations used by the chat system
- typedef enum e_chat_tearof_state
- {
- CHAT_PINNED = 0,
- CHAT_UNPINNED = 1,
- } EChatTearofState;
-
- enum { RESIZE_BAR_COUNT=4 };
-
LLNearbyChat(const LLSD& key);
~LLNearbyChat();
BOOL postBuild ();
- void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
-
- BOOL handleMouseDown (S32 x, S32 y, MASK mask);
- BOOL handleMouseUp (S32 x, S32 y, MASK mask);
- BOOL handleHover (S32 x, S32 y, MASK mask);
-
- BOOL handleRightMouseDown(S32 x, S32 y, MASK mask);
-
void addMessage (const LLChat& message);
- void onNearbySpeakers ();
- void onTearOff();
-
void onNearbyChatContextMenuItemClicked(const LLSD& userdata);
bool onNearbyChatCheckContextMenuItem(const LLSD& userdata);
+ void setDocked (bool docked, bool pop_on_undock = true);
+
/*virtual*/ void onOpen (const LLSD& key);
- /*virtual*/ void draw ();
+ virtual void setRect (const LLRect &rect);
private:
+ virtual void applySavedVariables();
+
+ void getAllowedRect (LLRect& rect);
+
+ void onNearbySpeakers ();
void add_timestamped_line(const LLChat& chat, const LLColor4& color);
- void pinn_panel();
- void float_panel();
private:
- EChatTearofState mEChatTearofState;
- S32 mStart_X;
- S32 mStart_Y;
-
LLHandle<LLView> mPopupMenuHandle;
- LLPanel* mChatCaptionPanel;
- LLViewerTextEditor* mChatHistoryEditor;
-
- bool m_isDirty;
+ LLChatHistory* mChatHistory;
};
#endif
diff --git a/indra/newview/llnearbychatbar.cpp b/indra/newview/llnearbychatbar.cpp
index c2e1019f43..bcb4edd7c1 100644
--- a/indra/newview/llnearbychatbar.cpp
+++ b/indra/newview/llnearbychatbar.cpp
@@ -36,6 +36,7 @@
#include "lltrans.h"
#include "llnearbychatbar.h"
+#include "llspeakbutton.h"
#include "llbottomtray.h"
#include "llagent.h"
#include "llgesturemgr.h"
@@ -45,6 +46,7 @@
#include "llviewerstats.h"
#include "llcommandhandler.h"
#include "llviewercontrol.h"
+#include "llnavigationbar.h"
S32 LLNearbyChatBar::sLastSpecialChatChannel = 0;
@@ -76,6 +78,10 @@ LLGestureComboBox::LLGestureComboBox(const LLGestureComboBox::Params& p)
// refresh list from current active gestures
refreshGestures();
+
+ // This forces using of halign from xml, since LLComboBox
+ // sets it to LLFontGL::LEFT, if text entry is disabled
+ mButton->setHAlign(p.drop_down_button.font_halign);
}
LLGestureComboBox::~LLGestureComboBox()
@@ -177,10 +183,36 @@ void LLGestureComboBox::draw()
LLComboBox::draw();
}
+//virtual
+void LLGestureComboBox::showList()
+{
+ LLComboBox::showList();
+
+ // 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 list_bottom;
+ mList->localPointToScreen(0, 0, &x, &list_bottom);
+
+ S32 max_height = nb_bottom - list_bottom;
+
+ LLRect rect = mList->getRect();
+ // List overlapped navigation bar, downsize it
+ if (rect.getHeight() > max_height)
+ {
+ rect.setOriginAndSize(rect.mLeft, rect.mBottom, rect.getWidth(), max_height);
+ mList->setRect(rect);
+ mList->reshape(rect.getWidth(), rect.getHeight());
+ }
+}
+
LLNearbyChatBar::LLNearbyChatBar()
: LLPanel()
, mChatBox(NULL)
{
+ mSpeakerMgr = LLLocalSpeakerMgr::getInstance();
}
//virtual
@@ -192,22 +224,21 @@ BOOL LLNearbyChatBar::postBuild()
mChatBox->setKeystrokeCallback(&onChatBoxKeystroke, this);
mChatBox->setFocusLostCallback(boost::bind(&onChatBoxFocusLost, _1, this));
- mChatBox->setIgnoreArrowKeys(TRUE);
+ mChatBox->setIgnoreArrowKeys( FALSE );
mChatBox->setCommitOnFocusLost( FALSE );
mChatBox->setRevertOnEsc( FALSE );
mChatBox->setIgnoreTab(TRUE);
mChatBox->setPassDelete(TRUE);
mChatBox->setReplaceNewlinesWithSpaces(FALSE);
- mChatBox->setMaxTextLength(1023);
mChatBox->setEnableLineHistory(TRUE);
mOutputMonitor = getChild<LLOutputMonitorCtrl>("chat_zone_indicator");
mOutputMonitor->setVisible(FALSE);
- mTalkBtn = getChild<LLTalkButton>("talk");
+ mSpeakBtn = getParent()->getChild<LLSpeakButton>("talk");
// Speak button should be initially disabled because
// it takes some time between logging in to world and connecting to voice channel.
- mTalkBtn->setEnabled(FALSE);
+ mSpeakBtn->setEnabled(FALSE);
// Registering Chat Bar to receive Voice client status change notifications.
gVoiceClient->addObserver(this);
@@ -229,6 +260,16 @@ bool LLNearbyChatBar::instanceExists()
void LLNearbyChatBar::draw()
{
+ LLRect rect = getRect();
+ S32 max_width = getMaxWidth();
+
+ if (rect.getWidth() > max_width)
+ {
+ rect.setLeftTopAndSize(rect.mLeft, rect.mTop, max_width, rect.getHeight());
+ reshape(rect.getWidth(), rect.getHeight(), FALSE);
+ setRect(rect);
+ }
+
displaySpeakingIndicator();
LLPanel::draw();
}
@@ -254,6 +295,32 @@ BOOL LLNearbyChatBar::handleKeyHere( KEY key, MASK mask )
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();
@@ -455,8 +522,8 @@ void LLNearbyChatBar::displaySpeakingIndicator()
LLUUID id;
id.setNull();
- mSpeakerMgr.update(TRUE);
- mSpeakerMgr.getSpeakerList(&speaker_list, FALSE);
+ mSpeakerMgr->update(TRUE);
+ mSpeakerMgr->getSpeakerList(&speaker_list, FALSE);
for (LLSpeakerMgr::speaker_list_t::iterator i = speaker_list.begin(); i != speaker_list.end(); ++i)
{
@@ -630,7 +697,7 @@ LLWString LLNearbyChatBar::stripChannelNumber(const LLWString &mesg, S32* channe
void LLNearbyChatBar::setPTTState(bool state)
{
- mTalkBtn->setSpeakBtnToggleState(state);
+ mSpeakBtn->setSpeakBtnToggleState(state);
}
void send_chat_from_viewer(const std::string& utf8_out_text, EChatType type, S32 channel)
@@ -686,7 +753,7 @@ void LLNearbyChatBar::onChange(EStatusType status, const std::string &channelURI
break;
}
- mTalkBtn->setEnabled(enable);
+ mSpeakBtn->setEnabled(enable);
}
// Creating the object registers with the dispatcher.
diff --git a/indra/newview/llnearbychatbar.h b/indra/newview/llnearbychatbar.h
index d6827315f2..aa25b6aa68 100644
--- a/indra/newview/llnearbychatbar.h
+++ b/indra/newview/llnearbychatbar.h
@@ -37,10 +37,13 @@
#include "llcombobox.h"
#include "llgesturemgr.h"
#include "llchat.h"
-#include "llchiclet.h"
#include "llvoiceclient.h"
#include "lloutputmonitorctrl.h"
-#include "llfloateractivespeakers.h"
+#include "llspeakers.h"
+
+
+class LLSpeakButton;
+
class LLGestureComboBox
: public LLComboBox
@@ -62,6 +65,9 @@ public:
virtual void changed() { refreshGestures(); }
protected:
+
+ virtual void showList();
+
LLFrameTimer mGestureLabelTimer;
std::vector<LLMultiGesture*> mGestures;
std::string mLabel;
@@ -97,6 +103,9 @@ public:
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;
+
/**
* Implements LLVoiceClientStatusObserver::onChange()
*/
@@ -119,9 +128,9 @@ protected:
static S32 sLastSpecialChatChannel;
LLLineEditor* mChatBox;
- LLTalkButton* mTalkBtn;
+ LLSpeakButton* mSpeakBtn;
LLOutputMonitorCtrl* mOutputMonitor;
- LLActiveSpeakerMgr mSpeakerMgr;
+ LLLocalSpeakerMgr* mSpeakerMgr;
};
#endif
diff --git a/indra/newview/llnearbychathandler.cpp b/indra/newview/llnearbychathandler.cpp
index 59b19b6dcb..8a8ad9d073 100644
--- a/indra/newview/llnearbychathandler.cpp
+++ b/indra/newview/llnearbychathandler.cpp
@@ -162,6 +162,8 @@ bool LLNearbyChatScreenChannel::createPoolToast()
LLToast::Params p;
p.panel = panel;
+ p.lifetime_secs = gSavedSettings.getS32("NearbyToastLifeTime");
+ p.fading_time_secs = gSavedSettings.getS32("NearbyToastFadingTime");
LLToast* toast = new LLToast(p);
@@ -188,6 +190,17 @@ void LLNearbyChatScreenChannel::addNotification(LLSD& 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();
@@ -225,7 +238,7 @@ void LLNearbyChatScreenChannel::showToastsBottom()
LLRect toast_rect;
S32 bottom = getRect().mBottom;
- S32 margin = gSavedSettings.getS32("ToastMargin");
+ S32 margin = gSavedSettings.getS32("ToastGap");
for(std::vector<LLToast*>::iterator it = m_active_toasts.begin(); it != m_active_toasts.end(); ++it)
{
@@ -249,8 +262,9 @@ void LLNearbyChatScreenChannel::showToastsBottom()
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;
}
}
@@ -315,6 +329,12 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
initChannel();
}
+ //only messages from AGENTS
+ if(CHAT_SOURCE_OBJECT == chat_msg.mSourceType)
+ {
+ return;//dn't show toast for messages from objects
+ }
+
LLUUID id;
id.generate();
@@ -330,6 +350,7 @@ void LLNearbyChatHandler::processChat(const LLChat& chat_msg)
notification["from_id"] = chat_msg.mFromID;
notification["time"] = chat_msg.mTime;
notification["source"] = (S32)chat_msg.mSourceType;
+ notification["chat_type"] = (S32)chat_msg.mChatType;
channel->addNotification(notification);
}
diff --git a/indra/newview/llnetmap.cpp b/indra/newview/llnetmap.cpp
index bd6e6cd0cb..b6b433c28f 100644
--- a/indra/newview/llnetmap.cpp
+++ b/indra/newview/llnetmap.cpp
@@ -65,21 +65,30 @@
static LLDefaultChildRegistry::Register<LLNetMap> r1("net_map");
-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 MAX_PRIM_RADIUS = 256.0f; // Don't try to draw giant mega-prims on the mini map
-LLNetMap::LLNetMap (const Params & p) :
- LLUICtrl (p),
- mScale(128.0f),
+LLNetMap::LLNetMap (const Params & p)
+: LLUICtrl (p),
mBackgroundColor (p.bg_color()),
- mRotateMap(FALSE)
+ 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(),
+ mRotateMap(FALSE),
+ mToolTipMsg()
{
- mObjectImageCenterGlobal = gAgent.getCameraPositionGlobal();
- mPixelsPerMeter = mScale / REGION_WIDTH_METERS;
}
LLNetMap::~LLNetMap()
diff --git a/indra/newview/llnetmap.h b/indra/newview/llnetmap.h
index 821c348835..5ebdd13384 100644
--- a/indra/newview/llnetmap.h
+++ b/indra/newview/llnetmap.h
@@ -38,12 +38,17 @@
#include "v3math.h"
#include "v3dmath.h"
#include "v4color.h"
-#include "llimage.h"
+#include "llpointer.h"
class LLColor4U;
class LLCoordGL;
+class LLImageRaw;
class LLTextBox;
-class LLViewerTexture ;
+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 LLUICtrl
{
diff --git a/indra/newview/llnotificationhandler.h b/indra/newview/llnotificationhandler.h
index cd4e640ec4..23998a0e5d 100644
--- a/indra/newview/llnotificationhandler.h
+++ b/indra/newview/llnotificationhandler.h
@@ -53,7 +53,8 @@ typedef enum e_notification_type
NT_GROUPCHAT,
NT_NEARBYCHAT,
NT_ALERT,
- NT_ALERTMODAL
+ NT_ALERTMODAL,
+ NT_OFFER
} ENotificationType;
/**
@@ -231,6 +232,27 @@ protected:
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);
+};
+
}
#endif
diff --git a/indra/newview/llnotificationmanager.cpp b/indra/newview/llnotificationmanager.cpp
index 81a6b32917..1083cf3634 100644
--- a/indra/newview/llnotificationmanager.cpp
+++ b/indra/newview/llnotificationmanager.cpp
@@ -63,6 +63,7 @@ void LLNotificationManager::init()
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));
@@ -70,6 +71,7 @@ void LLNotificationManager::init()
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()));
@@ -80,6 +82,7 @@ void LLNotificationManager::init()
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()));
}
//--------------------------------------------------------------------------
diff --git a/indra/newview/llnotificationofferhandler.cpp b/indra/newview/llnotificationofferhandler.cpp
new file mode 100644
index 0000000000..8e3a44682c
--- /dev/null
+++ b/indra/newview/llnotificationofferhandler.cpp
@@ -0,0 +1,153 @@
+/**
+ * @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 "llimview.h"
+#include "llimfloater.h"
+#include "llnotificationmanager.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->getWorldViewRect().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")
+ {
+ // add message to IM
+ LLUUID session_id = LLIMMgr::computeSessionID(IM_NOTHING_SPECIAL, notification->getPayload()["from_id"]);
+ if (!LLIMMgr::instance().hasSession(session_id))
+ {
+ // create session with faked type to avoid creating chicklets
+ session_id = LLIMMgr::instance().addSession(
+ notification->getSubstitutions()["NAME"], IM_NOTHING_SPECIAL,
+ notification->getPayload()["from_id"]);
+ }
+ LLIMMgr::instance().addMessage(session_id, LLUUID(),
+ notification->getSubstitutions()["NAME"],
+ notification->getMessage());
+
+ 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")
+ {
+ 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
index 070af432d6..dac7a4ca3a 100644
--- a/indra/newview/llnotificationscripthandler.cpp
+++ b/indra/newview/llnotificationscripthandler.cpp
@@ -37,6 +37,7 @@
#include "lltoastnotifypanel.h"
#include "llviewercontrol.h"
#include "llviewerwindow.h"
+#include "llnotificationmanager.h"
using namespace LLNotificationsUI;
@@ -129,7 +130,9 @@ void LLScriptHandler::onRejectToast(LLUUID& id)
{
LLNotificationPtr notification = LLNotifications::instance().find(id);
- if(notification)
+ if (notification
+ && LLNotificationManager::getInstance()->getHandlerForNotification(
+ notification->getType()) == this)
{
LLNotifications::instance().cancel(notification);
}
diff --git a/indra/newview/llnotificationtiphandler.cpp b/indra/newview/llnotificationtiphandler.cpp
index 5186a93569..543198c1d2 100644
--- a/indra/newview/llnotificationtiphandler.cpp
+++ b/indra/newview/llnotificationtiphandler.cpp
@@ -33,6 +33,8 @@
#include "llviewerprecompiledheaders.h" // must be first include
+#include "llfloaterreg.h"
+#include "llnearbychat.h"
#include "llnotificationhandler.h"
#include "lltoastnotifypanel.h"
#include "llviewercontrol.h"
@@ -84,11 +86,26 @@ bool LLTipHandler::processNotification(const LLSD& notify)
if(notify["sigtype"].asString() == "add" || notify["sigtype"].asString() == "change")
{
+ // archive message in nearby chat
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ LLChat chat_msg(notification->getMessage());
+ nearby_chat->addMessage(chat_msg);
+
+ // don't show toast if Nearby Chat is opened
+ if (nearby_chat->getVisible())
+ {
+ return true;
+ }
+ }
+
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;
diff --git a/indra/newview/lloutputmonitorctrl.cpp b/indra/newview/lloutputmonitorctrl.cpp
index 8bac9937f0..39381e3faa 100644
--- a/indra/newview/lloutputmonitorctrl.cpp
+++ b/indra/newview/lloutputmonitorctrl.cpp
@@ -80,7 +80,8 @@ LLOutputMonitorCtrl::LLOutputMonitorCtrl(const LLOutputMonitorCtrl::Params& p)
mImageLevel2(p.image_level_2),
mImageLevel3(p.image_level_3),
mAutoUpdate(p.auto_update),
- mSpeakerId(p.speaker_id)
+ mSpeakerId(p.speaker_id),
+ mIsAgentControl(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);
@@ -132,7 +133,14 @@ void LLOutputMonitorCtrl::draw()
if (getVisible() && mAutoUpdate && !mIsMuted && mSpeakerId.notNull())
{
setPower(gVoiceClient->getCurrentPower(mSpeakerId));
- setIsTalking(gVoiceClient->getIsSpeaking(mSpeakerId));
+ if(mIsAgentControl)
+ {
+ setIsTalking(gVoiceClient->getUserPTTState());
+ }
+ else
+ {
+ setIsTalking(gVoiceClient->getIsSpeaking(mSpeakerId));
+ }
}
LLPointer<LLUIImage> icon;
diff --git a/indra/newview/lloutputmonitorctrl.h b/indra/newview/lloutputmonitorctrl.h
index 7a7b8bc3a1..85ea552a57 100644
--- a/indra/newview/lloutputmonitorctrl.h
+++ b/indra/newview/lloutputmonitorctrl.h
@@ -81,6 +81,8 @@ public:
// 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);
@@ -100,6 +102,7 @@ private:
F32 mPower;
+ bool mIsAgentControl;
bool mIsMuted;
bool mIsTalking;
LLPointer<LLUIImage> mImageMute;
diff --git a/indra/newview/llpanelavatar.cpp b/indra/newview/llpanelavatar.cpp
index c543f85f22..6413d939f0 100644
--- a/indra/newview/llpanelavatar.cpp
+++ b/indra/newview/llpanelavatar.cpp
@@ -38,12 +38,12 @@
#include "llavatarconstants.h" // AVATAR_ONLINE
#include "llcallingcard.h"
#include "llcombobox.h"
-#include "lldateutil.h"
#include "llimview.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lltooldraganddrop.h"
#include "llscrollcontainer.h"
+#include "llavatariconctrl.h"
#include "llweb.h"
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
@@ -336,10 +336,10 @@ BOOL LLPanelAvatarProfile::postBuild()
childSetCommitCallback("share",(boost::bind(&LLPanelAvatarProfile::onShareButtonClick,this)),NULL);
LLTextureCtrl* pic = getChild<LLTextureCtrl>("2nd_life_pic");
- pic->setFallbackImageName("default_land_picture.j2c");
+ pic->setFallbackImageName("default_profile_picture.j2c");
pic = getChild<LLTextureCtrl>("real_world_pic");
- pic->setFallbackImageName("default_land_picture.j2c");
+ pic->setFallbackImageName("default_profile_picture.j2c");
resetControls();
resetData();
@@ -351,6 +351,8 @@ void LLPanelAvatarProfile::onOpen(const LLSD& key)
{
LLPanelProfileTab::onOpen(key);
+ mGroups.erase();
+
//Disable "Add Friend" button for friends.
childSetEnabled("add_friend", !LLAvatarActions::isFriend(getAvatarId()));
}
@@ -381,6 +383,7 @@ void LLPanelAvatarProfile::resetControls()
void LLPanelAvatarProfile::resetData()
{
+ mGroups.erase();
childSetValue("2nd_life_pic",LLUUID::null);
childSetValue("real_world_pic",LLUUID::null);
childSetValue("online_status",LLStringUtil::null);
@@ -428,11 +431,15 @@ void LLPanelAvatarProfile::processProfileProperties(const LLAvatarData* avatar_d
void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_groups)
{
- std::string groups;
+ // *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.
+
+ std::string groups = mGroups;
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();
- if(it_end != it)
+ if(groups.empty() && it_end != it)
{
groups = (*it).group_name;
++it;
@@ -443,12 +450,17 @@ void LLPanelAvatarProfile::processGroupProperties(const LLAvatarGroups* avatar_g
groups += ", ";
groups += group_data.group_name;
}
- childSetValue("sl_groups",groups);
+ mGroups = groups;
+ childSetValue("sl_groups",mGroups);
}
void LLPanelAvatarProfile::fillCommonData(const LLAvatarData* avatar_data)
{
- childSetValue("register_date", LLDateUtil::ageFromDate(avatar_data->born_on));
+ //remove avatar id from cache to get fresh info
+ LLAvatarIconIDCache::getInstance()->remove(avatar_data->avatar_id);
+
+
+ childSetValue("register_date", avatar_data->born_on );
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);
diff --git a/indra/newview/llpanelavatar.h b/indra/newview/llpanelavatar.h
index a03902caba..ae0b8e9844 100644
--- a/indra/newview/llpanelavatar.h
+++ b/indra/newview/llpanelavatar.h
@@ -173,6 +173,10 @@ protected:
void onCallButtonClick();
void onTeleportButtonClick();
void onShareButtonClick();
+
+private:
+
+ std::string mGroups;
};
/**
diff --git a/indra/newview/llpanelclassified.cpp b/indra/newview/llpanelclassified.cpp
index 7eaee92778..a29c9752e6 100644
--- a/indra/newview/llpanelclassified.cpp
+++ b/indra/newview/llpanelclassified.cpp
@@ -909,13 +909,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());
diff --git a/indra/newview/llpanelcontents.cpp b/indra/newview/llpanelcontents.cpp
index ea528a1df8..9d591ef43d 100644
--- a/indra/newview/llpanelcontents.cpp
+++ b/indra/newview/llpanelcontents.cpp
@@ -51,7 +51,7 @@
// project includes
#include "llagent.h"
#include "llfloaterbulkpermission.h"
-#include "llpanelinventory.h"
+#include "llpanelobjectinventory.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
@@ -59,6 +59,7 @@
#include "lltoolcomp.h"
#include "lltoolmgr.h"
#include "lltrans.h"
+#include "llviewerassettype.h"
#include "llviewerobject.h"
#include "llviewerregion.h"
#include "llviewerwindow.h"
@@ -89,14 +90,14 @@ BOOL LLPanelContents::postBuild()
childSetAction("button new script",&LLPanelContents::onClickNewScript, this);
childSetAction("button permissions",&LLPanelContents::onClickPermissions, this);
- mPanelInventory = getChild<LLPanelInventory>("contents_inventory");
+ mPanelInventoryObject = getChild<LLPanelObjectInventory>("contents_inventory");
return TRUE;
}
LLPanelContents::LLPanelContents()
: LLPanel(),
- mPanelInventory(NULL)
+ mPanelInventoryObject(NULL)
{
}
@@ -139,9 +140,9 @@ void LLPanelContents::refresh()
LLViewerObject* object = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(children_ok);
getState(object);
- if (mPanelInventory)
+ if (mPanelInventoryObject)
{
- mPanelInventory->refresh();
+ mPanelInventoryObject->refresh();
}
}
@@ -167,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,
diff --git a/indra/newview/llpanelcontents.h b/indra/newview/llpanelcontents.h
index bab980b524..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;
@@ -70,7 +75,7 @@ protected:
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/llpanelgroup.cpp b/indra/newview/llpanelgroup.cpp
index e2281743c9..61f2396168 100644
--- a/indra/newview/llpanelgroup.cpp
+++ b/indra/newview/llpanelgroup.cpp
@@ -33,19 +33,22 @@
#include "llpanelgroup.h"
+// Library includes
#include "llbutton.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 "llfloaterreg.h"
#include "llfloater.h"
+#include "llgroupactions.h"
#include "llagent.h"
-#include "llstatusbar.h" // can_afford_transaction()
#include "llsidetraypanelcontainer.h"
@@ -83,32 +86,14 @@ BOOL LLPanelGroupTab::postBuild()
return TRUE;
}
-
-
-void LLPanelGroupTab::handleClickHelp()
-{
- // Display the help text.
- std::string help_text( getHelpText() );
- if ( !help_text.empty() )
- {
- 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);
- }
-}
-
LLPanelGroup::LLPanelGroup()
-: LLPanel()
- ,LLGroupMgrObserver( LLUUID() )
- ,mAllowEdit(TRUE)
+: LLPanel(),
+ LLGroupMgrObserver( LLUUID() ),
+ mAllowEdit( TRUE )
{
// Set up the factory callbacks.
// Roles sub tabs
LLGroupMgr::getInstance()->addObserver(this);
-
}
@@ -247,6 +232,7 @@ void LLPanelGroup::onBackBtnClick()
}
}
+
void LLPanelGroup::onBtnCreate()
{
LLPanelGroupGeneral* panel_general = findChild<LLPanelGroupGeneral>("group_general_tab_panel");
@@ -274,46 +260,11 @@ void LLPanelGroup::onBtnApply(void* user_data)
LLPanelGroup* self = static_cast<LLPanelGroup*>(user_data);
self->apply();
}
+
void LLPanelGroup::onBtnJoin()
{
lldebugs << "joining group: " << mID << llendl;
-
- LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
-
- if (gdatap)
- {
- S32 cost = gdatap->mMembershipFee;
- LLSD args;
- args["COST"] = llformat("%d", cost);
- LLSD payload;
- payload["group_id"] = mID;
-
- if (can_afford_transaction(cost))
- {
- LLNotifications::instance().add("JoinGroupCanAfford", args, payload, LLPanelGroup::joinDlgCB);
- }
- else
- {
- LLNotifications::instance().add("JoinGroupCannotAfford", args, payload);
- }
- }
- else
- {
- llwarns << "LLGroupMgr::getInstance()->getGroupData(" << mID << ") was NULL" << llendl;
- }
-}
-bool LLPanelGroup::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;
+ LLGroupActions::join(mID);
}
void LLPanelGroup::onBtnCancel()
@@ -340,19 +291,33 @@ void LLPanelGroup::update(LLGroupChange gc)
if(gdatap)
{
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);
- LLButton* btn_join = getChild<LLButton>("btn_join");
bool join_btn_visible = !is_member && gdatap->mOpenEnrollment;
+
btn_join->setVisible(join_btn_visible);
+ join_text->setVisible(join_btn_visible);
+
if(join_btn_visible)
{
LLStringUtil::format_map_t string_args;
- string_args["[AMOUNT]"] = llformat("%d", gdatap->mMembershipFee);
- std::string fee_buff = getString("group_join_btn", string_args);
- btn_join->setLabelSelected(fee_buff);
- btn_join->setLabelUnselected(fee_buff);
+ 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);
}
}
}
@@ -361,6 +326,8 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
{
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;
@@ -371,7 +338,10 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
LLGroupMgrGroupData* gdatap = LLGroupMgr::getInstance()->getGroupData(mID);
if(gdatap)
+ {
childSetValue("group_name", gdatap->mName);
+ childSetToolTip("group_name",gdatap->mName);
+ }
LLButton* button_apply = findChild<LLButton>("btn_apply");
LLButton* button_refresh = findChild<LLButton>("btn_refresh");
@@ -429,16 +399,19 @@ void LLPanelGroup::setGroupID(const LLUUID& group_id)
getChild<LLUICtrl>("group_name")->setVisible(false);
getChild<LLUICtrl>("group_name_editor")->setVisible(true);
}
- else
+ else
{
- 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());
+ if(!is_same_id)
+ {
+ 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->canOpenClose(true);
tab_notices->canOpenClose(true);
diff --git a/indra/newview/llpanelgroup.h b/indra/newview/llpanelgroup.h
index 628e2389b6..306e6575fc 100644
--- a/indra/newview/llpanelgroup.h
+++ b/indra/newview/llpanelgroup.h
@@ -101,8 +101,6 @@ protected:
static void onBtnApply(void*);
static void onBtnRefresh(void*);
- static bool joinDlgCB(const LLSD& notification, const LLSD& response);
-
void reposButton(const std::string& name);
void reposButtons();
@@ -150,12 +148,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
- void handleClickHelp();
-
// This just connects the help button callback.
virtual BOOL postBuild();
@@ -173,11 +165,8 @@ public:
protected:
LLUUID mGroupID;
- std::string mHelpText;
-
BOOL mAllowEdit;
BOOL mHasModal;
-
};
#endif // LL_LLPANELGROUP_H
diff --git a/indra/newview/llpanelgroupgeneral.cpp b/indra/newview/llpanelgroupgeneral.cpp
index 0331fad60c..1c2875bf46 100644
--- a/indra/newview/llpanelgroupgeneral.cpp
+++ b/indra/newview/llpanelgroupgeneral.cpp
@@ -186,7 +186,7 @@ BOOL LLPanelGroupGeneral::postBuild()
}
mIncompleteMemberDataStr = getString("incomplete_member_data_str");
-
+
// If the group_id is null, then we are creating a new group
if (mGroupID.isNull())
{
@@ -476,8 +476,15 @@ 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;
+ LLNotifications::instance().add("GenericAlert", args);
+ }
+
+ return ret;
}
// static
diff --git a/indra/newview/llpanelgrouplandmoney.cpp b/indra/newview/llpanelgrouplandmoney.cpp
index e40fa19bb6..9023afc602 100644
--- a/indra/newview/llpanelgrouplandmoney.cpp
+++ b/indra/newview/llpanelgrouplandmoney.cpp
@@ -690,7 +690,7 @@ BOOL LLPanelGroupLandMoney::postBuild()
if ( mImplementationp->mGroupParcelsp )
{
- mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLButton::setEnabled, mImplementationp->mMapButtonp, true));
+ mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLPanelGroupLandMoney::onLandSelectionChanged, this));
mImplementationp->mGroupParcelsp->setCommitOnSelectionChange(true);
}
@@ -808,6 +808,11 @@ BOOL LLPanelGroupLandMoney::postBuild()
return LLPanelGroupTab::postBuild();
}
+void LLPanelGroupLandMoney::onLandSelectionChanged()
+{
+ mImplementationp->mMapButtonp->setEnabled( mImplementationp->mGroupParcelsp->getItemCount() > 0 );
+}
+
BOOL LLPanelGroupLandMoney::isVisibleByAgent(LLAgent* agentp)
{
return mAllowEdit && agentp->isInGroup(mGroupID);
@@ -1493,7 +1498,7 @@ void LLPanelGroupLandMoney::setGroupID(const LLUUID& id)
if ( mImplementationp->mGroupParcelsp )
{
- mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLButton::setEnabled, mImplementationp->mMapButtonp, true));
+ mImplementationp->mGroupParcelsp->setCommitCallback(boost::bind(&LLPanelGroupLandMoney::onLandSelectionChanged, this));
mImplementationp->mGroupParcelsp->setCommitOnSelectionChange(true);
}
diff --git a/indra/newview/llpanelgrouplandmoney.h b/indra/newview/llpanelgrouplandmoney.h
index 0f275ea9a8..7e08d26d6f 100644
--- a/indra/newview/llpanelgrouplandmoney.h
+++ b/indra/newview/llpanelgrouplandmoney.h
@@ -60,6 +60,8 @@ public:
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 0ce85818dd..22138a81ec 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -38,6 +38,7 @@
#include "llinventory.h"
#include "llviewerinventory.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
#include "llfloaterinventory.h"
#include "llagent.h"
diff --git a/indra/newview/llpanelgrouproles.cpp b/indra/newview/llpanelgrouproles.cpp
index 71486c908c..88aad4923d 100644
--- a/indra/newview/llpanelgrouproles.cpp
+++ b/indra/newview/llpanelgrouproles.cpp
@@ -361,20 +361,6 @@ 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;
diff --git a/indra/newview/llpanelgrouproles.h b/indra/newview/llpanelgrouproles.h
index bd5fc1d235..b6e2245e70 100644
--- a/indra/newview/llpanelgrouproles.h
+++ b/indra/newview/llpanelgrouproles.h
@@ -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);
diff --git a/indra/newview/llpanelimcontrolpanel.cpp b/indra/newview/llpanelimcontrolpanel.cpp
index a7590ac1dd..c9168670d5 100644
--- a/indra/newview/llpanelimcontrolpanel.cpp
+++ b/indra/newview/llpanelimcontrolpanel.cpp
@@ -34,10 +34,77 @@
#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"
+
+void LLPanelChatControlPanel::onCallButtonClicked()
+{
+ gIMMgr->startCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onEndCallButtonClicked()
+{
+ gIMMgr->endCall(mSessionId);
+}
+
+void LLPanelChatControlPanel::onOpenVoiceControlsClicked()
+{
+ // TODO: implement Voice Control Panel opening
+}
+
+void LLPanelChatControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
+{
+ bool is_call_started = ( new_state >= LLVoiceChannel::STATE_CALL_STARTED );
+ childSetVisible("end_call_btn", is_call_started);
+ childSetVisible("voice_ctrls_btn", is_call_started);
+ childSetVisible("call_btn", ! is_call_started);
+}
+
+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));
+
+ return TRUE;
+}
+
+void LLPanelChatControlPanel::draw()
+{
+ // hide/show start call and end call buttons
+ bool voice_enabled = LLVoiceClient::voiceEnabled();
+
+ LLIMModel::LLIMSession* session = LLIMModel::getInstance()->findIMSession(mSessionId);
+ if (!session) return;
+
+ bool session_initialized = session->mSessionInitialized;
+ bool callback_enabled = session->mCallBackEnabled;
+ LLViewerRegion* region = gAgent.getRegion();
+
+ BOOL enable_connect = (region && region->getCapability("ChatSessionRequest") != "")
+ && session_initialized
+ && voice_enabled
+ && callback_enabled;
+ childSetEnabled("call_btn", enable_connect);
+
+ LLPanel::draw();
+}
+
+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)
+ voice_channel->setStateChangedCallback(boost::bind(&LLPanelChatControlPanel::onVoiceChannelStateChanged, this, _1, _2));
+}
LLPanelIMControlPanel::LLPanelIMControlPanel()
{
@@ -51,28 +118,36 @@ BOOL LLPanelIMControlPanel::postBuild()
{
childSetAction("view_profile_btn", boost::bind(&LLPanelIMControlPanel::onViewProfileButtonClicked, this));
childSetAction("add_friend_btn", boost::bind(&LLPanelIMControlPanel::onAddFriendButtonClicked, this));
- childSetAction("call_btn", boost::bind(&LLPanelIMControlPanel::onCallButtonClicked, 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 TRUE;
+
+
+ return LLPanelChatControlPanel::postBuild();
+}
+
+void LLPanelIMControlPanel::onTeleportButtonClicked()
+{
+ LLAvatarActions::offerTeleport(mAvatarID);
+}
+void LLPanelIMControlPanel::onPayButtonClicked()
+{
+ LLAvatarActions::pay(mAvatarID);
}
void LLPanelIMControlPanel::onViewProfileButtonClicked()
{
- LLAvatarActions::showProfile(getChild<LLAvatarIconCtrl>("avatar_icon")->getAvatarId());
+ 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(avatar_icon->getAvatarId(), full_name);
-}
-
-void LLPanelIMControlPanel::onCallButtonClicked()
-{
- // *TODO: Implement
+ LLAvatarActions::requestFriendshipDialog(mAvatarID, full_name);
}
void LLPanelIMControlPanel::onShareButtonClicked()
@@ -80,22 +155,67 @@ void LLPanelIMControlPanel::onShareButtonClicked()
// *TODO: Implement
}
-void LLPanelIMControlPanel::setID(const LLUUID& avatar_id)
+void LLPanelIMControlPanel::setSessionId(const LLUUID& session_id)
{
+ LLPanelChatControlPanel::setSessionId(session_id);
+
+ LLIMModel& im_model = LLIMModel::instance();
+
+ mAvatarID = im_model.getOtherParticipantID(session_id);
+
// Disable "Add friend" button for friends.
- childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(avatar_id));
+ childSetEnabled("add_friend_btn", !LLAvatarActions::isFriend(mAvatarID));
+
+ getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(mAvatarID);
- getChild<LLAvatarIconCtrl>("avatar_icon")->setValue(avatar_id);
+ // Fetch the currect name
+ gCacheName->get(mAvatarID, FALSE, boost::bind(&LLPanelIMControlPanel::nameUpdatedCallback, this, _1, _2, _3, _4));
+
+ // Disable profile button if participant is not realy SL avatar
+ LLIMModel::LLIMSession* im_session =
+ im_model.findIMSession(session_id);
+ if( im_session && !im_session->mOtherParticipantIsAvatar )
+ childSetEnabled("view_profile_btn", FALSE);
}
+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);
+ }
+}
+LLPanelGroupControlPanel::LLPanelGroupControlPanel(const LLUUID& session_id)
+{
+ mSpeakerManager = LLIMModel::getInstance()->getSpeakerManager(session_id);
+}
BOOL LLPanelGroupControlPanel::postBuild()
{
childSetAction("group_info_btn", boost::bind(&LLPanelGroupControlPanel::onGroupInfoButtonClicked, this));
- childSetAction("call_btn", boost::bind(&LLPanelGroupControlPanel::onCallButtonClicked, this));
- return TRUE;
+ mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
+
+ return LLPanelChatControlPanel::postBuild();
+}
+
+LLPanelGroupControlPanel::~LLPanelGroupControlPanel()
+{
+ delete mParticipantList;
+ mParticipantList = NULL;
+}
+
+// virtual
+void LLPanelGroupControlPanel::draw()
+{
+ mSpeakerManager->update(true);
+ LLPanelChatControlPanel::draw();
}
void LLPanelGroupControlPanel::onGroupInfoButtonClicked()
@@ -103,14 +223,44 @@ 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::onCallButtonClicked()
+}
+
+void LLPanelGroupControlPanel::onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state)
{
- // *TODO: Implement
+ LLPanelChatControlPanel::onVoiceChannelStateChanged(old_state, new_state);
+ mAvatarList->setSpeakingIndicatorsVisible(new_state >= LLVoiceChannel::STATE_CALL_STARTED);
}
+void LLPanelGroupControlPanel::setSessionId(const LLUUID& session_id)
+{
+ LLPanelChatControlPanel::setSessionId(session_id);
-void LLPanelGroupControlPanel::setID(const LLUUID& id)
+ mGroupID = LLIMModel::getInstance()->getOtherParticipantID(session_id);
+}
+
+
+LLPanelAdHocControlPanel::LLPanelAdHocControlPanel(const LLUUID& session_id):LLPanelGroupControlPanel(session_id)
+{
+}
+
+BOOL LLPanelAdHocControlPanel::postBuild()
{
- mGroupID = id;
+ mAvatarList = getChild<LLAvatarList>("speakers_list");
+ mParticipantList = new LLParticipantList(mSpeakerManager, mAvatarList);
+
+ return LLPanelChatControlPanel::postBuild();
}
+
diff --git a/indra/newview/llpanelimcontrolpanel.h b/indra/newview/llpanelimcontrolpanel.h
index e82942a31d..ac5d86345e 100644
--- a/indra/newview/llpanelimcontrolpanel.h
+++ b/indra/newview/llpanelimcontrolpanel.h
@@ -34,7 +34,11 @@
#define LL_LLPANELIMCONTROLPANEL_H
#include "llpanel.h"
+#include "llvoicechannel.h"
+class LLSpeakerMgr;
+class LLAvatarList;
+class LLParticipantList;
class LLPanelChatControlPanel : public LLPanel
{
@@ -42,8 +46,19 @@ public:
LLPanelChatControlPanel() {};
~LLPanelChatControlPanel() {};
- // sets the group or avatar UUID
- virtual void setID(const LLUUID& avatar_id)= 0;
+ virtual BOOL postBuild();
+ virtual void draw();
+
+ void onCallButtonClicked();
+ void onEndCallButtonClicked();
+ void onOpenVoiceControlsClicked();
+
+ virtual void onVoiceChannelStateChanged(const LLVoiceChannel::EState& old_state, const LLVoiceChannel::EState& new_state);
+
+ virtual void setSessionId(const LLUUID& session_id);
+
+private:
+ LLUUID mSessionId;
};
@@ -55,33 +70,52 @@ public:
BOOL postBuild();
- void setID(const LLUUID& avatar_id);
+ void setSessionId(const LLUUID& session_id);
+
+protected:
+ void nameUpdatedCallback(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group);
private:
void onViewProfileButtonClicked();
void onAddFriendButtonClicked();
- void onCallButtonClicked();
void onShareButtonClicked();
+ void onTeleportButtonClicked();
+ void onPayButtonClicked();
+
+ LLUUID mAvatarID;
};
class LLPanelGroupControlPanel : public LLPanelChatControlPanel
{
public:
- LLPanelGroupControlPanel() {};
- ~LLPanelGroupControlPanel() {};
+ LLPanelGroupControlPanel(const LLUUID& session_id);
+ ~LLPanelGroupControlPanel();
BOOL postBuild();
- void setID(const LLUUID& id);
+ void setSessionId(const LLUUID& session_id);
+ /*virtual*/ void draw();
+
+protected:
+ LLUUID mGroupID;
+ LLSpeakerMgr* mSpeakerManager;
+ LLAvatarList* mAvatarList;
+ LLParticipantList* mParticipantList;
private:
void onGroupInfoButtonClicked();
- void onCallButtonClicked();
-
- LLUUID mGroupID;
+ 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 bce5525a40..417a804834 100644
--- a/indra/newview/llpanelland.cpp
+++ b/indra/newview/llpanelland.cpp
@@ -70,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"));
@@ -265,8 +264,3 @@ void LLPanelLandInfo::onClickAbout(void*)
LLFloaterReg::showInstance("about_land");
}
-
-void LLPanelLandInfo::onShowOwnersHelp(void* user_data)
-{
- LLNotifications::instance().add("ShowOwnersHelp");
-}
diff --git a/indra/newview/llpanelland.h b/indra/newview/llpanelland.h
index 92fe313405..02e7e7bf38 100644
--- a/indra/newview/llpanelland.h
+++ b/indra/newview/llpanelland.h
@@ -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/llpanellandmarkinfo.cpp b/indra/newview/llpanellandmarkinfo.cpp
new file mode 100644
index 0000000000..4985663833
--- /dev/null
+++ b/indra/newview/llpanellandmarkinfo.cpp
@@ -0,0 +1,420 @@
+/**
+ * @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 "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");
+
+LLPanelLandmarkInfo::LLPanelLandmarkInfo()
+: LLPanelPlaceInfo()
+{}
+
+// virtual
+LLPanelLandmarkInfo::~LLPanelLandmarkInfo()
+{}
+
+// virtual
+BOOL LLPanelLandmarkInfo::postBuild()
+{
+ LLPanelPlaceInfo::postBuild();
+
+ mOwner = getChild<LLTextBox>("owner");
+ mCreator = getChild<LLTextBox>("creator");
+ mCreated = getChild<LLTextBox>("created");
+
+ mTitleEditor = getChild<LLLineEditor>("title_editor");
+ mNotesEditor = getChild<LLTextEditor>("notes_editor");
+ mFolderCombo = getChild<LLComboBox>("folder_combo");
+
+ 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);
+ mTitleEditor->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;
+ bool is_info_type_landmark = type == LANDMARK;
+
+ landmark_info_panel->setVisible(is_info_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");
+
+ mTitleEditor->setEnabled(TRUE);
+ mNotesEditor->setEnabled(TRUE);
+ break;
+
+ case LANDMARK:
+ default:
+ mCurrentTitle = getString("title_landmark");
+
+ mTitleEditor->setEnabled(FALSE);
+ mNotesEditor->setEnabled(FALSE);
+ break;
+ }
+
+ populateFoldersList();
+
+ LLPanelPlaceInfo::setInfoType(type);
+}
+
+// virtual
+void LLPanelLandmarkInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+ LLPanelPlaceInfo::processParcelInfo(parcel_data);
+
+ 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 (mInfoType == CREATE_LANDMARK)
+ {
+ if (parcel_data.name.empty())
+ {
+ mTitleEditor->setText(llformat("%s (%d, %d, %d)",
+ parcel_data.sim_name.c_str(), region_x, region_y, region_z));
+ }
+ else
+ {
+ mTitleEditor->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);
+ }
+
+ mTitleEditor->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);
+ }
+
+ if (mNotesEditor->getReadOnly() == (enabled == TRUE))
+ {
+ mTitleEditor->setEnabled(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 mTitleEditor->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 = mTitleEditor->getText();
+ std::string desc = mNotesEditor->getText();
+
+ LLStringUtil::trim(name);
+ LLStringUtil::trim(desc);
+
+ // If typed name is empty use the parcel name instead.
+ if (name.empty())
+ {
+ name = mParcelName->getText();
+
+ // If no parcel exists use the region name instead.
+ if (name.empty())
+ {
+ name = mRegionName->getText();
+ }
+ }
+
+ LLStringUtil::replaceChar(desc, '\n', ' ');
+ // If no folder chosen use the "Landmarks" folder.
+ LLLandmarkActions::createLandmarkHere(name, desc,
+ folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(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..73e0ddb9cc
--- /dev/null
+++ b/indra/newview/llpanellandmarkinfo.h
@@ -0,0 +1,85 @@
+/**
+ * @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;
+ LLLineEditor* mTitleEditor;
+ LLTextEditor* mNotesEditor;
+ LLComboBox* mFolderCombo;
+};
+
+#endif // LL_LLPANELLANDMARKINFO_H
diff --git a/indra/newview/llpanellandmarks.cpp b/indra/newview/llpanellandmarks.cpp
index 1d79ea4a21..c516546282 100644
--- a/indra/newview/llpanellandmarks.cpp
+++ b/indra/newview/llpanellandmarks.cpp
@@ -4,7 +4,7 @@
*
* $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
@@ -35,32 +35,56 @@
#include "llbutton.h"
#include "llfloaterreg.h"
-#include "lllandmark.h"
-
+#include "llsdutil.h"
+#include "llsdutil_math.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 "llfloaterinventory.h"
-#include "llfoldervieweventlistener.h"
-#include "lllandmarklist.h"
+#include "llfolderviewitem.h"
+#include "llinventorypanel.h"
+#include "llinventorysubtreepanel.h"
+#include "lllandmarkactions.h"
+#include "llplacesinventorybridge.h"
#include "llsidetray.h"
-#include "lltabcontainer.h"
-#include "llworldmap.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(LLInventorySubTreePanel* inventory_list, const std::string& string);
+
+
LLLandmarksPanel::LLLandmarksPanel()
- : LLPanelPlacesTab(),
- mInventoryPanel(NULL)
+ : LLPanelPlacesTab()
+ , mFavoritesInventoryPanel(NULL)
+ , mLandmarksInventoryPanel(NULL)
+ , mMyInventoryPanel(NULL)
+ , mLibraryInventoryPanel(NULL)
+ , mCurrentSelectedList(NULL)
+ , mListCommands(NULL)
+ , mGearFolderMenu(NULL)
+ , mGearLandmarkMenu(NULL)
+ , mDirtyFilter(false)
{
- mSavedFolderState = new LLSaveFolderState();
- mSavedFolderState->setApply(FALSE);
-
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_landmarks.xml");
}
LLLandmarksPanel::~LLLandmarksPanel()
{
- delete mSavedFolderState;
}
BOOL LLLandmarksPanel::postBuild()
@@ -68,73 +92,63 @@ BOOL LLLandmarksPanel::postBuild()
if (!gInventory.isInventoryUsable())
return FALSE;
- mInventoryPanel = getChild<LLInventoryPanel>("landmarks_list");
- mInventoryPanel->setFilterTypes(0x1 << LLInventoryType::IT_LANDMARK);
- mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
- mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_LANDMARK);
- mInventoryPanel->setSelectCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2));
+ // mast be called before any other initXXX methods to init Gear menu
+ initListCommandsHandlers();
- LLFolderView* root_folder = mInventoryPanel->getRootFolder();
- root_folder->setReshapeCallback(boost::bind(&LLLandmarksPanel::onSelectionChange, this, _1, _2));
-
- mActionBtn = getChild<LLButton>("selector");
- root_folder->addChild(mActionBtn);
- mActionBtn->setEnabled(TRUE);
- childSetAction("selector", boost::bind(&LLLandmarksPanel::onSelectorButtonClicked, this), this);
+ U32 sort_order = gSavedSettings.getU32(LLInventoryPanel::DEFAULT_SORT_ORDER);
+ mSortByDate = sort_order & LLInventoryFilter::SO_DATE;
+ initFavoritesInventroyPanel();
+ initLandmarksInventroyPanel();
+ initMyInventroyPanel();
+ initLibraryInventroyPanel();
+ getChild<LLAccordionCtrlTab>("tab_favorites")->setDisplayChildren(true);
+ getChild<LLAccordionCtrlTab>("tab_landmarks")->setDisplayChildren(true);
+ gIdleCallbacks.addFunction(LLLandmarksPanel::doIdle, this);
return TRUE;
}
// virtual
void LLLandmarksPanel::onSearchEdit(const std::string& string)
{
- if (string == "")
- {
- mInventoryPanel->setFilterSubString(LLStringUtil::null);
+ static std::string prev_string("");
- // re-open folders that were initially open
- mSavedFolderState->setApply(TRUE);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- LLOpenFoldersWithSelection opener;
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener);
- mInventoryPanel->getRootFolder()->scrollToShowSelection();
- }
+ if (prev_string == string) return;
- gInventory.startBackgroundFetch();
+ // show all folders in Landmarks Accordion for empty filter
+ mLandmarksInventoryPanel->setShowFolderState(string.empty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS :
+ LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS
+ );
- if (mInventoryPanel->getFilterSubString().empty() && string.empty())
- {
- // current filter and new filter empty, do nothing
- return;
- }
+ filter_list(mFavoritesInventoryPanel, string);
+ filter_list(mLandmarksInventoryPanel, string);
+ filter_list(mMyInventoryPanel, string);
+ filter_list(mLibraryInventoryPanel, string);
- // save current folder open state if no filter currently applied
- if (mInventoryPanel->getRootFolder()->getFilterSubString().empty())
+ prev_string = string;
+ mDirtyFilter = true;
+
+ // 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)
{
- mSavedFolderState->setApply(FALSE);
- mInventoryPanel->getRootFolder()->applyFunctorRecursively(*mSavedFolderState);
- }
+ LLAccordionCtrlTab* tab = *iter;
+ tab->setVisible(true);
- // set new filter string
- mInventoryPanel->setFilterSubString(string);
+ // expand accordion to see matched items in all ones. See EXT-2014.
+ tab->changeOpenClose(false);
+ }
}
// virtual
void LLLandmarksPanel::onShowOnMap()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
- return;
-
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK)
- return;
-
- LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID());
- if (!inventory_item)
+ if (NULL == mCurrentSelectedList)
+ {
+ llwarns << "There are no selected list. No actions are performed." << llendl;
return;
-
- LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID());
+ }
+ LLLandmark* landmark = getCurSelectedLandmark();
if (!landmark)
return;
@@ -153,9 +167,12 @@ void LLLandmarksPanel::onShowOnMap()
// virtual
void LLLandmarksPanel::onTeleport()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
+ 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)
@@ -164,117 +181,783 @@ void LLLandmarksPanel::onTeleport()
}
}
-/*
// virtual
-void LLLandmarksPanel::onCopySLURL()
+void LLLandmarksPanel::updateVerbs()
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
+ if (!isTabVisible())
return;
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() != LLInventoryType::IT_LANDMARK)
- return;
+ bool landmark_selected = isLandmarkSelected();
+ mTeleportBtn->setEnabled(landmark_selected && isActionEnabled("teleport"));
+ mShowOnMapBtn->setEnabled(landmark_selected && isActionEnabled("show_on_map"));
- LLInventoryItem* inventory_item = gInventory.getItem(listenerp->getUUID());
- if (!inventory_item)
- return;
+ // 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);
- LLLandmark* landmark = gLandmarkList.getAsset(inventory_item->getAssetUUID());
- if (!landmark)
- return;
+ updateListCommands();
+}
- LLVector3d landmark_global_pos;
- if (!landmark->getGlobalPos(landmark_global_pos))
+void LLLandmarksPanel::onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ if (user_action && (items.size() > 0))
+ {
+ deselectOtherThan(inventory_list);
+ mCurrentSelectedList = inventory_list;
+ }
+
+ LLFolderViewItem* current_item = inventory_list->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
return;
- U64 new_region_handle = to_region_handle(landmark_global_pos);
+ updateVerbs();
+}
- LLWorldMap::url_callback_t cb = boost::bind(
- &LLPanelPlacesTab::onRegionResponse, this,
- landmark_global_pos, _1, _2, _3, _4);
+void LLLandmarksPanel::onSelectorButtonClicked()
+{
+ // TODO: mantipov: update getting of selected item
+ // TODO: bind to "i" button
+ LLFolderViewItem* cur_item = mFavoritesInventoryPanel->getRootFolder()->getCurSelectedItem();
+
+ LLFolderViewEventListener* listenerp = cur_item->getListener();
+ if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = listenerp->getUUID();
- LLWorldMap::getInstance()->sendHandleRegionRequest(new_region_handle, cb, std::string("unused"), false);
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// 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;
+}
+LLLandmark* LLLandmarksPanel::getCurSelectedLandmark() const
+{
+
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ if(cur_item && cur_item->getListener()->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ {
+ return LLLandmarkActions::getLandmark(cur_item->getListener()->getUUID());
+ }
+ return NULL;
+}
+
+LLFolderViewItem* LLLandmarksPanel::getCurSelectedItem () const
+{
+ return mCurrentSelectedList ? mCurrentSelectedList->getRootFolder()->getCurSelectedItem() : NULL;
+}
+
+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::updateVerbs()
+void LLLandmarksPanel::processParcelInfo(const LLParcelData& parcel_data)
{
- if (!isTabVisible())
+ //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())
+ {
+ LLLandmark* landmark = getCurSelectedLandmark();
+ LLFolderViewItem* cur_item = getCurSelectedItem();
+ LLUUID id = cur_item->getListener()->getUUID();
+ LLInventoryItem* inv_item = mCurrentSelectedList->getModel()->getItem(id);
+ if(landmark)
+ {
+ 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));
+ }
+ }
+}
+
+// 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::initFavoritesInventroyPanel()
+{
+ mFavoritesInventoryPanel = getChild<LLInventorySubTreePanel>("favorites_list");
+
+ initLandmarksPanel(mFavoritesInventoryPanel);
+
+ initAccordion("tab_favorites", mFavoritesInventoryPanel);
+}
+
+void LLLandmarksPanel::initLandmarksInventroyPanel()
+{
+ mLandmarksInventoryPanel = getChild<LLInventorySubTreePanel>("landmarks_list");
+
+ initLandmarksPanel(mLandmarksInventoryPanel);
+
+ 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::initMyInventroyPanel()
+{
+ mMyInventoryPanel= getChild<LLInventorySubTreePanel>("my_inventory_list");
+
+ initLandmarksPanel(mMyInventoryPanel);
+
+ initAccordion("tab_inventory", mMyInventoryPanel);
+}
+
+void LLLandmarksPanel::initLibraryInventroyPanel()
+{
+ mLibraryInventoryPanel = getChild<LLInventorySubTreePanel>("library_list");
+
+ initLandmarksPanel(mLibraryInventoryPanel);
+
+ initAccordion("tab_library", mLibraryInventoryPanel);
+}
+
+void LLLandmarksPanel::initLandmarksPanel(LLInventorySubTreePanel* inventory_list)
+{
+ 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());
+ }
+
+ // save initial folder state to avoid incorrect work while switching between Landmarks & Teleport History tabs
+ // See EXT-1609.
+ inventory_list->saveFolderState();
+}
+
+void LLLandmarksPanel::initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* 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, LLInventorySubTreePanel* inventory_list)
+{
+ bool expanded = param.asBoolean();
+
+ if(!expanded && (mCurrentSelectedList == inventory_list))
+ {
+ inventory_list->getRootFolder()->clearSelection();
+
+ mCurrentSelectedList = NULL;
+ updateVerbs();
+ }
+}
+
+void LLLandmarksPanel::deselectOtherThan(const LLInventorySubTreePanel* 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);
+}
+
+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);
+}
- BOOL enabled = FALSE;
+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);
+ }
+}
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (current_item)
+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)
+ {
+ LLSideTray::getInstance()->showPanel("panel_places",
+ LLSD().insert("type", "landmark").insert("id",landmark->getUUID()));
+ }
+ else
+ {
+ LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
+ }
+ }
+ else if ("category" == command_name)
{
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+ LLFolderViewItem* item = getCurSelectedItem();
+ if (item && mCurrentSelectedList == mLandmarksInventoryPanel)
{
- enabled = TRUE;
+ 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));
}
}
-
- mTeleportBtn->setEnabled(enabled);
- mShowOnMapBtn->setEnabled(enabled);
}
-void LLLandmarksPanel::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+void LLLandmarksPanel::onClipboardAction(const LLSD& userdata) const
{
- LLFolderViewItem* current_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
- if (!current_item)
+ 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);
+ }
+}
- LLFolderViewEventListener* listenerp = current_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+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->closeAllFolders();
+ }
+ else if ( "sort_by_date" == command_name)
{
- S32 bottom = 0;
- LLFolderViewItem* folder = current_item->getParentFolder();
+ 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;
- while ( folder->getParentFolder() != NULL )
+ // 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
+ )
{
- bottom += folder->getRect().mBottom;
- folder = folder->getParentFolder();
+ return false;
}
- LLRect rect = current_item->getRect();
- LLRect btn_rect(
- rect.mRight - mActionBtn->getRect().getWidth(),
- bottom + rect.mTop,
- rect.mRight,
- bottom + rect.mBottom);
+ }
+
+ // 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;
+ }
- mActionBtn->setRect(btn_rect);
- if (!mActionBtn->getVisible())
- mActionBtn->setVisible(TRUE);
+ 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 ( "sort_by_date" == command_name)
+ {
+ return mSortByDate;
+ }
+ else if("create_pick" == command_name)
+ {
+ return !LLAgentPicksInfo::getInstance()->isPickLimitReached();
}
else
{
- if (mActionBtn->getVisible())
- mActionBtn->setVisible(FALSE);
+ llwarns << "Unprocessed command has come: " << command_name << llendl;
}
- updateVerbs();
+ return true;
}
-void LLLandmarksPanel::onSelectorButtonClicked()
+void LLLandmarksPanel::onCustomAction(const LLSD& userdata)
{
- LLFolderViewItem* cur_item = mInventoryPanel->getRootFolder()->getCurSelectedItem();
+ 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)
+ {
+ LLLandmark* landmark = getCurSelectedLandmark();
+ if(!landmark) return;
+
+ 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;
+ }
+ }
+}
- LLFolderViewEventListener* listenerp = cur_item->getListener();
- if (listenerp->getInventoryType() == LLInventoryType::IT_LANDMARK)
+/*
+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())
{
- LLSD key;
- key["type"] = "landmark";
- key["id"] = listenerp->getUUID();
+ can_be_modified = true;
- LLSideTray::getInstance()->showPanel("panel_places", key);
+ // 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)
+ {
+ if ("cut" == command_name)
+ {
+ can_be_modified = mCurrentSelectedList->getRootFolder()->canCut();
+ }
+ else if ("rename" == command_name)
+ {
+ can_be_modified = getCurSelectedItem()->getListener()->isItemRenameable();
+ }
+ else if ("delete" == command_name)
+ {
+ can_be_modified = getCurSelectedItem()->getListener()->isItemRemovable();
+ }
+ 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;
+}
+
+// static
+void LLLandmarksPanel::doIdle(void* landmarks_panel)
+{
+ LLLandmarksPanel* panel = (LLLandmarksPanel* ) landmarks_panel;
+
+ if (panel->mDirtyFilter)
+ {
+ panel->updateFilteredAccordions();
}
+
}
-void LLLandmarksPanel::setSelectedItem(const LLUUID& obj_id)
+void LLLandmarksPanel::updateFilteredAccordions()
{
- mInventoryPanel->setSelection(obj_id, FALSE);
+ LLInventoryPanel* inventory_list = NULL;
+ LLAccordionCtrlTab* accordion_tab = NULL;
+ for (accordion_tabs_t::const_iterator iter = mAccordionTabs.begin(); iter != mAccordionTabs.end(); ++iter)
+ {
+ accordion_tab = *iter;
+ inventory_list = dynamic_cast<LLInventorySubTreePanel*> (accordion_tab->getAccordionView());
+ if (NULL == inventory_list) continue;
+ LLFolderView* fv = inventory_list->getRootFolder();
+
+ bool has_visible_children = fv->hasVisibleChildren();
+
+ accordion_tab->setVisible(has_visible_children);
+ }
+
+ // we have to arrange accordion tabs for cases when filter string is less restrictive but
+ // all items are still filtered.
+ static LLAccordionCtrl* accordion = getChild<LLAccordionCtrl>("landmarks_accordion");
+ accordion->arrange();
+
+ // now filter state is applied to accordion tabs
+ mDirtyFilter = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// HELPER FUNCTIONS
+//////////////////////////////////////////////////////////////////////////
+static void filter_list(LLInventorySubTreePanel* inventory_list, const std::string& string)
+{
+ if (string == "")
+ {
+ inventory_list->setFilterSubString(LLStringUtil::null);
+
+ // re-open folders that were initially open
+ inventory_list->restoreFolderState();
+ }
+
+ gInventory.startBackgroundFetch();
+
+ 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);
}
+// EOF
diff --git a/indra/newview/llpanellandmarks.h b/indra/newview/llpanellandmarks.h
index 14cbbd6123..d54761ed59 100644
--- a/indra/newview/llpanellandmarks.h
+++ b/indra/newview/llpanellandmarks.h
@@ -5,7 +5,7 @@
*
* $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
@@ -33,14 +33,21 @@
#ifndef LL_LLPANELLANDMARKS_H
#define LL_LLPANELLANDMARKS_H
+#include "lllandmark.h"
+
+// newview
#include "llinventorymodel.h"
#include "llpanelplacestab.h"
+#include "llpanelpick.h"
+#include "llremoteparcelrequest.h"
+class LLAccordionCtrlTab;
class LLFolderViewItem;
+class LLMenuGL;
class LLInventoryPanel;
-class LLSaveFolderState;
+class LLInventorySubTreePanel;
-class LLLandmarksPanel : public LLPanelPlacesTab
+class LLLandmarksPanel : public LLPanelPlacesTab, LLRemoteParcelInfoObserver
{
public:
LLLandmarksPanel();
@@ -50,17 +57,92 @@ public:
/*virtual*/ void onSearchEdit(const std::string& string);
/*virtual*/ void onShowOnMap();
/*virtual*/ void onTeleport();
- ///*virtual*/ void onCopySLURL();
/*virtual*/ void updateVerbs();
- void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onSelectionChange(LLInventorySubTreePanel* inventory_list, const std::deque<LLFolderViewItem*> &items, BOOL user_action);
void onSelectorButtonClicked();
- void setSelectedItem(const LLUUID& obj_id);
+
+protected:
+ /**
+ * @return true - if current selected panel is not null and selected item is a landmark
+ */
+ bool isLandmarkSelected() const;
+ bool isReceivedFolderSelected() const;
+ LLLandmark* getCurSelectedLandmark() const;
+ LLFolderViewItem* getCurSelectedItem () 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:
- LLInventoryPanel* mInventoryPanel;
- LLSaveFolderState* mSavedFolderState;
- LLButton* mActionBtn;
+ void initFavoritesInventroyPanel();
+ void initLandmarksInventroyPanel();
+ void initMyInventroyPanel();
+ void initLibraryInventroyPanel();
+ void initLandmarksPanel(LLInventorySubTreePanel* inventory_list);
+ void initAccordion(const std::string& accordion_tab_name, LLInventorySubTreePanel* inventory_list);
+ void onAccordionExpandedCollapsed(const LLSD& param, LLInventorySubTreePanel* inventory_list);
+ void deselectOtherThan(const LLInventorySubTreePanel* 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);
+
+ /**
+ * Static callback for gIdleCallbacks to perform actions out of drawing
+ */
+ static void doIdle(void* landmarks_panel);
+
+ /**
+ * Updates accordions according to filtered items in lists.
+ *
+ * It hides accordion for empty lists
+ */
+ void updateFilteredAccordions();
+
+private:
+ LLInventorySubTreePanel* mFavoritesInventoryPanel;
+ LLInventorySubTreePanel* mLandmarksInventoryPanel;
+ LLInventorySubTreePanel* mMyInventoryPanel;
+ LLInventorySubTreePanel* mLibraryInventoryPanel;
+ LLMenuGL* mGearLandmarkMenu;
+ LLMenuGL* mGearFolderMenu;
+ LLMenuGL* mMenuAdd;
+ LLInventorySubTreePanel* mCurrentSelectedList;
+
+ LLPanel* mListCommands;
+ bool mSortByDate;
+ bool mDirtyFilter;
+
+ typedef std::vector<LLAccordionCtrlTab*> accordion_tabs_t;
+ accordion_tabs_t mAccordionTabs;
};
#endif //LL_LLPANELLANDMARKS_H
diff --git a/indra/newview/llpanellogin.cpp b/indra/newview/llpanellogin.cpp
index 24e76e2c6e..5d826f0a56 100644
--- a/indra/newview/llpanellogin.cpp
+++ b/indra/newview/llpanellogin.cpp
@@ -198,7 +198,16 @@ 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);
@@ -234,9 +243,7 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
childSetAction("connect_btn", onClickConnect, this);
- setDefaultBtn("connect_btn");
-
- // childSetAction("quit_btn", onClickQuit, this);
+ getChild<LLPanel>("login_widgets")->setDefaultBtn("connect_btn");
std::string channel = gSavedSettings.getString("VersionChannelName");
std::string version = llformat("%d.%d.%d (%d)",
@@ -267,19 +274,20 @@ LLPanelLogin::LLPanelLogin(const LLRect &rect,
web_browser->setTabStop(FALSE);
// 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 );
@@ -297,6 +305,27 @@ 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->getVirtualWindowRect();
+ 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 )
{
LLMediaCtrl* web_browser = getChild<LLMediaCtrl>("login_html");
@@ -384,10 +413,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
@@ -418,12 +451,6 @@ BOOL LLPanelLogin::handleKeyHere(KEY key, MASK mask)
return TRUE;
}
- 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);
}
@@ -483,6 +510,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,
@@ -797,8 +837,17 @@ void LLPanelLogin::loadLoginPage()
LLMediaCtrl* web_browser = sInstance->getChild<LLMediaCtrl>("login_html");
- // navigate to the "real" page
- web_browser->navigateTo( oStr.str(), "text/html" );
+ // 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::handleMediaEvent(LLPluginClassMedia* /*self*/, EMediaEvent event)
@@ -883,22 +932,6 @@ void LLPanelLogin::onClickNewAccount(void*)
}
-// *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);
- }
-}
-
-
// static
void LLPanelLogin::onClickVersion(void*)
{
diff --git a/indra/newview/llpanellogin.h b/indra/newview/llpanellogin.h
index 5692b8d345..acb2001c22 100644
--- a/indra/newview/llpanellogin.h
+++ b/indra/newview/llpanellogin.h
@@ -56,6 +56,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);
@@ -86,10 +90,10 @@ public:
/*virtual*/ void handleMediaEvent(LLPluginClassMedia* self, EMediaEvent event);
private:
+ void reshapeBrowser();
static void onClickConnect(void*);
static void onClickNewAccount(void*);
// static bool newAccountAlertCallback(const LLSD& notification, const LLSD& response);
- static void onClickQuit(void*);
static void onClickVersion(void*);
static void onClickForgotPassword(void*);
static void onPassKey(LLLineEditor* caller, void* user_data);
diff --git a/indra/newview/llpanelmaininventory.cpp b/indra/newview/llpanelmaininventory.cpp
new file mode 100644
index 0000000000..25be09fa24
--- /dev/null
+++ b/indra/newview/llpanelmaininventory.cpp
@@ -0,0 +1,818 @@
+/**
+ * @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 "llfloaterinventory.h"
+#include "llinventorybridge.h"
+#include "llinventoryfunctions.h"
+#include "llinventorypanel.h"
+#include "llfiltereditor.h"
+#include "llfloaterreg.h"
+#include "llscrollcontainer.h"
+#include "llsdserialize.h"
+#include "llspinctrl.h"
+#include "lltooldraganddrop.h"
+
+static LLRegisterPanelClassWrapper<LLPanelMainInventory> t_inventory("panel_main_inventory"); // Seraph is this redundant with constructor?
+
+///----------------------------------------------------------------------------
+/// 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* mPanelInventoryDecorated;
+ LLSpinCtrl* mSpinSinceDays;
+ LLSpinCtrl* mSpinSinceHours;
+ LLInventoryFilter* mFilter;
+};
+
+///----------------------------------------------------------------------------
+/// LLPanelMainInventory
+///----------------------------------------------------------------------------
+
+LLPanelMainInventory::LLPanelMainInventory()
+ : LLPanel()
+{
+ 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(&LLInventoryPanel::onSelectionChange, 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(&LLInventoryPanel::onSelectionChange, 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.xml");
+ 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);
+
+ 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.xml");
+ 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();
+ }
+}
+
+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);
+ 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(uppercase_search_string);
+}
+
+
+ //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;
+ }
+ 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;
+}
+
+void LLPanelMainInventory::changed(U32 mask)
+{
+}
+
+
+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);
+}
+
+///----------------------------------------------------------------------------
+/// LLFloaterInventoryFinder
+///----------------------------------------------------------------------------
+
+LLFloaterInventoryFinder* LLPanelMainInventory::getFinder()
+{
+ return (LLFloaterInventoryFinder*)mFinderHandle.get();
+}
+
+
+LLFloaterInventoryFinder::LLFloaterInventoryFinder(LLPanelMainInventory* inventory_view) :
+ LLFloater(LLSD()),
+ mPanelInventoryDecorated(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 = mPanelInventoryDecorated->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->getFilterTypes();
+ 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
+ mPanelInventoryDecorated->getPanel()->setShowFolderState(getCheckShowEmpty() ?
+ LLInventoryFilter::SHOW_ALL_FOLDERS : LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS);
+ mPanelInventoryDecorated->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;
+ mPanelInventoryDecorated->getPanel()->setHoursAgo(hours);
+ mPanelInventoryDecorated->getPanel()->setSinceLogoff(getCheckSinceLogoff());
+ mPanelInventoryDecorated->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);
+}
diff --git a/indra/newview/llpanelmaininventory.h b/indra/newview/llpanelmaininventory.h
new file mode 100644
index 0000000000..a2b988e80c
--- /dev/null
+++ b/indra/newview/llpanelmaininventory.h
@@ -0,0 +1,125 @@
+/**
+ * @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 "llinventorymodel.h"
+#include "llfolderview.h"
+
+class LLFolderViewItem;
+class LLInventoryPanel;
+class LLSaveFolderState;
+class LLFilterEditor;
+class LLTabContainer;
+class LLFloaterInventoryFinder;
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// 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 mask);
+
+ LLInventoryPanel* getPanel() { return mActivePanel; }
+ LLInventoryPanel* getActivePanel() { 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();
+
+ 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);
+
+private:
+ LLFloaterInventoryFinder* getFinder();
+
+ LLFilterEditor* mFilterEditor;
+ LLTabContainer* mFilterTabs;
+ LLHandle<LLFloater> mFinderHandle;
+ LLInventoryPanel* mActivePanel;
+ LLSaveFolderState* mSavedFolderState;
+
+ std::string mFilterText;
+};
+
+#endif // LL_LLPANELMAININVENTORY_H
+
+
+
diff --git a/indra/newview/llpanelmediasettingsgeneral.cpp b/indra/newview/llpanelmediasettingsgeneral.cpp
index 3177ef9a21..85efe0f93e 100644
--- a/indra/newview/llpanelmediasettingsgeneral.cpp
+++ b/indra/newview/llpanelmediasettingsgeneral.cpp
@@ -32,6 +32,7 @@
#include "llviewerprecompiledheaders.h"
+#include "llagent.h"
#include "llpanelmediasettingsgeneral.h"
#include "llcombobox.h"
#include "llcheckboxctrl.h"
@@ -48,6 +49,7 @@
#include "llmediaentry.h"
#include "llmediactrl.h"
#include "llpanelcontents.h"
+#include "llpermissions.h"
#include "llpluginclassmedia.h"
#include "llfloatermediasettings.h"
#include "llfloatertools.h"
@@ -66,15 +68,11 @@ LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
mHeightPixels( NULL ),
mHomeURL( NULL ),
mCurrentURL( NULL ),
- mAltImageEnable( NULL ),
mParent( NULL ),
mMediaEditable(false)
{
// build dialog from XML
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_general.xml");
-// mCommitCallbackRegistrar.add("Media.ResetCurrentUrl", boost::bind(&LLPanelMediaSettingsGeneral::onBtnResetCurrentUrl, this));
-// mCommitCallbackRegistrar.add("Media.CommitHomeURL", boost::bind(&LLPanelMediaSettingsGeneral::onCommitHomeURL, this));
-
}
////////////////////////////////////////////////////////////////////////////////
@@ -82,7 +80,6 @@ LLPanelMediaSettingsGeneral::LLPanelMediaSettingsGeneral() :
BOOL LLPanelMediaSettingsGeneral::postBuild()
{
// connect member vars with UI widgets
- mAltImageEnable = getChild< LLCheckBoxCtrl >( LLMediaEntry::ALT_IMAGE_ENABLE_KEY );
mAutoLoop = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_LOOP_KEY );
mAutoPlay = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_PLAY_KEY );
mAutoScale = getChild< LLCheckBoxCtrl >( LLMediaEntry::AUTO_SCALE_KEY );
@@ -137,6 +134,11 @@ void LLPanelMediaSettingsGeneral::draw()
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
@@ -161,8 +163,7 @@ void LLPanelMediaSettingsGeneral::draw()
// current URL can change over time.
// updateCurrentURL();
- // enable/disable RESRET button depending on permissions
- // since this is the same as a navigate action
+ LLPermissions perm;
bool user_can_press_reset = mMediaEditable;
// several places modify this widget so we must collect states in one place
@@ -191,7 +192,6 @@ void LLPanelMediaSettingsGeneral::draw()
void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
{
LLPanelMediaSettingsGeneral *self =(LLPanelMediaSettingsGeneral *)userdata;
- self->mAltImageEnable ->clear();
self->mAutoLoop->clear();
self->mAutoPlay->clear();
self->mAutoScale->clear();
@@ -202,7 +202,6 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
self->mHeightPixels->clear();
self->mHomeURL->clear();
self->mWidthPixels->clear();
- self->mAltImageEnable ->setEnabled(editable);
self->mAutoLoop ->setEnabled(editable);
self->mAutoPlay ->setEnabled(editable);
self->mAutoScale ->setEnabled(editable);
@@ -213,7 +212,7 @@ void LLPanelMediaSettingsGeneral::clearValues( void* userdata, bool editable)
self->mHeightPixels ->setEnabled(editable);
self->mHomeURL ->setEnabled(editable);
self->mWidthPixels ->setEnabled(editable);
- self->mPreviewMedia->unloadMediaSource();
+ self->updateMediaPreview();
}
////////////////////////////////////////////////////////////////////////////////
@@ -271,7 +270,6 @@ void LLPanelMediaSettingsGeneral::initValues( void* userdata, const LLSD& media_
{ LLMediaEntry::HOME_URL_KEY, self->mHomeURL, "LLLineEditor" },
{ LLMediaEntry::FIRST_CLICK_INTERACT_KEY, self->mFirstClick, "LLCheckBoxCtrl" },
{ LLMediaEntry::WIDTH_PIXELS_KEY, self->mWidthPixels, "LLSpinCtrl" },
- { LLMediaEntry::ALT_IMAGE_ENABLE_KEY, self->mAltImageEnable, "LLCheckBoxCtrl" },
{ "", NULL , "" }
};
@@ -319,10 +317,10 @@ void LLPanelMediaSettingsGeneral::updateMediaPreview()
mPreviewMedia->navigateTo( mHomeURL->getValue().asString() );
}
else
- // new home URL will be empty if media is deleted but
- // we still need to clean out the preview.
+ // new home URL will be empty if media is deleted so display a
+ // "preview goes here" data url page
{
- mPreviewMedia->unloadMediaSource();
+ mPreviewMedia->navigateTo( "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" );
};
}
@@ -353,6 +351,16 @@ void LLPanelMediaSettingsGeneral::onClose(bool app_quitting)
void LLPanelMediaSettingsGeneral::onCommitHomeURL( LLUICtrl* ctrl, void *userdata )
{
LLPanelMediaSettingsGeneral* self =(LLPanelMediaSettingsGeneral *)userdata;
+
+ // check url user is trying to enter for home URL will pass whitelist
+ // and decline to accept it if it doesn't.
+ std::string home_url = self->mHomeURL->getValue().asString();
+ if ( ! self->mParent->passesWhiteList( home_url ) )
+ {
+ LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
+ return;
+ };
+
self->updateMediaPreview();
}
@@ -382,14 +390,12 @@ void LLPanelMediaSettingsGeneral::apply( void* userdata )
//
void LLPanelMediaSettingsGeneral::getValues( LLSD &fill_me_in )
{
- fill_me_in[LLMediaEntry::ALT_IMAGE_ENABLE_KEY] = mAltImageEnable->getValue();
fill_me_in[LLMediaEntry::AUTO_LOOP_KEY] = mAutoLoop->getValue();
fill_me_in[LLMediaEntry::AUTO_PLAY_KEY] = mAutoPlay->getValue();
fill_me_in[LLMediaEntry::AUTO_SCALE_KEY] = mAutoScale->getValue();
fill_me_in[LLMediaEntry::AUTO_ZOOM_KEY] = mAutoZoom->getValue();
fill_me_in[LLMediaEntry::CONTROLS_KEY] = mControls->getCurrentIndex();
- // XXX Don't send current URL!
- //fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
+ fill_me_in[LLMediaEntry::CURRENT_URL_KEY] = mCurrentURL->getValue();
fill_me_in[LLMediaEntry::HEIGHT_PIXELS_KEY] = mHeightPixels->getValue();
fill_me_in[LLMediaEntry::HOME_URL_KEY] = mHomeURL->getValue();
fill_me_in[LLMediaEntry::FIRST_CLICK_INTERACT_KEY] = mFirstClick->getValue();
@@ -438,3 +444,10 @@ bool LLPanelMediaSettingsGeneral::navigateHomeSelectedFace()
return all_face_media_navigated;
}
+////////////////////////////////////////////////////////////////////////////////
+//
+const std::string LLPanelMediaSettingsGeneral::getHomeUrl()
+{
+ return mHomeURL->getValue().asString();
+}
+
diff --git a/indra/newview/llpanelmediasettingsgeneral.h b/indra/newview/llpanelmediasettingsgeneral.h
index 1b60909786..e82a31382e 100644
--- a/indra/newview/llpanelmediasettingsgeneral.h
+++ b/indra/newview/llpanelmediasettingsgeneral.h
@@ -64,6 +64,8 @@ public:
bool navigateHomeSelectedFace();
void updateMediaPreview();
void updateCurrentURL();
+
+ const std::string getHomeUrl();
protected:
LLFloaterMediaSettings* mParent;
@@ -76,7 +78,6 @@ private:
LLComboBox* mControls;
LLCheckBoxCtrl* mAutoLoop;
LLCheckBoxCtrl* mFirstClick;
-// LLTextureCtrl* mMediaPreview;
LLCheckBoxCtrl* mAutoZoom;
LLCheckBoxCtrl* mAutoPlay;
LLCheckBoxCtrl* mAutoScale;
@@ -84,7 +85,6 @@ private:
LLSpinCtrl* mHeightPixels;
LLLineEditor* mHomeURL;
LLLineEditor* mCurrentURL;
- LLCheckBoxCtrl* mAltImageEnable;
LLMediaCtrl* mPreviewMedia;
};
diff --git a/indra/newview/llpanelmediasettingssecurity.cpp b/indra/newview/llpanelmediasettingssecurity.cpp
index cea105d7de..3577f63340 100644
--- a/indra/newview/llpanelmediasettingssecurity.cpp
+++ b/indra/newview/llpanelmediasettingssecurity.cpp
@@ -1,255 +1,341 @@
-/**
- * @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 "llfloaterreg.h"
-#include "llpanelmediasettingssecurity.h"
-#include "llpanelcontents.h"
-#include "llcheckboxctrl.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 "llfloaterwhitelistentry.h"
-#include "llfloatermediasettings.h"
-////////////////////////////////////////////////////////////////////////////////
-//
-LLPanelMediaSettingsSecurity::LLPanelMediaSettingsSecurity()
-{
- // build dialog from XML
- LLUICtrlFactory::getInstance()->buildPanel(this, "panel_media_settings_security.xml");
- mCommitCallbackRegistrar.add("Media.whitelistAdd", boost::bind(&LLPanelMediaSettingsSecurity::onBtnAdd, this));
- mCommitCallbackRegistrar.add("Media.whitelistDelete", boost::bind(&LLPanelMediaSettingsSecurity::onBtnDel, this));
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-BOOL LLPanelMediaSettingsSecurity::postBuild()
-{
- mEnableWhiteList = getChild< LLCheckBoxCtrl >( LLMediaEntry::WHITELIST_ENABLE_KEY );
- mWhiteListList = getChild< LLScrollListCtrl >( LLMediaEntry::WHITELIST_KEY );
-
- childSetAction("whitelist_add", onBtnAdd, this);
- childSetAction("whitelist_del", onBtnDel, this);
-
- setDefaultBtn("whitelist_add");
-
- return true;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// virtual
-LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
-{
-}
-
-////////////////////////////////////////////////////////////////////////////////
-//
-void LLPanelMediaSettingsSecurity::draw()
-{
- // housekeeping
- LLPanel::draw();
-
- // if list is empty, disable DEL button and checkbox to enable use of list
- if ( mWhiteListList->isEmpty() )
- {
- childSetEnabled( "whitelist_del", false );
- childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
- childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
- }
- else
- {
- childSetEnabled( "whitelist_del", true );
- childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
- childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
- };
-
- // if nothing is selected, disable DEL button
- if ( mWhiteListList->getSelectedValue().asString().empty() )
- {
- childSetEnabled( "whitelist_del", false );
- }
- else
- {
- childSetEnabled( "whitelist_del", true );
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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 [] =
+/**
+ * @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 "llfloaterreg.h"
+#include "llpanelmediasettingssecurity.h"
+#include "llpanelcontents.h"
+#include "llcheckboxctrl.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 "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 );
+
+ setDefaultBtn("whitelist_add");
+
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// virtual
+LLPanelMediaSettingsSecurity::~LLPanelMediaSettingsSecurity()
+{
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::draw()
+{
+ // housekeeping
+ LLPanel::draw();
+
+ // if list is empty, disable DEL button and checkbox to enable use of list
+ if ( mWhiteListList->isEmpty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, false );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ childSetEnabled( LLMediaEntry::WHITELIST_KEY, true );
+ childSetEnabled( LLMediaEntry::WHITELIST_ENABLE_KEY, true );
+ };
+
+ // if nothing is selected, disable DEL button
+ if ( mWhiteListList->getSelectedValue().asString().empty() )
+ {
+ childSetEnabled( "whitelist_del", false );
+ }
+ else
+ {
+ childSetEnabled( "whitelist_del", true );
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 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() )
+ {
+ // TODO: is iter guaranteed to be valid here?
+ std::string url = *iter;
+ list->addSimpleElement( url );
+ ++iter;
+ };
+ };
+ data_set[ i ].ctrl_ptr->setEnabled(editable);
+ data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
+ };
+ };
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// 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);
+}
+////////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::apply( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ // build LLSD Fragment
+ LLSD media_data_security;
+ self->getValues(media_data_security);
+ // this merges contents of LLSD passed in with what's there so this is ok
+ LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
+}
+
+////////////////////////////////////////////////////////////////////////////////
+//
+void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
+{
+ fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
+
+ // iterate over white list and extract items
+ std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+ fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
+ while( iter != white_list_items.end() )
+ {
+ std::string white_list_url = (*iter)->getValue().asString();
+ fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
+ ++iter;
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// 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() )
{
- { LLMediaEntry::WHITELIST_ENABLE_KEY, self->mEnableWhiteList, "LLCheckBoxCtrl" },
- { LLMediaEntry::WHITELIST_KEY, self->mWhiteListList, "LLScrollListCtrl" },
- { "", NULL , "" }
+ // build a URL comprised of default scheme and the original fragment
+ const std::string default_scheme( "http://" );
+ return default_scheme + src_url;
};
- 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() )
- {
- // TODO: is iter guaranteed to be valid here?
- std::string url = *iter;
- list->addSimpleElement( url );
- ++iter;
- };
- };
- data_set[ i ].ctrl_ptr->setEnabled(editable);
- data_set[ i ].ctrl_ptr->setTentative( media_settings[ tentative_key ].asBoolean() );
- };
- };
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// 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);
-}
-////////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::apply( void* userdata )
-{
- LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
-
- // build LLSD Fragment
- LLSD media_data_security;
- self->getValues(media_data_security);
- // this merges contents of LLSD passed in with what's there so this is ok
- LLSelectMgr::getInstance()->selectionSetMediaData( media_data_security );
-}
-
+ // 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. Can also
+// optionally pass the URL that you are trying to add to the widget since
+// it won't be added until this call returns.
+bool LLPanelMediaSettingsSecurity::passesWhiteList( const std::string& added_url,
+ 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* > white_list_items = mWhiteListList->getAllData();
+ std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
+ while( iter != white_list_items.end() )
+ {
+ const std::string whitelist_url = (*iter)->getValue().asString();
+ whitelist_strings.push_back( whitelist_url );
+
+ ++iter;
+ };
+
+ // add in the URL that might be added to the whitelist so we can test that too
+ if ( added_url.length() )
+ whitelist_strings.push_back( added_url );
+
+ // 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::addWhiteListItem(const std::string& url)
+{
+ // grab home URL from the general panel (via the parent floater)
+ std::string home_url( "" );
+ if ( mParent )
+ home_url = mParent->getHomeUrl();
+
+ // if the home URL is blank (user hasn't entered it yet) then
+ // don't bother to check if it passes the white list
+ if ( home_url.empty() )
+ {
+ mWhiteListList->addSimpleElement( url );
+ return;
+ };
+
+ // if the URL passes the white list, add it
+ if ( passesWhiteList( url, home_url ) )
+ {
+ mWhiteListList->addSimpleElement( url );
+ }
+ else
+ // display a message indicating you can't do that
+ {
+ LLNotifications::instance().add("WhiteListInvalidatesHomeUrl");
+ };
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
+{
+ LLFloaterReg::showInstance("whitelist_entry");
+}
+
+///////////////////////////////////////////////////////////////////////////////
+// static
+void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+{
+ LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+
+ self->mWhiteListList->deleteSelectedItems();
+}
+
////////////////////////////////////////////////////////////////////////////////
//
-void LLPanelMediaSettingsSecurity::getValues( LLSD &fill_me_in )
-{
- fill_me_in[LLMediaEntry::WHITELIST_ENABLE_KEY] = mEnableWhiteList->getValue();
-
- // iterate over white list and extract items
- std::vector< LLScrollListItem* > white_list_items = mWhiteListList->getAllData();
- std::vector< LLScrollListItem* >::iterator iter = white_list_items.begin();
- fill_me_in[LLMediaEntry::WHITELIST_KEY].clear();
- while( iter != white_list_items.end() )
- {
- std::string white_list_url = (*iter)->getValue().asString();
- fill_me_in[ LLMediaEntry::WHITELIST_KEY ].append( white_list_url );
- ++iter;
- };
-}
-
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::addWhiteListItem(const std::string& url)
-{
- mWhiteListList->addSimpleElement( url );
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::onBtnAdd( void* userdata )
-{
- LLFloaterReg::showInstance("whitelist_entry");
-}
-
-///////////////////////////////////////////////////////////////////////////////
-// static
-void LLPanelMediaSettingsSecurity::onBtnDel( void* userdata )
+void LLPanelMediaSettingsSecurity::setParent( LLFloaterMediaSettings* parent )
{
- LLPanelMediaSettingsSecurity *self =(LLPanelMediaSettingsSecurity *)userdata;
+ mParent = parent;
+};
- self->mWhiteListList->deleteSelectedItems();
-}
diff --git a/indra/newview/llpanelmediasettingssecurity.h b/indra/newview/llpanelmediasettingssecurity.h
index b7cf67c039..2555bb8dc8 100644
--- a/indra/newview/llpanelmediasettingssecurity.h
+++ b/indra/newview/llpanelmediasettingssecurity.h
@@ -37,6 +37,7 @@
class LLCheckBoxCtrl;
class LLScrollListCtrl;
+class LLFloaterMediaSettings;
class LLPanelMediaSettingsSecurity : public LLPanel
{
@@ -52,6 +53,12 @@ class LLPanelMediaSettingsSecurity : public LLPanel
static void initValues( void* userdata, const LLSD& media_settings,bool editable );
static void clearValues( void* userdata, bool editable);
void addWhiteListItem(const std::string& url);
+ void setParent( LLFloaterMediaSettings* parent );
+ const std::string makeValidUrl( const std::string& src_url );
+ bool passesWhiteList( const std::string& added_url, const std::string& test_url );
+
+ protected:
+ LLFloaterMediaSettings* mParent;
private:
LLCheckBoxCtrl* mEnableWhiteList;
diff --git a/indra/newview/llpanelobject.h b/indra/newview/llpanelobject.h
index 1ab4ff581e..58d9fe9b76 100644
--- a/indra/newview/llpanelobject.h
+++ b/indra/newview/llpanelobject.h
@@ -45,7 +45,6 @@ class LLUICtrl;
class LLButton;
class LLViewerObject;
class LLComboBox;
-class LLPanelInventory;
class LLColorSwatchCtrl;
class LLTextureCtrl;
class LLInventoryItem;
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
new file mode 100644
index 0000000000..79b33e29f5
--- /dev/null
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -0,0 +1,1927 @@
+/**
+ * @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 "roles_constants.h"
+
+#include "llagent.h"
+#include "llcallbacklist.h"
+#include "llfloaterbuycurrency.h"
+#include "llfloaterreg.h"
+#include "llinventorybridge.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 (LLInventoryItem*)(object->getInventoryObject(mUUID));
+ }
+ return NULL;
+}
+
+void LLTaskInvFVBridge::showProperties()
+{
+ LLSD key;
+ key["object"] = mPanel->getTaskUUID();
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ /*
+ 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() )
+ {
+ LLNotifications::instance().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"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_MODIFY) ? "PermYes" : "PermNo");
+ args["COPYPERM"] = LLNotifications::instance().getGlobalString((next_owner_mask & PERM_COPY) ? "PermYes" : "PermNo");
+ args["RESELLPERM"] = LLNotifications::instance().getGlobalString((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;
+ LLNotifications::instance().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 = LLNotification::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 = LLNotification::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 llinevntorybridge.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);
+ LLNotifications::instance().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());
+ }
+ LLNotifications::instance().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 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;
+ }
+ LLLiveLSLEditor* preview = LLFloaterReg::showTypedInstance<LLLiveLSLEditor>("preview_scriptedit", LLSD(mUUID), TAKE_FOCUS_YES);
+ if (preview && (object->permModify() || gAgent.isGodlike()))
+ {
+ preview->setObjectID(mPanel->getTaskUUID());
+ }
+}
+
+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;
+ 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;
+}
+
+// *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;
+ 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;
+ 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());
+ 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();
+ }
+}
diff --git a/indra/newview/llpanelobjectinventory.h b/indra/newview/llpanelobjectinventory.h
new file mode 100644
index 0000000000..6722bb212e
--- /dev/null
+++ b/indra/newview/llpanelobjectinventory.h
@@ -0,0 +1,102 @@
+/**
+ * @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);
+
+ 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/llpanelpeople.cpp b/indra/newview/llpanelpeople.cpp
index c94c38983d..65a7b5322b 100644
--- a/indra/newview/llpanelpeople.cpp
+++ b/indra/newview/llpanelpeople.cpp
@@ -42,6 +42,7 @@
#include "llpanelpeople.h"
// newview
+#include "llaccordionctrl.h"
#include "llaccordionctrltab.h"
#include "llagent.h"
#include "llavataractions.h"
@@ -87,7 +88,39 @@ protected:
}
};
+/** 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;
+ }
+};
+
static const LLAvatarItemRecentComparator RECENT_COMPARATOR;
+static const LLAvatarItemStatusComparator STATUS_COMPARATOR;
static LLRegisterPanelClassWrapper<LLPanelPeople> t_people("panel_people");
@@ -381,13 +414,17 @@ BOOL LLPanelPeople::postBuild()
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"));
@@ -395,7 +432,8 @@ BOOL LLPanelPeople::postBuild()
mNearbyList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
mRecentList->setContextMenu(&LLPanelPeopleMenus::gNearbyMenu);
- mRecentList->setComparator(&RECENT_COMPARATOR);
+ setSortOrder(mRecentList, (ESortOrder)gSavedSettings.getU32("RecentPeopleSortOrder"), false);
+ setSortOrder(mAllFriendList, (ESortOrder)gSavedSettings.getU32("FriendsSortOrder"), false);
LLPanel* groups_panel = getChild<LLPanel>(GROUP_TAB_NAME);
groups_panel->childSetAction("activate_btn", boost::bind(&LLPanelPeople::onActivateButtonClicked, this));
@@ -416,7 +454,7 @@ BOOL LLPanelPeople::postBuild()
mNearbyList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mNearbyList));
mRecentList->setCommitCallback(boost::bind(&LLPanelPeople::onAvatarListCommitted, this, mRecentList));
- mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onGroupInfoButtonClicked, this));
+ mGroupList->setDoubleClickCallback(boost::bind(&LLPanelPeople::onChatButtonClicked, this));
mGroupList->setCommitCallback(boost::bind(&LLPanelPeople::updateButtons, this));
LLAccordionCtrlTab* accordion_tab = getChild<LLAccordionCtrlTab>("tab_all");
@@ -446,12 +484,16 @@ BOOL LLPanelPeople::postBuild()
// 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.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.Friends.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onFriendsViewSortMenuItemCheck, this, _2));
+ enable_registrar.add("People.Recent.ViewSort.CheckItem", boost::bind(&LLPanelPeople::onRecentViewSortMenuItemCheck, this, _2));
LLMenuGL* plus_menu = LLUICtrlFactory::getInstance()->createFromFile<LLMenuGL>("menu_group_plus.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
mGroupPlusMenuHandle = plus_menu->getHandle();
@@ -475,6 +517,9 @@ BOOL LLPanelPeople::postBuild()
// 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;
}
@@ -519,6 +564,8 @@ void LLPanelPeople::updateFriendList()
mOnlineFriendList->setDirty();
mAllFriendList->setDirty();
+
+ showFriendsAccordionsIfNeeded();
}
void LLPanelPeople::updateNearbyList()
@@ -574,6 +621,10 @@ void LLPanelPeople::updateButtons()
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);
+
buttonSetVisible("group_info_btn", group_tab_active);
buttonSetVisible("chat_btn", group_tab_active);
buttonSetVisible("add_friend_btn", nearby_tab_active || recent_tab_active);
@@ -584,7 +635,6 @@ void LLPanelPeople::updateButtons()
if (group_tab_active)
{
- bool item_selected = mGroupList->getSelectedItem() != NULL;
bool cur_group_active = true;
if (item_selected)
@@ -592,7 +642,7 @@ void LLPanelPeople::updateButtons()
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("plus_btn", item_selected);
@@ -603,18 +653,18 @@ void LLPanelPeople::updateButtons()
bool is_friend = true;
// Check whether selected avatar is our friend.
- if ((selected_id = getCurrentItemID()).notNull())
+ if (item_selected)
{
+ selected_id = selected_uuids.front();
is_friend = LLAvatarTracker::instance().getBuddyInfo(selected_id) != NULL;
}
childSetEnabled("add_friend_btn", !is_friend);
}
- bool item_selected = selected_id.notNull();
buttonSetEnabled("teleport_btn", friends_tab_active && item_selected);
buttonSetEnabled("view_profile_btn", item_selected);
- buttonSetEnabled("im_btn", item_selected);
+ buttonSetEnabled("im_btn", (selected_uuids.size() >= 1)); // allow starting the friends conference for multiple selection
buttonSetEnabled("call_btn", item_selected && false); // not implemented yet
buttonSetEnabled("share_btn", item_selected && false); // not implemented yet
buttonSetEnabled("group_info_btn", item_selected);
@@ -653,6 +703,27 @@ LLUUID LLPanelPeople::getCurrentItemID() const
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.
@@ -672,6 +743,42 @@ void LLPanelPeople::showGroupMenu(LLMenuGL* menu)
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;
+ 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"; // *TODO: unused by current implementation
+
+ if (!setting.empty())
+ gSavedSettings.setU32(setting, order);
+ }
+}
+
void LLPanelPeople::onVisibilityChange(const LLSD& new_visibility)
{
if (new_visibility.asBoolean() == FALSE)
@@ -696,14 +803,15 @@ void LLPanelPeople::reSelectedCurrentTab()
void LLPanelPeople::onFilterEdit(const std::string& search_string)
{
- if (mFilterSubString == search_string)
- return;
+ std::string search_upper = search_string;
+ // Searches are case-insensitive
+ LLStringUtil::toUpper(search_upper);
+ LLStringUtil::trimHead(search_upper);
- mFilterSubString = search_string;
+ if (mFilterSubString == search_upper)
+ return;
- // Searches are case-insensitive
- LLStringUtil::toUpper(mFilterSubString);
- LLStringUtil::trimHead(mFilterSubString);
+ mFilterSubString = search_upper;
// Apply new filter.
mNearbyList->setNameFilter(mFilterSubString);
@@ -711,6 +819,8 @@ void LLPanelPeople::onFilterEdit(const std::string& search_string)
mAllFriendList->setNameFilter(mFilterSubString);
mRecentList->setNameFilter(mFilterSubString);
mGroupList->setNameFilter(mFilterSubString);
+
+ showFriendsAccordionsIfNeeded();
}
void LLPanelPeople::onTabSelected(const LLSD& param)
@@ -783,7 +893,17 @@ void LLPanelPeople::onAddFriendWizButtonClicked()
void LLPanelPeople::onDeleteFriendButtonClicked()
{
- LLAvatarActions::removeFriendDialog(getCurrentItemID());
+ 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()
@@ -800,10 +920,17 @@ void LLPanelPeople::onChatButtonClicked()
void LLPanelPeople::onImButtonClicked()
{
- LLUUID id = getCurrentItemID();
- if (id.notNull())
+ 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 )
{
- LLAvatarActions::startIM(id);
+ // for multiple selection start up friends conference
+ LLAvatarActions::startConference(selected_uuids);
}
}
@@ -854,15 +981,16 @@ void LLPanelPeople::onFriendsViewSortMenuItemClicked(const LLSD& userdata)
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")
{
- }
- else if (chosen_item == "organize_offline")
- {
+ mAllFriendList->toggleIcons();
+ mOnlineFriendList->toggleIcons();
}
}
@@ -889,6 +1017,7 @@ void LLPanelPeople::onNearbyViewSortMenuItemClicked(const LLSD& userdata)
}
else if (chosen_item == "view_icons")
{
+ mNearbyList->toggleIcons();
}
else if (chosen_item == "sort_distance")
{
@@ -900,18 +1029,44 @@ void LLPanelPeople::onRecentViewSortMenuItemClicked(const LLSD& userdata)
if (chosen_item == "sort_recent")
{
- mRecentList->setComparator(&RECENT_COMPARATOR);
- mRecentList->sort();
+ setSortOrder(mRecentList, E_SORT_BY_MOST_RECENT);
}
else if (chosen_item == "sort_name")
{
- mRecentList->sortByName();
+ 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()
{
// *TODO: not implemented yet
@@ -975,3 +1130,49 @@ void LLPanelPeople::onOpen(const LLSD& key)
else
reSelectedCurrentTab();
}
+
+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)
+ {
+ // 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();
+}
diff --git a/indra/newview/llpanelpeople.h b/indra/newview/llpanelpeople.h
index 03802015ce..9bf9befe90 100644
--- a/indra/newview/llpanelpeople.h
+++ b/indra/newview/llpanelpeople.h
@@ -57,6 +57,13 @@ public:
class Updater;
private:
+
+ typedef enum e_sort_oder {
+ E_SORT_BY_NAME = 0,
+ E_SORT_BY_STATUS = 1,
+ E_SORT_BY_MOST_RECENT = 2,
+ } ESortOrder;
+
// methods indirectly called by the updaters
void updateFriendList();
void updateNearbyList();
@@ -65,10 +72,12 @@ private:
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);
@@ -104,6 +113,9 @@ private:
void onGroupsViewSortMenuItemClicked(const LLSD& userdata);
void onRecentViewSortMenuItemClicked(const LLSD& userdata);
+ bool onFriendsViewSortMenuItemCheck(const LLSD& userdata);
+ bool onRecentViewSortMenuItemCheck(const LLSD& userdata);
+
// misc callbacks
static void onAvatarPicked(
const std::vector<std::string>& names,
@@ -112,6 +124,12 @@ private:
void onFriendsAccordionExpandedCollapsed(const LLSD& param, LLAvatarList* avatar_list);
+ void showAccordion(const std::string name, bool show);
+
+ void showFriendsAccordionsIfNeeded();
+
+ void onFriendListRefreshComplete(LLUICtrl*ctrl, const LLSD& param);
+
LLFilterEditor* mFilterEditor;
LLTabContainer* mTabContainer;
LLAvatarList* mOnlineFriendList;
diff --git a/indra/newview/llpanelpeoplemenus.cpp b/indra/newview/llpanelpeoplemenus.cpp
index 0e88058bb1..aaf6849fe9 100644
--- a/indra/newview/llpanelpeoplemenus.cpp
+++ b/indra/newview/llpanelpeoplemenus.cpp
@@ -55,7 +55,7 @@ ContextMenu::ContextMenu()
{
}
-void ContextMenu::show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y)
+void ContextMenu::show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y)
{
if (mMenu)
{
@@ -67,9 +67,16 @@ void ContextMenu::show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y)
mMenu->setParent(NULL);
}
delete mMenu;
+ mMenu = NULL;
+ mUUIDs.clear();
}
- mID = id;
+ 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);
@@ -80,47 +87,92 @@ void ContextMenu::show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y)
LLContextMenu* NearbyMenu::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;
LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
- registrar.add("Avatar.Profile", boost::bind(&LLAvatarActions::showProfile, mID));
- registrar.add("Avatar.AddFriend", boost::bind(&LLAvatarActions::requestFriendshipDialog, mID));
- registrar.add("Avatar.IM", boost::bind(&LLAvatarActions::startIM, mID));
- registrar.add("Avatar.Call", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented
- registrar.add("Avatar.OfferTeleport", boost::bind(&NearbyMenu::offerTeleport, this));
- registrar.add("Avatar.ShowOnMap", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented
- registrar.add("Avatar.Share", boost::bind(&LLAvatarActions::startIM, mID)); // *TODO: unimplemented
- registrar.add("Avatar.Pay", boost::bind(&LLAvatarActions::pay, mID));
- registrar.add("Avatar.BlockUnblock", boost::bind(&LLAvatarActions::toggleBlock, mID));
-
- 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());
+ 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::startIM, id)); // *TODO: unimplemented
+ 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::startIM, id)); // *TODO: unimplemented
+ 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::startConference, mUUIDs)); // *TODO: unimplemented
+ // 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(mID, firstname, lastname);
+ gCacheName->getName(id, firstname, lastname);
bool is_linden = !LLStringUtil::compareStrings(lastname, "Linden");
- bool is_self = mID == gAgentID;
+ bool is_self = id == gAgentID;
return !is_self && !is_linden;
}
else if (item == std::string("can_add"))
{
- return !LLAvatarActions::isFriend(mID);
+ // 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"))
{
- return LLAvatarActions::isFriend(mID);
+ const LLUUID& id = mUUIDs.front();
+ return LLAvatarActions::isFriend(id);
}
return false;
@@ -129,10 +181,11 @@ bool NearbyMenu::enableContextMenuItem(const LLSD& userdata)
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(mID);
+ return LLAvatarActions::isBlocked(id);
}
return false;
@@ -142,7 +195,8 @@ void NearbyMenu::offerTeleport()
{
// boost::bind cannot recognize overloaded method LLAvatarActions::offerTeleport(),
// so we have to use a wrapper.
- LLAvatarActions::offerTeleport(mID);
+ const LLUUID& id = mUUIDs.front();
+ LLAvatarActions::offerTeleport(id);
}
} // namespace LLPanelPeopleMenus
diff --git a/indra/newview/llpanelpeoplemenus.h b/indra/newview/llpanelpeoplemenus.h
index 0012ac38f8..ed0f8208f6 100644
--- a/indra/newview/llpanelpeoplemenus.h
+++ b/indra/newview/llpanelpeoplemenus.h
@@ -49,17 +49,17 @@ public:
/**
* Show the menu at specified coordinates.
- *
- * @param id either avatar or group id
+ *
+ * @param uuids - an array of avatar or group ids
*/
- /*virtual*/ void show(LLView* spawning_view, const LLUUID& id, S32 x, S32 y);
+ /*virtual*/ void show(LLView* spawning_view, const std::vector<LLUUID>& uuids, S32 x, S32 y);
protected:
virtual LLContextMenu* createMenu() = 0;
- LLUUID mID;
- LLContextMenu* mMenu;
+ std::vector<LLUUID> mUUIDs;
+ LLContextMenu* mMenu;
};
/**
diff --git a/indra/newview/llpanelpick.cpp b/indra/newview/llpanelpick.cpp
index 424e453a2f..f5c4f89702 100644
--- a/indra/newview/llpanelpick.cpp
+++ b/indra/newview/llpanelpick.cpp
@@ -38,13 +38,16 @@
#include "llpanel.h"
#include "message.h"
#include "llagent.h"
+#include "llagentpicksinfo.h"
#include "llbutton.h"
+#include "lliconctrl.h"
#include "lllineeditor.h"
#include "llparcel.h"
#include "llviewerparcelmgr.h"
#include "lltexteditor.h"
#include "lltexturectrl.h"
#include "lluiconstants.h"
+#include "llviewerregion.h"
#include "llworldmap.h"
#include "llfloaterworldmap.h"
#include "llfloaterreg.h"
@@ -60,6 +63,7 @@
#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]"
@@ -68,265 +72,161 @@
std::string SET_LOCATION_NOTICE("(will update after save)");
-LLPanelPick::LLPanelPick(BOOL edit_mode/* = FALSE */)
-: LLPanel(), LLAvatarPropertiesObserver(), LLRemoteParcelInfoObserver(),
- mEditMode(edit_mode),
- mSnapshotCtrl(NULL),
- mPickId(LLUUID::null),
- mCreatorId(LLUUID::null),
- mDataReceived(FALSE),
- mIsPickNew(false),
- mLocationChanged(false)
-{
- if (edit_mode)
- {
- LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
- LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
- }
- else
- {
- LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
- }
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//static
+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)
{
- if (mCreatorId.notNull()) LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
}
-void LLPanelPick::reset()
+LLPanelPickInfo::~LLPanelPickInfo()
{
- setEditMode(FALSE);
-
- mPickId.setNull();
- mCreatorId.setNull();
- mParcelId.setNull();
-
- setPickName("");
- setPickDesc("");
- setPickLocation("");
- mSnapshotCtrl->setImageAssetID(LLUUID::null);
-
- //*HACK just setting asset id to NULL not enough to clear
- //the texture controls, w/o setValid(FALSE) it continues to
- //draw the previously set image
- mSnapshotCtrl->setValid(FALSE);
-
- mDataReceived = FALSE;
-
- mPosGlobal.clearVec();
-
- childSetValue("maturity", "");
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
}
-BOOL LLPanelPick::postBuild()
+void LLPanelPickInfo::onOpen(const LLSD& key)
{
- mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
-
- if (mEditMode)
+ LLUUID avatar_id = key["avatar_id"];
+ if(avatar_id.isNull())
{
- enableSaveButton(FALSE);
-
- mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
-
- LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
- line_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1), NULL);
-
- LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
- text_edit->setKeystrokeCallback(boost::bind(&LLPanelPick::onPickChanged, this, _1));
-
- childSetAction("cancel_btn", boost::bind(&LLPanelPick::onClickCancel, this));
- childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPick::onClickSet, this));
- childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPick::onClickSave, this));
-
- mSnapshotCtrl->setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", true));
- mSnapshotCtrl->setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "edit_icon", false));
- }
- else
- {
- childSetAction("edit_btn", boost::bind(&LLPanelPick::onClickEdit, this));
- childSetAction("teleport_btn", boost::bind(&LLPanelPick::onClickTeleport, this));
- childSetAction("show_on_map_btn", boost::bind(&LLPanelPick::onClickMap, this));
-
+ return;
}
- // EXT-822. We have to process "Back" button click in both Edit & View Modes
- if (!mBackCb.empty())
+ if(getAvatarId().notNull())
{
- LLButton* button = findChild<LLButton>("back_btn");
- if (button) button->setClickedCallback(mBackCb);
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(
+ getAvatarId(), this);
}
- return TRUE;
-}
-
-void LLPanelPick::init(LLUUID creator_id, LLUUID pick_id)
-{
- mCreatorId = creator_id;
- mPickId = pick_id;
+ setAvatarId(avatar_id);
- //*TODO consider removing this, already called by setEditMode()
- updateButtons();
+ resetData();
+ resetControls();
- requestData();
-}
+ setPickId(key["pick_id"]);
+ setPickName(key["pick_name"]);
+ setPickDesc(key["pick_desc"]);
+ setSnapshotId(key["snapshot_id"]);
-void LLPanelPick::requestData()
-{
- mDataReceived = FALSE;
- LLAvatarPropertiesProcessor::instance().addObserver(mCreatorId, this);
- LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorId, mPickId);
+ LLAvatarPropertiesProcessor::getInstance()->addObserver(
+ getAvatarId(), this);
+ LLAvatarPropertiesProcessor::getInstance()->sendPickInfoRequest(
+ getAvatarId(), getPickId());
}
-void LLPanelPick::init(LLPickData *pick_data)
+BOOL LLPanelPickInfo::postBuild()
{
- mPickId = pick_data->pick_id;
- mCreatorId = pick_data->creator_id;
-
- setPickName(pick_data->name);
- setPickDesc(pick_data->desc);
-
- mSnapshotCtrl->setImageAssetID(pick_data->snapshot_id);
-
- //*HACK see reset() where the texture control was set to FALSE
- mSnapshotCtrl->setValid(TRUE);
-
- mPosGlobal = pick_data->pos_global;
- mSimName = pick_data->sim_name;
- mParcelId = pick_data->parcel_id;
-
- setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name,
- pick_data->sim_name, pick_data->pos_global));
-}
-
-void LLPanelPick::prepareNewPick(const LLVector3d pos_global,
- const std::string& name,
- const std::string& desc,
- const LLUUID& snapshot_id,
- const LLUUID& parcel_id)
-{
- mPickId.generate();
- mCreatorId = gAgent.getID();
- mPosGlobal = pos_global;
- setPickName(name);
- setPickDesc(desc);
- mSnapshotCtrl->setImageAssetID(snapshot_id);
- mParcelId = parcel_id;
-
- setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, name, pos_global));
+ mSnapshotCtrl = getChild<LLTextureCtrl>(XML_SNAPSHOT);
childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Pick"));
- mIsPickNew = true;
+ 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));
+
+ return TRUE;
}
-// Fill in some reasonable defaults for a new pick.
-void LLPanelPick::prepareNewPick()
+void LLPanelPickInfo::processProperties(void* data, EAvatarProcessorType type)
{
- // Try to fill in the current parcel
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (parcel)
+ if(APT_PICK_INFO != type)
{
- prepareNewPick(gAgent.getPositionGlobal(),
- parcel->getName(),
- parcel->getDesc(),
- parcel->getSnapshotID(),
- parcel->getID());
+ return;
}
-}
-
-/*virtual*/ void LLPanelPick::processProperties(void* data, EAvatarProcessorType type)
-{
- if (APT_PICK_INFO != type) return;
- if (!data) return;
-
- LLPickData* pick_data = static_cast<LLPickData *>(data);
- if (!pick_data) return;
- if (mPickId != pick_data->pick_id) return;
-
- init(pick_data);
- mDataReceived = TRUE;
- LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorId, this);
-
- if (!mEditMode)
+ LLPickData* pick_info = static_cast<LLPickData*>(data);
+ if(!pick_info
+ || pick_info->creator_id != getAvatarId()
+ || pick_info->pick_id != getPickId())
{
- LLRemoteParcelInfoProcessor::getInstance()->addObserver(pick_data->parcel_id, this);
- LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(pick_data->parcel_id);
+ return;
}
-}
+ setSnapshotId(pick_info->snapshot_id);
+ setPickName(pick_info->name);
+ setPickDesc(pick_info->desc);
+ setPosGlobal(pick_info->pos_global);
+ setPickLocation(createLocationText(pick_info->user_name, pick_info->original_name,
+ pick_info->sim_name, pick_info->pos_global));
-void LLPanelPick::setEditMode( BOOL edit_mode )
-{
- if (mEditMode == edit_mode) return;
- mEditMode = edit_mode;
-
- // preserve data before killing controls
- LLUUID snapshot_id = mSnapshotCtrl->getImageAssetID();
- LLRect old_rect = getRect();
-
- deleteAllChildren();
+ // *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
+}
- // *WORKAROUND: for EXT-931. Children are created for both XML_PANEL_EDIT_PICK & XML_PANEL_PICK_INFO files
- // The reason is in LLPanel::initPanelXML called from the LLUICtrlFactory::buildPanel().
- // It creates children from the xml file stored while previous initializing in the "mXMLFilename" member
- // and then in creates children from the parameters passed from the LLUICtrlFactory::buildPanel().
- // Xml filename is stored after LLPanel::initPanelXML is called (added with export-from-ll/viewer-2-0, r1594 into LLUICtrlFactory::buildPanel & LLUICtrlFactory::buildFloater)
- // In case panel creates children from the different xml files they appear from both files.
- // So, let clear xml filename related to this instance.
- setXMLFilename("");
+void LLPanelPickInfo::setExitCallback(const commit_callback_t& cb)
+{
+ getChild<LLButton>("back_btn")->setClickedCallback(cb);
+}
- if (edit_mode)
+void LLPanelPickInfo::processParcelInfo(const LLParcelData& parcel_data)
+{
+ // HACK: Flag 0x2 == adult region,
+ // Flag 0x1 == mature region, otherwise assume PG
+ std::string rating_icon = "icon_event.tga";
+ if (parcel_data.flags & 0x2)
{
- LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_EDIT_PICK);
+ rating_icon = "icon_event_adult.tga";
}
- else
+ else if (parcel_data.flags & 0x1)
{
- LLUICtrlFactory::getInstance()->buildPanel(this, XML_PANEL_PICK_INFO);
+ rating_icon = "icon_event_mature.tga";
}
- //*NOTE this code is from LLPanelMeProfile.togglePanel()... doubt this is a right way to do things
- reshape(old_rect.getWidth(), old_rect.getHeight());
- old_rect.setLeftTopAndSize(0, old_rect.getHeight(), old_rect.getWidth(), old_rect.getHeight());
- setRect(old_rect);
-
- // time to restore data
- setPickName(mName);
- setPickDesc(mDesc);
- setPickLocation(mLocation);
- mSnapshotCtrl->setImageAssetID(snapshot_id);
+ childSetValue("maturity", rating_icon);
- updateButtons();
+ //*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
}
-void LLPanelPick::onPickChanged(LLUICtrl* ctrl)
+void LLPanelPickInfo::setEditPickCallback(const commit_callback_t& cb)
{
- if(mLocationChanged)
- {
- // Pick was enabled in onClickSet
- return;
- }
+ getChild<LLButton>("edit_btn")->setClickedCallback(cb);
+}
- if( mSnapshotCtrl->isDirty()
- || getChild<LLLineEditor>("pick_name")->isDirty()
- || getChild<LLTextEditor>("pick_desc")->isDirty() )
+// PROTECTED AREA
+
+void LLPanelPickInfo::resetControls()
+{
+ if(getAvatarId() == gAgent.getID())
{
- enableSaveButton(TRUE);
+ childSetEnabled("edit_btn", TRUE);
+ childSetVisible("edit_btn", TRUE);
}
else
{
- enableSaveButton(FALSE);
+ childSetEnabled("edit_btn", FALSE);
+ childSetVisible("edit_btn", FALSE);
}
}
-//////////////////////////////////////////////////////////////////////////
-// PROTECTED AREA
-//////////////////////////////////////////////////////////////////////////
+void LLPanelPickInfo::resetData()
+{
+ setPickName(LLStringUtil::null);
+ setPickDesc(LLStringUtil::null);
+ setPickLocation(LLStringUtil::null);
+ setPickId(LLUUID::null);
+ setSnapshotId(LLUUID::null);
+ mPosGlobal.clearVec();
+ childSetValue("maturity", LLStringUtil::null);
+}
-//static
-std::string LLPanelPick::createLocationText(const std::string& owner_name, const std::string& original_name,
- const std::string& sim_name, const LLVector3d& pos_global)
+// static
+std::string LLPanelPickInfo::createLocationText(const std::string& owner_name, const std::string& original_name, const std::string& sim_name, const LLVector3d& pos_global)
{
std::string location_text;
location_text.append(owner_name);
@@ -354,23 +254,23 @@ std::string LLPanelPick::createLocationText(const std::string& owner_name, const
return location_text;
}
-void LLPanelPick::setPickName(std::string name)
+void LLPanelPickInfo::setSnapshotId(const LLUUID& id)
+{
+ mSnapshotCtrl->setImageAssetID(id);
+ mSnapshotCtrl->setValid(TRUE);
+}
+
+void LLPanelPickInfo::setPickName(const std::string& name)
{
childSetValue(XML_NAME, name);
-
- //preserving non-wrapped text for info/edit modes switching
- mName = name;
}
-void LLPanelPick::setPickDesc(std::string desc)
+void LLPanelPickInfo::setPickDesc(const std::string& desc)
{
childSetValue(XML_DESC, desc);
-
- //preserving non-wrapped text for info/edit modes switching
- mDesc = desc;
}
-void LLPanelPick::setPickLocation(const std::string& location)
+void LLPanelPickInfo::setPickLocation(const std::string& location)
{
childSetValue(XML_LOCATION, location);
@@ -378,208 +278,294 @@ void LLPanelPick::setPickLocation(const std::string& location)
mLocation = location;
}
-std::string LLPanelPick::getPickName()
+void LLPanelPickInfo::onClickMap()
{
- return childGetValue(XML_NAME).asString();
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+ LLFloaterReg::showInstance("world_map", "center");
}
-std::string LLPanelPick::getPickDesc()
+void LLPanelPickInfo::onClickTeleport()
{
- return childGetValue(XML_DESC).asString();
+ if (!getPosGlobal().isExactlyZero())
+ {
+ gAgent.teleportViaLocation(getPosGlobal());
+ LLFloaterWorldMap::getInstance()->trackLocation(getPosGlobal());
+ }
}
-std::string LLPanelPick::getPickLocation()
+void LLPanelPickInfo::onClickBack()
{
- return childGetValue(XML_LOCATION).asString();
+ LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(), this);
}
-void LLPanelPick::sendUpdate()
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+
+//static
+LLPanelPickEdit* LLPanelPickEdit::create()
{
- LLPickData pick_data;
+ LLPanelPickEdit* panel = new LLPanelPickEdit();
+ LLUICtrlFactory::getInstance()->buildPanel(panel, XML_PANEL_EDIT_PICK);
+ return panel;
+}
- // 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()) mPickId.generate();
+LLPanelPickEdit::LLPanelPickEdit()
+ : LLPanelPickInfo()
+ , mLocationChanged(false)
+ , mNeedData(true)
+ , mNewPick(false)
+{
+}
- pick_data.agent_id = gAgent.getID();
- pick_data.session_id = gAgent.getSessionID();
- pick_data.pick_id = mPickId;
- pick_data.creator_id = gAgentID;
+LLPanelPickEdit::~LLPanelPickEdit()
+{
+}
- //legacy var need to be deleted
- pick_data.top_pick = FALSE;
- pick_data.parcel_id = mParcelId;
- pick_data.name = getPickName();
- pick_data.desc = getPickDesc();
- pick_data.snapshot_id = mSnapshotCtrl->getImageAssetID();
- pick_data.pos_global = mPosGlobal;
- pick_data.sort_order = 0;
- pick_data.enabled = TRUE;
+void LLPanelPickEdit::onOpen(const LLSD& key)
+{
+ LLUUID pick_id = key["pick_id"];
+ mNeedData = true;
- mDataReceived = FALSE;
- LLAvatarPropertiesProcessor::instance().addObserver(gAgentID, this);
+ // creating new Pick
+ if(pick_id.isNull())
+ {
+ mNewPick = true;
- LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
+ setAvatarId(gAgent.getID());
+
+ resetData();
+ resetControls();
+
+ setPosGlobal(gAgent.getPositionGlobal());
+
+ LLUUID parcel_id = LLUUID::null, snapshot_id = LLUUID::null;
+ std::string pick_name, pick_desc;
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if(parcel)
+ {
+ parcel_id = parcel->getID();
+ pick_name = parcel->getName();
+ pick_desc = parcel->getDesc();
+ snapshot_id = parcel->getSnapshotID();
+ }
+
+ if(pick_name.empty())
+ {
+ LLViewerRegion* region = gAgent.getRegion();
+ if(region)
+ {
+ pick_name = region->getName();
+ }
+ }
+
+ setParcelID(parcel_id);
+ childSetValue("pick_name", pick_name);
+ childSetValue("pick_desc", pick_desc);
+ setSnapshotId(snapshot_id);
+ setPickLocation(createLocationText(LLStringUtil::null, SET_LOCATION_NOTICE,
+ pick_name, getPosGlobal()));
+
+ enableSaveButton(true);
+ }
+ // editing existing pick
+ else
+ {
+ mNewPick = false;
+ LLPanelPickInfo::onOpen(key);
+
+ enableSaveButton(false);
+ }
+
+ resetDirty();
}
+void LLPanelPickEdit::setPickData(const LLPickData* pick_data)
+{
+ if(!pick_data)
+ {
+ return;
+ }
-//-----------------------------------------
-// "PICK INFO" (VIEW MODE) BUTTON HANDLERS
-//-----------------------------------------
+ mNeedData = false;
-//static
-void LLPanelPick::onClickEdit()
+ setParcelID(pick_data->parcel_id);
+ childSetValue("pick_name", pick_data->name);
+ childSetValue("pick_desc", pick_data->desc);
+ setSnapshotId(pick_data->snapshot_id);
+ setPickLocation(createLocationText(pick_data->user_name, pick_data->original_name, /*pick_data->sim_name,*/
+ pick_data->name, pick_data->pos_global));
+}
+
+BOOL LLPanelPickEdit::postBuild()
{
- if (mEditMode) return;
- if (!mDataReceived) return;
- setEditMode(TRUE);
+ LLPanelPickInfo::postBuild();
+
+ mSnapshotCtrl->setOnSelectCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
+
+ LLLineEditor* line_edit = getChild<LLLineEditor>("pick_name");
+ line_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1), NULL);
+
+ LLTextEditor* text_edit = getChild<LLTextEditor>("pick_desc");
+ text_edit->setKeystrokeCallback(boost::bind(&LLPanelPickEdit::onPickChanged, this, _1));
+
+ childSetAction(XML_BTN_SAVE, boost::bind(&LLPanelPickEdit::onClickSave, this));
+ childSetAction("set_to_curr_location_btn", boost::bind(&LLPanelPickEdit::onClickSetLocation, this));
+
+ initTexturePickerMouseEvents();
+
+ return TRUE;
}
-//static
-void LLPanelPick::onClickTeleport()
+void LLPanelPickEdit::setSaveCallback(const commit_callback_t& cb)
{
- teleport(mPosGlobal);
+ getChild<LLButton>("save_changes_btn")->setClickedCallback(cb);
}
-//static
-void LLPanelPick::onClickMap()
+void LLPanelPickEdit::setCancelCallback(const commit_callback_t& cb)
{
- showOnMap(mPosGlobal);
+ getChild<LLButton>("cancel_btn")->setClickedCallback(cb);
}
+void LLPanelPickEdit::resetDirty()
+{
+ LLPanelPickInfo::resetDirty();
-//-----------------------------------------
-// "EDIT PICK" (EDIT MODE) BUTTON HANDLERS
-//-----------------------------------------
+ getChild<LLLineEditor>("pick_name")->resetDirty();
+ getChild<LLTextEditor>("pick_desc")->resetDirty();
+ mSnapshotCtrl->resetDirty();
+ mLocationChanged = false;
+}
-//static
-void LLPanelPick::onClickCancel()
+BOOL LLPanelPickEdit::isDirty() const
{
- if (!mEditMode) return;
-
- if (mIsPickNew)
+ if( LLPanelPickInfo::isDirty()
+ || mLocationChanged
+ || mSnapshotCtrl->isDirty()
+ || getChild<LLLineEditor>("pick_name")->isDirty()
+ || getChild<LLTextEditor>("pick_desc")->isDirty())
{
- mBackCb(this, LLSD());
- return;
+ return TRUE;
}
-
- LLUUID pick_id = mPickId;
- LLUUID creator_id = mCreatorId;
- reset();
- init(creator_id, pick_id);
+ return FALSE;
}
-// static
-void LLPanelPick::onClickSet()
-{
- if (!mEditMode) return;
- if (!mIsPickNew && !mDataReceived) return;
+// PROTECTED AREA
- // Save location for later.
- mPosGlobal = gAgent.getPositionGlobal();
+void LLPanelPickEdit::sendUpdate()
+{
+ LLPickData pick_data;
- LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if (parcel)
+ // 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())
{
- mParcelId = parcel->getID();
- mSimName = parcel->getName();
+ getPickId().generate();
}
- setPickLocation(createLocationText(std::string(""), SET_LOCATION_NOTICE, mSimName, mPosGlobal));
- mLocationChanged = true;
- enableSaveButton(TRUE);
-}
+ pick_data.agent_id = gAgent.getID();
+ pick_data.session_id = gAgent.getSessionID();
+ pick_data.pick_id = getPickId();
+ pick_data.creator_id = gAgent.getID();;
-// static
-void LLPanelPick::onClickSave()
-{
- if (!mEditMode) return;
- if (!mIsPickNew && !mDataReceived) return;
+ //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;
- sendUpdate();
-
- if (mIsPickNew)
+ LLAvatarPropertiesProcessor::instance().sendPickInfoUpdate(&pick_data);
+
+ if(mNewPick)
{
- mBackCb(this, LLSD());
- return;
+ // 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();
}
-
- setEditMode(FALSE);
}
-void LLPanelPick::updateButtons()
+void LLPanelPickEdit::onPickChanged(LLUICtrl* ctrl)
{
-
- // on Pick Info panel (for non-Agent picks) edit_btn should be invisible
- if (mEditMode)
+ if(isDirty())
{
- childSetLabelArg(XML_BTN_SAVE, SAVE_BTN_LABEL, std::string("Changes"));
+ enableSaveButton(true);
}
- else
+ else
{
- if (mCreatorId != gAgentID)
- {
- childSetEnabled("edit_btn", FALSE);
- childSetVisible("edit_btn", FALSE);
- }
- else
- {
- childSetEnabled("edit_btn", TRUE);
- childSetVisible("edit_btn", TRUE);
- }
+ enableSaveButton(false);
}
}
-void LLPanelPick::setExitCallback(commit_callback_t cb)
+void LLPanelPickEdit::resetData()
{
- mBackCb = cb;
- LLButton* button = findChild<LLButton>("back_btn");
- if (button) button->setClickedCallback(mBackCb);
+ LLPanelPickInfo::resetData();
+ mLocationChanged = false;
}
-//static
-void LLPanelPick::teleport(const LLVector3d& position)
+void LLPanelPickEdit::enableSaveButton(bool enable)
{
- if (!position.isExactlyZero())
+ childSetEnabled(XML_BTN_SAVE, enable);
+}
+
+void LLPanelPickEdit::onClickSetLocation()
+{
+ // Save location for later use.
+ setPosGlobal(gAgent.getPositionGlobal());
+
+ LLParcel* parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
+ if (parcel)
{
- gAgent.teleportViaLocation(position);
- LLFloaterWorldMap::getInstance()->trackLocation(position);
+ mParcelId = parcel->getID();
+ mSimName = parcel->getName();
}
+ setPickLocation(createLocationText(
+ LLStringUtil::null, SET_LOCATION_NOTICE, mSimName, getPosGlobal()));
+
+ mLocationChanged = true;
+ enableSaveButton(TRUE);
}
-//static
-void LLPanelPick::showOnMap(const LLVector3d& position)
+void LLPanelPickEdit::onClickSave()
{
- LLFloaterWorldMap::getInstance()->trackLocation(position);
- LLFloaterReg::showInstance("world_map", "center");
+ sendUpdate();
+
+ mLocationChanged = false;
+
+ LLSD params;
+ params["action"] = "save_new_pick";
+ notifyParent(params);
}
-void LLPanelPick::processParcelInfo(const LLParcelData& parcel_data)
+void LLPanelPickEdit::processProperties(void* data, EAvatarProcessorType type)
{
- if (mEditMode) return;
-
- // HACK: Flag 0x2 == adult region,
- // Flag 0x1 == mature region, otherwise assume PG
- std::string rating_icon = "icon_event.tga";
- if (parcel_data.flags & 0x2)
+ if(mNeedData)
{
- rating_icon = "icon_event_adult.tga";
+ LLPanelPickInfo::processProperties(data, type);
}
- else if (parcel_data.flags & 0x1)
- {
- rating_icon = "icon_event_mature.tga";
- }
-
- childSetValue("maturity", rating_icon);
+}
- //*NOTE we don't removeObserver(...) ourselves cause LLRemoveParcelProcessor does it for us
+// 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 LLPanelPick::enableSaveButton(bool enable)
+void LLPanelPickEdit::onTexturePickerMouseLeave(LLUICtrl* ctrl)
{
- if(!mEditMode)
- {
- return;
- }
- childSetEnabled(XML_BTN_SAVE, enable);
+ text_icon->setVisible(FALSE);
}
diff --git a/indra/newview/llpanelpick.h b/indra/newview/llpanelpick.h
index 82cba72bc4..2c0830f2ac 100644
--- a/indra/newview/llpanelpick.h
+++ b/indra/newview/llpanelpick.h
@@ -39,53 +39,47 @@
#include "llpanel.h"
#include "llremoteparcelrequest.h"
+#include "llavatarpropertiesprocessor.h"
+class LLIconCtrl;
class LLTextureCtrl;
class LLMessageSystem;
class LLAvatarPropertiesObserver;
-class LLPanelPick : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
+/**
+ * Panel for displaying Pick Information - snapshot, name, description, etc.
+ */
+class LLPanelPickInfo : public LLPanel, public LLAvatarPropertiesObserver, LLRemoteParcelInfoObserver
{
- LOG_CLASS(LLPanelPick);
+ LOG_CLASS(LLPanelPickInfo);
public:
- LLPanelPick(BOOL edit_mode = FALSE);
- /*virtual*/ ~LLPanelPick();
-
- // switches the panel to the VIEW mode and resets controls
- void reset();
+
+ // Creates new panel
+ static LLPanelPickInfo* create();
- /*virtual*/ BOOL postBuild();
+ virtual ~LLPanelPickInfo();
- // Prepares a new pick, including creating an id, giving a sane
- // initial position, etc (saved on clicking Save Pick button - onClickSave callback).
- void prepareNewPick();
- void prepareNewPick(const LLVector3d pos_global,
- const std::string& name,
- const std::string& desc,
- const LLUUID& snapshot_id,
- const LLUUID& parcel_id);
+ /**
+ * 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);
- //initializes the panel with data of the pick with id = pick_id
- //owned by the avatar with id = creator_id
- void init(LLUUID creator_id, LLUUID pick_id);
+ /*virtual*/ BOOL postBuild();
/*virtual*/ void processProperties(void* data, EAvatarProcessorType type);
- // switches the panel to either View or Edit mode
- void setEditMode(BOOL edit_mode);
-
- void onPickChanged(LLUICtrl* ctrl);
-
- // because this panel works in two modes (edit/view) we are
- // free from managing two panel for editing and viewing picks and so
- // are free from controlling switching between them in the parent panel (e.g. Me Profile)
- // but that causes such a complication that we cannot set a callback for a "Back" button
- // from the parent panel only once, so we have to preserve that callback
- // in the pick panel and set it for the back button everytime postBuild() is called.
- void setExitCallback(commit_callback_t cb);
+ /**
+ * Sets "Back" button click callback
+ */
+ virtual void setExitCallback(const commit_callback_t& cb);
- static void teleport(const LLVector3d& position);
- static void showOnMap(const LLVector3d& position);
+ /**
+ * Sets "Edit" button click callback
+ */
+ virtual void setEditPickCallback(const commit_callback_t& cb);
//This stuff we got from LLRemoteParcelObserver, in the last two we intentionally do nothing
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
@@ -94,63 +88,165 @@ public:
protected:
+ LLPanelPickInfo();
+
+ /**
+ * Resets Pick information
+ */
+ virtual void resetData();
+
+ /**
+ * Resets UI controls (visibility, values)
+ */
+ virtual void resetControls();
+
/**
* "Location text" is actually the owner name, the original
* name that owner gave the parcel, and the location.
*/
- static std::string createLocationText(const std::string& owner_name, const std::string& original_name,
- const std::string& sim_name, const LLVector3d& pos_global);
+ static std::string createLocationText(
+ const std::string& owner_name,
+ const std::string& original_name,
+ const std::string& sim_name,
+ const LLVector3d& pos_global);
+
+ virtual void setAvatarId(const LLUUID& avatar_id) { mAvatarId = avatar_id; }
+ virtual LLUUID& getAvatarId() { return mAvatarId; }
+
+ /**
+ * Sets snapshot id.
+ *
+ * Will mark snapshot control as valid if id is not null.
+ * Will mark snapshot control as invalid if id is null. If null id is a valid value,
+ * you have to manually mark snapshot is valid.
+ */
+ virtual void setSnapshotId(const LLUUID& id);
+
+ virtual void setPickId(const LLUUID& id) { mPickId = id; }
+ virtual LLUUID& getPickId() { return mPickId; }
+
+ virtual void setPickName(const std::string& name);
+
+ virtual void setPickDesc(const std::string& desc);
+
+ virtual void setPickLocation(const std::string& location);
+
+ virtual void setPosGlobal(const LLVector3d& pos) { mPosGlobal = pos; }
+ virtual LLVector3d& getPosGlobal() { return mPosGlobal; }
+
+ /**
+ * Callback for "Map" button, opens Map
+ */
+ void onClickMap();
- void setPickName(std::string name);
- void setPickDesc(std::string desc);
- void setPickLocation(const std::string& location);
+ /**
+ * Callback for "Teleport" button, teleports user to Pick location.
+ */
+ void onClickTeleport();
- std::string getPickName();
- std::string getPickDesc();
- std::string getPickLocation();
+ void onClickBack();
- void sendUpdate();
- void requestData();
+protected:
+
+ LLTextureCtrl* mSnapshotCtrl;
- void init(LLPickData *pick_data);
+ LLUUID mAvatarId;
+ LLVector3d mPosGlobal;
+ LLUUID mParcelId;
+ LLUUID mPickId;
+ std::string mSimName;
+ std::string mLocation;
+};
+
+/**
+ * Panel for creating/editing Pick.
+ */
+class LLPanelPickEdit : public LLPanelPickInfo
+{
+ LOG_CLASS(LLPanelPickEdit);
+public:
- void updateButtons();
+ /**
+ * Creates new panel
+ */
+ static LLPanelPickEdit* create();
- //-----------------------------------------
- // "PICK INFO" (VIEW MODE) BUTTON HANDLERS
- //-----------------------------------------
- void onClickEdit();
- void onClickTeleport();
- void onClickMap();
+ /*virtual*/ ~LLPanelPickEdit();
- //-----------------------------------------
- // "EDIT PICK" (EDIT MODE) BUTTON HANDLERS
- //-----------------------------------------
- void onClickSet();
- void onClickSave();
- void onClickCancel();
+ /*virtual*/ void onOpen(const LLSD& key);
- void enableSaveButton(bool enable);
+ 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 mEditMode;
- LLTextureCtrl* mSnapshotCtrl;
- BOOL mDataReceived;
- bool mIsPickNew;
- LLUUID mPickId;
- LLUUID mCreatorId;
- LLVector3d mPosGlobal;
- LLUUID mParcelId;
- std::string mSimName;
+ LLPanelPickEdit();
- //These strings are used to keep non-wrapped text
- std::string mName;
- std::string mDesc;
- std::string mLocation;
+ /**
+ * Sends Pick properties to server.
+ */
+ void sendUpdate();
+
+ /**
+ * 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:
- commit_callback_t mBackCb;
bool mLocationChanged;
+ bool mNeedData;
+ bool mNewPick;
+
+private:
+
+ void initTexturePickerMouseEvents();
+ void onTexturePickerMouseEnter(LLUICtrl* ctrl);
+ void onTexturePickerMouseLeave(LLUICtrl* ctrl);
+
+private:
+
+ LLIconCtrl* text_icon;
};
#endif // LL_LLPANELPICK_H
diff --git a/indra/newview/llpanelpicks.cpp b/indra/newview/llpanelpicks.cpp
index 979e9618da..2bf04f9681 100644
--- a/indra/newview/llpanelpicks.cpp
+++ b/indra/newview/llpanelpicks.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -33,9 +33,13 @@
#include "llviewerprecompiledheaders.h"
#include "llagent.h"
+#include "llagentpicksinfo.h"
#include "llavatarconstants.h"
#include "llflatlistview.h"
+#include "llfloaterreg.h"
+#include "llfloaterworldmap.h"
#include "lltexturectrl.h"
+#include "lltoggleablemenu.h"
#include "llviewergenericmessage.h" // send_generic_message
#include "llmenugl.h"
#include "llviewermenu.h"
@@ -52,6 +56,7 @@ 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 XML_BTN_OVERFLOW = "overflow_btn";
static const std::string PICK_ID("pick_id");
static const std::string PICK_CREATOR_ID("pick_creator_id");
@@ -68,7 +73,10 @@ LLPanelPicks::LLPanelPicks()
mPopupMenu(NULL),
mProfilePanel(NULL),
mPickPanel(NULL),
- mPicksList(NULL)
+ mPicksList(NULL),
+ mPanelPickInfo(NULL),
+ mPanelPickEdit(NULL),
+ mOverflowMenu(NULL)
{
}
@@ -87,7 +95,12 @@ void* LLPanelPicks::create(void* data /* = NULL */)
void LLPanelPicks::updateData()
{
- LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
+ // Send Picks request only when we need to, not on every onOpen(during tab switch).
+ if(isDirty())
+ {
+ mPicksList->clear();
+ LLAvatarPropertiesProcessor::getInstance()->sendAvatarPicksRequest(getAvatarId());
+ }
}
void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
@@ -130,6 +143,7 @@ void LLPanelPicks::processProperties(void* data, EAvatarProcessorType type)
picture->setMouseUpCallback(boost::bind(&LLPanelPicks::updateButtons, this));
}
+ resetDirty();
LLAvatarPropertiesProcessor::getInstance()->removeObserver(getAvatarId(),this);
updateButtons();
}
@@ -148,25 +162,56 @@ BOOL LLPanelPicks::postBuild()
{
mPicksList = getChild<LLFlatListView>("picks_list");
+ childSetAction(XML_BTN_NEW, boost::bind(&LLPanelPicks::onClickNew, this));
childSetAction(XML_BTN_DELETE, boost::bind(&LLPanelPicks::onClickDelete, this));
-
- childSetAction("teleport_btn", boost::bind(&LLPanelPicks::onClickTeleport, this));
- childSetAction("show_on_map_btn", boost::bind(&LLPanelPicks::onClickMap, this));
-
- childSetAction("info_btn", boost::bind(&LLPanelPicks::onClickInfo, this));
- childSetAction("new_btn", boost::bind(&LLPanelPicks::onClickNew, 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));
+ childSetAction(XML_BTN_OVERFLOW, boost::bind(&LLPanelPicks::onOverflowButtonClicked, this));
- CommitCallbackRegistry::ScopedRegistrar registar;
+ 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 overflow_registar;
+ overflow_registar.add("PicksList.Overflow", boost::bind(&LLPanelPicks::onOverflowMenuItemClicked, this, _2));
+ mOverflowMenu = LLUICtrlFactory::getInstance()->createFromFile<LLToggleableMenu>("menu_picks_overflow.xml", gMenuHolder, LLViewerMenuHolderGL::child_registry_t::instance());
return TRUE;
}
+void LLPanelPicks::onOverflowMenuItemClicked(const LLSD& param)
+{
+ std::string value = param.asString();
+
+ if("info" == value)
+ {
+ onClickInfo();
+ }
+ else if("teleport" == value)
+ {
+ onClickTeleport();
+ }
+ else if("map" == value)
+ {
+ onClickMap();
+ }
+}
+
+void LLPanelPicks::onOverflowButtonClicked()
+{
+ LLRect rect;
+ childGetRect(XML_BTN_OVERFLOW, rect);
+
+ mOverflowMenu->updateParent(LLMenuGL::sMenuContainer);
+ mOverflowMenu->setButtonRect(rect, this);
+ LLMenuGL::showPopup(this, mOverflowMenu, rect.mRight, rect.mTop);
+}
+
void LLPanelPicks::onOpen(const LLSD& key)
{
const LLUUID id(key.asUUID());
@@ -179,8 +224,6 @@ void LLPanelPicks::onOpen(const LLSD& key)
// Disable buttons when viewing profile for first time
if(getAvatarId() != id)
{
- clear();
-
childSetEnabled(XML_BTN_INFO,FALSE);
childSetEnabled(XML_BTN_TELEPORT,FALSE);
childSetEnabled(XML_BTN_SHOW_ON_MAP,FALSE);
@@ -197,9 +240,11 @@ void LLPanelPicks::onOpen(const LLSD& key)
mPopupMenu->setItemVisible("pick_separator", TRUE);
}
- if(getAvatarId() != key.asUUID())
+ if(getAvatarId() != id)
{
mPicksList->goToTop();
+ // Set dummy value to make panel dirty and make it reload picks
+ setValue(LLSD());
}
LLPanelProfileTab::onOpen(key);
@@ -247,7 +292,13 @@ void LLPanelPicks::onClickTeleport()
{
LLPickItem* pick_item = getSelectedPickItem();
if (!pick_item) return;
- LLPanelPick::teleport(pick_item->getPosGlobal());
+
+ LLVector3d pos = pick_item->getPosGlobal();
+ if (!pos.isExactlyZero())
+ {
+ gAgent.teleportViaLocation(pos);
+ LLFloaterWorldMap::getInstance()->trackLocation(pos);
+ }
}
//static
@@ -255,7 +306,9 @@ void LLPanelPicks::onClickMap()
{
LLPickItem* pick_item = getSelectedPickItem();
if (!pick_item) return;
- LLPanelPick::showOnMap(pick_item->getPosGlobal());
+
+ LLFloaterWorldMap::getInstance()->trackLocation(pick_item->getPosGlobal());
+ LLFloaterReg::showInstance("world_map", "center");
}
@@ -284,20 +337,18 @@ void LLPanelPicks::onDoubleClickItem(LLUICtrl* item)
void LLPanelPicks::updateButtons()
{
- int picks_num = mPicksList->size();
bool has_selected = mPicksList->numSelected();
- childSetEnabled(XML_BTN_INFO, has_selected);
-
if (getAvatarId() == gAgentID)
{
- childSetEnabled(XML_BTN_NEW, picks_num < MAX_AVATAR_PICKS);
+ childSetEnabled(XML_BTN_NEW, !LLAgentPicksInfo::getInstance()->isPickLimitReached());
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);
+ childSetEnabled(XML_BTN_OVERFLOW, has_selected);
}
void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
@@ -308,19 +359,18 @@ void LLPanelPicks::setProfilePanel(LLPanelProfile* profile_panel)
void LLPanelPicks::buildPickPanel()
{
- if (mPickPanel == NULL)
- {
- mPickPanel = new LLPanelPick();
- mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onClickBack, this));
- }
+// if (mPickPanel == NULL)
+// {
+// mPickPanel = new LLPanelPick();
+// mPickPanel->setExitCallback(boost::bind(&LLPanelPicks::onPanelPickClose, this, NULL));
+// }
}
void LLPanelPicks::onClickNew()
{
- buildPickPanel();
- mPickPanel->setEditMode(TRUE);
- mPickPanel->prepareNewPick();
- getProfilePanel()->togglePanel(mPickPanel);
+ createPickEditPanel();
+
+ getProfilePanel()->openPanel(mPanelPickEdit, LLSD());
}
void LLPanelPicks::onClickInfo()
@@ -328,28 +378,104 @@ void LLPanelPicks::onClickInfo()
LLSD selected_value = mPicksList->getSelectedValue();
if (selected_value.isUndefined()) return;
- buildPickPanel();
- mPickPanel->reset();
- mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
- getProfilePanel()->togglePanel(mPickPanel);
+ 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::onClickBack()
+void LLPanelPicks::onPanelPickClose(LLPanel* panel)
{
- getProfilePanel()->togglePanel(mPickPanel);
+ panel->setVisible(FALSE);
}
-void LLPanelPicks::onClickMenuEdit()
+void LLPanelPicks::onPanelPickSave(LLPanel* panel)
+{
+ 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::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()
{
- //*TODO, refactor - most of that is similar to onClickInfo
LLSD selected_value = mPicksList->getSelectedValue();
if (selected_value.isUndefined()) return;
- buildPickPanel();
- mPickPanel->reset();
- mPickPanel->init(selected_value[PICK_CREATOR_ID], selected_value[PICK_ID]);
- mPickPanel->setEditMode(TRUE);
- getProfilePanel()->togglePanel(mPickPanel);
+ 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::onClickMenuEdit()
+{
+ onPanelPickEdit();
}
inline LLPanelProfile* LLPanelPicks::getProfilePanel()
@@ -391,6 +517,10 @@ 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);
@@ -445,38 +575,32 @@ const std::string LLPickItem::getDescription()
void LLPickItem::update()
{
- mNeedData = true;
+ setNeedData(true);
LLAvatarPropertiesProcessor::instance().sendPickInfoRequest(mCreatorID, mPickID);
- mNeedData = false;
}
void LLPickItem::processProperties(void *data, EAvatarProcessorType type)
{
- if (APT_PICK_INFO != type) return;
- if (!data) return;
+ if (APT_PICK_INFO != type)
+ {
+ return;
+ }
LLPickData* pick_data = static_cast<LLPickData *>(data);
- if (!pick_data) return;
- if (mPickID != pick_data->pick_id) return;
+ if (!pick_data || mPickID != pick_data->pick_id)
+ {
+ return;
+ }
init(pick_data);
+ setNeedData(false);
LLAvatarPropertiesProcessor::instance().removeObserver(mCreatorID, this);
}
-// virtual
-void LLPanelPicks::onClosePanel()
-{
- // Toggle off Pick Info panel if it is visible.
- if(mPickPanel && mPickPanel->getVisible())
- {
- getProfilePanel()->togglePanel(mPickPanel);
- }
-}
-
BOOL LLPickItem::postBuild()
{
- setMouseEnterCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", true));
- setMouseLeaveCallback(boost::bind(&LLPanelPick::childSetVisible, this, "hovered_icon", false));
+ setMouseEnterCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", true));
+ setMouseLeaveCallback(boost::bind(&LLPanelPickInfo::childSetVisible, this, "hovered_icon", false));
return TRUE;
}
diff --git a/indra/newview/llpanelpicks.h b/indra/newview/llpanelpicks.h
index 18c571c735..5a2754ad10 100644
--- a/indra/newview/llpanelpicks.h
+++ b/indra/newview/llpanelpicks.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -44,11 +44,13 @@ class LLPanelProfile;
class LLMessageSystem;
class LLVector3d;
class LLPanelProfileTab;
-class LLPanelPick;
class LLAgent;
class LLMenuGL;
class LLPickItem;
class LLFlatListView;
+class LLPanelPickInfo;
+class LLPanelPickEdit;
+class LLToggleableMenu;
class LLPanelPicks
: public LLPanelProfileTab
@@ -74,22 +76,22 @@ public:
// parent panels failed to work (picks related code was in me profile panel)
void setProfilePanel(LLPanelProfile* profile_panel);
- /**
- * Closes LLPanelPick if it is visible.
- */
- /*virtual*/ void onClosePanel();
-
private:
void onClickDelete();
void onClickTeleport();
void onClickMap();
+ void onOverflowMenuItemClicked(const LLSD& param);
+ void onOverflowButtonClicked();
+
//------------------------------------------------
// Callbacks which require panel toggling
//------------------------------------------------
void onClickNew();
void onClickInfo();
- void onClickBack();
+ void onPanelPickClose(LLPanel* panel);
+ void onPanelPickSave(LLPanel* panel);
+ void onPanelPickEdit();
void onClickMenuEdit();
void buildPickPanel();
@@ -104,10 +106,18 @@ private:
LLPanelProfile* getProfilePanel();
+ void createPickInfoPanel();
+ void createPickEditPanel();
+// void openPickEditPanel(LLPickItem* pick);
+// void openPickInfoPanel(LLPickItem* pick);
+
LLMenuGL* mPopupMenu;
LLPanelProfile* mProfilePanel;
- LLPanelPick* mPickPanel;
+ LLPanelPickInfo* mPickPanel;
LLFlatListView* mPicksList;
+ LLPanelPickInfo* mPanelPickInfo;
+ LLPanelPickEdit* mPanelPickEdit;
+ LLToggleableMenu* mOverflowMenu;
};
class LLPickItem : public LLPanel, public LLAvatarPropertiesObserver
@@ -144,6 +154,14 @@ public:
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();
@@ -165,6 +183,10 @@ protected:
bool mNeedData;
std::string mPickName;
+ std::string mUserName;
+ std::string mOriginalName;
+ std::string mPickDescription;
+ std::string mSimName;
};
#endif // LL_LLPANELPICKS_H
diff --git a/indra/newview/llpanelplace.cpp b/indra/newview/llpanelplace.cpp
index c6840721a3..61e18195b8 100644
--- a/indra/newview/llpanelplace.cpp
+++ b/indra/newview/llpanelplace.cpp
@@ -58,6 +58,7 @@
//#include "llviewermenu.h" // create_landmark()
#include "llweb.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
LLPanelPlace::LLPanelPlace()
: LLPanel(),
diff --git a/indra/newview/llpanelplaceinfo.cpp b/indra/newview/llpanelplaceinfo.cpp
index 39055e4732..c600651015 100644
--- a/indra/newview/llpanelplaceinfo.cpp
+++ b/indra/newview/llpanelplaceinfo.cpp
@@ -1,10 +1,10 @@
/**
* @file llpanelplaceinfo.cpp
- * @brief Displays place information in Side Tray.
+ * @brief Base class for place information in Side Tray.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -38,58 +38,30 @@
#include "llsdutil.h"
#include "llsecondlifeurls.h"
-#include "llinventory.h"
-#include "llparcel.h"
+#include "llsdutil_math.h"
-#include "llqueryflags.h"
-
-#include "llbutton.h"
-#include "llcombobox.h"
-#include "lliconctrl.h"
#include "llscrollcontainer.h"
#include "lltextbox.h"
-#include "lltrans.h"
-#include "llaccordionctrl.h"
-#include "llaccordionctrltab.h"
#include "llagent.h"
-#include "llagentui.h"
#include "llavatarpropertiesprocessor.h"
-#include "llfloaterworldmap.h"
-#include "llinventorymodel.h"
-#include "lllandmarkactions.h"
+#include "llexpandabletextbox.h"
#include "llpanelpick.h"
#include "lltexturectrl.h"
#include "llviewerinventory.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
#include "llviewertexteditor.h"
-#include "llworldmap.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 std::string getFullFolderName(const LLViewerInventoryCategory* cat);
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats);
-
-static LLRegisterPanelClassWrapper<LLPanelPlaceInfo> t_place_info("panel_place_info");
LLPanelPlaceInfo::LLPanelPlaceInfo()
: LLPanel(),
mParcelID(),
mRequestedID(),
mPosRegion(),
- mLandmarkID(),
- mMinHeight(0),
- mScrollingPanel(NULL),
- mInfoPanel(NULL),
- mMediaPanel(NULL)
+ mMinHeight(0)
{}
+//virtual
LLPanelPlaceInfo::~LLPanelPlaceInfo()
{
if (mParcelID.notNull())
@@ -98,218 +70,41 @@ LLPanelPlaceInfo::~LLPanelPlaceInfo()
}
}
+//virtual
BOOL LLPanelPlaceInfo::postBuild()
{
- mTitle = getChild<LLTextBox>("panel_title");
+ mTitle = getChild<LLTextBox>("title");
mCurrentTitle = mTitle->getText();
- mForSaleIcon = getChild<LLIconCtrl>("icon_for_sale");
-
- // Since this is only used in the directory browser, always
- // disable the snapshot control. Otherwise clicking on it will
- // open a texture picker.
mSnapshotCtrl = getChild<LLTextureCtrl>("logo");
- mSnapshotCtrl->setEnabled(FALSE);
-
mRegionName = getChild<LLTextBox>("region_title");
mParcelName = getChild<LLTextBox>("parcel_title");
- mDescEditor = getChild<LLTextEditor>("description");
+ mDescEditor = getChild<LLExpandableTextBox>("description");
mMaturityRatingText = getChild<LLTextBox>("maturity_value");
- mParcelOwner = getChild<LLTextBox>("owner_value");
- mLastVisited = getChild<LLTextBox>("last_visited_value");
-
- mRatingText = getChild<LLTextBox>("rating_value");
- mVoiceText = getChild<LLTextBox>("voice_value");
- mFlyText = getChild<LLTextBox>("fly_value");
- mPushText = getChild<LLTextBox>("push_value");
- mBuildText = getChild<LLTextBox>("build_value");
- mScriptsText = getChild<LLTextBox>("scripts_value");
- mDamageText = getChild<LLTextBox>("damage_value");
-
- mRegionNameText = getChild<LLTextBox>("region_name");
- mRegionTypeText = getChild<LLTextBox>("region_type");
- 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");
-
- mOwner = getChild<LLTextBox>("owner");
- mCreator = getChild<LLTextBox>("creator");
- mCreated = getChild<LLTextBox>("created");
-
- mTitleEditor = getChild<LLLineEditor>("title_editor");
- mNotesEditor = getChild<LLTextEditor>("notes_editor");
- mFolderCombo = getChild<LLComboBox>("folder_combo");
-
- LLScrollContainer* scroll_container = getChild<LLScrollContainer>("scroll_container");
+ LLScrollContainer* scroll_container = getChild<LLScrollContainer>("place_scroll");
scroll_container->setBorderVisible(FALSE);
mMinHeight = scroll_container->getScrolledViewRect().getHeight();
- mScrollingPanel = getChild<LLPanel>("scrolling_panel");
- mInfoPanel = getChild<LLPanel>("info_panel");
- mMediaPanel = getChild<LLMediaPanel>("media_panel");
- if (!mMediaPanel)
- return FALSE;
-
return TRUE;
}
-void LLPanelPlaceInfo::displayItemInfo(const LLInventoryItem* pItem)
-{
- if (!pItem)
- return;
-
- mLandmarkID = pItem->getUUID();
-
- 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, this, 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, this, mOwner, _2, _3));
- }
- }
- else
- {
- LLUUID owner_id = perm.getOwner();
- if (!gCacheName->getFullName(owner_id, name))
- {
- gCacheName->get(owner_id, FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, 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);
- }
-
- mTitleEditor->setText(pItem->getName());
- mNotesEditor->setText(pItem->getDescription());
-}
-
-void LLPanelPlaceInfo::nameUpdatedCallback(
- LLTextBox* text,
- const std::string& first,
- const std::string& last)
-{
- text->setText(first + " " + last);
-}
-
+//virtual
void LLPanelPlaceInfo::resetLocation()
{
mParcelID.setNull();
mRequestedID.setNull();
- mLandmarkID.setNull();
mPosRegion.clearVec();
- mForSaleIcon->setVisible(FALSE);
+
std::string not_available = getString("not_available");
mMaturityRatingText->setValue(not_available);
- mParcelOwner->setValue(not_available);
- mLastVisited->setValue(not_available);
mRegionName->setText(not_available);
mParcelName->setText(not_available);
mDescEditor->setText(not_available);
- mCreator->setText(not_available);
- mOwner->setText(not_available);
- mCreated->setText(not_available);
- mTitleEditor->setText(LLStringUtil::null);
- mNotesEditor->setText(LLStringUtil::null);
+
mSnapshotCtrl->setImageAssetID(LLUUID::null);
mSnapshotCtrl->setFallbackImageName("default_land_picture.j2c");
-
- mRatingText->setText(not_available);
- mVoiceText->setText(not_available);
- mFlyText->setText(not_available);
- mPushText->setText(not_available);
- mBuildText->setText(not_available);
- mParcelScriptsText->setText(not_available);
- mDamageText->setText(not_available);
-
- mRegionNameText->setValue(not_available);
- mRegionTypeText->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
@@ -319,108 +114,55 @@ void LLPanelPlaceInfo::setParcelID(const LLUUID& parcel_id)
sendParcelInfoRequest();
}
+//virtual
void LLPanelPlaceInfo::setInfoType(INFO_TYPE type)
{
- LLPanel* landmark_info_panel = getChild<LLPanel>("landmark_info_panel");
- LLPanel* landmark_edit_panel = getChild<LLPanel>("landmark_edit_panel");
-
- bool is_info_type_agent = type == AGENT;
- bool is_info_type_create_landmark = type == CREATE_LANDMARK;
- bool is_info_type_landmark = type == LANDMARK;
- bool is_info_type_teleport_history = type == TELEPORT_HISTORY;
-
- getChild<LLTextBox>("maturity_label")->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<LLTextBox>("last_visited_label")->setVisible(is_info_type_teleport_history);
- mLastVisited->setVisible(is_info_type_teleport_history);
-
- landmark_info_panel->setVisible(is_info_type_landmark);
- landmark_edit_panel->setVisible(is_info_type_landmark || is_info_type_create_landmark);
-
- getChild<LLTextBox>("folder_lable")->setVisible(is_info_type_create_landmark);
- mFolderCombo->setVisible(is_info_type_create_landmark);
-
- getChild<LLAccordionCtrl>("advanced_info_accordion")->setVisible(is_info_type_agent);
-
- switch(type)
- {
- case CREATE_LANDMARK:
- mCurrentTitle = getString("title_create_landmark");
-
- mTitleEditor->setEnabled(TRUE);
- mNotesEditor->setEnabled(TRUE);
-
- populateFoldersList();
- break;
-
- case AGENT:
- case PLACE:
- mCurrentTitle = getString("title_place");
-
- if (!isMediaPanelVisible())
- {
- mTitle->setText(mCurrentTitle);
- }
- break;
-
- case LANDMARK:
- mCurrentTitle = getString("title_landmark");
-
- mTitleEditor->setEnabled(FALSE);
- mNotesEditor->setEnabled(FALSE);
-
- populateFoldersList();
- break;
-
- case TELEPORT_HISTORY:
- mCurrentTitle = getString("title_teleport_history");
- break;
- }
-
- if (type != AGENT)
- toggleMediaPanel(FALSE);
+ mTitle->setText(mCurrentTitle);
mInfoType = type;
}
-BOOL LLPanelPlaceInfo::isMediaPanelVisible()
+void LLPanelPlaceInfo::sendParcelInfoRequest()
{
- if (!mMediaPanel)
- return FALSE;
+ if (mParcelID != mRequestedID)
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
- return mMediaPanel->getVisible();
+ mRequestedID = mParcelID;
+ }
}
-void LLPanelPlaceInfo::toggleMediaPanel(BOOL visible)
+void LLPanelPlaceInfo::displayParcelInfo(const LLUUID& region_id,
+ const LLVector3d& pos_global)
{
- if (!mMediaPanel)
- return;
+ 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]);
- if (visible)
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
{
- mTitle->setText(getString("title_media"));
+ 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
{
- mTitle->setText(mCurrentTitle);
- }
-
- mInfoPanel->setVisible(!visible);
- mMediaPanel->setVisible(visible);
-}
-
-void LLPanelPlaceInfo::sendParcelInfoRequest()
-{
- if (mParcelID != mRequestedID)
- {
- LLRemoteParcelInfoProcessor::getInstance()->addObserver(mParcelID, this);
- LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(mParcelID);
-
- mRequestedID = mParcelID;
+ mDescEditor->setText(getString("server_update_text"));
}
}
@@ -448,13 +190,13 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
mSnapshotCtrl->setImageAssetID(parcel_data.snapshot_id);
}
- if(!parcel_data.name.empty())
+ if(!parcel_data.sim_name.empty())
{
- mParcelName->setText(parcel_data.name);
+ mRegionName->setText(parcel_data.sim_name);
}
else
{
- mParcelName->setText(LLStringUtil::null);
+ mRegionName->setText(LLStringUtil::null);
}
if(!parcel_data.desc.empty())
@@ -475,13 +217,6 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
}
mMaturityRatingText->setValue(rating);
- mRatingText->setValue(rating);
-
- //update for_sale banner, here we should use DFQ_FOR_SALE instead of PF_FOR_SALE
- //because we deal with remote parcel response format
- bool isForSale = (parcel_data.flags & DFQ_FOR_SALE) &&
- mInfoType == AGENT ? TRUE : FALSE;
- mForSaleIcon->setVisible(isForSale);
S32 region_x;
S32 region_y;
@@ -501,430 +236,19 @@ void LLPanelPlaceInfo::processParcelInfo(const LLParcelData& parcel_data)
region_z = llround(mPosRegion.mV[VZ]);
}
- std::string name = getString("not_available");
- if (!parcel_data.sim_name.empty())
- {
- name = llformat("%s (%d, %d, %d)",
- parcel_data.sim_name.c_str(), region_x, region_y, region_z);
- mRegionName->setText(name);
- }
-
- if (mInfoType == CREATE_LANDMARK)
- {
- if (parcel_data.name.empty())
- {
- mTitleEditor->setText(name);
- }
- else
- {
- mTitleEditor->setText(parcel_data.name);
- }
-
- // FIXME: Creating landmark works only for current agent location.
- std::string desc;
- LLAgentUI::buildLocationString(desc, LLAgentUI::LOCATION_FORMAT_FULL, gAgent.getPositionAgent());
- mNotesEditor->setText(desc);
-
- if (!LLLandmarkActions::landmarkAlreadyExists())
- {
- createLandmark(mFolderCombo->getValue().asUUID());
- }
- }
-}
-
-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"));
- }
-}
-
-void LLPanelPlaceInfo::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.
- switch(region->getSimAccess())
- {
- case SIM_ACCESS_MATURE:
- parcel_data.flags = 0x1;
- break;
-
- case SIM_ACCESS_ADULT:
- parcel_data.flags = 0x2;
- break;
-
- default:
- parcel_data.flags = 0;
- }
- parcel_data.desc = parcel->getDesc();
- parcel_data.name = parcel->getName();
- parcel_data.sim_name = region->getName();
- parcel_data.snapshot_id = parcel->getSnapshotID();
- 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())
- {
- mVoiceText->setText(on);
- }
- else
- {
- mVoiceText->setText(off);
- }
-
- if (!region->getBlockFly() && parcel->getAllowFly())
- {
- mFlyText->setText(on);
- }
- else
- {
- mFlyText->setText(off);
- }
-
- if (region->getRestrictPushObject() || parcel->getRestrictPushObject())
- {
- mPushText->setText(off);
- }
- else
- {
- mPushText->setText(on);
- }
-
- if (parcel->getAllowModify())
+ if (!parcel_data.name.empty())
{
- mBuildText->setText(on);
+ mParcelName->setText(llformat("%s (%d, %d, %d)",
+ parcel_data.name.c_str(), region_x, region_y, region_z));
}
else
{
- mBuildText->setText(off);
+ mParcelName->setText(getString("not_available"));
}
-
- if((region->getRegionFlags() & REGION_FLAGS_SKIP_SCRIPTS) ||
- (region->getRegionFlags() & REGION_FLAGS_ESTATE_SKIP_SCRIPTS) ||
- !parcel->getAllowOtherScripts())
- {
- mScriptsText->setText(off);
- }
- else
- {
- mScriptsText->setText(on);
- }
-
- if (region->getAllowDamage() || parcel->getAllowDamage())
- {
- mDamageText->setText(on);
- }
- else
- {
- mDamageText->setText(off);
- }
-
- mRegionNameText->setText(region->getName());
- mRegionTypeText->setText(region->getSimProductName());
- mRegionRatingText->setText(region->getSimAccessString());
-
- // 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, this, mRegionGroupText, _2, _3));
-
- gCacheName->get(parcel->getGroupID(), TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, 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, this, mParcelOwner, _2, _3));
- gCacheName->get(region->getOwner(), FALSE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, 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)
- {
- // Adding "For Sale" flag in remote parcel response format.
- parcel_data.flags |= DFQ_FOR_SALE;
-
- const LLUUID& auth_buyer_id = parcel->getAuthorizedBuyerID();
- if(auth_buyer_id.notNull())
- {
- gCacheName->get(auth_buyer_id, TRUE,
- boost::bind(&LLPanelPlaceInfo::nameUpdatedCallback, this, 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"));
- }
-
- 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"));
- }
- }
-
- processParcelInfo(parcel_data);
-
- // TODO: If agent is in currently within the selected parcel
- // show the "You Are Here" banner.
-
- getChild<LLAccordionCtrlTab>("sales_tab")->setVisible(for_sale);
-}
-
-void LLPanelPlaceInfo::updateEstateName(const std::string& name)
-{
- mEstateNameText->setText(name);
-}
-
-void LLPanelPlaceInfo::updateEstateOwnerName(const std::string& name)
-{
- mEstateOwnerText->setText(name);
-}
-
-void LLPanelPlaceInfo::updateCovenantText(const std::string &text)
-{
- mCovenantText->setText(text);
-}
-
-void LLPanelPlaceInfo::updateLastVisitedText(const LLDate &date)
-{
- if (date.isNull())
- {
- mLastVisited->setText(getString("unknown"));
- }
- else
- {
- std::string timeStr = getString("acquired_date");
- LLSD substitution;
- substitution["datetime"] = (S32) date.secondsSinceEpoch();
- LLStringUtil::format (timeStr, substitution);
- mLastVisited->setText(timeStr);
- }
-}
-
-void LLPanelPlaceInfo::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);
- }
-
- if (mNotesEditor->getReadOnly() == (enabled == TRUE))
- {
- mTitleEditor->setEnabled(enabled);
- mNotesEditor->setReadOnly(!enabled);
- mFolderCombo->setVisible(enabled);
- getChild<LLTextBox>("folder_lable")->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& LLPanelPlaceInfo::getLandmarkTitle() const
-{
- return mTitleEditor->getText();
-}
-
-const std::string LLPanelPlaceInfo::getLandmarkNotes() const
-{
- return mNotesEditor->getText();
-}
-
-const LLUUID LLPanelPlaceInfo::getLandmarkFolder() const
-{
- return mFolderCombo->getValue().asUUID();
-}
-
-BOOL LLPanelPlaceInfo::setLandmarkFolder(const LLUUID& id)
-{
- return mFolderCombo->setCurrentByID(id);
-}
-
-void LLPanelPlaceInfo::createLandmark(const LLUUID& folder_id)
-{
- std::string name = mTitleEditor->getText();
- std::string desc = mNotesEditor->getText();
-
- LLStringUtil::trim(name);
- LLStringUtil::trim(desc);
-
- // If typed name is empty use the parcel name instead.
- if (name.empty())
- {
- name = mParcelName->getText();
-
- // If no parcel exists use the region name instead.
- if (name.empty())
- {
- name = mRegionName->getText();
- }
- }
-
- LLStringUtil::replaceChar(desc, '\n', ' ');
- // If no folder chosen use the "Landmarks" folder.
- LLLandmarkActions::createLandmarkHere(name, desc,
- folder_id.notNull() ? folder_id : gInventory.findCategoryUUIDForType(LLAssetType::AT_LANDMARK));
-}
-
-void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel)
-{
- std::string name = mParcelName->getText();
- if (name.empty())
- {
- name = mRegionName->getText();
- }
-
- pick_panel->prepareNewPick(pos_global,
- name,
- mDescEditor->getText(),
- mSnapshotCtrl->getImageAssetID(),
- mParcelID);
}
// virtual
-void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility)
+void LLPanelPlaceInfo::handleVisibilityChange(BOOL new_visibility)
{
LLPanel::handleVisibilityChange(new_visibility);
@@ -942,90 +266,27 @@ void LLPanelPlaceInfo::handleVisibilityChange (BOOL new_visibility)
}
}
-void LLPanelPlaceInfo::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(LLAssetType::AT_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)
+void LLPanelPlaceInfo::createPick(const LLVector3d& pos_global, LLPanelPickEdit* pick_panel)
{
- return left.second < right.second;
-}
-
-static std::string getFullFolderName(const LLViewerInventoryCategory* cat)
-{
- std::string name = cat->getName();
- LLUUID parent_id;
-
- // translate category name, if it's right below the root
- // FIXME: it can throw notification about non existent string in strings.xml
- if (cat->getParentUUID().notNull() && cat->getParentUUID() == gInventory.getRootFolderID())
- {
- 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())
+ std::string name = mParcelName->getText();
+ if (name.empty())
{
- cat = gInventory.getCategory(parent_id);
- name = cat->getName() + "/" + name;
+ name = mRegionName->getText();
}
- return name;
+ LLPickData data;
+ data.pos_global = pos_global;
+ data.name = name;
+ data.desc = mDescEditor->getText();
+ data.snapshot_id = mSnapshotCtrl->getImageAssetID();
+ data.parcel_id = mParcelID;
+ pick_panel->setPickData(&data);
}
-static void collectLandmarkFolders(LLInventoryModel::cat_array_t& cats)
+// static
+void LLPanelPlaceInfo::nameUpdatedCallback(LLTextBox* text,
+ const std::string& first,
+ const std::string& last)
{
- LLUUID landmarks_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_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(LLAssetType::AT_FAVORITE);
- LLViewerInventoryCategory* favorites_cat = gInventory.getCategory(favorites_id);
- if (!favorites_cat)
- {
- llwarns << "Cannot find the favorites folder" << llendl;
- }
- else
- {
- cats.put(favorites_cat);
- }
+ text->setText(first + " " + last);
}
diff --git a/indra/newview/llpanelplaceinfo.h b/indra/newview/llpanelplaceinfo.h
index 3e8344ff12..ec30397cff 100644
--- a/indra/newview/llpanelplaceinfo.h
+++ b/indra/newview/llpanelplaceinfo.h
@@ -1,10 +1,10 @@
/**
* @file llpanelplaceinfo.h
- * @brief Displays place information in Side Tray.
+ * @brief Base class for place information in Side Tray.
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -38,20 +38,16 @@
#include "v3dmath.h"
#include "lluuid.h"
-#include "llpanelmedia.h"
#include "llremoteparcelrequest.h"
-class LLButton;
-class LLComboBox;
+class LLExpandableTextBox;
class LLInventoryItem;
-class LLLineEditor;
-class LLPanelPick;
+class LLPanelPickEdit;
class LLParcel;
-class LLIconCtrl;
class LLTextBox;
-class LLTextEditor;
class LLTextureCtrl;
class LLViewerRegion;
+class LLViewerInventoryCategory;
class LLPanelPlaceInfo : public LLPanel, LLRemoteParcelInfoObserver
{
@@ -72,30 +68,18 @@ public:
// Ignore all old location information, useful if you are
// recycling an existing dialog and need to clear it.
- void resetLocation();
+ 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)
+ // Depending on how the panel was triggered
+ // (from landmark or current location, or other)
// sets a corresponding title and contents.
- void setInfoType(INFO_TYPE type);
-
- // Create a landmark for the current location
- // in a folder specified by folder_id.
- void createLandmark(const LLUUID& folder_id);
-
- // Create a pick for the location specified
- // by global_pos.
- void createPick(const LLVector3d& pos_global, LLPanelPick* pick_panel);
-
- BOOL isMediaPanelVisible();
- void toggleMediaPanel(BOOL visible);
- void displayItemInfo(const LLInventoryItem* pItem);
- /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+ virtual void setInfoType(INFO_TYPE type);
+ // Requests remote parcel info by parcel ID.
void sendParcelInfoRequest();
// Displays information about a remote parcel.
@@ -103,95 +87,37 @@ public:
void displayParcelInfo(const LLUUID& region_id,
const LLVector3d& pos_global);
- // 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);
- void updateLastVisitedText(const LLDate &date);
-
- void nameUpdatedCallback(LLTextBox* text,
- const std::string& first,
- const std::string& last);
-
- 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);
+ /*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+
/*virtual*/ void handleVisibilityChange (BOOL new_visibility);
-private:
-
- void populateFoldersList();
-
- LLUUID mParcelID;
- LLUUID mRequestedID;
- LLUUID mLandmarkID;
- LLVector3 mPosRegion;
- std::string mCurrentTitle;
- S32 mMinHeight;
- INFO_TYPE mInfoType;
-
- LLTextBox* mTitle;
- LLIconCtrl* mForSaleIcon;
- LLTextureCtrl* mSnapshotCtrl;
- LLTextBox* mRegionName;
- LLTextBox* mParcelName;
- LLTextEditor* mDescEditor;
- LLTextBox* mMaturityRatingText;
- LLTextBox* mParcelOwner;
- LLTextBox* mLastVisited;
-
- LLTextBox* mRatingText;
- LLTextBox* mVoiceText;
- LLTextBox* mFlyText;
- LLTextBox* mPushText;
- LLTextBox* mBuildText;
- LLTextBox* mScriptsText;
- LLTextBox* mDamageText;
-
- LLTextBox* mRegionNameText;
- LLTextBox* mRegionTypeText;
- 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;
-
- LLTextBox* mOwner;
- LLTextBox* mCreator;
- LLTextBox* mCreated;
- LLLineEditor* mTitleEditor;
- LLTextEditor* mNotesEditor;
- LLComboBox* mFolderCombo;
- LLPanel* mScrollingPanel;
- LLPanel* mInfoPanel;
- LLMediaPanel* mMediaPanel;
+ // 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 mCurrentTitle;
+ S32 mMinHeight;
+ INFO_TYPE mInfoType;
+
+ LLTextBox* mTitle;
+ LLTextureCtrl* mSnapshotCtrl;
+ LLTextBox* mRegionName;
+ LLTextBox* mParcelName;
+ LLExpandableTextBox* mDescEditor;
+ LLTextBox* mMaturityRatingText;
};
#endif // LL_LLPANELPLACEINFO_H
diff --git a/indra/newview/llpanelplaceprofile.cpp b/indra/newview/llpanelplaceprofile.cpp
new file mode 100644
index 0000000000..2a9ba4697d
--- /dev/null
+++ b/indra/newview/llpanelplaceprofile.cpp
@@ -0,0 +1,586 @@
+/**
+ * @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 "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");
+ mLastVisited = getChild<LLTextBox>("last_visited_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);
+ mLastVisited->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;
+ bool is_info_type_teleport_history = type == TELEPORT_HISTORY;
+
+ getChild<LLTextBox>("maturity_label")->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<LLTextBox>("last_visited_label")->setVisible(is_info_type_teleport_history);
+ mLastVisited->setVisible(is_info_type_teleport_history);
+
+ 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);
+}
+
+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::updateLastVisitedText(const LLDate &date)
+{
+ if (date.isNull())
+ {
+ mLastVisited->setText(getString("unknown"));
+ }
+ else
+ {
+ std::string timeStr = getString("acquired_date");
+ LLSD substitution;
+ substitution["datetime"] = (S32) date.secondsSinceEpoch();
+ LLStringUtil::format (timeStr, substitution);
+ mLastVisited->setText(timeStr);
+ }
+}
+
+void LLPanelPlaceProfile::onForSaleBannerClick()
+{
+ LLViewerParcelMgr* mgr = LLViewerParcelMgr::getInstance();
+ LLParcelSelectionHandle hParcel = mgr->getFloatingParcelSelection();
+ LLViewerRegion* selected_region = mgr->getSelectionRegion();
+ if(!hParcel.isNull() && selected_region)
+ {
+ if(hParcel->getParcel()->getLocalID() == mSelectedParcelID &&
+ mLastSelectedRegionID ==selected_region->getRegionID())
+ {
+ if(hParcel->getParcel()->getSalePrice() - gStatusBar->getBalance() > 0)
+ {
+ LLFloaterBuyCurrency::buyCurrency("Buying selected land ", hParcel->getParcel()->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..b3ef4acf51
--- /dev/null
+++ b/indra/newview/llpanelplaceprofile.h
@@ -0,0 +1,121 @@
+/**
+ * @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);
+
+ // 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);
+ void updateLastVisitedText(const LLDate &date);
+
+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;
+ LLTextBox* mLastVisited;
+
+ 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
index d415b17538..8d117afcfe 100644
--- a/indra/newview/llpanelplaces.cpp
+++ b/indra/newview/llpanelplaces.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -50,15 +50,17 @@
#include "lluictrlfactory.h"
#include "llagent.h"
+#include "llagentpicksinfo.h"
#include "llavatarpropertiesprocessor.h"
#include "llfloaterworldmap.h"
#include "llinventorybridge.h"
#include "llinventorymodel.h"
#include "lllandmarkactions.h"
#include "lllandmarklist.h"
-#include "llpanelplaceinfo.h"
+#include "llpanellandmarkinfo.h"
#include "llpanellandmarks.h"
#include "llpanelpick.h"
+#include "llpanelplaceprofile.h"
#include "llpanelteleporthistory.h"
#include "llteleporthistorystorage.h"
#include "lltoggleablemenu.h"
@@ -120,7 +122,8 @@ LLPanelPlaces::LLPanelPlaces()
mFilterSubString(LLStringUtil::null),
mActivePanel(NULL),
mFilterEditor(NULL),
- mPlaceInfo(NULL),
+ mPlaceProfile(NULL),
+ mLandmarkInfo(NULL),
mPickPanel(NULL),
mItem(NULL),
mPlaceMenu(NULL),
@@ -134,7 +137,7 @@ LLPanelPlaces::LLPanelPlaces()
gInventory.addObserver(mInventoryObserver);
LLViewerParcelMgr::getInstance()->addAgentParcelChangedCallback(
- boost::bind(&LLPanelPlaces::onAgentParcelChange, this));
+ boost::bind(&LLPanelPlaces::updateVerbs, this));
//LLUICtrlFactory::getInstance()->buildPanel(this, "panel_places.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
}
@@ -157,9 +160,6 @@ BOOL LLPanelPlaces::postBuild()
mShowOnMapBtn = getChild<LLButton>("map_btn");
mShowOnMapBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShowOnMapButtonClicked, this));
-
- mShareBtn = getChild<LLButton>("share_btn");
- //mShareBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onShareButtonClicked, this));
mEditBtn = getChild<LLButton>("edit_btn");
mEditBtn->setClickedCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
@@ -178,6 +178,8 @@ BOOL LLPanelPlaces::postBuild()
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)
@@ -203,25 +205,32 @@ BOOL LLPanelPlaces::postBuild()
mFilterEditor->setCommitCallback(boost::bind(&LLPanelPlaces::onFilterEdit, this, _2, false));
}
- mPlaceInfo = getChild<LLPanelPlaceInfo>("panel_place_info");
+ 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));
- LLButton* back_btn = mPlaceInfo->getChild<LLButton>("back_btn");
+ back_btn = mLandmarkInfo->getChild<LLButton>("back_btn");
back_btn->setClickedCallback(boost::bind(&LLPanelPlaces::onBackButtonClicked, this));
- LLLineEditor* title_editor = mPlaceInfo->getChild<LLLineEditor>("title_editor");
+ LLLineEditor* title_editor = mLandmarkInfo->getChild<LLLineEditor>("title_editor");
title_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this), NULL);
- LLTextEditor* notes_editor = mPlaceInfo->getChild<LLTextEditor>("notes_editor");
+ LLTextEditor* notes_editor = mLandmarkInfo->getChild<LLTextEditor>("notes_editor");
notes_editor->setKeystrokeCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
- LLComboBox* folder_combo = mPlaceInfo->getChild<LLComboBox>("folder_combo");
+ LLComboBox* folder_combo = mLandmarkInfo->getChild<LLComboBox>("folder_combo");
folder_combo->setSelectionCallback(boost::bind(&LLPanelPlaces::onEditButtonClicked, this));
+
return TRUE;
}
void LLPanelPlaces::onOpen(const LLSD& key)
{
- if(mPlaceInfo == NULL || key.size() == 0)
+ if(!mPlaceProfile || !mLandmarkInfo || key.size() == 0)
return;
mFilterEditor->clear();
@@ -236,11 +245,11 @@ void LLPanelPlaces::onOpen(const LLSD& key)
if (mPlaceInfoType == AGENT_INFO_TYPE)
{
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::AGENT);
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::AGENT);
}
else if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
{
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::CREATE_LANDMARK);
if (key.has("x") && key.has("y") && key.has("z"))
{
@@ -253,11 +262,11 @@ void LLPanelPlaces::onOpen(const LLSD& key)
mPosGlobal = gAgent.getPositionGlobal();
}
- mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+ mLandmarkInfo->displayParcelInfo(LLUUID(), mPosGlobal);
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
+ mLandmarkInfo->setInfoType(LLPanelPlaceInfo::LANDMARK);
LLInventoryItem* item = gInventory.getItem(key["id"].asUUID());
if (!item)
@@ -267,17 +276,12 @@ void LLPanelPlaces::onOpen(const LLSD& key)
}
else if (mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
- if (mPlaceInfo->isMediaPanelVisible())
- {
- toggleMediaPanel();
- }
-
mPosGlobal = LLVector3d(key["x"].asReal(),
key["y"].asReal(),
key["z"].asReal());
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::PLACE);
- mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::PLACE);
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
}
else if (mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
@@ -288,9 +292,9 @@ void LLPanelPlaces::onOpen(const LLSD& key)
mPosGlobal = hist_items[index].mGlobalPos;
- mPlaceInfo->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
- mPlaceInfo->updateLastVisitedText(hist_items[index].mDate);
- mPlaceInfo->displayParcelInfo(LLUUID(), mPosGlobal);
+ mPlaceProfile->setInfoType(LLPanelPlaceInfo::TELEPORT_HISTORY);
+ mPlaceProfile->updateLastVisitedText(hist_items[index].mDate);
+ mPlaceProfile->displayParcelInfo(LLUUID(), mPosGlobal);
}
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
@@ -318,7 +322,7 @@ void LLPanelPlaces::onOpen(const LLSD& key)
void LLPanelPlaces::setItem(LLInventoryItem* item)
{
- if (!mPlaceInfo || !item)
+ if (!mLandmarkInfo || !item)
return;
mItem = item;
@@ -348,10 +352,19 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
if (is_landmark_editable)
{
- mPlaceInfo->setLandmarkFolder(mItem->getParentUUID());
+ 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);
+ }
+ }
}
- mPlaceInfo->displayItemInfo(mItem);
+ mLandmarkInfo->displayItemInfo(mItem);
LLLandmark* lm = gLandmarkList.getAsset(mItem->getAssetUUID(),
boost::bind(&LLPanelPlaces::onLandmarkLoaded, this, _1));
@@ -363,13 +376,13 @@ void LLPanelPlaces::setItem(LLInventoryItem* item)
void LLPanelPlaces::onLandmarkLoaded(LLLandmark* landmark)
{
- if (!mPlaceInfo)
+ if (!mLandmarkInfo)
return;
LLUUID region_id;
landmark->getRegionID(region_id);
landmark->getGlobalPos(mPosGlobal);
- mPlaceInfo->displayParcelInfo(region_id, mPosGlobal);
+ mLandmarkInfo->displayParcelInfo(region_id, mPosGlobal);
}
void LLPanelPlaces::onFilterEdit(const std::string& search_string, bool force_filter)
@@ -397,19 +410,10 @@ void LLPanelPlaces::onTabSelected()
mActivePanel->updateVerbs();
}
-/*
-void LLPanelPlaces::onShareButtonClicked()
-{
- // TODO: Launch the "Things" Share wizard
-}
-*/
-
void LLPanelPlaces::onTeleportButtonClicked()
{
- if (!mPlaceInfo)
- return;
-
- if (mPlaceInfo->getVisible())
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
{
if (mPlaceInfoType == LANDMARK_INFO_TYPE)
{
@@ -438,10 +442,8 @@ void LLPanelPlaces::onTeleportButtonClicked()
void LLPanelPlaces::onShowOnMapButtonClicked()
{
- if (!mPlaceInfo)
- return;
-
- if (mPlaceInfo->getVisible())
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel && panel->getVisible())
{
LLFloaterWorldMap* worldmap_instance = LLFloaterWorldMap::getInstance();
if(!worldmap_instance)
@@ -484,31 +486,31 @@ void LLPanelPlaces::onShowOnMapButtonClicked()
void LLPanelPlaces::onEditButtonClicked()
{
- if (!mPlaceInfo || isLandmarkEditModeOn)
+ if (!mLandmarkInfo || isLandmarkEditModeOn)
return;
isLandmarkEditModeOn = true;
- mPlaceInfo->toggleLandmarkEditMode(TRUE);
+ mLandmarkInfo->toggleLandmarkEditMode(TRUE);
updateVerbs();
}
void LLPanelPlaces::onSaveButtonClicked()
{
- if (!mPlaceInfo || mItem.isNull())
+ if (!mLandmarkInfo || mItem.isNull())
return;
- std::string current_title_value = mPlaceInfo->getLandmarkTitle();
+ std::string current_title_value = mLandmarkInfo->getLandmarkTitle();
std::string item_title_value = mItem->getName();
- std::string current_notes_value = mPlaceInfo->getLandmarkNotes();
+ 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 = mPlaceInfo->getLandmarkFolder();
+ LLUUID folder_id = mLandmarkInfo->getLandmarkFolder();
LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(mItem);
@@ -541,7 +543,7 @@ void LLPanelPlaces::onSaveButtonClicked()
void LLPanelPlaces::onCancelButtonClicked()
{
- if (!mPlaceInfo)
+ if (!mLandmarkInfo)
return;
if (mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE)
@@ -550,13 +552,13 @@ void LLPanelPlaces::onCancelButtonClicked()
}
else
{
- mPlaceInfo->toggleLandmarkEditMode(FALSE);
+ mLandmarkInfo->toggleLandmarkEditMode(FALSE);
isLandmarkEditModeOn = false;
updateVerbs();
// Reload the landmark properties.
- mPlaceInfo->displayItemInfo(mItem);
+ mLandmarkInfo->displayItemInfo(mItem);
}
}
@@ -585,7 +587,7 @@ void LLPanelPlaces::onOverflowButtonClicked()
if (mItem.notNull())
{
const LLUUID& item_id = mItem->getUUID();
- const LLUUID& trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH);
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
is_landmark_removable = gInventory.isObjectDescendentOf(item_id, gInventory.getRootFolderID()) &&
!gInventory.isObjectDescendentOf(item_id, trash_id);
}
@@ -606,6 +608,16 @@ void LLPanelPlaces::onOverflowButtonClicked()
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();
@@ -630,63 +642,60 @@ void LLPanelPlaces::onOverflowMenuItemClicked(const LLSD& param)
}
else if (item == "pick")
{
- if (!mPlaceInfo)
- return;
-
if (mPickPanel == NULL)
{
- mPickPanel = new LLPanelPick();
+ 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);
- mPickPanel->setEditMode(TRUE);
-
- mPlaceInfo->createPick(mPosGlobal, mPickPanel);
}
+ 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()
{
- if (!mPlaceInfo)
- return;
-
- if (mPlaceInfo->isMediaPanelVisible())
- {
- toggleMediaPanel();
- }
- else
- {
- togglePlaceInfoPanel(FALSE);
+ togglePlaceInfoPanel(FALSE);
- // Resetting mPlaceInfoType when Place Info panel is closed.
- mPlaceInfoType = LLStringUtil::null;
+ // Resetting mPlaceInfoType when Place Info panel is closed.
+ mPlaceInfoType = LLStringUtil::null;
- isLandmarkEditModeOn = false;
- }
+ isLandmarkEditModeOn = false;
updateVerbs();
}
-void LLPanelPlaces::toggleMediaPanel()
-{
- if (!mPlaceInfo)
- return;
-
- mPlaceInfo->toggleMediaPanel(!mPlaceInfo->isMediaPanelVisible());
-
- // Refresh the current place info because
- // the media panel controls can't refer to
- // the remote parcel media.
- onOpen(LLSD().insert("type", AGENT_INFO_TYPE));
-}
-
void LLPanelPlaces::togglePickPanel(BOOL visible)
{
setAllChildrenVisible(this, !visible);
@@ -697,26 +706,50 @@ void LLPanelPlaces::togglePickPanel(BOOL visible)
void LLPanelPlaces::togglePlaceInfoPanel(BOOL visible)
{
- if (!mPlaceInfo)
+ if (!mPlaceProfile || !mLandmarkInfo)
return;
- mPlaceInfo->setVisible(visible);
mFilterEditor->setVisible(!visible);
mTabContainer->setVisible(!visible);
- if (visible)
+ if (mPlaceInfoType == AGENT_INFO_TYPE ||
+ mPlaceInfoType == REMOTE_PLACE_INFO_TYPE ||
+ mPlaceInfoType == TELEPORT_HISTORY_INFO_TYPE)
{
- mPlaceInfo->resetLocation();
+ mPlaceProfile->setVisible(visible);
- LLRect rect = getRect();
- LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
- mPlaceInfo->reshape(new_rect.getWidth(),new_rect.getHeight());
+ 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 == 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);
+ }
}
}
void LLPanelPlaces::changedParcelSelection()
{
- if (!mPlaceInfo)
+ if (!mPlaceProfile)
return;
LLViewerParcelMgr* parcel_mgr = LLViewerParcelMgr::getInstance();
@@ -742,8 +775,8 @@ void LLPanelPlaces::changedParcelSelection()
}
}
- mPlaceInfo->resetLocation();
- mPlaceInfo->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);
+ mPlaceProfile->resetLocation();
+ mPlaceProfile->displaySelectedParcelInfo(parcel, region, mPosGlobal, is_current_parcel);
updateVerbs();
}
@@ -790,41 +823,32 @@ void LLPanelPlaces::changedInventory(U32 mask)
gInventory.removeObserver(mInventoryObserver);
}
-void LLPanelPlaces::onAgentParcelChange()
+void LLPanelPlaces::updateVerbs()
{
- if (!mPlaceInfo)
- return;
+ bool is_place_info_visible;
- if (mPlaceInfo->isMediaPanelVisible())
+ LLPanelPlaceInfo* panel = getCurrentInfoPanel();
+ if (panel)
{
- onOpen(LLSD().insert("type", AGENT_INFO_TYPE));
+ is_place_info_visible = panel->getVisible();
}
else
{
- updateVerbs();
+ is_place_info_visible = false;
}
-}
-
-void LLPanelPlaces::updateVerbs()
-{
- if (!mPlaceInfo)
- return;
- bool is_place_info_visible = mPlaceInfo->getVisible();
bool is_agent_place_info_visible = mPlaceInfoType == AGENT_INFO_TYPE;
bool is_create_landmark_visible = mPlaceInfoType == CREATE_LANDMARK_INFO_TYPE;
- bool is_media_panel_visible = mPlaceInfo->isMediaPanelVisible();
mTeleportBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
mShowOnMapBtn->setVisible(!is_create_landmark_visible && !isLandmarkEditModeOn);
- mShareBtn->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);
- mOverflowBtn->setEnabled(is_place_info_visible && !is_media_panel_visible && !is_create_landmark_visible);
+ mOverflowBtn->setEnabled(is_place_info_visible && !is_create_landmark_visible);
if (is_place_info_visible)
{
@@ -832,16 +856,13 @@ void LLPanelPlaces::updateVerbs()
{
// We don't need to teleport to the current location
// so check if the location is not within the current parcel.
- mTeleportBtn->setEnabled(!is_media_panel_visible &&
- !mPosGlobal.isExactlyZero() &&
+ mTeleportBtn->setEnabled(!mPosGlobal.isExactlyZero() &&
!LLViewerParcelMgr::getInstance()->inAgentParcel(mPosGlobal));
}
else if (mPlaceInfoType == LANDMARK_INFO_TYPE || mPlaceInfoType == REMOTE_PLACE_INFO_TYPE)
{
mTeleportBtn->setEnabled(TRUE);
}
-
- mShowOnMapBtn->setEnabled(!is_media_panel_visible);
}
else
{
@@ -850,6 +871,23 @@ void LLPanelPlaces::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();
diff --git a/indra/newview/llpanelplaces.h b/indra/newview/llpanelplaces.h
index ce20ffdc91..0d97353b66 100644
--- a/indra/newview/llpanelplaces.h
+++ b/indra/newview/llpanelplaces.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -37,7 +37,11 @@
class LLInventoryItem;
class LLFilterEditor;
class LLLandmark;
-class LLPanelPick;
+
+class LLPanelLandmarkInfo;
+class LLPanelPlaceProfile;
+
+class LLPanelPickEdit;
class LLPanelPlaceInfo;
class LLPanelPlacesTab;
class LLParcelSelection;
@@ -69,7 +73,6 @@ private:
void onFilterEdit(const std::string& search_string, bool force_filter);
void onTabSelected();
- //void onShareButtonClicked();
void onTeleportButtonClicked();
void onShowOnMapButtonClicked();
void onEditButtonClicked();
@@ -77,6 +80,7 @@ private:
void onCancelButtonClicked();
void onOverflowButtonClicked();
void onOverflowMenuItemClicked(const LLSD& param);
+ bool onOverflowMenuItemEnable(const LLSD& param);
void onCreateLandmarkButtonClicked(const LLUUID& folder_id);
void onBackButtonClicked();
@@ -84,20 +88,22 @@ private:
void togglePickPanel(BOOL visible);
void togglePlaceInfoPanel(BOOL visible);
- void onAgentParcelChange();
void updateVerbs();
+ LLPanelPlaceInfo* getCurrentInfoPanel();
+
LLFilterEditor* mFilterEditor;
LLPanelPlacesTab* mActivePanel;
LLTabContainer* mTabContainer;
- LLPanelPlaceInfo* mPlaceInfo;
- LLPanelPick* mPickPanel;
+ LLPanelPlaceProfile* mPlaceProfile;
+ LLPanelLandmarkInfo* mLandmarkInfo;
+
+ LLPanelPickEdit* mPickPanel;
LLToggleableMenu* mPlaceMenu;
LLToggleableMenu* mLandmarkMenu;
LLButton* mTeleportBtn;
LLButton* mShowOnMapBtn;
- LLButton* mShareBtn;
LLButton* mEditBtn;
LLButton* mSaveBtn;
LLButton* mCancelBtn;
diff --git a/indra/newview/llpanelplacestab.cpp b/indra/newview/llpanelplacestab.cpp
index 7c0a7b0cc4..42c871a41a 100644
--- a/indra/newview/llpanelplacestab.cpp
+++ b/indra/newview/llpanelplacestab.cpp
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -51,7 +51,6 @@ bool LLPanelPlacesTab::isTabVisible()
void LLPanelPlacesTab::setPanelPlacesButtons(LLPanelPlaces* panel)
{
- //mShareBtn = panel->getChild<LLButton>("share_btn");
mTeleportBtn = panel->getChild<LLButton>("teleport_btn");
mShowOnMapBtn = panel->getChild<LLButton>("map_btn");
}
diff --git a/indra/newview/llpanelplacestab.h b/indra/newview/llpanelplacestab.h
index 1c70869414..458694d766 100644
--- a/indra/newview/llpanelplacestab.h
+++ b/indra/newview/llpanelplacestab.h
@@ -4,7 +4,7 @@
*
* $LicenseInfo:firstyear=2009&license=viewergpl$
*
- * Copyright (c) 2004-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
@@ -44,10 +44,8 @@ public:
virtual void onSearchEdit(const std::string& string) = 0;
virtual void updateVerbs() = 0; // Updates buttons at the bottom of Places panel
- //virtual void onShare() = 0;
virtual void onShowOnMap() = 0;
virtual void onTeleport() = 0;
- //virtual void onCopySLURL() = 0;
bool isTabVisible(); // Check if parent TabContainer is visible.
@@ -58,7 +56,6 @@ public:
const LLUUID& snapshot_id,
bool teleport);
protected:
- //LLButton* mShareBtn;
LLButton* mTeleportBtn;
LLButton* mShowOnMapBtn;
};
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
new file mode 100644
index 0000000000..0b2a7e8756
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -0,0 +1,1112 @@
+/**
+ * @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 "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 "llviewercontrol.h"
+#include "llviewerparcelmgr.h"
+#include "llviewermedia.h"
+#include "llviewermediafocus.h"
+#include "llvovolume.h"
+#include "llweb.h"
+#include "llwindow.h"
+
+glh::matrix4f glh_get_current_modelview();
+glh::matrix4f glh_get_current_projection();
+
+const F32 ZOOM_NEAR_PADDING = 1.0f;
+const F32 ZOOM_MEDIUM_PADDING = 1.15f;
+const F32 ZOOM_FAR_PADDING = 1.5f;
+
+// 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),
+ mUpdatePercent(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.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.ToggleMute", boost::bind(&LLPanelPrimMediaControls::onToggleMute, this));
+
+ LLUICtrlFactory::getInstance()->buildPanel(this, "panel_prim_media_controls.xml");
+ mInactivityTimer.reset();
+ mFadeTimer.stop();
+ mCurrentZoom = ZOOM_NONE;
+ mScrollState = SCROLL_NONE;
+
+ mPanelHandle.bind(this);
+}
+LLPanelPrimMediaControls::~LLPanelPrimMediaControls()
+{
+}
+
+BOOL LLPanelPrimMediaControls::postBuild()
+{
+ LLButton* scroll_up_ctrl = getChild<LLButton>("scrollup");
+ scroll_up_ctrl->setClickedCallback(onScrollUp, this);
+ scroll_up_ctrl->setHeldDownCallback(onScrollUpHeld, this);
+ scroll_up_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_left_ctrl = getChild<LLButton>("scrollleft");
+ scroll_left_ctrl->setClickedCallback(onScrollLeft, this);
+ scroll_left_ctrl->setHeldDownCallback(onScrollLeftHeld, this);
+ scroll_left_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_right_ctrl = getChild<LLButton>("scrollright");
+ scroll_right_ctrl->setClickedCallback(onScrollRight, this);
+ scroll_right_ctrl->setHeldDownCallback(onScrollRightHeld, this);
+ scroll_right_ctrl->setMouseUpCallback(onScrollStop, this);
+ LLButton* scroll_down_ctrl = getChild<LLButton>("scrolldown");
+ scroll_down_ctrl->setClickedCallback(onScrollDown, this);
+ scroll_down_ctrl->setHeldDownCallback(onScrollDownHeld, this);
+ scroll_down_ctrl->setMouseUpCallback(onScrollStop, this);
+
+ LLUICtrl* media_address = getChild<LLUICtrl>("media_address");
+ media_address->setFocusReceivedCallback(boost::bind(&LLPanelPrimMediaControls::onInputURL, _1, this ));
+ mInactiveTimeout = gSavedSettings.getF32("MediaControlTimeout");
+ mControlFadeTime = gSavedSettings.getF32("MediaControlFadeTime");
+
+ mCurrentZoom = ZOOM_NONE;
+ // clicks on HUD 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())
+ {
+ mTargetImplID = media_impl->getMediaTextureID();
+ mTargetObjectID = objectp->getID();
+ mTargetObjectFace = face;
+ mTargetObjectNormal = pick_normal;
+ mClearFaceOnFade = false;
+ }
+ 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()
+{
+ const S32 MIN_HUD_WIDTH=400;
+ const S32 MIN_HUD_HEIGHT=120;
+
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ LLViewerObject* objectp = getTargetObject();
+
+ if(!media_impl)
+ {
+ 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;
+ // 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 HUD 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());
+ }
+
+ //
+ // Set the state of the buttons
+ //
+ LLUICtrl* back_ctrl = getChild<LLUICtrl>("back");
+ LLUICtrl* fwd_ctrl = getChild<LLUICtrl>("fwd");
+ LLUICtrl* reload_ctrl = getChild<LLUICtrl>("reload");
+ LLUICtrl* play_ctrl = getChild<LLUICtrl>("play");
+ LLUICtrl* pause_ctrl = getChild<LLUICtrl>("pause");
+ LLUICtrl* stop_ctrl = getChild<LLUICtrl>("stop");
+ LLUICtrl* media_stop_ctrl = getChild<LLUICtrl>("media_stop");
+ LLUICtrl* home_ctrl = getChild<LLUICtrl>("home");
+ LLUICtrl* close_ctrl = getChild<LLUICtrl>("close");
+ LLUICtrl* open_ctrl = getChild<LLUICtrl>("new_window");
+ LLUICtrl* zoom_ctrl = getChild<LLUICtrl>("zoom_frame");
+ LLPanel* media_loading_panel = getChild<LLPanel>("media_progress_indicator");
+ LLUICtrl* media_address_ctrl = getChild<LLUICtrl>("media_address");
+ LLUICtrl* media_play_slider_panel = getChild<LLUICtrl>("media_play_position");
+ LLUICtrl* media_play_slider_ctrl = getChild<LLUICtrl>("media_play_slider");
+ LLUICtrl* volume_ctrl = getChild<LLUICtrl>("media_volume");
+ LLButton* volume_btn = getChild<LLButton>("media_volume_button");
+ LLUICtrl* volume_up_ctrl = getChild<LLUICtrl>("volume_up");
+ LLUICtrl* volume_down_ctrl = getChild<LLUICtrl>("volume_down");
+ LLIconCtrl* whitelist_icon = getChild<LLIconCtrl>("media_whitelist_flag");
+ LLIconCtrl* secure_lock_icon = getChild<LLIconCtrl>("media_secure_lock_flag");
+
+ LLUICtrl* media_panel_scroll = getChild<LLUICtrl>("media_panel_scroll");
+ LLUICtrl* scroll_up_ctrl = getChild<LLUICtrl>("scrollup");
+ LLUICtrl* scroll_left_ctrl = getChild<LLUICtrl>("scrollleft");
+ LLUICtrl* scroll_right_ctrl = getChild<LLUICtrl>("scrollright");
+ LLUICtrl* scroll_down_ctrl = getChild<LLUICtrl>("scrolldown");
+
+ // 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.
+ back_ctrl->setVisible(has_focus);
+ fwd_ctrl->setVisible(has_focus);
+ reload_ctrl->setVisible(has_focus);
+ stop_ctrl->setVisible(false);
+ home_ctrl->setVisible(has_focus);
+ close_ctrl->setVisible(has_focus);
+ open_ctrl->setVisible(true);
+ media_address_ctrl->setVisible(has_focus && !mini_controls);
+ media_play_slider_panel->setVisible(has_focus && !mini_controls);
+ volume_ctrl->setVisible(false);
+ volume_up_ctrl->setVisible(false);
+ volume_down_ctrl->setVisible(false);
+
+ whitelist_icon->setVisible(!mini_controls && (media_data)?media_data->getWhiteListEnable():false);
+ // Disable zoom if HUD
+ zoom_ctrl->setEnabled(!objectp->isHUDAttachment());
+ secure_lock_icon->setVisible(false);
+ mCurrentURL = media_impl->getCurrentMediaURL();
+
+ back_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateBack() && can_navigate);
+ fwd_ctrl->setEnabled((media_impl != NULL) && media_impl->canNavigateForward() && can_navigate);
+ stop_ctrl->setEnabled(has_focus && can_navigate);
+ home_ctrl->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())
+ {
+ reload_ctrl->setEnabled(FALSE);
+ reload_ctrl->setVisible(FALSE);
+ media_stop_ctrl->setVisible(has_focus);
+ home_ctrl->setVisible(FALSE);
+ back_ctrl->setEnabled(has_focus);
+ fwd_ctrl->setEnabled(has_focus);
+ media_address_ctrl->setVisible(false);
+ media_address_ctrl->setEnabled(false);
+ media_play_slider_panel->setVisible(has_focus && !mini_controls);
+ media_play_slider_panel->setEnabled(has_focus && !mini_controls);
+
+ volume_ctrl->setVisible(has_focus);
+ volume_up_ctrl->setVisible(has_focus);
+ volume_down_ctrl->setVisible(has_focus);
+ volume_ctrl->setEnabled(has_focus);
+
+ whitelist_icon->setVisible(false);
+ secure_lock_icon->setVisible(false);
+ scroll_up_ctrl->setVisible(false);
+ scroll_left_ctrl->setVisible(false);
+ scroll_right_ctrl->setVisible(false);
+ scroll_down_ctrl->setVisible(false);
+ media_panel_scroll->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();
+ media_play_slider_ctrl->setValue(0);
+ media_play_slider_ctrl->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;
+ media_play_slider_ctrl->setValue(percent);
+ media_play_slider_ctrl->setEnabled(true);
+ }
+
+ // video vloume
+ if(volume <= 0.0)
+ {
+ volume_up_ctrl->setEnabled(TRUE);
+ volume_down_ctrl->setEnabled(FALSE);
+ media_impl->setVolume(0.0);
+ volume_btn->setToggleState(true);
+ }
+ else if (volume >= 1.0)
+ {
+ volume_up_ctrl->setEnabled(FALSE);
+ volume_down_ctrl->setEnabled(TRUE);
+ media_impl->setVolume(1.0);
+ volume_btn->setToggleState(false);
+ }
+ else
+ {
+ volume_up_ctrl->setEnabled(TRUE);
+ volume_down_ctrl->setEnabled(TRUE);
+ }
+
+ switch(result)
+ {
+ case LLPluginClassMediaOwner::MEDIA_PLAYING:
+ play_ctrl->setEnabled(FALSE);
+ play_ctrl->setVisible(FALSE);
+ pause_ctrl->setEnabled(TRUE);
+ pause_ctrl->setVisible(has_focus);
+ media_stop_ctrl->setEnabled(TRUE);
+
+ break;
+ case LLPluginClassMediaOwner::MEDIA_PAUSED:
+ default:
+ pause_ctrl->setEnabled(FALSE);
+ pause_ctrl->setVisible(FALSE);
+ play_ctrl->setEnabled(TRUE);
+ play_ctrl->setVisible(has_focus);
+ media_stop_ctrl->setEnabled(FALSE);
+ break;
+ }
+ }
+ else // web based
+ {
+ if(media_plugin)
+ {
+ mCurrentURL = media_plugin->getLocation();
+ }
+ else
+ {
+ mCurrentURL.clear();
+ }
+
+ play_ctrl->setVisible(FALSE);
+ pause_ctrl->setVisible(FALSE);
+ media_stop_ctrl->setVisible(FALSE);
+ media_address_ctrl->setVisible(has_focus && !mini_controls);
+ media_address_ctrl->setEnabled(has_focus && !mini_controls);
+ media_play_slider_panel->setVisible(FALSE);
+ media_play_slider_panel->setEnabled(FALSE);
+
+ volume_ctrl->setVisible(FALSE);
+ volume_up_ctrl->setVisible(FALSE);
+ volume_down_ctrl->setVisible(FALSE);
+ volume_ctrl->setEnabled(FALSE);
+ volume_up_ctrl->setEnabled(FALSE);
+ volume_down_ctrl->setEnabled(FALSE);
+
+ scroll_up_ctrl->setVisible(has_focus);
+ scroll_left_ctrl->setVisible(has_focus);
+ scroll_right_ctrl->setVisible(has_focus);
+ scroll_down_ctrl->setVisible(has_focus);
+ media_panel_scroll->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)
+ {
+ secure_lock_icon->setVisible(has_focus);
+ }
+
+ if(mCurrentURL!=mPreviousURL)
+ {
+ setCurrentURL();
+ mPreviousURL = mCurrentURL;
+ }
+
+ if(result == LLPluginClassMediaOwner::MEDIA_LOADING)
+ {
+ reload_ctrl->setEnabled(FALSE);
+ reload_ctrl->setVisible(FALSE);
+ stop_ctrl->setEnabled(TRUE);
+ stop_ctrl->setVisible(has_focus);
+ }
+ else
+ {
+ reload_ctrl->setEnabled(TRUE);
+ reload_ctrl->setVisible(has_focus);
+ stop_ctrl->setEnabled(FALSE);
+ stop_ctrl->setVisible(FALSE);
+ }
+ }
+
+
+ if(media_plugin)
+ {
+ //
+ // Handle progress bar
+ //
+ mUpdatePercent = media_plugin->getProgressPercent();
+ if(mUpdatePercent<100.0f)
+ {
+ media_loading_panel->setVisible(true);
+ getChild<LLProgressBar>("media_progress_bar")->setPercent(mUpdatePercent);
+ gFocusMgr.setTopCtrl(media_loading_panel);
+ }
+ else
+ {
+ media_loading_panel->setVisible(false);
+ gFocusMgr.setTopCtrl(NULL);
+ }
+ }
+
+ 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
+ //
+ glh::matrix4f mat = glh_get_current_projection()*glh_get_current_modelview();
+ 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();
+
+ 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));
+ }
+
+ LLCoordGL screen_min;
+ screen_min.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (min.mV[VX] + 1.f) * 0.5f);
+ screen_min.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (min.mV[VY] + 1.f) * 0.5f);
+
+ LLCoordGL screen_max;
+ screen_max.mX = llround((F32)gViewerWindow->getWorldViewWidth() * (max.mV[VX] + 1.f) * 0.5f);
+ screen_max.mY = llround((F32)gViewerWindow->getWorldViewHeight() * (max.mV[VY] + 1.f) * 0.5f);
+
+ // grow panel so that screenspace bounding box fits inside "media_region" element of HUD
+ LLRect media_controls_rect;
+ getParent()->screenRectToLocal(LLRect(screen_min.mX, screen_max.mY, screen_max.mX, screen_min.mY), &media_controls_rect);
+ LLView* media_region = getChild<LLView>("media_region");
+ media_controls_rect.mLeft -= media_region->getRect().mLeft;
+ media_controls_rect.mBottom -= media_region->getRect().mBottom;
+ media_controls_rect.mTop += getRect().getHeight() - media_region->getRect().mTop;
+ media_controls_rect.mRight += getRect().getWidth() - media_region->getRect().mRight;
+
+ LLRect old_hud_rect = media_controls_rect;
+ // keep all parts of HUD on-screen
+ media_controls_rect.intersectWith(getParent()->getLocalRect());
+
+ // clamp to minimum size, keeping centered
+ media_controls_rect.setCenterAndSize(media_controls_rect.getCenterX(), media_controls_rect.getCenterY(),
+ llmax(MIN_HUD_WIDTH, media_controls_rect.getWidth()), llmax(MIN_HUD_HEIGHT, media_controls_rect.getHeight()));
+
+ setShape(media_controls_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 = 1.f;
+ if(mFadeTimer.getStarted())
+ {
+ F32 time = mFadeTimer.getElapsedTimeF32();
+ alpha = llmax(lerp(1.0, 0.0, time / mControlFadeTime), 0.0f);
+
+ if(mFadeTimer.getElapsedTimeF32() >= 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;
+ mTargetImplID = LLUUID::null;
+ mTargetObjectID = LLUUID::null;
+ mTargetObjectFace = 0;
+ }
+ }
+ }
+
+ {
+ 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);
+
+ LLView* controls_view = NULL;
+ controls_view = getChild<LLView>("media_controls");
+
+ if(controls_view && controls_view->getVisible())
+ {
+ controls_view->screenPointToLocal(cursor_pos_gl.mX, cursor_pos_gl.mY, &x, &y);
+
+ LLView *hit_child = controls_view->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()
+{
+ LLViewerMediaFocus::getInstance()->clearFocus();
+ resetZoomLevel();
+ 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->stop();
+ }
+}
+
+void LLPanelPrimMediaControls::onClickZoom()
+{
+ focusOnTarget();
+
+ 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()
+{
+ if(mCurrentZoom != ZOOM_NONE)
+ {
+ mCurrentZoom = ZOOM_NONE;
+ updateZoom();
+ }
+}
+
+void LLPanelPrimMediaControls::updateZoom()
+{
+ F32 zoom_padding = 0.0f;
+ switch (mCurrentZoom)
+ {
+ case ZOOM_NONE:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ case ZOOM_FAR:
+ {
+ zoom_padding = ZOOM_FAR_PADDING;
+ break;
+ }
+ case ZOOM_MEDIUM:
+ {
+ zoom_padding = ZOOM_MEDIUM_PADDING;
+ break;
+ }
+ case ZOOM_NEAR:
+ {
+ zoom_padding = ZOOM_NEAR_PADDING;
+ break;
+ }
+ default:
+ {
+ gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ break;
+ }
+ }
+
+ if (zoom_padding > 0.0f)
+ LLViewerMediaFocus::setCameraZoom(getTargetObject(), mTargetObjectNormal, zoom_padding);
+}
+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();
+
+ LLUICtrl *media_address_ctrl = getChild<LLUICtrl>("media_address_url");
+ std::string url = media_address_ctrl->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
+ LLLineEditor* media_address_url = getChild<LLLineEditor>("media_address_url");
+ if (media_address_url && mCurrentURL != "about:blank")
+ {
+ media_address_url->setValue(mCurrentURL);
+ }
+#endif // USE_COMBO_BOX_FOR_MEDIA_URL
+}
+
+void LLPanelPrimMediaControls::onCommitSlider()
+{
+ focusOnTarget();
+
+ LLSlider* media_play_slider_ctrl = getChild<LLSlider>("media_play_slider");
+ LLViewerMediaImpl* media_impl = getTargetMediaImpl();
+ if (media_impl)
+ {
+ // get slider value
+ F64 slider_value = media_play_slider_ctrl->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);
+ getChild<LLButton>("media_volume")->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);
+ getChild<LLButton>("media_volume")->setToggleState(false);
+ }
+}
+
+
+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
+ {
+ media_impl->setVolume(0.5);
+ }
+ }
+}
+
diff --git a/indra/newview/llpanelprimmediacontrols.h b/indra/newview/llpanelprimmediacontrols.h
new file mode 100644
index 0000000000..3ec7aa2356
--- /dev/null
+++ b/indra/newview/llpanelprimmediacontrols.h
@@ -0,0 +1,148 @@
+/**
+ * @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 LLCoordWindow;
+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();
+ 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 onCommitURL();
+
+ void updateZoom();
+ void setCurrentURL();
+ void onCommitSlider();
+
+ void onCommitVolumeUp();
+ void onCommitVolumeDown();
+ void onToggleMute();
+
+ 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();
+ 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;
+ int mUpdatePercent;
+
+ LLUUID mTargetObjectID;
+ S32 mTargetObjectFace;
+ LLUUID mTargetImplID;
+ LLVector3 mTargetObjectNormal;
+};
+
+#endif // LL_PANELPRIMMEDIACONTROLS_H
diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp
index cda7942c1d..8147ff17f0 100644
--- a/indra/newview/llpanelprofile.cpp
+++ b/indra/newview/llpanelprofile.cpp
@@ -59,17 +59,61 @@ public:
return false;
}
- if (params[1].asString() == "about")
+ const std::string verb = params[1].asString();
+ if (verb == "about")
{
LLAvatarActions::showProfile(avatar_id);
return true;
}
- if (params[1].asString() == "inspect")
+ if (verb == "inspect")
{
LLFloaterReg::showInstance("inspect_avatar", LLSD().insert("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;
}
};
@@ -117,25 +161,21 @@ void LLPanelProfile::onOpen(const LLSD& key)
void LLPanelProfile::togglePanel(LLPanel* panel)
{
// TRUE - we need to open/expand "panel"
- bool expand = getChildList()->back() != panel; // mTabCtrl->getVisible();
+ bool expand = getChildList()->front() != panel; // mTabCtrl->getVisible();
if (expand)
{
- //*NOTE on view profile panel along with tabcontainer there is
- // a backbutton that will be shown when there will be a panel over it even
- //if that panel has visible backgroud
- setAllChildrenVisible(FALSE);
-
- panel->setVisible(TRUE);
if (panel->getParent() != this)
{
- addChildInBack(panel);
+ addChild(panel);
}
else
{
- sendChildToBack(panel);
+ sendChildToFront(panel);
}
+ panel->setVisible(TRUE);
+
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());
@@ -143,13 +183,12 @@ void LLPanelProfile::togglePanel(LLPanel* panel)
}
else
{
- this->setAllChildrenVisible(TRUE);
panel->setVisible(FALSE);
if (panel->getParent() == this)
{
removeChild(panel);
}
- sendChildToBack(getTabCtrl());
+
getTabCtrl()->getCurrentPanel()->onOpen(getAvatarId());
}
}
@@ -174,3 +213,35 @@ void LLPanelProfile::setAllChildrenVisible(BOOL 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);
+}
+
+void 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;
+ }
+ LLPanel::notifyParent(info);
+}
diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h
index bb893f257a..e0b827c986 100644
--- a/indra/newview/llpanelprofile.h
+++ b/indra/newview/llpanelprofile.h
@@ -53,6 +53,10 @@ public:
virtual void togglePanel(LLPanel*);
+ virtual void openPanel(LLPanel* panel, const LLSD& params);
+
+ void notifyParent(const LLSD& info);
+
protected:
LLPanelProfile();
diff --git a/indra/newview/llpanelprofileview.cpp b/indra/newview/llpanelprofileview.cpp
index f1db2416e4..d4ab5013f9 100644
--- a/indra/newview/llpanelprofileview.cpp
+++ b/indra/newview/llpanelprofileview.cpp
@@ -32,10 +32,12 @@
#include "llviewerprecompiledheaders.h"
+#include "llavatarconstants.h"
#include "lluserrelations.h"
#include "llpanelprofileview.h"
+#include "llavatarpropertiesprocessor.h"
#include "llcallingcard.h"
#include "llpanelavatar.h"
#include "llpanelpicks.h"
@@ -46,15 +48,48 @@ static LLRegisterPanelClassWrapper<LLPanelProfileView> t_panel_target_profile("p
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*/
@@ -65,6 +100,9 @@ void LLPanelProfileView::onOpen(const LLSD& key)
{
id = key["id"];
}
+
+ // subscribe observer to get online status. Request will be sent by LLPanelAvatarProfile itself
+ mAvatarStatusObserver->subscribe();
if(id.notNull() && getAvatarId() != id)
{
setAvatarId(id);
@@ -73,10 +111,12 @@ void LLPanelProfileView::onOpen(const LLSD& key)
// Update the avatar name.
gCacheName->get(getAvatarId(), FALSE,
boost::bind(&LLPanelProfileView::onAvatarNameCached, this, _1, _2, _3, _4));
-
+/*
+// disable this part of code according to EXT-2022. See processOnlineStatus
// status should only show if viewer has permission to view online/offline. EXT-453
mStatusText->setVisible(isGrantedToSeeOnlineStatus());
updateOnlineStatus();
+*/
LLPanelProfile::onOpen(key);
}
@@ -92,6 +132,7 @@ BOOL LLPanelProfileView::postBuild()
getTabContainer()[PANEL_PROFILE]->childSetVisible("status_combo", FALSE);
mStatusText = getChild<LLTextBox>("status");
+ mStatusText->setVisible(false);
childSetCommitCallback("back",boost::bind(&LLPanelProfileView::onBackBtnClick,this),NULL);
@@ -103,6 +144,10 @@ BOOL LLPanelProfileView::postBuild()
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)
{
@@ -130,13 +175,18 @@ void LLPanelProfileView::updateOnlineStatus()
return;
bool online = relationship->isOnline();
-// std::string statusName();
std::string status = getString(online ? "status_online" : "status_offline");
mStatusText->setValue(status);
}
+void LLPanelProfileView::processOnlineStatus(bool online)
+{
+ mAvatarIsOnline = online;
+ mStatusText->setVisible(online);
+}
+
void LLPanelProfileView::onAvatarNameCached(const LLUUID& id, const std::string& first_name, const std::string& last_name, BOOL is_group)
{
llassert(getAvatarId() == id);
@@ -150,7 +200,7 @@ void LLPanelProfileView::togglePanel(LLPanel* panel)
{
// LLPanelProfile::togglePanel shows/hides all children,
// we don't want to display online status for non friends, so re-hide it here
- mStatusText->setVisible(isGrantedToSeeOnlineStatus());
+ mStatusText->setVisible(mAvatarIsOnline);
}
}
diff --git a/indra/newview/llpanelprofileview.h b/indra/newview/llpanelprofileview.h
index 07a6c3a9a0..45c2fc116e 100644
--- a/indra/newview/llpanelprofileview.h
+++ b/indra/newview/llpanelprofileview.h
@@ -36,10 +36,13 @@
#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,
@@ -49,6 +52,7 @@ class LLPanelProfileView : public LLPanelProfile
{
LOG_CLASS(LLPanelProfileView);
friend class LLUICtrlFactory;
+ friend class AvatarStatusObserver;
public:
@@ -62,11 +66,24 @@ public:
/*virtual*/ void togglePanel(LLPanel* panel);
+ 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();
- void updateOnlineStatus();
+ bool isGrantedToSeeOnlineStatus(); // deprecated after EXT-2022 is implemented
+ void updateOnlineStatus(); // deprecated after EXT-2022 is implemented
+ void processOnlineStatus(bool online);
private:
// LLCacheName will call this function when avatar name is loaded from server.
@@ -78,6 +95,8 @@ private:
BOOL is_group);
LLTextBox* mStatusText;
+ AvatarStatusObserver* mAvatarStatusObserver;
+ bool mAvatarIsOnline;
};
#endif //LL_LLPANELPROFILEVIEW_H
diff --git a/indra/newview/llpanelteleporthistory.cpp b/indra/newview/llpanelteleporthistory.cpp
index e71ddfb283..a34f029095 100644
--- a/indra/newview/llpanelteleporthistory.cpp
+++ b/indra/newview/llpanelteleporthistory.cpp
@@ -4,7 +4,7 @@
*
* $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
@@ -47,6 +47,10 @@
#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;
+
class LLTeleportHistoryFlatItem : public LLPanel
{
public:
@@ -56,6 +60,8 @@ public:
virtual BOOL postBuild();
S32 getIndex() { return mIndex; }
+ void setIndex(S32 index) { mIndex = index; }
+ const std::string& getRegionName() { return mRegionName;}
/*virtual*/ void setValue(const LLSD& value);
@@ -65,9 +71,10 @@ public:
static void showPlaceInfoPanel(S32 index);
private:
- void onInfoBtnClick();
+ void onProfileBtnClick();
- LLButton* mInfoBtn;
+ LLButton* mProfileBtn;
+
LLTeleportHistoryPanel::ContextMenu *mContextMenu;
S32 mIndex;
@@ -89,8 +96,9 @@ BOOL LLTeleportHistoryFlatItem::postBuild()
LLTextBox *region = getChild<LLTextBox>("region");
region->setValue(mRegionName);
- mInfoBtn = getChild<LLButton>("info_btn");
- mInfoBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onInfoBtnClick, this));
+ mProfileBtn = getChild<LLButton>("profile_btn");
+
+ mProfileBtn->setClickedCallback(boost::bind(&LLTeleportHistoryFlatItem::onProfileBtnClick, this));
return true;
}
@@ -105,7 +113,7 @@ void LLTeleportHistoryFlatItem::setValue(const LLSD& value)
void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", true);
- mInfoBtn->setVisible(true);
+ mProfileBtn->setVisible(true);
LLPanel::onMouseEnter(x, y, mask);
}
@@ -113,7 +121,7 @@ void LLTeleportHistoryFlatItem::onMouseEnter(S32 x, S32 y, MASK mask)
void LLTeleportHistoryFlatItem::onMouseLeave(S32 x, S32 y, MASK mask)
{
childSetVisible("hovered_icon", false);
- mInfoBtn->setVisible(false);
+ mProfileBtn->setVisible(false);
LLPanel::onMouseLeave(x, y, mask);
}
@@ -136,7 +144,7 @@ void LLTeleportHistoryFlatItem::showPlaceInfoPanel(S32 index)
LLSideTray::getInstance()->showPanel("panel_places", params);
}
-void LLTeleportHistoryFlatItem::onInfoBtnClick()
+void LLTeleportHistoryFlatItem::onProfileBtnClick()
{
LLTeleportHistoryFlatItem::showPlaceInfoPanel(mIndex);
}
@@ -175,7 +183,7 @@ LLContextMenu* LLTeleportHistoryPanel::ContextMenu::createMenu()
registrar.add("TeleportHistory.Teleport", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onTeleport, this));
registrar.add("TeleportHistory.MoreInformation",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onInfo, this));
- registrar.add("TeleportHistory.Copy", boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopy, this));
+ registrar.add("TeleportHistory.CopyToClipboard",boost::bind(&LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard, this));
// create the context menu from the XUI
return LLUICtrlFactory::getInstance()->createFromFile<LLContextMenu>(
@@ -198,11 +206,11 @@ void LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback(const std::string& sl
gClipboard.copyFromString(utf8str_to_wstring(slurl));
}
-void LLTeleportHistoryPanel::ContextMenu::onCopy()
+void LLTeleportHistoryPanel::ContextMenu::onCopyToClipboard()
{
LLVector3d globalPos = LLTeleportHistoryStorage::getInstance()->getItems()[mIndex].mGlobalPos;
LLLandmarkActions::getSLURLfromPosGlobal(globalPos,
- boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1), false);
+ boost::bind(&LLTeleportHistoryPanel::ContextMenu::gotSLURLCallback, _1));
}
// Not yet implemented; need to remove buildPanel() from constructor when we switch
@@ -211,11 +219,13 @@ void LLTeleportHistoryPanel::ContextMenu::onCopy()
LLTeleportHistoryPanel::LLTeleportHistoryPanel()
: LLPanelPlacesTab(),
mFilterSubString(LLStringUtil::null),
+ mDirty(true),
+ mCurrentItem(0),
mTeleportHistory(NULL),
mHistoryAccordion(NULL),
- mStarButton(NULL),
mAccordionTabMenu(NULL),
- mLastSelectedScrollList(NULL)
+ mLastSelectedFlatlList(NULL),
+ mLastSelectedItemIndex(-1)
{
LLUICtrlFactory::getInstance()->buildPanel(this, "panel_teleport_history.xml");
}
@@ -230,7 +240,7 @@ BOOL LLTeleportHistoryPanel::postBuild()
mTeleportHistory = LLTeleportHistoryStorage::getInstance();
if (mTeleportHistory)
{
- mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::showTeleportHistory, this));
+ mTeleportHistory->setHistoryChangedCallback(boost::bind(&LLTeleportHistoryPanel::onTeleportHistoryChange, this, _1));
}
mHistoryAccordion = getChild<LLAccordionCtrl>("history_accordion");
@@ -277,13 +287,19 @@ BOOL LLTeleportHistoryPanel::postBuild()
if(gear_menu)
mGearMenuHandle = gear_menu->getHandle();
- mStarButton = getChild<LLButton>("star_btn");
- mStarButton->setCommitCallback(boost::bind(&LLTeleportHistoryPanel::onStarButtonCommit, this));
-
return TRUE;
}
// virtual
+void LLTeleportHistoryPanel::draw()
+{
+ if (mDirty)
+ refresh();
+
+ LLPanelPlacesTab::draw();
+}
+
+// virtual
void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
{
if (mFilterSubString != string)
@@ -296,10 +312,10 @@ void LLTeleportHistoryPanel::onSearchEdit(const std::string& string)
// virtual
void LLTeleportHistoryPanel::onShowOnMap()
{
- if (!mLastSelectedScrollList)
+ if (!mLastSelectedFlatlList)
return;
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem());
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
if(!itemp)
return;
@@ -316,10 +332,10 @@ void LLTeleportHistoryPanel::onShowOnMap()
// virtual
void LLTeleportHistoryPanel::onTeleport()
{
- if (!mLastSelectedScrollList)
+ if (!mLastSelectedFlatlList)
return;
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem());
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
if(!itemp)
return;
@@ -357,161 +373,234 @@ void LLTeleportHistoryPanel::updateVerbs()
if (!isTabVisible())
return;
- if (!mLastSelectedScrollList)
+ if (!mLastSelectedFlatlList)
{
mTeleportBtn->setEnabled(false);
mShowOnMapBtn->setEnabled(false);
- mStarButton->setEnabled(false);
- mStarButton->setToolTip(LLStringExplicit(""));
return;
}
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem());
+ LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
mTeleportBtn->setEnabled(NULL != itemp && itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1);
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);
- if (NULL != itemp)
+ tab_idx = -1;
+
+ while (tab_idx < tabs_cnt - 1 && item_date < tab_date)
{
- LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos(
- mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos);
+ tab_idx++;
- mStarButton->setEnabled(true);
- if (!landmark || landmark->getUUID().isNull())
+ if (tab_idx <= tabs_cnt - 4)
{
- mStarButton->setToggleState(true);
- // Landmark can be created only for current agent positon, which is most recent (last) item in teleport history.
- // mTeleportBtn is disabled only for that item.
- mStarButton->setToolTip(mTeleportBtn->getEnabled() ? getString("cant_create_lm_here") : getString("create_landmark"));
+ tab_date.secondsSinceEpoch(tab_date.secondsSinceEpoch() - seconds_in_day);
}
- else
+ else if (tab_idx == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
{
- mStarButton->setToggleState(false);
- mStarButton->setToolTip(getString("open_landmark"));
+ 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);
}
- }
- else
- {
- mStarButton->setEnabled(false);
- mStarButton->setToolTip(LLStringExplicit(""));
}
}
-void LLTeleportHistoryPanel::showTeleportHistory()
+void LLTeleportHistoryPanel::refresh()
{
if (!mHistoryAccordion)
+ {
+ mDirty = false;
return;
+ }
- const LLTeleportHistoryStorage::slurl_list_t& hist_items = mTeleportHistory->getItems();
-
- const U32 seconds_in_day = 24 * 60 * 60;
- LLDate curr_date = LLDate::now();
-
- S32 curr_tab = -1;
- S32 tabs_cnt = mItemContainers.size();
- S32 curr_year = 0, curr_month = 0, curr_day = 0;
-
- curr_date.split(&curr_year, &curr_month, &curr_day);
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day); // Set hour, min, and sec to 0
- curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() + seconds_in_day);
+ const LLTeleportHistoryStorage::slurl_list_t& items = mTeleportHistory->getItems();
+ LLDate tab_boundary_date = LLDate::now();
LLFlatListView* curr_flat_view = NULL;
- S32 index = hist_items.size() - 1;
-
- for (LLTeleportHistoryStorage::slurl_list_t::const_reverse_iterator iter = hist_items.rbegin();
- iter != hist_items.rend(); ++iter)
+ U32 added_items = 0;
+ while (mCurrentItem >= 0)
{
- std::string landmark_title = (*iter).mTitle;
+ std::string landmark_title = items[mCurrentItem].mTitle;
LLStringUtil::toUpper(landmark_title);
std::string::size_type match_offset = mFilterSubString.size() ? landmark_title.find(mFilterSubString) : std::string::npos;
bool passed = mFilterSubString.size() == 0 || match_offset != std::string::npos;
if (!passed)
- continue;
-
- if (curr_tab < tabs_cnt - 1)
{
- const LLDate &date = (*iter).mDate;
-
- if (date < curr_date)
- {
- LLAccordionCtrlTab* tab = NULL;
- while (curr_tab < tabs_cnt - 1 && date < curr_date)
- {
- curr_tab++;
+ mCurrentItem--;
+ continue;
+ }
- tab = mItemContainers.get(mItemContainers.size() - 1 - curr_tab);
- tab->setVisible(false);
+ const LLDate &date = items[mCurrentItem].mDate;
- if (curr_tab <= tabs_cnt - 4)
- {
- curr_date.secondsSinceEpoch(curr_date.secondsSinceEpoch() - seconds_in_day);
- }
- else if (curr_tab == tabs_cnt - 3) // 6 day and older, low boundary is 1 month
- {
- curr_date = LLDate::now();
- curr_date.split(&curr_year, &curr_month, &curr_day);
- curr_month--;
- if (0 == curr_month)
- {
- curr_month = 12;
- curr_year--;
- }
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else if (curr_tab == tabs_cnt - 2) // 1 month and older, low boundary is 6 months
- {
- curr_date = LLDate::now();
- curr_date.split(&curr_year, &curr_month, &curr_day);
- if (curr_month > 6)
- {
- curr_month -= 6;
- }
- else
- {
- curr_month += 6;
- curr_year--;
- }
- curr_date.fromYMDHMS(curr_year, curr_month, curr_day);
- }
- else // 6 months and older
- {
- curr_date.secondsSinceEpoch(0);
- }
- }
+ if (date < tab_boundary_date)
+ {
+ S32 tab_idx = 0;
+ getNextTab(date, tab_idx, tab_boundary_date);
- tab->setVisible(true);
+ LLAccordionCtrlTab* tab = mItemContainers.get(mItemContainers.size() - 1 - tab_idx);
+ tab->setVisible(true);
- curr_flat_view = getFlatListViewFromTab(tab);
- if (curr_flat_view)
- {
- curr_flat_view->clear();
- }
- }
+ curr_flat_view = getFlatListViewFromTab(tab);
}
if (curr_flat_view)
{
- curr_flat_view->addItem(new LLTeleportHistoryFlatItem(index, &mContextMenu, (*iter).mTitle));
+ LLTeleportHistoryFlatItem* item = new LLTeleportHistoryFlatItem(mCurrentItem, &mContextMenu, items[mCurrentItem].mTitle);
+ curr_flat_view->addItem(item);
+
+ if (mLastSelectedItemIndex == mCurrentItem)
+ curr_flat_view->selectItem(item, true);
}
- index--;
- }
+ mCurrentItem--;
- // Hide empty tabs from current to bottom
- for (curr_tab++; curr_tab < tabs_cnt; curr_tab++)
- mItemContainers.get(mItemContainers.size() - 1 - curr_tab)->setVisible(false);
+ if (++added_items >= ADD_LIMIT)
+ break;
+ }
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
+}
+
+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 = new LLTeleportHistoryFlatItem(history_items.size(), // index will be decremented inside loop below
+ &mContextMenu,
+ history_items[history_items.size() - 1].mTitle); // Most recent item, it was
+ // added instead of removed
+ 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)
+ {
+ 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;
+ 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)
+ fv->clear();
+ }
+
+ refresh();
}
void LLTeleportHistoryPanel::handleItemSelect(LLFlatListView* selected)
{
- mLastSelectedScrollList = selected;
+ mLastSelectedFlatlList = selected;
+ LLTeleportHistoryFlatItem* item = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedFlatlList->getSelectedItem());
+ if (item)
+ mLastSelectedItemIndex = item->getIndex();
S32 tabs_cnt = mItemContainers.size();
@@ -628,8 +717,6 @@ bool LLTeleportHistoryPanel::onClearTeleportHistoryDialog(const LLSD& notificati
LLTeleportHistoryStorage *th = LLTeleportHistoryStorage::getInstance();
th->purgeItems();
th->save();
-
- showTeleportHistory();
}
return false;
@@ -669,28 +756,3 @@ void LLTeleportHistoryPanel::onGearButtonClicked()
LLMenuGL::showPopup(this, menu, menu_x, menu_y);
}
-void LLTeleportHistoryPanel::onStarButtonCommit()
-{
- if (!mLastSelectedScrollList)
- return;
-
- LLTeleportHistoryFlatItem* itemp = dynamic_cast<LLTeleportHistoryFlatItem *> (mLastSelectedScrollList->getSelectedItem());
- if(!itemp)
- return;
-
- if (itemp->getIndex() < (S32)mTeleportHistory->getItems().size() - 1)
- {
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
- }
- else
- {
- LLViewerInventoryItem *landmark = LLLandmarkActions::findLandmarkForGlobalPos(
- mTeleportHistory->getItems()[itemp->getIndex()].mGlobalPos);
-
- if (!landmark || landmark->getUUID().isNull())
- LLSideTray::getInstance()->showPanel("panel_places", LLSD().insert("type", "create_landmark"));
- else
- LLTeleportHistoryFlatItem::showPlaceInfoPanel(itemp->getIndex());
- }
-}
-
diff --git a/indra/newview/llpanelteleporthistory.h b/indra/newview/llpanelteleporthistory.h
index f487c92836..b34d9e876c 100644
--- a/indra/newview/llpanelteleporthistory.h
+++ b/indra/newview/llpanelteleporthistory.h
@@ -5,7 +5,7 @@
*
* $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
@@ -57,7 +57,7 @@ public:
LLContextMenu* createMenu();
void onTeleport();
void onInfo();
- void onCopy();
+ void onCopyToClipboard();
static void gotSLURLCallback(const std::string& slurl);
@@ -69,6 +69,8 @@ public:
virtual ~LLTeleportHistoryPanel();
/*virtual*/ BOOL postBuild();
+ /*virtual*/ void draw();
+
/*virtual*/ void onSearchEdit(const std::string& string);
/*virtual*/ void onShowOnMap();
/*virtual*/ void onTeleport();
@@ -86,17 +88,22 @@ private:
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();
- void onStarButtonCommit();
LLTeleportHistoryStorage* mTeleportHistory;
LLAccordionCtrl* mHistoryAccordion;
- LLButton * mStarButton;
- LLFlatListView* mLastSelectedScrollList;
+ LLFlatListView* mLastSelectedFlatlList;
+ S32 mLastSelectedItemIndex;
+ bool mDirty;
+ S32 mCurrentItem;
std::string mFilterSubString;
typedef LLDynamicArray<LLAccordionCtrlTab*> item_containers_t;
diff --git a/indra/newview/llpanelvolume.cpp b/indra/newview/llpanelvolume.cpp
index 4ac109bf3d..5a70842a73 100644
--- a/indra/newview/llpanelvolume.cpp
+++ b/indra/newview/llpanelvolume.cpp
@@ -57,7 +57,6 @@
#include "llfirstuse.h"
#include "llfocusmgr.h"
#include "llmanipscale.h"
-#include "llpanelinventory.h"
#include "llpreviewscript.h"
#include "llresmgr.h"
#include "llselectmgr.h"
diff --git a/indra/newview/llpanelvolume.h b/indra/newview/llpanelvolume.h
index 9d197aafa5..7bc935f986 100644
--- a/indra/newview/llpanelvolume.h
+++ b/indra/newview/llpanelvolume.h
@@ -45,7 +45,6 @@ class LLUICtrl;
class LLButton;
class LLViewerObject;
class LLComboBox;
-class LLPanelInventory;
class LLColorSwatchCtrl;
class LLPanelVolume : public LLPanel
diff --git a/indra/newview/llparticipantlist.cpp b/indra/newview/llparticipantlist.cpp
new file mode 100644
index 0000000000..32223e314e
--- /dev/null
+++ b/indra/newview/llparticipantlist.cpp
@@ -0,0 +1,177 @@
+/**
+ * @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 "llavatarlist.h"
+#include "llspeakers.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
+LLParticipantList::LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list):
+ mSpeakerMgr(data_source),
+ mAvatarList(avatar_list),
+ mSortOrder(E_SORT_BY_NAME)
+{
+ mSpeakerAddListener = new SpeakerAddListener(*this);
+ mSpeakerRemoveListener = new SpeakerRemoveListener(*this);
+ mSpeakerClearListener = new SpeakerClearListener(*this);
+
+ mSpeakerMgr->addListener(mSpeakerAddListener, "add");
+ mSpeakerMgr->addListener(mSpeakerRemoveListener, "remove");
+ mSpeakerMgr->addListener(mSpeakerClearListener, "clear");
+
+ mAvatarList->setNoItemsCommentText(LLTrans::getString("LoadingData"));
+ mAvatarList->setDoubleClickCallback(boost::bind(&LLParticipantList::onAvatarListDoubleClicked, this, mAvatarList));
+
+ //Lets fill avatarList with existing speakers
+ LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+
+ 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++)
+ {
+ group_members.push_back((*it)->mID);
+ }
+ sort();
+}
+
+LLParticipantList::~LLParticipantList()
+{
+}
+
+void LLParticipantList::onAvatarListDoubleClicked(LLAvatarList* list)
+{
+ LLUUID clicked_id = list->getSelectedUUID();
+
+ if (clicked_id.isNull() || clicked_id == gAgent.getID())
+ return;
+
+ LLAvatarActions::startIM(clicked_id);
+}
+
+void LLParticipantList::setSortOrder(EParticipantSortOrder order)
+{
+ if ( mSortOrder != order )
+ {
+ mSortOrder = order;
+ sort();
+ }
+}
+
+bool LLParticipantList::onAddItemEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ LLAvatarList::uuid_vector_t& group_members = mAvatarList->getIDs();
+ LLUUID uu_id = event->getValue().asUUID();
+
+ LLAvatarList::uuid_vector_t::iterator found = std::find(group_members.begin(), group_members.end(), uu_id);
+ if(found != group_members.end())
+ {
+ llinfos << "Already got a buddy" << llendl;
+ return true;
+ }
+
+ group_members.push_back(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;
+}
+
+void LLParticipantList::sort()
+{
+ if ( !mAvatarList )
+ return;
+
+ // Mark AvatarList as dirty one
+ mAvatarList->setDirty();
+
+ // TODO: Implement more sorting orders after specs updating (EM)
+ switch ( mSortOrder ) {
+ case E_SORT_BY_NAME :
+ mAvatarList->sortByName();
+ break;
+ default :
+ llwarns << "Unrecognized sort order for " << mAvatarList->getName() << llendl;
+ return;
+ }
+}
+
+//
+// LLParticipantList::SpeakerAddListener
+//
+bool LLParticipantList::SpeakerAddListener::handleEvent(LLPointer<LLOldEvents::LLEvent> event, const LLSD& userdata)
+{
+ 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);
+}
diff --git a/indra/newview/llparticipantlist.h b/indra/newview/llparticipantlist.h
new file mode 100644
index 0000000000..8c209c0b20
--- /dev/null
+++ b/indra/newview/llparticipantlist.h
@@ -0,0 +1,111 @@
+/**
+ * @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"
+
+class LLSpeakerMgr;
+class LLAvatarList;
+
+class LLParticipantList
+{
+ LOG_CLASS(LLParticipantList);
+ public:
+ LLParticipantList(LLSpeakerMgr* data_source, LLAvatarList* avatar_list);
+ ~LLParticipantList();
+
+ typedef enum e_participant_sort_oder {
+ E_SORT_BY_NAME = 0,
+ } EParticipantSortOrder;
+
+ /**
+ * Set and sort Avatarlist by given order
+ */
+ void setSortOrder(EParticipantSortOrder order = E_SORT_BY_NAME);
+
+ 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);
+
+ /**
+ * 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);
+ };
+
+ private:
+ void onAvatarListDoubleClicked(LLAvatarList* list);
+
+ LLSpeakerMgr* mSpeakerMgr;
+ LLAvatarList* mAvatarList;
+
+ LLPointer<SpeakerAddListener> mSpeakerAddListener;
+ LLPointer<SpeakerRemoveListener> mSpeakerRemoveListener;
+ LLPointer<SpeakerClearListener> mSpeakerClearListener;
+
+ EParticipantSortOrder mSortOrder;
+};
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/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 ab253e012d..34e78b5c46 100644
--- a/indra/newview/llpreview.cpp
+++ b/indra/newview/llpreview.cpp
@@ -45,6 +45,7 @@
#include "lltooldraganddrop.h"
#include "llradiogroup.h"
#include "llassetstorage.h"
+#include "llviewerassettype.h"
#include "llviewerobject.h"
#include "llviewerobjectlist.h"
#include "lldbstrings.h"
@@ -317,7 +318,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())
{
@@ -406,7 +407,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;
@@ -492,3 +493,31 @@ void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
}
}
+
+void LLPreview::setAssetId(const LLUUID& asset_id)
+{
+ const LLViewerInventoryItem* item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
+ if(NULL == item)
+ {
+ return;
+ }
+
+ 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
+ {
+ // 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 c5f2bfcf47..506c135ca6 100644
--- a/indra/newview/llpreview.h
+++ b/indra/newview/llpreview.h
@@ -77,6 +77,7 @@ public:
void setObjectID(const LLUUID& object_id);
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 );
diff --git a/indra/newview/llpreviewgesture.cpp b/indra/newview/llpreviewgesture.cpp
index 32ed20bd56..7b3a20d102 100644
--- a/indra/newview/llpreviewgesture.cpp
+++ b/indra/newview/llpreviewgesture.cpp
@@ -130,10 +130,10 @@ LLPreviewGesture* LLPreviewGesture::show(const LLUUID& item_id, const LLUUID& ob
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.
@@ -1178,7 +1178,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
diff --git a/indra/newview/llpreviewscript.cpp b/indra/newview/llpreviewscript.cpp
index 19bb60b237..2382befcfa 100644
--- a/indra/newview/llpreviewscript.cpp
+++ b/indra/newview/llpreviewscript.cpp
@@ -89,7 +89,6 @@
#include "lltrans.h"
#include "llviewercontrol.h"
#include "llappviewer.h"
-#include "llpanelinventory.h"
const std::string HELLO_LSL =
"default\n"
@@ -452,7 +451,7 @@ bool LLScriptEdCore::hasChanged()
{
if (!mEditor) return false;
- return !mEditor->isPristine();
+ return ((!mEditor->isPristine() || mEnableSave) && mHasScriptData);
}
void LLScriptEdCore::draw()
@@ -1260,7 +1259,7 @@ 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.
@@ -1383,6 +1382,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset
delete item_uuid;
}
+
/// ---------------------------------------------------------------------------
/// LLLiveLSLEditor
/// ---------------------------------------------------------------------------
@@ -2145,6 +2145,7 @@ void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**)
}
}
+
void LLLiveLSLEditor::onMonoCheckboxClicked(LLUICtrl*, void* userdata)
{
LLLiveLSLEditor* self = static_cast<LLLiveLSLEditor*>(userdata);
diff --git a/indra/newview/llpreviewtexture.cpp b/indra/newview/llpreviewtexture.cpp
index 9d7338c111..86fa2c4695 100644
--- a/indra/newview/llpreviewtexture.cpp
+++ b/indra/newview/llpreviewtexture.cpp
@@ -38,6 +38,7 @@
#include "llagent.h"
#include "llbutton.h"
+#include "llcombobox.h"
#include "llfilepicker.h"
#include "llfloaterreg.h"
#include "llimagetga.h"
@@ -57,6 +58,10 @@ const S32 CLIENT_RECT_VPAD = 4;
const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
+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 ),
@@ -65,7 +70,8 @@ LLPreviewTexture::LLPreviewTexture(const LLSD& key)
mIsCopyable(FALSE),
mUpdateDimensions(TRUE),
mLastHeight(0),
- mLastWidth(0)
+ mLastWidth(0),
+ mAspectRatio(0.f)
{
const LLInventoryItem *item = getItem();
if(item)
@@ -144,6 +150,10 @@ BOOL LLPreviewTexture::postBuild()
}
}
+ childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
+ LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
+ combo->setCurrentByIndex(0);
+
return LLPreview::postBuild();
}
@@ -369,8 +379,13 @@ void LLPreviewTexture::updateDimensions()
S32 max_client_width = gViewerWindow->getWindowWidth() - horiz_pad;
S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad;
+ if (mAspectRatio > 0.f)
+ {
+ client_height = llceil((F32)client_width / mAspectRatio);
+ }
+
while ((client_width > max_client_width) ||
- (client_height > max_client_height ) )
+ (client_height > max_client_height ))
{
client_width /= 2;
client_height /= 2;
@@ -383,12 +398,12 @@ void LLPreviewTexture::updateDimensions()
childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->getFullWidth()));
childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->getFullHeight()));
- // add space for dimensions
+ // add space for dimensions and aspect ratio
S32 info_height = 0;
- LLRect dim_rect;
- childGetRect("dimensions", dim_rect);
- S32 dim_height = dim_rect.getHeight();
- info_height += dim_height + CLIENT_RECT_VPAD;
+ LLRect aspect_rect;
+ childGetRect("combo_aspect_ratio", aspect_rect);
+ S32 aspect_height = aspect_rect.getHeight();
+ info_height += aspect_height + CLIENT_RECT_VPAD;
view_height += info_height;
S32 button_height = 0;
@@ -445,27 +460,99 @@ void LLPreviewTexture::updateDimensions()
else
{
client_width = getRect().getWidth() - horiz_pad;
- client_height = getRect().getHeight() - vert_pad;
+ if (mAspectRatio > 0)
+ {
+ client_height = llround(client_width / mAspectRatio);
+ }
+ else
+ {
+ client_height = getRect().getHeight() - vert_pad;
+ }
}
- S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height
+ 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);
+ if (mAspectRatio > 0.f)
+ {
+ max_height = llmax(max_height, 1);
+
+ if (client_height > max_height)
+ {
+ client_height = max_height;
+ client_width = llround(client_height * mAspectRatio);
+ }
+ }
+ else
+ {
+ S32 max_width = getRect().getWidth() - horiz_pad;
+
+ client_height = llclamp(client_height, 1, max_height);
+ client_width = llclamp(client_width, 1, max_width);
+ }
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);
+ mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
+
+ // Hide the aspect ratio label if the window is too narrow
+ // Assumes the label should be to the right of the dimensions
+ LLRect dim_rect, aspect_label_rect;
+ childGetRect("aspect_ratio", aspect_label_rect);
+ childGetRect("dimensions", dim_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))
+ {
+ 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);
}
+void LLPreviewTexture::onAspectRatioCommit(LLUICtrl* ctrl, void* userdata)
+{
+ LLPreviewTexture* self = (LLPreviewTexture*) userdata;
+
+ 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 = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ mImage = LLViewerTextureManager::getFetchedTexture(mImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mImage->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
mAssetStatus = PREVIEW_ASSET_LOADING;
updateDimensions();
diff --git a/indra/newview/llpreviewtexture.h b/indra/newview/llpreviewtexture.h
index 9ace304fa6..520626b49f 100644
--- a/indra/newview/llpreviewtexture.h
+++ b/indra/newview/llpreviewtexture.h
@@ -38,6 +38,7 @@
#include "llframetimer.h"
#include "llviewertexture.h"
+class LLComboBox;
class LLImageRaw;
class LLPreviewTexture : public LLPreview
@@ -71,7 +72,9 @@ public:
protected:
void init();
/* virtual */ BOOL postBuild();
-
+ bool setAspectRatio(const F32 width, const F32 height);
+ static void onAspectRatioCommit(LLUICtrl*,void* userdata);
+
private:
void updateDimensions();
LLUUID mImageID;
@@ -88,6 +91,7 @@ private:
S32 mLastHeight;
S32 mLastWidth;
+ F32 mAspectRatio;
BOOL mUpdateDimensions;
};
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
index f704fecddd..760b1a7a4c 100644
--- a/indra/newview/llrootview.h
+++ b/indra/newview/llrootview.h
@@ -47,5 +47,27 @@ public:
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/llscreenchannel.cpp b/indra/newview/llscreenchannel.cpp
index a72100a9b3..e4dbcbd219 100644
--- a/indra/newview/llscreenchannel.cpp
+++ b/indra/newview/llscreenchannel.cpp
@@ -44,7 +44,6 @@
#include "lltrans.h"
#include "lldockablefloater.h"
-#include "llimpanel.h"
#include "llsyswellwindow.h"
#include "llimfloater.h"
@@ -138,7 +137,7 @@ void LLScreenChannel::updatePositionAndSize(LLRect old_world_rect, LLRect new_wo
}
//--------------------------------------------------------------------------
-void LLScreenChannel::addToast(LLToast::Params p)
+void LLScreenChannel::addToast(const LLToast::Params& p)
{
bool store_toast = false, show_toast = false;
@@ -191,19 +190,22 @@ void LLScreenChannel::onToastFade(LLToast* toast)
{
std::vector<ToastElem>::iterator it = find(mToastList.begin(), mToastList.end(), static_cast<LLPanel*>(toast));
- bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
- if(delete_toast)
- {
- mToastList.erase(it);
- deleteToast(toast);
- }
- else
+ if(it != mToastList.end())
{
- storeToast((*it));
- mToastList.erase(it);
- }
+ bool delete_toast = !mCanStoreToasts || !toast->getCanBeStored();
+ if(delete_toast)
+ {
+ mToastList.erase(it);
+ deleteToast(toast);
+ }
+ else
+ {
+ storeToast((*it));
+ mToastList.erase(it);
+ }
- redrawToasts();
+ redrawToasts();
+ }
}
//--------------------------------------------------------------------------
@@ -247,6 +249,7 @@ void LLScreenChannel::loadStoredToastsToChannel()
for(it = mStoredToastList.begin(); it != mStoredToastList.end(); ++it)
{
+ (*it).toast->setIsHidden(false);
(*it).toast->resetTimer();
mToastList.push_back((*it));
}
@@ -266,6 +269,7 @@ void LLScreenChannel::loadStoredToastByNotificationIDToChannel(LLUUID id)
mOverflowToastHidden = false;
LLToast* toast = (*it).toast;
+ toast->setIsHidden(false);
toast->resetTimer();
mToastList.push_back((*it));
mStoredToastList.erase(it);
@@ -381,7 +385,7 @@ void LLScreenChannel::showToastsBottom()
if(it != mToastList.rbegin())
{
bottom = (*(it-1)).toast->getRect().mTop;
- toast_margin = gSavedSettings.getS32("ToastMargin");
+ toast_margin = gSavedSettings.getS32("ToastGap");
}
toast_rect = (*it).toast->getRect();
@@ -394,7 +398,7 @@ void LLScreenChannel::showToastsBottom()
{
if( it != mToastList.rend()-1)
{
- stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastMargin")) > getRect().mTop;
+ stop_showing_toasts = ((*it).toast->getRect().mTop + gSavedSettings.getS32("OverflowToastHeight") + gSavedSettings.getS32("ToastGap")) > getRect().mTop;
}
}
@@ -412,7 +416,7 @@ void LLScreenChannel::showToastsBottom()
(*it).toast->stopTimer();
mHiddenToastsNum++;
}
- createOverflowToast(bottom, gSavedSettings.getS32("NotificationToastTime"));
+ createOverflowToast(bottom, gSavedSettings.getS32("NotificationTipToastLifeTime"));
}
}
@@ -426,7 +430,7 @@ void LLScreenChannel::showToastsCentre()
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("ToastMargin"), toast_rect.getWidth() ,toast_rect.getHeight());
+ 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);
@@ -443,13 +447,13 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
{
LLRect toast_rect;
LLToast::Params p;
- p.timer_period = timer;
+ p.lifetime_secs = timer;
mOverflowToastPanel = new LLToast(p);
if(!mOverflowToastPanel)
return;
- mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::onOverflowToastHide, this));
+ mOverflowToastPanel->setOnFadeCallback(boost::bind(&LLScreenChannel::closeOverflowToastPanel, this));
LLTextBox* text_box = mOverflowToastPanel->getChild<LLTextBox>("toast_text");
LLIconCtrl* icon = mOverflowToastPanel->getChild<LLIconCtrl>("icon");
@@ -465,7 +469,7 @@ void LLScreenChannel::createOverflowToast(S32 bottom, F32 timer)
toast_rect = mOverflowToastPanel->getRect();
mOverflowToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
- toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight());
+ toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());
mOverflowToastPanel->setRect(toast_rect);
text_box->setValue(text);
@@ -514,11 +518,12 @@ void LLScreenChannel::closeOverflowToastPanel()
}
//--------------------------------------------------------------------------
-void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer)
+void LLScreenChannel::createStartUpToast(S32 notif_num, F32 timer)
{
LLRect toast_rect;
LLToast::Params p;
- p.timer_period = timer;
+ p.lifetime_secs = timer;
+ p.enable_hide_btn = false;
mStartUpToastPanel = new LLToast(p);
if(!mStartUpToastPanel)
@@ -545,13 +550,15 @@ void LLScreenChannel::createStartUpToast(S32 notif_num, S32 bottom, F32 timer)
toast_rect = mStartUpToastPanel->getRect();
mStartUpToastPanel->reshape(getRect().getWidth(), toast_rect.getHeight(), true);
- toast_rect.setLeftTopAndSize(getRect().mLeft, bottom + toast_rect.getHeight()+gSavedSettings.getS32("ToastMargin"), getRect().getWidth(), toast_rect.getHeight());
+ toast_rect.setLeftTopAndSize(0, toast_rect.getHeight()+gSavedSettings.getS32("ToastGap"), getRect().getWidth(), toast_rect.getHeight());
mStartUpToastPanel->setRect(toast_rect);
text_box->setValue(text);
text_box->setVisible(TRUE);
icon->setVisible(TRUE);
+ addChild(mStartUpToastPanel);
+
mStartUpToastPanel->setVisible(TRUE);
}
@@ -572,7 +579,7 @@ void LLScreenChannel::closeStartUpToast()
{
if(mStartUpToastPanel != NULL)
{
- mStartUpToastPanel->closeFloater();
+ mStartUpToastPanel->setVisible(FALSE);
mStartUpToastPanel = NULL;
}
}
@@ -703,7 +710,7 @@ void LLScreenChannel::updateShowToastsState()
LLRect this_rect = getRect();
if(floater->getVisible() && floater->isDocked())
{
- channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastMargin"));
+ channel_bottom += (floater->getRect().getHeight() + gSavedSettings.getS32("ToastGap"));
}
if(channel_bottom != this_rect.mBottom)
diff --git a/indra/newview/llscreenchannel.h b/indra/newview/llscreenchannel.h
index 459c28ac7c..fd31690622 100644
--- a/indra/newview/llscreenchannel.h
+++ b/indra/newview/llscreenchannel.h
@@ -158,7 +158,7 @@ public:
// Operating with toasts
// add a toast to a channel
- void addToast(LLToast::Params p);
+ void addToast(const LLToast::Params& p);
// kill or modify a toast by its ID
void killToastByNotificationID(LLUUID id);
void modifyToastByNotificationID(LLUUID id, LLPanel* panel);
@@ -204,8 +204,7 @@ public:
// 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); }
+ reject_tost_signal_t mRejectToastSignal; boost::signals2::connection setOnRejectToastCallback(reject_tost_callback_t cb) { return mRejectToastSignal.connect(cb); }
private:
struct ToastElem
@@ -256,7 +255,7 @@ private:
void createOverflowToast(S32 bottom, F32 timer);
// create the StartUp Toast
- void createStartUpToast(S32 notif_num, S32 bottom, F32 timer);
+ void createStartUpToast(S32 notif_num, F32 timer);
// Channel's flags
static bool mWasStartUpToastShown;
diff --git a/indra/newview/llscrollingpanelparam.cpp b/indra/newview/llscrollingpanelparam.cpp
new file mode 100644
index 0000000000..1fbaeb94f5
--- /dev/null
+++ b/indra/newview/llscrollingpanelparam.cpp
@@ -0,0 +1,388 @@
+/**
+ * @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, param, min_weight);
+ pos_x += PARAM_HINT_WIDTH + 3 * BTN_BORDER;
+ mHintMax = new LLVisualParamHint( pos_x, pos_y, PARAM_HINT_WIDTH, PARAM_HINT_HEIGHT, mesh, param, 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);
+
+ // *TODO: Translate
+ std::string min_name = param->getMinDisplayName();
+ std::string max_name = 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
index 0b7621daa5..f95671685b 100644
--- a/indra/newview/llsearchcombobox.cpp
+++ b/indra/newview/llsearchcombobox.cpp
@@ -34,6 +34,7 @@
#include "llsearchcombobox.h"
#include "llkeyboard.h"
+#include "lltrans.h" // for LLTrans::getString()
#include "lluictrlfactory.h"
static LLDefaultChildRegistry::Register<LLSearchComboBox> r1("search_combo_box");
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index d163ceb30e..dd07a3c015 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -545,7 +545,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.
@@ -801,6 +801,8 @@ LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp, S32
return NULL;
}
+ mHoverObjects->mPrimaryObject = objectp;
+
objectp = objectp->getRootEdit();
// is the requested object the same as the existing hover object root?
@@ -834,6 +836,11 @@ LLSelectNode *LLSelectMgr::getHoverNode()
return mHoverObjects->getFirstRootNode();
}
+LLSelectNode *LLSelectMgr::getPrimaryHoverNode()
+{
+ return mHoverObjects->mSelectNodeMap[mHoverObjects->mPrimaryObject];
+}
+
void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp)
{
if (!objectp)
@@ -1441,7 +1448,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, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE));
+ objectp->setTEImage(te, LLViewerTextureManager::getFetchedTexture(mImageID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
return true;
}
@@ -1597,7 +1604,7 @@ BOOL LLSelectMgr::selectionRevertTextures()
}
else
{
- object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE));
+ object->setTEImage(te, LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
}
@@ -2460,8 +2467,7 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& result_id, std::string& name)
BOOL public_owner = (first_id.isNull() && !first_group_owned);
if (first_group_owned)
{
- // *TODO: We don't have group inspectors yet
- name = LLSLURL::buildCommand("group", first_id, "about");
+ name = LLSLURL::buildCommand("group", first_id, "inspect");
}
else if(!public_owner)
{
@@ -2821,7 +2827,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",
@@ -3400,7 +3406,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++ )
@@ -3490,6 +3496,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())
{
@@ -3590,6 +3597,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 ||
@@ -4595,7 +4605,7 @@ void LLSelectMgr::updateSilhouettes()
if (!mSilhouetteImagep)
{
- mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, TRUE);
+ mSilhouetteImagep = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", TRUE, LLViewerTexture::BOOST_UI);
}
mHighlightedObjects->cleanupNodes();
@@ -4903,7 +4913,7 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud)
{
inspect_item_id = inspect_instance->getSelectedUUID();
}
- LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getSelectedUUID();
+ LLUUID focus_item_id = LLViewerMediaFocus::getInstance()->getFocusedObjectID();
for (S32 pass = 0; pass < 2; pass++)
{
for (LLObjectSelection::iterator iter = mSelectedObjects->begin();
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 296502ff16..2050a73f26 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -404,6 +404,7 @@ public:
LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp, S32 face = -1);
LLSelectNode *getHoverNode();
+ LLSelectNode *getPrimaryHoverNode();
void highlightObjectOnly(LLViewerObject *objectp);
void highlightObjectAndFamily(LLViewerObject *objectp);
@@ -660,7 +661,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);
diff --git a/indra/newview/llsidepanelinventory.cpp b/indra/newview/llsidepanelinventory.cpp
new file mode 100644
index 0000000000..3cf17fb7f2
--- /dev/null
+++ b/indra/newview/llsidepanelinventory.cpp
@@ -0,0 +1,244 @@
+/**
+ * @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 "llsidepanelobjectinfo.h"
+#include "lltabcontainer.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";
+
+static LLRegisterPanelClassWrapper<LLSidepanelInventory> t_inventory("sidepanel_inventory");
+
+LLSidepanelInventory::LLSidepanelInventory()
+ : LLPanel(),
+ mSidepanelObjectInfo(NULL)
+{
+
+ //LLUICtrlFactory::getInstance()->buildPanel(this, "panel_inventory.xml"); // Called from LLRegisterPanelClass::defaultPanelClassBuilder()
+}
+
+LLSidepanelInventory::~LLSidepanelInventory()
+{
+}
+
+BOOL LLSidepanelInventory::postBuild()
+{
+ mInfoBtn = getChild<LLButton>("info_btn");
+ mInfoBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onInfoButtonClicked, this));
+
+ mShareBtn = getChild<LLButton>("share_btn");
+ mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this));
+
+ mShareBtn = getChild<LLButton>("share_btn");
+ mShareBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onShareButtonClicked, this));
+
+ mWearBtn = getChild<LLButton>("wear_btn");
+ mWearBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onWearButtonClicked, this));
+
+ mPlayBtn = getChild<LLButton>("play_btn");
+ mPlayBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onPlayButtonClicked, this));
+
+ mTeleportBtn = getChild<LLButton>("teleport_btn");
+ mTeleportBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onTeleportButtonClicked, this));
+
+ mOverflowBtn = getChild<LLButton>("overflow_btn");
+ mOverflowBtn->setClickedCallback(boost::bind(&LLSidepanelInventory::onOverflowButtonClicked, this));
+
+ mTabContainer = getChild<LLTabContainer>("Inventory Tabs");
+ mSidepanelObjectInfo = getChild<LLSidepanelObjectInfo>("sidepanel_object_info");
+
+ mPanelMainInventory = getChild<LLPanelMainInventory>("panel_main_inventory");
+ mPanelMainInventory->setSelectCallback(boost::bind(&LLSidepanelInventory::onSelectionChange, this, _1, _2));
+
+ LLButton* back_btn = mSidepanelObjectInfo->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;
+
+ mSidepanelObjectInfo->reset();
+
+ if (key.has("id"))
+ {
+ mSidepanelObjectInfo->setItemID(key["id"].asUUID());
+ }
+
+ if (key.has("object"))
+ {
+ mSidepanelObjectInfo->setObjectID(key["object"].asUUID());
+ }
+
+ toggleObjectInfoPanel(TRUE);
+}
+
+void LLSidepanelInventory::onInfoButtonClicked()
+{
+ LLInventoryItem *item = getSelectedItem();
+ if (item)
+ {
+ mSidepanelObjectInfo->reset();
+ mSidepanelObjectInfo->setItemID(item->getUUID());
+ toggleObjectInfoPanel(TRUE);
+ }
+}
+
+void LLSidepanelInventory::onShareButtonClicked()
+{
+}
+
+void LLSidepanelInventory::performActionOnSelection(const std::string &action)
+{
+ LLInventoryPanel *panel = mPanelMainInventory->getActivePanel();
+ LLFolderViewItem* current_item = panel->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return;
+ }
+ current_item->getListener()->performAction(panel->getRootFolder(), panel->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()
+{
+ toggleObjectInfoPanel(FALSE);
+ updateVerbs();
+}
+
+void LLSidepanelInventory::onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action)
+{
+ updateVerbs();
+}
+
+void LLSidepanelInventory::toggleObjectInfoPanel(BOOL visible)
+{
+ mSidepanelObjectInfo->setVisible(visible);
+ mTabContainer->setVisible(!visible);
+
+ if (visible)
+ {
+ mSidepanelObjectInfo->reset();
+ mSidepanelObjectInfo->setEditMode(FALSE);
+
+ LLRect rect = getRect();
+ LLRect new_rect = LLRect(rect.mLeft, rect.mTop, rect.mRight, mTabContainer->getRect().mBottom);
+ mSidepanelObjectInfo->reshape(new_rect.getWidth(),new_rect.getHeight());
+ }
+}
+
+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;
+
+ mInfoBtn->setEnabled(TRUE);
+ mShareBtn->setEnabled(TRUE);
+
+ 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()
+{
+ LLFolderViewItem* current_item = mPanelMainInventory->getActivePanel()->getRootFolder()->getCurSelectedItem();
+ if (!current_item)
+ {
+ return NULL;
+ }
+ const LLUUID &item_id = current_item->getListener()->getUUID();
+ LLInventoryItem *item = gInventory.getItem(item_id);
+ return item;
+}
diff --git a/indra/newview/llsidepanelinventory.h b/indra/newview/llsidepanelinventory.h
new file mode 100644
index 0000000000..62eeecc5e2
--- /dev/null
+++ b/indra/newview/llsidepanelinventory.h
@@ -0,0 +1,80 @@
+/**
+ * @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 LLInventoryItem;
+class LLSidepanelObjectInfo;
+class LLTabContainer;
+class LLPanelMainInventory;
+class LLFolderViewItem;
+
+class LLSidepanelInventory : public LLPanel
+{
+public:
+ LLSidepanelInventory();
+ virtual ~LLSidepanelInventory();
+
+ /*virtual*/ BOOL postBuild();
+ /*virtual*/ void onOpen(const LLSD& key);
+
+protected:
+ LLInventoryItem *getSelectedItem();
+ void onSelectionChange(const std::deque<LLFolderViewItem*> &items, BOOL user_action);
+ void onTabSelected();
+ void toggleObjectInfoPanel(BOOL visible);
+ void updateVerbs();
+ void performActionOnSelection(const std::string &action);
+
+ LLTabContainer* mTabContainer;
+ LLSidepanelObjectInfo* mSidepanelObjectInfo;
+ LLPanelMainInventory* mPanelMainInventory;
+
+ void onInfoButtonClicked();
+ void onShareButtonClicked();
+ void onWearButtonClicked();
+ void onPlayButtonClicked();
+ void onTeleportButtonClicked();
+ void onOverflowButtonClicked();
+ void onBackButtonClicked();
+
+ LLButton* mInfoBtn;
+ LLButton* mShareBtn;
+ LLButton* mWearBtn;
+ LLButton* mPlayBtn;
+ LLButton* mTeleportBtn;
+ LLButton* mOverflowBtn;
+};
+
+#endif //LL_LLSIDEPANELINVENTORY_H
diff --git a/indra/newview/llsidetray.cpp b/indra/newview/llsidetray.cpp
index 2be0aa40d2..a11ee05532 100644
--- a/indra/newview/llsidetray.cpp
+++ b/indra/newview/llsidetray.cpp
@@ -111,12 +111,72 @@ bool LLSideTray::instanceCreated ()
return sInstance!=0;
}
-LLSideTrayTab::LLSideTrayTab(const Params& params):mMainPanel(0)
+//////////////////////////////////////////////////////////////////////////////
+// LLSideTrayTab
+// Represents a single tab in the side tray, only used by LLSideTray
+//////////////////////////////////////////////////////////////////////////////
+
+class LLSideTrayTab: public LLPanel
{
- mImagePath = params.image_path;
- mTabTitle = params.tab_title;
- mDescription = params.description;
+ 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 arrange (S32 width, S32 height);
+ 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 draw();
+
+ void onOpen (const LLSD& key);
+
+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);
}
@@ -144,12 +204,6 @@ BOOL LLSideTrayTab::postBuild()
title_panel->getChild<LLTextBox>(TAB_PANEL_CAPTION_TITLE_BOX)->setValue(mTabTitle);
- static LLUIColor default_background_color = LLUIColorTable::instance().getColor("FloaterDefaultBackgroundColor");
- static LLUIColor focus_background_color = LLUIColorTable::instance().getColor("FloaterFocusBackgroundColor");
-
- setTransparentColor(default_background_color);
- setBackgroundColor(focus_background_color);
-
return true;
}
@@ -209,11 +263,6 @@ void LLSideTrayTab::reshape (S32 width, S32 height, BOOL called_from_parent )
void LLSideTrayTab::draw()
{
LLPanel::draw();
-
- //border
- gl_rect_2d(0,0,getRect().getWidth() - 1,getRect().getHeight() - 1,LLColor4::black,false);
-
-
}
void LLSideTrayTab::onOpen (const LLSD& key)
@@ -232,6 +281,18 @@ LLSideTrayTab* LLSideTrayTab::createInstance ()
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)
@@ -266,35 +327,6 @@ BOOL LLSideTray::postBuild()
setMouseOpaque(false);
return true;
}
-
-/**
- * add new panel to tab with tab_name name
- * @param tab_name - name of sidebar tab to add new panel
- * @param panel - pointer to panel
- */
-bool LLSideTray::addPanel ( const std::string& tab_name
- ,LLPanel* panel )
-{
- return false;
-}
-/**
- * Add new tab to side bar
- * @param tab_name - name of the new tab
- * @param image - image for new sidebar button
- * @param title - title for new tab
- */
-bool LLSideTray::addTab ( const std::string& tab_name
- ,const std::string& image
- ,const std::string& title)
-{
- LLSideTrayTab::Params params;
- params.image_path = image;
- params.tab_title = title;
- LLSideTrayTab* tab = LLUICtrlFactory::create<LLSideTrayTab> (params);
- addChild(tab,1);
- return true;
-}
-
LLSideTrayTab* LLSideTray::getTab(const std::string& name)
{
@@ -302,15 +334,19 @@ LLSideTrayTab* LLSideTray::getTab(const std::string& name)
}
-
-void LLSideTray::toggleTabButton (LLSideTrayTab* tab)
+void LLSideTray::toggleTabButton(LLSideTrayTab* tab)
{
if(tab == NULL)
return;
- string name = tab->getName();
- std::map<std::string,LLButton*>::iterator tIt = mTabButtons.find(name);
- if(tIt!=mTabButtons.end())
- tIt->second->setToggleState(!tIt->second->getToggleState());
+ 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)
@@ -318,9 +354,7 @@ bool LLSideTray::selectTabByIndex(size_t index)
if(index>=mTabs.size())
return false;
- LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(mTabs[index]);
- if(sidebar_tab == NULL)
- return false;
+ LLSideTrayTab* sidebar_tab = mTabs[index];
return selectTabByName(sidebar_tab->getName());
}
@@ -349,9 +383,7 @@ bool LLSideTray::selectTabByName (const std::string& name)
child_vector_const_iter_t child_it;
for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
{
- LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
+ LLSideTrayTab* sidebar_tab = *child_it;
sidebar_tab->setVisible(sidebar_tab == mActiveTab);
}
return true;
@@ -404,30 +436,42 @@ bool LLSideTray::addChild(LLView* view, S32 tab_group)
void LLSideTray::createButtons ()
{
- //create show/hide button
- mCollapseButton = createButton(EXPANDED_NAME,"",boost::bind(&LLSideTray::onToggleCollapse, this));
-
//create buttons for tabs
child_vector_const_iter_t child_it = mTabs.begin();
- ++child_it;
-
for ( ; child_it != mTabs.end(); ++child_it)
{
- LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
+ LLSideTrayTab* sidebar_tab = *child_it;
- string name = sidebar_tab->getName();
+ std::string name = sidebar_tab->getName();
- LLButton* button = createButton("",sidebar_tab->mImagePath,boost::bind(&LLSideTray::onTabButtonClick, this, sidebar_tab->getName()));
- mTabButtons[sidebar_tab->getName()] = button;
+ // The "home" button will open/close the whole panel, this will need to
+ // change if the home screen becomes its own tab.
+ if (name == "sidebar_home")
+ {
+ mCollapseButton = createButton("",sidebar_tab->mImage,
+ boost::bind(&LLSideTray::onToggleCollapse, this));
+ }
+ else
+ {
+ LLButton* button = createButton("",sidebar_tab->mImage,
+ boost::bind(&LLSideTray::onTabButtonClick, this, name));
+ mTabButtons[name] = button;
+ }
}
-
}
void LLSideTray::onTabButtonClick(string name)
{
-
+ LLSideTrayTab* side_bar = getTab(name);
+
+ if(side_bar == mActiveTab)
+ {
+ if(mCollapsed)
+ expandSideBar();
+ else
+ collapseSideBar();
+ return;
+ }
selectTabByName (name);
if(mCollapsed)
expandSideBar();
@@ -482,9 +526,7 @@ void LLSideTray::arrange ()
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 = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
+ LLSideTrayTab* sidebar_tab = *child_it;
ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
,sidetray_params.default_button_width
@@ -507,49 +549,78 @@ void LLSideTray::arrange ()
//arrange tabs
for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
{
- LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
-
+ LLSideTrayTab* sidebar_tab = *child_it;
sidebar_tab->setRect(ctrl_rect);
sidebar_tab->arrange(mMaxBarWidth,getRect().getHeight());
}
}
-void LLSideTray::collapseSideBar ()
+void LLSideTray::collapseSideBar()
{
mCollapsed = true;
- mCollapseButton->setLabel(COLLAPSED_NAME);
+ // 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 );
+ }
+ }
+
+ // Home tab doesn't put its button in mTabButtons
+ LLSideTrayTab* home_tab = getTab("sidebar_home");
+ if (home_tab)
+ {
+ mCollapseButton->setImageOverlay( home_tab->mImage );
+ }
mActiveTab->setVisible(FALSE);
reflectCollapseChange();
setFocus( FALSE );
}
-void LLSideTray::expandSideBar ()
+
+void LLSideTray::expandSideBar()
{
mCollapsed = false;
- mCollapseButton->setLabel(EXPANDED_NAME);
+ LLSideTrayTab* home_tab = getTab("sidebar_home");
+ if (home_tab)
+ {
+ mCollapseButton->setImageOverlay( home_tab->mImageSelected );
+ }
LLSD key;//empty
mActiveTab->onOpen(key);
mActiveTab->setVisible(TRUE);
reflectCollapseChange();
-
}
void LLSideTray::highlightFocused()
{
+ /* uncomment in case something change
if(!mActiveTab)
return;
- /* uncomment in case something change
BOOL dependent_has_focus = gFocusMgr.childHasKeyboardFocus(this);
setBackgroundOpaque( dependent_has_focus );
mActiveTab->setBackgroundOpaque( dependent_has_focus );
*/
- mActiveTab->setBackgroundOpaque( true );
+}
-
+BOOL LLSideTray::handleScrollWheel(S32 x, S32 y, S32 mask)
+{
+ BOOL ret = LLPanel::handleScrollWheel(x,y,mask);
+
+ if(!ret && childFromPoint(x,y) != 0 )
+ return TRUE;//mouse wheel over sidetray buttons, eat mouse wheel
+ return ret;
}
+
//virtual
BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask)
{
@@ -558,6 +629,7 @@ BOOL LLSideTray::handleMouseDown (S32 x, S32 y, MASK mask)
setFocus(true);
return ret;
}
+
void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent)
{
@@ -582,9 +654,7 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent)
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 = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
+ LLSideTrayTab* sidebar_tab = *child_it;
ctrl_rect.setLeftTopAndSize(0,getRect().getHeight()-offset
,sidetray_params.default_button_width
@@ -606,9 +676,7 @@ void LLSideTray::reshape (S32 width, S32 height, BOOL called_from_parent)
for ( child_it = mTabs.begin(); child_it != mTabs.end(); ++child_it)
{
- LLSideTrayTab* sidebar_tab = dynamic_cast<LLSideTrayTab*>(*child_it);
- if(sidebar_tab == NULL)
- continue;
+ LLSideTrayTab* sidebar_tab = *child_it;
sidebar_tab->reshape(mMaxBarWidth,getRect().getHeight());
ctrl_rect.setLeftTopAndSize(sidetray_params.default_button_width,getRect().getHeight(),mMaxBarWidth,getRect().getHeight());
sidebar_tab->setRect(ctrl_rect);
@@ -632,7 +700,9 @@ LLPanel* LLSideTray::showPanel (const std::string& panel_name, const LLSD& para
LLView* view = (*child_it)->findChildView(panel_name,true);
if(view)
{
- onTabButtonClick((*child_it)->getName());
+ selectTabByName ((*child_it)->getName());
+ if(mCollapsed)
+ expandSideBar();
LLSideTrayPanelContainer* container = dynamic_cast<LLSideTrayPanelContainer*>(view->getParent());
if(container)
@@ -666,7 +736,7 @@ void LLSideTray::resetPanelRect ()
static LLSideTray::Params sidetray_params(LLUICtrlFactory::getDefaultParams<LLSideTray>());
S32 panel_width = sidetray_params.default_button_width;
- panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
+ panel_width += mCollapsed ? 0 : mMaxBarWidth;
S32 panel_height = parent_rect.getHeight()-fake_top_offset;
@@ -683,7 +753,7 @@ void LLSideTray::setPanelRect ()
const LLRect& parent_rect = gViewerWindow->getRootView()->getRect();
S32 panel_width = sidetray_params.default_button_width;
- panel_width += mCollapsed ? sidetray_params.default_button_margin : mMaxBarWidth;
+ panel_width += mCollapsed ? 0 : mMaxBarWidth;
S32 panel_height = parent_rect.getHeight()-fake_top_offset - nav_rect.getHeight();
S32 panel_top = parent_rect.mTop-fake_top_offset - nav_rect.getHeight();
diff --git a/indra/newview/llsidetray.h b/indra/newview/llsidetray.h
index 13acbbb659..b49251ec79 100644
--- a/indra/newview/llsidetray.h
+++ b/indra/newview/llsidetray.h
@@ -36,59 +36,9 @@
#include "llpanel.h"
#include "string"
-class LLSideTray;
+class LLSideTrayTab;
class LLAccordionCtrl;
-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_path;
- Optional<std::string> tab_title;
- Optional<std::string> description;
- Params()
- : image_path("image"),
- 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 arrange (S32 width, S32 height);
- 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 draw();
-
- void onOpen (const LLSD& key);
-
-private:
- std::string mTabTitle;
- std::string mImagePath;
- std::string mDescription;
-
- LLView* mMainPanel;
-};
-
// 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.
@@ -112,21 +62,14 @@ public:
Optional<S32> default_button_height;
Optional<S32> default_button_margin;
- 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)
- {};
+ Params();
};
static LLSideTray* getInstance ();
static bool instanceCreated ();
protected:
LLSideTray(Params& params);
- typedef std::vector<LLView*> child_vector_t;
+ 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;
@@ -146,23 +89,6 @@ public:
*/
bool selectTabByIndex(size_t index);
- /**
- * add new panel to tab with tab_name name
- * @param tab_name - name of sidebar tab to add new panel
- * @param panel - pointer to panel
- */
- bool addPanel ( const std::string& tab_name
- ,LLPanel* panel );
- /**
- * Add new tab to side bar
- * @param tab_name - name of the new tab
- * @param image - image for new sidebar button
- * @param title - title for new tab
- */
- bool addTab ( const std::string& tab_name
- ,const std::string& image
- ,const std::string& title);
-
/**
* Activate tab with "panel_name" panel
* if no such tab - return NULL, otherwise a pointer to the panel
@@ -203,6 +129,7 @@ public:
bool addChild (LLView* view, S32 tab_group);
BOOL handleMouseDown (S32 x, S32 y, MASK mask);
+ BOOL handleScrollWheel(S32 x, S32 y, S32 mask);
void reshape (S32 width, S32 height, BOOL called_from_parent = TRUE);
S32 getTrayWidth();
diff --git a/indra/newview/llsky.cpp b/indra/newview/llsky.cpp
index a49b07c5d9..de99cb86fa 100644
--- a/indra/newview/llsky.cpp
+++ b/indra/newview/llsky.cpp
@@ -66,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
//////////////////////////////////////////////////////////////////////
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/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 7bf0d31d94..279e143851 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -659,8 +659,11 @@ void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group)
return;
}
- group->mLastUpdateDistance = group->mDistance;
- group->mLastUpdateViewAngle = group->mViewAngle;
+ if (group->changeLOD())
+ {
+ group->mLastUpdateDistance = group->mDistance;
+ group->mLastUpdateViewAngle = group->mViewAngle;
+ }
LLFastTimer ftm(FTM_REBUILD_VBO);
@@ -2701,7 +2704,7 @@ void renderTexturePriority(LLDrawable* drawable)
drawBox(center, size);
/*S32 boost = imagep->getBoostLevel();
- if (boost)
+ if (boost>LLViewerTexture::BOOST_NONE)
{
F32 t = (F32) boost / (F32) (LLViewerTexture::BOOST_MAX_LEVEL-1);
LLVector4 col = lerp(boost_cold, boost_hot, t);
diff --git a/indra/newview/llspeakbutton.cpp b/indra/newview/llspeakbutton.cpp
new file mode 100644
index 0000000000..cd765b0338
--- /dev/null
+++ b/indra/newview/llspeakbutton.cpp
@@ -0,0 +1,174 @@
+/**
+* @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 "llagent.h"
+#include "llbottomtray.h"
+#include "llfloaterreg.h"
+#include "llvoiceclient.h"
+#include "llvoicecontrolpanel.h"
+#include "lltransientfloatermgr.h"
+
+#include "llavatariconctrl.h"
+#include "llbutton.h"
+#include "llpanel.h"
+#include "lltextbox.h"
+#include "lloutputmonitorctrl.h"
+#include "llgroupmgr.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
+}
+
+LLSpeakButton::LLSpeakButton(const Params& p)
+: LLUICtrl(p)
+, mPrivateCallPanel(NULL)
+, 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->setClickedCallback(boost::bind(&LLSpeakButton::onClick_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);
+}
+
+LLSpeakButton::~LLSpeakButton()
+{
+}
+
+void LLSpeakButton::setSpeakBtnToggleState(bool state)
+{
+ mSpeakBtn->setToggleState(state);
+}
+
+void LLSpeakButton::onClick_SpeakBtn()
+{
+ bool speaking = mSpeakBtn->getToggleState();
+ gVoiceClient->setUserPTTState(speaking);
+}
+
+void LLSpeakButton::onClick_ShowBtn()
+{
+ if(!mShowBtn->getToggleState())
+ {
+ mPrivateCallPanel->onClickClose(mPrivateCallPanel);
+ delete mPrivateCallPanel;
+ mPrivateCallPanel = NULL;
+ mShowBtn->setToggleState(FALSE);
+ return;
+ }
+
+ S32 x = mSpeakBtn->getRect().mLeft;
+ S32 y = 0;
+
+ localPointToScreen(x, y, &x, &y);
+
+ mPrivateCallPanel = new LLVoiceControlPanel;
+ getRootView()->addChild(mPrivateCallPanel);
+
+ y = LLBottomTray::getInstance()->getRect().getHeight() + mPrivateCallPanel->getRect().getHeight();
+
+ LLRect rect;
+ rect.setLeftTopAndSize(x, y, mPrivateCallPanel->getRect().getWidth(), mPrivateCallPanel->getRect().getHeight());
+ mPrivateCallPanel->setRect(rect);
+
+
+ LLAvatarListItem* item = new LLAvatarListItem();
+ item->showLastInteractionTime(false);
+ item->showInfoBtn(true);
+ item->showSpeakingIndicator(true);
+ item->reshape(mPrivateCallPanel->getRect().getWidth(), item->getRect().getHeight(), FALSE);
+
+ mPrivateCallPanel->addItem(item);
+ mPrivateCallPanel->setVisible(TRUE);
+ mPrivateCallPanel->setFrontmost(TRUE);
+
+ mShowBtn->setToggleState(TRUE);
+}
+
diff --git a/indra/newview/llspeakbutton.h b/indra/newview/llspeakbutton.h
new file mode 100644
index 0000000000..f59ded2133
--- /dev/null
+++ b/indra/newview/llspeakbutton.h
@@ -0,0 +1,82 @@
+/**
+* @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 LLVoiceControlPanel;
+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();
+
+ void setSpeakBtnToggleState(bool state);
+
+protected:
+ friend class LLUICtrlFactory;
+ LLSpeakButton(const Params& p);
+
+ void onClick_SpeakBtn();
+
+ void onClick_ShowBtn();
+
+private:
+ LLButton* mSpeakBtn;
+ LLButton* mShowBtn;
+ LLVoiceControlPanel* 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..2341fcfc6d
--- /dev/null
+++ b/indra/newview/llspeakers.cpp
@@ -0,0 +1,639 @@
+/**
+ * @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 "llmutelist.h"
+#include "llsdutil.h"
+#include "lluicolortable.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+
+const F32 SPEAKER_TIMEOUT = 10.f; // seconds of not being on voice channel before removed from list of active speakers
+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;
+ }
+
+ gVoiceClient->setUserVolume(id, LLMuteList::getInstance()->getSavedResidentVolume(id));
+
+ mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+}
+
+
+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;
+}
+
+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 );
+}
+
+
+//
+// LLSpeakerMgr
+//
+
+LLSpeakerMgr::LLSpeakerMgr(LLVoiceChannel* channelp) :
+ mVoiceChannel(channelp)
+{
+}
+
+LLSpeakerMgr::~LLSpeakerMgr()
+{
+}
+
+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);
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ // 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();
+ }
+ }
+ }
+
+ 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(); )
+ {
+ 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++;
+
+ // remove speakers that have been gone too long
+ if (speakerp->mStatus == LLSpeaker::STATUS_NOT_IN_CHANNEL && speakerp->mActivityTimer.hasExpired())
+ {
+ fireEvent(new LLSpeakerListChangeEvent(this, speakerp->mID), "remove");
+
+ mSpeakers.erase(speakerp->mID);
+ sorted_speaker_it = mSpeakersSorted.erase(sorted_speaker_it);
+ }
+ else
+ {
+ ++sorted_speaker_it;
+ }
+ }
+}
+
+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));
+ }
+ }
+ }
+}
+
+LLPointer<LLSpeaker> LLSpeakerMgr::findSpeaker(const LLUUID& speaker_id)
+{
+ 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() )
+ {
+ speakerp->mIsModerator = speaker_it->second["is_moderator"];
+ speakerp->mModeratorMutedText =
+ speaker_it->second["mutes"]["text"];
+ }
+ }
+ }
+ 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())
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ 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"))
+ {
+ speakerp->mIsModerator = agent_info["is_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())
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ else if ( agent_transition == "ENTER")
+ {
+ // add or update speaker
+ speakerp = setSpeaker(agent_id);
+ }
+ else
+ {
+ llwarns << "bad membership list update "
+ << agent_transition << llendl;
+ }
+ }
+ }
+}
+
+
+//
+// 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)
+ {
+ fireEvent(new LLSpeakerListChangeEvent(this, LLUUID::null), "clear");
+ mSpeakers.clear();
+ mSpeakersSorted.clear();
+ mVoiceChannel = LLVoiceChannel::getCurrentVoiceChannel();
+ }
+ 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)
+ {
+ speakerp->mStatus = LLSpeaker::STATUS_NOT_IN_CHANNEL;
+ speakerp->mDotColor = INACTIVE_COLOR;
+ speakerp->mActivityTimer.resetWithExpiry(SPEAKER_TIMEOUT);
+ }
+ }
+ }
+}
diff --git a/indra/newview/llspeakers.h b/indra/newview/llspeakers.h
new file mode 100644
index 0000000000..e0f22bff4f
--- /dev/null
+++ b/indra/newview/llspeakers.h
@@ -0,0 +1,172 @@
+/**
+ * @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);
+
+ 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
+ LLFrameTimer mActivityTimer; // time out speakers when they are not part of current voice channel
+ 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 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 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();
+
+ typedef std::map<LLUUID, LLPointer<LLSpeaker> > speaker_map_t;
+ speaker_map_t mSpeakers;
+
+ speaker_list_t mSpeakersSorted;
+ LLFrameTimer mSpeechTimer;
+ LLVoiceChannel* mVoiceChannel;
+};
+
+class LLIMSpeakerMgr : public LLSpeakerMgr
+{
+public:
+ LLIMSpeakerMgr(LLVoiceChannel* channel);
+
+ void updateSpeakers(const LLSD& update);
+ void setSpeakers(const LLSD& speakers);
+protected:
+ virtual void updateSpeakerList();
+};
+
+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/llstartup.cpp b/indra/newview/llstartup.cpp
index 62435c6288..b23e7feda2 100644
--- a/indra/newview/llstartup.cpp
+++ b/indra/newview/llstartup.cpp
@@ -56,7 +56,6 @@
#include "llcachename.h"
#include "lldir.h"
#include "llerrorcontrol.h"
-#include "llfiltersd2xmlrpc.h"
#include "llfloaterreg.h"
#include "llfocusmgr.h"
#include "llhttpsender.h"
@@ -66,10 +65,11 @@
#include "llmemorystream.h"
#include "llmessageconfig.h"
#include "llmoveview.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"
@@ -83,6 +83,7 @@
#include "v3math.h"
#include "llagent.h"
+#include "llagentpicksinfo.h"
#include "llagentwearables.h"
#include "llagentpilot.h"
#include "llfloateravatarpicker.h"
@@ -102,7 +103,6 @@
#include "llfloaterland.h"
#include "llfloaterpreference.h"
#include "llfloatertopobjects.h"
-#include "llfloatertos.h"
#include "llfloaterworldmap.h"
#include "llgesturemgr.h"
#include "llgroupmgr.h"
@@ -115,13 +115,12 @@
#include "llfriendcard.h"
#include "llkeyboard.h"
#include "llloginhandler.h" // gLoginHandler, SLURL support
+#include "lllogininstance.h" // Host the login module.
#include "llpanellogin.h"
#include "llmutelist.h"
#include "llnotify.h"
#include "llpanelavatar.h"
#include "llavatarpropertiesprocessor.h"
-#include "llpaneldirbrowser.h"
-#include "llpaneldirland.h"
#include "llpanelevent.h"
#include "llpanelclassified.h"
#include "llpanelpick.h"
@@ -134,7 +133,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,7 +145,6 @@
#include "llurlsimstring.h"
#include "llurlhistory.h"
#include "llurlwhitelist.h"
-#include "lluserauth.h"
#include "llvieweraudio.h"
#include "llviewerassetstorage.h"
#include "llviewercamera.h"
@@ -189,6 +186,10 @@
#include "llwearable.h"
#include "llinventorybridge.h"
#include "llappearancemgr.h"
+#include "llavatariconctrl.h"
+
+#include "lllogin.h"
+#include "llevents.h"
#if LL_WINDOWS
#include "llwindebug.h"
@@ -203,12 +204,12 @@
// 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
//
@@ -218,12 +219,6 @@ extern S32 gStartImageHeight;
//
// local globals
//
-
-LLPointer<LLViewerTexture> gStartTexture;
-
-static LLHost gAgentSimHost;
-static BOOL gSkipOptionalUpdate = FALSE;
-
static bool gGotUseCircuitCodeAck = false;
static std::string sInitialOutfit;
static std::string sInitialOutfitGender; // "male" or "female"
@@ -232,6 +227,18 @@ 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";
+
+static LLEventStream sStartupStateWatcher("StartupState");
//
// local function declaration
@@ -244,8 +251,6 @@ 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);
@@ -255,6 +260,8 @@ 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)
{
@@ -314,9 +321,6 @@ void update_texture_fetch()
gTextureList.updateImages(0.10f);
}
-static std::vector<std::string> sAuthUris;
-static S32 sAuthUriNum = -1;
-
//Copies landmarks from the "Library" to "My Favorites"
void populate_favorites_bar()
{
@@ -330,7 +334,7 @@ void populate_favorites_bar()
S32 count = lib_cats->count();
for(S32 i = 0; i < count; ++i)
{
- if(lib_cats->get(i)->getPreferredType() == LLAssetType::AT_LANDMARK)
+ if(lib_cats->get(i)->getPreferredType() == LLFolderType::FT_LANDMARK)
{
lib_landmarks = lib_cats->get(i)->getUUID();
break;
@@ -347,7 +351,7 @@ void populate_favorites_bar()
gInventory.getDirectDescendentsOf(lib_landmarks, lm_cats, lm_items);
if (!lm_items) return;
- LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE);
+ const LLUUID favorites_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
if (favorites_id.isNull())
{
llerror("My Inventory is missing My Favorites", 0);
@@ -388,23 +392,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;
@@ -412,7 +404,7 @@ bool idle_startup()
static bool show_connect_box = true;
- static bool stipend_since_login = 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
@@ -433,12 +425,7 @@ bool idle_startup()
LLStringUtil::setLocale (LLTrans::getString(system));
- if (gNoRender)
- {
- // HACK, skip optional updates if you're running drones
- gSkipOptionalUpdate = TRUE;
- }
- else
+ if (!gNoRender)
{
//note: Removing this line will cause incorrect button size in the login screen. -- bao.
gTextureList.updateImages(0.01f) ;
@@ -751,27 +738,26 @@ 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();
// 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();
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;
@@ -782,9 +768,9 @@ 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");
+ gPassword = LLStartUp::loadPasswordFromDisk();
gSavedSettings.setBOOL("RememberPassword", TRUE);
#ifdef USE_VIEWER_AUTH
@@ -797,9 +783,9 @@ 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");
+ gPassword = LLStartUp::loadPasswordFromDisk();
show_connect_box = true;
}
@@ -835,7 +821,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)
{
@@ -847,7 +833,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();
@@ -909,36 +895,32 @@ bool idle_startup()
gViewerWindow->moveProgressViewToFront();
//reset the values that could have come in from a slurl
- if (!gLoginHandler.getWebLoginKey().isNull())
- {
- firstname = gLoginHandler.getFirstName();
- lastname = gLoginHandler.getLastName();
- web_login_key = gLoginHandler.getWebLoginKey();
- }
-
+ gFirstname = gLoginHandler.getFirstName();
+ gLastname = gLoginHandler.getLastName();
+
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);
+ gDirUtilp->setLindenUserDir(gFirstname, gLastname);
LLFile::mkdir(gDirUtilp->getLindenUserDir());
// Set PerAccountSettingsFile to the default value.
@@ -972,11 +954,18 @@ bool idle_startup()
gDirUtilp->setChatLogsDir(gSavedPerAccountSettings.getString("InstantMessageLogPath"));
}
- gDirUtilp->setPerAccountChatLogsDir(firstname, lastname);
+ gDirUtilp->setPerAccountChatLogsDir(gFirstname, gLastname);
LLFile::mkdir(gDirUtilp->getChatLogsDir());
LLFile::mkdir(gDirUtilp->getPerAccountChatLogsDir());
+ // chat history must be loaded AFTER chat directories are defined.
+ if (!gNoRender && gSavedPerAccountSettings.getBOOL("LogShowHistory"))
+ {
+ LLFloaterChat::loadHistory();
+ }
+
+
//good as place as any to create user windlight directories
std::string user_windlight_path_name(gDirUtilp->getExpandedFilename( LL_PATH_USER_SETTINGS , "windlight", ""));
LLFile::mkdir(user_windlight_path_name.c_str());
@@ -993,13 +982,6 @@ 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 );
@@ -1014,6 +996,9 @@ bool idle_startup()
// Load location history
LLLocationHistory::getInstance()->load();
+ // Load Avatars icons cache
+ LLAvatarIconIDCache::getInstance()->load();
+
//-------------------------------------------------
// Handle startup progress screen
//-------------------------------------------------
@@ -1028,7 +1013,7 @@ 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;
}
@@ -1061,616 +1046,139 @@ bool idle_startup()
gVFS->pokeFiles();
- // 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("adult_compliant");
- //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";
-
+ // Update progress status and the display loop.
auth_desc = LLTrans::getString("LoginInProgress");
- LLStartUp::setStartupState( STATE_LOGIN_AUTHENTICATE );
- }
-
- if (STATE_LOGIN_AUTHENTICATE == LLStartUp::getStartupState())
- {
- LL_DEBUGS("AppInit") << "STATE_LOGIN_AUTHENTICATE" << LL_ENDL;
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
- {
- start << gSavedSettings.getString("LoginLocation");
- }
-
- 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 );
- return FALSE;
- }
- if(STATE_LOGIN_NO_DATA_YET == 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 = LLTrans::getString("LoginInProgressNoFrozen");
- 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)
+ // Setting initial values...
+ LLLoginInstance* login = LLLoginInstance::getInstance();
+ login->setNotificationsInterface(LLNotifications::getInstance());
+ if(gNoRender)
{
- LL_DEBUGS("AppInit") << "waiting..." << LL_ENDL;
- return FALSE;
+ // HACK, skip optional updates if you're running drones
+ login->setSkipOptionalUpdate(true);
}
- LLStartUp::setStartupState( STATE_LOGIN_DOWNLOADING );
- progress += 0.01f;
- 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;
- }
+ 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_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 );
- LLFloaterReg::showInstance("message_tos", LLSD(message_response));
- // 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 );
- LLFloaterReg::showInstance("message_critical", LLSD(message_response));
- // 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)
+ if(reason_response == "key")
{
- 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;
+ // Couldn't login because user/password is wrong
+ // Clear the password
+ gPassword = "";
}
- 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())
+ if(reason_response == "update"
+ || reason_response == "optional")
{
- 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())
- {
- // 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);
- }
- text = LLUserAuth::getInstance()->getResponse("last_name");
- if(!text.empty()) lastname.assign(text);
- gSavedSettings.setString("FirstName", firstname);
- gSavedSettings.setString("LastName", lastname);
-
- if (gSavedSettings.getBOOL("RememberPassword"))
- {
- // 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 the base used to construct help URLs
- text = LLUserAuth::getInstance()->getResponse("help_url_format");
- 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);
- }
-
- // 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())
+ // Don't pop up a notification in the TOS case because
+ // LLFloaterTOS::onCancel() already scolded the user.
+ if (reason_response != "tos")
{
- 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())
- {
- gInventory.setRootFolderID( LLUUID( (*it).second ) );
- }
- }
-
- 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;
+ LLSD args;
+ args["ERROR_MESSAGE"] = emsg.str();
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
+ LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
}
//setup map of datetime strings to codes and slt & local time offset from utc
- LLStringOps::setupDatetimeInfo (gPacificDaylightTime);
- }
- 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)
- {
- sInitialOutfitGender = (*it).second;
- }
- }
-
- 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);
- }
+ // *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()
- && gInventory.getRootFolderID().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();
+ LL_INFOS("LLStartup") << "Notification: " << args << LL_ENDL;
LLNotifications::instance().add("ErrorMessage", args, LLSD(), login_alert_done);
- reset_login();
- gSavedSettings.setBOOL("AutoLogin", FALSE);
+ 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)
+ else
{
- 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;
+ // Still waiting for response.
+ // *TODO:Mani - Actually check for login progress.
+ // 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 = LLTrans::getString("LoginInProgressNoFrozen");
+ set_startup_status(progress, auth_desc, auth_message);
}
+
return FALSE;
}
@@ -1730,14 +1238,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.
@@ -1876,7 +1384,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();
@@ -1915,18 +1423,18 @@ 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,
+ gFirstSim,
MAX_TIMEOUT_COUNT,
FALSE,
TIMEOUT_SECONDS,
@@ -2037,105 +1545,99 @@ 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())
{
- gInventory.setLibraryRootFolderID( LLUUID( (*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())
{
- gInventory.setLibraryOwnerID( LLUUID( (*it).second ) );
+ gInventory.setLibraryOwnerID( LLUUID(id.asUUID()));
}
}
- options.clear();
- if(LLUserAuth::getInstance()->getOptions("inventory-skel-lib", options)
- && gInventory.getLibraryOwnerID().notNull())
+
+ LLSD inv_skel_lib = response["inventory-skel-lib"];
+ if(inv_skel_lib.isDefined() && gInventory.getLibraryOwnerID().notNull())
{
- if(!gInventory.loadSkeleton(options, gInventory.getLibraryOwnerID()))
+ 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();
-
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);
+ gSavedSettings.setString("TutorialURL", tutorial_url.asString());
}
- option_it = (*it).find("use_tutorial");
- if(option_it != (*it).end())
+
+ LLSD use_tutorial = (*it)["use_tutorial"];
+ if(use_tutorial.asString() == "true")
{
- if (option_it->second == "true")
- {
- show_hud = true;
- }
+ show_hud = true;
}
}
}
@@ -2147,19 +1649,22 @@ bool idle_startup()
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);
}
@@ -2168,7 +1673,7 @@ bool idle_startup()
gInventory.buildParentChildMap();
//all categories loaded. lets create "My Favorites" category
- gInventory.findCategoryUUIDForType(LLAssetType::AT_FAVORITE,true);
+ gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE,true);
// lets create "Friends" and "Friends/All" in the Inventory "Calling Cards" and fill it with buddies
LLFriendCardsManager::instance().syncFriendsFolder();
@@ -2223,7 +1728,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();
@@ -2271,34 +1776,20 @@ 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())
{
@@ -2354,8 +1845,8 @@ bool idle_startup()
if (!gAgent.isFirstLogin())
{
bool url_ok = LLURLSimString::sInstance.parse();
- if ((url_ok && agent_start_location == "url") ||
- (!url_ok && ((agent_start_location == gSavedSettings.getString("LoginLocation")))))
+ 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
@@ -2568,8 +2059,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 );
@@ -2593,7 +2086,7 @@ bool idle_startup()
// reset timers now that we are running "logged in" logic
LLFastTimer::reset();
-
+ LLAgentPicksInfo::getInstance()->requestNumberOfPicks();
return TRUE;
}
@@ -2859,230 +2352,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);
- 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
- }
-
- 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;
- }
-
- // 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);
- }
-
- 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;
- }
-
- 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
- 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
- update_exe_path =
- 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: "
- << update_exe_path << LL_ENDL;
-
- // *TODO: we could use the gdk equivilant to ensure the updater
- // gets started on the same screen.
- GError *error = NULL;
- if (!g_spawn_command_line_async(update_exe_path.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
- LLAppViewer::instance()->forceQuit();
- return false;
-}
void use_circuit_callback(void**, S32 result)
{
@@ -3254,15 +2523,6 @@ 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);
@@ -3438,11 +2698,7 @@ std::string LLStartUp::startupStateToString(EStartupState state)
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_PROCESS_RESPONSE );
RTNENUM( STATE_WORLD_INIT );
RTNENUM( STATE_SEED_GRANTED_WAIT );
@@ -3462,14 +2718,17 @@ 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;
+ LLSD stateInfo;
+ stateInfo["str"] = getStartupStateString();
+ stateInfo["enum"] = state;
+ sStartupStateWatcher.post(stateInfo);
}
@@ -3583,3 +2842,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 4532c5e586..7f869d014f 100644
--- a/indra/newview/llstartup.h
+++ b/indra/newview/llstartup.h
@@ -50,11 +50,7 @@ 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_PROCESS_RESPONSE, // Check authentication reply
STATE_WORLD_INIT, // Start building the world
STATE_MULTIMEDIA_INIT, // Init the rest of multimedia library
@@ -75,8 +71,6 @@ typedef enum {
// exported symbols
extern bool gAgentMovementCompleted;
extern LLPointer<LLViewerTexture> gStartTexture;
-extern std::string gInitialOutfit;
-extern std::string gInitialOutfitGender; // "male" or "female"
class LLStartUp
{
diff --git a/indra/newview/llstatusbar.cpp b/indra/newview/llstatusbar.cpp
index b0930cd86d..4dccdfd7e6 100644
--- a/indra/newview/llstatusbar.cpp
+++ b/indra/newview/llstatusbar.cpp
@@ -41,7 +41,6 @@
#include "llviewercontrol.h"
#include "llfloaterbuycurrency.h"
#include "llfloaterchat.h"
-#include "llfloaterdirectory.h" // to spawn search
#include "llfloaterlagmeter.h"
#include "llfloaterregioninfo.h"
#include "llfloaterscriptdebug.h"
diff --git a/indra/newview/llsyswellwindow.cpp b/indra/newview/llsyswellwindow.cpp
index 67a0528a06..723ac0fc33 100644
--- a/indra/newview/llsyswellwindow.cpp
+++ b/indra/newview/llsyswellwindow.cpp
@@ -45,29 +45,6 @@
#include "llnotificationmanager.h"
-// IM session ID can be the same as Avatar UUID. (See LLIMMgr::computeSessionID)
-// Probably notification ID also can be the same as Avatar UUID.
-// In case when session ID & notification ID are the same it will be impossible to add both
-// appropriate Items into Flat List.
-// Functions below are intended to wrap passed LLUUID into LLSD value with different "type".
-// Use them anywhere you need to add, get, remove items via the list
-inline
-LLSD get_notification_value(const LLUUID& notification_id)
-{
- return LLSD()
- .insert("type", "notification")
- .insert("uuid", notification_id);
-}
-
-inline
-LLSD get_session_value(const LLUUID& session_id)
-{
- return LLSD()
- .insert("type", "im_chiclet")
- .insert("uuid", session_id);
-}
-
-
//---------------------------------------------------------------------------------
LLSysWellWindow::LLSysWellWindow(const LLSD& key) : LLDockableFloater(NULL, key),
mChannel(NULL),
@@ -89,6 +66,7 @@ BOOL LLSysWellWindow::postBuild()
// init connections to the list's update events
connectListUpdaterToSignal("notify");
connectListUpdaterToSignal("groupnotify");
+ connectListUpdaterToSignal("offer");
// get a corresponding channel
initChannel();
@@ -136,6 +114,12 @@ void LLSysWellWindow::connectListUpdaterToSignal(std::string notification_type)
}
//---------------------------------------------------------------------------------
+void LLSysWellWindow::onStartUpToastClick(S32 x, S32 y, MASK mask)
+{
+ onChicletClick();
+}
+
+//---------------------------------------------------------------------------------
void LLSysWellWindow::onChicletClick()
{
// 1 - remove StartUp toast and channel if present
@@ -157,7 +141,7 @@ LLSysWellWindow::~LLSysWellWindow()
//---------------------------------------------------------------------------------
void LLSysWellWindow::addItem(LLSysWellItem::Params p)
{
- LLSD value = get_notification_value(p.notification_id);
+ LLSD value = p.notification_id;
// do not add clones
if( mMessageList->getItemByValue(value))
return;
@@ -191,7 +175,7 @@ void LLSysWellWindow::clear()
//---------------------------------------------------------------------------------
void LLSysWellWindow::removeItemByID(const LLUUID& id)
{
- if(mMessageList->removeItemByValue(get_notification_value(id)))
+ if(mMessageList->removeItemByValue(id))
{
handleItemRemoved(IT_NOTIFICATION);
reshapeWindow();
@@ -269,6 +253,10 @@ void LLSysWellWindow::toggleWindow()
if(!getVisible() || isMinimized())
{
+ if(mChannel)
+ {
+ mChannel->removeAndStoreAllStorableToasts();
+ }
if(isWindowEmpty())
{
return;
@@ -357,7 +345,7 @@ void LLSysWellWindow::reshapeWindow()
LLChiclet* LLSysWellWindow::findIMChiclet(const LLUUID& sessionId)
{
LLChiclet* res = NULL;
- RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(get_session_value(sessionId));
+ RowPanel* panel = mMessageList->getTypedItemByValue<RowPanel>(sessionId);
if (panel != NULL)
{
res = panel->mChiclet;
@@ -371,7 +359,7 @@ void LLSysWellWindow::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, get_session_value(sessionId)))
+ if (mMessageList->insertItemAfter(mSeparator, item, sessionId))
{
handleItemAdded(IT_INSTANT_MESSAGE);
}
@@ -389,7 +377,7 @@ void LLSysWellWindow::addIMRow(const LLUUID& sessionId, S32 chicletCounter,
//---------------------------------------------------------------------------------
void LLSysWellWindow::delIMRow(const LLUUID& sessionId)
{
- if (mMessageList->removeItemByValue(get_session_value(sessionId)))
+ if (mMessageList->removeItemByValue(sessionId))
{
handleItemRemoved(IT_INSTANT_MESSAGE);
}
@@ -422,8 +410,7 @@ bool LLSysWellWindow::isWindowEmpty()
void LLSysWellWindow::sessionAdded(const LLUUID& session_id,
const std::string& name, const LLUUID& other_participant_id)
{
- //*TODO get rid of get_session_value, session_id's are unique, cause performance degradation with lots chiclets (IB)
- if (mMessageList->getItemByValue(get_session_value(session_id)) == NULL)
+ if (mMessageList->getItemByValue(session_id) == NULL)
{
S32 chicletCounter = LLIMModel::getInstance()->getNumUnread(session_id);
if (chicletCounter > -1)
@@ -440,7 +427,17 @@ void LLSysWellWindow::sessionRemoved(const LLUUID& sessionId)
{
delIMRow(sessionId);
reshapeWindow();
- LLBottomTray::getInstance()->getSysWell()->updateUreadIMNotifications();
+}
+
+void LLSysWellWindow::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);
+ }
}
void LLSysWellWindow::handleItemAdded(EItemType added_item_type)
@@ -536,7 +533,7 @@ LLSysWellWindow::RowPanel::~RowPanel()
//---------------------------------------------------------------------------------
void LLSysWellWindow::RowPanel::onClosePanel()
{
- gIMMgr->removeSession(mChiclet->getSessionId());
+ gIMMgr->leaveSession(mChiclet->getSessionId());
// This row panel will be removed from the list in LLSysWellWindow::sessionRemoved().
}
diff --git a/indra/newview/llsyswellwindow.h b/indra/newview/llsyswellwindow.h
index 0c3f4d0587..cbc5f7358f 100644
--- a/indra/newview/llsyswellwindow.h
+++ b/indra/newview/llsyswellwindow.h
@@ -76,6 +76,7 @@ public:
void onItemClose(LLSysWellItem* item);
void onStoreToast(LLPanel* info_panel, LLUUID id);
void onChicletClick();
+ void onStartUpToastClick(S32 x, S32 y, MASK mask);
// size constants for the window and for its elements
static const S32 MAX_WINDOW_HEIGHT = 200;
@@ -108,6 +109,7 @@ private:
// 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);
// pointer to a corresponding channel's instance
LLNotificationsUI::LLScreenChannel* mChannel;
diff --git a/indra/newview/llteleporthistorystorage.cpp b/indra/newview/llteleporthistorystorage.cpp
index a588153ca2..d3bbda1c72 100644
--- a/indra/newview/llteleporthistorystorage.cpp
+++ b/indra/newview/llteleporthistorystorage.cpp
@@ -93,14 +93,12 @@ void LLTeleportHistoryStorage::onTeleportHistoryChange()
addItem(item.mTitle, item.mGlobalPos);
save();
-
- mHistoryChangedSignal();
}
void LLTeleportHistoryStorage::purgeItems()
{
mItems.clear();
- mHistoryChangedSignal();
+ mHistoryChangedSignal(-1);
}
void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d& global_pos)
@@ -116,15 +114,16 @@ bool LLTeleportHistoryStorage::compareByTitleAndGlobalPos(const LLTeleportHistor
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);
}
@@ -141,9 +140,12 @@ void LLTeleportHistoryStorage::addItem(const std::string title, const LLVector3d
// 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)
@@ -211,6 +213,8 @@ void LLTeleportHistoryStorage::load()
file.close();
std::sort(mItems.begin(), mItems.end(), LLSortItemsByDate());
+
+ mHistoryChangedSignal(-1);
}
void LLTeleportHistoryStorage::dump() const
@@ -234,7 +238,6 @@ boost::signals2::connection LLTeleportHistoryStorage::setHistoryChangedCallback(
}
void LLTeleportHistoryStorage::goToItem(S32 idx)
-
{
// Validate specified index.
if (idx < 0 || idx >= (S32)mItems.size())
diff --git a/indra/newview/llteleporthistorystorage.h b/indra/newview/llteleporthistorystorage.h
index f67c4e2fb9..2eaa94f2ed 100644
--- a/indra/newview/llteleporthistorystorage.h
+++ b/indra/newview/llteleporthistorystorage.h
@@ -80,8 +80,9 @@ public:
typedef std::vector<LLTeleportHistoryPersistentItem> slurl_list_t;
- typedef boost::function<void()> history_callback_t;
- typedef boost::signals2::signal<void()> history_signal_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();
diff --git a/indra/newview/lltexglobalcolor.cpp b/indra/newview/lltexglobalcolor.cpp
index e81c3731f7..595b24ad47 100644
--- a/indra/newview/lltexglobalcolor.cpp
+++ b/indra/newview/lltexglobalcolor.cpp
@@ -33,6 +33,7 @@
#include "llagent.h"
#include "lltexlayer.h"
#include "llvoavatar.h"
+#include "llwearable.h"
#include "lltexglobalcolor.h"
//-----------------------------------------------------------------------------
@@ -64,7 +65,7 @@ BOOL LLTexGlobalColor::setInfo(LLTexGlobalColorInfo *info)
iter++)
{
LLTexParamGlobalColor* param_color = new LLTexParamGlobalColor(this);
- if (!param_color->setInfo(*iter))
+ if (!param_color->setInfo(*iter, TRUE))
{
mInfo = NULL;
return FALSE;
@@ -95,10 +96,16 @@ const std::string& LLTexGlobalColor::getName() const
// LLTexParamGlobalColor
//-----------------------------------------------------------------------------
LLTexParamGlobalColor::LLTexParamGlobalColor(LLTexGlobalColor* tex_global_color) :
- LLTexLayerParamColor((LLTexLayer*)NULL),
+ LLTexLayerParamColor(tex_global_color->getAvatar()),
mTexGlobalColor(tex_global_color)
{
- mAvatar = tex_global_color->getAvatar();
+}
+
+/*virtual*/ LLViewerVisualParam* LLTexParamGlobalColor::cloneParam(LLWearable* wearable) const
+{
+ LLTexParamGlobalColor *new_param = new LLTexParamGlobalColor(mTexGlobalColor);
+ *new_param = *this;
+ return new_param;
}
void LLTexParamGlobalColor::onGlobalColorChanged(bool set_by_user)
diff --git a/indra/newview/lltexglobalcolor.h b/indra/newview/lltexglobalcolor.h
index 154b814392..1e6754133f 100644
--- a/indra/newview/lltexglobalcolor.h
+++ b/indra/newview/lltexglobalcolor.h
@@ -36,6 +36,7 @@
#include "lltexlayerparams.h"
class LLVOAvatar;
+class LLWearable;
class LLTexGlobalColorInfo;
class LLTexGlobalColor
@@ -67,7 +68,7 @@ public:
~LLTexGlobalColorInfo();
BOOL parseXml(LLXmlTreeNode* node);
-
+
private:
param_color_info_list_t mParamColorInfoList;
std::string mName;
@@ -77,6 +78,7 @@ class LLTexParamGlobalColor : public LLTexLayerParamColor
{
public:
LLTexParamGlobalColor(LLTexGlobalColor *tex_color);
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const;
protected:
/*virtual*/ void onGlobalColorChanged(bool set_by_user);
private:
diff --git a/indra/newview/lltexlayer.cpp b/indra/newview/lltexlayer.cpp
index 5a5f187415..73340cbc03 100644
--- a/indra/newview/lltexlayer.cpp
+++ b/indra/newview/lltexlayer.cpp
@@ -41,6 +41,9 @@
#include "llassetuploadresponders.h"
#include "lltexlayerparams.h"
#include "llui.h"
+#include "llagentwearables.h"
+#include "llwearable.h"
+#include "llviewervisualparam.h"
//#include "../tools/imdebug/imdebug.h"
@@ -66,90 +69,45 @@ LLBakedUploadData::LLBakedUploadData(const LLVOAvatarSelf* avatar,
// static
S32 LLTexLayerSetBuffer::sGLByteCount = 0;
-S32 LLTexLayerSetBuffer::sGLBumpByteCount = 0;
LLTexLayerSetBuffer::LLTexLayerSetBuffer(LLTexLayerSet* const owner,
- S32 width, S32 height,
- BOOL has_bump) :
+ S32 width, S32 height) :
// ORDER_LAST => must render these after the hints are created.
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),
- mHasBump(has_bump),
- mBumpTex(NULL)
+ mTexLayerSet(owner)
{
LLTexLayerSetBuffer::sGLByteCount += getSize();
- createBumpTexture() ;
}
LLTexLayerSetBuffer::~LLTexLayerSetBuffer()
{
LLTexLayerSetBuffer::sGLByteCount -= getSize();
-
- if( mBumpTex.notNull())
+ destroyGLTexture();
+ for( S32 order = 0; order < ORDER_COUNT; order++ )
{
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4;
+ LLViewerDynamicTexture::sInstances[order].erase(this); // will fail in all but one case.
}
}
//virtual
void LLTexLayerSetBuffer::restoreGLTexture()
{
- createBumpTexture() ;
LLViewerDynamicTexture::restoreGLTexture() ;
}
//virtual
void LLTexLayerSetBuffer::destroyGLTexture()
{
- if( mBumpTex.notNull() )
- {
- mBumpTex = NULL ;
- LLImageGL::sGlobalTextureMemoryInBytes -= mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount -= mFullWidth * mFullHeight * 4;
- }
-
LLViewerDynamicTexture::destroyGLTexture() ;
}
-void LLTexLayerSetBuffer::createBumpTexture()
-{
- if( mHasBump )
- {
- LLGLSUIDefault gls_ui;
- mBumpTex = LLViewerTextureManager::getLocalTexture(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, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
- stop_glerror();
-
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
-
- LLImageGL::sGlobalTextureMemoryInBytes += mFullWidth * mFullHeight * 4;
- LLTexLayerSetBuffer::sGLBumpByteCount += mFullWidth * mFullHeight * 4;
- }
-}
-
// 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()
@@ -242,8 +200,6 @@ void LLTexLayerSetBuffer::postRender(BOOL success)
BOOL LLTexLayerSetBuffer::render()
{
- U8* baked_bump_data = NULL;
-
// Default color mask for tex layer render
gGL.setColorMask(true, true);
@@ -252,33 +208,6 @@ BOOL LLTexLayerSetBuffer::render()
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, mFullWidth, mFullHeight );
- 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, mFullWidth, mFullHeight);
- stop_glerror();
-
- // if we need to upload the data, read it back into a buffer
- if( upload_now )
- {
- baked_bump_data = new U8[ mFullWidth * mFullHeight * 4 ];
- glReadPixels(mOrigin.mX, mOrigin.mY, mFullWidth, mFullHeight, GL_RGBA, GL_UNSIGNED_BYTE, baked_bump_data );
- stop_glerror();
- }
- }
- }
// Composite the color data
LLGLSUIDefault gls_ui;
@@ -294,7 +223,7 @@ BOOL LLTexLayerSetBuffer::render()
}
else
{
- readBackAndUpload(baked_bump_data);
+ readBackAndUpload();
}
}
@@ -306,7 +235,6 @@ BOOL LLTexLayerSetBuffer::render()
mGLTexturep->setGLTextureCreated(true);
mNeedsUpdate = FALSE;
- delete [] baked_bump_data;
return success;
}
@@ -330,7 +258,7 @@ BOOL LLTexLayerSetBuffer::updateImmediate()
return result;
}
-void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data)
+void LLTexLayerSetBuffer::readBackAndUpload()
{
// pointers for storing data to upload
U8* baked_color_data = new U8[ mFullWidth * mFullHeight * 4 ];
@@ -358,44 +286,25 @@ void LLTexLayerSetBuffer::readBackAndUpload(const U8* baked_bump_data)
// writes into baked_color_data
const char* comment_text = NULL;
- S32 baked_image_components = mBumpTex.notNull() ? 5 : 4; // red green blue [bump] clothing
+ 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
- S32 i = 0;
- for( S32 u = 0; u < mFullWidth; u++ )
- {
- for( S32 v = 0; v < mFullHeight; 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 < mFullWidth; u++ )
+ {
+ for( S32 v = 0; v < mFullHeight; v++ )
{
- S32 i = 0;
- for( S32 u = 0; u < mFullWidth; u++ )
- {
- for( S32 v = 0; v < mFullHeight; 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++;
- }
- }
+ 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++;
}
+ }
LLPointer<LLImageJ2C> compressedImage = new LLImageJ2C;
compressedImage->setRate(0.f);
@@ -548,23 +457,6 @@ void LLTexLayerSetBuffer::onTextureUploadComplete(const LLUUID& uuid,
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();
-
- mGLTexturep->updateBindStats(mFullWidth * mFullHeight * 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.
@@ -659,7 +551,6 @@ LLTexLayerSet::LLTexLayerSet(LLVOAvatarSelf* const avatar) :
mComposite( NULL ),
mAvatar( avatar ),
mUpdatesEnabled( FALSE ),
- mHasBump( FALSE ),
mInfo( NULL )
{
}
@@ -686,16 +577,25 @@ BOOL LLTexLayerSet::setInfo(const LLTexLayerSetInfo *info)
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;
}
if (!layer->isVisibilityMask())
{
- mLayerList.push_back( layer );
- }
+ mLayerList.push_back( layer );
+ }
else
{
mMaskLayerList.push_back(layer);
@@ -736,12 +636,12 @@ 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++)
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
layer->deleteCaches();
}
}
@@ -770,62 +670,37 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height )
LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE);
gGL.setColorMask(true, true);
- BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex);
+ // clear buffer area to ensure we don't pick up UI elements
+ {
+ 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();
+ }
// composite color layers
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
if (layer->getRenderPass() == LLTexLayer::RP_COLOR)
{
gGL.flush();
- success &= layer->render(x, y, width, height, render_morph);
+ success &= layer->render(x, y, width, height);
gGL.flush();
- if (layer->isMorphValid())
- {
- mAvatar->setMorphMasksValid(TRUE, mBakedTexIndex);
- }
}
}
- renderAlphaMaskTextures(width, height, false);
+ renderAlphaMaskTextures(x, y, width, height, false);
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() == LLTexLayer::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();
-
- return success;
-}
BOOL LLTexLayerSet::isBodyRegion(const std::string& region) const
{
@@ -869,11 +744,9 @@ void LLTexLayerSet::createComposite()
// Composite other avatars at reduced resolution
if( !mAvatar->isSelf() )
{
- // TODO: replace with sanity check to ensure not called for non-self avatars
-// 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 );
}
}
@@ -905,51 +778,27 @@ LLTexLayerSetBuffer* LLTexLayerSet::getComposite()
void LLTexLayerSet::gatherMorphMaskAlpha(U8 *data, S32 width, S32 height)
{
- S32 size = width * height;
-
memset(data, 255, width * height);
- BOOL render_morph = mAvatar->morphMaskNeedsUpdate(mBakedTexIndex);
-
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 );
- // TODO: eliminate need for layer morph mask valid flag
- layer->invalidateMorphMasks();
- mAvatar->invalidateMorphMasks(mBakedTexIndex);
- layer->renderMorphMasks(mComposite->getOriginX(), mComposite->getOriginY(), width, height, net_color, render_morph);
- alphaData = layer->getAlphaData();
- }
- if (alphaData)
- {
- for( S32 i = 0; i < size; i++ )
- {
- U8 curAlpha = data[i];
- U16 resultAlpha = curAlpha;
- resultAlpha *= (alphaData[i] + 1);
- resultAlpha = resultAlpha >> 8;
- data[i] = (U8)resultAlpha;
- }
- }
+ LLTexLayerInterface* layer = *iter;
+ layer->gatherAlphaMasks(data, mComposite->getOriginX(),mComposite->getOriginY(), width, height);
}
// Set alpha back to that of our alpha masks.
- renderAlphaMaskTextures(width, height, true);
+ renderAlphaMaskTextures(mComposite->getOriginX(), mComposite->getOriginY(), width, height, true);
}
-void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceClear)
+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() && mMaskLayerList.empty())
+ if (!info->mStaticAlphaFileName.empty())
{
LLGLSNoAlphaTest gls_no_alpha_test;
gGL.flush();
@@ -986,9 +835,9 @@ void LLTexLayerSet::renderAlphaMaskTextures(S32 width, S32 height, bool forceCle
gGL.getTexUnit(0)->setTextureBlendType( LLTexUnit::TB_REPLACE );
for (layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++)
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
gGL.flush();
- layer->blendAlphaTexture(width, height);
+ layer->blendAlphaTexture(x,y,width, height);
gGL.flush();
}
@@ -1006,21 +855,29 @@ void LLTexLayerSet::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_
mAvatar->applyMorphMask(tex_data, width, height, num_components, mBakedTexIndex);
}
-//-----------------------------------------------------------------------------
-// finds a specific layer based on a passed in name
-//-----------------------------------------------------------------------------
-LLTexLayer* LLTexLayerSet::findLayerByName(std::string name)
+BOOL LLTexLayerSet::isMorphValid()
{
for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
{
- LLTexLayer* layer = *iter;
+ LLTexLayerInterface* layer = *iter;
+ if (layer && !layer->isMorphValid())
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
- if (layer->getName().compare(name) == 0)
+void LLTexLayerSet::invalidateMorphMasks()
+{
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+ if (layer)
{
- return layer;
+ layer->invalidateMorphMasks();
}
}
- return NULL;
}
@@ -1190,7 +1047,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
{
LLTexLayerParamColorInfo * color_info = *color_info_iter;
LLTexLayerParamColor* param_color = new LLTexLayerParamColor(avatar);
- if (!param_color->setInfo(color_info))
+ 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;
@@ -1204,7 +1061,7 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
{
LLTexLayerParamAlphaInfo * alpha_info = *alpha_info_iter;
LLTexLayerParamAlpha* param_alpha = new LLTexLayerParamAlpha(avatar);
- if (!param_alpha->setInfo(alpha_info))
+ 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;
@@ -1215,6 +1072,138 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
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);
+ 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:
@@ -1228,23 +1217,22 @@ BOOL LLTexLayerInfo::createVisualParams(LLVOAvatar *avatar)
// * 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),
- mHasMorph(FALSE)
+LLTexLayer::LLTexLayer(LLTexLayerSet* const layer_set) :
+ LLTexLayerInterface( layer_set ),
+ mLocalTextureObject(NULL)
{
}
-LLTexLayer::LLTexLayer(const LLTexLayer &layer) :
- mTexLayerSet( layer.mTexLayerSet )
+LLTexLayer::LLTexLayer(const LLTexLayer &layer, LLWearable *wearable) :
+ LLTexLayerInterface( layer, wearable ),
+ mLocalTextureObject(NULL)
{
- setInfo(layer.getInfo());
-
-
- mHasMorph = layer.mHasMorph;
+}
+LLTexLayer::LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable) :
+ LLTexLayerInterface( layer_template, wearable ),
+ mLocalTextureObject(lto)
+{
}
LLTexLayer::~LLTexLayer()
@@ -1267,44 +1255,9 @@ LLTexLayer::~LLTexLayer()
// setInfo
//-----------------------------------------------------------------------------
-BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info)
+BOOL LLTexLayer::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
{
- llassert(mInfo == NULL);
- mInfo = info;
- //mID = info->mID; // No ID
-
- if (info->mRenderPass == LLTexLayer::RP_BUMP)
- mTexLayerSet->setBump(TRUE);
-
- 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 = new LLTexLayerParamColor(this);
- if (!param_color->setInfo(*iter))
- {
- 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 = new LLTexLayerParamAlpha( this );
- if (!param_alpha->setInfo(*iter))
- {
- mInfo = NULL;
- return FALSE;
- }
- mParamAlphaList.push_back( param_alpha );
- }
-
- return TRUE;
+ return LLTexLayerInterface::setInfo(info, wearable);
}
//static
@@ -1312,12 +1265,12 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
{
for (param_color_list_t::const_iterator iter = param_list.begin();
iter != param_list.end(); iter++)
-{
+ {
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;
@@ -1330,13 +1283,14 @@ void LLTexLayer::calculateTexLayerColor(const param_color_list_t &param_list, LL
default:
llassert(0);
break;
- }
+ }
}
net_color.clamp();
}
-void LLTexLayer::deleteCaches()
+/*virtual*/ void LLTexLayer::deleteCaches()
{
+ // 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++ )
{
@@ -1345,7 +1299,7 @@ void LLTexLayer::deleteCaches()
}
}
-BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
+BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height)
{
LLGLEnable color_mat(GL_COLOR_MATERIAL);
gPipeline.disableLights();
@@ -1373,7 +1327,7 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
// 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 (!mHasMorph)
+/* if (!mHasMorph)
{
BOOL skip_layer = TRUE;
@@ -1394,9 +1348,9 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
return success;
}
- }
+ }//*/
- renderMorphMasks(x, y, width, height, net_color, render_morph);
+ 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);
@@ -1414,7 +1368,19 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
{
{
LLViewerTexture* tex = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) )
+ 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( tex )
{
@@ -1431,10 +1397,10 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
}
}
- else
- {
- success = FALSE;
- }
+// else
+// {
+// success = FALSE;
+// }
}
}
@@ -1484,12 +1450,13 @@ BOOL LLTexLayer::render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph)
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 (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); 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));
}
@@ -1544,7 +1511,7 @@ BOOL LLTexLayer::findNetColor(LLColor4* net_color) const
return FALSE; // No need to draw a separate colored polygon
}
-BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
+BOOL LLTexLayer::blendAlphaTexture(S32 x, S32 y, S32 width, S32 height)
{
BOOL success = TRUE;
@@ -1569,17 +1536,14 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
{
if (getInfo()->mLocalTexture >=0 && getInfo()->mLocalTexture < TEX_NUM_INDICES)
{
- LLViewerTexture* tex = NULL;
- if (mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex))
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (tex)
{
- 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;
- }
+ 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;
}
}
}
@@ -1587,8 +1551,12 @@ BOOL LLTexLayer::blendAlphaTexture(S32 width, S32 height)
return success;
}
+/*virtual*/ void LLTexLayer::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
+{
+ addAlphaMask(data, originX, originY, width, height);
+}
-BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph)
+BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color)
{
BOOL success = TRUE;
@@ -1627,49 +1595,38 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
// Accumulate the alpha component of the texture
if( getInfo()->mLocalTexture != -1 )
{
- LLViewerTexture* tex = NULL;
- if( mTexLayerSet->getAvatar()->getLocalTextureGL((ETextureIndex)getInfo()->mLocalTexture, &tex ) )
- {
- if( tex && (tex->getComponents() == 4) )
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if( tex && (tex->getComponents() == 4) )
+ {
+ LLGLSNoAlphaTest gls_no_alpha_test;
- LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
-
- gGL.getTexUnit(0)->bind(tex);
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+ LLTexUnit::eTextureAddressMode old_mode = tex->getAddressMode();
+
+ gGL.getTexUnit(0)->bind(tex);
+ 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 )
- {
- if( (tex->getComponents() == 4) ||
- ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
- {
- LLGLSNoAlphaTest gls_no_alpha_test;
- gGL.getTexUnit(0)->bind(tex);
- gl_rect_2d_simple_tex( width, height );
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
- }
- }
- else
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
+ {
+ if( (tex->getComponents() == 4) ||
+ ( (tex->getComponents() == 1) && getInfo()->mStaticImageIsMask ) )
{
- success = FALSE;
+ LLGLSNoAlphaTest gls_no_alpha_test;
+ gGL.getTexUnit(0)->bind(tex);
+ 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 );
@@ -1686,10 +1643,10 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
gGL.setColorMask(true, true);
- if (render_morph && mHasMorph)
+ 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 (param_alpha_list_t::const_iterator iter = mParamAlphaList.begin(); iter != mParamAlphaList.end(); iter++)
@@ -1726,106 +1683,269 @@ BOOL LLTexLayer::renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLC
return success;
}
-// 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)
+ S32 size = width * height;
+ U8* alphaData = getAlphaData();
+ if (!alphaData && hasAlphaParams())
{
- return FALSE;
+ 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();
}
- GLenum format_options[4] = { GL_LUMINANCE, GL_LUMINANCE_ALPHA, GL_RGB, GL_RGBA };
- GLenum format = format_options[in_components-1];
- if( is_mask )
+ if (alphaData)
{
- llassert( 1 == in_components );
- format = GL_ALPHA;
+ for( S32 i = 0; i < size; i++ )
+ {
+ U8 curAlpha = data[i];
+ U16 resultAlpha = curAlpha;
+ resultAlpha *= (alphaData[i] + 1);
+ resultAlpha = resultAlpha >> 8;
+ data[i] = (U8)resultAlpha;
+ }
}
+}
- if( (in_width != SCRATCH_TEX_WIDTH) || (in_height != SCRATCH_TEX_HEIGHT) )
+// private helper function
+LLUUID LLTexLayer::getUUID()
+{
+ LLUUID uuid;
+ if( getInfo()->mLocalTexture != -1 )
{
- LLGLSNoAlphaTest gls_no_alpha_test;
+ LLViewerTexture* tex = mLocalTextureObject->getImage();
+ if (tex)
+ {
+ uuid = mLocalTextureObject->getID();
+ }
+ }
+ if( !getInfo()->mStaticImageFileName.empty() )
+ {
+ LLViewerTexture* tex = LLTexLayerStaticImageList::getInstance()->getTexture(getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask);
+ if( tex )
+ {
+ uuid = tex->getID();
+ }
+ }
+ return uuid;
+}
- 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 )
- {
- llassert( 1 == in_components );
- internal_format = GL_ALPHA8;
- }
-
- U32 name = 0;
- LLImageGL::generateTextures(1, &name );
- stop_glerror();
- gGL.getTexUnit(0)->bindManual(LLTexUnit::TT_TEXTURE, name);
- stop_glerror();
+//-----------------------------------------------------------------------------
+// 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)
+//-----------------------------------------------------------------------------
+LLTexLayerTemplate::LLTexLayerTemplate(LLTexLayerSet* layer_set) :
+ LLTexLayerInterface(layer_set)
+{
+}
- LLImageGL::setManualImage(
- GL_TEXTURE_2D, 0, internal_format,
- in_width, in_height,
- format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
+LLTexLayerTemplate::LLTexLayerTemplate(const LLTexLayerTemplate &layer) :
+ LLTexLayerInterface(layer)
+{
+}
- gGL.getTexUnit(0)->setTextureFilteringOption(LLTexUnit::TFO_BILINEAR);
-
- gGL.getTexUnit(0)->setTextureAddressMode(LLTexUnit::TAM_CLAMP);
+LLTexLayerTemplate::~LLTexLayerTemplate()
+{
+}
- gl_rect_2d_simple_tex( width, height );
+//-----------------------------------------------------------------------------
+// setInfo
+//-----------------------------------------------------------------------------
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+/*virtual*/ BOOL LLTexLayerTemplate::setInfo(const LLTexLayerInfo* info, LLWearable* wearable )
+{
+ return LLTexLayerInterface::setInfo(info, wearable);
+}
- LLImageGL::deleteTextures(1, &name );
- stop_glerror();
+U32 LLTexLayerTemplate::updateWearableCache()
+{
+ mWearableCache.clear();
+
+ S32 te = mInfo->mLocalTexture;
+ if (te == -1)
+ {
+ //this isn't a cloneable layer
+ return 0;
}
- else
+ 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++)
{
- LLGLSNoAlphaTest gls_no_alpha_test;
-
- if( !mTexLayerSet->getAvatar()->bindScratchTexture(format) )
+ LLWearable* wearable = gAgentWearables.getWearable(wearable_type, i);
+ if (!wearable)
{
- return FALSE;
+ continue;
}
+ mWearableCache.push_back(wearable);
+ added++;
+ }
+ return added;
+}
+LLTexLayer* LLTexLayerTemplate::getLayer(U32 i)
+{
+ if (mWearableCache.size() <= i || i < 0)
+ {
+ return NULL;
+ }
+ LLWearable *wearable = mWearableCache[i];
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ if (wearable)
+ {
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
+ }
+ if (lto)
+ {
+ layer = lto->getTexLayer(getName());
+ }
+ return layer;
+}
- glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, in_width, in_height, format, GL_UNSIGNED_BYTE, in_data );
- stop_glerror();
+/*virtual*/ BOOL LLTexLayerTemplate::render(S32 x, S32 y, S32 width, S32 height)
+{
+ BOOL success = TRUE;
+ updateWearableCache();
+ for (wearable_cache_t::const_iterator iter = mWearableCache.begin(); iter!= mWearableCache.end(); iter++)
+ {
+ LLWearable* wearable = NULL;
+ LLLocalTextureObject *lto = NULL;
+ LLTexLayer *layer = NULL;
+ wearable = *iter;
+ if (wearable)
+ {
+ lto = wearable->getLocalTextureObject(mInfo->mLocalTexture);
+ }
+ if (lto)
+ {
+ layer = lto->getTexLayer(getName());
+ }
+ if (layer)
+ {
+ wearable->writeToAvatar(FALSE, FALSE);
+ layer->setLTO(lto);
+ success &= layer->render(x,y,width,height);
+ }
+ }
- gl_rect_2d_simple_tex( width, height );
+ return success;
+}
- gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
+/*virtual*/ BOOL LLTexLayerTemplate::blendAlphaTexture( S32 x, S32 y, S32 width, S32 height) // Multiplies a single alpha texture against the frame buffer
+{
+ BOOL success = TRUE;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ success &= layer->blendAlphaTexture(x,y,width,height);
+ }
}
-
- return TRUE;
+ return success;
}
-void LLTexLayer::requestUpdate()
+/*virtual*/ void LLTexLayerTemplate::gatherAlphaMasks(U8 *data, S32 originX, S32 originY, S32 width, S32 height)
{
- mTexLayerSet->requestUpdate();
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->addAlphaMask(data, originX, originY, width, height);
+ }
+ }
}
-const std::string& LLTexLayer::getName() const
+/*virtual*/ void LLTexLayerTemplate::setHasMorph(BOOL newval)
{
- return mInfo->mName;
+ mHasMorph = newval;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->setHasMorph(newval);
+ }
+ }
}
-LLTexLayer::ERenderPass LLTexLayer::getRenderPass() const
+/*virtual*/ void LLTexLayerTemplate::deleteCaches()
{
- return mInfo->mRenderPass;
+ U32 num_wearables = updateWearableCache();
+ for (U32 i = 0; i < num_wearables; i++)
+ {
+ LLTexLayer *layer = getLayer(i);
+ if (layer)
+ {
+ layer->deleteCaches();
+ }
+ }
}
-const std::string& LLTexLayer::getGlobalColor() const
+
+
+
+//-----------------------------------------------------------------------------
+// finds a specific layer based on a passed in name
+//-----------------------------------------------------------------------------
+LLTexLayerInterface* LLTexLayerSet::findLayerByName(const std::string& name)
{
- return mInfo->mGlobalColor;
+ for( layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+
+ if (layer->getName() == name)
+ {
+ return layer;
+ }
+ }
+ for( layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
+ {
+ LLTexLayerInterface* layer = *iter;
+
+ if (layer->getName() == name)
+ {
+ return layer;
+ }
+ }
+ return NULL;
}
-void LLTexLayer::invalidateMorphMasks()
+void LLTexLayerSet::cloneTemplates(LLLocalTextureObject *lto, LLVOAvatarDefines::ETextureIndex tex_index, LLWearable *wearable)
{
- mMorphMasksValid = FALSE;
+ // initialize all texlayers with this texture type for this LTO
+ for( LLTexLayerSet::layer_list_t::iterator iter = mLayerList.begin(); iter != mLayerList.end(); iter++ )
+ {
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
}
-
-BOOL LLTexLayer::isVisibilityMask() const
+ for( LLTexLayerSet::layer_list_t::iterator iter = mMaskLayerList.begin(); iter != mMaskLayerList.end(); iter++ )
{
- return mInfo->mIsVisibilityMask;
+ LLTexLayerTemplate* layer = (LLTexLayerTemplate*)*iter;
+ if (layer->getInfo()->getLocalTexture() == (S32) tex_index)
+ {
+ lto->addTexLayer(layer, wearable);
+ }
+ }
}
-
//-----------------------------------------------------------------------------
// LLTexLayerStaticImageList
//-----------------------------------------------------------------------------
diff --git a/indra/newview/lltexlayer.h b/indra/newview/lltexlayer.h
index 6922eae0e1..cd8f27a96b 100644
--- a/indra/newview/lltexlayer.h
+++ b/indra/newview/lltexlayer.h
@@ -52,19 +52,20 @@ class LLTexLayerParamColor;
class LLTexLayerParamColorInfo;
class LLTexLayerParamAlpha;
class LLTexLayerParamAlphaInfo;
-
+class LLWearable;
+class LLViewerVisualParam;
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;
+
//-----------------------------------------------------------------------------
-// LLTexLayer
-// A single texture layer
-// Only exists for llvoavatarself
+// LLTexLayerInterface
+// Interface class to generalize functionality shared by LLTexLayer and LLTexLayerTemplate.
-class LLTexLayer
+class LLTexLayerInterface
{
public:
enum ERenderPass
@@ -74,36 +75,37 @@ public:
RP_SHINE
};
- LLTexLayer(LLTexLayerSet* const layer_set);
- LLTexLayer(const LLTexLayer &layer);
- ~LLTexLayer();
+ LLTexLayerInterface(LLTexLayerSet* const layer_set);
+ LLTexLayerInterface(const LLTexLayerInterface &layer, LLWearable *wearable);
+ virtual ~LLTexLayerInterface() {}
const LLTexLayerInfo* getInfo() const { return mInfo; }
- BOOL setInfo(const LLTexLayerInfo *info); // This sets mInfo and calls initialization functions
- BOOL render(S32 x, S32 y, S32 width, S32 height, BOOL render_morph);
+ 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; }
- void deleteCaches();
- U8* getAlphaData();
+ virtual void deleteCaches() = 0;
void invalidateMorphMasks();
- void setHasMorph(BOOL newval) { mHasMorph = newval; }
+ virtual void setHasMorph(BOOL newval) { mHasMorph = newval; }
+ BOOL hasMorph() { return mHasMorph; }
BOOL isMorphValid() { return mMorphMasksValid; }
const std::string& getName() const;
ERenderPass getRenderPass() const;
- const std::string& getGlobalColor() const;
+ const std::string& getGlobalColor() const;
- BOOL findNetColor(LLColor4* color) const;
- BOOL renderImageRaw(U8* in_data, S32 in_width, S32 in_height, S32 in_components, S32 width, S32 height, BOOL is_mask);
- BOOL blendAlphaTexture(S32 width, S32 height); // Multiplies a single alpha texture against the frame buffer
- BOOL renderMorphMasks(S32 x, S32 y, S32 width, S32 height, const LLColor4 &layer_color, BOOL render_morph);
+ 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;
- static void calculateTexLayerColor(const param_color_list_t &param_list, LLColor4 &net_color);
+ LLTexLayerSet* getLayerSet() {return mTexLayerSet;}
-private:
+ LLViewerVisualParam* getVisualParamPtr(S32 index);
+
+
+protected:
LLTexLayerSet* const mTexLayerSet;
// Layers can have either mParamColorList, mGlobalColor, or mFixedColor. They are looked for in that order.
@@ -111,27 +113,96 @@ private:
// mGlobalColor name stored in mInfo
// mFixedColor value stored in mInfo
param_alpha_list_t mParamAlphaList;
-
+
BOOL mMorphMasksValid;
- typedef std::map<U32, U8*> alpha_cache_t;
- alpha_cache_t mAlphaCache;
BOOL mStaticImageInvalid;
BOOL mHasMorph;
const LLTexLayerInfo *mInfo;
+
+};
+
+//-----------------------------------------------------------------------------
+// LLTexLayerTemplate
+// Template class
+// Only exists for llvoavatarself
+
+class LLTexLayerTemplate : public LLTexLayerInterface
+{
+public:
+ 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();
+private:
+ U32 updateWearableCache();
+ LLTexLayer* getLayer(U32 i);
+ typedef std::vector<LLWearable*> wearable_cache_t;
+ wearable_cache_t mWearableCache;
+
+};
+
+//-----------------------------------------------------------------------------
+// LLTexLayer
+// A single texture layer
+// Only exists for llvoavatarself
+
+class LLTexLayer : public LLTexLayerInterface
+{
+public:
+ LLTexLayer(LLTexLayerSet* const layer_set);
+ LLTexLayer(const LLTexLayer &layer, LLWearable *wearable);
+ LLTexLayer(const LLTexLayerTemplate &layer_template, LLLocalTextureObject *lto, LLWearable *wearable);
+ /*virtual*/ ~LLTexLayer();
+
+ /*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);
+
+ /*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);
+
+ 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; }
private:
std::string mName;
@@ -174,7 +245,7 @@ public:
BOOL setInfo(const LLTexLayerSetInfo *info); // This sets mInfo and calls initialization functions
BOOL render(S32 x, S32 y, S32 width, S32 height);
- BOOL renderBump(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();
@@ -191,28 +262,28 @@ public:
void deleteCaches();
void gatherMorphMaskAlpha(U8 *data, S32 width, S32 height);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components);
- void renderAlphaMaskTextures(S32 width, S32 height, bool forceClear = false);
- LLTexLayer* findLayerByName(std::string name);
+ 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()); }
- void setBump(BOOL b) { mHasBump = b; }
- BOOL hasBump() const { return mHasBump; }
LLVOAvatarDefines::EBakedTextureIndex getBakedTexIndex() { return mBakedTexIndex; }
void setBakedTexIndex( LLVOAvatarDefines::EBakedTextureIndex index) { mBakedTexIndex = index; }
public:
static BOOL sHasCaches;
+ typedef std::vector<LLTexLayerInterface *> layer_list_t;
+
private:
- typedef std::vector<LLTexLayer *> layer_list_t;
layer_list_t mLayerList;
layer_list_t mMaskLayerList;
LLPointer<LLTexLayerSetBuffer> mComposite;
LLVOAvatarSelf* const mAvatar; // Backlink only; don't make this an LLPointer.
BOOL mUpdatesEnabled;
- BOOL mHasBump;
LLVOAvatarDefines::EBakedTextureIndex mBakedTexIndex;
@@ -245,14 +316,13 @@ private:
class LLTexLayerSetBuffer : public LLViewerDynamicTexture
{
public:
- LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height, BOOL has_bump);
+ LLTexLayerSetBuffer(LLTexLayerSet* const owner, S32 width, S32 height);
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();
@@ -260,8 +330,7 @@ public:
void cancelUpload();
BOOL uploadPending() { return mUploadPending; }
BOOL render( S32 x, S32 y, S32 width, S32 height );
- void readBackAndUpload(const U8* baked_bump_data);
- void createBumpTexture();
+ void readBackAndUpload();
static void onTextureUploadComplete(const LLUUID& uuid,
void* userdata,
@@ -276,17 +345,14 @@ private:
void popProjection() const;
private:
- const BOOL mHasBump;
LLTexLayerSet* const mTexLayerSet;
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)
- LLPointer<LLViewerTexture> mBumpTex; // zero if none
static S32 sGLByteCount;
- static S32 sGLBumpByteCount;
};
//
diff --git a/indra/newview/lltexlayerparams.cpp b/indra/newview/lltexlayerparams.cpp
index 7a1ee95a65..74e0fa077e 100644
--- a/indra/newview/lltexlayerparams.cpp
+++ b/indra/newview/lltexlayerparams.cpp
@@ -33,13 +33,14 @@
#include "llagent.h"
#include "lltexlayer.h"
#include "llvoavatarself.h"
+#include "llwearable.h"
#include "lltexlayerparams.h"
#include "llui.h"
//-----------------------------------------------------------------------------
// LLTexLayerParam
//-----------------------------------------------------------------------------
-LLTexLayerParam::LLTexLayerParam(LLTexLayer *layer) :
+LLTexLayerParam::LLTexLayerParam(LLTexLayerInterface *layer) :
mTexLayer(layer),
mAvatar(NULL)
{
@@ -47,6 +48,10 @@ LLTexLayerParam::LLTexLayerParam(LLTexLayer *layer) :
{
mAvatar = mTexLayer->getTexLayerSet()->getAvatar();
}
+ else
+ {
+ llerrs << "LLTexLayerParam constructor passed with NULL reference for layer!" << llendl;
+ }
}
LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
@@ -56,15 +61,19 @@ LLTexLayerParam::LLTexLayerParam(LLVOAvatar *avatar) :
}
-BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info)
+BOOL LLTexLayerParam::setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar )
{
LLViewerVisualParam::setInfo(info);
- mAvatar->addVisualParam( this);
+
+ if (add_to_avatar)
+ {
+ mAvatar->addVisualParam( this);
+ }
+
return TRUE;
}
-
//-----------------------------------------------------------------------------
// LLTexLayerParamAlpha
//-----------------------------------------------------------------------------
@@ -102,7 +111,7 @@ void LLTexLayerParamAlpha::getCacheByteCount(S32* gl_bytes)
}
}
-LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayer* layer) :
+LLTexLayerParamAlpha::LLTexLayerParamAlpha(LLTexLayerInterface* layer) :
LLTexLayerParam(layer),
mCachedProcessedTexture(NULL),
mNeedsCreateTexture(FALSE),
@@ -131,6 +140,13 @@ LLTexLayerParamAlpha::~LLTexLayerParamAlpha()
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
@@ -159,22 +175,28 @@ void LLTexLayerParamAlpha::setWeight(F32 weight, BOOL set_by_user)
{
mCurWeight = new_weight;
- LLVOAvatar* avatar = mTexLayer->getTexLayerSet()->getAvatar();
- if (avatar->getSex() & getSex())
+ 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())
{
set_by_user = FALSE;
}
- avatar->invalidateComposite(mTexLayer->getTexLayerSet(), set_by_user);
+ mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), set_by_user);
mTexLayer->invalidateMorphMasks();
- avatar->updateMeshTextures();
+ mAvatar->updateMeshTextures();
}
}
}
void LLTexLayerParamAlpha::setAnimationTarget(F32 target_value, BOOL set_by_user)
{
+ // do not animate dummy parameters
+ if (mIsDummy)
+ {
+ setWeight(target_value, set_by_user);
+ return;
+ }
+
mTargetWeight = target_value;
setWeight(target_value, set_by_user);
mIsAnimating = TRUE;
@@ -313,7 +335,7 @@ BOOL LLTexLayerParamAlpha::render(S32 x, S32 y, S32 width, S32 height)
// 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())
+ if (!mAvatar->isSelf())
{
mCachedProcessedTexture = NULL;
}
@@ -377,7 +399,7 @@ BOOL LLTexLayerParamAlphaInfo::parseXml(LLXmlTreeNode* node)
-LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayer* layer) :
+LLTexLayerParamColor::LLTexLayerParamColor(LLTexLayerInterface* layer) :
LLTexLayerParam(layer),
mAvgDistortionVec(1.f, 1.f, 1.f)
{
@@ -393,6 +415,13 @@ 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();
@@ -444,14 +473,16 @@ void LLTexLayerParamColor::setWeight(F32 weight, BOOL set_by_user)
return;
}
- if (mAvatar->getSex() & getSex())
+ if ((mAvatar->getSex() & getSex()) && (mAvatar->isSelf() && !mIsDummy)) // only trigger a baked texture update if we're changing a wearable's visual param.
{
onGlobalColorChanged(set_by_user);
if (mTexLayer)
{
mAvatar->invalidateComposite(mTexLayer->getTexLayerSet(), set_by_user);
+ mAvatar->updateMeshTextures();
}
}
+
// llinfos << "param " << mName << " = " << new_weight << llendl;
}
}
diff --git a/indra/newview/lltexlayerparams.h b/indra/newview/lltexlayerparams.h
index 49feb01b5e..98365864f9 100644
--- a/indra/newview/lltexlayerparams.h
+++ b/indra/newview/lltexlayerparams.h
@@ -36,15 +36,18 @@
class LLTexLayer;
class LLVOAvatar;
+class LLWearable;
class LLTexLayerParam : public LLViewerVisualParam
{
public:
- LLTexLayerParam(LLTexLayer *layer);
+ LLTexLayerParam(LLTexLayerInterface *layer);
LLTexLayerParam(LLVOAvatar *avatar);
- /* Virtual */ BOOL setInfo(LLViewerVisualParamInfo *info);
+ /*virtual*/ BOOL setInfo(LLViewerVisualParamInfo *info, BOOL add_to_avatar );
+ /*virtual*/ LLViewerVisualParam* cloneParam(LLWearable* wearable) const = 0;
+
protected:
- LLTexLayer* mTexLayer;
+ LLTexLayerInterface* mTexLayer;
LLVOAvatar* mAvatar;
};
@@ -54,10 +57,12 @@ protected:
class LLTexLayerParamAlpha : public LLTexLayerParam
{
public:
- LLTexLayerParamAlpha( LLTexLayer* layer );
+ 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 ) {}
@@ -129,10 +134,12 @@ public:
OP_COUNT = 3 // Number of operations
};
- LLTexLayerParamColor( LLTexLayer* layer );
+ 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 ) {}
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index b5aec1b80b..de00ca8420 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -47,7 +47,9 @@
#include "llfolderview.h"
#include "llfoldervieweventlistener.h"
#include "llinventory.h"
+#include "llinventoryfunctions.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llfloaterinventory.h"
#include "lllineeditor.h"
#include "llui.h"
@@ -424,7 +426,7 @@ BOOL LLFloaterTexturePicker::postBuild()
mInventoryPanel->getRootFolder()->getFilter()->markDefault();
// Commented out to stop opening all folders with textures
- // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE);
+ // mInventoryPanel->openDefaultFolderForType(LLFolderType::FT_TEXTURE);
// don't put keyboard focus on selected item, because the selection callback
// will assume that this was user input
@@ -458,7 +460,7 @@ BOOL LLFloaterTexturePicker::postBuild()
// virtual
void LLFloaterTexturePicker::draw()
{
- static LLUICachedControl<S32> floater_header_size ("UIFloaterHeaderSize", 0);
+ S32 floater_header_size = getHeaderHeight();
if (mOwner)
{
// draw cone of context pointing back to texture swatch
@@ -527,7 +529,7 @@ void LLFloaterTexturePicker::draw()
mTexturep = NULL;
if(mImageAssetID.notNull())
{
- mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
+ mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES);
mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
}
else if (!mFallbackImageName.empty())
@@ -1071,7 +1073,7 @@ BOOL LLTextureCtrl::handleMouseDown(S32 x, S32 y, MASK mask)
{
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;
@@ -1188,7 +1190,7 @@ void LLTextureCtrl::draw()
}
else if (!mImageAssetID.isNull())
{
- mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES, IMMEDIATE_NO);
+ mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, MIPMAP_YES);
mTexturep->setBoostLevel(LLViewerTexture::BOOST_PREVIEW);
}
else if (!mFallbackImageName.empty())
diff --git a/indra/newview/lltexturefetch.cpp b/indra/newview/lltexturefetch.cpp
index 63af170fa9..88fc7f98c0 100644
--- a/indra/newview/lltexturefetch.cpp
+++ b/indra/newview/lltexturefetch.cpp
@@ -1371,7 +1371,7 @@ 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);
diff --git a/indra/newview/lltextureview.cpp b/indra/newview/lltextureview.cpp
index ea675c5a6e..dafa4f25ca 100644
--- a/indra/newview/lltextureview.cpp
+++ b/indra/newview/lltextureview.cpp
@@ -168,7 +168,7 @@ void LLTextureBar::draw()
{
color = LLColor4::green4;
}
- else if (mImagep->getBoostLevel())
+ else if (mImagep->getBoostLevel() > LLViewerTexture::BOOST_NONE)
{
color = LLColor4::magenta;
}
diff --git a/indra/newview/lltoast.cpp b/indra/newview/lltoast.cpp
index 84931e4d2d..903df21e78 100644
--- a/indra/newview/lltoast.cpp
+++ b/indra/newview/lltoast.cpp
@@ -41,17 +41,32 @@
using namespace LLNotificationsUI;
//--------------------------------------------------------------------------
-LLToast::LLToast(LLToast::Params p) : LLModalDialog(LLSD(), p.is_modal),
- mPanel(p.panel),
- mTimerValue(p.timer_period),
- 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),
- mHideBtnPressed(false)
+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)
{
LLUICtrlFactory::getInstance()->buildFloater(this, "panel_toast.xml", NULL);
@@ -67,11 +82,11 @@ LLToast::LLToast(LLToast::Params p) : LLModalDialog(LLSD(), p.is_modal),
}
// init callbacks if present
- if(!p.on_delete_toast.empty())
- mOnDeleteToastSignal.connect(p.on_delete_toast);
+ if(!p.on_delete_toast().empty())
+ mOnDeleteToastSignal.connect(p.on_delete_toast());
- if(!p.on_mouse_enter.empty())
- mOnMouseEnterSignal.connect(p.on_mouse_enter);
+ if(!p.on_mouse_enter().empty())
+ mOnMouseEnterSignal.connect(p.on_mouse_enter());
}
//--------------------------------------------------------------------------
@@ -103,22 +118,22 @@ void LLToast::setAndStartTimer(F32 period)
{
if(mCanFade)
{
- mTimerValue = period;
+ mToastLifetime = period;
mTimer.start();
}
}
//--------------------------------------------------------------------------
-bool LLToast::timerHasExpired()
+bool LLToast::lifetimeHasExpired()
{
if (mTimer.getStarted())
{
F32 elapsed_time = mTimer.getElapsedTimeF32();
- if (elapsed_time > gSavedSettings.getS32("ToastOpaqueTime"))
+ if ((mToastLifetime - elapsed_time) <= mToastFadingTime)
{
setBackgroundOpaque(FALSE);
}
- if (elapsed_time > mTimerValue)
+ if (elapsed_time > mToastLifetime)
{
return true;
}
@@ -131,7 +146,8 @@ void LLToast::hide()
{
setVisible(FALSE);
mTimer.stop();
- mOnFadeSignal(this);
+ mIsHidden = true;
+ mOnFadeSignal(this);
}
//--------------------------------------------------------------------------
@@ -147,9 +163,7 @@ void LLToast::tick()
{
if(mCanFade)
{
- setVisible(FALSE);
- mTimer.stop();
- mOnFadeSignal(this);
+ hide();
}
}
@@ -183,7 +197,7 @@ void LLToast::insertPanel(LLPanel* panel)
//--------------------------------------------------------------------------
void LLToast::draw()
{
- if(timerHasExpired())
+ if(lifetimeHasExpired())
{
tick();
}
@@ -194,6 +208,16 @@ void LLToast::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);
diff --git a/indra/newview/lltoast.h b/indra/newview/lltoast.h
index 29c231a01d..b670f47045 100644
--- a/indra/newview/lltoast.h
+++ b/indra/newview/lltoast.h
@@ -57,37 +57,29 @@ public:
typedef boost::function<void (LLToast* toast)> toast_callback_t;
typedef boost::signals2::signal<void (LLToast* toast)> toast_signal_t;
- struct Params
+ struct Params : public LLInitParam::Block<Params>
{
- LLPanel* panel;
- LLUUID notif_id; //notification ID
- LLUUID session_id; //im session ID
- LLNotificationPtr notification;
- F32 timer_period;
- toast_callback_t on_delete_toast;
- toast_callback_t on_mouse_enter;
- bool can_fade;
- bool can_be_stored;
- bool enable_hide_btn;
- bool is_modal;
- bool is_tip;
- bool force_show;
- bool force_store;
-
- Params() : can_fade(true),
- can_be_stored(true),
- is_modal(false),
- is_tip(false),
- enable_hide_btn(true),
- force_show(false),
- force_store(false),
- panel(NULL),
- timer_period(gSavedSettings.getS32("NotificationToastTime"))
-
- {};
+ 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(LLToast::Params p);
+ LLToast(const LLToast::Params& p);
virtual ~LLToast();
BOOL postBuild();
@@ -134,6 +126,8 @@ public:
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; }
// Registers signals/callbacks for events
@@ -153,7 +147,7 @@ public:
private:
// check timer
- bool timerHasExpired();
+ bool lifetimeHasExpired();
// on timer finished function
void tick();
@@ -161,8 +155,10 @@ private:
LLUUID mSessionID;
LLNotificationPtr mNotification;
+ // timer counts a lifetime of a toast
LLTimer mTimer;
- F32 mTimerValue;
+ F32 mToastLifetime; // in seconds
+ F32 mToastFadingTime; // in seconds
LLPanel* mPanel;
LLButton* mHideBtn;
@@ -172,6 +168,7 @@ private:
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)
};
}
diff --git a/indra/newview/lltoastalertpanel.cpp b/indra/newview/lltoastalertpanel.cpp
index e4a3f8603b..beb31bc833 100644
--- a/indra/newview/lltoastalertpanel.cpp
+++ b/indra/newview/lltoastalertpanel.cpp
@@ -30,6 +30,9 @@
* $/LicenseInfo$
*/
+// *NOTE: this module is a copy-paste of llui/llalertdialog.h
+// Can we re-implement this as a subclass of LLAlertDialog and
+// avoid all this code duplication? It already caused EXT-2232.
#include "llviewerprecompiledheaders.h" // must be first include
@@ -56,7 +59,7 @@ const F32 DEFAULT_BUTTON_DELAY = 0.5f;
const S32 MSG_PAD = 8;
/*static*/ LLControlGroup* LLToastAlertPanel::sSettings = NULL;
-/*static*/ LLToastAlertPanel::URLLoader* LLToastAlertPanel::sURLLoader;
+/*static*/ LLAlertURLLoader* LLToastAlertPanel::sURLLoader;
//-----------------------------------------------------------------------------
// Private methods
diff --git a/indra/newview/lltoastalertpanel.h b/indra/newview/lltoastalertpanel.h
index af0c9a9ddd..840143a2a9 100644
--- a/indra/newview/lltoastalertpanel.h
+++ b/indra/newview/lltoastalertpanel.h
@@ -30,6 +30,10 @@
* $/LicenseInfo$
*/
+// *NOTE: this module is a copy-paste of llui/llalertdialog.h
+// Can we re-implement this as a subclass of LLAlertDialog and
+// avoid all this code duplication? It already caused EXT-2232.
+
#ifndef LL_TOASTALERTPANEL_H
#define LL_TOASTALERTPANEL_H
@@ -37,6 +41,7 @@
#include "llfloater.h"
#include "llui.h"
#include "llnotifications.h"
+#include "llalertdialog.h"
class LLButton;
class LLCheckBoxCtrl;
@@ -57,14 +62,7 @@ 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)
+ static void setURLLoader(LLAlertURLLoader* loader)
{
sURLLoader = loader;
}
@@ -97,7 +95,7 @@ private:
BOOL hasTitleBar() const;
private:
- static URLLoader* sURLLoader;
+ static LLAlertURLLoader* sURLLoader;
static LLControlGroup* sSettings;
struct ButtonData
diff --git a/indra/newview/lltoastgroupnotifypanel.cpp b/indra/newview/lltoastgroupnotifypanel.cpp
index e26a0776ff..f82573f46c 100644
--- a/indra/newview/lltoastgroupnotifypanel.cpp
+++ b/indra/newview/lltoastgroupnotifypanel.cpp
@@ -38,6 +38,7 @@
#include "llbutton.h"
#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
#include "llnotify.h"
#include "lltextbox.h"
@@ -219,7 +220,6 @@ bool LLToastGroupNotifyPanel::isAttachmentOpenable(LLAssetType::EType type)
switch(type)
{
case LLAssetType::AT_LANDMARK:
- case LLAssetType::AT_FAVORITE:
case LLAssetType::AT_NOTECARD:
case LLAssetType::AT_IMAGE_JPEG:
case LLAssetType::AT_IMAGE_TGA:
diff --git a/indra/newview/lltoastimpanel.cpp b/indra/newview/lltoastimpanel.cpp
index c2cd63900b..c02fd7a5ef 100644
--- a/indra/newview/lltoastimpanel.cpp
+++ b/indra/newview/lltoastimpanel.cpp
@@ -32,7 +32,6 @@
#include "llviewerprecompiledheaders.h"
#include "lltoastimpanel.h"
-#include "llimpanel.h"
const S32 LLToastIMPanel::DEFAULT_MESSAGE_MAX_LINE_COUNT = 6;
diff --git a/indra/newview/lltoastnotifypanel.cpp b/indra/newview/lltoastnotifypanel.cpp
index 86b162247a..0c23947a8c 100644
--- a/indra/newview/lltoastnotifypanel.cpp
+++ b/indra/newview/lltoastnotifypanel.cpp
@@ -36,178 +36,106 @@
#include "llviewercontrol.h"
#include "lluiconstants.h"
#include "llrect.h"
-#include "lliconctrl.h"
-#include "lltexteditor.h"
-#include "lltextbox.h"
-#include "lldbstrings.h"
-#include "llchat.h"
-#include "llfloaterchat.h"
#include "lltrans.h"
-#include "lloverlaybar.h"
-
const S32 BOTTOM_PAD = VPAD * 3;
+const S32 BUTTON_WIDTH = 90;
//static
const LLFontGL* LLToastNotifyPanel::sFont = NULL;
const LLFontGL* LLToastNotifyPanel::sFontSmall = NULL;
-LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToastPanel(notification) {
- mIsTip = notification->getType() == "notifytip";
- mNumOptions = 0;
- mNumButtons = 0;
- mIsScriptDialog = (notification->getName() == "ScriptDialog"
- || notification->getName() == "ScriptDialogGroup");
- mAddedDefaultBtn = false;
+LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) :
+LLToastPanel(notification),
+mTextBox(NULL),
+mIcon(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");
+ mIcon = getChild<LLIconCtrl>("info_icon");
- // clicking on a button does not steal current focus
- setIsChrome(TRUE);
+ // 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;
- // class init
+ // setup parameters
+ // get a notification message
+ mMessage = notification->getMessage();
+ // init font variables
if (!sFont)
{
sFont = LLFontGL::getFontSansSerif();
sFontSmall = LLFontGL::getFontSansSerifSmall();
}
-
- // setup paramaters
- mMessage = notification->getMessage();
-
+ // clicking on a button does not steal current focus
+ setIsChrome(TRUE);
// initialize
setFocusRoot(!mIsTip);
-
- // 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;
-
+ // get a form for the notification
LLNotificationFormPtr form(notification->getForm());
-
+ // get number of elements
mNumOptions = form->getNumElements();
- LLRect rect = mIsTip ? getNotifyTipRect(mMessage)
- : getNotifyRect(mNumOptions, mIsScriptDialog, mIsCaution);
- setRect(rect);
- setFollows(mIsTip ? (FOLLOWS_BOTTOM|FOLLOWS_RIGHT) : (FOLLOWS_TOP|FOLLOWS_RIGHT));
- setBackgroundVisible(FALSE);
- setBackgroundOpaque(TRUE);
-
- LLIconCtrl* icon;
- LLTextEditor* text;
-
- const S32 TOP = getRect().getHeight() - (mIsTip ? (S32)sFont->getLineHeight() : 32);
- const S32 BOTTOM = (S32)sFont->getLineHeight();
- S32 x = HPAD + HPAD;
- S32 y = TOP;
-
- LLIconCtrl::Params common_params;
- common_params.rect(LLRect(x, y, x+32, TOP-32));
- common_params.mouse_opaque(false);
- common_params.follows.flags(FOLLOWS_LEFT | FOLLOWS_TOP);
+ // customize panel's outfit
+ // preliminary adjust panel's layout
+ mIsTip ? adjustPanelForTipNotice() : adjustPanelForScriptNotice(form);
+ // choose a right icon
if (mIsTip)
{
// use the tip notification icon
- common_params.image(LLUI::getUIImage("notify_tip_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_tip_icon.tga");
+ LLRect icon_rect = mIcon->getRect();
+ icon_rect.setLeftTopAndSize(icon_rect.mLeft, getRect().getHeight() - VPAD, icon_rect.getWidth(), icon_rect.getHeight());
+ mIcon->setRect(icon_rect);
}
else if (mIsCaution)
{
// use the caution notification icon
- common_params.image(LLUI::getUIImage("notify_caution_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_caution_icon.tga");
}
else
{
// use the default notification icon
- common_params.image(LLUI::getUIImage("notify_box_icon.tga"));
- icon = LLUICtrlFactory::create<LLIconCtrl> (common_params);
+ mIcon->setValue("notify_box_icon.tga");
}
- icon->setMouseOpaque(FALSE);
- addChild(icon);
-
- x += HPAD + HPAD + 32;
-
+ // adjust text options according to the notification type
// add a caution textbox at the top of a caution notification
- LLTextBox* caution_box = NULL;
if (mIsCaution && !mIsTip)
{
- S32 caution_height = ((S32)sFont->getLineHeight() * 2) + VPAD;
- LLTextBox::Params params;
- params.name("caution_box");
- params.rect(LLRect(x, y, getRect().getWidth() - 2, caution_height));
- params.font(sFont);
- params.mouse_opaque(false);
- params.font.style("BOLD");
- params.text_color(LLUIColorTable::instance().getColor("NotifyCautionWarnColor"));
- params.bg_readonly_color(LLUIColorTable::instance().getColor("NotifyCautionBoxColor"));
- params.border_visible(false);
- params.wrap(true);
- caution_box = LLUICtrlFactory::create<LLTextBox> (params);
- caution_box->setValue(notification->getMessage());
-
- addChild(caution_box);
-
- // adjust the vertical position of the next control so that
- // it appears below the caution textbox
- y = y - caution_height;
+ mTextBox = getChild<LLTextBox>("caution_text_box");
}
else
{
-
- const S32 BTN_TOP = BOTTOM_PAD + (((mNumOptions-1+2)/3)) * (BTN_HEIGHT+VPAD);
-
- // Tokenization on \n is handled by LLTextBox
-
- const S32 MAX_LENGTH = 512 + 20 +
- DB_FIRST_NAME_BUF_SIZE +
- DB_LAST_NAME_BUF_SIZE +
- DB_INV_ITEM_NAME_BUF_SIZE; // For script dialogs: add space for title.
-
- LLTextEditor::Params params;
- params.name("box");
- params.rect(LLRect(x, y, getRect().getWidth()-2, mIsTip ? BOTTOM : BTN_TOP+16));
- params.max_text_length(MAX_LENGTH);
- params.read_only(true);
- params.default_text(mMessage);
- params.font(sFont);
- params.embedded_items(false);
- params.wrap(true);
- params.tab_stop(false);
- params.mouse_opaque(false);
- params.bg_readonly_color(LLColor4::transparent);
- params.text_readonly_color(LLUIColorTable::instance().getColor("NotifyTextColor"));
- params.enabled(false);
- params.border_visible(false);
- text = LLUICtrlFactory::create<LLTextEditor> (params);
- addChild(text);
+ mTextBox = getChild<LLTextEditor>("text_editor_box");
}
- if (mIsTip)
- {
- // TODO: Make a separate archive for these.
- LLChat chat(mMessage);
- chat.mSourceType = CHAT_SOURCE_SYSTEM;
- LLFloaterChat::addChatHistory(chat);
- }
- else
- {
- LLButton::Params p;
- p.name(std::string("next"));
- p.rect(LLRect(getRect().getWidth()-26, BOTTOM_PAD + 20, getRect().getWidth()-2, BOTTOM_PAD));
- p.image_selected.name("notify_next.png");
- p.image_unselected.name("notify_next.png");
- p.font(sFont);
- p.scale_image(true);
- p.tool_tip(LLTrans::getString("next").c_str());
+ // *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->setVisible(TRUE);
+ mTextBox->setValue(notification->getMessage());
+ // add buttons for a script notification
+ if (!mIsTip)
+ {
for (S32 i = 0; i < mNumOptions; i++)
{
-
LLSD form_element = form->getElement(i);
if (form_element["type"].asString() != "button")
{
@@ -222,137 +150,63 @@ LLToastNotifyPanel::LLToastNotifyPanel(LLNotificationPtr& notification) : LLToas
addButton("OK", LLTrans::getString("ok"), FALSE, TRUE);
mAddedDefaultBtn = true;
}
-
-
}
+
+ // adjust panel's height to the text size
+ mInfoPanel->setFollowsAll();
+ snapToMessageHeight(mTextBox, MAX_LENGTH);
}
-LLToastNotifyPanel::~LLToastNotifyPanel() {
+LLToastNotifyPanel::~LLToastNotifyPanel()
+{
std::for_each(mBtnCallbackData.begin(), mBtnCallbackData.end(), DeletePointer());
}
-LLRect LLToastNotifyPanel::getNotifyRect(S32 num_options, BOOL mIsScriptDialog, BOOL is_caution)
+void LLToastNotifyPanel::adjustPanelForScriptNotice(const LLNotificationFormPtr form)
{
- S32 notify_height = gSavedSettings.getS32("NotifyBoxHeight");
- if (is_caution)
+ F32 buttons_num = 0;
+ S32 button_rows = 0;
+
+ // calculate number of buttons
+ for (S32 i = 0; i < mNumOptions; i++)
{
- // make caution-style dialog taller to accomodate extra text,
- // as well as causing the accept/decline buttons to be drawn
- // in a different position, to help prevent "quick-click-through"
- // of many permissions prompts
- notify_height = gSavedSettings.getS32("PermissionsCautionNotifyBoxHeight");
+ if (form->getElement(i)["type"].asString() == "button")
+ {
+ buttons_num++;
+ }
}
- const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
- const S32 TOP = getRect().getHeight();
- const S32 RIGHT =getRect().getWidth();
- const S32 LEFT = RIGHT - NOTIFY_WIDTH;
-
- if (num_options < 1)
+ // calculate necessary height for the button panel
+ // if notification form contains no buttons - reserve a place for OK button
+ // script notifications have extra line for an IGNORE button
+ if(mIsScriptDialog)
{
- num_options = 1;
+ button_rows = llceil((buttons_num - 1) / 3.0f) + 1;
}
-
- // Add two "blank" option spaces.
- if (mIsScriptDialog)
+ else
{
- num_options += 2;
+ button_rows = llmax( 1, llceil(buttons_num / 3.0f));
}
- S32 additional_lines = (num_options-1) / 3;
-
- notify_height += additional_lines * (BTN_HEIGHT + VPAD);
+ S32 button_panel_height = button_rows * BTN_HEIGHT + (button_rows + 1) * VPAD + BOTTOM_PAD;
- return LLRect(LEFT, TOP, RIGHT, TOP-notify_height);
+ //adjust layout
+ LLRect button_rect = mControlPanel->getRect();
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight() + button_panel_height);
+ mControlPanel->reshape(button_rect.getWidth(), button_panel_height);
}
// static
-LLRect LLToastNotifyPanel::getNotifyTipRect(const std::string &utf8message)
+void LLToastNotifyPanel::adjustPanelForTipNotice()
{
- S32 line_count = 1;
- LLWString message = utf8str_to_wstring(utf8message);
- S32 message_len = message.length();
-
- const S32 NOTIFY_WIDTH = gSavedSettings.getS32("NotifyBoxWidth");
- // Make room for the icon area.
- const S32 text_area_width = NOTIFY_WIDTH - HPAD * 4 - 32;
-
- const llwchar* wchars = message.c_str();
- const llwchar* start = wchars;
- const llwchar* end;
- S32 total_drawn = 0;
- BOOL done = FALSE;
-
- do
- {
- line_count++;
-
- for (end=start; *end != 0 && *end != '\n'; end++)
- ;
-
- if( *end == 0 )
- {
- end = wchars + message_len;
- done = TRUE;
- }
-
- S32 remaining = end - start;
- while( remaining )
- {
- S32 drawn = sFont->maxDrawableChars( start, (F32)text_area_width, remaining, TRUE );
-
- if( 0 == drawn )
- {
- drawn = 1; // Draw at least one character, even if it doesn't all fit. (avoids an infinite loop)
- }
-
- total_drawn += drawn;
- start += drawn;
- remaining -= drawn;
-
- if( total_drawn < message_len )
- {
- if( (wchars[ total_drawn ] != '\n') )
- {
- // wrap because line was too long
- line_count++;
- }
- }
- else
- {
- done = TRUE;
- }
- }
-
- total_drawn++; // for '\n'
- end++;
- start = end;
- } while( !done );
+ LLRect info_rect = mInfoPanel->getRect();
+ LLRect this_rect = getRect();
- const S32 MIN_NOTIFY_HEIGHT = 72;
- const S32 MAX_NOTIFY_HEIGHT = 600;
- S32 notify_height = llceil((F32) (line_count+1) * sFont->getLineHeight());
- if(gOverlayBar)
- {
- notify_height += gOverlayBar->getBoundingRect().mTop;
- }
- else
- {
- // *FIX: this is derived from the padding caused by the
- // rounded rects, shouldn't be a const here.
- notify_height += 10;
- }
- notify_height += VPAD;
- notify_height = llclamp(notify_height, MIN_NOTIFY_HEIGHT, MAX_NOTIFY_HEIGHT);
-
- const S32 RIGHT = getRect().getWidth();
- const S32 LEFT = RIGHT - NOTIFY_WIDTH;
-
- return LLRect(LEFT, notify_height, RIGHT, 0);
+ mControlPanel->setVisible(FALSE);
+ reshape(getRect().getWidth(), mInfoPanel->getRect().getHeight());
}
-
// static
void LLToastNotifyPanel::onClickButton(void* data)
{
@@ -371,10 +225,6 @@ void LLToastNotifyPanel::onClickButton(void* data)
// virtual
LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::string& label, BOOL is_option, BOOL is_default)
{
- // make caution notification buttons slightly narrower
- // so that 3 of them can fit without overlapping the "next" button
- S32 btn_width = mIsCaution? 84 : 90;
-
LLRect btn_rect;
LLButton* btn;
S32 btn_height= BTN_HEIGHT;
@@ -397,9 +247,9 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri
}
}
- btn_rect.setOriginAndSize(x + (index % 3) * (btn_width+HPAD+HPAD) + ignore_pad,
+ btn_rect.setOriginAndSize(x + (index % 3) * (BUTTON_WIDTH+HPAD+HPAD) + ignore_pad,
BOTTOM_PAD + (index / 3) * (BTN_HEIGHT+VPAD),
- btn_width - 2*ignore_pad,
+ BUTTON_WIDTH - 2*ignore_pad,
btn_height);
InstanceAndS32* userdata = new InstanceAndS32;
@@ -422,7 +272,7 @@ LLButton* LLToastNotifyPanel::addButton(const std::string& name, const std::stri
btn = LLUICtrlFactory::create<LLButton>(p);
- addChild(btn, -1);
+ mControlPanel->addChild(btn, -1);
if (is_default)
{
diff --git a/indra/newview/lltoastnotifypanel.h b/indra/newview/lltoastnotifypanel.h
index df58c06f25..66534edcdf 100644
--- a/indra/newview/lltoastnotifypanel.h
+++ b/indra/newview/lltoastnotifypanel.h
@@ -38,6 +38,9 @@
#include "llnotifications.h"
#include "llbutton.h"
#include "lltoastpanel.h"
+#include "lliconctrl.h"
+#include "lltexteditor.h"
+#include "lltextbox.h"
/**
@@ -46,15 +49,15 @@
*
* Replaces class LLNotifyBox.
*/
-class LLToastNotifyPanel: public LLToastPanel {
+class LLToastNotifyPanel: public LLToastPanel
+{
public:
LLToastNotifyPanel(LLNotificationPtr&);
virtual ~LLToastNotifyPanel();
- bool isTip() {return mIsTip;}
- static LLToastNotifyPanel * buildNotifyPanel(LLNotificationPtr notification);
protected:
LLButton* addButton(std::string const &name, const std::string& label, BOOL is_option, BOOL is_default);
+
// Used for callbacks
struct InstanceAndS32
{
@@ -65,16 +68,23 @@ protected:
private:
- // Returns the rect, relative to gNotifyView, where this
- // notify box should be placed.
- LLRect getNotifyRect(S32 num_options, BOOL layout_script_dialog, BOOL is_caution);
- LLRect getNotifyTipRect(const std::string &message);
+ void adjustPanelForScriptNotice(const LLNotificationFormPtr form);
+ void adjustPanelForTipNotice();
+
+ // panel elements
+ LLTextBase* mTextBox;
+ LLIconCtrl* mIcon;
+ 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; // is this a caution notification?
+ bool mIsCaution;
+
std::string mMessage;
S32 mNumOptions;
S32 mNumButtons;
diff --git a/indra/newview/lltoastpanel.cpp b/indra/newview/lltoastpanel.cpp
index 7b477470aa..ef75e06047 100644
--- a/indra/newview/lltoastpanel.cpp
+++ b/indra/newview/lltoastpanel.cpp
@@ -34,6 +34,9 @@
#include "lltoastpanel.h"
+//static
+const S32 LLToastPanel::MIN_PANEL_HEIGHT = 40; // VPAD(4)*2 + ICON_HEIGHT(32)
+
LLToastPanel::LLToastPanel(LLNotificationPtr& notification)
{
mNotification = notification;
@@ -50,8 +53,13 @@ std::string LLToastPanel::getTitle()
}
//snap to the message height if it is visible
-void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
+void LLToastPanel::snapToMessageHeight(LLTextBase* message, S32 maxLineCount)
{
+ if(!message)
+ {
+ return;
+ }
+
//Add message height if it is visible
if (message->getVisible())
{
@@ -61,22 +69,16 @@ void LLToastPanel::snapToMessageHeight(LLTextBox* message, S32 maxLineCount)
LLRect messageRect = message->getRect();
S32 oldTextHeight = messageRect.getHeight();
- //Reshape the toast to give the message max height.
- //This needed to calculate lines count according to specified text
- heightDelta = maxTextHeight - oldTextHeight;
- reshape( getRect().getWidth(), getRect().getHeight() + heightDelta);
-
//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->getTextPixelHeight();
+ S32 requiredTextHeight = message->getContentsRect().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(), getRect().getHeight() + heightDelta);
+ reshape( getRect().getWidth(), llmax(getRect().getHeight() + heightDelta, MIN_PANEL_HEIGHT));
}
-
}
diff --git a/indra/newview/lltoastpanel.h b/indra/newview/lltoastpanel.h
index 418373e8c6..a88127b008 100644
--- a/indra/newview/lltoastpanel.h
+++ b/indra/newview/lltoastpanel.h
@@ -58,9 +58,11 @@ public:
virtual std::string getTitle();
virtual const LLUUID& getID() { return mNotification->id();}
+
+ static const S32 MIN_PANEL_HEIGHT;
protected:
LLNotificationPtr mNotification;
- void snapToMessageHeight(LLTextBox* message, S32 maxLineCount);
+ void snapToMessageHeight(LLTextBase* message, S32 maxLineCount);
};
#endif /* LL_TOASTPANEL_H */
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index bc0a654eb9..959cb3f182 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -92,7 +92,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;
}
@@ -109,7 +109,7 @@ public:
LLInventoryItem* item)
{
if(item) return true;
- if(cat && (cat->getPreferredType() == LLAssetType::AT_NONE))
+ if(cat && (cat->getPreferredType() == LLFolderType::FT_NONE))
{
return true;
}
@@ -1317,8 +1317,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;
@@ -1905,7 +1904,7 @@ BOOL LLToolDragAndDrop::isInventoryGroupGiveAcceptable(LLInventoryItem* item)
switch(item->getType())
{
case LLAssetType::AT_OBJECT:
- if(my_avatar->isWearingAttachment(item->getUUID(), TRUE))
+ if(my_avatar->isWearingAttachment(item->getUUID()))
{
acceptable = FALSE;
}
@@ -2088,7 +2087,7 @@ 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;
@@ -2170,8 +2169,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;
@@ -2249,8 +2247,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;
@@ -2388,7 +2385,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;
@@ -2443,7 +2440,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;
@@ -2502,7 +2499,7 @@ EAcceptance LLToolDragAndDrop::dad3dWearCategory(
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;
diff --git a/indra/newview/lltoolpie.cpp b/indra/newview/lltoolpie.cpp
index b015f668e4..24017202cc 100644
--- a/indra/newview/lltoolpie.cpp
+++ b/indra/newview/lltoolpie.cpp
@@ -48,6 +48,7 @@
#include "lltooltip.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
+#include "llkeyboard.h"
#include "llmediaentry.h"
#include "llmenugl.h"
#include "llmutelist.h"
@@ -518,11 +519,7 @@ BOOL LLToolPie::handleHover(S32 x, S32 y, MASK mask)
if(!object)
{
- // We need to clear media hover flag
- if (LLViewerMediaFocus::getInstance()->getMouseOverFlag())
- {
- LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
- }
+ LLViewerMediaFocus::getInstance()->clearHover();
}
}
@@ -601,6 +598,9 @@ BOOL LLToolPie::handleDoubleClick(S32 x, S32 y, MASK mask)
static bool needs_tooltip(LLSelectNode* nodep)
{
+ if (!nodep)
+ return false;
+
LLViewerObject* object = nodep->getObject();
LLViewerObject *parent = (LLViewerObject *)object->getParent();
if (object->flagHandleTouch()
@@ -735,8 +735,51 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
{
tooltip_msg.append( nodep->mName );
}
-
- bool needs_tip = needs_tooltip(nodep);
+
+ 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)
{
@@ -744,8 +787,13 @@ BOOL LLToolPie::handleToolTip(S32 local_x, S32 local_y, MASK mask)
mPick = mHoverPick;
LLToolTipMgr::instance().show(LLToolTip::Params()
.message(tooltip_msg)
- .image(LLUI::getUIImage("Info"))
- .click_callback(boost::bind(showObjectInspector, hover_object->getID()))
+ .image(LLUI::getUIImage("Info_Off"))
+ .click_callback(boost::bind(showObjectInspector, hover_object->getID(), mHoverPick.mObjectFace))
+ .time_based_media(is_time_based_media)
+ .web_based_media(is_web_based_media)
+ .media_playing(is_media_playing)
+ .click_playmedia_callback(boost::bind(playCurrentMedia, mHoverPick))
+ .click_homepage_callback(boost::bind(VisitHomePage, mHoverPick))
.visible_time_near(6.f)
.visible_time_far(3.f)
.wrap(false));
@@ -928,6 +976,20 @@ static void show_inspector(const char* inspector, const char* param, const LLUUI
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)
{
@@ -940,6 +1002,113 @@ 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();
+ }
+ }
+}
+
+
void LLToolPie::handleDeselect()
{
if( hasMouseCapture() )
@@ -1029,7 +1198,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
pick.mObjectFace < 0 ||
pick.mObjectFace >= objectp->getNumTEs())
{
- LLSelectMgr::getInstance()->deselect();
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
@@ -1037,29 +1205,31 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
- // 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.
-
- // is media playing on this face?
+ // 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 (tep
- && mep
- && gSavedSettings.getBOOL("MediaOnAPrimUI")
+ if (gSavedSettings.getBOOL("MediaOnAPrimUI")
&& media_impl.notNull())
{
- // LLObjectSelectionHandle selection = /*LLViewerMediaFocus::getInstance()->getSelection()*/ LLSelectMgr::getInstance()->getSelection();
- if (/*! selection->contains(pick.getObject(), pick.mObjectFace)*/
- ! LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
+ if (!LLViewerMediaFocus::getInstance()->isFocusedOnFace(pick.getObject(), pick.mObjectFace) )
{
- LLViewerMediaFocus::getInstance()->setFocusFace(TRUE, pick.getObject(), pick.mObjectFace, media_impl);
+ LLViewerMediaFocus::getInstance()->setFocusFace(pick.getObject(), pick.mObjectFace, media_impl, pick.mNormal);
}
else
{
- media_impl->mouseDown(pick.mUVCoords);
+ // 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.
}
@@ -1067,7 +1237,6 @@ bool LLToolPie::handleMediaClick(const LLPickInfo& pick)
return true;
}
- LLSelectMgr::getInstance()->deselect();
LLViewerMediaFocus::getInstance()->clearFocus();
return false;
@@ -1081,50 +1250,53 @@ bool LLToolPie::handleMediaHover(const LLPickInfo& pick)
LLPointer<LLViewerObject> objectp = pick.getObject();
- // Early out cases. Must clear mouse over media focus flag
+ // 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()->setMouseOverFlag(false);
+ LLViewerMediaFocus::getInstance()->clearHover();
return false;
}
-
- // 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.
-
- // is media playing on this face?
+ // 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(LLViewerMediaFocus::getInstance()->getFocus() && media_impl.notNull())
- {
- media_impl->mouseMove(pick.mUVCoords);
-
- gViewerWindow->setCursor(media_impl->getLastSetCursor());
- }
- else
+
+ if(media_impl.notNull())
{
- gViewerWindow->setCursor(UI_CURSOR_ARROW);
- }
+ // 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);
+ }
- // Set mouse over flag if unset
- if (! LLViewerMediaFocus::getInstance()->getMouseOverFlag())
- {
- LLSelectMgr::getInstance()->setHoverObject(objectp, pick.mObjectFace);
- LLViewerMediaFocus::getInstance()->setMouseOverFlag(true, media_impl);
- LLViewerMediaFocus::getInstance()->setPickInfo(pick);
+ return true;
}
-
- return true;
}
- LLViewerMediaFocus::getInstance()->setMouseOverFlag(false);
+
+ // In all other cases, clear media hover.
+ LLViewerMediaFocus::getInstance()->clearHover();
return false;
}
diff --git a/indra/newview/lltoolpie.h b/indra/newview/lltoolpie.h
index 5faedbec5a..3660c68552 100644
--- a/indra/newview/lltoolpie.h
+++ b/indra/newview/lltoolpie.h
@@ -78,6 +78,10 @@ public:
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 pickLeftMouseDownCallback();
diff --git a/indra/newview/lltracker.cpp b/indra/newview/lltracker.cpp
index 5929ecd928..1a61717658 100644
--- a/indra/newview/lltracker.cpp
+++ b/indra/newview/lltracker.cpp
@@ -416,10 +416,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;
@@ -433,7 +433,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/lltransientdockablefloater.cpp b/indra/newview/lltransientdockablefloater.cpp
new file mode 100644
index 0000000000..7e4d4988d1
--- /dev/null
+++ b/indra/newview/lltransientdockablefloater.cpp
@@ -0,0 +1,96 @@
+/**
+ * @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);
+}
+
+LLTransientDockableFloater::~LLTransientDockableFloater()
+{
+ LLTransientFloaterMgr::getInstance()->unregisterTransientFloater(this);
+}
+
+void LLTransientDockableFloater::setVisible(BOOL visible)
+{
+ LLView* dock = getDockWidget();
+ if(visible && isDocked())
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(dock);
+ }
+ }
+ else
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(dock);
+ }
+ }
+
+ LLDockableFloater::setVisible(visible);
+}
+
+void LLTransientDockableFloater::setDocked(bool docked, bool pop_on_undock)
+{
+ LLView* dock = getDockWidget();
+ if(docked)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->addControlView(dock);
+ }
+ }
+ else
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(this);
+ if (dock != NULL)
+ {
+ LLTransientFloaterMgr::getInstance()->removeControlView(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..6e8a3afd22
--- /dev/null
+++ b/indra/newview/lltransientdockablefloater.h
@@ -0,0 +1,57 @@
+/**
+ * @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"
+
+/**
+ * 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
+{
+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);
+};
+
+#endif /* LL_TRANSIENTDOCKABLEFLOATER_H */
diff --git a/indra/newview/lltransientfloatermgr.cpp b/indra/newview/lltransientfloatermgr.cpp
new file mode 100644
index 0000000000..7befb87248
--- /dev/null
+++ b/indra/newview/lltransientfloatermgr.cpp
@@ -0,0 +1,110 @@
+/**
+ * @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"
+
+
+LLTransientFloaterMgr::LLTransientFloaterMgr()
+{
+ gViewerWindow->getRootView()->addMouseDownCallback(boost::bind(
+ &LLTransientFloaterMgr::leftMouseClickCallback, this, _1, _2, _3));
+}
+
+void LLTransientFloaterMgr::registerTransientFloater(LLFloater* floater)
+{
+ mTransSet.insert(floater);
+}
+
+void LLTransientFloaterMgr::unregisterTransientFloater(LLFloater* floater)
+{
+ mTransSet.erase(floater);
+}
+
+void LLTransientFloaterMgr::addControlView(LLView* view)
+{
+ mControlsSet.insert(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
+ mControlsSet.erase(view);
+}
+
+void LLTransientFloaterMgr::hideTransientFloaters()
+{
+ for (std::set<LLFloater*>::iterator it = mTransSet.begin(); it
+ != mTransSet.end(); it++)
+ {
+ LLFloater* floater = *it;
+ if (floater->isDocked())
+ {
+ floater->setVisible(FALSE);
+ }
+ }
+}
+
+void LLTransientFloaterMgr::leftMouseClickCallback(S32 x, S32 y,
+ MASK mask)
+{
+ bool hide = true;
+ for (controls_set_t::iterator it = mControlsSet.begin(); it
+ != mControlsSet.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))
+ {
+ hide = false;
+ break;
+ }
+ }
+
+ if (hide)
+ {
+ hideTransientFloaters();
+ }
+}
+
diff --git a/indra/newview/lltransientfloatermgr.h b/indra/newview/lltransientfloatermgr.h
new file mode 100644
index 0000000000..cef6e1fe45
--- /dev/null
+++ b/indra/newview/lltransientfloatermgr.h
@@ -0,0 +1,63 @@
+/**
+ * @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"
+
+
+/**
+ * Provides functionality to hide transient floaters.
+ */
+class LLTransientFloaterMgr: public LLSingleton<LLTransientFloaterMgr>
+{
+public:
+ LLTransientFloaterMgr();
+ void registerTransientFloater(LLFloater* floater);
+ void unregisterTransientFloater(LLFloater* floater);
+ void addControlView(LLView* view);
+ void removeControlView(LLView* view);
+
+private:
+ void hideTransientFloaters();
+ void leftMouseClickCallback(S32 x, S32 y, MASK mask);
+
+private:
+ std::set<LLFloater*> mTransSet;
+ typedef std::set<LLView*> controls_set_t;
+ controls_set_t mControlsSet;
+};
+
+#endif // LL_LLTRANSIENTFLOATERMGR_H
diff --git a/indra/newview/lluilistener.cpp b/indra/newview/lluilistener.cpp
new file mode 100644
index 0000000000..9c643e78de
--- /dev/null
+++ b/indra/newview/lluilistener.cpp
@@ -0,0 +1,50 @@
+/**
+ * @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(const std::string& name):
+ LLDispatchListener(name, "op")
+{
+ add("call", &LLUIListener::call, LLSD().insert("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..ea904a99ff
--- /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 "lleventdispatcher.h"
+#include <string>
+
+class LLSD;
+
+class LLUIListener: public LLDispatchListener
+{
+public:
+ LLUIListener(const std::string& name);
+
+private:
+ void call(const LLSD& event) const;
+};
+
+#endif /* ! defined(LL_LLUILISTENER_H) */
diff --git a/indra/newview/llurldispatcher.cpp b/indra/newview/llurldispatcher.cpp
index e7a8ad6605..841902f683 100644
--- a/indra/newview/llurldispatcher.cpp
+++ b/indra/newview/llurldispatcher.cpp
@@ -36,7 +36,6 @@
// viewer includes
#include "llagent.h" // teleportViaLocation()
#include "llcommandhandler.h"
-#include "llfloaterdirectory.h"
#include "llfloaterhelpbrowser.h"
#include "llfloaterreg.h"
#include "llfloaterurldisplay.h"
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
new file mode 100644
index 0000000000..c974171c2c
--- /dev/null
+++ b/indra/newview/llviewerassettype.cpp
@@ -0,0 +1,114 @@
+/**
+ * @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_ROOT_CATEGORY, new ViewerAssetEntry(DAD_ROOT_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/llviewercamera.cpp b/indra/newview/llviewercamera.cpp
index ee6ef6ffee..f65baea6ca 100644
--- a/indra/newview/llviewercamera.cpp
+++ b/indra/newview/llviewercamera.cpp
@@ -120,9 +120,8 @@ 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;
}
diff --git a/indra/newview/llviewercontrol.cpp b/indra/newview/llviewercontrol.cpp
index fa82612114..35226a1632 100644
--- a/indra/newview/llviewercontrol.cpp
+++ b/indra/newview/llviewercontrol.cpp
@@ -511,13 +511,34 @@ bool toggle_show_snapshot_button(const LLSD& newvalue)
bool toggle_show_navigation_panel(const LLSD& newvalue)
{
- LLNavigationBar::getInstance()->showNavigationPanel(newvalue.asBoolean());
+ LLRect floater_view_rect = gFloaterView->getRect();
+ LLRect notify_view_rect = gNotifyBoxView->getRect();
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
+
+ //if newvalue contains 0 => navbar should turn invisible, so floater_view_rect should get higher,
+ //and to do this pm=1, else if navbar becomes visible pm=-1 so floater_view_rect gets lower.
+ int pm=newvalue.asBoolean()?-1:1;
+ floater_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+ notify_view_rect.mTop += pm*(navbar->getDefNavBarHeight()-navbar->getDefFavBarHeight());
+ gFloaterView->setRect(floater_view_rect);
+ floater_view_rect = gFloaterView->getRect();
+ navbar->showNavigationPanel(newvalue.asBoolean());
return true;
}
bool toggle_show_favorites_panel(const LLSD& newvalue)
{
- LLNavigationBar::getInstance()->showFavoritesPanel(newvalue.asBoolean());
+ LLRect floater_view_rect = gFloaterView->getRect();
+ LLRect notify_view_rect = gNotifyBoxView->getRect();
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
+
+ //if newvalue contains 0 => favbar should turn invisible, so floater_view_rect should get higher,
+ //and to do this pm=1, else if favbar becomes visible pm=-1 so floater_view_rect gets lower.
+ int pm=newvalue.asBoolean()?-1:1;
+ floater_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+ notify_view_rect.mTop += pm*navbar->getDefFavBarHeight();
+ gFloaterView->setRect(floater_view_rect);
+ navbar->showFavoritesPanel(newvalue.asBoolean());
return true;
}
@@ -688,7 +709,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 b1f14eca7b..9b4e80cae0 100644
--- a/indra/newview/llviewercontrol.h
+++ b/indra/newview/llviewercontrol.h
@@ -43,6 +43,9 @@
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();
diff --git a/indra/newview/llviewercontrollistener.cpp b/indra/newview/llviewercontrollistener.cpp
new file mode 100644
index 0000000000..ecba1b8eb0
--- /dev/null
+++ b/indra/newview/llviewercontrollistener.cpp
@@ -0,0 +1,102 @@
+/**
+ * @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()
+ : LLDispatchListener("LLViewerControl", "group")
+{
+ add("Global", boost::bind(&LLViewerControlListener::set, &gSavedSettings, _1));
+ add("PerAccount", boost::bind(&LLViewerControlListener::set, &gSavedPerAccountSettings, _1));
+ add("Warning", boost::bind(&LLViewerControlListener::set, &gWarningSettings, _1));
+ add("Crash", 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..cacf97e908
--- /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 "lleventdispatcher.h"
+
+class LLControlGroup;
+class LLSD;
+
+class LLViewerControlListener : public LLDispatchListener
+{
+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/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index e88217fae6..9ca2d3f61d 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -57,7 +57,7 @@
#include "llfloaterchat.h"
#include "llfloaterchatterbox.h"
#include "llfloaterdaycycle.h"
-#include "llfloaterdirectory.h"
+#include "llfloatersearch.h"
#include "llfloaterenvsettings.h"
#include "llfloaterfonttest.h"
#include "llfloatergesture.h"
@@ -80,6 +80,7 @@
#include "llfloatermap.h"
#include "llfloatermemleak.h"
#include "llfloaternamedesc.h"
+#include "llfloaternearbymedia.h"
#include "llfloaternotificationsconsole.h"
#include "llfloateropenobject.h"
#include "llfloaterpay.h"
@@ -109,6 +110,7 @@
#include "llfloaterwindlight.h"
#include "llfloaterworldmap.h"
#include "llinspectavatar.h"
+#include "llinspectgroup.h"
#include "llinspectobject.h"
#include "llmediaremotectrl.h"
#include "llmoveview.h"
@@ -146,7 +148,6 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("bumps", "floater_bumps.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterBump>);
LLFloaterReg::add("camera", "floater_camera.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCamera>);
- LLFloaterReg::add("camera_presets", "floater_camera_presets.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCameraPresets>);
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>);
@@ -172,6 +173,7 @@ void LLViewerFloaterReg::registerFloaters()
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();
LLFloaterReg::add("lagmeter", "floater_lagmeter.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterLagMeter>);
@@ -186,9 +188,10 @@ void LLViewerFloaterReg::registerFloaters()
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("syswell_window", "floater_sys_well.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLSysWellWindow>);
+
+ 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("nearby_chat", "floater_nearby_chat.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLNearbyChat>);
LLFloaterReg::add("openobject", "floater_openobject.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterOpenObject>);
@@ -230,9 +233,9 @@ void LLViewerFloaterReg::registerFloaters()
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_directory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterDirectory>);
+ LLFloaterReg::add("search", "floater_search.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSearch>);
- LLFloaterReg::add("ui_preview", "floater_ui_preview.xml", &LLFloaterReg::build<LLFloaterUIPreview>);
+ 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");
diff --git a/indra/newview/llviewerfoldertype.cpp b/indra/newview/llviewerfoldertype.cpp
new file mode 100644
index 0000000000..384538364f
--- /dev/null
+++ b/indra/newview/llviewerfoldertype.cpp
@@ -0,0 +1,263 @@
+/**
+ * @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
+ )
+ :
+ LLDictionaryEntry(empty_string), // no reverse lookup needed on non-ensembles, so just leave this blank
+ mIconName(icon_name),
+ mNewCategoryName(new_category_name)
+ {
+ 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)
+ {
+ 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;
+};
+
+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
+ // |-------------------------|---------------------------|
+ addEntry(LLFolderType::FT_TEXTURE, new ViewerFolderEntry("Textures", "inv_folder_texture.tga"));
+ addEntry(LLFolderType::FT_SOUND, new ViewerFolderEntry("Sounds", "inv_folder_sound.tga"));
+ addEntry(LLFolderType::FT_CALLINGCARD, new ViewerFolderEntry("Calling Cards", "inv_folder_callingcard.tga"));
+ addEntry(LLFolderType::FT_LANDMARK, new ViewerFolderEntry("Landmarks", "inv_folder_landmark.tga"));
+ addEntry(LLFolderType::FT_CLOTHING, new ViewerFolderEntry("Clothing", "inv_folder_clothing.tga"));
+ addEntry(LLFolderType::FT_OBJECT, new ViewerFolderEntry("Objects", "inv_folder_object.tga"));
+ addEntry(LLFolderType::FT_NOTECARD, new ViewerFolderEntry("Notecards", "inv_folder_notecard.tga"));
+ addEntry(LLFolderType::FT_CATEGORY, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga"));
+ addEntry(LLFolderType::FT_ROOT_CATEGORY, new ViewerFolderEntry("Inventory", ""));
+ addEntry(LLFolderType::FT_LSL_TEXT, new ViewerFolderEntry("Scripts", "inv_folder_script.tga"));
+ addEntry(LLFolderType::FT_BODYPART, new ViewerFolderEntry("Body Parts", "inv_folder_bodypart.tga"));
+ addEntry(LLFolderType::FT_TRASH, new ViewerFolderEntry("Trash", "inv_folder_trash.tga"));
+ addEntry(LLFolderType::FT_SNAPSHOT_CATEGORY, new ViewerFolderEntry("Photo Album", "inv_folder_snapshot.tga"));
+ addEntry(LLFolderType::FT_LOST_AND_FOUND, new ViewerFolderEntry("Lost And Found", "inv_folder_lostandfound.tga"));
+ addEntry(LLFolderType::FT_ANIMATION, new ViewerFolderEntry("Animations", "inv_folder_animation.tga"));
+ addEntry(LLFolderType::FT_GESTURE, new ViewerFolderEntry("Gestures", "inv_folder_gesture.tga"));
+ addEntry(LLFolderType::FT_FAVORITE, new ViewerFolderEntry("Favorite", "inv_folder_plain_closed.tga"));
+
+ addEntry(LLFolderType::FT_CURRENT_OUTFIT, new ViewerFolderEntry("Current Outfit", "inv_folder_current_outfit.tga"));
+ addEntry(LLFolderType::FT_OUTFIT, new ViewerFolderEntry("New Outfit", "inv_folder_outfit.tga"));
+ addEntry(LLFolderType::FT_MY_OUTFITS, new ViewerFolderEntry("My Outfits", "inv_folder_my_outfits.tga"));
+ addEntry(LLFolderType::FT_INBOX, new ViewerFolderEntry("Inbox", "inv_folder_inbox.tga"));
+
+ addEntry(LLFolderType::FT_NONE, new ViewerFolderEntry("New Folder", "inv_folder_plain_closed.tga"));
+}
+
+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();
+}
+
+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..a6aea62b2a
--- /dev/null
+++ b/indra/newview/llviewerfoldertype.h
@@ -0,0 +1,57 @@
+/**
+ * @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 asset_type); // folder icon name
+ 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/llviewerinventory.cpp b/indra/newview/llviewerinventory.cpp
index dc53358311..1d62ead843 100644
--- a/indra/newview/llviewerinventory.cpp
+++ b/indra/newview/llviewerinventory.cpp
@@ -37,23 +37,25 @@
#include "indra_constants.h"
#include "llagent.h"
-#include "llfoldertype.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 "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"
///----------------------------------------------------------------------------
/// Local function declarations, constants, enums, and typedefs
@@ -358,7 +360,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),
@@ -415,7 +417,7 @@ void LLViewerInventoryCategory::updateServer(BOOL is_new) const
{
// communicate that change with the server.
- if (LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
+ if (LLFolderType::lookupIsProtectedType(mPreferredType))
{
LLNotifications::instance().add("CannotModifyProtectedCategories");
return;
@@ -439,7 +441,7 @@ void LLViewerInventoryCategory::removeFromServer( void )
llinfos << "Removing inventory category " << mUUID << " from server."
<< llendl;
// communicate that change with the server.
- if(LLAssetType::lookupIsProtectedCategoryType(mPreferredType))
+ if(LLFolderType::lookupIsProtectedType(mPreferredType))
{
LLNotifications::instance().add("CannotRemoveProtectedCategories");
return;
@@ -542,7 +544,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))
{
@@ -580,7 +582,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());
@@ -591,8 +593,8 @@ bool LLViewerInventoryCategory::exportFileLocal(LLFILE* fp) const
void LLViewerInventoryCategory::determineFolderType()
{
- LLAssetType::EType original_type = getPreferredType();
- if (LLAssetType::lookupIsProtectedCategoryType(original_type))
+ LLFolderType::EType original_type = getPreferredType();
+ if (LLFolderType::lookupIsProtectedType(original_type))
return;
U64 folder_valid = 0;
@@ -611,32 +613,32 @@ void LLViewerInventoryCategory::determineFolderType()
const LLViewerInventoryItem *item = (*item_iter);
if (item->getIsLinkType())
return;
- if (item->getInventoryType() == LLInventoryType::IT_WEARABLE)
+ if (item->isWearableType())
{
- const EWearableType wearable_type = EWearableType(item->getFlags() & LLInventoryItem::II_FLAGS_WEARABLES_MASK);
+ const EWearableType wearable_type = item->getWearableType();
const std::string& wearable_name = LLWearableDictionary::getTypeName(wearable_type);
- U64 valid_folder_types = LLFolderType::lookupValidFolderTypes(wearable_name);
+ U64 valid_folder_types = LLViewerFolderType::lookupValidFolderTypes(wearable_name);
folder_valid |= valid_folder_types;
folder_invalid |= ~valid_folder_types;
}
}
- for (U8 i = LLAssetType::AT_FOLDER_ENSEMBLE_START; i <= LLAssetType::AT_FOLDER_ENSEMBLE_END; i++)
+ for (U8 i = LLFolderType::FT_ENSEMBLE_START; i <= LLFolderType::FT_ENSEMBLE_END; i++)
{
if ((folder_valid & (1LL << i)) &&
!(folder_invalid & (1LL << i)))
{
- changeType((LLAssetType::EType)i);
+ changeType((LLFolderType::EType)i);
return;
}
}
}
- if (LLAssetType::lookupIsEnsembleCategoryType(original_type))
+ if (LLFolderType::lookupIsEnsembleType(original_type))
{
- changeType(LLAssetType::AT_NONE);
+ changeType(LLFolderType::FT_NONE);
}
}
-void LLViewerInventoryCategory::changeType(LLAssetType::EType new_folder_type)
+void LLViewerInventoryCategory::changeType(LLFolderType::EType new_folder_type)
{
const LLUUID &folder_id = getUUID();
const LLUUID &parent_id = getParentUUID();
@@ -656,7 +658,6 @@ void LLViewerInventoryCategory::changeType(LLAssetType::EType new_folder_type)
setPreferredType(new_folder_type);
gInventory.addChangedMask(LLInventoryObserver::LABEL, folder_id);
- gInventory.updateLinkedObjects(folder_id);
}
///----------------------------------------------------------------------------
@@ -729,6 +730,14 @@ 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)
@@ -940,7 +949,7 @@ void copy_inventory_from_notecard(const LLUUID& object_id, const LLUUID& notecar
body["notecard-id"] = notecard_inv_id;
body["object-id"] = object_id;
body["item-id"] = src->getUUID();
- body["folder-id"] = gInventory.findCategoryUUIDForType(src->getType());
+ body["folder-id"] = gInventory.findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(src->getType()));
body["callback-id"] = (LLSD::Integer)callback_id;
request["message"] = "CopyInventoryFromNotecard";
@@ -956,7 +965,7 @@ void create_new_item(const std::string& name,
U32 next_owner_perm)
{
std::string desc;
- LLAssetType::generateDescriptionFor(asset_type, desc);
+ LLViewerAssetType::generateDescriptionFor(asset_type, desc);
next_owner_perm = (next_owner_perm) ? next_owner_perm : PERM_MOVE | PERM_TRANSFER;
@@ -981,121 +990,123 @@ 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)
-void menu_create_inventory_item(LLFolderView* folder, LLFolderBridge *bridge, const LLSD& userdata)
+// ! 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)
{
- std::string type = userdata.asString();
+ std::string type_name = userdata.asString();
- if (("category" == type) || ("current" == type) || ("outfit" == type) || ("my_otfts" == type) )
- {
- LLAssetType::EType a_type = LLAssetType::AT_NONE;
- if ("current" == type)
- a_type = LLAssetType::AT_CURRENT_OUTFIT;
- if ("outfit" == type)
- a_type = LLAssetType::AT_OUTFIT;
- if ("my_otfts" == type)
- a_type = LLAssetType::AT_MY_OUTFITS;
- LLUUID category;
+ if (("category" == type_name) || ("current" == type_name) || ("outfit" == type_name) || ("my_otfts" == type_name))
+ {
+ LLFolderType::EType preferred_type = LLFolderType::lookup(type_name);
+
+ LLUUID parent_id;
if (bridge)
{
- category = gInventory.createNewCategory(bridge->getUUID(), a_type, LLStringUtil::null);
+ parent_id = bridge->getUUID();
+ }
+ else if (default_parent_uuid.notNull())
+ {
+ parent_id = default_parent_uuid;
}
else
{
- category = gInventory.createNewCategory(gInventory.getRootFolderID(), a_type, LLStringUtil::null);
+ parent_id = gInventory.getRootFolderID();
}
+
+ LLUUID category = gInventory.createNewCategory(parent_id, preferred_type, LLStringUtil::null);
gInventory.notifyObservers();
folder->setSelectionByID(category, TRUE);
}
- else if ("lsl" == type)
+ else if ("lsl" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_LSL_TEXT);
+ 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)
+ else if ("notecard" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_NOTECARD);
+ 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)
+ else if ("gesture" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_GESTURE);
+ 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 if ("shirt" == type)
+ else if ("shirt" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_SHIRT);
}
- else if ("pants" == type)
+ else if ("pants" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_PANTS);
}
- else if ("shoes" == type)
+ else if ("shoes" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_SHOES);
}
- else if ("socks" == type)
+ else if ("socks" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_SOCKS);
}
- else if ("jacket" == type)
+ else if ("jacket" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_JACKET);
}
- else if ("skirt" == type)
+ else if ("skirt" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_SKIRT);
}
- else if ("gloves" == type)
+ else if ("gloves" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_GLOVES);
}
- else if ("undershirt" == type)
+ else if ("undershirt" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_UNDERSHIRT);
}
- else if ("underpants" == type)
+ else if ("underpants" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_CLOTHING);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_CLOTHING);
LLFolderBridge::createWearable(parent_id, WT_UNDERPANTS);
}
- else if ("shape" == type)
+ else if ("shape" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART);
LLFolderBridge::createWearable(parent_id, WT_SHAPE);
}
- else if ("skin" == type)
+ else if ("skin" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART);
LLFolderBridge::createWearable(parent_id, WT_SKIN);
}
- else if ("hair" == type)
+ else if ("hair" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART);
LLFolderBridge::createWearable(parent_id, WT_HAIR);
}
- else if ("eyes" == type)
+ else if ("eyes" == type_name)
{
- LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLAssetType::AT_BODYPART);
+ const LLUUID parent_id = bridge ? bridge->getUUID() : gInventory.findCategoryUUIDForType(LLFolderType::FT_BODYPART);
LLFolderBridge::createWearable(parent_id, WT_EYES);
}
@@ -1269,6 +1280,22 @@ U32 LLViewerInventoryItem::getFlags() const
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();
diff --git a/indra/newview/llviewerinventory.h b/indra/newview/llviewerinventory.h
index 5692875ec6..529425aa25 100644
--- a/indra/newview/llviewerinventory.h
+++ b/indra/newview/llviewerinventory.h
@@ -74,6 +74,8 @@ public:
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.
@@ -183,7 +185,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);
@@ -219,7 +221,7 @@ public:
bool exportFileLocal(LLFILE* fp) const;
bool importFileLocal(LLFILE* fp);
void determineFolderType();
- void changeType(LLAssetType::EType new_folder_type);
+ void changeType(LLFolderType::EType new_folder_type);
protected:
LLUUID mOwnerID;
S32 mVersion;
@@ -339,6 +341,7 @@ void copy_inventory_from_notecard(const LLUUID& object_id,
void menu_create_inventory_item(LLFolderView* folder,
LLFolderBridge* bridge,
- const LLSD& userdata);
+ const LLSD& userdata,
+ const LLUUID& default_parent_uuid = LLUUID::null);
#endif // LL_LLVIEWERINVENTORY_H
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 c003579684..221b5460f1 100644
--- a/indra/newview/llviewerjointattachment.h
+++ b/indra/newview/llviewerjointattachment.h
@@ -82,9 +82,9 @@ public:
S32 getGroup() const { return mGroup; }
S32 getPieSlice() const { return mPieSlice; }
- LLViewerObject *getObject() const { return mAttachedObject; }
- S32 getNumObjects() const { return (mAttachedObject ? 1 : 0); }
- const LLUUID& getItemID() const { return mItemID; }
+ 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 cd60a8d560..5b8902dec4 100644
--- a/indra/newview/llviewerjointmesh.cpp
+++ b/indra/newview/llviewerjointmesh.cpp
@@ -582,7 +582,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy)
}
else
{
- gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT_AVATAR));
+ gGL.getTexUnit(0)->bind(LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT));
}
if (gRenderForSelect)
diff --git a/indra/newview/llviewerjoystick.cpp b/indra/newview/llviewerjoystick.cpp
index b919e3d1c1..b593fbfb00 100644
--- a/indra/newview/llviewerjoystick.cpp
+++ b/indra/newview/llviewerjoystick.cpp
@@ -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 b565ed5696..a3904bd2c3 100644
--- a/indra/newview/llviewerjoystick.h
+++ b/indra/newview/llviewerjoystick.h
@@ -82,8 +82,9 @@ protected:
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 2dc317e067..8fd646ee93 100644
--- a/indra/newview/llviewerkeyboard.cpp
+++ b/indra/newview/llviewerkeyboard.cpp
@@ -99,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())
{
diff --git a/indra/newview/llviewermedia.cpp b/indra/newview/llviewermedia.cpp
index 2b972614f1..40bf9fb1fe 100644
--- a/indra/newview/llviewermedia.cpp
+++ b/indra/newview/llviewermedia.cpp
@@ -48,6 +48,8 @@
#include "llevent.h" // LLSimpleListener
#include "llnotifications.h"
#include "lluuid.h"
+#include "llkeyboard.h"
+#include "llmutelist.h"
#include <boost/bind.hpp> // for SkinFolder listener
#include <boost/signals2.hpp>
@@ -154,10 +156,10 @@ public:
{
if(!mInitialized && ! mime_type.empty())
{
- if (mMediaImpl->initializeMedia(mime_type))
+ if(mMediaImpl->initializeMedia(mime_type))
{
mInitialized = true;
- mMediaImpl->play();
+ mMediaImpl->loadURI();
}
}
}
@@ -166,10 +168,10 @@ public:
viewer_media_t mMediaImpl;
bool mInitialized;
};
-typedef std::vector<LLViewerMediaImpl*> impl_list;
-static impl_list sViewerMediaImplList;
+static LLViewerMedia::impl_list sViewerMediaImplList;
static LLTimer sMediaCreateTimer;
static const F32 LLVIEWERMEDIA_CREATE_DELAY = 1.0f;
+static F32 sGlobalVolume = 1.0f;
//////////////////////////////////////////////////////////////////////////////////////////
static void add_media_impl(LLViewerMediaImpl* media)
@@ -180,8 +182,8 @@ static void add_media_impl(LLViewerMediaImpl* media)
//////////////////////////////////////////////////////////////////////////////////////////
static void remove_media_impl(LLViewerMediaImpl* media)
{
- impl_list::iterator iter = sViewerMediaImplList.begin();
- impl_list::iterator end = sViewerMediaImplList.end();
+ LLViewerMedia::impl_list::iterator iter = sViewerMediaImplList.begin();
+ LLViewerMedia::impl_list::iterator end = sViewerMediaImplList.end();
for(; iter != end; iter++)
{
@@ -193,6 +195,15 @@ static void remove_media_impl(LLViewerMediaImpl* media)
}
}
+class LLViewerMediaMuteListObserver : public LLMuteListObserver
+{
+ /* virtual */ void onChange() { LLViewerMedia::muteListChanged();}
+};
+
+static LLViewerMediaMuteListObserver sViewerMediaMuteListObserver;
+static bool sViewerMediaMuteListObserverInitialized = false;
+static bool sInWorldMediaDisabled = false;
+
//////////////////////////////////////////////////////////////////////////////////////////
// LLViewerMedia
@@ -250,16 +261,12 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->mMediaSource->setSize(media_entry->getWidthPixels(), media_entry->getHeightPixels());
}
- if((was_loaded || media_entry->getAutoPlay()) && !update_from_self)
+ if((was_loaded || (media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))) && !update_from_self)
{
if(!media_entry->getCurrentURL().empty())
{
needs_navigate = (media_entry->getCurrentURL() != previous_url);
}
- else if(!media_entry->getHomeURL().empty())
- {
- needs_navigate = (media_entry->getHomeURL() != previous_url);
- }
}
}
else
@@ -273,7 +280,7 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
media_impl->setHomeURL(media_entry->getHomeURL());
- if(media_entry->getAutoPlay())
+ if(media_entry->getAutoPlay() && gSavedSettings.getBOOL("AutoPlayMedia"))
{
needs_navigate = true;
}
@@ -282,8 +289,6 @@ viewer_media_t LLViewerMedia::updateMediaImpl(LLMediaEntry* media_entry, const s
if(media_impl && needs_navigate)
{
std::string url = media_entry->getCurrentURL();
- if(url.empty())
- url = media_entry->getHomeURL();
media_impl->navigateTo(url, "", true, true);
}
@@ -387,20 +392,75 @@ bool LLViewerMedia::textureHasMedia(const LLUUID& texture_id)
// static
void LLViewerMedia::setVolume(F32 volume)
{
+ if(volume != sGlobalVolume)
+ {
+ sGlobalVolume = volume;
+ impl_list::iterator iter = sViewerMediaImplList.begin();
+ impl_list::iterator end = sViewerMediaImplList.end();
+
+ for(; iter != end; iter++)
+ {
+ LLViewerMediaImpl* pimpl = *iter;
+ pimpl->updateVolume();
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+F32 LLViewerMedia::getVolume()
+{
+ 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++)
{
LLViewerMediaImpl* pimpl = *iter;
- pimpl->setVolume(volume);
+ pimpl->mNeedsMuteCheck = true;
}
}
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+void LLViewerMedia::setInWorldMediaDisabled(bool disabled)
+{
+ sInWorldMediaDisabled = disabled;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+// static
+bool LLViewerMedia::getInWorldMediaDisabled()
+{
+ return sInWorldMediaDisabled;
+}
+
+LLViewerMedia::impl_list &LLViewerMedia::getPriorityList()
+{
+ return sViewerMediaImplList;
+}
+
// This is the predicate function used to sort sViewerMediaImplList by priority.
-static inline bool compare_impl_interest(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
+bool LLViewerMedia::priorityComparitor(const LLViewerMediaImpl* i1, const LLViewerMediaImpl* i2)
{
- if(i1->hasFocus())
+ if(i1->isForcedUnloaded())
+ {
+ // Muted or failed items always go to the end of the list, period.
+ return false;
+ }
+ else if(i2->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;
@@ -442,7 +502,7 @@ void LLViewerMedia::updateMedia()
}
// Sort the static instance list using our interest criteria
- std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), compare_impl_interest);
+ std::stable_sort(sViewerMediaImplList.begin(), sViewerMediaImplList.end(), priorityComparitor);
// Go through the list again and adjust according to priority.
iter = sViewerMediaImplList.begin();
@@ -452,6 +512,7 @@ void LLViewerMedia::updateMedia()
int impl_count_total = 0;
int impl_count_interest_low = 0;
int impl_count_interest_normal = 0;
+ int i = 0;
#if 0
LL_DEBUGS("PluginPriority") << "Sorted impls:" << llendl;
@@ -474,8 +535,9 @@ void LLViewerMedia::updateMedia()
LLPluginClassMedia::EPriority new_priority = LLPluginClassMedia::PRIORITY_NORMAL;
- if(impl_count_total > (int)max_instances)
+ 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;
}
@@ -535,7 +597,23 @@ void LLViewerMedia::updateMedia()
}
}
+ if(new_priority != LLPluginClassMedia::PRIORITY_UNLOADED)
+ {
+ impl_count_total++;
+ }
+
pimpl->setPriority(new_priority);
+
+ if(pimpl->getUsedInUI())
+ {
+ // Any impls used in the UI should not be in the proximity list.
+ pimpl->mProximity = -1;
+ }
+ else
+ {
+ // Other impls just get the same ordering as the priority list (for now).
+ pimpl->mProximity = i;
+ }
#if 0
LL_DEBUGS("PluginPriority") << " " << pimpl
@@ -548,7 +626,8 @@ void LLViewerMedia::updateMedia()
#endif
total_cpu += pimpl->getCPUUsage();
- impl_count_total++;
+
+ i++;
}
LL_DEBUGS("PluginPriority") << "Total reported CPU usage is " << total_cpu << llendl;
@@ -579,6 +658,8 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mMediaAutoScale(media_auto_scale),
mMediaLoop(media_loop),
mNeedsNewTexture(true),
+ mTextureUsedWidth(0),
+ mTextureUsedHeight(0),
mSuspendUpdates(false),
mVisible(true),
mLastSetCursor( UI_CURSOR_ARROW ),
@@ -587,10 +668,25 @@ LLViewerMediaImpl::LLViewerMediaImpl( const LLUUID& texture_id,
mUsedInUI(false),
mHasFocus(false),
mPriority(LLPluginClassMedia::PRIORITY_UNLOADED),
- mDoNavigateOnLoad(false),
- mDoNavigateOnLoadServerRequest(false),
+ mNavigateRediscoverType(false),
+ mNavigateServerRequest(false),
+ mMediaSourceFailed(false),
+ mRequestedVolume(1.0f),
+ mIsMuted(false),
+ mNeedsMuteCheck(false),
+ mPreviousMediaState(MEDIA_NONE),
+ mPreviousMediaTime(0.0f),
+ mIsDisabled(false),
+ mProximity(-1),
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);
@@ -638,16 +734,20 @@ void LLViewerMediaImpl::emitEvent(LLPluginClassMedia* plugin, LLViewerMediaObser
//////////////////////////////////////////////////////////////////////////////////////////
bool LLViewerMediaImpl::initializeMedia(const std::string& mime_type)
{
- if((mMediaSource == NULL) || (mMimeType != mime_type))
+ bool mimeTypeChanged = (mMimeType != mime_type);
+ bool pluginChanged = (LLMIMETypes::implType(mMimeType) != LLMIMETypes::implType(mime_type));
+
+ if(!mMediaSource || pluginChanged)
{
- if(! initializePlugin(mime_type))
- {
- // This may be the case where the plugin's priority is PRIORITY_UNLOADED
- return false;
- }
+ // 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;
}
- // play();
return (mMediaSource != NULL);
}
@@ -660,16 +760,13 @@ void LLViewerMediaImpl::createMediaSource()
return;
}
- if(mDoNavigateOnLoad)
+ if(! mMediaURL.empty())
{
- if(! mMediaURL.empty())
- {
- navigateTo(mMediaURL, mMimeType, false, mDoNavigateOnLoadServerRequest);
- }
- else if(! mMimeType.empty())
- {
- initializeMedia(mMimeType);
- }
+ navigateInternal();
+ }
+ else if(! mMimeType.empty())
+ {
+ initializeMedia(mMimeType);
}
}
@@ -703,7 +800,7 @@ void LLViewerMediaImpl::setMediaType(const std::string& media_type)
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;
@@ -774,6 +871,9 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
return false;
}
+ // If we got here, we want to ignore previous init failures.
+ mMediaSourceFailed = false;
+
LLPluginClassMedia* media_source = newSourceFromMediaType(mMimeType, this, mMediaWidth, mMediaHeight);
if (media_source)
@@ -782,14 +882,61 @@ bool LLViewerMediaImpl::initializePlugin(const std::string& media_type)
media_source->setLoop(mMediaLoop);
media_source->setAutoScale(mMediaAutoScale);
media_source->setBrowserUserAgent(LLViewerMedia::getCurrentUserAgent());
+ media_source->focus(mHasFocus);
mMediaSource = media_source;
+
+ updateVolume();
+
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)
+ {
+ mMediaSource->loadURI( mMediaURL );
+
+ if(mPreviousMediaState == MEDIA_PLAYING)
+ {
+ // This media was playing before this instance was unloaded.
+
+ 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)
{
mMediaWidth = width;
@@ -803,24 +950,21 @@ void LLViewerMediaImpl::setSize(int width, int height)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::play()
{
- // first stop any previously playing media
- // stop();
-
- // mMediaSource->addObserver( this );
+ // If the media source isn't there, try to initialize it and load an URL.
if(mMediaSource == NULL)
{
- if(!initializePlugin(mMimeType))
+ 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();
}
- mMediaSource->loadURI( mMediaURL );
- if(/*mMediaSource->pluginSupportsMediaTime()*/ true)
- {
- start();
- }
+ // always start the media
+ start();
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -828,7 +972,15 @@ void LLViewerMediaImpl::stop()
{
if(mMediaSource)
{
- mMediaSource->stop();
+ if(mMediaSource->pluginSupportsMediaBrowser())
+ {
+ mMediaSource->browse_stop();
+ }
+ else
+ {
+ mMediaSource->stop();
+ }
+
// destroyMediaSource();
}
}
@@ -863,13 +1015,26 @@ void LLViewerMediaImpl::seek(F32 time)
//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::setVolume(F32 volume)
{
+ mRequestedVolume = volume;
+ updateVolume();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::updateVolume()
+{
if(mMediaSource)
{
- mMediaSource->setVolume(volume);
+ mMediaSource->setVolume(mRequestedVolume * LLViewerMedia::getVolume());
}
}
//////////////////////////////////////////////////////////////////////////////////////////
+F32 LLViewerMediaImpl::getVolume()
+{
+ return mRequestedVolume;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
void LLViewerMediaImpl::focus(bool focus)
{
mHasFocus = focus;
@@ -895,8 +1060,18 @@ bool LLViewerMediaImpl::hasFocus() const
return mHasFocus;
}
+std::string LLViewerMediaImpl::getCurrentMediaURL()
+{
+ if(!mCurrentMediaURL.empty())
+ {
+ return mCurrentMediaURL;
+ }
+
+ return mMediaURL;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
+void LLViewerMediaImpl::mouseDown(S32 x, S32 y, MASK mask, S32 button)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -904,12 +1079,12 @@ void LLViewerMediaImpl::mouseDown(S32 x, S32 y)
// llinfos << "mouse down (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOWN, button, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
+void LLViewerMediaImpl::mouseUp(S32 x, S32 y, MASK mask, S32 button)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -917,12 +1092,12 @@ void LLViewerMediaImpl::mouseUp(S32 x, S32 y)
// llinfos << "mouse up (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, button, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
+void LLViewerMediaImpl::mouseMove(S32 x, S32 y, MASK mask)
{
scaleMouse(&x, &y);
mLastMouseX = x;
@@ -930,50 +1105,65 @@ void LLViewerMediaImpl::mouseMove(S32 x, S32 y)
// llinfos << "mouse move (" << x << ", " << y << ")" << llendl;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, x, y, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseDown(const LLVector2& texture_coords, MASK mask, S32 button)
{
if(mMediaSource)
{
mouseDown(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask, button);
}
}
-void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseUp(const LLVector2& texture_coords, MASK mask, S32 button)
{
if(mMediaSource)
{
mouseUp(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask, button);
}
}
-void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords)
+void LLViewerMediaImpl::mouseMove(const LLVector2& texture_coords, MASK mask)
{
if(mMediaSource)
{
mouseMove(
llround(texture_coords.mV[VX] * mMediaSource->getTextureWidth()),
- llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()));
+ llround((1.0f - texture_coords.mV[VY]) * mMediaSource->getTextureHeight()),
+ mask);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::mouseDoubleClick(S32 x, S32 y, MASK mask, S32 button)
+{
+ scaleMouse(&x, &y);
+ mLastMouseX = x;
+ mLastMouseY = y;
+ if (mMediaSource)
+ {
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, button, x, y, mask);
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::mouseLeftDoubleClick(S32 x, S32 y)
+void LLViewerMediaImpl::scrollWheel(S32 x, S32 y, MASK mask)
{
scaleMouse(&x, &y);
mLastMouseX = x;
mLastMouseY = y;
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_DOUBLE_CLICK, x, y, 0);
+ mMediaSource->scrollEvent(x, y, mask);
}
}
@@ -982,7 +1172,7 @@ void LLViewerMediaImpl::onMouseCaptureLost()
{
if (mMediaSource)
{
- mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, mLastMouseX, mLastMouseY, 0);
+ mMediaSource->mouseEvent(LLPluginClassMedia::MOUSE_EVENT_UP, 0, mLastMouseX, mLastMouseY, 0);
}
}
@@ -1000,49 +1190,146 @@ BOOL LLViewerMediaImpl::handleMouseUp(S32 x, S32 y, MASK mask)
return TRUE;
}
+
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateHome()
-{
- mMediaURL = mHomeURL;
- mDoNavigateOnLoad = !mMediaURL.empty();
- mDoNavigateOnLoadServerRequest = false;
+std::string LLViewerMediaImpl::getName() const
+{
+ if (mMediaSource)
+ {
+ return mMediaSource->getMediaName();
+ }
- if(mMediaSource)
+ return LLStringUtil::null;
+};
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateBack()
+{
+ if (mMediaSource)
{
- mMediaSource->loadURI( mHomeURL );
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 step_scale = 0.02; // temp , can be changed
+ F64 back_step = mMediaSource->getCurrentTime() - (mMediaSource->getDuration()*step_scale);
+ if(back_step < 0.0)
+ {
+ back_step = 0.0;
+ }
+ mMediaSource->seek(back_step);
+ //mMediaSource->start(-2.0);
+ }
+ else
+ {
+ mMediaSource->browse_back();
+ }
}
}
//////////////////////////////////////////////////////////////////////////////////////////
-void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
+void LLViewerMediaImpl::navigateForward()
{
- if(server_request)
+ if (mMediaSource)
{
- setNavState(MEDIANAVSTATE_SERVER_SENT);
+ if(mMediaSource->pluginSupportsMediaTime())
+ {
+ F64 step_scale = 0.02; // temp , can be changed
+ F64 forward_step = mMediaSource->getCurrentTime() + (mMediaSource->getDuration()*step_scale);
+ if(forward_step > mMediaSource->getDuration())
+ {
+ forward_step = mMediaSource->getDuration();
+ }
+ mMediaSource->seek(forward_step);
+ //mMediaSource->start(2.0);
+ }
+ else
+ {
+ mMediaSource->browse_forward();
+ }
}
- else
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateReload()
+{
+ navigateTo(getCurrentMediaURL(), "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateHome()
+{
+ navigateTo(mHomeURL, "", true, false);
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mime_type, bool rediscover_type, bool server_request)
+{
+ if(mMediaURL != url)
{
- setNavState(MEDIANAVSTATE_NONE);
+ // Don't carry media play state across distinct URLs.
+ resetPreviousMediaState();
}
- // Always set the current URL.
+ // 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;
- // If the current URL is not null, make the instance do a navigate on load.
- mDoNavigateOnLoad = !mMediaURL.empty();
-
// and if this was a server request, the navigate on load will also need to be one.
- mDoNavigateOnLoadServerRequest = server_request;
+ 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;
}
- if(rediscover_type)
+ navigateInternal();
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+void LLViewerMediaImpl::navigateInternal()
+{
+ // Helpful to have media urls in log file. Shouldn't be spammy.
+ llinfos << "media id= " << mTextureId << " url=" << mMediaURL << " mime_type=" << mMimeType << llendl;
+
+ 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);
@@ -1058,7 +1345,7 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// We use "data" internally for a text/html url for loading the login screen
if(initializeMedia("text/html"))
{
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
}
else
@@ -1066,24 +1353,18 @@ void LLViewerMediaImpl::navigateTo(const std::string& url, const std::string& mi
// This catches 'rtsp://' urls
if(initializeMedia(scheme))
{
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
}
}
- else if (mMediaSource)
+ else if(initializeMedia(mMimeType))
{
- mMediaSource->loadURI( mMediaURL );
- }
- else if(initializeMedia(mime_type) && mMediaSource)
- {
- mMediaSource->loadURI( mMediaURL );
+ loadURI();
}
else
{
- LL_WARNS("Media") << "Couldn't navigate to: " << url << " as there is no media type for: " << mime_type << LL_ENDL;
- return;
+ LL_WARNS("Media") << "Couldn't navigate to: " << mMediaURL << " as there is no media type for: " << mMimeType << LL_ENDL;
}
-
}
//////////////////////////////////////////////////////////////////////////////////////////
@@ -1100,10 +1381,43 @@ void LLViewerMediaImpl::navigateStop()
bool LLViewerMediaImpl::handleKeyHere(KEY key, MASK mask)
{
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)
{
- result = mMediaSource->keyEvent(LLPluginClassMedia::KEY_EVENT_DOWN ,key, mask);
+ // 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;
@@ -1116,7 +1430,12 @@ bool LLViewerMediaImpl::handleUnicodeCharHere(llwchar uni_char)
if (mMediaSource)
{
- mMediaSource->textInput(wstring_to_utf8str(LLWString(1, uni_char)));
+ // 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;
@@ -1174,6 +1493,7 @@ void LLViewerMediaImpl::update()
if(mMediaSource->isPluginExited())
{
+ resetPreviousMediaState();
destroyMediaSource();
return;
}
@@ -1250,8 +1570,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
if (mNeedsNewTexture
|| placeholder_image->getUseMipMaps()
- || placeholder_image->getWidth() != mMediaSource->getTextureWidth()
- || placeholder_image->getHeight() != mMediaSource->getTextureHeight())
+ || (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;
@@ -1283,6 +1606,11 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
// 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;
@@ -1290,7 +1618,7 @@ LLViewerMediaTexture* LLViewerMediaImpl::updatePlaceholderImage()
//////////////////////////////////////////////////////////////////////////////////////////
-LLUUID LLViewerMediaImpl::getMediaTextureID()
+LLUUID LLViewerMediaImpl::getMediaTextureID() const
{
return mTextureId;
}
@@ -1370,12 +1698,63 @@ bool LLViewerMediaImpl::hasMedia()
}
//////////////////////////////////////////////////////////////////////////////////////////
+//
+void LLViewerMediaImpl::resetPreviousMediaState()
+{
+ mPreviousMediaState = MEDIA_NONE;
+ mPreviousMediaTime = 0.0f;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
+//
+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;
+}
+
+//////////////////////////////////////////////////////////////////////////////////////////
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(mMimeType);
+ LLNotifications::instance().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(mMimeType);
// SJB: This is getting called every frame if the plugin fails to load, continuously respawining the alert!
@@ -1422,7 +1801,21 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
case LLViewerMediaObserver::MEDIA_EVENT_NAVIGATE_COMPLETE:
{
LL_DEBUGS("Media") << "MEDIA_EVENT_NAVIGATE_COMPLETE, uri is: " << plugin->getNavigateURI() << LL_ENDL;
- setNavState(MEDIANAVSTATE_NONE);
+
+ 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;
@@ -1432,10 +1825,12 @@ void LLViewerMediaImpl::handleMediaEvent(LLPluginClassMedia* plugin, LLPluginCla
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
@@ -1535,10 +1930,35 @@ void LLViewerMediaImpl::calculateInterest()
}
else
{
- // I don't think this case should ever be hit.
- LL_WARNS("Plugin") << "no texture!" << LL_ENDL;
+ // This will be a relatively common case now, since it will always be true for unloaded media.
mInterest = 0.0f;
}
+
+ 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()
@@ -1564,11 +1984,11 @@ void LLViewerMediaImpl::setUsedInUI(bool used_in_ui)
{
if(getVisible())
{
- mPriority = LLPluginClassMedia::PRIORITY_NORMAL;
+ setPriority(LLPluginClassMedia::PRIORITY_NORMAL);
}
else
{
- mPriority = LLPluginClassMedia::PRIORITY_HIDDEN;
+ setPriority(LLPluginClassMedia::PRIORITY_HIDDEN);
}
createMediaSource();
@@ -1589,6 +2009,15 @@ F64 LLViewerMediaImpl::getCPUUsage() const
void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
{
+ if(mPriority != priority)
+ {
+ LL_INFOS("PluginPriority")
+ << "changing priority of media id " << mTextureId
+ << " from " << LLPluginClassMedia::priorityToString(mPriority)
+ << " to " << LLPluginClassMedia::priorityToString(priority)
+ << LL_ENDL;
+ }
+
mPriority = priority;
if(priority == LLPluginClassMedia::PRIORITY_UNLOADED)
@@ -1596,6 +2025,11 @@ void LLViewerMediaImpl::setPriority(LLPluginClassMedia::EPriority priority)
if(mMediaSource)
{
// Need to unload the media source
+
+ // First, save off previous media state
+ mPreviousMediaState = mMediaSource->getStatus();
+ mPreviousMediaTime = mMediaSource->getCurrentTime();
+
destroyMediaSource();
}
}
@@ -1625,9 +2059,11 @@ void LLViewerMediaImpl::setNavState(EMediaNavState 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;
}
}
@@ -1644,11 +2080,13 @@ void LLViewerMediaImpl::addObject(LLVOVolume* obj)
}
mObjectList.push_back(obj) ;
+ mNeedsMuteCheck = true;
}
void LLViewerMediaImpl::removeObject(LLVOVolume* obj)
{
mObjectList.remove(obj) ;
+ mNeedsMuteCheck = true;
}
const std::list< LLVOVolume* >* LLViewerMediaImpl::getObjectList() const
@@ -1656,6 +2094,19 @@ 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;
+}
+
//////////////////////////////////////////////////////////////////////////////////////////
//static
void LLViewerMedia::toggleMusicPlay(void*)
diff --git a/indra/newview/llviewermedia.h b/indra/newview/llviewermedia.h
index c9ba5841e9..4cb0817735 100644
--- a/indra/newview/llviewermedia.h
+++ b/indra/newview/llviewermedia.h
@@ -66,10 +66,15 @@ private:
observerListType mObservers;
};
+class LLViewerMediaImpl;
+
class LLViewerMedia
{
LOG_CLASS(LLViewerMedia);
public:
+
+ typedef std::vector<LLViewerMediaImpl*> impl_list;
+
// Special case early init for just web browser component
// so we can show login screen. See .cpp file for details. JC
@@ -95,6 +100,16 @@ class LLViewerMedia
static void toggleMusicPlay(void*);
static void toggleMediaPlay(void*);
static void mediaStop(void*);
+ static F32 getVolume();
+ static void muteListChanged();
+ static void setInWorldMediaDisabled(bool disabled);
+ static bool getInWorldMediaDisabled();
+
+ // 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);
};
// Implementation functions not exported into header file
@@ -121,6 +136,7 @@ public:
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);
@@ -130,26 +146,34 @@ public:
void start();
void seek(F32 time);
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);
- void mouseUp(S32 x, S32 y);
- void mouseMove(S32 x, S32 y);
- void mouseDown(const LLVector2& texture_coords);
- void mouseUp(const LLVector2& texture_coords);
- void mouseMove(const LLVector2& texture_coords);
- void mouseLeftDoubleClick(S32 x,S32 y );
+ 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 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() { return mMediaURL; }
+ std::string getMediaURL() const { return mMediaURL; }
+ std::string getCurrentMediaURL();
std::string getHomeURL() { return mHomeURL; }
void setHomeURL(const std::string& home_url) { mHomeURL = home_url; };
std::string getMimeType() { return mMimeType; }
@@ -157,7 +181,7 @@ public:
void update();
void updateImagesMediaStreams();
- LLUUID getMediaTextureID();
+ LLUUID getMediaTextureID() const;
void suspendUpdates(bool suspend) { mSuspendUpdates = suspend; };
void setVisible(bool visible);
@@ -166,6 +190,14 @@ public:
bool isMediaPlaying();
bool isMediaPaused();
bool hasMedia();
+ bool isMediaFailed() { return mMediaSourceFailed; };
+ void resetPreviousMediaState();
+
+ void setDisabled(bool disabled) { mIsDisabled = disabled; };
+ bool isMediaDisabled() { return mIsDisabled; };
+
+ // returns true if this instance should not be loaded (disabled, muted object, crashed, etc.)
+ bool isForcedUnloaded() const;
ECursorType getLastSetCursor() { return mLastSetCursor; };
@@ -196,7 +228,7 @@ public:
/*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 { return LLStringUtil::null; };
+ /*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 {};
@@ -218,6 +250,7 @@ public:
void addObject(LLVOVolume* obj) ;
void removeObject(LLVOVolume* obj) ;
const std::list< LLVOVolume* >* getObjectList() const ;
+ LLVOVolume *getSomeObject();
void setUpdated(BOOL updated) ;
BOOL isUpdated() ;
@@ -225,6 +258,7 @@ public:
void calculateInterest();
F64 getInterest() const { return mInterest; };
F64 getApproximateTextureInterest();
+ S32 getProximity() const { return mProximity; };
// 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.
@@ -240,12 +274,14 @@ public:
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_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_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;
@@ -259,9 +295,10 @@ public:
LLPluginClassMedia* mMediaSource;
LLUUID mTextureId;
bool mMovieImageHasMips;
- std::string mMediaURL;
+ 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).
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;
@@ -269,6 +306,8 @@ public:
bool mMediaAutoScale;
bool mMediaLoop;
bool mNeedsNewTexture;
+ S32 mTextureUsedWidth;
+ S32 mTextureUsedHeight;
bool mSuspendUpdates;
bool mVisible;
ECursorType mLastSetCursor;
@@ -277,9 +316,16 @@ public:
bool mUsedInUI;
bool mHasFocus;
LLPluginClassMedia::EPriority mPriority;
- bool mDoNavigateOnLoad;
- bool mDoNavigateOnLoadServerRequest;
-
+ bool mNavigateRediscoverType;
+ bool mNavigateServerRequest;
+ bool mMediaSourceFailed;
+ F32 mRequestedVolume;
+ bool mIsMuted;
+ bool mNeedsMuteCheck;
+ int mPreviousMediaState;
+ F64 mPreviousMediaTime;
+ bool mIsDisabled;
+ S32 mProximity;
private:
BOOL mIsUpdated ;
diff --git a/indra/newview/llviewermediafocus.cpp b/indra/newview/llviewermediafocus.cpp
index f9377ab37b..b2a0fa4b1c 100644
--- a/indra/newview/llviewermediafocus.cpp
+++ b/indra/newview/llviewermediafocus.cpp
@@ -35,7 +35,7 @@
//LLViewerMediaFocus
#include "llviewerobjectlist.h"
-#include "llpanelmediahud.h"
+#include "llpanelprimmediacontrols.h"
#include "llpluginclassmedia.h"
#include "llagent.h"
#include "lltoolpie.h"
@@ -48,12 +48,17 @@
#include "llviewerparcelmgr.h"
#include "llweb.h"
#include "llmediaentry.h"
+#include "llkeyboard.h"
+#include "lltoolmgr.h"
+#include "llvovolume.h"
+
//
// LLViewerMediaFocus
//
LLViewerMediaFocus::LLViewerMediaFocus()
-: mMouseOverFlag(false)
+: mFocusedObjectFace(0),
+ mHoverObjectFace(0)
{
}
@@ -63,110 +68,113 @@ LLViewerMediaFocus::~LLViewerMediaFocus()
// Clean up in cleanupClass() instead.
}
-void LLViewerMediaFocus::cleanupClass()
-{
- LLViewerMediaFocus *self = LLViewerMediaFocus::getInstance();
+void LLViewerMediaFocus::setFocusFace(LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl, LLVector3 pick_normal)
+{
+ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
- if(self)
+ LLViewerMediaImpl *old_media_impl = getFocusedMediaImpl();
+ if(old_media_impl)
{
- // mMediaHUD will have been deleted by this point -- don't try to delete it.
-
- /* Richard says:
- all widgets are supposed to be destroyed at the same time
- you shouldn't hold on to pointer to them outside of ui code
- you can use the LLHandle approach
- if you want to be type safe, you'll need to add a LLRootHandle to whatever derived class you are pointing to
- look at llview::gethandle
- its our version of a weak pointer
- */
- if(self->mMediaHUD.get())
- {
- self->mMediaHUD.get()->setMediaImpl(NULL);
- }
- self->mMediaImpl = NULL;
+ 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;
-
-void LLViewerMediaFocus::setFocusFace( BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl )
-{
- LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel();
-
- if(mMediaImpl.notNull())
- {
- mMediaImpl->focus(false);
- }
-
- if (b && media_impl.notNull())
+ if (media_impl.notNull() && objectp.notNull())
{
bool face_auto_zoom = false;
- mMediaImpl = media_impl;
- mMediaImpl->focus(true);
- LLSelectMgr::getInstance()->deselectAll();
- LLSelectMgr::getInstance()->selectObjectOnly(objectp, face);
+ 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);
- if(objectp.notNull())
+ LLTextureEntry* tep = objectp->getTE(face);
+ if(tep->hasMedia())
{
- LLTextureEntry* tep = objectp->getTE(face);
- if(! tep->hasMedia())
- {
- // Error condition
- }
LLMediaEntry* mep = tep->getMediaData();
face_auto_zoom = mep->getAutoZoom();
- if(! mep->getAutoPlay())
+ if(!media_impl->hasMedia())
{
std::string url = mep->getCurrentURL().empty() ? mep->getHomeURL() : mep->getCurrentURL();
media_impl->navigateTo(url, "", true);
}
}
- mFocus = LLSelectMgr::getInstance()->getSelection();
- if(mMediaHUD.get() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
- {
- mMediaHUD.get()->resetZoomLevel();
- mMediaHUD.get()->nextZoomLevel();
- }
- if (!mFocus->isEmpty())
+ else
{
- gFocusMgr.setKeyboardFocus(this);
+ // This should never happen.
+ llwarns << "Can't find media entry for focused face" << llendl;
}
- mObjectID = objectp->getID();
- mObjectFace = face;
- // LLViewerMedia::addObserver(this, mObjectID);
+ 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() && face_auto_zoom && ! parcel->getMediaPreventCameraZoom())
+ {
+ mMediaControls.get()->resetZoomLevel();
+ mMediaControls.get()->nextZoomLevel();
+ }
}
else
{
- gFocusMgr.setKeyboardFocus(NULL);
- if(! parcel->getMediaPreventCameraZoom())
+ if(mFocusedImplID.notNull())
{
- if (!mFocus->isEmpty())
+ if(mMediaControls.get())
{
- gAgent.setFocusOnAvatar(TRUE, ANIMATE);
+ mMediaControls.get()->resetZoomLevel();
}
}
- mFocus = NULL;
- // LLViewerMedia::remObserver(this, mObjectID);
-
- // Null out the media hud media pointer
- if(mMediaHUD.get())
+
+ if(hasFocus())
{
- mMediaHUD.get()->setMediaImpl(NULL);
+ gFocusMgr.setKeyboardFocus(NULL);
}
+
+ mFocusedImplID = LLUUID::null;
+ mFocusedObjectID = LLUUID::null;
+ mFocusedObjectFace = 0;
+ }
+}
- // and null out the media impl
- mMediaImpl = NULL;
- mObjectID = LLUUID::null;
- mObjectFace = 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;
}
- if(mMediaHUD.get())
+ else
{
- mMediaHUD.get()->setMediaFocus(b);
+ mHoverObjectID = LLUUID::null;
+ mHoverObjectFace = 0;
+ mHoverImplID = LLUUID::null;
}
}
+
+void LLViewerMediaFocus::clearHover()
+{
+ setHoverFace(NULL, 0, NULL);
+}
+
+
bool LLViewerMediaFocus::getFocus()
{
if (gFocusMgr.getKeyboardFocus() == this)
@@ -176,22 +184,15 @@ bool LLViewerMediaFocus::getFocus()
return false;
}
-// This function selects an ideal viewing distance given a selection bounding box, normal, and padding value
-void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
+// 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)
{
- LLPickInfo& pick = LLToolPie::getInstance()->getPick();
-
- if(LLSelectMgr::getInstance()->getSelection()->isEmpty())
- {
- pick = mPickInfo;
- setFocusFace(true, pick.getObject(), pick.mObjectFace, mMediaImpl);
- }
-
- if (!LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ if (object)
{
gAgent.setFocusOnAvatar(FALSE, ANIMATE);
- LLBBox selection_bbox = LLSelectMgr::getInstance()->getBBoxOfSelection();
+ LLBBox bbox = object->getBoundingBoxAgent();
+ LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent());
F32 height;
F32 width;
F32 depth;
@@ -199,7 +200,7 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
F32 distance;
// We need the aspect ratio, and the 3 components of the bbox as height, width, and depth.
- F32 aspect_ratio = getBBoxAspectRatio(selection_bbox, pick.mNormal, &height, &width, &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
@@ -227,84 +228,96 @@ void LLViewerMediaFocus::setCameraZoom(F32 padding_factor)
distance += depth * 0.5;
// Finally animate the camera to this new position and focal point
- gAgent.setCameraPosAndFocusGlobal(LLSelectMgr::getInstance()->getSelectionCenterGlobal() + LLVector3d(pick.mNormal * distance),
- LLSelectMgr::getInstance()->getSelectionCenterGlobal(), LLSelectMgr::getInstance()->getSelection()->getFirstObject()->mID );
+ 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()
{
- if(mMediaImpl.notNull())
- mMediaImpl->focus(true);
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(true);
LLFocusableElement::onFocusReceived();
}
void LLViewerMediaFocus::onFocusLost()
{
- if(mMediaImpl.notNull())
- mMediaImpl->focus(false);
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
+ media_impl->focus(false);
+
gViewerWindow->focusClient();
- mFocus = NULL;
LLFocusableElement::onFocusLost();
}
-void LLViewerMediaFocus::setMouseOverFlag(bool b, viewer_media_t media_impl)
+
+BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
{
- if (b && media_impl.notNull())
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl)
{
- if(! mMediaHUD.get())
- {
- LLPanelMediaHUD* media_hud = new LLPanelMediaHUD(mMediaImpl);
- mMediaHUD = media_hud->getHandle();
- gHUDView->addChild(media_hud);
- }
- mMediaHUD.get()->setMediaImpl(media_impl);
+ media_impl->handleKeyHere(key, mask);
- if(mMediaImpl.notNull() && (mMediaImpl != media_impl))
+ if (key == KEY_ESCAPE)
{
- mMediaImpl->focus(false);
+ clearFocus();
}
-
- mMediaImpl = media_impl;
}
- mMouseOverFlag = b;
-}
-LLUUID LLViewerMediaFocus::getSelectedUUID()
-{
- LLViewerObject* object = mFocus->getFirstObject();
- return object ? object->getID() : LLUUID::null;
-}
-#if 0 // Must re-implement when the new media api event system is ready
-void LLViewerMediaFocus::onNavigateComplete( const EventType& event_in )
-{
- if (hasFocus() && mLastURL != event_in.getStringValue())
- {
- LLViewerMedia::focus(true, mObjectID);
- // spoof mouse event to reassert focus
- LLViewerMedia::mouseDown(1,1, mObjectID);
- LLViewerMedia::mouseUp(1,1, mObjectID);
- }
- mLastURL = event_in.getStringValue();
-}
-#endif
-BOOL LLViewerMediaFocus::handleKey(KEY key, MASK mask, BOOL called_from_parent)
-{
- if(mMediaImpl.notNull())
- mMediaImpl->handleKeyHere(key, mask);
+
return true;
}
BOOL LLViewerMediaFocus::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent)
{
- if(mMediaImpl.notNull())
- mMediaImpl->handleUnicodeCharHere(uni_char);
+ 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;
- if(mFocus.notNull() && mMediaImpl.notNull() && mMediaImpl->hasMedia())
+ LLViewerMediaImpl* media_impl = getFocusedMediaImpl();
+ if(media_impl && media_impl->hasMedia())
{
- mMediaImpl->getMediaPlugin()->scrollEvent(x, y, clicks);
+ // 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;
@@ -312,19 +325,69 @@ BOOL LLViewerMediaFocus::handleScrollWheel(S32 x, S32 y, S32 clicks)
void LLViewerMediaFocus::update()
{
- if (mMediaHUD.get())
+ if(mFocusedImplID.notNull() || mFocusedObjectID.notNull())
{
- if(mFocus.notNull() || mMouseOverFlag || mMediaHUD.get()->isMouseOver())
+ // We have a focused impl/face.
+ if(!getFocus())
{
- // mMediaHUD.get()->setVisible(true);
- mMediaHUD.get()->updateShape();
+ // 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
+ else if(LLToolMgr::getInstance()->inBuildMode())
{
- mMediaHUD.get()->setVisible(false);
+ // 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)
{
@@ -393,5 +456,74 @@ F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3&
bool LLViewerMediaFocus::isFocusedOnFace(LLPointer<LLViewerObject> objectp, S32 face)
{
- return objectp->getID() == mObjectID && face == mObjectFace;
+ 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.
+ // For now, use +z to look at the top of the object.
+ LLVector3 normal(0.0f, 0.0f, 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
index 2688a8b708..89ee0ae283 100644
--- a/indra/newview/llviewermediafocus.h
+++ b/indra/newview/llviewermediafocus.h
@@ -40,7 +40,7 @@
#include "llselectmgr.h"
class LLViewerMediaImpl;
-class LLPanelMediaHUD;
+class LLPanelPrimMediaControls;
class LLViewerMediaFocus :
public LLFocusableElement,
@@ -50,44 +50,63 @@ public:
LLViewerMediaFocus();
~LLViewerMediaFocus();
- static void cleanupClass();
-
- void setFocusFace(BOOL b, LLPointer<LLViewerObject> objectp, S32 face, viewer_media_t media_impl);
- void clearFocus() { setFocusFace(false, NULL, 0, NULL); }
+ // 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*/ // void onNavigateComplete( const EventType& event_in );
-
/*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);
- LLUUID getSelectedUUID();
- LLObjectSelectionHandle getSelection() { return mFocus; }
-
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);
- void setCameraZoom(F32 padding_factor);
- void setMouseOverFlag(bool b, viewer_media_t media_impl = NULL);
- bool getMouseOverFlag() { return mMouseOverFlag; }
- void setPickInfo(LLPickInfo pick_info) { mPickInfo = pick_info; }
- F32 getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth);
-
- // TODO: figure out why selection mgr hates me
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:
- LLObjectSelectionHandle mFocus;
- std::string mLastURL;
- bool mMouseOverFlag;
- LLPickInfo mPickInfo;
- LLHandle<LLPanelMediaHUD> mMediaHUD;
- LLUUID mObjectID;
- S32 mObjectFace;
- viewer_media_t mMediaImpl;
+
+ LLHandle<LLPanelPrimMediaControls> mMediaControls;
+ LLObjectSelectionHandle mSelection;
+
+ LLUUID mFocusedObjectID;
+ S32 mFocusedObjectFace;
+ LLUUID mFocusedImplID;
+ LLVector3 mFocusedObjectNormal;
+
+ LLUUID mHoverObjectID;
+ S32 mHoverObjectFace;
+ LLUUID mHoverImplID;
+ LLVector3 mHoverObjectNormal;
};
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index b4e0d88e79..b30acd47f1 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -50,6 +50,7 @@
#include "llfocusmgr.h"
#include "llfontgl.h"
#include "llinstantmessage.h"
+#include "llinventorypanel.h"
#include "llpermissionsflags.h"
#include "llrect.h"
#include "llsecondlifeurls.h"
@@ -97,7 +98,6 @@
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
#include "llfloaterdaycycle.h"
-#include "llfloaterdirectory.h"
#include "llfloaterchatterbox.h"
#include "llfloaterfonttest.h"
#include "llfloatergodtools.h"
@@ -146,7 +146,6 @@
#include "llmenucommands.h"
#include "llmenugl.h"
#include "llmimetypes.h"
-#include "llmorphview.h"
#include "llmoveview.h"
#include "llmutelist.h"
#include "llnotify.h"
@@ -207,6 +206,7 @@
#include "llwaterparammanager.h"
#include "llfloaternotificationsconsole.h"
#include "llfloatercamera.h"
+#include "lluilistener.h"
#include "lltexlayer.h"
#include "llappearancemgr.h"
@@ -414,6 +414,8 @@ public:
static LLMenuParcelObserver* gMenuParcelObserver = NULL;
+static LLUIListener sUIListener("UI");
+
LLMenuParcelObserver::LLMenuParcelObserver()
{
LLViewerParcelMgr::getInstance()->addObserver(this);
@@ -1635,16 +1637,6 @@ class LLAdvancedToggleCharacterGeometry : public view_listener_t
}
};
-class LLEnableGodCustomerService : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
-{
- bool new_value = enable_god_customer_service(NULL);
- return new_value;
- }
-};
-
-
/////////////////////////////
// TEST MALE / TEST FEMALE //
@@ -1686,34 +1678,6 @@ class LLAdvancedTogglePG : public view_listener_t
};
-
-////////////////////////////
-// ALLOW TAP-TAP-HOLD RUN //
-////////////////////////////
-
-
-class LLAdvancedToggleAllowTapTapHoldRun : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- gAllowTapTapHoldRun = !(gAllowTapTapHoldRun);
- return true;
- }
-};
-
-class LLAdvancedCheckAllowTapTapHoldRun : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- bool new_value = gAllowTapTapHoldRun;
- return new_value;
- }
-};
-
-
-
-
-
class LLAdvancedForceParamsToDefault : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -2806,7 +2770,7 @@ 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;
@@ -2999,11 +2963,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(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();
@@ -3027,9 +3000,7 @@ class LLAvatarFreeze : public view_listener_t
callback_freeze);
}
}
- return true;
- }
-};
+}
class LLAvatarVisibleDebug : public view_listener_t
{
@@ -3039,14 +3010,6 @@ class LLAvatarVisibleDebug : public view_listener_t
}
};
-class LLAvatarEnableDebug : public view_listener_t
-{
- bool handleEvent(const LLSD& userdata)
- {
- return gAgent.isGodlike();
- }
-};
-
class LLAvatarDebug : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -3063,7 +3026,7 @@ class LLAvatarDebug : public view_listener_t
strings.push_back(avatar->getID().asString());
LLUUID invoice;
send_generic_message("dumptempassetdata", strings, invoice);
- LLFloaterReg::showInstance( "avatar_tetures", LLSD(avatar->getID()) );
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(avatar->getID()) );
}
return true;
}
@@ -3123,11 +3086,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(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;
@@ -3178,38 +3150,41 @@ class LLAvatarEject : public view_listener_t
}
}
}
- return true;
- }
-};
+}
-class LLAvatarEnableFreezeEject : public view_listener_t
+bool enable_freeze_eject(const LLSD& avatar_id)
{
- bool handleEvent(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;
- return new_value;
+ // 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
{
@@ -3458,26 +3433,22 @@ bool enable_standup_self()
return new_value;
}
-class LLSelfFriends : public view_listener_t
+// Used from the login screen to aid in UI work on side tray
+void handle_show_side_tray()
{
- bool handleEvent(const LLSD& userdata)
- {
- // Open "Friends" tab of the "People" panel in side tray.
- LLSD param;
- param["people_panel_tab_name"] = "friends_panel";
-
- LLSideTray::getInstance()->showPanel("panel_people", param);
- return true;
- }
-};
+ LLSideTray* side_tray = LLSideTray::getInstance();
+ LLView* root = gViewerWindow->getRootView();
+ // automatically removes and re-adds if there already
+ root->addChild(side_tray);
+}
-class LLSelfGroups : public view_listener_t
+class LLShowPanelPeopleTab : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
{
- // Open "Groups" tab of the "People" panel in side tray.
+ // Open tab of the "People" panel in side tray.
LLSD param;
- param["people_panel_tab_name"] = "groups_panel";
+ param["people_panel_tab_name"] = userdata.asString();
LLSideTray::getInstance()->showPanel("panel_people", param);
return true;
}
@@ -3510,12 +3481,8 @@ 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);
@@ -4033,7 +4000,7 @@ void handle_god_request_avatar_geometry(void *)
{
if (gAgent.isGodlike())
{
- LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", NULL);
+ LLSelectMgr::getInstance()->sendGodlikeRequest("avatar toggle", "");
}
}
@@ -4195,12 +4162,10 @@ void handle_take_copy()
{
if (LLSelectMgr::getInstance()->getSelection()->isEmpty()) return;
- LLUUID category_id =
- gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT);
+ 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
{
@@ -4281,7 +4246,7 @@ class LLObjectEnableReturn : public view_listener_t
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);
}
@@ -4342,8 +4307,7 @@ 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();
@@ -4359,7 +4323,7 @@ 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;
@@ -4733,6 +4697,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
@@ -5807,12 +5861,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)
@@ -5912,24 +5966,27 @@ class LLAttachmentDrop : public view_listener_t
class LLAttachmentDetachFromPoint : public view_listener_t
{
bool handleEvent(const LLSD& user_data)
-{
- LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
-
- LLViewerObject* attached_object = attachment ? attachment->getObject() : NULL;
-
- 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() );
- }
+ const LLViewerJointAttachment *attachment = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, user_data.asInteger(), (LLViewerJointAttachment*)NULL);
+ if (attachment->getNumObjects() > 0)
+ {
+ 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++)
+ {
+ LLViewerObject *attached_object = (*iter);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, attached_object->getLocalID());
+ }
+ gMessageSystem->sendReliable( gAgent.getRegionHost() );
+ }
return true;
-}
+ }
};
static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
@@ -5938,25 +5995,31 @@ static bool onEnableAttachmentLabel(LLUICtrl* ctrl, const LLSD& data)
LLMenuItemGL* menu = dynamic_cast<LLMenuItemGL*>(ctrl);
if (menu)
{
- LLViewerJointAttachment *attachmentp = get_if_there(gAgent.getAvatarObject()->mAttachmentPoints, data["index"].asInteger(), (LLViewerJointAttachment*)NULL);
- if (attachmentp)
- {
- label = data["label"].asString();
- 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(const LLSD& userdata)
@@ -6043,33 +6106,37 @@ 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 )
+ if (object)
{
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);
+ }
}
}
}
@@ -6172,11 +6239,11 @@ class LLAttachmentPointFilled : public view_listener_t
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->getObject() != NULL;
+ {
+ enable = found_it->second->getNumObjects() > 0;
}
return enable;
-}
+ }
};
class LLAvatarSendIM : public view_listener_t
@@ -6399,17 +6466,23 @@ 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;
+ }
}
}
@@ -6697,7 +6770,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;
}
@@ -6814,25 +6887,26 @@ void handle_debug_avatar_textures(void*)
LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getPrimaryObject();
if (objectp)
{
- LLFloaterReg::showInstance( "avatar_tetures", LLSD(objectp->getID()) );
+ LLFloaterReg::showInstance( "avatar_textures", LLSD(objectp->getID()) );
}
}
void handle_grab_texture(void* data)
{
- ETextureIndex index = (ETextureIndex)((intptr_t)data);
+ 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 = "Unknown";
- const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(index);
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture(tex_index);
if (texture_dict->mIsBakedTexture)
{
EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
@@ -6899,7 +6973,8 @@ BOOL enable_grab_texture(void* data)
const LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
if ( avatar )
{
- return avatar->canGrabLocalTexture(index);
+ // MULTI-WEARABLE:
+ return avatar->canGrabLocalTexture(index,0);
}
return FALSE;
}
@@ -6958,7 +7033,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 *)
@@ -7369,52 +7444,10 @@ class LLEditEnableTakeOff : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
std::string clothing = userdata.asString();
- bool new_value = false;
- if (clothing == "shirt")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_SHIRT);
- }
- if (clothing == "pants")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_PANTS);
- }
- if (clothing == "shoes")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_SHOES);
- }
- if (clothing == "socks")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_SOCKS);
- }
- if (clothing == "jacket")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_JACKET);
- }
- if (clothing == "gloves")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_GLOVES);
- }
- if (clothing == "undershirt")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_UNDERSHIRT);
- }
- if (clothing == "underpants")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_UNDERPANTS);
- }
- if (clothing == "skirt")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_SKIRT);
- }
- if (clothing == "alpha")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_ALPHA);
- }
- if (clothing == "tattoo")
- {
- new_value = LLAgentWearables::selfHasWearable(WT_TATTOO);
- }
- return new_value;
+ EWearableType type = LLWearableDictionary::typeNameToType(clothing);
+ if (type >= WT_SHAPE && type < WT_COUNT)
+ return LLAgentWearables::selfHasWearable(type);
+ return false;
}
};
@@ -7423,53 +7456,13 @@ class LLEditTakeOff : public view_listener_t
bool handleEvent(const LLSD& userdata)
{
std::string clothing = userdata.asString();
- if (clothing == "shirt")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_SHIRT);
- }
- else if (clothing == "pants")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_PANTS);
- }
- else if (clothing == "shoes")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_SHOES);
- }
- else if (clothing == "socks")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_SOCKS);
- }
- else if (clothing == "jacket")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_JACKET);
- }
- else if (clothing == "gloves")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_GLOVES);
- }
- else if (clothing == "undershirt")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_UNDERSHIRT);
- }
- else if (clothing == "underpants")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_UNDERPANTS);
- }
- else if (clothing == "skirt")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_SKIRT);
- }
- else if (clothing == "alpha")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_ALPHA);
- }
- else if (clothing == "tattoo")
- {
- LLAgentWearables::userRemoveWearable((void*)WT_TATTOO);
- }
- else if (clothing == "all")
+ if (clothing == "all")
+ LLAgentWearables::userRemoveAllClothes();
+ else
{
- LLAgentWearables::userRemoveAllClothes(NULL);
+ EWearableType type = LLWearableDictionary::typeNameToType(clothing);
+ if (type >= WT_SHAPE && type < WT_COUNT)
+ LLAgentWearables::userRemoveWearable(type);
}
return true;
}
@@ -7639,8 +7632,10 @@ void initialize_menus()
LLUICtrl::CommitCallbackRegistry::Registrar& commit = LLUICtrl::CommitCallbackRegistry::currentRegistrar();
LLUICtrl::VisibleCallbackRegistry::Registrar& visible = LLUICtrl::VisibleCallbackRegistry::currentRegistrar();
- // Enable God Mode
- view_listener_t::addMenu(new LLEnableGodCustomerService(), "EnableGodCustomerService");
+ // 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));
+ visible.add("IsGodCustomerService", boost::bind(&is_god_customer_service));
// Agent
commit.add("Agent.toggleFlying", boost::bind(&LLAgent::toggleFlying));
@@ -7729,6 +7724,7 @@ void initialize_menus()
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");
@@ -7742,6 +7738,7 @@ void initialize_menus()
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");
@@ -7830,7 +7827,7 @@ void initialize_menus()
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()));
@@ -7853,8 +7850,6 @@ void initialize_menus()
view_listener_t::addMenu(new LLAdvancedTogglePG(), "Advanced.TogglePG");
// Advanced > Character (toplevel)
- view_listener_t::addMenu(new LLAdvancedToggleAllowTapTapHoldRun(), "Advanced.ToggleAllowTapTapHoldRun");
- view_listener_t::addMenu(new LLAdvancedCheckAllowTapTapHoldRun(), "Advanced.CheckAllowTapTapHoldRun");
view_listener_t::addMenu(new LLAdvancedForceParamsToDefault(), "Advanced.ForceParamsToDefault");
view_listener_t::addMenu(new LLAdvancedReloadVertexShader(), "Advanced.ReloadVertexShader");
view_listener_t::addMenu(new LLAdvancedToggleAnimationInfo(), "Advanced.ToggleAnimationInfo");
@@ -7932,25 +7927,24 @@ void initialize_menus()
view_listener_t::addMenu(new LLSelfEnableRemoveAllAttachments(), "Self.EnableRemoveAllAttachments");
// we don't use boost::bind directly to delay side tray construction
- view_listener_t::addMenu(new LLSelfFriends(), "Self.Friends");
- view_listener_t::addMenu(new LLSelfGroups(), "Self.Groups");
+ view_listener_t::addMenu( new LLShowPanelPeopleTab(), "SideTray.PanelPeopleTab");
// Avatar pie menu
view_listener_t::addMenu(new LLObjectMute(), "Avatar.Mute");
view_listener_t::addMenu(new LLAvatarAddFriend(), "Avatar.AddFriend");
view_listener_t::addMenu(new LLAvatarAddContact(), "Avatar.AddContact");
- view_listener_t::addMenu(new LLAvatarFreeze(), "Avatar.Freeze");
+ 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 LLAvatarEnableDebug(), "Avatar.EnableDebug");
view_listener_t::addMenu(new LLAvatarInviteToGroup(), "Avatar.InviteToGroup");
view_listener_t::addMenu(new LLAvatarGiveCard(), "Avatar.GiveCard");
- view_listener_t::addMenu(new LLAvatarEject(), "Avatar.Eject");
+ commit.add("Avatar.Eject", boost::bind(&handle_avatar_eject, LLSD()));
view_listener_t::addMenu(new LLAvatarSendIM(), "Avatar.SendIM");
view_listener_t::addMenu(new LLAvatarReportAbuse(), "Avatar.ReportAbuse");
view_listener_t::addMenu(new LLAvatarEnableAddFriend(), "Avatar.EnableAddFriend");
- view_listener_t::addMenu(new LLAvatarEnableFreezeEject(), "Avatar.EnableFreezeEject");
+ enable.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
+ visible.add("Avatar.EnableFreezeEject", boost::bind(&enable_freeze_eject, _2));
// Object pie menu
view_listener_t::addMenu(new LLObjectBuild(), "Object.Build");
diff --git a/indra/newview/llviewermenu.h b/indra/newview/llviewermenu.h
index d28d54c933..b65878b5e6 100644
--- a/indra/newview/llviewermenu.h
+++ b/indra/newview/llviewermenu.h
@@ -84,7 +84,6 @@ 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 set_underclothes_menu_options();
@@ -102,6 +101,14 @@ void handle_take_copy();
void handle_look_at_selection(const LLSD& param);
void handle_zoom_to_object(LLUUID object_id);
+// 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);
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index 1cfeec5627..d17c7e486f 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -219,7 +219,7 @@ const std::string upload_pick(void* data)
args["EXTENSION"] = ext;
args["VALIDS"] = valid_extensions;
LLNotifications::instance().add("InvalidFileExtension", args);
- return NULL;
+ return std::string();
}
}//end else (non-null extension)
@@ -319,7 +319,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);
@@ -493,7 +493,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,
@@ -810,7 +810,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,7 +856,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;
@@ -903,7 +903,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,
@@ -915,7 +915,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,
@@ -973,14 +973,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;
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index bf21292082..da78537a29 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -33,7 +33,7 @@
#ifndef LLVIEWERMENUFILE_H
#define LLVIEWERMENUFILE_H
-#include "llassettype.h"
+#include "llfoldertype.h"
#include "llinventorytype.h"
class LLTransactionID;
@@ -45,7 +45,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 +60,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 aa662b713e..ea1097c477 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -72,7 +72,6 @@
#include "llviewercontrol.h"
#include "lldrawpool.h"
#include "llfirstuse.h"
-#include "llfloateractivespeakers.h"
#include "llfloateranimpreview.h"
#include "llfloaterbuycurrency.h"
#include "llfloaterbuyland.h"
@@ -89,12 +88,13 @@
#include "llhudeffect.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llimpanel.h"
#include "llinventorymodel.h"
+#include "llinventorypanel.h"
#include "llfloaterinventory.h"
#include "llmenugl.h"
#include "llmoveview.h"
#include "llmutelist.h"
+#include "llnearbychat.h"
#include "llnotifications.h"
#include "llnotify.h"
#include "llpanelgrouplandmoney.h"
@@ -140,7 +140,7 @@
#include "llgroupactions.h"
#include "llagentui.h"
#include "llpanelblockedlist.h"
-#include "llpanelplaceinfo.h"
+#include "llpanelplaceprofile.h"
#include <boost/tokenizer.hpp>
#include <boost/algorithm/string/split.hpp>
@@ -209,7 +209,6 @@ 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;
LLMessageSystem* msg = gMessageSystem;
const LLSD& payload = notification["payload"];
@@ -219,10 +218,11 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
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);
@@ -235,7 +235,9 @@ 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.
@@ -247,6 +249,7 @@ bool friendship_offer_callback(const LLSD& notification, const LLSD& response)
msg->addUUIDFast(_PREHASH_TransactionID, payload["session_id"]);
msg->sendReliable(LLHost(payload["sender"].asString()));
break;
+ }
default:
// close button probably, possibly timed out
break;
@@ -767,8 +770,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())
{
@@ -875,7 +877,7 @@ void open_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));
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
LLInventoryItem* item;
for(; it != end; ++it)
{
@@ -946,13 +948,12 @@ void open_offer(const std::vector<LLUUID>& items, const std::string& from_name)
}
//Trash Check
- 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))
{
return;
}
- LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND);
+ const LLUUID lost_and_found_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
//BOOL inventory_has_focus = gFocusMgr.childHasKeyboardFocus(view);
BOOL user_is_away = gAwayTimer.getStarted();
@@ -1596,8 +1597,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data)
// 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);
+
+ LLNearbyChat* nearby_chat = LLFloaterReg::getTypedInstance<LLNearbyChat>("nearby_chat", LLSD());
+ if(nearby_chat)
+ {
+ nearby_chat->addMessage(chat);
+ }
}
else
{
@@ -1712,7 +1717,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 ";
@@ -1846,7 +1851,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)
{
@@ -1946,46 +1951,10 @@ 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";
- }
-
- if (session_id.notNull())
- {
- chat.mFromID = session_id;
- }
- else
- {
- // This message originated on a region without the updated code for task id and slurl information.
- // We just need a unique ID for this object that isn't the owner ID.
- // If it is the owner ID it will overwrite the style that contains the link to that owner's profile.
- // This isn't ideal - it will make 1 style for all objects owned by the the same person/group.
- // This works because the only thing we can really do in this case is show the owner name and link to their profile.
- chat.mFromID = from_id ^ gAgent.getSessionID();
- }
- std::ostringstream link;
- link << "secondlife:///app/objectim/" << session_id
- << LLURI::mapToQueryString(query_string);
-
- chat.mURL = link.str();
- chat.mText = name + separator_string + message.substr(message_offset);
-
- // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because
- // IMs from objcts don't open IM sessions.
- chat.mSourceType = CHAT_SOURCE_OBJECT;
- LLFloaterChat::addChat(chat, FALSE, FALSE);
+ LLSD substitutions;
+ substitutions["MSG"] = message.substr(message_offset);
+ LLNotifications::instance().add("ServerObjectMessage", substitutions);
}
break;
case IM_FROM_TASK_AS_ALERT:
@@ -2176,7 +2145,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()));
@@ -2413,7 +2382,7 @@ 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:
@@ -2421,7 +2390,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data)
verb = "";
break;
case CHAT_TYPE_SHOUT:
- verb = "(" + LLTrans::getString("shout") + ")";
+ verb = LLTrans::getString("shout") + " ";
break;
case CHAT_TYPE_START:
case CHAT_TYPE_STOP:
@@ -2629,11 +2598,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())
@@ -2946,46 +2914,37 @@ void process_agent_movement_complete(LLMessageSystem* msg, void**)
if (!gLastVersionChannel.empty())
{
- LLSD payload;
- payload["message"] = version_channel;
- LLNotifications::instance().add("ServerVersionChanged", LLSD(), payload, server_version_changed_callback);
- }
-
- gLastVersionChannel = version_channel;
-}
-
-bool server_version_changed_callback(const LLSD& notification, const LLSD& response)
-{
- if(notification["payload"]["message"].asString() =="")
- return false;
- std::string url ="http://wiki.secondlife.com/wiki/Release_Notes/";
- //parse the msg string
- std::string server_version = notification["payload"]["message"].asString();
- 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))
+ // 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() - 2))
+ if (i != (s_vect.size() - 1))
{
- url += s_vect[i] + "_";
+ if(i != (s_vect.size() - 2))
+ {
+ url += s_vect[i] + "_";
+ }
+ else
+ {
+ url += s_vect[i] + "/";
+ }
}
else
{
- url += s_vect[i] + "/";
+ url += s_vect[i].substr(0,4);
}
}
- else
- {
- url += s_vect[i].substr(0,4);
- }
+
+ LLSD args;
+ args["URL"] = url;
+ LLNotifications::instance().add("ServerVersionChanged", args);
}
-
- LLWeb::loadURL(url);
- return false;
-}
+ gLastVersionChannel = version_channel;
+}
void process_crossed_region(LLMessageSystem* msg, void**)
{
@@ -4851,7 +4810,7 @@ void container_inventory_arrived(LLViewerObject* object,
// create a new inventory category to put this in
LLUUID cat_id;
cat_id = gInventory.createNewCategory(gInventory.getRootFolderID(),
- LLAssetType::AT_NONE,
+ LLFolderType::FT_NONE,
LLTrans::getString("AcquiredItems"));
InventoryObjectList::const_iterator it = inventory->begin();
@@ -4901,7 +4860,7 @@ void container_inventory_arrived(LLViewerObject* object,
}
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();
@@ -5581,7 +5540,7 @@ void process_covenant_reply(LLMessageSystem* msg, void**)
LLPanelLandCovenant::updateEstateOwnerName(owner_name);
LLFloaterBuyLand::updateEstateOwnerName(owner_name);
- LLPanelPlaceInfo* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceInfo>("panel_place_info");
+ LLPanelPlaceProfile* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceProfile>("panel_place_profile");
if (panel)
{
panel->updateEstateName(estate_name);
@@ -5715,7 +5674,7 @@ void onCovenantLoadComplete(LLVFS *vfs,
LLPanelLandCovenant::updateCovenantText(covenant_text);
LLFloaterBuyLand::updateCovenantText(covenant_text, asset_uuid);
- LLPanelPlaceInfo* panel = dynamic_cast<LLPanelPlaceInfo*>(LLSideTray::getInstance()->showPanel("panel_place_info", LLSD()));
+ LLPanelPlaceProfile* panel = LLSideTray::getInstance()->findChild<LLPanelPlaceProfile>("panel_place_profile");
if (panel)
{
panel->updateCovenantText(covenant_text);
diff --git a/indra/newview/llviewermessage.h b/indra/newview/llviewermessage.h
index c15e5df675..e24da2013d 100644
--- a/indra/newview/llviewermessage.h
+++ b/indra/newview/llviewermessage.h
@@ -132,7 +132,6 @@ void container_inventory_arrived(LLViewerObject* object,
// agent movement
void send_complete_agent_movement(const LLHost& sim_host);
void process_agent_movement_complete(LLMessageSystem* msg, void**);
-bool server_version_changed_callback(const LLSD& notification, const LLSD& response);
void process_crossed_region(LLMessageSystem* msg, void**);
void process_teleport_start(LLMessageSystem* msg, void**);
void process_teleport_progress(LLMessageSystem* msg, void**);
diff --git a/indra/newview/llviewernetwork.cpp b/indra/newview/llviewernetwork.cpp
index 918b15ef09..801c46035a 100644
--- a/indra/newview/llviewernetwork.cpp
+++ b/indra/newview/llviewernetwork.cpp
@@ -35,6 +35,8 @@
#include "llviewernetwork.h"
#include "llviewercontrol.h"
+#include "llevents.h"
+#include "lllogin.h"
struct LLGridData
{
@@ -155,6 +157,10 @@ LLViewerLogin::LLViewerLogin() :
{
}
+ LLViewerLogin::~LLViewerLogin()
+ {
+ }
+
void LLViewerLogin::setGridChoice(EGridInfo grid)
{
if(grid < 0 || grid >= GRID_INFO_COUNT)
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 1f4f1322fd..26411ce152 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -219,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)
{
@@ -2927,7 +2928,7 @@ void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */)
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID sculpt_id = sculpt_params->getSculptTexture();
- LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
+ LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
}
if (boost_children)
@@ -3690,7 +3691,7 @@ void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
// if (mDrawable.notNull() && mDrawable->isVisible())
// {
const LLUUID& image_id = getTE(te)->getID();
- mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
// }
}
@@ -3716,7 +3717,7 @@ S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost hos
uuid == LLUUID::null)
{
retval = LLPrimitive::setTETexture(te, uuid);
- mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
setChanged(TEXTURE);
if (mDrawable.notNull())
{
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index bec36f9da7..b8ae31118c 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -676,6 +676,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 acdc2c2513..2927ca5292 100644
--- a/indra/newview/llviewerobjectlist.cpp
+++ b/indra/newview/llviewerobjectlist.cpp
@@ -174,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 ;
}
@@ -200,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;
@@ -246,8 +266,8 @@ 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();
}
@@ -294,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
{
@@ -308,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;
}
@@ -318,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;
}
@@ -357,7 +377,6 @@ void LLViewerObjectList::processObjectUpdate(LLMessageSystem *mesgsys,
U8 compbuffer[2048];
S32 uncompressed_length = 2048;
S32 compressed_length;
-
compressed_dp.reset();
U32 flags = 0;
@@ -398,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++;
}
}
@@ -412,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++;
}
}
@@ -420,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)
@@ -441,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;
}
}
@@ -452,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;
}
@@ -462,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
@@ -475,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())
@@ -623,7 +652,7 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent)
mCurLazyUpdateIndex = 0;
}
- mCurBin = (++mCurBin) % NUM_BINS;
+ mCurBin = (mCurBin + 1) % NUM_BINS;
LLVOAvatar::cullAvatarsByPixelArea();
}
@@ -808,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())
@@ -1179,21 +1216,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);
+ }
}
}
}
diff --git a/indra/newview/llviewerparcelmedia.cpp b/indra/newview/llviewerparcelmedia.cpp
index a3f9c839a0..6233a337a6 100644
--- a/indra/newview/llviewerparcelmedia.cpp
+++ b/indra/newview/llviewerparcelmedia.cpp
@@ -226,11 +226,13 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
media_height,
media_auto_scale,
media_loop);
- sMediaImpl->navigateTo(media_url);
+ sMediaImpl->navigateTo(media_url, mime_type, true);
}
}
else
{
+ 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,
@@ -238,7 +240,7 @@ void LLViewerParcelMedia::play(LLParcel* parcel)
media_height,
media_auto_scale,
media_loop);
- sMediaImpl->navigateTo(media_url);
+ sMediaImpl->navigateTo(media_url, mime_type, true);
}
LLFirstUse::useMedia();
@@ -544,6 +546,18 @@ void LLViewerParcelMedia::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent
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;
};
}
diff --git a/indra/newview/llviewerparcelmgr.cpp b/indra/newview/llviewerparcelmgr.cpp
index 7ca11d8364..aa0987aa7d 100644
--- a/indra/newview/llviewerparcelmgr.cpp
+++ b/indra/newview/llviewerparcelmgr.cpp
@@ -56,6 +56,7 @@
#include "llparcelselection.h"
#include "llresmgr.h"
#include "llsdutil.h"
+#include "llsdutil_math.h"
#include "llstatusbar.h"
#include "llui.h"
#include "llviewertexture.h"
@@ -842,8 +843,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);
+ }
}
}
@@ -1161,10 +1165,11 @@ 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)
diff --git a/indra/newview/llviewerparcelmgr.h b/indra/newview/llviewerparcelmgr.h
index 3964a56bf6..1c8fe23dba 100644
--- a/indra/newview/llviewerparcelmgr.h
+++ b/indra/newview/llviewerparcelmgr.h
@@ -246,7 +246,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);
diff --git a/indra/newview/llviewerprecompiledheaders.h b/indra/newview/llviewerprecompiledheaders.h
index 21d4c72428..bb317aeb5f 100644
--- a/indra/newview/llviewerprecompiledheaders.h
+++ b/indra/newview/llviewerprecompiledheaders.h
@@ -105,7 +105,6 @@
#include "llstl.h"
#include "llstrider.h"
#include "llstring.h"
-#include "llstringtable.h"
#include "llsys.h"
#include "llthread.h"
#include "lltimer.h"
diff --git a/indra/newview/llviewerstats.cpp b/indra/newview/llviewerstats.cpp
index 994fbd8475..6e07d8f246 100644
--- a/indra/newview/llviewerstats.cpp
+++ b/indra/newview/llviewerstats.cpp
@@ -52,7 +52,6 @@
#include "llvlmanager.h"
#include "llagent.h"
#include "llviewercontrol.h"
-#include "llfloaterdirectory.h"
#include "llfloatertools.h"
#include "lldebugview.h"
#include "llfasttimerview.h"
@@ -813,8 +812,6 @@ void send_stats()
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
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 0ce1ecc6ee..6f8818be6e 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -44,6 +44,9 @@
#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"
@@ -59,15 +62,53 @@
#include "lltooltip.h"
#include "lltrans.h"
#include "lluictrlfactory.h"
+#include "llviewerassettype.h"
#include "llviewercontrol.h"
#include "llviewerinventory.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:
+
+ 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
///----------------------------------------------------------------------------
@@ -130,22 +171,41 @@ public:
mToolTip = inv_item->getName() + '\n' + inv_item->getDescription();
}
- /*virtual*/ S32 getWidth(S32 first_char, S32 num_chars) const
+ /*virtual*/ bool getDimensions(S32 first_char, S32 num_chars, S32& width, S32& height) const
{
if (num_chars == 0)
{
- return 0;
+ width = 0;
+ height = 0;
}
else
{
- return EMBEDDED_ITEM_LABEL_PADDING + mImage->getWidth() + mStyle->getFont()->getWidth(mLabel.c_str());
+ 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
{
- return 1;
+ // 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)
{
@@ -165,14 +225,10 @@ public:
}
F32 right_x;
- mStyle->getFont()->render(mLabel, 0, image_rect.mRight + EMBEDDED_ITEM_LABEL_PADDING, draw_rect.mBottom, color, LLFontGL::LEFT, LLFontGL::BOTTOM, LLFontGL::UNDERLINE, LLFontGL::NO_SHADOW, mLabel.length(), S32_MAX, &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*/ S32 getMaxHeight() const
- {
- return llmax(mImage->getHeight(), llceil(mStyle->getFont()->getLineHeight()));
- }
/*virtual*/ bool canEdit() const { return false; }
@@ -467,19 +523,17 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const
}
break;
- case LLAssetType::AT_SOUND: img_name = "Inv_Sound"; 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_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_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;
- //TODO need img_name
- case LLAssetType::AT_FAVORITE: img_name = "Inv_Landmark"; break;
- default: llassert(0);
+ 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);
}
return LLUI::getUIImage(img_name);
@@ -694,11 +748,10 @@ BOOL LLViewerTextEditor::handleHover(S32 x, S32 y, MASK mask)
if( LLToolDragAndDrop::getInstance()->isOverThreshold( screen_x, screen_y ) )
{
LLToolDragAndDrop::getInstance()->beginDrag(
- LLAssetType::lookupDragAndDropType( mDragItem->getType() ),
+ LLViewerAssetType::lookupDragAndDropType( mDragItem->getType() ),
mDragItem->getUUID(),
LLToolDragAndDrop::SOURCE_NOTECARD,
mPreviewID, mObjectID);
-
return LLToolDragAndDrop::getInstance()->handleHover( x, y, mask );
}
getWindow()->setCursor(UI_CURSOR_HAND);
@@ -1101,14 +1154,12 @@ void LLViewerTextEditor::openEmbeddedLandmark( LLInventoryItem* item, llwchar wc
if (!item)
return;
- LLSD key;
- key["type"] = "landmark";
- key["id"] = item->getUUID();
-
- LLPanelPlaces *panel = dynamic_cast<LLPanelPlaces*>(LLSideTray::getInstance()->showPanel("panel_places", key));
- if (panel)
+ LLLandmark* landmark = gLandmarkList.getAsset(item->getAssetUUID(),
+ boost::bind(&LLEmbeddedLandmarkCopied::processForeignLandmark, _1, mObjectID, mNotecardInventoryID, item));
+ if (landmark)
{
- panel->setItem(item);
+ LLEmbeddedLandmarkCopied::processForeignLandmark(landmark, mObjectID,
+ mNotecardInventoryID, item);
}
}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index a0ab4cb1e6..6b8c8c01d4 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -93,6 +93,7 @@ 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
@@ -134,7 +135,7 @@ LLViewerMediaTexture* LLViewerTextureManager::getMediaTexture(const LLUUID& id,
return tex ;
}
-LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error)
+LLViewerFetchedTexture* LLViewerTextureManager::staticCastToFetchedTexture(LLTexture* tex, BOOL report_error)
{
if(!tex)
{
@@ -191,25 +192,27 @@ LLPointer<LLViewerTexture> LLViewerTextureManager::getLocalTexture(const U32 wid
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTexture(
const LLUUID &image_id,
BOOL usemipmaps,
- BOOL level_immediate,
+ S32 boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
LLHost request_from_host)
{
- return gTextureList.getImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ;
+ llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ;
+ 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,
- BOOL level_immediate,
+ S32 boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
const LLUUID& force_id)
{
- return gTextureList.getImageFromFile(filename, usemipmaps, level_immediate, texture_type, internal_format, primary_format, force_id) ;
+ llassert_always(boost_priority >= LLViewerTexture::BOOST_NONE) ;
+ return gTextureList.getImageFromFile(filename, usemipmaps, boost_priority, texture_type, internal_format, primary_format, force_id) ;
}
LLViewerFetchedTexture* LLViewerTextureManager::getFetchedTextureFromHost(const LLUUID& image_id, LLHost host)
@@ -255,10 +258,10 @@ void LLViewerTextureManager::init()
image_raw = NULL;
LLViewerFetchedTexture::sDefaultImagep->dontDiscard();
#else
- LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
+ LLViewerFetchedTexture::sDefaultImagep = LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
#endif
- LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, TRUE);
+ LLViewerFetchedTexture::sSmokeImagep = LLViewerTextureManager::getFetchedTexture(IMG_SMOKE, TRUE, LLViewerTexture::BOOST_UI);
LLViewerFetchedTexture::sSmokeImagep->setNoDelete() ;
LLViewerTexture::initClass() ;
@@ -415,6 +418,7 @@ void LLViewerTexture::init(bool firstinit)
mDontDiscard = FALSE;
mMaxVirtualSize = 0.f;
mNeedsResetMaxVirtualSize = FALSE ;
+ mParcelMedia = NULL ;
}
//virtual
@@ -522,6 +526,12 @@ F32 LLViewerTexture::getMaxVirtualSize()
return mMaxVirtualSize ;
}
+//virtual
+void LLViewerTexture::setKnownDrawSize(S32 width, S32 height)
+{
+ //nothing here.
+}
+
//virtual
void LLViewerTexture::addFace(LLFace* facep)
{
@@ -852,6 +862,7 @@ void LLViewerFetchedTexture::init(bool firstinit)
mKnownDrawWidth = 0;
mKnownDrawHeight = 0;
+ mKnownDrawSizeChanged = FALSE ;
if (firstinit)
{
@@ -1084,10 +1095,17 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
}
// Call with 0,0 to turn this feature off.
+//virtual
void LLViewerFetchedTexture::setKnownDrawSize(S32 width, S32 height)
{
- mKnownDrawWidth = width;
- mKnownDrawHeight = height;
+ if(mKnownDrawWidth != width || mKnownDrawHeight != height)
+ {
+ mKnownDrawWidth = width;
+ mKnownDrawHeight = height;
+
+ mKnownDrawSizeChanged = TRUE ;
+ mFullyLoaded = FALSE ;
+ }
addTextureStats((F32)(width * height));
}
@@ -1104,13 +1122,26 @@ void LLViewerFetchedTexture::processTextureStats()
mDesiredDiscardLevel = getMaxDiscardLevel() ;
}
else
- {
- mDesiredDiscardLevel = 0;
- if (mFullWidth > MAX_IMAGE_SIZE_DEFAULT || mFullHeight > MAX_IMAGE_SIZE_DEFAULT)
+ {
+ if(!mKnownDrawWidth || !mKnownDrawHeight || mFullWidth <= mKnownDrawWidth || mFullHeight <= mKnownDrawHeight)
{
- mDesiredDiscardLevel = 1; // MAX_IMAGE_SIZE_DEFAULT = 1024 and max size ever is 2048
+ 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 ;
@@ -1121,8 +1152,6 @@ void LLViewerFetchedTexture::processTextureStats()
//texture does not have any data, so we don't know the size of the image, treat it like 32 * 32.
F32 LLViewerFetchedTexture::calcDecodePriorityForUnknownTexture(F32 pixel_priority)
{
- 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 + 1;
ddiscard = llclamp(ddiscard, 1, 9);
@@ -1169,7 +1198,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
// Don't decode anything we don't need
priority = -1.0f;
}
- else if (mBoostLevel == LLViewerTexture::BOOST_UI && !have_all_data)
+ else if ((mBoostLevel == LLViewerTexture::BOOST_UI || mBoostLevel == LLViewerTexture::BOOST_ICON) && !have_all_data)
{
priority = 1.f;
}
@@ -1213,7 +1242,7 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
{
ddiscard+=2;
}
- else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == 0)
+ else if (mGLTexturep.notNull() && !mGLTexturep->getBoundRecently() && mBoostLevel == LLViewerTexture::BOOST_NONE)
{
ddiscard-=2;
}
@@ -1225,11 +1254,11 @@ F32 LLViewerFetchedTexture::calcDecodePriority()
pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); // priority range = 100000-900000
if ( mBoostLevel > BOOST_HIGH)
{
- priority = 1000000.f + pixel_priority + 1000.f * mBoostLevel;
+ priority = 1000000.f + pixel_priority + 1000.f * (mBoostLevel - LLViewerTexture::BOOST_NONE);
}
else
{
- priority += 0.f + pixel_priority + 1000.f * mBoostLevel;
+ priority += 0.f + pixel_priority + 1000.f * (mBoostLevel - LLViewerTexture::BOOST_NONE);
}
}
return priority;
@@ -1409,7 +1438,7 @@ bool LLViewerFetchedTexture::updateFetch()
}
if (!mDontDiscard)
{
- if (mBoostLevel == 0)
+ if (mBoostLevel == LLViewerTexture::BOOST_NONE)
{
desired_discard = llmax(desired_discard, current_discard-1);
}
@@ -2121,22 +2150,29 @@ void LLViewerMediaTexture::updateClass()
{
static const F32 MAX_INACTIVE_TIME = 30.f ;
+#if 0
+ //force to play media.
+ gSavedSettings.setBOOL("AudioSteamingMedia", true) ;
+ gSavedSettings.setBOOL("AudioStreamingVideo", true) ;
+#endif
+
for(media_map_t::iterator iter = sMediaMap.begin() ; iter != sMediaMap.end(); )
{
LLViewerMediaTexture* mediap = iter->second;
-
- //
- //Note: delay some time to delete the media textures to stop endlessly creating and immediately removing media texture.
- //
- if(mediap->getNumRefs() == 1 && mediap->getLastReferencedTimer()->getElapsedTimeF32() > MAX_INACTIVE_TIME) //one by sMediaMap
- {
- media_map_t::iterator cur = iter++ ;
- sMediaMap.erase(cur) ;
- }
- else
+
+ if(mediap->getNumRefs() == 1) //one reference by sMediaMap
{
- ++iter ;
+ //
+ //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 ;
}
}
@@ -2189,11 +2225,22 @@ LLViewerMediaTexture::LLViewerMediaTexture(const LLUUID& id, BOOL usemipmaps, LL
mIsPlaying = FALSE ;
setMediaImpl() ;
+
+ 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 */)
@@ -2244,10 +2291,9 @@ BOOL LLViewerMediaTexture::findFaces()
mMediaFaceList.clear() ;
BOOL ret = TRUE ;
-
- //for parcel media
- LLViewerTexture* tex = gTextureList.findImage(mID) ;
- if(tex)
+
+ LLViewerTexture* tex = gTextureList.findImage(mID) ;
+ if(tex) //this media is a parcel media for tex.
{
const ll_face_list_t* face_list = tex->getFaceList() ;
for(ll_face_list_t::const_iterator iter = face_list->begin(); iter != face_list->end(); ++iter)
@@ -2358,7 +2404,7 @@ void LLViewerMediaTexture::addFace(LLFace* facep)
mTextureList.push_back(facep->getTexture()) ; //a parcel media.
return ;
}
-
+
llerrs << "The face does not have a valid texture before media texture." << llendl ;
}
@@ -2434,10 +2480,11 @@ void LLViewerMediaTexture::removeFace(LLFace* facep)
void LLViewerMediaTexture::stopPlaying()
{
- if(mMediaImplp)
- {
- mMediaImplp->stop() ;
- }
+ // 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 ;
}
diff --git a/indra/newview/llviewertexture.h b/indra/newview/llviewertexture.h
index 596bfea670..ff8f14e879 100644
--- a/indra/newview/llviewertexture.h
+++ b/indra/newview/llviewertexture.h
@@ -107,21 +107,22 @@ public:
enum EBoostLevel
{
- BOOST_NONE = 0,
- BOOST_AVATAR_BAKED = 1,
- BOOST_AVATAR = 2,
- BOOST_CLOUDS = 3,
- BOOST_SCULPTED = 4,
+ //skip 0 and 1 to avoid mistakenly mixing boost level with boolean numbers.
+ BOOST_NONE = 2,
+ BOOST_AVATAR_BAKED = 3,
+ BOOST_AVATAR = 4,
+ BOOST_CLOUDS = 5,
+ BOOST_SCULPTED = 6,
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_UI = 15,
- BOOST_PREVIEW = 16,
- BOOST_MAP = 17,
- BOOST_MAP_LAYER = 18,
+ BOOST_ICON = 15,
+ BOOST_UI = 16,
+ BOOST_PREVIEW = 17,
+ BOOST_MAP = 18,
BOOST_AVATAR_SELF = 19, // needed for baking avatar
BOOST_MAX_LEVEL
};
@@ -163,6 +164,7 @@ public:
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) ;
@@ -220,6 +222,10 @@ public:
BOOL getDontDiscard() const { return mDontDiscard; }
//-----------------
+ void setParcelMedia(LLViewerMediaTexture* media) {mParcelMedia = media;}
+ BOOL hasParcelMedia() const { return mParcelMedia != NULL;}
+ LLViewerMediaTexture* getParcelMedia() const { return mParcelMedia;}
+
/*virtual*/ void updateBindStatsForTester() ;
protected:
void cleanup() ;
@@ -246,6 +252,9 @@ protected:
LLPointer<LLImageGL> mGLTexturep ;
S8 mDontDiscard; // Keep full res version of this image (for UI, etc)
+ //do not use LLPointer here.
+ LLViewerMediaTexture* mParcelMedia ;
+
protected:
typedef enum
{
@@ -357,7 +366,7 @@ public:
// 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.
- void setKnownDrawSize(S32 width, S32 height);
+ /*virtual*/ void setKnownDrawSize(S32 width, S32 height);
void setIsMissingAsset();
/*virtual*/ BOOL isMissingAsset() const { return mIsMissingAsset; }
@@ -406,6 +415,8 @@ private:
BOOL mFullyLoaded;
protected:
+ std::string mLocalFileName;
+
S32 mOrigWidth;
S32 mOrigHeight;
@@ -413,8 +424,7 @@ protected:
// Used for UI textures to not decode, even if we have more data.
S32 mKnownDrawWidth;
S32 mKnownDrawHeight;
-
- std::string mLocalFileName;
+ BOOL mKnownDrawSizeChanged ;
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
@@ -570,7 +580,7 @@ public:
static LLTexturePipelineTester* sTesterp ;
//returns NULL if tex is not a LLViewerFetchedTexture nor derived from LLViewerFetchedTexture.
- static LLViewerFetchedTexture* staticCastToFetchedTexture(LLViewerTexture* tex, BOOL report_error = FALSE) ;
+ static LLViewerFetchedTexture* staticCastToFetchedTexture(LLTexture* tex, BOOL report_error = FALSE) ;
//
//"find-texture" just check if the texture exists, if yes, return it, otherwise return null.
@@ -592,7 +602,7 @@ public:
static LLViewerFetchedTexture* getFetchedTexture(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ S32 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,
@@ -601,7 +611,7 @@ public:
static LLViewerFetchedTexture* getFetchedTextureFromFile(const std::string& filename,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ S32 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,
diff --git a/indra/newview/llviewertexturelist.cpp b/indra/newview/llviewertexturelist.cpp
index dac2331ca3..d2be1ac9b5 100644
--- a/indra/newview/llviewertexturelist.cpp
+++ b/indra/newview/llviewertexturelist.cpp
@@ -111,10 +111,10 @@ void LLViewerTextureList::doPreloadImages()
LL_DEBUGS("ViewerImages") << "Preloading images..." << LL_ENDL;
// Set the "missing asset" image
- LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, IMMEDIATE_YES);
+ LLViewerFetchedTexture::sMissingAssetImagep = LLViewerTextureManager::getFetchedTextureFromFile("missing_asset.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
// Set the "white" image
- LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, IMMEDIATE_YES);
+ LLViewerFetchedTexture::sWhiteImagep = LLViewerTextureManager::getFetchedTextureFromFile("white.tga", MIPMAP_NO, LLViewerFetchedTexture::BOOST_UI);
LLUIImageList* image_list = LLUIImageList::getInstance();
@@ -131,31 +131,31 @@ void LLViewerTextureList::doPreloadImages()
// prefetch specific UUIDs
LLViewerTextureManager::getFetchedTexture(IMG_SHOT, TRUE);
LLViewerTextureManager::getFetchedTexture(IMG_SMOKE_POOF, TRUE);
- LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTextureFromFile("silhouette.j2c", MIPMAP_YES, IMMEDIATE_YES);
+ 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, IMMEDIATE_YES);
+ 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, IMMEDIATE_YES);
+ 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, IMMEDIATE_YES);
+ 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, IMMEDIATE_YES, LLViewerTexture::FETCHED_TEXTURE,
+ image = LLViewerTextureManager::getFetchedTextureFromFile("transparent.j2c", MIPMAP_YES, LLViewerFetchedTexture::BOOST_UI, LLViewerTexture::FETCHED_TEXTURE,
0,0,LLUUID("8dcd4a48-2d37-4909-9f78-f7a9eb4ef903"));
if (image)
{
@@ -197,7 +197,7 @@ void LLViewerTextureList::doPrefetchImages()
if(LLViewerTexture::FETCHED_TEXTURE == texture_type || LLViewerTexture::LOD_TEXTURE == texture_type)
{
- LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, FALSE, texture_type);
+ LLViewerFetchedTexture* image = LLViewerTextureManager::getFetchedTexture(uuid, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, texture_type);
if (image)
{
image->addTextureStats((F32)pixel_area);
@@ -315,7 +315,7 @@ void LLViewerTextureList::restoreGL()
LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string& filename,
BOOL usemipmaps,
- BOOL level_immediate,
+ S32 boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -325,14 +325,14 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
{
// Never mind that this ignores image_set_id;
// getImage() will handle that later.
- return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE);
+ return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
}
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, TRUE);
+ return LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI);
}
// generate UUID based on hash of filename
@@ -369,10 +369,14 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
addImage(imagep);
- if (level_immediate)
+ if (boost_priority != 0)
{
- imagep->dontDiscard();
- imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
+ if (boost_priority == LLViewerFetchedTexture::BOOST_UI ||
+ boost_priority == LLViewerFetchedTexture::BOOST_ICON)
+ {
+ imagep->dontDiscard();
+ }
+ imagep->setBoostLevel(boost_priority);
}
}
@@ -384,7 +388,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImageFromFile(const std::string&
LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
BOOL usemipmaps,
- BOOL level_immediate,
+ S32 boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -396,14 +400,14 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
if ((&image_id == NULL) || image_id.isNull())
{
- return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, TRUE));
+ return (LLViewerTextureManager::getFetchedTexture(IMG_DEFAULT, TRUE, LLViewerTexture::BOOST_UI));
}
LLPointer<LLViewerFetchedTexture> imagep = findImage(image_id);
if (imagep.isNull())
{
- imagep = createImage(image_id, usemipmaps, level_immediate, texture_type, internal_format, primary_format, request_from_host) ;
+ imagep = createImage(image_id, usemipmaps, boost_priority, texture_type, internal_format, primary_format, request_from_host) ;
}
imagep->setGLTextureCreated(true);
@@ -414,7 +418,7 @@ LLViewerFetchedTexture* LLViewerTextureList::getImage(const LLUUID &image_id,
//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,
- BOOL level_immediate,
+ S32 boost_priority,
S8 texture_type,
LLGLint internal_format,
LLGLenum primary_format,
@@ -443,16 +447,20 @@ LLViewerFetchedTexture* LLViewerTextureList::createImage(const LLUUID &image_id,
addImage(imagep);
- if (level_immediate)
+ if (boost_priority != 0)
{
- imagep->dontDiscard();
- imagep->setBoostLevel(LLViewerFetchedTexture::BOOST_UI);
+ 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, either pass level_immediate == TRUE here, or call setNoDelete() afterwards.
+ //if this texture should be set to NO_DELETE, call setNoDelete() afterwards.
imagep->forceActive() ;
}
@@ -1163,7 +1171,7 @@ void LLViewerTextureList::receiveImageHeader(LLMessageSystem *msg, void **user_d
U8 *data = new U8[data_size];
msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
- LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (!image)
{
delete [] data;
@@ -1227,7 +1235,7 @@ void LLViewerTextureList::receiveImagePacket(LLMessageSystem *msg, void **user_d
U8 *data = new U8[data_size];
msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size);
- LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ LLViewerFetchedTexture *image = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (!image)
{
delete [] data;
@@ -1286,7 +1294,7 @@ void LLUIImageList::cleanUp()
mUITextureList.clear() ;
}
-LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id)
+LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id, S32 priority)
{
// use id as image name
std::string image_name = image_id.asString();
@@ -1298,10 +1306,12 @@ LLUIImagePtr LLUIImageList::getUIImageByID(const LLUUID& image_id)
return found_it->second;
}
- return loadUIImageByID(image_id);
+ const BOOL use_mips = FALSE;
+ const LLRect scale_rect = LLRect::null;
+ return loadUIImageByID(image_id, use_mips, scale_rect, priority);
}
-LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name)
+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);
@@ -1310,18 +1320,24 @@ LLUIImagePtr LLUIImageList::getUIImage(const std::string& image_name)
return found_it->second;
}
- return loadUIImageByName(image_name, image_name);
+ const BOOL use_mips = FALSE;
+ const LLRect scale_rect = LLRect::null;
+ return loadUIImageByName(image_name, image_name, use_mips, scale_rect, priority);
}
-LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename, BOOL use_mips, const LLRect& scale_rect)
+LLUIImagePtr LLUIImageList::loadUIImageByName(const std::string& name, const std::string& filename,
+ BOOL use_mips, const LLRect& scale_rect, S32 boost_priority )
{
- LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTextureFromFile(filename, MIPMAP_NO, IMMEDIATE_YES);
+ if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::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)
+LLUIImagePtr LLUIImageList::loadUIImageByID(const LLUUID& id,
+ BOOL use_mips, const LLRect& scale_rect, S32 boost_priority)
{
- LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, IMMEDIATE_YES);
+ if (boost_priority == 0) boost_priority = LLViewerFetchedTexture::BOOST_UI;
+ LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(id, MIPMAP_NO, boost_priority);
return loadUIImage(imagep, id.asString(), use_mips, scale_rect);
}
@@ -1332,11 +1348,11 @@ LLUIImagePtr LLUIImageList::loadUIImage(LLViewerFetchedTexture* imagep, const st
imagep->setAddressMode(LLTexUnit::TAM_CLAMP);
//all UI images are non-deletable
- imagep->setNoDelete() ;
+ imagep->setNoDelete();
LLUIImagePtr new_imagep = new LLUIImage(name, imagep);
mUIImages.insert(std::make_pair(name, new_imagep));
- mUITextureList.push_back(imagep) ;
+ mUITextureList.push_back(imagep);
LLUIImageLoadData* datap = new LLUIImageLoadData;
datap->mImageName = name;
@@ -1474,7 +1490,7 @@ bool LLUIImageList::initFromFile()
}
UIImageDeclarations images;
- LLXUIParser::instance().readXUI(root, images);
+ LLXUIParser::instance().readXUI(root, images, base_file_path);
if (!images.validateBlock()) return false;
diff --git a/indra/newview/llviewertexturelist.h b/indra/newview/llviewertexturelist.h
index 11d1dd855f..6948db70f8 100644
--- a/indra/newview/llviewertexturelist.h
+++ b/indra/newview/llviewertexturelist.h
@@ -131,7 +131,7 @@ private:
LLViewerFetchedTexture * getImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ S32 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,
@@ -140,7 +140,7 @@ private:
LLViewerFetchedTexture * getImageFromFile(const std::string& filename,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ S32 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,
@@ -149,7 +149,7 @@ private:
LLViewerFetchedTexture* createImage(const LLUUID &image_id,
BOOL usemipmap = TRUE,
- BOOL level_immediate = FALSE, // Get the requested level immediately upon creation.
+ S32 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,
@@ -159,7 +159,7 @@ private:
// 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, FALSE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
+ { return getImage(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); }
public:
typedef std::set<LLPointer<LLViewerFetchedTexture> > image_list_t;
@@ -202,8 +202,8 @@ class LLUIImageList : public LLImageProviderInterface, public LLSingleton<LLUIIm
{
public:
// LLImageProviderInterface
- LLUIImagePtr getUIImageByID(const LLUUID& id);
- LLUIImagePtr getUIImage(const std::string& name);
+ /*virtual*/ LLUIImagePtr getUIImageByID(const LLUUID& id, S32 priority);
+ /*virtual*/ LLUIImagePtr getUIImage(const std::string& name, S32 priority);
void cleanUp();
bool initFromFile();
@@ -212,8 +212,10 @@ public:
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);
- LLUIImagePtr loadUIImageByID(const LLUUID& id, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
+ LLUIImagePtr loadUIImageByName(const std::string& name, const std::string& filename,
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
+ LLUIImagePtr loadUIImageByID(const LLUUID& id,
+ BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null, S32 boost_priority = 0);
LLUIImagePtr loadUIImage(LLViewerFetchedTexture* imagep, const std::string& name, BOOL use_mips = FALSE, const LLRect& scale_rect = LLRect::null);
diff --git a/indra/newview/llviewervisualparam.cpp b/indra/newview/llviewervisualparam.cpp
index 7d717ed6dc..b088ef0730 100644
--- a/indra/newview/llviewervisualparam.cpp
+++ b/indra/newview/llviewervisualparam.cpp
@@ -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()
//-----------------------------------------------------------------------------
diff --git a/indra/newview/llviewervisualparam.h b/indra/newview/llviewervisualparam.h
index 77a95db564..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);
@@ -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 fc6467ea23..9b3dbcd2f6 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -32,6 +32,10 @@
#include "llviewerprecompiledheaders.h"
+#if LL_WINDOWS
+#pragma warning (disable : 4355) // 'this' used in initializer list: yes, intentionally
+#endif
+
// system library includes
#include <stdio.h>
#include <iostream>
@@ -138,7 +142,6 @@
#include "llstatview.h"
#include "llsurface.h"
#include "llsurfacepatch.h"
-#include "llimview.h"
#include "lltexlayer.h"
#include "lltextbox.h"
#include "lltexturecache.h"
@@ -195,6 +198,7 @@
#include "llfloaternotificationsconsole.h"
#include "llnearbychat.h"
+#include "llviewerwindowlistener.h"
#if LL_WINDOWS
#include <tchar.h> // For Unicode conversion methods
@@ -1204,7 +1208,8 @@ LLViewerWindow::LLViewerWindow(
mResDirty(false),
mStatesDirty(false),
mIsFullscreenChecked(false),
- mCurrResolutionIndex(0)
+ mCurrResolutionIndex(0),
+ mViewerWindowListener(new LLViewerWindowListener("LLViewerWindow", 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"));
@@ -1502,11 +1507,6 @@ void LLViewerWindow::initWorldUI()
// currently needs to happen before initializing chat or IM
LLFloaterReg::getInstance("communicate");
- if ( gSavedPerAccountSettings.getBOOL("LogShowHistory") )
- {
- LLFloaterChat::loadHistory();
- }
-
LLRect morph_view_rect = full_window;
morph_view_rect.stretch( -STATUS_BAR_HEIGHT );
morph_view_rect.mTop = full_window.mTop - 32;
@@ -1518,11 +1518,12 @@ void LLViewerWindow::initWorldUI()
getRootView()->addChild(gMorphView);
// Make space for nav bar.
+ LLNavigationBar* navbar = LLNavigationBar::getInstance();
LLRect floater_view_rect = gFloaterView->getRect();
LLRect notify_view_rect = gNotifyBoxView->getRect();
- floater_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+ floater_view_rect.mTop -= navbar->getDefNavBarHeight();
floater_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
- notify_view_rect.mTop -= NAVIGATION_BAR_HEIGHT;
+ notify_view_rect.mTop -= navbar->getDefNavBarHeight();
notify_view_rect.mBottom += LLBottomTray::getInstance()->getRect().getHeight();
gFloaterView->setRect(floater_view_rect);
gNotifyBoxView->setRect(notify_view_rect);
@@ -1549,20 +1550,19 @@ void LLViewerWindow::initWorldUI()
gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor().get() );
// Navigation bar
-
- LLNavigationBar* navbar = LLNavigationBar::getInstance();
navbar->reshape(root_rect.getWidth(), navbar->getRect().getHeight(), TRUE); // *TODO: redundant?
navbar->translate(0, root_rect.getHeight() - menu_bar_height - navbar->getRect().getHeight()); // FIXME
navbar->setBackgroundColor(gMenuBarView->getBackgroundColor().get());
+
if (!gSavedSettings.getBOOL("ShowNavbarNavigationPanel"))
{
- navbar->showNavigationPanel(FALSE);
+ toggle_show_navigation_panel(LLSD(0));
}
if (!gSavedSettings.getBOOL("ShowNavbarFavoritesPanel"))
{
- navbar->showFavoritesPanel(FALSE);
+ toggle_show_favorites_panel(LLSD(0));
}
if (!gSavedSettings.getBOOL("ShowCameraButton"))
@@ -1632,6 +1632,14 @@ void LLViewerWindow::shutdownViews()
{
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;
@@ -2105,31 +2113,30 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask)
// arrow keys move avatar while chatting hack
if (chat_editor && chat_editor->hasFocus())
{
- if (chat_editor->getText().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 )
+ 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_DOWN:
- // let CTRL DOWN through for chat line history
- if( MASK_CONTROL == mask )
- {
- 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;
}
}
}
@@ -2298,7 +2305,9 @@ void LLViewerWindow::handleScrollWheel(S32 clicks)
}
// Zoom the camera in and out behavior
- gAgent.handleScrollWheel(clicks);
+
+ if(top_ctrl == 0 && mWorldViewRect.pointInRect(mCurrentMousePoint.mX, mCurrentMousePoint.mY) )
+ gAgent.handleScrollWheel(clicks);
return;
}
@@ -2414,19 +2423,35 @@ void LLViewerWindow::updateUI()
BOOL handled_by_top_ctrl = FALSE;
LLUICtrl* top_ctrl = gFocusMgr.getTopCtrl();
LLMouseHandler* mouse_captor = gFocusMgr.getMouseCapture();
+ LLView* captor_view = dynamic_cast<LLView*>(mouse_captor);
+
+ //FIXME: only include captor and captor's ancestors if mouse is truly over them --RN
//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;
- // start at current mouse captor (if is a view) or UI root
- LLView* root_view = NULL;
- root_view = dynamic_cast<LLView*>(mouse_captor);
+ // 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)
{
root_view = mRootView;
}
+ // include all ancestors of captor_view as automatically having mouse
+ if (captor_view)
+ {
+ 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();
+ }
+ }
+
// 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
@@ -2605,8 +2630,24 @@ void LLViewerWindow::updateUI()
{
it.skipDescendants();
}
- else if (viewp->getMouseOpaque())
+ // 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 != gNotifyBoxView
+ && 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, tool_tip_msg);
@@ -4157,8 +4198,9 @@ void LLViewerWindow::drawMouselookInstructions()
instructions, 0,
getVirtualWorldViewRect().getCenterX(),
getVirtualWorldViewRect().mBottom + INSTRUCTIONS_PAD,
- LLColor4( 0.0f, 0.0f, 0.0f, 0.6f ),
- LLFontGL::HCENTER, LLFontGL::TOP);
+ LLColor4( 1.0f, 1.0f, 1.0f, 0.5f ),
+ LLFontGL::HCENTER, LLFontGL::TOP,
+ LLFontGL::NORMAL,LLFontGL::DROP_SHADOW);
}
S32 LLViewerWindow::getWindowHeight() const
diff --git a/indra/newview/llviewerwindow.h b/indra/newview/llviewerwindow.h
index 231b857d1f..d7c403739e 100644
--- a/indra/newview/llviewerwindow.h
+++ b/indra/newview/llviewerwindow.h
@@ -53,6 +53,8 @@
#include <boost/function.hpp>
#include <boost/signals2.hpp>
+#include <boost/scoped_ptr.hpp>
+
class LLView;
class LLViewerObject;
@@ -65,6 +67,7 @@ class LLImageRaw;
class LLHUDIcon;
class LLWindow;
class LLRootView;
+class LLViewerWindowListener;
#define PICK_HALF_WIDTH 5
#define PICK_DIAMETER (2 * PICK_HALF_WIDTH + 1)
@@ -456,6 +459,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;
diff --git a/indra/newview/llviewerwindowlistener.cpp b/indra/newview/llviewerwindowlistener.cpp
new file mode 100644
index 0000000000..317e361c80
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.cpp
@@ -0,0 +1,87 @@
+/**
+ * @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(const std::string& pumpname, LLViewerWindow* llviewerwindow):
+ LLDispatchListener(pumpname, "op"),
+ 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", &LLViewerWindowListener::saveSnapshot, saveSnapshotArgs);
+ add("requestReshape", &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->getWindowDisplayWidth());
+ S32 height(mViewerWindow->getWindowDisplayHeight());
+ 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..59c636ecec
--- /dev/null
+++ b/indra/newview/llviewerwindowlistener.h
@@ -0,0 +1,35 @@
+/**
+ * @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 "lleventdispatcher.h"
+
+class LLViewerWindow;
+class LLSD;
+
+/// Listen on an LLEventPump with specified name for LLViewerWindow request events.
+class LLViewerWindowListener: public LLDispatchListener
+{
+public:
+ /// Specify the pump name on which to listen, and bind the LLViewerWindow
+ /// instance to use (e.g. gViewerWindow).
+ LLViewerWindowListener(const std::string& pumpname, 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/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index 9437d8797e..acf1222455 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -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"
@@ -43,6 +49,7 @@
#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"
@@ -86,7 +93,12 @@
#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;
@@ -612,7 +624,7 @@ F32 LLVOAvatar::sGreyUpdateTime = 0.f;
// Helper functions
//-----------------------------------------------------------------------------
static F32 calc_bouncy_animation(F32 x);
-static U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures);
+static U32 calc_shame(const LLVOVolume* volume, std::set<LLUUID> &textures);
//-----------------------------------------------------------------------------
// LLVOAvatar()
@@ -677,7 +689,6 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id,
mBakedTextureDatas[i].mIsUsed = false;
mBakedTextureDatas[i].mMaskTexName = 0;
mBakedTextureDatas[i].mTextureIndex = LLVOAvatarDictionary::bakedToLocalTextureIndex((EBakedTextureIndex)i);
- mBakedTextureDatas[i].mMorphMasksValid = FALSE;
}
mDirtyMesh = TRUE; // Dirty geometry, need to regenerate.
@@ -781,7 +792,8 @@ LLVOAvatar::~LLVOAvatar()
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());
@@ -932,7 +944,7 @@ void LLVOAvatar::dumpBakedStatus()
for (LLVOAvatarDictionary::BakedTextures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::BakedEntry *baked_dict = iter->second;
const ETextureIndex index = baked_dict->mTextureIndex;
@@ -1124,7 +1136,7 @@ void LLVOAvatar::initInstance(void)
for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
+ ++iter)
{
const EMeshIndex mesh_index = iter->first;
const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
@@ -1170,7 +1182,7 @@ void LLVOAvatar::initInstance(void)
//-------------------------------------------------------------------------
for (LLVOAvatarDictionary::Meshes::const_iterator iter = LLVOAvatarDictionary::getInstance()->getMeshes().begin();
iter != LLVOAvatarDictionary::getInstance()->getMeshes().end();
- iter++)
+ ++iter)
{
const EMeshIndex mesh_index = iter->first;
const LLVOAvatarDictionary::MeshEntry *mesh_dict = iter->second;
@@ -1179,7 +1191,8 @@ void LLVOAvatar::initInstance(void)
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++)
+ iter != mMeshLOD[mesh_index]->mMeshParts.end();
+ ++iter)
{
LLViewerJointMesh* mesh = (LLViewerJointMesh*) *iter;
mBakedTextureDatas[(int)baked_texture_index].mMeshes.push_back(mesh);
@@ -1346,27 +1359,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]);
+ }
}
}
}
@@ -1560,7 +1578,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))
@@ -1603,7 +1621,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))
@@ -1666,11 +1684,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);
@@ -1815,7 +1833,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);
@@ -1834,10 +1853,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);
@@ -1860,10 +1879,10 @@ void LLVOAvatar::restoreMeshData()
updateJointLODs();
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(TRUE);
@@ -2312,34 +2331,39 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_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();
}
}
}
@@ -2360,7 +2384,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;
}
@@ -2423,28 +2447,20 @@ void LLVOAvatar::idleUpdateAppearanceAnimation()
}
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, mAppearanceAnimSetByUser);
+ }
}
}
@@ -2462,6 +2478,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
@@ -2521,7 +2556,7 @@ void LLVOAvatar::idleUpdateLoadingEffect()
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;
@@ -3533,19 +3568,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())
+ if (LLViewerObject *attached_object = (*attachment_iter))
{
- llinfos << attachment->getName() << " visible" << llendl;
- }
- else
- {
- 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;
+ }
}
}
}
@@ -3793,7 +3834,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 (getImage(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;
@@ -3954,7 +3995,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
{
if (layer_baked[i] && !mBakedTextureDatas[i].mIsLoaded)
{
- gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex ));
+ gGL.getTexUnit(0)->bind(getImage( mBakedTextureDatas[i].mTextureIndex, 0 ));
}
}
}
@@ -3962,17 +4003,32 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
mMaxPixelArea = 0.f;
mMinPixelArea = 99999999.f;
mHasGrey = FALSE; // debug
- for (U32 index = 0; index < getNumTEs(); index++)
+ for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++)
{
- LLViewerFetchedTexture *imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(index), TRUE);
- if (imagep)
+ 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++)
+ {
+ imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE);
+ if (imagep)
+ {
+ const LLVOAvatarDictionary::TextureEntry *texture_dict = LLVOAvatarDictionary::getInstance()->getTexture((ETextureIndex)texture_index);
+ const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex;
+ if (texture_dict->mIsLocalTexture)
+ {
+ addLocalTextureStats((ETextureIndex)texture_index, imagep, texel_area_ratio, render_avatar, layer_baked[baked_index]);
+ }
+ }
+ }
+ if (isIndexBakedTexture((ETextureIndex) texture_index))
{
- const LLTextureEntry *te = getTE(index);
- const F32 texel_area_ratio = fabs(te->mScaleS * te->mScaleT);
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())
{
@@ -3982,25 +4038,7 @@ void LLVOAvatar::updateTextures(LLAgent &agent)
<< " 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::TextureEntry *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 );
}
}
@@ -4033,13 +4071,13 @@ void LLVOAvatar::addBakedTextureStats( LLViewerFetchedTexture* imagep, F32 pixel
}
//virtual
-void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep)
+void LLVOAvatar::setImage(const U8 te, LLViewerTexture *imagep, const U32 index)
{
setTEImage(te, imagep);
}
//virtual
-LLViewerTexture* LLVOAvatar::getImage(const U8 te) const
+LLViewerTexture* LLVOAvatar::getImage(const U8 te, const U32 index) const
{
return getTEImage(te);
}
@@ -4707,7 +4745,7 @@ BOOL LLVOAvatar::loadAvatar()
// avatar_lad.xml : <morph_masks>
for (LLVOAvatarXmlInfo::morph_info_list_t::iterator iter = sAvatarXmlInfo->mMorphMaskInfoList.begin();
iter != sAvatarXmlInfo->mMorphMaskInfoList.end();
- iter++)
+ ++iter)
{
LLVOAvatarXmlInfo::LLVOAvatarMorphInfo *info = *iter;
@@ -4731,13 +4769,19 @@ BOOL LLVOAvatar::loadAvatar()
// avatar_lad.xml : <driver_parameters>
for (LLVOAvatarXmlInfo::driver_info_list_t::iterator iter = sAvatarXmlInfo->mDriverInfoList.begin();
iter != sAvatarXmlInfo->mDriverInfoList.end();
- iter++)
+ ++iter)
{
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))
+ {
+ llwarns << "could not link driven params for avatar " << this->getFullname() << " id: " << driver_param->getID() << llendl;
+ continue;
+ }
}
else
{
@@ -4746,6 +4790,19 @@ BOOL LLVOAvatar::loadAvatar()
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;
}
@@ -4758,7 +4815,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;
@@ -4794,7 +4852,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);
@@ -4814,7 +4873,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")
@@ -4895,7 +4955,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;
@@ -4911,7 +4971,7 @@ BOOL LLVOAvatar::loadMeshNodes()
mesh = &mHairMesh0; */
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::MeshEntry *mesh_dict = mesh_iter->second;
@@ -4983,7 +5043,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());
@@ -5017,7 +5077,7 @@ 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++)
+ ++layerset_iter)
{
// Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
LLTexLayerSetInfo *layerset_info = *layerset_iter;
@@ -5375,7 +5435,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)
@@ -5395,7 +5458,7 @@ LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* vi
//-----------------------------------------------------------------------------
// attachObject()
//-----------------------------------------------------------------------------
-LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
{
LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object);
@@ -5414,6 +5477,30 @@ LLViewerJointAttachment *LLVOAvatar::attachObject(LLViewerObject *viewer_object)
}
//-----------------------------------------------------------------------------
+// attachObject()
+//-----------------------------------------------------------------------------
+U32 LLVOAvatar::getNumAttachments() const
+{
+ U32 num_attachments = 0;
+ for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
+ iter != mAttachmentPoints.end();
+ ++iter)
+ {
+ const LLViewerJointAttachment *attachment_pt = (*iter).second;
+ num_attachments += attachment_pt->getNumObjects();
+ }
+ return num_attachments;
+}
+
+//-----------------------------------------------------------------------------
+// canAttachMoreObjects()
+//-----------------------------------------------------------------------------
+BOOL LLVOAvatar::canAttachMoreObjects() const
+{
+ return (getNumAttachments() < MAX_AGENT_ATTACHMENTS);
+}
+
+//-----------------------------------------------------------------------------
// lazyAttach()
//-----------------------------------------------------------------------------
void LLVOAvatar::lazyAttach()
@@ -5438,16 +5525,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);
+ }
}
}
}
@@ -5459,61 +5551,18 @@ 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 (isSelf())
- {
- // 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 (isSelf())
- {
- // Then 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::dumpCat(LLAppearanceManager::getCOF(),"Removing attachment link:");
- LLAppearanceManager::removeItemLinks(item_id, false);
-
- }
-
- // BAP - needs to change for label to track link.
- gInventory.addChangedMask(LLInventoryObserver::LABEL, item_id);
- gInventory.notifyObservers();
- }
return TRUE;
}
}
-
return FALSE;
}
@@ -5595,7 +5644,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;
@@ -5765,9 +5814,38 @@ BOOL LLVOAvatar::updateIsFullyLoaded()
loading = TRUE;
}
+ updateRuthTimer(loading);
return processFullyLoadedChange(loading);
}
+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,
@@ -5822,10 +5900,10 @@ void LLVOAvatar::updateMeshTextures()
// if user has never specified a texture, assign the default
for (U32 i=0; i < getNumTEs(); i++)
{
- const LLViewerTexture* te_image = getImage(i);
+ const LLViewerTexture* te_image = getImage(i, 0);
if(!te_image || te_image->getID().isNull() || (te_image->getID() == IMG_DEFAULT))
{
- setImage(i, LLViewerTextureManager::getFetchedTexture(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.
}
}
@@ -5888,7 +5966,7 @@ void LLVOAvatar::updateMeshTextures()
}
else if (!self_customizing && is_layer_baked[i])
{
- LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex ), TRUE) ;
+ 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).
@@ -5923,7 +6001,7 @@ void LLVOAvatar::updateMeshTextures()
if (!is_layer_baked[BAKED_HAIR] || self_customizing)
{
const LLColor4 color = mTexHairColor ? mTexHairColor->getColor() : LLColor4(1,1,1,1);
- LLViewerTexture* hair_img = getImage( TEX_HAIR );
+ LLViewerTexture* hair_img = getImage( TEX_HAIR, 0 );
for (U32 i = 0; i < mBakedTextureDatas[BAKED_HAIR].mMeshes.size(); i++)
{
mBakedTextureDatas[BAKED_HAIR].mMeshes[i]->setColor( color.mV[VX], color.mV[VY], color.mV[VZ], color.mV[VW] );
@@ -5936,18 +6014,21 @@ void LLVOAvatar::updateMeshTextures()
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::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] && mBakedTextureDatas[baked_index].mIsLoaded) || other_culled;
- setLocalTexture(texture_index, getImage(texture_index), is_baked_ready );
+ if (isSelf())
+ {
+ setBakedReady(texture_index, is_baked_ready);
+ }
}
}
removeMissingBakedTextures();
@@ -5963,6 +6044,13 @@ void LLVOAvatar::setLocalTexture( ETextureIndex type, LLViewerTexture* in_tex, B
llassert(0);
}
+//virtual
+void LLVOAvatar::setBakedReady(LLVOAvatarDefines::ETextureIndex type, BOOL baked_version_exists, U32 index)
+{
+ // invalid for anyone but self
+ llassert(0);
+}
+
void LLVOAvatar::addChat(const LLChat& chat)
{
std::deque<LLChat>::iterator chat_iter;
@@ -6002,28 +6090,6 @@ void LLVOAvatar::addMaskedMorph(EBakedTextureIndex index, LLPolyMorphTarget* mor
}
}
-// invalidates morph masks for a given layer. Don't pass a parameter to invalidate all morph masks.
-void LLVOAvatar::invalidateMorphMasks(LLVOAvatarDefines::EBakedTextureIndex index)
-{
- setMorphMasksValid(FALSE, index);
-}
-
-// updates morph masks to be a value for a given layer. Don't pass an argument to set value for all morph masks
-void LLVOAvatar::setMorphMasksValid(BOOL new_status, LLVOAvatarDefines::EBakedTextureIndex index)
-{
- if (index == BAKED_NUM_INDICES)
- {
- for (U8 tex = 0; tex < (U8)BAKED_NUM_INDICES; tex++)
- {
- mBakedTextureDatas[tex].mMorphMasksValid = new_status;
- }
- }
- else if (index < BAKED_NUM_INDICES)
- {
- mBakedTextureDatas[index].mMorphMasksValid = new_status;
- }
-}
-
// returns TRUE if morph masks are present and not valid for a given baked texture, FALSE otherwise
BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index)
{
@@ -6032,9 +6098,20 @@ BOOL LLVOAvatar::morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex inde
return FALSE;
}
- if (!mBakedTextureDatas[index].mMaskedMorphs.empty() && !mBakedTextureDatas[index].mMorphMasksValid)
+ if (!mBakedTextureDatas[index].mMaskedMorphs.empty())
{
- return TRUE;
+ if (isSelf())
+ {
+ LLTexLayerSet *layer_set = mBakedTextureDatas[index].mTexLayerSet;
+ if (layer_set)
+ {
+ return !layer_set->isMorphValid();
+ }
+ }
+ else
+ {
+ return FALSE;
+ }
}
return FALSE;
@@ -6049,7 +6126,7 @@ void LLVOAvatar::applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_com
}
for (morph_list_t::const_iterator iter = mBakedTextureDatas[index].mMaskedMorphs.begin();
- iter != mBakedTextureDatas[index].mMaskedMorphs.end(); iter++)
+ iter != mBakedTextureDatas[index].mMaskedMorphs.end(); ++iter)
{
const LLMaskedMorph* maskedMorph = (*iter);
maskedMorph->mMorphTarget->applyMask(tex_data, width, height, num_components, maskedMorph->mInvert);
@@ -6068,9 +6145,9 @@ void LLVOAvatar::releaseComponentTextures()
{
// ! 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)->getID() == getImage(TEX_SKIRT_BAKED)->getID())
+ if (isTextureDefined(TEX_HAIR_BAKED) && getImage(TEX_HAIR_BAKED,0)->getID() == getImage(TEX_SKIRT_BAKED,0)->getID())
{
- if (getImage(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);
@@ -6095,63 +6172,64 @@ void LLVOAvatar::releaseComponentTextures()
}
}
-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";
+ 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] = "pants_red";
- param_name[1] = "pants_green";
- param_name[2] = "pants_blue";
+ 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] = "shoes_red";
- param_name[1] = "shoes_green";
- param_name[2] = "shoes_blue";
+ 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] = "socks_red";
- param_name[1] = "socks_green";
- param_name[2] = "socks_blue";
+ 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] = "jacket_red";
- param_name[1] = "jacket_green";
- param_name[2] = "jacket_blue";
+ 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] = "gloves_red";
- param_name[1] = "gloves_green";
- param_name[2] = "gloves_blue";
+ 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] = "undershirt_red";
- param_name[1] = "undershirt_green";
- param_name[2] = "undershirt_blue";
+ 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";
+ 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] = "skirt_red";
- param_name[1] = "skirt_green";
- param_name[2] = "skirt_blue";
+ param_name[0] = 921; //"skirt_red";
+ param_name[1] = 922; //"skirt_green";
+ param_name[2] = 923; //"skirt_blue";
break;
default:
@@ -6164,7 +6242,7 @@ BOOL LLVOAvatar::teToColorParams( ETextureIndex te, const char* param_name[3] )
void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, BOOL set_by_user )
{
- 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 );
@@ -6176,7 +6254,7 @@ void LLVOAvatar::setClothesColor( ETextureIndex te, const LLColor4& new_color, B
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] );
@@ -6200,10 +6278,11 @@ void LLVOAvatar::dumpAvatarTEs( const std::string& context )
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::TextureEntry *texture_dict = iter->second;
- const LLViewerTexture* te_image = getImage(iter->first);
+ // TODO: handle multiple textures for self
+ const LLViewerTexture* te_image = getImage(iter->first,0);
if( !te_image )
{
llinfos << " " << texture_dict->mName << ": null ptr" << llendl;
@@ -6248,25 +6327,11 @@ BOOL LLVOAvatar::isWearingWearableType(EWearableType type) const
indicator_te = TEX_UPPER_SHIRT; */
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::TextureEntry *texture_dict = tex_iter->second;
if (texture_dict->mWearableType == type)
{
- // If you're checking your own clothing, check the component texture
- if (isSelf())
- {
- 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
@@ -6293,10 +6358,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();
@@ -6307,11 +6372,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;
}
@@ -6323,24 +6388,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());
+ }
}
}
}
@@ -6369,7 +6444,7 @@ void LLVOAvatar::onFirstTEMessageReceived()
// (That is, don't do a transition from unbaked to baked.)
if (layer_baked)
{
- LLViewerFetchedTexture* image = LLViewerTextureManager::staticCastToFetchedTexture(getImage( mBakedTextureDatas[i].mTextureIndex ), TRUE) ;
+ 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) )
@@ -6433,7 +6508,7 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys )
&& baked_index != BAKED_SKIRT)
{
setTEImage(mBakedTextureDatas[baked_index].mTextureIndex,
- LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE));
+ LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[baked_index].mLastTextureIndex, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
}
@@ -6617,15 +6692,15 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
BOOL found_texture_id = false;
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
if (texture_dict->mIsUsedByBakedTexture)
{
const ETextureIndex texture_index = iter->first;
- const LLViewerTexture *baked_img = self->getImage(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 = texture_dict->mBakedTextureIndex;
self->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1, baked_index);
@@ -6634,7 +6709,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture
{
LLImageGL::deleteTextures(1, &(self->mBakedTextureDatas[baked_index].mMaskTexName));
}
-
self->mBakedTextureDatas[baked_index].mMaskTexName = gl_name;
found_texture_id = true;
break;
@@ -6712,7 +6786,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
mHeadMesh1.setTexture( head_baked ); */
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex );
+ LLViewerTexture* image_baked = getImage( mBakedTextureDatas[i].mTextureIndex, 0 );
if (id == image_baked->getID())
{
mBakedTextureDatas[i].mIsLoaded = true;
@@ -6724,14 +6798,14 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id )
}
if (mBakedTextureDatas[i].mTexLayerSet)
{
- mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
+ //mBakedTextureDatas[i].mTexLayerSet->destroyComposite();
}
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, getImage(*local_tex_iter), TRUE);
+ setBakedReady(*local_tex_iter, TRUE);
}
// ! BACKWARDS COMPATIBILITY !
@@ -6787,7 +6861,8 @@ void LLVOAvatar::dumpArchetypeXML( void* )
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex)te) == type)
{
- LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te);
+ // MULTIPLE_WEARABLES: extend to multiple wearables?
+ LLViewerTexture* te_image = avatar->getImage((ETextureIndex)te, 0);
if( te_image )
{
std::string uuid_str;
@@ -7574,21 +7649,26 @@ void LLVOAvatar::idleUpdateRenderCost()
++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);
+ shame += 10;
+ const LLVOVolume* volume = drawable->getVOVolume();
+ if (volume)
+ {
+ shame += calc_shame(volume, textures);
+ }
}
}
}
- }
+ }
shame += textures.size() * 5;
@@ -7618,7 +7698,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const ETextureIndex index = iter->first;
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
@@ -7636,7 +7716,7 @@ const std::string LLVOAvatar::getBakedStatusForPrintout() const
}
-U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
+U32 calc_shame(const LLVOVolume* volume, std::set<LLUUID> &textures)
{
if (!volume)
{
@@ -7668,20 +7748,20 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
const LLVector3& sc = volume->getScale();
scale += (U32) sc.mV[0] + (U32) sc.mV[1] + (U32) sc.mV[2];
- LLDrawable* drawablep = volume->mDrawable;
+ const LLDrawable* drawablep = volume->mDrawable;
if (volume->isSculpted())
{
- LLSculptParams *sculpt_params = (LLSculptParams *) volume->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ const 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 LLFace* face = drawablep->getFace(i);
const LLTextureEntry* te = face->getTextureEntry();
- LLViewerTexture* img = face->getTexture();
+ const LLViewerTexture* img = face->getTexture();
textures.insert(img->getID());
@@ -7723,13 +7803,14 @@ U32 calc_shame(LLVOVolume* volume, std::set<LLUUID> &textures)
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++)
+ iter != child_list.end();
+ ++iter)
{
- LLViewerObject* child_objectp = *iter;
- LLDrawable* child_drawablep = child_objectp->mDrawable;
+ const LLViewerObject* child_objectp = *iter;
+ const LLDrawable* child_drawablep = child_objectp->mDrawable;
if (child_drawablep)
{
- LLVOVolume* child_volumep = child_drawablep->getVOVolume();
+ const LLVOVolume* child_volumep = child_drawablep->getVOVolume();
if (child_volumep)
{
shame += calc_shame(child_volumep, textures);
@@ -7763,7 +7844,7 @@ BOOL LLVOAvatar::isTextureDefined(LLVOAvatarDefines::ETextureIndex te, U32 index
return FALSE;
}
- return (getImage(te)->getID() != IMG_DEFAULT_AVATAR &&
- getImage(te)->getID() != IMG_DEFAULT);
+ 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 ef5358198d..cf86612ce6 100644
--- a/indra/newview/llvoavatar.h
+++ b/indra/newview/llvoavatar.h
@@ -195,7 +195,6 @@ public:
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
@@ -206,7 +205,7 @@ public:
virtual BOOL updateCharacter(LLAgent &agent);
void idleUpdateVoiceVisualizer(bool voice_enabled);
void idleUpdateMisc(bool detailed_update);
- void idleUpdateAppearanceAnimation();
+ virtual void idleUpdateAppearanceAnimation();
void idleUpdateLipSync(bool voice_enabled);
void idleUpdateLoadingEffect();
void idleUpdateWindEffect();
@@ -247,15 +246,19 @@ public:
//--------------------------------------------------------------------
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
** **
*******************************************************************************/
@@ -268,12 +271,14 @@ private:
public:
void updateHeadOffset();
F32 getPelvisToFoot() const { return mPelvisToFoot; }
+
LLVector3 mHeadOffset; // current head position
LLViewerJoint mRoot;
protected:
static BOOL parseSkeletonFile(const std::string& filename);
void buildCharacter();
- BOOL loadAvatar();
+ virtual BOOL loadAvatar();
+
BOOL setupBone(const LLVOAvatarBoneInfo* info, LLViewerJoint* parent, S32 &current_volume_num, S32 &current_joint_num);
BOOL buildSkeleton(const LLVOAvatarSkeletonInfo *info);
private:
@@ -350,10 +355,8 @@ private:
// Morph masks
//--------------------------------------------------------------------
public:
- void invalidateMorphMasks(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
BOOL morphMaskNeedsUpdate(LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
void addMaskedMorph(LLVOAvatarDefines::EBakedTextureIndex index, LLPolyMorphTarget* morph_target, BOOL invert, std::string layer);
- void setMorphMasksValid(BOOL new_status, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
void applyMorphMask(U8* tex_data, S32 width, S32 height, S32 num_components, LLVOAvatarDefines::EBakedTextureIndex index = LLVOAvatarDefines::BAKED_NUM_INDICES);
//--------------------------------------------------------------------
@@ -484,7 +487,6 @@ protected:
// 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;
- BOOL mMorphMasksValid;
};
typedef std::vector<BakedTextureData> bakedtexturedata_vec_t;
bakedtexturedata_vec_t mBakedTextureDatas;
@@ -495,13 +497,15 @@ protected:
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:
- virtual void setImage(const U8 te, LLViewerTexture *imagep);
- virtual LLViewerTexture* getImage(const U8 te) const;
+ 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);
@@ -605,7 +609,7 @@ private:
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]);
+ static BOOL teToColorParams(LLVOAvatarDefines::ETextureIndex te, U32 *param_name);
//--------------------------------------------------------------------
// Global colors
@@ -637,15 +641,15 @@ public:
**/
public:
- BOOL isWearingWearableType(EWearableType type ) const;
+ virtual BOOL isWearingWearableType(EWearableType type ) const;
//--------------------------------------------------------------------
// Attachments
//--------------------------------------------------------------------
public:
void clampAttachmentPositions();
- virtual LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
- BOOL detachObject(LLViewerObject *viewer_object);
+ virtual const LLViewerJointAttachment* attachObject(LLViewerObject *viewer_object);
+ virtual BOOL detachObject(LLViewerObject *viewer_object);
static LLVOAvatar* findAvatarFromAttachment(LLViewerObject* obj);
protected:
LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object);
@@ -668,6 +672,9 @@ public:
LLBBox getHUDBBox() const;
void rebuildHUD();
void resetHUDAttachments();
+ BOOL canAttachMoreObjects() const;
+protected:
+ U32 getNumAttachments() const; // O(N), not O(1)
/** Wearables
** **
@@ -793,7 +800,6 @@ public:
BOOL isSitting(){return mIsSitting;}
void sitOnObject(LLViewerObject *sit_object);
void getOffObject();
-
private:
// set this property only with LLVOAvatar::sitDown method
BOOL mIsSitting;
diff --git a/indra/newview/llvoavatardefines.cpp b/indra/newview/llvoavatardefines.cpp
index 978a61972f..49c4a1a6c8 100644
--- a/indra/newview/llvoavatardefines.cpp
+++ b/indra/newview/llvoavatardefines.cpp
@@ -61,14 +61,17 @@ LLVOAvatarDictionary::Textures::Textures()
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, "UIImgDefaultTattooUUID", WT_TATTOO));
- addEntry(TEX_UPPER_TATTOO, new TextureEntry("upper_tattoo", TRUE, BAKED_NUM_INDICES, "UIImgDefaultTattooUUID", WT_TATTOO));
- addEntry(TEX_LOWER_TATTOO, new TextureEntry("lower_tattoo", TRUE, BAKED_NUM_INDICES, "UIImgDefaultTattooUUID", WT_TATTOO));
+
+ 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));
@@ -81,34 +84,34 @@ LLVOAvatarDictionary::BakedTextures::BakedTextures()
{
// Baked textures
addEntry(BAKED_HEAD, new BakedEntry(TEX_HEAD_BAKED,
- "head", "18ded8d6-bcfc-e415-8539-944c0f5ea7a6",
+ "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", "338c29e3-3024-4dbb-998d-7c04cf4fa88f",
+ "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", "91b4a2c7-1b1a-ba16-9a16-1f8f8dcc1c3f",
+ "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", "b2cf28af-b840-1071-3c6a-78085d8128b5",
+ "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", "ea800387-ea1a-14e0-56cb-24f2022f969a",
+ "skirt", "03e7e8cb-1368-483b-b6f3-74850838ba63",
1, TEX_SKIRT,
1, WT_SKIRT));
addEntry(BAKED_HAIR, new BakedEntry(TEX_HAIR_BAKED,
- "hair", "0af1ef7c-ad24-11dd-8790-001f5bf833e8",
+ "hair", "a60e85a9-74e8-48d8-8a2d-8129f28d9b61",
2, TEX_HAIR, TEX_HAIR_ALPHA,
2, WT_HAIR, WT_ALPHA));
}
@@ -245,8 +248,6 @@ EBakedTextureIndex LLVOAvatarDictionary::findBakedByRegionName(std::string name)
//static
const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
{
- /* switch( index )
- case TEX_UPPER_SHIRT: return LLUUID( gSavedSettings.getString("UIImgDefaultShirtUUID") ); */
const TextureEntry *texture_dict = getInstance()->getTexture(index);
const std::string &default_image_name = texture_dict->mDefaultImageName;
if (default_image_name == "")
@@ -262,9 +263,6 @@ const LLUUID LLVOAvatarDictionary::getDefaultTextureImageID(ETextureIndex index)
// static
EWearableType LLVOAvatarDictionary::getTEWearableType(ETextureIndex index )
{
- /* switch(index)
- case TEX_UPPER_SHIRT:
- return WT_SHIRT; */
return getInstance()->getTexture(index)->mWearableType;
}
diff --git a/indra/newview/llvoavatarself.cpp b/indra/newview/llvoavatarself.cpp
index 76a4bfbf0c..6c3348b247 100644
--- a/indra/newview/llvoavatarself.cpp
+++ b/indra/newview/llvoavatarself.cpp
@@ -30,61 +30,41 @@
* $/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 <stdio.h>
-#include <ctype.h>
-
-#include "llaudioengine.h"
-#include "noise.h"
+#include "pipeline.h"
-// TODO: Seraph - Remove unnecessary headers. These are copied from llvoavatar.h.
#include "llagent.h" // Get state values from here
#include "llagentwearables.h"
-#include "llviewercontrol.h"
-#include "lldrawpoolavatar.h"
-#include "lldriverparam.h"
-#include "lleditingmotion.h"
-#include "llemote.h"
-#include "llface.h"
-#include "llfirstuse.h"
-#include "llheadrotmotion.h"
#include "llhudeffecttrail.h"
#include "llhudmanager.h"
-#include "llkeyframefallmotion.h"
-#include "llkeyframestandmotion.h"
-#include "llkeyframewalkmotion.h"
-#include "llmutelist.h"
#include "llselectmgr.h"
-#include "llsprite.h"
-#include "lltargetingmotion.h"
-#include "lltexlayer.h"
-#include "lltexglobalcolor.h"
#include "lltoolgrab.h" // for needsRenderBeam
#include "lltoolmgr.h" // for needsRenderBeam
#include "lltoolmorph.h"
#include "lltrans.h"
#include "llviewercamera.h"
-#include "llviewertexturelist.h"
#include "llviewermenu.h"
#include "llviewerobjectlist.h"
-#include "llviewerparcelmgr.h"
#include "llviewerstats.h"
-#include "llvovolume.h"
-#include "llworld.h"
-#include "pipeline.h"
-#include "llviewershadermgr.h"
-#include "llsky.h"
-#include "llanimstatelabels.h"
-#include "llgesturemgr.h" //needed to trigger the voice gesticulations
-#include "llvoiceclient.h"
-#include "llvoicevisualizer.h" // Ventrella
+#include "llviewerregion.h"
#include "llappearancemgr.h"
-#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;
@@ -182,6 +162,28 @@ void LLVOAvatarSelf::markDead()
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;
@@ -285,10 +287,10 @@ BOOL LLVOAvatarSelf::buildMenus()
{
BOOL attachment_found = FALSE;
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->getGroup() == i)
{
LLMenuItemCallGL::Params item_params;
@@ -304,9 +306,9 @@ BOOL LLVOAvatarSelf::buildMenus()
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Object.AttachToAvatar";
- item_params.on_click.parameter = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Object.EnableWear";
- item_params.on_enable.parameter = curiter->first;
+ item_params.on_enable.parameter = iter->first;
LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
gAttachPieMenu->addChild(item);
@@ -331,10 +333,10 @@ BOOL LLVOAvatarSelf::buildMenus()
{
BOOL attachment_found = FALSE;
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->getGroup() == i)
{
LLMenuItemCallGL::Params item_params;
@@ -349,9 +351,9 @@ BOOL LLVOAvatarSelf::buildMenus()
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Attachment.Detach";
- item_params.on_click.parameter = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Attachment.EnableDetach";
- item_params.on_enable.parameter = curiter->first;
+ item_params.on_enable.parameter = iter->first;
LLMenuItemCallGL* item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
gDetachPieMenu->addChild(item);
@@ -370,10 +372,10 @@ BOOL LLVOAvatarSelf::buildMenus()
// add screen attachments
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->getGroup() == 8)
{
LLMenuItemCallGL::Params item_params;
@@ -388,16 +390,16 @@ BOOL LLVOAvatarSelf::buildMenus()
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Object.AttachToAvatar";
- item_params.on_click.parameter = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Object.EnableWear";
- item_params.on_enable.parameter = curiter->first;
+ 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 = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Attachment.PointFilled";
- item_params.on_enable.parameter = curiter->first;
+ item_params.on_enable.parameter = iter->first;
item = LLUICtrlFactory::create<LLMenuItemCallGL>(item_params);
gDetachScreenPieMenu->addChild(item);
}
@@ -411,10 +413,10 @@ BOOL LLVOAvatarSelf::buildMenus()
break;
}
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() != (pass == 1))
{
continue;
@@ -431,12 +433,12 @@ BOOL LLVOAvatarSelf::buildMenus()
}
item_params.name =(item_params.label );
item_params.on_click.function_name = "Object.AttachToAvatar";
- item_params.on_click.parameter = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Object.EnableWear";
- item_params.on_enable.parameter = curiter->first;
+ item_params.on_enable.parameter = iter->first;
//* TODO: Skinning:
//LLSD params;
- //params["index"] = curiter->first;
+ //params["index"] = iter->first;
//params["label"] = attachment->getName();
//item->addEventHandler("on_enable", LLMenuItemCallGL::MenuCallback().function_name("Attachment.Label").parameter(params));
@@ -444,9 +446,9 @@ BOOL LLVOAvatarSelf::buildMenus()
gAttachSubMenu->addChild(item);
item_params.on_click.function_name = "Attachment.DetachFromPoint";
- item_params.on_click.parameter = curiter->first;
+ item_params.on_click.parameter = iter->first;
item_params.on_enable.function_name = "Attachment.PointFilled";
- item_params.on_enable.parameter = curiter->first;
+ 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);
@@ -472,15 +474,15 @@ BOOL LLVOAvatarSelf::buildMenus()
// 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 != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
+ 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, curiter->first));
+ attachment_pie_menu_map.insert(std::make_pair(pie_index, iter->first));
}
}
@@ -545,7 +547,7 @@ BOOL LLVOAvatarSelf::loadLayersets()
BOOL success = TRUE;
for (LLVOAvatarXmlInfo::layer_info_list_t::const_iterator iter = sAvatarXmlInfo->mLayerInfoList.begin();
iter != sAvatarXmlInfo->mLayerInfoList.end();
- iter++)
+ ++iter)
{
// Construct a layerset for each one specified in avatar_lad.xml and initialize it as such.
const LLTexLayerSetInfo *info = *iter;
@@ -563,7 +565,7 @@ BOOL LLVOAvatarSelf::loadLayersets()
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++)
+ ++baked_iter)
{
const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
if (layer_set->isBodyRegion(baked_dict->mName))
@@ -586,10 +588,10 @@ BOOL LLVOAvatarSelf::loadLayersets()
// 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++)
+ ++morph_iter)
{
LLMaskedMorph *morph = *morph_iter;
- LLTexLayer * layer = layer_set->findLayerByName(morph->mLayer);
+ LLTexLayerInterface* layer = layer_set->findLayerByName(morph->mLayer);
if (layer)
{
layer->setHasMorph(TRUE);
@@ -631,6 +633,85 @@ LLJoint *LLVOAvatarSelf::getJoint(const std::string &name)
return LLVOAvatar::getJoint(name);
}
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user )
+{
+ if (!which_param)
+ {
+ return FALSE;
+ }
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(which_param->getID());
+ return setParamWeight(param,weight,set_by_user);
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user )
+{
+ if (!param_name)
+ {
+ return FALSE;
+ }
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(param_name);
+ return setParamWeight(param,weight,set_by_user);
+}
+
+/*virtual*/ BOOL LLVOAvatarSelf::setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user )
+{
+ LLViewerVisualParam *param = (LLViewerVisualParam*) LLCharacter::getVisualParam(index);
+ return setParamWeight(param,weight,set_by_user);
+}
+
+BOOL LLVOAvatarSelf::setParamWeight(LLViewerVisualParam *param, F32 weight, BOOL set_by_user )
+{
+ 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, set_by_user);
+ }
+ }
+ }
+
+ return LLCharacter::setVisualParamWeight(param,weight,set_by_user);
+}
+
+/*virtual*/
+void LLVOAvatarSelf::updateVisualParams()
+{
+ for (U32 type = 0; type < WT_COUNT; type++)
+ {
+ LLWearable *wearable = gAgentWearables.getTopWearable((EWearableType)type);
+ if (wearable)
+ {
+ wearable->writeToAvatar(FALSE, FALSE);
+ }
+ }
+
+ LLVOAvatar::updateVisualParams();
+}
+
+/*virtual*/
+void LLVOAvatarSelf::idleUpdateAppearanceAnimation()
+{
+ // Animate all top-level wearable visual parameters
+ gAgentWearables.animateAllWearableParams(calcMorphAmount(), mAppearanceAnimSetByUser);
+
+ // apply wearable visual params to avatar
+ updateVisualParams();
+
+ //allow avatar to process updates
+ LLVOAvatar::idleUpdateAppearanceAnimation();
+
+}
+
// virtual
void LLVOAvatarSelf::requestStopMotion(LLMotion* motion)
{
@@ -831,10 +912,10 @@ void LLVOAvatarSelf::restoreMeshData()
void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
{
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(TRUE);
@@ -861,6 +942,11 @@ void LLVOAvatarSelf::updateAttachmentVisibility(U32 camera_mode)
}
}
+/*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.
@@ -870,7 +956,7 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type )
{
for (LLVOAvatarDictionary::BakedTextures::const_iterator baked_iter = LLVOAvatarDictionary::getInstance()->getBakedTextures().begin();
baked_iter != LLVOAvatarDictionary::getInstance()->getBakedTextures().end();
- baked_iter++)
+ ++baked_iter)
{
const LLVOAvatarDictionary::BakedEntry *baked_dict = baked_iter->second;
const LLVOAvatarDefines::EBakedTextureIndex index = baked_iter->first;
@@ -878,15 +964,14 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type )
{
for (LLVOAvatarDefines::wearables_vec_t::const_iterator type_iter = baked_dict->mWearables.begin();
type_iter != baked_dict->mWearables.end();
- type_iter++)
+ ++type_iter)
{
const EWearableType comp_type = *type_iter;
if (comp_type == type)
{
if (mBakedTextureDatas[index].mTexLayerSet)
{
- mBakedTextureDatas[index].mTexLayerSet->requestUpdate();
- mBakedTextureDatas[index].mTexLayerSet->requestUpload();
+ invalidateComposite(mBakedTextureDatas[index].mTexLayerSet, TRUE);
}
break;
}
@@ -898,59 +983,36 @@ void LLVOAvatarSelf::wearableUpdated( EWearableType type )
//-----------------------------------------------------------------------------
// isWearingAttachment()
//-----------------------------------------------------------------------------
-// Warning: include_linked_items = TRUE makes this operation expensive.
-BOOL LLVOAvatarSelf::isWearingAttachment( const LLUUID& inv_item_id , BOOL include_linked_items ) const
+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 != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ const LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getAttachedObject(base_inv_item_id))
{
return TRUE;
}
}
-
- if (include_linked_items)
- {
- LLInventoryModel::item_array_t item_array;
- gInventory.collectLinkedItems(inv_item_id, item_array);
- 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();
- for (attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
- iter != mAttachmentPoints.end(); )
- {
- attachment_map_t::const_iterator curiter = iter++;
- const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == item_id )
- {
- return TRUE;
- }
- }
- }
- }
-
return FALSE;
}
//-----------------------------------------------------------------------------
// getWornAttachment()
//-----------------------------------------------------------------------------
-LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id ) const
+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 != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ LLViewerJointAttachment* attachment = iter->second;
+ if (LLViewerObject *attached_object = attachment->getAttachedObject(base_inv_item_id))
{
- return attachment->getObject();
+ return attached_object;
}
}
return NULL;
@@ -958,12 +1020,13 @@ LLViewerObject* LLVOAvatarSelf::getWornAttachment( const LLUUID& inv_item_id ) c
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 != mAttachmentPoints.end();
+ ++iter)
{
- attachment_map_t::const_iterator curiter = iter++;
- const LLViewerJointAttachment* attachment = curiter->second;
- if( attachment->getItemID() == inv_item_id )
+ const LLViewerJointAttachment* attachment = iter->second;
+ if (attachment->getAttachedObject(base_inv_item_id))
{
return attachment->getName();
}
@@ -973,9 +1036,9 @@ const std::string LLVOAvatarSelf::getAttachedPointName(const LLUUID& inv_item_id
}
//virtual
-LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object)
+const LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_object)
{
- LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object);
+ const LLViewerJointAttachment *attachment = LLVOAvatar::attachObject(viewer_object);
if (!attachment)
{
return 0;
@@ -984,19 +1047,58 @@ LLViewerJointAttachment *LLVOAvatarSelf::attachObject(LLViewerObject *viewer_obj
updateAttachmentVisibility(gAgent.getCameraMode());
// Then make sure the inventory is in sync with the avatar.
- LLViewerInventoryItem *item = gInventory.getItem(attachment->getItemID());
- if (item)
- {
- LLAppearanceManager::dumpCat(LLAppearanceManager::getCOF(),"Adding attachment link:");
- LLAppearanceManager::wearItem(item,false); // Add COF link for item.
+ // Should just be the last object added
+ if (attachment->isObjectAttached(viewer_object))
+ {
+ const LLUUID& attachment_id = viewer_object->getItemID();
+ LLAppearanceManager::registerAttachment(attachment_id);
}
- gInventory.addChangedMask(LLInventoryObserver::LABEL, attachment->getItemID());
- gInventory.notifyObservers();
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::unregisterAttachment(attachment_id);
+ }
+
+ return TRUE;
+ }
+ return FALSE;
+}
+
void LLVOAvatarSelf::getAllAttachmentsArray(LLDynamicArray<S32>& attachments)
{
for (LLVOAvatar::attachment_map_t::const_iterator iter = mAttachmentPoints.begin();
@@ -1105,6 +1207,25 @@ BOOL LLVOAvatarSelf::getLocalTextureGL(ETextureIndex type, LLViewerTexture** tex
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;
@@ -1115,7 +1236,8 @@ const LLUUID& LLVOAvatarSelf::getLocalTextureID(ETextureIndex type, U32 index) c
return local_tex_obj->getImage()->getID();
}
return IMG_DEFAULT_AVATAR;
-}
+}
+
//-----------------------------------------------------------------------------
// isLocalTextureDataAvailable()
@@ -1128,7 +1250,7 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset)
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++)
+ ++baked_iter)
{
const EBakedTextureIndex baked_index = baked_iter->first;
if (layerset == mBakedTextureDatas[baked_index].mTexLayerSet)
@@ -1137,10 +1259,15 @@ BOOL LLVOAvatarSelf::isLocalTextureDataAvailable(const LLTexLayerSet* layerset)
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 tex_index = *local_tex_iter;
- ret &= (getLocalDiscardLevel(tex_index) >= 0);
+ 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;
}
@@ -1164,11 +1291,17 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons
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)
{
- if (getLocalDiscardLevel(*local_tex_iter) != 0)
+ 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++)
{
- return FALSE;
+ if (getLocalDiscardLevel(*local_tex_iter, wearable_index) != 0)
+ {
+ return FALSE;
+ }
}
}
return TRUE;
@@ -1181,17 +1314,33 @@ BOOL LLVOAvatarSelf::isLocalTextureDataFinal(const LLTexLayerSet* layerset) cons
BOOL LLVOAvatarSelf::isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index) const
{
LLUUID id;
+ BOOL isDefined = TRUE;
if (isIndexLocalTexture(type))
{
- id = getLocalTextureID(type, index);
+ 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 (id != IMG_DEFAULT_AVATAR &&
- id != IMG_DEFAULT);
+
+ return isDefined;
}
//-----------------------------------------------------------------------------
@@ -1202,7 +1351,8 @@ void LLVOAvatarSelf::requestLayerSetUploads()
{
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
+ 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();
@@ -1237,8 +1387,8 @@ void LLVOAvatarSelf::invalidateComposite( LLTexLayerSet* layerset, BOOL set_by_u
}
// llinfos << "LLVOAvatar::invalidComposite() " << layerset->getBodyRegion() << llendl;
- invalidateMorphMasks(layerset->getBakedTexIndex());
layerset->requestUpdate();
+ layerset->invalidateMorphMasks();
if( set_by_user )
{
@@ -1277,7 +1427,8 @@ void LLVOAvatarSelf::setupComposites()
{
for (U32 i = 0; i < mBakedTextureDatas.size(); i++)
{
- BOOL layer_baked = isTextureDefined(mBakedTextureDatas[i].mTextureIndex);
+ 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);
@@ -1298,15 +1449,15 @@ void LLVOAvatarSelf::updateComposites()
}
// virtual
-S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 index) const
+S32 LLVOAvatarSelf::getLocalDiscardLevel(ETextureIndex type, U32 wearable_index) const
{
if (!isIndexLocalTexture(type)) return FALSE;
- const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, index);
+ const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(type, wearable_index);
if (local_tex_obj)
{
if (type >= 0
- && getLocalTextureID(type,index) != IMG_DEFAULT_AVATAR
+ && local_tex_obj->getID() != IMG_DEFAULT_AVATAR
&& !local_tex_obj->getImage()->isMissingAsset())
{
return local_tex_obj->getImage()->getDiscardLevel();
@@ -1370,7 +1521,7 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
return;
}
EWearableType wearable_type = LLVOAvatarDictionary::getInstance()->getTEWearableType(type);
- if (!gAgentWearables.getWearable(wearable_type,0))
+ if (!gAgentWearables.getWearable(wearable_type,index))
{
// no wearable is loaded, cannot set the texture.
return;
@@ -1382,6 +1533,13 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
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)
{
@@ -1414,10 +1572,22 @@ void LLVOAvatarSelf::setLocalTexture(ETextureIndex type, LLViewerTexture* src_te
tex->setMinDiscardLevel(desired_discard);
}
}
- local_tex_obj->setBakedReady( baked_version_ready );
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
{
@@ -1428,7 +1598,7 @@ void LLVOAvatarSelf::dumpLocalTextures() const
if (isTextureDefined(baked_equiv[i])) */
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
if (!texture_dict->mIsLocalTexture || !texture_dict->mIsUsedByBakedTexture)
@@ -1439,7 +1609,8 @@ void LLVOAvatarSelf::dumpLocalTextures() const
const std::string &name = texture_dict->mName;
const LLLocalTextureObject *local_tex_obj = getLocalTextureObject(iter->first, 0);
- if (isTextureDefined(baked_equiv))
+ // 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
@@ -1499,6 +1670,31 @@ void LLVOAvatarSelf::onLocalTextureLoaded(BOOL success, LLViewerFetchedTexture *
}
}
+/*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()
{
@@ -1517,7 +1713,7 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
loading = TRUE;
}
- if (!isTextureDefined(TEX_HAIR))
+ if (!isTextureDefined(TEX_HAIR, 0))
{
loading = TRUE;
}
@@ -1525,13 +1721,13 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
if (!mPreviousFullyLoaded)
{
if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_LOWER].mTexLayerSet) &&
- (!isTextureDefined(TEX_LOWER_BAKED)))
+ (!isTextureDefined(TEX_LOWER_BAKED, 0)))
{
loading = TRUE;
}
if (!isLocalTextureDataAvailable(mBakedTextureDatas[BAKED_UPPER].mTexLayerSet) &&
- (!isTextureDefined(TEX_UPPER_BAKED)))
+ (!isTextureDefined(TEX_UPPER_BAKED, 0)))
{
loading = TRUE;
}
@@ -1542,11 +1738,11 @@ BOOL LLVOAvatarSelf::updateIsFullyLoaded()
continue;
BakedTextureData& texture_data = mBakedTextureDatas[i];
- if (!isTextureDefined(texture_data.mTextureIndex))
+ 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 );
+ LLViewerTexture* baked_img = getImage( texture_data.mTextureIndex, 0 );
if (!baked_img || !baked_img->hasGLTexture())
{
loading = TRUE;
@@ -1570,9 +1766,9 @@ const LLUUID& LLVOAvatarSelf::grabLocalTexture(ETextureIndex type, U32 index) co
BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const
{
// Check if the texture hasn't been baked yet.
- if (!isTextureDefined(type))
+ if (!isTextureDefined(type, index))
{
- lldebugs << "getTEImage( " << (U32) type << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
+ lldebugs << "getTEImage( " << (U32) type << ", " << index << " )->getID() == IMG_DEFAULT_AVATAR" << llendl;
return FALSE;
}
@@ -1592,10 +1788,11 @@ BOOL LLVOAvatarSelf::canGrabLocalTexture(ETextureIndex type, U32 index) const
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++)
+ ++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)
{
@@ -1767,7 +1964,7 @@ void LLVOAvatarSelf::processRebakeAvatarTextures(LLMessageSystem* msg, void**)
TEX_UPPER_BAKED, */
for (LLVOAvatarDictionary::Textures::const_iterator iter = LLVOAvatarDictionary::getInstance()->getTextures().begin();
iter != LLVOAvatarDictionary::getInstance()->getTextures().end();
- iter++)
+ ++iter)
{
const ETextureIndex index = iter->first;
const LLVOAvatarDictionary::TextureEntry *texture_dict = iter->second;
diff --git a/indra/newview/llvoavatarself.h b/indra/newview/llvoavatarself.h
index 17744cce1b..6e52b33634 100644
--- a/indra/newview/llvoavatarself.h
+++ b/indra/newview/llvoavatarself.h
@@ -57,6 +57,7 @@ public:
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();
@@ -85,6 +86,17 @@ public:
/*virtual*/ void requestStopMotion(LLMotion* motion);
/*virtual*/ LLJoint* getJoint(const std::string &name);
+ /*virtual*/ BOOL setVisualParamWeight(LLVisualParam *which_param, F32 weight, BOOL set_by_user = FALSE );
+ /*virtual*/ BOOL setVisualParamWeight(const char* param_name, F32 weight, BOOL set_by_user = FALSE );
+ /*virtual*/ BOOL setVisualParamWeight(S32 index, F32 weight, BOOL set_by_user = 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 set_by_user = FALSE );
+
+
/** Initialization
** **
*******************************************************************************/
@@ -160,31 +172,38 @@ public:
//--------------------------------------------------------------------
public:
/*virtual*/ bool hasPendingBakedUploads() const;
- S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
+ S32 getLocalDiscardLevel(LLVOAvatarDefines::ETextureIndex type, U32 index) const;
bool areTexturesCurrent() const;
BOOL isLocalTextureDataAvailable(const LLTexLayerSet* layerset) const;
BOOL isLocalTextureDataFinal(const LLTexLayerSet* layerset) const;
- /*virtual*/ BOOL isTextureDefined(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) 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 = 0) const;
- const LLUUID& getLocalTextureID(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
- void setLocalTextureTE(U8 te, LLViewerTexture* image, BOOL set_by_user, U32 index = 0);
- const LLUUID& grabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
- BOOL canGrabLocalTexture(LLVOAvatarDefines::ETextureIndex type, U32 index = 0) const;
+ 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, BOOL set_by_user, 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 setLocalTexture(LLVOAvatarDefines::ETextureIndex type, LLViewerTexture* tex, BOOL baked_version_exits, U32 index = 0);
+ /*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 = 0);
- LLLocalTextureObject* getLocalTextureObject(LLVOAvatarDefines::ETextureIndex i, U32 index = 0) 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
//--------------------------------------------------------------------
@@ -203,7 +222,6 @@ protected:
public:
void requestLayerSetUploads();
void requestLayerSetUpdate(LLVOAvatarDefines::ETextureIndex i);
-protected:
LLTexLayerSet* getLayerSet(LLVOAvatarDefines::ETextureIndex index) const;
//--------------------------------------------------------------------
@@ -250,25 +268,27 @@ protected:
**/
public:
- void wearableUpdated(EWearableType type);
+ /*virtual*/ BOOL isWearingWearableType(EWearableType type) const;
+ void wearableUpdated(EWearableType type);
+protected:
+ U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const;
//--------------------------------------------------------------------
// Attachments
//--------------------------------------------------------------------
public:
void updateAttachmentVisibility(U32 camera_mode);
- BOOL isWearingAttachment(const LLUUID& inv_item_id, BOOL include_linked_items = FALSE) const;
- LLViewerObject* getWornAttachment(const LLUUID& inv_item_id ) const;
+ 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*/ LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
+ /*virtual*/ const LLViewerJointAttachment *attachObject(LLViewerObject *viewer_object);
+ /*virtual*/ BOOL detachObject(LLViewerObject *viewer_object);
void getAllAttachmentsArray(LLDynamicArray<S32>& attachments);
//--------------------------------------------------------------------
// HUDs
//--------------------------------------------------------------------
private:
- U32 getNumWearables(LLVOAvatarDefines::ETextureIndex i) const;
-
LLViewerJoint* mScreenp; // special purpose joint for HUD attachments
/** Attachments
diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp
index 570a3334b9..110433a27d 100644
--- a/indra/newview/llvograss.cpp
+++ b/indra/newview/llvograss.cpp
@@ -106,7 +106,7 @@ void LLVOGrass::updateSpecies()
SpeciesMap::const_iterator it = sSpeciesTable.begin();
mSpecies = (*it).first;
}
- setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE));
+ setTEImage(0, LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE));
}
diff --git a/indra/newview/llvoicechannel.cpp b/indra/newview/llvoicechannel.cpp
new file mode 100644
index 0000000000..cefc88ebee
--- /dev/null
+++ b/indra/newview/llvoicechannel.cpp
@@ -0,0 +1,880 @@
+/**
+ * @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 "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;
+
+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
+ 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;
+ }
+
+ doSetState(state);
+}
+
+void LLVoiceChannel::doSetState(const EState& new_state)
+{
+ EState old_state = mState;
+ mState = new_state;
+ if (!mStateChangedCallback.empty())
+ mStateChangedCallback(old_state, mState);
+}
+
+void LLVoiceChannel::toggleCallWindowIfNeeded(EState state)
+{
+ if (state == STATE_CONNECTED)
+ {
+ LLFloaterReg::showInstance("voice_call", mSessionID);
+ }
+ // By checking that current state is CONNECTED we make sure that the call window
+ // has been shown, hence there's something to hide. This helps when user presses
+ // the "End call" button right after initiating the call.
+ // *TODO: move this check to LLFloaterCall?
+ else if (state == STATE_HUNG_UP && mState == STATE_CONNECTED)
+ {
+ LLFloaterReg::hideInstance("voice_call", mSessionID);
+ }
+}
+
+//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);
+
+#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
+ }
+}
+
+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)
+{
+ // HACK: Open/close the call window if needed.
+ toggleCallWindowIfNeeded(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())
+ {
+ 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();
+ }
+
+ // Add the party to the list of people with which we've recently interacted.
+ LLRecentPeople::instance().add(mOtherUserID);
+ }
+}
+
+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)
+{
+ // HACK: Open/close the call window if needed.
+ toggleCallWindowIfNeeded(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);
+ doSetState(state);
+ return;
+ }
+ LLVoiceChannel::setState(state);
+}
diff --git a/indra/newview/llvoicechannel.h b/indra/newview/llvoicechannel.h
new file mode 100644
index 0000000000..8f1e9ff02d
--- /dev/null
+++ b/indra/newview/llvoicechannel.h
@@ -0,0 +1,179 @@
+/**
+ * @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 boost::function<void(const EState& old_state, const EState& new_state)> state_changed_callback_t;
+
+ 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; }
+
+ void setStateChangedCallback(state_changed_callback_t callback) { mStateChangedCallback = callback; }
+
+ 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);
+ /**
+ * Use this method if you want mStateChangedCallback to be executed while state is changed
+ */
+ void doSetState(const EState& state);
+ void toggleCallWindowIfNeeded(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;
+
+private:
+ state_changed_callback_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 6401389c8f..df5481c874 100644
--- a/indra/newview/llvoiceclient.cpp
+++ b/indra/newview/llvoiceclient.cpp
@@ -57,13 +57,13 @@
#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 "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()
@@ -254,6 +254,7 @@ protected:
std::string nameString;
std::string audioMediaString;
std::string displayNameString;
+ std::string deviceString;
int participantType;
bool isLocallyMuted;
bool isModeratorMuted;
@@ -485,6 +486,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();
@@ -508,7 +517,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--;
@@ -580,6 +588,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))
@@ -596,18 +606,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))
{
@@ -648,12 +653,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)
{
@@ -1160,7 +1161,8 @@ LLVoiceClient::LLVoiceClient() :
mVoiceEnabled(false),
mWriteInProgress(false),
- mLipSyncEnabled(false)
+ mLipSyncEnabled(false),
+ mAPIVersion("Unknown")
{
gVoiceClient = this;
@@ -1664,7 +1666,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())
@@ -1679,17 +1680,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();
}
@@ -1701,7 +1703,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
{
@@ -3749,6 +3751,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)
{
@@ -4972,7 +4975,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;
}
}
@@ -6488,7 +6491,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);
}
@@ -6528,7 +6531,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;
}
}
@@ -6921,7 +6924,8 @@ void LLVoiceClient::notifyFriendObservers()
void LLVoiceClient::lookupName(const LLUUID &id)
{
- gCacheName->get(id, FALSE, &LLVoiceClient::onAvatarNameLookup);
+ BOOL is_group = FALSE;
+ gCacheName->get(id, is_group, &LLVoiceClient::onAvatarNameLookup);
}
//static
diff --git a/indra/newview/llvoiceclient.h b/indra/newview/llvoiceclient.h
index bddd18dee8..9df96d9a52 100644
--- a/indra/newview/llvoiceclient.h
+++ b/indra/newview/llvoiceclient.h
@@ -204,6 +204,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
@@ -739,6 +742,8 @@ static std::string nameFromsipURI(const std::string &uri);
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 9bafc03a6d..e777d7362f 100644
--- a/indra/newview/llvoicevisualizer.cpp
+++ b/indra/newview/llvoicevisualizer.cpp
@@ -142,7 +142,7 @@ LLVoiceVisualizer::LLVoiceVisualizer( const U8 type )
for (int i=0; i<NUM_VOICE_SYMBOL_WAVES; i++)
{
mSoundSymbol.mWaveFadeOutStartTime [i] = mCurrentTime;
- mSoundSymbol.mTexture [i] = LLViewerTextureManager::getFetchedTextureFromFile(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;
diff --git a/indra/newview/llvopartgroup.cpp b/indra/newview/llvopartgroup.cpp
index 7585842623..143cd2d9c6 100644
--- a/indra/newview/llvopartgroup.cpp
+++ b/indra/newview/llvopartgroup.cpp
@@ -249,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
diff --git a/indra/newview/llvosky.cpp b/indra/newview/llvosky.cpp
index 33b86660fa..d37deaf53d 100644
--- a/indra/newview/llvosky.cpp
+++ b/indra/newview/llvosky.cpp
@@ -376,9 +376,9 @@ LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
mSun.setIntensity(SUN_INTENSITY);
mMoon.setIntensity(0.1f * SUN_INTENSITY);
- mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE);
+ mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE);
+ mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
mBloomTexturep->setNoDelete() ;
@@ -472,9 +472,9 @@ void LLVOSky::restoreGL()
{
mSkyTex[i].restoreGL();
}
- mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, TRUE);
+ mSunTexturep = LLViewerTextureManager::getFetchedTexture(gSunTextureID, TRUE, LLViewerTexture::BOOST_UI);
mSunTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
- mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, TRUE);
+ mMoonTexturep = LLViewerTextureManager::getFetchedTexture(gMoonTextureID, TRUE, LLViewerTexture::BOOST_UI);
mMoonTexturep->setAddressMode(LLTexUnit::TAM_CLAMP);
mBloomTexturep = LLViewerTextureManager::getFetchedTexture(IMG_BLOOM1);
mBloomTexturep->setNoDelete() ;
@@ -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;
}
diff --git a/indra/newview/llvosky.h b/indra/newview/llvosky.h
index 466cdfdcd0..62c934fb41 100644
--- a/indra/newview/llvosky.h
+++ b/indra/newview/llvosky.h
@@ -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(); }
diff --git a/indra/newview/llvotree.cpp b/indra/newview/llvotree.cpp
index 615ae13bc2..ec118d89bc 100644
--- a/indra/newview/llvotree.cpp
+++ b/indra/newview/llvotree.cpp
@@ -311,7 +311,7 @@ U32 LLVOTree::processUpdateMessage(LLMessageSystem *mesgsys,
//
// Load Species-Specific data
//
- mTreeImagep = LLViewerTextureManager::getFetchedTexture(sSpeciesTable[mSpecies]->mTextureID, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ 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;
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 583246c23e..f6343b4134 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -91,6 +91,57 @@ LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient =
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) : mObject(obj) {}
+ 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();
+ }
+ }
+ 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)
+ { mObject->updateObjectMediaData(data); }
+
+ virtual F64 getDistanceFromAvatar() const
+ { return mObject->getRenderPosition().length(); }
+
+ virtual F64 getTotalMediaInterest() const
+ { return mObject->getTotalMediaInterest(); }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mObject->getRegion()->getCapability(name); }
+
+private:
+ LLPointer<LLVOVolume> mObject;
+};
+
+
LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
: LLViewerObject(id, pcode, regionp),
mVolumeImpl(NULL)
@@ -134,8 +185,12 @@ LLVOVolume::~LLVOVolume()
// static
void LLVOVolume::initClass()
{
- sObjectMediaClient = new LLObjectMediaDataClient();
- sObjectMediaNavigateClient = new LLObjectMediaNavigateClient();
+ // gSavedSettings better be around
+ const F32 queue_timer_delay = gSavedSettings.getF32("PrimMediaRequestQueueDelay");
+ const F32 retry_timer_delay = gSavedSettings.getF32("PrimMediaRetryTimerDelay");
+ const U32 max_retries = gSavedSettings.getU32("PrimMediaMaxRetries");
+ sObjectMediaClient = new LLObjectMediaDataClient(queue_timer_delay, retry_timer_delay, max_retries);
+ sObjectMediaNavigateClient = new LLObjectMediaNavigateClient(queue_timer_delay, retry_timer_delay, max_retries);
}
// static
@@ -319,13 +374,23 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys,
}
}
}
- if (retval & (MEDIA_URL_REMOVED | MEDIA_URL_ADDED | MEDIA_URL_UPDATED | MEDIA_FLAGS_CHANGED)) {
- // If the media changed at all, request new media data
- if(mMedia)
+ 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) ) )
{
- llinfos << "Media URL: " << mMedia->mMediaURL << llendl;
+ // 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();
}
- requestMediaDataUpdate();
+ 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();
@@ -600,7 +665,7 @@ void LLVOVolume::updateTextures()
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
LLUUID id = sculpt_params->getSculptTexture();
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (mSculptTexture.notNull())
{
S32 lod = llmin(mLOD, 3);
@@ -674,15 +739,15 @@ F32 LLVOVolume::getTextureVirtualSize(LLFace* face)
face->setPixelArea(face_area);
- if (face_area <= 0)
+ if (face_area <= 0.f)
{
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)
+ F32 texel_area = (tdim * 0.5f).lengthSquared()*F_PI;
+ if (texel_area <= 0.f)
{
// Probably animated, use default
texel_area = 1.f;
@@ -811,7 +876,7 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
if (isSculpted())
{
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
if (mSculptTexture.notNull())
{
//ignore sculpt GL usage since bao fixed this in a separate branch
@@ -971,7 +1036,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));
@@ -1624,7 +1689,7 @@ bool LLVOVolume::hasMedia() const
void LLVOVolume::requestMediaDataUpdate()
{
- sObjectMediaClient->fetchMedia(this);
+ sObjectMediaClient->fetchMedia(new LLMediaDataClientObjectImpl(this));
}
void LLVOVolume::cleanUpMediaImpls()
@@ -1703,6 +1768,118 @@ void LLVOVolume::syncMediaData(S32 texture_index, const LLSD &media_data, bool m
// << ((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();
+ if (url.empty())
+ {
+ url = mep->getHomeURL();
+ }
+ if (! url.empty())
+ {
+ LL_INFOS("LLMediaDataClient") << "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
+ {
+
+ llinfos << "broadcasting navigate with URI " << new_location << llendl;
+
+ sObjectMediaNavigateClient->navigate(new LLMediaDataClientObjectImpl(this), face_index, new_location);
+ }
+}
+
void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event)
{
switch(event)
@@ -1714,49 +1891,8 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
{
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.
-
- 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);
- std::string new_location = plugin->getLocation();
-
- // 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;
- }
- }
- 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
- // NOTE: the only way block_navigation can be true is if we found the media entry, so we're guaranteed here that mep is not NULL.
- impl->navigateTo(mep->getCurrentURL());
- }
- else
- {
-
- llinfos << "broadcasting navigate with URI " << new_location << llendl;
-
- sObjectMediaNavigateClient->navigate(this, face_index, new_location);
- }
+ // 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;
@@ -1773,6 +1909,29 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
}
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;
}
@@ -1781,7 +1940,7 @@ void LLVOVolume::mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin,
void LLVOVolume::sendMediaDataUpdate()
{
- sObjectMediaClient->updateMedia(this);
+ sObjectMediaClient->updateMedia(new LLMediaDataClientObjectImpl(this));
}
void LLVOVolume::removeMediaImpl(S32 texture_index)
@@ -1874,6 +2033,22 @@ viewer_media_t LLVOVolume::getMediaImpl(U8 face_id) const
return NULL;
}
+F64 LLVOVolume::getTotalMediaInterest() const
+{
+ F64 interest = (F64)0.0;
+ int i = 0;
+ const int end = getNumTEs();
+ for ( ; i < end; ++i)
+ {
+ const viewer_media_t &impl = getMediaImpl(i);
+ if (!impl.isNull())
+ {
+ interest += impl->getInterest();
+ }
+ }
+ return interest;
+}
+
S32 LLVOVolume::getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id)
{
S32 end = (S32)mMediaImplList.size() ;
@@ -2812,6 +2987,7 @@ static LLFastTimer::DeclareTimer FTM_REBUILD_VBO("VBO Rebuilt");
void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
{
+ llpushcallstacks ;
if (group->changeLOD())
{
group->mLastUpdateDistance = group->mDistance;
@@ -3042,6 +3218,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
static LLFastTimer::DeclareTimer FTM_VOLUME_GEOM("Volume Geometry");
void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
{
+ llpushcallstacks ;
if (group->isState(LLSpatialGroup::MESH_DIRTY) && !group->isState(LLSpatialGroup::GEOM_DIRTY))
{
LLFastTimer tm(FTM_VOLUME_GEOM);
@@ -3132,6 +3309,7 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
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);
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 250c3ed917..00810b22c4 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -233,7 +233,23 @@ public:
BOOL canBeFlexible() const;
BOOL setIsFlexible(BOOL is_flexible);
- void updateObjectMediaData(const LLSD &media_data_duples);
+ // 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);
+
+ // 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
@@ -244,6 +260,7 @@ public:
viewer_media_t getMediaImpl(U8 face_id) const;
S32 getFaceIndexWithMediaImpl(const LLViewerMediaImpl* media_impl, S32 start_face_id);
+ F64 getTotalMediaInterest() const;
bool hasMedia() const;
diff --git a/indra/newview/llvowlsky.cpp b/indra/newview/llvowlsky.cpp
index 8621e5e1d9..d3238f16a8 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)
diff --git a/indra/newview/llwaterparammanager.cpp b/indra/newview/llwaterparammanager.cpp
index 136ffe607d..c8cc6a3d8e 100644
--- a/indra/newview/llwaterparammanager.cpp
+++ b/indra/newview/llwaterparammanager.cpp
@@ -304,7 +304,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/llwearable.cpp b/indra/newview/llwearable.cpp
index 0d3dd10a01..2b4861ce4f 100644
--- a/indra/newview/llwearable.cpp
+++ b/indra/newview/llwearable.cpp
@@ -35,6 +35,7 @@
#include "llagent.h"
#include "llagentwearables.h"
#include "llfloatercustomize.h"
+#include "lllocaltextureobject.h"
#include "llviewertexturelist.h"
#include "llinventorymodel.h"
#include "llviewerregion.h"
@@ -44,6 +45,9 @@
#include "llwearable.h"
#include "lldictionary.h"
#include "lltrans.h"
+#include "lltexlayer.h"
+#include "llvisualparam.h"
+#include "lltexglobalcolor.h"
using namespace LLVOAvatarDefines;
@@ -56,7 +60,7 @@ 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());
@@ -64,7 +68,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();
@@ -129,17 +133,19 @@ BOOL LLWearable::exportFile(LLFILE* file) const
}
// 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::const_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;
@@ -156,7 +162,7 @@ BOOL LLWearable::exportFile(LLFILE* file) const
for (te_map_t::const_iterator iter = mTEMap.begin(); iter != mTEMap.end(); ++iter)
{
S32 te = iter->first;
- const LLUUID& image_id = iter->second.getID();
+ const LLUUID& image_id = iter->second->getID();
if( fprintf( file, "%d %s\n", te, image_id.asString().c_str()) < 0 )
{
return FALSE;
@@ -165,6 +171,41 @@ BOOL LLWearable::exportFile(LLFILE* file) const
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 )
{
// *NOTE: changing the type or size of this buffer will require
@@ -287,7 +328,7 @@ BOOL LLWearable::importFile( LLFILE* file )
}
if( 0 <= type && type < WT_COUNT )
{
- mType = (EWearableType)type;
+ setType((EWearableType)type);
}
else
{
@@ -296,7 +337,6 @@ BOOL LLWearable::importFile( LLFILE* file )
return FALSE;
}
-
// parameters header
S32 num_parameters = 0;
fields_read = fscanf( file, "parameters %d\n", &num_parameters );
@@ -306,6 +346,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. " << llendl;
+ }
+
// parameters
S32 i;
for( i = 0; i < num_parameters; i++ )
@@ -318,7 +363,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
@@ -349,11 +394,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];
+ }
- //TODO: check old values
- mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, 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;
}
@@ -389,13 +449,13 @@ BOOL LLWearable::isOldVersion() const
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;
}
@@ -442,13 +502,17 @@ BOOL LLWearable::isDirty() const
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;
@@ -460,21 +524,25 @@ BOOL LLWearable::isDirty() const
{
if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- LLViewerTexture* 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;
- }
-
- te_map_t::const_iterator iter = mTEMap.find(te);
- if(iter != mTEMap.end())
- {
- const LLUUID& image_id = iter->second.getID();
- 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;
+ }
}
}
}
@@ -500,35 +568,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 (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, LLVOAvatarDictionary::getDefaultTextureImageID((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( BOOL set_by_user, BOOL update_customize_floater )
{
LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
llassert( avatar );
if( !avatar )
{
+ llerrs << "could not get avatar object to write to for wearable " << this->getName() << llendl;
return;
}
@@ -537,10 +617,11 @@ 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());
+ F32 weight = getVisualParamWeight(param_id);
+
// only animate with user-originated changes
if (set_by_user)
{
@@ -568,36 +649,22 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
LLUUID image_id;
if(iter != mTEMap.end())
{
- image_id = iter->second.getID();
+ image_id = iter->second->getID();
}
else
{
image_id = LLVOAvatarDictionary::getDefaultTextureImageID((ETextureIndex) te);
}
- LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, FALSE, LLViewerTexture::LOD_TEXTURE );
- avatar->setLocalTextureTE(te, image, set_by_user);
+ LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE );
+ // MULTI-WEARABLE: replace hard-coded 0
+ avatar->setLocalTextureTE(te, image, set_by_user, 0);
}
}
- avatar->updateVisualParams();
- if( gFloaterCustomize )
+ if( gFloaterCustomize && update_customize_floater )
{
- LLViewerInventoryItem* item;
- // MULTI_WEARABLE:
- item = (LLViewerInventoryItem*)gInventory.getItem(gAgentWearables.getWearableItemID(mType,0));
- U32 perm_mask = PERM_NONE;
- BOOL is_complete = FALSE;
- if(item)
- {
- perm_mask = item->getPermissions().getMaskOwner();
- is_complete = item->isComplete();
- if(!is_complete)
- {
- item->fetchFromServer();
- }
- }
- gFloaterCustomize->setWearable(mType, this, perm_mask, is_complete);
+ gFloaterCustomize->setWearable(mType, 0);
gFloaterCustomize->setCurrentWearableType( mType );
}
@@ -615,6 +682,7 @@ void LLWearable::writeToAvatar( BOOL set_by_user )
// }
}
+
// 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 )
@@ -645,16 +713,6 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
}
}
- // Pull textures
- LLViewerTexture* image = LLViewerTextureManager::getFetchedTexture( IMG_DEFAULT_AVATAR );
- for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
- {
- if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == type)
- {
- avatar->setLocalTextureTE(te, image, set_by_user);
- }
- }
-
if( gFloaterCustomize )
{
gFloaterCustomize->setWearable(type, NULL, PERM_ALL, TRUE);
@@ -669,53 +727,11 @@ void LLWearable::removeFromAvatar( EWearableType type, BOOL set_by_user )
// }
}
-
-
-// Updates asset from the user's avatar
-void LLWearable::readFromAvatar()
-{
- LLVOAvatar* avatar = gAgent.getAvatarObject();
- llassert( avatar );
- if( !avatar )
- {
- return;
- }
-
- mDefinitionVersion = LLWearable::sCurrentDefinitionVersion;
-
- 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->getWeight();
- }
- }
-
- mTEMap.clear();
- for( S32 te = 0; te < TEX_NUM_INDICES; te++ )
- {
- if (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
- {
- LLViewerTexture* image = avatar->getTEImage( te );
- if( image )
- {
- mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image->getID());
- }
- }
- }
-
- //if( gFloaterCustomize )
- //{
- // mDescription = gFloaterCustomize->getWearableDescription( mType );
- //}
-}
-
// 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 )
{
@@ -728,39 +744,55 @@ void LLWearable::copyDataFrom(const LLWearable* src)
mDescription = src->mDescription;
mPermissions = src->mPermissions;
mSaleInfo = src->mSaleInfo;
- mType = src->mType;
+ 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( (param->getWearableType() == mType) && (param->getGroup() == VISUAL_PARAM_GROUP_TWEAKABLE ) )
+ if( (param->getWearableType() == mType) )
{
S32 id = param->getID();
- F32 weight = get_if_there(src->mVisualParamMap, id, param->getDefaultWeight() );
- mVisualParamMap[id] = weight;
+ F32 weight = src->getVisualParamWeight(id);
+ mSavedVisualParamMap[id] = weight;
}
}
+ 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 (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
{
- te_map_t::const_iterator iter = mTEMap.find(te);
+ te_map_t::const_iterator iter = src->mTEMap.find(te);
LLUUID image_id;
- if(iter != mTEMap.end())
+ LLViewerFetchedTexture *image = NULL;
+ if(iter != src->mTEMap.end())
{
- image_id = iter->second.getID();
+ 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
{
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);
}
- mTEMap[te] = LLLocalTextureObject(NULL, NULL, NULL, image_id);
+ createLayers(te);
}
}
+
+ // 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();
}
void LLWearable::setItemID(const LLUUID& item_id)
@@ -773,29 +805,275 @@ const LLUUID& LLWearable::getItemID() const
return mItemID;
}
-LLLocalTextureObject* LLWearable::getLocalTextureObject(S32 index) const
+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() )
+ {
+ LLLocalTextureObject* lto = iter->second;
+ return lto;
+ }
+ return NULL;
+}
+
+const LLLocalTextureObject* LLWearable::getConstLocalTextureObject(S32 index) const
{
te_map_t::const_iterator iter = mTEMap.find(index);
if( iter != mTEMap.end() )
{
- return (LLLocalTextureObject*) &iter->second;
+ const LLLocalTextureObject* lto = iter->second;
+ return lto;
}
return NULL;
}
void LLWearable::setLocalTextureObject(S32 index, LLLocalTextureObject *lto)
{
+ if( mTEMap.find(index) != mTEMap.end() )
+ {
+ mTEMap.erase(index);
+ }
if( lto )
{
- LLLocalTextureObject obj(*lto);
- mTEMap[index] = obj;
+ mTEMap[index] = new LLLocalTextureObject(*lto);
+ }
+}
+
+
+void LLWearable::addVisualParam(LLVisualParam *param)
+{
+ if( mVisualParamIndexMap[param->getID()] )
+ {
+ delete mVisualParamIndexMap[param->getID()];
+ }
+ param->setIsDummy(FALSE);
+ mVisualParamIndexMap[param->getID()] = param;
+}
+
+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 set_by_user)
+{
+ if( is_in_map(mVisualParamIndexMap, param_index ) )
+ {
+ LLVisualParam *wearable_param = mVisualParamIndexMap[param_index];
+ wearable_param->setWeight(value, set_by_user);
}
else
{
- mTEMap.erase(index);
+ 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 set_by_user)
+{
+ for(visual_param_index_map_t::iterator iter = mVisualParamIndexMap.begin();
+ iter != mVisualParamIndexMap.end();
+ ++iter)
+ {
+ LLVisualParam *param = (LLVisualParam*) iter->second;
+ param->animate(delta, set_by_user);
+ }
+}
+
+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++ )
+ {
+ color.mV[index] = getVisualParamWeight(param_name[index]);
+ }
+ }
+ return color;
+}
+
+void LLWearable::setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user )
+{
+ 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], set_by_user);
+ }
+ }
+}
+
+void LLWearable::revertValues()
+{
+ //update saved settings so wearable is no longer dirty
+ for (param_map_t::const_iterator iter = mSavedVisualParamMap.begin(); iter != mSavedVisualParamMap.end(); iter++)
+ {
+ S32 id = iter->first;
+ F32 value = iter->second;
+ setVisualParamWeight(id, value, TRUE);
+ }
+
+ 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 (LLVOAvatarDictionary::getTEWearableType((ETextureIndex) te) == mType)
+ {
+ 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();
+}
+
struct LLWearableSaveData
{
EWearableType mType;
@@ -838,7 +1116,7 @@ void LLWearable::saveNewAsset() const
{
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();
@@ -882,6 +1160,7 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda
// delete the context data
delete data;
+
}
std::ostream& operator<<(std::ostream &s, const LLWearable &w)
@@ -893,11 +1172,12 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w)
//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";
}
@@ -906,7 +1186,7 @@ std::ostream& operator<<(std::ostream &s, const LLWearable &w)
iter != w.mTEMap.end(); ++iter)
{
S32 te = iter->first;
- const LLUUID& image_id = iter->second.getID();
+ const LLUUID& image_id = iter->second->getID();
s << " " << te << " " << image_id << "\n";
}
return s;
diff --git a/indra/newview/llwearable.h b/indra/newview/llwearable.h
index d7b4d3f91e..96631811c5 100644
--- a/indra/newview/llwearable.h
+++ b/indra/newview/llwearable.h
@@ -43,6 +43,9 @@
#include "lllocaltextureobject.h"
class LLViewerInventoryItem;
+class LLVisualParam;
+class LLTexGlobalColorInfo;
+class LLTexGlobalColor;
class LLWearable
{
@@ -66,7 +69,7 @@ public:
const LLAssetID& getAssetID() const { return mAssetID; }
const LLTransactionID& getTransactionID() const { return mTransactionID; }
EWearableType getType() const { return mType; }
- void setType(EWearableType type) { mType = type; }
+ 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; }
@@ -81,11 +84,12 @@ public:
LLLocalTextureObject* getLocalTextureObject(S32 index) const;
public:
+ typedef std::vector<LLVisualParam*> visual_param_vec_t;
+
BOOL isDirty() const;
BOOL isOldVersion() const;
- void writeToAvatar( BOOL set_by_user );
- void readFromAvatar();
+ void writeToAvatar( BOOL set_by_user, BOOL update_customize_floater = TRUE );
void removeFromAvatar( BOOL set_by_user ) { LLWearable::removeFromAvatar( mType, set_by_user ); }
static void removeFromAvatar( EWearableType type, BOOL set_by_user );
@@ -104,9 +108,37 @@ public:
friend std::ostream& operator<<(std::ostream &s, const LLWearable &w);
void setItemID(const LLUUID& item_id);
+
+ LLLocalTextureObject* getLocalTextureObject(S32 index);
+ const LLLocalTextureObject* getConstLocalTextureObject(S32 index) const;
+
void setLocalTextureObject(S32 index, LLLocalTextureObject *lto);
+ void addVisualParam(LLVisualParam *param);
+ void setVisualParams();
+ void setVisualParamWeight(S32 index, F32 value, BOOL set_by_user);
+ F32 getVisualParamWeight(S32 index) const;
+ LLVisualParam* getVisualParam(S32 index) const;
+ void getVisualParams(visual_param_vec_t &list);
+ void animateParams(F32 delta, BOOL set_by_user);
+
+ LLColor4 getClothesColor(S32 te) const;
+ void setClothesColor( S32 te, const LLColor4& new_color, BOOL set_by_user );
+
+ void revertValues();
+
+ BOOL isOnTop() const;
+
private:
+ 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 saveValues();
+ 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.
std::string mName;
@@ -118,9 +150,12 @@ 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, LLLocalTextureObject> te_map_t;
+ param_map_t mSavedVisualParamMap; // last saved version of visual params
+
+ visual_param_index_map_t mVisualParamIndexMap;
+
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
};
diff --git a/indra/newview/llwearablelist.cpp b/indra/newview/llwearablelist.cpp
index 1275312676..da62223aac 100644
--- a/indra/newview/llwearablelist.cpp
+++ b/indra/newview/llwearablelist.cpp
@@ -74,21 +74,8 @@ LLWearableList::~LLWearableList()
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)
{
- LLAssetID assetID = _assetID;
-
- // A bit of a hack since wearables database doesn't contain asset types...
- // Perform indirection in case this assetID is in fact a link. This only works
- // because of the assumption that all assetIDs and itemIDs are unique (i.e.
- // no assetID is also used as an itemID elsewhere); therefore if the assetID
- // exists as an itemID in the user's inventory, then this must be a link.
- const LLInventoryItem *linked_item = gInventory.getItem(_assetID);
- if (linked_item)
- {
- assetID = linked_item->getAssetUUID();
- asset_type = linked_item->getType();
- }
llassert( (asset_type == LLAssetType::AT_CLOTHING) || (asset_type == LLAssetType::AT_BODYPART) );
LLWearable* instance = get_if_there(mList, assetID, (LLWearable*)NULL );
if( instance )
@@ -218,38 +205,19 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID
}
-LLWearable* LLWearableList::createCopyFromAvatar(const LLWearable* old_wearable, const std::string& new_name)
-{
- lldebugs << "LLWearableList::createCopyFromAvatar()" << llendl;
-
- LLWearable *wearable = generateNewWearable();
- 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);
-
- // Send to the dataserver
- wearable->saveNewAsset();
-
- return wearable;
-}
-
-
-LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable)
+LLWearable* LLWearableList::createCopy(const LLWearable* old_wearable, const std::string& new_name)
{
lldebugs << "LLWearableList::createCopy()" << llendl;
LLWearable *wearable = generateNewWearable();
wearable->copyDataFrom(old_wearable);
-
+
LLPermissions perm(old_wearable->getPermissions());
perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), LLUUID::null, true);
wearable->setPermissions(perm);
+ if (!new_name.empty()) wearable->setName(new_name);
+
// Send to the dataserver
wearable->saveNewAsset();
@@ -273,7 +241,6 @@ LLWearable* LLWearableList::createNewWearable( EWearableType type )
wearable->setPermissions(perm);
// Description and sale info have default values.
-
wearable->setParamsToDefaults();
wearable->setTexturesToDefaults();
diff --git a/indra/newview/llwearablelist.h b/indra/newview/llwearablelist.h
index f844c0f443..e5155c66a4 100644
--- a/indra/newview/llwearablelist.h
+++ b/indra/newview/llwearablelist.h
@@ -53,8 +53,7 @@ public:
void(*asset_arrived_callback)(LLWearable*, void* userdata),
void* userdata);
- LLWearable* createCopyFromAvatar(const LLWearable* old_wearable, const std::string& new_name = std::string());
- LLWearable* createCopy(const LLWearable* old_wearable);
+ LLWearable* createCopy(const LLWearable* old_wearable, const std::string& new_name = std::string());
LLWearable* createNewWearable(EWearableType type);
// Callback
diff --git a/indra/newview/llweb.cpp b/indra/newview/llweb.cpp
index 3204c2d264..72431bd22f 100644
--- a/indra/newview/llweb.cpp
+++ b/indra/newview/llweb.cpp
@@ -43,8 +43,9 @@
#include "llfloatermediabrowser.h"
#include "llfloaterreg.h"
#include "llalertdialog.h"
+#include "lltoastalertpanel.h"
-class URLLoader : public LLAlertDialog::URLLoader
+class URLLoader : public LLAlertURLLoader
{
virtual void load(const std::string& url , bool force_open_externally)
{
@@ -65,6 +66,7 @@ static URLLoader sAlertURLLoader;
void LLWeb::initClass()
{
LLAlertDialog::setURLLoader(&sAlertURLLoader);
+ LLToastAlertPanel::setURLLoader(&sAlertURLLoader);
}
diff --git a/indra/newview/llwldaycycle.cpp b/indra/newview/llwldaycycle.cpp
index 10a9703d1a..7f0c1a13f3 100644
--- a/indra/newview/llwldaycycle.cpp
+++ b/indra/newview/llwldaycycle.cpp
@@ -36,6 +36,7 @@
#include "llsdserialize.h"
#include "llwlparammanager.h"
#include "llnotifications.h"
+#include "llxmlnode.h"
#include <map>
diff --git a/indra/newview/llwlparammanager.cpp b/indra/newview/llwlparammanager.cpp
index 4bf64816c7..c6fd35c142 100644
--- a/indra/newview/llwlparammanager.cpp
+++ b/indra/newview/llwlparammanager.cpp
@@ -196,7 +196,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;
+ //llinfos << "Loading WindLight sky setting from " << pathName << llendl;
llifstream presetsXML;
presetsXML.open(pathName.c_str());
@@ -317,7 +317,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]);
diff --git a/indra/newview/llworldmap.cpp b/indra/newview/llworldmap.cpp
index b8ecd9556f..355d4141c3 100644
--- a/indra/newview/llworldmap.cpp
+++ b/indra/newview/llworldmap.cpp
@@ -37,7 +37,6 @@
#include "llregionhandle.h"
#include "message.h"
-#include "llappviewer.h" // for gPacificDaylightTime
#include "llagent.h"
#include "llmapresponders.h"
#include "llviewercontrol.h"
@@ -94,6 +93,13 @@ LLVector3d LLSimInfo::getGlobalPos(LLVector3 local_pos) const
return pos;
}
+LLVector3 LLSimInfo::getLocalPos(LLVector3d global_pos) const
+{
+ LLVector3d sim_origin = from_region_handle(mHandle);
+ return LLVector3(global_pos - sim_origin);
+}
+
+
//---------------------------------------------------------------------------
// World Map
@@ -519,7 +525,7 @@ void LLWorldMap::processMapLayerReply(LLMessageSystem* msg, void**)
LLWorldMapLayer new_layer;
new_layer.LayerDefined = TRUE;
msg->getUUIDFast(_PREHASH_LayerData, _PREHASH_ImageID, new_layer.LayerImageID, block);
- new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ new_layer.LayerImage = LLViewerTextureManager::getFetchedTexture(new_layer.LayerImageID, MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
gGL.getTexUnit(0)->bind(new_layer.LayerImage);
new_layer.LayerImage->setAddressMode(LLTexUnit::TAM_CLAMP);
@@ -634,14 +640,15 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**)
siminfo->mMapImageID[agent_flags] = image_id;
#ifdef IMMEDIATE_IMAGE_LOAD
- siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ siminfo->mCurrentImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[LLWorldMap::getInstance()->mCurrentMap],
+ MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
siminfo->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
#endif
if (siminfo->mMapImageID[2].notNull())
{
#ifdef IMMEDIATE_IMAGE_LOAD
- siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ siminfo->mOverlayImage = LLViewerTextureManager::getFetchedTexture(siminfo->mMapImageID[2], MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
#endif
}
else
diff --git a/indra/newview/llworldmap.h b/indra/newview/llworldmap.h
index 9daee38752..366de8f071 100644
--- a/indra/newview/llworldmap.h
+++ b/indra/newview/llworldmap.h
@@ -78,6 +78,7 @@ public:
LLSimInfo();
LLVector3d getGlobalPos(LLVector3 local_pos) const;
+ LLVector3 getLocalPos(LLVector3d global_pos) const;
public:
U64 mHandle;
diff --git a/indra/newview/llworldmapview.cpp b/indra/newview/llworldmapview.cpp
index 30736b1e03..9a249d14f8 100644
--- a/indra/newview/llworldmapview.cpp
+++ b/indra/newview/llworldmapview.cpp
@@ -47,7 +47,6 @@
#include "llcallingcard.h"
#include "llviewercontrol.h"
#include "llcylinder.h"
-#include "llfloaterdirectory.h"
#include "llfloatermap.h"
#include "llfloaterworldmap.h"
#include "llfocusmgr.h"
@@ -369,7 +368,7 @@ void LLWorldMapView::draw()
continue;
}
- current_image->setBoostLevel(LLViewerTexture::BOOST_MAP_LAYER);
+ current_image->setBoostLevel(LLViewerTexture::BOOST_MAP);
current_image->setKnownDrawSize(llround(pix_width * LLUI::sGLScaleFactor.mV[VX]), llround(pix_height * LLUI::sGLScaleFactor.mV[VY]));
if (!current_image->hasGLTexture())
@@ -512,7 +511,8 @@ void LLWorldMapView::draw()
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
- info->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ info->mCurrentImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[LLWorldMap::getInstance()->mCurrentMap],
+ MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
info->mCurrentImage->setAddressMode(LLTexUnit::TAM_CLAMP);
simimage = info->mCurrentImage;
gGL.getTexUnit(0)->bind(simimage);
@@ -525,7 +525,7 @@ void LLWorldMapView::draw()
(textures_requested_this_tick < MAX_REQUEST_PER_TICK)))
{
textures_requested_this_tick++;
- info->mOverlayImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[2], MIPMAP_TRUE, FALSE, LLViewerTexture::LOD_TEXTURE);
+ info->mOverlayImage = LLViewerTextureManager::getFetchedTexture(info->mMapImageID[2], MIPMAP_TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
info->mOverlayImage->setAddressMode(LLTexUnit::TAM_CLAMP);
overlayimage = info->mOverlayImage;
gGL.getTexUnit(0)->bind(overlayimage);
@@ -822,7 +822,7 @@ void LLWorldMapView::draw()
else
{
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, getString("Loading"), "");
}
@@ -1898,20 +1898,20 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask )
id.toString(uuid_str);
uuid_str = uuid_str.substr(28);
sscanf(uuid_str.c_str(), "%X", &event_id);
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "event").insert("id", event_id));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "events").insert("id", event_id));
break;
}
case MAP_ITEM_LAND_FOR_SALE:
case MAP_ITEM_LAND_FOR_SALE_ADULT:
{
LLFloaterReg::hideInstance("world_map");
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "land").insert("id", id));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "destinations").insert("id", id));
break;
}
case MAP_ITEM_CLASSIFIED:
{
LLFloaterReg::hideInstance("world_map");
- LLFloaterReg::showInstance("search", LLSD().insert("panel", "classified").insert("id", id));
+ LLFloaterReg::showInstance("search", LLSD().insert("category", "classifieds").insert("id", id));
break;
}
default:
diff --git a/indra/newview/llxmlrpclistener.cpp b/indra/newview/llxmlrpclistener.cpp
new file mode 100644
index 0000000000..af8cb6b9fb
--- /dev/null
+++ b/indra/newview/llxmlrpclistener.cpp
@@ -0,0 +1,496 @@
+/**
+ * @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()
+// other Linden headers
+#include "llerror.h"
+#include "stringize.h"
+#include "llxmlrpctransaction.h"
+
+#include <xmlrpc-epi/xmlrpc.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..70859e8ea5 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);
}
@@ -385,7 +398,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 +522,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 0fcdf2da4f..a71362a139 100644
--- a/indra/newview/macview_Prefix.h
+++ b/indra/newview/macview_Prefix.h
@@ -66,7 +66,6 @@
#include "llfloaterbuildoptions.h"
#include "llfloaterchat.h"
#include "llfloatercustomize.h"
-#include "llfloaterdirectory.h"
#include "llfloatergroups.h"
#include "llfloaterworldmap.h"
#include "llfloatermute.h"
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index c736d0ccc8..3390463aa6 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -35,7 +35,7 @@
#include "pipeline.h"
// library includes
-#include "llaudioengine.h" // For MAX_BUFFERS for debugging.
+#include "llaudioengine.h" // For debugging.
#include "imageids.h"
#include "llerror.h"
#include "llviewercontrol.h"
@@ -1474,7 +1474,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)
@@ -1797,6 +1797,7 @@ void LLPipeline::rebuildPriorityGroups()
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);
@@ -3872,44 +3873,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())
+ if (LLViewerObject* attached_object = (*attachment_iter))
{
- continue;
- }
-
- for (S32 j = 0; j < drawable->getNumFaces(); ++j)
- {
- 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);
+ }
+ }
+ }
}
- }
+ }
}
}
@@ -4289,7 +4294,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;
}
@@ -4475,7 +4480,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());
@@ -7903,6 +7908,7 @@ void LLPipeline::generateHighlight(LLCamera& camera)
mHighlight.flush();
gGL.setColorMask(true, false);
+ gViewerWindow->setup3DViewport();
}
}
@@ -8682,10 +8688,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(), *LLViewerCamera::getInstance());
+ }
}
}
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/viewerRes.rc b/indra/newview/res/viewerRes.rc
index 38570e1a7e..433070ce34 100644
--- a/indra/newview/res/viewerRes.rc
+++ b/indra/newview/res/viewerRes.rc
@@ -134,8 +134,8 @@ TOOLMEDIAOPEN CURSOR "toolmediaopen.cur"
//
VS_VERSION_INFO VERSIONINFO
- FILEVERSION 2,0,0,0
- PRODUCTVERSION 2,0,0,0
+ FILEVERSION 2,0,0,3256
+ PRODUCTVERSION 2,0,0,3256
FILEFLAGSMASK 0x3fL
#ifdef _DEBUG
FILEFLAGS 0x1L
@@ -152,12 +152,12 @@ BEGIN
BEGIN
VALUE "CompanyName", "Linden Lab"
VALUE "FileDescription", "Second Life"
- VALUE "FileVersion", "2.0.0.0"
+ VALUE "FileVersion", "2.0.0.3256"
VALUE "InternalName", "Second Life"
VALUE "LegalCopyright", "Copyright © 2001-2008, Linden Research, Inc."
VALUE "OriginalFilename", "SecondLife.exe"
VALUE "ProductName", "Second Life"
- VALUE "ProductVersion", "2.0.0.0"
+ VALUE "ProductVersion", "2.0.0.3256"
END
END
BLOCK "VarFileInfo"
diff --git a/indra/newview/skins/default/colors.xml b/indra/newview/skins/default/colors.xml
index 4d8f88c80b..572a4cf9e9 100644
--- a/indra/newview/skins/default/colors.xml
+++ b/indra/newview/skins/default/colors.xml
@@ -66,6 +66,9 @@
name="Blue"
value="0 0 1 1" />
<color
+ name="Yellow"
+ value="1 1 0 1" />
+ <color
name="Unused?"
value="1 0 1 1" />
<color
@@ -305,6 +308,9 @@
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
@@ -405,10 +411,10 @@
reference="White" />
<color
name="MapAvatarColor"
- reference="White" />
+ reference="Green" />
<color
name="MapAvatarFriendColor"
- reference="Unused?" />
+ reference="Yellow" />
<color
name="MapAvatarSelfColor"
value="0.53125 0 0.498047 1" />
@@ -567,7 +573,7 @@
reference="White_05" />
<color
name="ScrollDisabledColor"
- reference="Unused?" />
+ reference="White_25" />
<color
name="ScrollHighlightedColor"
reference="Unused?" />
@@ -645,7 +651,7 @@
value="0 0 0 .33" />
<color
name="TimeTextColor"
- reference="LtGray_50" />
+ reference="LtGray" />
<color
name="TitleBarFocusColor"
reference="White_10" />
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..5f3426eb60
--- /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..44a621b216
--- /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/loading/loading.html b/indra/newview/skins/default/html/en-us/loading/loading.html
index 34e5c84c4d..1c62d2f73e 100644
--- a/indra/newview/skins/default/html/en-us/loading/loading.html
+++ b/indra/newview/skins/default/html/en-us/loading/loading.html
@@ -1,9 +1,9 @@
-<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="sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;loading...
- </td>
- </tr>
-</table>
-</body>
+<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="sl_logo_rotate_black.gif" align="absmiddle"><br/>&nbsp;&nbsp;&nbsp;loading...
+ </td>
+ </tr>
+</table>
+</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..c4260b34c0
--- /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..b3953448e9
--- /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..ab15a073ba
--- /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..ab37e41f04
--- /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..35cf74a35f
--- /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..0215bd7e47
--- /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..50f3dfb0c5
--- /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..a83e1123d0
--- /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..892c0b9f7f
--- /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..1ac07bff34
--- /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..3b5b8679b4
--- /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..d1d5d25c92
--- /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/bottomtray/Notices_Unread.png b/indra/newview/skins/default/textures/bottomtray/Notices_Unread.png
new file mode 100644
index 0000000000..98f1f04b9a
--- /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
index 6f2726c3e6..d7ec04237b 100644
--- a/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.png
+++ b/indra/newview/skins/default/textures/bottomtray/Snapshot_Off.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/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/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/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/Inv_Alpha.png b/indra/newview/skins/default/textures/icons/Inv_Alpha.png
new file mode 100644
index 0000000000..e8d246c6fa
--- /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
index 8b69434066..ab42c61a92 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Animation.png
+++ 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
index 9d98bfaa7d..97e874d70d 100644
--- a/indra/newview/skins/default/textures/icons/Inv_BodyShape.png
+++ b/indra/newview/skins/default/textures/icons/Inv_BodyShape.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
index 49a54b82e1..e8d246c6fa 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Clothing.png
+++ 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
index 6d0321dde9..e619f56c2b 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Eye.png
+++ 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
index 30aa6e04ac..342a973d00 100644
--- a/indra/newview/skins/default/textures/icons/Inv_FolderClosed.png
+++ 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
index 792ef446e8..0507c2cbaf 100644
--- a/indra/newview/skins/default/textures/icons/Inv_FolderOpen.png
+++ 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
index c49ae523c8..52695ec19b 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Gesture.png
+++ 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
index d81bc961d4..d6a2113aaf 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Gloves.png
+++ 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
index 5e68f1ffea..ae941b0dd5 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Hair.png
+++ 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
index 0e28f45f19..3859666f7c 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Jacket.png
+++ 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
index 6648a23393..f8ce765c50 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Landmark.png
+++ b/indra/newview/skins/default/textures/icons/Inv_Landmark.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
index 830a71311f..4645ab8e91 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Notecard.png
+++ 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
index a88d0dc4b3..f883696a82 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Object.png
+++ 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
index 2527f7f9c3..fe2389f074 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Pants.png
+++ 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
index e9c9b163fd..0fba27a7aa 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Script.png
+++ 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
index 7cc880a124..81c1538dd2 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Shirt.png
+++ 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
index 0b148647eb..51e1c7bbb7 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Shoe.png
+++ 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
index 8e20638bba..b7da922046 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Skin.png
+++ 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
index 40860a3599..246e9a87aa 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Skirt.png
+++ 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
index 17e710a843..39efd2be1b 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Snapshot.png
+++ 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
index b8169dcb36..30d7d7c239 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Socks.png
+++ 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
index 1a50dd17da..44c271c868 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Sound.png
+++ 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..e8d246c6fa
--- /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
index 2d6d1b54bb..dbc41c5e99 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Texture.png
+++ 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
index 77f56c574f..b1e7c2a55f 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Underpants.png
+++ 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
index 954eab7660..9340dbb975 100644
--- a/indra/newview/skins/default/textures/icons/Inv_Undershirt.png
+++ b/indra/newview/skins/default/textures/icons/Inv_Undershirt.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/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/navbar/BuyArrow_Over.png b/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
index 7c10aaaead..41cb88628a 100644
--- a/indra/newview/skins/default/textures/navbar/BuyArrow_Over.png
+++ 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
index 9d7716c6de..a02675502a 100644
--- a/indra/newview/skins/default/textures/navbar/BuyArrow_Press.png
+++ 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/Search.png b/indra/newview/skins/default/textures/navbar/Search.png
index c43519d5f1..0d0e330bc7 100644
--- a/indra/newview/skins/default/textures/navbar/Search.png
+++ b/indra/newview/skins/default/textures/navbar/Search.png
Binary files differ
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index 2c09689ec6..cf7ab46dd5 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -6,6 +6,8 @@
<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" />
@@ -27,9 +29,9 @@
<texture name="BottomTray_BG" file_name="bottomtray/BottomTray_BG.png" preload="false" />
- <texture name="BuyArrow_Off" file_name="navbar/BuyArrow_Off.png" preload="false" />
- <texture name="BuyArrow_Over" file_name="navbar/BuyArrow_Over.png" preload="false" />
- <texture name="BuyArrow_Press" file_name="navbar/BuyArrow_Press.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" />
@@ -65,8 +67,9 @@
<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_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" />
@@ -88,15 +91,20 @@
<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" />
+ <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="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="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" />
@@ -139,12 +147,15 @@
<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" />
+ <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="Inv_Acessories" file_name="icons/Inv_Acessories.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" />
@@ -157,6 +168,8 @@
<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_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" />
@@ -169,6 +182,7 @@
<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" />
@@ -222,6 +236,8 @@
<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="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" />
@@ -249,6 +265,42 @@
<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_drk_Build" file_name="icons/parcel_drk_Build.png" preload="false" />
+ <texture name="parcel_drk_BuildNo" file_name="icons/parcel_drk_BuildNo.png" preload="false" />
+ <texture name="parcel_drk_Damage" file_name="icons/parcel_drk_Damage.png" preload="false" />
+ <texture name="parcel_drk_DamageNo" file_name="icons/parcel_drk_DamageNo.png" preload="false" />
+ <texture name="parcel_drk_Fly" file_name="icons/parcel_drk_Fly.png" preload="false" />
+ <texture name="parcel_drk_FlyNo" file_name="icons/parcel_drk_FlyNo.png" preload="false" />
+ <texture name="parcel_drk_ForSale" file_name="icons/parcel_drk_ForSale.png" preload="false" />
+ <texture name="parcel_drk_ForSaleNo" file_name="icons/parcel_drk_ForSaleNo.png" preload="false" />
+ <texture name="parcel_drk_M" file_name="icons/parcel_drk_M.png" preload="false" />
+ <texture name="parcel_drk_PG" file_name="icons/parcel_drk_PG.png" preload="false" />
+ <texture name="parcel_drk_Push" file_name="icons/parcel_drk_Push.png" preload="false" />
+ <texture name="parcel_drk_PushNo" file_name="icons/parcel_drk_PushNo.png" preload="false" />
+ <texture name="parcel_drk_R" file_name="icons/parcel_drk_R.png" preload="false" />
+ <texture name="parcel_drk_Scripts" file_name="icons/parcel_drk_Scripts.png" preload="false" />
+ <texture name="parcel_drk_ScriptsNo" file_name="icons/parcel_drk_ScriptsNo.png" preload="false" />
+ <texture name="parcel_drk_Voice" file_name="icons/parcel_drk_Voice.png" preload="false" />
+ <texture name="parcel_drk_VoiceNo" file_name="icons/parcel_drk_VoiceNo.png" preload="false" />
+
+ <texture name="parcel_lght_Build" file_name="icons/parcel_lght_Build.png" preload="false" />
+ <texture name="parcel_lght_BuildNo" file_name="icons/parcel_lght_BuildNo.png" preload="false" />
+ <texture name="parcel_lght_Damage" file_name="icons/parcel_lght_Damage.png" preload="false" />
+ <texture name="parcel_lght_DamageNo" file_name="icons/parcel_lght_DamageNo.png" preload="false" />
+ <texture name="parcel_lght_Fly" file_name="icons/parcel_lght_Fly.png" preload="false" />
+ <texture name="parcel_lght_FlyNo" file_name="icons/parcel_lght_FlyNo.png" preload="false" />
+ <texture name="parcel_lght_ForSale" file_name="icons/parcel_lght_ForSale.png" preload="false" />
+ <texture name="parcel_lght_ForSaleNo" file_name="icons/parcel_lght_ForSaleNo.png" preload="false" />
+ <texture name="parcel_lght_M" file_name="icons/parcel_lght_M.png" preload="false" />
+ <texture name="parcel_lght_PG" file_name="icons/parcel_lght_PG.png" preload="false" />
+ <texture name="parcel_lght_Push" file_name="icons/parcel_lght_Push.png" preload="false" />
+ <texture name="parcel_lght_PushNo" file_name="icons/parcel_lght_PushNo.png" preload="false" />
+ <texture name="parcel_lght_R" file_name="icons/parcel_lght_R.png" preload="false" />
+ <texture name="parcel_lght_Scripts" file_name="icons/parcel_lght_Scripts.png" preload="false" />
+ <texture name="parcel_lght_ScriptsNo" file_name="icons/parcel_lght_ScriptsNo.png" preload="false" />
+ <texture name="parcel_lght_Voice" file_name="icons/parcel_lght_Voice.png" preload="false" />
+ <texture name="parcel_lght_VoiceNo" file_name="icons/parcel_lght_VoiceNo.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" />
@@ -329,7 +381,7 @@
<texture name="SliderThumb_Disabled" file_name="widgets/SliderThumb_Disabled.png" />
<texture name="SliderThumb_Press" file_name="widgets/SliderThumb_Press.png" />
- <texture name="Snapshot_Off" file_name="bottomtray/Snapshot_Off.png" preload="false" />
+ <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" />
@@ -349,6 +401,10 @@
<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_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_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" />
@@ -392,7 +448,8 @@
<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="Toast_CloseBtn" file_name="windows/Toast_CloseBtn.png" preload="true" />
- <texture name="Toast" file_name="windows/Toast.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="Tool_Create" file_name="build/Tool_Create.png" preload="false" />
<texture name="Tool_Dozer" file_name="build/Tool_Dozer.png" preload="false" />
@@ -425,16 +482,24 @@
<texture name="VoicePTT_On" file_name="bottomtray/VoicePTT_On.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" />
- <texture name="Window_Foreground" file_name="windows/Window_Foreground.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" />
<!--WARNING OLD ART *do not use*-->
+ <texture name="Banner_ForSale" file_name="Banner_ForSale.png" preload="false" />
+ <texture name="Banner_YouAreHere" file_name="Banner_YouAreHere.png" preload="false" />
+
<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" />
@@ -444,8 +509,6 @@
<texture name="cam_zoom_plus_in.tga" preload="false" />
<texture name="cam_zoom_minus_in.tga" preload="false" />
- <texture name="icn_clear_lineeditor.tga" />
-
<texture name="icn_chatbar.tga" />
<texture name="icn_media-pause.tga" />
<texture name="icn_media-play.tga" />
@@ -481,15 +544,6 @@
<texture name="move_down_in.tga" preload="false" />
<texture name="move_down_out.tga" preload="false" />
- <texture name="tool_grab.tga" />
- <texture name="tool_grab_active.tga" />
-
- <texture name="tool_face.tga" />
- <texture name="tool_face_active.tga" />
-
- <texture name="tool_create.tga" />
- <texture name="tool_create_active.tga" />
-
<texture name="up_arrow.tga" file_name="up_arrow.png" />
<texture name="down_arrow.tga" file_name="down_arrow.png" />
@@ -528,7 +582,6 @@
<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" />
@@ -555,54 +608,6 @@
<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_current_outfit.tga" />
- <texture name="inv_folder_gesture.tga" />
- <texture name="inv_folder_landmark.tga" />
- <texture name="inv_folder_lostandfound.tga" />
- <texture name="inv_folder_my_outfits.tga" />
- <texture name="inv_folder_notecard.tga" />
- <texture name="inv_folder_object.tga" />
- <texture name="inv_folder_outfit.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_linkitem.tga" />
- <texture name="inv_item_linkfolder.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" />
@@ -629,37 +634,6 @@
<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" />
@@ -675,11 +649,6 @@
<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" />
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/windows/Inspector_Background.png b/indra/newview/skins/default/textures/windows/Inspector_Background.png
index 807e8e553c..4c2a728ac5 100644
--- a/indra/newview/skins/default/textures/windows/Inspector_Background.png
+++ b/indra/newview/skins/default/textures/windows/Inspector_Background.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/Window_Background.png b/indra/newview/skins/default/textures/windows/Window_Background.png
index e9f15e76b9..db253900af 100644
--- a/indra/newview/skins/default/textures/windows/Window_Background.png
+++ 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
index e76e9f3c79..b81ec5b43c 100644
--- a/indra/newview/skins/default/textures/windows/Window_Foreground.png
+++ 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/xui/da/floater_about.xml b/indra/newview/skins/default/xui/da/floater_about.xml
index 81d4d3fdfd..f0c9c45d04 100644
--- a/indra/newview/skins/default/xui/da/floater_about.xml
+++ b/indra/newview/skins/default/xui/da/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Om [APP_NAME]">
+<floater name="floater_about" title="OM [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 c4cf722159..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Om land">
+<floater name="floaterland" title="OM LAND">
<tab_container name="landtab">
<panel label="Generelt" name="land_general_panel">
<text name="Name:">
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 f93f0a3525..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Vælg beboer">
+<floater name="avatarpicker" title="VÆLG BEBOER">
<tab_container name="ResidentChooserTabs">
<panel label="Søg" name="SearchPanel">
<text name="InstructSearchResidentName">
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 318a23df4c..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" />
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 3b3e14ad64..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Gitter indstillinger">
+<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" />
diff --git a/indra/newview/skins/default/xui/da/floater_bulk_perms.xml b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml
index 77ae7fe060..9cf44d6479 100644
--- a/indra/newview/skins/default/xui/da/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/da/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Masse-ændring af rettigheder på indhold">
+<floater name="floaterbulkperms" title="MASSE-ÆNDRING AF RETTIGHEDER PÅ INDHOLD">
<text name="applyto">
Indholdstyper
</text>
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 1c5876572b..a2b6dec91c 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>
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 1d42ffb45a..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy land" title="Køb land">
+<floater name="buy land" title="KØB LAND">
<text name="region_name_label">
Region:
</text>
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_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 c8e1fc813b..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>
diff --git a/indra/newview/skins/default/xui/da/floater_customize.xml b/indra/newview/skins/default/xui/da/floater_customize.xml
index b434bea1ce..b2409f1682 100644
--- a/indra/newview/skins/default/xui/da/floater_customize.xml
+++ b/indra/newview/skins/default/xui/da/floater_customize.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Appearance" width="509">
+<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">
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 0ca7874c37..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,5 +1,5 @@
<?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" />
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 907771c67a..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Redigering af omgivelser">
+<floater name="Environment Editor Floater" title="REDIGERING AF OMGIVELSER">
<text name="EnvTimeText">
Tid på dagen
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_font_test.xml b/indra/newview/skins/default/xui/da/floater_font_test.xml
index 7d8ef1b310..591d07188c 100644
--- a/indra/newview/skins/default/xui/da/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/da/floater_font_test.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="contents" title="Font test">
+<floater name="contents" title="FONT TEST">
<text name="linea">
OverrideTest, skal vises her som fonten &apos;Times&apos;. (Fra default/xui/en-us)
</text>
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 dcc1b8d2e8..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Hardware opsætning">
+<floater name="Hardware Settings Floater" title="HARDWARE OPSÆTNING">
<text name="Filtering:">
Filtrering:
</text>
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_inspect.xml b/indra/newview/skins/default/xui/da/floater_inspect.xml
index 56c3f6f784..0610e9408f 100644
--- a/indra/newview/skins/default/xui/da/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/da/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Inspecér objekter">
+<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"/>
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 9f28440fb0..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>
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 60a7d78aea..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" />
diff --git a/indra/newview/skins/default/xui/da/floater_joystick.xml b/indra/newview/skins/default/xui/da/floater_joystick.xml
index 280650a04b..4954b7b619 100644
--- a/indra/newview/skins/default/xui/da/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/da/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Joystick opsætning">
+<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"/>
diff --git a/indra/newview/skins/default/xui/da/floater_lagmeter.xml b/indra/newview/skins/default/xui/da/floater_lagmeter.xml
index 7e7c2dc0d3..bcf15ea926 100644
--- a/indra/newview/skins/default/xui/da/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/da/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Lag måler">
+<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:
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 bd623e7b75..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="land holdings floater" title="Mit land">
+<floater name="land holdings floater" title="MIT LAND">
<scroll_list name="parcel list">
<column label="Navn" name="name"/>
<column label="Region" name="location"/>
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 d345409859..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,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="Følg markøreren" name="lock_check" />
<combo_box label="LÃ¥s" name="history_combo" left_delta="114" width="70"/>
<button label="Tilbage" name="back_btn" />
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_mute_object.xml b/indra/newview/skins/default/xui/da/floater_mute_object.xml
index e64557b177..4145918b49 100644
--- a/indra/newview/skins/default/xui/da/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/da/floater_mute_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="Bloker objekt via navn">
+<floater name="mute by name" title="BLOKER OBJEKT VIA NAVN">
<text name="message">
Blokering via navn har ikke betydning for lyde.
Du skal skrive det præcise navn på objektet.
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 d37e3177fa..5875b7a967 100644
--- a/indra/newview/skins/default/xui/da/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/da/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Objekt indhold">
+<floater name="objectcontents" title="OBJEKT INDHOLD">
<text name="object_name">
[DESC]:
</text>
diff --git a/indra/newview/skins/default/xui/da/floater_perm_prefs.xml b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml
index f4b9b0a664..69a8d3af94 100644
--- a/indra/newview/skins/default/xui/da/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/da/floater_perm_prefs.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="perm prefs" title="Standard tilladelser ved hentning">
+<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"/>
diff --git a/indra/newview/skins/default/xui/da/floater_postcard.xml b/indra/newview/skins/default/xui/da/floater_postcard.xml
index 24d45062ae..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>
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_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_notecard.xml b/indra/newview/skins/default/xui/da/floater_preview_notecard.xml
index 68d04d6f9b..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview notecard" title="Note:">
+<floater name="preview notecard" title="NOTE:">
<button label="Gem" label_selected="Gem" name="Save"/>
<text name="desc txt">
Beskrivelse:
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 01f152c43a..6f1e2884eb 100644
--- a/indra/newview/skins/default/xui/da/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/da/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Rapportér misbrug">
+<floater name="floater_report_abuse" title="RAPPORTÉR MISBRUG">
<texture_picker label="" name="screenshot"/>
<check_box label="Inkludér billede" name="screen_check"/>
<text name="reporter_title">
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 6990e8db0e..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Script: Rotation Script">
+<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT">
<text name="desc txt">
Beskrivelse:
</text>
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 d4dae8951f..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,5 +1,5 @@
<?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" />
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 87023b4f64..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,5 @@
<?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">
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 60f99deae2..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,5 +1,5 @@
<?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_box.item name="TRUE" label="TRUE (Valgt)" />
<combo_box.item name="FALSE" label="FALSE (Fravalgt)" />
diff --git a/indra/newview/skins/default/xui/da/floater_snapshot.xml b/indra/newview/skins/default/xui/da/floater_snapshot.xml
index d7a5179890..3eed869db4 100644
--- a/indra/newview/skins/default/xui/da/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/da/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Se foto">
+<floater name="Snapshot" title="SE FOTO">
<text name="type_label">
Hvor skal foto hen?
</text>
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 606d290e1d..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="Sound Preview" 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
index 0443553d50..8c33f3ecb3 100644
--- a/indra/newview/skins/default/xui/da/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/da/floater_statistics.xml
@@ -1,2 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="stats floater" title="Statistik"/>
+<floater name="stats floater" title="STATISTIK"/>
diff --git a/indra/newview/skins/default/xui/da/floater_telehub.xml b/indra/newview/skins/default/xui/da/floater_telehub.xml
index cd1fb33831..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>
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 c35e3aec4c..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/da/floater_tools.xml b/indra/newview/skins/default/xui/da/floater_tools.xml
index f653feea2d..c3287bac84 100644
--- a/indra/newview/skins/default/xui/da/floater_tools.xml
+++ b/indra/newview/skins/default/xui/da/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Byg">
+<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"/>
@@ -464,7 +464,7 @@
Område: [AREA] m².
</text>
<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"/>
+ <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
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_water.xml b/indra/newview/skins/default/xui/da/floater_water.xml
index 33a10579ab..63880b4a69 100644
--- a/indra/newview/skins/default/xui/da/floater_water.xml
+++ b/indra/newview/skins/default/xui/da/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Avanceret opsætning af vand">
+<floater name="Water Floater" title="AVANCERET OPSÆTNING AF VAND">
<text name="KeyFramePresetsText">
Vand opsætninger:
</text>
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 9754b1f074..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Avanceret opsætning for himmel">
+<floater name="WindLight floater" title="AVANCERET OPSÆTNING FOR HIMMEL">
<text name="KeyFramePresetsText">
Faste indstillinger:
</text>
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 d4b58f6232..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Verdenskort">
+<floater name="worldmap" title="VERDENSKORT">
<tab_container name="maptab">
<panel label="Objekter" name="objects_mapview"/>
<panel label="Terræn" name="terrain_mapview"/>
diff --git a/indra/newview/skins/default/xui/da/notifications.xml b/indra/newview/skins/default/xui/da/notifications.xml
index 5ab8e4eb30..42f55d4678 100644
--- a/indra/newview/skins/default/xui/da/notifications.xml
+++ b/indra/newview/skins/default/xui/da/notifications.xml
@@ -1079,7 +1079,7 @@ Fleksible genstande er ikke fysiske og man kan gå igennem dem, indtil fleksibel
<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 &#8984;-Opt-Shift-D.
+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.
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..b4d0fa20ef
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/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="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_preferences_alerts.xml b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
new file mode 100644
index 0000000000..c7a49ef307
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_alerts.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Popups" name="popups" title="Popups">
+ <text name="dont_show_label">
+ Vis ikke disse popups:
+ </text>
+ <button label="Aktivér denne popup" name="enable_popup" />
+ <button label="Aktivér alle popups..." name="reset_dialogs_btn"
+ tool_tip="Viser alle de valgfrie popups og &apos;første gangs&apos; beskeder." />
+ <text name="show_label">
+ Vis disse popups:
+ </text>
+ <button label="Deaktivér alle disse popups..." name="skip_dialogs_btn"
+ tool_tip="Viser ingen af de valgfrie popups og &apos;første gangs&apos; beskeder." />
+ <text name="text_box2" width="310">
+ Ved tilbud om tekstdokumenter, teksturer og landemærker:
+ </text>
+ <check_box label="Accepter automatisk" name="accept_new_inventory" />
+ <check_box label="Vis automatisk efter accept" name="show_new_inventory" />
+ <check_box label="Vis nye objekter i beholdning automatisk" name="show_in_inventory" />
+</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..d50c05a192
--- /dev/null
+++ b/indra/newview/skins/default/xui/da/panel_preferences_sound.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Lyd &amp; video" name="Preference Media panel">
+ <slider label="Generel" name="System Volume"/>
+ <slider label="Omgivelser" name="Wind Volume"/>
+ <slider label="Effekter" name="SFX Volume"/>
+ <slider label="Media" name="Media Volume"/>
+ <slider label="Brugerflade" name="UI Volume"/>
+ <slider label="Musik" name="Music Volume"/>
+ <slider label="Tale" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Stemme chat er ikke tilgængelig
+ </text_editor>
+ <check_box label="Aktivér stemme chat" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Hør stemmer fra kamera position" />
+ <radio_item name="1" label="Hør stemmer fra avatar position" />
+ </radio_group>
+ <button label="Enheds Indstillinger" name="device_settings_btn"/>
+ <text name="muting_text">
+ Lydstyrke:
+ </text>
+ <text name="streaming_prefs_text">
+ Streaming indstillinger:
+ </text>
+ <text name="audio_prefs_text">
+ Lyd indstillinger:
+ </text>
+ <panel label="Lydstyrke" name="Volume Panel" />
+ <check_box label="Afspil musik når det er muligt"
+ name="streaming_music" />
+ <check_box label="Afspil video når det er muligt"
+ name="streaming_video" />
+ <check_box label="Afspil automatisk medie" name="auto_streaming_video" />
+ <check_box label="Sluk lyd når vinduet er minimeret" name="mute_when_minimized" />
+ <slider label="Doppler effekt" name="Doppler Effect" />
+ <slider label="Rækkevidde" name="Distance Factor" />
+ <slider label="Styrkefald/afstand" name="Rolloff Factor" />
+ <spinner label="Penge lydstyrke" name="L$ Change Threshold" />
+ <spinner label="Livspoint lydstyrke" name="Health Change Threshold" />
+</panel>
diff --git a/indra/newview/skins/default/xui/da/strings.xml b/indra/newview/skins/default/xui/da/strings.xml
index 9849f2f56d..945833d57a 100644
--- a/indra/newview/skins/default/xui/da/strings.xml
+++ b/indra/newview/skins/default/xui/da/strings.xml
@@ -484,16 +484,16 @@
Vælg bibliotek
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -603,6 +603,9 @@
<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>
@@ -621,4 +624,31 @@
<string name="close_on_no_ability">
Du har ikke længere mulighed for at deltage i samtalen
</string>
+ <string name="AcctTypeResident">
+ Beboer
+ </string>
+ <string name="AcctTypeTrial">
+ På prøve
+ </string>
+ <string name="AcctTypeCharterMember">
+ æresmedlem
+ </string>
+ <string name="AcctTypeEmployee">
+ Linden Lab medarbejder
+ </string>
+ <string name="PaymentInfoUsed">
+ Betalende medlem
+ </string>
+ <string name="PaymentInfoOnFile">
+ Registreret betalende
+ </string>
+ <string name="NoPaymentInfoOnFile">
+ Ingen betalingsinfo
+ </string>
+ <string name="AgeVerified">
+ Alders-checket
+ </string>
+ <string name="NotAgeVerified">
+ Ikke alders-checket
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/de/floater_about.xml b/indra/newview/skins/default/xui/de/floater_about.xml
index d36f5a43f6..6e51fe3e2d 100644
--- a/indra/newview/skins/default/xui/de/floater_about.xml
+++ b/indra/newview/skins/default/xui/de/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Ãœber [APP_NAME]">
+<floater name="floater_about" title="ÃœBER [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 853302d15c..ceb831c12d 100644
--- a/indra/newview/skins/default/xui/de/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_about_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="Land-Info">
+<floater name="floaterland" title="LAND-INFO">
<tab_container name="landtab">
<panel label="Allgemein" name="land_general_panel">
<text name="Name:">
diff --git a/indra/newview/skins/default/xui/de/floater_auction.xml b/indra/newview/skins/default/xui/de/floater_auction.xml
index 42f6a07dc3..9d0db766c9 100644
--- a/indra/newview/skins/default/xui/de/floater_auction.xml
+++ b/indra/newview/skins/default/xui/de/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Linden-Landverkauf starten">
+<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" />
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..e1ea792694 100644
--- a/indra/newview/skins/default/xui/de/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/de/floater_avatar_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Einwohner auswählen">
+<floater name="avatarpicker" title="EINWOHNER AUSWÄHLEN">
<tab_container name="ResidentChooserTabs">
<panel label="Suchen" name="SearchPanel">
<text name="InstructSearchResidentName">
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..3072735c66 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,5 @@
<?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">
<text name="label">
Gebackene Texturen
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_beacons.xml b/indra/newview/skins/default/xui/de/floater_beacons.xml
index 0992727e73..58e2e2681f 100644
--- a/indra/newview/skins/default/xui/de/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/de/floater_beacons.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="beacons" title="Beacons">
+<floater name="beacons" title="BEACONS">
<panel name="beacons_panel">
<check_box label="Auf Berührung beschränkte Skriptobjekte" name="touch_only"/>
<check_box label="Skripting-Objekte" name="scripted"/>
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..58f117f6b1 100644
--- a/indra/newview/skins/default/xui/de/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/de/floater_build_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Rasteroptionen">
+<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" />
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..fff6aa4b73 100644
--- a/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/de/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Mehrere Inhaltsberechtigungen ändern">
+<floater name="floaterbulkperms" title="MEHRERE INHALTSBERECHTIGUNGEN ÄNDERN">
<text name="applyto">
Inhaltsarten
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_bumps.xml b/indra/newview/skins/default/xui/de/floater_bumps.xml
index 7b21042c2b..b7909bf02d 100644
--- a/indra/newview/skins/default/xui/de/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/de/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Rempler, Stöße und Schläge">
+<floater name="floater_bumps" title="REMPLER, STÖßE UND SCHLÄGE">
<text name="none_detected">
Nicht erkannt
</text>
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..47ea6a1bd4 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_contents.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_buy_contents" title="Inhalte kaufen" min_width="300">
+<floater name="floater_buy_contents" title="INHALTE KAUFEN" min_width="300">
<text name="contains_text">
[NAME] enthält:
</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..05750a1782 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="buy currency" title="Geld kaufen">
+<floater name="buy currency" title="GELD KAUFEN">
<text name="info_buying">
Kaufe Geld:
</text>
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 e0abf8fae9..72a35db78c 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>
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..df6bf76240 100644
--- a/indra/newview/skins/default/xui/de/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/de/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="contents" title="Objektkopie kaufen">
+<floater name="contents" title="OBJEKTKOPIE KAUFEN">
<text name="contents_text">
samt Inhalt:
</text>
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..398645347b 100644
--- a/indra/newview/skins/default/xui/de/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/de/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Gruppen">
+<floater name="groups" title="GRUPPEN">
<text name="groupdesc">
Gruppe wählen:
</text>
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 fa2f616249..47f256918a 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">
+<floater name="ColorPicker" title="FARBAUSWAHL">
<text name="r_val_text">
Rot:
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_customize.xml b/indra/newview/skins/default/xui/de/floater_customize.xml
index 06b53dd8b4..f1ecd21c01 100644
--- a/indra/newview/skins/default/xui/de/floater_customize.xml
+++ b/indra/newview/skins/default/xui/de/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Körperteile" name="body_parts_placeholder"/>
<panel label="Form" name="Shape">
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..9108f3c2e5 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" />
+<floater name="floater_device_settings" title="GERÄTE-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..c9afcc8471 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,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Umwelt-Editor">
+<floater name="Environment Editor Floater" title="UMWELT-EDITOR">
<text name="EnvTimeText">
Tageszeit
</text>
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..522d966431 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="SCHRIFTART-TEST">
<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..aff0a9b92d 100644
--- a/indra/newview/skins/default/xui/de/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/de/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Aktive Gesten">
+<floater name="gestures" title="AKTIVE GESTEN">
<text name="help_label">
Doppelklicken Sie auf eine Geste, um Animationen und Sound &#10;abzuspielen.
</text>
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 c7cfb5d9d3..f93a9b9476 100644
--- a/indra/newview/skins/default/xui/de/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/de/floater_god_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="godtools floater" title="Gott-Werkzeuge">
+<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"
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 4051776b0d..68f7d6872e 100644
--- a/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/de/floater_hardware_settings.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Hardware-Einstellungen">
+<floater name="Hardware Settings Floater" title="HARDWARE-EINSTELLUNGEN">
<text name="Filtering:">
Filtern:
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_hud.xml b/indra/newview/skins/default/xui/de/floater_hud.xml
index 0f11e2346d..18584e57ca 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" />
+<floater name="floater_hud" title="TUTORIAL" />
diff --git a/indra/newview/skins/default/xui/de/floater_inspect.xml b/indra/newview/skins/default/xui/de/floater_inspect.xml
index f8c9b62824..f9421788bd 100644
--- a/indra/newview/skins/default/xui/de/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/de/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="Objekt prüfen" min_width="450" >
+<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" />
diff --git a/indra/newview/skins/default/xui/de/floater_inventory.xml b/indra/newview/skins/default/xui/de/floater_inventory.xml
index c8c67240d8..6444e87882 100644
--- a/indra/newview/skins/default/xui/de/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/de/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory" title="Inventar">
+<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" />
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 3e79a31abd..ef85efdae0 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,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="item properties" title="Inventarobjekt-Eigenschaften">
+<floater name="item properties" title="INVENTAROBJEKT-EIGENSCHAFTEN">
<text name="LabelItemNameTitle">
Name:
</text>
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 2f2eb5aa8d..8dfffe06d1 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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Inventory Finder" title="inventar_letzte_objekte">
+<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" />
diff --git a/indra/newview/skins/default/xui/de/floater_joystick.xml b/indra/newview/skins/default/xui/de/floater_joystick.xml
index ccf6f14ead..9507d063d1 100644
--- a/indra/newview/skins/default/xui/de/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/de/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Joystick-Konfiguration">
+<floater name="Joystick" title="JOYSTICK-KONFIGURATION">
<check_box name="enable_joystick" width="80" label="Joystick aktivieren:"/>
<text left="140" name="joystick_type" width="360"/>
<spinner label="X-Achse" name="JoystickAxis1"/>
diff --git a/indra/newview/skins/default/xui/de/floater_lagmeter.xml b/indra/newview/skins/default/xui/de/floater_lagmeter.xml
index 4dd9fd6c76..9468557fc4 100644
--- a/indra/newview/skins/default/xui/de/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/de/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_lagmeter" title="Lag-Anzeige">
+<floater name="floater_lagmeter" title="LAG-ANZEIGE">
<button name="client_lagmeter" tool_tip="Client-Lag-Status" />
<text name="client">
Client:
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..3975211117 100644
--- a/indra/newview/skins/default/xui/de/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/de/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?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="Region" name="location"/>
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..5afeb03395 100644
--- a/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/de/floater_live_lsleditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Skript: Neues Skript">
+<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" />
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..dd6d559c40 100644
--- a/indra/newview/skins/default/xui/de/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/de/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="Cursor folgen" name="lock_check" />
<combo_box label="Sperren" name="history_combo" />
<button label="Zurück" name="back_btn" />
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..a16c2408fe 100644
--- a/indra/newview/skins/default/xui/de/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/de/floater_media_browser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_about" title="Medienbrowser">
+<floater name="floater_about" title="MEDIENBROWSER">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Zurück" name="back" />
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..44249a6075 100644
--- a/indra/newview/skins/default/xui/de/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/de/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Speicherverlust-Simulation">
+<floater name="MemLeak" title="SPEICHERVERLUST-SIMULATION">
<spinner label="Verlustgeschwindigkeit (Bytes pro Frame):" name="leak_speed" />
<spinner label="Max. Speicherverlust (MB):" name="max_leak" />
<text name="total_leaked_label">
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 60c6ff008c..8cc8a56523 100644
--- a/indra/newview/skins/default/xui/de/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/de/floater_mute_object.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="mute by name" title="Objekt nach Name stummschalten">
+<floater name="mute by name" title="OBJEKT NACH NAME STUMMSCHALTEN">
<text name="message">
Stummschalten nach Name betrifft nur Chat und IM, keine
Sounds. Sie müssen den Objektnamen exakt angeben.
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..30614b7578 100644
--- a/indra/newview/skins/default/xui/de/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/de/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Kontakte">
+<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" />
diff --git a/indra/newview/skins/default/xui/de/floater_notification.xml b/indra/newview/skins/default/xui/de/floater_notification.xml
index 48ff900d5a..48a26a0e98 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="KONSOLE: MELDUNGEN">
<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..0c075dd63a 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">
+<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>
diff --git a/indra/newview/skins/default/xui/de/floater_openobject.xml b/indra/newview/skins/default/xui/de/floater_openobject.xml
index fa465c08c7..d7575876e1 100644
--- a/indra/newview/skins/default/xui/de/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/de/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Objektinhalte">
+<floater name="objectcontents" title="OBJEKTINHALTE">
<text name="object_name">
[DESC]:
</text>
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..3641f41b8c 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="HOCHLADE-BERECHTIGUNGEN (STANDARD)">
<panel label="Berechtigungen" name="permissions">
<button label="?" label_selected="?" name="help"/>
<check_box label="Mit Gruppe teilen" name="share_with_group"/>
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 2755704660..fc552339d3 100644
--- a/indra/newview/skins/default/xui/de/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/de/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="Foto per E-Mail senden">
+<floater name="Postcard" title="FOTO PER E-MAIL SENDEN">
<text name="to_label">
E-Mail des Empfängers:
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_preferences.xml b/indra/newview/skins/default/xui/de/floater_preferences.xml
index 5f68282b9f..02aa440be7 100644
--- a/indra/newview/skins/default/xui/de/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/de/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Einstellungen">
+<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" />
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..be702145c3 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,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Vertrauliche Informationen" />
+<floater name="classified_preview" title="VERTRAULICHE INFORMATIONEN" />
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..21e8c67787 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,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Event-Informationen" />
+<floater name="event_preview" title="EVENT-INFORMATIONEN" />
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 da90d66e4d..2c3258440f 100644
--- a/indra/newview/skins/default/xui/de/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/de/floater_preview_notecard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview notecard" title="Hinweis:">
+<floater name="preview notecard" title="HINWEIS:">
<button label="Speichern" label_selected="Speichern" name="Save" />
<text name="desc txt">
Beschreibung:
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..e7dd09d4da 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" />
+<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 a8df587cfa..a5dd9fa4b1 100644
--- a/indra/newview/skins/default/xui/de/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/de/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Missbrauch melden">
+<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"/>
<text name="reporter_title">
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_preview.xml b/indra/newview/skins/default/xui/de/floater_script_preview.xml
index 3ab5732055..be6017cff5 100644
--- a/indra/newview/skins/default/xui/de/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_preview.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Skript: Rotationsskript">
+<floater name="preview lsl text" title="SKRIPT: ROTATIONSSKRIPT">
<text name="desc txt">
Beschreibung:
</text>
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..b2011a4dfb 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,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Rückgängig">
+<floater name="queue" title="RÜCKGÄNGIG">
<button label="Schließen" label_selected="Schließen" name="close" left="215" 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 bd93427456..aae302e230 100644
--- a/indra/newview/skins/default/xui/de/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/de/floater_script_search.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Skriptsuche">
+<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" />
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 1499bb0152..47ab51d502 100644
--- a/indra/newview/skins/default/xui/de/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/de/floater_sell_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="sell land" title="Land verkaufen">
+<floater name="sell land" title="LAND VERKAUFEN">
<scroll_container name="profile_scroll">
<panel name="scroll_content_panel">
<text name="info_parcel_label">
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 034cfca017..ea3295797d 100644
--- a/indra/newview/skins/default/xui/de/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/de/floater_settings_debug.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="settings_debug" title="Debug-Einstellungen">
+<floater name="settings_debug" title="DEBUG-EINSTELLUNGEN">
<combo_box name="boolean_combo">
<combo_box.item name="TRUE" label="WAHR" />
<combo_box.item name="FALSE" label="FALSCH" />
diff --git a/indra/newview/skins/default/xui/de/floater_snapshot.xml b/indra/newview/skins/default/xui/de/floater_snapshot.xml
index bc8a1f42f1..64db511aa9 100644
--- a/indra/newview/skins/default/xui/de/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/de/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Foto-Vorschau">
+<floater name="Snapshot" title="FOTO-VORSCHAU">
<text name="type_label">
Zweck des Fotos
</text>
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 1e5ac179b5..14126b6a44 100644
--- a/indra/newview/skins/default/xui/de/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/de/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">
Name:
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_statistics.xml b/indra/newview/skins/default/xui/de/floater_statistics.xml
index 26e976a59c..506c18bd98 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="STATISTIKLEISTE"/>
diff --git a/indra/newview/skins/default/xui/de/floater_telehub.xml b/indra/newview/skins/default/xui/de/floater_telehub.xml
index 264411c166..2ba4e575a8 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" >
+<floater name="telehub" title="TELEHUB" min_height="310" height="310" >
<text name="status_text_connected">
Telehub verbunden mit Objekt [OBJECT]
</text>
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 fff6ab5c74..7e2fc26fdf 100644
--- a/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/de/floater_texture_ctrl.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="texture picker" title="Auswählen: Textur">
+<floater name="texture picker" title="AUSWÄHLEN: TEXTUR">
<string name="choose_picture">
Zum Auswählen eines Bildes hier klicken
</string>
diff --git a/indra/newview/skins/default/xui/de/floater_tools.xml b/indra/newview/skins/default/xui/de/floater_tools.xml
index 90cbbd7861..6bad64324b 100644
--- a/indra/newview/skins/default/xui/de/floater_tools.xml
+++ b/indra/newview/skins/default/xui/de/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Bauen">
+<floater name="toolbox floater" title="" short_title="BAUEN">
<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"/>
@@ -518,7 +518,7 @@ Primitiv" name="sculpt texture control" tool_tip="Klicken Sie hier, um ein Bild
Fläche: [AREA] m²
</text>
<button label="Info zu Land..." label_selected="Info zu Land..." name="button about land"/>
- <check_box label="Eigentümer anzeigen" name="checkbox show owners" tool_tip="Parzellen nach Eigentümer farbig kennzeichnen"/>
+ <check_box label="Eigentümer anzeigen" name="checkbox show owners" tool_tip="Parzellen nach Eigentümer farbig kennzeichnen: &#10;&#10;Grün = Ihr Land &#10;Blau = Das Land Ihrer Gruppe &#10;Rot = Im Eigentum anderer &#10;Geld = Zum Verkauf &#10;Lila = Zur Auktion &#10;Grau = Öffentlich"/>
<button label="?" label_selected="?" name="button show owners help"/>
<text name="label_parcel_modify">
Parzelle ändern
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..082eb8894d 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 GELADEN...">
<text name="title_text">
Wird geladen...
</text>
diff --git a/indra/newview/skins/default/xui/de/floater_water.xml b/indra/newview/skins/default/xui/de/floater_water.xml
index 95b469434a..0880470c58 100644
--- a/indra/newview/skins/default/xui/de/floater_water.xml
+++ b/indra/newview/skins/default/xui/de/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Erweiterter Wasser-Editor">
+<floater name="Water Floater" title="ERWEITERTER WASSER-EDITOR">
<text name="KeyFramePresetsText">
Voreinstellungen:
</text>
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..df0b513a85 100644
--- a/indra/newview/skins/default/xui/de/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/de/floater_windlight_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Erweiterter Himmel-Editor">
+<floater name="WindLight floater" title="ERWEITERTER HIMMEL-EDITOR">
<text name="KeyFramePresetsText">
Voreinstellungen:
</text>
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 d3366e5871..665eafe5b8 100644
--- a/indra/newview/skins/default/xui/de/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/de/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Weltkarte">
+<floater name="worldmap" title="WELTKARTE">
<tab_container name="maptab">
<panel label="Objekte" name="objects_mapview"/>
<panel label="Terrain" name="terrain_mapview"/>
diff --git a/indra/newview/skins/default/xui/de/notifications.xml b/indra/newview/skins/default/xui/de/notifications.xml
index b738b2d864..ebe2d9b260 100644
--- a/indra/newview/skins/default/xui/de/notifications.xml
+++ b/indra/newview/skins/default/xui/de/notifications.xml
@@ -1696,7 +1696,7 @@ Ist die Option aktiviert, können Käufer ihr Land in dieser Region weiterverkau
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.
+ 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“.
@@ -1704,7 +1704,7 @@ 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“.
+Ö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.
@@ -2849,7 +2849,7 @@ Ein flexibles Objekt ist ein Phantom und nicht physisch, bis die Option „Flexi
<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.
+Drücken Sie in Windows Strg+Alt+D (Mac: &#8997;&#8984;D) zum Ein- und Ausschalten dieses Menüs.
</notification>
<notification name="FirstSculptedPrim">
Sie bearbeiten ein geformtes Primitiv.
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..3203eacdb5
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/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="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>
+ <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">
+ Antwort für Beschäftigt-Modus:
+ </text>
+ </panel>
+ </panel>
+</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..0ad6291537
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_alerts.xml
@@ -0,0 +1,24 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Popups" name="popups" title="Popups">
+ <text>
+ Popups nicht anzeigen:
+ </text>
+ <text name="dont_show_label">
+ Diese Popups nicht anzeigen:
+ </text>
+ <button label="Dieses Popup aktivieren" name="enable_popup"/>
+ <text>
+ Popups anzeigen:
+ </text>
+ <text name="show_label">
+ Diese Popups anzeigen:
+ </text>
+ <text name="text_box2">
+ Anbieten von Notizkarten, Texturen und Landmarken:
+ </text>
+ <check_box label="Automatisch annehmen" name="accept_new_inventory"/>
+ <check_box label="Nach Annahme automatisch anzeigen" name="show_new_inventory"/>
+ <button width="200" label="Alle Popups aktivieren..." name="reset_dialogs_btn" tool_tip="Alle optionalen Popups und „Das erste Mal“-Meldungen aktivieren."/>
+ <button width="200" label="Alle diese Popups deaktivieren..." name="skip_dialogs_btn" tool_tip="Alle optionalen Popups und „Das erste Mal“-Meldungen deaktivieren."/>
+ <check_box label="Neue Objekte im Inventar automatisch anzeigen" name="show_in_inventory"/>
+</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..b52e535114
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_privacy.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Kommunikation" name="im">
+ <text name="text_box">
+ Mein Onlinestatus:
+ </text>
+ <check_box label="Nur Freunden und Gruppen meinen Online-Status mitteilen" name="online_visibility"/>
+ <text name="text_box2">
+ IM-Optionen:
+ </text>
+ <text name="log_in_to_change">
+ Zum Ändern anmelden
+ </text>
+ <check_box label="IM an E-Mail senden ([EMAIL])" name="send_im_to_email"/>
+ <check_box label="IM in Chat-Konsole anzeigen" name="include_im_in_chat_console"/>
+ <check_box label="Zeitstempel in IM anzeigen" name="show_timestamps_check"/>
+ <check_box label="Online-Freundbenachrichtigungen anzeigen" name="friends_online_notify_checkbox"/>
+ <text name="text_box3">
+ Antwort für
+Beschäftigt-Modus:
+ </text>
+ <text name="text_box4">
+ Protokolloptionen:
+ </text>
+ <check_box label="IM-Verlauf auf meinem Computer speichern" name="log_instant_messages"/>
+ <check_box label="Zeitstempel in IM-Verlauf anzeigen" name="log_instant_messages_timestamp"/>
+ <check_box label="Ende des letzten IM-Gesprächs anzeigen" name="log_show_history"/>
+ <check_box label="Verlauf des lokalen Chats auf meinem Computer speichern" name="log_chat"/>
+ <check_box label="Zeitstempel im Verlauf des lokalen Chats anzeigen" name="log_chat_timestamp"/>
+ <check_box label="Eingehende IM in Chat-Verlauf anzeigen" name="log_chat_IM"/>
+ <check_box label="Datum mit Zeitstempeln hinzufügen" name="log_date_timestamp"/>
+ <button label="Pfad ändern" label_selected="Pfad ändern" name="log_path_button"/>
+</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..97ec745d4d
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_setup.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Kamera" name="Input panel">
+ <text name=" Mouselook Options:">
+ Mouselook-Optionen:
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Mausempfindlichkeit:
+ </text>
+ <check_box label="Maus umkehren" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Auto-Flug-Optionen:
+ </text>
+ <check_box label="Zum Fliegen/Landen nach oben/unten halten" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Kameraoptionen:
+ </text>
+ <text name="camera_fov_label">
+ Kamera-Sichtwinkel:
+ </text>
+ <text name="Camera Follow Distance:">
+ Kameraabstand:
+ </text>
+ <check_box label="Automatischer Kameraschwenk im Bearbeiten-Modus" name="edit_camera_movement" tool_tip="Automatische Kamerapositionierung bei Wechsel in und aus dem Bearbeitungsmodus verwenden"/>
+ <check_box label="Automatischer Kameraschwenk im Aussehen-Modus" name="appearance_camera_movement" tool_tip="Automatische Kamerapositionierung im Bearbeitenmodus verwenden"/>
+ <text name="text2">
+ Avatar-Anzeigeoptionen:
+ </text>
+ <check_box label="Avatar in Mouselook anzeigen" name="first_person_avatar_visible"/>
+ <button label="Joystick-Einrichtung" name="joystick_setup_button"/>
+</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..3c4d8203fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/de/panel_preferences_sound.xml
@@ -0,0 +1,73 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="Audio und Video" name="Preference Media panel">
+ <slider label="Master" name="System Volume"/>
+ <slider label="Umgebung" name="Wind Volume"/>
+ <slider label="Sounds" name="SFX Volume"/>
+ <slider label="Medien" name="Media Volume"/>
+ <slider label="UI" name="UI Volume"/>
+ <slider label="Musik" name="Music Volume"/>
+ <slider label="Sprache" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Voice-Chat ist nicht verfügbar
+ </text_editor>
+ <check_box label="Voice-Chat aktivieren" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Voice-Chat von Kameraposition aus hören" />
+ <radio_item name="1" label="Voice-Chat von Avatarposition aus hören" />
+ </radio_group>
+ <button label="Geräte-Einstellungen" name="device_settings_btn"/>
+ <text name="muting_text">
+ Lautstärke:
+ </text>
+ <check_box label="Audio stummschalten" name="disable audio" />
+ <text name="streaming_prefs_text">
+ Streaming-Einstellungen:
+ </text>
+ <text name="audio_prefs_text">
+ Audio-Einstellungen:
+ </text>
+ <panel label="Lautstärke" name="Volume Panel" />
+ <check_box label="Medien automatisch wiedergeben" name="auto_streaming_video" />
+ <check_box label="Audio stummschalten, wenn Fenster minimiert ist"
+ name="mute_when_minimized" />
+ <text name="streaming_text">
+ Streaming:
+ </text>
+ <check_box label="Streaming-Musik abspielen" name="streaming_music" />
+ <check_box label="Streaming-Media abspielen" name="streaming_video" />
+ <text name="system_volume_text">
+ Soundeffekte:
+ </text>
+ <text name="wind_volume_text">
+ Windlautstärke:
+ </text>
+ <text name="footsteps_volume_text">
+ Schrittlautstärke:
+ </text>
+ <text name="ui_volume_text">
+ UI-Volumen:
+ </text>
+ <slider label="Dopplereffekt" name="Doppler Effect" />
+ <slider label="Distanzfaktor" name="Distance Factor" />
+ <slider label="Rolloff-Faktor" name="Rolloff Factor" />
+ <spinner label="L$ Änderungs-Grenzwert" name="L$ Change Threshold" />
+ <spinner label="Gesundheitsschwellwert" name="Health Change Threshold" />
+ <text name="doppler_effect_text">
+ Audio-Einstellungen:
+ </text>
+ <text name="distance_factor_text">
+ Distanzfaktor:
+ </text>
+ <text name="rolloff_factor_text">
+ Rolloff-Faktor:
+ </text>
+ <text name="default_upload_bitrate_text">
+ Standard-Upload-Bitrate:
+ </text>
+ <radio_group name="bitrate">
+ <radio_item name="32kbps" label="32 kbit/s" />
+ <radio_item name="64kbps" label="64 kbit/s" />
+ <radio_item name="96kbps" label="96 kbit/s" />
+ <radio_item name="128kbps" label="128 kbit/s" />
+ </radio_group>
+</panel>
diff --git a/indra/newview/skins/default/xui/de/strings.xml b/indra/newview/skins/default/xui/de/strings.xml
index 5df1570bfd..af9185e0b7 100644
--- a/indra/newview/skins/default/xui/de/strings.xml
+++ b/indra/newview/skins/default/xui/de/strings.xml
@@ -488,16 +488,16 @@
Verzeichnis auswählen
</string>
<string name="accel-mac-control">
- Strg-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Umschalt-
+ &#8679;
</string>
<string name="accel-win-control">
Strg+
@@ -603,6 +603,9 @@
<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>
@@ -621,4 +624,31 @@
<string name="close_on_no_ability">
Sie haben nicht mehr die Berechtigung an der Chat-Sitzung teilzunehmen.
</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>
</strings>
diff --git a/indra/newview/skins/default/xui/en/favorites_bar_button.xml b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
index dcd85e1f58..361f5a7bc8 100644
--- a/indra/newview/skins/default/xui/en/favorites_bar_button.xml
+++ b/indra/newview/skins/default/xui/en/favorites_bar_button.xml
@@ -4,20 +4,20 @@
<button
follows="left|bottom"
halign="center"
- height="23"
+ height="15"
image_disabled="transparent.j2c"
image_disabled_selected="transparent.j2c"
image_selected="transparent.j2c"
image_unselected="transparent.j2c"
- image_hover_selected="PushButton_Selected"
- image_hover_unselected="PushButton_Off"
- image_pressed="PushButton_Press"
- image_pressed_selected="PushButton_Selected_Press"
+ image_hover_selected="Favorite_Link_Over"
+ image_hover_unselected="Favorite_Link_Over"
+ image_pressed="Favorite_Link_Over"
+ image_pressed_selected="Favorite_Link_Over"
hover_glow_amount="0.15"
layout="topleft"
- left="2"
+ left="0"
name="favorites_bar_btn"
tab_stop="false"
- top="2"
+ top="0"
use_ellipses="true"
width="120" />
diff --git a/indra/newview/skins/default/xui/en/floater_aaa.xml b/indra/newview/skins/default/xui/en/floater_aaa.xml
index 6d64d13db7..4d5268681b 100644
--- a/indra/newview/skins/default/xui/en/floater_aaa.xml
+++ b/indra/newview/skins/default/xui/en/floater_aaa.xml
@@ -1,12 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="440"
layout="topleft"
name="floater_aaa"
help_topic="floater_aaa"
save_rect="true"
can_resize="true"
- title="About [APP_NAME]"
+ title="ABOUT [APP_NAME]"
width="470">
<text_editor
follows="left|top|right|bottom"
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index dc6af79db5..c74b1929b4 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -1,72 +1,64 @@
<?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 [APP_NAME]"
+ title="ABOUT [APP_NAME]"
width="470">
- <floater.string
- name="you_are_at">
- You are at [POSITION]
- </floater.string>
- <floater.string
- name="in_region">
- in [REGION] located at
- </floater.string>
- <floater.string
- name="CPU">
- CPU:
- </floater.string>
- <floater.string
- name="Memory">
- Memory: [MEM] MB
- </floater.string>
- <floater.string
- name="OSVersion">
- OS Version:
- </floater.string>
- <floater.string
- name="GraphicsCardVendor">
- Graphics Card Vendor:
- </floater.string>
- <floater.string
- name="GraphicsCard">
- Graphics Card:
- </floater.string>
- <floater.string
- name="OpenGLVersion">
- OpenGL Version:
- </floater.string>
- <floater.string
- name="LibCurlVersion">
- libcurl Version:
- </floater.string>
- <floater.string
- name="J2CDecoderVersion">
- J2C Decoder Version:
- </floater.string>
- <floater.string
- name="AudioDriverVersion">
- Audio Driver Version:
- </floater.string>
- <floater.string
- name="none">
- (none)
- </floater.string>
- <floater.string
- name="LLMozLibVersion">
- LLMozLib Version:
- </floater.string>
<floater.string
- name="LLQtWebkitVersion">
- Qt Webkit Version: 4.5.2
+ 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="PacketsLost">
- Packets Lost: [LOST]/[IN] ([PCT]%)
- </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"
@@ -78,6 +70,7 @@
<panel
border="true"
label="Support"
+ help_topic="about_support_tab"
name="support_panel">
<text_editor
allow_html="true"
@@ -103,6 +96,7 @@
<panel
border="true"
label="Credits"
+ help_topic="about_credits_tab"
name="credits_panel">
<text_editor
enabled="false"
@@ -134,6 +128,7 @@ It is a rare mind indeed that can render the hitherto non-existent blindingly ob
<panel
border="true"
label="Licenses"
+ help_topic="about_licenses_tab"
name="licenses_panel">
<text_editor
enabled="false"
@@ -154,11 +149,13 @@ DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 20
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.
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 524495d83d..615d1bf18d 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -1,4 +1,4 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
can_tear_off="false"
height="420"
@@ -6,7 +6,7 @@
name="floaterland"
help_topic="floaterland"
save_rect="true"
- title="About Land"
+ title="ABOUT LAND"
width="460">
<floater.string
name="Minutes">
@@ -40,6 +40,7 @@
label="General"
layout="topleft"
left="1"
+ help_topic="land_general_tab"
name="land_general_panel"
top="-31"
width="458">
@@ -535,6 +536,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label="Covenant"
layout="topleft"
left_delta="-1"
+ help_topic="land_covenant_tab"
name="land_covenant_panel"
top_delta="-47"
width="458">
@@ -801,6 +803,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label="Objects"
layout="topleft"
left_delta="0"
+ help_topic="land_objects_tab"
name="land_objects_panel"
top_delta="-47"
width="458">
@@ -846,7 +849,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
left_delta="152"
name="objects_available"
top_delta="0"
- width="212">
+ width="260">
[COUNT] out of [MAX] ([AVAILABLE] available)
</text>
<text
@@ -867,7 +870,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="152"
+ left_delta="200"
name="object_contrib_text"
top_delta="0"
width="212">
@@ -891,7 +894,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="152"
+ left_delta="200"
name="total_objects_text"
top_delta="0"
width="48">
@@ -906,7 +909,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
left="28"
name="Owned by parcel owner:"
top="84"
- width="128">
+ width="176">
Owned by parcel owner:
</text>
<text
@@ -915,7 +918,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="128"
+ left_delta="176"
name="owner_objects_text"
top_delta="0"
width="48">
@@ -931,7 +934,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Show"
layout="topleft"
name="ShowOwner"
- right="-190"
+ right="-140"
width="60" />
<button
bottom="100"
@@ -943,7 +946,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Return..."
layout="topleft"
name="ReturnOwner..."
- right="-60"
+ right="-10"
tool_tip="Return objects to their owners."
width="119" />
<text
@@ -955,7 +958,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
left="28"
name="Set to group:"
top="104"
- width="128">
+ width="176">
Set to group:
</text>
<text
@@ -964,7 +967,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="128"
+ left_delta="176"
name="group_objects_text"
top_delta="0"
width="48">
@@ -980,7 +983,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Show"
layout="topleft"
name="ShowGroup"
- right="-190"
+ right="-140"
width="60" />
<button
bottom="120"
@@ -992,7 +995,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Return..."
layout="topleft"
name="ReturnGroup..."
- right="-60"
+ right="-10"
tool_tip="Return objects to their owners."
width="119" />
<text
@@ -1004,7 +1007,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
left="28"
name="Owned by others:"
top="124"
- width="128">
+ width="176">
Owned by others:
</text>
<text
@@ -1013,7 +1016,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="128"
+ left_delta="176"
name="other_objects_text"
top_delta="0"
width="48">
@@ -1029,7 +1032,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Show"
layout="topleft"
name="ShowOther"
- right="-190"
+ right="-140"
width="60" />
<button
bottom="140"
@@ -1041,7 +1044,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label_selected="Return..."
layout="topleft"
name="ReturnOther..."
- right="-60"
+ right="-10"
tool_tip="Return objects to their owners."
width="119" />
<text
@@ -1053,7 +1056,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
left="28"
name="Selected / sat upon:"
top="144"
- width="128">
+ width="176">
Selected / sat upon:
</text>
<text
@@ -1062,7 +1065,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
follows="left|top"
height="16"
layout="topleft"
- left_delta="128"
+ left_delta="176"
name="selected_objects_text"
top_delta="0"
width="48">
@@ -1089,7 +1092,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
layout="topleft"
max_length="6"
name="clean other time"
- right="-100"
+ right="-50"
width="56" />
<text
type="string"
@@ -1166,6 +1169,7 @@ Go to World menu &gt; About Land or select another parcel to show its details.
label="Options"
layout="topleft"
left_delta="0"
+ help_topic="land_options_tab"
name="land_options_panel"
top_delta="31"
width="458">
@@ -1483,16 +1487,6 @@ Only large parcels can be listed in search.
name="item12"
value="other" />
</combo_box>
- <button
- follows="left|top"
- height="18"
- label="?"
- label_selected="?"
- layout="topleft"
- left_pad="15"
- name="?"
- top_delta="0"
- width="18" />
<check_box
height="16"
label="Mature Content"
@@ -1556,7 +1550,7 @@ Only large parcels can be listed in search.
layout="topleft"
left_pad="5"
name="Clear"
- tool_tip="Clear the landing point."
+ tool_tip="Clear the landing point"
top_delta="0"
width="50" />
<text
@@ -1576,7 +1570,7 @@ Only large parcels can be listed in search.
layout="topleft"
left_delta="116"
name="landing type"
- tool_tip="Teleport Routing -- select how to handle teleports onto your land."
+ tool_tip="Teleport Routing -- select how to handle teleports onto your land"
top_delta="0"
width="120">
<combo_box.item
@@ -1603,6 +1597,7 @@ Only large parcels can be listed in search.
label="Media"
layout="topleft"
left_delta="0"
+ help_topic="land_media_tab"
name="land_media_panel"
top_delta="1"
width="458">
@@ -1865,6 +1860,7 @@ Texture:
label="Audio"
layout="topleft"
left_delta="0"
+ help_topic="land_audio_tab"
name="land_audio_panel"
top_delta="1"
width="458">
@@ -1912,16 +1908,6 @@ Texture:
name="check sound local"
top_delta="0"
width="292" />
- <button
- follows="left|top"
- height="18"
- label="?"
- label_selected="?"
- layout="topleft"
- left_delta="292"
- name="?"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -1968,6 +1954,7 @@ Texture:
label="Access"
layout="topleft"
left_delta="0"
+ help_topic="land_access_tab"
name="land_access_panel"
top_delta="31"
width="458">
diff --git a/indra/newview/skins/default/xui/en/floater_activeim.xml b/indra/newview/skins/default/xui/en/floater_activeim.xml
index f81250e7b9..96fe0aa70c 100644
--- a/indra/newview/skins/default/xui/en/floater_activeim.xml
+++ b/indra/newview/skins/default/xui/en/floater_activeim.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
name="floater_activeim"
help_topic="floater_activeim"
title="ACTIVE IM"
@@ -29,4 +30,4 @@
name="chiclet_row_panel_list"
width="318"/>
</scroll_container>
-</floater> \ No newline at end of file
+</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
index 3a2337bfff..ebce758d3d 100644
--- a/indra/newview/skins/default/xui/en/floater_animation_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_animation_preview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="556"
layout="topleft"
@@ -196,7 +197,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
left="10"
max_val="4"
name="priority"
- tool_tip="Controls which other animations can be overridden by this animation."
+ tool_tip="Controls which other animations can be overridden by this animation"
width="160" />
<check_box
top_pad="0"
@@ -206,7 +207,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
left="10"
width="100"
name="loop_check"
- tool_tip="Makes this animation loop." />
+ tool_tip="Makes this animation loop" />
<spinner
follows="left|top"
height="23"
@@ -219,7 +220,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
left="30"
max_val="100"
name="loop_in_point"
- tool_tip="Sets point in animation that looping returns to."
+ tool_tip="Sets point in animation that looping returns to"
width="110" />
<spinner
bottom_delta="0"
@@ -232,7 +233,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
left_pad="10"
max_val="100"
name="loop_out_point"
- tool_tip="Sets point in animation that ends a loop."
+ tool_tip="Sets point in animation that ends a loop"
label_width="45"
width="120" />
<text
@@ -252,7 +253,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
layout="topleft"
left_pad="0"
name="hand_pose_combo"
- tool_tip="Controls what hands do during animation."
+ tool_tip="Controls what hands do during animation"
width="150">
<combo_box.item
label="Spread"
@@ -325,7 +326,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
layout="topleft"
left_pad="0"
name="emote_combo"
- tool_tip="Controls what face does during animation.">
+ tool_tip="Controls what face does during animation">
<combo_box.item
label="(None)"
name="[None]" />
@@ -430,7 +431,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
left="10"
max_val="10"
name="ease_in_time"
- tool_tip="Amount of time (in seconds) over which animations blends in."
+ tool_tip="Amount of time (in seconds) over which animations blends in"
top_pad="10"
width="200" />
<spinner
@@ -444,7 +445,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
top_pad="0"
max_val="10"
name="ease_out_time"
- tool_tip="Amount of time (in seconds) over which animations blends out."
+ tool_tip="Amount of time (in seconds) over which animations blends out"
width="200" />
<button
follows="top|right"
@@ -454,8 +455,7 @@ Maximum animation length is [MAX_LENGTH] seconds.
layout="topleft"
left="10"
name="play_btn"
- picture_style="true"
- tool_tip="Play/pause your animation."
+ tool_tip="Play/pause your animation"
top_pad="0"
width="28" />
<button
@@ -466,7 +466,6 @@ Maximum animation length is [MAX_LENGTH] seconds.
layout="topleft"
left_pad="4"
name="stop_btn"
- picture_style="true"
tool_tip="Stop animation playback"
top_delta="0"
width="28" />
diff --git a/indra/newview/skins/default/xui/en/floater_auction.xml b/indra/newview/skins/default/xui/en/floater_auction.xml
index 29f8b49794..9c6d114c4c 100644
--- a/indra/newview/skins/default/xui/en/floater_auction.xml
+++ b/indra/newview/skins/default/xui/en/floater_auction.xml
@@ -1,13 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
- height="368"
+ height="412"
layout="topleft"
- min_height="368"
+ min_height="412"
min_width="420"
name="floater_auction"
help_topic="floater_auction"
- title="Start Linden Land Sale"
+ title="START LINDEN LAND SALE"
width="420">
<floater.string
name="already for sale">
@@ -49,21 +50,47 @@
left_delta="0"
name="snapshot_btn"
top_pad="4"
- width="96">
+ width="150">
<button.commit_callback
function="ClickSnapshot" />
</button>
<button
follows="left|bottom"
height="20"
- label="OK"
- label_selected="OK"
+ 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="ok_btn"
+ name="start_auction_btn"
top_delta="0"
- width="48">
+ width="150">
<button.commit_callback
- function="ClickOK" />
+ 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
index e1f8011cbe..a0f9bb59fd 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_picker.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="350"
layout="topleft"
@@ -7,7 +8,7 @@
min_width="265"
name="avatarpicker"
help_topic="avatarpicker"
- title="Choose Resident"
+ title="CHOOSE RESIDENT"
width="265">
<floater.string
name="not_found">
@@ -40,6 +41,7 @@
label="Search"
layout="topleft"
left="6"
+ help_topic="avatarpicker_search_tab"
name="SearchPanel"
top="150"
width="132">
@@ -84,6 +86,51 @@
top="52"
width="132" />
</panel>
+ <panel
+ border="none"
+ height="150"
+ label="Friends"
+ layout="topleft"
+ left="6"
+ help_topic="avatarpicker_friends_tab"
+ 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"
@@ -91,6 +138,7 @@
label="Near Me"
layout="topleft"
left="6"
+ help_topic="avatarpicker_near_me_tab"
name="NearMePanel"
top="150"
width="132">
@@ -139,7 +187,6 @@
height="28"
width="28"
name="Refresh"
- picture_style="true"
image_overlay="Refresh_Off" />
<scroll_list
follows="all"
diff --git a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
index f6b965f139..a0cb94eb69 100644
--- a/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/en/floater_avatar_textures.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="950"
layout="topleft"
name="avatar_texture_debug"
help_topic="avatar_texture_debug"
- title="Avatar Textures"
- width="960">
+ title="AVATAR TEXTURES"
+ width="1250">
<floater.string
name="InvalidAvatar">
INVALID AVATAR
@@ -41,6 +42,7 @@
name="Dump"
top_delta="1"
width="150" />
+
<texture_picker
height="143"
label="Hair"
@@ -54,11 +56,20 @@
label="Hair"
layout="topleft"
left_pad="7"
- name="hair"
+ 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"
@@ -70,11 +81,28 @@
label="Makeup"
layout="topleft"
left_pad="7"
- name="head bodypaint"
+ 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"
@@ -86,9 +114,18 @@
label="Eye"
layout="topleft"
left_pad="7"
- name="iris"
+ 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"
@@ -99,10 +136,10 @@
width="128" />
<texture_picker
height="143"
- label="Upper Body Tattoo"
+ label="Upper Body Bodypaint"
layout="topleft"
left_pad="7"
- name="upper bodypaint"
+ name="upper_bodypaint"
top_delta="0"
width="128" />
<texture_picker
@@ -110,7 +147,7 @@
label="Undershirt"
layout="topleft"
left_pad="7"
- name="undershirt"
+ name="upper_undershirt"
top_delta="0"
width="128" />
<texture_picker
@@ -118,7 +155,7 @@
label="Gloves"
layout="topleft"
left_pad="7"
- name="gloves"
+ name="upper_gloves"
top_delta="0"
width="128" />
<texture_picker
@@ -126,7 +163,7 @@
label="Shirt"
layout="topleft"
left_pad="7"
- name="shirt"
+ name="upper_shirt"
top_delta="0"
width="128" />
<texture_picker
@@ -134,11 +171,28 @@
label="Upper Jacket"
layout="topleft"
left_pad="7"
- name="upper jacket"
+ 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"
@@ -147,10 +201,10 @@
width="128" />
<texture_picker
height="143"
- label="Lower Body Tattoo"
+ label="Lower Body Bodypaint"
layout="topleft"
left_pad="7"
- name="lower bodypaint"
+ name="lower_bodypaint"
top_delta="0"
width="128" />
<texture_picker
@@ -158,7 +212,7 @@
label="Underpants"
layout="topleft"
left_pad="7"
- name="underpants"
+ name="lower_underpants"
top_delta="0"
width="128" />
<texture_picker
@@ -166,7 +220,7 @@
label="Socks"
layout="topleft"
left_pad="7"
- name="socks"
+ name="lower_socks"
top_delta="0"
width="128" />
<texture_picker
@@ -174,7 +228,7 @@
label="Shoes"
layout="topleft"
left_pad="7"
- name="shoes"
+ name="lower_shoes"
top_delta="0"
width="128" />
<texture_picker
@@ -182,7 +236,7 @@
label="Pants"
layout="topleft"
left_pad="7"
- name="pants"
+ name="lower_pants"
top_delta="0"
width="128" />
<texture_picker
@@ -190,9 +244,26 @@
label="Jacket"
layout="topleft"
left_pad="7"
- name="lower jacket"
+ 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"
@@ -209,4 +280,5 @@
name="skirt"
top_delta="0"
width="128" />
+
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_beacons.xml b/indra/newview/skins/default/xui/en/floater_beacons.xml
index 09b1735e04..c8f6c613af 100644
--- a/indra/newview/skins/default/xui/en/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/en/floater_beacons.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="225"
layout="topleft"
name="beacons"
@@ -7,7 +8,7 @@
save_rect="true"
save_visibility="true"
single_instance="true"
- title="Beacons"
+ title="BEACONS"
width="240">
<panel
follows="left|top|right|bottom"
@@ -53,7 +54,7 @@
height="16"
layout="topleft"
left="20"
- tool_tip="Beacon Width"
+ tool_tip="Beacon width"
name="beacon_width_label"
top_pad="3"
width="128">
diff --git a/indra/newview/skins/default/xui/en/floater_build_options.xml b/indra/newview/skins/default/xui/en/floater_build_options.xml
index 42a063928c..f0e678af00 100644
--- a/indra/newview/skins/default/xui/en/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_build_options.xml
@@ -1,12 +1,13 @@
<?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"
+ title="GRID OPTIONS"
width="264">
<spinner
control_name="GridResolution"
@@ -61,7 +62,7 @@
height="16"
layout="topleft"
left="10"
- tool_tip="Grid Opacity"
+ tool_tip="Grid opacity"
name="grid_opacity_label"
top_pad="5"
width="128">
diff --git a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
index ef6af28786..7ae079f553 100644
--- a/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/en/floater_bulk_perms.xml
@@ -1,11 +1,12 @@
<?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"
+ title="EDIT CONTENT PERMISSIONS"
width="270">
<floater.string
name="nothing_to_modify_text">
diff --git a/indra/newview/skins/default/xui/en/floater_bumps.xml b/indra/newview/skins/default/xui/en/floater_bumps.xml
index d1f6706875..303c28d7c8 100644
--- a/indra/newview/skins/default/xui/en/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/en/floater_bumps.xml
@@ -1,11 +1,12 @@
<?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"
+ title="BUMPS, PUSHES &amp; HITS"
width="400">
<floater.string
name="none_detected">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_contents.xml b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
index 718f83c9a2..833e8beb8d 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_contents.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_contents.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="290"
layout="topleft"
@@ -8,7 +9,7 @@
name="floater_buy_contents"
help_topic="floater_buy_contents"
save_rect="true"
- title="Buy Contents"
+ title="BUY CONTENTS"
width="280">
<floater.string
name="no_copy_text">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_currency.xml b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
index 041cd2a118..75711cdf89 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_currency.xml
@@ -1,12 +1,13 @@
<?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"
- title="Buy L$"
width="350">
<floater.string
name="buy_currency">
@@ -28,7 +29,7 @@
layout="topleft"
left="20"
height="30"
- top="30"
+ top="25"
width="300"
name="info_need_more">
You need more L$
@@ -53,7 +54,7 @@
layout="topleft"
left="20"
height="30"
- top="30"
+ top="25"
width="200"
name="info_buying">
Buy L$
@@ -67,7 +68,7 @@
layout="topleft"
left="20"
name="balance_label"
- top="70"
+ top="65"
width="210">
I have
</text>
@@ -91,7 +92,7 @@
follows="top|left"
font="SansSerifMedium"
height="16"
- top="100"
+ top="95"
layout="topleft"
left="20"
name="currency_action"
@@ -133,7 +134,7 @@
height="16"
layout="topleft"
left="20"
- top="130"
+ top="125"
name="buying_label"
width="210">
For the price
@@ -148,10 +149,10 @@
height="16"
top_delta="0"
layout="topleft"
- left="170"
+ left="150"
name="currency_est"
- width="150">
- [LOCALAMOUNT]
+ width="170">
+ approx. [LOCALAMOUNT]
</text>
<text
type="string"
@@ -161,7 +162,7 @@
follows="top|left"
height="16"
layout="topleft"
- top="130"
+ top="125"
left="170"
width="150"
halign="right"
@@ -171,11 +172,11 @@
<text
type="string"
font="SansSerifSmall"
- top="150"
+ top="145"
length="1"
follows="top|left"
- halign="right"
height="16"
+ halign="right"
left="150"
width="170"
layout="topleft"
@@ -191,7 +192,7 @@
layout="topleft"
left="20"
name="total_label"
- top="170"
+ top="165"
width="210">
My new balance will be
</text>
@@ -212,28 +213,58 @@
<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/ payment method] | [http://www.secondlife.com/ currency] | [http://www.secondlife.com exchange rate]
+ </text>
+ <text
+ type="string"
+ length="1"
+ text_color="0.7 0.7 0.7 0.5"
follows="top|left"
layout="topleft"
- top="195"
+ 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 the L$.
-You&apos;ll need to try again.
+ 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"
- top="195"
+ halign="right"
+ top="213"
left="20"
width="300"
height="30"
name="purchase_warning_notenough">
- You aren&apos;t buying enough L$.
-Increase the amount to buy.
+ You aren&apos;t buying enough L$. Please increase the amount.
</text>
<button
diff --git a/indra/newview/skins/default/xui/en/floater_buy_land.xml b/indra/newview/skins/default/xui/en/floater_buy_land.xml
index 6d1c2c1cb9..0f710a8047 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_land.xml
@@ -1,12 +1,13 @@
<?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"
+ title="BUY LAND"
width="740">
<floater.string
name="can_resell">
diff --git a/indra/newview/skins/default/xui/en/floater_buy_object.xml b/indra/newview/skins/default/xui/en/floater_buy_object.xml
index 7930622e54..f0e5e30010 100644
--- a/indra/newview/skins/default/xui/en/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_buy_object.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="290"
layout="topleft"
@@ -9,7 +10,7 @@
help_topic="contents"
save_rect="true"
single_instance="true"
- title="Buy Copy of Object"
+ title="BUY COPY OF OBJECT"
width="280">
<floater.string
name="title_buy_text">
diff --git a/indra/newview/skins/default/xui/en/floater_camera.xml b/indra/newview/skins/default/xui/en/floater_camera.xml
index 86c75a3946..a569b62e96 100644
--- a/indra/newview/skins/default/xui/en/floater_camera.xml
+++ b/indra/newview/skins/default/xui/en/floater_camera.xml
@@ -1,17 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_dock="true"
- can_minimize="true"
- can_close="true"
+ can_minimize="false"
+ can_close="true"
center_horiz="true"
- follows="top"
- height="110"
+ follows="bottom"
+ height="152"
layout="topleft"
name="camera_floater"
help_topic="camera_floater"
save_rect="true"
save_visibility="true"
- width="105">
+ width="150">
<floater.string
name="rotate_tooltip">
Rotate Camera Around Focus
@@ -25,81 +26,145 @@
Move Camera Up and Down, Left and Right
</floater.string>
<panel
- border="true"
- height="79"
+ border="false"
+ height="110"
layout="topleft"
- left="0"
+ left="2"
top="0"
- mouse_opaque="false"
+ mouse_opaque="false"
name="controls"
- width="105">
- <joystick_rotate
- follows="top|left"
- height="64"
- image_selected="cam_rotate_in.tga"
- image_unselected="cam_rotate_out.tga"
- layout="topleft"
- left="2"
- name="cam_rotate_stick"
- picture_style="true"
- quadrant="left"
- scale_image="false"
- sound_flags="3"
- tool_tip="Orbit Camera Around Focus"
- top="15"
- width="64" />
+ width="148">
<joystick_track
follows="top|left"
- height="64"
- image_selected="cam_tracking_in.tga"
- image_unselected="cam_tracking_out.tga"
+ height="78"
+ image_selected="Cam_Tracking_In"
+ image_unselected="Cam_Tracking_Out"
layout="topleft"
- left="2"
+ left="45"
name="cam_track_stick"
- picture_style="true"
quadrant="left"
scale_image="false"
sound_flags="3"
- tool_tip="Move Camera Up and Down, Left and Right"
- top="15"
+ tool_tip="Move camera up and down, left and right"
+ top="22"
visible="false"
- width="64" />
+ width="78" />
+ <!--TODO: replace with slider, + - images -->
<joystick_zoom
follows="top|left"
- height="64"
- image_unselected="cam_zoom_out.tga"
+ height="78"
+ image_unselected="ScrollThumb_Vert"
layout="topleft"
- left_delta="70"
- minus_image="cam_zoom_minus_in.tga"
+ left="7"
+ minus_image="ScrollThumb_Vert"
name="zoom"
- picture_style="true"
- plus_image="cam_zoom_plus_in.tga"
+ plus_image="ScrollThumb_Vert"
+ quadrant="left"
+ scale_image="false"
+ sound_flags="3"
+ tool_tip="Zoom camera toward focus"
+ top="22"
+ width="20" />
+ <joystick_rotate
+ follows="top|left"
+ height="78"
+ image_selected="Cam_Rotate_In"
+ image_unselected="Cam_Rotate_Out"
+ layout="topleft"
+ left="45"
+ name="cam_rotate_stick"
quadrant="left"
scale_image="false"
sound_flags="3"
- tool_tip="Zoom Camera Towards Focus"
- top_delta="0"
- width="16" />
+ visible="true"
+ tool_tip="Orbit camera around focus"
+ top="22"
+ width="78" />
+ <panel
+ height="78"
+ layout="topleft"
+ left="36"
+ name="camera_presets"
+ top="30"
+ visible="false"
+ width="78">
+ <button
+ height="30"
+ image_selected="CameraPreset_Rear"
+ image_unselected="CameraPreset_Rear"
+ layout="topleft"
+ left="5"
+ name="rear_view"
+ tool_tip="Rear View"
+ top="2"
+ width="30">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="rear_view" />
+ </button>
+ <button
+ height="30"
+ image_selected="CameraPreset_3_4"
+ image_unselected="CameraPreset_3_4"
+ layout="topleft"
+ left_pad="5"
+ name="group_view"
+ tool_tip="Group View"
+ top="2"
+ width="30">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="group_view" />
+ </button>
+ <button
+ height="30"
+ image_selected="CameraPreset_Front"
+ image_unselected="CameraPreset_Front"
+ layout="topleft"
+ left="5"
+ name="front_view"
+ tool_tip="Front View"
+ top_pad="5"
+ width="30">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="front_view" />
+ </button>
+ <button
+ height="30"
+ image_selected="CameraPreset_Mouselook"
+ image_unselected="CameraPreset_Mouselook"
+ layout="topleft"
+ left_pad="5"
+ name="mouselook_view"
+ tool_tip="Mouselook View"
+ top_pad="-30"
+ width="30">
+ <click_callback
+ function="CameraPresets.ChangeView"
+ parameter="mouselook_view" />
+ </button>
+ </panel>
</panel>
<panel
- border="true"
- height="25"
+ border="false"
+ height="42"
layout="topleft"
- left="0"
- top_pad="1"
+ left="2"
+ top_pad="0"
name="buttons"
- width="105">
+ width="148">
<button
height="23"
label=""
layout="topleft"
- left="2"
+ left="23"
is_toggle="true"
image_overlay="Cam_Orbit_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="orbit_btn"
tab_stop="false"
- tool_tip="Orbit Camera"
+ tool_tip="Orbit camera"
value="true"
width="25">
</button>
@@ -110,10 +175,10 @@
left_pad="0"
is_toggle="true"
image_overlay="Cam_Pan_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="pan_btn"
tab_stop="false"
- tool_tip="Pan Camera"
+ tool_tip="Pan camera"
width="25">
</button>
<button
@@ -122,10 +187,10 @@
layout="topleft"
left_pad="0"
image_overlay="Cam_Avatar_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="avatarview_btn"
tab_stop="false"
- tool_tip="See as Avatar"
+ tool_tip="See as avatar"
width="25">
</button>
<button
@@ -135,12 +200,11 @@
left_pad="0"
is_toggle="true"
image_overlay="Cam_FreeCam_Off"
- image_selected="PushButton_Selected_Press"
+ image_selected="PushButton_Selected_Press"
name="freecamera_btn"
tab_stop="false"
- tool_tip="View Object"
+ 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
index 371e239fdb..dc1ee5f24e 100644
--- a/indra/newview/skins/default/xui/en/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/en/floater_choose_group.xml
@@ -1,10 +1,11 @@
<?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"
+ title="GROUPS"
width="280">
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_color_picker.xml b/indra/newview/skins/default/xui/en/floater_color_picker.xml
index f2146339a7..4380ff8f4b 100644
--- a/indra/newview/skins/default/xui/en/floater_color_picker.xml
+++ b/indra/newview/skins/default/xui/en/floater_color_picker.xml
@@ -1,12 +1,13 @@
<?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"
+ title="COLOR PICKER"
width="440">
<text
type="string"
@@ -167,27 +168,29 @@
<check_box
follows="left|bottom"
height="20"
- label="Apply Now"
+ label="Apply now"
layout="topleft"
left="12"
name="apply_immediate"
top_pad="185"
width="100" />
- <button
- follows="left|top"
- height="32"
+ <button
+ follows="left|bottom"
+ height="28"
+ image_selected="eye_button_active.tga"
+ image_unselected="eye_button_inactive.tga"
layout="topleft"
- left_pad="30"
- name="color_pipette"
- picture_style="true"
- width="32" />
+ left_pad="50"
+ name="Pipette"
+ width="28" />
<button
follows="right|bottom"
height="20"
label="Ok"
- label_selected="Select"
+ label_selected="Ok"
layout="topleft"
- left_pad="50"
+ right="-120"
+ top_delta="9"
name="select_btn"
width="100" />
<button
@@ -197,6 +200,7 @@
label_selected="Cancel"
layout="topleft"
left_pad="5"
+ right="-10"
name="cancel_btn"
width="100" />
<text
diff --git a/indra/newview/skins/default/xui/en/floater_critical.xml b/indra/newview/skins/default/xui/en/floater_critical.xml
index 7d1a1113b0..7b5451553f 100644
--- a/indra/newview/skins/default/xui/en/floater_critical.xml
+++ b/indra/newview/skins/default/xui/en/floater_critical.xml
@@ -1,11 +1,11 @@
<?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"
- help_topic="modal_container"
width="600">
<button
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 3b6d5452e3..6c4f10e61e 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
follows="left|top"
height="540"
@@ -8,7 +9,7 @@
name="floater customize"
help_topic="floater_customize"
save_rect="true"
- title="Appearance"
+ title="APPEARANCE"
top_delta="-185"
width="494">
<tab_container
@@ -39,10 +40,10 @@
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -192,7 +193,7 @@
font="SansSerif"
height="16"
layout="topleft"
- left="26"
+ left="8"
name="title"
top="8"
width="355">
@@ -298,7 +299,7 @@ scratch and wear it.
left="8"
name="Create New"
top="104"
- width="120" />
+ width="140" />
<button
follows="right|bottom"
height="20"
@@ -335,15 +336,16 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
+ follows="left|top"
height="16"
layout="topleft"
- left_delta="-325"
+ left="8"
mouse_opaque="true"
top_delta="3"
width="16" />
@@ -398,7 +400,7 @@ scratch and wear it.
font="SansSerif"
height="16"
layout="topleft"
- left="26"
+ left="8"
name="title"
top="8"
width="355">
@@ -590,15 +592,15 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
layout="topleft"
- left_delta="-325"
+ left="8"
mouse_opaque="true"
top_delta="3"
width="16" />
@@ -653,7 +655,7 @@ scratch and wear it.
font="SansSerif"
height="16"
layout="topleft"
- left="26"
+ left="8"
name="title"
top="8"
width="355">
@@ -818,10 +820,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -1006,15 +1008,15 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
layout="topleft"
- left_delta="-325"
+ left="8"
mouse_opaque="true"
top_delta="3"
width="16" />
@@ -1039,7 +1041,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -1099,7 +1101,7 @@ scratch and wear it.
font="SansSerif"
height="16"
layout="topleft"
- left="26"
+ left="8"
name="title"
top="8"
width="355">
@@ -1156,21 +1158,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -1227,15 +1214,15 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
layout="topleft"
- left_delta="-325"
+ left="8"
mouse_opaque="true"
top_delta="3"
width="16" />
@@ -1260,7 +1247,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -1320,7 +1307,7 @@ scratch and wear it.
font="SansSerif"
height="16"
layout="topleft"
- left="26"
+ left="8"
name="title"
top="8"
width="355">
@@ -1377,21 +1364,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -1448,10 +1420,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -1524,21 +1496,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -1600,7 +1557,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -1669,10 +1626,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -1745,21 +1702,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -1821,7 +1763,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -1890,10 +1832,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -1966,21 +1908,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -2054,7 +1981,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -2123,10 +2050,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -2199,21 +2126,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -2275,7 +2187,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -2344,10 +2256,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -2420,21 +2332,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -2496,7 +2393,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -2565,10 +2462,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -2641,21 +2538,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -2717,7 +2599,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -2786,10 +2668,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -2862,21 +2744,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -2938,7 +2805,7 @@ scratch and wear it.
layout="topleft"
left_delta="0"
name="Color/Tint"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="80"
width="64" />
<button
@@ -3007,10 +2874,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -3083,21 +2950,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
@@ -3309,10 +3161,10 @@ scratch and wear it.
height="18"
image_name="Lock"
layout="topleft"
- left="333"
+ left="315"
mouse_opaque="true"
name="square"
- top="5"
+ top="4"
width="18" />
<icon
height="16"
@@ -3385,21 +3237,6 @@ scratch and wear it.
width="373">
Located in [PATH]
</text>
- <spinner
- decimal_digits="0"
- follows="left|top|right"
- height="16"
- increment="1"
- initial_value="0"
- label="Item"
- label_width="30"
- layout="topleft"
- left_delta="2"
- max_val="5"
- name="index"
- text_enabled_color="110, 15, 15, 255"
- top_pad="6"
- width="87" />
<text
type="string"
length="1"
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
index b044cd41e6..35f3e643c3 100644
--- a/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_day_cycle_options.xml
@@ -1,11 +1,12 @@
<?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"
+ title="DAY CYCLE EDITOR"
width="646">
<tab_container
follows="left|top"
@@ -27,16 +28,6 @@
name="Day Cycle"
top="0"
width="642">
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="15"
- label="?"
- layout="topleft"
- left="612"
- name="WLDayCycleHelp"
- top="3"
- width="18" />
<multi_slider
can_edit_text="true"
control_name="WLTimeSlider"
diff --git a/indra/newview/skins/default/xui/en/floater_device_settings.xml b/indra/newview/skins/default/xui/en/floater_device_settings.xml
index 8901608374..91a7a678da 100644
--- a/indra/newview/skins/default/xui/en/floater_device_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_device_settings.xml
@@ -1,10 +1,11 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?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"
+ title="VOICE CHAT DEVICE SETTINGS"
width="405">
<panel
bottom="260"
diff --git a/indra/newview/skins/default/xui/en/floater_env_settings.xml b/indra/newview/skins/default/xui/en/floater_env_settings.xml
index 5e87e065a4..5233cb023d 100644
--- a/indra/newview/skins/default/xui/en/floater_env_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_env_settings.xml
@@ -1,11 +1,12 @@
<?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"
+ title="ENVIRONMENT EDITOR"
width="600">
<floater.string
name="timeStr">
@@ -105,7 +106,7 @@
layout="topleft"
left="390"
name="EnvWaterColor"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top="30"
width="40" />
<text
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
index 4975111111..e4ac8fed77 100644
--- a/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
+++ b/indra/newview/skins/default/xui/en/floater_first_time_tip.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_close="true"
can_minimize="false"
height="250"
diff --git a/indra/newview/skins/default/xui/en/floater_font_test.xml b/indra/newview/skins/default/xui/en/floater_font_test.xml
index 6f9038df62..3ab19ec9d9 100644
--- a/indra/newview/skins/default/xui/en/floater_font_test.xml
+++ b/indra/newview/skins/default/xui/en/floater_font_test.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="800"
layout="topleft"
@@ -7,7 +8,7 @@
min_width="154"
name="contents"
help_topic="contents"
- title="Font Test"
+ title="FONT TEST"
width="500">
<text
type="string"
@@ -199,7 +200,7 @@
bottom_delta="20"
follows="left|top|right"
font="SansSerif"
- font_shadow="hard"
+ font_shadow="none"
height="16"
layout="topleft"
left="16">
diff --git a/indra/newview/skins/default/xui/en/floater_gesture.xml b/indra/newview/skins/default/xui/en/floater_gesture.xml
index 3d0a969112..b23482655c 100644
--- a/indra/newview/skins/default/xui/en/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_gesture.xml
@@ -1,10 +1,11 @@
<?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"
+ title="GESTURES"
background_visible="true"
follows="all"
label="Places"
@@ -59,7 +60,7 @@
<button
follows="bottom|left"
font="SansSerifBigBold"
- tool_tip="Change sort and view of Recent Residents list"
+ tool_tip="Change sort and view of recent residents list"
height="18"
image_disabled="OptionsMenu_Disabled"
image_selected="OptionsMenu_Press"
@@ -67,7 +68,6 @@
layout="topleft"
left="10"
name="recent_viewsort_btn"
- picture_style="true"
top="5"
width="18" />
<button
@@ -80,8 +80,7 @@
layout="topleft"
left_pad="5"
name="new_gesture_btn"
- picture_style="true"
- tool_tip="Make new Gesture"
+ tool_tip="Make new gesture"
top_delta="0"
width="18" />
<button
@@ -94,8 +93,7 @@
layout="topleft"
left_pad="230"
name="del_btn"
- picture_style="true"
- tool_tip="Delete this Gesture"
+ tool_tip="Delete this gesture"
top_delta="0"
width="18" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_god_tools.xml b/indra/newview/skins/default/xui/en/floater_god_tools.xml
index 615c35e6c3..79eed52fbf 100644
--- a/indra/newview/skins/default/xui/en/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_god_tools.xml
@@ -1,10 +1,11 @@
<?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"
+ title="GOD TOOLS"
width="400">
<tab_container
follows="left|top"
@@ -23,6 +24,7 @@
layout="topleft"
left="1"
mouse_opaque="false"
+ help_topic="godtools_grid_tab"
name="grid"
top="16"
width="398">
@@ -61,6 +63,7 @@
layout="topleft"
left_delta="0"
mouse_opaque="false"
+ help_topic="godtools_region_tab"
name="region"
top_delta="0"
width="398">
@@ -96,7 +99,7 @@
layout="topleft"
left="10"
name="check prelude"
- tool_tip="Set this to make the region a prelude."
+ tool_tip="Set this to make the region a prelude"
top_pad="10"
width="180">
<check_box.commit_callback
@@ -108,7 +111,7 @@
layout="topleft"
left_delta="0"
name="check fixed sun"
- tool_tip="Fix the sun position (like in Region/Estate &gt; Terrain."
+ tool_tip="Fix the sun position (like in Region/Estate &gt; Terrain"
top_pad="4"
width="180">
<check_box.commit_callback
@@ -132,7 +135,7 @@
layout="topleft"
left_delta="0"
name="check visible"
- tool_tip="Set this to make the region visible to non-gods."
+ tool_tip="Set this to make the region visible to non-gods"
top_pad="4"
width="180">
<check_box.commit_callback
@@ -144,7 +147,7 @@
layout="topleft"
left_delta="0"
name="check damage"
- tool_tip="Set this to enable damage in this region."
+ tool_tip="Set this to enable damage in this region"
top_pad="4"
width="180">
<check_box.commit_callback
@@ -156,7 +159,7 @@
layout="topleft"
left_delta="0"
name="block dwell"
- tool_tip="Set this to make the region not compute traffic."
+ tool_tip="Set this to make the region not compute traffic"
top_pad="4"
width="180">
<check_box.commit_callback
@@ -180,7 +183,7 @@
layout="topleft"
left_delta="0"
name="is sandbox"
- tool_tip="Toggle whether this is a sandbox region."
+ tool_tip="Toggle whether this is a sandbox region"
top_pad="4"
width="180">
<check_box.commit_callback
@@ -195,7 +198,7 @@
layout="topleft"
left="12"
name="Bake Terrain"
- tool_tip="Save the current terrain as default."
+ tool_tip="Save the current terrain as default"
top_pad="32"
width="110">
<button.commit_callback
@@ -209,7 +212,7 @@
label_selected="Revert Terrain"
layout="topleft"
name="Revert Terrain"
- tool_tip="Replace the current terrain with default."
+ tool_tip="Replace the current terrain with default"
top_pad="10"
width="110">
<button.commit_callback
@@ -223,7 +226,7 @@
label_selected="Swap Terrain"
layout="topleft"
name="Swap Terrain"
- tool_tip="Swap current terrain with default."
+ tool_tip="Swap current terrain with default"
top_pad="10"
width="110">
<button.commit_callback
@@ -423,7 +426,7 @@
layout="topleft"
left="278"
name="Refresh"
- tool_tip="Click here to refresh the above information."
+ tool_tip="Click here to refresh the above information"
top_pad="10"
width="110">
<button.commit_callback
@@ -438,7 +441,7 @@
layout="topleft"
left="278"
name="Apply"
- tool_tip="Click here to apply any changes from above."
+ tool_tip="Click here to apply any changes from above"
top="317"
width="110">
<button.commit_callback
@@ -453,7 +456,7 @@
layout="topleft"
left="130"
name="Select Region"
- tool_tip="Select the whole region with the land tool."
+ tool_tip="Select the whole region with the land tool"
top="238"
width="110">
<button.commit_callback
@@ -468,7 +471,7 @@
layout="topleft"
left_delta="0"
name="Autosave now"
- tool_tip="Save gzipped state to autosave directory."
+ tool_tip="Save gzipped state to autosave directory"
top_pad="10"
width="110">
<button.commit_callback
@@ -483,6 +486,7 @@
layout="topleft"
left_delta="0"
mouse_opaque="false"
+ help_topic="godtools_objects_tab"
name="objects"
top_delta="0"
width="398">
@@ -559,7 +563,7 @@
layout="topleft"
left="278"
name="Apply"
- tool_tip="Click here to apply any changes from above."
+ tool_tip="Click here to apply any changes from above"
top="54"
width="110">
<button.commit_callback
@@ -574,7 +578,7 @@
layout="topleft"
left="8"
name="Set Target"
- tool_tip="Set the target avatar for object deletion."
+ tool_tip="Set the target avatar for object deletion"
top="78"
width="110">
<button.commit_callback
@@ -646,7 +650,7 @@
layout="topleft"
left="12"
name="Get Top Colliders"
- tool_tip="Gets list of objects experiencing the most narrowphase callbacks."
+ tool_tip="Gets list of objects experiencing the most narrowphase callbacks"
top_pad="20"
width="130">
<button.commit_callback
@@ -661,7 +665,7 @@
layout="topleft"
left_delta="0"
name="Get Top Scripts"
- tool_tip="Gets list of objects spending the most time running scripts."
+ tool_tip="Gets list of objects spending the most time running scripts"
top_pad="5"
width="130">
<button.commit_callback
@@ -676,7 +680,7 @@
layout="topleft"
left_delta="0"
name="Scripts digest"
- tool_tip="Gets a list of all scripts and number of occurences of each."
+ tool_tip="Gets a list of all scripts and number of occurences of each"
top_pad="5"
width="130" >
<button.commit_callback
@@ -690,6 +694,7 @@
label="Request"
layout="topleft"
left_delta="0"
+ help_topic="godtools_request_tab"
name="request"
top_delta="0"
width="398">
diff --git a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
index c695753ca3..1e2440580e 100644
--- a/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_hardware_settings.xml
@@ -1,10 +1,11 @@
<?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"
+ title="HARDWARE SETTINGS"
width="500">
<text
type="string"
@@ -131,8 +132,8 @@
layout="topleft"
left="10"
max_val="4096"
- name="GrapicsCardTextureMemory"
- 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."
+ 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
diff --git a/indra/newview/skins/default/xui/en/floater_help_browser.xml b/indra/newview/skins/default/xui/en/floater_help_browser.xml
index 512b4c85a1..f50ff01230 100644
--- a/indra/newview/skins/default/xui/en/floater_help_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_help_browser.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
@@ -9,7 +10,7 @@
help_topic="floater_help_browser"
save_rect="true"
single_instance="true"
- title="Help Browser"
+ title="HELP BROWSER"
width="620">
<floater.string
name="home_page_url">
diff --git a/indra/newview/skins/default/xui/en/floater_hud.xml b/indra/newview/skins/default/xui/en/floater_hud.xml
index 23e0ef50fd..99a6a95828 100644
--- a/indra/newview/skins/default/xui/en/floater_hud.xml
+++ b/indra/newview/skins/default/xui/en/floater_hud.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="292"
layout="topleft"
@@ -7,7 +8,7 @@
help_topic="floater_hud"
save_rect="true"
save_visibility="true"
- title="Tutorial"
+ title="TUTORIAL"
width="362">
<web_browser
border_visible="false"
diff --git a/indra/newview/skins/default/xui/en/floater_im.xml b/indra/newview/skins/default/xui/en/floater_im.xml
index b6cf05aefc..92a6111759 100644
--- a/indra/newview/skins/default/xui/en/floater_im.xml
+++ b/indra/newview/skins/default/xui/en/floater_im.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<multi_floater
+ legacy_header_height="18"
can_resize="true"
follows="left|bottom"
height="422"
diff --git a/indra/newview/skins/default/xui/en/floater_im_session.xml b/indra/newview/skins/default/xui/en/floater_im_session.xml
index 0921ccfb95..70af2f63b6 100644
--- a/indra/newview/skins/default/xui/en/floater_im_session.xml
+++ b/indra/newview/skins/default/xui/en/floater_im_session.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
background_visible="true"
follows="left|top|right|bottom"
- height="250"
+ height="369"
layout="topleft"
left="0"
name="panel_im"
@@ -11,10 +12,13 @@
can_dock="true"
can_minimize="true"
visible="true"
- width="315">
+ width="520"
+ can_resize="true"
+ min_width="350"
+ min_height="350">
<layout_stack follows="left|top|right|bottom"
- height="235"
- width="315"
+ height="354"
+ width="520"
layout="topleft"
orientation="horizontal"
name="im_panels"
@@ -24,45 +28,48 @@
name="panel_im_control_panel"
layout="topleft"
top_delta="-3"
- min_width="96"
- width="96"
- height="225"
+ height="354"
+ follows="left"
label="IM Control Panel"
+ auto_resize="false"
user_resize="false" />
- <layout_panel height="235"
- width="200"
- left_delta="96"
+ <layout_panel height="354"
+ width="355"
+ left_delta="146"
top="0"
user_resize="false">
<button height="12"
+ follows="left|top"
top="8"
label="&lt;&lt;"
layout="topleft"
width="35"
name="slide_left_btn" />
<button height="12"
+ follows="left|top"
top="8"
label="&gt;&gt;"
layout="topleft"
width="35"
name="slide_right_btn" />
- <text_editor
- enabled="false"
- type="string"
+ <chat_history
length="1"
- follows="left|top|right"
+ follows="left|top|right|bottom"
font="SansSerif"
- height="185"
+ height="300"
layout="topleft"
- max_length="2147483647"
- name="im_text"
+ name="chat_history"
parse_highlights="true"
allow_html="true"
- track_bottom="true"
- width="195"
- word_wrap="true">
- </text_editor>
- <line_editor follows="left|right" name="chat_editor" height="20" layout="topleft" width="190">
+ width="350">
+ </chat_history>
+ <line_editor
+ follows="left|right"
+ height="20"
+ label="To"
+ layout="topleft"
+ name="chat_editor"
+ width="345">
</line_editor>
</layout_panel>
</layout_stack>
diff --git a/indra/newview/skins/default/xui/en/floater_image_preview.xml b/indra/newview/skins/default/xui/en/floater_image_preview.xml
index 4e4fe97e62..2562daf4b3 100644
--- a/indra/newview/skins/default/xui/en/floater_image_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_image_preview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="440"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_incoming_call.xml b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
index 95e4247a05..16873df310 100644
--- a/indra/newview/skins/default/xui/en/floater_incoming_call.xml
+++ b/indra/newview/skins/default/xui/en/floater_incoming_call.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_close="false"
can_minimize="false"
can_tear_off="false"
@@ -7,7 +8,7 @@
layout="topleft"
name="incoming call"
help_topic="incoming_call"
- title="Unknown Person is calling"
+ title="UNKNOWN PERSON IS CALLING"
width="240">
<floater.string
name="anonymous">
diff --git a/indra/newview/skins/default/xui/en/floater_inspect.xml b/indra/newview/skins/default/xui/en/floater_inspect.xml
index 339604e658..3f7642fafe 100644
--- a/indra/newview/skins/default/xui/en/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/en/floater_inspect.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="300"
layout="topleft"
@@ -8,7 +9,7 @@
name="inspect"
help_topic="inspect"
save_rect="true"
- title="Inspect Objects"
+ title="INSPECT OBJECTS"
width="400">
<floater.string
name="timeStamp">
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 0f06558dd1..30639f955f 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_resize="true"
height="563"
@@ -11,7 +12,7 @@
save_rect="true"
save_visibility="true"
single_instance="true"
- title="Inventory"
+ title="INVENTORY"
width="467">
<floater.string
name="Title">
@@ -29,403 +30,16 @@
name="Fetched">
Fetched
</floater.string>
- <filter_editor
- search_button_visible="false"
- text_pad_left="12"
- follows="left|top|right"
- height="16"
- label="Type here to search"
- layout="topleft"
- left="6"
- name="inventory search editor"
- top="34"
- width="455" />
- <tab_container
- follows="left|top|right|bottom"
- height="508"
- layout="topleft"
- left_delta="-4"
- name="inventory filter tabs"
- tab_position="top"
- top_pad="4"
- width="463">
- <inventory_panel
- follows="left|top|right|bottom"
- height="491"
- label="All Items"
- layout="topleft"
- left="1"
- name="All Items"
- top="16"
- width="461" />
- <inventory_panel
- follows="left|top|right|bottom"
- height="491"
- label="Recent Items"
- layout="topleft"
- left_delta="0"
- name="Recent Items"
- top_delta="0"
- width="461" />
- </tab_container>
- <menu_bar
- bg_visible="false"
- follows="left|top|right"
- height="18"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="Inventory Menu"
- top_delta="-38"
- width="461">
- <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.ResetFilter" />
- </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 Note"
- 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
+ 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">
+</panel>
</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
index 2882f233c2..4ca6002c13 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml
@@ -1,12 +1,13 @@
<?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"
+ title="INVENTORY ITEM PROPERTIES"
width="350">
<floater.string
name="unknown">
@@ -33,10 +34,10 @@
height="18"
image_name="Lock"
layout="topleft"
- left="294"
+ left="276"
mouse_opaque="true"
name="IconLocked"
- top="5"
+ top="4"
width="18" />
<text
type="string"
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
index 6556a14730..90fee857fb 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml
@@ -1,11 +1,12 @@
<?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"
+ title="INVENTORY_RECENT_ITEMS"
width="280">
<icon
height="16"
diff --git a/indra/newview/skins/default/xui/en/floater_joystick.xml b/indra/newview/skins/default/xui/en/floater_joystick.xml
index c0bcfd2271..4d67e4c343 100644
--- a/indra/newview/skins/default/xui/en/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/en/floater_joystick.xml
@@ -1,10 +1,11 @@
<?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"
+ title="JOYSTICK CONFIGURATION"
width="550">
<floater.string
name="NoDevice">
diff --git a/indra/newview/skins/default/xui/en/floater_lagmeter.xml b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
index 2a431edcdd..19f5155f88 100644
--- a/indra/newview/skins/default/xui/en/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/en/floater_lagmeter.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="150"
layout="topleft"
name="floater_lagmeter"
help_topic="floater_lagmeter"
save_rect="true"
- title="Lag Meter"
+ title="LAG METER"
width="350">
<floater.string
name="max_title_msg">
@@ -183,7 +184,6 @@
layout="topleft"
left="8"
name="client_lagmeter"
- picture_style="true"
tab_stop="false"
tool_tip="Client lag status"
top="24"
@@ -202,7 +202,7 @@
Client
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
type="string"
length="1"
bottom="40"
@@ -216,7 +216,7 @@
Normal
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
bottom="56"
follows="left|top"
height="16"
@@ -232,7 +232,6 @@
layout="topleft"
left="8"
name="network_lagmeter"
- picture_style="true"
tab_stop="false"
tool_tip="Network lag status"
top="64"
@@ -251,7 +250,7 @@
Network
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
type="string"
length="1"
bottom="80"
@@ -265,7 +264,7 @@
Normal
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
bottom="96"
follows="left|top"
height="16"
@@ -281,7 +280,6 @@
layout="topleft"
left="8"
name="server_lagmeter"
- picture_style="true"
tab_stop="false"
tool_tip="Server lag status"
top="104"
@@ -300,7 +298,7 @@
Server
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
type="string"
length="1"
bottom="120"
@@ -314,7 +312,7 @@
Normal
</text>
<text
- visiblity_control="LagMeterShrunk"
+ invisiblity_control="LagMeterShrunk"
bottom="136"
follows="left|top"
height="16"
@@ -322,15 +320,6 @@
left="40"
name="server_lag_cause"
right="-32" />
- <!--button
- bottom="145"
- follows="left|top"
- height="18"
- label="?"
- layout="topleft"
- name="server_help"
- right="-10"
- width="18" /-->
<button
follows="left|top"
height="20"
@@ -338,6 +327,7 @@
layout="topleft"
left="10"
name="minimize"
+ tool_tip="Toggle floater size"
top_delta="4"
width="40">
<button.commit_callback
diff --git a/indra/newview/skins/default/xui/en/floater_land_holdings.xml b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
index f887b48ed0..2c04a94613 100644
--- a/indra/newview/skins/default/xui/en/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/en/floater_land_holdings.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
- height="400"
+ legacy_header_height="18"
+ height="430"
layout="topleft"
name="land holdings floater"
help_topic="land_holdings_floater"
- title="My Land"
- width="280">
+ title="MY LAND"
+ width="600">
<floater.string
name="area_string">
[AREA] m²
@@ -14,81 +15,82 @@
draw_heading="true"
height="170"
layout="topleft"
- left="8"
+ left="10"
name="parcel list"
- top="24"
- width="270">
+ top="28"
+ width="580">
<scroll_list.columns
label="Parcel"
name="name"
- width="69" />
+ width="167" />
<scroll_list.columns
label="Region"
name="location"
- width="74" />
+ width="180" />
<scroll_list.columns
label="Type"
name="type"
- width="55" />
+ width="145" />
<scroll_list.columns
label="Area"
name="area"
- width="10" />
+ width="88" />
<scroll_list.columns
label=""
name="hidden"
width="-1" />
</scroll_list>
<button
- height="20"
- font="SansSerifSmall"
+ height="23"
+ font="SansSerifBold"
label="Teleport"
label_selected="Teleport"
layout="topleft"
- left_delta="4"
+ top="208"
+ left="10"
name="Teleport"
tool_tip="Teleport to the center of this land."
- top_pad="4"
- width="100" />
+ width="80" />
<button
- height="20"
- font="SansSerifSmall"
+ height="23"
+ font="SansSerifBold"
label="Map"
label_selected="Map"
layout="topleft"
- left_pad="4"
+ top="208"
+ left="95"
name="Show on Map"
- tool_tip="Show this land on the world map."
- top_delta="0"
- width="100" />
+ tool_tip="Show this land on the world map"
+ width="80" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
layout="topleft"
- left="12"
+ top="251"
+ left="10"
name="contrib_label"
- top="222"
- width="480">
+ height="16"
+ width="580">
Contributions to your groups:
</text>
<scroll_list
draw_heading="true"
height="75"
layout="topleft"
- left_delta="-4"
name="grant list"
- top_pad="4"
- width="270">
+ top="271"
+ left="10"
+ width="580">
<scroll_list.columns
label="Group"
name="group"
- width="125" />
+ width="290"
+ left_pad="10" />
<scroll_list.columns
label="Area"
name="area"
- width="125" />
+ width="290" />
</scroll_list>
<text
type="string"
@@ -96,12 +98,11 @@
follows="left|top"
height="16"
layout="topleft"
- left_delta="4"
name="allowed_label"
- top_pad="4"
- width="150">
- Allowed land holdings at
-current payment plan:
+ top="366"
+ left="10"
+ width="290">
+ Allowed land holdings at current payment plan:
</text>
<text
type="string"
@@ -109,10 +110,10 @@ current payment plan:
follows="left|top"
height="16"
layout="topleft"
- left_pad="5"
name="allowed_text"
- top_delta="10"
- width="132">
+ top="366"
+ left="305"
+ width="290">
[AREA] m²
</text>
<text
@@ -121,10 +122,10 @@ current payment plan:
follows="left|top"
height="16"
layout="topleft"
- left="12"
+ top="386"
+ left="10"
name="current_label"
- top_pad="5"
- width="150">
+ width="290">
Current land holdings:
</text>
<text
@@ -133,10 +134,10 @@ current payment plan:
follows="left|top"
height="16"
layout="topleft"
- left_pad="5"
+ top="386"
+ left="305"
name="current_text"
- top_delta="0"
- width="132">
+ width="290">
[AREA] m²
</text>
<text
@@ -146,12 +147,11 @@ current payment plan:
font="SansSerifBold"
height="16"
layout="topleft"
- left="12"
+ top="406"
+ left="10"
name="available_label"
- top_pad="5"
- width="150">
- Available for land
-purchases:
+ width="290">
+ Available for land purchases:
</text>
<text
type="string"
@@ -160,10 +160,10 @@ purchases:
font="SansSerifBold"
height="16"
layout="topleft"
- left_pad="5"
name="available_text"
- top_delta="5"
- width="140">
+ top="406"
+ left="305"
+ width="290">
[AREA] m²
</text>
-</floater> \ No newline at end of file
+</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
index dc6c8302a0..e94717fe32 100644
--- a/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/en/floater_live_lsleditor.xml
@@ -1,5 +1,6 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
bevel_style="none"
border_style="line"
can_resize="true"
@@ -11,7 +12,7 @@
name="script ed float"
help_topic="script_ed_float"
save_rect="true"
- title="Script: New Script"
+ title="SCRIPT: NEW SCRIPT"
width="500">
<floater.string
name="not_allowed">
diff --git a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
index fd2ee6ce5c..a5b477313c 100644
--- a/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/en/floater_lsl_guide.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
follows="left|top"
height="400"
@@ -9,7 +10,7 @@
name="script ed float"
help_topic="script_ed_float"
save_rect="true"
- title="LSL Wiki"
+ title="LSL WIKI"
width="370">
<check_box
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/floater_map.xml b/indra/newview/skins/default/xui/en/floater_map.xml
index dc6a02efe1..7b4c5f38a1 100644
--- a/indra/newview/skins/default/xui/en/floater_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_map.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
follows="top|right"
height="225"
@@ -67,7 +68,6 @@
left="0"
name="floater_map_north"
right="10"
- text="N"
text_color="1 1 1 0.7"
top="215">
N
diff --git a/indra/newview/skins/default/xui/en/floater_media_browser.xml b/indra/newview/skins/default/xui/en/floater_media_browser.xml
index ad2c50c6d9..d6b20c8015 100644
--- a/indra/newview/skins/default/xui/en/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_browser.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="440"
layout="topleft"
@@ -9,7 +10,7 @@
help_topic="floater_about"
save_rect="true"
single_instance="true"
- title="Media Browser"
+ title="MEDIA BROWSER"
width="820">
<floater.string
name="home_page_url">
@@ -126,7 +127,6 @@
layout="topleft"
left_delta="55"
name="play"
- picture_style="true"
top_delta="0"
width="55" />
<button
@@ -137,7 +137,6 @@
layout="topleft"
left_delta="0"
name="pause"
- picture_style="true"
top_delta="0"
width="55" />
<button
diff --git a/indra/newview/skins/default/xui/en/floater_media_settings.xml b/indra/newview/skins/default/xui/en/floater_media_settings.xml
index 6ba26f938d..6b884d46a7 100644
--- a/indra/newview/skins/default/xui/en/floater_media_settings.xml
+++ b/indra/newview/skins/default/xui/en/floater_media_settings.xml
@@ -1,20 +1,75 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater bottom="-666" 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="430" min_width="620"
- mouse_opaque="true" name="Medis 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
+ legacy_header_height="18"
+ bottom="-666"
+ 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="430"
+ min_width="620"
+ mouse_opaque="true"
+ name="Medis 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
index bd83da02aa..28a29c42aa 100644
--- a/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/en/floater_mem_leaking.xml
@@ -1,12 +1,13 @@
<?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"
+ title="SIMULATE A MEMORY LEAK"
width="350">
<spinner
decimal_digits="0"
diff --git a/indra/newview/skins/default/xui/en/floater_moveview.xml b/indra/newview/skins/default/xui/en/floater_moveview.xml
index f82e01dd1f..5a8ffcebea 100644
--- a/indra/newview/skins/default/xui/en/floater_moveview.xml
+++ b/indra/newview/skins/default/xui/en/floater_moveview.xml
@@ -1,8 +1,9 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_dock="true"
can_close="true"
- can_minimize="true"
+ can_minimize="false"
center_horiz="true"
follows="bottom"
height="110"
@@ -37,7 +38,7 @@
Fly Backwards (press Down Arrow or S)
</string>
<panel
- border="true"
+ border="false"
height="83"
follows="left|top"
layout="topleft"
@@ -55,9 +56,8 @@
layout="topleft"
left="17"
name="turn left btn"
- picture_style="true"
scale_image="false"
- tool_tip="Turn Left (press Left Arrow or A)"
+ tool_tip="Turn left (press Left Arrow or A)"
top="45"
width="25" />
<button
@@ -69,9 +69,8 @@
layout="topleft"
left_pad="34"
name="turn right btn"
- picture_style="true"
scale_image="false"
- tool_tip="Turn Right (press Right Arrow or D)"
+ tool_tip="Turn right (press Right Arrow or D)"
top_delta="0"
width="25" />
<button
@@ -83,9 +82,8 @@
layout="topleft"
left="10"
name="move up btn"
- picture_style="true"
scale_image="false"
- tool_tip="Fly Up, Press &quot;E&quot;"
+ tool_tip="Fly up, press &quot;E&quot;"
top="14"
width="25" />
<button
@@ -97,9 +95,8 @@
layout="topleft"
left_pad="45"
name="move down btn"
- picture_style="true"
scale_image="false"
- tool_tip="Fly Down, Press &quot;C&quot;"
+ tool_tip="Fly down, press &quot;C&quot;"
top_delta="0"
width="20" />
<joystick_turn
@@ -111,10 +108,9 @@
layout="topleft"
left="46"
name="forward btn"
- picture_style="true"
quadrant="up"
scale_image="false"
- tool_tip="Walk Forward (press Up Arrow or W)"
+ tool_tip="Walk forward (press up arrow or W)"
top_delta="10"
width="21" />
<joystick_turn
@@ -126,16 +122,15 @@
layout="topleft"
left_delta="0"
name="backward btn"
- picture_style="true"
quadrant="down"
scale_image="false"
- tool_tip="Walk Backward (press Down Arrow or S)"
+ tool_tip="Walk backward (press down arrow or S)"
top_delta="30"
width="21" />
</panel>
<!-- Width and height of this panel should be synchronized with panel_stand_stop_flying.xml -->
<panel
- border="true"
+ border="false"
height="27"
layout="topleft"
left="0"
@@ -152,7 +147,7 @@
name="mode_walk_btn"
left="10"
pad_right="0"
- tool_tip="Walking Mode"
+ tool_tip="Walking mode"
top="2"
width="31" />
<button
@@ -167,7 +162,7 @@
name="mode_run_btn"
pad_left="0"
pad_right="0"
- tool_tip="Running Mode"
+ tool_tip="Running mode"
top="2"
width="31" />
<button
@@ -181,7 +176,7 @@
name="mode_fly_btn"
pad_left="0"
pad_right="0"
- tool_tip="Flying Mode"
+ tool_tip="Flying mode"
top="2"
width="31" />
<button
@@ -192,7 +187,7 @@
layout="topleft"
left="0"
name="stop_fly_btn"
- tool_tip="Stop Flying"
+ tool_tip="Stop flying"
top="2"
width="115" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/floater_mute_object.xml b/indra/newview/skins/default/xui/en/floater_mute_object.xml
index 06a03ff340..454b1c43b2 100644
--- a/indra/newview/skins/default/xui/en/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_mute_object.xml
@@ -1,11 +1,12 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?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"
+ title="BLOCK OBJECT BY NAME"
width="375">
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_my_friends.xml b/indra/newview/skins/default/xui/en/floater_my_friends.xml
index a9a18f44c4..e7efcc7844 100644
--- a/indra/newview/skins/default/xui/en/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/en/floater_my_friends.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_close="false"
can_resize="true"
height="390"
@@ -10,7 +11,7 @@
help_topic="floater_my_friends"
save_rect="true"
single_instance="true"
- title="Contacts"
+ title="CONTACTS"
width="395">
<tab_container
follows="all"
@@ -28,6 +29,7 @@
label="Friends"
layout="topleft"
left="0"
+ help_topic="my_friends_friends_tab"
name="friends_panel"
width="370" />
<panel
@@ -36,6 +38,7 @@
label="Groups"
layout="topleft"
left="0"
+ help_topic="my_friends_groups_tab"
name="groups_panel"
width="370" />
</tab_container>
diff --git a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
index f1976afb4a..7f58ea132e 100644
--- a/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
+++ b/indra/newview/skins/default/xui/en/floater_nearby_chat.xml
@@ -1,52 +1,37 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
- background_opaque="false"
- background_visible="true"
+<floater
+ legacy_header_height="18"
+ can_minimize="true"
+ can_tear_off="false"
+ can_resize="false"
+ can_drag_on_left="false"
+ can_close="false"
+ can_dock="true"
bevel_style="in"
- bg_alpha_color="0.3 0.3 0.3 1.0"
height="300"
layout="topleft"
name="nearby_chat"
help_topic="nearby_chat"
save_rect="true"
- title="Nearby Chat"
+ title="NEARBY CHAT"
+ save_dock_state="true"
+ save_visibility="true"
single_instance="true"
width="320">
- <panel top="20" width="320" 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="5" left="250"
- 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="5" left="275"
- 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="5" left="300"
- width="15" height="15" follows="top|right"
- color="1 1 1 1" enabled="true" image_name="closebox.tga"
- name="close_btn"/>
- </panel>
- <text_editor
+ <chat_history
allow_html="true"
bg_readonly_color="ChatHistoryBgColor"
bg_writeable_color="ChatHistoryBgColor"
- follows="left|top|right|bottom"
+ follows="all"
+ left="1"
+ top="20"
font="SansSerif"
layout="topleft"
- height="320"
- max_length="2147483647"
- name="Chat History Editor"
+ height="280"
+ name="chat_history"
parse_highlights="true"
- read_only="true"
text_color="ChatHistoryTextColor"
text_readonly_color="ChatHistoryTextColor"
- bottom="0"
- track_bottom="true"
- width="250"
- word_wrap="true" />
+ width="320"/>
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_notification.xml b/indra/newview/skins/default/xui/en/floater_notification.xml
index cd88ec2f3f..1f9ddecac2 100644
--- a/indra/newview/skins/default/xui/en/floater_notification.xml
+++ b/indra/newview/skins/default/xui/en/floater_notification.xml
@@ -1,11 +1,12 @@
<?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"
+ title="NOTIFICATIONS CONSOLE"
width="200">
<text_editor
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_notifications_console.xml b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
index 3783417cdb..ca81b9bcf0 100644
--- a/indra/newview/skins/default/xui/en/floater_notifications_console.xml
+++ b/indra/newview/skins/default/xui/en/floater_notifications_console.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="500"
layout="topleft"
@@ -7,7 +8,7 @@
name="notifications_console"
help_topic="notifications_console"
single_instance="true"
- title="Notifications Console"
+ title="NOTIFICATIONS CONSOLE"
width="500">
<combo_box
follows="left|right|top"
diff --git a/indra/newview/skins/default/xui/en/floater_openobject.xml b/indra/newview/skins/default/xui/en/floater_openobject.xml
index 17f7e9bf67..3fd118df1c 100644
--- a/indra/newview/skins/default/xui/en/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/en/floater_openobject.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
default_tab_group="1"
height="350"
@@ -9,7 +10,7 @@
name="objectcontents"
help_topic="objectcontents"
save_rect="true"
- title="Object Contents"
+ title="OBJECT CONTENTS"
width="300">
<text
type="string"
@@ -25,7 +26,7 @@
width="284">
[DESC]:
</text>
- <panel_inventory
+ <panel_inventory_object
background_visible="false"
draw_border="false"
follows="all"
diff --git a/indra/newview/skins/default/xui/en/floater_pay.xml b/indra/newview/skins/default/xui/en/floater_pay.xml
index 5f70f09a34..b4becfa022 100644
--- a/indra/newview/skins/default/xui/en/floater_pay.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="185"
layout="topleft"
@@ -34,7 +35,7 @@
type="string"
length="1"
follows="left|top"
- font="SansSerif"
+ font="SansSerifSmall"
height="16"
layout="topleft"
left_pad="7"
@@ -44,6 +45,7 @@
</text>
<button
height="23"
+ font="SansSerifSmall"
label="L$1"
label_selected="L$1"
layout="topleft"
@@ -53,7 +55,8 @@
width="80" />
<button
height="23"
- label="L$5"
+ label="L$1"
+ font="SansSerif"
label_selected="L$5"
layout="topleft"
left_pad="15"
@@ -62,6 +65,7 @@
<button
height="23"
label="L$10"
+ font="SansSerifHuge"
label_selected="L$10"
layout="topleft"
left="25"
diff --git a/indra/newview/skins/default/xui/en/floater_pay_object.xml b/indra/newview/skins/default/xui/en/floater_pay_object.xml
index acff55386b..1946920a9c 100644
--- a/indra/newview/skins/default/xui/en/floater_pay_object.xml
+++ b/indra/newview/skins/default/xui/en/floater_pay_object.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="220"
layout="topleft"
@@ -7,32 +8,14 @@
help_topic="give_money"
save_rect="true"
width="225">
- <text
- type="string"
- length="1"
- follows="left|top"
- font="SansSerifBold"
- height="18"
- layout="topleft"
- left="12"
- name="payee_group"
- top="7"
- width="75">
- Pay group:
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- font="SansSerifBold"
- height="18"
- layout="topleft"
- left="12"
- name="payee_resident"
- top="7"
- width="75">
- Pay resident:
- </text>
+ <string
+ name="payee_group">
+ Pay Group
+ </string>
+ <string
+ name="payee_resident">
+ Pay Resident
+ </string>
<icon
height="16"
width="16"
@@ -40,7 +23,7 @@
mouse_opaque="true"
name="icon_person"
tool_tip="Person"
- top_pad="0"
+ top_pad="24"
left="10"
/>
<text
diff --git a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
index f65bb6f32f..6faab84159 100644
--- a/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
+++ b/indra/newview/skins/default/xui/en/floater_perm_prefs.xml
@@ -1,11 +1,12 @@
<?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"
+ title="DEFAULT UPLOAD PERMISSIONS"
width="315">
<panel
follows="left|top|right|bottom"
@@ -16,20 +17,6 @@
name="permissions"
top="20"
width="315">
- <button
- follows="left"
- height="18"
- label="?"
- label_selected="?"
- layout="topleft"
- left="260"
- name="help"
- top="7"
- width="22">
- <button.commit_callback
- function="Notification.Show"
- parameter="ClickUploadHelpPermissions" />
- </button>
<check_box
control_name="ShareWithGroup"
height="16"
diff --git a/indra/newview/skins/default/xui/en/floater_post_process.xml b/indra/newview/skins/default/xui/en/floater_post_process.xml
index aaf7aecd6b..05559adf89 100644
--- a/indra/newview/skins/default/xui/en/floater_post_process.xml
+++ b/indra/newview/skins/default/xui/en/floater_post_process.xml
@@ -1,10 +1,11 @@
<?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"
+ title="POST-PROCESS SETTINGS"
width="400">
<tab_container
follows="left|top"
@@ -23,6 +24,7 @@
layout="topleft"
left="1"
mouse_opaque="false"
+ help_topic="post_process_color_filter_tab"
name="wmiColorFilterPanel"
top="0"
width="398">
@@ -184,6 +186,7 @@
layout="topleft"
left_delta="0"
mouse_opaque="false"
+ help_topic="post_process_night_vision_tab"
name="wmiNightVisionPanel"
top_delta="-236"
width="398">
@@ -279,6 +282,7 @@
label="Bloom"
layout="topleft"
left_delta="0"
+ help_topic="post_process_bloom_tab"
name="wmiBloomPanel"
top_delta="-236"
width="398">
@@ -374,6 +378,7 @@
layout="topleft"
left_delta="0"
mouse_opaque="false"
+ help_topic="post_process_extras_tab"
name="Extras"
top_delta="-236"
width="398">
diff --git a/indra/newview/skins/default/xui/en/floater_postcard.xml b/indra/newview/skins/default/xui/en/floater_postcard.xml
index d93cad6dbd..3a7b6cc832 100644
--- a/indra/newview/skins/default/xui/en/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/en/floater_postcard.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_minimize="false"
can_resize="true"
@@ -9,7 +10,7 @@
min_width="450"
name="Postcard"
help_topic="postcard"
- title="Email Snapshot"
+ title="EMAIL SNAPSHOT"
width="450">
<floater.string
name="default_subject">
diff --git a/indra/newview/skins/default/xui/en/floater_preferences.xml b/indra/newview/skins/default/xui/en/floater_preferences.xml
index d655c268b2..d182cdc6bb 100644
--- a/indra/newview/skins/default/xui/en/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/en/floater_preferences.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
center_horiz="true"
center_vert="true"
default_tab_group="1"
@@ -8,36 +9,36 @@
name="Preferences"
help_topic="preferences"
single_instance="true"
- title="Preferences"
+ title="PREFERENCES"
width="620">
<button
follows="right|bottom"
- height="20"
+ height="23"
label="OK"
label_selected="OK"
layout="topleft"
- left="427"
+ right="-105"
name="OK"
- top="435"
+ top="433"
width="90">
<button.commit_callback
function="Pref.OK" />
</button>
<button
follows="right|bottom"
- height="20"
+ height="23"
label="Cancel"
label_selected="Cancel"
layout="topleft"
- left_pad="3"
+ left_pad="5"
name="Cancel"
- top_delta="0"
+ right="-10"
width="90" >
<button.commit_callback
function="Pref.Cancel" />
</button>
<tab_container
- follows="left|top|right|bottom"
+ follows="all"
height="410"
layout="topleft"
left="0"
@@ -48,59 +49,61 @@
top="21"
width="620">
<panel
- class="panel_preference"
+ class="panel_preference"
filename="panel_preferences_general.xml"
label="General"
layout="topleft"
+ help_topic="preferences_general_tab"
name="general" />
<panel
- class="panel_preference"
+ 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_im.xml"
+ filename="panel_preferences_privacy.xml"
label="Privacy"
layout="topleft"
+ help_topic="preferences_im_tab"
name="im" />
<panel
class="panel_preference"
- filename="panel_preferences_audio.xml"
+ 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_popups.xml"
+ filename="panel_preferences_alerts.xml"
label="Alerts"
layout="topleft"
+ help_topic="preferences_msgs_tab"
name="msgs" />
<panel
class="panel_preference"
- filename="panel_preferences_input.xml"
+ 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" />
- <panel
- class="panel_preference"
- filename="panel_preferences_advanced2.xml"
- label="Move or Kill"
- layout="topleft"
- name="advanced2" />
</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
index 5756f9590e..3b84358484 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_animation.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_animation.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
height="85"
layout="topleft"
@@ -43,7 +44,7 @@
layout="topleft"
left="10"
name="Anim play btn"
- tool_tip="Play this animation so that others can see it."
+ tool_tip="Play this animation so that others can see it"
top="47"
width="125" />
<button
@@ -54,7 +55,7 @@
layout="topleft"
left_pad="5"
name="Anim audition btn"
- tool_tip="Play this animation so that only you can see it."
+ 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
index 07167c3ae4..2017cf2bd1 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_classified.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_classified.xml
@@ -1,12 +1,13 @@
<?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"
+ title="CLASSIFIED INFORMATION"
width="440">
<floater.string
name="Title">
diff --git a/indra/newview/skins/default/xui/en/floater_preview_event.xml b/indra/newview/skins/default/xui/en/floater_preview_event.xml
index 77fbe7c060..a4066b34c5 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_event.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_event.xml
@@ -1,12 +1,13 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<?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"
+ title="EVENT INFORMATION"
width="440">
<floater.string
name="Title">
diff --git a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
index a523f40bb8..4f3978a5e3 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture.xml
@@ -1,7 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
- height="800"
+ height="460"
layout="topleft"
name="gesture_preview"
help_topic="gesture_preview"
@@ -46,10 +47,11 @@
height="10"
layout="topleft"
left="10"
- name="Name"
+ name="desc_label"
top="25"
+ font.style="BOLD"
width="100">
- Name (not working yet):
+ Description:
</text>
<line_editor
follows="left|top"
@@ -67,70 +69,270 @@
height="10"
layout="topleft"
left="10"
- name="desc_label"
+ font.style="BOLD"
+ name="trigger_label"
top_pad="10"
width="100">
- Description:
+ Trigger:
</text>
<line_editor
follows="left|top"
- height="40"
+ 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="desc2"
+ 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"
+ font="SansSerifSmall"
+ 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" />
-
- <accordion
- layout="topleft"
- left="2"
- width="276"
- top="95"
- height="580"
- follows="all"
- name="group_accordion">
- <accordion_tab
- min_height="90"
- title="Shortcuts"
- name="snapshot_destination_tab"
- an_resize="false">
- <panel
- class="floater_preview_shortcut"
- filename="floater_preview_gesture_shortcut.xml"
- name="floater_preview_shortcut"/>
- </accordion_tab>
- <accordion_tab
- min_height="400"
- title="Steps"
- name="snapshot_file_settings_tab"
- can_resize="false">
- <panel
- class="floater_preview_steps"
- filename="floater_preview_gesture_steps.xml"
- name="floater_preview_steps"/>
- </accordion_tab>
- <accordion_tab
- min_height="155"
- title="Info"
- name="snapshot_capture_tab"
- can_resize="false">
- <panel
- class="floater_preview_info"
- filename="floater_preview_gesture_info.xml"
- name="floater_preview_info"/>
- </accordion_tab>
- <!--accordion_tab
- min_height="100"
- title="Permissions"
- name="snapshot_capture_tab2"
- can_resize="false">
- <panel
- class="floater_snapshot_capture"
- filename="floater_snapshot_Permissions.xml"
- name="snapshot_capture_panel2"/>
- </accordion_tab-->
- </accordion>
- <!--check_box
+ <button
+ follows="top|left"
+ height="20"
+ font="SansSerifSmall"
+ label="Up"
+ layout="topleft"
+ left_pad="10"
+ name="up_btn"
+ top_delta="0"
+ width="70" />
+ <button
+ follows="top|left"
+ height="20"
+ font="SansSerifSmall"
+ label="Down"
+ layout="topleft"
+ left_delta="0"
+ name="down_btn"
+ top_pad="10"
+ width="70" />
+ <button
+ follows="top|left"
+ height="20"
+ font="SansSerifSmall"
+ 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"
@@ -138,35 +340,24 @@
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="365"
- width="100" /-->
-
+ top_pad="0"
+ width="100" />
<button
- follows="bottom|left"
+ follows="top|left"
height="20"
label="Preview"
layout="topleft"
- left="20"
+ left_delta="75"
name="preview_btn"
- top_pad="30"
+ top_delta="2"
width="80" />
<button
follows="top|left"
height="20"
label="Save"
layout="topleft"
- left_pad="5"
+ left_pad="10"
name="save_btn"
top_delta="0"
width="80" />
- <button
- follows="top|left"
- height="20"
- label="Cancel (not working)"
- layout="topleft"
- left_pad="5"
- name="cancel_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
index 43e4f8a348..66408a5057 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_info.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
follows="left|top"
height="155"
@@ -7,7 +8,7 @@
name="Gesture"
help_topic="gesture"
save_rect="true"
- title="Gesture Shortcut"
+ title="GESTURE SHORTCUT"
width="260">
<scroll_list
follows="top|left"
@@ -53,4 +54,4 @@
name="save_btn"
top_delta="0"
width="80" /-->
-</floater> \ No newline at end of file
+</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
index 606ae1a82a..26252a7a16 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_shortcut.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
follows="left|top"
height="90"
@@ -7,7 +8,7 @@
name="Gesture"
help_topic="gesture"
save_rect="true"
- title="Gesture Shortcut"
+ title="GESTURE SHORTCUT"
width="260">
<text
type="string"
@@ -84,4 +85,4 @@
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> \ No newline at end of file
+</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
index 4b4f611b59..34f707cd2a 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_gesture_steps.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
follows="left|top"
height="155"
@@ -7,7 +8,7 @@
name="Gesture"
help_topic="gesture"
save_rect="true"
- title="Gesture Shortcut"
+ title="GESTURE SHORTCUT"
width="260">
<scroll_list
follows="top|left"
@@ -238,4 +239,4 @@ unless you add wait steps.
name="wait_time_editor"
top_delta="0"
width="50" /-->
-</floater> \ No newline at end of file
+</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
index 448b0fa6af..06dbdc9539 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_notecard.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_resize="true"
default_tab_group="1"
@@ -10,7 +11,7 @@
min_width="234"
name="preview notecard"
help_topic="preview_notecard"
- title="Note:"
+ title="NOTE:"
width="400">
<floater.string
name="no_object">
@@ -33,10 +34,10 @@
height="18"
image_name="Lock"
layout="topleft"
- left="340"
+ left="322"
mouse_opaque="true"
name="lock"
- top="1"
+ top="4"
width="18" />
<text
type="string"
@@ -74,7 +75,7 @@
left="4"
max_length="65536"
name="Notecard Editor"
- allow_html="true"
+ allow_html="false"
handle_edit_keys_directly="true"
tab_group="1"
top="46"
@@ -83,7 +84,7 @@
Loading...
</text_editor>
<button
- follows="left|bottom"
+ follows="right|bottom"
height="22"
label="Save"
label_selected="Save"
diff --git a/indra/newview/skins/default/xui/en/floater_preview_sound.xml b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
index 4220655a6f..95347f0dff 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_sound.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_sound.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
height="85"
layout="topleft"
@@ -44,7 +45,7 @@
sound_flags="0"
top="55"
left="10"
- tool_tip="Play this sound so that others can hear it."
+ tool_tip="Play this sound so that others can hear it"
width="125" />
<button
follows="left|top"
@@ -55,7 +56,7 @@
layout="topleft"
name="Sound audition btn"
sound_flags="0"
- tool_tip="Play this sound so that only you can hear it."
+ tool_tip="Play this sound so that only you can hear it"
left_pad="10"
width="125" />
diff --git a/indra/newview/skins/default/xui/en/floater_preview_texture.xml b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
index a243cb399e..e7abfb075a 100644
--- a/indra/newview/skins/default/xui/en/floater_preview_texture.xml
+++ b/indra/newview/skins/default/xui/en/floater_preview_texture.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_resize="true"
follows="left|bottom"
@@ -45,22 +46,22 @@
<button
follows="left|bottom"
height="22"
- label="Delete"
+ label="OK"
layout="topleft"
left="80"
- name="Discard"
+ name="Keep"
top="302"
width="100" />
<button
follows="left|bottom"
height="22"
- label="Save"
+ label="Cancel"
layout="topleft"
left_pad="5"
- name="Keep"
+ name="Discard"
top_delta="0"
width="100" />
- <text
+ <text
type="string"
length="1"
follows="left|bottom"
@@ -68,8 +69,66 @@
layout="topleft"
left="13"
name="dimensions"
- top="287"
+ top="309"
width="303">
[WIDTH]px x [HEIGHT]px
</text>
+ <text
+ type="string"
+ length="1"
+ bg_visible="false"
+ border_drop_shadow_visible="false"
+ border_visible="false"
+ top="309"
+ drop_shadow_visible="true"
+ enabled="true"
+ follows="right|bottom"
+ font="SansSerifSmall"
+ h_pad="0"
+ halign="right"
+ height="14"
+ left="54"
+ mouse_opaque="true"
+ name="aspect_ratio"
+ v_pad="0"
+ width="110">
+ Preview Aspect Ratio
+ </text>
+ <combo_box
+ allow_text_entry="true"
+ top="306"
+ follows="right|bottom"
+ height="20"
+ left="176"
+ 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 1st Life profile">
+ 1:1
+ </combo_item>
+ <combo_item name="4:3" value="4:3" tool_tip="2nd 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>
</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
index 3fadc15616..9bb30f8e86 100644
--- a/indra/newview/skins/default/xui/en/floater_region_info.xml
+++ b/indra/newview/skins/default/xui/en/floater_region_info.xml
@@ -1,11 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="512"
help_topic="regioninfo"
layout="topleft"
name="regioninfo"
save_rect="true"
- title="Region/Estate"
+ title="REGION/ESTATE"
width="480">
<tab_container
bottom="512"
diff --git a/indra/newview/skins/default/xui/en/floater_report_abuse.xml b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
index abde4ba5fa..696233676c 100644
--- a/indra/newview/skins/default/xui/en/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/en/floater_report_abuse.xml
@@ -1,10 +1,11 @@
<?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"
+ title="REPORT ABUSE"
width="333">
<floater.string
name="Screenshot">
@@ -14,19 +15,19 @@
allow_no_texture="true"
default_image_name="None"
follows="left|top"
- height="125"
+ height="150"
layout="topleft"
- left="10"
- name="screenshot"
- top="23"
- width="160" />
+ left="60"
+ name=""
+ top="15"
+ width="220" />
<check_box
height="15"
label="Use this screenshot"
layout="topleft"
- left_pad="5"
+ left="8"
name="screen_check"
- top="120"
+ top_pad="-12"
width="116" />
<text
type="string"
@@ -38,8 +39,8 @@
layout="topleft"
left="10"
name="reporter_title"
- top="140"
- width="60">
+ top_pad="0"
+ width="100">
Reporter:
</text>
<text
@@ -48,24 +49,25 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="10"
+ left_pad="5"
name="reporter_field"
top_delta="0"
- width="193">
- Loremipsum Dolorsitamut
+ use_ellipses="true"
+ width="200">
+ Loremipsum Dolorsitamut Longnamez
</text>
<text
type="string"
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="sim_title"
- top_pad="5"
- width="60">
+ top_pad="2"
+ width="100">
Region:
</text>
<text
@@ -74,10 +76,11 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="2"
+ left_pad="5"
name="sim_field"
top_delta="0"
- width="193">
+ use_ellipses="true"
+ width="200">
Region Name
</text>
<text
@@ -85,13 +88,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="pos_title"
- top_pad="5"
- width="50">
+ top_pad="2"
+ width="100">
Position:
</text>
<text
@@ -100,10 +103,10 @@
follows="left|top"
height="16"
layout="topleft"
- left_pad="12"
+ left_pad="5"
name="pos_field"
top_delta="0"
- width="193">
+ width="200">
{128.1, 128.1, 15.4}
</text>
<text
@@ -114,7 +117,7 @@
layout="topleft"
left="10"
name="select_object_label"
- top_pad="5"
+ top_pad="2"
width="310">
Click the button, then the abusive object:
</text>
@@ -123,7 +126,6 @@
layout="topleft"
left_delta="0"
name="pick_btn"
- picture_style="true"
image_overlay="Inv_Object"
tool_tip="Object Picker - Identify an object as the subject of this report"
top_pad="0"
@@ -133,13 +135,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
name="object_name_label"
top_delta="0"
- width="60">
+ width="80">
Object:
</text>
<text
@@ -151,7 +153,8 @@
left_pad="6"
name="object_name"
top_delta="0"
- width="157">
+ use_ellipses="true"
+ width="185">
Consetetur Sadipscing
</text>
<text
@@ -159,13 +162,13 @@
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="48"
name="owner_name_label"
top_pad="0"
- width="60">
+ width="80">
Owner:
</text>
<text
@@ -177,8 +180,9 @@
left_pad="6"
name="owner_name"
top_delta="0"
- width="157">
- Hendrerit Vulputate
+ use_ellipses="true"
+ width="185">
+ Hendrerit Vulputate Kamawashi Longname
</text>
<combo_box
height="23"
@@ -349,8 +353,8 @@
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -368,11 +372,10 @@
left_delta="0"
max_length="32"
name="abuser_name_edit"
- top_pad="2"
+ top_pad="0"
width="195" />
<button
height="23"
- font="SansSerifSmall"
label="Choose"
layout="topleft"
left_pad="5"
@@ -394,13 +397,13 @@
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left="10"
name="abuser_name_title2"
- top_pad="5"
+ top_pad="2"
width="313">
Location of Abuse:
</text>
@@ -413,19 +416,19 @@
left="10"
max_length="256"
name="abuse_location_edit"
- top_pad="2"
+ top_pad="0"
width="313" />
<text
type="string"
length="1"
follows="left|top"
height="16"
- font.name="SansSerif"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
name="sum_title"
- top_pad="5"
+ top_pad="2"
width="313">
Summary:
</text>
@@ -438,14 +441,14 @@
left_delta="0"
max_length="64"
name="summary_edit"
- top_pad="2"
+ top_pad="0"
width="313" />
<text
type="string"
length="1"
follows="left|top"
- height="16"
- font.name="SansSerif"
+ height="14"
+ font.name="SansSerif"
font.style="BOLD"
layout="topleft"
left_delta="0"
@@ -461,9 +464,9 @@
height="16"
layout="topleft"
name="bug_aviso"
- left_pad="0"
+ left_pad="10"
width="200">
- Please be as specific as possible.
+ Please be as specific as possible
</text>
<text_editor
follows="left|top"
@@ -479,16 +482,15 @@
type="string"
length="1"
follows="left|top"
- height="50"
+ height="30"
layout="topleft"
left="10"
- font.name="SansSerif"
- font.style="BOLD"
+ font.name="SansSerifSmall"
name="incomplete_title"
- top_pad="5"
+ top_pad="2"
word_wrap="true"
width="313">
- Note: Incomplete reports won't be investigated.
+ * Incomplete reports won't be investigated
</text>
<button
left="80"
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
index 2085b74a55..bd9925be1d 100644
--- a/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_debug_panel.xml
@@ -1,13 +1,14 @@
<?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]"
+ short_title="[ALL SCRIPTS]"
+ title="[ALL SCRIPTS]"
width="440">
<text_editor
bottom="197"
diff --git a/indra/newview/skins/default/xui/en/floater_script_preview.xml b/indra/newview/skins/default/xui/en/floater_script_preview.xml
index 54ab30124a..bb0702c353 100644
--- a/indra/newview/skins/default/xui/en/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_preview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_resize="true"
height="550"
@@ -10,7 +11,7 @@
name="preview lsl text"
help_topic="preview_lsl_text"
save_rect="true"
- title="Script: Rotation Script"
+ title="SCRIPT: ROTATION SCRIPT"
top_delta="0"
width="500">
<floater.string
@@ -30,10 +31,10 @@
height="18"
image_name="Lock"
layout="topleft"
- left="444"
+ left="426"
mouse_opaque="true"
name="lock"
- top="3"
+ top="4"
width="18" />
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_script_queue.xml b/indra/newview/skins/default/xui/en/floater_script_queue.xml
index 467dcfae20..60a26fcf1d 100644
--- a/indra/newview/skins/default/xui/en/floater_script_queue.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_queue.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
auto_tile="true"
can_resize="true"
height="400"
@@ -7,7 +8,7 @@
name="queue"
help_topic="queue"
save_rect="true"
- title="Reset Progress"
+ title="RESET PROGRESS"
width="300">
<floater.string
name="Starting">
diff --git a/indra/newview/skins/default/xui/en/floater_script_search.xml b/indra/newview/skins/default/xui/en/floater_script_search.xml
index 545abc39a2..ade0156bc7 100644
--- a/indra/newview/skins/default/xui/en/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/en/floater_script_search.xml
@@ -1,11 +1,12 @@
<?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"
+ title="SCRIPT SEARCH"
width="300">
<check_box
control_name="LSLFindCaseInsensitivity"
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..f7ba719dc2
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_search.xml
@@ -0,0 +1,61 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ can_resize="true"
+ height="400"
+ layout="topleft"
+ min_height="140"
+ min_width="467"
+ name="floater_search"
+ help_topic="floater_search"
+ save_rect="true"
+ single_instance="true"
+ title="SEARCH [SECOND_LIFE]"
+ width="620">
+ <floater.string
+ name="search_url">
+ http://eniac21.lindenlab.com:10001/viewer
+ </floater.string>
+ <floater.string
+ name="loading_text">
+ Loading...
+ </floater.string>
+ <floater.string
+ name="done_text">
+ Done
+ </floater.string>
+ <layout_stack
+ bottom="400"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="10"
+ name="stack1"
+ top="20"
+ width="600">
+ <layout_panel
+ height="12"
+ layout="topleft"
+ left_delta="0"
+ name="external_controls"
+ top_delta="0"
+ user_resize="false"
+ width="570">
+ <web_browser
+ bottom="-10"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="0"
+ name="browser"
+ top="0"
+ width="570" />
+ <text
+ follows="bottom|left"
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="status_text"
+ top_pad="4"
+ width="150" />
+ </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
index 8e1317440e..31d133ff9b 100644
--- a/indra/newview/skins/default/xui/en/floater_select_key.xml
+++ b/indra/newview/skins/default/xui/en/floater_select_key.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
border="true"
can_close="false"
can_minimize="false"
height="100"
layout="topleft"
name="modal container"
- help_topic="modal_container"
width="240">
<button
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_sell_land.xml b/indra/newview/skins/default/xui/en/floater_sell_land.xml
index 652ed96192..2cf800fb15 100644
--- a/indra/newview/skins/default/xui/en/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_sell_land.xml
@@ -1,18 +1,18 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="450"
layout="topleft"
name="sell land"
help_topic="sell_land"
single_instance="true"
- title="Sell Land"
+ title="SELL LAND"
width="313">
<scroll_container
color="DkGray2"
follows="left|top|right|bottom"
height="435"
- min_height="300"
layout="topleft"
name="profile_scroll"
reserve_scroll_corner="true"
@@ -95,27 +95,16 @@
width="200">
To sell this parcel:
</text>
- <icon
- follows="top|left"
- height="64"
- image_name="badge_note.j2c"
- layout="topleft"
- left="0"
- name="step_price"
- top="206"
- width="64" />
<text
type="string"
length="1"
- bottom_delta="-38"
follows="top|left"
font="SansSerif"
height="16"
layout="topleft"
- left="72"
- name="price_label"
- right="-20">
- Set a price:
+ left="30"
+ name="price_label">
+ 1. Set a price:
</text>
<text
type="string"
@@ -123,9 +112,8 @@
follows="top|left"
height="16"
layout="topleft"
- left="72"
- name="price_text"
- right="-20">
+ left="40"
+ name="price_text">
Choose an appropriate price.
</text>
<text
@@ -133,7 +121,7 @@
length="1"
height="16"
layout="topleft"
- left="72"
+ left="40"
name="price_ld"
width="20">
L$
@@ -155,32 +143,22 @@
length="1"
height="16"
layout="topleft"
- left="72"
+ left="40"
name="price_per_m"
top_delta="25"
width="200">
(L$[PER_METER] per m²)
</text>
- <icon
- follows="top|left"
- height="64"
- image_name="badge_note.j2c"
- layout="topleft"
- left="0"
- name="step_sell_to"
- width="64" />
<text
type="string"
length="1"
- bottom_delta="-38"
follows="top|left"
font="SansSerif"
height="16"
layout="topleft"
- left="72"
- name="sell_to_label"
- right="-20">
- Sell the land to:
+ left="30"
+ name="sell_to_label">
+ 2. Sell the land to:
</text>
<text
type="string"
@@ -188,7 +166,7 @@
follows="top|left"
height="25"
layout="topleft"
- left="72"
+ left="40"
word_wrap="true"
name="sell_to_text"
right="-20">
@@ -234,26 +212,16 @@
name="sell_to_select_agent"
top_delta="0"
width="60" />
- <icon
- follows="top|left"
- height="64"
- image_name="badge_note.j2c"
- layout="topleft"
- left="0"
- name="step_sell_objects"
- width="64" />
<text
type="string"
length="1"
- bottom_delta="-38"
follows="top|left"
font="SansSerif"
height="16"
layout="topleft"
- left="72"
- name="sell_objects_label"
- right="-20">
- Sell the objects with the land?
+ left="30"
+ name="sell_objects_label">
+ 3. Sell the objects with the land?
</text>
<text
type="string"
@@ -263,7 +231,7 @@
height="25"
layout="topleft"
word_wrap="true"
- left="72"
+ left="40"
name="sell_objects_text">
Land owner&apos;s transferable objects on parcel will change ownership.
</text>
@@ -272,7 +240,7 @@
follows="top|right"
height="40"
layout="topleft"
- left="72"
+ left="40"
name="sell_objects"
right="420">
<radio_item
@@ -303,7 +271,7 @@
label="Show Objects"
layout="topleft"
name="show_objects"
- left="100"
+ left="70"
top_pad="10"
width="110" />
<text
diff --git a/indra/newview/skins/default/xui/en/floater_settings_debug.xml b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
index b7779687ec..ffb11f3f18 100644
--- a/indra/newview/skins/default/xui/en/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/en/floater_settings_debug.xml
@@ -1,11 +1,12 @@
<?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"
+ title="DEBUG SETTINGS"
width="350">
<combo_box
allow_text_entry="true"
diff --git a/indra/newview/skins/default/xui/en/floater_snapshot.xml b/indra/newview/skins/default/xui/en/floater_snapshot.xml
index bd1484c0fe..95a40e27f7 100644
--- a/indra/newview/skins/default/xui/en/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/en/floater_snapshot.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
follows="left|top"
height="526"
@@ -7,7 +8,7 @@
name="Snapshot"
help_topic="snapshot"
save_rect="true"
- title="Snapshot Preview"
+ title="SNAPSHOT PREVIEW"
width="215">
<floater.string
name="unknown">
@@ -125,7 +126,7 @@
layout="topleft"
left="10"
name="more_btn"
- tool_tip="Advanced Options"
+ tool_tip="Advanced options"
top="270"
width="80" />
<button
@@ -136,7 +137,7 @@
layout="topleft"
left_delta="0"
name="less_btn"
- tool_tip="Advanced Options"
+ tool_tip="Advanced options"
top_delta="0"
width="80" />
<text
diff --git a/indra/newview/skins/default/xui/en/floater_sound_preview.xml b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
index 3b1eae9293..ca54ee6604 100644
--- a/indra/newview/skins/default/xui/en/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_sound_preview.xml
@@ -1,10 +1,11 @@
<?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"
+ title="SOUND.WAV"
width="300">
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_statistics.xml b/indra/newview/skins/default/xui/en/floater_statistics.xml
index 653bc942e5..3a4e845141 100644
--- a/indra/newview/skins/default/xui/en/floater_statistics.xml
+++ b/indra/newview/skins/default/xui/en/floater_statistics.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
follows="right|top"
height="392"
@@ -7,5 +8,5 @@
mouse_opaque="false"
name="stats floater"
help_topic="stats_floater"
- title="Statistics"
+ 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
index 205e6efe70..68a4867167 100644
--- a/indra/newview/skins/default/xui/en/floater_stats.xml
+++ b/indra/newview/skins/default/xui/en/floater_stats.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
follows="top|right"
height="400"
@@ -8,7 +9,7 @@
help_topic="statistics"
save_rect="true"
save_visibility="true"
- title="Statistics"
+ title="STATISTICS"
width="250">
<scroll_container
follows="top|left|bottom|right"
diff --git a/indra/newview/skins/default/xui/en/floater_sys_well.xml b/indra/newview/skins/default/xui/en/floater_sys_well.xml
index aef5707fd4..e1f07a49e7 100644
--- a/indra/newview/skins/default/xui/en/floater_sys_well.xml
+++ b/indra/newview/skins/default/xui/en/floater_sys_well.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater
+<floater
+ legacy_header_height="18"
bevel_style="in"
left="0"
top="0"
diff --git a/indra/newview/skins/default/xui/en/floater_telehub.xml b/indra/newview/skins/default/xui/en/floater_telehub.xml
index 95de27e0ea..cc0ab8c57e 100644
--- a/indra/newview/skins/default/xui/en/floater_telehub.xml
+++ b/indra/newview/skins/default/xui/en/floater_telehub.xml
@@ -1,10 +1,11 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
height="250"
layout="topleft"
name="telehub"
help_topic="telehub"
- title="Telehub"
+ title="TELEHUB"
width="280">
<text
type="string"
diff --git a/indra/newview/skins/default/xui/en/floater_test_button.xml b/indra/newview/skins/default/xui/en/floater_test_button.xml
index ce17873a67..2bd0d1a0fa 100644
--- a/indra/newview/skins/default/xui/en/floater_test_button.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_button.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="500"
layout="topleft"
@@ -95,7 +96,6 @@
layout="topleft"
left="200"
name="image_button"
- picture_style="true"
top="20"
width="16" />
<button
@@ -106,7 +106,6 @@
layout="topleft"
left_delta="0"
name="image_color_button"
- picture_style="true"
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
index 66a5b9267d..9977e85a9d 100644
--- a/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_checkbox.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_combobox.xml b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
index 956d5669b8..317d8f5ba8 100644
--- a/indra/newview/skins/default/xui/en/floater_test_combobox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_combobox.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
index 2011f57d8b..9143048aeb 100644
--- a/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_inspectors.xml
@@ -1,11 +1,12 @@
<?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"
+ title="TEST INSPECTORS"
width="400">
<text
height="20"
@@ -93,7 +94,9 @@
top_pad="10"
left_delta="0"
height="20"
- width="100"/>
+ width="100"
+ commit_callback.function="ShowGroupInspector"
+ commit_callback.parameter="" />
<button
name="place_btn"
label="Place"
@@ -112,13 +115,23 @@
follows="left|top"
font="SansSerif"
height="20"
- layout="topleft"
left="0"
max_length="65536"
name="slurl"
top_pad="4"
- width="100">
+ 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
index 209859bb29..c6acb7c96e 100644
--- a/indra/newview/skins/default/xui/en/floater_test_layout.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_layout.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="500"
layout="topleft"
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
index 251ca4c9bf..e017d404c6 100644
--- a/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_line_editor.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
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
index 98d6d5bda7..1d2086d9bc 100644
--- a/indra/newview/skins/default/xui/en/floater_test_list_view.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_list_view.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
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
index dd551b6d51..c6b4cca6b9 100644
--- a/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_navigation_bar.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="200"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
index 35190c0e1a..7ef2d97cdc 100644
--- a/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_radiogroup.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_slider.xml b/indra/newview/skins/default/xui/en/floater_test_slider.xml
index 3545f88df7..57d8e686ce 100644
--- a/indra/newview/skins/default/xui/en/floater_test_slider.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_slider.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_spinner.xml b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
index c4e5bc9e99..3c44a4884d 100644
--- a/indra/newview/skins/default/xui/en/floater_test_spinner.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_spinner.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_test_textbox.xml b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
index 8305452c85..9e2e9e74e3 100644
--- a/indra/newview/skins/default/xui/en/floater_test_textbox.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_textbox.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="400"
layout="topleft"
@@ -114,16 +115,59 @@
Escaped greater than &gt;
</text>
<text
- type="string"
- length="1"
- bottom="390"
- label="N"
- layout="topleft"
- left="10"
- name="floater_map_north"
- right="30"
- text_color="1 1 1 0.7"
- top="370">
- N
- </text>
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="right_aligned_text"
+ width="380"
+ halign="right"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Right aligned text
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="centered_text"
+ width="380"
+ halign="center"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Centered text
+ </text>
+ <text
+ type="string"
+ length="1"
+ height="60"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="left_aligned_text"
+ width="380"
+ halign="left"
+ text_color="1 1 1 0.7"
+ top_pad="10">
+ Left aligned text
+ </text>
+ <text
+ type="string"
+ length="1"
+ bottom="390"
+ label="N"
+ layout="topleft"
+ left="10"
+ name="floater_map_north"
+ right="30"
+ text_color="1 1 1 0.7"
+ top="370">
+ N
+ </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
index cc0fc34dd5..718d724aa6 100644
--- a/indra/newview/skins/default/xui/en/floater_test_widgets.xml
+++ b/indra/newview/skins/default/xui/en/floater_test_widgets.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<!-- Sample "floater" window with examples of common widgets.
+<!-- Sample "floater" window with examples of common widgets.
Notes:
XML UI (XUI) files use spaces for indentation, not tabs.
@@ -15,17 +15,18 @@
Otherwise specify location with left and top attributes.
-->
<floater
- can_dock="true"
+ legacy_header_height="18"
+ can_dock="true"
can_resize="true"
- title="Test Floater"
+ title="TEST FLOATER"
height="500"
- min_width="850"
- min_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
@@ -34,15 +35,15 @@
<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"
+ follows="top|left"
+ tool_tip="menu"
left="2"
name="test_menu_bar"
top="16">
@@ -70,7 +71,7 @@
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. -->
@@ -84,27 +85,27 @@
</text>
<!-- First column -->
-
+
<button
height="20"
- follows="top|left"
+ follows="top|left"
label="Button"
layout="topleft"
left_delta="0"
name="test_button"
- tool_tip="button"
+ tool_tip="button"
top="80"
- width="100" />
+ width="100" />
<!-- "flyout_button" is a button that can spawn a menu -->
<flyout_button
- follows="top|left"
+ follows="top|left"
height="20"
label="Flyout"
layout="topleft"
left_delta="0"
name="fly_btn"
top_pad="15"
- tool_tip="flyout button"
+ tool_tip="flyout button"
width="100">
<flyout_button.item
label="Item 1"
@@ -120,19 +121,19 @@
bottom_delta="35"
label="Checkbox"
layout="topleft"
- tool_tip="checkbox"
+ tool_tip="checkbox"
name="test_checkbox" />
<!-- "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"
+ follows="top|left"
height="16"
width="150"
label="Combobox"
layout="topleft"
- tool_tip="combo box"
+ tool_tip="combo box"
name="test_combo_box">
<combo_box.item
name="item1"
@@ -148,21 +149,21 @@
image_name="icon_avatar_online.tga"
layout="topleft"
left_delta="0"
- tool_tip="icon"
+ tool_tip="icon"
name="test_icon"
top_pad="40"
width="16" />
- <!-- "line_editor" allows a single line of editable text input.
+ <!-- "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"
+ follows="top|left"
layout="topleft"
left_delta="0"
name="test_line_editor"
top_pad="20"
- tool_tip="line editor"
+ tool_tip="line editor"
width="200">
Line Editor Sample Text
</line_editor>
@@ -175,18 +176,18 @@
layout="topleft"
left_delta="0"
name="search editor"
- tool_tip="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"
+ follows="top|left"
layout="topleft"
left_delta="0"
name="test_progress_bar"
top_pad="30"
- tool_tip="progress bar"
+ tool_tip="progress bar"
width="200" />
<!-- "stat_view" is a container for statistics graphs. It is only used
for debugging/diagnostic displays. -->
@@ -198,10 +199,10 @@
name="axis_view"
show_label="true"
top_pad="30"
- tool_tip="stat view"
+ tool_tip="stat view"
width="200">
<stat_bar
- width="100"
+ width="100"
bar_max="100"
bottom_delta="30"
label="Test Stat"
@@ -210,9 +211,9 @@
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
@@ -220,7 +221,7 @@
layout="topleft"
left_pad="90"
name="size_radio_group"
- tool_tip="radio group"
+ tool_tip="radio group"
top="80"
width="200">
<radio_item
@@ -236,10 +237,10 @@
<!-- "scroll_list" is a scrolling list of columnar data. -->
<scroll_list
bottom_delta="100"
- follows="top|left"
+ follows="top|left"
height="80"
draw_heading="true"
- tool_tip="scroll list"
+ tool_tip="scroll list"
layout="topleft">
<scroll_list.columns
dynamic_width="true"
@@ -261,29 +262,29 @@
<!-- "slider" is a horizontal input widget for numerical data. -->
<slider
bottom_delta="45"
- follows="top|left"
+ follows="top|left"
layout="topleft"
min_val="0"
max_val="100"
initial_value="20"
label="Slider"
name="test_slider"
- tool_tip="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"
+ follows="top|left"
label="Spinner"
layout="topleft"
- label_width="45"
- name="test_spinner"
+ label_width="45"
+ name="test_spinner"
tool_tip="spinner"/>
<text
bottom_delta="50"
- follows="top|left"
- font.name="SansSerifSmall"
+ follows="top|left"
+ font.name="SansSerifSmall"
font.style = "UNDERLINE"
layout="topleft"
name="test_text"
@@ -292,23 +293,23 @@
</text>
<text
top_pad="10"
- follows="top|left"
+ follows="top|left"
layout="topleft"
- width="60"
- use_ellipses="true"
+ 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
+ <!-- "text_editor" is a multi-line text input widget, similar to
textarea in HTML. -->
<text_editor
height="40"
- follows="top|left|bottom"
+ follows="top|left|bottom"
layout="topleft"
left_delta="0"
name="test_text_editor"
- tool_tip="text editor"
+ tool_tip="text editor"
top_pad="25"
width="200">
Text Editor
@@ -329,17 +330,19 @@ 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="575"
name="group_tab_container"
tab_position="top"
- tool_tip="tab container"
+ tab_height="20"
+ tool_tip="tab container"
top="80"
width="250">
<!-- "panel" is a container for widgets. It is automatically resized to
diff --git a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
index f2b701b88d..4679ae467d 100644
--- a/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/en/floater_texture_ctrl.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
can_resize="true"
height="290"
@@ -8,7 +9,7 @@
min_width="410"
name="texture picker"
help_topic="texture_picker"
- title="Pick: Texture"
+ title="PICK: TEXTURE"
width="410">
<floater.string
name="choose_picture">
@@ -22,14 +23,16 @@
type="string"
length="1"
follows="left|top"
+ text_color="White"
+ font="SansSerifBig"
halign="center"
- height="14"
+ height="17"
layout="topleft"
left="4"
name="Multiple"
top="96"
width="163">
- Multiple
+ Multiple textures
</text>
<text
type="string"
@@ -41,7 +44,7 @@
name="unknown"
top_pad="80"
width="163">
- Dimensions: [DIMENSIONS]
+ Size: [DIMENSIONS]
</text>
<button
enabled="false"
@@ -54,7 +57,7 @@
left_delta="0"
name="Default"
top_pad="4"
- width="64" />
+ width="80" />
<button
enabled="false"
follows="left|bottom"
@@ -66,7 +69,7 @@
left_pad="4"
name="None"
top_delta="0"
- width="64" />
+ width="80" />
<button
follows="left|bottom"
font="SansSerifSmall"
@@ -76,75 +79,75 @@
layout="topleft"
left="4"
name="Blank"
- top="232"
- width="64" />
- <check_box
- height="24"
+ 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="Show Folders"
+ label="Apply now"
layout="topleft"
- left="175"
- name="show_folders_check"
- top="20"
- width="201" />
+ left="4"
+ name="apply_immediate_check"
+ top="262"
+ width="120" />
<filter_editor
follows="left|top|right"
- height="16"
- label="Type here to search"
+ height="23"
+ label="Filter textures"
layout="topleft"
- left_delta="0"
+ left="175"
name="inventory search editor"
- top_delta="0"
+ top="20"
width="231" />
<inventory_panel
allow_multi_select="false"
- border="true"
- follows="left|top|right|bottom"
- height="216"
+ 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
- follows="left|bottom"
- height="20"
- initial_value="true"
- label="Apply Immediately"
- layout="topleft"
- left="4"
- name="apply_immediate_check"
- top="262"
- width="150" />
- <button
- follows="left|bottom"
- height="32"
- image_selected="eye_button_active.tga"
- image_unselected="eye_button_inactive.tga"
+ <check_box
+ height="14"
+ initial_value="false"
+ label="Show folders"
layout="topleft"
- left="139"
- name="Pipette"
- picture_style="true"
- top="250"
- width="32" />
- <button
+ name="show_folders_check"
+ top_pad="0"
+ left_delta="-3"
+ width="200" />
+ <button
follows="right|bottom"
height="20"
- label="Cancel"
- label_selected="Cancel"
+ label="Ok"
+ label_selected="Ok"
layout="topleft"
- left="186"
- name="Cancel"
- top="262"
+ right="-120"
+ name="Select"
width="100" />
<button
follows="right|bottom"
height="20"
- label="Select"
- label_selected="Select"
+ label="Cancel"
+ label_selected="Cancel"
layout="topleft"
- left_pad="4"
- name="Select"
- top_delta="0"
+ 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
index 0e9dc5e750..c33d7cf31d 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1,12 +1,15 @@
<?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"
+ short_title="BUILD TOOLS"
single_instance="true"
sound_flags="0"
width="280">
@@ -32,7 +35,7 @@
</floater.string>
<floater.string
name="status_grab">
- Drag to move, Ctrl to lift, Ctrl-Shift to rotate
+ Drag to move, Ctrl to lift, Ctrl+Shift to rotate
</floater.string>
<floater.string
name="status_place">
@@ -72,7 +75,6 @@
layout="topleft"
left="10"
name="button focus"
- picture_style="true"
tool_tip="Focus"
width="20">
<button.commit_callback
@@ -87,9 +89,8 @@
image_selected="Tool_Grab"
image_unselected="Tool_Grab"
layout="topleft"
- left_pad="8"
+ left_pad="20"
name="button move"
- picture_style="true"
tool_tip="Move"
width="20">
<button.commit_callback
@@ -104,9 +105,8 @@
image_selected="Tool_Face"
image_unselected="Tool_Face"
layout="topleft"
- left_pad="8"
+ left_pad="20"
name="button edit"
- picture_style="true"
tool_tip="Edit"
width="20">
<button.commit_callback
@@ -121,9 +121,8 @@
image_selected="Tool_Create"
image_unselected="Tool_Create"
layout="topleft"
- left_pad="8"
+ left_pad="20"
name="button create"
- picture_style="true"
tool_tip="Create"
width="20">
<button.commit_callback
@@ -138,9 +137,8 @@
image_selected="Tool_Dozer"
image_unselected="Tool_Dozer"
layout="topleft"
- left_pad="8"
+ left_pad="20"
name="button land"
- picture_style="true"
tool_tip="Land"
width="20">
<button.commit_callback
@@ -180,7 +178,7 @@
name="radio orbit" />
<radio_item
top_pad="6"
- label="Pan (Ctrl-Shift)"
+ label="Pan (Ctrl+Shift)"
layout="topleft"
name="radio pan" />
<radio_group.commit_callback
@@ -207,71 +205,71 @@
layout="topleft"
name="move_radio_group">
<radio_item
- top_pad="6"
+ top_pad="6"
label="Move"
layout="topleft"
name="radio move" />
<radio_item
- top_pad="6"
+ top_pad="6"
label="Lift (Ctrl)"
layout="topleft"
name="radio lift" />
<radio_item
- top_pad="6"
- label="Spin (Ctrl-Shift)"
+ top_pad="6"
+ label="Spin (Ctrl+Shift)"
layout="topleft"
name="radio spin" />
<radio_group.commit_callback
- function="BuildTool.commitRadioMove"/>
- </radio_group>
- <radio_group
+ function="BuildTool.commitRadioMove"/>
+ </radio_group>
+ <radio_group
follows="left|top"
- left="10"
- top="54"
- height="70"
+ left="10"
+ top="54"
+ height="70"
layout="topleft"
- name="edit_radio_group">
+ name="edit_radio_group">
<radio_item
- label="Move"
- layout="topleft"
- name="radio position" />
+ label="Move"
+ layout="topleft"
+ name="radio position" />
<radio_item
- top_pad="6"
+ top_pad="6"
label="Rotate (Ctrl)"
layout="topleft"
name="radio rotate" />
<radio_item
- top_pad="6"
- label="Stretch (Ctrl-Shift)"
+ top_pad="6"
+ label="Stretch (Ctrl+Shift)"
layout="topleft"
name="radio stretch" />
<radio_item
- top_pad="6"
- label="Select Texture"
+ top_pad="6"
+ label="Select Face"
layout="topleft"
name="radio select face" />
- <radio_group.commit_callback
- function="BuildTool.commitRadioEdit"/>
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioEdit"/>
</radio_group>
<check_box
left="10"
follows="left|top"
height="16"
- control_name="EditLinkedParts"
+ control_name="EditLinkedParts"
label="Edit linked"
layout="topleft"
name="checkbox edit linked parts" >
<check_box.commit_callback
- function="BuildTool.selectComponent"/>
+ function="BuildTool.selectComponent"/>
</check_box>
- <check_box
+ <check_box
control_name="ScaleUniform"
height="19"
label="Stretch Both Sides"
layout="topleft"
left="143"
name="checkbox uniform"
- top="50"
+ top="50"
width="134" />
<check_box
control_name="ScaleStretchTextures"
@@ -292,10 +290,9 @@
name="checkbox snap to grid"
width="134" />
<combo_box
- height="20"
+ height="19"
layout="topleft"
follows="left|top"
- top_pad="4"
name="combobox grid mode"
width="108">
<combo_box.item
@@ -313,20 +310,18 @@
<combo_box.commit_callback
function="BuildTool.gridMode"/>
</combo_box>
- <button
+ <button
left_pad="0"
- right="-12"
image_disabled="ForwardArrow_Disabled"
image_selected="ForwardArrow_Press"
image_unselected="ForwardArrow_Off"
- picture_style="true"
- label_selected="Options"
layout="topleft"
name="Options..."
- tool_tip="Grid Options"
+ tool_tip="Grid options"
top_delta="0"
+ right="-10"
width="18"
- height="18" >
+ height="19" >
<button.commit_callback
function="BuildTool.gridOptions"/>
</button>
@@ -340,7 +335,6 @@
layout="topleft"
left="4"
name="ToolCube"
- picture_style="true"
tool_tip="Cube"
top="51"
width="20" />
@@ -354,7 +348,6 @@
layout="topleft"
left_delta="26"
name="ToolPrism"
- picture_style="true"
tool_tip="Prism"
top_delta="0"
width="20" />
@@ -362,13 +355,12 @@
follows="left|top"
height="20"
image_disabled="Object_Pyramid"
- image_disabled_selected="object_pyramid_active.tga"
- image_selected="object_pyramid_active.tga"
+ image_disabled_selected="Object_Pyramid"
+ image_selected="Object_Pyramid"
image_unselected="Object_Pyramid"
layout="topleft"
left_delta="26"
name="ToolPyramid"
- picture_style="true"
tool_tip="Pyramid"
top_delta="0"
width="20" />
@@ -376,13 +368,12 @@
follows="left|top"
height="20"
image_disabled="Object_Tetrahedron"
- image_disabled_selected="object_tetrahedron_active.tga"
- image_selected="object_tetrahedron_active.tga"
+ image_disabled_selected="Object_Tetrahedron"
+ image_selected="Object_Tetrahedron"
image_unselected="Object_Tetrahedron"
layout="topleft"
left_delta="26"
name="ToolTetrahedron"
- picture_style="true"
tool_tip="Tetrahedron"
top_delta="0"
width="20" />
@@ -396,7 +387,6 @@
layout="topleft"
left_delta="26"
name="ToolCylinder"
- picture_style="true"
tool_tip="Cylinder"
top_delta="0"
width="20" />
@@ -410,7 +400,6 @@
layout="topleft"
left_delta="26"
name="ToolHemiCylinder"
- picture_style="true"
tool_tip="Hemicylinder"
top_delta="0"
width="20" />
@@ -424,7 +413,6 @@
layout="topleft"
left_delta="26"
name="ToolCone"
- picture_style="true"
tool_tip="Cone"
top_delta="0"
width="20" />
@@ -438,7 +426,6 @@
layout="topleft"
left_delta="26"
name="ToolHemiCone"
- picture_style="true"
tool_tip="Hemicone"
top_delta="0"
width="20" />
@@ -452,7 +439,6 @@
layout="topleft"
left_delta="26"
name="ToolSphere"
- picture_style="true"
tool_tip="Sphere"
top_delta="0"
width="20" />
@@ -466,7 +452,6 @@
layout="topleft"
left_delta="26"
name="ToolHemiSphere"
- picture_style="true"
tool_tip="Hemisphere"
top_delta="0"
width="20" />
@@ -480,7 +465,6 @@
layout="topleft"
left="4"
name="ToolTorus"
- picture_style="true"
tool_tip="Torus"
top="77"
width="20" />
@@ -494,7 +478,6 @@
layout="topleft"
left_delta="26"
name="ToolTube"
- picture_style="true"
tool_tip="Tube"
top_delta="0"
width="20" />
@@ -508,7 +491,6 @@
layout="topleft"
left_delta="26"
name="ToolRing"
- picture_style="true"
tool_tip="Ring"
top_delta="0"
width="20" />
@@ -522,7 +504,6 @@
layout="topleft"
left_delta="26"
name="ToolTree"
- picture_style="true"
tool_tip="Tree"
top_delta="0"
width="20" />
@@ -536,7 +517,6 @@
layout="topleft"
left_delta="26"
name="ToolGrass"
- picture_style="true"
tool_tip="Grass"
top_delta="0"
width="20" />
@@ -715,33 +695,31 @@
layout="topleft"
left="135"
name="button apply to selection"
- tool_tip="Modify Selected Land"
+ tool_tip="Modify selected land"
width="78">
<button.commit_callback
function="BuildTool.applyToSelection"/>
</button>
<text
type="string"
- text_color="LabelSelectedDisabledColor"
length="1"
height="12"
follows="left|top"
halign="right"
layout="topleft"
- right="-13"
+ right="-10"
name="obj_count"
- top_pad="8"
+ top_pad="6"
width="143">
Objects: [COUNT]
</text>
<text
type="string"
- text_color="LabelSelectedDisabledColor"
length="1"
follows="left|top"
halign="right"
layout="topleft"
- right="-13"
+ right="-10"
name="prim_count"
width="143">
Prims: [COUNT]
@@ -749,30 +727,33 @@
<tab_container
follows="left|top"
height="400"
- layout="topleft"
+ halign="center"
left="0"
name="Object Info Tabs"
tab_max_width="55"
tab_min_width="40"
tab_position="top"
- top="180"
+ tab_height="25"
+ top="170"
width="280">
- <panel
- border="false"
- follows="left|top|right|bottom"
- label="General"
- layout="topleft"
- mouse_opaque="false"
- name="General"
- top="16">
- <panel.string
- name="text deed continued">
- Deed
- </panel.string>
- <panel.string
- name="text deed">
- Deed
- </panel.string>
+ <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
@@ -868,7 +849,6 @@
width="90">
Creator:
</text>
-<!-- TODO: add person inspector to creator name -->
<text
type="string"
length="1"
@@ -891,7 +871,6 @@
width="90">
Owner:
</text>
-<!--TODO: add person inspector to owner name-->
<text
type="string"
length="1"
@@ -911,31 +890,30 @@
left="10"
height="18"
name="Group:"
- top_pad="5"
+ 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="2"
- name="button set group"
- picture_style="true"
- tab_stop="false"
- tool_tip="Choose a group to share this object's permissions"
- width="10" />
+ <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="4"
+ left_pad="5"
top_delta="-1"
name="Group Name Proxy"
width="150" />
@@ -948,9 +926,9 @@
layout="topleft"
name="button deed"
top_pad="0"
- left="83"
- tool_tip="Deeding gives this item away with Next Owner permissions. Group shared objects can be deeded by a group officer."
- width="100" />
+ 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"
@@ -969,7 +947,7 @@
top_pad="15"
left="10"
name="label click action"
- width="100">
+ width="90">
Click to:
</text>
<combo_box
@@ -977,7 +955,7 @@
height="20"
layout="topleft"
name="clickaction"
- width="158"
+ width="168"
left_pad="0">
<combo_box.item
label="Touch (default)"
@@ -1007,7 +985,7 @@
layout="topleft"
name="checkbox for sale"
left="10"
- width="100" />
+ width="90" />
<!-- NEW SALE TYPE COMBO BOX -->
<combo_box
left_pad="0"
@@ -1033,8 +1011,11 @@
label="Original"
value="1" />
</combo_box>
-<!-- NEW PRICE SPINNER -->
- <spinner
+<!-- 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"
@@ -1043,38 +1024,37 @@
control_name="Edit Cost"
name="Edit Cost"
label="Price: L$"
- label_width="70"
- width="168"
- min_val="1"
+ label_width="65"
+ width="150"
+ min_val="0"
height="20"
max_val="999999999" />
<check_box
- height="15"
- width="100"
- 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
+ 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="FloaterUnfocusBorderColor"
+ bg_alpha_color="DkGray"
name="perms_build"
left="0"
- top="240"
+ top="241"
height="120"
- width="280">
+ width="278">
<text
type="string"
length="1"
left="10"
- top_pad="10"
+ top_pad="9"
text_color="EmphasisColor"
height="16"
follows="left|top|right"
@@ -1088,7 +1068,6 @@
follows="left|top"
name="Anyone can:"
width="250"
- top_pad="5"
left="10">
Anyone:
</text>
@@ -1213,16 +1192,17 @@
width="50">
F:
</text>
- </panel>
+ </panel>
</panel>
<panel
border="false"
- follows="left|top|right|bottom"
+ 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">
@@ -1248,7 +1228,7 @@
label="Temporary"
layout="topleft"
name="Temporary Checkbox Ctrl"
- tool_tip="Causes object to be deleted 1 minute after creation."
+ tool_tip="Causes object to be deleted 1 minute after creation"
top_pad="0"
width="123" />
<check_box
@@ -1380,7 +1360,7 @@
layout="topleft"
left_delta="0"
name="label rotation"
- top_pad="6"
+ top_pad="10"
width="121">
Rotation (degrees)
</text>
@@ -1449,7 +1429,7 @@
height="19"
layout="topleft"
name="comboBaseType"
- top="5"
+ top="6"
left="125"
width="150">
<combo_box.item
@@ -1489,7 +1469,7 @@
height="19"
layout="topleft"
name="material"
- top_pad="0"
+ top_pad="5"
width="150">
<combo_box.item
label="Stone"
@@ -1528,7 +1508,7 @@
layout="topleft"
left_delta="0"
name="text cut"
- top_pad="6"
+ top_pad="5"
width="150">
Path Cut (begin/end)
</text>
@@ -1610,7 +1590,7 @@
type="string"
length="1"
follows="left|top"
- height="10"
+ height="15"
layout="topleft"
left="125"
name="Hollow Shape"
@@ -1623,7 +1603,7 @@
layout="topleft"
left_delta="0"
name="hole"
- top_pad="4"
+ top_pad="3"
width="150">
<combo_box.item
label="Default"
@@ -1650,7 +1630,7 @@
layout="topleft"
left_delta="0"
name="text twist"
- top_pad="8"
+ top_pad="5"
width="150">
Twist (begin/end)
</text>
@@ -1692,7 +1672,7 @@
layout="topleft"
left="125"
name="scale_taper"
- top_pad="6"
+ top_pad="3"
width="150">
Taper
</text>
@@ -1945,7 +1925,7 @@
layout="topleft"
left_delta="0"
name="sculpt mirror control"
- tool_tip="Flips sculpted prim along the X axis."
+ tool_tip="Flips sculpted prim along the X axis"
top_pad="8"
visible="false"
width="130" />
@@ -1955,7 +1935,7 @@
layout="topleft"
left_delta="0"
name="sculpt invert control"
- tool_tip="Inverts the sculpted prims normals, making it appear inside-out."
+ tool_tip="Inverts the sculpted prims normals, making it appear inside-out"
top_pad="4"
visible="false"
width="121" />
@@ -2005,12 +1985,13 @@
<panel
border="false"
- follows="left|top|right|bottom"
+ 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">
@@ -2044,7 +2025,7 @@
layout="topleft"
left="10"
name="Flexible1D Checkbox Ctrl"
- tool_tip="Allows object to flex about the Z axis. (Client-side only)"
+ tool_tip="Allows object to flex about the Z axis (Client-side only)"
top_pad="10"
width="121" />
<spinner
@@ -2176,7 +2157,7 @@
left_pad="10"
top_pad="-17"
name="colorswatch"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
width="40" />
<texture_picker
allow_no_texture="true"
@@ -2242,12 +2223,13 @@
</panel>
<panel
border="false"
- follows="left|top|right|bottom"
+ 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">
@@ -2278,9 +2260,9 @@
height="80"
label="Color"
layout="topleft"
- left_pad="25"
+ left_pad="15"
name="colorswatch"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top_delta="0"
width="64" />
<text
@@ -2289,10 +2271,10 @@
follows="left|top"
height="10"
layout="topleft"
- left_pad="20"
+ left_pad="15"
name="color trans"
top="6"
- width="100">
+ width="110">
Transparency %
</text>
<spinner
@@ -2355,7 +2337,7 @@
left_delta="0"
name="combobox texgen"
top_pad="4"
- width="87">
+ width="60">
<combo_box.item
label="Default"
name="Default"
@@ -2374,7 +2356,7 @@
name="label shininess"
left_pad="5"
top_pad="-36"
- width="80">
+ width="60">
Shininess
</text>
<combo_box
@@ -2383,7 +2365,7 @@
left_delta="0"
name="combobox shininess"
top_pad="4"
- width="80">
+ width="60">
<combo_box.item
label="None"
name="None"
@@ -2537,7 +2519,7 @@
name="tex scale"
top_pad="5"
width="200">
- Repeats per Face
+ Repeats / Face
</text>
<spinner
follows="left|top"
@@ -2586,9 +2568,9 @@
height="19"
increment="1"
initial_value="0"
- label="Rotation (degrees)"
+ label="RotationËš"
layout="topleft"
- label_width="100"
+ label_width="100"
left="10"
max_val="9999"
min_val="-9999"
@@ -2601,7 +2583,7 @@
follows="left|top"
height="19"
initial_value="1"
- label="Repeats Per Meter"
+ label="Repeats / Meter"
layout="topleft"
label_width="100"
left="10"
@@ -2613,7 +2595,7 @@
<button
follows="left|top"
font="SansSerifSmall"
- height="18"
+ height="19"
label="Apply"
label_selected="Apply"
layout="topleft"
@@ -2642,7 +2624,7 @@
left="20"
min_val="-1"
name="TexOffsetU"
- top_pad="5"
+ top_pad="6"
width="160" />
<spinner
follows="left|top"
@@ -2656,109 +2638,123 @@
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="19"
+ height="12"
layout="topleft"
left="10"
- name="textbox autofix"
- top_pad="4"
- width="160">
- Align media texture
-(must load first)
- </text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="19"
- label="Align"
- label_selected="Align"
- layout="topleft"
- left="122"
- name="button align"
- top_pad="-19"
- width="68" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="12"
- layout="topleft"
- left="10"
- top_pad="0"
- name="media_tex"
- width="100">
- Media:
+ top_pad="5"
+ name="media_tex"
+ width="260">
+ Media URL
</text>
<line_editor
- follows="left|top|right"
- height="18"
- layout="topleft"
- left="20"
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left="10"
read_only="true"
- name="media_info"
- select_on_focus="true"
- top_delta="12"
- width="230" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="13"
- width="13"
- image_unselected="add_btn.tga"
- label=""
- layout="topleft"
- left="20"
- name="add_media"
- top_pad="3">
+ name="media_info"
+ select_on_focus="true"
+ 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="left|top"
- font="SansSerifSmall"
- height="13"
- width="13"
- image_unselected="del_btn.tga"
- label=""
- layout="topleft"
- left_pad="10"
- name="delete_media"
- top_delta="0"
- left_delta="10" >
+ 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="left|top"
- font="SansSerifSmall"
- height="15"
- width="15"
- image_unselected="gear.tga"
- label=""
- layout="topleft"
+ <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"
- left_delta="190">
+ top_delta="0"
+ width="18">
<button.commit_callback
function="BuildTool.EditMedia"/>
</button>
- </panel>
+ <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"
+ font="SansSerifSmall"
+ height="19"
+ label="Align"
+ label_selected="Align Media"
+ layout="topleft"
+ left="10"
+ name="button align"
+ top_pad="5"
+ width="100" />
+ </panel>
+ </panel>
<panel
border="false"
- follows="left|top|right|bottom"
+ 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="22"
+ height="19"
label="New Script"
label_selected="New Script"
layout="topleft"
@@ -2768,13 +2764,13 @@
width="120" />
<button
follows="left|top"
- height="22"
+ height="19"
label="Permissions"
layout="topleft"
left_pad="8"
name="button permissions"
width="130" />
- <panel_inventory
+ <panel_inventory_object
follows="left|top"
height="210"
layout="topleft"
@@ -2782,10 +2778,10 @@
name="contents_inventory"
top="50"
width="260" />
- </panel>
+ </panel>
</tab_container>
- <panel
- follows="left|top"
+ <panel
+ follows="left|top"
height="384"
layout="topleft"
left_delta="0"
@@ -2832,8 +2828,8 @@
<button
follows="left|top"
height="20"
- label="Land profile"
- label_selected="Land profile"
+ label="About Land"
+ label_selected="About Land"
layout="topleft"
left_delta="0"
name="button about land"
@@ -2846,18 +2842,9 @@
layout="topleft"
left_delta="0"
name="checkbox show owners"
- tool_tip="Colorize the parcels according to the type of owner"
+ 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" />
- <!--TODO: HOOK UP TO HELP VIEWER-->
- <!-- <button
- image_overlay="Arrow_Right_Off"
- picture_style="true"
- left_pad="5"
- name="button show owners help"
- tool_tip="See an explanation of colors"
- width="26"
- height="22" />-->
<text
type="string"
length="1"
diff --git a/indra/newview/skins/default/xui/en/floater_top_objects.xml b/indra/newview/skins/default/xui/en/floater_top_objects.xml
index 07ffc204f9..d2db26daec 100644
--- a/indra/newview/skins/default/xui/en/floater_top_objects.xml
+++ b/indra/newview/skins/default/xui/en/floater_top_objects.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="350"
layout="topleft"
@@ -7,7 +8,7 @@
min_width="450"
name="top_objects"
help_topic="top_objects"
- title="loading..."
+ title="LOADING..."
width="550">
<floater.string
name="top_scripts_title">
diff --git a/indra/newview/skins/default/xui/en/floater_tos.xml b/indra/newview/skins/default/xui/en/floater_tos.xml
index b290a9c87d..4e2cce1428 100644
--- a/indra/newview/skins/default/xui/en/floater_tos.xml
+++ b/indra/newview/skins/default/xui/en/floater_tos.xml
@@ -1,11 +1,11 @@
<?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"
- help_topic="modal_container"
width="600">
<floater.string
name="real_url">
diff --git a/indra/newview/skins/default/xui/en/floater_ui_preview.xml b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
index 4ed6787f53..8b2136c2dc 100644
--- a/indra/newview/skins/default/xui/en/floater_ui_preview.xml
+++ b/indra/newview/skins/default/xui/en/floater_ui_preview.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
height="640"
layout="topleft"
@@ -8,7 +9,7 @@
name="gui_preview_tool"
help_topic="gui_preview_tool"
single_instance="true"
- title="XUI Preview Tool"
+ title="XUI PREVIEW TOOL"
width="750">
<panel
bottom="640"
@@ -102,7 +103,6 @@
top_delta="0"
width="85" />
<button
- enabled="false"
follows="right|top"
height="25"
is_toggle="true"
@@ -171,6 +171,15 @@
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"
@@ -347,14 +356,22 @@
</panel>
<scroll_container
follows="top|right|bottom"
- height="637"
+ height="600"
layout="topleft"
- left_delta="550"
+ left="750"
name="overlap_scroll"
reserve_scroll_corner="true"
- top_delta="2"
+ top="20"
width="300">
- <panel
+ <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"
@@ -362,14 +379,14 @@
bg_opaque_color="1 1 1 1"
border="true"
follows="top|right|bottom"
- height="637"
+ height="600"
label="Overlap Panel"
layout="topleft"
- left_delta="0"
+ 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="-607"
+ top="0"
visible="false"
width="300" />
<text
@@ -380,12 +397,11 @@
height="30"
layout="topleft"
left="10"
- left_delta="10"
name="overlap_panel_label"
- right="-50"
- top="0"
+ 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
index 6c1fb65bdd..1ab42cb140 100644
--- a/indra/newview/skins/default/xui/en/floater_url_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_url_entry.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="87"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_water.xml b/indra/newview/skins/default/xui/en/floater_water.xml
index febfd1929e..b13a11c05d 100644
--- a/indra/newview/skins/default/xui/en/floater_water.xml
+++ b/indra/newview/skins/default/xui/en/floater_water.xml
@@ -1,11 +1,12 @@
<?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"
+ title="ADVANCED WATER EDITOR"
width="700">
<floater.string
name="WLDefaultWaterNames">
@@ -15,7 +16,7 @@
type="string"
length="1"
follows="left|top|right"
- font="SansSerif"
+ font.style="BOLD"
height="16"
layout="topleft"
left="10"
@@ -27,7 +28,7 @@
<combo_box
height="18"
layout="topleft"
- left_delta="110"
+ left_pad="10"
name="WaterPresetsCombo"
top_delta="-2"
width="150" />
@@ -39,7 +40,7 @@
left_pad="20"
name="WaterNewPreset"
top_delta="1"
- width="70" />
+ width="90" />
<button
height="20"
label="Save"
@@ -48,7 +49,7 @@
left_pad="10"
name="WaterSavePreset"
top_delta="0"
- width="70" />
+ width="90" />
<button
height="20"
label="Delete"
@@ -57,10 +58,12 @@
left_pad="10"
name="WaterDeletePreset"
top_delta="0"
- width="70" />
+ width="90" />
<tab_container
+ border="false"
follows="left|top"
height="180"
+ halign="center"
layout="topleft"
left="0"
name="Water Tabs"
@@ -69,14 +72,16 @@
width="700">
<panel
border="true"
- follows="left|top|right|bottom"
+ border_color="EmphasisColor"
+ follows="all"
height="180"
label="Settings"
layout="topleft"
- left="1"
+ left="0"
mouse_opaque="false"
+ help_topic="water_settings_tab"
name="Settings"
- top="60"
+ top="0"
width="698">
<text
type="string"
@@ -88,21 +93,10 @@
left="10"
name="BHText"
top="4"
- width="355">
+ width="200">
Water Fog Color
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterFogColorHelp"
- top_delta="-2"
- width="18" />
<color_swatch
- border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
color="0.5 0.5 0.5 1"
follows="left|top"
@@ -110,7 +104,7 @@
layout="topleft"
left="40"
name="WaterFogColor"
- tool_tip="Click to open Color Picker"
+ tool_tip="Click to open color picker"
top="30"
width="40" />
<text
@@ -123,19 +117,9 @@
left="10"
name="WaterFogDensText"
top="74"
- width="355">
+ width="200">
Fog Density Exponent
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterFogDensityHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterFogDensity"
decimal_digits="1"
@@ -158,19 +142,9 @@
left_delta="-14"
name="WaterUnderWaterFogModText"
top_delta="4"
- width="355">
+ width="200">
Underwater Fog Modifier
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterUnderWaterFogModHelp"
- top_delta="-2"
- width="18" />
<slider
decimal_digits="2"
follows="left"
@@ -193,93 +167,44 @@
left="245"
name="BDensText"
top="4"
- width="355">
+ width="200">
Reflection Wavelet Scale
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterNormalScaleHelp"
- top_delta="-2"
- width="18" />
- <text
- type="string"
- length="1"
- follows="left|top|right"
- halign="center"
- height="16"
- layout="topleft"
- left="245"
- name="BHText2"
- top="21"
- width="10">
- 1
- </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">
- 2
- </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">
- 3
- </text>
<slider
control_name="WaterNormalScaleX"
decimal_digits="1"
follows="left"
- height="10"
+ height="15"
initial_value="0.7"
+ label="1"
layout="topleft"
- left_pad="4"
max_val="10"
name="WaterNormalScaleX"
- top_delta="-3"
+ top_pad="20"
width="200" />
<slider
control_name="WaterNormalScaleY"
decimal_digits="1"
follows="left"
- height="10"
+ height="15"
initial_value="0.7"
+ label="2"
layout="topleft"
- left_delta="0"
max_val="10"
name="WaterNormalScaleY"
- top_pad="1"
+ top_pad="0"
width="200" />
<slider
control_name="WaterNormalScaleZ"
decimal_digits="1"
follows="left"
- height="10"
+ height="15"
initial_value="0.7"
+ label="3"
layout="topleft"
- left_delta="0"
max_val="10"
name="WaterNormalScaleZ"
- top_pad="1"
+ top_pad="0"
width="200" />
<text
type="string"
@@ -288,22 +213,11 @@
font="SansSerif"
height="16"
layout="topleft"
- left_delta="-14"
name="HDText"
- top_delta="2"
- width="355">
+ top_pad="-10"
+ width="200">
Fresnel Scale
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterFresnelScaleHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterFresnelScale"
decimal_digits="2"
@@ -312,9 +226,8 @@
increment="0.01"
initial_value="0.7"
layout="topleft"
- left="259"
name="WaterFresnelScale"
- top="100"
+ top_pad="20"
width="200" />
<text
type="string"
@@ -323,22 +236,11 @@
font="SansSerif"
height="16"
layout="topleft"
- left_delta="-14"
name="FresnelOffsetText"
- top_delta="-1"
- width="355">
+ top_pad="-10"
+ width="200">
Fresnel Offset
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterFresnelOffsetHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterFresnelOffset"
decimal_digits="2"
@@ -347,9 +249,8 @@
increment="0.01"
initial_value="0.7"
layout="topleft"
- left="259"
name="WaterFresnelOffset"
- top="135"
+ top_pad="20"
width="200" />
<text
type="string"
@@ -361,19 +262,9 @@
left="480"
name="DensMultText"
top="4"
- width="355">
+ width="200">
Refract Scale Above
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterScaleAboveHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterScaleAbove"
decimal_digits="2"
@@ -396,19 +287,9 @@
left_delta="-14"
name="WaterScaleBelowText"
top_delta="-3"
- width="355">
+ width="200">
Refract Scale Below
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterScaleBelowHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterScaleBelow"
decimal_digits="2"
@@ -431,19 +312,9 @@
left_delta="-14"
name="MaxAltText"
top_delta="-2"
- width="355">
+ width="200">
Blur Multiplier
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WaterBlurMultiplierHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WaterBlurMult"
follows="left"
@@ -459,14 +330,15 @@
</panel>
<panel
border="true"
- follows="left|top|right|bottom"
+ follows="all"
height="180"
label="Image"
layout="topleft"
- left_delta="0"
+ left="0"
mouse_opaque="false"
+ help_topic="water_waves_tab"
name="Waves"
- top_delta="44"
+ top="0"
width="698">
<text
type="string"
@@ -477,20 +349,10 @@
layout="topleft"
left="10"
name="BHText"
- top="4"
- width="355">
+ top="10"
+ width="200">
Big Wave Direction
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="145"
- name="WaterWave1Help"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -500,7 +362,7 @@
layout="topleft"
left="10"
name="WaterWave1DirXText"
- top="21"
+ top_pad="4"
width="10">
X
</text>
@@ -513,7 +375,7 @@
layout="topleft"
left_delta="0"
name="WaterWave1DirYText"
- top_delta="11"
+ top_delta="18"
width="10">
Y
</text>
@@ -529,7 +391,7 @@
max_val="4"
min_val="-4"
name="WaterWave1DirX"
- top="40"
+ top="55"
width="200" />
<slider
control_name="WaterWave1DirY"
@@ -543,7 +405,7 @@
max_val="4"
min_val="-4"
name="WaterWave1DirY"
- top_pad="1"
+ top_pad="5"
width="200" />
<text
type="string"
@@ -558,16 +420,6 @@
width="355">
Little Wave Direction
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="145"
- name="WaterWave2Help"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -577,7 +429,7 @@
layout="topleft"
left="10"
name="WaterWave2DirXText"
- top="71"
+ top="90"
width="10">
X
</text>
@@ -590,7 +442,7 @@
layout="topleft"
left_delta="0"
name="WaterWave2DirYText"
- top_delta="11"
+ top_delta="20"
width="10">
Y
</text>
@@ -606,7 +458,7 @@
max_val="4"
min_val="-4"
name="WaterWave2DirX"
- top="90"
+ top="115"
width="200" />
<slider
control_name="WaterWave2DirY"
@@ -620,7 +472,7 @@
max_val="4"
min_val="-4"
name="WaterWave2DirY"
- top_pad="1"
+ top_pad="10"
width="200" />
<text
type="string"
@@ -632,19 +484,9 @@
left="240"
name="BHText3"
top="4"
- width="355">
+ width="200">
Normal Map
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="125"
- name="WaterNormalMapHelp"
- top_delta="-2"
- width="18" />
<texture_picker
height="143"
layout="topleft"
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
index e698dfe2dc..9a95e3dfef 100644
--- a/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
+++ b/indra/newview/skins/default/xui/en/floater_wearable_save_as.xml
@@ -1,12 +1,12 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
border="true"
can_close="false"
can_minimize="false"
height="100"
layout="topleft"
name="modal container"
- help_topic="modal_container"
width="240">
<button
height="20"
diff --git a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
index 4f501b65f3..ef68d03a45 100644
--- a/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
+++ b/indra/newview/skins/default/xui/en/floater_whitelist_entry.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_minimize="false"
height="108"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/floater_windlight_options.xml b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
index 872bd704d5..0cb7814c6a 100644
--- a/indra/newview/skins/default/xui/en/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/en/floater_windlight_options.xml
@@ -1,11 +1,12 @@
<?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"
+ title="ADVANCED SKY EDITOR"
width="700">
<floater.string
name="WLDefaultSkyNames">
@@ -70,10 +71,12 @@
<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
@@ -84,6 +87,7 @@
layout="topleft"
left="1"
mouse_opaque="false"
+ help_topic="windlight_atmosphere_tab"
name="Atmosphere"
top="60"
width="698">
@@ -100,16 +104,6 @@
width="355">
Blue Horizon
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLBlueHorizonHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -223,16 +217,6 @@
width="355">
Haze Horizon
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLHazeHorizonHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLHazeHorizon"
decimal_digits="2"
@@ -258,16 +242,6 @@
width="355">
Blue Density
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLBlueDensityHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -381,16 +355,6 @@
width="355">
Haze Density
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLHazeDensityHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLHazeDensity"
decimal_digits="2"
@@ -417,16 +381,6 @@
width="355">
Density Multiplier
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLDensityMultHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLDensityMult"
decimal_digits="2"
@@ -453,16 +407,6 @@
width="355">
Distance Multiplier
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLDistanceMultHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLDistancMult"
decimal_digits="1"
@@ -488,16 +432,6 @@
width="355">
Max Altitude
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLMaxAltitudeHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLMaxAltitude"
decimal_digits="0"
@@ -519,6 +453,7 @@
label="Lighting"
layout="topleft"
left_delta="0"
+ help_topic="windlight_lighting_tab"
name="Lighting"
top_delta="4"
width="698">
@@ -535,16 +470,6 @@
width="355">
Sun/Moon Color
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLSunlightColorHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -658,16 +583,6 @@
width="355">
Sun/Moon Position
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLTimeOfDayHelp"
- top_delta="-2"
- width="18" />
<icon
height="20"
image_name="icon_diurnal.tga"
@@ -700,16 +615,6 @@
width="355">
Ambient
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLAmbientHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -823,16 +728,6 @@
width="355">
East Angle
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLEastAngleHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLEastAngle"
decimal_digits="2"
@@ -858,16 +753,6 @@
width="355">
Sun Glow
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLSunGlowHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLGlowB"
decimal_digits="2"
@@ -910,16 +795,6 @@
width="200">
Scene Gamma
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLSceneGammaHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLGamma"
decimal_digits="2"
@@ -946,16 +821,6 @@
width="355">
Star Brightness
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLStarBrightnessHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLStarAlpha"
decimal_digits="2"
@@ -978,6 +843,7 @@
layout="topleft"
left_delta="0"
mouse_opaque="false"
+ help_topic="windlight_clouds_tab"
name="Clouds"
top_delta="4"
width="698">
@@ -994,16 +860,6 @@
width="355">
Cloud Color
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLCloudColorHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -1117,16 +973,6 @@
width="355">
Cloud XY/Density
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLCloudDensityHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -1215,16 +1061,6 @@
width="355">
Cloud Coverage
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLCloudCoverageHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLCloudCoverage"
decimal_digits="2"
@@ -1250,16 +1086,6 @@
width="355">
Cloud Scale
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLCloudScaleHelp"
- top_delta="-2"
- width="18" />
<slider
control_name="WLCloudScale"
decimal_digits="2"
@@ -1286,16 +1112,6 @@
width="355">
Cloud Detail (XY/Density)
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="150"
- name="WLCloudDetailHelp"
- top_delta="-2"
- width="18" />
<text
type="string"
length="1"
@@ -1384,16 +1200,6 @@
width="355">
Cloud Scroll X
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="125"
- name="WLCloudScrollXHelp"
- top_delta="-2"
- width="18" />
<check_box
control_name="WLCloudLockX"
follows="left"
@@ -1430,16 +1236,6 @@
width="355">
Cloud Scroll Y
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="125"
- name="WLCloudScrollYHelp"
- top_delta="-2"
- width="18" />
<check_box
control_name="WLCloudLockY"
follows="left"
@@ -1473,16 +1269,6 @@
name="DrawClassicClouds"
top="104"
width="200" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left="608"
- name="WLClassicCloudsHelp"
- top="84"
- width="18" />
</panel>
</tab_container>
</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
index bd76b10312..f5ae611f93 100644
--- a/indra/newview/skins/default/xui/en/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/en/floater_world_map.xml
@@ -1,5 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<floater
+ legacy_header_height="18"
can_resize="true"
center_horiz="true"
center_vert="true"
@@ -12,7 +13,7 @@
save_rect="true"
save_visibility="true"
single_instance="true"
- title="World Map"
+ title="WORLD MAP"
width="800">
<tab_container
follows="left|top|right|bottom"
@@ -30,6 +31,7 @@
label="Objects"
layout="topleft"
left="1"
+ help_topic="worldmap_objects_tab"
name="objects_mapview"
top="19"
width="540" />
@@ -40,6 +42,7 @@
label="Terrain"
layout="topleft"
left_delta="0"
+ help_topic="worldmap_terrain_tab"
name="terrain_mapview"
top_delta="3"
width="540" />
@@ -323,7 +326,7 @@
left_pad="4"
max_chars="60"
name="friend combo"
- tool_tip="Friend to Show on Map"
+ tool_tip="Friend to show on map"
top_delta="-4"
width="202">
<combo_box.item
@@ -353,7 +356,7 @@
left_pad="4"
max_chars="64"
name="landmark combo"
- tool_tip="Landmark to Show on Map"
+ tool_tip="Landmark to show on map"
top_delta="-4"
width="202">
<combo_box.item
@@ -417,7 +420,8 @@
left_delta="0"
name="search_results"
top_pad="10"
- width="222">
+ width="222"
+ sort_column="1">
<scroll_list.columns
label=""
name="icon"
diff --git a/indra/newview/skins/default/xui/en/fonts.xml b/indra/newview/skins/default/xui/en/fonts.xml
index dec9839d1a..f3da62a896 100644
--- a/indra/newview/skins/default/xui/en/fonts.xml
+++ b/indra/newview/skins/default/xui/en/fonts.xml
@@ -18,7 +18,7 @@
</os>
</font>
- <font name="SansSerifBold"
+ <font name="SansSerifBold"
comment="Name of bold sans-serif font">
<file>DejaVuSans-Bold.ttf</file>
<os name="Windows">
@@ -39,20 +39,20 @@
</os>
</font>
- <font name="SansSerif"
- comment="Name of bold sans-serif 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 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 name="SansSerif"
+ comment="Name of bold italic sans-serif font"
font_style="BOLD|ITALIC">
<file>DejaVuSans-BoldOblique.ttf</file>
</font>
@@ -140,11 +140,11 @@
<font_size name="Monospace"
comment="Size for monospaced font (points, or 1/72 of an inch)"
- size="9.0"
+ size="8.0"
/>
<font_size name="Huge"
comment="Size of huge font (points, or 1/72 of an inch)"
- size="16.0"
+ size="15.0"
/>
<font_size name="Large"
comment="Size of large font (points, or 1/72 of an inch)"
@@ -156,7 +156,6 @@
/>
<font_size name="Small"
comment="Size of small font (points, or 1/72 of an inch)"
- size="8.0"
+ size="7.8"
/>
</fonts>
-
diff --git a/indra/newview/skins/default/xui/en/inspect_avatar.xml b/indra/newview/skins/default/xui/en/inspect_avatar.xml
index a934e541da..2c1e2b6dc0 100644
--- a/indra/newview/skins/default/xui/en/inspect_avatar.xml
+++ b/indra/newview/skins/default/xui/en/inspect_avatar.xml
@@ -4,8 +4,9 @@
Single instance - only have one at a time, recycle it each spawn
-->
<floater
+ legacy_header_height="18"
bevel_style="in"
- bg_opaque_color="MouseGray"
+ bg_opaque_image="Inspector_Background"
can_close="false"
can_minimize="false"
height="138"
@@ -47,7 +48,6 @@
value="Grumpity ProductEngine"
width="240"
word_wrap="false" />
- <!-- Leave text fields blank so it doesn't flash when data arrives off the network -->
<text
follows="all"
height="16"
@@ -86,7 +86,7 @@
min_val="0.05"
name="volume_slider"
show_text="false"
- tool_tip="Voice Volume"
+ tool_tip="Voice volume"
top_pad="0"
value="0.5"
width="150" />
@@ -102,7 +102,6 @@
left_pad="0"
top_delta="4"
name="mute_btn"
- picture_style="true"
width="16" />
<avatar_icon
follows="all"
@@ -122,12 +121,13 @@
image_unselected="ForwardArrow_Off"
layout="topleft"
name="view_profile_btn"
- picture_style="true"
right="-8"
top="35"
left_delta="110"
tab_stop="false"
width="18" />
+ <!-- Overlapping buttons for default actions
+ llinspectavatar.cpp makes visible the most likely default action -->
<button
follows="bottom|left"
height="23"
@@ -136,6 +136,16 @@
top="246"
name="add_friend_btn"
width="100" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="IM"
+ left_delta="0"
+ top_delta="0"
+ name="im_btn"
+ width="100"
+ commit_callback.function="InspectAvatar.IM"
+ />
<menu_button
follows="top|left"
height="18"
@@ -144,7 +154,6 @@
image_unselected="OptionsMenu_Off"
menu_filename="menu_inspect_avatar_gear.xml"
name="gear_btn"
- picture_style="true"
right="-10"
top="249"
width="18" />
@@ -157,7 +166,6 @@
image_unselected="OptionsMenu_Off"
menu_filename="menu_inspect_self_gear.xml"
name="gear_self_btn"
- picture_style="true"
right="-10"
top="249"
width="18" />
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..e5e5007c56
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/inspect_group.xml
@@ -0,0 +1,109 @@
+<?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="138"
+ layout="topleft"
+ name="inspect_group"
+ single_instance="true"
+ sound_flags="0"
+ visible="true"
+ width="245">
+ <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="SansSerifLargeBold"
+ height="18"
+ left="8"
+ name="group_name"
+ top="5"
+ text_color="white"
+ use_ellipses="true"
+ width="240"
+ word_wrap="false">
+ Grumpity's Grumpy Group of Moose
+ </text>
+ <text
+ follows="all"
+ font="SansSerifSmallBold"
+ text_color="White"
+ height="18"
+ left="8"
+ name="group_subtitle"
+ use_ellipses="true"
+ top_pad="0"
+ width="170">
+ 123 members
+ </text>
+ <text
+ follows="all"
+ height="50"
+ left="8"
+ name="group_details"
+ top_pad="0"
+ width="170"
+ 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="15"
+ left="8"
+ name="group_cost"
+ top_pad="2"
+ width="170">
+L$123 to join
+ </text>
+ <icon
+ follows="all"
+ height="38"
+ right="-25"
+ mouse_opaque="true"
+ name="group_icon"
+ top="24"
+ width="38" />
+ <!-- Must be tab_stop="true" so something can hold focus even when the
+ other buttons are disabled or invisible, otherwise inspector closes -->
+ <button
+ follows="top|left"
+ height="18"
+ image_disabled="ForwardArrow_Disabled"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
+ name="view_profile_btn"
+ right="-8"
+ top="35"
+ left_delta="110"
+ tab_stop="true"
+ width="18"
+ commit_callback.function="InspectGroup.ViewProfile" />
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Join"
+ left="8"
+ top="246"
+ name="join_btn"
+ width="100"
+ commit_callback.function="InspectGroup.Join"/>
+ <button
+ follows="bottom|left"
+ height="23"
+ label="Leave"
+ left="8"
+ top="246"
+ name="leave_btn"
+ width="100"
+ commit_callback.function="InspectGroup.Leave"/>
+</floater>
diff --git a/indra/newview/skins/default/xui/en/inspect_object.xml b/indra/newview/skins/default/xui/en/inspect_object.xml
index 73a7bef77d..1365a0483f 100644
--- a/indra/newview/skins/default/xui/en/inspect_object.xml
+++ b/indra/newview/skins/default/xui/en/inspect_object.xml
@@ -4,8 +4,9 @@
Single instance - only have one at a time, recycle it each spawn
-->
<floater
+ legacy_header_height="18"
bevel_style="in"
- bg_opaque_color="MouseGray"
+ bg_opaque_image="Inspector_Background"
can_close="false"
can_minimize="false"
height="145"
@@ -70,7 +71,7 @@ owner James Linden
width="150">
L$300,000
</text>
- <text
+ <text
follows="all"
height="30"
left="8"
@@ -83,24 +84,35 @@ This is a really long description for an object being as how it is at least 80 c
</text>
<!-- Overlapping buttons for all default actions. Show "Buy" if
for sale, "Sit" if can sit, etc. -->
+ <text
+ follows="all"
+ height="15"
+ left_delta="0"
+ name="object_media_url"
+ top_pad="-5"
+ width="291"
+ max_length = "50"
+ use_ellipses="true"
+ word_wrap="true"/>
+
<button
- follows="top|left"
- font="SansSerif"
- height="23"
- label="Buy"
- left="10"
- name="buy_btn"
- top="114"
- width="100" />
+ follows="top|left"
+ font="SansSerif"
+ height="20"
+ label="Buy"
+ left="10"
+ name="buy_btn"
+ top="114"
+ width="75" />
<button
follows="top|left"
font="SansSerif"
- height="23"
+ height="20"
label="Pay"
left_delta="0"
name="pay_btn"
top_delta="0"
- width="100" />
+ width="75" />
<button
follows="top|left"
font="SansSerif"
@@ -109,16 +121,16 @@ This is a really long description for an object being as how it is at least 80 c
left_delta="0"
name="take_free_copy_btn"
top_delta="0"
- width="100" />
+ width="75" />
<button
follows="top|left"
font="SansSerifSmall"
- height="23"
+ height="20"
label="Touch"
left_delta="0"
name="touch_btn"
top_delta="0"
- width="100" />
+ width="75" />
<button
follows="top|left"
font="SansSerif"
@@ -127,17 +139,28 @@ This is a really long description for an object being as how it is at least 80 c
left_delta="0"
name="sit_btn"
top_delta="0"
- width="100" />
+ width="75" />
<button
follows="top|left"
font="SansSerifSmall"
- height="23"
+ height="20"
label="Open"
left_delta="0"
name="open_btn"
top_delta="0"
- width="100" />
- <!-- non-overlapping buttons here -->
+ width="75" />
+ <icon
+ name="secure_browsing"
+ image_name="Lock"
+ left_delta="80"
+ visible="false"
+ width="18"
+ height="18"
+ top_delta="2"
+ tool_tip="Secure Browsing"
+ follows="left|top"/>
+
+ <!-- non-overlapping buttons here -->
<menu_button
follows="top|left"
height="18"
@@ -146,7 +169,6 @@ This is a really long description for an object being as how it is at least 80 c
image_unselected="OptionsMenu_Off"
menu_filename="menu_inspect_object_gear.xml"
name="gear_btn"
- picture_style="true"
right="-10"
top_delta="5"
width="18" />
@@ -158,7 +180,6 @@ This is a really long description for an object being as how it is at least 80 c
image_unselected="ForwardArrow_Off"
layout="topleft"
name="more_info_btn"
- picture_style="true"
right="-5"
top="20"
left_delta="110"
diff --git a/indra/newview/skins/default/xui/en/menu_group_plus.xml b/indra/newview/skins/default/xui/en/menu_group_plus.xml
index 2029b19c1c..e83d07baec 100644
--- a/indra/newview/skins/default/xui/en/menu_group_plus.xml
+++ b/indra/newview/skins/default/xui/en/menu_group_plus.xml
@@ -1,7 +1,7 @@
<?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="true">
+ 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>
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
index 5279f9d141..8ee67b9a02 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_avatar_gear.xml
@@ -7,7 +7,6 @@
name="Gear Menu">
<menu_item_call
label="View Profile"
- layout="topleft"
enabled="true"
name="view_profile">
<menu_item_call.on_click
@@ -15,83 +14,72 @@
</menu_item_call>
<menu_item_call
label="Add Friend"
- layout="topleft"
name="add_friend">
<menu_item_call.on_click
function="InspectAvatar.AddFriend"/>
</menu_item_call>
<menu_item_call
label="IM"
- layout="topleft"
name="im">
<menu_item_call.on_click
function="InspectAvatar.IM"/>
</menu_item_call>
<menu_item_call
label="Call"
- layout="topleft"
enabled="true"
name="call">
</menu_item_call>
<menu_item_call
label="Teleport"
- layout="topleft"
name="teleport">
<menu_item_call.on_click
function="InspectAvatar.Teleport"/>
</menu_item_call>
<menu_item_call
label="Invite to Group"
- layout="topleft"
name="invite_to_group">
<menu_item_call.on_click
function="InspectAvatar.InviteToGroup"/>
</menu_item_call>
- <menu_item_separator layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="Block"
- layout="topleft"
name="block">
<menu_item_call.on_click
function="InspectAvatar.Block"/>
</menu_item_call>
<menu_item_call
label="Report"
- layout="topleft"
name="report">
<menu_item_call.on_click
function="InspectAvatar.Report"/>
</menu_item_call>
<menu_item_call
label="Freeze"
- layout="topleft"
name="freeze">
<menu_item_call.on_click
function="InspectAvatar.Freeze"/>
<menu_item_call.on_visible
- function="InspectAvatar.VisibleGodMode"/>
+ function="InspectAvatar.VisibleFreezeEject"/>
</menu_item_call>
<menu_item_call
label="Eject"
- layout="topleft"
name="eject">
<menu_item_call.on_click
function="InspectAvatar.Eject"/>
<menu_item_call.on_visible
- function="InspectAvatar.VisibleGodMode"/>
+ function="InspectAvatar.VisibleFreezeEject"/>
</menu_item_call>
<menu_item_call
label="Debug"
- layout="topleft"
name="debug">
<menu_item_call.on_click
- function="InspectAvatar.Debug"/>
+ function="Avatar.Debug"/>
<menu_item_call.on_visible
- function="InspectAvatar.VisibleGodMode"/>
+ function="IsGodCustomerService"/>
</menu_item_call>
<menu_item_call
label="Find On Map"
- layout="topleft"
name="find_on_map">
<menu_item_call.on_click
function="InspectAvatar.FindOnMap"/>
@@ -100,16 +88,14 @@
</menu_item_call>
<menu_item_call
label="Zoom In"
- layout="topleft"
name="zoom_in">
<menu_item_call.on_click
function="InspectAvatar.ZoomIn"/>
</menu_item_call>
<menu_item_call
label="Pay"
- layout="topleft"
name="pay">
<menu_item_call.on_click
function="InspectAvatar.Pay"/>
</menu_item_call>
-</menu> \ No newline at end of file
+</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
index 240822e5ca..3d65878cf8 100644
--- a/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
+++ b/indra/newview/skins/default/xui/en/menu_inspect_self_gear.xml
@@ -1,53 +1,49 @@
-<?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"
- layout="topleft"
- enabled="true"
- name="stand_up">
- <menu_item_call.on_click
- function="Self.StandUp"
- parameter="" />
- <menu_item_call.on_visible
- function="Self.VisibleStandUp" />
- </menu_item_call>
- <menu_item_call
- label="My Appearance"
- layout="topleft"
- name="my_appearance">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="appearance" />
- <menu_item_call.on_enable
- function="Edit.EnableCustomizeAvatar" />
- </menu_item_call>
- <menu_item_call
- label="My Profile"
- layout="topleft"
- enabled="true"
- name="my_profile">
- <menu_item_call.on_click
- function="ShowAgentProfile"
- parameter="agent" />
- </menu_item_call>
- <menu_item_call
- label="My Friends"
- layout="topleft"
- name="my_friends">
- <menu_item_call.on_click
- function="Self.Friends"
- parameter="" />
- </menu_item_call>
- <menu_item_call
- label="My Groups"
- layout="topleft"
- name="my_groups">
- <menu_item_call.on_click
- function="Self.Groups" />
- </menu_item_call>
-</menu> \ No newline at end of file
+<?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.VisibleStandUp" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Appearance"
+ name="my_appearance">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="appearance" />
+ <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
index 72cbd3bcd5..62940b87dc 100644
--- a/indra/newview/skins/default/xui/en/menu_inventory.xml
+++ b/indra/newview/skins/default/xui/en/menu_inventory.xml
@@ -457,14 +457,6 @@
function="Inventory.DoToSelected"
parameter="replaceoutfit" />
</menu_item_call>
- <menu_item_call
- label="Wear As Ensemble"
- layout="topleft"
- name="Wear As Ensemble">
- <menu_item_call.on_click
- function="Inventory.DoToSelected"
- parameter="wearasensemble" />
- </menu_item_call>
<menu_item_separator
layout="topleft" />
<menu_item_call
@@ -486,11 +478,12 @@
parameter="open" />
</menu_item_call>
<menu_item_separator
- layout="topleft" />
+ layout="topleft"
+ name="Landmark Separator" />
<menu_item_call
label="About Landmark"
layout="topleft"
- name="Teleport To Landmark">
+ name="About Landmark">
<menu_item_call.on_click
function="Inventory.DoToSelected"
parameter="about" />
diff --git a/indra/newview/skins/default/xui/en/menu_landmark.xml b/indra/newview/skins/default/xui/en/menu_landmark.xml
index 64fec3ab40..93b6db222a 100644
--- a/indra/newview/skins/default/xui/en/menu_landmark.xml
+++ b/indra/newview/skins/default/xui/en/menu_landmark.xml
@@ -28,5 +28,16 @@
<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
index 8c78b0c82f..dfa5adb743 100644
--- a/indra/newview/skins/default/xui/en/menu_login.xml
+++ b/indra/newview/skins/default/xui/en/menu_login.xml
@@ -10,22 +10,18 @@
<menu
create_jump_keys="true"
label="Me"
- layout="topleft"
name="File">
<menu_item_call
label="Preferences"
- layout="topleft"
name="Preferences..."
shortcut="control|P">
<menu_item_call.on_click
function="ShowFloater"
parameter="preferences" />
</menu_item_call>
- <menu_item_separator
- layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="Quit [APP_NAME]"
- layout="topleft"
name="Quit"
shortcut="control|Q">
<menu_item_call.on_click
@@ -36,7 +32,6 @@
<menu
create_jump_keys="true"
label="Edit"
- layout="topleft"
name="Edit"
width="153">
</menu>
@@ -44,22 +39,18 @@
<menu
create_jump_keys="true"
label="Help"
- layout="topleft"
name="Help">
<menu_item_call
label="[SECOND_LIFE] Help"
- layout="topleft"
name="Second Life Help"
shortcut="F1">
<menu_item_call.on_click
function="ShowFloater"
parameter="help f1" />
</menu_item_call>
- <menu_item_separator
- layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="About [APP_NAME]"
- layout="topleft"
name="About Second Life">
<menu_item_call.on_click
function="ShowFloater"
@@ -69,7 +60,6 @@
<menu
create_jump_keys="true"
label="Debug"
- layout="topleft"
name="Debug"
tear_off="true">
<!-- Need a copy of the edit menu here so keyboard shortcuts like
@@ -78,12 +68,10 @@
<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
@@ -93,7 +81,6 @@
</menu_item_call>
<menu_item_call
label="Redo"
- layout="topleft"
name="Redo"
shortcut="control|Y">
<menu_item_call.on_click
@@ -101,11 +88,9 @@
<menu_item_call.on_enable
function="Edit.EnableRedo" />
</menu_item_call>
- <menu_item_separator
- layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="Cut"
- layout="topleft"
name="Cut"
shortcut="control|X">
<menu_item_call.on_click
@@ -115,7 +100,6 @@
</menu_item_call>
<menu_item_call
label="Copy"
- layout="topleft"
name="Copy"
shortcut="control|C">
<menu_item_call.on_click
@@ -125,7 +109,6 @@
</menu_item_call>
<menu_item_call
label="Paste"
- layout="topleft"
name="Paste"
shortcut="control|V">
<menu_item_call.on_click
@@ -135,7 +118,6 @@
</menu_item_call>
<menu_item_call
label="Delete"
- layout="topleft"
name="Delete"
shortcut="Del">
<menu_item_call.on_click
@@ -145,7 +127,6 @@
</menu_item_call>
<menu_item_call
label="Duplicate"
- layout="topleft"
name="Duplicate"
shortcut="control|D">
<menu_item_call.on_click
@@ -153,11 +134,9 @@
<menu_item_call.on_enable
function="Edit.EnableDuplicate" />
</menu_item_call>
- <menu_item_separator
- layout="topleft" />
+ <menu_item_separator />
<menu_item_call
label="Select All"
- layout="topleft"
name="Select All"
shortcut="control|A">
<menu_item_call.on_click
@@ -167,7 +146,6 @@
</menu_item_call>
<menu_item_call
label="Deselect"
- layout="topleft"
name="Deselect"
shortcut="control|E">
<menu_item_call.on_click
@@ -178,8 +156,7 @@
</menu>
<menu_item_separator />
<menu_item_call
- label="Debug Settings editor"
- layout="topleft"
+ label="Show Debug Settings"
name="Debug Settings">
<menu_item_call.on_click
function="Advanced.ShowDebugSettings"
@@ -187,7 +164,6 @@
</menu_item_call>
<menu_item_call
label="UI/Color Settings"
- layout="topleft"
name="UI/Color Settings">
<menu_item_call.on_click
function="Advanced.ShowDebugSettings"
@@ -196,7 +172,6 @@
<menu_item_separator />
<menu_item_call
label="XUI Preview Tool"
- layout="topleft"
name="UI Preview Tool"
shortcut="control|T">
<menu_item_call.on_click
@@ -206,7 +181,6 @@
<menu_item_separator />
<menu_item_call
label="Widget Test"
- layout="topleft"
name="Widget Test"
shortcut="control|shift|T">
<menu_item_call.on_click
@@ -222,10 +196,24 @@
function="ShowFloater"
parameter="test_inspectors" />
</menu_item_call>
+ <menu_item_call
+ label="Show Side Tray"
+ name="Show Side Tray">
+ <menu_item_call.on_click
+ function="Advanced.ShowSideTray" />
+ </menu_item_call>
+ <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="Show TOS"
- layout="topleft"
name="TOS">
<menu_item_call.on_click
function="ShowFloater"
@@ -233,7 +221,6 @@
</menu_item_call>
<menu_item_call
label="Show Critical Message"
- layout="topleft"
name="Critical">
<menu_item_call.on_click
function="ShowFloater"
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_people_friends_view_sort.xml b/indra/newview/skins/default/xui/en/menu_people_friends_view_sort.xml
index 6ef1eb9513..f1117d1419 100644
--- 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
@@ -1,20 +1,36 @@
<?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="true">
- <menu_item_call name="sort_name" label="Sort by Name">
- <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="sort_name" />
- </menu_item_call>
- <menu_item_call name="sort_status" label="Sort by Status">
- <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="sort_status" />
- </menu_item_call>
+ 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_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
- <menu_item_call name="organize_offline" label="Organize Offline Friends">
- <menu_item_call.on_click function="People.Friends.ViewSort.Action" userdata="organize_offline" />
- </menu_item_call>
+ <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" />
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
index ec8582f5b5..6dd44255bf 100644
--- 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
@@ -1,7 +1,7 @@
<?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="true">
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
<menu_item_check
label="Display Group Icons"
layout="topleft"
@@ -13,4 +13,15 @@
function="CheckControl"
parameter="GroupListShowIcons" />
</menu_item_check>
+ <menu_item_check
+ label="Leave Selected Group"
+ layout="topleft"
+ name="Leave Selected Group">
+ <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>
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..df74d2dcd4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_people_nearby_multiselect.xml
@@ -0,0 +1,47 @@
+<?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" />
+ </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
index 2b0f029016..c002cd078f 100644
--- 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
@@ -1,7 +1,7 @@
<?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="true">
+ mouse_opaque="false" opaque="true" color="MenuDefaultBgColor" drop_shadow="false">
<menu_item_call name="sort_recent" label="Sort by Recent Speakers">
<menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_recent" />
</menu_item_call>
@@ -12,9 +12,14 @@
<menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="sort_distance" />
</menu_item_call>
<menu_item_separator layout="topleft" />
- <menu_item_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Nearby.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
+ <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" />
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
index d9606de90d..cfd6dc78b6 100644
--- 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
@@ -1,17 +1,36 @@
<?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="true">
- <menu_item_call name="sort_most" label="Sort by Most Recent">
- <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="sort_recent" />
- </menu_item_call>
- <menu_item_call name="sort_name" label="Sort by Name">
- <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="sort_name" />
- </menu_item_call>
+ 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_call name="view_icons" label="View People Icons">
- <menu_item_call.on_click function="People.Recent.ViewSort.Action" userdata="view_icons" />
- </menu_item_call>
+ <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" />
diff --git a/indra/newview/skins/default/xui/en/menu_place.xml b/indra/newview/skins/default/xui/en/menu_place.xml
index 01f62985ca..1b96eb51f0 100644
--- a/indra/newview/skins/default/xui/en/menu_place.xml
+++ b/indra/newview/skins/default/xui/en/menu_place.xml
@@ -20,6 +20,9 @@
<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"/>
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..c849188699
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/menu_places_gear_folder.xml
@@ -0,0 +1,127 @@
+<?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" />
+ </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" />
+ </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..63d1a67d0f
--- /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_teleport_history_item.xml b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
index 515278c23d..0160d52b17 100644
--- a/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/menu_teleport_history_item.xml
@@ -17,10 +17,10 @@
function="TeleportHistory.MoreInformation" />
</menu_item_call>
<menu_item_call
- label="Copy"
+ label="Copy to Clipboard"
layout="topleft"
- name="Copy">
+ name="CopyToClipboard">
<menu_item_call.on_click
- function="TeleportHistory.Copy" />
+ function="TeleportHistory.CopyToClipboard" />
</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..7c9e6f0796
--- /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_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
index 6f7e659f48..35c2269b0d 100644
--- a/indra/newview/skins/default/xui/en/menu_url_objectim.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_objectim.xml
@@ -12,6 +12,13 @@
<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">
diff --git a/indra/newview/skins/default/xui/en/menu_url_parcel.xml b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
index 3804f7f780..f477c310fb 100644
--- a/indra/newview/skins/default/xui/en/menu_url_parcel.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_parcel.xml
@@ -12,6 +12,15 @@
<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">
diff --git a/indra/newview/skins/default/xui/en/menu_url_slurl.xml b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
index 58714f1f42..98abc206a5 100644
--- a/indra/newview/skins/default/xui/en/menu_url_slurl.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_slurl.xml
@@ -12,6 +12,13 @@
<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">
diff --git a/indra/newview/skins/default/xui/en/menu_url_teleport.xml b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
index ff52d7e109..289e32bcf4 100644
--- a/indra/newview/skins/default/xui/en/menu_url_teleport.xml
+++ b/indra/newview/skins/default/xui/en/menu_url_teleport.xml
@@ -12,6 +12,15 @@
<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">
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 57ea24ac0e..ebdfb01787 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -19,7 +19,7 @@
parameter="preferences" />
</menu_item_call>
<menu_item_call
- label="Manage My Account"
+ label="My Dashboard"
layout="topleft"
name="Manage My Account">
<menu_item_call.on_click
@@ -56,7 +56,7 @@
function="Edit.EnableCustomizeAvatar" />
</menu_item_call>
<menu_item_check
- label="My Things"
+ label="My Inventory"
layout="topleft"
name="Inventory"
shortcut="control|I">
@@ -114,25 +114,22 @@
layout="topleft"
name="Communicate"
tear_off="true">
- <menu_item_check
+ <menu_item_call
label="My Friends"
layout="topleft"
name="My Friends"
shortcut="control|shift|F">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="contacts.friends" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="contacts.friends" />
- </menu_item_check>
+ <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="Floater.Show"
- parameter="contacts.groups" />
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
</menu_item_call>
<menu_item_separator
layout="topleft" />
@@ -155,17 +152,26 @@
function="Floater.Toggle"
parameter="nearby_chat" />
</menu_item_check>
- <menu_item_check
- label="Nearby Speakers"
+ <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="active_speakers" />
+ parameter="nearby_media" />
<menu_item_check.on_click
function="Floater.Toggle"
- parameter="active_speakers" />
+ parameter="nearby_media" />
</menu_item_check>
<!--menu_item_check
label="Block List"
@@ -232,7 +238,7 @@
<menu_item_separator
layout="topleft" />
<menu_item_call
- label="Place Profile"
+ label="About Land"
layout="topleft"
name="About Land">
<menu_item_call.on_click
@@ -272,6 +278,28 @@
name="Land"
tear_off="true">
<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"
@@ -292,16 +320,6 @@
function="ToggleControl"
parameter="ShowParcelOwners" />
</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>
<menu_item_separator
layout="topleft" />
@@ -355,7 +373,8 @@
label="World Map"
layout="topleft"
name="World Map"
- shortcut="control|M">
+ shortcut="control|M"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Floater.Visible"
parameter="world_map" />
@@ -950,36 +969,57 @@
function="Tools.EnableToolNotPie" />
</menu_item_call>
</menu>
- <menu
- create_jump_keys="true"
- label="Beacons"
+ </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="Beacons"
- tear_off="true">
- <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="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>
+ 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
@@ -1057,6 +1097,14 @@
<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_separator/>
<menu_item_check
label="Limit Select Distance"
layout="topleft"
@@ -1151,6 +1199,17 @@
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"
@@ -1158,6 +1217,17 @@
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"
@@ -1243,7 +1313,7 @@
function="View.CheckShowHoverTips" />
</menu_item_check>
<!-- <menu_item_check
- label="Tips On All Objects"
+ label="Show Tips On All Objects"
layout="topleft"
name="Tips On All Objects">
<menu_item_check.on_check
@@ -1255,29 +1325,9 @@
function="View.CheckShowHoverTips" />
</menu_item_check>
</menu>-->
- <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_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
create_jump_keys="true"
label="Rendering Types"
@@ -1544,6 +1594,17 @@
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"
@@ -1565,6 +1626,234 @@
</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_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"
@@ -1603,7 +1892,8 @@
label="Texture Console"
layout="topleft"
name="Texture Console"
- shortcut="control|shift|3">
+ shortcut="control|shift|3"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="texture" />
@@ -1615,7 +1905,8 @@
label="Debug Console"
layout="topleft"
name="Debug Console"
- shortcut="control|shift|4">
+ shortcut="control|shift|4"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="debug" />
@@ -1627,7 +1918,8 @@
label="Fast Timers"
layout="topleft"
name="Fast Timers"
- shortcut="control|shift|9">
+ shortcut="control|shift|9"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="fast timers" />
@@ -1639,7 +1931,8 @@
label="Memory"
layout="topleft"
name="Memory"
- shortcut="control|shift|0">
+ shortcut="control|shift|0"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="memory view" />
@@ -1651,7 +1944,8 @@
label="Notifications Console"
layout="topleft"
name="Notifications"
- shortcut="control|shift|5">
+ shortcut="control|shift|5"
+ use_mac_ctrl="true">
<menu_item_check.on_check
function="Advanced.CheckConsole"
parameter="notifications" />
@@ -2042,374 +2336,6 @@
</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_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
- 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
- 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_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 Tool"
- layout="topleft"
- name="Select Tool"
- tear_off="true">
- <menu_item_call
- label="Focus"
- 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"
- 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"
- 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"
- 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"
- 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"
- shortcut="alt|Enter">
- <menu_item_call.on_click
- function="View.Fullscreen" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
label="Rendering"
layout="topleft"
name="Rendering"
@@ -2590,6 +2516,141 @@
parameter="RenderHighlightEnable" />
</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"
@@ -2880,7 +2941,8 @@
function="Advanced.GrabBakedTexture"
parameter="iris" />
<menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="iris" />
</menu_item_call>
<menu_item_call
label="Head"
@@ -2890,7 +2952,8 @@
function="Advanced.GrabBakedTexture"
parameter="head" />
<menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="head" />
</menu_item_call>
<menu_item_call
label="Upper Body"
@@ -2900,7 +2963,8 @@
function="Advanced.GrabBakedTexture"
parameter="upper" />
<menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="upper" />
</menu_item_call>
<menu_item_call
label="Lower Body"
@@ -2910,7 +2974,8 @@
function="Advanced.GrabBakedTexture"
parameter="lower" />
<menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="lower" />
</menu_item_call>
<menu_item_call
label="Skirt"
@@ -2920,17 +2985,8 @@
function="Advanced.GrabBakedTexture"
parameter="skirt" />
<menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
- </menu_item_call>
- <menu_item_call
- label="Skirt"
- layout="topleft"
- name="Hair">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="hair" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture" />
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="skirt" />
</menu_item_call>
</menu>
<menu
@@ -2953,7 +3009,7 @@
<menu_item_call.on_click
function="Advanced.ToggleCharacterGeometry" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Test Male"
@@ -3136,7 +3192,18 @@
function="Advanced.CompressImage" />
</menu_item_call>
<menu_item_check
- label="Console Window"
+ 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
@@ -3146,6 +3213,8 @@
function="ToggleControl"
parameter="ShowConsoleWindow" />
</menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
<menu_item_check
label="Show Admin Menu"
layout="topleft"
@@ -3193,7 +3262,7 @@
<menu_item_call.on_click
function="Admin.ForceTakeCopy" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Force Owner To Me"
@@ -3202,7 +3271,7 @@
<menu_item_call.on_click
function="Admin.HandleObjectOwnerSelf" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Force Owner Permissive"
@@ -3211,7 +3280,7 @@
<menu_item_call.on_click
function="Admin.HandleObjectOwnerPermissive" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Delete"
@@ -3221,7 +3290,7 @@
<menu_item_call.on_click
function="Admin.HandleForceDelete" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Lock"
@@ -3231,7 +3300,7 @@
<menu_item_call.on_click
function="Admin.HandleObjectLock" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Get Assets IDs"
@@ -3241,7 +3310,7 @@
<menu_item_call.on_click
function="Admin.HandleObjectAssetIDs" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
</menu>
<menu
@@ -3257,7 +3326,7 @@
<menu_item_call.on_click
function="Admin.HandleForceParcelOwnerToMe" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Set to Linden Content"
@@ -3267,7 +3336,7 @@
<menu_item_call.on_click
function="Admin.HandleForceParcelToContent" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Claim Public Land"
@@ -3276,7 +3345,7 @@
<menu_item_call.on_click
function="Admin.HandleClaimPublicLand" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
</menu>
<menu
@@ -3292,7 +3361,7 @@
<menu_item_call.on_click
function="Admin.HandleRegionDumpTempAssetData" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
<menu_item_call
label="Save Region State"
@@ -3301,7 +3370,7 @@
<menu_item_call.on_click
function="Admin.OnSaveState" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
</menu>
<menu_item_call
@@ -3312,7 +3381,7 @@
function="Floater.Show"
parameter="god_tools" />
<menu_item_call.on_enable
- function="EnableGodCustomerService" />
+ function="IsGodCustomerService" />
</menu_item_call>
</menu>
<menu
diff --git a/indra/newview/skins/default/xui/en/mime_types.xml b/indra/newview/skins/default/xui/en/mime_types.xml
index 2de9449ea6..76c0d027f3 100644
--- a/indra/newview/skins/default/xui/en/mime_types.xml
+++ b/indra/newview/skins/default/xui/en/mime_types.xml
@@ -163,8 +163,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype name="application/javascript">
<label name="application/javascript_label">
@@ -208,7 +208,7 @@
</mimetype>
<mimetype name="application/smil">
<label name="application/smil_label">
- Synchronized Multimedia Integration Language (SMIL)
+ Synchronized Multimedia Integration Language (SMIL)
</label>
<widgettype>
movie
@@ -348,8 +348,8 @@
web
</widgettype>
<impl>
- media_plugin_webkit
- </impl>
+ media_plugin_webkit
+ </impl>
</mimetype>
<mimetype menu="1" name="text/plain">
<label name="text/plain_label">
@@ -381,8 +381,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype name="video/mp4">
<label name="video/mp4_label">
@@ -392,8 +392,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype menu="1" name="video/quicktime">
<label name="video/quicktime_label">
@@ -403,8 +403,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype name="video/x-ms-asf">
<label name="video/x-ms-asf_label">
@@ -414,8 +414,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype name="video/x-ms-wmv">
<label name="video/x-ms-wmv_label">
@@ -425,8 +425,8 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </impl>
+ media_plugin_quicktime
+ </impl>
</mimetype>
<mimetype menu="1" name="video/x-msvideo">
<label name="video/x-msvideo_label">
@@ -436,7 +436,7 @@
movie
</widgettype>
<impl>
- media_plugin_quicktime
- </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
index 833001b34b..989dc88851 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -13,7 +13,7 @@
<global name="implicitclosebutton">
Close
</global>
-
+
<template name="okbutton">
<form>
<button
@@ -154,7 +154,7 @@ No tutorial is currently available.
icon="alertmodal.tga"
name="BadInstallation"
type="alertmodal">
- An error occurred while updating [APP_NAME]. Please download the latest version of the Viewer. http://get.secondlife.com
+ An error occurred while updating [APP_NAME]. Please [http://get.secondlife.com download the latest version] of the Viewer.
<usetemplate
name="okbutton"
yestext="Ok"/>
@@ -370,80 +370,6 @@ Add this Ability to &apos;[ROLE_NAME]&apos;?
</notification>
<notification
- icon="alertmodal.tga"
- name="ClickPublishHelpLand"
- type="alertmodal">
-Selecting the &quot;Publish in Search&quot;
-Checking this box will show:
-- this parcel in search results
-- this parcel&apos;s public objects
-- this parcel in web search
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickSoundHelpLand"
- type="alertmodal">Media and Music can only be experienced within the parcel. Sound and Voice options can be restricted to the parcel or will be heard by residents outside the parcel depending on their maturity Rating. Go to Knowledge Base to learn more about how to set these options?
- <url option="0" name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=5046
- </url>
- <usetemplate
- name="okcancelbuttons"
- yestext="Go to Knowledge Base"
- notext="Close" />
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickSearchHelpAll"
- type="alertmodal">
-Search results are organized based on the tab you are in, your maturity Rating, the category chosen, and other factors. For more details, please see the Knowledge Base.
- <url option="0" name="url">
- https://support.secondlife.com/ics/support/default.asp?deptID=4417&amp;task=knowledge&amp;questionID=4722
- </url>
- <usetemplate
- name="okcancelbuttons"
- yestext="Go to Knowledge Base"
- notext="Close" />
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickPublishHelpLandDisabled"
- type="alertmodal">
-You can&apos;t make this parcel show in search because it is located in a region that forbids this.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickPublishHelpAvatar"
- type="alertmodal">
-Selecting &quot;Show in Search&quot; will show:
-- my profile in search results
-- a link to my profile in public group pages
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickPartnerHelpAvatar"
- type="alertmodal">
-You can propose to another Resident or dissolve an existing partnership through the [SECOND_LIFE] website.
-
-Go to the [SECOND_LIFE] web site for more information on partnering?
- <usetemplate
- name="okcancelbuttons"
- notext="Cancel"
- yestext="Go to Page"/>
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="ClickUploadHelpPermissions"
- type="alertmodal">
-Your default permissions may not work in older regions.
- </notification>
-
-<notification
icon="alertmodal.tga"
name="ClickUnimplemented"
type="alertmodal">
@@ -452,19 +378,6 @@ Sorry, not implemented yet.
<notification
icon="alertmodal.tga"
- name="ClickWebProfileHelpAvatar"
- type="alertmodal">
-If this Resident has set a web profile URL then you can:
- * Click &apos;Load&apos; to see the page in this Web tab.
- * Click Load &gt; &apos;In external browser&apos; to view the page in your default web browser.
- * Click Load &gt; &apos;Home URL&apos; to return to this Resident&apos;s web profile if you&apos;ve navigated away.
-
-When viewing your own profile, you can enter any URL as your web profile and click OK to set it.
-Other residents can visit the URL you set when they look at your profile.
- </notification>
-
- <notification
- icon="alertmodal.tga"
name="JoinGroupCanAfford"
type="alertmodal">
Joining this group costs L$[COST].
@@ -485,6 +398,20 @@ You do not have enough L$ to join this group.
<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?
@@ -650,7 +577,7 @@ Scripts must be allowed to run for weapons to work.
icon="alertmodal.tga"
name="MultipleFacesSelected"
type="alertmodal">
-Multiple faces are currently selected.
+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 Texture and click on the desired face of that object then click Add.
<usetemplate
@@ -661,6 +588,19 @@ To place the media on only one face, choose Select Texture and click on the desi
<notification
icon="alertmodal.tga"
+ name="WhiteListInvalidatesHomeUrl"
+ type="alertmodal">
+Adding this entry to the whitelist will invalidate the home URL you
+specified for this instance of media. You are not allowed to do this
+so the entry cannot be added to the whitelist.
+ <usetemplate
+ name="okbutton"
+ yestext="Ok"/>
+ </notification>
+
+
+ <notification
+ icon="alertmodal.tga"
name="MustBeInParcel"
type="alertmodal">
You must be standing inside the land parcel to set its Landing Point.
@@ -743,6 +683,14 @@ You can not wear clothes or body parts that are in the trash
<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.
@@ -756,7 +704,7 @@ 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
+ <url
option="0"
name="url"
openexternally = "1">
@@ -773,7 +721,7 @@ You need an account to enter [SECOND_LIFE]. Would you like to create one now?
icon="alertmodal.tga"
name="AddClassified"
type="alertmodal">
-Classified ads appear in the &apos;Classified&apos; section of the Search directory and on www.secondlife.com for one week.
+Classified ads appear in the &apos;Classified&apos; section of the Search directory and on [http://www.secondlife.com 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.
@@ -1025,13 +973,13 @@ There was a problem saving a compiled script due to the following reason: [REASO
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.
+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"
@@ -1924,21 +1872,6 @@ Join land?
<notification
icon="alertmodal.tga"
- name="ShowOwnersHelp"
- type="alertmodal">
-Show owners:
-Color parcels to show the owner type.
-
-Green = Your land
-Aqua = Your Group&apos;s land
-Red = Owned by others
-Yellow = For sale
-Purple = For auction
-Grey = Public
- </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?
@@ -2374,7 +2307,7 @@ You can use [SECOND_LIFE] normally and other people will see you correctly.
[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 www.secondlife.com to create a new account?
+Return to [http://join.secondlife.com secondlife.com] to create a new account?
<usetemplate
name="okcancelbuttons"
notext="Continue"
@@ -2391,7 +2324,7 @@ You can either check your Internet connection and try again in a few minutes, cl
<url option="1" name="url">
http://secondlife.com/support/
- </url>
+ </url>
<form name="form">
<button
default="true"
@@ -2766,7 +2699,7 @@ Do you want to open your Web browser to view this content?
icon="alertmodal.tga"
name="WebLaunchJoinNow"
type="alertmodal">
-Go to secondlife.com to manage your account?
+Go to your [http://secondlife.com/account/ Dashboard] to manage your account?
<usetemplate
ignoretext="Launch my browser to manage my account"
name="okcancelignore"
@@ -2812,18 +2745,6 @@ Visit the [SECOND_LIFE] Public Issue Tracker, where you can report bugs and othe
<notification
icon="alertmodal.tga"
- name="WebLaunchPublicIssueHelp"
- type="alertmodal">
-Visit the [SECOND_LIFE] Wiki for info on how to use the Public Issue Tracker.
- <usetemplate
- ignoretext="Launch my browser to view instructions for 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.
@@ -3128,7 +3049,7 @@ Teleport to [PICK]?
notext="Cancel"
yestext="Teleport"/>
</notification>
-
+
<notification
icon="alert.tga"
label="Message everyone in your Estate"
@@ -3599,125 +3520,6 @@ Type a short announcement which will be sent to everyone in this region.
<notification
icon="alertmodal.tga"
- label="Block Terraform"
- name="HelpRegionBlockTerraform"
- type="alertmodal">
-If this box is checked, land owners will not be able to terraform their land regardless of the per-parcel &apos;Edit Terrain&apos; setting.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Block Fly"
- name="HelpRegionBlockFly"
- type="alertmodal">
-If this box is checked, people will not be able to fly in this region regardless of the per-parcel &apos;Fly&apos; setting.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Bulk Change Content Permissions"
- name="HelpBulkPermission"
- type="alertmodal">
-The Bulk Permissions tool helps you to quickly change the permissions on multiple items in the contents of the selected object(s). However, please note that you are only setting permissions on the items in the Contents of the selected objects -- not permissions on the container object(s) themselves.
-
-Also note, the permissions are not applied to the nested contents of any of the contained items. Your request only operates on items exactly one level deep.
-
-You can selectively choose which types of items to modify by using the checklist under &apos;Content Types&apos; here. Snapshots are included when you select Textures.
-
-* This tool will only succeed at changing permissions on items you are allowed to change.
-* You cannot grant any Next owner permissions which you do not already have.
-* The Next owner permissions are merely requests. If any item cannot take all of the new permissions, none of its permissions will change.
-
-When you are ready to change the permissions in bulk, click &apos;Apply&apos; and wait for the results to display.
-
-If you close the Bulk Permissions window while permissions are being changed, it will halt the operation.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Allow Damage"
- name="HelpRegionAllowDamage"
- type="alertmodal">
-If this box is checked, the health system across all parcels regardless of individual parcel settings. If this box is left unchecked, individual parcel owners will still be able to activate the health system on their parcels.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Agent Limit"
- name="HelpRegionAgentLimit"
- type="alertmodal">
-Sets the maximum number of avatars allowed in this region.
-Performance may vary depending on the number avatars present.
-
-Default: 40
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Object Bonus"
- name="HelpRegionObjectBonus"
- type="alertmodal">
-The Object Bonus is a multiplier for primitives allowed on any given parcel. The range allowed is 1 to 10. Set at &apos;1&apos;, each 512m² parcel is allowed 117 objects. Set at &apos;2&apos;, each 512m² parcel is allowed 234, or twice as many, and so on. The max number of objects allowed per region remains 15,000 no matter what the Object Bonus is. Once set, be aware that lowering the Object Bonus may cause objects to be returned or deleted.
-
-Default: 1.0
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Maturity"
- name="HelpRegionMaturity"
- type="alertmodal">
-Sets the maturity Rating of the Region, as shown in the menu bar at the top of any Resident&apos;s viewer, and in tooltips on the World Map when the cursor hovers over this Region. This setting also affects access to this Region and search results. Other Residents may only enter Regions or view search results with the same maturity Ratings they have chosen in their preferences.
-
-It may take some time for this change to be reflected on the map.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Restrict Pushing"
- name="HelpRegionRestrictPushObject"
- type="alertmodal">
-This checkbox sets the full region to restricted push permissions.
-When enabled, Residents may only be pushed by themselves or by the parcel&apos;s owner.
-(Push refers to the llPushObject() LSL function.)
-
-Default: Off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Parcel Join/Subdivide"
- name="HelpParcelChanges"
- type="alertmodal">
-This checkbox sets whether or not parcels not owned by the estate owner can be joined or subdivided.
-If this option is unchecked:
- * Only estate owners or managers can join or subdivide parcels.
- * They may only join or subdivide parcels belonging to the owner, or to a group where they have the appropriate group powers.
-If this option is checked:
- * All parcel owners can join or subdivide the parcels they own.
- * For group owned parcels, those with appropriate group powers may join or subdivide parcels.
-
-Default: Checked
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Do Not Show In Search"
- name="HelpRegionSearch"
- type="alertmodal">
-Checking this box will block parcel owners from listing their parcels in search.
-
-Default: Off
- </notification>
-
- <notification
- icon="alertmodal.tga"
label="Changed Region Maturity"
name="RegionMaturityChange"
type="alertmodal">
@@ -3727,260 +3529,6 @@ It may take some time for the change to be reflected on the map.
<notification
icon="alertmodal.tga"
- label="Land Resale"
- name="HelpRegionLandResell"
- type="alertmodal">
-Estate owners and managers can sell any land owned by the estate owner.
-If this option is left unchecked, buyers cannot resell their land in this region.
-If this option is checked, buyers can resell their land in this region.
-
-Default: Disallow
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Disable Scripts"
- name="HelpRegionDisableScripts"
- type="alertmodal">
-When sim performance is poor, a script may be to blame. Open the Statistics Bar (Ctrl-Shift-1). Look at the Simulator Physics FPS.
-If it is lower than 45, open the Time panel located at the bottom of the Stats Bar. If Script Time reads 25 ms or higher, click the Get Top Scripts button. You will be given the name and location of scripts that may be causing poor performance.
-
-Checking the Disable Scripts box and then pressing the Apply button will temporarily disable all scripts in this region. You may need to do this in order to travel to the location of a noted &apos;top script&apos;. Once you have arrived at the location, investigate the script to determine if it is causing the problem. You may want to contact the owner of the script or delete or return the object.
-Uncheck the Disable Script box and then Apply to reactivate the scripts in the region.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Disable Collisions"
- name="HelpRegionDisableCollisions"
- type="alertmodal">
-When sim performance is poor, physical objects may be to blame.
-Open the Statistics Bar (Ctrl-Shift-1). Look at the Simulator Physics FPS. If it is lower than 45, open the Time panel located at the bottom of the Stats Bar. If Sim Time (Physics) reads 20 ms or higher, click the Get Top Colliders button.
-You will be given the name and location of physical objects that may be causing poor performance.
-
-Checking the Disable Collisions box and then pressing the Apply button will temporarily disable object-object collisions. You may need to do this in order to travel to the location of a noted &apos;top collider&apos;. Once you have arrived at the location, investigate the object - is it constantly colliding with other objects? You may want to contact the owner of the object or delete or return the object.
-Uncheck the Disable Collisions box and then Apply to reactivate collisions in the region.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Disable Physics"
- name="HelpRegionDisablePhysics"
- type="alertmodal">
-Disable Physics is similar to Disable Collisions, except all physics simulation is disabled. This means that not only will objects stop colliding, but avatars will be unable to move.
-
-This should only be used when Disable Collisions does not give back enough performance to the region to investigate a physics problem or Top Collider.
-
-Be sure to re-enable physics when you are done, or avatars will continue to be unable to move.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Top Colliders"
- name="HelpRegionTopColliders"
- type="alertmodal">
-Show a list of objects experiencing the greatest number of potential object-object collisions. These objects can slow performance. Select Advanced &gt; Performance Tools &gt; Statistics Bar and look under Simulator &gt; Time &gt; Physics Time to see if more than 20 ms is being spent in physics.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Top Scripts"
- name="HelpRegionTopScripts"
- type="alertmodal">
-Show a list of objects spending the most time running LSL scripts. These objects can slow performance.
-Select Advanced &gt; Performance Tools &gt; Statistics Bar and look under Simulator &gt; Time &gt; Script Time to see if more than 25 ms is being spent in scripts.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Restart Region"
- name="HelpRegionRestart"
- type="alertmodal">
-Restart the server process running this region after a two minute warning. All Residents in the region will be disconnected. The region will save its data, and should come back up within 90 seconds.
-
-Restarting the region will not fix most performance problems, and should usually be used only when directed.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Water Height"
- name="HelpRegionWaterHeight"
- type="alertmodal">
-This is the height in meters where water appears. If this setting is anything other than 20 and you have water that is adjacent to the edge of world or &apos;void&apos; water, there will be a visible gap.
-
-Default: 20
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Terrain Raise"
- name="HelpRegionTerrainRaise"
- type="alertmodal">
-This is the distance in meters that parcel owners can raise their terrain above the &apos;baked&apos; terrain default height.
-
-Default: 4
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Terrain Lower"
- name="HelpRegionTerrainLower"
- type="alertmodal">
-This is the distance in meters that parcel owners can lower their terrain below the &apos;baked&apos; terrain default height.
-
-Default: -4
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Upload RAW Terrain"
- name="HelpRegionUploadRaw"
- type="alertmodal">
-This button uploads a .RAW file to the region you are in.
-The file must have the correct dimensions (RGB, 256x256) and 13 channels. The best way to create a terrain file is to download the existing RAW file. A good first step is to modify the red channel (land height), and upload it.
-
-The upload can take up to 45 seconds. Note that uploading a terrain file *will not* move the objects that are on the land, only the terrain itself and the permissions associated with the parcels. This can result in objects going underground.
-
-For more information on editing region height fields, consult F1 Help.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Download RAW Terrain"
- name="HelpRegionDownloadRaw"
- type="alertmodal">
-This button downloads a file containing the height field data, parcel dimensions, parcel for sale status and some parcel permissions for this region. When opening the file in a program such as Photoshop you must specify the document&apos;s dimensions which are: RGB, 256x256 with 13 channels. This terrain file cannot be opened in any other way.
-
-For more information on editing region height fields, consult F1 help.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Use Estate Sun"
- name="HelpRegionUseEstateSun"
- type="alertmodal">
-This checkbox makes the sun position in this region the same as the sun position in the rest of the estate.
-
-Default: on
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Fixed Sun"
- name="HelpRegionFixedSun"
- type="alertmodal">
-This checkbox sets the sun position to the position in the Phase slider and stops the sun from moving.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Bake Terrain"
- name="HelpRegionBakeTerrain"
- type="alertmodal">
-This button saves the current shape of the terrain as the new default for the region. Once baked, the land can revert to the saved shape whenever you or others use the Edit Terrain &apos;Revert&apos; option. The baked terrain is also the middle point for the terrain raise and lower limits.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Estate Managers"
- name="HelpEstateEstateManager"
- type="alertmodal">
-An estate manager is a Resident to whom you have delegated control of region and estate settings. An estate manager can change any setting in these panels, except for uploading, downloading, and baking terrain. In particular, they can allow or ban Residents from your estate.
-
-Estate managers can only be added or removed by the owner of the estate, not by each other. Please only choose Residents you trust as estate managers, as you will be ultimately responsible for their actions.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Use Global Time"
- name="HelpEstateUseGlobalTime"
- type="alertmodal">
-This checkbox makes the sun in your estate follow the same position as on the Linden-owned &apos;mainland&apos; estates.
-
-Default: on
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Fixed Sun"
- name="HelpEstateFixedSun"
- type="alertmodal">
-This checkbox sets the sun position to the position in the Phase slider and stops the sun from moving.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Public Access"
- name="HelpEstateExternallyVisible"
- type="alertmodal">
-This checkbox sets whether Residents who are on other estates can enter this estate without being on an access list.
-
-Default: on
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Allow Direct Teleport"
- name="HelpEstateAllowDirectTeleport"
- type="alertmodal">
-When checked, allows Residents to directly teleport to any point in your estate. When unchecked, Residents teleport to the nearest telehub.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Allow Access"
- name="HelpEstateAllowResident"
- type="alertmodal">
-Access to this estate will be limited to Residents listed here and any groups below. This setting is only available when Public Access is unchecked.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Allow Group Access"
- name="HelpEstateAllowGroup"
- type="alertmodal">
-Access to this estate will be limited to groups listed here and any Residents above. This setting is only available when Public Access is unchecked.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Abuse Email Address"
- name="HelpEstateAbuseEmailAddress"
- type="alertmodal">
-Setting this to a valid email address will cause abuse reports on this estate to be sent to that address.
-Setting it blank will cause abuse reports to be sent only to Linden Lab.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Deny Access"
- name="HelpEstateBanResident"
- type="alertmodal">
-Residents on this list are denied access to your estate, regardless of any other settings.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- label="Allow Voice Chat"
- name="HelpEstateVoiceChat"
- type="alertmodal">
-Parcels in this estate are allowed to have their own voice channels in which residents may hear and talk with others nearby.
-
-Default: off
- </notification>
-
- <notification
- icon="alertmodal.tga"
label="Voice Version Mismatch"
name="VoiceVersionMismatch"
type="alertmodal">
@@ -3989,18 +3537,6 @@ This version of [APP_NAME] is not compatible with the Voice Chat feature in this
<notification
icon="alertmodal.tga"
- label="Estate Covenant"
- name="HelpEstateCovenant"
- type="alertmodal">
-Setting an estate covenant enables you to sell parcels within that estate. If a covenant is not set, you cannot sell the land. The notecard for your covenant can be empty if you do not wish to apply any rules or advise buyers of anything in relation to the land before they buy it.
-
-A covenant can be used to communicate rules, guidelines, cultural information or simply your own expectations to the prospective buyer. This can include zoning, building regulations, payment options or any other information you feel it is important for the new owner to have seen and to have agreed to before they purchase.
-
-The buyer must agree to the covenant by ticking the check box before they will be able to finish the purchase. Estate covenants are always visible in the About Land dialog for any parcels that have one set.
- </notification>
-
- <notification
- icon="alertmodal.tga"
label="Can&apos;t Buy Objects"
name="BuyObjectOneOwner"
type="alertmodal">
@@ -4216,7 +3752,7 @@ There are no items in this object that you are allowed to copy.
icon="alertmodal.tga"
name="WebLaunchAccountHistory"
type="alertmodal">
-Go to secondlife.com to see your account history?
+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"
@@ -4226,18 +3762,6 @@ Go to secondlife.com to see your account history?
<notification
icon="alertmodal.tga"
- name="ClickOpenF1Help"
- type="alertmodal">
-Do you want to visit [SECOND_LIFE] help?
- <usetemplate
- ignoretext="Launch my browser to view Help/Support"
- name="okcancelignore"
- notext="Cancel"
- yestext="Go"/>
- </notification>
-
- <notification
- icon="alertmodal.tga"
name="ConfirmQuit"
type="alertmodal">
Are you sure you want to quit?
@@ -4253,14 +3777,9 @@ Are you sure you want to quit?
icon="alertmodal.tga"
name="HelpReportAbuseEmailLL"
type="alertmodal">
-Use this tool to report violations of the Terms of Service and Community Standards. See:
-
-http://secondlife.com/corporate/tos.php
-http://secondlife.com/corporate/cs.php
+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 of the Terms of Service and Community Standards are investigated and resolved. You can view the incident resolution on the Incident Report at:
-
-http://secondlife.com/support/incidentreport.php
+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>
@@ -4328,9 +3847,9 @@ 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] Community Standards or Terms of Service. However, the Abuse Team does not handle and will not respond to requests to remove content from the [SECOND_LIFE] world.
+(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 DMCA Policy at http://secondlife.com/corporate/dmca.php.
+(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;.
@@ -4418,7 +3937,7 @@ Are you sure you want to delete your travel, web, and search history?
<usetemplate
name="okcancelbuttons"
notext="Cancel"
- yestext="Yes"/>
+ yestext="OK"/>
</notification>
<notification
@@ -4471,31 +3990,6 @@ Link to this from a web page to give others easy access to this location, or try
<notification
icon="alertmodal.tga"
- name="GraphicsPreferencesHelp"
- type="alertmodal">
-This panel controls window size and resolution and the quality of the client&apos;s graphics. The Preferences &gt; Graphics interface allows you to choose between four graphics levels: Low, Mid, High, and Ultra. You may also customize your graphics settings by clicking the Advanced button and manipulating the following settings:
-
-Shaders: Enable or disable various types of pixel shaders.
-
-Reflection Detail: Sets the types of objects that water can reflect.
-
-Avatar Rendering: Sets options that affect how the client renders avatars.
-
-Draw Distance: Affects how far out from your viewpoint objects will be rendered in the scene.
-
-Max Particle Count: Sets the maximum number of particles you are able to see on your screen at once.
-
-Post Process Quality: Sets the resolution with which Glow is rendered.
-
-Mesh Detail: Sets the amount of detail or number of triangles used in rendering certain objects. A higher value takes longer to render, but makes these objects appear with more detail.
-
-Lighting Detail: Selects what types of lights you would like to render.
-
-Terrain Detail: Sets the amount of detail you would like to see for the terrain texture.
- </notification>
-
- <notification
- icon="alertmodal.tga"
name="WLSavePresetAlert"
type="alertmodal">
Do you wish to overwrite the saved preset?
@@ -4542,306 +4036,6 @@ PostProcess Effect exists. Do you still wish overwrite it?
</notification>
<notification
- icon="alertmodal.tga"
- name="HelpEditSky"
- type="alertmodal">
-Edit the WindLight sliders to create and save a set of skies.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpEditDayCycle"
- type="alertmodal">
-Set which skies to turn to throughout the day.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="EnvSettingsHelpButton"
- type="alertmodal">
-These settings adjust the way the environment looks locally on your computer. Your graphics card needs to support atmospheric shaders in order to have access to all of the settings.
-
-Adjust the &quot;Time of Day&quot; slider to change the day&apos;s phase locally on the viewer.
-
-Adjust the &quot;Cloud Cover&quot; slider to control how much the clouds cover the sky.
-
-Pick a color in the &quot;Water Color&quot; color picker to change the color of the water.
-
-Adjust the &quot;Water Fog&quot; slider to control how dense the fog is underwater.
-
-Click &quot;Use Estate Time&quot; to reset the time of day to the region&apos;s current time of day and remain linked to it.
-
-Click &quot;Advanced Sky&quot; to bring up an editor with more advanced settings for the sky.
-
-Click &quot;Advanced Water&quot; to bring up an editor with more advanced settings for the water.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpDayCycle"
- type="alertmodal">
-The Day Cycle Editor gives you control over the sky during [SECOND_LIFE]&apos;s day/night cycle. This is the cycle that is used by the Basic Environment Editor&apos;s Time of Day slider.
-
-The Day Cycle Editor works by setting keyframes. These are nodes (represented by the gray blips on the time graph) that have Sky Presets associated with them. As the Time of Day progresses, the WindLight sky &quot;animates&quot; as it interpolates between these keyframes.
-
-The yellow arrow above the timeline represents your current view, based on Time of Day. Click and drag it to see how your day will animate. You may add or delete keyframes by pressing the Add Key and Delete Key buttons to the right of the timeline.
-
-You can set the time position of a keyframe by either dragging it along the timeline, or by setting its value manually in the Key Frame Settings frame. Within the Key Frame Settings frame, you&apos;ll be able to associate the keyframe with its respective WindLight preset.
-
-Length of Cycle dictates the overall duration of a &quot;day&quot;. Setting this to a low value (for instance, 2 min.) will mean your entire 24-hour timeline will animate in only two real minutes! Once you are satisfied with your timeline and keyframe cycle, use the Play and Stop buttons to preview the results. Remember- you can also move the yellow time-indicator arrow above the timeline to see the cycle animate interactively. Using the Use Estate Time button will synchronize your day length and time of day with the Estate&apos;s day cycle.
-
-Once you are pleased with your Day Cycle, you can save and load it with the Save Test Day and Load Test Day buttons. Note that, for now, we only allow one Day Cycle.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpBlueHorizon"
- type="alertmodal">
-Use the Red/Green/Blue (RGB) sliders to adjust the color of the sky. You can use the Intensity (I) slider to move all three RGB sliders in unison.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpHazeHorizon"
- type="alertmodal">
-Haze Horizon is one of the most useful parameters for adjusting overall light exposure in the scene. It is effective for simulating many exposure settings, such as white-outs from the sun and darker, closed-iris settings.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpBlueDensity"
- type="alertmodal">
-Blue Density affects the overall color saturation of the sky and fog. If you move the Intensity (I) slider to the right, colors will become brighter and more vibrant. If you move it all the way to the left, the colors will become duller, eventually fading to black and white. If you want to fine-tune the sky&apos;s color balance, you can control individual elements of saturation by using the Red/Green/Blue (RGB) sliders.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpHazeDensity"
- type="alertmodal">
-Haze Density controls the level of dull, gray haze in the atmosphere. It is effective for simulating scenes with high levels of smoke and man-made pollutants. It is also effective for simulating fog and mist.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpDensityMult"
- type="alertmodal">
-The Density Multiplier can be used to affect the overall atmospheric density. At lower settings, it creates a feeling of &quot;thin air&quot;, and at higher settings, it creates a very heavy, smoggy effect.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpDistanceMult"
- type="alertmodal">
-Adjusts WindLight&apos;s perceived distance. A value of zero effectively turns off WindLight&apos;s influence on terrain and objects. Values greater than 1 simulate greater distances for thicker atmospheric effects.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpMaxAltitude"
- type="alertmodal">
-Max Altitude adjusts the altitude calculations WindLight performs when computing its atmospheric lighting. At later times of day, it is useful for adjusting how &quot;deep&quot; the sunset appears.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpSunlightColor"
- type="alertmodal">
-Adjusts the color and intensity of the direct light in the scene.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpSunAmbient"
- type="alertmodal">
-Adjusts the color and intensity of ambient atmospheric light in the scene.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpSunGlow"
- type="alertmodal">
-The Size slider controls the size of the sun.
-The Focus slider controls how blurred the sun is over the sky.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpSceneGamma"
- type="alertmodal">
-Adjust the screen&apos;s distribution of light and dark.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpStarBrightness"
- type="alertmodal">
-Adjusts the brightness of the stars in the sky.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpTimeOfDay"
- type="alertmodal">
-Controls the location of the sun in the sky.
-Similar to elevation.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpEastAngle"
- type="alertmodal">
-Controls the location of the sun in the sky.
-Similar to azimuth.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudColor"
- type="alertmodal">
-Edits the color of the clouds. It is generally recommended to keep it whitish, but hey, have fun if you want.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudDetail"
- type="alertmodal">
-Controls the detail image layered on top of the main cloud image. X and Y control its position. D (Density) controls how puffy or fractured the clouds appear.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudDensity"
- type="alertmodal">
-Allows you to control the position of the clouds with the X and Y sliders and how dense they are with the the D slider.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudCoverage"
- type="alertmodal">
-Controls how much the clouds cover the sky.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudScale"
- type="alertmodal">
-Controls the scaling of the cloud image on the sky dome.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudScrollX"
- type="alertmodal">
-Controls the speed of the clouds as they move in the X direction.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpCloudScrollY"
- type="alertmodal">
-Controls the speed of the clouds as they move in the Y direction.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpClassicClouds"
- type="alertmodal">
-Check this box to enable rendering of [SECOND_LIFE]&apos;s older classic clouds in addition to WindLight&apos;s clouds.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterFogColor"
- type="alertmodal">
-Chooses the color of the underwater fog.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterFogDensity"
- type="alertmodal">
-Controls how dense the water fog is and how far you can see underwater.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpUnderWaterFogMod"
- type="alertmodal">
-Modifies the effect of the Fog Density Exponent to control how far you can see when your avatar is underwater.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterGlow"
- type="alertmodal">
-Controls how much the surface of the water glows.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterNormalScale"
- type="alertmodal">
-Controls the scaling of the three wavelets that make up the water.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterFresnelScale"
- type="alertmodal">
-Controls how much light is reflected at different angles.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterFresnelOffset"
- type="alertmodal">
-Controls how much light intensity is reflected.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterScaleAbove"
- type="alertmodal">
-Controls how much light is refracted from looking above the surface of the water.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterScaleBelow"
- type="alertmodal">
-Controls how much light is refracted from looking from below the surface of the water.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterBlurMultiplier"
- type="alertmodal">
-Controls how waves and reflections are mixed.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterNormalMap"
- type="alertmodal">
-Controls what normal map is layered across the water to determine reflections/refractions.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterWave1"
- type="alertmodal">
-Controls where and how fast the large scaled version of the normal map moves in the X and Y direction.
- </notification>
-
- <notification
- icon="alertmodal.tga"
- name="HelpWaterWave2"
- type="alertmodal">
-Controls where and how fast the the small scaled version of the normal map moves in the X and Y direction.
- </notification>
-
- <notification
icon="alert.tga"
name="NewSkyPreset"
type="alert">
@@ -5428,7 +4622,7 @@ Deactivated gestures with same trigger:
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 QuickTime site (http://www.apple.com/quicktime) and install the QuickTime Player.
+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"
@@ -5488,6 +4682,13 @@ The objects on the selected parcel that are NOT owned by you have been returned
<notification
icon="notify.tga"
+ name="ServerObjectMessage"
+ type="notify">
+[MSG]
+ </notification>
+
+ <notification
+ icon="notify.tga"
name="NotSafe"
type="notify">
This land has damage enabled.
@@ -5583,14 +4784,6 @@ Your account cannot connect to this teen grid region.
<notification
icon="notify.tga"
- name="NoHelpIslandTP"
- type="notify">
-You cannot teleport back to Help Island.
-Go to &apos;Help Island Public&apos; to repeat the tutorial.
- </notification>
-
- <notification
- icon="notify.tga"
name="ImproperPaymentStatus"
type="notify">
You do not have proper payment status to enter this region.
@@ -5753,11 +4946,11 @@ An object named [OBJECTFROMNAME] owned by [FIRST] [LAST] has given you a [OBJECT
<button
index="0"
name="Keep"
- text="Keep"/>
+ text="OK"/>
<button
index="1"
name="Discard"
- text="Discard"/>
+ text="Cancel"/>
<button
index="2"
name="Mute"
@@ -5774,11 +4967,11 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<button
index="0"
name="Keep"
- text="Keep"/>
+ text="OK"/>
<button
index="1"
name="Discard"
- text="Discard"/>
+ text="Cancel"/>
<button
index="2"
name="Mute"
@@ -5789,21 +4982,17 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<notification
icon="notify.tga"
name="UserGiveItem"
- type="notify">
+ type="offer">
[NAME] has given you a [OBJECTTYPE] named &apos;[OBJECTNAME]&apos;.
<form name="form">
<button
index="0"
name="Keep"
- text="Keep"/>
+ text="Accept"/>
<button
index="1"
name="Discard"
- text="Discard"/>
- <button
- index="2"
- name="Mute"
- text="Block"/>
+ text="No, thanks"/>
</form>
</notification>
@@ -5839,7 +5028,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<notification
icon="notify.tga"
name="TeleportOffered"
- type="notify">
+ type="offer">
[NAME] has offered to teleport you to their location:
[MESSAGE]
@@ -5876,7 +5065,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<notification
icon="notify.tga"
name="OfferFriendship"
- type="notify">
+ type="offer">
[NAME] is offering friendship.
[MESSAGE]
@@ -5916,7 +5105,7 @@ An object named [OBJECTFROMNAME] owned by (an unknown Resident) has given you a
<notification
icon="notify.tga"
name="FriendshipAccepted"
- type="notify">
+ type="offer">
[NAME] accepted your friendship offer.
</notification>
@@ -6105,6 +5294,16 @@ Your L$ balance is shown in the upper-right.
<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.
@@ -6198,8 +5397,8 @@ This object is flexible. Flexis must be phantom and not physical.
You opened the Advanced menu.
To toggle this menu,
- Windows: Ctrl-Alt-D
- Mac: &#8984;-Opt-D
+ Windows: Ctrl+Alt+D
+ Mac: &#8997;&#8984;D
</notification>
@@ -6470,7 +5669,7 @@ An error has occurred while trying to connect to voice chat for [VOICE_CHANNEL_N
name="ServerVersionChanged"
priority="high"
type="notifytip">
-You just entered a region using a different server version, which may affect performance. Click to see the release notes.
+You just entered a region using a different server version, which may affect performance. [[URL] View the release notes.]
</notification>
<notification
@@ -6487,20 +5686,6 @@ The SLurl you clicked on is not supported.
<button index="0" name="respondbutton" text="Respond"/>
</form>
</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="notifytip.tga"
name="AttachmentSaved" type="notifytip">
@@ -6569,12 +5754,11 @@ Yes
<global name="PermNo">
No
</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 -->
+<!-- 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.
+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>
+ </global>
+</notifications>
diff --git a/indra/newview/skins/default/xui/en/panel_activeim_row.xml b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
index 4dc4a9ff46..8b815b0f71 100644
--- a/indra/newview/skins/default/xui/en/panel_activeim_row.xml
+++ b/indra/newview/skins/default/xui/en/panel_activeim_row.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel
+<panel
name="panel_activeim_row"
layout="topleft"
follows="left|right"
@@ -7,56 +7,51 @@
left="0"
height="35"
width="318"
- background_visible="true"
- bevel_style="in"
- bg_alpha_color="0 0 0 0">
+ background_visible="false">
<chiclet_im_p2p
name="p2p_chiclet"
layout="topleft"
follows="left"
- top="5"
+ top="3"
left="5"
height="25"
- width="45">
+ width="25">
</chiclet_im_p2p>
<chiclet_im_group
name="group_chiclet"
layout="topleft"
follows="left"
- top="5"
+ top="3"
left="5"
height="25"
- width="45">
+ width="25">
</chiclet_im_group>
<text
type="string"
name="contact_name"
layout="topleft"
- top="8"
- left_pad="6"
- height="28"
- width="235"
+ top="10"
+ left_pad="0"
+ height="14"
+ width="245"
length="1"
follows="right|left"
- font="SansSerifBold"
- text_color="White">
- Contact Name
+ use_ellipses="true"
+ font="SansSerifBold">
+ Grumpity ProductEngine
</text>
<button
- top="5"
- left_pad="5"
- width="15"
- height="15"
+ 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_hide_btn.tga"
- image_disabled="toast_hide_btn.tga"
- image_selected="toast_hide_btn.tga"
- image_hover_selected="toast_hide_btn.tga"
- image_disabled_selected="toast_hide_btn.tga"
+ 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..0246e21d25
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_adhoc_control_panel.xml
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="false"
+ height="215"
+ name="panel_im_control_panel"
+ width="180">
+
+ <avatar_list
+ color="DkGray2"
+ follows="left|top|right|bottom"
+ height="130"
+ ignore_online_status="true"
+ layout="topleft"
+ left="3"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="false"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ top="10"
+ width="180"/>
+
+ <panel
+ background_visible="true"
+ bg_alpha_color="0.2 0.2 0.2 1"
+ border="false"
+ bottom="1"
+ follows="left|bottom"
+ height="70"
+ left="0"
+ left_pad="0"
+ name="panel_call_buttons"
+ top_pad="0"
+ width="180">
+
+ <button
+ bottom="10"
+ height="20"
+ label="Call"
+ left_delta="28"
+ name="call_btn"
+ width="125"/>
+
+ <button
+ bottom="40"
+ height="20"
+ label="Leave Call"
+ name="end_call_btn"
+ visible="false"
+ width="125"/>
+
+ <button
+ enabled="false"
+ bottom="10"
+ height="20"
+ label="Open Voice Controls"
+ name="voice_ctrls_btn"
+ visible="false"
+ width="125"/>
+
+ </panel>
+
+</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
index c3ae2d953a..0c42686531 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_list_item.xml
@@ -8,7 +8,7 @@
top="0"
width="320">
<icon
- follows="top|right|left"
+ follows="top|right|left"
height="24"
image_name="ListItem_Over"
layout="topleft"
@@ -38,51 +38,54 @@
width="20" />
<text
follows="left|right"
- font="SansSerifSmallBold"
- height="20"
+ font="SansSerifSmall"
+ height="15"
layout="topleft"
left_pad="5"
name="avatar_name"
- text_color="white"
- top="4"
- use_ellipses="true"
+ top="6"
+ use_ellipses="true"
value="Unknown"
- width="180" />
+ width="182" />
<text
follows="right"
- font="SansSerif"
- height="20"
+ font="SansSerifSmall"
+ height="15"
layout="topleft"
- left_pad="10"
- name="avatar_status"
- text_color="0.5 0.5 0.5 1"
- value="Away"
- width="50" />
+ left_pad="8"
+ name="last_interaction"
+ text_color="LtGray_50"
+ value="0s"
+ width="24" />
<output_monitor
auto_update="true"
follows="right"
draw_border="false"
height="16"
layout="topleft"
- left_pad="3"
+ left_pad="0"
mouse_opaque="true"
name="speaking_indicator"
- top="4"
visible="true"
width="20" />
<button
follows="right"
- font="SansSerifBigBold"
- height="18"
- image_disabled="Info"
- image_disabled_selected="Info"
- image_hover_selected="Info"
- image_selected="Info"
- image_unselected="Info"
- layout="topleft"
- left_pad="2"
+ height="16"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ right="-31"
name="info_btn"
- picture_style="true"
- top="2"
- width="18" />
+ top_delta="-2"
+ width="16" />
+ <button
+ follows="right"
+ height="20"
+ image_overlay="ForwardArrow_Off"
+ layout="topleft"
+ left_pad="5"
+ right="-3"
+ name="profile_btn"
+ top_delta="-2"
+ 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
index e4f6e7bd44..16c8660781 100644
--- a/indra/newview/skins/default/xui/en/panel_avatar_tag.xml
+++ b/indra/newview/skins/default/xui/en/panel_avatar_tag.xml
@@ -55,7 +55,6 @@
top="65"
left="10"
right="-10"
- can_resize="true"
height="100"
follows="left|top|bottom|right"
font="SansSerifSmall"
diff --git a/indra/newview/skins/default/xui/en/panel_bars.xml b/indra/newview/skins/default/xui/en/panel_bars.xml
index 9c06329eaf..527ec4e007 100644
--- a/indra/newview/skins/default/xui/en/panel_bars.xml
+++ b/indra/newview/skins/default/xui/en/panel_bars.xml
@@ -5,65 +5,14 @@
layout="topleft"
left="0"
mouse_opaque="false"
- name="bottom_panel"
+ name="screen"
width="1024">
- <panel
- follows="left|right|top|bottom"
- height="728"
- layout="topleft"
- left="0"
- mouse_opaque="false"
- name="status"
- top="0"
- width="1024" />
- <layout_stack
- border_size="0"
- follows="left|right|bottom|top"
- height="768"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="bar_stack"
- top_delta="0"
- use_bounding_rect="true"
- width="1024">
- <layout_panel
- follows="left|right|top|bottom"
- height="768"
- layout="topleft"
- left="0"
- mouse_opaque="false"
- name="spacer"
- top="0"
- user_resize="false"
- width="1024" />
- <layout_panel
- auto_resize="false"
- height="200"
- layout="topleft"
- min_height="200"
- mouse_opaque="false"
- name="overlay"
- use_bounding_rect="true"
- user_resize="false"
- width="1024" />
- <layout_panel
- auto_resize="false"
- filename="panel_toolbar.xml"
- layout="topleft"
- min_height="28"
- name="toolbar"
- use_bounding_rect="true"
- user_resize="false"
- 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="65" 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>
- <panel
- follows="left|right|top|bottom"
- height="728"
- layout="topleft"
- left_delta="0"
- mouse_opaque="false"
- name="hud"
- top_delta="-10"
- width="1024" />
+ </layout_stack>
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_bottomtray.xml b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
index b4847368b2..f833e0a1cb 100644
--- a/indra/newview/skins/default/xui/en/panel_bottomtray.xml
+++ b/indra/newview/skins/default/xui/en/panel_bottomtray.xml
@@ -2,21 +2,22 @@
<panel
mouse_opaque="true"
background_visible="true"
- bg_alpha_color="0.25 0.25 0.25 1"
- bg_opaque_color="0.25 0.25 0.25 1"
+ bg_alpha_color="DkGray"
+ bg_opaque_color="DkGray"
follows="left|bottom|right"
- height="28"
+ height="33"
layout="topleft"
left="0"
name="bottom_tray"
top="28"
- border_visible="true"
+ chrome="true"
+ border_visible="false"
width="1000">
<layout_stack
- mouse_opaque="false"
+ mouse_opaque="false"
border_size="0"
- clip="false"
- follows="left|right|bottom|top"
+ clip="false"
+ follows="all"
height="28"
layout="topleft"
left="0"
@@ -26,28 +27,83 @@
width="1000">
<icon
auto_resize="false"
- color="0 0 0 0"
follows="left|right"
height="10"
image_name="spacer24.tga"
layout="topleft"
left="0"
top="0"
- width="5"/>
+ width="4" />
<layout_panel
- mouse_opaque="false"
- auto_resize="true"
+ mouse_opaque="false"
+ auto_resize="false"
follows="left|right"
height="28"
layout="topleft"
- left="5"
- min_height="28"
- width="450"
+ left="0"
+ min_height="23"
+ width="310"
top="0"
- min_width="305"
+ min_width="300"
name="chat_bar"
user_resize="false"
- filename="panel_nearby_chat_bar.xml"/>
+ 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="96"
+ name="speak_panel"
+ user_resize="false">
+ <talk_button
+ follows="right"
+ height="23"
+ speak_button.tab_stop="true"
+ show_button.tab_stop="true"
+ layout="topleft"
+ left="0"
+ name="talk"
+ top="3"
+ width="100" />
+ </layout_panel>
+ <icon
+ auto_resize="false"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ name="DUMMY"
+ top="0"
+ width="4"/>
+ <layout_panel
+ mouse_opaque="false"
+ auto_resize="false"
+ follows="right"
+ height="28"
+ layout="topleft"
+ min_height="28"
+ width="80"
+ top_delta="0"
+ min_width="76"
+ name="gesture_panel"
+ user_resize="false">
+ <button
+ follows="right"
+ height="23"
+ label="Gesture"
+ layout="topleft"
+ name="Gesture"
+ left="0"
+ top="3"
+ use_ellipses="true"
+ width="80" />
+ </layout_panel>
<icon
auto_resize="false"
color="0 0 0 0"
@@ -58,30 +114,28 @@
left="0"
name="DUMMY"
top="0"
- width="3"/>
+ width="4"/>
<layout_panel
- mouse_opaque="false"
+ mouse_opaque="false"
auto_resize="false"
follows="right"
height="28"
layout="topleft"
- left="5"
min_height="28"
- width="70"
- top_delta="-10"
- min_width="70"
name="movement_panel"
- user_resize="false">
+ width="80"
+ min_width="76">
<button
- follows="right"
- height="20"
+ follows="left|right"
+ height="23"
+ use_ellipses="true"
is_toggle="true"
label="Move"
layout="topleft"
name="movement_btn"
- tool_tip="Shows/Hide Movement controls"
- top="6"
- width="70">
+ tool_tip="Show/hide movement controls"
+ top="3"
+ width="80">
<button.init_callback
function="Button.SetDockableFloaterToggle"
parameter="moveview" />
@@ -97,105 +151,89 @@
left="0"
name="DUMMY"
top="0"
- width="8"/>
+ width="4"/>
<layout_panel
- mouse_opaque="false"
+ mouse_opaque="false"
auto_resize="false"
- follows="right"
+ follows="left|right"
height="28"
layout="topleft"
min_height="28"
- min_width="100"
+ min_width="76"
name="cam_panel"
top_delta="-10"
width="100">
<button
- follows="right"
- height="20"
+ follows="left|right"
+ height="23"
+ use_ellipses="true"
is_toggle="true"
label="View"
layout="topleft"
left="0"
- tool_tip="Shows/Hide Camera controls"
- top="6"
+ tool_tip="Show/hide camera controls"
+ top="3"
name="camera_btn"
- width="70">
+ width="80">
<button.init_callback
function="Button.SetDockableFloaterToggle"
parameter="camera" />
</button>
- <button
- follows="right"
- name="camera_presets_btn"
- top="6"
- height="20"
- width="20"
- left_pad="0"
- is_toggle="true"
- picture_style="true"
- image_selected="toggle_button_selected"
- image_unselected="toggle_button_off">
- <button.init_callback
- function="Button.SetDockableFloaterToggle"
- parameter="camera_presets"
- />
- </button>
</layout_panel>
+ <icon
+ auto_resize="false"
+ color="0 0 0 0"
+ follows="left|right"
+ height="10"
+ image_name="spacer24.tga"
+ layout="topleft"
+ left="0"
+ name="DUMMY"
+ top="0"
+ width="4"/>
<layout_panel
- mouse_opaque="false"
+ mouse_opaque="false"
auto_resize="false"
- follows="right"
+ follows="left|right"
height="28"
layout="topleft"
- min_height="28"
- min_width="35"
name="snapshot_panel"
- top_delta="-10"
- width="35">
- <split_button
- arrow_position="right"
- follows="right"
- height="18"
+ width="40">
+ <button
+ follows="left|right"
+ height="23"
left="0"
- layout="topleft"
+ label=""
+ layout="topleft"
name="snapshots"
- top="6"
- width="35">
- <split_button.arrow_button
- image_selected="camera_presets/camera_presets_arrow_right.png"
- image_unselected="camera_presets/camera_presets_arrow_right.png"
- image_disabled_selected="camera_presets/camera_presets_arrow_right.png"
- image_disabled="camera_presets/camera_presets_arrow_right.png"
- name="snapshot_settings"
- tool_tip="Snapshot Settings" />
- <split_button.item
- image_selected="camera_presets/camera_presets_snapshot.png"
- image_unselected="camera_presets/camera_presets_snapshot.png"
- name="snapshot"
- tool_tip="Take Snapshot" />
- </split_button>
+ width="36"
+ top="3"
+ image_overlay="Snapshot_Off"
+ tool_tip="Take snapshot"
+ />
</layout_panel>
<layout_panel
mouse_opaque="false"
follows="left|right"
height="28"
layout="topleft"
- min_height="28"
top="0"
name="chiclet_list_panel"
- width="150"
- user_resize="false">
+ width="189"
+ min_width="189"
+ user_resize="false"
+ auto_resize="true">
<chiclet_panel
- mouse_opaque="false"
+ mouse_opaque="false"
follows="left|right"
- height="25"
+ height="28"
layout="topleft"
left="0"
name="chiclet_list"
- top="1"
+ top="0"
chiclet_padding="3"
scrolling_offset="40"
- width="150" />
+ width="189" />
</layout_panel>
<icon
auto_resize="false"
@@ -207,36 +245,6 @@
left="0"
top="0"
width="5"/>
- <icon
- auto_resize="false"
- color="0 0 0 0"
- follows="left|right"
- height="10"
- image_name="spacer24.tga"
- layout="topleft"
- left="0"
- top="0"
- width="10"/>
- <view_border
- auto_resize="false"
- bevel_style="in"
- follows="left|right"
- height="28"
- layout="topleft"
- left="270"
- name="well_separator"
- top="0"
- width="1" />
- <icon
- auto_resize="false"
- color="0 0 0 0"
- follows="left|right"
- height="10"
- image_name="spacer24.tga"
- layout="topleft"
- left="0"
- top="0"
- width="10"/>
<layout_panel
auto_resize="false"
follows="right"
@@ -245,41 +253,43 @@
min_height="28"
top="0"
name="sys_well_panel"
- width="48"
- min_width="48"
+ width="34"
+ min_width="34"
user_resize="false">
<chiclet_notification
follows="right"
- height="25"
+ height="23"
layout="topleft"
left="0"
name="sys_well"
- top="2"
- width="48">
+ top="4"
+ width="34">
<button
- image_selected="bottom_tray_sys_notifications_selected.tga"
- image_unselected="bottom_tray_sys_notifications.tga"/>
- <unread_notifications
+ auto_resize="true"
+ halign="right"
+ height="23"
+ follows="right"
+ flash_color="EmphasisColor"
+ name="Unread"
+ image_overlay="Notices_Unread"
width="20"
- height="20"
+ />
+ <unread_notifications
+ width="34"
+ height="23"
left="22"
- top="23"/>
-<!--
- <chiclet_notification.commit_callback
- function="Notification.Show"
- parameter="ClickUnimplemented" />
- -->
- </chiclet_notification>
+ top="23" />
+ </chiclet_notification>
</layout_panel>
- <icon
+ <icon
auto_resize="false"
color="0 0 0 0"
follows="left|right"
height="10"
image_name="spacer24.tga"
layout="topleft"
- left="0"
+ right="-1"
top="0"
- width="5"/>
+ width="26"/>
</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..64519b2571
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_chat_header.xml
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ background_visible="true"
+ bevel_style="in"
+ bg_alpha_color="black"
+ follows="left|top|right"
+ height="20"
+ label="im_header"
+ layout="topleft"
+ name="im_header" >
+ <avatar_icon
+ follows="left"
+ height="16"
+ image_name="icon_avatar_online.tga"
+ layout="topleft"
+ left="2"
+ mouse_opaque="true"
+ name="avatar_icon"
+ top="2"
+ width="16" />
+ <text
+ follows="left|right"
+ font="SansSerifBigBold"
+ height="20"
+ layout="topleft"
+ left_pad="6"
+ right="-50"
+ name="user_name"
+ text_color="white"
+ top="3"
+ value="Darth Vader"
+ use_ellipses="true" />
+ <text
+ follows="right"
+ font="SansSerifBig"
+ height="20"
+ layout="topleft"
+ name="time_box"
+ right="0"
+ text_color="white"
+ top="3"
+ value="23:30"
+ width="50" />
+</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
index 78f53562cd..05b04bbf8e 100644
--- a/indra/newview/skins/default/xui/en/panel_chat_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_chat_item.xml
@@ -5,10 +5,10 @@
name="instant_message"
width="300"
height="180"
- background_opaque="false"
- background_visible="true"
+ background_opaque="true"
+ background_visible="false"
follows="left|top|right|bottom"
- bg_alpha_color="0.3 0.3 0.3 1.0">
+ bg_alpha_color="0.3 0.3 0.3 0">
<panel width="250" height="30" background_visible="true" background_opaque="false" bg_alpha_color="0.0 0.0 0.0 1.0" name="msg_caption">
<avatar_icon
top="25" left="10" width="20" height="20" follows="left|top"
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..d0a2ddb289
--- /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="1"
+ 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
index fde795260e..18d12aef70 100644
--- a/indra/newview/skins/default/xui/en/panel_classified.xml
+++ b/indra/newview/skins/default/xui/en/panel_classified.xml
@@ -40,7 +40,7 @@
layout="topleft"
left_delta="0"
name="given_name_editor"
- tool_tip="Name must begin with a letter or number, not punctuation."
+ tool_tip="Name must begin with a letter or number, not punctuation"
top_delta="288"
width="400" />
<text_editor
@@ -61,7 +61,7 @@
layout="topleft"
left="20"
name="location_editor"
- tool_tip="Set the location for this classified to your current position."
+ tool_tip="Set the location for this classified to your current position"
width="400" />
<button
follows="left|top"
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_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..f9ef038314
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_gloves.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..f4c03399fe
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_jacket.xml
@@ -0,0 +1,77 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..ab105afd88
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_pants.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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
index 453e1319a6..f4a212ba0a 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_pick.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_pick.xml
@@ -2,73 +2,78 @@
<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"
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="SansSerifHugeBold"
+ font="SansSerifHuge"
height="15"
layout="topleft"
- left="10"
+ left_pad="10"
name="title"
text_color="white"
top="5"
width="250">
Edit Pick
</text>
- <button
- follows="top|right"
- height="20"
- image_overlay="BackArrow_Off"
- layout="topleft"
- name="back_btn"
- picture_style="true"
- right="-20"
- top="7"
- width="20" />
<scroll_container
color="DkGray2"
- follows="left|top|right|bottom"
- height="470"
+ follows="all"
+ height="510"
layout="topleft"
left="10"
top_pad="10"
name="profile_scroll"
- reserve_scroll_corner="true"
+ reserve_scroll_corner="false"
opaque="true"
width="313">
<panel
name="scroll_content_panel"
- follows="left|top|right"
+ follows="left|top"
+ min_height="300"
layout="topleft"
top="0"
+ background_visible="false"
+ height="470"
left="0"
- width="298"
- height="555">
+ width="295">
<texture_picker
follows="left|top|right"
height="197"
- width="280"
+ width="290"
layout="topleft"
top="20"
left="10"
name="pick_snapshot" />
- <icon
- height="16"
- image_name="image_edit_icon.tga"
- layout="topleft"
- name="edit_icon"
- left="245"
- top="35"
- visible="true"
- width="16" />
+ <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"
@@ -80,8 +85,9 @@
left="10"
top="215"
name="Name:"
- text_color="white">
- Name:
+ text_color="white"
+ width="290">
+ Title:
</text>
<line_editor
follows="left|top|right"
@@ -93,7 +99,7 @@
max_length="63"
name="pick_name"
text_color="black"
- width="280" />
+ width="290" />
<text
type="string"
length="1"
@@ -105,13 +111,14 @@
left="10"
top_pad="20"
name="description_label"
- text_color="white">
+ text_color="white"
+ width="290">
Description:
</text>
<text_editor
follows="left|top|right"
height="100"
- width="280"
+ width="290"
hide_scrollbar="false"
layout="topleft"
left="10"
@@ -131,7 +138,8 @@
left="10"
name="location_label"
text_color="white"
- top_pad="20">
+ top_pad="20"
+ width="290">
Location:
</text>
<text
@@ -144,8 +152,7 @@
name="pick_location"
right="-10"
top_pad="2"
- text_color="white"
- width="280"
+ width="290"
word_wrap="true">
loading...
</text>
@@ -154,22 +161,24 @@
height="20"
label="Set to Current Location"
layout="topleft"
- left="10"
+ left="8"
+ top_pad="0"
name="set_to_curr_location_btn"
width="200" />
</panel>
</scroll_container>
<panel
follows="left|right|bottom"
- height="30"
+ height="20"
label="bottom_panel"
layout="topleft"
left="10"
name="bottom_panel"
- top_pad="2">
+ top_pad="5"
+ width="303">
<button
follows="bottom|left"
- height="25"
+ height="19"
label="Save [WHAT]"
layout="topleft"
name="save_changes_btn"
@@ -178,12 +187,12 @@
width="130" />
<button
follows="bottom|left"
- height="25"
+ height="19"
label="Cancel"
layout="topleft"
name="cancel_btn"
left_pad="5"
- top_delta="0"
+ 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
index b13058f40a..2378ae518b 100644
--- a/indra/newview/skins/default/xui/en/panel_edit_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_edit_profile.xml
@@ -1,20 +1,19 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- class="edit_profile_panel"
background_visible="true"
- bevel_style="in"
- follows="left|top|right|bottom"
- height="420"
+ class="edit_profile_panel"
+ follows="all"
+ height="535"
label="Profile Edit"
layout="topleft"
- left="10"
- mouse_opaque="true"
+ left="0"
name="edit_profile_panel"
- top="10"
- width="255">
+ top="0"
+ width="313">
<string
name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
</string>
<string
name="AcctTypeResident"
@@ -50,190 +49,153 @@
<string
name="no_partner_text"
value="None" />
- <scroll_container
+ <scroll_container
color="DkGray2"
- follows="left|top|right|bottom"
- height="300"
+ follows="all"
+ height="505"
+ min_height="300"
layout="topleft"
left="0"
name="profile_scroll"
reserve_scroll_corner="true"
opaque="true"
- width="255">
+ 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="scroll_content_panel"
+ name="data_panel"
follows="left|top|right"
- layout="topleft"
- top="0"
- left="0"
- width="240"
- height="760">
- <panel
- background_visible="true"
- bg_alpha_color="DkGray2"
- follows="left|top|right|bottom"
- height="750"
- layout="topleft"
- left="0"
- name="data_panel"
- top_pad="10"
- width="260">
+ layout="topleft"
+ top="0"
+ height="505"
+ min_height="300"
+ left="0"
+ width="313">
<panel
- follows="left|top"
- height="120"
- layout="topleft"
- left="10"
name="lifes_images_panel"
- top_pad="10"
- width="265">
- <panel
- height="137"
- layout="topleft"
- left="0"
- name="second_life_image_panel"
- top="0"
- width="125">
- <text
- type="string"
- length="1"
- follows="left|top|right|bottom"
- font="SansSerifSmall"
- font.style="BOLD"
- height="15"
- layout="topleft"
- left="0"
- name="second_life_photo_title_text"
- text_color="white"
- top="0"
- width="240">
- [SECOND_LIFE]:
- </text>
- <texture_picker
- allow_no_texture="true"
- default_image_name="None"
- follows="top|left"
- height="117"
- layout="topleft"
- left="0"
- name="2nd_life_pic"
- top_pad="5"
- width="102" />
+ 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="16"
- image_name="image_edit_icon.tga"
+ <icon
+ height="18"
+ image_name="AddItem_Off"
layout="topleft"
- left="75"
name="2nd_life_edit_icon"
- tool_tip="Click to select an image"
- top="35"
- width="16" />
+ 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="125"
+ height="100"
layout="topleft"
left="120"
- top="30"
+ top="18"
+ max_length="512"
name="sl_description_edit"
- width="115"
+ width="173"
word_wrap="true">
</text_editor>
<panel
- height="137"
- layout="topleft"
- left="10"
- name="first_life_image_panel"
- top_pad="20"
- width="125">
- <text
- type="string"
- length="1"
- follows="left|top|right|bottom"
- font="SansSerifSmall"
- font.style="BOLD"
- height="15"
- layout="topleft"
- left="0"
- name="real_world_photo_title_text"
- text_color="white"
- top="0"
- width="125">
- Real World:
- </text>
- <texture_picker
- allow_no_texture="true"
- default_image_name="None"
- follows="top|left"
- height="117"
- layout="topleft"
- left="0"
- name="real_world_pic"
- top_pad="5"
- width="102" />
+ 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="16"
- image_name="image_edit_icon.tga"
+ <icon
+ height="18"
+ image_name="AddItem_Off"
layout="topleft"
- left="85"
name="real_world_edit_icon"
- tool_tip="Click to select an image"
- top="210"
- width="16" />
+ 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="125"
+ height="100"
layout="topleft"
left="120"
- top="195"
+ max_length="512"
+ top="142"
name="fl_description_edit"
- width="115"
+ width="173"
word_wrap="true">
</text_editor>
<text
- type="string"
- follows="left|top"
- font="SansSerifSmall"
- font.style="BOLD"
- height="15"
- layout="topleft"
- left="10"
- name="online_me_status_text"
- text_color="white"
- top_pad="20"
- width="255">
- Status:
- </text>
- <combo_box
- font="SansSerifSmall"
- follows="left|top"
- height="18"
- layout="topleft"
- left="10"
- top_pad="5"
- name="status_combo"
- width="140">
- <combo_box.item
- label="Online"
- name="online"
- value="online" />
- <combo_box.item
- label="Away"
- name="away"
- value="away" />
- <combo_box.item
- label="Busy"
- name="busy"
- value="busy" />
- </combo_box>
- <text
type="string"
length="1"
follows="left|top"
@@ -244,8 +206,8 @@
left="10"
name="title_homepage_text"
text_color="white"
- top_pad="20"
- width="240">
+ top_pad="10"
+ width="285">
Homepage:
</text>
<line_editor
@@ -253,54 +215,54 @@
font="SansSerifSmall"
height="20"
layout="topleft"
- left="9"
+ left="10"
+ top_pad="0"
+ value="http://"
name="homepage_edit"
- width="220">
- TODO
+ width="285">
</line_editor>
<check_box
follows="left|top"
font="SansSerifSmall"
- label="Show me in Search results"
+ label="Show me in Search results"
layout="topleft"
left="10"
name="show_in_search_checkbox"
- height="16"
+ height="15"
text_enabled_color="white"
- top_pad="20"
- width="240"/>
+ top_pad="10"
+ width="240" />
<text
follows="left|top"
font="SansSerifSmall"
- font.style="BOLD"
+ font.style="BOLD"
height="15"
layout="topleft"
left="10"
name="title_acc_status_text"
text_color="white"
- top_pad="15"
- value="Account Status:"
- width="100" />
+ top_pad="5"
+ value="My Account:"
+ width="285" />
<text
type="string"
follows="left|top"
font="SansSerifSmall"
height="15"
layout="topleft"
- left_pad="10"
+ left="10"
name="my_account_link"
- top_delta="0"
- value="Go to Dashboard"
- width="100"/>
+ value="Go to My Dashboard"
+ width="285" />
<text
follows="left|top|right"
- height="15"
+ height="20"
layout="topleft"
left="10"
name="acc_status_text"
top_pad="5"
value="Resident. No payment info on file."
- width="255"
+ width="285"
word_wrap="true" />
<text
follows="left|top"
@@ -311,26 +273,26 @@
left="10"
name="title_partner_text"
text_color="white"
- top_pad="15"
- value="Partner:"
- width="100" />
+ 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"
- top_delta="0"
value="[[URL] Edit]"
- width="100" />
+ width="150" />
<panel
follows="left|top|right"
height="15"
layout="topleft"
left="10"
name="partner_data_panel"
- top_pad="10"
- width="255">
+ width="285">
<text
follows="left|top|right"
height="30"
@@ -339,94 +301,22 @@
name="partner_text"
top="0"
value="[FIRST] [LAST]"
- width="240"
+ width="285"
word_wrap="true" />
</panel>
- <text
- type="string"
- length="1"
- follows="left|top"
- font="SansSerifSmall"
- font.style="BOLD"
- height="15"
- layout="topleft"
- left="10"
- name="title_afk_text"
- text_color="white"
- top_pad="15"
- width="240">
- Away Timeout:
- </text>
- <spinner
- control_name="AFKTimeout"
- decimal_digits="0"
- follows="left|top"
- height="16"
- increment="1"
- initial_value="300"
- label=""
- label_width="0"
- layout="topleft"
- left="10"
- max_val="600"
- min_val="30"
- name="afk_timeout_spinner"
- top_pad="5"
- width="50" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="10"
- name="seconds_textbox"
- top_delta="0"
- width="128">
- seconds
- </text>
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- font="SansSerifSmall"
- font.style="BOLD"
- left="12"
- mouse_opaque="false"
- name="text_box3"
- top_pad="25"
- width="240">
- Busy Mode Response:
- </text>
- <text_editor
- control_name="BusyModeResponse2"
- commit_on_focus_lost = "true"
- follows="left|top"
- height="70"
- layout="topleft"
- left="12"
- name="busy_response"
- top_pad="10"
- width="240"
- word_wrap="true">
- log_in_to_change
- </text_editor>
</panel>
</panel>
</scroll_container>
- <panel
+ <panel
follows="bottom|left"
- height="30"
+ height="20"
left="10"
name="profile_me_buttons_panel"
- top_pad="10"
- width="240">
+ top_pad="5"
+ width="303">
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
label="Save Changes"
layout="topleft"
left="0"
@@ -435,16 +325,12 @@
width="130" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
label="Cancel"
layout="topleft"
- left_pad="5"
+ left_pad="10"
name="cancel_btn"
- top_delta="0"
+ 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..9a13dfa3c4
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_shirt.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..154b9d959c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_shoes.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..d0f4d75444
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_skirt.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..acc6d482a7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_socks.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..4f5c1c08b7
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_underpants.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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..715674e88b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_edit_undershirt.xml
@@ -0,0 +1,65 @@
+<?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
+ border_color="0.45098 0.517647 0.607843 1"
+ 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_group_control_panel.xml b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
index a9363df259..763dd7b922 100644
--- a/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_control_panel.xml
@@ -1,31 +1,71 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="panel_im_control_panel"
- width="96"
- height="215"
- border="false">
- <avatar_list
- width="90"
- column_padding="0"
- draw_heading="true"
- draw_stripes="false"
- follows="left|top|bottom|right"
- layout="topleft"
- left="3"
- name="speakers_list"
- search_column="1"
- sort_column="2"
- top="10"
- height="150" />
-
- <button name="group_info_btn"
- label="Group Info"
- left_delta="3"
- width="90"
- height="20" />
-
- <button name="call_btn"
- label="Call"
- width="90"
- height="20" />
+<panel
+ border="false"
+ height="238"
+ name="panel_im_control_panel"
+ width="180">
+
+ <avatar_list
+ color="DkGray2"
+ follows="left|top|right|bottom"
+ height="130"
+ ignore_online_status="true"
+ layout="topleft"
+ left="3"
+ name="speakers_list"
+ opaque="false"
+ show_info_btn="false"
+ show_profile_btn="false"
+ show_speaking_indicator="false"
+ top="10"
+ width="180"/>
+
+ <button
+ bottom_pad="0"
+ height="20"
+ label="Group Info"
+ left_delta="28"
+ name="group_info_btn"
+ width="125"/>
+
+ <panel
+ background_visible="true"
+ bg_alpha_color="0.2 0.2 0.2 1"
+ border="false"
+ bottom="1"
+ follows="left|bottom"
+ height="70"
+ left="0"
+ left_pad="0"
+ name="panel_call_buttons"
+ top_pad="0"
+ width="180">
+
+ <button
+ bottom="10"
+ height="20"
+ label="Call Group"
+ left_delta="28"
+ name="call_btn"
+ width="125"/>
+
+ <button
+ bottom="40"
+ height="20"
+ label="Leave Call"
+ name="end_call_btn"
+ visible="false"
+ width="125"/>
+
+ <button
+ enabled="false"
+ bottom="10"
+ height="20"
+ label="Open Voice Controls"
+ name="voice_ctrls_btn"
+ visible="false"
+ width="125"/>
+
+ </panel>
</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
index 9a4480127d..4f24c7a745 100644
--- a/indra/newview/skins/default/xui/en/panel_group_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_general.xml
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- border="true"
follows="all"
- height="445"
+ height="380"
label="General"
class="panel_group_general"
layout="topleft"
- left="1"
+ left="0"
+ top="0"
name="general_tab"
- top="500"
- width="280">
+ width="303">
<panel.string
name="help_text">
The General tab contains general information about this group, a list of members, general Group Preferences and member options.
@@ -18,65 +17,38 @@ Hover your mouse over the options for more help.
</panel.string>
<panel.string
name="group_info_unchanged">
- General group information has changed.
+ General group information has changed
</panel.string>
<panel.string
name="incomplete_member_data_str">
Retrieving member data
</panel.string>
- <panel.string
- name="group_join_btn">
- Join (L$[AMOUNT])
- </panel.string>
- <!--<button
- follows="left|top"
- height="16"
- label="?"
- label_selected="?"
- layout="topleft"
- left="255"
- name="help_button"
- top="8"
- width="20" /> -->
<text_editor
type="string"
follows="left|top"
left="5"
- height="75"
+ height="60"
layout="topleft"
max_length="511"
name="charter"
top="5"
- width="260"
+ width="303"
word_wrap="true">
- Group Charter
+ Group Charter
</text_editor>
- <text
- follows="left|top"
- type="string"
- font="SansSerifBig"
- tool_tip="Owners are shown in bold."
- height="16"
- layout="topleft"
- left="5"
- name="text_owners_and_visible_members"
- top_pad="10"
- width="270">
- Members
- </text>
<name_list
column_padding="0"
draw_heading="true"
follows="left|top"
- heading_height="14"
- height="80"
+ heading_height="16"
+ height="130"
layout="topleft"
left_delta="0"
name="visible_members"
top_pad="0"
- width="263">
+ width="303">
<name_list.columns
- label="Member Name"
+ label="Member"
name="name"
relative_width="0.6" />
<name_list.columns
@@ -84,26 +56,16 @@ Hover your mouse over the options for more help.
name="title"
relative_width="0.4" />
</name_list>
- <text
- follows="left|top"
- height="16"
- type="string"
- top_pad="10"
- font="SansSerifBig"
- layout="topleft"
- name="text_group_preferences">
- Group Preferences
- </text>
<text
follows="left|top"
type="string"
- height="16"
+ height="14"
layout="topleft"
left_delta="0"
name="active_title_label"
- top_pad="8"
- width="240">
- My Active Title
+ top_pad="5"
+ width="303">
+ My Title
</text>
<combo_box
follows="left|top"
@@ -112,58 +74,58 @@ Hover your mouse over the options for more help.
left_delta="0"
name="active_title"
tool_tip="Sets the title that appears in your avatar&apos;s name tag when this group is active."
- top_pad="0"
- width="240" />
+ top_pad="2"
+ width="303" />
<check_box
height="16"
font="SansSerifSmall"
label="Receive notices"
layout="topleft"
- left_delta="0"
+ 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="240" />
+ width="303" />
<check_box
height="16"
label="Show in my profile"
layout="topleft"
- left_delta="0"
+ left="5"
name="list_groups_in_profile"
- tool_tip="Sets whether you want to show this group in your Profile"
+ tool_tip="Sets whether you want to show this group in your profile"
top_pad="5"
- width="240" />
+ width="303" />
<panel
background_visible="true"
bevel_style="in"
border="true"
bg_alpha_color="FloaterUnfocusBorderColor"
follows="left|top"
- height="125"
+ height="93"
layout="topleft"
- left_delta="0"
+ left="5"
name="preferences_container"
- top_pad="10"
- width="263">
+ top_pad="5"
+ width="303">
<check_box
follows="right|top"
height="16"
label="Open enrollment"
layout="topleft"
- left_delta="0"
+ 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:"
+ 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."
+ tool_tip="Sets whether to require an enrollment fee to join the group"
top_pad="5"
- width="90" />
+ width="300" />
<spinner
decimal_digits="0"
follows="left|top"
@@ -173,43 +135,38 @@ Hover your mouse over the options for more help.
label_width="20"
label="L$"
layout="topleft"
- left="25"
+ right="-10"
max_val="99999"
- top_pad="5"
+ left_pad="2"
name="spin_enrollment_fee"
tool_tip="New members must pay this fee to join the group when Enrollment Fee is checked."
- top_delta="-2"
- width="75" />
+ width="105" />
<check_box
height="16"
initial_value="true"
label="Show in search"
layout="topleft"
- left="4"
+ left="10"
name="show_in_group_list"
- tool_tip="Let people see this group in search results."
+ tool_tip="Let people see this group in search results"
top_pad="4"
- width="90" />
+ width="300" />
<combo_box
height="20"
layout="topleft"
left_delta="0"
name="group_mature_check"
- tool_tip="Sets whether your group information is considered mature."
- top_pad="10"
- width="240">
- <combo_box.item
- label="- Select Mature -"
- name="select_mature"
- value="Select" />
- <combo_box.item
- label="Mature Content"
- name="mature"
- value="Mature" />
+ tool_tip="Sets whether your group information is considered mature"
+ top_pad="5"
+ width="190">
<combo_box.item
label="PG Content"
name="pg"
value="Not Mature" />
- </combo_box>
+ <combo_box.item
+ label="Mature Content"
+ name="mature"
+ value="Mature" />
+ </combo_box>
</panel>
-</panel> \ No newline at end of file
+</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
index fb4ce436e8..de1323d9cb 100644
--- a/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_info_sidetray.xml
@@ -1,66 +1,71 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-
<panel
- follows="left|top|right|bottom"
- height="660"
- label="Group Info"
- layout="topleft"
- name="panel_group_info"
- border="false"
- width="300">
+background_visible="true"
+ follows="all"
+ height="570"
+ label="Group Info"
+ layout="topleft"
+ min_height="425"
+ left="0"
+ top="20"
+ name="GroupInfo"
+ width="333">
<panel.string
name="default_needs_apply_text">
- There are unapplied changes on the current tab.
+ There are unsaved changes to the current tab
</panel.string>
<panel.string
name="want_apply_text">
- Do you want to apply these changes?
+ 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
- layout="topleft"
- name="back"
- right="-9"
- top="0"
- width="25"
- height="25"
- label=""
follows="top|right"
+ height="23"
image_overlay="BackArrow_Off"
- tab_stop="false" />
- <text
layout="topleft"
- top="0"
+ name="back"
left="10"
- width="250"
- height="20"
+ 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"
- follows="top|left|right"
- mouse_opaque="true"
+ top="0"
+ value="(Loading...)"
use_ellipses="true"
- name="group_name">(Loading...)</text>
+ width="300" />
<line_editor
follows="left|top"
font="SansSerif"
label="Type your new group name here"
layout="topleft"
- left_delta="0"
+ left_delta="10"
max_length="35"
name="group_name_editor"
top_delta="5"
width="250"
height="20"
- visible="true" />
+ visible="false" />
<texture_picker
follows="left|top"
height="113"
label=""
layout="topleft"
- left="10"
+ left="20"
name="insignia"
tool_tip="Click to choose a picture"
top_pad="5"
@@ -75,7 +80,7 @@
name="prepend_founded_by"
top_delta="0"
width="140">
- Founded by:
+ Founder:
</text>
<name_box
follows="left|top"
@@ -84,70 +89,185 @@
layout="topleft"
left_delta="0"
name="founder_name"
- top_pad="10"
+ top_pad="2"
use_ellipses="true"
width="140" />
- <button
+ <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"
- height="20"
- label="Join"
- label_selected="Join"
- name="btn_join"
visible="true"
- width="65" />
- <button
- top="632"
- height="20"
- font="SansSerifSmall"
- label="Save"
- label_selected="Save"
- name="btn_apply"
- left="5"
- width="65" />
+ 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
+ follows="all"
+ height="425"
+ layout="topleft"
+ left="0"
+ name="groups_accordion"
+ top_pad="15"
+ width="336">
+ <accordion_tab
+ expanded="true"
+ layout="topleft"
+ name="group_general_tab"
+ title="General">
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ height="323"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="general_scroll"
+ reserve_scroll_corner="false"
+ width="333">
+ <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"
+ width="303" />
+ </scroll_container>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_roles_tab"
+ title="Roles">
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ height="323"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="roles_scroll"
+ reserve_scroll_corner="false"
+ width="333">
+ <panel
+ border="false"
+ class="panel_group_roles"
+ filename="panel_group_roles.xml"
+ layout="topleft"
+ left="0"
+ help_topic="group_roles_tab"
+ name="group_roles_tab_panel"
+ top="0"
+ width="303" />
+ </scroll_container>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_notices_tab"
+ title="Notices">
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ height="323"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="notices_scroll"
+ reserve_scroll_corner="false"
+ width="333">
+ <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"
+ width="303" />
+ </scroll_container>
+ </accordion_tab>
+ <accordion_tab
+ expanded="false"
+ layout="topleft"
+ name="group_land_tab"
+ title="Land/Assets">
+ <scroll_container
+ color="DkGray2"
+ opaque="true"
+ height="323"
+ follows="all"
+ layout="topleft"
+ left="0"
+ top="0"
+ name="land_scroll"
+ reserve_scroll_corner="false"
+ width="333">
+ <panel
+ border="false"
+ class="panel_group_land_money"
+ filename="panel_group_land_money.xml"
+ layout="topleft"
+ left="0"
+ help_topic="group_land_money_tab"
+ name="group_land_tab_panel"
+ top="0"
+ width="313" />
+ </scroll_container>
+ </accordion_tab>
+ </accordion>
+ <button
follows="top|left"
- height="20"
+ height="22"
image_overlay="Refresh_Off"
layout="topleft"
+ left="5"
name="btn_refresh"
- picture_style="true"
- top="632"
- left="75"
- width="20" />
- <button
- top="632"
+ top_pad="-15"
+ width="23" />
+ <button
height="20"
label="Create"
- label_selected="Create"
+ label_selected="New group"
name="btn_create"
- left="5"
+ left_pad="10"
visible="false"
- width="65" />
- <button
- top="632"
- left="75"
+ width="100" />
+ <!-- <button
+ left_pad="10"
height="20"
label="Cancel"
label_selected="Cancel"
name="btn_cancel"
visible="false"
+ width="65" />-->
+ <button
+ height="20"
+ font="SansSerifSmall"
+ label="Save"
+ label_selected="Save"
+ name="btn_apply"
+ left_pad="10"
+ right="-10"
width="65" />
- <accordion layout="topleft" left="2" width="296" top="135" height="500" follows="all" name="group_accordion">
- <accordion_tab min_height="445" title="Group General" name="group_general_tab">
- <panel class="panel_group_general" filename="panel_group_general.xml" name="group_general_tab_panel"/>
- </accordion_tab>
- <accordion_tab min_height="380" title="Group Roles" name="group_roles_tab" expanded="False" can_resize="false">
- <panel class="panel_group_roles" filename="panel_group_roles.xml" name="group_roles_tab_panel"/>
- </accordion_tab>
- <accordion_tab min_height="530" title="Group Notices" name="group_notices_tab" expanded="False" can_resize="false">
- <panel class="panel_group_notices" filename="panel_group_notices.xml" name="group_notices_tab_panel"/>
- </accordion_tab>
- <accordion_tab min_height="270" title="Group Land Money" name="group_land_tab" expanded="False" can_resize="false">
- <panel class="panel_group_land_money" filename="panel_group_land_money.xml" name="group_land_tab_panel"/>
- </accordion_tab>
- </accordion>
-
-
</panel> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/panel_group_invite.xml b/indra/newview/skins/default/xui/en/panel_group_invite.xml
index 68b30faa1c..1996977acb 100644
--- a/indra/newview/skins/default/xui/en/panel_group_invite.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_invite.xml
@@ -49,7 +49,7 @@ Resident Chooser&apos; to start.
left_delta="0"
multi_select="true"
name="invitee_list"
- tool_tip="Hold the Ctrl key and click resident names to multi-select."
+ tool_tip="Hold the Ctrl key and click resident names to multi-select"
top_pad="4"
width="200" />
<button
@@ -59,7 +59,7 @@ Resident Chooser&apos; to start.
layout="topleft"
left_delta="0"
name="remove_button"
- tool_tip="Removes residents selected above from the invite list."
+ tool_tip="Removes residents selected above from the invite list"
top_pad="4"
width="200" />
<text
@@ -78,7 +78,7 @@ Resident Chooser&apos; to start.
layout="topleft"
left_delta="0"
name="role_name"
- tool_tip="Choose from the list of Roles you are allowed to assign members to."
+ tool_tip="Choose from the list of Roles you are allowed to assign members to"
top_delta="16"
width="196" />
<button
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
index 999aa814b1..0c6f81f8fd 100644
--- a/indra/newview/skins/default/xui/en/panel_group_land_money.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_land_money.xml
@@ -1,25 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- border="true"
+ border="false"
follows="all"
- height="410"
+ height="510"
label="Land &amp; L$"
layout="topleft"
left="1"
name="land_money_tab"
- top="490"
- width="280">
+ top="0"
+ width="313">
<panel.string
name="help_text">
- Parcels owned by the group are listed along with contribution details. A warning appears until the Total Land in Use is less than or equal to the Total Contribution. The Planning, Details, and Sales tabs provide information about the group&apos;s finances.
+ Parcels owned by a group are listed along with contribution details. 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 do not have permission to view group owned land.
+ You don&apos;t have permission to view group owned land
</panel.string>
<panel.string
name="cant_view_group_accounting_text">
- You do not have permission to view the group&apos;s accounting information.
+ You don&apos;t have permission to view the group&apos;s accounting information.
</panel.string>
<panel.string
name="loading_txt">
@@ -27,19 +27,8 @@
</panel.string>
<panel.string
name="land_contrib_error">
- Unable to set your land contribution.
+ Unable to set your land contribution
</panel.string>
- <!--
- <button
- follows="left|top"
- height="16"
- label="?"
- layout="topleft"
- left="250"
- name="help_button"
- top="8"
- width="20" />
- -->
<!-- <text
type="string"
follows="left|top"
@@ -55,29 +44,29 @@
<scroll_list
draw_heading="true"
follows="top"
- heading_height="14"
- height="100"
+ heading_height="20"
+ height="150"
layout="topleft"
- left="5"
+ left="0"
name="group_parcel_list"
- top_pad="10"
- width="265">
+ top_pad="0"
+ width="313">
<scroll_list.columns
label="Parcel"
name="name"
- width="67" />
+ width="78" />
<scroll_list.columns
label="Region"
name="location"
- width="72" />
+ width="78" />
<scroll_list.columns
label="Type"
name="type"
- width="60" />
+ width="70" />
<scroll_list.columns
label="Area"
name="area"
- width="20" />
+ width="50" />
<scroll_list.columns
label=""
name="hidden"
@@ -85,14 +74,14 @@
</scroll_list>
<button
follows="top"
- height="20"
+ height="23"
label="Map"
label_selected="Map"
layout="topleft"
- left="150"
name="map_button"
- top_pad="10"
- width="125"
+ right="-10"
+ top_pad="5"
+ width="95"
enabled="false" />
<text
type="string"
@@ -102,11 +91,12 @@
layout="topleft"
left="5"
name="total_contributed_land_label"
- top_pad="10"
+ top_pad="0"
width="130">
Total Contribution:
</text>
<text
+ text_color="EmphasisColor"
type="string"
follows="left|top"
height="16"
@@ -130,6 +120,7 @@
Total Land In Use:
</text>
<text
+ text_color="EmphasisColor"
type="string"
follows="left|top"
height="16"
@@ -153,6 +144,7 @@
Land Available:
</text>
<text
+ text_color="EmphasisColor"
type="string"
follows="left|top"
height="16"
@@ -179,22 +171,22 @@
border_style="line"
border_thickness="1"
follows="left|top"
- height="16"
+ height="19"
layout="topleft"
left_pad="5"
max_length="10"
name="your_contribution_line_editor"
- top_delta="-2"
+ top_delta="0"
width="95" />
<text
type="string"
follows="left|top"
height="16"
layout="topleft"
- left_pad="5"
+ left_pad="3"
name="your_contribution_units"
top_delta="2">
- ( m² )
+ m²
</text>
<text
type="string"
@@ -204,13 +196,13 @@
layout="topleft"
left="140"
name="your_contribution_max_value"
- top_pad="0"
+ top_pad="2"
width="95">
([AMOUNT] max)
</text>
<icon
height="16"
- image_name="smicon_warn.tga"
+ image_name="notify_next"
layout="topleft"
left="9"
name="group_over_limit_icon"
@@ -222,15 +214,15 @@
type="string"
word_wrap="true"
font="SansSerifSmall"
- height="40"
+ height="35"
layout="topleft"
- left_pad="5"
+ left_pad="0"
name="group_over_limit_text"
- text_color="GroupOverTierColor"
+ text_color="EmphasisColor"
top_delta="0"
- width="250">
- Group members must contribute more land credits to support land in use.
- </text>
+ width="290">
+ Group members must contribute more land credits to support land in use
+ </text>
<text
type="string"
follows="left|top"
@@ -239,133 +231,136 @@
layout="topleft"
left="10"
name="group_money_heading"
+ text_color="EmphasisColor"
top_pad="0"
width="150">
Group L$
</text>
<tab_container
follows="all"
- height="100"
+ height="200"
+ halign="center"
layout="topleft"
left="10"
name="group_money_tab_container"
tab_position="top"
- top_pad="10"
- width="265">
+ tab_height="20"
+ top_pad="2"
+ tab_min_width="70"
+ width="300">
<panel
- border="true"
- follows="left|top|right|bottom"
+ border="false"
+ follows="all"
height="180"
- label="Planning"
+ label="PLANNING"
layout="topleft"
- left="1"
+ left="0"
+ help_topic="group_money_planning_tab"
name="group_money_planning_tab"
top="5"
- width="265">
+ width="300">
<text_editor
type="string"
- bg_readonly_color="0.784314 0.819608 0.8 1"
follows="all"
- font="Monospace"
- height="172"
+ font="SansSerif"
+ height="140"
layout="topleft"
- left="8"
+ left="0"
max_length="4096"
name="group_money_planning_text"
- top="5"
- width="250">
- Computing...
+ top="0"
+ width="300"
+ word_wrap="true">
+ Loading...
</text_editor>
</panel>
<panel
- border="true"
- follows="left|top|right|bottom"
+ border="false"
+ follows="all"
height="180"
- label="Details"
+ label="DETAILS"
layout="topleft"
- left_delta="0"
+ left="0"
+ help_topic="group_money_details_tab"
name="group_money_details_tab"
- top_delta="0"
- width="265">
+ top="5"
+ width="300">
<text_editor
type="string"
- bg_readonly_color="0.784314 0.819608 0.8 1"
follows="all"
- font="Monospace"
height="140"
layout="topleft"
- left="8"
+ left="0"
max_length="4096"
name="group_money_details_text"
- top="7"
- width="250">
- Computing...
- </text_editor>
- <button
- height="20"
- label="&lt; Earlier"
- label_selected="&lt; Earlier"
- layout="topleft"
- left="5"
- name="earlier_details_button"
- tool_tip="Go back in time"
- top_pad="10"
- width="125" />
+ top="0"
+ width="300"
+ word_wrap="true">
+ Loading...
+ </text_editor>
<button
- height="20"
- label="Later &gt;"
- label_selected="Later &gt;"
- layout="topleft"
- left_pad="5"
- name="later_details_button"
- tool_tip="Go forward in time"
- top_delta="0"
- width="125" />
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Left_Off"
+ layout="topleft"
+ name="earlier_details_button"
+ tool_tip="Back"
+ top_pad="3"
+ right="-35"
+ width="31" />
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Right_Off"
+ layout="topleft"
+ left_pad="10"
+ name="later_details_button"
+ tool_tip="Next"
+ width="31" />
</panel>
<panel
- border="true"
- follows="left|top|right|bottom"
+ border="false"
+ follows="all"
height="180"
- label="Sales"
+ label="SALES"
layout="topleft"
left_delta="0"
+ help_topic="group_money_sales_tab"
name="group_money_sales_tab"
top_delta="-1"
- width="265">
+ width="300">
<text_editor
type="string"
- bg_readonly_color="0.784314 0.819608 0.8 1"
follows="all"
- font="Monospace"
height="140"
layout="topleft"
- left="8"
+ left="0"
max_length="4096"
name="group_money_sales_text"
- top="7"
- width="250">
- Computing...
+ top="0"
+ width="300"
+ word_wrap="true">
+ Loading...
</text_editor>
- <button
- height="20"
- label="&lt; Earlier"
- label_selected="&lt; Earlier"
- layout="topleft"
- left="5"
- name="earlier_sales_button"
- tool_tip="Go back in time"
- top_pad="10"
- width="125" />
- <button
- height="20"
- label="Later &gt;"
- label_selected="Later &gt;"
- layout="topleft"
- left_pad="5"
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Left_Off"
+ layout="topleft"
+ name="earlier_sales_button"
+ tool_tip="Back"
+ top_pad="3"
+ right="-35"
+ width="31" />
+ <button
+ follows="left|top"
+ height="23"
+ image_overlay="Arrow_Right_Off"
+ layout="topleft"
+ left_pad="10"
name="later_sales_button"
- tool_tip="Go forward in time"
- top_delta="0"
- width="125" />
+ tool_tip="Next"
+ width="31" />
</panel>
</tab_container>
-</panel>
+</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
index 3f49bfad36..5f6b911620 100644
--- a/indra/newview/skins/default/xui/en/panel_group_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_list_item.xml
@@ -8,7 +8,7 @@
top="0"
width="320">
<icon
- follows="top|right|left"
+ follows="top|right|left"
height="24"
image_name="ListItem_Over"
layout="topleft"
@@ -28,39 +28,43 @@
visible="false"
width="320" />
<icon
- follows="top|left"
- height="18"
- image_name="icon_group.tga"
- layout="topleft"
- left="5"
+ height="20"
+ image_name="Generic_Group"
+ name="group_icon"
mouse_opaque="true"
- name="group_icon"
- top="4"
- width="18" />
- <text
+ left="5"
+ top="2"
+ width="20" />
+ <text
follows="left|right"
font="SansSerifSmall"
- height="17"
+ height="15"
layout="topleft"
left_pad="5"
name="group_name"
- text_color="white"
- top="7"
- use_ellipses="true"
+ top="6"
+ use_ellipses="true"
value="Unknown"
- width="263" />
+ width="242" />
<button
follows="right"
- height="18"
- image_disabled="Info"
- image_disabled_selected="Info"
- image_hover_selected="Info"
- image_selected="Info"
- image_unselected="Info"
- layout="topleft"
+ height="16"
+ image_pressed="Info_Press"
+ image_unselected="Info_Over"
+ left_pad="3"
+ right="-31"
name="info_btn"
- picture_style="true"
- right="-5"
- top="4"
- width="18" />
+ 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"
+ 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
index 82a3c98dd9..24a4005a45 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notices.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notices.xml
@@ -1,14 +1,13 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- border="true"
follows="all"
height="485"
label="Notices"
layout="topleft"
- left="1"
+ left="0"
name="notices_tab"
- top="485"
- width="280">
+ top="0"
+ width="313">
<panel.string
name="help_text">
Notices are a quick way to communicate across a
@@ -20,69 +19,48 @@ the General tab.
</panel.string>
<panel.string
name="no_notices_text">
- There are no past notices.
+ There are no past notices
</panel.string>
- <!-- <button
- follows="left|top"
- height="16"
- label="?"
- label_selected="?"
- layout="topleft"
- left="250"
- name="help_button"
- top="8"
- width="20" /> -->
- <!--<text
- follows="left|top"
- type="string"
- font="SansSerifBig"
- height="16"
- layout="topleft"
- left="10"
- name="lbl"
- top_pad="10"
- width="269">
- Group Notices Archive
- </text> -->
<text
follows="left|top"
type="string"
word_wrap="true"
- height="40"
+ height="30"
layout="topleft"
- left_delta="10"
+ left="10"
name="lbl2"
- top_pad="10"
- width="270">
- Notices are kept for 14 days. Notice lists are limited to 200 notices per group on a daily basis.
+ top="5"
+ width="300">
+ Notices are kept for 14 days
+Groups are limited to 200 notices/group daily
</text>
<scroll_list
follows="left|top"
column_padding="0"
draw_heading="true"
- heading_height="14"
- height="109"
+ heading_height="16"
+ height="125"
layout="topleft"
- left_delta="0"
+ left="0"
name="notice_list"
top_pad="0"
- width="265">
+ width="303">
<scroll_list.columns
label=""
name="icon"
- width="16" />
+ width="20" />
<scroll_list.columns
label="Subject"
name="subject"
- width="100" />
+ width="125" />
<scroll_list.columns
label="From"
name="from"
- width="83" />
+ width="90" />
<scroll_list.columns
label="Date"
name="date"
- width="50" />
+ width="30" />
<scroll_list.columns
name="sort"
width="-1" />
@@ -93,39 +71,40 @@ the General tab.
layout="topleft"
name="notice_list_none_found"
visible="false">
- None found.
+ None found
</text>
- <button
- follows="left|top"
- height="20"
- font="SansSerifSmall"
- label="New Notice"
- label_selected="Create New Notice"
+ <button
+ follows="bottom|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ label="Create a new notice"
+ left="15"
+ name="create_new_notice"
+ tool_tip="Create a new notice"
+ top_delta="-5"
+ width="18" />
+ <button
+ follows="top|left"
+ height="22"
+ image_overlay="Refresh_Off"
layout="topleft"
- left_delta="0"
- name="create_new_notice"
- top_delta="4"
- width="125" />
- <button
- follows="left|top"
- height="20"
- font="SansSerifSmall"
- label="Refresh"
- label_selected="Refresh List"
- layout="topleft"
- left_pad="12"
name="refresh_notices"
- top_delta="0"
- width="125" />
+ right="-5"
+ top_delta="5"
+ width="23" />
<panel
follows="left|top"
- height="268"
+ height="300"
label="Create New Notice"
layout="topleft"
left="0"
- name="panel_create_new_notice"
top_pad="10"
- width="265">
+ visible="false"
+ name="panel_create_new_notice"
+ width="303">
<text
follows="left|top"
type="string"
@@ -135,29 +114,17 @@ the General tab.
left="10"
mouse_opaque="false"
name="lbl"
- top_pad="0"
- width="265">
+ text_color="EmphasisColor"
+ top="0"
+ width="200">
Create a Notice
</text>
<text
follows="left|top"
type="string"
- word_wrap="true"
- height="90"
- layout="topleft"
- left_delta="0"
- name="lbl2"
- top_pad="4"
- width="195">
- You can add a single item to a notice by dragging it from your inventory to this panel. Attached items must be copiable and transferrable, and you can&apos;t send a folder.
- </text>
- <text
- follows="left|top"
- type="string"
halign="left"
height="16"
layout="topleft"
- left_delta="0"
name="lbl3"
top_pad="10"
width="60">
@@ -171,8 +138,7 @@ the General tab.
left_pad="3"
max_length="63"
name="create_subject"
- top_delta="-1"
- width="200" />
+ width="220" />
<text
follows="left|top"
type="string"
@@ -181,106 +147,100 @@ the General tab.
layout="topleft"
left="10"
name="lbl4"
- top_pad="10"
+ top_pad="5"
width="60">
Message:
</text>
<text_editor
- height="75"
+ height="90"
layout="topleft"
left_pad="3"
max_length="511"
name="create_message"
top_delta="0"
- width="200"
+ width="220"
word_wrap="true" />
<text
follows="left|top"
type="string"
halign="left"
- height="16"
+ height="14"
layout="topleft"
left="10"
name="lbl5"
- top_pad="10"
- width="60">
+ width="200">
Attach:
</text>
<line_editor
enabled="false"
- height="16"
+ height="19"
layout="topleft"
- left_pad="3"
- max_length="63"
+ max_length="90"
mouse_opaque="false"
name="create_inventory_name"
- top_delta="0"
- width="200" />
+ 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 here to attach something -- >
+ </text>
<icon
- height="16"
+ height="72"
+ image_name="DropTarget"
layout="topleft"
- left_delta="0"
- name="create_inv_icon"
- top_delta="0"
- width="16" />
+ left_pad="10"
+ mouse_opaque="true"
+ name="drop_icon"
+ top_delta="-10"
+ width="72" />
<button
follows="left|top"
- height="20"
- font="SansSerifSmall"
- label="Remove Attachment"
- label_selected="Remove Attachment"
+ height="23"
+ label="Remove"
layout="topleft"
- left="10"
+ left="70"
name="remove_attachment"
- top_pad="10"
- width="135" />
+ top_delta="45"
+ width="90" />
<button
follows="left|top"
- height="20"
- font="SansSerifSmall"
+ height="23"
label="Send"
label_selected="Send Notice"
layout="topleft"
- left_delta="138"
+ right="-10"
+ top_pad="20"
name="send_notice"
- top_delta="0"
- width="125" />
- <panel
- bevel_style="in"
- border="true"
- height="71"
- layout="topleft"
- left="200"
- name="drop_target2"
- top="20"
- width="71" />
- <icon
- height="59"
- image_name="icon_groupnoticeinventory.tga"
- layout="topleft"
- left_delta="6"
- mouse_opaque="true"
- name="drop_icon"
- top="26"
- width="59" />
- <group_drop_target
+ width="100" />
+ <group_drop_target
height="466"
- layout="topleft"
+ top="0"
left="0"
+ layout="topleft"
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."
- top="-198"
- width="280" />
+ width="295" />
</panel>
<panel
follows="left|top"
- height="268"
+ height="300"
label="View Past Notice"
layout="topleft"
left="0"
+ visible="true"
name="panel_view_past_notice"
- top="197"
- width="265">
+ top="180"
+ width="303">
<text
type="string"
font="SansSerifBig"
@@ -289,6 +249,7 @@ the General tab.
left="10"
mouse_opaque="false"
name="lbl"
+ text_color="EmphasisColor"
top_pad="0"
width="265">
Archived Notice
@@ -300,9 +261,9 @@ the General tab.
layout="topleft"
left_delta="0"
name="lbl2"
- top_pad="4"
+ top_pad="2"
width="265">
- To send a new notice, click the &apos;Create New Notice&apos; button above.
+ To send a new notice, click the + button
</text>
<text
type="string"
@@ -311,7 +272,7 @@ the General tab.
layout="topleft"
left_delta="0"
name="lbl3"
- top_pad="24"
+ top_pad="15"
visible="false"
width="60">
Subject:
@@ -342,13 +303,13 @@ the General tab.
</text>
<text_editor
enabled="false"
- height="150"
+ height="205"
layout="topleft"
left="10"
max_length="511"
name="view_message"
top_delta="-35"
- width="260"
+ width="285"
word_wrap="true" />
<line_editor
enabled="false"
@@ -359,7 +320,7 @@ the General tab.
mouse_opaque="false"
name="view_inventory_name"
top_pad="10"
- width="260" />
+ width="285" />
<icon
height="16"
layout="topleft"
@@ -369,14 +330,12 @@ the General tab.
width="16" />
<button
follows="left|top"
- height="20"
- font="SansSerifSmall"
- label="Open Attachment"
- label_selected="Open Attachment"
+ height="23"
+ label="Open attachment"
layout="topleft"
- left_delta="0"
+ right="-10"
name="open_attachment"
- top_pad="10"
+ top_pad="5"
width="135" />
</panel>
-</panel> \ No newline at end of file
+</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
index f97daf922f..bd98996ae1 100644
--- a/indra/newview/skins/default/xui/en/panel_group_notify.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_notify.xml
@@ -7,13 +7,13 @@
4
</string>
<panel follows="top" background_visible="true" bevel_style="in" bg_alpha_color="black"
- height="50" label="header" layout="topleft" left="0" name="header"
+ height="30" label="header" layout="topleft" left="0" name="header"
top="0" width="350">
- <icon follows="left|top|right|bottom" height="40" width="40" layout="topleft"
+ <icon follows="left|top|right|bottom" height="20" width="20" layout="topleft"
top="5" left="5" mouse_opaque="true" name="group_icon"/>
<text type="string" length="1" follows="left|top|right|bottom"
- font="SansSerifBigBold" height="20" layout="topleft" left="60" name="title"
- text_color="GroupNotifyTextColor" top="20" width="275" use_ellipses="true">
+ font="SansSerifBigBold" height="20" layout="topleft" left_pad="10" name="title"
+ text_color="GroupNotifyTextColor" top="5" width="275" use_ellipses="true">
Sender Name / Group Name
</text>
</panel>
@@ -65,7 +65,7 @@
follows="left|bottom|right" height="15" width="15"
layout="topleft" bottom="122" left="25" mouse_opaque="true" name="attachment_icon" visible="true"
/>
- <text font="SansSerif" font.style="UNDERLINE" font_shadow="hard"
+ <text font="SansSerif" font.style="UNDERLINE" font_shadow="none"
type="string" length="1" follows="left|bottom|right" layout="topleft"
left="45" bottom="122" height="15" width="280" name="attachment"
text_color="GroupNotifyTextColor" visible="true">
diff --git a/indra/newview/skins/default/xui/en/panel_group_roles.xml b/indra/newview/skins/default/xui/en/panel_group_roles.xml
index 6435951157..5ed464bcec 100644
--- a/indra/newview/skins/default/xui/en/panel_group_roles.xml
+++ b/indra/newview/skins/default/xui/en/panel_group_roles.xml
@@ -1,184 +1,47 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- border="true"
- height="490"
+ border="false"
+ height="552"
label="Members &amp; Roles"
layout="topleft"
- left="1"
+ left="0"
+ top="0"
name="roles_tab"
- top="490"
- width="280">
+ width="313">
<panel.string
name="default_needs_apply_text">
- There are unapplied changes on the current sub-tab.
+ There are unsaved changes to the current tab
</panel.string>
<panel.string
name="want_apply_text">
- Do you want to apply these changes?
+ Do you want to save these changes?
</panel.string>
<panel.string
name="help_text" />
- <!--
- <button
- follows="left|top"
- height="16"
- label="?"
- layout="topleft"
- left="250"
- name="help_button"
- top="8"
- width="20" />
- -->
- <!--<panel
- follows="left|top"
- height="80"
- layout="topleft"
- left="10"
- name="members_header"
- top_pad="10"
- width="270">
- <text
- type="string"
- font="SansSerifBig"
- height="16"
- layout="topleft"
- left="0"
- name="static"
- top="0"
- width="270">
- Members &amp; Roles
- </text>
- <text
- type="string"
- word_wrap="true"
- height="40"
- layout="topleft"
- left_delta="0"
- name="static2"
- top_pad="4"
- width="270">
- Group Members are assigned Roles with Abilities. These settings can easily be customized, allowing for greater organization and flexibility.
- </text>
- </panel>
- <panel
- follows="left|top"
- height="24"
- layout="topleft"
- left_delta="0"
- name="roles_header"
- top_delta="0"
- visible="false"
- width="270">
- <text
- type="string"
- font="SansSerifBig"
- height="16"
- layout="topleft"
- left="0"
- name="static"
- top="0"
- width="270">
- Roles
- </text>
- <text
- type="string"
- word_wrap="true"
- height="40"
- layout="topleft"
- left_delta="0"
- name="role_properties_modifiable"
- top_pad="4"
- visible="false"
- width="270">
- Select a Role below. You can modify its Name, Description and Member Title.
- </text>
- <text
- type="string"
- word_wrap="true"
- height="40"
- layout="topleft"
- left_delta="0"
- name="role_properties_not_modifiable"
- top_delta="0"
- width="270">
- Select a Role below to see its properties, Members and allowed Abilities.
- </text>
- <text
- type="string"
- word_wrap="true"
- height="16"
- layout="topleft"
- left_delta="0"
- name="role_actions_modifiable"
- top_delta="24"
- visible="false"
- width="270">
- You can also assign Abilities to the Role.
- </text>
- <text
- type="string"
- word_wrap="true"
- height="16"
- layout="topleft"
- left_delta="0"
- name="role_actions_not_modifiable"
- top_delta="0"
- width="270">
- You may view, but not modify, assigned Abilities.
- </text>
- </panel>
- <panel
- follows="left|top"
- height="24"
- layout="topleft"
- left_delta="0"
- name="actions_header"
- top_delta="0"
- visible="false"
- width="270">
- <text
- type="string"
- font="SansSerifBig"
- height="16"
- layout="topleft"
- left="0"
- name="static"
- top="0"
- width="270">
- Abilities
- </text>
- <text
- type="string"
- word_wrap="true"
- height="40"
- layout="topleft"
- left_delta="0"
- name="static2"
- top_pad="4"
- width="270">
- You can view an Ability&apos;s Description and which Roles and Members can execute the Ability.
- </text>
- </panel> -->
<tab_container
+ border="false"
follows="left|top"
- height="180"
+ height="245"
+ halign="center"
layout="topleft"
left="5"
name="roles_tab_container"
tab_position="top"
- top="10"
- width="265">
+ tab_height="20"
+ tab_min_width="96"
+ top="3"
+ width="303">
<panel
- border="true"
- height="165"
- label="Members"
+ border="false"
+ height="220"
+ label="MEMBERS"
layout="topleft"
- left="1"
+ left="0"
+ help_topic="roles_members_tab"
name="members_sub_tab"
tool_tip="Members"
- top="17"
class="panel_group_members_subtab"
- width="265">
+ width="300">
<panel.string
name="help_text">
You can add or remove Roles assigned to Members.
@@ -189,108 +52,88 @@ clicking on their names.
layout="topleft"
top="10"
left="4"
- width="255"
+ width="280"
height="20"
follows="left|top|right"
max_length="250"
label="Filter Members"
- name="filter_input"
- font="SansSerif" />
- <!--<line_editor
- border_style="line"
- border_thickness="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="4"
- max_length="63"
- name="search_text"
- top="10"
- width="90" />
- <button
- font="SansSerifSmall"
- height="20"
- label="Search"
- layout="topleft"
- left_pad="5"
- name="search_button"
- top_delta="-2"
- width="80" />
- <button
+ name="filter_input" />
+ <!-- <button
enabled="false"
font="SansSerifSmall"
height="20"
label="Show All"
layout="topleft"
- left_pad="0"
+ left_pad="-90"
name="show_all_button"
- top_delta="0"
- width="80" /> -->
+ top_delta="-6"
+ width="80" />-->
<name_list
column_padding="0"
draw_heading="true"
- heading_height="14"
- height="100"
+ heading_height="20"
+ height="160"
follows="left|top"
layout="topleft"
- left="4"
+ left="0"
multi_select="true"
name="member_list"
- top_pad="6"
- width="255">
+ top_pad="2"
+ width="300">
<name_list.columns
label="Member"
name="name"
- width="90" />
+ relative_width="0.45" />
<name_list.columns
label="Donations"
name="donated"
- width="95" />
+ relative_width="0.3" />
<name_list.columns
label="Online"
name="online"
- width="80" />
+ relative_width="0.2" />
</name_list>
<button
height="20"
font="SansSerifSmall"
label="Invite"
layout="topleft"
- left_delta="0"
+ left="5"
name="member_invite"
- top_pad="6"
- width="125" />
+ top_pad="3"
+ width="100" />
<button
height="20"
font="SansSerifSmall"
label="Eject"
layout="topleft"
left_pad="5"
+ right="-5"
name="member_eject"
- top_delta="0"
- width="125" />
+ width="100" />
+ <!--What is this?-->
<icon
height="16"
- image_name="inv_folder_plain_closed.tga"
+ image_name="Inv_FolderClosed"
layout="topleft"
name="power_folder_icon"
visible="false"
width="16" />
</panel>
<panel
- border="true"
- height="164"
- label="Roles"
+ border="false"
+ height="220"
+ label="ROLES"
layout="topleft"
- left_delta="0"
+ left="0"
+ help_topic="roles_roles_tab"
name="roles_sub_tab"
class="panel_group_roles_subtab"
- top="17"
- width="265">
+ width="300">
<panel.string
name="help_text">
Roles have a title and an allowed list of Abilities
-that Members can perform. Members can belong to
+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>
@@ -300,7 +143,7 @@ including the Everyone and Owner Roles.
</panel.string>
<panel.string
name="power_folder_icon">
- inv_folder_plain_closed.tga
+ Inv_FolderClosed
</panel.string>
<panel.string
name="power_all_have_icon">
@@ -310,40 +153,19 @@ including the Everyone and Owner Roles.
name="power_partial_icon">
checkbox_enabled_false.tga
</panel.string>
- <filter_editor
- layout="topleft"
- top="10"
- left="4"
- width="255"
- height="20"
- follows="left|top|right"
- max_length="250"
- label="Filter Roles"
- name="filter_input"
- font="SansSerif" />
- <!--<line_editor
- border_style="line"
- border_thickness="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="4"
- max_length="63"
- name="search_text"
- top="10"
- width="90" />
- <button
- font="SansSerifSmall"
- height="20"
- label="Search"
- layout="topleft"
- left_pad="5"
- name="search_button"
- top_delta="-2"
- width="80" />
+ <filter_editor
+ layout="topleft"
+ top="10"
+ left="4"
+ width="280"
+ height="20"
+ follows="left|top|right"
+ max_length="250"
+ label="Filter Roles"
+ name="filter_input" />
+ <!--
<button
enabled="false"
- font="SansSerifSmall"
height="20"
label="Show All"
layout="topleft"
@@ -354,14 +176,16 @@ including the Everyone and Owner Roles.
<scroll_list
column_padding="0"
draw_heading="true"
+ draw_stripes="false"
follows="left|top"
- heading_height="14"
- height="100"
+ heading_height="20"
+ height="150"
layout="topleft"
- left="4"
+ search_column="1"
+ left="0"
name="role_list"
top_pad="4"
- width="255">
+ width="300">
<scroll_list.columns
label="Role"
name="name"
@@ -380,7 +204,7 @@ including the Everyone and Owner Roles.
font="SansSerifSmall"
label="Add Role"
layout="topleft"
- left_delta="0"
+ left="5"
name="role_create"
top_pad="6"
width="125" />
@@ -390,57 +214,38 @@ including the Everyone and Owner Roles.
label="Delete Role"
layout="topleft"
left_pad="5"
+ right="-5"
name="role_delete"
top_delta="0"
width="125" />
</panel>
<panel
- border="true"
- height="164"
- label="Abilities"
+ border="false"
+ height="220"
+ label="ABILITIES"
layout="topleft"
- left_delta="0"
+ left="0"
+ help_topic="roles_actions_tab"
name="actions_sub_tab"
class="panel_group_actions_subtab"
- top="17"
tool_tip="You can view an Ability&apos;s Description and which Roles and Members can execute the Ability."
- width="265">
+ width="300">
<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>
- <filter_editor
- layout="topleft"
- top="10"
- left="4"
- width="255"
- height="20"
- follows="left|top|right"
- max_length="250"
- label="Filter Abilities"
- name="filter_input"
- font="SansSerif" />
- <!--<line_editor
- border_style="line"
- border_thickness="1"
- follows="left|top"
- height="16"
- layout="topleft"
- left="4"
- max_length="63"
- name="search_text"
- top="10"
- width="90" />
- <button
- font="SansSerifSmall"
- height="20"
- label="Search"
- layout="topleft"
- left_pad="5"
- name="search_button"
- top_delta="-2"
- width="80" />
+ <filter_editor
+ layout="topleft"
+ top="10"
+ left="4"
+ width="280"
+ height="20"
+ follows="left|top|right"
+ max_length="250"
+ label="Filter Abilities"
+ name="filter_input" />
+ <!--
<button
enabled="false"
font="SansSerifSmall"
@@ -455,19 +260,19 @@ things in this group. There&apos;s a broad variety of Abilities.
column_padding="0"
draw_stripes="false"
follows="left|top"
- height="100"
+ height="160"
layout="topleft"
- left="6"
+ left="0"
multi_select="true"
name="action_list"
search_column="1"
- tool_tip="Select an Ability to view more details."
+ tool_tip="Select an Ability to view more details"
top_pad="6"
- width="255">
+ width="300">
<scroll_list.columns
label=""
name="icon"
- width="18" />
+ width="16" />
<scroll_list.columns
label=""
name="action"
@@ -475,7 +280,7 @@ things in this group. There&apos;s a broad variety of Abilities.
</scroll_list>
<icon
height="16"
- image_name="inv_folder_plain_closed.tga"
+ image_name="Inv_FolderClosed"
layout="topleft"
name="power_folder_icon"
visible="false"
@@ -483,105 +288,93 @@ things in this group. There&apos;s a broad variety of Abilities.
</panel>
</tab_container>
<panel
- height="170"
+ height="252"
layout="topleft"
follows="left|top"
left="10"
name="members_footer"
top_pad="10"
- width="265">
+ top_delta="0"
+ width="300">
<text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
follows="left|top"
left="0"
name="static"
- top_pad="0"
- width="100">
+ top_pad="5"
+ width="295">
Assigned Roles
</text>
- <text
- type="string"
- font="SansSerif"
- height="16"
- layout="topleft"
- follows="left|top"
- left_pad="35"
- name="static2"
- top_delta="0"
- width="100">
- Allowed Abilities
- </text>
<scroll_list
draw_stripes="false"
follows="left|top"
- height="150"
+ height="80"
layout="topleft"
left="0"
name="member_assigned_roles"
- top_pad="5"
- width="130">
+ top_pad="0"
+ width="295">
<scroll_list.columns
label=""
name="checkbox"
- width="18" />
+ width="30" />
<scroll_list.columns
label=""
name="role"
- width="107" />
+ width="265" />
</scroll_list>
- <scroll_list
- draw_stripes="false"
- height="150"
+ <text
+ type="string"
+ height="16"
layout="topleft"
follows="left|top"
- left_pad="5"
+ left="0"
+ name="static2"
+ top_pad="5"
+ width="295">
+ Allowed Abilities
+ </text>
+ <scroll_list
+ draw_stripes="false"
+ height="80"
+ layout="topleft"
+ left="0"
name="member_allowed_actions"
- tool_tip="For Details of each Allowed Ability see the Abilities tab."
- top_delta="0"
- width="130">
+ search_column="2"
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0"
+ width="295">
<scroll_list.columns
label=""
name="icon"
- width="14" />
+ width="20" />
<scroll_list.columns
label=""
name="action"
- width="126" />
+ width="275" />
</scroll_list>
</panel>
<panel
- height="215"
+ height="297"
layout="topleft"
- left_delta="0"
+ left="10"
name="roles_footer"
top_delta="0"
+ top="245"
visible="false"
- width="270">
+ width="300">
<text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
left="0"
name="static"
top="0"
- width="100">
+ width="140">
Name
</text>
- <text
- type="string"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_pad="35"
- name="static2"
- top_delta="0"
- width="100">
- Description
- </text>
<line_editor
type="string"
border_style="line"
@@ -590,21 +383,19 @@ things in this group. There&apos;s a broad variety of Abilities.
height="20"
layout="topleft"
left="0"
- max_length="20"
+ max_length="295"
name="role_name"
top_pad="0"
- width="130">
+ width="295">
Employees
</line_editor>
<text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
- left_delta="0"
name="static3"
- top_pad="10"
- width="100">
+ top_pad="5"
+ width="295">
Title
</text>
<line_editor
@@ -614,158 +405,159 @@ things in this group. There&apos;s a broad variety of Abilities.
follows="left|top"
height="20"
layout="topleft"
- left_delta="0"
- max_length="20"
+ max_length="295"
name="role_title"
top_pad="0"
- width="130">
- (waiting)
+ width="295">
+ (waiting)
</line_editor>
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ left="0"
+ name="static2"
+ top_pad="5"
+ width="100">
+ Description
+ </text>
<text_editor
type="string"
halign="left"
- height="48"
+ height="35"
layout="topleft"
- left="135"
- max_length="254"
+ left="0"
+ max_length="295"
name="role_description"
- top="16"
- width="130"
+ top_pad="0"
+ width="295"
word_wrap="true">
- (waiting)
+ (waiting)
</text_editor>
<text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
+ follows="left|top"
left="0"
- name="static4"
- top="85"
- width="120">
- Assigned Members
- </text>
- <text
- type="string"
- font="SansSerif"
- height="16"
- layout="topleft"
- left_pad="15"
- name="static5"
- tool_tip="A list of Abilities the currently selected role can perform."
- top_delta="0"
- width="100">
- Allowed Abilities
+ name="static"
+ top_pad="5"
+ width="295">
+ Assigned Roles
</text>
<name_list
draw_stripes="false"
- height="150"
+ height="50"
layout="topleft"
left="0"
name="role_assigned_members"
top_pad="0"
- width="130" />
+ width="295" />
<check_box
- height="16"
- label="Members are visible"
+ height="15"
+ label="Reveal members"
layout="topleft"
- left_delta="0"
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="10"
- width="130" />
+ tool_tip="Sets whether members of this role are visible in the General tab to people outside of the group."
+ top_pad="3"
+ width="290" />
+ <text
+ type="string"
+ height="16"
+ layout="topleft"
+ follows="left|top"
+ left="0"
+ name="static2"
+ top_pad="5"
+ width="295">
+ Allowed Abilities
+ </text>
<scroll_list
draw_stripes="false"
- height="150"
+ height="50"
layout="topleft"
- left="135"
+ left="0"
name="role_allowed_actions"
search_column="2"
- tool_tip="For Details of each Allowed Ability see the Abilities tab."
- top="101"
- width="130">
+ tool_tip="For details of each allowed ability see the abilities tab"
+ top_pad="0"
+ width="295">
<scroll_list.columns
label=""
name="icon"
- width="2" />
+ width="20" />
<scroll_list.columns
label=""
name="checkbox"
- width="16" />
+ width="20" />
<scroll_list.columns
label=""
name="action"
- width="220" />
+ width="250" />
</scroll_list>
</panel>
<panel
- height="215"
+ height="303"
layout="topleft"
- left_delta="0"
+ left="10"
name="actions_footer"
top_delta="0"
+ top="245"
visible="false"
- width="265">
+ width="300">
<text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
- left="0"
name="static"
- top="0"
width="200">
- Description
+ Ability description
</text>
<text_editor
type="string"
enabled="false"
halign="left"
- height="48"
+ height="80"
layout="topleft"
left_delta="0"
max_length="512"
name="action_description"
top_pad="0"
- width="265"
+ 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"
- font="SansSerif"
height="16"
layout="topleft"
left_delta="0"
name="static2"
- top_pad="10"
- width="125">
- Roles with Ability
+ top_pad="5"
+ width="295">
+ Roles with this ability
</text>
- <text
+ <scroll_list
+ height="60"
+ layout="topleft"
+ left="0"
+ name="action_roles"
+ top_pad="0"
+ width="295" />
+ <text
type="string"
- font="SansSerif"
height="16"
layout="topleft"
- left_pad="10"
name="static3"
- top_delta="0"
- width="125">
- Members with Ability
+ top_pad="5"
+ width="295">
+ Members with this ability
</text>
- <scroll_list
- height="150"
- layout="topleft"
- left="0"
- name="action_roles"
- top="90"
- width="130" />
<name_list
- height="150"
+ height="100"
layout="topleft"
- left_pad="5"
name="action_members"
- top_delta="0"
- width="130" />
+ top_pad="0"
+ width="295" />
</panel>
</panel>
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
index 7dc94d1141..c8b134cdf0 100644
--- a/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
+++ b/indra/newview/skins/default/xui/en/panel_im_control_panel.xml
@@ -1,32 +1,101 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<panel name="panel_im_control_panel"
- width="96"
- height="215"
- border="false">
-
- <avatar_icon name="avatar_icon"
- width="96"
- height="96" />
-
- <button name="view_profile_btn"
- label="View Profile"
- left_delta="3"
- width="90"
- height="20" />
-
- <button name="add_friend_btn"
- label="Add Friend"
- width="90"
- height="20" />
-
- <button name="call_btn"
- label="Call"
- width="90"
- height="20" />
-
- <button name="share_btn"
- label="Share"
- width="90"
- height="20" />
+<panel
+ border="false"
+ height="350"
+ name="panel_im_control_panel"
+ width="131">
+
+ <avatar_icon
+ follows="left|top"
+ height="125"
+ left_delta="3"
+ name="avatar_icon"
+ top="-10"
+ width="125"/>
+
+ <text
+ follows="left|right"
+ font="SansSerifBig"
+ height="16"
+ layout="topleft"
+ name="avatar_name"
+ use_ellipses="true"
+ value="Unknown"
+ width="125" />
+
+ <button
+ follows="left|bottom"
+ height="20"
+ label="View Profile"
+ name="view_profile_btn"
+ width="125"/>
+
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Add Friend"
+ name="add_friend_btn"
+ width="125"/>
+
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Teleport"
+ name="teleport_btn"
+ width="125"/>
+
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Share"
+ name="share_btn"
+ width="125"/>
+
+ <button
+ follows="left|bottom"
+ height="20"
+ label="Pay"
+ name="pay_btn"
+ width="125"/>
+
+ <panel
+ background_visible="true"
+ bg_alpha_color="0.2 0.2 0.2 1"
+ border="false"
+ bottom="1"
+ follows="left|bottom"
+ height="70"
+ left="0"
+ left_pad="0"
+ name="panel_call_buttons"
+ top_pad="0"
+ width="131">
+
+ <button
+ bottom="10"
+ height="20"
+ label="Call"
+ left_delta="3"
+ name="call_btn"
+ width="125"/>
+
+ <button
+ bottom="40"
+ height="20"
+ label="Leave Call"
+ name="end_call_btn"
+ visible="false"
+ width="125"/>
+
+ <button
+ enabled="false"
+ bottom="10"
+ height="20"
+ label="Open Voice Controls"
+ name="voice_ctrls_btn"
+ visible="false"
+ width="125"/>
+
+ </panel>
</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
index 00ede1fb2c..26d8304551 100644
--- a/indra/newview/skins/default/xui/en/panel_instant_message.xml
+++ b/indra/newview/skins/default/xui/en/panel_instant_message.xml
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
background_visible="true"
- bevel_style="in"
bg_alpha_color="0.3 0.3 0.3 0"
- height="140"
+ height="175"
label="im_panel"
layout="topleft"
left="0"
name="im_panel"
top="0"
- width="350">
+ width="305">
<string
name="message_max_lines_count">
6
@@ -19,50 +18,52 @@
bevel_style="in"
bg_alpha_color="black"
follows="top"
- height="30"
+ height="20"
label="im_header"
layout="topleft"
left="5"
name="im_header"
top="5"
- width="340">
+ width="295">
<avatar_icon
follows="right"
height="20"
image_name="icon_avatar_online.tga"
layout="topleft"
- left="5"
+ left="0"
mouse_opaque="true"
name="avatar_icon"
- top="5"
+ top="0"
width="20" />
<icon
follows="right"
height="20"
image_name="icon_top_pick.tga"
layout="topleft"
- left="5"
+ left="0"
mouse_opaque="true"
name="sys_msg_icon"
- top="5"
+ top="0"
width="20" />
<text
follows="left|right"
- font="SansSerifBigBold"
+ font="SansSerifBold"
height="20"
layout="topleft"
- left_pad="10"
+ left_pad="5"
name="user_name"
text_color="white"
top="5"
value="Darth Vader"
- width="250" />
+ width="295" />
+ <!-- TIME STAMP -->
<text
follows="right"
- font="SansSerifBig"
+ font="SansSerif"
height="20"
layout="topleft"
- left_pad="10"
+ halign="right"
+ left="245"
name="time_box"
text_color="white"
top="5"
@@ -71,25 +72,25 @@
</panel>
<text
follows="left|top|bottom|right"
- height="60"
+ height="86"
layout="topleft"
left="10"
name="message"
text_color="white"
- top="40"
+ top="33"
use_ellipses="true"
value="MESSAGE"
- width="330"
+ width="285"
word_wrap="true"
max_length="350" />
<button
follows="bottom"
- font="SansSerifBigBold"
+ font="SansSerifBold"
height="25"
- label="reply"
+ label="Reply"
layout="topleft"
- left="120"
+ left="97"
name="reply"
- top="110"
+ top="137"
width="110" />
</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..0c24adfad5
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_landmark_info.xml
@@ -0,0 +1,256 @@
+<?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>
+ <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="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="all"
+ 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" />
+ <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" />
+ <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" />
+ <line_editor
+ background_image_disabled="task_panel_background.png"
+ follows="left|top|right"
+ height="22"
+ layout="topleft"
+ left="0"
+ max_length="63"
+ name="title_editor"
+ prevalidate_callback="ascii"
+ text_readonly_color="white"
+ top_pad="5"
+ 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
index 9ee80a37d7..f05684db10 100644
--- a/indra/newview/skins/default/xui/en/panel_landmarks.xml
+++ b/indra/newview/skins/default/xui/en/panel_landmarks.xml
@@ -1,34 +1,131 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
name="Landmarks"
- bottom="0"
- height="326"
+ top="0"
+ height="400"
+ layout="topleft"
left="0"
width="380"
border="true"
background_visible="true"
bg_alpha_color="DkGray2"
follows="left|top|right|bottom">
- <inventory_panel
- allow_multi_select="true"
- border="true"
- bottom="0"
- follows="left|top|right|bottom"
- height="326"
- left="0"
- mouse_opaque="true"
- name="landmarks_list"
- width="380"/>
- <button
- bottom="0"
- halign="center"
- height="16"
- label=">"
- enabled="false"
- mouse_opaque="false"
- name="selector"
- width="20"
- left="0"
- follows="right|bottom"
- tool_tip="View landmark properties"/>
+ <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">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="favorites_list"
+ start_folder="Favorite"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_landmarks"
+ title="Landmarks">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ 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">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ bottom="0"
+ follows="left|top|right|bottom"
+ height="126"
+ left="0"
+ mouse_opaque="true"
+ name="my_inventory_list"
+ start_folder="INVENTORY"
+ width="380"/>
+ </accordion_tab>
+ <accordion_tab
+ layout="topleft"
+ name="tab_library"
+ title="Library">
+ <inventory_subtree_panel
+ allow_multi_select="true"
+ border="true"
+ 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
index aeeb884036..1646cba0a7 100644
--- a/indra/newview/skins/default/xui/en/panel_login.xml
+++ b/indra/newview/skins/default/xui/en/panel_login.xml
@@ -15,27 +15,34 @@
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
border_visible="false"
bottom="600"
follows="all"
- layout="topleft"
left="0"
name="login_html"
- right="-1"
start_url=""
- top="1" />
+ top="0"
+ height="600"
+ width="800"/>
+ <panel
+ follows="left|bottom|right"
+ name="login_widgets"
+ layout="topleft"
+ left="0"
+ top="0">
<text
- type="string"
- length="1"
follows="left|bottom"
font="SansSerif"
height="16"
- layout="topleft"
left="32"
name="first_name_text"
top="530"
@@ -46,7 +53,6 @@
follows="left|bottom"
handle_edit_keys_directly="true"
height="20"
- layout="topleft"
left_delta="0"
max_length="31"
name="first_name_edit"
@@ -55,12 +61,9 @@
top_pad="2"
width="120" />
<text
- type="string"
- length="1"
follows="left|bottom"
font="SansSerif"
height="16"
- layout="topleft"
left="164"
name="last_name_text"
top="530"
@@ -72,7 +75,6 @@
font="SansSerif"
handle_edit_keys_directly="true"
height="20"
- layout="topleft"
left_delta="0"
max_length="31"
name="last_name_edit"
@@ -81,12 +83,9 @@
top_pad="2"
width="120" />
<text
- type="string"
- length="1"
follows="left|bottom"
font="SansSerif"
height="16"
- layout="topleft"
left="296"
name="password_text"
top="530"
@@ -98,7 +97,6 @@
font="SansSerif"
handle_edit_keys_directly="true"
height="20"
- layout="topleft"
left_delta="0"
max_length="16"
name="password_edit"
@@ -124,12 +122,9 @@
name="server_combo"
width="100" />
<text
- type="string"
- length="1"
follows="left|bottom"
font="SansSerif"
height="16"
- layout="topleft"
left="32"
name="start_location_text"
top="576"
@@ -141,7 +136,6 @@
control_name="LoginLocation"
follows="left|bottom"
height="23"
- layout="topleft"
left_pad="0"
max_chars="128"
name="start_location_combo"
@@ -164,21 +158,15 @@
control_name="RememberPassword"
follows="left|bottom"
height="16"
- label="Remember me"
- layout="topleft"
+ label="Remember password"
left_pad="10"
name="remember_check"
top_delta="3"
width="138" />
<text
- type="string"
- length="1"
follows="right|bottom"
halign="right"
height="16"
- hover="true"
- hover_color="0.2 0.45 0.72 1"
- layout="topleft"
left="-210"
name="create_new_account_text"
top="539"
@@ -186,14 +174,9 @@
Create a new account
</text>
<text
- type="string"
- length="1"
follows="right|bottom"
halign="right"
height="16"
- hover="true"
- hover_color="0.2 0.45 0.72 1"
- layout="topleft"
left_delta="0"
name="forgot_password_text"
top_pad="4"
@@ -201,18 +184,14 @@
Forgot your name or password?
</text>
<text
- type="string"
- length="1"
follows="right|bottom"
halign="right"
height="16"
- hover="true"
- hover_color="0.2 0.45 0.72 1"
- layout="topleft"
left="-310"
name="channel_text"
top="579"
width="300">
[VERSION]
</text>
+ </panel>
</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..9a3fdcc327
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -0,0 +1,415 @@
+<?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="inventory panel"
+ width="330">
+ <panel.string
+ name="Title">
+ Things
+ </panel.string>
+ <filter_editor
+ text_pad_left="12"
+ follows="left|top|right"
+ font="SanSerif"
+ height="20"
+ label="Filter"
+ layout="topleft"
+ left="15"
+ name="inventory search editor"
+ top="34"
+ width="300" />
+ <tab_container
+ follows="left|top|right|bottom"
+ height="300"
+ layout="topleft"
+ left_delta="-4"
+ name="inventory filter tabs"
+ tab_position="top"
+ top_pad="4"
+ width="305">
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="All Items"
+ layout="topleft"
+ left="1"
+ name="All Items"
+ top="16"
+ width="290" />
+ <inventory_panel
+ follows="left|top|right|bottom"
+ height="295"
+ label="Recent Items"
+ layout="topleft"
+ left_delta="0"
+ name="Recent Items"
+ top_delta="0"
+ width="290" />
+ </tab_container>
+ <menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ height="18"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="Inventory Menu"
+ top_delta="-45"
+ 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.ResetFilter" />
+ </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 Note"
+ 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_media_settings_general.xml b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
index a56f1cf8fe..cc47e99c2c 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_general.xml
@@ -8,6 +8,7 @@
left="102"
mouse_opaque="true"
name="Media Settings General"
+ help_topic = "media_settings_general"
width="365">
<text
@@ -31,6 +32,27 @@
<!-- <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
+ </text>
+
<text
bottom_delta="-20"
follows="top|left"
@@ -61,27 +83,6 @@
<button.commit_callback
function="Media.ResetCurrentUrl"/>
</button>
-
- <web_browser
- border_visible="false"
- 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
- </text>
-
<text
bottom_delta="-5"
follows="top|left"
@@ -135,7 +136,8 @@
<check_box
bottom_delta="-25"
- enabled="true"
+ visible="false"
+ enabled="false"
follows="left|top"
font="SansSerifSmall"
height="16"
@@ -148,7 +150,7 @@
width="150" />
<check_box
- bottom_delta="-25"
+ bottom_delta="0"
enabled="true"
follows="left|top"
font="SansSerifSmall"
@@ -168,20 +170,6 @@
font="SansSerifSmall"
height="16"
initial_value="false"
- label="Use Default Alternative Image"
- left="10"
- mouse_opaque="true"
- name="alt_image_enable"
- 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"
@@ -234,7 +222,7 @@
label=""
label_width="0"
left_delta="40"
- max_val="2000"
+ max_val="2048"
min_val="0"
mouse_opaque="true"
name="width_pixels"
@@ -246,7 +234,7 @@
<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="2000" min_val="0" mouse_opaque="true"
+ 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
index 0cc1406d62..85f534c4a3 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_permissions.xml
@@ -8,6 +8,7 @@
left="102"
mouse_opaque="true"
name="Media settings for controls"
+ help_topic = "media_settings_controls"
width="365">
<text
@@ -15,7 +16,6 @@
follows="top|left"
height="15"
left="10"
- name="media_perms_label_owner"
enabled="false">
Owner
</text>
@@ -53,9 +53,8 @@
follows="top|left"
height="15"
left="10"
- name="media_perms_label_group"
enabled="false">
- Group
+ Group:
</text>
<name_box
@@ -101,7 +100,6 @@
follows="top|left"
height="15"
left="10"
- name="media_perms_label_anyone"
enabled="false">
Anyone
</text>
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
index 695e956e41..a26f74844e 100644
--- a/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
+++ b/indra/newview/skins/default/xui/en/panel_media_settings_security.xml
@@ -8,6 +8,7 @@
left="102"
mouse_opaque="true"
name="Media Settings Security"
+ help_topic = "media_settings_security"
width="365">
<check_box
bottom_delta="-40"
diff --git a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
index 60d3256c44..44fd44cde5 100644
--- a/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_navigation_bar.xml
@@ -4,14 +4,38 @@
background_visible="true"
bg_opaque_color="MouseGray"
follows="left|top|right"
- height="60"
+ height="65"
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="65"
+ 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="65"
+ width="600"/>
<panel
background_visible="false"
follows="left|top|right"
- height="60"
+ top="5"
+ height="23"
layout="topleft"
name="navigation_panel"
width="600">
@@ -28,7 +52,6 @@
layout="topleft"
left="10"
name="back_btn"
- picture_style="true"
tool_tip="Go back to previous location"
top="3"
width="31" />
@@ -46,7 +69,6 @@
layout="topleft"
left_pad="0"
name="forward_btn"
- picture_style="true"
tool_tip="Go forward one location"
top_delta="0"
width="31" />
@@ -63,7 +85,6 @@
layout="topleft"
left_pad="7"
name="home_btn"
- picture_style="true"
tool_tip="Teleport to my home location"
top_delta="0"
width="32" />
@@ -104,7 +125,6 @@
<!-- left_pad="5" -->
<!-- mouse_opaque="false" -->
<!-- name="search_bg" -->
- <!-- picture_style="true" -->
<!-- top_delta="0" -->
<!-- width="168" /> -->
@@ -131,12 +151,12 @@
<favorites_bar
follows="left|right|top"
- height="25"
+ height="15"
layout="topleft"
- left="5"
+ left="0"
name="favorite"
image_drag_indication="Arrow_Down"
chevron_button_tool_tip="Show more of My Favorites"
- top="32"
+ bottom="62"
width="590" />
</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
index d914583352..555fedb1ff 100644
--- a/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_nearby_chat_bar.xml
@@ -6,26 +6,32 @@
layout="topleft"
left="0"
name="chat_bar"
- top="24"
- width="510">
+ top="21"
+ width="310">
+ <string name="min_width">
+ 310
+ </string>
+ <string name="max_width">
+ 320
+ </string>
<line_editor
border_style="line"
border_thickness="1"
follows="left|right"
- height="20"
+ height="23"
label="Click here to chat."
layout="topleft"
left_delta="7"
left="0"
+ max_length="254"
name="chat_box"
- tool_tip="Press Enter to say, Ctrl-Enter to shout."
- top="3"
+ tool_tip="Press Enter to say, Ctrl+Enter to shout"
+ top="0"
width="250" />
<output_monitor
auto_update="true"
follows="right"
draw_border="false"
- halign="left"
height="16"
layout="topleft"
left_pad="-24"
@@ -34,34 +40,19 @@
top="4"
visible="true"
width="20" />
- <button
- follows="right"
- width="45"
- top="3"
- layout="topleft"
- left_pad="5"
- label="Log"
- height="20">
- <button.commit_callback function="Floater.Toggle" parameter="nearby_chat"/>
- </button>
- <chiclet_talk
+ <button
follows="right"
- height="20"
- speak_button.font="SansSerifMedium"
- speak_button.tab_stop="true"
- show_button.tab_stop="true"
- layout="topleft"
- left_pad="5"
- name="talk"
- top="3"
- width="100" />
- <gesture_combo_box
- follows="right"
- height="20"
- label="Gestures"
+ is_toggle="true"
+ width="45"
+ top="0"
layout="topleft"
- name="Gesture"
- left_pad="5"
- top="3"
- width="90" />
+ left_pad="8"
+ label="Log"
+ height="23"
+ name="show_nearby_chat"
+ tool_tip="Show/hide 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
index 4274a37497..5333dfa2f5 100644
--- a/indra/newview/skins/default/xui/en/panel_notes.xml
+++ b/indra/newview/skins/default/xui/en/panel_notes.xml
@@ -1,14 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- bevel_style="in"
- follows="left|top|right|bottom"
- height="460"
+ follows="all"
+ height="535"
label="Notes &amp; Privacy"
layout="topleft"
left="0"
name="panel_notes"
top="0"
- width="313">
+ width="313"
+>
<layout_stack
name="layout"
orientation="vertical"
@@ -16,34 +16,28 @@
layout="topleft"
left="0"
top="0"
- height="430"
- width="313"
+ height="517"
border_size="0">
<panel
name="notes_stack"
follows="all"
layout="topleft"
top="0"
- left="0"
- height="390"
- width="313">
+ left="0">
<scroll_container
color="DkGray2"
- follows="left|top|right|bottom"
- height="390"
+ follows="all"
layout="topleft"
left="0"
name="profile_scroll"
opaque="true"
- top="0"
- width="313">
+ top="0">
<panel
- height="350"
- layout="topleft"
- name="profile_scroll_panel"
- top="0"
- left="0"
- width="293">
+ layout="topleft"
+ name="profile_scroll_panel"
+ top="0"
+ left="0"
+ width="303">
<text
follows="left|top"
font="SansSerifBold"
@@ -52,17 +46,17 @@
left="10"
name="status_message"
text_color="white"
- top="5"
+ top="20"
value="My private notes:"
width="293" />
<text_editor
follows="left|top"
- height="200"
+ height="120"
layout="topleft"
left="10"
max_length="1000"
name="notes_edit"
- text_color="black"
+ text_color="DkGray"
top_pad="10"
width="280"
word_wrap="true" />
@@ -74,70 +68,91 @@
left="10"
name="status_message2"
text_color="white"
- top_pad="10"
- value="Let this person:"
+ top_pad="30"
+ value="Allow this person to:"
width="293" />
<check_box
enabled="false"
- height="20"
+ height="16"
label="See my online status"
layout="topleft"
left="20"
name="status_check"
- top_pad="0"
width="293" />
<check_box
enabled="false"
- height="20"
+ height="16"
label="See me on the map"
layout="topleft"
left="20"
name="map_check"
- top_pad="0"
width="293" />
<check_box
enabled="false"
- height="20"
+ height="16"
label="Edit, delete or take my objects"
layout="topleft"
left="20"
name="objects_check"
- top_pad="0"
width="293" />
</panel>
</scroll_container>
</panel>
<panel
- follows="bottom"
+ follows="bottom|left"
height="30"
layout="topleft"
- left="10"
+ left="0"
name="notes_buttons_panel"
- top_pad="5"
- width="280"
auto_resize="false">
- <button
- enabled="false"
- follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Teleport"
- layout="topleft"
- left="0"
- name="teleport_btn"
- top="0"
- width="75" />
- <button
- enabled="false"
- follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Map"
- layout="topleft"
- name="show_on_map_btn"
- top="0"
- left_pad="5"
- width="85" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Add"
+ layout="topleft"
+ left="0"
+ mouse_opaque="false"
+ name="add_friend"
+ top="5"
+ width="55" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="IM"
+ layout="topleft"
+ name="im"
+ top="5"
+ left_pad="5"
+ width="40" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="19"
+ label="Call"
+ layout="topleft"
+ name="call"
+ left_pad="5"
+ top="5"
+ width="55" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ height="19"
+ label="Map"
+ layout="topleft"
+ name="show_on_map_btn"
+ top="5"
+ left_pad="5"
+ width="50" />
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Teleport"
+ layout="topleft"
+ name="teleport"
+ left_pad="5"
+ top="5"
+ width="90" />
</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..34a185fb44
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_notification.xml
@@ -0,0 +1,100 @@
+<?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="10"
+ 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="10"
+ 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="90"
+ layout="topleft"
+ left="10"
+ name="text_box"
+ read_only="true"
+ text_color="white"
+ top="10"
+ visible="false"
+ width="300"
+ wrap="true"/>
+ <text
+ border_visible="false"
+ follows="left|right|top|bottom"
+ font="SansSerifBold"
+ height="90"
+ layout="topleft"
+ left="45"
+ name="caution_text_box"
+ text_color="1 0.82 0.46 1"
+ top="5"
+ visible="false"
+ width="300"
+ 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"
+ 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"/>
+ </panel>
+ <panel
+ background_visible="false"
+ follows="left|right|bottom"
+ label="control_panel"
+ layout="topleft"
+ left="0"
+ left_delta="-38"
+ name="control_panel"
+ top="20">
+ </panel>
+ <!--
+ <icon
+ follows="left|top"
+ height="32"
+ image_name="notify_tip_icon.tga"
+ layout="topleft"
+ left="8"
+ mouse_opaque="false"
+ name="info_icon"
+ top="20"
+ width="32" /> -->
+</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
index c67ae41677..7b6c0f33da 100644
--- a/indra/newview/skins/default/xui/en/panel_notifications_channel.xml
+++ b/indra/newview/skins/default/xui/en/panel_notifications_channel.xml
@@ -71,7 +71,6 @@
layout="topleft"
left_delta="0"
name="header"
- picture_style="true"
top_delta="-20"
width="100" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_people.xml b/indra/newview/skins/default/xui/en/panel_people.xml
index 786c39c5e9..d6e2aa64fa 100644
--- a/indra/newview/skins/default/xui/en/panel_people.xml
+++ b/indra/newview/skins/default/xui/en/panel_people.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Side tray panel -->
<panel
background_visible="true"
-color="DkGray"
follows="all"
height="570"
label="People"
@@ -10,7 +10,6 @@ color="DkGray"
name="people_panel"
top="0"
left="0"
- bevel_style="none"
width="333">
<string
name="no_people"
@@ -35,47 +34,49 @@ color="DkGray"
value="Filter Groups" />
<filter_editor
follows="left|top|right"
- font="SansSerif"
height="23"
layout="topleft"
left="15"
+ label="Filter"
max_length="300"
name="filter_input"
- text_color="black"
+ text_color="Black"
top="3"
- width="300" />
+ width="303" />
<tab_container
follows="all"
- height="488"
+ height="500"
layout="topleft"
left="10"
name="tabs"
- bevel_style="in"
+ tab_min_width="70"
+ tab_height="30"
tab_position="top"
- top_pad="15"
+ top_pad="10"
+ halign="center"
width="313">
<panel
- follows="all"
- height="488"
- label="Nearby"
+ 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="430"
+ height="470"
+ ignore_online_status="true"
layout="topleft"
left="0"
+ multi_select="true"
name="avatar_list"
top="0"
- volume_column_width="20"
width="313" />
<panel
- background_visible="true"
- bevel_style="none"
- top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
@@ -85,8 +86,7 @@ color="DkGray"
width="313">
<button
follows="bottom|left"
- font="SansSerifBigBold"
- tool_tip="Change sort and view of Residents list"
+ tool_tip="Options"
height="18"
image_disabled="OptionsMenu_Disabled"
image_selected="OptionsMenu_Press"
@@ -94,67 +94,73 @@ color="DkGray"
layout="topleft"
left="10"
name="nearby_view_sort_btn"
- picture_style="true"
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" />
</panel>
</panel>
<panel
- background_visible="true"
- bevel_style="none"
follows="all"
- color="DkGray2"
- height="460"
- left="0"
- top="0"
- label="Friends"
+ height="500"
+ label="FRIENDS"
layout="topleft"
+ left="0"
+ help_topic="people_friends_tab"
name="friends_panel"
+ top="0"
width="313">
<accordion
follows="all"
- height="430"
+ height="470"
layout="topleft"
left="0"
name="friends_accordion"
top="0"
width="313">
<accordion_tab
- can_resize="false"
layout="topleft"
- height="230"
+ height="235"
min_height="150"
name="tab_online"
title="Online">
<avatar_list
+ allow_select="true"
follows="all"
- height="150"
layout="topleft"
left="0"
+ multi_select="true"
name="avatars_online"
top="0"
width="313" />
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
- height="230"
+ height="235"
name="tab_all"
title="All">
<avatar_list
+ allow_select="true"
follows="all"
- height="230"
layout="topleft"
left="0"
+ multi_select="true"
name="avatars_all"
top="0"
width="313" />
</accordion_tab>
</accordion>
<panel
- background_visible="true"
- bevel_style="none"
- top_pad="0"
follows="left|right|bottom"
height="30"
label="bottom_panel"
@@ -164,8 +170,7 @@ color="DkGray"
width="313">
<button
follows="bottom|left"
- font="SansSerifBigBold"
- tool_tip="Change sort and view of Friends list"
+ tool_tip="Options"
height="18"
image_disabled="OptionsMenu_Disabled"
image_selected="OptionsMenu_Press"
@@ -173,12 +178,10 @@ color="DkGray"
layout="topleft"
left="10"
name="friends_viewsort_btn"
- picture_style="true"
top="5"
width="18" />
<button
follows="bottom|left"
- font="SansSerifBigBold"
height="18"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
@@ -186,48 +189,43 @@ color="DkGray"
layout="topleft"
left_pad="5"
name="add_btn"
- picture_style="true"
tool_tip="Offer friendship to a resident"
top_delta="0"
width="18" />
<button
follows="bottom|left"
- font="SansSerifBigBold"
height="18"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
image_disabled="TrashItem_Disabled"
layout="topleft"
- left_pad="230"
+ left_pad="10"
+ right="-10"
name="del_btn"
- picture_style="true"
tool_tip="Remove selected person from your Friends list"
top_delta="0"
width="18" />
</panel>
</panel>
<panel
- background_visible="true"
- bevel_style="none"
- follows="left|top|right|bottom"
- height="390"
- label="Groups"
- top="0"
+ 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="left|top|right|bottom"
- height="357"
+ follows="all"
+ height="470"
layout="topleft"
- color="DkGray2"
left="0"
name="group_list"
- top="2"
+ top="0"
width="313" />
<panel
- background_visible="true"
- bevel_style="none"
top_pad="0"
follows="left|right|bottom"
height="30"
@@ -238,8 +236,7 @@ color="DkGray"
width="313">
<button
follows="bottom|left"
- font="SansSerifBigBold"
- tool_tip="Change sort and view of Groups list"
+ tool_tip="Options"
height="18"
image_disabled="OptionsMenu_Disabled"
image_selected="OptionsMenu_Press"
@@ -247,12 +244,10 @@ color="DkGray"
layout="topleft"
left="10"
name="groups_viewsort_btn"
- picture_style="true"
- top="5"
+ top="7"
width="18" />
<button
follows="bottom|left"
- font="SansSerifBigBold"
height="18"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
@@ -260,61 +255,45 @@ color="DkGray"
layout="topleft"
left_pad="5"
name="plus_btn"
- picture_style="true"
tool_tip="Join group/Create new group"
top_delta="0"
width="18" />
<button
follows="bottom|left"
- font="SansSerifBigBold"
height="10"
- image_hover_selected="group_activate_btn.tga"
- image_selected="group_activate_btn.tga"
- image_unselected="group_activate_btn.tga"
+ image_hover_selected="Activate_Checkmark"
+ image_selected="Activate_Checkmark"
+ image_unselected="Activate_Checkmark"
layout="topleft"
left_pad="24"
name="activate_btn"
- picture_style="true"
tool_tip="Activate selected group"
top_delta="5"
width="10" />
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="TrashItem_Press"
- image_unselected="TrashItem_Off"
- layout="topleft"
- left_pad="196"
- name="minus_btn"
- picture_style="true"
- tool_tip="Leave selected group"
- top_delta="-5"
- width="18" />
</panel>
</panel>
<panel
- background_visible="true"
- bevel_style="none"
- top="0"
- follows="left|top|right|bottom"
- height="390"
- label="Recent"
+ follows="all"
+ height="500"
+ label="RECENT"
layout="topleft"
+ left="0"
+ help_topic="people_recent_tab"
name="recent_panel"
+ top="0"
width="313">
<avatar_list
- color="DkGray2"
- follows="left|top|right|bottom"
- height="357"
+ allow_select="true"
+ follows="all"
+ height="470"
layout="topleft"
left="0"
+ multi_select="true"
name="avatar_list"
- top="2"
+ show_last_interaction_time="true"
+ top="0"
width="313" />
<panel
- background_visible="true"
- bevel_style="none"
top_pad="0"
follows="left|right|bottom"
height="30"
@@ -325,8 +304,7 @@ color="DkGray"
width="313">
<button
follows="bottom|left"
- font="SansSerifBigBold"
- tool_tip="Change sort and view of Recent Residents list"
+ tool_tip="Options"
height="18"
image_disabled="OptionsMenu_Disabled"
image_selected="OptionsMenu_Press"
@@ -334,9 +312,20 @@ color="DkGray"
layout="topleft"
left="10"
name="recent_viewsort_btn"
- picture_style="true"
- top="5"
+ 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" />
</panel>
</panel>
</tab_container>
@@ -344,7 +333,7 @@ color="DkGray"
animate="false"
border_size="0"
follows="left|right|bottom"
- height="27"
+ height="25"
layout="topleft"
left="10"
name="button_bar"
@@ -352,104 +341,88 @@ color="DkGray"
width="313">
<layout_panel
default_tab_group="1"
- follows="left|top|right"
+ follows="left|top"
height="25"
layout="topleft"
left="0"
name="view_profile_btn_panel"
top="-25"
- width="65">
+ width="100">
<button
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
label="Profile"
layout="topleft"
name="view_profile_btn"
tool_tip="Show picture, groups, and other residents information"
- width="65" />
- </layout_panel>
- <layout_panel
- default_tab_group="1"
- follows="left|top|right"
- height="25"
- layout="topleft"
- left_delta="0"
- min_width="85"
- name="add_friend_btn_panel"
- top_delta="0"
- width="85">
- <button
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
- label="Add Friend"
- layout="topleft"
- name="add_friend_btn"
- tool_tip="Add selected resident to your Friends List"
- width="85" />
+ width="100" />
</layout_panel>
<layout_panel
default_tab_group="1"
- follows="left|top|right"
- height="25"
+ follows="left|top"
+ height="19"
layout="topleft"
+ left="0"
min_width="80"
name="group_info_btn_panel"
- width="80">
+ width="100">
<button
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
label="Group Profile"
layout="topleft"
name="group_info_btn"
tool_tip="Show group information"
- width="80" />
+ width="100" />
</layout_panel>
<layout_panel
default_tab_group="1"
- follows="left|top|right"
+ follows="left|top"
height="25"
layout="topleft"
+ left_pad="5"
min_width="45"
name="chat_btn_panel"
top_delta="0"
- width="45">
+ width="100">
<button
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
- label="Chat"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
+ label="Group Chat"
layout="topleft"
name="chat_btn"
tool_tip="Open chat session"
- width="45" />
+ width="100" />
</layout_panel>
<layout_panel
default_tab_group="1"
- follows="left|top|right"
+ follows="left|top|"
height="25"
layout="topleft"
+ left_pad="5"
min_width="35"
name="im_btn_panel"
top_delta="0"
- width="35">
+ width="50">
<button
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
label="IM"
layout="topleft"
name="im_btn"
tool_tip="Open instant message session"
- width="35" />
+ width="50" />
</layout_panel>
<layout_panel
default_tab_group="1"
follows="left|top|right"
height="25"
layout="topleft"
+ left_pad="5"
min_width="40"
name="call_btn_panel"
top_delta="0"
@@ -457,53 +430,55 @@ color="DkGray"
width="40">
<button
enabled="false"
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
label="Call"
layout="topleft"
name="call_btn"
- width="40" />
+ width="50" />
</layout_panel>
<layout_panel
default_tab_group="1"
- follows="left|top|right"
+ follows="left|top"
height="25"
layout="topleft"
+ left_pad="5"
min_width="65"
name="teleport_btn_panel"
top_delta="0"
- width="65">
+ width="100">
<button
- follows="left|top|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="19"
label="Teleport"
layout="topleft"
name="teleport_btn"
tool_tip="Offer teleport"
- width="65" />
+ width="100" />
</layout_panel>
- <layout_panel
+ <layout_panel
default_tab_group="1"
enabled="false"
- follows="left|top|right"
+ follows="left|top"
height="25"
layout="topleft"
+ left_pad="5"
min_width="50"
name="share_btn_panel"
top_delta="0"
visible="false"
- width="50">
+ width="80">
<button
enabled="false"
- follows="top|left|right"
- font="SansSerifSmallBold"
- height="25"
+ follows="top|left"
+ font="SansSerifSmall"
+ height="19"
label="Share"
layout="topleft"
name="share_btn"
- width="50" />
+ width="80" />
</layout_panel>
</layout_stack>
</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
index 7d5ae3d78a..cf18aa2d39 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_info.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_info.xml
@@ -1,43 +1,46 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- bevel_style="in"
- follows="left|top|right|bottom"
+ background_visible="true"
+ follows="all"
height="570"
layout="topleft"
left="0"
+ min_height="350"
name="panel_pick_info"
top="0"
width="333">
<button
- follows="top|left"
- height="25"
- width="25"
+ follows="top|right"
+ height="23"
image_overlay="BackArrow_Off"
layout="topleft"
name="back_btn"
- picture_style="true"
left="10"
- top="7" />
+ tab_stop="false"
+ top="2"
+ width="23" />
<text
- follows="top|left"
+ follows="top|left|right"
font="SansSerifHugeBold"
- height="22"
+ height="26"
layout="topleft"
- left_pad="15"
+ left_pad="10"
name="title"
text_color="white"
+ top="0"
value="Pick Info"
- width="270" />
+ use_ellipses="true"
+ width="275" />
<scroll_container
color="DkGray2"
opaque="true"
follows="all"
- height="470"
+ height="500"
layout="topleft"
left="10"
top_pad="10"
name="profile_scroll"
- reserve_scroll_corner="true"
+ reserve_scroll_corner="false"
width="313">
<panel
name="scroll_content_panel"
@@ -57,11 +60,11 @@
left="10"
name="pick_snapshot"
top="20"
- width="280" />
+ width="290" />
<text
follows="left|top|right"
- height="20"
- width="280"
+ height="35"
+ width="290"
layout="topleft"
font="SansSerifBig"
font.style="BOLD"
@@ -70,14 +73,14 @@
name="pick_name"
text_color="white"
value="[name]"
- word_wrap="true" />
+ use_ellipses="true" />
<text
follows="left|top"
height="25"
layout="topleft"
left="10"
name="pick_location"
- width="280"
+ width="290"
word_wrap="true"
value="[loading...]" />
<text
@@ -86,47 +89,47 @@
layout="topleft"
left="10"
name="pick_desc"
- width="280"
+ width="290"
value="[description]"
word_wrap="true" />
</panel>
</scroll_container>
<panel
follows="left|right|bottom"
- height="30"
+ height="20"
layout="topleft"
- top_pad="5"
+ top_pad="8"
left="10"
name="buttons">
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Edit"
+ font="SansSerifSmall"
+ height="19"
+ label="Teleport"
layout="topleft"
left="0"
- name="edit_btn"
+ name="teleport_btn"
top="0"
- width="80" />
+ width="90" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Teleport"
+ font="SansSerifSmall"
+ height="19"
+ label="Map"
layout="topleft"
- left_pad="5"
- name="teleport_btn"
+ left_pad="10"
+ name="show_on_map_btn"
top="0"
- width="80" />
+ width="90" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Map"
+ font="SansSerifSmall"
+ height="19"
+ label="Edit"
layout="topleft"
- left_pad="5"
- name="show_on_map_btn"
+ right="-1"
+ name="edit_btn"
top="0"
- width="80" />
+ 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
index 686faab8eb..7ff227ecb6 100644
--- a/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_pick_list_item.xml
@@ -2,79 +2,81 @@
<panel
bevel_style="none"
follows="top|left|right"
- height="120"
+ height="85"
layout="topleft"
left="0"
name="picture_item"
top="0"
- width="305">
+ width="313">
<icon
- follows="top|bottom|left|right"
- height="120"
+ follows="all"
+ height="85"
image_name="ListItem_Over"
- left="0"
+ right="-3"
mouse_opaque="false"
name="hovered_icon"
- top="0"
+ top="1"
scale_image="true"
visible="false"
- width="305"/>
+ width="307"/>
<icon
- follows="top|bottom|left|right"
- height="120"
+ follows="all"
+ height="85"
image_name="ListItem_Select"
- left="0"
+ right="-3"
mouse_opaque="false"
name="selected_icon"
- top="0"
+ top="1"
scale_image="true"
visible="false"
- width="305"/>
+ width="307"/>
<texture_picker
allow_no_texture="true"
- default_image_name="None"
+ border_enabled="true"
+ default_image_name="TabIcon_Places_Large"
enabled="false"
follows="left|top"
- height="120"
+ height="80"
layout="topleft"
- left="5"
+ left="10"
mouse_opaque="false"
name="picture"
tab_stop="false"
- top="5"
- top_pad="5"
- width="120" />
+ top="10"
+ top_pad="10"
+ width="90" />
<text
follows="top|left|right"
+ font="SansSerifSmallBold"
height="16"
layout="topleft"
- left="135"
+ left="110"
name="picture_name"
text_color="white"
- top="5"
- use_ellipses="true"
- width="130"
- word_wrap="true" />
- <text
+ top="9"
+ use_ellipses="false"
+ width="197"
+ word_wrap="false" />
+ <expandable_text
follows="top|left|right"
- height="75"
+ font="SansSerifSmall"
+ height="40"
layout="topleft"
- left="135"
+ left="110"
name="picture_descr"
- top_pad="10"
- use_ellipses="true"
- width="130"
+ top_pad="3"
+ width="178"
word_wrap="true" />
<button
follows="top|right"
height="16"
- image_selected="Info_Press"
- image_unselected="Info_Off"
+ image_selected="BuyArrow_Press"
+ image_pressed="BuyArrow_Press"
+ image_unselected="BuyArrow_Press"
layout="topleft"
name="info_chevron"
- picture_style="true"
- right="290"
+ right="-7"
tab_stop="false"
- top="5"
+ top="27"
width="16" />
</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_picks.xml b/indra/newview/skins/default/xui/en/panel_picks.xml
index 1bd1953397..ae61852f68 100644
--- a/indra/newview/skins/default/xui/en/panel_picks.xml
+++ b/indra/newview/skins/default/xui/en/panel_picks.xml
@@ -1,16 +1,16 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- follows="left|top|right|bottom"
- height="555"
+ follows="all"
+ height="535"
label="Picks"
layout="topleft"
left="0"
name="panel_picks"
top="0"
width="313">
- <flat_list_view
+ <flat_list_view
color="DkGray2"
- follows="left|top|right|bottom"
+ follows="all"
height="465"
layout="topleft"
left="0"
@@ -18,14 +18,14 @@
opaque="true"
top="0"
width="313" />
- <panel
+ <panel
background_visible="true"
bevel_style="none"
enabled="false"
auto_resize="false"
follows="bottom"
left="0"
- height="23"
+ height="18"
label="bottom_panel"
layout="topleft"
name="edit_panel"
@@ -34,60 +34,94 @@
<button
enabled="false"
follows="bottom|left"
- font="SansSerifBigBold"
height="18"
image_selected="OptionsMenu_Press"
image_unselected="OptionsMenu_Off"
image_disabled="OptionsMenu_Disabled"
layout="topleft"
- left="10"
+ left="0"
name="gear_menu_btn"
- picture_style="true"
top="5"
width="18" />
<button
follows="bottom|left"
- font="SansSerifBigBold"
height="18"
image_disabled="AddItem_Disabled"
image_selected="AddItem_Press"
image_unselected="AddItem_Off"
layout="topleft"
- left="35"
+ left_pad="15"
name="new_btn"
- picture_style="true"
- tool_tip="Create New Pick at Current Location"
+ tool_tip="Create new pick at current location"
top="5"
width="18" />
<button
follows="bottom|right"
- font="SansSerifBigBold"
height="18"
image_disabled="TrashItem_Disabled"
image_selected="TrashItem_Press"
image_unselected="TrashItem_Off"
layout="topleft"
name="trash_btn"
- picture_style="true"
right="-10"
top="5"
width="18" />
</panel>
<panel
- follows="bottom"
- auto_resize="false"
layout="topleft"
- height="30"
+ left="0"
+ height="25"
+ top_pad="10"
name="buttons_cucks"
+ help_topic="picks_button_tab"
width="313">
- <button
- enabled="false"
- follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Map"
- layout="topleft"
- name="show_on_map_btn"
- width="85" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Info"
+ layout="topleft"
+ left="5"
+ name="info_btn"
+ tab_stop="false"
+ top="0"
+ width="55" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Teleport"
+ layout="topleft"
+ left_pad="5"
+ name="teleport_btn"
+ tab_stop="false"
+ top="0"
+ width="77" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Map"
+ layout="topleft"
+ left_pad="5"
+ name="show_on_map_btn"
+ tab_stop="false"
+ top="0"
+ width="50" />
+ <button
+ enabled="false"
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="â–¼"
+ layout="topleft"
+ name="overflow_btn"
+ right="-10"
+ tab_stop="false"
+ top="0"
+ width="30" />
</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..65f150b33c
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_place_profile.xml
@@ -0,0 +1,919 @@
+<?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_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" />
+ <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="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="all"
+ height="533"
+ layout="topleft"
+ left="0"
+ min_height="300"
+ name="scrolling_panel"
+ top="0"
+ value="&gt;"
+ 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="all"
+ 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" />
+ <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">
+ <scroll_container
+ color="DkGray2"
+ follows="all"
+ height="132"
+ layout="topleft"
+ left="0"
+ name="parcel_scroll"
+ opaque="true"
+ top="0"
+ width="290">
+ <panel
+ follows="all"
+ height="165"
+ layout="topleft"
+ left="0"
+ top="0"
+ width="275">
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="parcel_drk_PG"
+ layout="topleft"
+ left="20"
+ name="rating_icon"
+ top="0"
+ width="18" />
+ <text
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left_pad="8"
+ name="rating_label"
+ value="Rating:"
+ width="80" />
+ <text
+ follows="right|top"
+ height="16"
+ layout="topleft"
+ left_pad="0"
+ name="rating_value"
+ top_delta="0"
+ value="unknown"
+ width="120" />
+ <icon
+ follows="top|left"
+ height="18"
+ image_name="parcel_drk_Voice"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="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_drk_Fly"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="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_drk_Push"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="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_drk_Build"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="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_drk_Scripts"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="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_drk_Damage"
+ layout="topleft"
+ left="20"
+ 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="76" />
+ <text
+ follows="right|top"
+ height="14"
+ layout="topleft"
+ left_pad="0"
+ name="damage_value"
+ top_delta="0"
+ value="Off"
+ width="60" />
+ <button
+ follows="bottom|right"
+ height="19"
+ label="About Land"
+ layout="topleft"
+ name="about_land_btn"
+ right="-5"
+ tab_stop="false"
+ top="138"
+ width="90">
+ <click_callback
+ function="ShowFloater"
+ parameter="about_land" />
+ </button>
+ </panel>
+ </scroll_container>
+ </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="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_name"
+ top_delta="0"
+ value="Mooseland"
+ width="195" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_type_label"
+ top_pad="5"
+ value="Type:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_type"
+ top_delta="0"
+ value="Moose"
+ width="195" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_rating_label"
+ top_pad="7"
+ value="Rating:"
+ width="80" />
+ <icon
+ follows="top|left"
+ height="16"
+ image_name="parcel_drk_PG"
+ 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="Explicit"
+ width="100" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_owner_label"
+ top_pad="5"
+ value="Owner:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_owner"
+ top_delta="0"
+ value="moose Van Moose"
+ width="195" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="region_group_label"
+ top_pad="5"
+ value="Group:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left_pad="0"
+ name="region_group"
+ top_delta="0"
+ use_ellipses="true"
+ width="195">
+ The Mighty Moose of mooseville soundvillemoose
+ </text>
+ <button
+ follows="bottom|right"
+ height="19"
+ label="Region/Estate"
+ layout="topleft"
+ name="region_info_btn"
+ right="-5"
+ tab_stop="false"
+ width="105">
+ <click_callback
+ function="ShowFloater"
+ 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="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="90"
+ name="estate_name"
+ top_delta="0"
+ width="160" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="estate_rating_label"
+ top_pad="5"
+ value="Rating:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="90"
+ name="estate_rating"
+ top_delta="0"
+ width="160" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="estate_owner_label"
+ top_pad="5"
+ value="Owner:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="90"
+ name="estate_owner"
+ top_delta="0"
+ width="160" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="covenant_label"
+ top_pad="5"
+ value="Covenant:"
+ width="220" />
+ <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="280" />
+ </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="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="sales_price"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="area_label"
+ top_pad="5"
+ value="Area:"
+ width="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="area"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="traffic_label"
+ top_pad="5"
+ value="Traffic:"
+ width="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="traffic"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="primitives_label"
+ top_pad="5"
+ value="Primitives:"
+ width="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="primitives"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="parcel_scripts_label"
+ top_pad="5"
+ value="Scripts:"
+ width="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="parcel_scripts"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="terraform_limits_label"
+ top_pad="5"
+ value="Terraform limits:"
+ width="100" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="110"
+ name="terraform_limits"
+ top_delta="0"
+ width="140" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="subdivide_label"
+ top_pad="5"
+ value="Subdivide/Join ability:"
+ width="220" />
+ <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="245" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="resale_label"
+ top_pad="5"
+ value="ReSale ability:"
+ width="80" />
+ <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="245" />
+ <text
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="10"
+ name="sale_to_label"
+ top_pad="5"
+ value="For sale to:"
+ width="80" />
+ <text
+ follows="left|top|right"
+ height="15"
+ layout="topleft"
+ left="90"
+ name="sale_to"
+ top_delta="0"
+ width="160" />
+ </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
index 1761c80a39..cbbcfe5068 100644
--- a/indra/newview/skins/default/xui/en/panel_places.xml
+++ b/indra/newview/skins/default/xui/en/panel_places.xml
@@ -1,111 +1,121 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
- background_visible="true"
+background_visible="true"
follows="all"
- height="400"
+ height="570"
label="Places"
layout="topleft"
min_height="350"
- min_width="240"
name="places panel"
+ top="0"
+ left="0"
width="333">
<string
name="landmarks_tab_title"
- value="Landmarks" />
+ value="MY LANDMARKS" />
<string
name="teleport_history_tab_title"
- value="Teleport History" />
+ value="TELEPORT HISTORY" />
<filter_editor
follows="left|top|right"
font="SansSerif"
height="23"
- label="Filter"
layout="topleft"
left="15"
+ label="Filter"
+ max_length="300"
name="Filter"
top="3"
- width="300" />
+ width="303" />
<tab_container
follows="all"
- height="326"
+ halign="center"
+ height="500"
layout="topleft"
- left="9"
+ left="10"
name="Places Tabs"
+ tab_min_width="80"
+ tab_height="30"
tab_position="top"
- top="30"
+ 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="places_info_tab"
+ name="panel_place_profile"
+ top="5"
+ visible="false"
width="313" />
<panel
- class="panel_place_info"
- filename="panel_place_info.xml"
+ class="panel_landmark_info"
+ filename="panel_landmark_info.xml"
follows="all"
- height="326"
+ height="533"
layout="topleft"
left="0"
- name="panel_place_info"
- top="30"
- visible="false" />
+ help_topic="places_info_tab"
+ name="panel_landmark_info"
+ top="5"
+ visible="false"
+ width="313" />
<panel
- height="25"
+ height="19"
layout="topleft"
left="0"
+ help_topic="places_button_tab"
name="button_panel"
- top_pad="10"
width="313">
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Teleport"
layout="topleft"
left="5"
name="teleport_btn"
top="0"
- width="77" />
+ width="100" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Map"
layout="topleft"
left_pad="5"
name="map_btn"
top="0"
- width="50" />
- <button
- enabled="false"
- follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
- label="Share"
- layout="topleft"
- left_pad="5"
- name="share_btn"
- top="0"
- width="60" />
+ width="70" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Edit"
layout="topleft"
left_pad="5"
name="edit_btn"
top="0"
- width="50" />
+ width="70" />
<button
follows="bottom|right"
- font="SansSerifSmallBold"
- height="25"
- label="â–¼"
+ font="SansSerifSmall"
+ height="19"
+ image_disabled="ForwardArrow_Disabled"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
layout="topleft"
name="overflow_btn"
right="-10"
top="0"
- width="30" />
+ width="18" />
<button
follows="bottom|right"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Close"
layout="topleft"
name="close_btn"
@@ -114,8 +124,8 @@
width="60" />
<button
follows="bottom|right"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Cancel"
layout="topleft"
name="cancel_btn"
@@ -124,8 +134,8 @@
width="60" />
<button
follows="bottom|right"
- font="SansSerifSmallBold"
- height="25"
+ font="SansSerifSmall"
+ height="19"
label="Save"
layout="topleft"
name="save_btn"
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
index 06ecfdc995..613decad8d 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_advanced.xml
@@ -20,60 +20,58 @@
</panel.string>
<check_box
control_name="UseChatBubbles"
+ follows="left|top"
height="16"
- label="Bubble Chat"
+ label="Bubble chat"
layout="topleft"
left="30"
top="10"
name="bubble_text_chat"
width="150" />
-
+ <color_swatch
+ border_color="0.45098 0.517647 0.607843 1"
+ 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" />
<slider
control_name="ChatBubbleOpacity"
+ follows="left|top"
height="16"
increment="0.05"
initial_value="1"
label="Opacity"
layout="topleft"
- left_delta="50"
- top_pad="5"
+ left_delta="-230"
+ top_pad="-28"
label_width="50"
name="bubble_chat_opacity"
width="200" />
-
- <!-- <check_box
- control_name="UIAutoScale"
- height="16"
- label="Resolution independent scale"
- layout="topleft"
- left="30"
- name="ui_auto_scale"
- top_pad="10"
- width="256" />-->
- <!--
- <combo_box
- height="18"
- layout="topleft"
- left_pad="5"
- name="fullscreen combo"
- top_delta="-1"
- width="150" /-->
<text
+ follows="left|top"
type="string"
length="1"
height="25"
layout="topleft"
left="30"
- top_pad="20"
+ top_pad="5"
name="AspectRatioLabel1"
tool_tip="width / height"
label_width="50"
width="120">
- Aspect Ratio
+ Aspect ratio
</text>
<combo_box
allow_text_entry="true"
height="20"
+ follows="left|top"
layout="topleft"
left_pad="0"
max_chars="100"
@@ -104,6 +102,7 @@
</combo_box>
<check_box
control_name="FullScreenAutoDetectAspectRatio"
+ follows="left|top"
height="25"
label="Auto-detect"
layout="topleft"
@@ -113,14 +112,14 @@
<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="10"
+ top_pad="5"
width="270">
Camera:
</text>
@@ -128,7 +127,7 @@ Camera:
can_edit_text="true"
control_name="CameraAngle"
decimal_digits="2"
- top_pad="10"
+ top_pad="5"
follows="left|top"
height="16"
increment="0.025"
@@ -159,56 +158,62 @@ Camera:
name="camera_offset_scale"
show_text="false"
width="240"
- top_pad="10"/>
+ top_pad="5"/>
<text
+ follows="left|top"
type="string"
length="1"
height="10"
left="30"
name="heading2"
- width="270">
+ 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="10" />
+ 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="10"
+ top_pad="5"
width="270">
-My Avatar:
+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="10"/>
+ top_pad="0"/>
<check_box
- control_name="ArrowKeysMoveAvatar"
+ control_name="ArrowKeysAlwaysMove"
+ follows="left|top"
height="20"
label="Arrow keys always move me"
layout="topleft"
@@ -217,7 +222,8 @@ My Avatar:
width="237"
top_pad="0"/>
<check_box
- control_name="TapTapHoldtoRun"
+ control_name="AllowTapTapHoldRun"
+ follows="left|top"
height="20"
label="Tap-tap-hold to run"
layout="topleft"
@@ -225,48 +231,30 @@ My Avatar:
name="tap_tap_hold_to_run"
width="237"
top_pad="0"/>
- <!--menu_item_check
- label="Tap-Tap-Hold to Run"
- layout="topleft"
- name="Tap-Tap-Hold to Run">
- <menu_item_check.on_check
- function="Advanced.CheckAllowTapTapHoldRun"
- parameter="TapTapHoldRun" />
- <menu_item_check.on_click
- function="Advanced.ToggleAllowTapTapHoldRun" />
- </menu_item_check-->
<check_box
- control_name="EnableLipSync"
+ control_name="LipSyncEnabled"
+ follows="left|top"
height="20"
- label="Move my avatar's lips when speaking"
+ label="Move avatar lips when speaking"
layout="topleft"
left_delta="0"
name="enable_lip_sync"
width="237"
top_pad="0" />
- <!--menu_item_check
- label="Enable Lip Sync(Beta)"
- layout="topleft"
- name="Enable Lip Sync(Beta)">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="LipSyncEnabled" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="LipSyncEnabled" />
- </menu_item_check-->
<check_box
- control_name="test"
+ control_name="ShowScriptErrors"
+ follows="left|top"
height="20"
label="Show script errors"
layout="topleft"
left="30"
name="show_script_errors"
width="256"
- top_pad="10"/>
+ top_pad="5"/>
<radio_group
- enabled_control="EnableShowScriptErrors"
- control_name="ShowScriptErrorsLocation"
+ enabled_control="ShowScriptErrors"
+ control_name="ShowScriptErrorsLocation"
+ follows="top|left"
draw_border="false"
height="40"
layout="topleft"
@@ -280,17 +268,66 @@ My Avatar:
layout="topleft"
left="3"
name="0"
- top="3"
+ top="0"
width="315" />
<radio_item
height="16"
label="In window"
layout="topleft"
- left_delta="0"
+ left_delta="175"
name="1"
- top_delta="16"
+ top_delta="0"
width="315" />
</radio_group>
-
-
-</panel> \ No newline at end of file
+ <check_box
+ follows="top|left"
+ enabled_control="EnableVoiceChat"
+ control_name="PushToTalkToggle"
+ height="20"
+ label="Use Push-to-talk in toggle mode"
+ 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 push-to-talk trigger to switch your microphone on and off. When not in toggle mode, the microphone is active only when the trigger is 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-talk trigger"
+ top_pad="0"
+ width="280" />
+ <button
+ follows="top|left"
+ enabled_control="EnableVoiceChat"
+ height="20"
+ 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"
+ font="SansSerif"
+ halign="center"
+ height="20"
+ 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..a94df4150d
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_alerts.xml
@@ -0,0 +1,120 @@
+<?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"
+ enabled="false"
+ 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 alerts:
+ </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="20"
+ 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="20"
+ 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 alerts:
+ </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
index f4696152f9..645863e7a4 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_chat.xml
@@ -29,7 +29,7 @@
height="16"
label="Medium"
layout="topleft"
- left_pad="12"
+ left_delta="145"
name="radio2"
top_delta="0"
width="125" />
@@ -37,7 +37,7 @@
height="16"
label="Large"
layout="topleft"
- left_pad="12"
+ left_delta="170"
name="radio3"
top_delta="0"
width="125" />
@@ -220,37 +220,12 @@
<color_swatch
border_color="0.45098 0.517647 0.607843 1"
can_apply_immediately="true"
- color="0 0 0 1"
- control_name="BackgroundChatColor"
- follows="left|top"
- height="47"
- layout="topleft"
- left="180"
- name="background"
- top_pad="-17"
- width="44" />
- <text
- type="string"
- length="1"
- follows="left|top"
- height="10"
- layout="topleft"
- left_pad="5"
- mouse_opaque="false"
- name="text_box8"
- top_delta="5"
- width="95">
- Bubble
- </text>
- <color_swatch
- border_color="0.45098 0.517647 0.607843 1"
- can_apply_immediately="true"
color="0.6 0.6 1 1"
control_name="HTMLLinkColor"
follows="left|top"
height="47"
layout="topleft"
- left="350"
+ left="180"
name="links"
top_pad="-17"
width="44" />
diff --git a/indra/newview/skins/default/xui/en/panel_preferences_general.xml b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
index a94cfbeec4..975d21aaa6 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_general.xml
@@ -33,7 +33,7 @@
width="170">
<combo_box.item
enabled="true"
- label="System Default"
+ label="System default"
name="System Default Language"
value="default" />
<combo_box.item
@@ -189,7 +189,7 @@
name="start_location_textbox"
top_delta="20"
width="394">
- Start Location:
+ Start location:
</text>
<combo_box
control_name="LoginLocation"
@@ -213,7 +213,7 @@
control_name="ShowStartLocation"
height="16"
initial_value="true"
- label="Show on Login"
+ label="Show on login"
layout="topleft"
left_delta="175"
name="show_location_checkbox"
@@ -272,7 +272,7 @@
layout="topleft"
left_delta="0"
name="show_my_name_checkbox1"
- top_pad="5"
+ top_pad="-7"
width="300" />
<check_box
enabled_control="AvatarNameTagMode"
@@ -303,7 +303,7 @@
layout="topleft"
left="30"
name="effects_color_textbox"
- top_pad="10"
+ top_pad="5"
width="400">
My Effects:
</text>
@@ -316,7 +316,76 @@
left_delta="50"
name="effect_color_swatch"
tool_tip="Click to open Color Picker"
- top_pad="10"
+ top_pad="5"
width="32" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="30"
+ name="title_afk_text"
+ text_color="white"
+ top_pad="-5"
+ width="190">
+ Away timeout:
+ </text>
+ <spinner
+ control_name="AFKTimeout"
+ decimal_digits="0"
+ follows="left|top"
+ halign="right"
+ height="15"
+ increment="1"
+ initial_value="300"
+ label=""
+ label_width="0"
+ layout="topleft"
+ left_delta="50"
+ max_val="600"
+ min_val="30"
+ name="afk_timeout_spinner"
+ top_pad="5"
+ width="50" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="left"
+ height="15"
+ layout="topleft"
+ left_pad="2"
+ name="seconds_textbox"
+ width="70">
+ seconds
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ text_color="white"
+ left="30"
+ mouse_opaque="false"
+ name="text_box3"
+ top_pad="10"
+ width="240">
+ Busy mode response:
+ </text>
+ <text_editor
+ control_name="BusyModeResponse2"
+ commit_on_focus_lost = "true"
+ follows="left|top"
+ height="56"
+ layout="topleft"
+ left_delta="50"
+ name="busy_response"
+ width="400"
+ word_wrap="true"
+ top_pad="5">
+ 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
index ecfb0048a3..b1308a1942 100644
--- a/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
+++ b/indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml
@@ -26,7 +26,7 @@
height="16"
label="Use fullscreen"
layout="topleft"
- left_delta="30"
+ left_delta="50"
name="windowed mode"
top_pad="4"
width="175">
@@ -48,41 +48,36 @@
length="1"
enabled="true"
name="640x480"
- value="640 x 480">
- 640x480
- </combo_box.item>
+ value="640 x 480"
+ label="640x480"/>
<combo_box.item
type="string"
length="1"
enabled="true"
name="800x600"
- value="800 x 600">
- 800x600
- </combo_box.item>
+ value="800 x 600"
+ label="800x600"/>
<combo_box.item
type="string"
length="1"
enabled="true"
name="720x480"
- value="720 x 480">
- 720x480 (NTSC)
- </combo_box.item>
+ value="720 x 480"
+ label="720x480 (NTSC)"/>
<combo_box.item
type="string"
length="1"
enabled="true"
name="768x576"
- value="768 x 576">
- 768x576 (PAL)
- </combo_box.item>
+ value="768 x 576"
+ label="768x576 (PAL)"/>
<combo_box.item
type="string"
length="1"
enabled="true"
name="1024x768"
- value="1024 x 768">
- 1024x768
- </combo_box.item>
+ value="1024 x 768"
+ label="1024x768"/>
<combo_box.commit_callback
function="Pref.setControlFalse"
parameter="FullScreenAutoDetectAspectRatio" />
@@ -97,7 +92,7 @@
name="UI Size:"
top_pad="4"
width="300">
- UI Size:
+ UI size:
</text>
<slider
can_edit_text="true"
@@ -108,7 +103,7 @@
increment="0.025"
initial_value="1"
layout="topleft"
- left_delta="32"
+ left_delta="52"
max_val="1.4"
min_val="0.75"
name="ui_scale_slider"
@@ -295,7 +290,7 @@
control_name="RenderObjectBump"
height="16"
initial_value="true"
- label="Bump Mapping and Shiny"
+ label="Bump mapping and shiny"
layout="topleft"
left_delta="0"
name="BumpShiny"
@@ -305,11 +300,11 @@
control_name="VertexShaderEnable"
height="16"
initial_value="true"
- label="Basic Shaders"
+ label="Basic shaders"
layout="topleft"
left_delta="0"
name="BasicShaders"
- tool_tip="Disabling this option may prevent some graphics card drivers from crashing."
+ tool_tip="Disabling this option may prevent some graphics card drivers from crashing"
top_pad="1"
width="315">
<check_box.commit_callback
@@ -319,7 +314,7 @@
control_name="WindLightUseAtmosShaders"
height="16"
initial_value="true"
- label="Atmospheric Shaders"
+ label="Atmospheric shaders"
layout="topleft"
left_delta="0"
name="WindLightUseAtmosShaders"
@@ -332,7 +327,7 @@
control_name="RenderWaterReflections"
height="16"
initial_value="true"
- label="Water Reflections"
+ label="Water reflections"
layout="topleft"
left_delta="0"
name="Reflections"
@@ -351,7 +346,7 @@
name="ReflectionDetailText"
top_pad="7"
width="128">
- Reflection Detail:
+ Reflection detail:
</text>
<radio_group
control_name="RenderReflectionDetail"
@@ -364,7 +359,7 @@
width="321">
<radio_item
height="16"
- label="Terrain and Trees"
+ label="Terrain and trees"
layout="topleft"
left="3"
name="0"
@@ -372,7 +367,7 @@
width="315" />
<radio_item
height="16"
- label="All Static Objects"
+ label="All static objects"
layout="topleft"
left_delta="0"
name="1"
@@ -380,7 +375,7 @@
width="315" />
<radio_item
height="16"
- label="All Avatars and Objects"
+ label="All avatars and objects"
layout="topleft"
left_delta="0"
name="2"
@@ -405,13 +400,13 @@
name="AvatarRenderingText"
top_pad="5"
width="128">
- Avatar Rendering:
+ Avatar rendering:
</text>
<check_box
control_name="RenderUseImpostors"
height="16"
initial_value="true"
- label="Avatar Impostors"
+ label="Avatar impostors"
layout="topleft"
left_delta="0"
name="AvatarImpostors"
@@ -421,7 +416,7 @@
control_name="RenderAvatarVP"
height="16"
initial_value="true"
- label="Hardware Skinning"
+ label="Hardware skinning"
layout="topleft"
left_delta="0"
name="AvatarVertexProgram"
@@ -434,7 +429,7 @@
control_name="RenderAvatarCloth"
height="16"
initial_value="true"
- label="Avatar Cloth"
+ label="Avatar cloth"
layout="topleft"
left_delta="0"
name="AvatarCloth"
@@ -448,7 +443,7 @@
height="16"
increment="8"
initial_value="160"
- label="Draw Distance:"
+ label="Draw distance:"
label_width="140"
layout="topleft"
left="216"
@@ -479,7 +474,7 @@
height="16"
increment="256"
initial_value="4096"
- label="Max. Particle Count:"
+ label="Max. particle count:"
label_width="140"
layout="topleft"
left="216"
@@ -494,7 +489,7 @@
height="16"
increment="1"
initial_value="8"
- label="Post Process Quality:"
+ label="Post process quality:"
label_width="140"
layout="topleft"
left_delta="0"
@@ -518,7 +513,7 @@
name="MeshDetailText"
top_pad="5"
width="128">
- Mesh Detail:
+ Mesh detail:
</text>
<slider
control_name="RenderVolumeLODFactor"
@@ -729,7 +724,7 @@
name="LightingDetailText"
top_pad="8"
width="128">
- Lighting Detail:
+ Lighting detail:
</text>
<radio_group
control_name="RenderLightingDetail"
@@ -767,7 +762,7 @@
name="TerrainDetailText"
top="465"
width="128">
- Terrain Detail:
+ Terrain detail:
</text>
<radio_group
control_name="RenderTerrainDetail"
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..ce7939c00f
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_privacy.xml
@@ -0,0 +1,219 @@
+<?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="20"
+ 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
+ control_name="AutoPlayMedia"
+ height="16"
+ label="Allow Media Autoplay"
+ layout="topleft"
+ left="30"
+ name="autoplay_enabled"
+ top_pad="10"
+ width="350" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="30"
+ mouse_opaque="false"
+ top_pad="10"
+ width="350">
+ Logs:
+ </text>
+ <check_box
+
+ enabled="false"
+ control_name="LogInstantMessages"
+ height="16"
+ label="Save logs on my computer"
+ layout="topleft"
+ left="30"
+ name="log_instant_messages"
+ top_pad="10"
+ width="350">
+ <check_box.commit_callback
+ function="Pref.Logging" />
+ </check_box>
+ <radio_group
+ control_name="IMLogOptions"
+ enabled="false"
+ height="80"
+ layout="topleft"
+ left_delta="50"
+ name="ChatIMLogs"
+ width="350"
+ top_pad="0">
+ <radio_item
+ height="16"
+ label="Chat"
+ layout="topleft"
+ left="0"
+ name="radio1"
+ top="3"
+ width="200" />
+ <radio_item
+ height="16"
+ label="IM"
+ layout="topleft"
+ left_delta="0"
+ name="radio2"
+ top_pad="3"
+ width="200" />
+ <radio_item
+ height="16"
+ label="Both, together"
+ layout="topleft"
+ left_delta="0"
+ name="radio3"
+ top_pad="3"
+ width="200" />
+ <radio_item
+ height="16"
+ label="Both, separate"
+ layout="topleft"
+ left_delta="0"
+ name="radio4"
+ top_pad="3"
+ width="200" />
+ </radio_group>
+ <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" />
+ <line_editor
+ bottom="366"
+ control_name="InstantMessageLogFolder"
+ enabled="false"
+ follows="top|left|right"
+ halign="right"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ name="log_path_string"
+ top_pad="5" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ top_pad="1"
+ width="128"
+ text_color="LtGray_50">
+ Location of logs
+ </text>
+ <button
+ enabled="false"
+ follows="right|bottom"
+ height="20"
+ label="Browse"
+ label_selected="Browse"
+ layout="topleft"
+ left_pad="115"
+ name="log_path_button"
+ top_delta="-21"
+ width="145">
+ <button.commit_callback
+ function="Pref.LogPath" />
+ </button>
+ <button
+ follows="left|bottom"
+ height="20"
+ 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..9cf0bd26d8
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_setup.xml
@@ -0,0 +1,341 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="left|top|right|bottom"
+ height="408"
+ label="Input &amp; Camera"
+ layout="topleft"
+ left="102"
+ name="Input panel"
+ top="1"
+ width="517">
+ <button
+ height="20"
+ 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="10"
+ initial_value="50"
+ layout="topleft"
+ left_delta="150"
+ max_val="1500"
+ min_val="50"
+ 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="BrowserProxyPort"
+ enabled_control="BrowserProxyEnabled"
+ decimal_digits="0"
+ follows="left|top"
+ height="16"
+ increment="1"
+ initial_value="80"
+ label="Port number:"
+ label_width="75"
+ layout="topleft"
+ left_delta="160"
+ max_val="12000"
+ min_val="10"
+ name="web_proxy_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="10"
+ initial_value="50"
+ layout="topleft"
+ left_delta="150"
+ max_val="1000"
+ min_val="10"
+ name="cache_size"
+ top_delta="-1"
+ 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>
+ <line_editor
+ control_name="CacheLocationTopFolder"
+ border_style="line"
+ border_thickness="1"
+ enabled="false"
+ follows="left|top"
+ font="SansSerif"
+ handle_edit_keys_directly="true"
+ height="20"
+ layout="topleft"
+ left="80"
+ max_length="4096"
+ name="cache_location"
+ top_pad="20"
+ width="205" />
+ <button
+ follows="left|top"
+ height="22"
+ 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="22"
+ label="Reset"
+ label_selected="Set"
+ 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="80"
+ name="Cache location"
+ top_delta="20"
+ width="300"
+ text_color="LtGray_50">
+ Cache location
+ </text>
+ <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"
+ 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)"
+ layout="topleft"
+ left_delta="0"
+ name="external"
+ 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"
+ label="Web proxy"
+ left_delta="0"
+ mouse_opaque="true"
+ name="web_proxy_enabled"
+ radio_style="false"
+ width="400" />
+ <line_editor
+ control_name="BrowserProxyAddress"
+ enabled_control="BrowserProxyEnabled"
+ follows="left|top"
+ font="SansSerif"
+ height="20"
+ layout="topleft"
+ left_delta="1"
+ name="web_proxy_editor"
+ tool_tip="The name or IP address of the proxy you would like to use"
+ top_pad="4"
+ width="200" />
+ <button
+ follows="left|top"
+ height="22"
+ enabled="false"
+ label="Browse"
+ label_selected="Browse"
+ layout="topleft"
+ left_pad="5"
+ name="set_proxy"
+ top_pad="-21"
+ width="100">
+ <button.commit_callback
+ function="Pref.SetCache" />
+ </button>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="-203"
+ name="Proxy location"
+ top_delta="20"
+ width="300"
+ text_color="LtGray_50">
+ Proxy location
+ </text></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..c3e0cb352b
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_preferences_sound.xml
@@ -0,0 +1,520 @@
+<?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_pad="5"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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="right|top"
+ height="16"
+ control_name ="EnableVoiceChat"
+ disabled_control="CmdLineDisableVoice"
+ label="Voice"
+ left="50"
+ 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_width="0"
+ layout="topleft"
+ left="165"
+ top_delta="0"
+ name="Voice Volume"
+ show_text="false"
+ slider_label.halign="right"
+ volume="true"
+ width="185">
+ <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_drk_VoiceNo"
+ image_unselected="parcel_drk_Voice"
+ 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="170"
+ name="Listen from"
+ width="200">
+ Listen from:
+ </text>
+ <icon
+ follows="left"
+ height="18"
+ image_name="Cam_FreeCam_Off"
+ name="camera_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18" />
+ <icon
+ follows="left"
+ height="18"
+ image_name="Move_Walk_Off"
+ name="avatar_icon"
+ mouse_opaque="false"
+ visible="true"
+ width="18" />
+ <radio_group
+ enabled_control="EnableVoiceChat"
+ control_name="VoiceEarLocation"
+ draw_border="false"
+ follows="left"
+ left_delta="20"
+ top = "210"
+ width="221"
+ height="38"
+ name="ear_location">
+ <radio_item
+ height="16"
+ label="Camera position"
+ left_pad="1"
+ follows="topleft"
+ name="0"
+ top_delta="-30"
+ width="200" />
+ <radio_item
+ height="16"
+ follows="topleft"
+ label="Avatar position"
+ left_delta="0"
+ name="1"
+ top_delta="19"
+ width="200" />
+ </radio_group>
+ <button
+ control_name="ShowDeviceSettings"
+ follows="left|bottom"
+ height="19"
+ is_toggle="true"
+ label="Input / Output Devices"
+ layout="topleft"
+ left="165"
+ top_pad="12"
+ name="device_settings_btn"
+ width="190">
+ </button>
+ <panel
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ visiblity_control="ShowDeviceSettings"
+ border="false"
+ follows="top|left"
+ height="145"
+ label="DeviceSettings"
+ layout="topleft"
+ left="0"
+ name="device_settings_panel"
+ class="panel_voice_device_settings"
+ width="501">
+ <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="19"
+ control_name="VoiceInputAudioDevice"
+ layout="topleft"
+ left="165"
+ max_chars="128"
+ name="voice_input_device"
+ top_pad="0"
+ width="200" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="165"
+ name="My volume label"
+ top_pad="10"
+ 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="0"
+ 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="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" />
+ <!-- <text
+ type="string"
+ height="37"
+ left="30"
+ name="voice_intro_text1"
+ top_pad="-4"
+ width="410"
+ word_wrap="true">
+ Adjust the slider to control how loud you sound to other people. To test your volume, simply speak into your microphone
+ </text>-->
+ <icon
+ height="18"
+ image_name="parcel_lght_Voice"
+ 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="19"
+ layout="topleft"
+ left="165"
+ max_chars="128"
+ name="voice_output_device"
+ top_pad="0"
+ width="200" />
+ </panel>
+ <!-- Until new panel is hooked up to code, we need to be able to get to
+ the old window to change input devices. James -->
+ <button
+ follows="left|bottom"
+ label="Old"
+ name="legacy_device_window_btn"
+ height="16"
+ left="20"
+ top="-270"
+ width="40"
+ commit_callback.function="Floater.Show"
+ commit_callback.parameter="pref_voicedevicesettings"
+ />
+ </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..fc5ccdb63e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_prim_media_controls.xml
@@ -0,0 +1,580 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ follows="left|right|top|bottom"
+ name="MediaControls"
+ bg_alpha_color="1 1 1 0"
+ height="160"
+ layout="topleft"
+ mouse_opaque="false"
+ width="800">
+ <panel
+ name="media_region"
+ bottom="125"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="20"
+ mouse_opaque="false"
+ right="-20"
+ top="20" />
+ <layout_stack
+ follows="left|right|bottom"
+ height="32"
+ layout="topleft"
+ animate="false"
+ left="0"
+ orientation="horizontal"
+ top="96">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ <panel
+ name="media_progress_indicator"
+ height="22"
+ layout="topleft"
+ left="0"
+ top="0"
+ auto_resize="false"
+ user_resize="false"
+ min_width="100"
+ width="200">
+ <progress_bar
+ name="media_progress_bar"
+ color_bar="1 1 1 0.96"
+ follows="left|right|top"
+ height="16"
+ layout="topleft"
+ left="0"
+ tool_tip="Media is Loading"/>
+ </panel>
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+ <layout_stack
+ name="media_controls"
+ follows="left|right"
+ animate="false"
+ height="32"
+ layout="topleft"
+ left="0"
+ orientation="horizontal"
+ top="128">
+ <!-- outer layout_panels center the inner one -->
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ <layout_panel
+ name="back"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="22"
+ width="22"
+ top="4">
+ <button
+ auto_resize="false"
+ height="22"
+ image_selected="media_btn_back.png"
+ image_unselected="media_btn_back.png"
+ layout="topleft"
+ tool_tip="Step back"
+ width="22"
+ top_delta="4">
+ <button.commit_callback
+ function="MediaCtrl.Back" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="fwd"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="10"
+ min_width="17"
+ width="17">
+ <button
+ height="22"
+ image_selected="media_btn_forward.png"
+ image_unselected="media_btn_forward.png"
+ layout="topleft"
+ tool_tip="Step forward"
+ top_delta="0"
+ min_width="17"
+ width="17">
+ <button.commit_callback
+ function="MediaCtrl.Forward" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="home"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="-2"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_home.png"
+ image_unselected="media_btn_home.png"
+ layout="topleft"
+ tool_tip="Home page"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Home" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="media_stop"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="2"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_stop.tga"
+ image_unselected="button_anim_stop.tga"
+ layout="topleft"
+ tool_tip="Stop media"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="reload"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="6"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_reload.png"
+ image_unselected="media_btn_reload.png"
+ layout="topleft"
+ tool_tip="Reload"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Reload" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="stop"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="10"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_stoploading.png"
+ image_unselected="media_btn_stoploading.png"
+ layout="topleft"
+ tool_tip = "Stop loading"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Stop" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="play"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="14"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_play.tga"
+ image_unselected="button_anim_play.tga"
+ layout="topleft"
+ tool_tip = "Play media"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Play" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="pause"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ top="18"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="button_anim_pause.tga"
+ image_unselected="button_anim_pause.tga"
+ layout="topleft"
+ tool_tip = "Pause media">
+ <button.commit_callback
+ function="MediaCtrl.Pause" />
+ </button>
+ </layout_panel>
+ <!-- media URL entry -->
+ <layout_panel
+ name="media_address"
+ auto_resize="true"
+ user_resize="false"
+ height="22"
+ follows="left|right|bottom"
+ layout="topleft"
+ width="190"
+ min_width="90">
+ <!--
+ RE-ENABLE THIS WHEN WE HAVE A HISTORY DROP-DOWN AGAIN
+
+<combo_box
+name="media_address_url"
+allow_text_entry="true"
+height="22"
+layout="topleft"
+max_chars="1024"
+tool_tip = "Media URL"
+<combo_box.commit_callback
+function="MediaCtrl.CommitURL" />
+</combo_box>
+ -->
+ <line_editor
+ name="media_address_url"
+ follows="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
+ animate="false"
+ follows="right"
+ width="32"
+ min_width="32"
+ height="16"
+ top="3"
+ orientation="horizontal"
+ left_pad="-38">
+ <icon
+ name="media_whitelist_flag"
+ follows="top|right"
+ height="16"
+ image_name="smicon_warn.tga"
+ layout="topleft"
+ tool_tip="White List enabled"
+ min_width="16"
+ width="16" />
+ <icon
+ name="media_secure_lock_flag"
+ height="16"
+ image_name="inv_item_eyes.tga"
+ layout="topleft"
+ tool_tip="Secured Browsing"
+ min_width="16"
+ width="16" />
+ </layout_stack>
+ </layout_panel>
+ <layout_panel
+ name="media_play_position"
+ auto_resize="true"
+ user_resize="false"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ min_width="100"
+ width="200">
+ <slider_bar
+ name="media_play_slider"
+ follows="left|right|top"
+ height="22"
+ increment="0.05"
+ initial_value="0.5"
+ layout="topleft"
+ tool_tip="Movie play progress"
+ min_width="100"
+ width="200">
+ <slider_bar.commit_callback
+ function="MediaCtrl.JumpProgress" />
+ </slider_bar>
+ </layout_panel>
+ <layout_panel
+ name="media_volume"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ height="24"
+ min_width="24"
+ width="24">
+ <button
+ name="media_volume_button"
+ height="22"
+ image_selected="icn_speaker-muted_dark.tga"
+ image_unselected="icn_speaker_dark.tga"
+ is_toggle="true"
+ layout="topleft"
+ scale_image="false"
+ tool_tip="Mute This Media"
+ top_delta="22"
+ min_width="24"
+ width="24" >
+ <button.commit_callback
+ function="MediaCtrl.ToggleMute" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_up"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="20"
+ height="14"
+ width="20">
+ <button
+ top="-3"
+ height="14"
+ image_selected="media_btn_scrollup.png"
+ image_unselected="media_btn_scrollup.png"
+ layout="topleft"
+ tool_tip="Volume up"
+ scale_image="true"
+ min_width="20"
+ width="20" >
+ <button.commit_callback
+ function="MediaCtrl.CommitVolumeUp" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ name="volume_down"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="20"
+ height="14"
+ width="20">
+ <button
+ top="-5"
+ height="14"
+ image_selected="media_btn_scrolldown.png"
+ image_unselected="media_btn_scrolldown.png"
+ layout="topleft"
+ tool_tip="Volume down"
+ scale_image="true"
+ min_width="20"
+ width="20">
+ <button.commit_callback
+ function="MediaCtrl.CommitVolumeDown" />
+ </button>
+ </layout_panel>
+ <!-- Scroll pad -->
+<!--
+disabled
+ <layout_panel
+ name="media_panel_scroll"
+ auto_resize="false"
+ user_resize="false"
+ height="32"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ min_width="32"
+ width="32">
+ <icon
+ height="32"
+ image_name="media_panel_scrollbg.png"
+ layout="topleft"
+ top="0"
+ min_width="32"
+ width="32" />
+ <button
+ name="scrollup"
+ height="8"
+ image_selected="media_btn_scrollup.png"
+ image_unselected="media_btn_scrollup.png"
+ layout="topleft"
+ tool_tip="Scroll up"
+ scale_image="false"
+ left="12"
+ top_delta="4"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrollleft"
+ height="8"
+ image_selected="media_btn_scrollleft.png"
+ image_unselected="media_btn_scrollleft.png"
+ layout="topleft"
+ left="3"
+ tool_tip="Scroll left"
+ scale_image="false"
+ top="12"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrollright"
+ height="8"
+ image_selected="media_btn_scrollright.png"
+ image_unselected="media_btn_scrollright.png"
+ layout="topleft"
+ left_pad="9"
+ tool_tip="Scroll right"
+ scale_image="false"
+ top_delta="0"
+ min_width="8"
+ width="8" />
+ <button
+ name="scrolldown"
+ height="8"
+ image_selected="media_btn_scrolldown.png"
+ image_unselected="media_btn_scrolldown.png"
+ layout="topleft"
+ left="12"
+ tool_tip="Scroll down"
+ scale_image="false"
+ top="20"
+ min_width="8"
+ width="8" />
+ </layout_panel>
+disabled
+-->
+ <layout_panel
+ name="zoom_frame"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ height="28"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_optimalzoom.png"
+ image_unselected="media_btn_optimalzoom.png"
+ layout="topleft"
+ tool_tip="Zoom"
+ min_width="22"
+ width="22">
+ <button.commit_callback
+ function="MediaCtrl.Zoom" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="new_window"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="22"
+ width="22">
+ <button
+ height="22"
+ image_selected="media_btn_newwindow.png"
+ image_unselected="media_btn_newwindow.png"
+ layout="topleft"
+ tool_tip = "Open URL in browser"
+ top_delta="-3"
+ min_width="24"
+ width="24" >
+ <button.commit_callback
+ function="MediaCtrl.Open" />
+ </button>
+ </layout_panel>
+<!--
+ <panel
+ height="22"
+ layout="topleft"
+ auto_resize="false"
+ min_width="3"
+ width="3">
+ <icon
+ height="22"
+ image_name="media_panel_divider.png"
+ layout="topleft"
+ top="0"
+ min_width="3"
+ width="3" />
+ </panel>
+-->
+ <layout_panel
+ name="close"
+ auto_resize="false"
+ user_resize="false"
+ layout="topleft"
+ min_width="21"
+ width="21" >
+ <button
+ height="22"
+ image_selected="media_btn_done.png"
+ image_unselected="media_btn_done.png"
+ layout="topleft"
+ tool_tip ="Close media control"
+ top_delta="-4"
+ width="21" >
+ <button.commit_callback
+ function="MediaCtrl.Close" />
+ </button>
+ </layout_panel>
+ <layout_panel
+ width="0"
+ layout="topleft"
+ user_resize="false" />
+ </layout_stack>
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml
index 78aff64216..23d55b33e2 100644
--- a/indra/newview/skins/default/xui/en/panel_profile.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel
follows="all"
- height="560"
+ height="535"
label="Profile"
layout="topleft"
left="0"
@@ -10,7 +10,8 @@
width="313">
<string
name="CaptionTextAcctInfo">
- [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION]
+ [ACCTTYPE]
+[PAYMENTINFO] [AGEVERIFICATION]
</string>
<string
name="payment_update_link_url">
@@ -26,33 +27,32 @@
<string
name="no_partner_text"
value="None" />
- <scroll_container
+ <scroll_container
color="DkGray2"
- follows="left|top|right|bottom"
- height="500"
- min_height="300"
+ follows="all"
+ height="485"
layout="topleft"
name="profile_scroll"
reserve_scroll_corner="true"
opaque="true"
top="0"
width="313">
+ <panel
+ name="scroll_content_panel"
+ follows="left|top|right"
+ height="485"
+ layout="topleft"
+ top="0"
+ left="0"
+ width="313">
<panel
- name="scroll_content_panel"
- follows="left|top|right"
- layout="topleft"
- top="0"
- left="0"
- width="300"
- height="700">
- <panel
- follows="left|top"
- height="117"
- layout="topleft"
- left="10"
- name="second_life_image_panel"
- top="10"
- width="285">
+ follows="left|top"
+ height="117"
+ layout="topleft"
+ left="10"
+ name="second_life_image_panel"
+ top="0"
+ width="280">
<texture_picker
allow_no_texture="true"
default_image_name="None"
@@ -66,7 +66,6 @@
width="102" />
<text
follows="left|top|right"
- font="SansSerifSmall"
font.style="BOLD"
height="15"
layout="topleft"
@@ -75,15 +74,18 @@
text_color="white"
top_delta="0"
value="[SECOND_LIFE]:"
- width="170" />
+ width="165" />
<expandable_text
follows="left|top|right"
- height="90"
+ height="95"
layout="topleft"
+ left="107"
+ textbox.max_length="512"
name="sl_description_edit"
- width="170"
+ top_pad="-3"
+ width="173"
expanded_bg_visible="true"
- expanded_bg_color="black">
+ 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>
@@ -94,7 +96,7 @@
top_pad="10"
left="10"
name="first_life_image_panel"
- width="285">
+ width="280">
<texture_picker
allow_no_texture="true"
default_image_name="None"
@@ -107,7 +109,6 @@
width="102" />
<text
follows="left|top|right"
- font="SansSerifSmall"
font.style="BOLD"
height="15"
layout="topleft"
@@ -116,15 +117,18 @@
text_color="white"
top_delta="0"
value="Real World:"
- width="175" />
+ width="165" />
<expandable_text
follows="left|top|right"
- height="90"
+ height="95"
layout="topleft"
+ left="107"
+ textbox.max_length="512"
name="fl_description_edit"
- width="170"
+ top_pad="-3"
+ width="173"
expanded_bg_visible="true"
- expanded_bg_color="black">
+ 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>
@@ -138,7 +142,7 @@
left="10"
name="me_homepage_text"
text_color="white"
- top_pad="10"
+ top_pad="0"
width="280">
Homepage:
</text>
@@ -148,19 +152,21 @@
layout="topleft"
left="10"
name="homepage_edit"
+ top_pad="0"
value="http://librarianavengers.org"
width="280"
- word_wrap="false" />
+ word_wrap="false"
+ use_ellipses="true"
+ />
<text
follows="left|top"
- font="SansSerifSmall"
font.style="BOLD"
- height="15"
+ height="10"
layout="topleft"
left="10"
name="title_member_text"
text_color="white"
- top_pad="20"
+ top_pad="10"
value="Member Since:"
width="280" />
<text
@@ -169,20 +175,18 @@
layout="topleft"
left="10"
name="register_date"
- top_pad="5"
value="05/31/1976"
width="280"
word_wrap="true" />
<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="15"
+ top_pad="10"
value="Account Status:"
width="280" />
<!-- <text
@@ -198,24 +202,23 @@
width="100"/> -->
<text
follows="left|top"
- height="15"
+ height="20"
layout="topleft"
left="10"
name="acc_status_text"
- top_pad="5"
+ top_pad="0"
value="Resident. No payment info on file."
width="280"
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="15"
+ top_pad="5"
value="Partner:"
width="280" />
<panel
@@ -224,11 +227,11 @@
layout="topleft"
left="10"
name="partner_data_panel"
- top_pad="5"
+ top_pad="0"
width="280">
<text
follows="left|top"
- height="15"
+ height="10"
layout="topleft"
left="0"
name="partner_text"
@@ -239,107 +242,111 @@
</panel>
<text
follows="left|top"
- font="SansSerifSmall"
font.style="BOLD"
height="15"
layout="topleft"
left="10"
name="title_groups_text"
text_color="white"
- top_pad="15"
+ top_pad="8"
value="Groups:"
width="280" />
- <text
+ <expandable_text
follows="left|top|bottom"
- height="160"
+ height="60"
layout="topleft"
left="10"
- name="sl_groups"
- top_pad="5"
+ name="sl_groups"
+ top_pad="0"
width="280"
- word_wrap="true">
+ 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.
- </text>
+ </expandable_text>
</panel>
- </scroll_container>
-
- <panel
+ </scroll_container>
+ <panel
follows="bottom|left"
layout="topleft"
left="0"
name="profile_buttons_panel"
- top_pad="0"
- height="25"
- width="313">
+ top_pad="2"
+ bottom="10"
+ height="19"
+ width="303">
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
label="Add Friend"
layout="topleft"
left="0"
mouse_opaque="false"
name="add_friend"
- top="0"
- width="90" />
+ top="5"
+ width="75" />
<button
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
label="IM"
layout="topleft"
name="im"
- top="0"
- left_pad="0"
- width="40" />
+ top="5"
+ left_pad="5"
+ width="45" />
<button
enabled="false"
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
label="Call"
layout="topleft"
name="call"
- left_pad="0"
- top="0"
- width="50" />
+ left_pad="5"
+ top="5"
+ width="45" />
<button
+ enabled="false"
follows="bottom|left"
- font="SansSerifSmallBold"
- height="25"
+ height="19"
+ label="Map"
+ layout="topleft"
+ name="show_on_map_btn"
+ top="5"
+ left_pad="5"
+ width="45" />
+ <button
+ follows="bottom|left"
+ height="19"
label="Teleport"
layout="topleft"
name="teleport"
- left_pad="0"
- top="0"
- width="77" />
- </panel>
- <panel
+ left_pad="5"
+ top="5"
+ width="80" />
+ </panel>
+ <panel
follows="bottom|left"
layout="topleft"
left="0"
+ top_pad="-17"
name="profile_me_buttons_panel"
- top_pad="0"
visible="false"
- height="25"
- width="313">
+ height="19"
+ width="303">
<button
- follows="bottom|left"
- height="23"
+ follows="bottom|right"
+ font="SansSerifSmall"
+ height="19"
+ left="10"
label="Edit Profile"
- layout="topleft"
- left="0"
name="edit_profile_btn"
- top="0"
width="130" />
<button
- follows="bottom|left"
- height="23"
+ follows="bottom|right"
+ height="19"
label="Edit Appearance"
- layout="topleft"
- left_pad="5"
+ left_pad="10"
name="edit_appearance_btn"
- top="0"
+ right="-10"
width="130" />
- </panel>
+ </panel>
</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
index 606535115d..b015346a79 100644
--- a/indra/newview/skins/default/xui/en/panel_profile_view.xml
+++ b/indra/newview/skins/default/xui/en/panel_profile_view.xml
@@ -5,7 +5,6 @@
height="570"
layout="topleft"
min_height="350"
- min_width="240"
name="panel_target_profile"
width="333">
<string
@@ -16,65 +15,70 @@
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
follows="top|left|right"
font="SansSerifHugeBold"
- height="20"
+ height="26"
layout="topleft"
- left="10"
+ left_pad="10"
name="user_name"
text_color="white"
top="0"
value="(Loading...)"
- width="250" />
+ use_ellipses="true"
+ width="275" />
<text
follows="top|left"
- height="16"
+ height="13"
layout="topleft"
- left="10"
+ left="45"
name="status"
text_color="LtGray_50"
- top_pad="5"
value="Online"
- width="100" />
- <button
- follows="top|right"
- height="25"
- image_overlay="BackArrow_Off"
- layout="topleft"
- name="back"
- picture_style="true"
- right="-10"
- tab_stop="false"
- top="0"
- width="25" />
+ width="150" />
<tab_container
- follows="left|top|right|bottom"
- height="560"
+ follows="all"
+ height="535"
+ halign="center"
layout="topleft"
left="10"
+ min_width="333"
name="tabs"
- tab_min_width="75"
+ tab_min_width="80"
+ tab_height="30"
tab_position="top"
- top_pad="15"
- width="285">
+ top_pad="10"
+ width="313">
<panel
class="panel_profile"
filename="panel_profile.xml"
- label="Profile"
+ label="PROFILE"
layout="topleft"
+ help_topic="profile_profile_tab"
name="panel_profile" />
<panel
class="panel_picks"
filename="panel_picks.xml"
- label="Picks"
+ label="PICKS"
layout="topleft"
+ help_topic="profile_picks_tab"
name="panel_picks" />
<panel
class="panel_notes"
filename="panel_notes.xml"
- label="Notes &amp; Privacy"
+ 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
index 9abaf29f57..18c2228906 100644
--- a/indra/newview/skins/default/xui/en/panel_progress.xml
+++ b/indra/newview/skins/default/xui/en/panel_progress.xml
@@ -62,7 +62,7 @@
<text
follows="left|right|top"
font="SansSerifHuge"
- font_shadow="hard"
+ font_shadow="none"
halign="left"
height="20"
layout="topleft"
@@ -74,7 +74,7 @@
<text
follows="left|right|top"
font="SansSerif"
- font_shadow="hard"
+ font_shadow="none"
halign="left"
height="20"
layout="topleft"
@@ -96,7 +96,7 @@
<text
follows="left|right|top|bottom"
font="SansSerifLarge"
- font_shadow="hard"
+ font_shadow="none"
halign="left"
height="100"
layout="topleft"
@@ -129,7 +129,6 @@
layout="topleft"
left="-106"
name="cancel_btn"
- picture_style="true"
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
index b3147f5e6b..49fc930cd8 100644
--- a/indra/newview/skins/default/xui/en/panel_region_covenant.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_covenant.xml
@@ -103,17 +103,6 @@
width="308">
Last Modified Wed Dec 31 16:00:00 1969
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="5"
- name="covenant_help"
- top_delta="-2"
- width="18" />
-
<text_editor
enabled="false"
follows="left|top"
diff --git a/indra/newview/skins/default/xui/en/panel_region_debug.xml b/indra/newview/skins/default/xui/en/panel_region_debug.xml
index 78e5678455..a1bca4229d 100644
--- a/indra/newview/skins/default/xui/en/panel_region_debug.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_debug.xml
@@ -40,16 +40,6 @@
tool_tip="Disable all scripts in this region"
top="30"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="70"
- name="disable_scripts_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Disable Collisions"
@@ -59,16 +49,6 @@
tool_tip="Disable non-avatar collisions in this region"
top="50"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="70"
- name="disable_collisions_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Disable Physics"
@@ -79,16 +59,6 @@
top="70"
width="80" />
<button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="70"
- name="disable_physics_help"
- top_delta="2"
- width="18" />
- <button
enabled="false"
follows="left|top"
font="SansSerifSmall"
@@ -162,7 +132,7 @@
layout="topleft"
left_delta="60"
name="return_scripts"
- tool_tip="Return only objects which have scripts."
+ tool_tip="Return only objects which have scripts"
top_delta="0"
width="80" />
<check_box
@@ -207,16 +177,6 @@
<button
follows="left|top"
font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="top_colliders_help"
- top_delta="2"
- width="18" />
- <button
- follows="left|top"
- font="SansSerifSmall"
height="20"
label="Get Top Scripts..."
layout="topleft"
@@ -228,16 +188,6 @@
<button
follows="left|top"
font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="top_scripts_help"
- top_delta="2"
- width="18" />
- <button
- follows="left|top"
- font="SansSerifSmall"
height="20"
label="Restart Region"
layout="topleft"
@@ -249,16 +199,6 @@
<button
follows="left|top"
font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="restart_help"
- top_delta="2"
- width="18" />
- <button
- follows="left|top"
- font="SansSerifSmall"
height="20"
label="Delay Restart"
layout="topleft"
diff --git a/indra/newview/skins/default/xui/en/panel_region_estate.xml b/indra/newview/skins/default/xui/en/panel_region_estate.xml
index afcefcbd3b..add1476179 100644
--- a/indra/newview/skins/default/xui/en/panel_region_estate.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_estate.xml
@@ -94,16 +94,6 @@ regions in the estate.
name="use_global_time_check"
top="132"
width="200" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="20"
- name="use_global_time_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Fixed Sun"
@@ -112,16 +102,6 @@ regions in the estate.
name="fixed_sun_check"
top="152"
width="100" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="120"
- name="fixed_sun_help"
- top_delta="2"
- width="18" />
<icon
height="20"
image_name="icon_day_cycle.tga"
@@ -151,16 +131,6 @@ regions in the estate.
name="externally_visible_check"
top_pad="6"
width="200" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="20"
- name="externally_visible_help"
- top_delta="2"
- width="18" />
<text
type="string"
length="1"
@@ -180,7 +150,7 @@ regions in the estate.
layout="topleft"
left_delta="0"
name="limit_payment"
- tool_tip="Ban unidentified residents."
+ tool_tip="Ban unidentified residents"
top_pad="2"
width="278" />
<check_box
@@ -201,16 +171,6 @@ regions in the estate.
name="voice_chat_check"
top="304"
width="200" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="20"
- name="voice_chat_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Direct Teleport"
@@ -219,16 +179,6 @@ regions in the estate.
name="allow_direct_teleport"
top_pad="4"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="140"
- name="allow_direct_teleport_help"
- top_delta="2"
- width="18" />
<text
type="string"
length="1"
@@ -250,16 +200,6 @@ regions in the estate.
top_pad="5"
width="205" />
<button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="12"
- name="abuse_email_address_help"
- top_dekta="0"
- width="18" />
- <button
enabled="false"
follows="left|top"
height="20"
@@ -300,16 +240,6 @@ regions in the estate.
width="200">
Estate Managers:
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="182"
- name="estate_manager_help"
- top_delta="-1"
- width="18" />
<view_border
bevel_style="none"
follows="top|left"
@@ -357,16 +287,6 @@ regions in the estate.
width="200">
Allowed Residents:
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="182"
- name="allow_resident_help"
- top_delta="-1"
- width="18" />
<view_border
bevel_style="none"
follows="top|left"
@@ -414,16 +334,6 @@ regions in the estate.
width="200">
Allowed Groups:
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="182"
- name="allow_group_help"
- top_delta="-1"
- width="18" />
<view_border
bevel_style="none"
follows="top|left"
@@ -471,16 +381,6 @@ regions in the estate.
width="200">
Banned Residents:
</text>
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_delta="182"
- name="ban_resident_help"
- top_delta="-1"
- width="18" />
<view_border
bevel_style="none"
follows="top|left"
diff --git a/indra/newview/skins/default/xui/en/panel_region_general.xml b/indra/newview/skins/default/xui/en/panel_region_general.xml
index 160ae96fc4..42c6319699 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general.xml
@@ -83,16 +83,6 @@
name="block_terraform_check"
top="70"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="terraform_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Block Fly"
@@ -101,16 +91,6 @@
name="block_fly_check"
top="90"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="fly_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Damage"
@@ -119,16 +99,6 @@
name="allow_damage_check"
top="110"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="damage_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Restrict Pushing"
@@ -137,16 +107,6 @@
name="restrict_pushobject"
top="130"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="restrict_pushobject_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Land Resell"
@@ -155,16 +115,6 @@
name="allow_land_resell_check"
top="160"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="land_resell_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Land Join/Divide"
@@ -173,16 +123,6 @@
name="allow_parcel_changes_check"
top="180"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="parcel_changes_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Block Land Show in Search"
@@ -192,16 +132,6 @@
tool_tip="Let people see this region and its parcels in search results"
top="200"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="parcel_search_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -215,16 +145,6 @@
name="agent_limit_spin"
top="240"
width="170" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="25"
- name="agent_limit_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -238,16 +158,6 @@
name="object_bonus_spin"
top="260"
width="170" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="25"
- name="object_bonus_help"
- top_delta="2"
- width="18" />
<text
follows="left|top"
height="20"
@@ -281,16 +191,6 @@
value="13" />
</combo_box>
<button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="access_help"
- top_delta="2"
- width="18" />
- <button
enabled="false"
follows="left|top"
height="20"
@@ -299,10 +199,7 @@
left="108"
name="apply_btn"
top="320"
- width="100">
- <button.commit_callback
- function="RegionInfo.Cancel" />
- </button>
+ width="100"/>
<button
follows="left|top"
height="20"
@@ -338,5 +235,8 @@
left="250"
name="manage_telehub_btn"
top="70"
- width="150" />
+ 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
index 9b9c62dbf9..bffd84877f 100644
--- a/indra/newview/skins/default/xui/en/panel_region_general_layout.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_general_layout.xml
@@ -83,16 +83,6 @@
name="block_terraform_check"
top="70"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="terraform_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Block Fly"
@@ -101,16 +91,6 @@
name="block_fly_check"
top="90"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="fly_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Damage"
@@ -119,16 +99,6 @@
name="allow_damage_check"
top="110"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="damage_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Restrict Pushing"
@@ -137,16 +107,6 @@
name="restrict_pushobject"
top="130"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="restrict_pushobject_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Land Resell"
@@ -155,16 +115,6 @@
name="allow_land_resell_check"
top="160"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="land_resell_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Allow Land Join/Divide"
@@ -173,16 +123,6 @@
name="allow_parcel_changes_check"
top="180"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="parcel_changes_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Block Land Show in Search"
@@ -192,16 +132,6 @@
tool_tip="Let people see this region and its parcels in search results"
top="200"
width="80" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="115"
- name="parcel_search_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -215,16 +145,6 @@
name="agent_limit_spin"
top="240"
width="170" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="25"
- name="agent_limit_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -238,16 +158,6 @@
name="object_bonus_spin"
top="260"
width="170" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="25"
- name="object_bonus_help"
- top_delta="2"
- width="18" />
<text
follows="left|top"
height="20"
@@ -281,16 +191,6 @@
value="13" />
</combo_box>
<button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="access_help"
- top_delta="2"
- width="18" />
- <button
enabled="false"
follows="left|top"
height="20"
@@ -299,10 +199,7 @@
left="108"
name="apply_btn"
top="320"
- width="100">
- <button.commit_callback
- function="RegionInfo.Cancel" />
- </button>
+ width="100"/>
<button
follows="left|top"
height="20"
@@ -338,5 +235,8 @@
left_delta="0"
name="manage_telehub_btn"
top_pad="20"
- width="150" />
+ 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
index 148d9500bb..ffd51bf510 100644
--- a/indra/newview/skins/default/xui/en/panel_region_terrain.xml
+++ b/indra/newview/skins/default/xui/en/panel_region_terrain.xml
@@ -42,16 +42,6 @@
name="water_height_spin"
top="40"
width="180" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="5"
- name="water_height_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -64,16 +54,6 @@
name="terrain_raise_spin"
top="60"
width="180" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="5"
- name="terrain_raise_help"
- top_delta="2"
- width="18" />
<spinner
follows="left|top"
height="20"
@@ -87,16 +67,6 @@
name="terrain_lower_spin"
top="80"
width="180" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="5"
- name="terrain_lower_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Use Estate Sun"
@@ -105,16 +75,6 @@
name="use_estate_sun_check"
top="35"
width="100" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="70"
- name="use_estate_sun_help"
- top_delta="2"
- width="18" />
<check_box
height="20"
label="Fixed Sun"
@@ -123,16 +83,6 @@
name="fixed_sun_check"
top="55"
width="100" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="70"
- name="fixed_sun_help"
- top_delta="2"
- width="18" />
<icon
height="20"
image_name="icon_day_cycle.tga"
@@ -184,16 +134,6 @@
width="170" />
<button
follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="download_raw_help"
- top_delta="2"
- width="18" />
- <button
- follows="left|top"
height="20"
label="Upload RAW terrain..."
layout="topleft"
@@ -204,16 +144,6 @@
width="170" />
<button
follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="upload_raw_help"
- top_delta="2"
- width="18" />
- <button
- follows="left|top"
height="20"
label="Bake Terrain"
layout="topleft"
@@ -222,14 +152,4 @@
tool_tip="Set current terrain as mid-point for raise/lower limits"
top="283"
width="100" />
- <button
- follows="left|top"
- font="SansSerifSmall"
- height="18"
- label="?"
- layout="topleft"
- left_pad="10"
- name="bake_terrain_help"
- top_delta="2"
- width="18" />
</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
index 21ecd01839..44afadf65a 100644
--- a/indra/newview/skins/default/xui/en/panel_scrolling_param.xml
+++ b/indra/newview/skins/default/xui/en/panel_scrolling_param.xml
@@ -56,7 +56,6 @@
layout="topleft"
left="2"
name="less"
- picture_style="true"
tab_stop="false"
top="0"
width="132" />
@@ -70,7 +69,6 @@
layout="topleft"
left_pad="2"
name="more"
- picture_style="true"
tab_stop="false"
top_delta="0"
width="132" />
diff --git a/indra/newview/skins/default/xui/en/panel_side_tray.xml b/indra/newview/skins/default/xui/en/panel_side_tray.xml
index d3d45640cb..3582de1c71 100644
--- a/indra/newview/skins/default/xui/en/panel_side_tray.xml
+++ b/indra/newview/skins/default/xui/en/panel_side_tray.xml
@@ -1,4 +1,6 @@
<?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"
@@ -6,21 +8,24 @@
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_home"
help_topic="sidebar_home"
tab_title="Home"
description="Home."
image="TabIcon_Open_Off"
+ image_selected="TabIcon_Close_Off"
mouse_opaque="false"
- background_opaque="false"
background_visible="true"
>
<panel
name="panel_home"
filename="panel_sidetray_home_tab.xml"
label="home"
- border="true"
/>
</sidetray_tab>
@@ -30,8 +35,8 @@
tab_title="People"
description="Find your friends, contacts and people nearby."
image="TabIcon_People_Off"
+ image_selected="TabIcon_People_Selected"
mouse_opaque="false"
- background_opaque="false"
background_visible="true"
>
<panel_container
@@ -42,20 +47,17 @@
class="panel_people"
name="panel_people"
filename="panel_people.xml"
- border="true"
/>
<panel
class="panel_profile_view"
name="panel_profile_view"
filename="panel_profile_view.xml"
- border="true"
/>
<panel
class="panel_group_info_sidetray"
name="panel_group_info_sidetray"
filename="panel_group_info_sidetray.xml"
label="Group Info"
- border="true"
font="SansSerifBold"
/>
<panel
@@ -63,12 +65,12 @@
name="panel_block_list_sidetray"
filename="panel_block_list_sidetray.xml"
label="Blocked Residents &amp; Objects"
- border="true"
font="SansSerifBold"
/>
</panel_container>
</sidetray_tab>
+
<sidetray_tab
name="sidebar_places"
help_topic="sidebar_places"
@@ -76,6 +78,7 @@
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"
>
@@ -84,7 +87,6 @@
name="panel_places"
filename="panel_places.xml"
label="Places"
- border="true"
font="SansSerifBold"
/>
</sidetray_tab>
@@ -95,6 +97,7 @@
tab_title="Me"
description="Edit your public profile and Picks."
image="TabIcon_Me_Off"
+ image_selected="TabIcon_Me_Selected"
mouse_opaque="false"
background_visible="true"
>
@@ -103,7 +106,6 @@
name="panel_me_profile"
filename="panel_me_profile.xml"
label="Me"
- border="true"
/>
</sidetray_tab>
@@ -113,19 +115,36 @@
tab_title="Appearance"
description="Change your appearance and current look."
image="TabIcon_Appearance_Off"
+ image_selected="TabIcon_Appearance_Selected"
mouse_opaque="false"
- background_opaque="false"
background_visible="true"
>
<panel
class="panel_appearance"
name="panel_appearance"
filename="panel_appearance.xml"
- border="true"
label="Edit Appearance"
font="SansSerifBold"
/>
</sidetray_tab>
+ <sidetray_tab
+ name="sidebar_inventory"
+ help_topic="sidebar_inventory"
+ tab_title="Inventory"
+ description="Browse your inventory."
+ image="TabIcon_Inventory_Off"
+ image_selected="TabIcon_Inventory_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>
</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
index 9845a9eb78..0a9c70303e 100644
--- 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
@@ -19,16 +19,17 @@
top="4"
value="Side Panel"
width="255" />
- <button
+ <button
follows="left|right|top"
- font="SansSerif"
- height="23"
- label="?"
+ height="16"
+ image_selected="Icon_Help_Press"
+ image_unselected="Icon_Help_Foreground"
+ image_disabled="Icon_Help_Press"
layout="topleft"
name="show_help"
- top="5"
- right="-8"
- width="28"
+ top="10"
+ right="-11"
+ width="16"
tool_tip="Show Help">
<button.commit_callback
function="Button.ShowHelp" />
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
index 88379a5ed3..9636e32187 100644
--- a/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
+++ b/indra/newview/skins/default/xui/en/panel_sidetray_home_tab.xml
@@ -1,9 +1,8 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<!-- Part of side tray, see that XML file for panel config -->
<panel
- background_visible="true"
- bevel_style="in"
- follows="left|top|right|bottom"
- height="420"
+ follows="all"
+ height="560"
label="home_tab"
layout="topleft"
name="home_tab"
@@ -13,38 +12,37 @@
bg_alpha_color="DkGray2"
class="panel_sidetray_home_info"
follows="left|top|right"
- height="130"
+ height="90"
layout="topleft"
- left="10"
+ left="15"
+ top="17"
name="sidebar_people"
- width="313">
+ width="303">
<text
follows="left|right|top"
font="SansSerifBigBold"
height="30"
layout="topleft"
- left="5"
+ left="10"
mouse_opaque="false"
name="tab_name"
- text_color="white"
+ text_color="EmphasisColor"
top="10"
value="People"
width="200"
word_wrap="true" />
<icon
- color="DkGray"
follows="top|right"
height="20"
layout="topleft"
name="tab_icon"
right="-10"
top="10"
- image_name="TabIcon_People_Off"
+ image_name="TabIcon_People_Selected"
width="20" />
<text
follows="left|right|bottom"
- font="SansSerifBold"
- height="120"
+ height="90"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -61,38 +59,37 @@
bg_alpha_color="DkGray2"
class="panel_sidetray_home_info"
follows="left|top|right"
- height="130"
+ height="90"
layout="topleft"
- left="10"
+ left="15"
+ top_pad="15"
name="sidebar_places"
- width="313">
+ width="303">
<text
follows="left|right|top"
font="SansSerifBigBold"
height="30"
layout="topleft"
- left="5"
+ left="10"
mouse_opaque="false"
name="tab_name"
- text_color="white"
+ text_color="EmphasisColor"
top="10"
value="Places"
width="200"
word_wrap="true" />
<icon
- color="DkGray"
follows="top|right"
height="20"
layout="topleft"
name="tab_icon"
right="-10"
top="10"
- width="20"
+ width="20"
image_name="TabIcon_Places_Selected"/>
<text
- follows="left|right|bottom|top"
- font="SansSerifBold"
- height="120"
+ follows="all"
+ height="90"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -109,38 +106,37 @@
bg_alpha_color="DkGray2"
class="panel_sidetray_home_info"
follows="left|top|right"
- height="130"
+ height="90"
layout="topleft"
- left="10"
+ left="15"
+ top_pad="15"
name="sidebar_me"
- width="313">
+ width="303">
<text
follows="left|right|top"
font="SansSerifBigBold"
height="30"
layout="topleft"
- left="5"
+ left="10"
mouse_opaque="false"
name="tab_name"
- text_color="white"
+ text_color="EmphasisColor"
top="10"
value="My Profile"
width="200"
word_wrap="true" />
<icon
- color="DkGray"
follows="top|right"
height="20"
layout="topleft"
name="tab_icon"
right="-10"
top="10"
- width="20"
+ width="20"
image_name="TabIcon_Me_Selected"/>
<text
- follows="left|right|bottom|top"
- font="SansSerifBold"
- height="120"
+ follows="all"
+ height="90"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -157,38 +153,37 @@
bg_alpha_color="DkGray2"
class="panel_sidetray_home_info"
follows="left|top|right"
- height="130"
+ height="90"
layout="topleft"
- left="10"
+ left="15"
+ top_pad="15"
name="sidebar_appearance"
- width="313">
+ width="303">
<text
follows="left|right|top"
font="SansSerifBigBold"
height="30"
layout="topleft"
- left="5"
+ left="10"
mouse_opaque="false"
name="tab_name"
- text_color="white"
+ text_color="EmphasisColor"
top="10"
value="My Appearance"
width="200"
word_wrap="true" />
<icon
- color="DkGray"
follows="top|right"
height="20"
layout="topleft"
name="tab_icon"
right="-10"
top="10"
- width="20"
- image_name="TabIcon_Appearance_Off"/>
+ width="20"
+ image_name="TabIcon_Appearance_Selected"/>
<text
- follows="left|right|bottom|top"
- font="SansSerifBold"
- height="120"
+ follows="all"
+ height="90"
layout="topleft"
left="10"
mouse_opaque="false"
@@ -200,4 +195,51 @@
Change your appearance and current look.
</text>
</panel>
+ <panel
+ background_visible="true"
+ bg_alpha_color="DkGray2"
+ class="panel_sidetray_home_info"
+ follows="left|top|right"
+ height="90"
+ layout="topleft"
+ left="15"
+ top_pad="15"
+ name="sidebar_inventory"
+ width="303">
+ <text
+ follows="left|right|top"
+ font="SansSerifBigBold"
+ height="30"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="tab_name"
+ text_color="EmphasisColor"
+ top="10"
+ value="My Inventory"
+ width="200"
+ word_wrap="true" />
+ <icon
+ follows="top|right"
+ height="20"
+ layout="topleft"
+ name="tab_icon"
+ right="-10"
+ top="10"
+ width="20"
+ image_name="TabIcon_Inventory_Selected"/>
+ <text
+ follows="all"
+ height="90"
+ layout="topleft"
+ left="10"
+ mouse_opaque="false"
+ name="tab_description"
+ right="-10"
+ text_color="white"
+ top="40"
+ word_wrap="true">
+ Browse your inventory.
+ </text>
+ </panel>
</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
index 4d91a544c3..c8703aa895 100644
--- a/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml
+++ b/indra/newview/skins/default/xui/en/panel_stand_stop_flying.xml
@@ -4,12 +4,12 @@
height="25"
layout="topleft"
name="panel_stand_stop_flying"
- mouse_opaque="false"
- visible="false"
+ mouse_opaque="false"
+ visible="false"
width="115">
<button
follows="left|bottom"
- height="20"
+ height="19"
label="Stand"
layout="topleft"
name="stand_btn"
@@ -19,11 +19,11 @@
width="115" />
<button
follows="left|bottom"
- height="20"
+ height="19"
label="Stop Flying"
layout="topleft"
name="stop_fly_btn"
- tool_tip="Stop Flying"
+ tool_tip="Stop flying"
top="2"
visible="false"
width="115" />
diff --git a/indra/newview/skins/default/xui/en/panel_status_bar.xml b/indra/newview/skins/default/xui/en/panel_status_bar.xml
index 05ad3ee16f..7b9c9f47a2 100644
--- a/indra/newview/skins/default/xui/en/panel_status_bar.xml
+++ b/indra/newview/skins/default/xui/en/panel_status_bar.xml
@@ -41,19 +41,18 @@
</panel.string>
<button
auto_resize="true"
- halign="left"
+ halign="right"
follows="right|bottom"
font="SansSerifSmall"
- image_color="White_05"
- flash_color="EmphasisColor"
- image_overlay="BuyArrow_Over"
- height="18"
- layout="topleft"
- left="-210"
+ image_selected="BuyArrow_Over"
+ image_unselected="BuyArrow_Off"
+ image_pressed="BuyArrow_Press"
+ height="16"
+ left="-220"
name="buycurrency"
- picture_style="true"
- tool_tip="My Balance: Click here to buy more L$"
- top="0"
+ pad_right="22px"
+ tool_tip="My Balance: Click to buy more L$"
+ top="1"
width="117" />
<text
type="string"
@@ -64,148 +63,21 @@
height="16"
top="3"
layout="topleft"
- left_pad="5"
+ left_pad="15"
name="TimeText"
text_color="TimeTextColor"
- tool_tip="Current Time (Pacific)"
+ tool_tip="Current time (Pacific)"
width="80">
12:00 AM
</text>
- <button
- follows="right|bottom"
- height="16"
- layout="topleft"
- left_delta="-537"
- image_selected="Inv_DangerousScript"
- image_unselected="Inv_DangerousScript"
- name="scriptout"
- picture_style="true"
- scale_image="false"
- tool_tip="Script Warnings and Errors"
- top="0"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="16"
- image_selected="Health"
- image_unselected="Health"
- layout="topleft"
- left_pad="7"
- name="health"
- picture_style="true"
- scale_image="false"
- tool_tip="Health"
- top="0"
- visible="false"
- width="16" />
- <text
- bg_visible="false"
- text_readonly_color="HealthTextColor"
- follows="rsight|bottom"
- font_shadow="hard"
- height="16"
- layout="topleft"
- left_pad="18"
- name="HealthText"
- text_color="HealthTextColor"
- tool_tip="Health"
- top="0"
- visible="false"
- width="31">
- 100%
- </text>
- <button
- follows="right|bottom"
- height="16"
- image_selected="Move_Fly_Disabled"
- image_unselected="Move_Fly_Disabled"
- layout="topleft"
- left_pad="7"
- name="no_fly"
- picture_style="true"
- scale_image="false"
- tool_tip="Flying not allowed"
- top="3"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="16"
- image_selected="Tool_Create"
- image_unselected="Tool_Create"
- layout="topleft"
- left_pad="7"
- name="no_build"
- picture_style="true"
- scale_image="false"
- tool_tip="Building/Rezzing not allowed"
- top="0"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="16"
- image_selected="Inv_Script"
- image_unselected="Inv_Script"
- layout="topleft"
- left_pad="7"
- name="no_scripts"
- picture_style="true"
- scale_image="false"
- tool_tip="Scripts not allowed"
- top="0"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="16"
- image_selected="Inv_Gesture"
- image_unselected="Inv_Gesture"
- layout="topleft"
- left_pad="7"
- name="restrictpush"
- picture_style="true"
- scale_image="false"
- tool_tip="No Pushing"
- top="0"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="18"
- image_selected="Microphone_Mute"
- image_unselected="Microphone_Mute"
- layout="topleft"
- left_pad="7"
- name="status_no_voice"
- picture_style="true"
- scale_image="false"
- tool_tip="Voice not available here"
- top="1"
- visible="false"
- width="16" />
- <button
- follows="right|bottom"
- height="16"
- image_selected="Icon_For_Sale"
- image_unselected="Icon_For_Sale"
- layout="topleft"
- left_pad="7"
- name="buyland"
- picture_style="true"
- tool_tip="Buy this parcel"
- top="0"
- visible="false"
- width="16" />
<text
enabled="true"
follows="right|bottom"
halign="center"
height="12"
layout="topleft"
- left_delta="-4"
+ left_delta="0"
name="stat_btn"
- top_delta="3"
- width="20" />
+ 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
index 53ee0d159d..7722583ce2 100644
--- a/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_sys_well_item.xml
@@ -1,65 +1,40 @@
<?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"
+ name="sys_well_item"
+ title="sys_well_item"
visible="true"
- top="0"
- left="0"
- width="318"
- height="35"
+ 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" >
-
- <icon
- top="8"
- left="8"
- width="20"
- height="20"
- layout="topleft"
- follows="left"
- name="icon"
- label=""
- mouse_opaque="false"
- image_name="lag_status_warning.tga"
- />
-
+ follows="left|right">
<text
- top="2"
- left_pad="8"
- width="255"
- height="28"
+ top="2"
+ left="10"
+ width="267"
+ height="28"
layout="topleft"
follows="right|left"
- font="SansSerifBold"
text_color="white"
- use_ellipses="true"
+ use_ellipses="true"
word_wrap="true"
mouse_opaque="false"
name="title" >
- Select your streaming media preference. Select your streaming media preference.
- </text>
-
+ Beware the trout. BEWARE! THE! TROUT!
+ </text>
<button
- top="5"
- left_pad="5"
- width="15"
- height="15"
+ top="5"
+ right="-5"
+ width="17"
+ height="17"
layout="topleft"
follows="right"
- name="close_btn"
+ name="close_btn"
mouse_opaque="true"
- label=""
tab_stop="false"
- image_unselected="toast_hide_btn.tga"
- image_disabled="toast_hide_btn.tga"
- image_selected="toast_hide_btn.tga"
- image_hover_selected="toast_hide_btn.tga"
- image_disabled_selected="toast_hide_btn.tga"
+ image_unselected="Icon_Close_Toast"
+ image_selected="Icon_Close_Toast"
/>
-
-</panel>
+</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
index b0cd75117f..01204ba779 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history.xml
@@ -1,15 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<panel name="Teleport History" bottom="0" height="326" left="0" width="380"
border="true" follows="left|top|right|bottom">
- <string
- name="cant_create_lm_here"
- value="Please teleport to selected location before creating Landmark. " />
- <string
- name="create_landmark"
- value="Create Landmark" />
- <string
- name="open_landmark"
- value="Open Landmark panel" />
<accordion
follows="left|top|right|bottom"
height="300"
@@ -19,12 +10,10 @@
name="history_accordion"
width="380">
<accordion_tab
- can_resize="false"
layout="topleft"
name="today"
title="Today">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -35,12 +24,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="yesterday"
title="Yesterday">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -51,12 +38,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="2_days_ago"
title="2 days ago">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -67,12 +52,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="3_days_ago"
title="3 days ago">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -83,12 +66,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="4_days_ago"
title="4 days ago">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -99,12 +80,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="5_days_ago"
title="5 days ago">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -115,12 +94,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="6_days_and_older"
title="6 days and older">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -131,12 +108,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="1_month_and_older"
title="1 month and older">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -147,12 +122,10 @@
</flat_list_view>
</accordion_tab>
<accordion_tab
- can_resize="false"
layout="topleft"
name="6_months_and_older"
title="6 months and older">
<flat_list_view
- draw_heading="false"
follows="all"
height="150"
layout="topleft"
@@ -185,22 +158,7 @@
layout="topleft"
left="10"
name="gear_btn"
- picture_style="true"
top="5"
width="18" />
- <button
- follows="bottom|left"
- font="SansSerifBigBold"
- height="18"
- image_selected="Favorite_Star_Active"
- image_disabled="Favorite_Star_Off"
- image_unselected="Favorite_Star_Press"
- layout="topleft"
- left_pad="5"
- name="star_btn"
- picture_style="true"
- tool_tip=""
- top_delta="0"
- 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
index 63c2d4538e..1f67a0a732 100644
--- a/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
+++ b/indra/newview/skins/default/xui/en/panel_teleport_history_item.xml
@@ -18,7 +18,7 @@
visible="false"
width="380" />
<icon
- height="20"
+ height="24"
follows="top|right|left"
image_name="ListItem_Select"
layout="topleft"
@@ -26,17 +26,16 @@
name="selected_icon"
top="0"
visible="false"
- width="380" />
+ width="320" />
<icon
- height="20"
- follows="top|right|left"
- image_name="ListItem_Select"
+ height="16"
+ follows="top|left"
+ image_name="Inv_Landmark"
layout="topleft"
left="0"
name="landmark_icon"
top="0"
- visible="false"
- width="20" />
+ width="16" />
<text
follows="left|right"
height="20"
@@ -46,21 +45,17 @@
name="region"
text_color="white"
top="4"
- value="Unknown"
- width="330" />
+ value="..."
+ width="242" />
<button
follows="right"
- height="18"
- image_disabled="Info"
- image_disabled_selected="Info"
- image_hover_selected="Info"
- image_selected="Info"
- image_unselected="Info"
+ height="20"
+ image_overlay="ForwardArrow_Off"
layout="topleft"
- name="info_btn"
- picture_style="true"
+ left_pad="5"
+ right="-3"
+ name="profile_btn"
+ top_delta="-2"
visible="false"
- right="-5"
- top="2"
- width="18" />
+ 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
index 01fd84e09d..7f7777586c 100644
--- a/indra/newview/skins/default/xui/en/panel_toast.xml
+++ b/indra/newview/skins/default/xui/en/panel_toast.xml
@@ -1,25 +1,33 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<!-- All our XML is utf-8 encoded. -->
+<!-- All this does is establish the position of the "close" button on the toast. -->
+
<floater
+ legacy_header_height="18"
name="toast"
title=""
visible="false"
layout="topleft"
- width="350"
- height="72"
- left="100"
- top="500"
- follows="right|bottom"
- bevel_style="in"
+ width="305"
+ left="0"
+ top="0"
+ follows="right|bottom"
+ bg_opaque_image="Toast_Background"
+ 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"
+ can_dock="false"
+ border_visible = "false"
+ border_drop_shadow_visible = "false"
+ drop_shadow_visible = "false"
+ border = "false"
>
+ <!--
<text
visible="false"
follows="left|top|right|bottom"
@@ -35,36 +43,33 @@
Toast text;
</text>
<icon
- top="20"
- left="10"
- width="32"
+ top="20"
+ left="10"
+ width="32"
height="32"
follows="top|left"
layout="topleft"
visible="false"
- color="1 1 1 1"
- enabled="true"
+ color="1 1 1 1"
+ enabled="true"
image_name="notify_tip_icon.tga"
- mouse_opaque="true"
+ mouse_opaque="true"
name="icon"
- />
+ />-->
<button
layout="topleft"
- top="-5"
- left="335"
- width="20"
- height="20"
+ top="-6"
+ left="293"
+ width="17"
+ height="17"
follows="top|right"
- visible="false"
- enabled="true"
- mouse_opaque="true"
- name="hide_btn"
- label=""
+ visible="false"
+ enabled="true"
+ mouse_opaque="false"
+ name="hide_btn"
+ label=""
tab_stop="false"
- image_unselected="toast_hide_btn.tga"
- image_disabled="toast_hide_btn.tga"
- image_selected="toast_hide_btn.tga"
- image_hover_selected="toast_hide_btn.tga"
- image_disabled_selected="toast_hide_btn.tga"
+ image_unselected="Toast_CloseBtn"
+ image_selected="Toast_CloseBtn"
/>
-</floater>
+</floater>
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..d0c3cdfafc
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/sidepanel_inventory.xml
@@ -0,0 +1,122 @@
+<?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="objects panel"
+ width="333">
+ <tab_container
+ follows="all"
+ height="390"
+ layout="topleft"
+ left="9"
+ name="Inventory Tabs"
+ tab_position="top"
+ top="0"
+ width="313"
+ tab_height="0"
+ visible="true">
+ <panel
+ class="panel_main_inventory"
+ filename="panel_main_inventory.xml"
+ follows="all"
+ layout="topleft"
+ left="0"
+ name="panel_main_inventory"
+ top="15"
+ label=""
+ height="330"
+ width="467">
+ <panel
+ height="25"
+ layout="bottomright"
+ left="0"
+ help_topic="objects_button_tab"
+ name="button_panel"
+ bottom="0"
+ width="313">
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Info"
+ layout="topleft"
+ left="0"
+ name="info_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="true"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Share"
+ layout="topleft"
+ left_pad="5"
+ name="share_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Wear"
+ layout="topleft"
+ left="130"
+ name="wear_btn"
+ top="0"
+ width="60" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Play"
+ layout="topleft"
+ name="play_btn"
+ left="130"
+ top="0"
+ width="50" />
+ <button
+ enabled="false"
+ follows="bottom|left"
+ font="SansSerifSmallBold"
+ height="25"
+ label="Teleport"
+ layout="topleft"
+ left="130"
+ name="teleport_btn"
+ top="0"
+ width="77" />
+ <button
+ follows="bottom|right"
+ font="SansSerifSmallBold"
+ height="25"
+ label="v"
+ layout="topleft"
+ name="overflow_btn"
+ right="-10"
+ top="0"
+ width="30" />
+ </panel>
+ </panel>
+ </tab_container>
+
+ <panel
+ class="sidepanel_object_info"
+ filename="sidepanel_object_info.xml"
+ follows="all"
+ height="360"
+ layout="topleft"
+ left="0"
+ help_topic="objects_info_tab"
+ name="sidepanel_object_info"
+ top="30"
+ visible="false" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index 44875e9a25..ec2673644f 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -14,7 +14,10 @@
<!-- starting up -->
<string name="StartupDetectingHardware">Detecting hardware...</string>
<string name="StartupLoading">Loading</string>
- <string name="Fullbright">Fullbright (Legacy)</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>
@@ -58,9 +61,7 @@
<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>
- <string name="TooltipAltLeft">Alt-Left arrow for previous tab</string>
- <string name="TooltipAltRight">Alt-Right arrow for next tab</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>
@@ -72,11 +73,17 @@
<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_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>
@@ -127,7 +134,7 @@
<string name="AssetErrorPriceMismatch">Viewer and server do not agree on price</string>
<string name="AssetErrorUnknownStatus">Unknown status</string>
- <!-- Asset Type Human Names -->
+ <!-- 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>
@@ -135,23 +142,23 @@
<string name="legacy script">legacy script</string>
<string name="clothing">clothing</string>
<string name="object">object</string>
- <string name="note card">note card</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="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>
+ <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>
@@ -230,8 +237,10 @@
<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>
@@ -259,10 +268,6 @@
<string name="TrackYourCamera">Track your camera</string>
<string name="ControlYourCamera">Control your camera</string>
- <!-- IM -->
- <string name="IM_logging_string">-- Instant message logging enabled --</string>
- <string name="Unnamed">(Unnamed)</string>
-
<!-- Sim Access labels -->
<string name="SIM_ACCESS_PG">PG</string>
<string name="SIM_ACCESS_MATURE">Mature</string>
@@ -637,7 +642,7 @@ Sets the script timer to zero
float llGetAndResetTime()
Returns the script time in seconds and then resets the script timer to zero
</string>
- <string name="LSLTipText_llSound" translate="false">
+ <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>
@@ -1814,6 +1819,7 @@ this texture in your inventory
<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])" />
<!-- Gestures labels -->
<!-- use value="" because they have preceding spaces -->
@@ -1946,6 +1952,10 @@ this texture in your inventory
<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>
@@ -2012,15 +2022,14 @@ this texture in your inventory
<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]
+ all estates owned by [OWNER]
</string>
- <string name="RegionInfoAllEstatesYouOwn">all estates you owned</string>
+ <string name="RegionInfoAllEstatesYouOwn">all estates that you own</string>
<string name="RegionInfoAllEstatesYouManage">
- all estates that
-you managed for [OWNER]
+ 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>
@@ -2038,9 +2047,6 @@ you managed for [OWNER]
<!-- panel contents -->
<string name="PanelContentsNewScript">New Script</string>
- <!-- panel avatar -->
- <!-- <string name="None">None</string> Duplicate-->
-
<!-- Mute -->
<string name="MuteByName">(by name)</string>
<string name="MuteAgent">(resident)</string>
@@ -2110,6 +2116,15 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
<string name="AddLandmarkNavBarMenu">Add Landmark...</string>
<string name="EditLandmarkNavBarMenu">Edit 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>
@@ -2175,6 +2190,7 @@ Expected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh
<!-- media -->
<string name="Multiple Media">Multiple Media</string>
+ <string name="Play Media">Play/Pause Media</string>
<!-- OSMessageBox messages -->
<string name="MBCmdLineError">
@@ -2225,9 +2241,8 @@ Running in window.
<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 in a window.
-Please go to Control Panels &gt; Display &gt; Settings and set the screen to 32-bit color.
-Alternately, if you choose to run fullscreen, [APP_NAME] will automatically adjust the screen each time it runs.
+ [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.
@@ -2246,14 +2261,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<!-- Avatar Shape Information -->
<string name="5 O'Clock Shadow">5 O'Clock Shadow</string>
-<string name="5 O'Clock Shadow bump">5 O'Clock Shadow bump</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="BELLY">BELLY</string>
+
<string name="Back Bangs">Back Bangs</string>
<string name="Back Bangs Down">Back Bangs Down</string>
<string name="Back Bangs Up">Back Bangs Up</string>
@@ -2270,9 +2285,9 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Big">Big</string>
<string name="Big Butt">Big Butt</string>
<string name="Big Eyeball">Big Eyeball</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 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>
@@ -2288,10 +2303,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Body Thick">Body Thick</string>
<string name="Body Thickness">Body Thickness</string>
<string name="Body Thin">Body Thin</string>
-<string name="Bottom">Bottom</string>
-<string name="Bottom Left">Bottom Left</string>
-<string name="Bottom Right">Bottom Right</string>
-<string name="Bottom bump">Bottom bump</string>
+
<string name="Bow Legged">Bow Legged</string>
<string name="Breast Buoyancy">Breast Buoyancy</string>
<string name="Breast Cleavage">Breast Cleavage</string>
@@ -2303,23 +2315,22 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Bugged Eyes">Bugged Eyes</string>
<string name="Bulbous">Bulbous</string>
<string name="Bulbous Nose">Bulbous Nose</string>
-<string name="Bump base">Bump base</string>
-<string name="Bump upperdef">Bump upperdef</string>
+
+
<string name="Bushy Eyebrows">Bushy Eyebrows</string>
<string name="Bushy Hair">Bushy Hair</string>
<string name="Butt Size">Butt Size</string>
-<string name="CHEST">CHEST</string>
-<string name="Center">Center</string>
-<string name="Center 2">Center 2</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">Chest</string>
<string name="Chest Size">Chest Size</string>
-<string name="Chin">Chin</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 Curtains bump">Chin Curtains bump</string>
+
<string name="Chin Depth">Chin Depth</string>
<string name="Chin Heavy">Chin Heavy</string>
<string name="Chin In">Chin In</string>
@@ -2335,13 +2346,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Closed Right">Closed Right</string>
<string name="Coin Purse">Coin Purse</string>
<string name="Collar Back">Collar Back</string>
-<string name="Collar Back Height Cloth">Collar Back Height Cloth</string>
-<string name="Collar Back Shadow Height">Collar Back Shadow Height</string>
-<string name="Collar Back bump">Collar Back bump</string>
+
+
+
<string name="Collar Front">Collar Front</string>
-<string name="Collar Front Height Cloth">Collar Front Height Cloth</string>
-<string name="Collar Front Shadow Height">Collar Front Shadow Height</string>
-<string name="Collar Front bump">Collar Front bump</string>
+
+
+
<string name="Corner Down">Corner Down</string>
<string name="Corner Normal">Corner Normal</string>
<string name="Corner Up">Corner Up</string>
@@ -2375,11 +2386,11 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Eyeball Size">Eyeball Size</string>
<string name="Eyebrow Arc">Eyebrow Arc</string>
<string name="Eyebrow Density">Eyebrow Density</string>
-<string name="Eyebrow Density Bump">Eyebrow Density Bump</string>
+
<string name="Eyebrow Height">Eyebrow Height</string>
<string name="Eyebrow Points">Eyebrow Points</string>
<string name="Eyebrow Size">Eyebrow Size</string>
-<string name="Eyebrow Size Bump">Eyebrow Size Bump</string>
+
<string name="Eyelash Length">Eyelash Length</string>
<string name="Eyeliner">Eyeliner</string>
<string name="Eyeliner Color">Eyeliner Color</string>
@@ -2429,21 +2440,21 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Full Sides">Full Sides</string>
<string name="Glossy">Glossy</string>
<string name="Glove Fingers">Glove Fingers</string>
-<string name="Glove Fingers bump">Glove Fingers bump</string>
+
<string name="Glove Length">Glove Length</string>
-<string name="Glove Length bump">Glove Length bump</string>
-<string name="HEAD">HEAD</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 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 Thickess</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="Hair Volume">Hair: Volume</string>
<string name="Hand Size">Hand Size</string>
<string name="Handlebars">Handlebars</string>
<string name="Head Length">Head Length</string>
@@ -2462,15 +2473,15 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Hip Length">Hip Length</string>
<string name="Hip Width">Hip Width</string>
<string name="In">In</string>
-<string name="In Shdw Color">In Shdw Color</string>
-<string name="In Shdw Opacity">In Shdw Opacity</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 Collar Back bump">Jacket Collar Back bump</string>
-<string name="Jacket Collar Front bump">Jacket Collar Front bump</string>
+
+
<string name="Jacket Length">Jacket Length</string>
-<string name="Jacket Sleeve Length bump">Jacket Sleeve Length bump</string>
+
<string name="Jacket Wrinkles">Jacket Wrinkles</string>
<string name="Jaw Angle">Jaw Angle</string>
<string name="Jaw Jut">Jaw Jut</string>
@@ -2479,22 +2490,10 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Jowls">Jowls</string>
<string name="Knee Angle">Knee Angle</string>
<string name="Knock Kneed">Knock Kneed</string>
-<string name="L Forearm">L Forearm</string>
-<string name="L Lower Leg">L Lower Leg</string>
-<string name="L Upper Arm">L Upper Arm</string>
-<string name="L Upper Leg">L Upper Leg</string>
<string name="Large">Large</string>
<string name="Large Hands">Large Hands</string>
-<string name="Left">Left</string>
-<string name="Left Ear">Left Ear</string>
-<string name="Left Eyeball">Left Eyeball</string>
-<string name="Left Foot">Left Foot</string>
-<string name="Left Hand">Left Hand</string>
-<string name="Left Hip">Left Hip</string>
<string name="Left Part">Left Part</string>
-<string name="Left Pec">Left Pec</string>
-<string name="Left Shoulder">Left Shoulder</string>
<string name="Leg Length">Leg Length</string>
<string name="Leg Muscles">Leg Muscles</string>
<string name="Less">Less</string>
@@ -2512,7 +2511,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Less Square">Less Square</string>
<string name="Less Volume">Less Volume</string>
<string name="Less soul">Less soul</string>
-<string name="Light">Light</string>
<string name="Lighter">Lighter</string>
<string name="Lip Cleft">Lip Cleft</string>
<string name="Lip Cleft Depth">Lip Cleft Depth</string>
@@ -2534,11 +2532,11 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Long Torso">Long Torso</string>
<string name="Long arms">Long arms</string>
<string name="Longcuffs">Longcuffs</string>
-<string name="Loose Lower Clothing">Loose Lower Clothing</string>
+
<string name="Loose Pants">Loose Pants</string>
<string name="Loose Shirt">Loose Shirt</string>
<string name="Loose Sleeves">Loose Sleeves</string>
-<string name="Loose Upper Clothing">Loose Upper Clothing</string>
+
<string name="Love Handles">Love Handles</string>
<string name="Low">Low</string>
<string name="Low Heels">Low Heels</string>
@@ -2548,7 +2546,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Lower">Lower</string>
<string name="Lower Bridge">Lower Bridge</string>
<string name="Lower Cheeks">Lower Cheeks</string>
-<string name="Lower Clothes Shading">Lower Clothes Shading</string>
+
<string name="Male">Male</string>
<string name="Middle Part">Middle Part</string>
<string name="More">More</string>
@@ -2574,14 +2572,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="More Volume">More Volume</string>
<string name="More soul">More soul</string>
<string name="Moustache">Moustache</string>
-<string name="Moustache bump">Moustache bump</string>
-<string name="Mouth">Mouth</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="NECK">NECK</string>
+
<string name="Nail Polish">Nail Polish</string>
<string name="Nail Polish Color">Nail Polish Color</string>
<string name="Narrow">Narrow</string>
@@ -2603,10 +2600,8 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="No Spikes">No Spikes</string>
<string name="No White">No White</string>
<string name="No Wrinkles">No Wrinkles</string>
-<string name="None">None</string>
<string name="Normal Lower">Normal Lower</string>
<string name="Normal Upper">Normal Upper</string>
-<string name="Nose">Nose</string>
<string name="Nose Left">Nose Left</string>
<string name="Nose Right">Nose Right</string>
<string name="Nose Size">Nose Size</string>
@@ -2616,7 +2611,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Nose Width">Nose Width</string>
<string name="Nostril Division">Nostril Division</string>
<string name="Nostril Width">Nostril Width</string>
-<string name="NotHair">NotHair</string>
+
<string name="Old">Old</string>
<string name="Opaque">Opaque</string>
<string name="Open">Open</string>
@@ -2626,27 +2621,26 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Open Right">Open Right</string>
<string name="Orange">Orange</string>
<string name="Out">Out</string>
-<string name="Out Shdw Color">Out Shdw Color</string>
-<string name="Out Shdw Opacity">Out Shdw Opacity</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="PELVIS">PELVIS</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 Length Cloth">Pants Length Cloth</string>
-<string name="Pants Length Shadow">Pants Length Shadow</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="Pelvis">Pelvis</string>
<string name="Pigment">Pigment</string>
<string name="Pigtails">Pigtails</string>
<string name="Pink">Pink</string>
@@ -2662,24 +2656,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Pop Right Eye">Pop Right Eye</string>
<string name="Puffy">Puffy</string>
<string name="Puffy Eyelids">Puffy Eyelids</string>
-<string name="R Forearm">R Forearm</string>
-<string name="R Lower Leg">R Lower Leg</string>
-<string name="R Upper Arm">R Upper Arm</string>
-<string name="R Upper Leg">R Upper Leg</string>
<string name="Rainbow Color">Rainbow Color</string>
<string name="Red Hair">Red Hair</string>
<string name="Red Skin">Red Skin</string>
<string name="Regular">Regular</string>
<string name="Regular Muscles">Regular Muscles</string>
-<string name="Right">Right</string>
-<string name="Right Ear">Right Ear</string>
-<string name="Right Eyeball">Right Eyeball</string>
-<string name="Right Foot">Right Foot</string>
-<string name="Right Hand">Right Hand</string>
-<string name="Right Hip">Right Hip</string>
<string name="Right Part">Right Part</string>
-<string name="Right Pec">Right Pec</string>
-<string name="Right Shoulder">Right Shoulder</string>
<string name="Rosy Complexion">Rosy Complexion</string>
<string name="Round">Round</string>
<string name="Round Forehead">Round Forehead</string>
@@ -2707,12 +2689,12 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Shift Mouth">Shift Mouth</string>
<string name="Shift Right">Shift Right</string>
<string name="Shirt Bottom">Shirt Bottom</string>
-<string name="Shirt Bottom Cloth">Shirt Bottom Cloth</string>
+
<string name="Shirt Fit">Shirt Fit</string>
-<string name="Shirt Shadow Bottom">Shirt Shadow Bottom</string>
+
<string name="Shirt Wrinkles">Shirt Wrinkles</string>
<string name="Shoe Height">Shoe Height</string>
-<string name="Shoe Height bump">Shoe Height bump</string>
+
<string name="Short">Short</string>
<string name="Short Arms">Short Arms</string>
<string name="Short Legs">Short Legs</string>
@@ -2728,7 +2710,7 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Side Bangs Up">Side Bangs Up</string>
<string name="Side Fringe">Side Fringe</string>
<string name="Sideburns">Sideburns</string>
-<string name="Sideburns bump">Sideburns bump</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>
@@ -2736,35 +2718,32 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Skinny Neck">Skinny Neck</string>
<string name="Skirt Fit">Skirt Fit</string>
<string name="Skirt Length">Skirt Length</string>
-<string name="Skull">Skull</string>
<string name="Slanted Forehead">Slanted Forehead</string>
<string name="Sleeve Length">Sleeve Length</string>
-<string name="Sleeve Length Cloth">Sleeve Length Cloth</string>
-<string name="Sleeve Length Shadow">Sleeve Length Shadow</string>
-<string name="Sleeve Length bump">Sleeve Length bump</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="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="Socks Length bump">Socks Length bump</string>
+
<string name="Some">Some</string>
<string name="Soulpatch">Soulpatch</string>
-<string name="Soulpatch bump">Soulpatch bump</string>
+
<string name="Sparse">Sparse</string>
<string name="Spiked Hair">Spiked Hair</string>
-<string name="Spine">Spine</string>
<string name="Square">Square</string>
<string name="Square Toe">Square Toe</string>
<string name="Squash Head">Squash Head</string>
<string name="Squash/Stretch Head">Squash/Stretch Head</string>
-<string name="Stomach">Stomach</string>
<string name="Stretch Head">Stretch Head</string>
<string name="Sunken">Sunken</string>
<string name="Sunken Chest">Sunken Chest</string>
@@ -2796,9 +2775,6 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Tilt Right">Tilt Right</string>
<string name="Toe Shape">Toe Shape</string>
<string name="Toe Thickness">Toe Thickness</string>
-<string name="Top">Top</string>
-<string name="Top Left">Top Left</string>
-<string name="Top Right">Top Right</string>
<string name="Torso Length">Torso Length</string>
<string name="Torso Muscles">Torso Muscles</string>
<string name="Torso Scrawny">Torso Scrawny</string>
@@ -2809,13 +2785,13 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<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 Clothes Shading">Upper Clothes Shading</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="Waist Height Cloth">Waist Height Cloth</string>
-<string name="Waist Height Shadow">Waist Height Shadow</string>
+
+
<string name="Well-Fed">Well-Fed</string>
<string name="White Hair">White Hair</string>
<string name="Wide">Wide</string>
@@ -2824,13 +2800,14 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
<string name="Wide Lips">Wide Lips</string>
<string name="Wild">Wild</string>
<string name="Wrinkles">Wrinkles</string>
-
- <!-- Favorites Bar -->
- <string name="location_ctrl_add_landmark">Add to My Landmarks</string>
- <string name="location_ctrl_edit_landmark">Edit My Landmark</string>
- <string name="favorite_landmark_loading_tooltip">(Loading...)</string>
-
- <!-- Strings used by the (currently Linux) auto-updater app -->
+
+ <!-- Favorites Bar -->
+ <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>
+
+ <!-- Strings used by the (currently Linux) auto-updater app -->
<string name="UpdaterWindowTitle">
[APP_NAME] Update
</string>
@@ -2862,7 +2839,30 @@ If you continue to receive this message, contact the [SUPPORT_SITE].
Failed to start viewer
</string>
- <!-- IM system messages -->
+ <!-- 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="ringing-im">
+ Joining Voice Chat...
+ </string>
+ <string name="connected-im">
+ Connected, click End Call to hang up
+ </string>
+ <string name="hang_up-im">
+ Left Voice Chat
+ </string>
+ <string name="answering-im">
+ Connecting...
+ </string>
+ <string name="inventory_item_offered-im">
+ Inventory item offered
+ </string>
+
<string name="only_user_message">
You are the only user in this session.
</string>
diff --git a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
index 3ff0b3062a..08c337455c 100644
--- a/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
+++ b/indra/newview/skins/default/xui/en/widgets/accordion_tab.xml
@@ -1,12 +1,14 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<accordion_tab
- header_bg_color="0.68 0.68 0.68 1"
- header_txt_color="0.68 0.68 0.68 1"
+ font="SansSerifBold"
+ 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.png"
+ header_image="Accordion_Off"
header_image_over="Accordion_Over"
header_image_pressed="Accordion_Press"
+ header_image_expanded="Accordion_Selected"
+ header_text_color="LtGray"
/>
diff --git a/indra/newview/skins/default/xui/en/widgets/button.xml b/indra/newview/skins/default/xui/en/widgets/button.xml
index 3e7e07749a..5bb48ef5aa 100644
--- a/indra/newview/skins/default/xui/en/widgets/button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/button.xml
@@ -11,6 +11,7 @@
image_color="ButtonImageColor"
image_color_disabled="ButtonImageColor"
flash_color="ButtonFlashBgColor"
+ font="SansSerifSmall"
hover_glow_amount="0.15"
halign="center"
scale_image="true">
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..32916c0816
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/chat_history.xml
@@ -0,0 +1,18 @@
+<?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="5"
+ bottom_separator_pad="5"
+ top_header_pad="17"
+ bottom_header_pad="10"
+ max_length="2147483647"
+ enabled="false"
+ track_bottom="true"
+ name="chat_history"
+ type="string"
+ word_wrap="true" /> \ No newline at end of file
diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
index 0dbca318b6..fa3cb9275e 100644
--- a/indra/newview/skins/default/xui/en/widgets/combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml
@@ -4,15 +4,13 @@
max_chars="20"
follows="right|top">
<combo_box.combo_button name="Combobox Button"
- label=""
hover_glow_amount="0.15"
font="SansSerifSmall"
- scale_image="true"
+ scale_image="false"
image_unselected="ComboButton_Off"
image_selected="ComboButton_Selected"
image_disabled="ComboButton_Disabled" />
<combo_box.drop_down_button name="Drop Down Button"
- label=""
hover_glow_amount="0.15"
font="SansSerifSmall"
scale_image="true"
@@ -23,7 +21,11 @@
<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" />
+ font="SansSerifSmall"
+ text_tentative_color="TextFgColor" />
</combo_box>
diff --git a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
index 120deaaef5..f59c46b2f5 100644
--- a/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/expandable_text.xml
@@ -3,8 +3,9 @@
max_height="300" >
<textbox
more_label="More"
- follows="left|top"
+ follows="left|top|right"
name="text"
+ allow_scroll="true"
use_ellipses="true"
word_wrap="true"
tab_stop="true"
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
index 8078579806..888b4eaf7c 100644
--- a/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
+++ b/indra/newview/skins/default/xui/en/widgets/flat_list_view.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<flat_list_view
allow_select="true"
- color="DkGray2"
+ color="PanelFocusBackgroundColor"
item_pad="0"
keep_one_selected="true"
multi_select="false"
diff --git a/indra/newview/skins/default/xui/en/widgets/floater.xml b/indra/newview/skins/default/xui/en/widgets/floater.xml
index 4a866c2eb2..6660fbf1a8 100644
--- a/indra/newview/skins/default/xui/en/widgets/floater.xml
+++ b/indra/newview/skins/default/xui/en/widgets/floater.xml
@@ -1,6 +1,10 @@
<?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"/>
+ background_opaque="false"
+ header_height="25" />
diff --git a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
index 89e442baec..6171be034f 100644
--- a/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/gesture_combo_box.xml
@@ -15,15 +15,16 @@
image_disabled_selected="ComboButton_Disabled_Selected" />
<gesture_combo_box.drop_down_button name="Drop Down Button"
label=""
+ halign="center"
hover_glow_amount="0.15"
font="SansSerif"
scale_image="true"
- pad_right="24"
- image_unselected="DropDown_Off"
- image_selected="DropDown_Selected"
- image_disabled="DropDown_Disabled"
- image_disabled_selected="DropDown_Disabled_Selected" />
- <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor" />
+ image_unselected="PushButton_Off"
+ image_selected="PushButton_Selected"
+ image_disabled="PushButton_Disabled"
+ image_disabled_selected="PushButton_Selected_Disabled" />
+ <gesture_combo_box.combo_list bg_writeable_color="MenuDefaultBgColor"
+ scroll_bar_bg_visible="true" />
<gesture_combo_box.combo_editor name="Combo Text Entry"
select_on_focus="true"
font="SansSerifSmall" />
diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml
index defa6ff00d..d88bcfab1d 100644
--- a/indra/newview/skins/default/xui/en/widgets/location_input.xml
+++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml
@@ -20,8 +20,6 @@
allow_new_values="true"
>
<info_button name="Place Information"
- label=""
- tool_tip="See more info about the current location"
width="16"
height="16"
follows="left|top"
@@ -31,21 +29,18 @@
image_disabled_selected="Info_Off"
image_disabled="Info_Off" />
<add_landmark_button name="Add Landmark"
- label=""
hover_glow_amount="0.15"
image_hover_selected="Favorite_Star_Over"
image_hover_unselected="Favorite_Star_Over"
width="18"
height="18"
- tool_tip="Add this to My Landmarks"
follows="right|top"
scale_image="false"
top="19"
left="-3" />
<combo_button name="Location History"
label=""
- pad_right="0"
- tool_tip="My Location History"/>
+ pad_right="0"/>
<combo_list bg_writeable_color="MenuDefaultBgColor" page_lines="10"
scroll_bar_bg_visible="true" />
<combo_editor name="Combo Text Entry"
diff --git a/indra/newview/skins/default/xui/en/widgets/menu.xml b/indra/newview/skins/default/xui/en/widgets/menu.xml
index 58543338f6..53034afa61 100644
--- a/indra/newview/skins/default/xui/en/widgets/menu.xml
+++ b/indra/newview/skins/default/xui/en/widgets/menu.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<menu bg_color="MenuDefaultBgColor"
bg_visible="true"
- drop_shadow="true"
+ drop_shadow="false"
tear_off="false"
shortcut_pad="15">
</menu>
diff --git a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
index 505c7ba936..98b3e2faaa 100644
--- a/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/output_monitor.xml
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<output_monitor
- image_mute="mute_icon.tga"
+ image_mute="parcel_lght_VoiceNo"
image_off="VoicePTT_Off"
image_on="VoicePTT_On"
image_level_1="VoicePTT_Lvl1"
diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml
index b81a70b845..7262c0dc5c 100644
--- a/indra/newview/skins/default/xui/en/widgets/panel.xml
+++ b/indra/newview/skins/default/xui/en/widgets/panel.xml
@@ -1,5 +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"/> \ No newline at end of file
+ background_opaque="false"
+ chrome="false"/> \ No newline at end of file
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
index a054b4ee60..56204201ef 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_combo_box.xml
@@ -13,8 +13,7 @@
<combo_editor
name="child1"
select_on_focus="true"
- text_pad_left="20"
- tool_tip="Search"
+ text_pad_left="28"
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active"/>
@@ -24,12 +23,11 @@
page_lines="10"
scroll_bar_bg_visible="true" />
<search_button label=""
+ top_pad="5"
+ left_pad="10"
name="child3"
- top_pad="4"
- left_pad="4"
width="13"
height="13"
- tool_tip="Search"
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
index f482ff3b89..9a79243b03 100644
--- a/indra/newview/skins/default/xui/en/widgets/search_editor.xml
+++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml
@@ -7,14 +7,14 @@
background_image="TextField_Search_Off"
background_image_disabled="TextField_Search_Disabled"
background_image_focused="TextField_Search_Active" >
- <search_button label=""
+ <search_button
top_pad="4"
left_pad="4"
width="13"
height="13"
image_unselected="Search"
image_selected="Search" />
- <clear_button label=""
+ <clear_button
image_unselected="Icon_Close_Foreground"
image_selected="Icon_Close_Press" />
</search_editor>
diff --git a/indra/newview/skins/default/xui/en/widgets/split_button.xml b/indra/newview/skins/default/xui/en/widgets/split_button.xml
index c0d3c6d7f6..2ff9ada90a 100644
--- a/indra/newview/skins/default/xui/en/widgets/split_button.xml
+++ b/indra/newview/skins/default/xui/en/widgets/split_button.xml
@@ -1,24 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<split_button
+<split_button
font="SansSerifSmall"
arrow_position="left"
follows="right|top">
- <split_button.arrow_button
- name="Arrow Button"
- label=""
- font="SansSerifSmall"
- scale_image="true"
- image_selected="camera_presets/camera_presets_arrow.png"
- image_unselected="camera_presets/camera_presets_arrow.png"
- image_disabled_selected="camera_presets/camera_presets_arrow.png"
- image_disabled="camera_presets/camera_presets_arrow.png"
- width="10"/>
<split_button.items_panel
background_visible="true"
border="true"
bg_alpha_color="1 1 1 1"
bg_opaq_color="1 1 1 1"
+ 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
index 6dfb6ecf9c..f1401140de 100644
--- a/indra/newview/skins/default/xui/en/widgets/tab_container.xml
+++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml
@@ -1,9 +1,25 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
<tab_container tab_min_width="60"
tab_max_width="150"
- tab_top_image_unselected="TabTop_Middle_Off"
- tab_top_image_selected="TabTop_Middle_Selected"
+ font_halign="center"
+ font="SansSerif"
+ tab_height="21">
+ <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_Left_Off"
- tab_left_image_selected="TabTop_Left_Selected"/> \ No newline at end of file
+ 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="TabTop_Middle_Off"
+ tab_left_image_selected="TabTop_Middle_Selected"/>
+ <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="TabTop_Middle_Off"
+ tab_left_image_selected="TabTop_Middle_Selected"/>
+</tab_container> \ No newline at end of file
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..d9f39b6937
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/talk_button.xml
@@ -0,0 +1,35 @@
+<?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
+ name="left"
+ label="Speak"
+ label_selected="Speak"
+ font="SansSerifSmall"
+ tab_stop="false"
+ is_toggle="true"
+ />
+ <show_button
+ name="right"
+ label=""
+ left="0"
+ top="0"
+ right="20"
+ bottom="0"
+ tab_stop="false"
+ is_toggle="true"
+ image_selected="ComboButton_UpSelected"
+ image_unselected="ComboButton_UpOff"
+ />
+ <monitor
+ name="monitor"
+ left="0"
+ top="18"
+ right="18"
+ bottom="0"
+ />
+</talk_button>
diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml
index 22bda45923..5dd09e663b 100644
--- a/indra/newview/skins/default/xui/en/widgets/text.xml
+++ b/indra/newview/skins/default/xui/en/widgets/text.xml
@@ -3,7 +3,7 @@
mouse_opaque="false"
name="text_box"
font="SansSerifSmall"
- font_shadow="soft"
+ font_shadow="none"
tab_stop="false"
halign="left"
hover_color="LabelSelectedColor"
diff --git a/indra/newview/skins/default/xui/en/widgets/textbase.xml b/indra/newview/skins/default/xui/en/widgets/textbase.xml
index e5dc022633..6dd92ea34b 100644
--- a/indra/newview/skins/default/xui/en/widgets/textbase.xml
+++ b/indra/newview/skins/default/xui/en/widgets/textbase.xml
@@ -1,4 +1,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<textbase allow_scroll="true"
- h_pad="5"
- v_pad="5"/>
+<textbase/>
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..6b49f832fd
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/widgets/tool_tip.xml
@@ -0,0 +1,10 @@
+<?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_color="ToolTipBgColor"
+ background_visible="true"
+ />
diff --git a/indra/newview/skins/default/xui/es/floater_about.xml b/indra/newview/skins/default/xui/es/floater_about.xml
index 071d505569..5545ab29e0 100644
--- a/indra/newview/skins/default/xui/es/floater_about.xml
+++ b/indra/newview/skins/default/xui/es/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Acerca de [APP_NAME]">
+<floater name="floater_about" title="ACERCA DE [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 bc775c1b1c..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,5 +1,5 @@
<?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 name="Name:">
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 68a56ac678..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">
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 c3e4acacf0..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opciones de la cuadrícula">
+<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"/>
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 2346798f94..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,5 +1,5 @@
<?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>
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 a01e07e694..af542acbce 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>
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 7ee15955eb..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,5 +1,5 @@
<?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>
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_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 616c373d18..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>
diff --git a/indra/newview/skins/default/xui/es/floater_customize.xml b/indra/newview/skins/default/xui/es/floater_customize.xml
index 1322b9a5cf..94452dae6b 100644
--- a/indra/newview/skins/default/xui/es/floater_customize.xml
+++ b/indra/newview/skins/default/xui/es/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Partes del cuerpo" name="body_parts_placeholder"/>
<panel label="Forma" name="Shape" width="389">
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 9ee7fc3ead..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"/>
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 65710fc5ed..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,5 +1,5 @@
<?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
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 e7f1a7aca2..496881f2d2 100644
--- a/indra/newview/skins/default/xui/es/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/es/floater_gesture.xml
@@ -1,5 +1,5 @@
<?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.
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 ea2571ecb8..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"
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 29750ee737..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>
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_inspect.xml b/indra/newview/skins/default/xui/es/floater_inspect.xml
index 026081bc04..3c8b38648f 100644
--- a/indra/newview/skins/default/xui/es/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/es/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Examinar objetos" min_width="450">
+<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="Propietario" name="owner_name"/>
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 4df3ca2cf6..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>
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 7cd787bfb5..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"/>
diff --git a/indra/newview/skins/default/xui/es/floater_joystick.xml b/indra/newview/skins/default/xui/es/floater_joystick.xml
index 2e0fb87744..75c53dd646 100644
--- a/indra/newview/skins/default/xui/es/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/es/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuración del joystick">
+<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"/>
diff --git a/indra/newview/skins/default/xui/es/floater_lagmeter.xml b/indra/newview/skins/default/xui/es/floater_lagmeter.xml
index 1af0bb065c..54c4ce8c6a 100644
--- a/indra/newview/skins/default/xui/es/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/es/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?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:
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 5df319905d..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"/>
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 226c3482af..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,5 +1,5 @@
<?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" left="4"/>
<check_box label="Mono" name="mono" left="106"/>
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 859a2d3812..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,5 +1,5 @@
<?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" left_delta="120" width="70"/>
<button label="Atrás" name="back_btn" left_delta="75"/>
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 79c8980c02..ff50b56a32 100644
--- a/indra/newview/skins/default/xui/es/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/es/floater_media_browser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Navegador">
+<floater name="floater_about" title="NAVEGADOR">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Atrás" name="back" width="75"/>
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_mute_object.xml b/indra/newview/skins/default/xui/es/floater_mute_object.xml
index 0cf38c09ee..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Ignorar un objeto según su nombre">
+<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.
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 60487b829c..89c79e8833 100644
--- a/indra/newview/skins/default/xui/es/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/es/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Contenido del objeto">
+<floater name="objectcontents" title="CONTENIDO DEL OBJETO">
<text name="object_name">
[DESC]:
</text>
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 6a9811c058..ace3204cc7 100644
--- a/indra/newview/skins/default/xui/es/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/es/floater_postcard.xml
@@ -1,5 +1,5 @@
<?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:
diff --git a/indra/newview/skins/default/xui/es/floater_preferences.xml b/indra/newview/skins/default/xui/es/floater_preferences.xml
index df7fc93dd9..5fe4ae3b64 100644
--- a/indra/newview/skins/default/xui/es/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/es/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferencias" min_width="350" width="646">
+<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"/>
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_notecard.xml b/indra/newview/skins/default/xui/es/floater_preview_notecard.xml
index 4d11520335..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,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="Guardar" label_selected="Guardar" name="Save"/>
<text name="desc txt">
Descripción:
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 8ae8c212e6..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">
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 0d8cd0b406..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="preview lsl text" title="Script: script de rotación">
+<floater name="preview lsl text" title="SCRIPT: SCRIPT DE ROTACIÓN">
<text name="desc txt">
Descripción:
</text>
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 3c8dc2fe9c..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Buscar en el script" width="320">
+<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"/>
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 bce13c1e33..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,5 @@
<?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">
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 1d5ad2f34c..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,5 +1,5 @@
<?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_box.item name="TRUE" label="TRUE" />
<combo_box.item name="FALSE" label="FALSE" />
diff --git a/indra/newview/skins/default/xui/es/floater_snapshot.xml b/indra/newview/skins/default/xui/es/floater_snapshot.xml
index c1ace23503..afea6c09fe 100644
--- a/indra/newview/skins/default/xui/es/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/es/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?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>
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 74084e9db9..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" min_height="310" height="310">
+<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>
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 8b661a6041..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/es/floater_tools.xml b/indra/newview/skins/default/xui/es/floater_tools.xml
index 06f0a6d4d0..24db352ac4 100644
--- a/indra/newview/skins/default/xui/es/floater_tools.xml
+++ b/indra/newview/skins/default/xui/es/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Construir" width="288">
+<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"/>
@@ -516,7 +516,7 @@
Superficie: [AREA] m²
</text>
<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"/>
+ <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
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 95f2c39d42..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>
diff --git a/indra/newview/skins/default/xui/es/floater_water.xml b/indra/newview/skins/default/xui/es/floater_water.xml
index 934fc7882b..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>
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 e240dea0b5..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,5 +1,5 @@
<?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>
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 6521e72d5a..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"/>
diff --git a/indra/newview/skins/default/xui/es/notifications.xml b/indra/newview/skins/default/xui/es/notifications.xml
index 4a2dec9210..86f3f1f125 100644
--- a/indra/newview/skins/default/xui/es/notifications.xml
+++ b/indra/newview/skins/default/xui/es/notifications.xml
@@ -1760,7 +1760,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.
@@ -1769,7 +1769,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:
@@ -2917,7 +2917,7 @@ Los objetos flexibles no pueden ser materiales, y serán inmateriales hasta que
<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 &#8984;-Opt-D.
+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;.
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_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_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/strings.xml b/indra/newview/skins/default/xui/es/strings.xml
index 0735bb0082..294e407278 100644
--- a/indra/newview/skins/default/xui/es/strings.xml
+++ b/indra/newview/skins/default/xui/es/strings.xml
@@ -498,16 +498,16 @@ Si aun así persiste este mensaje, reinicie su ordenador.
Si sigue recibiendo este mensaje, contacte con el [SUPPORT_SITE].
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Alt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Mayús-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -615,6 +615,9 @@ Si sigue recibiendo este mensaje, contacte con el [SUPPORT_SITE].
<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>
@@ -633,4 +636,31 @@ Si sigue recibiendo este mensaje, contacte con el [SUPPORT_SITE].
<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 7b918be075..53e48352f1 100644
--- a/indra/newview/skins/default/xui/fr/floater_about.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="A propos de [APP_NAME]">
+<floater name="floater_about" title="A PROPOS DE [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 f2d2dbfa07..0729c79cbb 100644
--- a/indra/newview/skins/default/xui/fr/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_about_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterland" title="À propos du terrain">
+<floater name="floaterland" title="À PROPOS DU TERRAIN">
<tab_container name="landtab">
<panel label="Général" name="land_general_panel">
<text name="Name:">
diff --git a/indra/newview/skins/default/xui/fr/floater_auction.xml b/indra/newview/skins/default/xui/fr/floater_auction.xml
index 4bdf9df1be..3ec95a60c5 100644
--- a/indra/newview/skins/default/xui/fr/floater_auction.xml
+++ b/indra/newview/skins/default/xui/fr/floater_auction.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_auction" title="Commencer la vente de terrain Linden">
+<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_box.item name="Auction" label="Enchères" />
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..c713d3e930 100644
--- a/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml
+++ b/indra/newview/skins/default/xui/fr/floater_avatar_picker.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Choisir le résident">
+<floater name="avatarpicker" title="CHOISIR LE RÉSIDENT">
<tab_container name="ResidentChooserTabs">
<panel label="Rechercher" name="SearchPanel">
<text name="InstructSearchResidentName">
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..569126f3ec 100644
--- a/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml
+++ b/indra/newview/skins/default/xui/fr/floater_avatar_textures.xml
@@ -1,5 +1,5 @@
<?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 DE L&apos;AVATAR">
<text name="label">
Textures fixées
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_beacons.xml b/indra/newview/skins/default/xui/fr/floater_beacons.xml
index 0b060983ee..4f5c5d442f 100644
--- a/indra/newview/skins/default/xui/fr/floater_beacons.xml
+++ b/indra/newview/skins/default/xui/fr/floater_beacons.xml
@@ -1,5 +1,5 @@
<?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"/>
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..76e8e2f637 100644
--- a/indra/newview/skins/default/xui/fr/floater_build_options.xml
+++ b/indra/newview/skins/default/xui/fr/floater_build_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="build options floater" title="Options de la grille">
+<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" />
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..98b7faa2cc 100644
--- a/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
+++ b/indra/newview/skins/default/xui/fr/floater_bulk_perms.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floaterbulkperms" title="Changement des droits relatifs au contenu">
+<floater name="floaterbulkperms" title="CHANGEMENT DES DROITS RELATIFS AU CONTENU">
<text name="applyto">
Types de contenu
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_bumps.xml b/indra/newview/skins/default/xui/fr/floater_bumps.xml
index e12c7ed17d..e439c30524 100644
--- a/indra/newview/skins/default/xui/fr/floater_bumps.xml
+++ b/indra/newview/skins/default/xui/fr/floater_bumps.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_bumps" title="Collisions, coups et bousculades">
+<floater name="floater_bumps" title="COLLISIONS, COUPS ET BOUSCULADES">
<text name="none_detected">
Aucun détecté
</text>
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..e8b47f5365 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 CE CONTENU">
<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..9112d30be2 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_currency.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="buy currency" title="Acheter des L$">
+<floater name="buy currency" title="ACHETER DES L$">
<text left="5" name="info_buying">
Achat de L$ :
</text>
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 aaf1577114..2b93098847 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 LE TERRAIN">
<text name="region_name_label">
Région :
</text>
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..893d559e6e 100644
--- a/indra/newview/skins/default/xui/fr/floater_buy_object.xml
+++ b/indra/newview/skins/default/xui/fr/floater_buy_object.xml
@@ -1,5 +1,5 @@
<?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 :
</text>
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..15cdd4d332 100644
--- a/indra/newview/skins/default/xui/fr/floater_choose_group.xml
+++ b/indra/newview/skins/default/xui/fr/floater_choose_group.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="groups" title="Groupes">
+<floater name="groups" title="GROUPES">
<text name="groupdesc">
Choisissez un groupe :
</text>
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 94bcad070e..996f3e9b07 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="CHOIX DE TEXTURE ET DE COULEUR">
<text name="r_val_text">
Rouge :
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_customize.xml b/indra/newview/skins/default/xui/fr/floater_customize.xml
index 1250c46933..bf70c5415e 100644
--- a/indra/newview/skins/default/xui/fr/floater_customize.xml
+++ b/indra/newview/skins/default/xui/fr/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Parties du corps" name="body_parts_placeholder"/>
<panel label="Silhouette" left="154" name="Shape" width="389">
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..5374b4e593 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,3 @@
<?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" />
+ 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..7d6de114be 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,5 @@
<?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">
<text bottom="-45" name="EnvTimeText">
Heure de la
journée
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..3a32e8adc5 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 LA 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..b3026478ff 100644
--- a/indra/newview/skins/default/xui/fr/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/fr/floater_gesture.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="gestures" title="Gestes utilisés">
+<floater name="gestures" title="GESTES UTILISÉS">
<text name="help_label">
Double-cliquez sur un geste pour jouer les animations
et les sons.
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 461956ff34..33cb43f7ac 100644
--- a/indra/newview/skins/default/xui/fr/floater_god_tools.xml
+++ b/indra/newview/skins/default/xui/fr/floater_god_tools.xml
@@ -1,5 +1,5 @@
<?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" />
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 11d7fc28e9..6c1ea09c90 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="CONFIGURATION DU MATÉRIEL">
<text name="Filtering:">
Filtres :
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_hud.xml b/indra/newview/skins/default/xui/fr/floater_hud.xml
index 55c8b57ae2..13ca0e8770 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" />
+<floater name="floater_hud" title="DIDACTICIEL" />
diff --git a/indra/newview/skins/default/xui/fr/floater_inspect.xml b/indra/newview/skins/default/xui/fr/floater_inspect.xml
index f140c66de0..944a157f17 100644
--- a/indra/newview/skins/default/xui/fr/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="inspect" title="Inspecter les objets">
+<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" />
diff --git a/indra/newview/skins/default/xui/fr/floater_inventory.xml b/indra/newview/skins/default/xui/fr/floater_inventory.xml
index 7173025d18..a83a95fa75 100644
--- a/indra/newview/skins/default/xui/fr/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/fr/floater_inventory.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Inventory" title="Inventaire">
+<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"/>
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 ec83d5bcaa..2885a7e316 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,5 @@
<?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 DE L&apos;OBJET DE L&apos;INVENTAIRE">
<text name="LabelItemNameTitle">
Nom :
</text>
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 634bb6e2e9..8fb8d3c6f4 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"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_joystick.xml b/indra/newview/skins/default/xui/fr/floater_joystick.xml
index 75800847d7..546c95de4c 100644
--- a/indra/newview/skins/default/xui/fr/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/fr/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuration du joystick">
+<floater name="Joystick" title="CONFIGURATION DU JOYSTICK">
<check_box name="enable_joystick" label="Activer :"/>
<spinner label="Mapping axe des X " name="JoystickAxis1"/>
<spinner label="Mapping axe des Y" name="JoystickAxis2"/>
diff --git a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
index 54069c9c49..593ad903b9 100644
--- a/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/fr/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_lagmeter" title="Mesure du lag">
+<floater name="floater_lagmeter" title="MESURE DU LAG">
<button name="client_lagmeter" tool_tip="Statut du lag client"/>
<text name="client">
Client :
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..17adafa8d9 100644
--- a/indra/newview/skins/default/xui/fr/floater_land_holdings.xml
+++ b/indra/newview/skins/default/xui/fr/floater_land_holdings.xml
@@ -1,5 +1,5 @@
<?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="Région" name="location"/>
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..76db22cea4 100644
--- a/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml
+++ b/indra/newview/skins/default/xui/fr/floater_live_lsleditor.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Script : Nouveau script">
+<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"/>
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..2e3d88264e 100644
--- a/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/fr/floater_lsl_guide.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script ed float" title="Wiki LSL">
+<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"/>
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..5a787a6bf9 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,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Navigateur">
+<floater name="floater_about" title="NAVIGATEUR">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Précédente" name="back" width="75"/>
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 8ee3a23b95..e62aad6cd3 100644
--- a/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml
+++ b/indra/newview/skins/default/xui/fr/floater_mem_leaking.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="MemLeak" title="Simulation fuite mémoire">
+<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" />
<text name="total_leaked_label">
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..aae5770d51 100644
--- a/indra/newview/skins/default/xui/fr/floater_mute_object.xml
+++ b/indra/newview/skins/default/xui/fr/floater_mute_object.xml
@@ -1,5 +1,5 @@
<?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 LES OBJETS 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.
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..841a42a0ea 100644
--- a/indra/newview/skins/default/xui/fr/floater_my_friends.xml
+++ b/indra/newview/skins/default/xui/fr/floater_my_friends.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="floater_my_friends" title="Contacts">
+<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" />
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..fd3782bac2 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"/>
</floater>
diff --git a/indra/newview/skins/default/xui/fr/floater_openobject.xml b/indra/newview/skins/default/xui/fr/floater_openobject.xml
index 3761200d48..5ffa2f236d 100644
--- a/indra/newview/skins/default/xui/fr/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/fr/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Contenu des objets">
+<floater name="objectcontents" title="CONTENU DES OBJETS">
<text name="object_name">
[DESC]:
</text>
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..4b885f3afb 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="DROITS 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 ab21d7423a..9c998c1838 100644
--- a/indra/newview/skins/default/xui/fr/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/fr/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Postcard" title="Envoyer la photo par e-mail">
+<floater name="Postcard" title="ENVOYER LA PHOTO PAR E-MAIL">
<text name="to_label" width="135">
E-mail du destinataire :
</text>
diff --git a/indra/newview/skins/default/xui/fr/floater_preferences.xml b/indra/newview/skins/default/xui/fr/floater_preferences.xml
index 9dab4d642c..ccd29a01dc 100644
--- a/indra/newview/skins/default/xui/fr/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Preferences" title="Préférences" min_width="330" width="626">
+<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" />
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..436a386dc8 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,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="classified_preview" title="Informations sur la petite annonce" />
+<floater name="classified_preview" title="INFORMATIONS SUR LA PETITE ANNONCE" />
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..30eeeec70d 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,2 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="event_preview" title="Informations sur l&apos;événement" />
+<floater name="event_preview" title="INFORMATIONS SUR L&apos;ÉVÉNEMENT" />
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 a23b906df6..ea52442236 100644
--- a/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml
+++ b/indra/newview/skins/default/xui/fr/floater_preview_notecard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview notecard" title="Remarque :">
+<floater name="preview notecard" title="REMARQUE :">
<button label="Enregistrer" label_selected="Enregistrer" name="Save" />
<text name="desc txt">
Description :
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..3ec1ebf7e6 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 ET 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 687b3068e6..be97165a3e 100644
--- a/indra/newview/skins/default/xui/fr/floater_report_abuse.xml
+++ b/indra/newview/skins/default/xui/fr/floater_report_abuse.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_report_abuse" title="Signaler une infraction">
+<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"/>
<text name="reporter_title" width="60">
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_preview.xml b/indra/newview/skins/default/xui/fr/floater_script_preview.xml
index b767081625..43541e8de3 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_preview.xml
+++ b/indra/newview/skins/default/xui/fr/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 de rotation">
+<floater name="preview lsl text" title="SCRIPT : SCRIPT DE ROTATION">
<text name="desc txt">
Description :
</text>
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..d5f39e7ace 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,4 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="queue" title="Réinitialiser progression">
+<floater name="queue" title="RÉINITIALISER PROGRESSION">
<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 6f912026c4..49b0ffe542 100644
--- a/indra/newview/skins/default/xui/fr/floater_script_search.xml
+++ b/indra/newview/skins/default/xui/fr/floater_script_search.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="script search" title="Recherche de scripts" width="320">
+<floater name="script search" title="RECHERCHE DE SCRIPTS" width="320">
<check_box label="Non sensible à la casse" name="case_text" left="75"/>
<button label="Rechercher" label_selected="Rechercher" name="search_btn" width="96"/>
<button label="Remplacer" label_selected="Remplacer" name="replace_btn" left="111" width="96"/>
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 643a9435db..81c3ccc79a 100644
--- a/indra/newview/skins/default/xui/fr/floater_sell_land.xml
+++ b/indra/newview/skins/default/xui/fr/floater_sell_land.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="sell land" title="Vendre terrain">
+<floater name="sell land" title="VENDRE TERRAIN">
<scroll_container name="profile_scroll">
<panel name="scroll_content_panel">
<text name="info_parcel_label">
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 e67b8e2f79..f0781d0b32 100644
--- a/indra/newview/skins/default/xui/fr/floater_settings_debug.xml
+++ b/indra/newview/skins/default/xui/fr/floater_settings_debug.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="settings_debug" title="Paramétrages du mode Debug">
+<floater name="settings_debug" title="PARAMÉTRAGES DU MODE DEBUG">
<combo_box name="boolean_combo">
<combo_box.item name="TRUE" label="TRUE" />
<combo_box.item name="FALSE" label="FALSE" />
diff --git a/indra/newview/skins/default/xui/fr/floater_snapshot.xml b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
index 49c6ff04a6..a28e64f7af 100644
--- a/indra/newview/skins/default/xui/fr/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/fr/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Prévisualiser la photo" width="247">
+<floater name="Snapshot" title="PRÉVISUALISER LA PHOTO" width="247">
<text name="type_label">
Destination de la photo
</text>
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 1ab3a4a714..9e2b30b3f6 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>
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_telehub.xml b/indra/newview/skins/default/xui/fr/floater_telehub.xml
index e6201785bd..c89eea517e 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" >
+<floater name="telehub" title="TÉLÉHUB" min_height="310" height="310" >
<text name="status_text_connected">
Téléhub connecté à l&apos;objet [OBJECT]
</text>
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 fa8b65d8a5..ff84025a44 100644
--- a/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
+++ b/indra/newview/skins/default/xui/fr/floater_texture_ctrl.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="texture picker" title="Texture">
+<floater name="texture picker" title="TEXTURE">
<string name="choose_picture">
Cliquez pour sélectionner une image
</string>
diff --git a/indra/newview/skins/default/xui/fr/floater_tools.xml b/indra/newview/skins/default/xui/fr/floater_tools.xml
index c675374545..3638c3fb42 100644
--- a/indra/newview/skins/default/xui/fr/floater_tools.xml
+++ b/indra/newview/skins/default/xui/fr/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Construire">
+<floater name="toolbox floater" title="" short_title="CONSTRUIRE">
<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"/>
@@ -458,7 +458,7 @@
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"/>
+ <check_box label="Afficher les propriétaires" name="checkbox show owners" tool_tip="Colorie les parcelles en fonction de leur propriétaire : &#10;&#10;Vert = votre terrain &#10;Turquoise = le terrain de votre groupe &#10;Rouge = appartenant à d&apos;autres &#10;Jaune = en vente &#10;Mauve = aux enchères &#10;Gris = public"/>
<button label="?" label_selected="?" name="button show owners help" left_delta="154"/>
<text name="label_parcel_modify">
Modifier la parcelle
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_water.xml b/indra/newview/skins/default/xui/fr/floater_water.xml
index 9b77c2450d..3de5fee0ce 100644
--- a/indra/newview/skins/default/xui/fr/floater_water.xml
+++ b/indra/newview/skins/default/xui/fr/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Éditeur d&apos;eau avancé">
+<floater name="Water Floater" title="ÉDITEUR D&apos;EAU AVANCé">
<text name="KeyFramePresetsText">
Préréglages eau :
</text>
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..4ff55d87b6 100644
--- a/indra/newview/skins/default/xui/fr/floater_windlight_options.xml
+++ b/indra/newview/skins/default/xui/fr/floater_windlight_options.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Éditeur de ciel avancé" width="706">
+<floater name="WindLight floater" title="ÉDITEUR DE CIEL AVANCÉ" width="706">
<text name="KeyFramePresetsText">
Préréglages ciel :
</text>
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 ec2db5f163..1f76202dee 100644
--- a/indra/newview/skins/default/xui/fr/floater_world_map.xml
+++ b/indra/newview/skins/default/xui/fr/floater_world_map.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="worldmap" title="Carte du monde">
+<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"/>
diff --git a/indra/newview/skins/default/xui/fr/notifications.xml b/indra/newview/skins/default/xui/fr/notifications.xml
index a604569303..a38cf858e0 100644
--- a/indra/newview/skins/default/xui/fr/notifications.xml
+++ b/indra/newview/skins/default/xui/fr/notifications.xml
@@ -1682,7 +1682,7 @@ Si cette option est cochée, les propriétaires sont libres de revendre leur par
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.
+ 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.
@@ -1692,7 +1692,7 @@ 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.
+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.
@@ -2842,7 +2842,7 @@ Les objets flexibles ne peuvent pas avoir de propriétés physiques et doivent r
<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 &#8984;-Opt-Maj-D
+Pour activer/désactiver ce menu sous Windows, appuyez sur Ctrl+Alt+D. Sur un Mac, appuyez sur &#8997;&#8984;D
</notification>
<notification name="FirstSculptedPrim">
Vous êtes en train d&apos;éditer un sculptie.
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..3a1585bce2
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/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="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" />
+ <string name="AgeVerified"
+ value="Âge vérifié" />
+ <string name="NotAgeVerified"
+ value="Âge non vérifié" />
+ <string name="partner_edit_link_url">
+ http://www.secondlife.com/account/partners.php?lang=fr
+ </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="Partenaire :"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ Réponse si occupé(e) :
+ </text>
+ </panel>
+ </panel>
+</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..61fcd912f5
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_alerts.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Pop-ups" name="popups" title="Pop-ups">
+ <text name="text_box">
+ Ne pas afficher les pop-ups :
+ </text>
+ <text name="dont_show_label">
+ Ne pas afficher ces pop-ups :
+ </text>
+ <button label="Activer ce pop-up" label_selected="Autoriser ce pop-up" name="enable_popup"/>
+ <text name="show_label">
+ Afficher ces pop-ups :
+ </text>
+ <button label="Désactiver tous les pop-ups" name="skip_dialogs_btn" tool_tip="Désactiver tous les pop-ups et les notifications envoyées lors d&apos;un premier usage." width="185"/>
+ <text name="text_box2">
+ Offres de notes, textures et repères :
+ </text>
+ <button label="Activer tous les pop-ups" label_selected="Réinitialiser les dialogues &apos;Afficher la prochaine fois&apos;..." name="reset_dialogs_btn" tool_tip="Activer tous les pop-ups et les notifications envoyées lors d&apos;un premier usage." width="185"/>
+ <check_box label="Accepter automatiquement" name="accept_new_inventory"/>
+ <check_box label="Afficher après avoir accepté" name="show_new_inventory"/>
+ <check_box label="Ouvrir l&apos;inventaire et sélectionner les objets reçus" name="show_in_inventory"/>
+</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..527097b392
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_privacy.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Communication" name="im">
+ <text name="text_box">
+ Mon statut en ligne :
+ </text>
+ <check_box label="Seuls mes amis et groupes voient quand je suis connecté(e)" name="online_visibility"/>
+ <text name="log_in_to_change">
+ se connecter pour changer
+ </text>
+ <check_box label="Envoyer les IM à mon adresse e-mail ([EMAIL])" name="send_im_to_email"/>
+ <check_box label="Afficher les IM dans la console du chat" name="include_im_in_chat_console"/>
+ <check_box label="Afficher l&apos;heure dans les IM" name="show_timestamps_check"/>
+ <check_box label="Me prévenir quand des amis se connectent" name="friends_online_notify_checkbox"/>
+ <text name="text_box3">
+ Réponse si occupé(e) :
+ </text>
+ <text name="text_box4">
+ Enregistrements :
+ </text>
+ <check_box label="Enregistrer les IM sur mon ordinateur" name="log_instant_messages"/>
+ <check_box label="Inclure les heures" name="log_instant_messages_timestamp"/>
+ <check_box label="Enregistrer le chat local sur mon ordinateur" name="log_chat"/>
+ <check_box label="Inclure la fin de la dernière conversation IM" name="log_show_history"/>
+ <check_box label="Inclure les heures" name="log_chat_timestamp"/>
+ <check_box label="Inclure les IM reçus" name="log_chat_IM"/>
+ <check_box label="Inclure la date avec les heures" name="log_date_timestamp"/>
+ <button label="Changer d&apos;emplacement" label_selected="Changer d&apos;emplacement" name="log_path_button" width="150"/>
+ <line_editor left="308" name="log_path_string" right="-20"/>
+ <text name="text_box2">
+ IM :
+ </text>
+</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..b52ab672b0
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_setup.xml
@@ -0,0 +1,30 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Contrôle et caméra" name="Input panel">
+ <text name=" Mouselook Options:">
+ Vue subjective :
+ </text>
+ <text name=" Mouse Sensitivity:">
+ Sensibilité de la souris :
+ </text>
+ <check_box label="Inverser la souris" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ Vol automatique :
+ </text>
+ <check_box label="Voler/atterrir en appuyant sur la flèche du haut/bas" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ Options de la caméra :
+ </text>
+ <text name="camera_fov_label">
+ Angle de vision :
+ </text>
+ <text name="Camera Follow Distance:">
+ Distance :
+ </text>
+ <check_box label="Ajustement automatique en mode Édition" name="edit_camera_movement" tool_tip="Positionner automatiquement la caméra lors de l&apos;entrée ou de la sortie du mode Édition"/>
+ <check_box label="Ajustement automatique en mode Édition d&apos;apparence" name="appearance_camera_movement" tool_tip="Positionner automatiquement la caméra en mode Édition"/>
+ <text name="text2">
+ Affichage de l&apos;avatar :
+ </text>
+ <check_box label="Montrer l&apos;avatar en vue subjective" name="first_person_avatar_visible"/>
+ <button label="Configuration du joystick" name="joystick_setup_button" width="175"/>
+</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..facd22988c
--- /dev/null
+++ b/indra/newview/skins/default/xui/fr/panel_preferences_sound.xml
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="Audio et vidéo" name="Preference Media panel">
+ <slider label="Principal" name="System Volume"/>
+ <slider label="Son ambiant" name="Wind Volume"/>
+ <slider label="Sons" name="SFX Volume"/>
+ <slider label="Média" name="Media Volume"/>
+ <slider label="Interface" name="UI Volume"/>
+ <slider label="Musique" name="Music Volume"/>
+ <slider label="Voix" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ Le chat vocal n&apos;est pas disponible
+ </text_editor>
+ <check_box label="Activer la voix" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="Écouter depuis la position de la caméra." />
+ <radio_item name="1" label="Écouter depuis la position de l&apos;avatar." />
+ </radio_group>
+ <button label="Paramètres du matériel" name="device_settings_btn"/>
+ <text name="muting_text">
+ Volume :
+ </text>
+ <panel name="Volume Panel" width="249"/>
+ <check_box label="Couper le son" name="disable audio"/>
+ <text bottom="-195" name="streaming_prefs_text" width="145">
+ Média :
+ </text>
+ <text name="audio_prefs_text">
+ Audio :
+ </text>
+ <panel label="Volume" name="Volume Panel"/>
+ <check_box label="Couper le son lorsque la fenêtre est minimisée" name="mute_when_minimized"/>
+ <check_box label="Jouer la musique disponible" name="streaming_music"/>
+ <check_box label="Jouer le média disponible" name="streaming_video"/>
+ <check_box label="Lire automatiquement le média" name="auto_streaming_video"/>
+ <slider label="Effet Doppler" label_width="115" name="Doppler Effect"/>
+ <slider label="Facteur d&apos;éloignement" label_width="115" name="Distance Factor"/>
+ <slider label="Facteur d&apos;atténuation" label_width="115" name="Rolloff Factor"/>
+ <spinner label="Alerte L$" name="L$ Change Threshold"/>
+ <spinner label="Alerte santé" name="Health Change Threshold"/>
+</panel>
diff --git a/indra/newview/skins/default/xui/fr/strings.xml b/indra/newview/skins/default/xui/fr/strings.xml
index 6bdee836d9..070d2cd1a5 100644
--- a/indra/newview/skins/default/xui/fr/strings.xml
+++ b/indra/newview/skins/default/xui/fr/strings.xml
@@ -488,16 +488,16 @@
Choisir le répertoire
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Maj-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -604,6 +604,9 @@
<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>
@@ -622,4 +625,31 @@
<string name="close_on_no_ability">
Vous ne pouvez plus participer à la session de chat.
</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
+ </string>
+ <string name="AgeVerified">
+ Âge vérifié
+ </string>
+ <string name="NotAgeVerified">
+ Âge non vérifié
+ </string>
</strings>
diff --git a/indra/newview/skins/default/xui/it/floater_about.xml b/indra/newview/skins/default/xui/it/floater_about.xml
index 2c91375930..a5aff9d486 100644
--- a/indra/newview/skins/default/xui/it/floater_about.xml
+++ b/indra/newview/skins/default/xui/it/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Informazioni su [APP_NAME]">
+<floater name="floater_about" title="INFORMAZIONI SU [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 ede581c5ed..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:">
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 a223e30fb5..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">
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 2c60aeda2b..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opzioni della griglia">
+<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"/>
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 2836f98970..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,5 +1,5 @@
<?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>
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 a24f0dbe7a..6b881683f1 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>
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 d6036c19dd..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>
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_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 1e6d7bc3f0..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>
diff --git a/indra/newview/skins/default/xui/it/floater_customize.xml b/indra/newview/skins/default/xui/it/floater_customize.xml
index eac673e004..ad6111718a 100644
--- a/indra/newview/skins/default/xui/it/floater_customize.xml
+++ b/indra/newview/skins/default/xui/it/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Parti del corpo" name="body_parts_placeholder"/>
<panel label="Forma del corpo" name="Shape" left="124" width="389">
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 4c62d4f5a2..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,5 +1,5 @@
<?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"/>
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 36f97bda81..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,5 +1,5 @@
<?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
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 997e13ecb5..91b7381d13 100644
--- a/indra/newview/skins/default/xui/it/floater_gesture.xml
+++ b/indra/newview/skins/default/xui/it/floater_gesture.xml
@@ -1,5 +1,5 @@
<?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.
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 688f9137a2..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>
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_inspect.xml b/indra/newview/skins/default/xui/it/floater_inspect.xml
index 6028c40557..1a4e6c3c1b 100644
--- a/indra/newview/skins/default/xui/it/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/it/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Ispeziona oggetti" min_width="450">
+<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="Proprietario" name="owner_name"/>
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 e32f57e9f4..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>
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 c2c05b4023..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" width="165">
+<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 b7b7663910..d74ff9bfb4 100644
--- a/indra/newview/skins/default/xui/it/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/it/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configurazione Joystick">
+<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"/>
diff --git a/indra/newview/skins/default/xui/it/floater_lagmeter.xml b/indra/newview/skins/default/xui/it/floater_lagmeter.xml
index af70ad9d31..5ed748da69 100644
--- a/indra/newview/skins/default/xui/it/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/it/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?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" />
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 85661c28d7..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"/>
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 bb1f6116cf..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,5 +1,5 @@
<?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" left="4"/>
<check_box label="Mono" name="mono" left="106"/>
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 ec62dd087d..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,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="Segui il cursore" name="lock_check"/>
<combo_box label="Blocca" name="history_combo" left_delta="120" width="70"/>
<button label="Indietro" name="back_btn" left_delta="75"/>
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 4d3462b348..7a5f9c9fcb 100644
--- a/indra/newview/skins/default/xui/it/floater_media_browser.xml
+++ b/indra/newview/skins/default/xui/it/floater_media_browser.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Browser multimediale">
+<floater name="floater_about" title="BROWSER MULTIMEDIALE">
<layout_stack name="stack1">
<layout_panel name="nav_controls">
<button label="Indietro" name="back" width="75"/>
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_mute_object.xml b/indra/newview/skins/default/xui/it/floater_mute_object.xml
index 6bacdcab41..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,5 +1,5 @@
<?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.
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_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 5132771acc..5ea3b634d4 100644
--- a/indra/newview/skins/default/xui/it/floater_postcard.xml
+++ b/indra/newview/skins/default/xui/it/floater_postcard.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Postcard" title="Invia la fotografia via email">
+<floater name="Postcard" title="INVIA LA FOTOGRAFIA VIA EMAIL">
<text name="to_label" width="135">
Email del destinatario:
</text>
diff --git a/indra/newview/skins/default/xui/it/floater_preferences.xml b/indra/newview/skins/default/xui/it/floater_preferences.xml
index 6277300bee..172449554d 100644
--- a/indra/newview/skins/default/xui/it/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/it/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferenze" min_width="350" width="646">
+<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"/>
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_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 c67fc69db6..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:
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 470fb76135..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Cerca Script" width="320">
+<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"/>
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 79dd2c5abf..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,5 @@
<?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">
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 6dd1b7978d..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,5 +1,5 @@
<?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_box.item name="TRUE" label="VERO"/>
<combo_box.item name="FALSE" label="FALSO"/>
diff --git a/indra/newview/skins/default/xui/it/floater_snapshot.xml b/indra/newview/skins/default/xui/it/floater_snapshot.xml
index 808158ff7e..e226ce6ffe 100644
--- a/indra/newview/skins/default/xui/it/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/it/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Snapshot" title="Anteprima della fotografia" width="247">
+<floater name="Snapshot" title="ANTEPRIMA DELLA FOTOGRAFIA" width="247">
<text name="type_label">
Destinazione della fotografia
</text>
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 0c5199dbc7..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" min_height="310" height="310" width="286">
+<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286">
<text name="status_text_connected">
Telehub connesso all&apos;oggetto [OBJECT]
</text>
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 677a567808..8e6f27e162 100644
--- a/indra/newview/skins/default/xui/it/floater_tools.xml
+++ b/indra/newview/skins/default/xui/it/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Costruisci" width="288">
+<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"/>
@@ -518,7 +518,7 @@
Area: [AREA] m²
</text>
<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"/>
+ <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
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 470e21769c..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/it/floater_water.xml b/indra/newview/skins/default/xui/it/floater_water.xml
index 33f91ed1c8..13db1d4589 100644
--- a/indra/newview/skins/default/xui/it/floater_water.xml
+++ b/indra/newview/skins/default/xui/it/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Editor avanzato dell&apos;acqua">
+<floater name="Water Floater" title="EDITOR AVANZATO DELL&apos;ACQUA">
<text name="KeyFramePresetsText" width="224">
Impostazioni predeterminate dell&apos;acqua:
</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 5076c777dc..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,5 +1,5 @@
<?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>
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 e19335fe07..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"/>
diff --git a/indra/newview/skins/default/xui/it/notifications.xml b/indra/newview/skins/default/xui/it/notifications.xml
index 29ddca3b17..8f8a969ace 100644
--- a/indra/newview/skins/default/xui/it/notifications.xml
+++ b/indra/newview/skins/default/xui/it/notifications.xml
@@ -1747,7 +1747,7 @@ 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 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.
@@ -1758,7 +1758,7 @@ 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 &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;.
@@ -2923,7 +2923,7 @@ Gli oggetti flessibili non possono essere fisici e devano essere fantasma fino a
<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 &#8984;-Opt-D.
+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.
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_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_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/strings.xml b/indra/newview/skins/default/xui/it/strings.xml
index 67b946e1de..bc3cc38a40 100644
--- a/indra/newview/skins/default/xui/it/strings.xml
+++ b/indra/newview/skins/default/xui/it/strings.xml
@@ -484,16 +484,16 @@
Scegli la cartella
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -600,6 +600,9 @@
<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>
@@ -618,4 +621,31 @@
<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/ja/floater_about.xml b/indra/newview/skins/default/xui/ja/floater_about.xml
index a9b3d81a3b..834d49e169 100644
--- a/indra/newview/skins/default/xui/ja/floater_about.xml
+++ b/indra/newview/skins/default/xui/ja/floater_about.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="floater_about" title="[APP_NAME]ã«ã¤ã„ã¦">
<tab_container name="about_tab">
<panel name="credits_panel">
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..f189acf101 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
+<floater name="floater_device_settings" title="ボイスãƒãƒ£ãƒƒãƒˆæ©Ÿå™¨ã®è¨­å®š" />
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 d4037487b7..2200809925 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,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="アニメーション" name="check_animation" />
<check_box label="コーリング・カード" name="check_calling_card" />
<check_box label="æœ" name="check_clothing" />
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..e535fc731f 100644
--- a/indra/newview/skins/default/xui/ja/floater_lsl_guide.xml
+++ b/indra/newview/skins/default/xui/ja/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="カーソルを追ã†" name="lock_check" />
<combo_box label="ロック" name="history_combo" />
<button label="戻る" name="back_btn" />
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_sound_preview.xml b/indra/newview/skins/default/xui/ja/floater_sound_preview.xml
index b247914389..d5109fe539 100644
--- a/indra/newview/skins/default/xui/ja/floater_sound_preview.xml
+++ b/indra/newview/skins/default/xui/ja/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">
åå‰ï¼š
</text>
diff --git a/indra/newview/skins/default/xui/ja/floater_tools.xml b/indra/newview/skins/default/xui/ja/floater_tools.xml
index 72c6fbc04b..5840773dbd 100644
--- a/indra/newview/skins/default/xui/ja/floater_tools.xml
+++ b/indra/newview/skins/default/xui/ja/floater_tools.xml
@@ -456,7 +456,7 @@
é¢ç©ï¼š[AREA]平方メートル
</text>
<button label="土地情報..." label_selected="土地情報..." name="button about land"/>
- <check_box label="オーナーを表示" name="checkbox show owners" tool_tip="所有権別ã«åŒºç”»ã‚’色分ã‘ã—ã¾ã™"/>
+ <check_box label="オーナーを表示" name="checkbox show owners" tool_tip="所有権別ã«åŒºç”»ã‚’色分ã‘ã—ã¾ã™ï¼š &#10;&#10;ç·‘ = ã‚ãªãŸã®åœŸåœ° &#10;アクア = ã‚ãªãŸã®ã‚°ãƒ«ãƒ¼ãƒ—所有地 &#10;赤 = 他人ãŒæ‰€æœ‰ã™ã‚‹åœŸåœ° &#10;黄色 = 売り出ã—中 &#10;ç´« = オークション &#10;グレー = パブリック"/>
<button label="?" label_selected="?" name="button show owners help" left_delta="114"/>
<text name="label_parcel_modify">
区画ã®ç·¨é›†
diff --git a/indra/newview/skins/default/xui/ja/notifications.xml b/indra/newview/skins/default/xui/ja/notifications.xml
index 5c22fbf474..4d067d2823 100644
--- a/indra/newview/skins/default/xui/ja/notifications.xml
+++ b/indra/newview/skins/default/xui/ja/notifications.xml
@@ -1809,7 +1809,7 @@ L$[AMOUNT]ã§ã€ã“ã®ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã‚’今ã™ã公開ã—ã¾ã™ã‹ï
</notification>
<notification label="スクリプトを無効化" name="HelpRegionDisableScripts">
スクリプトãŒåŽŸå› ã§ã‚·ãƒ ã®çŠ¶æ³ãŒæ‚ªããªã‚‹å ´åˆãŒã‚ã‚Šã¾ã™ã€‚
-統計グラフをã ã—ã¦ï¼ˆCtrl-Shift-1)ã€
+統計グラフをã ã—ã¦ï¼ˆCtrl+Shift+1)ã€
シミュレーターフィジックスFPSを見ã¦ãã ã•ã„。
45より数ãŒä½Žã‘ã‚Œã°ã€ä¸€ç•ªä¸‹ã«ä½ç½®ã—ã¦ã„るタイムパãƒãƒ«ã‚’é–‹ã„ã¦ãã ã•ã„。
スクリプト時間ãŒ25ms以上ã§ã‚ã‚Œã°ã€
@@ -1828,7 +1828,7 @@ L$[AMOUNT]ã§ã€ã“ã®ã‚¯ãƒ©ã‚·ãƒ•ã‚¡ã‚¤ãƒ‰åºƒå‘Šã‚’今ã™ã公開ã—ã¾ã™ã‹ï
<notification label="è¡çªã‚’無効化" name="HelpRegionDisableCollisions">
物ç†çš„オブジェクトãŒåŽŸå› ã§ã€
シムã®å‡¦ç†ãŒé‡ããªã‚‹ã“ã¨ãŒã‚ã‚Šã¾ã™ã€‚
-統計グラフを開ã„ã¦ï¼ˆCtrl-Shift-1)ã€
+統計グラフを開ã„ã¦ï¼ˆCtrl+Shift+1)ã€
シミュレーターフィジックスFPSを見ã¦ãã ã•ã„。
数値ãŒ45より低ã‘ã‚Œã°ã€çµ±è¨ˆãƒãƒ¼ã®ä¸‹ã«ä½ç½®ã—ã¦ã„るタイムパãƒãƒ«ã‚’é–‹ã„ã¦ãã ã•ã„。
ã‚‚ã—シムタイム(物ç†çš„作用)ãŒ20 msより長ã„å ´åˆã¯ã€
@@ -3128,8 +3128,8 @@ Mキーを押ã—ã¦å¤‰æ›´ã—ã¾ã™ã€‚
[SECOND_LIFE] をデãƒãƒƒã‚°ã™ã‚‹ãƒ‡ãƒ™ãƒ­ãƒƒãƒ‘ーã«ã¨ã£ã¦
有用ãªæ©Ÿèƒ½ãŒã‚ã‚Šã¾ã™ã€‚
ã“ã®ãƒ¡ãƒ‹ãƒ¥ãƒ¼ã‚’切り替ãˆã‚‹ã«ã¯ã€
-Windowsã§ã¯Ctrl-Alt-Dを押ã—ã¾ã™ã€‚
-Macã®å ´åˆã¯ã€&#8984;-Opt-Shift-Dを押ã—ã¦ãã ã•ã„。
+Windowsã§ã¯Ctrl+Alt+Dを押ã—ã¾ã™ã€‚
+Macã®å ´åˆã¯ã€&#8997;&#8984;Dを押ã—ã¦ãã ã•ã„。
</notification>
<notification name="FirstSculptedPrim">
スカルプトプリムを編集ã—ã¦ã„ã¾ã™ã€‚
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..2cf8456187
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/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="ä½äºº" />
+ <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>
+ <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="パートナー:"/>
+ <panel name="partner_data_panel">
+ <text name="partner_text" value="[FIRST] [LAST]"/>
+ </panel>
+ <text name="text_box3">
+ å–ã‚Šè¾¼ã¿ä¸­å¿œç­”メッセージ:
+ </text>
+ </panel>
+ </panel>
+</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..96123c9d98
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_alerts.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="ãƒãƒƒãƒ—アップ" name="popups" title="ãƒãƒƒãƒ—アップ">
+ <text name="text_box">
+ ãƒãƒƒãƒ—アップを表示ã—ãªã„:
+ </text>
+ <text name="dont_show_label">
+ 次ã®ãƒãƒƒãƒ—アップã¯è¡¨ç¤ºã—ãªã„:
+ </text>
+ <button label="ã“ã‚Œã¯è¡¨ç¤ºã™ã‚‹" label_selected="ã“ã‚Œã¯è¡¨ç¤ºã™ã‚‹" name="enable_popup"/>
+ <text name="show_label" width="300" >
+ 次ã®ãƒãƒƒãƒ—アップã¯è¡¨ç¤ºï¼š
+ </text>
+ <text name="text_box2" width="280">
+ ノートカードã€ãƒ†ã‚¯ã‚¹ãƒãƒ£ã€ãƒ©ãƒ³ãƒ‰ãƒžãƒ¼ã‚¯ã®æ供:
+ </text>
+ <check_box label="自動的ã«æ‰¿èª" name="accept_new_inventory"/>
+ <check_box label="承èªå¾Œã€è‡ªå‹•çš„ã«é–²è¦§" name="show_new_inventory"/>
+ <button width="235" label="ãƒãƒƒãƒ—アップ全ã¦ã‚’有効化..." label_selected="「次回表示ã€ãƒ€ã‚¤ã‚¢ãƒ­ã‚°ãƒªã‚»ãƒƒãƒˆ..." name="reset_dialogs_btn" tool_tip="å…¨ã¦ã®ã‚ªãƒ—ショナルãƒãƒƒãƒ—アップã¨ã€Œåˆå›žä½¿ç”¨ã€é€šçŸ¥ã‚’有効ã«ã—ã¦ãã ã•ã„。"/>
+ <button width="235" label="ã“れらã®ãƒãƒƒãƒ—アップ全ã¦ã‚’無効化..." name="skip_dialogs_btn" tool_tip="å…¨ã¦ã®ã‚ªãƒ—ショナルãƒãƒƒãƒ—アップã¨ã€Œåˆå›žä½¿ç”¨ã€é€šçŸ¥ã‚’無効ã«ã—ã¦ãã ã•ã„。"/>
+ <check_box label="æ–°ãŸã«å—ã‘å–ã£ãŸã‚ªãƒ–ジェクトをæŒã¡ç‰©ã«è‡ªå‹•çš„ã«è¡¨ç¤º" name="show_in_inventory"/>
+</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..20299542fb
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_privacy.xml
@@ -0,0 +1,32 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="ãƒãƒ£ãƒƒãƒˆè¨­å®š" name="im">
+ <text name="text_box">
+ オンライン通知:
+ </text>
+ <check_box label="フレンドã¨ã‚°ãƒ«ãƒ¼ãƒ—ã®ã¿è‡ªåˆ†ã®ã‚ªãƒ³ãƒ©ã‚¤ãƒ³ã‚’確èªå¯èƒ½ã«" name="online_visibility"/>
+ <text name="text_box2">
+ IMオプション:
+ </text>
+ <text name="log_in_to_change">
+ ログインã—ã¦å¤‰æ›´ã—ã¦ãã ã•ã„
+ </text>
+ <check_box label="IMã‚’é›»å­ãƒ¡ãƒ¼ãƒ«ï¼ˆ[EMAIL])ã¸é€ä¿¡" name="send_im_to_email"/>
+ <check_box label="ãƒãƒ£ãƒƒãƒˆã‚³ãƒ³ã‚½ãƒ¼ãƒ«ã«IMを表示ã™ã‚‹" name="include_im_in_chat_console"/>
+ <check_box label="IMã«ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を表示" name="show_timestamps_check"/>
+ <check_box label="オンライン・フレンド通知を表示" name="friends_online_notify_checkbox"/>
+ <text name="text_box4">
+ 記録オプション:
+ </text>
+ <check_box label="IMログを自分ã®ã‚³ãƒ³ãƒ”ュータã«ä¿å­˜" name="log_instant_messages"/>
+ <check_box label="IMログã«ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を表示" name="log_instant_messages_timestamp"/>
+ <check_box label="ローカルãƒãƒ£ãƒƒãƒˆã®ãƒ­ã‚°ã‚’自分ã®ã‚³ãƒ³ãƒ”ュータã«ä¿å­˜" name="log_chat"/>
+ <check_box label="最後ã®IMãƒãƒ£ãƒƒãƒˆã®æœ«å°¾ã‚’表示" name="log_show_history"/>
+ <check_box label="ローカルãƒãƒ£ãƒƒãƒˆã®ãƒ­ã‚°ã«ã‚¿ã‚¤ãƒ ã‚¹ã‚¿ãƒ³ãƒ—を表示" name="log_chat_timestamp"/>
+ <check_box label="ローカルãƒãƒ£ãƒƒãƒˆã®ãƒ­ã‚°ã«å—ä¿¡IMを表示" name="log_chat_IM"/>
+ <check_box label="タイムスタンプã«æ—¥ä»˜ã‚’加ãˆã‚‹" name="log_date_timestamp"/>
+ <button label="パス変更" label_selected="パス変更" name="log_path_button"/>
+ <text name="text_box3">
+ å–ã‚Šè¾¼ã¿ä¸­
+応答メッセージ:
+ </text>
+</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..ded6f9df38
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_setup.xml
@@ -0,0 +1,31 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes"?>
+<panel label="æ“作ã¨ã‚«ãƒ¡ãƒ©" name="Input panel">
+ <text name=" Mouselook Options:">
+ 一人称視点
+(マウスルック):
+ </text>
+ <text name=" Mouse Sensitivity:">
+ 感度:
+ </text>
+ <check_box label="上下をå転" name="invert_mouse"/>
+ <text name=" Auto Fly Options:">
+ 自動飛行オプション:
+ </text>
+ <check_box label="上下矢å°ã‚­ãƒ¼ã®é•·æŠ¼ã—ã§é£›è¡Œï¼ç€åœ°" name="automatic_fly"/>
+ <text name=" Camera Options:">
+ カメラ・オプション:
+ </text>
+ <text name="camera_fov_label">
+ カメラ視野角:
+ </text>
+ <text name="Camera Follow Distance:">
+ カメラ追従è·é›¢ï¼š
+ </text>
+ <check_box label="編集カメラã®è‡ªå‹•ç§»å‹•" name="edit_camera_movement" tool_tip="編集モードã®é–‹å§‹ã€çµ‚了時ã¯ã‚«ãƒ¡ãƒ©è‡ªå‹•ä½ç½®èª¿æ•´ã‚’使用"/>
+ <check_box label="容姿カメラã®è‡ªå‹•ç§»å‹•" name="appearance_camera_movement" tool_tip="編集モードã§ã¯ã€ã‚«ãƒ¡ãƒ©è‡ªå‹•ä½ç½®èª¿æ•´ã‚’使用"/>
+ <text name="text2">
+ ã‚¢ãƒã‚¿ãƒ¼è¡¨ç¤ºï¼š
+ </text>
+ <check_box label="ã‚¢ãƒã‚¿ãƒ¼ã‚’一人称視点(マウスルック)ã§è¡¨ç¤º" name="first_person_avatar_visible"/>
+ <button label="ジョイスティック設定" name="joystick_setup_button"/>
+</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..d8763193ae
--- /dev/null
+++ b/indra/newview/skins/default/xui/ja/panel_preferences_sound.xml
@@ -0,0 +1,77 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel label="音声ã¨ãƒ“デオ" name="Preference Media panel">
+ <slider label="マスター" name="System Volume"/>
+ <slider label="風ã®éŸ³é‡" name="Wind Volume"/>
+ <slider label="サウンド" name="SFX Volume"/>
+ <slider label="メディア" name="Media Volume"/>
+ <slider label="UI" name="UI Volume"/>
+ <slider label="ミュージック" name="Music Volume"/>
+ <slider label="ボイス" name="Voice Volume"/>
+ <text_editor name="voice_unavailable">
+ ボイスãƒãƒ£ãƒƒãƒˆã‚’利用ã§ãã¾ã›ã‚“
+ </text_editor>
+ <check_box label="ボイスãƒãƒ£ãƒƒãƒˆã‚’有効ã«ã™ã‚‹" name="enable_voice_check"/>
+ <radio_group name="ear_location">
+ <radio_item name="0" label="カメラã®ä½ç½®ã‹ã‚‰ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚’èžã。" />
+ <radio_item name="1" label="ã‚¢ãƒã‚¿ãƒ¼ã®ä½ç½®ã‹ã‚‰ãƒœã‚¤ã‚¹ãƒãƒ£ãƒƒãƒˆã‚’èžã。" />
+ </radio_group>
+ <button label="機器ã®è¨­å®š" name="device_settings_btn"/>
+ <text name="muting_text">
+ ボリューム:
+ </text>
+ <check_box label="オーディオをミュート" name="disable audio" />
+ <text name="streaming_prefs_text">
+ ストリーム環境設定:
+ </text>
+ <text name="audio_prefs_text">
+ オーディオ環境設定:
+ </text>
+ <panel label="ボリューム" name="Volume Panel" />
+ <check_box label="メディアを自動å†ç”Ÿ" name="auto_streaming_video" />
+ <check_box
+ label="ウィンドウãŒæœ€å°åŒ–ã•ã‚ŒãŸã¨ãã«ã‚ªãƒ¼ãƒ‡ã‚£ã‚ªã‚’ミュート"
+ name="mute_when_minimized" />
+ <text name="streaming_text">
+ ストリーミング:
+ </text>
+ <check_box label="音楽ãŒã‚ã‚‹å ´åˆå†ç”Ÿã™ã‚‹"
+ name="streaming_music" />
+ <check_box
+ label="ストリーミング・メディア使用å¯æ™‚ã«å†ç”Ÿ"
+ name="streaming_video" />
+ <text name="system_volume_text">
+ サウンド効果:
+ </text>
+ <text name="wind_volume_text">
+ 風ã®éŸ³é‡ï¼š
+ </text>
+ <text name="footsteps_volume_text">
+ 足音:
+ </text>
+ <text name="ui_volume_text">
+ UI音é‡ï¼š
+ </text>
+ <slider label="ドップラー効果" name="Doppler Effect" />
+ <slider label="é éš”è¦å› " name="Distance Factor" />
+ <slider label="ロールオフ係数" name="Rolloff Factor" />
+ <spinner label="L$変更基準点" name="L$ Change Threshold" />
+ <spinner label="ヘルス変化基準点" name="Health Change Threshold" />
+ <text name="doppler_effect_text">
+ オーディオ環境設定:
+ </text>
+ <text name="distance_factor_text">
+ è·é›¢ä¿‚数:
+ </text>
+ <text name="rolloff_factor_text">
+ ロールオフ:
+ </text>
+ <text name="default_upload_bitrate_text">
+ デフォルトUL速度:
+ </text>
+ <radio_group name="bitrate">
+ <radio_item name="32kbps" label="32kbps" />
+ <radio_item name="64kbps" label="64kbps" />
+ <radio_item name="96kbps" label="96kbps" />
+ <radio_item name="128kbps" label="128kbps" />
+ </radio_group>
+</panel>
diff --git a/indra/newview/skins/default/xui/ja/strings.xml b/indra/newview/skins/default/xui/ja/strings.xml
index 7b21146651..0eb26754cf 100644
--- a/indra/newview/skins/default/xui/ja/strings.xml
+++ b/indra/newview/skins/default/xui/ja/strings.xml
@@ -488,16 +488,16 @@
å‚ç…§
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -603,6 +603,9 @@
<string name="no_ability_error">
ã‚ãªãŸã«ã¯ãã®èƒ½åŠ›ãŒã‚ã‚Šã¾ã›ã‚“。
</string>
+ <string name="no_ability">
+ ã‚ãªãŸã«ã¯ãã®èƒ½åŠ›ãŒã‚ã‚Šã¾ã›ã‚“。
+ </string>
<string name="not_a_mod_error">
ã‚ãªãŸã¯ã‚»ãƒƒã‚·ãƒ§ãƒ³ãƒ»ãƒ¢ãƒ‡ãƒ¬ãƒ¼ã‚¿ã§ã¯ã‚ã‚Šã¾ã›ã‚“。
</string>
@@ -621,4 +624,31 @@
<string name="close_on_no_ability">
ã“ã®ãƒãƒ£ãƒƒãƒˆãƒ»ã‚»ãƒƒã‚·ãƒ§ãƒ³ã‚’継続ã™ã‚‹ã“ã¨ã¯ã§ãã¾ã›ã‚“
</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>
</strings>
diff --git a/indra/newview/skins/default/xui/nl/floater_about.xml b/indra/newview/skins/default/xui/nl/floater_about.xml
index 9ad947df66..0c57a22be1 100644
--- a/indra/newview/skins/default/xui/nl/floater_about.xml
+++ b/indra/newview/skins/default/xui/nl/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Over [APP_NAME]">
+<floater name="floater_about" title="OVER [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 6aa80c00db..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:">
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 df0614b3d2..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,5 +1,5 @@
<?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>
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..b6fc743abe 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>
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 1bb02cc7d0..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>
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_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 a357e874f7..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>
diff --git a/indra/newview/skins/default/xui/nl/floater_customize.xml b/indra/newview/skins/default/xui/nl/floater_customize.xml
index 99a109ab78..4de26347e1 100644
--- a/indra/newview/skins/default/xui/nl/floater_customize.xml
+++ b/indra/newview/skins/default/xui/nl/floater_customize.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater customize" title="Uiterlijk" width="551">
+<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">
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 d66c0b2205..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Environment Editor Floater" title="Omgeving editor">
+<floater name="Environment Editor Floater" title="OMGEVING EDITOR">
<text bottom="-42" name="EnvTimeText">
Tijd van de
dag
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 96c9d59f90..6a0885b57f 100644
--- a/indra/newview/skins/default/xui/nl/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/nl/floater_inspect.xml
@@ -1,5 +1,5 @@
<?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="Eigenaar" name="owner_name"/>
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 ccc39034f5..505e3cd719 100644
--- a/indra/newview/skins/default/xui/nl/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/nl/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Joystick configuratie">
+<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"/>
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_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_mute_object.xml b/indra/newview/skins/default/xui/nl/floater_mute_object.xml
index ca3b34c3a2..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="mute by name" title="Negeer object op naam">
+<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
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 10b502be1c..832c63403d 100644
--- a/indra/newview/skins/default/xui/nl/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/nl/floater_openobject.xml
@@ -1,5 +1,5 @@
<?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>
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 c1c9492286..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"/>
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 a6d10f2244..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>
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 012198d7b6..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,5 +1,5 @@
<?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" width="110">
Rapporteur:
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_sell_land.xml b/indra/newview/skins/default/xui/nl/floater_sell_land.xml
index 3981f3ccc2..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,5 @@
<?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">
diff --git a/indra/newview/skins/default/xui/nl/floater_snapshot.xml b/indra/newview/skins/default/xui/nl/floater_snapshot.xml
index c7174d42f3..251f3690da 100644
--- a/indra/newview/skins/default/xui/nl/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/nl/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?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>
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 8fe8e06c03..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" width="292">
+<floater name="telehub" title="TELEHUB" width="292">
<text name="status_text_connected">
Telehub verbonden met object [OBJECT]
</text>
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 13a68747c6..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>
diff --git a/indra/newview/skins/default/xui/nl/floater_tools.xml b/indra/newview/skins/default/xui/nl/floater_tools.xml
index 268a2cc7df..f79d3dbd6b 100644
--- a/indra/newview/skins/default/xui/nl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/nl/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Bouwen" width="288">
+<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"/>
@@ -515,7 +515,7 @@
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"/>
+ <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
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 cc252352eb..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/nl/floater_water.xml b/indra/newview/skins/default/xui/nl/floater_water.xml
index 2238008fd8..1fb1ca241b 100644
--- a/indra/newview/skins/default/xui/nl/floater_water.xml
+++ b/indra/newview/skins/default/xui/nl/floater_water.xml
@@ -1,5 +1,5 @@
<?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
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 e1eebaf92f..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"/>
diff --git a/indra/newview/skins/default/xui/nl/notifications.xml b/indra/newview/skins/default/xui/nl/notifications.xml
index 1d0caa76cd..9a83eaea61 100644
--- a/indra/newview/skins/default/xui/nl/notifications.xml
+++ b/indra/newview/skins/default/xui/nl/notifications.xml
@@ -1756,7 +1756,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.
@@ -1764,7 +1764,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.
@@ -2916,7 +2916,7 @@ Flexibele objecten mogen niet fysiek zijn en moeten fantoom zijn tot de &apos;fl
<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 &#8984;-Opt-D.
+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.
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/strings.xml b/indra/newview/skins/default/xui/nl/strings.xml
index bb073f735d..49ebcd319c 100644
--- a/indra/newview/skins/default/xui/nl/strings.xml
+++ b/indra/newview/skins/default/xui/nl/strings.xml
@@ -487,16 +487,16 @@
Kies folder
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -604,6 +604,9 @@
<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>
@@ -622,4 +625,31 @@
<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_land.xml b/indra/newview/skins/default/xui/pl/floater_about_land.xml
index 83d4b717a7..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,5 +1,5 @@
<?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 name="Name:">
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..b0b8935433 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>
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 ff371b38c0..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>
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_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 d6ffe1837a..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>
diff --git a/indra/newview/skins/default/xui/pl/floater_customize.xml b/indra/newview/skins/default/xui/pl/floater_customize.xml
index 64d9300621..0c01d15faf 100755
--- a/indra/newview/skins/default/xui/pl/floater_customize.xml
+++ b/indra/newview/skins/default/xui/pl/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Części Ciała" name="body_parts_placeholder"/>
<panel label="Kształt" name="Shape">
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 ea8db99570..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,5 +1,5 @@
<?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" />
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 3e0809b193..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Environment Editor Floater" title="Edytor Åšrodowiska">
+<floater name="Environment Editor Floater" title="EDYTOR ÅšRODOWISKA">
<text name="EnvTimeText">
Czas
</text>
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 df821f3b6d..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"/>
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 f1e6e5ea9e..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Hardware Settings Floater" title="Ustawienia Sprzętowe">
+<floater name="Hardware Settings Floater" title="USTAWIENIA SPRZĘTOWE">
<text name="Filtering:">
Filtrowanie:
</text>
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_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 c32d1eeabf..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>
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 2224c026ef..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" />
diff --git a/indra/newview/skins/default/xui/pl/floater_joystick.xml b/indra/newview/skins/default/xui/pl/floater_joystick.xml
index 2ab92dfbb7..22ac458b85 100755
--- a/indra/newview/skins/default/xui/pl/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/pl/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" width="590" title="Konfiguracja Joysticka">
+<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"/>
@@ -116,4 +116,4 @@
<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_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_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 0470f4d6dc..fbbed0f11d 100755
--- a/indra/newview/skins/default/xui/pl/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/pl/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="objectcontents" title="Zawartość Obiektu">
+<floater name="objectcontents" title="ZAWARTOŚĆ OBIEKTU">
<text name="object_name">
[DESC]:
</text>
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 0081d1d3a7..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,5 +1,5 @@
<?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" />
diff --git a/indra/newview/skins/default/xui/pl/floater_postcard.xml b/indra/newview/skins/default/xui/pl/floater_postcard.xml
index e5bdaf2ba9..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>
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_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_notecard.xml b/indra/newview/skins/default/xui/pl/floater_preview_notecard.xml
index 0b3b9063c4..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,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="Zapisz" label_selected="Zapisz" name="Save" />
<text name="desc txt">
Opis:
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 853c669ade..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">
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 ca3fde33e7..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Skrypt: Skrypt Obrotu">
+<floater name="preview lsl text" title="SKRYPT: SKRYPT OBROTU">
<text name="desc txt">
Opis:
</text>
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 50a9de1500..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,5 +1,5 @@
<?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" />
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 579dcd6745..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,5 @@
<?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">
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 99fa444a1b..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,5 +1,5 @@
<?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_box.item name="TRUE" label="PRAWDA" />
<combo_box.item name="FALSE" label="NIEPRAWDA" />
diff --git a/indra/newview/skins/default/xui/pl/floater_snapshot.xml b/indra/newview/skins/default/xui/pl/floater_snapshot.xml
index 4945cf6413..c807087170 100755
--- a/indra/newview/skins/default/xui/pl/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/pl/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?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>
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 917ab95ecc..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>
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 6d4df12e4b..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/pl/floater_tools.xml b/indra/newview/skins/default/xui/pl/floater_tools.xml
index 574ffa2542..e898c283c5 100755
--- a/indra/newview/skins/default/xui/pl/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pl/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Buduj">
+<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"/>
@@ -526,7 +526,7 @@
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ść
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_water.xml b/indra/newview/skins/default/xui/pl/floater_water.xml
index a22b5809dc..7333633c1d 100755
--- a/indra/newview/skins/default/xui/pl/floater_water.xml
+++ b/indra/newview/skins/default/xui/pl/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="Water Floater" title="Zaawansowany Edytor Wody">
+<floater name="Water Floater" title="ZAAWANSOWANY EDYTOR WODY">
<text name="KeyFramePresetsText">
Ustawienia Wody:
</text>
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 94c20c06f7..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="WindLight floater" title="Zaawansowany Edytor Nieba">
+<floater name="WindLight floater" title="ZAAWANSOWANY EDYTOR NIEBA">
<text name="KeyFramePresetsText">
Ustawienia Nieba:
</text>
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 65f1c8ae59..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"/>
diff --git a/indra/newview/skins/default/xui/pl/notifications.xml b/indra/newview/skins/default/xui/pl/notifications.xml
index fd652a5af8..3cf9be507d 100644
--- a/indra/newview/skins/default/xui/pl/notifications.xml
+++ b/indra/newview/skins/default/xui/pl/notifications.xml
@@ -1713,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.
@@ -1722,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.
@@ -2867,7 +2867,7 @@ Obiekty elastyczne nie mogą być fizyczne i muszą być typu fantom.
<notification name="FirstDebugMenus">
Zaawansowane menu zostało włączone.
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 &#8984;-Opt-D (Mac).
+To menu jest aktywowane dzięki kombinacji klawiszy Ctrl+Alt+D (Windows) lub &#8997;&#8984;D (Mac).
</notification>
<notification name="FirstSculptedPrim">
Edytujesz sculpt.
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_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_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/strings.xml b/indra/newview/skins/default/xui/pl/strings.xml
index 294353ee03..1f67944f86 100755
--- a/indra/newview/skins/default/xui/pl/strings.xml
+++ b/indra/newview/skins/default/xui/pl/strings.xml
@@ -487,16 +487,16 @@
Wybierz Katalog
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -603,6 +603,9 @@
<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>
@@ -621,4 +624,31 @@
<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 12cc879cbc..9c19b12893 100644
--- a/indra/newview/skins/default/xui/pt/floater_about.xml
+++ b/indra/newview/skins/default/xui/pt/floater_about.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="floater_about" title="Sobre o [APP_NAME]">
+<floater name="floater_about" title="SOBRE O [APP_NAME]">
<tab_container name="about_tab">
<panel name="credits_panel">
<text_editor name="credits_editor">
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 417d24608e..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,5 +1,5 @@
<?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 name="Name:">
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 4e1598c8fa..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="avatarpicker" title="Escolha o Residente" min_width="285" width="285">
+<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">
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 ebc9d0f0c8..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="build options floater" title="Opções de grade">
+<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"/>
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 3e8713d59e..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,5 +1,5 @@
<?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>
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..ceeb070c4e 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>
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 2caf057283..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,5 +1,5 @@
<?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>
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_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 76da972b5d..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>
diff --git a/indra/newview/skins/default/xui/pt/floater_customize.xml b/indra/newview/skins/default/xui/pt/floater_customize.xml
index 4bced69664..55946933e7 100644
--- a/indra/newview/skins/default/xui/pt/floater_customize.xml
+++ b/indra/newview/skins/default/xui/pt/floater_customize.xml
@@ -1,5 +1,5 @@
<?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">
<placeholder label="Partes de corpo" name="body_parts_placeholder"/>
<panel label="Forma" name="Shape">
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 f02cca9c25..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,5 +1,5 @@
<?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"/>
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 d3ed760551..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>
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 9406658f62..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"/>
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 0f9c1fd487..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>
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_inspect.xml b/indra/newview/skins/default/xui/pt/floater_inspect.xml
index f3c23f008e..97c2c6eaeb 100644
--- a/indra/newview/skins/default/xui/pt/floater_inspect.xml
+++ b/indra/newview/skins/default/xui/pt/floater_inspect.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="inspect" title="Inspecionar Objeto" min_width="450">
+<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="Proprietário" name="owner_name"/>
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 69752253b6..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>
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 83df449ae6..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" width="165">
+<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"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_joystick.xml b/indra/newview/skins/default/xui/pt/floater_joystick.xml
index ac7b7fd02a..0793a0b161 100644
--- a/indra/newview/skins/default/xui/pt/floater_joystick.xml
+++ b/indra/newview/skins/default/xui/pt/floater_joystick.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Joystick" title="Configuração do Joystick">
+<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"/>
diff --git a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
index 6657641992..2728633438 100644
--- a/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
+++ b/indra/newview/skins/default/xui/pt/floater_lagmeter.xml
@@ -1,5 +1,5 @@
<?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" />
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 4734d665ef..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"/>
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 d2654de589..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,5 +1,5 @@
<?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" left="86"/>
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 4f60ef23a6..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,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="Seguir o Cursor" name="lock_check" />
<combo_box label="Bloquear" name="history_combo" left_delta="120" width="70"/>
<button label="Anterior" name="back_btn" left_delta="75"/>
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..3437dfcdba 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,5 @@
<?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">
<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_mute_object.xml b/indra/newview/skins/default/xui/pt/floater_mute_object.xml
index 7ec0051a7d..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,5 +1,5 @@
<?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.
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 d3b72b4b18..0dc2852bac 100644
--- a/indra/newview/skins/default/xui/pt/floater_openobject.xml
+++ b/indra/newview/skins/default/xui/pt/floater_openobject.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="objectcontents" title="Conteúdo do objeto">
+<floater name="objectcontents" title="CONTEÚDO DO OBJETO">
<text name="object_name">
[DESC]:
</text>
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 62fd050ea4..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>
diff --git a/indra/newview/skins/default/xui/pt/floater_preferences.xml b/indra/newview/skins/default/xui/pt/floater_preferences.xml
index 0e9ef768b5..d2c3c79160 100644
--- a/indra/newview/skins/default/xui/pt/floater_preferences.xml
+++ b/indra/newview/skins/default/xui/pt/floater_preferences.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Preferences" title="Preferências" min_width="332" width="628">
+<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"/>
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_notecard.xml b/indra/newview/skins/default/xui/pt/floater_preview_notecard.xml
index e0a133d8ab..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,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="Salvar" label_selected="Salvar" name="Save"/>
<text name="desc txt">
Descrição:
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 51d7ef8190..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:
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 2a7680565f..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<floater name="preview lsl text" title="Script: Rotation Script">
+<floater name="preview lsl text" title="SCRIPT: ROTATION SCRIPT">
<text name="desc txt">
Descrição:
</text>
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 c904c0f816..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="script search" title="Busca de Script" width="320">
+<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"/>
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 d3581405ff..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,5 @@
<?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">
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 f7b468bb22..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,5 +1,5 @@
<?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_box.item name="TRUE" label="VERDADEIRO" />
<combo_box.item name="FALSE" label="FALSO" />
diff --git a/indra/newview/skins/default/xui/pt/floater_snapshot.xml b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
index a924706cb9..c3c4c73a89 100644
--- a/indra/newview/skins/default/xui/pt/floater_snapshot.xml
+++ b/indra/newview/skins/default/xui/pt/floater_snapshot.xml
@@ -1,5 +1,5 @@
<?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>
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 11886c7cab..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" min_height="310" height="310" width="286">
+<floater name="telehub" title="TELEHUB" min_height="310" height="310" width="286">
<text name="status_text_connected">
Telehub conectado ao objeto [OBJECT]
</text>
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 784540a48e..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,5 +1,5 @@
<?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>
diff --git a/indra/newview/skins/default/xui/pt/floater_tools.xml b/indra/newview/skins/default/xui/pt/floater_tools.xml
index 1b5cbd91b2..b9ab018606 100644
--- a/indra/newview/skins/default/xui/pt/floater_tools.xml
+++ b/indra/newview/skins/default/xui/pt/floater_tools.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="toolbox floater" title="" short_title="Construir" width="288">
+<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"/>
@@ -514,7 +514,7 @@
Ã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"/>
+ <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
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 cd94b51b16..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>
diff --git a/indra/newview/skins/default/xui/pt/floater_water.xml b/indra/newview/skins/default/xui/pt/floater_water.xml
index ceb4414058..bad9aa0943 100644
--- a/indra/newview/skins/default/xui/pt/floater_water.xml
+++ b/indra/newview/skins/default/xui/pt/floater_water.xml
@@ -1,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="Water Floater" title="Editor de Ãgua Avançado">
+<floater name="Water Floater" title="EDITOR DE ÃGUA AVANÇADO">
<text name="KeyFramePresetsText" width="154">
Pré-configurações da Ãgua:
</text>
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 0de8bd22f8..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,5 +1,5 @@
<?xml version="1.0" encoding="utf-8" standalone="yes"?>
-<floater name="WindLight floater" title="Editor de Céu Avançado">
+<floater name="WindLight floater" title="EDITOR DE CÉU AVANÇADO">
<text name="KeyFramePresetsText" width="130">
Pré-definições de Céu:
</text>
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 056d121520..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"/>
diff --git a/indra/newview/skins/default/xui/pt/notifications.xml b/indra/newview/skins/default/xui/pt/notifications.xml
index 14d2ab53e3..0ee2c5cb84 100644
--- a/indra/newview/skins/default/xui/pt/notifications.xml
+++ b/indra/newview/skins/default/xui/pt/notifications.xml
@@ -1730,10 +1730,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.
@@ -2875,7 +2875,7 @@ Objetos flexíveis não podem ser físicos e devem ser fantasmas até que a caix
<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 &#8984;-Opt-D.
+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.
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_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_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/strings.xml b/indra/newview/skins/default/xui/pt/strings.xml
index b6788567e2..2d3514e5fe 100644
--- a/indra/newview/skins/default/xui/pt/strings.xml
+++ b/indra/newview/skins/default/xui/pt/strings.xml
@@ -484,16 +484,16 @@
Escolher Diretório
</string>
<string name="accel-mac-control">
- Ctrl-
+ &#8963;
</string>
<string name="accel-mac-command">
- Cmd-
+ &#8984;
</string>
<string name="accel-mac-option">
- Opt-
+ &#8997;
</string>
<string name="accel-mac-shift">
- Shift-
+ &#8679;
</string>
<string name="accel-win-control">
Ctrl+
@@ -599,6 +599,9 @@
<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>
@@ -617,4 +620,31 @@
<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/tests/llagentaccess_test.cpp b/indra/newview/tests/llagentaccess_test.cpp
index 42872d85fb..e08193f785 100644
--- a/indra/newview/tests/llagentaccess_test.cpp
+++ b/indra/newview/tests/llagentaccess_test.cpp
@@ -29,6 +29,8 @@
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
+
+#include "linden_common.h"
#include "../test/lltut.h"
#include "../llagentaccess.h"
diff --git a/indra/newview/tests/llcapabilitylistener_test.cpp b/indra/newview/tests/llcapabilitylistener_test.cpp
index f66ae9404f..4759c7dc91 100644
--- a/indra/newview/tests/llcapabilitylistener_test.cpp
+++ b/indra/newview/tests/llcapabilitylistener_test.cpp
@@ -5,7 +5,30 @@
* @brief Test for llcapabilitylistener.cpp.
*
* $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
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
@@ -24,9 +47,9 @@
#include "../test/lltut.h"
#include "../llcapabilityprovider.h"
#include "lluuid.h"
-#include "llerrorcontrol.h"
#include "tests/networkio.h"
#include "tests/commtest.h"
+#include "tests/wrapllerrs.h"
#include "stringize.h"
#if defined(LL_WINDOWS)
@@ -104,28 +127,6 @@ namespace tut
typedef llcapears_group::object llcapears_object;
llcapears_group llsdmgr("llcapabilitylistener");
- struct CaptureError: public LLError::OverrideFatalFunction
- {
- CaptureError():
- LLError::OverrideFatalFunction(boost::bind(&CaptureError::operator(), this, _1))
- {
- LLError::setPrintLocation(false);
- }
-
- struct FatalException: public std::runtime_error
- {
- FatalException(const std::string& what): std::runtime_error(what) {}
- };
-
- void operator()(const std::string& message)
- {
- error = message;
- throw FatalException(message);
- }
-
- std::string error;
- };
-
template<> template<>
void llcapears_object::test<1>()
{
@@ -137,10 +138,10 @@ namespace tut
std::string threw;
try
{
- CaptureError capture;
+ WrapLL_ERRS capture;
regionPump.post(request);
}
- catch (const CaptureError::FatalException& e)
+ catch (const WrapLL_ERRS::FatalException& e)
{
threw = e.what();
}
@@ -184,10 +185,10 @@ namespace tut
std::string threw;
try
{
- CaptureError capture;
+ WrapLL_ERRS capture;
regionPump.post(request);
}
- catch (const CaptureError::FatalException& e)
+ catch (const WrapLL_ERRS::FatalException& e)
{
threw = e.what();
}
@@ -246,10 +247,10 @@ namespace tut
std::string threw;
try
{
- CaptureError capture;
+ WrapLL_ERRS capture;
regionPump.post(request);
}
- catch (const CaptureError::FatalException& e)
+ catch (const WrapLL_ERRS::FatalException& e)
{
threw = e.what();
}
diff --git a/indra/newview/tests/lldateutil_test.cpp b/indra/newview/tests/lldateutil_test.cpp
index 30e39a3bcf..ed753b6ff7 100644
--- a/indra/newview/tests/lldateutil_test.cpp
+++ b/indra/newview/tests/lldateutil_test.cpp
@@ -28,6 +28,9 @@
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
+
+#include "linden_common.h"
+
#include "../test/lltut.h"
#include "../lldateutil.h"
diff --git a/indra/newview/tests/lllogininstance_test.cpp b/indra/newview/tests/lllogininstance_test.cpp
new file mode 100644
index 0000000000..d31a81e128
--- /dev/null
+++ b/indra/newview/tests/lllogininstance_test.cpp
@@ -0,0 +1,423 @@
+/**
+ * @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; }
+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..445ec7aa34
--- /dev/null
+++ b/indra/newview/tests/llmediadataclient_test.cpp
@@ -0,0 +1,501 @@
+/**
+ * @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,DIST,INT,URL1,URL2) " \
+<llsd> \
+ <map> \
+ <key>uuid</key> \
+ <string>" ID "</string> \
+ <key>distance</key> \
+ <real>" DIST "</real> \
+ <key>interest</key> \
+ <real>" INT "</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 " \
+ </map> \
+</llsd>"
+
+#define _DATA(ID,DIST,INT) _DATA_URLS(ID,DIST,INT,FAKE_OBJECT_MEDIA_CAP_URL,FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL)
+
+const char *DATA = _DATA(VALID_OBJECT_ID,"1.0","1.0");
+
+#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;
+
+// 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:
+ if ( url == FAKE_OBJECT_MEDIA_CAP_URL_503 )
+ {
+ responder->error(HTTP_SERVICE_UNAVAILABLE, "fake reason");
+ }
+ else if (url == FAKE_OBJECT_MEDIA_NAVIGATE_CAP_URL_ERROR)
+ {
+ LLSD result;
+ LLSD error;
+ error["code"] = LLObjectMediaNavigateClient::ERROR_PERMISSION_DENIED_CODE;
+ result["error"] = error;
+ responder->result(result);
+ }
+ else {
+ responder->result(LLSD());
+ }
+}
+
+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)
+ { mRep["media_data"] = media_data_array; }
+
+ virtual F64 getDistanceFromAvatar() const
+ { return (LLSD::Real)mRep["distance"]; }
+
+ virtual F64 getTotalMediaInterest() const
+ { return (LLSD::Real)mRep["interest"]; }
+
+ virtual std::string getCapabilityUrl(const std::string &name) const
+ { return mRep["cap_urls"][name]; }
+
+ int getNumBounceBacks() const
+ { return mNumBounceBacks; }
+
+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;
+
+ //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,"3.0","1.0"));
+ LLMediaDataClientObject::ptr_t o2 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_2,"1.0","1.0"));
+ LLMediaDataClientObject::ptr_t o3 = new LLMediaDataClientObjectTest(
+ _DATA(VALID_OBJECT_ID_3,"2.0","1.0"));
+ {
+ 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",
+ "1.0",
+ 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",
+ "1.0",
+ 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);
+ }
+
+
+}
diff --git a/indra/newview/tests/llviewerhelputil_test.cpp b/indra/newview/tests/llviewerhelputil_test.cpp
index 40f7d532bc..988d28c301 100644
--- a/indra/newview/tests/llviewerhelputil_test.cpp
+++ b/indra/newview/tests/llviewerhelputil_test.cpp
@@ -30,6 +30,9 @@
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
+// Precompiled header
+#include "../llviewerprecompiledheaders.h"
+
#include "../test/lltut.h"
#include "../llviewerhelputil.h"
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/viewer_manifest.py b/indra/newview/viewer_manifest.py
index 545fa29675..b85d31d1ac 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -164,28 +164,103 @@ class WindowsManifest(ViewerManifest):
return ''.join(self.channel().split()) + '.exe'
+ 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):
+ WindowsManifest.copy_action = WindowsManifest.test_msvcrt_and_copy_action
+
+ def enable_no_crt_manifest_check(self):
+ WindowsManifest.copy_action = WindowsManifest.test_for_no_msvcrt_manifest_and_copy_action
+
+ def disable_manifest_check(self):
+ 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())
+ # 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())
+
+ self.enable_crt_manifest_check()
# Plugin host application
self.path(os.path.join(os.pardir,
'llplugin', 'slplugin', self.args['configuration'], "slplugin.exe"),
"slplugin.exe")
-
- # need to get the kdu dll from any of the build directories as well
+
+ # need to get the llcommon.dll from the build directory as well
+ if self.prefix(src=self.args['configuration'], dst=""):
+ 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.end_prefix()
+
+ # need to get the kdu dll from the build directory 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:
+ self.path('%s/llkdu.dll' % self.args['configuration'], dst='llkdu.dll')
+ except RuntimeError:
print "Skipping llkdu.dll"
- pass
- self.path(src="licenses-win32.txt", dst="licenses.txt")
+ self.disable_manifest_check()
+
+ # For textures
+ if self.prefix(src=self.args['configuration'], dst=""):
+ if(self.args['configuration'].lower() == 'debug'):
+ self.path("openjpegd.dll")
+ else:
+ self.path("openjpeg.dll")
+ self.end_prefix()
+
+ self.path(src="licenses-win32.txt", dst="licenses.txt")
self.path("featuretable.txt")
# For use in crash reporting (generates minidumps)
@@ -194,11 +269,7 @@ class WindowsManifest(ViewerManifest):
# For using FMOD for sound... DJS
self.path("fmod.dll")
- # For textures
- if self.prefix(src="../../libraries/i686-win32/lib/release", dst=""):
- self.path("openjpeg.dll")
- self.end_prefix()
-
+ 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")
@@ -209,7 +280,6 @@ class WindowsManifest(ViewerManifest):
self.path("media_plugin_webkit.dll")
self.end_prefix()
- # For WebKit/Qt plugin runtimes
if self.prefix(src="../../libraries/i686-win32/lib/release", dst="llplugin"):
self.path("libeay32.dll")
self.path("qtcore4.dll")
@@ -230,6 +300,8 @@ class WindowsManifest(ViewerManifest):
self.path("qtiff4.dll")
self.end_prefix()
+ self.disable_manifest_check()
+
# 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=""):
@@ -243,11 +315,8 @@ class WindowsManifest(ViewerManifest):
self.path("Microsoft.VC80.CRT.manifest")
self.end_prefix()
- # The config file name needs to match the exe's name.
- self.path(src="%s/secondlife-bin.exe.config" % self.args['configuration'], dst=self.final_exe() + ".config")
-
# Vivox runtimes
- if self.prefix(src="vivox-runtime/i686-win32", dst=""):
+ if self.prefix(src=self.args['configuration'], dst=""):
self.path("SLVoice.exe")
self.path("alut.dll")
self.path("vivoxsdk.dll")
@@ -256,22 +325,22 @@ class WindowsManifest(ViewerManifest):
self.end_prefix()
# 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 self.prefix(src=self.args['configuration'], dst=""):
+ try:
+ if self.args['configuration'] == 'Debug':
+ self.path('libtcmalloc_minimal-debug.dll')
+ else:
+ self.path('libtcmalloc_minimal.dll')
+ except:
+ print "Skipping libtcmalloc_minimal.dll"
+ self.end_prefix()
def nsi_file_commands(self, install=True):
def wpath(path):
@@ -392,7 +461,11 @@ 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
@@ -468,16 +541,31 @@ class DarwinManifest(ViewerManifest):
self.path("vivox-runtime/universal-darwin/libvivoxsdk.dylib", "libvivoxsdk.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")
@@ -485,6 +573,24 @@ 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")
@@ -509,7 +615,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')})
@@ -538,12 +644,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 500 -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()
@@ -577,24 +683,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)
@@ -667,15 +774,17 @@ 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
self.path("secondlife-stripped","bin/do-not-directly-run-secondlife-bin")
self.path("../linux_crash_logger/linux-crash-logger-stripped","bin/linux-crash-logger.bin")
@@ -696,20 +805,30 @@ class Linux_i686Manifest(LinuxManifest):
#self.path("secondlife-i686.supp")
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")
+ 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
diff --git a/indra/test/CMakeLists.txt b/indra/test/CMakeLists.txt
index a5df23860c..cc9fa598f2 100644
--- a/indra/test/CMakeLists.txt
+++ b/indra/test/CMakeLists.txt
@@ -13,7 +13,8 @@ include(LLXML)
include(LScript)
include(Linking)
include(Tut)
-include(Boost)
+
+include(GoogleMock)
include_directories(
${LLCOMMON_INCLUDE_DIRS}
@@ -24,28 +25,21 @@ include_directories(
${LLVFS_INCLUDE_DIRS}
${LLXML_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}
+ ${GOOGLEMOCK_INCLUDE_DIRS}
)
set(test_SOURCE_FILES
io.cpp
# llapp_tut.cpp # Temporarily removed until thread issues can be solved
- llbase64_tut.cpp
llblowfish_tut.cpp
llbuffer_tut.cpp
- lldependencies_tut.cpp
lldoubledispatch_tut.cpp
- llerror_tut.cpp
llevents_tut.cpp
- llhost_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
llpermissions_tut.cpp
llpipeutil.cpp
llsaleinfo_tut.cpp
@@ -58,22 +52,17 @@ set(test_SOURCE_FILES
llstreamtools_tut.cpp
lltemplatemessagebuilder_tut.cpp
lltimestampcache_tut.cpp
- lltiming_tut.cpp
lltranscode_tut.cpp
- lltreeiterators_tut.cpp
lltut.cpp
- lluri_tut.cpp
lluuidhashmap_tut.cpp
- llxfer_tut.cpp
message_tut.cpp
- reflection_tut.cpp
- stringize_tut.cpp
test.cpp
)
set(test_HEADER_FILES
CMakeLists.txt
+ debug.h
llpipeutil.h
llsdtraits.h
lltut.h
@@ -107,6 +96,8 @@ target_link_libraries(test
${LLXML_LIBRARIES}
${LSCRIPT_LIBRARIES}
${LLCOMMON_LIBRARIES}
+ ${EXPAT_LIBRARIES}
+ ${GOOGLEMOCK_LIBRARIES}
${APRICONV_LIBRARIES}
${PTHREAD_LIBRARY}
${WINDOWS_LIBRARIES}
@@ -126,16 +117,21 @@ 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})
+ELSE(WINDOWS)
+ set(LD_LIBRARY_PATH ${ARCH_PREBUILT_DIRS}:${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}:/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/llevents_tut.cpp b/indra/test/llevents_tut.cpp
index e401f89b22..31130c3c79 100644
--- a/indra/test/llevents_tut.cpp
+++ b/indra/test/llevents_tut.cpp
@@ -32,96 +32,10 @@
// other Linden headers
#include "lltut.h"
#include "stringize.h"
+#include "tests/listener.h"
using boost::assign::list_of;
-/*****************************************************************************
-* test listener class
-*****************************************************************************/
-class Listener;
-std::ostream& operator<<(std::ostream&, const Listener&);
-
-class Listener
-{
-public:
- Listener(const std::string& name):
- mName(name)
- {
-// std::cout << *this << ": ctor\n";
- }
- Listener(const Listener& that):
- mName(that.mName),
- mLastEvent(that.mLastEvent)
- {
-// std::cout << *this << ": copy\n";
- }
- virtual ~Listener()
- {
-// std::cout << *this << ": dtor\n";
- }
- std::string getName() const { return mName; }
- bool call(const LLSD& event)
- {
-// std::cout << *this << "::call(" << event << ")\n";
- mLastEvent = event;
- return false;
- }
- bool callstop(const LLSD& event)
- {
-// std::cout << *this << "::callstop(" << event << ")\n";
- mLastEvent = event;
- return true;
- }
- LLSD getLastEvent() const
- {
-// std::cout << *this << "::getLastEvent() -> " << mLastEvent << "\n";
- return mLastEvent;
- }
- 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;
-}
-
-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;
-}
-
template<typename T>
T make(const T& value) { return value; }
@@ -174,14 +88,7 @@ namespace tut
// 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);
- // 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.
- LLBoundListener connection = per_frame.listen(listener0.getName(),
- boost::bind(&Listener::call,
- boost::ref(listener0),
- _1));
+ LLBoundListener connection = listener0.listenTo(per_frame);
ensure("connected", connection.connected());
ensure("not blocked", ! connection.blocked());
per_frame.post(1);
@@ -207,6 +114,10 @@ namespace tut
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));
}
@@ -221,8 +132,7 @@ namespace tut
}
ensure("threw DupListenerName", threw);
// do it right this time
- per_frame.listen(listener1.getName(),
- boost::bind(&Listener::call, boost::ref(listener1), _1));
+ listener1.listenTo(per_frame);
per_frame.post(5);
check_listener("got", listener0, 5);
check_listener("got", listener1, 5);
@@ -252,16 +162,10 @@ namespace tut
LLEventPump& per_frame(pumps.obtain("per-frame"));
listener0.reset(0);
listener1.reset(0);
- LLBoundListener bound0 = per_frame.listen(listener0.getName(),
- boost::bind(&Listener::callstop,
- boost::ref(listener0),
- _1));
- LLBoundListener bound1 = per_frame.listen(listener1.getName(),
- boost::bind(&Listener::call,
- boost::ref(listener1),
- _1),
- // after listener0
- make<LLEventPump::NameList>(list_of(listener0.getName())));
+ 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());
@@ -301,7 +205,7 @@ namespace tut
// LLEventQueue.
LLEventPump& mainloop(pumps.obtain("mainloop"));
ensure("LLEventQueue leaf class", dynamic_cast<LLEventQueue*>(&login));
- login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+ listener0.listenTo(login);
listener0.reset(0);
login.post(1);
check_listener("waiting for queued event", listener0, 0);
@@ -354,11 +258,10 @@ namespace tut
{
set_test_name("stopListening()");
LLEventPump& login(pumps.obtain("login"));
- login.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+ listener0.listenTo(login);
login.stopListening(listener0.getName());
// should not throw because stopListening() should have removed name
- login.listen(listener0.getName(),
- boost::bind(&Listener::callstop, boost::ref(listener0), _1));
+ listener0.listenTo(login, &Listener::callstop);
LLBoundListener wrong = login.getListener("bogus");
ensure("bogus connection disconnected", ! wrong.connected());
ensure("bogus connection blocked", wrong.blocked());
@@ -378,10 +281,8 @@ namespace tut
boost::bind(&LLEventPump::post, boost::ref(filter0), _1));
upstream.listen(filter1.getName(),
boost::bind(&LLEventPump::post, boost::ref(filter1), _1));
- filter0.listen(listener0.getName(),
- boost::bind(&Listener::call, boost::ref(listener0), _1));
- filter1.listen(listener1.getName(),
- boost::bind(&Listener::call, boost::ref(listener1), _1));
+ listener0.listenTo(filter0);
+ listener1.listenTo(filter1);
listener0.reset(0);
listener1.reset(0);
upstream.post(1);
@@ -536,7 +437,7 @@ namespace tut
// Passing a string LLEventPump name to LLListenerOrPumpName
listener0.reset(0);
LLEventStream random("random");
- random.listen(listener0.getName(), boost::bind(&Listener::call, boost::ref(listener0), _1));
+ listener0.listenTo(random);
eventSource("random");
check_listener("got by pump name", listener0, 17);
bool threw = false;
diff --git a/indra/test/llsdmessagebuilder_tut.cpp b/indra/test/llsdmessagebuilder_tut.cpp
index 34f3530308..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"
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..d125bb0005 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().insert("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/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 94766a0ba2..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;
@@ -147,7 +152,7 @@ private:
stream << "\tPassed Tests:\t" << mPassedTests;
if (mPassedTests == mTotalTests)
{
- stream << "\t\\o/ yay!!";
+ stream << "\tYAY!! \\o/";
}
stream << std::endl;
@@ -235,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);
diff --git a/indra/test_apps/llplugintest/CMakeLists.txt b/indra/test_apps/llplugintest/CMakeLists.txt
index 789ead04fe..53b981cccd 100644
--- a/indra/test_apps/llplugintest/CMakeLists.txt
+++ b/indra/test_apps/llplugintest/CMakeLists.txt
@@ -28,7 +28,7 @@ include_directories(
if (DARWIN)
include(CMakeFindFrameworks)
- find_library(CARBON_LIBRARY Carbon)
+ find_library(COREFOUNDATION_LIBRARY CoreFoundation)
endif (DARWIN)
### demo_plugin
@@ -136,7 +136,7 @@ endif (DARWIN)
# ${media_simple_test_SOURCE_FILES}
#)
#
-#add_dependencies(media_simple_test copy_win_libs)
+#add_dependencies(media_simple_test stage_third_party_libs)
#
#set_target_properties(media_simple_test
# PROPERTIES
@@ -177,7 +177,7 @@ endif (DARWIN)
#)
#
#add_dependencies(media_plugin_test
-# copy_win_libs
+# stage_third_party_libs
# SLPlugin
# demo_media_plugin
# ${LLPLUGIN_LIBRARIES}
@@ -261,6 +261,7 @@ set(llmediaplugintest_SOURCE_FILES
add_executable(llmediaplugintest
WIN32
+ MACOSX_BUNDLE
${llmediaplugintest_SOURCE_FILES}
)
@@ -280,11 +281,19 @@ target_link_libraries(llmediaplugintest
${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
- copy_win_libs
+ stage_third_party_libs
SLPlugin
media_plugin_quicktime
media_plugin_webkit
+ media_plugin_example
${LLPLUGIN_LIBRARIES}
${LLMESSAGE_LIBRARIES}
${LLCOMMON_LIBRARIES}
@@ -300,43 +309,210 @@ 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."
+ )
+
+ # copy the llcommon dylib and its dependencies to Contents/Resources.
+ 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}
+ )
+ # FIXME: these paths should come from somewhere reliable. The canonical list seems to be in indra/newview/viewer_manifest.py
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.3.7.dylib ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libapr-1.0.3.7.dylib
+ )
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.3.8.dylib ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libaprutil-1.0.3.8.dylib
+ )
+ add_custom_command(TARGET llmediaplugintest POST_BUILD
+ COMMAND ${CMAKE_COMMAND} -E copy ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.0.5.0.dylib ${PLUGINS_DESTINATION_DIR}
+ DEPENDS ${ARCH_PREBUILT_DIRS_RELEASE}/libexpat.0.5.0.dylib
+ )
+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} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ COMMAND ${CMAKE_COMMAND} -E copy ${BUILT_SLPLUGIN} ${PLUGINS_DESTINATION_DIR}
DEPENDS ${BUILT_SLPLUGIN}
)
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} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ 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} ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ 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 build configuration directory, which is what the mac wants...
+ # 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 ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ 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 ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}/
+ 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})
+
+ # 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
+ 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})
+
+ copy_if_different(
+ "${SHARED_LIB_STAGING_DIR}/${CMAKE_CFG_INTDIR}"
+ "${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_CFG_INTDIR}"
+ out_targets
+ llcommon.dll libapr-1.dll libaprutil-1.dll libapriconv-1.dll
+ )
+ set(plugin_test_targets ${plugin_test_targets} ${out_targets})
+
+ add_custom_target(copy_plugintest_libs ALL
+ DEPENDS
+ ${plugin_test_targets}
+ llcommon
+ )
+
+ add_dependencies(llmediaplugintest copy_plugintest_libs)
+
+endif(WINDOWS)
diff --git a/indra/test_apps/llplugintest/bookmarks.txt b/indra/test_apps/llplugintest/bookmarks.txt
index 796cc5d1b2..b8b83df386 100644
--- a/indra/test_apps/llplugintest/bookmarks.txt
+++ b/indra/test_apps/llplugintest/bookmarks.txt
@@ -8,7 +8,15 @@
(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) Neat Javascript 3D,http://gyu.que.jp/jscloth/
+(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
@@ -26,3 +34,4 @@
(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
index 7869763302..d987915bb8 100644
--- a/indra/test_apps/llplugintest/llmediaplugintest.cpp
+++ b/indra/test_apps/llplugintest/llmediaplugintest.cpp
@@ -44,6 +44,7 @@
#if __APPLE__
#include <GLUT/glut.h>
+ #include <CoreFoundation/CoreFoundation.h>
#else
#define FREEGLUT_STATIC
#include "GL/freeglut.h"
@@ -274,8 +275,6 @@ void LLMediaPluginTest::bindTexture(GLuint texture, GLint row_length, GLint alig
{
glEnable( GL_TEXTURE_2D );
-// std::cerr << "binding texture " << texture << std::endl;
-
glBindTexture( GL_TEXTURE_2D, texture );
glPixelStorei( GL_UNPACK_ROW_LENGTH, row_length );
glPixelStorei( GL_UNPACK_ALIGNMENT, alignment );
@@ -407,7 +406,7 @@ void LLMediaPluginTest::draw( int draw_type )
// 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 )
+ //if ( mMediaPanels[ panel ]->mReadyToRender )
{
glMatrixMode( GL_TEXTURE );
glPushMatrix();
@@ -618,10 +617,10 @@ void LLMediaPluginTest::idle()
if ( mSelectedPanel )
{
// set volume based on slider if we have time media
-// if ( mGluiMediaTimeControlWindowFlag )
-// {
-// mSelectedPanel->mMediaSource->setVolume( (float)mMediaTimeControlVolume / 100.0f );
-// };
+ //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+
@@ -1187,7 +1186,7 @@ void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
windowPosToTexturePos( x, y, media_x, media_y, id );
if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, media_x, media_y, 0 );
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_DOWN, 0, media_x, media_y, 0 );
}
else
if ( state == GLUT_UP )
@@ -1203,7 +1202,7 @@ void LLMediaPluginTest::mouseButton( int button, int state, int x, int y )
selectPanelById( id );
if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, media_x, media_y, 0 );
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_UP, 0, media_x, media_y, 0 );
};
};
};
@@ -1217,7 +1216,7 @@ void LLMediaPluginTest::mousePassive( int x, int y )
windowPosToTexturePos( x, y, media_x, media_y, id );
if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, media_x, media_y, 0 );
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
}
////////////////////////////////////////////////////////////////////////////////
@@ -1228,7 +1227,7 @@ void LLMediaPluginTest::mouseMove( int x, int y )
windowPosToTexturePos( x, y, media_x, media_y, id );
if ( mSelectedPanel )
- mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, media_x, media_y, 0 );
+ mSelectedPanel->mMediaSource->mouseEvent( LLPluginClassMedia::MOUSE_EVENT_MOVE, 0, media_x, media_y, 0 );
}
////////////////////////////////////////////////////////////////////////////////
@@ -1460,6 +1459,9 @@ std::string LLMediaPluginTest::mimeTypeFromUrl( std::string& url )
else
if ( url.find( ".txt" ) != 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;
}
@@ -1484,6 +1486,9 @@ std::string LLMediaPluginTest::pluginNameFromMimeType( std::string& mime_type )
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" );
@@ -1796,7 +1801,7 @@ void LLMediaPluginTest::getRandomMediaSize( int& width, int& height, std::string
// adjust this random size if it's a browser so we get
// a more useful size for testing..
- if ( mime_type == "text/html" )
+ if ( mime_type == "text/html" || mime_type == "example/example" )
{
width = ( ( rand() % 100 ) + 100 ) * 4;
height = ( width * ( ( rand() % 400 ) + 1000 ) ) / 1000;
@@ -2007,6 +2012,11 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
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;
@@ -2033,6 +2043,10 @@ void LLMediaPluginTest::handleMediaEvent(LLPluginClassMedia* self, EMediaEvent e
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;
}
}
@@ -2107,6 +2121,25 @@ void glutMouseButton( int button, int state, int x, int 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 );
diff --git a/indra/tools/vstool/README.txt b/indra/tools/vstool/README.txt
index e419180031..6f64aa41df 100644
--- a/indra/tools/vstool/README.txt
+++ b/indra/tools/vstool/README.txt
@@ -1,9 +1,9 @@
-VSTool is a command line utility to manipulate VisualStudio settings.
-
-The windows cmake project configuration uses VSTool.exe
-
-A handy upgrade:
- figure out how to make cmake build this csharp app
- - or write the app using script (jscript?!?) so it doesn't need to be built.
-
-
+VSTool is a command line utility to manipulate VisualStudio settings.
+
+The windows cmake project configuration uses VSTool.exe
+
+A handy upgrade:
+ figure out how to make cmake build this csharp app
+ - or write the app using script (jscript?!?) so it doesn't need to be built.
+
+
diff --git a/indra/tools/vstool/VSTool.csproj b/indra/tools/vstool/VSTool.csproj
index 24f1031f81..5d8764b6bf 100644
--- a/indra/tools/vstool/VSTool.csproj
+++ b/indra/tools/vstool/VSTool.csproj
@@ -1,95 +1,95 @@
-<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
- <PropertyGroup>
- <ProjectType>Local</ProjectType>
- <ProductVersion>8.0.50727</ProductVersion>
- <SchemaVersion>2.0</SchemaVersion>
- <ProjectGuid>{96943E2D-1373-4617-A117-D0F997A94919}</ProjectGuid>
- <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
- <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
- <ApplicationIcon>
- </ApplicationIcon>
- <AssemblyKeyContainerName>
- </AssemblyKeyContainerName>
- <AssemblyName>VSTool</AssemblyName>
- <AssemblyOriginatorKeyFile>
- </AssemblyOriginatorKeyFile>
- <DefaultClientScript>JScript</DefaultClientScript>
- <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
- <DefaultTargetSchema>IE50</DefaultTargetSchema>
- <DelaySign>false</DelaySign>
- <OutputType>Exe</OutputType>
- <RootNamespace>VSTool</RootNamespace>
- <RunPostBuildEvent>Always</RunPostBuildEvent>
- <StartupObject>VSTool.VSToolMain</StartupObject>
- <FileUpgradeFlags>
- </FileUpgradeFlags>
- <UpgradeBackupLocation>
- </UpgradeBackupLocation>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
- <OutputPath>.\</OutputPath>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <BaseAddress>285212672</BaseAddress>
- <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
- <ConfigurationOverrideFile>
- </ConfigurationOverrideFile>
- <DefineConstants>DEBUG;TRACE</DefineConstants>
- <DocumentationFile>
- </DocumentationFile>
- <DebugSymbols>true</DebugSymbols>
- <FileAlignment>4096</FileAlignment>
- <NoStdLib>false</NoStdLib>
- <NoWarn>
- </NoWarn>
- <Optimize>false</Optimize>
- <RegisterForComInterop>false</RegisterForComInterop>
- <RemoveIntegerChecks>false</RemoveIntegerChecks>
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
- <WarningLevel>4</WarningLevel>
- <DebugType>full</DebugType>
- <ErrorReport>prompt</ErrorReport>
- </PropertyGroup>
- <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
- <OutputPath>.\</OutputPath>
- <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
- <BaseAddress>285212672</BaseAddress>
- <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
- <ConfigurationOverrideFile>
- </ConfigurationOverrideFile>
- <DefineConstants>TRACE</DefineConstants>
- <DocumentationFile>
- </DocumentationFile>
- <DebugSymbols>false</DebugSymbols>
- <FileAlignment>4096</FileAlignment>
- <NoStdLib>false</NoStdLib>
- <NoWarn>
- </NoWarn>
- <Optimize>true</Optimize>
- <RegisterForComInterop>false</RegisterForComInterop>
- <RemoveIntegerChecks>false</RemoveIntegerChecks>
- <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
- <WarningLevel>4</WarningLevel>
- <DebugType>none</DebugType>
- <ErrorReport>prompt</ErrorReport>
- </PropertyGroup>
- <ItemGroup>
- <Reference Include="System">
- <Name>System</Name>
- </Reference>
- <Reference Include="System.Data">
- <Name>System.Data</Name>
- </Reference>
- </ItemGroup>
- <ItemGroup>
- <Compile Include="main.cs">
- <SubType>Code</SubType>
- </Compile>
- </ItemGroup>
- <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
- <PropertyGroup>
- <PreBuildEvent>
- </PreBuildEvent>
- <PostBuildEvent>
- </PostBuildEvent>
- </PropertyGroup>
+<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+ <PropertyGroup>
+ <ProjectType>Local</ProjectType>
+ <ProductVersion>8.0.50727</ProductVersion>
+ <SchemaVersion>2.0</SchemaVersion>
+ <ProjectGuid>{96943E2D-1373-4617-A117-D0F997A94919}</ProjectGuid>
+ <Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
+ <Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
+ <ApplicationIcon>
+ </ApplicationIcon>
+ <AssemblyKeyContainerName>
+ </AssemblyKeyContainerName>
+ <AssemblyName>VSTool</AssemblyName>
+ <AssemblyOriginatorKeyFile>
+ </AssemblyOriginatorKeyFile>
+ <DefaultClientScript>JScript</DefaultClientScript>
+ <DefaultHTMLPageLayout>Grid</DefaultHTMLPageLayout>
+ <DefaultTargetSchema>IE50</DefaultTargetSchema>
+ <DelaySign>false</DelaySign>
+ <OutputType>Exe</OutputType>
+ <RootNamespace>VSTool</RootNamespace>
+ <RunPostBuildEvent>Always</RunPostBuildEvent>
+ <StartupObject>VSTool.VSToolMain</StartupObject>
+ <FileUpgradeFlags>
+ </FileUpgradeFlags>
+ <UpgradeBackupLocation>
+ </UpgradeBackupLocation>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
+ <OutputPath>.\</OutputPath>
+ <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+ <BaseAddress>285212672</BaseAddress>
+ <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+ <ConfigurationOverrideFile>
+ </ConfigurationOverrideFile>
+ <DefineConstants>DEBUG;TRACE</DefineConstants>
+ <DocumentationFile>
+ </DocumentationFile>
+ <DebugSymbols>true</DebugSymbols>
+ <FileAlignment>4096</FileAlignment>
+ <NoStdLib>false</NoStdLib>
+ <NoWarn>
+ </NoWarn>
+ <Optimize>false</Optimize>
+ <RegisterForComInterop>false</RegisterForComInterop>
+ <RemoveIntegerChecks>false</RemoveIntegerChecks>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <WarningLevel>4</WarningLevel>
+ <DebugType>full</DebugType>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
+ <OutputPath>.\</OutputPath>
+ <AllowUnsafeBlocks>false</AllowUnsafeBlocks>
+ <BaseAddress>285212672</BaseAddress>
+ <CheckForOverflowUnderflow>false</CheckForOverflowUnderflow>
+ <ConfigurationOverrideFile>
+ </ConfigurationOverrideFile>
+ <DefineConstants>TRACE</DefineConstants>
+ <DocumentationFile>
+ </DocumentationFile>
+ <DebugSymbols>false</DebugSymbols>
+ <FileAlignment>4096</FileAlignment>
+ <NoStdLib>false</NoStdLib>
+ <NoWarn>
+ </NoWarn>
+ <Optimize>true</Optimize>
+ <RegisterForComInterop>false</RegisterForComInterop>
+ <RemoveIntegerChecks>false</RemoveIntegerChecks>
+ <TreatWarningsAsErrors>false</TreatWarningsAsErrors>
+ <WarningLevel>4</WarningLevel>
+ <DebugType>none</DebugType>
+ <ErrorReport>prompt</ErrorReport>
+ </PropertyGroup>
+ <ItemGroup>
+ <Reference Include="System">
+ <Name>System</Name>
+ </Reference>
+ <Reference Include="System.Data">
+ <Name>System.Data</Name>
+ </Reference>
+ </ItemGroup>
+ <ItemGroup>
+ <Compile Include="main.cs">
+ <SubType>Code</SubType>
+ </Compile>
+ </ItemGroup>
+ <Import Project="$(MSBuildBinPath)\Microsoft.CSharp.targets" />
+ <PropertyGroup>
+ <PreBuildEvent>
+ </PreBuildEvent>
+ <PostBuildEvent>
+ </PostBuildEvent>
+ </PropertyGroup>
</Project> \ No newline at end of file
diff --git a/indra/tools/vstool/VSTool.sln b/indra/tools/vstool/VSTool.sln
index 8859671802..543a0a2efc 100644
--- a/indra/tools/vstool/VSTool.sln
+++ b/indra/tools/vstool/VSTool.sln
@@ -1,19 +1,19 @@
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Any CPU = Debug|Any CPU
- Release|Any CPU = Release|Any CPU
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+Microsoft Visual Studio Solution File, Format Version 9.00
+# Visual Studio 2005
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "VSTool", "VSTool.csproj", "{96943E2D-1373-4617-A117-D0F997A94919}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Any CPU = Debug|Any CPU
+ Release|Any CPU = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {96943E2D-1373-4617-A117-D0F997A94919}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {96943E2D-1373-4617-A117-D0F997A94919}.Release|Any CPU.Build.0 = Release|Any CPU
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/indra/tools/vstool/main.cs b/indra/tools/vstool/main.cs
index cc268d59d9..5c41c916e2 100644
--- a/indra/tools/vstool/main.cs
+++ b/indra/tools/vstool/main.cs
@@ -1,711 +1,711 @@
-// Code about getting running instances visual studio
-// was borrowed from
-// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
-
-
-using System;
-using System.Collections;
-using System.Collections.Generic;
-using System.Reflection;
-using System.Runtime.InteropServices;
-using System.Runtime.InteropServices.ComTypes;
-using Microsoft.CSharp;
-
-namespace VSTool
-{
- // The MessageFilter class comes from:
- // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx
- // It allows vstool to get timing error messages from
- // visualstudio and handle them.
- public class MessageFilter : IOleMessageFilter
- {
- //
- // Class containing the IOleMessageFilter
- // thread error-handling functions.
-
- // Start the filter.
- public static void Register()
- {
- IOleMessageFilter newFilter = new MessageFilter();
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(newFilter, out oldFilter);
- }
-
- // Done with the filter, close it.
- public static void Revoke()
- {
- IOleMessageFilter oldFilter = null;
- CoRegisterMessageFilter(null, out oldFilter);
- }
-
- //
- // IOleMessageFilter functions.
- // Handle incoming thread requests.
- int IOleMessageFilter.HandleInComingCall(int dwCallType,
- System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
- lpInterfaceInfo)
- {
- //Return the flag SERVERCALL_ISHANDLED.
- return 0;
- }
-
- // Thread call was rejected, so try again.
- int IOleMessageFilter.RetryRejectedCall(System.IntPtr
- hTaskCallee, int dwTickCount, int dwRejectType)
- {
- if (dwRejectType == 2)
- // flag = SERVERCALL_RETRYLATER.
- {
- // Retry the thread call immediately if return >=0 &
- // <100.
- return 99;
- }
- // Too busy; cancel call.
- return -1;
- }
-
- int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
- int dwTickCount, int dwPendingType)
- {
- //Return the flag PENDINGMSG_WAITDEFPROCESS.
- return 2;
- }
-
- // Implement the IOleMessageFilter interface.
- [DllImport("Ole32.dll")]
- private static extern int
- CoRegisterMessageFilter(IOleMessageFilter newFilter, out
- IOleMessageFilter oldFilter);
- }
-
- [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
- InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
- interface IOleMessageFilter
- {
- [PreserveSig]
- int HandleInComingCall(
- int dwCallType,
- IntPtr hTaskCaller,
- int dwTickCount,
- IntPtr lpInterfaceInfo);
-
- [PreserveSig]
- int RetryRejectedCall(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwRejectType);
-
- [PreserveSig]
- int MessagePending(
- IntPtr hTaskCallee,
- int dwTickCount,
- int dwPendingType);
- }
-
- class ViaCOM
- {
- public static object GetProperty(object from_obj, string prop_name)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.GetProperty, null,
- from_obj,
- null);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error getting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object SetProperty(object from_obj, string prop_name, object new_value)
- {
- try
- {
- object[] args = { new_value };
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- prop_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.SetProperty,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error setting property: \"{0}\"", prop_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
-
- public static object CallMethod(object from_obj, string method_name, params object[] args)
- {
- try
- {
- Type objType = from_obj.GetType();
- return objType.InvokeMember(
- method_name,
- BindingFlags.DeclaredOnly |
- BindingFlags.Public |
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.InvokeMethod,
- null,
- from_obj,
- args);
- }
- catch (Exception e)
- {
- Console.WriteLine("Error calling method \"{0}\"", method_name);
- Console.WriteLine(e.Message);
- throw e;
- }
- }
- };
-
- /// <summary>
- /// The main entry point class for VSTool.
- /// </summary>
- class VSToolMain
- {
- #region Interop imports
- [DllImport("ole32.dll")]
- public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
-
- [DllImport("ole32.dll")]
- public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
- #endregion
-
- static System.Boolean ignore_case = true;
-
- static string solution_name = null;
- static bool use_new_vs = false;
- static Hashtable projectDict = new Hashtable();
- static string startup_project = null;
- static string config = null;
-
- static object dte = null;
- static object solution = null;
-
- /// <summary>
- /// The main entry point for the application.
- /// </summary>
- [STAThread]
- static int Main(string[] args)
- {
- int retVal = 0;
- bool need_save = false;
-
- try
- {
- parse_command_line(args);
-
- Console.WriteLine("Editing solution: {0}", solution_name);
-
- bool found_open_solution = GetDTEAndSolution();
-
- if (dte == null || solution == null)
- {
- retVal = 1;
- }
- else
- {
- MessageFilter.Register();
-
- // Walk through all of the projects in the solution
- // and list the type of each project.
- foreach (DictionaryEntry p in projectDict)
- {
- string project_name = (string)p.Key;
- string working_dir = (string)p.Value;
- if (SetProjectWorkingDir(solution, project_name, working_dir))
- {
- need_save = true;
- }
- }
-
- if (config != null)
- {
- need_save = SetActiveConfig(config);
- }
-
- if (startup_project != null)
- {
- need_save = SetStartupProject(startup_project);
- }
-
- if (need_save)
- {
- if (found_open_solution == false)
- {
- ViaCOM.CallMethod(solution, "Close", null);
- }
- }
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- retVal = 1;
- }
- finally
- {
- if (solution != null)
- {
- Marshal.ReleaseComObject(solution);
- solution = null;
- }
-
- if (dte != null)
- {
- Marshal.ReleaseComObject(dte);
- dte = null;
- }
-
- MessageFilter.Revoke();
- }
- return retVal;
- }
-
- public static bool parse_command_line(string[] args)
- {
- string options_desc =
- "--solution <solution_name> : MSVC solution name. (required)\n" +
- "--use_new_vs : Ignore running versions of visual studio.\n" +
- "--workingdir <project> <dir> : Set working dir of a VC project.\n" +
- "--config <config> : Set the active config for the solution.\n" +
- "--startup <project> : Set the startup project for the solution.\n";
-
- try
- {
- // Command line param parsing loop.
- int i = 0;
- for (; i < args.Length; ++i)
- {
- if ("--solution" == args[i])
- {
- if (solution_name != null)
- {
- throw new ApplicationException("Found second --solution option");
- }
- solution_name = args[++i];
- }
- else if ("--use_new_vs" == args[i])
- {
- use_new_vs = true;
- }
-
- else if ("--workingdir" == args[i])
- {
- string project_name = args[++i];
- string working_dir = args[++i];
- projectDict.Add(project_name, working_dir);
- }
- else if ("--config" == args[i])
- {
- if (config != null)
- {
- throw new ApplicationException("Found second --config option");
- }
- config = args[++i];
- }
- else if ("--startup" == args[i])
- {
- if (startup_project != null)
- {
- throw new ApplicationException("Found second --startup option");
- }
- startup_project = args[++i];
- }
- else
- {
- throw new ApplicationException("Found unrecognized token on command line: " + args[i]);
- }
- }
-
- if (solution_name == null)
- {
- throw new ApplicationException("The --solution option is required.");
- }
- }
- catch(ApplicationException e)
- {
-
- Console.WriteLine("Oops! " + e.Message);
- Console.Write("Command line:");
- foreach (string arg in args)
- {
- Console.Write(" " + arg);
- }
- Console.Write("\n\n");
- Console.WriteLine("VSTool command line usage");
- Console.Write(options_desc);
- throw e;
- }
- return true;
- }
-
- public static bool GetDTEAndSolution()
- {
- bool found_open_solution = true;
-
- Console.WriteLine("Looking for existing VisualStudio instance...");
-
- // Get an instance of the currently running Visual Studio .NET IDE.
- // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");
- string full_solution_name = System.IO.Path.GetFullPath(solution_name);
- if (false == use_new_vs)
- {
- dte = GetIDEInstance(full_solution_name);
- }
-
- if (dte == null)
- {
- try
- {
- Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance...");
- Console.WriteLine(" Reading .sln file version...");
- string version = GetSolutionVersion(full_solution_name);
-
- Console.WriteLine(" Using version: {0}...", version);
- string progid = GetVSProgID(version);
-
- Type objType = Type.GetTypeFromProgID(progid);
- dte = System.Activator.CreateInstance(objType);
- Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name);
-
- solution = ViaCOM.GetProperty(dte, "Solution");
- object[] openArgs = { full_solution_name };
- ViaCOM.CallMethod(solution, "Open", openArgs);
- }
- catch (Exception e)
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Quitting do to error opening: {0}", full_solution_name);
- solution = null;
- dte = null;
- return found_open_solution;
- }
- found_open_solution = false;
- }
-
- if (solution == null)
- {
- solution = ViaCOM.GetProperty(dte, "Solution");
- }
-
- return found_open_solution;
- }
-
- /// <summary>
- /// Get the DTE object for the instance of Visual Studio IDE that has
- /// the specified solution open.
- /// </summary>
- /// <param name="solutionFile">The absolute filename of the solution</param>
- /// <returns>Corresponding DTE object or null if no such IDE is running</returns>
- public static object GetIDEInstance( string solutionFile )
- {
- Hashtable runningInstances = GetIDEInstances( true );
- IDictionaryEnumerator enumerator = runningInstances.GetEnumerator();
-
- while ( enumerator.MoveNext() )
- {
- try
- {
- object ide = enumerator.Value;
- if (ide != null)
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case))
- {
- return ide;
- }
- }
- }
- catch{}
- }
-
- return null;
- }
-
- /// <summary>
- /// Get a table of the currently running instances of the Visual Studio .NET IDE.
- /// </summary>
- /// <param name="openSolutionsOnly">Only return instances that have opened a solution</param>
- /// <returns>A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object</returns>
- public static Hashtable GetIDEInstances( bool openSolutionsOnly )
- {
- Hashtable runningIDEInstances = new Hashtable();
- Hashtable runningObjects = GetRunningObjectTable();
-
- IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
- while ( rotEnumerator.MoveNext() )
- {
- string candidateName = (string) rotEnumerator.Key;
- if (!candidateName.StartsWith("!VisualStudio.DTE"))
- continue;
-
- object ide = rotEnumerator.Value;
- if (ide == null)
- continue;
-
- if (openSolutionsOnly)
- {
- try
- {
- object sol = ViaCOM.GetProperty(ide, "Solution");
- string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName");
- if (solutionFile != String.Empty)
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- catch {}
- }
- else
- {
- runningIDEInstances[ candidateName ] = ide;
- }
- }
- return runningIDEInstances;
- }
-
- /// <summary>
- /// Get a snapshot of the running object table (ROT).
- /// </summary>
- /// <returns>A hashtable mapping the name of the object in the ROT to the corresponding object</returns>
- [STAThread]
- public static Hashtable GetRunningObjectTable()
- {
- Hashtable result = new Hashtable();
-
- int numFetched = 0;
- IRunningObjectTable runningObjectTable;
- IEnumMoniker monikerEnumerator;
- IMoniker[] monikers = new IMoniker[1];
-
- GetRunningObjectTable(0, out runningObjectTable);
- runningObjectTable.EnumRunning(out monikerEnumerator);
- monikerEnumerator.Reset();
-
- while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0)
- {
- IBindCtx ctx;
- CreateBindCtx(0, out ctx);
-
- string runningObjectName;
- monikers[0].GetDisplayName(ctx, null, out runningObjectName);
-
- object runningObjectVal;
- runningObjectTable.GetObject( monikers[0], out runningObjectVal);
-
- result[ runningObjectName ] = runningObjectVal;
- }
-
- return result;
- }
-
- public static string GetSolutionVersion(string solutionFullFileName)
- {
- string version;
- System.IO.StreamReader solutionStreamReader = null;
- string firstLine;
- string format;
-
- try
- {
- solutionStreamReader = new System.IO.StreamReader(solutionFullFileName);
- do
- {
- firstLine = solutionStreamReader.ReadLine();
- }
- while (firstLine == "");
-
- format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim();
-
- switch(format)
- {
- case "7.00":
- version = "VC70";
- break;
-
- case "8.00":
- version = "VC71";
- break;
-
- case "9.00":
- version = "VC80";
- break;
-
- case "10.00":
- version = "VC90";
- break;
- default:
- throw new ApplicationException("Unknown .sln version: " + format);
- }
- }
- finally
- {
- if(solutionStreamReader != null)
- {
- solutionStreamReader.Close();
- }
- }
-
- return version;
- }
-
- public static string GetVSProgID(string version)
- {
- string progid = null;
- switch(version)
- {
- case "VC70":
- progid = "VisualStudio.DTE.7";
- break;
-
- case "VC71":
- progid = "VisualStudio.DTE.7.1";
- break;
-
- case "VC80":
- progid = "VisualStudio.DTE.8.0";
- break;
-
- case "VC90":
- progid = "VisualStudio.DTE.9.0";
- break;
- default:
- throw new ApplicationException("Can't handle VS version: " + version);
- }
-
- return progid;
- }
-
- public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir)
- {
- bool made_change = false;
- Console.WriteLine("Looking for project {0}...", project_name);
- try
- {
- object prjs = ViaCOM.GetProperty(sol, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for(int i = 1; i <= (int)count; ++i)
- {
- object[] prjItemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs);
- string name = (string)ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare(name, project_name, ignore_case))
- {
- Console.WriteLine("Found project: {0}", project_name);
- Console.WriteLine("Setting working directory");
-
- string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName");
- Console.WriteLine(full_project_name);
-
- // *NOTE:Mani Thanks to incompatibilities between different versions of the
- // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to
- // the VCProjectEngine types from a different version than the one built
- // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built
- // in VS 8.0. To avoid this problem, we can use the com object interfaces directly,
- // without the type casting. Its tedious code, but it seems to work.
-
- // oCfgs should be assigned to a 'Project.Configurations' collection.
- object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations");
-
- // oCount will be assigned to the number of configs present in oCfgs.
- object oCount = ViaCOM.GetProperty(oCfgs, "Count");
-
- for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex)
- {
- object[] itemArgs = {(object)cfgIndex};
- object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs);
- object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings");
- ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir);
- }
-
- break;
- }
- }
- made_change = true;
- }
- catch( Exception e )
- {
- Console.WriteLine(e.Message);
- Console.WriteLine("Failed to set working dir for project, {0}.", project_name);
- }
-
- return made_change;
- }
-
- public static bool SetStartupProject(string startup_project)
- {
- bool result = false;
- try
- {
- // You need the 'unique name of the project to set StartupProjects.
- // find the project by generic name.
- Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project);
- object prjs = ViaCOM.GetProperty(solution, "Projects");
- object count = ViaCOM.GetProperty(prjs, "Count");
- for (int i = 1; i <= (int)count; ++i)
- {
- object[] itemArgs = { (object)i };
- object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs);
- object prjName = ViaCOM.GetProperty(prj, "Name");
- if (0 == string.Compare((string)prjName, startup_project, ignore_case))
- {
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName"));
- Console.WriteLine(" Success!");
- result = true;
- break;
- }
- }
-
- if (result == false)
- {
- Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project);
- }
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set the startup project!");
- Console.WriteLine(e.Message);
- }
- return result;
- }
-
- public static bool SetActiveConfig(string config)
- {
- bool result = false;
- try
- {
- Console.WriteLine("Trying to set active config to \"{0}\"", config);
- object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
- object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations");
- object[] itemArgs = { (object)config };
- object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs);
- ViaCOM.CallMethod(solCfg, "Activate", null);
- Console.WriteLine(" Success!");
- result = true;
- }
- catch (Exception e)
- {
- Console.WriteLine(" Failed to set \"{0}\" as the active config.", config);
- Console.WriteLine(e.Message);
- }
- return result;
- }
- }
-}
+// Code about getting running instances visual studio
+// was borrowed from
+// http://www.codeproject.com/KB/cs/automatingvisualstudio.aspx
+
+
+using System;
+using System.Collections;
+using System.Collections.Generic;
+using System.Reflection;
+using System.Runtime.InteropServices;
+using System.Runtime.InteropServices.ComTypes;
+using Microsoft.CSharp;
+
+namespace VSTool
+{
+ // The MessageFilter class comes from:
+ // http://msdn.microsoft.com/en-us/library/ms228772(VS.80).aspx
+ // It allows vstool to get timing error messages from
+ // visualstudio and handle them.
+ public class MessageFilter : IOleMessageFilter
+ {
+ //
+ // Class containing the IOleMessageFilter
+ // thread error-handling functions.
+
+ // Start the filter.
+ public static void Register()
+ {
+ IOleMessageFilter newFilter = new MessageFilter();
+ IOleMessageFilter oldFilter = null;
+ CoRegisterMessageFilter(newFilter, out oldFilter);
+ }
+
+ // Done with the filter, close it.
+ public static void Revoke()
+ {
+ IOleMessageFilter oldFilter = null;
+ CoRegisterMessageFilter(null, out oldFilter);
+ }
+
+ //
+ // IOleMessageFilter functions.
+ // Handle incoming thread requests.
+ int IOleMessageFilter.HandleInComingCall(int dwCallType,
+ System.IntPtr hTaskCaller, int dwTickCount, System.IntPtr
+ lpInterfaceInfo)
+ {
+ //Return the flag SERVERCALL_ISHANDLED.
+ return 0;
+ }
+
+ // Thread call was rejected, so try again.
+ int IOleMessageFilter.RetryRejectedCall(System.IntPtr
+ hTaskCallee, int dwTickCount, int dwRejectType)
+ {
+ if (dwRejectType == 2)
+ // flag = SERVERCALL_RETRYLATER.
+ {
+ // Retry the thread call immediately if return >=0 &
+ // <100.
+ return 99;
+ }
+ // Too busy; cancel call.
+ return -1;
+ }
+
+ int IOleMessageFilter.MessagePending(System.IntPtr hTaskCallee,
+ int dwTickCount, int dwPendingType)
+ {
+ //Return the flag PENDINGMSG_WAITDEFPROCESS.
+ return 2;
+ }
+
+ // Implement the IOleMessageFilter interface.
+ [DllImport("Ole32.dll")]
+ private static extern int
+ CoRegisterMessageFilter(IOleMessageFilter newFilter, out
+ IOleMessageFilter oldFilter);
+ }
+
+ [ComImport(), Guid("00000016-0000-0000-C000-000000000046"),
+ InterfaceTypeAttribute(ComInterfaceType.InterfaceIsIUnknown)]
+ interface IOleMessageFilter
+ {
+ [PreserveSig]
+ int HandleInComingCall(
+ int dwCallType,
+ IntPtr hTaskCaller,
+ int dwTickCount,
+ IntPtr lpInterfaceInfo);
+
+ [PreserveSig]
+ int RetryRejectedCall(
+ IntPtr hTaskCallee,
+ int dwTickCount,
+ int dwRejectType);
+
+ [PreserveSig]
+ int MessagePending(
+ IntPtr hTaskCallee,
+ int dwTickCount,
+ int dwPendingType);
+ }
+
+ class ViaCOM
+ {
+ public static object GetProperty(object from_obj, string prop_name)
+ {
+ try
+ {
+ Type objType = from_obj.GetType();
+ return objType.InvokeMember(
+ prop_name,
+ BindingFlags.GetProperty, null,
+ from_obj,
+ null);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error getting property: \"{0}\"", prop_name);
+ Console.WriteLine(e.Message);
+ throw e;
+ }
+ }
+
+ public static object SetProperty(object from_obj, string prop_name, object new_value)
+ {
+ try
+ {
+ object[] args = { new_value };
+ Type objType = from_obj.GetType();
+ return objType.InvokeMember(
+ prop_name,
+ BindingFlags.DeclaredOnly |
+ BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.Instance |
+ BindingFlags.SetProperty,
+ null,
+ from_obj,
+ args);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error setting property: \"{0}\"", prop_name);
+ Console.WriteLine(e.Message);
+ throw e;
+ }
+ }
+
+ public static object CallMethod(object from_obj, string method_name, params object[] args)
+ {
+ try
+ {
+ Type objType = from_obj.GetType();
+ return objType.InvokeMember(
+ method_name,
+ BindingFlags.DeclaredOnly |
+ BindingFlags.Public |
+ BindingFlags.NonPublic |
+ BindingFlags.Instance |
+ BindingFlags.InvokeMethod,
+ null,
+ from_obj,
+ args);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine("Error calling method \"{0}\"", method_name);
+ Console.WriteLine(e.Message);
+ throw e;
+ }
+ }
+ };
+
+ /// <summary>
+ /// The main entry point class for VSTool.
+ /// </summary>
+ class VSToolMain
+ {
+ #region Interop imports
+ [DllImport("ole32.dll")]
+ public static extern int GetRunningObjectTable(int reserved, out IRunningObjectTable prot);
+
+ [DllImport("ole32.dll")]
+ public static extern int CreateBindCtx(int reserved, out IBindCtx ppbc);
+ #endregion
+
+ static System.Boolean ignore_case = true;
+
+ static string solution_name = null;
+ static bool use_new_vs = false;
+ static Hashtable projectDict = new Hashtable();
+ static string startup_project = null;
+ static string config = null;
+
+ static object dte = null;
+ static object solution = null;
+
+ /// <summary>
+ /// The main entry point for the application.
+ /// </summary>
+ [STAThread]
+ static int Main(string[] args)
+ {
+ int retVal = 0;
+ bool need_save = false;
+
+ try
+ {
+ parse_command_line(args);
+
+ Console.WriteLine("Editing solution: {0}", solution_name);
+
+ bool found_open_solution = GetDTEAndSolution();
+
+ if (dte == null || solution == null)
+ {
+ retVal = 1;
+ }
+ else
+ {
+ MessageFilter.Register();
+
+ // Walk through all of the projects in the solution
+ // and list the type of each project.
+ foreach (DictionaryEntry p in projectDict)
+ {
+ string project_name = (string)p.Key;
+ string working_dir = (string)p.Value;
+ if (SetProjectWorkingDir(solution, project_name, working_dir))
+ {
+ need_save = true;
+ }
+ }
+
+ if (config != null)
+ {
+ need_save = SetActiveConfig(config);
+ }
+
+ if (startup_project != null)
+ {
+ need_save = SetStartupProject(startup_project);
+ }
+
+ if (need_save)
+ {
+ if (found_open_solution == false)
+ {
+ ViaCOM.CallMethod(solution, "Close", null);
+ }
+ }
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ retVal = 1;
+ }
+ finally
+ {
+ if (solution != null)
+ {
+ Marshal.ReleaseComObject(solution);
+ solution = null;
+ }
+
+ if (dte != null)
+ {
+ Marshal.ReleaseComObject(dte);
+ dte = null;
+ }
+
+ MessageFilter.Revoke();
+ }
+ return retVal;
+ }
+
+ public static bool parse_command_line(string[] args)
+ {
+ string options_desc =
+ "--solution <solution_name> : MSVC solution name. (required)\n" +
+ "--use_new_vs : Ignore running versions of visual studio.\n" +
+ "--workingdir <project> <dir> : Set working dir of a VC project.\n" +
+ "--config <config> : Set the active config for the solution.\n" +
+ "--startup <project> : Set the startup project for the solution.\n";
+
+ try
+ {
+ // Command line param parsing loop.
+ int i = 0;
+ for (; i < args.Length; ++i)
+ {
+ if ("--solution" == args[i])
+ {
+ if (solution_name != null)
+ {
+ throw new ApplicationException("Found second --solution option");
+ }
+ solution_name = args[++i];
+ }
+ else if ("--use_new_vs" == args[i])
+ {
+ use_new_vs = true;
+ }
+
+ else if ("--workingdir" == args[i])
+ {
+ string project_name = args[++i];
+ string working_dir = args[++i];
+ projectDict.Add(project_name, working_dir);
+ }
+ else if ("--config" == args[i])
+ {
+ if (config != null)
+ {
+ throw new ApplicationException("Found second --config option");
+ }
+ config = args[++i];
+ }
+ else if ("--startup" == args[i])
+ {
+ if (startup_project != null)
+ {
+ throw new ApplicationException("Found second --startup option");
+ }
+ startup_project = args[++i];
+ }
+ else
+ {
+ throw new ApplicationException("Found unrecognized token on command line: " + args[i]);
+ }
+ }
+
+ if (solution_name == null)
+ {
+ throw new ApplicationException("The --solution option is required.");
+ }
+ }
+ catch(ApplicationException e)
+ {
+
+ Console.WriteLine("Oops! " + e.Message);
+ Console.Write("Command line:");
+ foreach (string arg in args)
+ {
+ Console.Write(" " + arg);
+ }
+ Console.Write("\n\n");
+ Console.WriteLine("VSTool command line usage");
+ Console.Write(options_desc);
+ throw e;
+ }
+ return true;
+ }
+
+ public static bool GetDTEAndSolution()
+ {
+ bool found_open_solution = true;
+
+ Console.WriteLine("Looking for existing VisualStudio instance...");
+
+ // Get an instance of the currently running Visual Studio .NET IDE.
+ // dte = (EnvDTE.DTE)System.Runtime.InteropServices.Marshal.GetActiveObject("VisualStudio.DTE.7.1");
+ string full_solution_name = System.IO.Path.GetFullPath(solution_name);
+ if (false == use_new_vs)
+ {
+ dte = GetIDEInstance(full_solution_name);
+ }
+
+ if (dte == null)
+ {
+ try
+ {
+ Console.WriteLine(" Didn't find open solution, starting new background VisualStudio instance...");
+ Console.WriteLine(" Reading .sln file version...");
+ string version = GetSolutionVersion(full_solution_name);
+
+ Console.WriteLine(" Using version: {0}...", version);
+ string progid = GetVSProgID(version);
+
+ Type objType = Type.GetTypeFromProgID(progid);
+ dte = System.Activator.CreateInstance(objType);
+ Console.WriteLine(" Reading solution: \"{0}\"", full_solution_name);
+
+ solution = ViaCOM.GetProperty(dte, "Solution");
+ object[] openArgs = { full_solution_name };
+ ViaCOM.CallMethod(solution, "Open", openArgs);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e.Message);
+ Console.WriteLine("Quitting do to error opening: {0}", full_solution_name);
+ solution = null;
+ dte = null;
+ return found_open_solution;
+ }
+ found_open_solution = false;
+ }
+
+ if (solution == null)
+ {
+ solution = ViaCOM.GetProperty(dte, "Solution");
+ }
+
+ return found_open_solution;
+ }
+
+ /// <summary>
+ /// Get the DTE object for the instance of Visual Studio IDE that has
+ /// the specified solution open.
+ /// </summary>
+ /// <param name="solutionFile">The absolute filename of the solution</param>
+ /// <returns>Corresponding DTE object or null if no such IDE is running</returns>
+ public static object GetIDEInstance( string solutionFile )
+ {
+ Hashtable runningInstances = GetIDEInstances( true );
+ IDictionaryEnumerator enumerator = runningInstances.GetEnumerator();
+
+ while ( enumerator.MoveNext() )
+ {
+ try
+ {
+ object ide = enumerator.Value;
+ if (ide != null)
+ {
+ object sol = ViaCOM.GetProperty(ide, "Solution");
+ if (0 == string.Compare((string)ViaCOM.GetProperty(sol, "FullName"), solutionFile, ignore_case))
+ {
+ return ide;
+ }
+ }
+ }
+ catch{}
+ }
+
+ return null;
+ }
+
+ /// <summary>
+ /// Get a table of the currently running instances of the Visual Studio .NET IDE.
+ /// </summary>
+ /// <param name="openSolutionsOnly">Only return instances that have opened a solution</param>
+ /// <returns>A hashtable mapping the name of the IDE in the running object table to the corresponding DTE object</returns>
+ public static Hashtable GetIDEInstances( bool openSolutionsOnly )
+ {
+ Hashtable runningIDEInstances = new Hashtable();
+ Hashtable runningObjects = GetRunningObjectTable();
+
+ IDictionaryEnumerator rotEnumerator = runningObjects.GetEnumerator();
+ while ( rotEnumerator.MoveNext() )
+ {
+ string candidateName = (string) rotEnumerator.Key;
+ if (!candidateName.StartsWith("!VisualStudio.DTE"))
+ continue;
+
+ object ide = rotEnumerator.Value;
+ if (ide == null)
+ continue;
+
+ if (openSolutionsOnly)
+ {
+ try
+ {
+ object sol = ViaCOM.GetProperty(ide, "Solution");
+ string solutionFile = (string)ViaCOM.GetProperty(sol, "FullName");
+ if (solutionFile != String.Empty)
+ {
+ runningIDEInstances[ candidateName ] = ide;
+ }
+ }
+ catch {}
+ }
+ else
+ {
+ runningIDEInstances[ candidateName ] = ide;
+ }
+ }
+ return runningIDEInstances;
+ }
+
+ /// <summary>
+ /// Get a snapshot of the running object table (ROT).
+ /// </summary>
+ /// <returns>A hashtable mapping the name of the object in the ROT to the corresponding object</returns>
+ [STAThread]
+ public static Hashtable GetRunningObjectTable()
+ {
+ Hashtable result = new Hashtable();
+
+ int numFetched = 0;
+ IRunningObjectTable runningObjectTable;
+ IEnumMoniker monikerEnumerator;
+ IMoniker[] monikers = new IMoniker[1];
+
+ GetRunningObjectTable(0, out runningObjectTable);
+ runningObjectTable.EnumRunning(out monikerEnumerator);
+ monikerEnumerator.Reset();
+
+ while (monikerEnumerator.Next(1, monikers, new IntPtr(numFetched)) == 0)
+ {
+ IBindCtx ctx;
+ CreateBindCtx(0, out ctx);
+
+ string runningObjectName;
+ monikers[0].GetDisplayName(ctx, null, out runningObjectName);
+
+ object runningObjectVal;
+ runningObjectTable.GetObject( monikers[0], out runningObjectVal);
+
+ result[ runningObjectName ] = runningObjectVal;
+ }
+
+ return result;
+ }
+
+ public static string GetSolutionVersion(string solutionFullFileName)
+ {
+ string version;
+ System.IO.StreamReader solutionStreamReader = null;
+ string firstLine;
+ string format;
+
+ try
+ {
+ solutionStreamReader = new System.IO.StreamReader(solutionFullFileName);
+ do
+ {
+ firstLine = solutionStreamReader.ReadLine();
+ }
+ while (firstLine == "");
+
+ format = firstLine.Substring(firstLine.LastIndexOf(" ")).Trim();
+
+ switch(format)
+ {
+ case "7.00":
+ version = "VC70";
+ break;
+
+ case "8.00":
+ version = "VC71";
+ break;
+
+ case "9.00":
+ version = "VC80";
+ break;
+
+ case "10.00":
+ version = "VC90";
+ break;
+ default:
+ throw new ApplicationException("Unknown .sln version: " + format);
+ }
+ }
+ finally
+ {
+ if(solutionStreamReader != null)
+ {
+ solutionStreamReader.Close();
+ }
+ }
+
+ return version;
+ }
+
+ public static string GetVSProgID(string version)
+ {
+ string progid = null;
+ switch(version)
+ {
+ case "VC70":
+ progid = "VisualStudio.DTE.7";
+ break;
+
+ case "VC71":
+ progid = "VisualStudio.DTE.7.1";
+ break;
+
+ case "VC80":
+ progid = "VisualStudio.DTE.8.0";
+ break;
+
+ case "VC90":
+ progid = "VisualStudio.DTE.9.0";
+ break;
+ default:
+ throw new ApplicationException("Can't handle VS version: " + version);
+ }
+
+ return progid;
+ }
+
+ public static bool SetProjectWorkingDir(object sol, string project_name, string working_dir)
+ {
+ bool made_change = false;
+ Console.WriteLine("Looking for project {0}...", project_name);
+ try
+ {
+ object prjs = ViaCOM.GetProperty(sol, "Projects");
+ object count = ViaCOM.GetProperty(prjs, "Count");
+ for(int i = 1; i <= (int)count; ++i)
+ {
+ object[] prjItemArgs = { (object)i };
+ object prj = ViaCOM.CallMethod(prjs, "Item", prjItemArgs);
+ string name = (string)ViaCOM.GetProperty(prj, "Name");
+ if (0 == string.Compare(name, project_name, ignore_case))
+ {
+ Console.WriteLine("Found project: {0}", project_name);
+ Console.WriteLine("Setting working directory");
+
+ string full_project_name = (string)ViaCOM.GetProperty(prj, "FullName");
+ Console.WriteLine(full_project_name);
+
+ // *NOTE:Mani Thanks to incompatibilities between different versions of the
+ // VCProjectEngine.dll assembly, we can't cast the objects recevied from the DTE to
+ // the VCProjectEngine types from a different version than the one built
+ // with. ie, VisualStudio.DTE.7.1 objects can't be converted in a project built
+ // in VS 8.0. To avoid this problem, we can use the com object interfaces directly,
+ // without the type casting. Its tedious code, but it seems to work.
+
+ // oCfgs should be assigned to a 'Project.Configurations' collection.
+ object oCfgs = ViaCOM.GetProperty(ViaCOM.GetProperty(prj, "Object"), "Configurations");
+
+ // oCount will be assigned to the number of configs present in oCfgs.
+ object oCount = ViaCOM.GetProperty(oCfgs, "Count");
+
+ for (int cfgIndex = 1; cfgIndex <= (int)oCount; ++cfgIndex)
+ {
+ object[] itemArgs = {(object)cfgIndex};
+ object oCfg = ViaCOM.CallMethod(oCfgs, "Item", itemArgs);
+ object oDebugSettings = ViaCOM.GetProperty(oCfg, "DebugSettings");
+ ViaCOM.SetProperty(oDebugSettings, "WorkingDirectory", (object)working_dir);
+ }
+
+ break;
+ }
+ }
+ made_change = true;
+ }
+ catch( Exception e )
+ {
+ Console.WriteLine(e.Message);
+ Console.WriteLine("Failed to set working dir for project, {0}.", project_name);
+ }
+
+ return made_change;
+ }
+
+ public static bool SetStartupProject(string startup_project)
+ {
+ bool result = false;
+ try
+ {
+ // You need the 'unique name of the project to set StartupProjects.
+ // find the project by generic name.
+ Console.WriteLine("Trying to set \"{0}\" to the startup project", startup_project);
+ object prjs = ViaCOM.GetProperty(solution, "Projects");
+ object count = ViaCOM.GetProperty(prjs, "Count");
+ for (int i = 1; i <= (int)count; ++i)
+ {
+ object[] itemArgs = { (object)i };
+ object prj = ViaCOM.CallMethod(prjs, "Item", itemArgs);
+ object prjName = ViaCOM.GetProperty(prj, "Name");
+ if (0 == string.Compare((string)prjName, startup_project, ignore_case))
+ {
+ object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
+ ViaCOM.SetProperty(solBuild, "StartupProjects", ViaCOM.GetProperty(prj, "UniqueName"));
+ Console.WriteLine(" Success!");
+ result = true;
+ break;
+ }
+ }
+
+ if (result == false)
+ {
+ Console.WriteLine(" Could not find project \"{0}\" in the solution.", startup_project);
+ }
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(" Failed to set the startup project!");
+ Console.WriteLine(e.Message);
+ }
+ return result;
+ }
+
+ public static bool SetActiveConfig(string config)
+ {
+ bool result = false;
+ try
+ {
+ Console.WriteLine("Trying to set active config to \"{0}\"", config);
+ object solBuild = ViaCOM.GetProperty(solution, "SolutionBuild");
+ object solCfgs = ViaCOM.GetProperty(solBuild, "SolutionConfigurations");
+ object[] itemArgs = { (object)config };
+ object solCfg = ViaCOM.CallMethod(solCfgs, "Item", itemArgs);
+ ViaCOM.CallMethod(solCfg, "Activate", null);
+ Console.WriteLine(" Success!");
+ result = true;
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(" Failed to set \"{0}\" as the active config.", config);
+ Console.WriteLine(e.Message);
+ }
+ return result;
+ }
+ }
+}
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..7a30315b9a
--- /dev/null
+++ b/indra/viewer_components/login/lllogin.cpp
@@ -0,0 +1,374 @@
+/**
+ * @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:
+ void sendProgressEvent(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;
+ }
+
+ 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)
+{
+ LL_INFOS("LLLogin") << "Entering coroutine " << LLCoros::instance().getName(self)
+ << " with uri '" << uri << "', credentials " << credentials << LL_ENDL;
+ // Arriving in SRVRequest state
+ LLEventStream replyPump("reply", true);
+ // Should be an array of one or more uri strings.
+ LLSD rewrittenURIs;
+ {
+ LLEventTimeout filter(replyPump);
+ sendProgressEvent("offline", "srvrequest");
+
+ // Request SRV record.
+ LL_INFOS("LLLogin") << "Requesting SRV record from " << uri << LL_ENDL;
+
+ // *NOTE:Mani - Completely arbitrary timeout value for SRV request.
+ filter.errorAfter(5, "SRV Request timed out!");
+
+ // Make request
+ LLSD request;
+ request["op"] = "rewriteURI";
+ request["uri"] = uri;
+ request["reply"] = replyPump.getName();
+ rewrittenURIs = postAndWait(self, request, "LLAres", filter);
+ } // we no longer need the filter
+
+ LLEventPump& xmlrpcPump(LLEventPumps::instance().obtain("LLXMLRPCTransaction"));
+
+ // 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"] = replyPump.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;
+ 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(replyPump.getName(),
+ postAndWait(self, request, xmlrpcPump, replyPump, "reply"));
+ mAuthResponse["status"].asString() == "Downloading";
+ mAuthResponse = validateResponse(replyPump.getName(),
+ waitForEventOn(self, replyPump)))
+ {
+ // Still Downloading -- send progress update.
+ sendProgressEvent("offline", "downloading");
+ }
+ 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;
+ }
+
+ // 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["next_url"];
+ request["method"] = mAuthResponse["next_method"];
+ } // 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.
+ sendProgressEvent("offline", "fail.login", mAuthResponse["responses"]);
+}
+
+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..a8ae2883d5
--- /dev/null
+++ b/indra/viewer_components/login/tests/lllogin_test.cpp
@@ -0,0 +1,417 @@
+/**
+ * @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"
+
+/*****************************************************************************
+* 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 repsonses 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' repsond 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["next_url"] = "login.indeterminate.com";
+ data["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");
+
+ // 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");
+ }
+}