From 9ec432034dc3c45d7ce763eb02dae4cc7f6b8da8 Mon Sep 17 00:00:00 2001 From: Steven Bennetts Date: Sun, 21 Jun 2009 08:04:56 +0000 Subject: merge -r 122421-124917 viewer-2.0.0-2 -> viewer-2.0.0-3 ignore-dead-branch --- doc/contributions.txt | 5 + indra/CMakeLists.txt | 5 + indra/cmake/GooglePerfTools.cmake | 8 +- indra/cmake/LLCommon.cmake | 4 + indra/cmake/Linking.cmake | 1 + indra/cmake/Variables.cmake | 1 + indra/integration_tests/CMakeLists.txt | 3 + .../integration_tests/llui_libtest/CMakeLists.txt | 97 + .../llui_libtest/llui_libtest.cpp | 196 + .../integration_tests/llui_libtest/llui_libtest.h | 36 + .../integration_tests/llui_libtest/llwidgetreg.cpp | 106 + indra/integration_tests/llui_libtest/llwidgetreg.h | 43 + indra/llaudio/llaudiodecodemgr.cpp | 2 +- indra/llcharacter/llbvhloader.cpp | 161 +- indra/llcharacter/llbvhloader.h | 51 +- indra/llcharacter/llcharacter.h | 12 +- indra/llcharacter/lljointstate.h | 2 +- indra/llcharacter/llkeyframemotionparam.cpp | 7 +- indra/llcharacter/llmotioncontroller.cpp | 4 +- indra/llcharacter/llmotioncontroller.h | 6 +- indra/llcharacter/llmultigesture.cpp | 64 +- indra/llcharacter/llmultigesture.h | 10 +- indra/llcharacter/llpose.h | 6 +- indra/llcharacter/llvisualparam.h | 22 +- indra/llcommon/CMakeLists.txt | 34 + indra/llcommon/is_approx_equal_fraction.h | 23 + indra/llcommon/linden_common.h | 18 +- indra/llcommon/llallocator.cpp | 140 + indra/llcommon/llallocator.h | 63 + indra/llcommon/llallocator_heap_profile.cpp | 149 + indra/llcommon/llallocator_heap_profile.h | 77 + indra/llcommon/llassettype.cpp | 287 +- indra/llcommon/llassettype.h | 137 +- indra/llcommon/llboost.h | 15 + indra/llcommon/llcommon.cpp | 2 + indra/llcommon/llcommon.h | 3 +- indra/llcommon/lldate.cpp | 58 +- indra/llcommon/lldate.h | 4 +- indra/llcommon/lldeleteutils.h | 53 + indra/llcommon/lldictionary.h | 102 + indra/llcommon/lldoubledispatch.h | 332 + indra/llcommon/llerrorthread.cpp | 2 + indra/llcommon/llevent.h | 2 +- indra/llcommon/llevents.h | 2 +- indra/llcommon/llfasttimer.h | 484 +- indra/llcommon/llinstancetracker.h | 121 + indra/llcommon/llmd5.cpp | 1 + indra/llcommon/llmemory.cpp | 208 +- indra/llcommon/llmemory.h | 429 +- indra/llcommon/llmemtype.cpp | 237 + indra/llcommon/llmemtype.h | 300 +- indra/llcommon/llpointer.h | 177 + indra/llcommon/llptrto.cpp | 108 + indra/llcommon/llptrto.h | 93 + indra/llcommon/llqueuedthread.cpp | 2 + indra/llcommon/llrefcount.cpp | 49 + indra/llcommon/llrefcount.h | 78 + indra/llcommon/llsafehandle.h | 167 + indra/llcommon/llsdserialize.cpp | 2 +- indra/llcommon/llsdserialize.h | 3 +- indra/llcommon/llsdutil.cpp | 9 + indra/llcommon/llsdutil.h | 1 + indra/llcommon/llsecondlifeurls.cpp | 34 +- indra/llcommon/llsecondlifeurls.h | 13 +- indra/llcommon/llsingleton.h | 158 + indra/llcommon/llstacktrace.cpp | 141 + indra/llcommon/llstacktrace.h | 44 + indra/llcommon/llstat.cpp | 42 +- indra/llcommon/llstat.h | 25 +- indra/llcommon/llstring.cpp | 76 + indra/llcommon/llstring.h | 252 +- indra/llcommon/llthread.h | 1 - indra/llcommon/lltimer.cpp | 9 +- indra/llcommon/lltimer.h | 9 +- indra/llcommon/lltreeiterators.h | 711 ++ indra/llcommon/llversionviewer.h | 8 +- .../tests/llallocator_heap_profile_test.cpp | 150 + indra/llcommon/tests/llallocator_test.cpp | 86 + indra/llcommon/tests/llmemtype_test.cpp | 123 + indra/llcrashlogger/llcrashlogger.cpp | 4 + indra/llimage/llimage.cpp | 14 +- indra/llimage/llimage.h | 5 +- indra/llimage/llimagedxt.h | 1 + indra/llimage/llimagej2c.cpp | 6 +- indra/llimage/llimagetga.cpp | 4 +- indra/llimage/llimageworker.h | 1 + indra/llimagej2coj/llimagej2coj.cpp | 2 +- indra/llinventory/lleconomy.h | 2 +- indra/llinventory/llinventory.cpp | 117 +- indra/llinventory/llinventory.h | 13 +- indra/llinventory/llinventorytype.cpp | 199 +- indra/llinventory/llinventorytype.h | 18 +- indra/llinventory/lllandmark.cpp | 22 +- indra/llinventory/lllandmark.h | 25 +- indra/llinventory/llnotecard.h | 2 +- indra/llinventory/llparcel.cpp | 4 +- indra/llinventory/llparcel.h | 1 + indra/llinventory/llpermissions.cpp | 63 +- indra/llinventory/llpermissions.h | 3 - indra/llinventory/llsaleinfo.cpp | 34 +- indra/llinventory/llsaleinfo.h | 3 - indra/llmath/llmath.h | 4 +- indra/llmath/llrect.h | 6 +- indra/llmath/llsdutil_math.cpp | 5 +- indra/llmath/llvolume.h | 2 +- indra/llmath/llvolumemgr.h | 6 +- indra/llmath/v3color.cpp | 36 + indra/llmath/v3color.h | 1 + indra/llmath/v4color.cpp | 70 + indra/llmath/v4color.h | 16 +- indra/llmath/v4coloru.h | 6 + indra/llmessage/llares.h | 3 +- indra/llmessage/llcachename.cpp | 217 +- indra/llmessage/llcachename.h | 27 +- indra/llmessage/llhttpclientadapter.cpp | 7 +- indra/llmessage/llhttpclientadapter.h | 9 +- indra/llmessage/llhttpclientinterface.h | 7 +- indra/llmessage/llhttpnode.h | 3 +- indra/llmessage/llhttpnodeadapter.h | 15 +- indra/llmessage/llinstantmessage.cpp | 2 +- indra/llmessage/llinstantmessage.h | 3 +- indra/llmessage/llmessagesenderinterface.h | 7 +- indra/llmessage/llregionpresenceverifier.cpp | 25 +- indra/llmessage/llregionpresenceverifier.h | 25 +- indra/llmessage/llstoredmessage.cpp | 2 +- indra/llmessage/llstoredmessage.h | 2 +- indra/llmessage/lltemplatemessagedispatcher.cpp | 17 +- indra/llmessage/lltemplatemessagedispatcher.h | 17 +- indra/llmessage/lltransfersourceasset.cpp | 2 + indra/llmessage/lltrustedmessageservice.cpp | 17 +- indra/llmessage/lltrustedmessageservice.h | 17 +- indra/llmessage/message.cpp | 3 + indra/llmessage/message.h | 2 +- indra/llmessage/message_prehash.cpp | 2 +- indra/llmessage/tests/commtest.h | 23 + indra/llmessage/tests/llcurl_stub.cpp | 10 +- indra/llmessage/tests/llhttpclientadapter_test.cpp | 7 +- .../tests/lltemplatemessagedispatcher_test.cpp | 17 +- indra/llmessage/tests/lltesthttpclientadapter.cpp | 2 +- indra/llmessage/tests/lltesthttpclientadapter.h | 2 +- indra/llmessage/tests/lltestmessagesender.cpp | 2 +- indra/llmessage/tests/lltestmessagesender.h | 2 +- .../tests/lltrustedmessageservice_test.cpp | 17 +- indra/llmessage/tests/networkio.h | 23 + indra/llprimitive/llmaterialtable.cpp | 11 + indra/llprimitive/llmaterialtable.h | 2 + indra/llprimitive/llprimitive.cpp | 2 +- indra/llprimitive/llprimitive.h | 2 +- indra/llprimitive/llprimtexturelist.cpp | 7 +- indra/llprimitive/llprimtexturelist.h | 7 +- indra/llprimitive/tests/llmessagesystem_stub.cpp | 42 + indra/llprimitive/tests/llprimitive_test.cpp | 214 + indra/llrender/llfontbitmapcache.cpp | 7 +- indra/llrender/llfontbitmapcache.h | 7 +- indra/llrender/llfontgl.cpp | 118 +- indra/llrender/llfontgl.h | 47 +- indra/llrender/llfontregistry.cpp | 19 +- indra/llrender/llfontregistry.h | 13 +- indra/llrender/llgl.cpp | 201 +- indra/llrender/llgl.h | 9 + indra/llrender/llglslshader.cpp | 10 +- indra/llrender/llimagegl.cpp | 53 +- indra/llrender/llimagegl.h | 14 +- indra/llrender/llrender.cpp | 5 +- indra/llrender/llrender.h | 3 +- indra/llrender/llrendertarget.cpp | 13 +- indra/llrender/llrendertarget.h | 4 + indra/llrender/llvertexbuffer.cpp | 136 +- indra/llrender/llvertexbuffer.h | 1 - indra/llui/CMakeLists.txt | 50 +- indra/llui/llbutton.cpp | 734 +- indra/llui/llbutton.h | 199 +- indra/llui/llcallbackmap.h | 19 +- indra/llui/llcheckboxctrl.cpp | 282 +- indra/llui/llcheckboxctrl.h | 73 +- indra/llui/llcombobox.cpp | 588 +- indra/llui/llcombobox.h | 131 +- indra/llui/llconsole.cpp | 393 + indra/llui/llconsole.h | 162 + indra/llui/llcontainerview.cpp | 301 + indra/llui/llcontainerview.h | 92 + indra/llui/lldraghandle.cpp | 105 +- indra/llui/lldraghandle.h | 44 +- indra/llui/llf32uictrl.cpp | 57 + indra/llui/llf32uictrl.h | 83 + indra/llui/llfloater.cpp | 1666 ++-- indra/llui/llfloater.h | 302 +- indra/llui/llfloaterreg.cpp | 423 + indra/llui/llfloaterreg.h | 152 + indra/llui/llflyoutbutton.cpp | 94 + indra/llui/llflyoutbutton.h | 71 + indra/llui/llfocusmgr.cpp | 20 +- indra/llui/llfunctorregistry.h | 2 +- indra/llui/lliconctrl.cpp | 128 +- indra/llui/lliconctrl.h | 32 +- indra/llui/llkeywords.cpp | 4 +- indra/llui/lllayoutstack.cpp | 740 ++ indra/llui/lllayoutstack.h | 105 + indra/llui/lllazyvalue.h | 88 + indra/llui/lllineeditor.cpp | 720 +- indra/llui/lllineeditor.h | 178 +- indra/llui/llmenugl.cpp | 3618 ++++----- indra/llui/llmenugl.h | 612 +- indra/llui/llmodaldialog.cpp | 48 +- indra/llui/llmodaldialog.h | 2 +- indra/llui/llmultifloater.cpp | 510 ++ indra/llui/llmultifloater.h | 107 + indra/llui/llmultislider.cpp | 220 +- indra/llui/llmultislider.h | 97 +- indra/llui/llmultisliderctrl.cpp | 394 +- indra/llui/llmultisliderctrl.h | 71 +- indra/llui/llnotifications.cpp | 161 +- indra/llui/llnotifications.h | 97 +- indra/llui/llpanel.cpp | 1219 +-- indra/llui/llpanel.h | 174 +- indra/llui/llprogressbar.cpp | 141 +- indra/llui/llprogressbar.h | 45 +- indra/llui/llradiogroup.cpp | 257 +- indra/llui/llradiogroup.h | 79 +- indra/llui/llresizebar.cpp | 37 +- indra/llui/llresizebar.h | 26 +- indra/llui/llresizehandle.cpp | 57 +- indra/llui/llresizehandle.h | 13 +- indra/llui/llresmgr.cpp | 147 +- indra/llui/llresmgr.h | 25 +- indra/llui/llscrollbar.cpp | 239 +- indra/llui/llscrollbar.h | 72 +- indra/llui/llscrollcontainer.cpp | 317 +- indra/llui/llscrollcontainer.h | 37 +- indra/llui/llscrollingpanellist.cpp | 64 +- indra/llui/llscrollingpanellist.h | 30 +- indra/llui/llscrolllistcell.cpp | 413 + indra/llui/llscrolllistcell.h | 223 + indra/llui/llscrolllistcolumn.cpp | 320 + indra/llui/llscrolllistcolumn.h | 189 + indra/llui/llscrolllistctrl.cpp | 1886 +---- indra/llui/llscrolllistctrl.h | 433 +- indra/llui/llscrolllistitem.cpp | 157 + indra/llui/llscrolllistitem.h | 129 + indra/llui/llsdparam.cpp | 158 + indra/llui/llsdparam.h | 107 + indra/llui/llsearcheditor.cpp | 124 + indra/llui/llsearcheditor.h | 98 + indra/llui/llslider.cpp | 160 +- indra/llui/llslider.h | 71 +- indra/llui/llsliderctrl.cpp | 341 +- indra/llui/llsliderctrl.h | 119 +- indra/llui/llspinctrl.cpp | 373 +- indra/llui/llspinctrl.h | 74 +- indra/llui/llstatbar.cpp | 293 + indra/llui/llstatbar.h | 108 + indra/llui/llstatgraph.cpp | 163 + indra/llui/llstatgraph.h | 76 + indra/llui/llstatview.cpp | 80 + indra/llui/llstatview.h | 66 + indra/llui/llstyle.cpp | 32 +- indra/llui/llstyle.h | 9 +- indra/llui/lltabcontainer.cpp | 814 +- indra/llui/lltabcontainer.h | 133 +- indra/llui/lltextbox.cpp | 249 +- indra/llui/lltextbox.h | 81 +- indra/llui/lltexteditor.cpp | 574 +- indra/llui/lltexteditor.h | 110 +- indra/llui/lltextparser.cpp | 55 +- indra/llui/lltextparser.h | 34 +- indra/llui/llui.cpp | 396 +- indra/llui/llui.h | 311 +- indra/llui/lluicolortable.cpp | 155 + indra/llui/lluicolortable.h | 58 + indra/llui/lluictrl.cpp | 440 +- indra/llui/lluictrl.h | 211 +- indra/llui/lluictrlfactory.cpp | 1103 ++- indra/llui/lluictrlfactory.h | 408 +- indra/llui/lluifwd.h | 1 - indra/llui/lluiimage.cpp | 166 + indra/llui/lluiimage.h | 114 + indra/llui/lluistring.cpp | 14 +- indra/llui/llview.cpp | 1350 ++-- indra/llui/llview.h | 361 +- indra/llui/llviewborder.cpp | 143 +- indra/llui/llviewborder.h | 57 +- indra/llui/llviewmodel.cpp | 163 + indra/llui/llviewmodel.h | 219 + indra/llui/llviewquery.h | 2 +- indra/llvfs/lldir.cpp | 55 +- indra/llvfs/lldir.h | 34 +- indra/llvfs/lldir_linux.cpp | 8 +- indra/llvfs/lldir_linux.h | 3 +- indra/llvfs/lldir_mac.cpp | 8 +- indra/llvfs/lldir_mac.h | 3 +- indra/llvfs/lldir_solaris.cpp | 8 +- indra/llvfs/lldir_solaris.h | 3 +- indra/llvfs/lldir_win32.cpp | 17 +- indra/llvfs/lldir_win32.h | 3 +- indra/llvfs/lllfsthread.h | 2 +- indra/llvfs/llpidlock.cpp | 7 +- indra/llvfs/llpidlock.h | 7 +- indra/llvfs/llvfs.cpp | 2 + indra/llwindow/CMakeLists.txt | 6 +- indra/llwindow/lldxhardware.cpp | 1 + indra/llwindow/llkeyboard.cpp | 2 +- indra/llwindow/llkeyboardmacosx.cpp | 2 +- indra/llwindow/llkeyboardsdl.cpp | 2 +- indra/llwindow/llkeyboardwin32.cpp | 10 +- indra/llwindow/llpreeditor.h | 2 +- indra/llwindow/llwindow.cpp | 233 +- indra/llwindow/llwindow.h | 83 +- indra/llwindow/llwindowcallbacks.cpp | 201 + indra/llwindow/llwindowcallbacks.h | 85 + indra/llwindow/llwindowheadless.cpp | 6 +- indra/llwindow/llwindowheadless.h | 9 +- indra/llwindow/llwindowmacosx.cpp | 27 +- indra/llwindow/llwindowmacosx.h | 6 +- indra/llwindow/llwindowmesaheadless.cpp | 5 +- indra/llwindow/llwindowmesaheadless.h | 3 +- indra/llwindow/llwindowsdl.cpp | 16 +- indra/llwindow/llwindowsdl.h | 5 +- indra/llwindow/llwindowwin32.cpp | 124 +- indra/llwindow/llwindowwin32.h | 4 +- indra/llxml/CMakeLists.txt | 3 + indra/llxml/llcontrol.cpp | 711 +- indra/llxml/llcontrol.h | 288 +- indra/llxml/llcontrolgroupreader.h | 73 +- indra/llxml/llxmlnode.cpp | 148 +- indra/llxml/llxmlnode.h | 30 +- indra/lscript/lscript_execute.h | 2 + indra/newview/CMakeLists.txt | 194 +- indra/newview/app_settings/cmd_line.xml | 50 + indra/newview/app_settings/ignorable_dialogs.xml | 291 + indra/newview/app_settings/settings.xml | 8062 +++++++------------- indra/newview/app_settings/settings_files.xml | 61 +- indra/newview/app_settings/std_bump.ini | 30 +- indra/newview/character/avatar_lad.xml | 109 +- indra/newview/character/checkerboard.tga | Bin 0 -> 16428 bytes indra/newview/character/invisible_head.tga | Bin 0 -> 140793 bytes .../installers/windows/installer_template.nsi | 3 +- indra/newview/llagent.cpp | 1935 +---- indra/newview/llagent.h | 1668 ++-- indra/newview/llagentaccess.cpp | 52 +- indra/newview/llagentaccess.h | 32 +- indra/newview/llagentlanguage.h | 2 +- indra/newview/llagentpilot.cpp | 9 +- indra/newview/llagentpilot.h | 1 + indra/newview/llagentwearables.cpp | 1584 ++++ indra/newview/llagentwearables.h | 235 + indra/newview/llappviewer.cpp | 592 +- indra/newview/llappviewer.h | 23 +- indra/newview/llappviewermacosx.cpp | 49 +- indra/newview/llappviewerwin32.cpp | 63 +- indra/newview/llassetuploadresponders.cpp | 246 +- indra/newview/llavatariconctrl.cpp | 255 + indra/newview/llavatariconctrl.h | 89 + indra/newview/llavatarlist.cpp | 163 + indra/newview/llavatarlist.h | 63 + indra/newview/llavatarlistitem.cpp | 273 + indra/newview/llavatarlistitem.h | 102 + indra/newview/llavatarpropertiesprocessor.cpp | 441 ++ indra/newview/llavatarpropertiesprocessor.h | 206 + indra/newview/llbottomtray.cpp | 343 + indra/newview/llbottomtray.h | 91 + indra/newview/llcallingcard.cpp | 2 +- indra/newview/llchatbar.cpp | 147 +- indra/newview/llchatbar.h | 7 +- indra/newview/llchiclet.cpp | 725 ++ indra/newview/llchiclet.h | 286 + indra/newview/llcloud.h | 2 +- indra/newview/llcolorswatch.cpp | 154 +- indra/newview/llcolorswatch.h | 57 +- indra/newview/llcompilequeue.cpp | 255 +- indra/newview/llcompilequeue.h | 65 +- indra/newview/llcurrencyuimanager.cpp | 4 +- indra/newview/lldebugmessagebox.cpp | 131 +- indra/newview/lldebugmessagebox.h | 4 +- indra/newview/lldebugview.cpp | 63 +- indra/newview/lldebugview.h | 14 +- indra/newview/lldirpicker.cpp | 1 + indra/newview/lldrawable.h | 3 +- indra/newview/lldrawpoolavatar.cpp | 23 +- indra/newview/lldrawpoolbump.cpp | 8 +- indra/newview/lldrawpoolsky.cpp | 69 +- indra/newview/lldrawpooltree.cpp | 1 - indra/newview/lldrawpoolwater.cpp | 1 - indra/newview/lldynamictexture.cpp | 7 +- indra/newview/lleventnotifier.cpp | 5 +- indra/newview/llface.h | 1 - indra/newview/llfasttimerview.cpp | 1129 ++- indra/newview/llfasttimerview.h | 43 +- indra/newview/llfavoritesbar.cpp | 579 ++ indra/newview/llfavoritesbar.h | 89 + indra/newview/llfilepicker.cpp | 8 + indra/newview/llfirstuse.cpp | 66 +- indra/newview/llflexibleobject.h | 1 - indra/newview/llfloaterabout.cpp | 132 +- indra/newview/llfloaterabout.h | 14 +- indra/newview/llfloateranimpreview.cpp | 181 +- indra/newview/llfloateranimpreview.h | 8 +- indra/newview/llfloaterauction.cpp | 40 +- indra/newview/llfloaterauction.h | 14 +- indra/newview/llfloateravatarpicker.cpp | 78 +- indra/newview/llfloateravatarpicker.h | 5 +- indra/newview/llfloateravatartextures.cpp | 29 +- indra/newview/llfloateravatartextures.h | 1 + indra/newview/llfloaterbeacons.cpp | 8 +- indra/newview/llfloaterbeacons.h | 4 +- indra/newview/llfloaterbuildoptions.cpp | 48 +- indra/newview/llfloaterbuildoptions.h | 13 +- indra/newview/llfloaterbulkpermission.cpp | 19 +- indra/newview/llfloaterbulkpermission.h | 1 + indra/newview/llfloaterbump.cpp | 56 +- indra/newview/llfloaterbump.h | 17 +- indra/newview/llfloaterbuy.cpp | 23 +- indra/newview/llfloaterbuy.h | 2 +- indra/newview/llfloaterbuycontents.cpp | 15 +- indra/newview/llfloaterbuycontents.h | 2 +- indra/newview/llfloaterbuycurrency.cpp | 20 +- indra/newview/llfloaterbuyland.cpp | 41 +- indra/newview/llfloatercamera.cpp | 56 +- indra/newview/llfloatercamera.h | 2 +- indra/newview/llfloaterchat.cpp | 193 +- indra/newview/llfloaterchat.h | 24 +- indra/newview/llfloaterchatterbox.cpp | 92 +- indra/newview/llfloaterchatterbox.h | 101 +- indra/newview/llfloatercolorpicker.cpp | 254 +- indra/newview/llfloatercolorpicker.h | 10 +- indra/newview/llfloaterdaycycle.cpp | 14 +- indra/newview/llfloaterdaycycle.h | 2 +- indra/newview/llfloaterenvsettings.cpp | 72 +- indra/newview/llfloaterenvsettings.h | 4 +- indra/newview/llfloaterevent.cpp | 12 +- indra/newview/llfloaterevent.h | 2 +- indra/newview/llfloaterfonttest.cpp | 11 +- indra/newview/llfloaterfonttest.h | 7 +- indra/newview/llfloaterfriends.cpp | 241 +- indra/newview/llfloaterfriends.h | 16 +- indra/newview/llfloatergesture.cpp | 74 +- indra/newview/llfloatergesture.h | 2 +- indra/newview/llfloatergodtools.cpp | 194 +- indra/newview/llfloatergodtools.h | 25 +- indra/newview/llfloatergroupinvite.cpp | 41 +- indra/newview/llfloatergroupinvite.h | 5 +- indra/newview/llfloatergroups.cpp | 116 +- indra/newview/llfloatergroups.h | 11 +- indra/newview/llfloaterhandler.cpp | 2 +- indra/newview/llfloaterhardwaresettings.cpp | 23 +- indra/newview/llfloaterhardwaresettings.h | 10 +- indra/newview/llfloaterhud.cpp | 17 +- indra/newview/llfloaterimagepreview.cpp | 45 +- indra/newview/llfloaterinspect.cpp | 33 +- indra/newview/llfloaterjoystick.cpp | 60 +- indra/newview/llfloaterjoystick.h | 5 +- indra/newview/llfloaterlagmeter.cpp | 20 +- indra/newview/llfloaterlagmeter.h | 4 +- indra/newview/llfloaterland.cpp | 143 +- indra/newview/llfloaterland.h | 9 +- indra/newview/llfloaterlandholdings.cpp | 20 +- indra/newview/llfloatermap.cpp | 178 +- indra/newview/llfloatermap.h | 44 +- indra/newview/llfloatermemleak.cpp | 8 +- indra/newview/llfloaternamedesc.cpp | 8 +- indra/newview/llfloaternotificationsconsole.cpp | 28 +- indra/newview/llfloaternotificationsconsole.h | 1 + indra/newview/llfloateropenobject.cpp | 34 +- indra/newview/llfloateropenobject.h | 3 +- indra/newview/llfloaterparcel.cpp | 12 +- indra/newview/llfloaterparcel.h | 2 +- indra/newview/llfloaterperms.cpp | 7 +- indra/newview/llfloaterpostcard.cpp | 33 +- indra/newview/llfloaterpostcard.h | 6 +- indra/newview/llfloaterpostprocess.cpp | 33 +- indra/newview/llfloaterpostprocess.h | 4 +- indra/newview/llfloaterpreference.cpp | 1106 ++- indra/newview/llfloaterpreference.h | 127 +- indra/newview/llfloaterproperties.cpp | 94 +- indra/newview/llfloaterproperties.h | 12 +- indra/newview/llfloaterregioninfo.cpp | 105 +- indra/newview/llfloaterregioninfo.h | 14 +- indra/newview/llfloaterreporter.cpp | 254 +- indra/newview/llfloaterreporter.h | 8 +- indra/newview/llfloaterscriptdebug.cpp | 84 +- indra/newview/llfloaterscriptdebug.h | 10 +- indra/newview/llfloatersellland.cpp | 19 +- indra/newview/llfloatersellland.h | 3 +- indra/newview/llfloatersettingsdebug.cpp | 91 +- indra/newview/llfloatersettingsdebug.h | 10 +- indra/newview/llfloatersnapshot.cpp | 170 +- indra/newview/llfloatersnapshot.h | 27 +- indra/newview/llfloatertelehub.cpp | 10 +- indra/newview/llfloatertelehub.h | 2 +- indra/newview/llfloatertools.cpp | 528 +- indra/newview/llfloatertools.h | 50 +- indra/newview/llfloatertopobjects.cpp | 23 +- indra/newview/llfloatertos.cpp | 4 +- indra/newview/llfloateruipreview.cpp | 1550 ++++ indra/newview/llfloateruipreview.h | 216 + indra/newview/llfloaterurldisplay.cpp | 3 +- indra/newview/llfloaterurlentry.cpp | 34 +- indra/newview/llfloaterurlentry.h | 6 +- indra/newview/llfloatervoicedevicesettings.cpp | 27 +- indra/newview/llfloatervoicedevicesettings.h | 9 +- indra/newview/llfloaterwater.cpp | 61 +- indra/newview/llfloaterwater.h | 4 +- indra/newview/llfloaterwindlight.cpp | 66 +- indra/newview/llfloaterwindlight.h | 4 +- indra/newview/llfloaterworldmap.cpp | 226 +- indra/newview/llfloaterworldmap.h | 25 +- indra/newview/llfolderview.cpp | 501 +- indra/newview/llfolderview.h | 133 +- indra/newview/llgesturemgr.cpp | 7 +- indra/newview/llglsandbox.cpp | 124 +- indra/newview/llgroupactions.cpp | 141 + indra/newview/llgroupactions.h | 79 + indra/newview/llgrouplist.cpp | 70 + indra/newview/llgrouplist.h | 53 + indra/newview/llgroupmgr.cpp | 2 +- indra/newview/llhudeffect.h | 3 - indra/newview/llhudicon.h | 2 +- indra/newview/llhudmanager.cpp | 4 +- indra/newview/llhudmanager.h | 2 +- indra/newview/llhudobject.h | 2 +- indra/newview/llhudrender.cpp | 26 +- indra/newview/llhudrender.h | 2 + indra/newview/llhudtext.cpp | 52 +- indra/newview/llhudtext.h | 2 +- indra/newview/llhudview.cpp | 7 +- indra/newview/llimpanel.cpp | 165 +- indra/newview/llimpanel.h | 16 +- indra/newview/llimview.cpp | 378 +- indra/newview/llimview.h | 46 +- indra/newview/llinventorybridge.cpp | 1202 +-- indra/newview/llinventorybridge.h | 262 +- indra/newview/llinventorymodel.cpp | 105 +- indra/newview/llinventorymodel.h | 8 + indra/newview/lljoystickbutton.cpp | 187 +- indra/newview/lljoystickbutton.h | 74 +- indra/newview/lllandmarklist.cpp | 61 +- indra/newview/lllandmarklist.h | 13 +- indra/newview/lllocationhistory.cpp | 134 + indra/newview/lllocationhistory.h | 68 + indra/newview/lllocationinputctrl.cpp | 513 ++ indra/newview/lllocationinputctrl.h | 119 + indra/newview/lllogchat.cpp | 29 +- indra/newview/llloginhandler.cpp | 10 +- indra/newview/llmanip.cpp | 57 +- indra/newview/llmaniprotate.cpp | 38 +- indra/newview/llmanipscale.cpp | 6 +- indra/newview/llmaniptranslate.cpp | 8 +- indra/newview/llmemoryview.cpp | 204 +- indra/newview/llmemoryview.h | 22 +- indra/newview/llmenucommands.cpp | 47 +- indra/newview/llmenucommands.h | 6 - indra/newview/llmetricperformancetester.cpp | 258 + indra/newview/llmetricperformancetester.h | 159 + indra/newview/llmorphview.cpp | 14 +- indra/newview/llmorphview.h | 10 +- indra/newview/llmoveview.cpp | 43 +- indra/newview/llmoveview.h | 4 +- indra/newview/llmutelist.cpp | 33 +- indra/newview/llnamebox.cpp | 17 +- indra/newview/llnamebox.h | 17 +- indra/newview/llnameeditor.cpp | 62 +- indra/newview/llnameeditor.h | 26 +- indra/newview/llnamelistctrl.cpp | 328 +- indra/newview/llnamelistctrl.h | 76 +- indra/newview/llnavigationbar.cpp | 533 ++ indra/newview/llnavigationbar.h | 103 + indra/newview/llnetmap.cpp | 422 +- indra/newview/llnetmap.h | 106 +- indra/newview/lloutputmonitorctrl.cpp | 141 + indra/newview/lloutputmonitorctrl.h | 92 + indra/newview/lloverlaybar.cpp | 28 +- indra/newview/lloverlaybar.h | 1 - indra/newview/llpanelavatar.cpp | 2418 +----- indra/newview/llpanelavatar.h | 341 +- indra/newview/llpanelclassified.cpp | 74 +- indra/newview/llpanelcontents.cpp | 58 +- indra/newview/llpanelcontents.h | 2 +- indra/newview/llpanelface.cpp | 72 +- indra/newview/llpanelface.h | 23 +- indra/newview/llpanelgroup.cpp | 196 +- indra/newview/llpanelgroup.h | 15 +- indra/newview/llpanelgroupgeneral.cpp | 75 +- indra/newview/llpanelgroupgeneral.h | 2 +- indra/newview/llpanelgroupinvite.cpp | 33 +- indra/newview/llpanelgroupinvite.h | 2 +- indra/newview/llpanelgrouplandmoney.cpp | 87 +- indra/newview/llpanelgrouplandmoney.h | 2 +- indra/newview/llpanelgroupnotices.cpp | 93 +- indra/newview/llpanelgroupnotices.h | 4 +- indra/newview/llpanelgrouproles.cpp | 155 +- indra/newview/llpanelgrouproles.h | 24 +- indra/newview/llpanelland.cpp | 4 +- indra/newview/llpanelland.h | 2 +- indra/newview/llpanellandmarks.cpp | 252 + indra/newview/llpanellandmarks.h | 61 + indra/newview/llpanellandmedia.cpp | 6 +- indra/newview/llpanellogin.cpp | 98 +- indra/newview/llpanellogin.h | 6 +- indra/newview/llpanelobject.cpp | 79 +- indra/newview/llpanelobject.h | 14 +- indra/newview/llpanelpeople.cpp | 729 ++ indra/newview/llpanelpeople.h | 122 + indra/newview/llpanelpermissions.cpp | 77 +- indra/newview/llpanelpermissions.h | 14 +- indra/newview/llpanelpick.cpp | 597 +- indra/newview/llpanelpick.h | 106 +- indra/newview/llpanelpicks.cpp | 469 ++ indra/newview/llpanelpicks.h | 153 + indra/newview/llpanelplace.cpp | 280 +- indra/newview/llpanelplace.h | 13 +- indra/newview/llpanelplaceinfo.cpp | 382 + indra/newview/llpanelplaceinfo.h | 109 + indra/newview/llpanelplaces.cpp | 293 + indra/newview/llpanelplaces.h | 85 + indra/newview/llpanelplacestab.cpp | 98 + indra/newview/llpanelplacestab.h | 68 + indra/newview/llpanelprofileview.cpp | 112 + indra/newview/llpanelprofileview.h | 69 + indra/newview/llpanelteleporthistory.cpp | 218 + indra/newview/llpanelteleporthistory.h | 72 + indra/newview/llpanelvolume.cpp | 28 +- indra/newview/llpanelvolume.h | 10 +- indra/newview/llparcelselection.h | 3 +- indra/newview/llpreview.cpp | 304 +- indra/newview/llpreview.h | 58 +- indra/newview/llpreviewanim.cpp | 71 +- indra/newview/llpreviewanim.h | 11 +- indra/newview/llpreviewgesture.cpp | 241 +- indra/newview/llpreviewgesture.h | 31 +- indra/newview/llpreviewnotecard.cpp | 172 +- indra/newview/llpreviewnotecard.h | 21 +- indra/newview/llpreviewscript.cpp | 739 +- indra/newview/llpreviewscript.h | 96 +- indra/newview/llpreviewsound.cpp | 37 +- indra/newview/llpreviewsound.h | 7 +- indra/newview/llpreviewtexture.cpp | 182 +- indra/newview/llpreviewtexture.h | 25 +- indra/newview/llprogressview.cpp | 9 +- indra/newview/llprogressview.h | 2 +- indra/newview/llrecentpeople.cpp | 69 + indra/newview/llrecentpeople.h | 101 + indra/newview/llremoteparcelrequest.cpp | 118 +- indra/newview/llremoteparcelrequest.h | 64 +- indra/newview/llrootview.h | 55 + indra/newview/llsavedsettingsglue.cpp | 30 +- indra/newview/llsavedsettingsglue.h | 10 +- indra/newview/llselectmgr.cpp | 40 +- indra/newview/llselectmgr.h | 10 +- indra/newview/llsidetray.cpp | 746 ++ indra/newview/llsidetray.h | 240 + indra/newview/llslurl.cpp | 114 + indra/newview/llslurl.h | 85 + indra/newview/llspatialpartition.h | 5 +- indra/newview/llstartup.cpp | 327 +- indra/newview/llstartup.h | 4 + indra/newview/llstatusbar.cpp | 336 +- indra/newview/llstatusbar.h | 40 +- indra/newview/llstylemap.cpp | 6 +- indra/newview/llsurface.cpp | 2 +- indra/newview/llsurface.h | 1 - indra/newview/llsurfacepatch.h | 2 +- indra/newview/llteleporthistory.cpp | 198 + indra/newview/llteleporthistory.h | 225 + indra/newview/lltexglobalcolor.cpp | 150 + indra/newview/lltexglobalcolor.h | 86 + indra/newview/lltexlayer.cpp | 1505 ++-- indra/newview/lltexlayer.h | 576 +- indra/newview/lltexlayerparams.cpp | 541 ++ indra/newview/lltexlayerparams.h | 180 + indra/newview/lltexturecache.cpp | 2 +- indra/newview/lltexturectrl.cpp | 522 +- indra/newview/lltexturectrl.h | 72 +- indra/newview/lltexturefetch.cpp | 15 + indra/newview/lltexturefetch.h | 1 + indra/newview/lltextureview.cpp | 61 +- indra/newview/lltextureview.h | 4 +- indra/newview/lltool.cpp | 2 +- indra/newview/lltoolbar.cpp | 251 +- indra/newview/lltoolbar.h | 21 +- indra/newview/lltoolbrush.cpp | 2 +- indra/newview/lltoolcomp.cpp | 21 +- indra/newview/lltooldraganddrop.cpp | 41 +- indra/newview/lltoolface.cpp | 7 +- indra/newview/lltoolfocus.cpp | 2 +- indra/newview/lltoolgrab.cpp | 4 +- indra/newview/lltoolgrab.h | 2 +- indra/newview/lltoolgun.cpp | 5 +- indra/newview/lltoolindividual.cpp | 5 +- indra/newview/lltoolmgr.cpp | 94 +- indra/newview/lltoolmgr.h | 8 +- indra/newview/lltoolmorph.cpp | 7 +- indra/newview/lltoolobjpicker.cpp | 5 +- indra/newview/lltoolpie.cpp | 272 +- indra/newview/lltoolpie.h | 10 +- indra/newview/lltoolpipette.cpp | 24 +- indra/newview/lltoolpipette.h | 13 +- indra/newview/lltoolplacer.cpp | 100 +- indra/newview/lltoolplacer.h | 39 - indra/newview/lltoolselect.cpp | 8 +- indra/newview/lltoolselectland.cpp | 9 +- indra/newview/lltoolselectrect.cpp | 3 +- indra/newview/lltoolview.cpp | 4 +- indra/newview/lltracker.cpp | 23 +- indra/newview/lltracker.h | 2 +- indra/newview/lluploaddialog.cpp | 17 +- indra/newview/llurldispatcher.cpp | 109 +- indra/newview/llurldispatcher.h | 9 - indra/newview/llviewchildren.cpp | 8 +- indra/newview/llviewercamera.cpp | 122 +- indra/newview/llviewercamera.h | 1 + indra/newview/llviewercontrol.cpp | 387 +- indra/newview/llviewercontrol.h | 112 +- indra/newview/llviewerdisplay.cpp | 76 +- indra/newview/llviewerfloaterreg.cpp | 112 + indra/newview/llviewerfloaterreg.h | 43 + indra/newview/llviewergesture.cpp | 3 +- indra/newview/llviewerinventory.cpp | 199 +- indra/newview/llviewerinventory.h | 11 + indra/newview/llviewerjointattachment.h | 16 +- indra/newview/llviewerkeyboard.cpp | 29 +- indra/newview/llviewermedia.cpp | 2 +- indra/newview/llviewermenu.cpp | 5172 +++++++------ indra/newview/llviewermenu.h | 51 +- indra/newview/llviewermenufile.cpp | 106 +- indra/newview/llviewermessage.cpp | 262 +- indra/newview/llviewermessage.h | 3 +- indra/newview/llviewernetwork.cpp | 2 +- indra/newview/llviewerobject.cpp | 42 +- indra/newview/llviewerobject.h | 3 +- indra/newview/llviewerobjectlist.cpp | 26 +- indra/newview/llviewerobjectlist.h | 13 +- indra/newview/llviewerparcelmedia.cpp | 8 +- indra/newview/llviewerparcelmgr.cpp | 48 +- indra/newview/llviewerparcelmgr.h | 22 +- indra/newview/llviewerparceloverlay.cpp | 40 +- indra/newview/llviewerpartsim.h | 2 +- indra/newview/llviewerpartsource.h | 3 +- indra/newview/llviewerprecompiledheaders.h | 29 +- indra/newview/llviewerregion.cpp | 7 +- indra/newview/llviewerregion.h | 3 - indra/newview/llviewerstats.cpp | 114 +- indra/newview/llviewerstats.h | 23 +- indra/newview/llviewertexteditor.cpp | 187 +- indra/newview/llviewertexteditor.h | 28 +- indra/newview/llviewervisualparam.cpp | 14 +- indra/newview/llviewervisualparam.h | 2 +- indra/newview/llviewerwindow.cpp | 1377 ++-- indra/newview/llviewerwindow.h | 62 +- indra/newview/llvoavatar.cpp | 3389 +++----- indra/newview/llvoavatar.h | 1331 ++-- indra/newview/llvoavatardefines.cpp | 265 +- indra/newview/llvoavatardefines.h | 183 +- indra/newview/llvoavatarself.cpp | 2016 +++++ indra/newview/llvoavatarself.h | 321 + indra/newview/llvograss.cpp | 10 - indra/newview/llvoiceclient.cpp | 113 +- indra/newview/llvoiceclient.h | 4 +- indra/newview/llvoicevisualizer.cpp | 26 +- indra/newview/llvosky.cpp | 6 +- indra/newview/llvotree.cpp | 2 +- indra/newview/llvovolume.cpp | 76 +- indra/newview/llwearable.cpp | 248 +- indra/newview/llwearable.h | 96 +- indra/newview/llwearablelist.cpp | 107 +- indra/newview/llwearablelist.h | 30 +- indra/newview/llweb.cpp | 31 +- indra/newview/llweb.h | 7 - indra/newview/llwldaycycle.cpp | 3 +- indra/newview/llwldaycycle.h | 2 - indra/newview/llworld.cpp | 1 + indra/newview/llworld.h | 2 +- indra/newview/llworldmap.cpp | 20 +- indra/newview/llworldmap.h | 7 +- indra/newview/llworldmapview.cpp | 113 +- indra/newview/llworldmapview.h | 6 +- indra/newview/macview_Prefix.h | 2 - indra/newview/pipeline.cpp | 153 +- indra/newview/pipeline.h | 4 +- indra/newview/res/bitmap2.bmp | Bin 0 -> 25118 bytes indra/newview/res/install_icon.BMP | Bin 0 -> 262198 bytes indra/newview/res/loginbackground.bmp | Bin 0 -> 336054 bytes indra/newview/res/uninstall_icon.BMP | Bin 0 -> 262198 bytes indra/newview/skins/default/colors.xml | 3160 +++++++- .../skins/default/textures/jump_left_in.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_left_out.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_right_in.tga | Bin 0 -> 812 bytes .../skins/default/textures/jump_right_out.tga | Bin 0 -> 812 bytes .../skins/default/textures/menu_separator.png | Bin 0 -> 2831 bytes indra/newview/skins/default/textures/show_btn.tga | Bin 0 -> 3884 bytes .../skins/default/textures/show_btn_selected.tga | Bin 0 -> 3884 bytes indra/newview/skins/default/textures/textures.xml | 191 +- .../newview/skins/default/textures/transparent.j2c | Bin 0 -> 172 bytes .../skins/default/textures/voice_meter_dot.j2c | Bin 0 -> 499 bytes .../skins/default/textures/voice_meter_rings.j2c | Bin 0 -> 2518 bytes .../skins/default/xui/da/floater_about_land.xml | 438 +- .../default/xui/da/floater_animation_preview.xml | 161 +- .../skins/default/xui/da/floater_buy_land.xml | 72 +- .../skins/default/xui/da/floater_customize.xml | 512 +- .../default/xui/da/floater_hardware_settings.xml | 22 +- .../skins/default/xui/da/floater_image_preview.xml | 40 +- .../xui/da/floater_inventory_item_properties.xml | 8 +- .../default/xui/da/floater_preview_gesture.xml | 44 +- .../skins/default/xui/da/floater_report_abuse.xml | 191 +- .../skins/default/xui/da/floater_sell_land.xml | 20 +- .../default/xui/da/floater_settings_debug.xml | 8 +- .../skins/default/xui/da/floater_snapshot.xml | 154 +- .../newview/skins/default/xui/da/floater_tools.xml | 591 +- .../skins/default/xui/da/floater_world_map.xml | 88 +- indra/newview/skins/default/xui/da/panel_login.xml | 12 +- .../default/xui/da/panel_preferences_chat.xml | 12 +- .../default/xui/da/panel_preferences_general.xml | 147 +- .../default/xui/da/panel_preferences_graphics1.xml | 68 +- .../default/xui/de/floater_animation_preview.xml | 148 +- .../skins/default/xui/de/floater_buy_land.xml | 13 +- .../skins/default/xui/de/floater_god_tools.xml | 24 +- .../default/xui/de/floater_hardware_settings.xml | 20 +- .../skins/default/xui/de/floater_image_preview.xml | 40 +- .../xui/de/floater_inventory_item_properties.xml | 8 +- .../default/xui/de/floater_preview_gesture.xml | 8 +- .../skins/default/xui/de/floater_report_abuse.xml | 144 +- .../skins/default/xui/de/floater_sell_land.xml | 20 +- .../default/xui/de/floater_settings_debug.xml | 8 +- .../skins/default/xui/de/floater_sound_preview.xml | 16 +- indra/newview/skins/default/xui/de/floater_tos.xml | 8 +- .../skins/default/xui/de/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/de/panel_login.xml | 12 +- .../default/xui/de/panel_preferences_chat.xml | 12 +- .../default/xui/de/panel_preferences_graphics1.xml | 68 +- .../skins/default/xui/en/accordion_parent.xml | 7 + .../newview/skins/default/xui/en/floater_about.xml | 117 + .../skins/default/xui/en/floater_about_land.xml | 2139 ++++++ .../default/xui/en/floater_animation_preview.xml | 475 ++ .../skins/default/xui/en/floater_auction.xml | 61 + .../skins/default/xui/en/floater_avatar_picker.xml | 208 + .../default/xui/en/floater_avatar_textures.xml | 211 + .../skins/default/xui/en/floater_beacons.xml | 86 + .../skins/default/xui/en/floater_build_options.xml | 71 + .../skins/default/xui/en/floater_bulk_perms.xml | 337 + .../newview/skins/default/xui/en/floater_bumps.xml | 47 + .../skins/default/xui/en/floater_buy_contents.xml | 94 + .../skins/default/xui/en/floater_buy_currency.xml | 294 + .../skins/default/xui/en/floater_buy_land.xml | 696 ++ .../skins/default/xui/en/floater_buy_object.xml | 108 + .../skins/default/xui/en/floater_camera.xml | 69 + .../skins/default/xui/en/floater_choose_group.xml | 49 + .../skins/default/xui/en/floater_color_picker.xml | 228 + .../skins/default/xui/en/floater_critical.xml | 57 + .../skins/default/xui/en/floater_customize.xml | 3574 +++++++++ .../default/xui/en/floater_day_cycle_options.xml | 613 ++ .../default/xui/en/floater_device_settings.xml | 16 + .../skins/default/xui/en/floater_env_settings.xml | 174 + .../skins/default/xui/en/floater_font_test.xml | 336 + .../skins/default/xui/en/floater_gesture.xml | 91 + .../skins/default/xui/en/floater_god_tools.xml | 685 ++ .../default/xui/en/floater_hardware_settings.xml | 158 + indra/newview/skins/default/xui/en/floater_hud.xml | 20 + indra/newview/skins/default/xui/en/floater_im.xml | 78 + .../skins/default/xui/en/floater_image_preview.xml | 125 + .../skins/default/xui/en/floater_incoming_call.xml | 67 + .../skins/default/xui/en/floater_inspect.xml | 64 + .../skins/default/xui/en/floater_inventory.xml | 423 + .../xui/en/floater_inventory_item_properties.xml | 395 + .../xui/en/floater_inventory_view_finder.xml | 281 + .../skins/default/xui/en/floater_joystick.xml | 859 +++ .../skins/default/xui/en/floater_lagmeter.xml | 337 + .../skins/default/xui/en/floater_land_holdings.xml | 164 + .../default/xui/en/floater_live_lsleditor.xml | 71 + .../skins/default/xui/en/floater_lsl_guide.xml | 62 + indra/newview/skins/default/xui/en/floater_map.xml | 172 + .../skins/default/xui/en/floater_media_browser.xml | 144 + .../skins/default/xui/en/floater_mem_leaking.xml | 110 + .../skins/default/xui/en/floater_moveview.xml | 127 + .../skins/default/xui/en/floater_mute_object.xml | 55 + .../skins/default/xui/en/floater_my_friends.xml | 41 + .../skins/default/xui/en/floater_nearby_chat.xml | 32 + .../skins/default/xui/en/floater_notification.xml | 36 + .../xui/en/floater_notifications_console.xml | 36 + .../skins/default/xui/en/floater_openobject.xml | 57 + indra/newview/skins/default/xui/en/floater_pay.xml | 129 + .../skins/default/xui/en/floater_pay_object.xml | 174 + .../skins/default/xui/en/floater_perm_prefs.xml | 106 + .../skins/default/xui/en/floater_post_process.xml | 420 + .../skins/default/xui/en/floater_postcard.xml | 156 + .../skins/default/xui/en/floater_preferences.xml | 153 + .../default/xui/en/floater_preview_animation.xml | 57 + .../default/xui/en/floater_preview_classified.xml | 22 + .../skins/default/xui/en/floater_preview_event.xml | 22 + .../default/xui/en/floater_preview_gesture.xml | 351 + .../default/xui/en/floater_preview_notecard.xml | 105 + .../skins/default/xui/en/floater_preview_sound.xml | 61 + .../default/xui/en/floater_preview_texture.xml | 77 + .../skins/default/xui/en/floater_region_info.xml | 18 + .../skins/default/xui/en/floater_report_abuse.xml | 454 ++ .../skins/default/xui/en/floater_script_debug.xml | 19 + .../default/xui/en/floater_script_debug_panel.xml | 20 + .../default/xui/en/floater_script_preview.xml | 62 + .../skins/default/xui/en/floater_script_queue.xml | 49 + .../skins/default/xui/en/floater_script_search.xml | 90 + .../skins/default/xui/en/floater_select_key.xml | 32 + .../skins/default/xui/en/floater_sell_land.xml | 315 + .../default/xui/en/floater_settings_debug.xml | 108 + .../skins/default/xui/en/floater_snapshot.xml | 370 + .../skins/default/xui/en/floater_sound_preview.xml | 75 + .../skins/default/xui/en/floater_statistics.xml | 10 + .../newview/skins/default/xui/en/floater_stats.xml | 30 + .../skins/default/xui/en/floater_telehub.xml | 132 + .../skins/default/xui/en/floater_test_button.xml | 111 + .../skins/default/xui/en/floater_test_checkbox.xml | 83 + .../skins/default/xui/en/floater_test_combobox.xml | 143 + .../skins/default/xui/en/floater_test_layout.xml | 88 + .../default/xui/en/floater_test_radiogroup.xml | 81 + .../skins/default/xui/en/floater_test_slider.xml | 77 + .../skins/default/xui/en/floater_test_spinner.xml | 93 + .../skins/default/xui/en/floater_test_textbox.xml | 129 + .../skins/default/xui/en/floater_test_widgets.xml | 342 + .../skins/default/xui/en/floater_texture_ctrl.xml | 149 + .../newview/skins/default/xui/en/floater_tools.xml | 2866 +++++++ .../skins/default/xui/en/floater_top_objects.xml | 224 + indra/newview/skins/default/xui/en/floater_tos.xml | 79 + .../skins/default/xui/en/floater_ui_preview.xml | 381 + .../skins/default/xui/en/floater_url_entry.xml | 69 + .../newview/skins/default/xui/en/floater_water.xml | 656 ++ .../default/xui/en/floater_wearable_save_as.xml | 58 + .../default/xui/en/floater_windlight_options.xml | 1487 ++++ .../skins/default/xui/en/floater_world_map.xml | 540 ++ indra/newview/skins/default/xui/en/fonts.xml | 108 + .../skins/default/xui/en/menu_avatar_icon.xml | 43 + .../skins/default/xui/en/menu_favorites.xml | 39 + .../skins/default/xui/en/menu_group_plus.xml | 11 + .../skins/default/xui/en/menu_inventory.xml | 518 ++ indra/newview/skins/default/xui/en/menu_login.xml | 105 + .../newview/skins/default/xui/en/menu_mini_map.xml | 56 + indra/newview/skins/default/xui/en/menu_navbar.xml | 85 + .../skins/default/xui/en/menu_nearby_chat.xml | 43 + indra/newview/skins/default/xui/en/menu_slurl.xml | 37 + indra/newview/skins/default/xui/en/menu_viewer.xml | 3545 +++++++++ indra/newview/skins/default/xui/en/mime_types.xml | 456 ++ .../newview/skins/default/xui/en/notifications.xml | 6470 ++++++++++++++++ .../skins/default/xui/en/panel_audio_device.xml | 153 + .../default/xui/en/panel_avatar_list_item.xml | 65 + indra/newview/skins/default/xui/en/panel_bars.xml | 69 + .../skins/default/xui/en/panel_bottomtray.xml | 41 + .../skins/default/xui/en/panel_classified.xml | 135 + .../skins/default/xui/en/panel_edit_pick.xml | 147 + .../skins/default/xui/en/panel_edit_profile.xml | 243 + .../newview/skins/default/xui/en/panel_friends.xml | 124 + .../skins/default/xui/en/panel_group_general.xml | 316 + .../skins/default/xui/en/panel_group_invite.xml | 102 + .../default/xui/en/panel_group_land_money.xml | 373 + .../skins/default/xui/en/panel_group_notices.xml | 378 + .../skins/default/xui/en/panel_group_roles.xml | 743 ++ .../newview/skins/default/xui/en/panel_groups.xml | 111 + .../skins/default/xui/en/panel_landmark_info.xml | 258 + .../skins/default/xui/en/panel_landmarks.xml | 10 + indra/newview/skins/default/xui/en/panel_login.xml | 221 + .../skins/default/xui/en/panel_navigation_bar.xml | 142 + .../skins/default/xui/en/panel_nearby_chat.xml | 27 + indra/newview/skins/default/xui/en/panel_notes.xml | 202 + .../default/xui/en/panel_notifications_channel.xml | 77 + .../newview/skins/default/xui/en/panel_people.xml | 443 ++ .../skins/default/xui/en/panel_pick_info.xml | 184 + indra/newview/skins/default/xui/en/panel_picks.xml | 173 + .../newview/skins/default/xui/en/panel_places.xml | 86 + .../default/xui/en/panel_preferences_chat.xml | 370 + .../default/xui/en/panel_preferences_general.xml | 427 ++ .../default/xui/en/panel_preferences_graphics1.xml | 915 +++ .../newview/skins/default/xui/en/panel_profile.xml | 574 ++ .../skins/default/xui/en/panel_profile_view.xml | 64 + .../skins/default/xui/en/panel_progress.xml | 133 + .../skins/default/xui/en/panel_region_covenant.xml | 328 + .../skins/default/xui/en/panel_region_debug.xml | 272 + .../skins/default/xui/en/panel_region_estate.xml | 519 ++ .../skins/default/xui/en/panel_region_general.xml | 350 + .../skins/default/xui/en/panel_region_terrain.xml | 239 + .../skins/default/xui/en/panel_region_texture.xml | 340 + .../skins/default/xui/en/panel_script_ed.xml | 190 + .../skins/default/xui/en/panel_scrolling_param.xml | 92 + .../skins/default/xui/en/panel_side_tray.xml | 95 + .../default/xui/en/panel_side_tray_tab_caption.xml | 15 + .../skins/default/xui/en/panel_status_bar.xml | 252 + .../default/xui/en/panel_teleport_history.xml | 12 + .../skins/default/xui/en/panel_world_map.xml | 128 + .../newview/skins/default/xui/en/role_actions.xml | 187 + indra/newview/skins/default/xui/en/strings.xml | 788 ++ .../skins/default/xui/en/teleport_strings.xml | 90 + .../skins/default/xui/en/widgets/button.xml | 17 + .../skins/default/xui/en/widgets/check_box.xml | 18 + .../skins/default/xui/en/widgets/color_swatch.xml | 10 + .../skins/default/xui/en/widgets/combo_box.xml | 22 + .../skins/default/xui/en/widgets/drop_down.xml | 20 + .../skins/default/xui/en/widgets/flyout_button.xml | 13 + .../newview/skins/default/xui/en/widgets/icon.xml | 7 + .../skins/default/xui/en/widgets/line_editor.xml | 18 + .../default/xui/en/widgets/location_input.xml | 66 + .../newview/skins/default/xui/en/widgets/menu.xml | 6 + .../default/xui/en/widgets/menu_item_call.xml | 6 + .../default/xui/en/widgets/menu_item_check.xml | 6 + .../default/xui/en/widgets/menu_item_separator.xml | 6 + .../skins/default/xui/en/widgets/multi_slider.xml | 6 + .../default/xui/en/widgets/multi_slider_bar.xml | 10 + .../skins/default/xui/en/widgets/name_editor.xml | 2 + .../newview/skins/default/xui/en/widgets/panel.xml | 5 + .../skins/default/xui/en/widgets/progress_bar.xml | 21 + .../skins/default/xui/en/widgets/radio_group.xml | 6 + .../skins/default/xui/en/widgets/radio_item.xml | 9 + .../skins/default/xui/en/widgets/scroll_bar.xml | 19 + .../default/xui/en/widgets/scroll_container.xml | 3 + .../skins/default/xui/en/widgets/scroll_list.xml | 16 + .../skins/default/xui/en/widgets/search_editor.xml | 6 + .../skins/default/xui/en/widgets/side_tray.xml | 8 + .../default/xui/en/widgets/simple_text_editor.xml | 11 + .../skins/default/xui/en/widgets/slider.xml | 16 + .../skins/default/xui/en/widgets/slider_bar.xml | 7 + .../skins/default/xui/en/widgets/spinner.xml | 5 + .../skins/default/xui/en/widgets/tab_container.xml | 9 + .../newview/skins/default/xui/en/widgets/text.xml | 16 + .../skins/default/xui/en/widgets/text_editor.xml | 19 + .../default/xui/en/widgets/texture_picker.xml | 9 + .../skins/default/xui/en/widgets/view_border.xml | 8 + .../skins/default/xui/en/widgets/web_browser.xml | 2 + indra/newview/skins/default/xui/en/xui_version.xml | 4 + .../default/xui/es/floater_animation_preview.xml | 173 +- .../skins/default/xui/es/floater_buy_land.xml | 23 +- .../skins/default/xui/es/floater_customize.xml | 14 +- .../skins/default/xui/es/floater_god_tools.xml | 24 +- .../default/xui/es/floater_hardware_settings.xml | 24 +- .../skins/default/xui/es/floater_image_preview.xml | 50 +- .../xui/es/floater_inventory_item_properties.xml | 16 +- .../default/xui/es/floater_preview_gesture.xml | 24 +- .../skins/default/xui/es/floater_report_abuse.xml | 148 +- .../skins/default/xui/es/floater_sell_land.xml | 20 +- .../default/xui/es/floater_settings_debug.xml | 10 +- .../skins/default/xui/es/floater_snapshot.xml | 128 +- .../skins/default/xui/es/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/es/panel_login.xml | 12 +- .../default/xui/es/panel_preferences_chat.xml | 17 +- .../default/xui/es/panel_preferences_graphics1.xml | 112 +- .../default/xui/fr/floater_animation_preview.xml | 148 +- .../skins/default/xui/fr/floater_auction.xml | 8 +- .../skins/default/xui/fr/floater_buy_land.xml | 13 +- .../skins/default/xui/fr/floater_god_tools.xml | 24 +- .../default/xui/fr/floater_hardware_settings.xml | 20 +- .../skins/default/xui/fr/floater_image_preview.xml | 40 +- .../xui/fr/floater_inventory_item_properties.xml | 8 +- .../default/xui/fr/floater_preview_gesture.xml | 9 +- .../skins/default/xui/fr/floater_sell_land.xml | 20 +- .../default/xui/fr/floater_settings_debug.xml | 8 +- .../skins/default/xui/fr/floater_snapshot.xml | 120 +- .../skins/default/xui/fr/floater_sound_preview.xml | 16 +- .../newview/skins/default/xui/fr/floater_tools.xml | 246 +- indra/newview/skins/default/xui/fr/floater_tos.xml | 8 +- .../skins/default/xui/fr/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/fr/panel_login.xml | 16 +- .../default/xui/fr/panel_preferences_chat.xml | 12 +- .../default/xui/fr/panel_preferences_graphics1.xml | 68 +- .../default/xui/it/floater_animation_preview.xml | 167 +- .../skins/default/xui/it/floater_buy_land.xml | 23 +- .../skins/default/xui/it/floater_customize.xml | 8 +- .../default/xui/it/floater_hardware_settings.xml | 26 +- .../skins/default/xui/it/floater_image_preview.xml | 45 +- .../xui/it/floater_inventory_item_properties.xml | 16 +- .../default/xui/it/floater_preview_gesture.xml | 17 +- .../skins/default/xui/it/floater_report_abuse.xml | 149 +- .../skins/default/xui/it/floater_sell_land.xml | 20 +- .../default/xui/it/floater_settings_debug.xml | 10 +- .../skins/default/xui/it/floater_snapshot.xml | 138 +- .../skins/default/xui/it/floater_world_map.xml | 8 +- .../default/xui/it/panel_preferences_chat.xml | 14 +- .../default/xui/it/panel_preferences_graphics1.xml | 96 +- .../default/xui/ja/floater_animation_preview.xml | 148 +- .../skins/default/xui/ja/floater_buy_land.xml | 13 +- .../default/xui/ja/floater_hardware_settings.xml | 20 +- .../skins/default/xui/ja/floater_image_preview.xml | 40 +- .../xui/ja/floater_inventory_item_properties.xml | 8 +- .../default/xui/ja/floater_preview_gesture.xml | 8 +- .../skins/default/xui/ja/floater_sell_land.xml | 12 +- .../default/xui/ja/floater_settings_debug.xml | 8 +- .../skins/default/xui/ja/floater_snapshot.xml | 120 +- .../skins/default/xui/ja/floater_sound_preview.xml | 16 +- .../newview/skins/default/xui/ja/floater_tools.xml | 246 +- indra/newview/skins/default/xui/ja/floater_tos.xml | 8 +- .../skins/default/xui/ja/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/ja/panel_login.xml | 14 +- .../default/xui/ja/panel_preferences_chat.xml | 12 +- .../default/xui/ja/panel_preferences_graphics1.xml | 68 +- .../skins/default/xui/nl/floater_buy_land.xml | 15 +- .../skins/default/xui/nl/floater_customize.xml | 32 +- .../skins/default/xui/nl/floater_report_abuse.xml | 158 +- .../skins/default/xui/nl/floater_sell_land.xml | 20 +- .../skins/default/xui/nl/floater_snapshot.xml | 126 +- .../skins/default/xui/nl/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/nl/panel_login.xml | 14 +- .../skins/default/xui/pl/floater_buy_land.xml | 12 +- .../skins/default/xui/pl/floater_god_tools.xml | 24 +- .../default/xui/pl/floater_hardware_settings.xml | 20 +- .../skins/default/xui/pl/floater_image_preview.xml | 40 +- .../xui/pl/floater_inventory_item_properties.xml | 8 +- .../default/xui/pl/floater_preview_gesture.xml | 8 +- .../skins/default/xui/pl/floater_report_abuse.xml | 144 +- .../skins/default/xui/pl/floater_sell_land.xml | 20 +- .../default/xui/pl/floater_settings_debug.xml | 8 +- .../skins/default/xui/pl/floater_snapshot.xml | 120 +- .../skins/default/xui/pl/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/pl/panel_login.xml | 14 +- .../default/xui/pl/panel_preferences_chat.xml | 12 +- .../default/xui/pl/panel_preferences_graphics1.xml | 68 +- .../default/xui/pt/floater_animation_preview.xml | 173 +- .../skins/default/xui/pt/floater_buy_land.xml | 31 +- .../skins/default/xui/pt/floater_customize.xml | 8 +- .../skins/default/xui/pt/floater_god_tools.xml | 24 +- .../default/xui/pt/floater_hardware_settings.xml | 20 +- .../skins/default/xui/pt/floater_image_preview.xml | 45 +- .../xui/pt/floater_inventory_item_properties.xml | 10 +- .../default/xui/pt/floater_preview_gesture.xml | 32 +- .../skins/default/xui/pt/floater_report_abuse.xml | 148 +- .../skins/default/xui/pt/floater_sell_land.xml | 20 +- .../default/xui/pt/floater_settings_debug.xml | 8 +- .../skins/default/xui/pt/floater_snapshot.xml | 132 +- .../skins/default/xui/pt/floater_world_map.xml | 8 +- indra/newview/skins/default/xui/pt/panel_login.xml | 16 +- .../default/xui/pt/panel_preferences_chat.xml | 14 +- .../default/xui/pt/panel_preferences_graphics1.xml | 88 +- indra/newview/skins/paths.xml | 2 +- indra/newview/tests/llagentaccess_test.cpp | 137 +- indra/newview/viewer_manifest.py | 21 +- indra/test/CMakeLists.txt | 5 + indra/test/lldoubledispatch_tut.cpp | 245 + indra/test/llhttpdate_tut.cpp | 3 + indra/test/llpermissions_tut.cpp | 11 +- indra/test/llsaleinfo_tut.cpp | 15 +- indra/test/llscriptresource_tut.cpp | 7 +- indra/test/lltimestampcache_tut.cpp | 7 +- indra/test/lltranscode_tut.cpp | 7 +- indra/test/test.h | 5 +- indra/win_crash_logger/CMakeLists.txt | 1 + install.xml | 19 + 1135 files changed, 121922 insertions(+), 53159 deletions(-) create mode 100644 indra/integration_tests/CMakeLists.txt create mode 100644 indra/integration_tests/llui_libtest/CMakeLists.txt create mode 100644 indra/integration_tests/llui_libtest/llui_libtest.cpp create mode 100644 indra/integration_tests/llui_libtest/llui_libtest.h create mode 100644 indra/integration_tests/llui_libtest/llwidgetreg.cpp create mode 100644 indra/integration_tests/llui_libtest/llwidgetreg.h create mode 100644 indra/llcommon/llallocator.cpp create mode 100644 indra/llcommon/llallocator.h create mode 100644 indra/llcommon/llallocator_heap_profile.cpp create mode 100644 indra/llcommon/llallocator_heap_profile.h create mode 100644 indra/llcommon/lldeleteutils.h create mode 100644 indra/llcommon/lldictionary.h create mode 100755 indra/llcommon/lldoubledispatch.h create mode 100644 indra/llcommon/llinstancetracker.h create mode 100644 indra/llcommon/llmemtype.cpp create mode 100644 indra/llcommon/llpointer.h create mode 100644 indra/llcommon/llptrto.cpp create mode 100644 indra/llcommon/llptrto.h create mode 100644 indra/llcommon/llrefcount.cpp create mode 100644 indra/llcommon/llrefcount.h create mode 100644 indra/llcommon/llsafehandle.h create mode 100644 indra/llcommon/llsingleton.h create mode 100644 indra/llcommon/llstacktrace.cpp create mode 100644 indra/llcommon/llstacktrace.h create mode 100644 indra/llcommon/lltreeiterators.h create mode 100644 indra/llcommon/tests/llallocator_heap_profile_test.cpp create mode 100644 indra/llcommon/tests/llallocator_test.cpp create mode 100644 indra/llcommon/tests/llmemtype_test.cpp create mode 100644 indra/llprimitive/tests/llmessagesystem_stub.cpp create mode 100644 indra/llprimitive/tests/llprimitive_test.cpp create mode 100644 indra/llui/llconsole.cpp create mode 100644 indra/llui/llconsole.h create mode 100644 indra/llui/llcontainerview.cpp create mode 100644 indra/llui/llcontainerview.h create mode 100644 indra/llui/llf32uictrl.cpp create mode 100644 indra/llui/llf32uictrl.h create mode 100644 indra/llui/llfloaterreg.cpp create mode 100644 indra/llui/llfloaterreg.h create mode 100644 indra/llui/llflyoutbutton.cpp create mode 100644 indra/llui/llflyoutbutton.h create mode 100644 indra/llui/lllayoutstack.cpp create mode 100644 indra/llui/lllayoutstack.h create mode 100644 indra/llui/lllazyvalue.h create mode 100644 indra/llui/llmultifloater.cpp create mode 100644 indra/llui/llmultifloater.h create mode 100644 indra/llui/llscrolllistcell.cpp create mode 100644 indra/llui/llscrolllistcell.h create mode 100644 indra/llui/llscrolllistcolumn.cpp create mode 100644 indra/llui/llscrolllistcolumn.h create mode 100644 indra/llui/llscrolllistitem.cpp create mode 100644 indra/llui/llscrolllistitem.h create mode 100644 indra/llui/llsdparam.cpp create mode 100644 indra/llui/llsdparam.h create mode 100644 indra/llui/llsearcheditor.cpp create mode 100644 indra/llui/llsearcheditor.h create mode 100644 indra/llui/llstatbar.cpp create mode 100644 indra/llui/llstatbar.h create mode 100644 indra/llui/llstatgraph.cpp create mode 100644 indra/llui/llstatgraph.h create mode 100644 indra/llui/llstatview.cpp create mode 100644 indra/llui/llstatview.h create mode 100644 indra/llui/lluicolortable.cpp create mode 100644 indra/llui/lluicolortable.h create mode 100644 indra/llui/lluiimage.cpp create mode 100644 indra/llui/lluiimage.h create mode 100644 indra/llui/llviewmodel.cpp create mode 100644 indra/llui/llviewmodel.h create mode 100644 indra/llwindow/llwindowcallbacks.cpp create mode 100644 indra/llwindow/llwindowcallbacks.h create mode 100644 indra/newview/app_settings/ignorable_dialogs.xml create mode 100644 indra/newview/character/checkerboard.tga create mode 100755 indra/newview/character/invisible_head.tga create mode 100644 indra/newview/llagentwearables.cpp create mode 100644 indra/newview/llagentwearables.h create mode 100644 indra/newview/llavatariconctrl.cpp create mode 100644 indra/newview/llavatariconctrl.h create mode 100644 indra/newview/llavatarlist.cpp create mode 100644 indra/newview/llavatarlist.h create mode 100644 indra/newview/llavatarlistitem.cpp create mode 100644 indra/newview/llavatarlistitem.h create mode 100644 indra/newview/llavatarpropertiesprocessor.cpp create mode 100644 indra/newview/llavatarpropertiesprocessor.h create mode 100644 indra/newview/llbottomtray.cpp create mode 100644 indra/newview/llbottomtray.h create mode 100644 indra/newview/llchiclet.cpp create mode 100644 indra/newview/llchiclet.h create mode 100644 indra/newview/llfavoritesbar.cpp create mode 100644 indra/newview/llfavoritesbar.h create mode 100644 indra/newview/llfloateruipreview.cpp create mode 100644 indra/newview/llfloateruipreview.h create mode 100644 indra/newview/llgroupactions.cpp create mode 100644 indra/newview/llgroupactions.h create mode 100644 indra/newview/llgrouplist.cpp create mode 100644 indra/newview/llgrouplist.h create mode 100644 indra/newview/lllocationhistory.cpp create mode 100644 indra/newview/lllocationhistory.h create mode 100644 indra/newview/lllocationinputctrl.cpp create mode 100644 indra/newview/lllocationinputctrl.h create mode 100644 indra/newview/llmetricperformancetester.cpp create mode 100644 indra/newview/llmetricperformancetester.h create mode 100644 indra/newview/llnavigationbar.cpp create mode 100644 indra/newview/llnavigationbar.h create mode 100644 indra/newview/lloutputmonitorctrl.cpp create mode 100644 indra/newview/lloutputmonitorctrl.h create mode 100644 indra/newview/llpanellandmarks.cpp create mode 100644 indra/newview/llpanellandmarks.h create mode 100644 indra/newview/llpanelpeople.cpp create mode 100644 indra/newview/llpanelpeople.h create mode 100644 indra/newview/llpanelpicks.cpp create mode 100644 indra/newview/llpanelpicks.h create mode 100644 indra/newview/llpanelplaceinfo.cpp create mode 100644 indra/newview/llpanelplaceinfo.h create mode 100644 indra/newview/llpanelplaces.cpp create mode 100644 indra/newview/llpanelplaces.h create mode 100644 indra/newview/llpanelplacestab.cpp create mode 100644 indra/newview/llpanelplacestab.h create mode 100644 indra/newview/llpanelprofileview.cpp create mode 100644 indra/newview/llpanelprofileview.h create mode 100644 indra/newview/llpanelteleporthistory.cpp create mode 100644 indra/newview/llpanelteleporthistory.h create mode 100644 indra/newview/llrecentpeople.cpp create mode 100644 indra/newview/llrecentpeople.h create mode 100644 indra/newview/llrootview.h create mode 100644 indra/newview/llsidetray.cpp create mode 100644 indra/newview/llsidetray.h create mode 100644 indra/newview/llslurl.cpp create mode 100644 indra/newview/llslurl.h create mode 100644 indra/newview/llteleporthistory.cpp create mode 100644 indra/newview/llteleporthistory.h create mode 100644 indra/newview/lltexglobalcolor.cpp create mode 100644 indra/newview/lltexglobalcolor.h create mode 100644 indra/newview/lltexlayerparams.cpp create mode 100644 indra/newview/lltexlayerparams.h create mode 100644 indra/newview/llviewerfloaterreg.cpp create mode 100644 indra/newview/llviewerfloaterreg.h create mode 100644 indra/newview/llvoavatarself.cpp create mode 100644 indra/newview/llvoavatarself.h create mode 100644 indra/newview/res/bitmap2.bmp create mode 100644 indra/newview/res/install_icon.BMP create mode 100644 indra/newview/res/loginbackground.bmp create mode 100644 indra/newview/res/uninstall_icon.BMP create mode 100644 indra/newview/skins/default/textures/jump_left_in.tga create mode 100644 indra/newview/skins/default/textures/jump_left_out.tga create mode 100644 indra/newview/skins/default/textures/jump_right_in.tga create mode 100644 indra/newview/skins/default/textures/jump_right_out.tga create mode 100644 indra/newview/skins/default/textures/menu_separator.png create mode 100644 indra/newview/skins/default/textures/show_btn.tga create mode 100644 indra/newview/skins/default/textures/show_btn_selected.tga create mode 100644 indra/newview/skins/default/textures/transparent.j2c create mode 100644 indra/newview/skins/default/textures/voice_meter_dot.j2c create mode 100644 indra/newview/skins/default/textures/voice_meter_rings.j2c create mode 100644 indra/newview/skins/default/xui/en/accordion_parent.xml create mode 100644 indra/newview/skins/default/xui/en/floater_about.xml create mode 100644 indra/newview/skins/default/xui/en/floater_about_land.xml create mode 100644 indra/newview/skins/default/xui/en/floater_animation_preview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_auction.xml create mode 100644 indra/newview/skins/default/xui/en/floater_avatar_picker.xml create mode 100644 indra/newview/skins/default/xui/en/floater_avatar_textures.xml create mode 100644 indra/newview/skins/default/xui/en/floater_beacons.xml create mode 100644 indra/newview/skins/default/xui/en/floater_build_options.xml create mode 100644 indra/newview/skins/default/xui/en/floater_bulk_perms.xml create mode 100644 indra/newview/skins/default/xui/en/floater_bumps.xml create mode 100644 indra/newview/skins/default/xui/en/floater_buy_contents.xml create mode 100644 indra/newview/skins/default/xui/en/floater_buy_currency.xml create mode 100644 indra/newview/skins/default/xui/en/floater_buy_land.xml create mode 100644 indra/newview/skins/default/xui/en/floater_buy_object.xml create mode 100644 indra/newview/skins/default/xui/en/floater_camera.xml create mode 100644 indra/newview/skins/default/xui/en/floater_choose_group.xml create mode 100644 indra/newview/skins/default/xui/en/floater_color_picker.xml create mode 100644 indra/newview/skins/default/xui/en/floater_critical.xml create mode 100644 indra/newview/skins/default/xui/en/floater_customize.xml create mode 100644 indra/newview/skins/default/xui/en/floater_day_cycle_options.xml create mode 100644 indra/newview/skins/default/xui/en/floater_device_settings.xml create mode 100644 indra/newview/skins/default/xui/en/floater_env_settings.xml create mode 100644 indra/newview/skins/default/xui/en/floater_font_test.xml create mode 100644 indra/newview/skins/default/xui/en/floater_gesture.xml create mode 100644 indra/newview/skins/default/xui/en/floater_god_tools.xml create mode 100644 indra/newview/skins/default/xui/en/floater_hardware_settings.xml create mode 100644 indra/newview/skins/default/xui/en/floater_hud.xml create mode 100644 indra/newview/skins/default/xui/en/floater_im.xml create mode 100644 indra/newview/skins/default/xui/en/floater_image_preview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_incoming_call.xml create mode 100644 indra/newview/skins/default/xui/en/floater_inspect.xml create mode 100644 indra/newview/skins/default/xui/en/floater_inventory.xml create mode 100644 indra/newview/skins/default/xui/en/floater_inventory_item_properties.xml create mode 100644 indra/newview/skins/default/xui/en/floater_inventory_view_finder.xml create mode 100644 indra/newview/skins/default/xui/en/floater_joystick.xml create mode 100644 indra/newview/skins/default/xui/en/floater_lagmeter.xml create mode 100644 indra/newview/skins/default/xui/en/floater_land_holdings.xml create mode 100644 indra/newview/skins/default/xui/en/floater_live_lsleditor.xml create mode 100644 indra/newview/skins/default/xui/en/floater_lsl_guide.xml create mode 100644 indra/newview/skins/default/xui/en/floater_map.xml create mode 100644 indra/newview/skins/default/xui/en/floater_media_browser.xml create mode 100644 indra/newview/skins/default/xui/en/floater_mem_leaking.xml create mode 100644 indra/newview/skins/default/xui/en/floater_moveview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_mute_object.xml create mode 100644 indra/newview/skins/default/xui/en/floater_my_friends.xml create mode 100644 indra/newview/skins/default/xui/en/floater_nearby_chat.xml create mode 100644 indra/newview/skins/default/xui/en/floater_notification.xml create mode 100644 indra/newview/skins/default/xui/en/floater_notifications_console.xml create mode 100644 indra/newview/skins/default/xui/en/floater_openobject.xml create mode 100644 indra/newview/skins/default/xui/en/floater_pay.xml create mode 100644 indra/newview/skins/default/xui/en/floater_pay_object.xml create mode 100644 indra/newview/skins/default/xui/en/floater_perm_prefs.xml create mode 100644 indra/newview/skins/default/xui/en/floater_post_process.xml create mode 100644 indra/newview/skins/default/xui/en/floater_postcard.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preferences.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_animation.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_classified.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_event.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_gesture.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_notecard.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_sound.xml create mode 100644 indra/newview/skins/default/xui/en/floater_preview_texture.xml create mode 100644 indra/newview/skins/default/xui/en/floater_region_info.xml create mode 100644 indra/newview/skins/default/xui/en/floater_report_abuse.xml create mode 100644 indra/newview/skins/default/xui/en/floater_script_debug.xml create mode 100644 indra/newview/skins/default/xui/en/floater_script_debug_panel.xml create mode 100644 indra/newview/skins/default/xui/en/floater_script_preview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_script_queue.xml create mode 100644 indra/newview/skins/default/xui/en/floater_script_search.xml create mode 100644 indra/newview/skins/default/xui/en/floater_select_key.xml create mode 100644 indra/newview/skins/default/xui/en/floater_sell_land.xml create mode 100644 indra/newview/skins/default/xui/en/floater_settings_debug.xml create mode 100644 indra/newview/skins/default/xui/en/floater_snapshot.xml create mode 100644 indra/newview/skins/default/xui/en/floater_sound_preview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_statistics.xml create mode 100644 indra/newview/skins/default/xui/en/floater_stats.xml create mode 100644 indra/newview/skins/default/xui/en/floater_telehub.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_button.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_checkbox.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_combobox.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_layout.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_radiogroup.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_slider.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_spinner.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_textbox.xml create mode 100644 indra/newview/skins/default/xui/en/floater_test_widgets.xml create mode 100644 indra/newview/skins/default/xui/en/floater_texture_ctrl.xml create mode 100644 indra/newview/skins/default/xui/en/floater_tools.xml create mode 100644 indra/newview/skins/default/xui/en/floater_top_objects.xml create mode 100644 indra/newview/skins/default/xui/en/floater_tos.xml create mode 100644 indra/newview/skins/default/xui/en/floater_ui_preview.xml create mode 100644 indra/newview/skins/default/xui/en/floater_url_entry.xml create mode 100644 indra/newview/skins/default/xui/en/floater_water.xml create mode 100644 indra/newview/skins/default/xui/en/floater_wearable_save_as.xml create mode 100644 indra/newview/skins/default/xui/en/floater_windlight_options.xml create mode 100644 indra/newview/skins/default/xui/en/floater_world_map.xml create mode 100644 indra/newview/skins/default/xui/en/fonts.xml create mode 100644 indra/newview/skins/default/xui/en/menu_avatar_icon.xml create mode 100644 indra/newview/skins/default/xui/en/menu_favorites.xml create mode 100644 indra/newview/skins/default/xui/en/menu_group_plus.xml create mode 100644 indra/newview/skins/default/xui/en/menu_inventory.xml create mode 100644 indra/newview/skins/default/xui/en/menu_login.xml create mode 100644 indra/newview/skins/default/xui/en/menu_mini_map.xml create mode 100644 indra/newview/skins/default/xui/en/menu_navbar.xml create mode 100644 indra/newview/skins/default/xui/en/menu_nearby_chat.xml create mode 100644 indra/newview/skins/default/xui/en/menu_slurl.xml create mode 100644 indra/newview/skins/default/xui/en/menu_viewer.xml create mode 100644 indra/newview/skins/default/xui/en/mime_types.xml create mode 100644 indra/newview/skins/default/xui/en/notifications.xml create mode 100644 indra/newview/skins/default/xui/en/panel_audio_device.xml create mode 100644 indra/newview/skins/default/xui/en/panel_avatar_list_item.xml create mode 100644 indra/newview/skins/default/xui/en/panel_bars.xml create mode 100644 indra/newview/skins/default/xui/en/panel_bottomtray.xml create mode 100644 indra/newview/skins/default/xui/en/panel_classified.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_pick.xml create mode 100644 indra/newview/skins/default/xui/en/panel_edit_profile.xml create mode 100644 indra/newview/skins/default/xui/en/panel_friends.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_general.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_invite.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_land_money.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_notices.xml create mode 100644 indra/newview/skins/default/xui/en/panel_group_roles.xml create mode 100644 indra/newview/skins/default/xui/en/panel_groups.xml create mode 100644 indra/newview/skins/default/xui/en/panel_landmark_info.xml create mode 100644 indra/newview/skins/default/xui/en/panel_landmarks.xml create mode 100644 indra/newview/skins/default/xui/en/panel_login.xml create mode 100644 indra/newview/skins/default/xui/en/panel_navigation_bar.xml create mode 100644 indra/newview/skins/default/xui/en/panel_nearby_chat.xml create mode 100644 indra/newview/skins/default/xui/en/panel_notes.xml create mode 100644 indra/newview/skins/default/xui/en/panel_notifications_channel.xml create mode 100644 indra/newview/skins/default/xui/en/panel_people.xml create mode 100644 indra/newview/skins/default/xui/en/panel_pick_info.xml create mode 100644 indra/newview/skins/default/xui/en/panel_picks.xml create mode 100644 indra/newview/skins/default/xui/en/panel_places.xml create mode 100644 indra/newview/skins/default/xui/en/panel_preferences_chat.xml create mode 100644 indra/newview/skins/default/xui/en/panel_preferences_general.xml create mode 100644 indra/newview/skins/default/xui/en/panel_preferences_graphics1.xml create mode 100644 indra/newview/skins/default/xui/en/panel_profile.xml create mode 100644 indra/newview/skins/default/xui/en/panel_profile_view.xml create mode 100644 indra/newview/skins/default/xui/en/panel_progress.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_covenant.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_debug.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_estate.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_general.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_terrain.xml create mode 100644 indra/newview/skins/default/xui/en/panel_region_texture.xml create mode 100644 indra/newview/skins/default/xui/en/panel_script_ed.xml create mode 100644 indra/newview/skins/default/xui/en/panel_scrolling_param.xml create mode 100644 indra/newview/skins/default/xui/en/panel_side_tray.xml create mode 100644 indra/newview/skins/default/xui/en/panel_side_tray_tab_caption.xml create mode 100644 indra/newview/skins/default/xui/en/panel_status_bar.xml create mode 100644 indra/newview/skins/default/xui/en/panel_teleport_history.xml create mode 100644 indra/newview/skins/default/xui/en/panel_world_map.xml create mode 100644 indra/newview/skins/default/xui/en/role_actions.xml create mode 100644 indra/newview/skins/default/xui/en/strings.xml create mode 100644 indra/newview/skins/default/xui/en/teleport_strings.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/button.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/check_box.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/color_swatch.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/combo_box.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/drop_down.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/flyout_button.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/icon.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/line_editor.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/location_input.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/menu.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/menu_item_call.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/menu_item_check.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/multi_slider.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/name_editor.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/panel.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/progress_bar.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/radio_group.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/radio_item.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/scroll_bar.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/scroll_container.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/scroll_list.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/search_editor.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/side_tray.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/slider.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/slider_bar.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/spinner.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/tab_container.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/text.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/text_editor.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/texture_picker.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/view_border.xml create mode 100644 indra/newview/skins/default/xui/en/widgets/web_browser.xml create mode 100644 indra/newview/skins/default/xui/en/xui_version.xml create mode 100755 indra/test/lldoubledispatch_tut.cpp diff --git a/doc/contributions.txt b/doc/contributions.txt index 31ea1bbc5b..a4647f005d 100644 --- a/doc/contributions.txt +++ b/doc/contributions.txt @@ -197,6 +197,7 @@ Feep Larsson VWR-4444 Flemming Congrejo CT-193 + CT-318 Fluf Fredriksson VWR-3450 Fremont Cunningham @@ -274,6 +275,9 @@ Jacek Antonelli VWR-597 VWR-2054 VWR-2448 + VWR-2896 + VWR-2947 + VWR-2948 VWR-3605 JB Kraft VWR-5283 @@ -350,6 +354,7 @@ Michelle2 Zenovka Mm Alder VWR-3777 VWR-4794 + VWR-13578 Mr Greggan VWR-445 Nicholaz Beresford diff --git a/indra/CMakeLists.txt b/indra/CMakeLists.txt index 7f4c2c33c1..1010b199a1 100644 --- a/indra/CMakeLists.txt +++ b/indra/CMakeLists.txt @@ -1,3 +1,4 @@ + # -*- cmake -*- # cmake_minimum_required should appear before any @@ -110,3 +111,7 @@ if (SERVER) add_subdirectory(${SERVER_PREFIX}tools) endif (WINDOWS) endif (SERVER) + +# Define after the custom viewer and server targets are created so individual +# apps can add themselves as dependencies +add_subdirectory(${INTEGRATION_TESTS_PREFIX}integration_tests) diff --git a/indra/cmake/GooglePerfTools.cmake b/indra/cmake/GooglePerfTools.cmake index aff65cb53e..355ecb58f0 100644 --- a/indra/cmake/GooglePerfTools.cmake +++ b/indra/cmake/GooglePerfTools.cmake @@ -6,9 +6,11 @@ if (STANDALONE) else (STANDALONE) use_prebuilt_binary(google) if (WINDOWS) + use_prebuilt_binary(google-perftools) set(TCMALLOC_LIBRARIES debug libtcmalloc_minimal-debug - optimized libtcmalloc_minimal-debug) + optimized libtcmalloc_minimal) + set(GOOGLE_PERFTOOLS_FOUND "YES") endif (WINDOWS) if (LINUX) set(TCMALLOC_LIBRARIES tcmalloc) @@ -27,6 +29,10 @@ endif (GOOGLE_PERFTOOLS_FOUND) # XXX Disable temporarily, until we have compilation issues on 64-bit # Etch sorted. set(USE_GOOGLE_PERFTOOLS OFF) +if (WINDOWS) + # *TODO -reenable this once we get server usage sorted out + #set(USE_GOOGLE_PERFTOOLS ON) +endif (WINDOWS) if (USE_GOOGLE_PERFTOOLS) set(TCMALLOC_FLAG -DLL_USE_TCMALLOC=1) diff --git a/indra/cmake/LLCommon.cmake b/indra/cmake/LLCommon.cmake index 410766e4f9..ef202dd879 100644 --- a/indra/cmake/LLCommon.cmake +++ b/indra/cmake/LLCommon.cmake @@ -4,6 +4,7 @@ include(APR) include(Boost) include(EXPAT) include(ZLIB) +include(GooglePerfTools) set(LLCOMMON_INCLUDE_DIRS ${LIBS_OPEN_DIR}/llcommon @@ -13,3 +14,6 @@ set(LLCOMMON_INCLUDE_DIRS ) set(LLCOMMON_LIBRARIES llcommon) + +add_definitions(${TCMALLOC_FLAG}) + diff --git a/indra/cmake/Linking.cmake b/indra/cmake/Linking.cmake index 2bddb95178..eaa8a6dc29 100644 --- a/indra/cmake/Linking.cmake +++ b/indra/cmake/Linking.cmake @@ -42,6 +42,7 @@ if (WINDOWS) wldap32 gdi32 user32 + dbghelp ) else (WINDOWS) set(WINDOWS_LIBRARIES "") diff --git a/indra/cmake/Variables.cmake b/indra/cmake/Variables.cmake index 75b66a85da..6559051b5a 100644 --- a/indra/cmake/Variables.cmake +++ b/indra/cmake/Variables.cmake @@ -23,6 +23,7 @@ set(LIBS_SERVER_PREFIX) set(SCRIPTS_PREFIX ../scripts) set(SERVER_PREFIX) set(VIEWER_PREFIX) +set(INTEGRATION_TESTS_PREFIX) set(LIBS_CLOSED_DIR ${CMAKE_SOURCE_DIR}/${LIBS_CLOSED_PREFIX}) set(LIBS_OPEN_DIR ${CMAKE_SOURCE_DIR}/${LIBS_OPEN_PREFIX}) diff --git a/indra/integration_tests/CMakeLists.txt b/indra/integration_tests/CMakeLists.txt new file mode 100644 index 0000000000..67e8fbf1f2 --- /dev/null +++ b/indra/integration_tests/CMakeLists.txt @@ -0,0 +1,3 @@ +# -*- cmake -*- + +add_subdirectory(llui_libtest) diff --git a/indra/integration_tests/llui_libtest/CMakeLists.txt b/indra/integration_tests/llui_libtest/CMakeLists.txt new file mode 100644 index 0000000000..68556ac4ab --- /dev/null +++ b/indra/integration_tests/llui_libtest/CMakeLists.txt @@ -0,0 +1,97 @@ +# -*- cmake -*- + +project (llui_libtest) + +include(00-Common) +include(LLCommon) +include(LLImage) +include(LLImageJ2COJ) # ugh, needed for images +include(LLMath) +include(LLRender) +include(LLWindow) +include(LLUI) +include(LLVFS) # ugh, needed for LLDir +include(LLXML) +include(Linking) +# include(Tut) + +include_directories( + ${FREETYPE_INCLUDE_DIRS} + ${LLCOMMON_INCLUDE_DIRS} + ${LLIMAGE_INCLUDE_DIRS} + ${LLMATH_INCLUDE_DIRS} + ${LLRENDER_INCLUDE_DIRS} + ${LLUI_INCLUDE_DIRS} + ${LLVFS_INCLUDE_DIRS} + ${LLWINDOW_INCLUDE_DIRS} + ${LLXML_INCLUDE_DIRS} + ) + +set(llui_libtest_SOURCE_FILES + llui_libtest.cpp + llwidgetreg.cpp + ) + +set(llui_libtest_HEADER_FILES + CMakeLists.txt + llui_libtest.h + llwidgetreg.h + ) + +set_source_files_properties(${llui_libtest_HEADER_FILES} + PROPERTIES HEADER_FILE_ONLY TRUE) + +list(APPEND llui_libtest_SOURCE_FILES ${llui_libtest_HEADER_FILES}) + +add_executable(llui_libtest ${llui_libtest_SOURCE_FILES}) + +# Link with OS-specific libraries for LLWindow dependency +if (DARWIN) + find_library(COCOA_LIBRARY Cocoa) + set(OS_LIBRARIES ${COCOA_LIBRARY}) +elseif (WINDOWS) + set(OS_LIBRARIES ${WINDOWS_LIBRARIES}) +elseif (LINUX) + set(OS_LIBRARIES) +else (DARWIN) + message(FATAL_ERROR "unknown platform") +endif (DARWIN) + +# Libraries on which this library depends, needed for Linux builds +# Sort by high-level to low-level +target_link_libraries(llui_libtest + llui + ${OS_LIBRARIES} + ${GOOGLE_PERFTOOLS_LIBRARIES} + ) + +if (WINDOWS) + set_target_properties(llui_libtest + PROPERTIES + LINK_FLAGS "/NODEFAULTLIB:LIBCMT" + LINK_FLAGS_DEBUG "/NODEFAULTLIB:MSVCRT /NODEFAULTLIB:LIBCMTD" + ) + + # Copy over OpenJPEG.dll + # *NOTE: On Windows with VS2005, only the first comment prints + set(OPENJPEG_RELEASE + "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/release/openjpeg.dll") + add_custom_command( TARGET llui_libtest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OPENJPEG_RELEASE} ${CMAKE_CURRENT_BINARY_DIR} + COMMENT "Copying OpenJPEG DLLs to binary directory" + ) + set(OPENJPEG_DEBUG + "${CMAKE_SOURCE_DIR}/../libraries/i686-win32/lib/debug/openjpegd.dll") + add_custom_command( TARGET llui_libtest POST_BUILD + COMMAND ${CMAKE_COMMAND} -E copy_if_different + ${OPENJPEG_DEBUG} ${CMAKE_CURRENT_BINARY_DIR} + ) +endif (WINDOWS) + +if (VIEWER) + # Ensure people working on the viewer don't break this library + # *NOTE: This could be removed, or only built by Parabuild, if the build + # and link times become too long. JC + add_dependencies(viewer llui_libtest) +endif (VIEWER) diff --git a/indra/integration_tests/llui_libtest/llui_libtest.cpp b/indra/integration_tests/llui_libtest/llui_libtest.cpp new file mode 100644 index 0000000000..f8caa7990b --- /dev/null +++ b/indra/integration_tests/llui_libtest/llui_libtest.cpp @@ -0,0 +1,196 @@ +/** + * @file llui_libtest.cpp + * @brief Integration test for the LLUI library + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llui_libtest.h" + +// project includes +#include "llwidgetreg.h" + +// linden library includes +#include "llcontrol.h" // LLControlGroup +#include "lldir.h" +#include "llerrorcontrol.h" +#include "llfloater.h" +#include "llfontgl.h" +#include "lltrans.h" +#include "llui.h" +#include "lluictrlfactory.h" + +#include + +// *TODO: switch to using TUT +// *TODO: teach Parabuild about this program, run automatically after full builds + +// We can't create LLImageGL objects because we have no window or rendering +// context. Provide enough of an LLUIImage to test the LLUI library without +// an underlying image. +class TestUIImage : public LLUIImage +{ +public: + TestUIImage() + : LLUIImage( std::string(), NULL ) // NULL ImageGL, don't deref! + { } + + /*virtual*/ S32 getWidth() const + { + return 16; + } + + /*virtual*/ S32 getHeight() const + { + return 16; + } +}; + +// We need to supply dummy images +class TestImageProvider : public LLImageProviderInterface +{ +public: + /*virtual*/ LLPointer getUIImage(const std::string& name) + { + return makeImage(); + } + + /*virtual*/ LLPointer getUIImageByID(const LLUUID& id) + { + return makeImage(); + } + + /*virtual*/ void cleanUp() + { + } + + LLPointer makeImage() + { + LLPointer image_gl; + LLPointer image = new LLUIImage( std::string(), image_gl); + return image; + } +}; + +static std::string get_xui_dir() +{ + std::string delim = gDirUtilp->getDirDelimiter(); + return gDirUtilp->getAppRODataDir() + delim + std::string("skins") + delim + "default" + delim + "xui" + delim; +} + +int main(int argc, char** argv) +{ + // Must init LLError for llerrs to actually cause errors. + LLError::initForApplication("."); + + // Font lookup needs directory support + gDirUtilp->initAppDirs("SecondLife", "../../../newview"); + gDirUtilp->setSkinFolder("default"); + + std::string config_filename = gDirUtilp->getExpandedFilename( + LL_PATH_APP_SETTINGS, "settings.xml"); + LLControlGroup config_group("config"); + config_group.loadFromFile(config_filename); + + std::string color_filename = gDirUtilp->getExpandedFilename( + LL_PATH_DEFAULT_SKIN, "colors.xml"); + LLControlGroup color_group("color"); + color_group.loadFromFile(color_filename); + + LLControlGroup floater_group("floater"); + LLControlGroup ignores_group("ignores"); + LLUI::settings_map_t settings; + settings["config"] = &config_group; + settings["color"] = &color_group; + settings["floater"] = &floater_group; + settings["ignores"] = &ignores_group; + + // Don't use real images as we don't have a GL context + TestImageProvider image_provider; + LLUI::initClass(settings, &image_provider); + + const bool no_register_widgets = false; + LLWidgetReg::initClass( no_register_widgets ); + + // Unclear if this is needed + LLUI::setupPaths(); + // Otherwise we get translation warnings when setting up floaters + // (tooltips for buttons) + std::set default_args; + LLTrans::parseStrings("strings.xml", default_args); + + LLFontManager::initClass(); + + // Creating widgets apparently requires fonts to be initialized, + // otherwise it crashes. + LLFontGL::initClass(96.f, 1.f, 1.f, + gDirUtilp->getAppRODataDir(), + LLUI::getXUIPaths(), + false ); // don't create gl textures + + LLFloaterView::Params fvparams; + fvparams.name("Floater View"); + fvparams.rect( LLRect(0,480,640,0) ); + fvparams.mouse_opaque(false); + fvparams.follows.flags(FOLLOWS_ALL); + fvparams.tab_stop(false); + gFloaterView = LLUICtrlFactory::create (fvparams); + + // Convert all test floaters to new XML format + std::string delim = gDirUtilp->getDirDelimiter(); + std::string xui_dir = get_xui_dir() + "en" + delim; + std::string filename; + while (gDirUtilp->getNextFileInDir(xui_dir, "floater_test_*.xml", filename, false)) + { + if (filename.find("_new.xml") != std::string::npos) + { + // don't re-export other test floaters + continue; + } + llinfos << "Converting " << filename << llendl; + // Build a floater and output new attributes + LLXMLNodePtr output_node = new LLXMLNode(); + LLFloater* floater = new LLFloater(); + LLUICtrlFactory::getInstance()->buildFloater(floater, + filename, + FALSE, // don't open floater + output_node); + std::string out_filename = xui_dir + filename; + std::string::size_type extension_pos = out_filename.rfind(".xml"); + out_filename.resize(extension_pos); + out_filename += "_new.xml"; + + llinfos << "Output: " << out_filename << llendl; + LLFILE* floater_file = LLFile::fopen(out_filename.c_str(), "w"); + LLXMLNode::writeHeaderToFile(floater_file); + output_node->writeToFile(floater_file); + fclose(floater_file); + } + return 0; +} diff --git a/indra/integration_tests/llui_libtest/llui_libtest.h b/indra/integration_tests/llui_libtest/llui_libtest.h new file mode 100644 index 0000000000..a84d57dba9 --- /dev/null +++ b/indra/integration_tests/llui_libtest/llui_libtest.h @@ -0,0 +1,36 @@ +/** + * @file llui_libtest.h + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLUI_LIBTEST_H +#define LLUI_LIBTEST_H + +// TODO + +#endif diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.cpp b/indra/integration_tests/llui_libtest/llwidgetreg.cpp new file mode 100644 index 0000000000..417f3059d6 --- /dev/null +++ b/indra/integration_tests/llui_libtest/llwidgetreg.cpp @@ -0,0 +1,106 @@ +/** + * @file llwidgetreg.cpp + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llwidgetreg.h" + +#include "llbutton.h" +#include "llcheckboxctrl.h" +#include "llcombobox.h" +#include "llcontainerview.h" +#include "lliconctrl.h" +#include "llmenugl.h" +#include "llmultislider.h" +#include "llmultisliderctrl.h" +#include "llprogressbar.h" +#include "llradiogroup.h" +#include "llscrollcontainer.h" +#include "llscrollingpanellist.h" +#include "llscrolllistctrl.h" +#include "llslider.h" +#include "llsliderctrl.h" +#include "llspinctrl.h" +#include "llstatview.h" +#include "lltabcontainer.h" +#include "lltextbox.h" +#include "lltexteditor.h" +#include "llflyoutbutton.h" +#include "llsearcheditor.h" +#include "lllayoutstack.h" + +void LLWidgetReg::initClass(bool register_widgets) +{ + // Only need to register if the Windows linker has optimized away the + // references to the object files. + if (register_widgets) + { + LLDefaultWidgetRegistry::Register button("button"); + LLDefaultWidgetRegistry::Register check_box("check_box"); + LLDefaultWidgetRegistry::Register combo_box("combo_box"); + LLDefaultWidgetRegistry::Register flyout_button("flyout_button"); + LLDefaultWidgetRegistry::Register container_view("container_view"); + LLDefaultWidgetRegistry::Register icon("icon"); + LLDefaultWidgetRegistry::Register line_editor("line_editor"); + LLDefaultWidgetRegistry::Register search_editor("search_editor"); + LLDefaultWidgetRegistry::Register menu_item_separator("menu_item_separator"); + LLDefaultWidgetRegistry::Register menu_item_call_gl("menu_item_call"); + LLDefaultWidgetRegistry::Register menu_item_check_gl("menu_item_check"); + LLDefaultWidgetRegistry::Register menu("menu"); + LLDefaultWidgetRegistry::Register menu_bar("menu_bar"); + LLDefaultWidgetRegistry::Register context_menu("context_menu"); + LLDefaultWidgetRegistry::Register multi_slider_bar("multi_slider_bar"); + LLDefaultWidgetRegistry::Register multi_slider("multi_slider"); + LLDefaultWidgetRegistry::Register panel("panel", &LLPanel::fromXML); + LLDefaultWidgetRegistry::Register layout_stack("layout_stack", &LLLayoutStack::fromXML); + LLDefaultWidgetRegistry::Register progress_bar("progress_bar"); + LLDefaultWidgetRegistry::Register radio_group("radio_group"); + LLDefaultWidgetRegistry::Register radio_item("radio_item"); + LLDefaultWidgetRegistry::Register scroll_container("scroll_container"); + LLDefaultWidgetRegistry::Register scrolling_panel_list("scrolling_panel_list"); + LLDefaultWidgetRegistry::Register scroll_list("scroll_list"); + LLDefaultWidgetRegistry::Register slider_bar("slider_bar"); + LLDefaultWidgetRegistry::Register slider("slider"); + LLDefaultWidgetRegistry::Register spinner("spinner"); + LLDefaultWidgetRegistry::Register stat_bar("stat_bar"); + //LLDefaultWidgetRegistry::Register placeholder("placeholder"); + LLDefaultWidgetRegistry::Register tab_container("tab_container"); + LLDefaultWidgetRegistry::Register text("text"); + LLDefaultWidgetRegistry::Register simple_text_editor("simple_text_editor"); + LLDefaultWidgetRegistry::Register ui_ctrl("ui_ctrl"); + LLDefaultWidgetRegistry::Register stat_view("stat_view"); + //LLDefaultWidgetRegistry::Register locate("locate"); + //LLDefaultWidgetRegistry::Register pad("pad"); + LLDefaultWidgetRegistry::Register view_border("view_border"); + } + + // *HACK: Usually this is registered as a viewer text editor + LLDefaultWidgetRegistry::Register text_editor("text_editor"); +} diff --git a/indra/integration_tests/llui_libtest/llwidgetreg.h b/indra/integration_tests/llui_libtest/llwidgetreg.h new file mode 100644 index 0000000000..eac818608d --- /dev/null +++ b/indra/integration_tests/llui_libtest/llwidgetreg.h @@ -0,0 +1,43 @@ +/** + * @file llwidgetreg.h + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLWIDGETREG_H +#define LLWIDGETREG_H + +// Register all widgets with the builder registry. +// Useful on Windows where linker discards all references to the +// static LLDefaultWidgetRegistry::Register<> calls. +class LLWidgetReg +{ +public: + static void initClass(bool register_widgets); +}; + +#endif diff --git a/indra/llaudio/llaudiodecodemgr.cpp b/indra/llaudio/llaudiodecodemgr.cpp index 5b6db3bd87..6a494d1983 100644 --- a/indra/llaudio/llaudiodecodemgr.cpp +++ b/indra/llaudio/llaudiodecodemgr.cpp @@ -40,8 +40,8 @@ #include "llstring.h" #include "lldir.h" #include "llendianswizzle.h" -#include "audioengine.h" #include "llassetstorage.h" +#include "llrefcount.h" #include "vorbis/codec.h" #include "vorbis/vorbisfile.h" diff --git a/indra/llcharacter/llbvhloader.cpp b/indra/llcharacter/llbvhloader.cpp index e1f8ce53fb..24391eb8f3 100644 --- a/indra/llcharacter/llbvhloader.cpp +++ b/indra/llcharacter/llbvhloader.cpp @@ -56,7 +56,7 @@ const F32 ROTATION_MOTION_THRESHOLD = 0.001f; char gInFile[1024]; /* Flawfinder: ignore */ char gOutFile[1024]; /* Flawfinder: ignore */ - +/* //------------------------------------------------------------------------ // Status Codes //------------------------------------------------------------------------ @@ -91,7 +91,7 @@ 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."; - +*/ //------------------------------------------------------------------------ // find_next_whitespace() //------------------------------------------------------------------------ @@ -124,7 +124,9 @@ LLQuaternion::Order bvhStringToOrder( char *str ) //----------------------------------------------------------------------------- // LLBVHLoader() //----------------------------------------------------------------------------- -LLBVHLoader::LLBVHLoader(const char* buffer) + +/* + LLBVHLoader::LLBVHLoader(const char* buffer) { reset(); @@ -144,7 +146,7 @@ LLBVHLoader::LLBVHLoader(const char* buffer) } } - char error_text[128]; /* Flawfinder: ignore */ + char error_text[128]; // Flawfinder: ignore S32 error_line; mStatus = loadBVHFile(buffer, error_text, error_line); if (mStatus != LLBVHLoader::ST_OK) @@ -158,6 +160,49 @@ LLBVHLoader::LLBVHLoader(const char* buffer) mInitialized = TRUE; } +*/ +LLBVHLoader::LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine) +{ + reset(); + errorLine = 0; + mStatus = loadTranslationTable("anim.ini"); + loadStatus = mStatus; + llinfos<<"Load Status 00 : "<< loadStatus << llendl; + if (mStatus == E_ST_NO_XLT_FILE) + { + //llwarns << "NOTE: No translation table found." << llendl; + loadStatus = mStatus; + return; + } + else + { + if (mStatus != E_ST_OK) + { + //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl; + errorLine = getLineNumber(); + loadStatus = mStatus; + return; + } + } + + char error_text[128]; /* Flawfinder: ignore */ + S32 error_line; + mStatus = loadBVHFile(buffer, error_text, error_line); + + if (mStatus != E_ST_OK) + { + //llwarns << "ERROR: [line: " << getLineNumber() << "] " << mStatus << llendl; + loadStatus = mStatus; + errorLine = getLineNumber(); + return; + } + + applyTranslations(); + optimize(); + + mInitialized = TRUE; +} + LLBVHLoader::~LLBVHLoader() { @@ -167,7 +212,7 @@ LLBVHLoader::~LLBVHLoader() //------------------------------------------------------------------------ // LLBVHLoader::loadTranslationTable() //------------------------------------------------------------------------ -LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) +ELoadStatus LLBVHLoader::loadTranslationTable(const char *fileName) { mLineNumber = 0; mTranslations.clear(); @@ -182,7 +227,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) infile.open(path, LL_APR_R); apr_file_t *fp = infile.getFileHandle(); if (!fp) - return ST_NO_XLT_FILE; + return E_ST_NO_XLT_FILE; llinfos << "NOTE: Loading translation table: " << fileName << llendl; @@ -194,9 +239,9 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) // load header //-------------------------------------------------------------------- if ( ! getLine(fp) ) - return ST_EOF; + return E_ST_EOF; if ( strncmp(mLine, "Translations 1.0", 16) ) - return ST_NO_XLT_HEADER; + return E_ST_NO_XLT_HEADER; //-------------------------------------------------------------------- // load data one line at a time @@ -222,7 +267,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char name[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " [%127[^]]", name) != 1 ) - return ST_NO_XLT_NAME; + return E_ST_NO_XLT_NAME; if (strcmp(name, "GLOBALS")==0) { @@ -245,7 +290,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char emote_str[1024]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %1023s", emote_str) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EMOTE; + return E_ST_NO_XLT_EMOTE; mEmoteName.assign( emote_str ); // llinfos << "NOTE: Emote: " << mEmoteName.c_str() << llendl; @@ -260,7 +305,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 priority; if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return ST_NO_XLT_PRIORITY; + return E_ST_NO_XLT_PRIORITY; mPriority = priority; // llinfos << "NOTE: Priority: " << mPriority << llendl; @@ -288,7 +333,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_LOOP; + return E_ST_NO_XLT_LOOP; } mLoopInPoint = loop_in * mDuration; @@ -305,7 +350,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) F32 duration; char type[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EASEIN; + return E_ST_NO_XLT_EASEIN; mEaseIn = duration; continue; @@ -319,7 +364,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) F32 duration; char type[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %f %127s", &duration, type) != 2 ) /* Flawfinder: ignore */ - return ST_NO_XLT_EASEOUT; + return E_ST_NO_XLT_EASEOUT; mEaseOut = duration; continue; @@ -332,7 +377,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 handMorph; if (sscanf(mLine, " %*s = %d", &handMorph) != 1) - return ST_NO_XLT_HAND; + return E_ST_NO_XLT_HAND; mHand = handMorph; continue; @@ -380,7 +425,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &constraint.mTargetOffset.mV[VY], &constraint.mTargetOffset.mV[VZ]) != 13) { - return ST_NO_CONSTRAINT; + return E_ST_NO_CONSTRAINT; } } else @@ -440,7 +485,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &constraint.mTargetOffset.mV[VY], &constraint.mTargetOffset.mV[VZ]) != 13) { - return ST_NO_CONSTRAINT; + return E_ST_NO_CONSTRAINT; } } else @@ -463,7 +508,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) // at this point there must be a valid trans pointer //---------------------------------------------------------------- if ( ! trans ) - return ST_NO_XLT_NAME; + return E_ST_NO_XLT_NAME; //---------------------------------------------------------------- // check for ignore flag @@ -472,7 +517,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char trueFalse[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", trueFalse) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_IGNORE; + return E_ST_NO_XLT_IGNORE; trans->mIgnore = (LLStringUtil::compareInsensitive(trueFalse, "true")==0); continue; @@ -497,12 +542,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } continue; @@ -523,12 +568,12 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } } else { - return ST_NO_XLT_RELATIVE; + return E_ST_NO_XLT_RELATIVE; } continue; @@ -541,7 +586,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char outName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", outName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_OUTNAME; + return E_ST_NO_XLT_OUTNAME; trans->mOutName = outName; continue; @@ -557,7 +602,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &fm.mMatrix[0][0], &fm.mMatrix[0][1], &fm.mMatrix[0][2], &fm.mMatrix[1][0], &fm.mMatrix[1][1], &fm.mMatrix[1][2], &fm.mMatrix[2][0], &fm.mMatrix[2][1], &fm.mMatrix[2][2] ) != 9 ) - return ST_NO_XLT_MATRIX; + return E_ST_NO_XLT_MATRIX; trans->mFrameMatrix = fm; continue; @@ -573,7 +618,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) &om.mMatrix[0][0], &om.mMatrix[0][1], &om.mMatrix[0][2], &om.mMatrix[1][0], &om.mMatrix[1][1], &om.mMatrix[1][2], &om.mMatrix[2][0], &om.mMatrix[2][1], &om.mMatrix[2][2] ) != 9 ) - return ST_NO_XLT_MATRIX; + return E_ST_NO_XLT_MATRIX; trans->mOffsetMatrix = om; continue; @@ -586,7 +631,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char mergeParentName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", mergeParentName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_MERGEPARENT; + return E_ST_NO_XLT_MERGEPARENT; trans->mMergeParentName = mergeParentName; continue; @@ -599,7 +644,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { char mergeChildName[128]; /* Flawfinder: ignore */ if ( sscanf(mLine, " %*s = %127s", mergeChildName) != 1 ) /* Flawfinder: ignore */ - return ST_NO_XLT_MERGECHILD; + return E_ST_NO_XLT_MERGECHILD; trans->mMergeChildName = mergeChildName; continue; @@ -612,7 +657,7 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) { S32 priority; if ( sscanf(mLine, " %*s = %d", &priority) != 1 ) - return ST_NO_XLT_PRIORITY; + return E_ST_NO_XLT_PRIORITY; trans->mPriorityModifier = priority; continue; @@ -621,14 +666,14 @@ LLBVHLoader::Status LLBVHLoader::loadTranslationTable(const char *fileName) } infile.close() ; - return ST_OK; + return E_ST_OK; } //------------------------------------------------------------------------ // LLBVHLoader::loadBVHFile() //------------------------------------------------------------------------ -LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line) +ELoadStatus LLBVHLoader::loadBVHFile(const char *buffer, char* error_text, S32 &err_line) { std::string line; @@ -650,14 +695,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // consume hierarchy //-------------------------------------------------------------------- if (iter == tokens.end()) - return ST_EOF; + return E_ST_EOF; line = (*(iter++)); err_line++; if ( !strstr(line.c_str(), "HIERARCHY") ) { // llinfos << line << llendl; - return ST_NO_HIER; + return E_ST_NO_HIER; } //-------------------------------------------------------------------- @@ -669,7 +714,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // get next line //---------------------------------------------------------------- if (iter == tokens.end()) - return ST_EOF; + return E_ST_EOF; line = (*(iter++)); err_line++; @@ -719,7 +764,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex else { strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ - return ST_NO_JOINT; + return E_ST_NO_JOINT; } //---------------------------------------------------------------- @@ -729,7 +774,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(line.c_str(), "%*s %79s", jointName) != 1 ) /* Flawfinder: ignore */ { strncpy(error_text, line.c_str(), 127); /* Flawfinder: ignore */ - return ST_NO_NAME; + return E_ST_NO_NAME; } //---------------------------------------------------------------- @@ -754,7 +799,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -765,7 +810,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "{") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_OFFSET; + return E_ST_NO_OFFSET; } else { @@ -777,7 +822,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -788,7 +833,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "OFFSET") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_OFFSET; + return E_ST_NO_OFFSET; } //---------------------------------------------------------------- @@ -796,7 +841,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //---------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -807,7 +852,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "CHANNELS") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_CHANNELS; + return E_ST_NO_CHANNELS; } //---------------------------------------------------------------- @@ -820,14 +865,14 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROTATION; + return E_ST_NO_ROTATION; } const char axis = *(p - 1); if ((axis != 'X') && (axis != 'Y') && (axis != 'Z')) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_AXIS; + return E_ST_NO_AXIS; } joint->mOrder[i] = axis; @@ -842,7 +887,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "MOTION") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_MOTION; + return E_ST_NO_MOTION; } //-------------------------------------------------------------------- @@ -850,7 +895,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //-------------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -858,13 +903,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "Frames:") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAMES; + return E_ST_NO_FRAMES; } if ( sscanf(line.c_str(), "Frames: %d", &mNumFrames) != 1 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAMES; + return E_ST_NO_FRAMES; } //-------------------------------------------------------------------- @@ -872,7 +917,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex //-------------------------------------------------------------------- if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -880,13 +925,13 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( !strstr(line.c_str(), "Frame Time:") ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAME_TIME; + return E_ST_NO_FRAME_TIME; } if ( sscanf(line.c_str(), "Frame Time: %f", &mFrameTime) != 1 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_FRAME_TIME; + return E_ST_NO_FRAME_TIME; } mDuration = (F32)mNumFrames * mFrameTime; @@ -903,7 +948,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex // get next line if (iter == tokens.end()) { - return ST_EOF; + return E_ST_EOF; } line = (*(iter++)); err_line++; @@ -922,7 +967,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(p, "%f %f %f", key.mPos, key.mPos+1, key.mPos+2) != 3 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_POS; + return E_ST_NO_POS; } } @@ -931,19 +976,19 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p = find_next_whitespace(++p); if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p = find_next_whitespace(++p); if (!p) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } // get 3 rot values for joint @@ -951,7 +996,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex if ( sscanf(p, " %f %f %f", rot, rot+1, rot+2) != 3 ) { strncpy(error_text, line.c_str(), 127); /*Flawfinder: ignore*/ - return ST_NO_ROT; + return E_ST_NO_ROT; } p++; @@ -962,7 +1007,7 @@ LLBVHLoader::Status LLBVHLoader::loadBVHFile(const char *buffer, char* error_tex } } - return ST_OK; + return E_ST_OK; } diff --git a/indra/llcharacter/llbvhloader.h b/indra/llcharacter/llbvhloader.h index 6937b9d835..ecdfc95478 100644 --- a/indra/llcharacter/llbvhloader.h +++ b/indra/llcharacter/llbvhloader.h @@ -184,6 +184,41 @@ public: S32 mPriorityModifier; }; +typedef enum e_load_status + { + E_ST_OK, + E_ST_EOF, + E_ST_NO_CONSTRAINT, + E_ST_NO_FILE, + E_ST_NO_HIER, + E_ST_NO_JOINT, + E_ST_NO_NAME, + E_ST_NO_OFFSET, + E_ST_NO_CHANNELS, + E_ST_NO_ROTATION, + E_ST_NO_AXIS, + E_ST_NO_MOTION, + E_ST_NO_FRAMES, + E_ST_NO_FRAME_TIME, + E_ST_NO_POS, + E_ST_NO_ROT, + E_ST_NO_XLT_FILE, + E_ST_NO_XLT_HEADER, + E_ST_NO_XLT_NAME, + E_ST_NO_XLT_IGNORE, + E_ST_NO_XLT_RELATIVE, + E_ST_NO_XLT_OUTNAME, + E_ST_NO_XLT_MATRIX, + E_ST_NO_XLT_MERGECHILD, + E_ST_NO_XLT_MERGEPARENT, + E_ST_NO_XLT_PRIORITY, + E_ST_NO_XLT_LOOP, + E_ST_NO_XLT_EASEIN, + E_ST_NO_XLT_EASEOUT, + E_ST_NO_XLT_HAND, + E_ST_NO_XLT_EMOTE + } ELoadStatus; + //------------------------------------------------------------------------ // TranslationMap //------------------------------------------------------------------------ @@ -194,9 +229,11 @@ class LLBVHLoader friend class LLKeyframeMotion; public: // Constructor - LLBVHLoader(const char* buffer); +// LLBVHLoader(const char* buffer); + LLBVHLoader(const char* buffer, ELoadStatus &loadStatus, S32 &errorLine); ~LLBVHLoader(); - + +/* // Status Codes typedef const char *Status; static const char *ST_OK; @@ -230,13 +267,13 @@ public: static const char *ST_NO_XLT_EASEOUT; static const char *ST_NO_XLT_HAND; static const char *ST_NO_XLT_EMOTE; - +*/ // Loads the specified translation table. - Status loadTranslationTable(const char *fileName); + ELoadStatus loadTranslationTable(const char *fileName); // Load the specified BVH file. // Returns status code. - Status loadBVHFile(const char *buffer, char *error_text, S32 &error_line); + ELoadStatus loadBVHFile(const char *buffer, char *error_text, S32 &error_line); // Applies translations to BVH data loaded. void applyTranslations(); @@ -260,7 +297,7 @@ public: BOOL isInitialized() { return mInitialized; } - Status getStatus() { return mStatus; } + ELoadStatus getStatus() { return mStatus; } protected: // Consumes one line of input from file. @@ -287,7 +324,7 @@ protected: std::string mEmoteName; BOOL mInitialized; - Status mStatus; + ELoadStatus mStatus; // computed values F32 mDuration; }; diff --git a/indra/llcharacter/llcharacter.h b/indra/llcharacter/llcharacter.h index 0112788884..cd8f9e63fb 100644 --- a/indra/llcharacter/llcharacter.h +++ b/indra/llcharacter/llcharacter.h @@ -42,7 +42,7 @@ #include "llmotioncontroller.h" #include "llvisualparam.h" #include "string_table.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLPolyMesh; @@ -169,7 +169,7 @@ public: void updateMotions(e_update_t update_type); LLAnimPauseRequest requestPause(); - BOOL areAnimationsPaused() { return mMotionController.isPaused(); } + BOOL areAnimationsPaused() const { return mMotionController.isPaused(); } void setAnimTimeFactor(F32 factor) { mMotionController.setTimeFactor(factor); } void setTimeStep(F32 time_step) { mMotionController.setTimeStep(time_step); } @@ -231,9 +231,9 @@ public: return (mCurIterator++)->second; } - LLVisualParam* getVisualParam(S32 id) + LLVisualParam* getVisualParam(S32 id) const { - VisualParamIndexMap_t::iterator iter = mVisualParamIndexMap.find(id); + VisualParamIndexMap_t::const_iterator iter = mVisualParamIndexMap.find(id); return (iter == mVisualParamIndexMap.end()) ? 0 : iter->second; } S32 getVisualParamID(LLVisualParam *id) @@ -246,11 +246,11 @@ public: } return 0; } - S32 getVisualParamCount() { return (S32)mVisualParamIndexMap.size(); } + S32 getVisualParamCount() const { return (S32)mVisualParamIndexMap.size(); } LLVisualParam* getVisualParam(const char *name); - ESex getSex() { return mSex; } + ESex getSex() const { return mSex; } void setSex( ESex sex ) { mSex = sex; } U32 getAppearanceSerialNum() const { return mAppearanceSerialNum; } diff --git a/indra/llcharacter/lljointstate.h b/indra/llcharacter/lljointstate.h index 16ad0e1200..e40cf2673f 100644 --- a/indra/llcharacter/lljointstate.h +++ b/indra/llcharacter/lljointstate.h @@ -37,7 +37,7 @@ // Header Files //----------------------------------------------------------------------------- #include "lljoint.h" -#include "llmemory.h" +#include "llrefcount.h" //----------------------------------------------------------------------------- // class LLJointState diff --git a/indra/llcharacter/llkeyframemotionparam.cpp b/indra/llcharacter/llkeyframemotionparam.cpp index 622405a5e1..c4333fc0fd 100644 --- a/indra/llcharacter/llkeyframemotionparam.cpp +++ b/indra/llcharacter/llkeyframemotionparam.cpp @@ -347,8 +347,11 @@ BOOL LLKeyframeMotionParam::loadMotions() // Load named file by concatenating the character prefix with the motion name. // Load data into a buffer to be parsed. //------------------------------------------------------------------------- - std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) - + "_" + getName() + ".llp"; + //std::string path = gDirUtilp->getExpandedFilename(LL_PATH_MOTIONS,mCharacter->getAnimationPrefix()) + // + "_" + getName() + ".llp"; + //RN: deprecated unused reference to "motion" directory + std::string path; + //------------------------------------------------------------------------- // open the file diff --git a/indra/llcharacter/llmotioncontroller.cpp b/indra/llcharacter/llmotioncontroller.cpp index 006d2b5f62..bb9625b2bd 100644 --- a/indra/llcharacter/llmotioncontroller.cpp +++ b/indra/llcharacter/llmotioncontroller.cpp @@ -1019,9 +1019,9 @@ bool LLMotionController::isMotionLoading(LLMotion* motion) //----------------------------------------------------------------------------- // findMotion() //----------------------------------------------------------------------------- -LLMotion* LLMotionController::findMotion(const LLUUID& id) +LLMotion* LLMotionController::findMotion(const LLUUID& id) const { - motion_map_t::iterator iter = mAllMotions.find(id); + motion_map_t::const_iterator iter = mAllMotions.find(id); if(iter == mAllMotions.end()) { return NULL; diff --git a/indra/llcharacter/llmotioncontroller.h b/indra/llcharacter/llmotioncontroller.h index 9271483a25..5c3ec223cb 100644 --- a/indra/llcharacter/llmotioncontroller.h +++ b/indra/llcharacter/llmotioncontroller.h @@ -153,12 +153,12 @@ public: // pause and continue all motions void pauseAllMotions(); void unpauseAllMotions(); - BOOL isPaused() { return mPaused; } + BOOL isPaused() const { return mPaused; } void setTimeStep(F32 step); void setTimeFactor(F32 time_factor); - F32 getTimeFactor() { return mTimeFactor; } + F32 getTimeFactor() const { return mTimeFactor; } motion_list_t& getActiveMotions() { return mActiveMotions; } @@ -167,7 +167,7 @@ public: //protected: bool isMotionActive( LLMotion *motion ); bool isMotionLoading( LLMotion *motion ); - LLMotion *findMotion( const LLUUID& id ); + LLMotion *findMotion( const LLUUID& id ) const; protected: // internal operations act on motion instances directly diff --git a/indra/llcharacter/llmultigesture.cpp b/indra/llcharacter/llmultigesture.cpp index 7fe21dbc93..701d6889ca 100644 --- a/indra/llcharacter/llmultigesture.cpp +++ b/indra/llcharacter/llmultigesture.cpp @@ -243,7 +243,7 @@ void LLMultiGesture::dump() //--------------------------------------------------------------------------- LLGestureStepAnimation::LLGestureStepAnimation() : LLGestureStep(), - mAnimName("None"), + mAnimName("None"), mAnimAssetID(), mFlags(0x0) { } @@ -292,20 +292,27 @@ BOOL LLGestureStepAnimation::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepAnimation::getLabel() const +// *TODO: Translate +std::vector LLGestureStepAnimation::getLabel() const { - std::string label; + std::vector strings; + +// std::string label; if (mFlags & ANIM_FLAG_STOP) { - label = "Stop Animation: "; + strings.push_back( "AnimFlagStop"); + +// label = "Stop Animation: "; } else { - label = "Start Animation: "; + strings.push_back( "AnimFlagStart"); + +// label = "Start Animation: "; } - label += mAnimName; - return label; + strings.push_back( mAnimName); +// label += mAnimName; + return strings; } void LLGestureStepAnimation::dump() @@ -359,12 +366,15 @@ BOOL LLGestureStepSound::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepSound::getLabel() const +// *TODO: Translate +std::vector LLGestureStepSound::getLabel() const { - std::string label("Sound: "); - label += mSoundName; - return label; + std::vector strings; + strings.push_back( "Sound"); + strings.push_back( mSoundName); +// std::string label("Sound: "); +// label += mSoundName; + return strings; } void LLGestureStepSound::dump() @@ -414,12 +424,13 @@ BOOL LLGestureStepChat::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepChat::getLabel() const +// *TODO: Translate +std::vector LLGestureStepChat::getLabel() const { - std::string label("Chat: "); - label += mChatText; - return label; + std::vector strings; + strings.push_back("Chat"); + strings.push_back(mChatText); + return strings; } void LLGestureStepChat::dump() @@ -467,22 +478,27 @@ BOOL LLGestureStepWait::deserialize(LLDataPacker& dp) dp.unpackU32(mFlags, "flags"); return TRUE; } - -std::string LLGestureStepWait::getLabel() const +// *TODO: Translate +std::vector LLGestureStepWait::getLabel() const { - std::string label("--- Wait: "); + std::vector strings; + strings.push_back( "Wait" ); + +// std::string label("--- Wait: "); if (mFlags & WAIT_FLAG_TIME) { char buffer[64]; /* Flawfinder: ignore */ snprintf(buffer, sizeof(buffer), "%.1f seconds", (double)mWaitSeconds); /* Flawfinder: ignore */ - label += buffer; + strings.push_back(buffer); +// label += buffer; } else if (mFlags & WAIT_FLAG_ALL_ANIM) { - label += "until animations are done"; + strings.push_back("until animations are done"); + // label += "until animations are done"; } - return label; + return strings; } diff --git a/indra/llcharacter/llmultigesture.h b/indra/llcharacter/llmultigesture.h index eb15f600ca..fdffb35c31 100644 --- a/indra/llcharacter/llmultigesture.h +++ b/indra/llcharacter/llmultigesture.h @@ -130,7 +130,7 @@ public: virtual EStepType getType() = 0; // Return a user-readable label for this step - virtual std::string getLabel() const = 0; + virtual std::vector getLabel() const = 0; virtual S32 getMaxSerialSize() const = 0; virtual BOOL serialize(LLDataPacker& dp) const = 0; @@ -152,7 +152,7 @@ public: virtual EStepType getType() { return STEP_ANIMATION; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -175,7 +175,7 @@ public: virtual EStepType getType() { return STEP_SOUND; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -198,7 +198,7 @@ public: virtual EStepType getType() { return STEP_CHAT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; @@ -223,7 +223,7 @@ public: virtual EStepType getType() { return STEP_WAIT; } - virtual std::string getLabel() const; + virtual std::vector getLabel() const; virtual S32 getMaxSerialSize() const; virtual BOOL serialize(LLDataPacker& dp) const; diff --git a/indra/llcharacter/llpose.h b/indra/llcharacter/llpose.h index 5698f21614..2b976b219d 100644 --- a/indra/llcharacter/llpose.h +++ b/indra/llcharacter/llpose.h @@ -36,12 +36,14 @@ //----------------------------------------------------------------------------- // Header Files //----------------------------------------------------------------------------- -#include -#include "llmap.h" #include "lljointstate.h" #include "lljoint.h" +#include "llmap.h" +#include "llpointer.h" + #include +#include //----------------------------------------------------------------------------- diff --git a/indra/llcharacter/llvisualparam.h b/indra/llcharacter/llvisualparam.h index 3a0c1bbc77..25c41e8509 100644 --- a/indra/llcharacter/llvisualparam.h +++ b/indra/llcharacter/llvisualparam.h @@ -112,7 +112,7 @@ public: virtual void stopAnimating(BOOL set_by_user); // Interface methods - S32 getID() { return mID; } + S32 getID() const { return mID; } void setID(S32 id) { llassert(!mInfo); mID = id; } const std::string& getName() const { return mInfo->mName; } @@ -124,22 +124,22 @@ public: void setMaxDisplayName(const std::string& s) { mInfo->mMaxName = s; } void setMinDisplayName(const std::string& s) { mInfo->mMinName = s; } - EVisualParamGroup getGroup() { return mInfo->mGroup; } - F32 getMinWeight() { return mInfo->mMinWeight; } - F32 getMaxWeight() { return mInfo->mMaxWeight; } - F32 getDefaultWeight() { return mInfo->mDefaultWeight; } - ESex getSex() { return mInfo->mSex; } + EVisualParamGroup getGroup() const { return mInfo->mGroup; } + F32 getMinWeight() const { return mInfo->mMinWeight; } + F32 getMaxWeight() const { return mInfo->mMaxWeight; } + F32 getDefaultWeight() const { return mInfo->mDefaultWeight; } + ESex getSex() const { return mInfo->mSex; } - F32 getWeight() { return mIsAnimating ? mTargetWeight : mCurWeight; } - F32 getCurrentWeight() { return mCurWeight; } - F32 getLastWeight() { return mLastWeight; } - BOOL isAnimating() { return mIsAnimating; } + F32 getWeight() const { return mIsAnimating ? mTargetWeight : mCurWeight; } + F32 getCurrentWeight() const { return mCurWeight; } + F32 getLastWeight() const { return mLastWeight; } + BOOL isAnimating() const { return mIsAnimating; } LLVisualParam* getNextParam() { return mNext; } void setNextParam( LLVisualParam *next ); virtual void setAnimating(BOOL is_animating) { mIsAnimating = is_animating; } - BOOL getAnimating() { return mIsAnimating; } + BOOL getAnimating() const { return mIsAnimating; } protected: F32 mCurWeight; // current weight diff --git a/indra/llcommon/CMakeLists.txt b/indra/llcommon/CMakeLists.txt index beac8df636..bf46c2c038 100644 --- a/indra/llcommon/CMakeLists.txt +++ b/indra/llcommon/CMakeLists.txt @@ -3,7 +3,9 @@ project(llcommon) include(00-Common) +include(LLAddBuildTest) include(LLCommon) +include(Boost) include_directories( ${EXPAT_INCLUDE_DIRS} @@ -11,7 +13,14 @@ include_directories( ${ZLIB_INCLUDE_DIRS} ) +# add_executable(lltreeiterators lltreeiterators.cpp) +# +# target_link_libraries(lltreeiterators +# ${LLCOMMON_LIBRARIES}) + set(llcommon_SOURCE_FILES + llallocator.cpp + llallocator_heap_profile.cpp llapp.cpp llapr.cpp llassettype.cpp @@ -40,11 +49,14 @@ set(llcommon_SOURCE_FILES llmd5.cpp llmemory.cpp llmemorystream.cpp + llmemtype.cpp llmetrics.cpp llmortician.cpp + llptrto.cpp llprocessor.cpp llqueuedthread.cpp llrand.cpp + llrefcount.cpp llrun.cpp llsd.cpp llsdserialize.cpp @@ -52,6 +64,7 @@ set(llcommon_SOURCE_FILES llsdutil.cpp llsecondlifeurls.cpp llstat.cpp + llstacktrace.cpp llstreamtools.cpp llstring.cpp llstringtable.cpp @@ -78,6 +91,8 @@ set(llcommon_HEADER_FILES indra_constants.h linden_common.h linked_lists.h + llallocator.h + llallocator_heap_profile.h llagentconstants.h llapp.h llapr.h @@ -98,8 +113,11 @@ set(llcommon_HEADER_FILES lldate.h lldefs.h lldependencies.h + lldeleteutils.h lldepthstack.h + lldictionary.h lldlinked.h + lldoubledispatch.h lldqueueptr.h llendianswizzle.h llenum.h @@ -121,6 +139,7 @@ set(llcommon_HEADER_FILES llheartbeat.h llhttpstatuscodes.h llindexedqueue.h + llinstancetracker.h llkeythrottle.h lllazy.h lllinkedqueue.h @@ -137,23 +156,30 @@ set(llcommon_HEADER_FILES llmetrics.h llmortician.h llnametable.h + llpointer.h llpreprocessor.h llpriqueuemap.h llprocessor.h llptrskiplist.h llptrskipmap.h + llptrto.h llqueuedthread.h llrand.h + llrefcount.h llrun.h + llrefcount.h + llsafehandle.h llsd.h llsdserialize.h llsdserialize_xml.h llsdutil.h llsecondlifeurls.h llsimplehash.h + llsingleton.h llskiplist.h llskipmap.h llstack.h + llstacktrace.h llstat.h llstatenums.h llstl.h @@ -164,6 +190,7 @@ set(llcommon_HEADER_FILES llsys.h llthread.h lltimer.h + lltreeiterators.h lluri.h lluuid.h lluuidhashmap.h @@ -199,6 +226,8 @@ target_link_libraries( ${APR_LIBRARIES} ${EXPAT_LIBRARIES} ${ZLIB_LIBRARIES} + ${BOOST_PROGRAM_OPTIONS_LIBRARY} + ${BOOST_REGEX_LIBRARY} ) include(LLAddBuildTest) @@ -208,3 +237,8 @@ SET(llcommon_TEST_SOURCE_FILES ) LL_ADD_PROJECT_UNIT_TESTS(llcommon "${llcommon_TEST_SOURCE_FILES}") +# *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/is_approx_equal_fraction.h b/indra/llcommon/is_approx_equal_fraction.h index f95b148590..d369fbc5b3 100644 --- a/indra/llcommon/is_approx_equal_fraction.h +++ b/indra/llcommon/is_approx_equal_fraction.h @@ -7,7 +7,30 @@ * making llcommon depend on llmath. * * $LicenseInfo:firstyear=2009&license=viewergpl$ + * * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ diff --git a/indra/llcommon/linden_common.h b/indra/llcommon/linden_common.h index f9d5877ab2..9adf24a492 100644 --- a/indra/llcommon/linden_common.h +++ b/indra/llcommon/linden_common.h @@ -33,6 +33,11 @@ #ifndef LL_LINDEN_COMMON_H #define LL_LINDEN_COMMON_H +// *NOTE: Please keep includes here to a minimum! +// +// Files included here are included in every library .cpp file and +// are not precompiled. + #if defined(LL_WINDOWS) && defined(_DEBUG) # if _MSC_VER >= 1400 // Visual C++ 2005 or later # define _CRTDBG_MAP_ALLOC @@ -51,23 +56,22 @@ #include #include #include -#include -#include +#include -// Work Microsoft compiler warnings +// Work around Microsoft compiler warnings in STL headers #ifdef LL_WINDOWS #pragma warning (disable : 4702) // unreachable code #pragma warning (disable : 4244) // conversion from time_t to S32 #endif // LL_WINDOWS -#include #include #include #include #include #ifdef LL_WINDOWS -#pragma warning (3 : 4702) // we like level 3, not 4 +// 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) ) @@ -78,6 +82,7 @@ #endif // LL_WINDOWS // Linden only libs in alpha-order other than stdtypes.h +// *NOTE: Please keep includes here to a minimum, see above. #include "stdtypes.h" #include "lldefs.h" #include "llerror.h" @@ -85,8 +90,5 @@ #include "llfasttimer.h" #include "llfile.h" #include "llformat.h" -#include "llstring.h" -#include "llsys.h" -#include "lltimer.h" #endif diff --git a/indra/llcommon/llallocator.cpp b/indra/llcommon/llallocator.cpp new file mode 100644 index 0000000000..eed9d1e7db --- /dev/null +++ b/indra/llcommon/llallocator.cpp @@ -0,0 +1,140 @@ +/** + * @file llallocator.cpp + * @brief Implementation of the LLAllocator class. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llallocator.h" + +#if LL_USE_TCMALLOC + +#include "google/heap-profiler.h" +#include "google/commandlineflags_public.h" + +DECLARE_bool(heap_profile_use_stack_trace); +//DECLARE_double(tcmalloc_release_rate); + +// static +void LLAllocator::pushMemType(S32 type) +{ + if(isProfiling()) + { + PushMemType(type); + } +} + +// static +S32 LLAllocator::popMemType() +{ + if (isProfiling()) + { + return PopMemType(); + } + else + { + return -1; + } +} + +void LLAllocator::setProfilingEnabled(bool should_enable) +{ + // NULL disables dumping to disk + static char const * const PREFIX = NULL; + if(should_enable) + { + HeapProfilerSetUseStackTrace(false); + HeapProfilerStart(PREFIX); + } + else + { + HeapProfilerStop(); + } +} + +// static +bool LLAllocator::isProfiling() +{ + return IsHeapProfilerRunning(); +} + +std::string LLAllocator::getRawProfile() +{ + // *TODO - fix google-perftools to accept an buffer to avoid this + // malloc-copy-free cycle. + char * buffer = GetHeapProfile(); + std::string ret = buffer; + free(buffer); + return ret; +} + +#else // LL_USE_TCMALLOC + +// +// stub implementations for when tcmalloc is disabled +// + +// static +void LLAllocator::pushMemType(S32 type) +{ +} + +// static +S32 LLAllocator::popMemType() +{ + return -1; +} + +void LLAllocator::setProfilingEnabled(bool should_enable) +{ +} + +// static +bool LLAllocator::isProfiling() +{ + return false; +} + +std::string LLAllocator::getRawProfile() +{ + return std::string(); +} + +#endif // LL_USE_TCMALLOC + +LLAllocatorHeapProfile const & LLAllocator::getProfile() +{ + mProf.mLines.clear(); + + // *TODO - avoid making all these extra copies of things... + std::string prof_text = getRawProfile(); + //std::cout << prof_text << std::endl; + mProf.parse(prof_text); + return mProf; +} diff --git a/indra/llcommon/llallocator.h b/indra/llcommon/llallocator.h new file mode 100644 index 0000000000..2b70fee0b8 --- /dev/null +++ b/indra/llcommon/llallocator.h @@ -0,0 +1,63 @@ +/** + * @file llallocator.h + * @brief Declaration of the LLAllocator class. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLALLOCATOR_H +#define LL_LLALLOCATOR_H + +#include + +#include "llmemtype.h" +#include "llallocator_heap_profile.h" + +class LLAllocator { + friend class LLMemoryView; + friend class LLMemType; + +private: + static void pushMemType(S32 type); + static S32 popMemType(); + +public: + void setProfilingEnabled(bool should_enable); + + static bool isProfiling(); + + LLAllocatorHeapProfile const & getProfile(); + +private: + std::string getRawProfile(); + +private: + LLAllocatorHeapProfile mProf; +}; + +#endif // LL_LLALLOCATOR_H diff --git a/indra/llcommon/llallocator_heap_profile.cpp b/indra/llcommon/llallocator_heap_profile.cpp new file mode 100644 index 0000000000..d82ee9ed81 --- /dev/null +++ b/indra/llcommon/llallocator_heap_profile.cpp @@ -0,0 +1,149 @@ +/** + * @file llallocator_heap_profile.cpp + * @brief Implementation of the parser for tcmalloc heap profile data. + * @author Brad Kittenbrink + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" +#include "llallocator_heap_profile.h" + +#if LL_MSVC +// disable warning about boost::lexical_cast returning uninitialized data +// when it fails to parse the string +#pragma warning (disable:4701) +#endif + +#include +#include +#include +#include + +static const std::string HEAP_PROFILE_MAGIC_STR = "heap profile:"; + +static bool is_separator(char c) +{ + return isspace(c) || c == '[' || c == ']' || c == ':'; +} + +void LLAllocatorHeapProfile::parse(std::string const & prof_text) +{ + // a typedef for handling a token in the string buffer + // it's a begin/end pair of string::const_iterators + typedef boost::iterator_range range_t; + + mLines.clear(); + + if(prof_text.compare(0, HEAP_PROFILE_MAGIC_STR.length(), HEAP_PROFILE_MAGIC_STR) != 0) + { + // *TODO - determine if there should be some better error state than + // mLines being empty. -brad + llwarns << "invalid heap profile data passed into parser." << llendl; + return; + } + + std::vector< range_t > prof_lines; + + std::string::const_iterator prof_begin = prof_text.begin() + HEAP_PROFILE_MAGIC_STR.length(); + + range_t prof_range(prof_begin, prof_text.end()); + boost::algorithm::split(prof_lines, + prof_range, + boost::bind(std::equal_to(), '\n', _1)); + + std::vector< range_t >::const_iterator i; + for(i = prof_lines.begin(); i != prof_lines.end() && !i->empty(); ++i) + { + range_t const & line_text = *i; + + std::vector line_elems; + + boost::algorithm::split(line_elems, + line_text, + is_separator); + + std::vector< range_t >::iterator j; + j = line_elems.begin(); + + while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens + llassert_always(j != line_elems.end()); + U32 live_count = boost::lexical_cast(*j); + ++j; + + while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens + llassert_always(j != line_elems.end()); + U64 live_size = boost::lexical_cast(*j); + ++j; + + while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens + llassert_always(j != line_elems.end()); + U32 tot_count = boost::lexical_cast(*j); + ++j; + + while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens + llassert_always(j != line_elems.end()); + U64 tot_size = boost::lexical_cast(*j); + ++j; + + while(j != line_elems.end() && j->empty()) { ++j; } // skip any separator tokens + llassert_always(j != line_elems.end()); + ++j; // skip the '@' + + mLines.push_back(line(live_count, live_size, tot_count, tot_size)); + line & current_line = mLines.back(); + + for(; j != line_elems.end(); ++j) + { + if(!j->empty()) { + U32 marker = boost::lexical_cast(*j); + current_line.mTrace.push_back(marker); + } + } + } + + // *TODO - parse MAPPED_LIBRARIES section here if we're ever interested in it +} + +void LLAllocatorHeapProfile::dump(std::ostream & out) const +{ + lines_t::const_iterator i; + for(i = mLines.begin(); i != mLines.end(); ++i) + { + out << i->mLiveCount << ": " << i->mLiveSize << '[' << i->mTotalCount << ": " << i->mTotalSize << "] @"; + + stack_trace::const_iterator j; + for(j = i->mTrace.begin(); j != i->mTrace.end(); ++j) + { + out << ' ' << *j; + } + out << '\n'; + } + out.flush(); +} + diff --git a/indra/llcommon/llallocator_heap_profile.h b/indra/llcommon/llallocator_heap_profile.h new file mode 100644 index 0000000000..19758df544 --- /dev/null +++ b/indra/llcommon/llallocator_heap_profile.h @@ -0,0 +1,77 @@ +/** + * @file llallocator_heap_profile.h + * @brief Declaration of the parser for tcmalloc heap profile data. + * @author Brad Kittenbrink + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLALLOCATOR_HEAP_PROFILE_H +#define LL_LLALLOCATOR_HEAP_PROFILE_H + +#include "stdtypes.h" + +#include +#include + +class LLAllocatorHeapProfile +{ +public: + typedef int stack_marker; + + typedef std::vector stack_trace; + + struct line { + line(U32 live_count, U64 live_size, U32 tot_count, U64 tot_size) : + mLiveSize(live_size), + mTotalSize(tot_size), + mLiveCount(live_count), + mTotalCount(tot_count) + { + } + U64 mLiveSize, mTotalSize; + U32 mLiveCount, mTotalCount; + stack_trace mTrace; + }; + + typedef std::vector lines_t; + + LLAllocatorHeapProfile() + { + } + + void parse(std::string const & prof_text); + + void dump(std::ostream & out) const; + +public: + lines_t mLines; +}; + + +#endif // LL_LLALLOCATOR_HEAP_PROFILE_H diff --git a/indra/llcommon/llassettype.cpp b/indra/llcommon/llassettype.cpp index cf3bf89b4f..6715b6722d 100644 --- a/indra/llcommon/llassettype.cpp +++ b/indra/llcommon/llassettype.cpp @@ -33,145 +33,112 @@ #include "linden_common.h" #include "llassettype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llsingleton.h" -#include "llstring.h" -#include "lltimer.h" - -// I added lookups for exact text of asset type enums in addition to the ones below, so shoot me. -Steve +///---------------------------------------------------------------------------- +/// Class LLAssetType +///---------------------------------------------------------------------------- +struct AssetEntry : public LLDictionaryEntry +{ + AssetEntry(const char *desc_name, + const char *type_name, // 8 character limit! + const char *human_name, + const char *category_name, // used by llinventorymodel when creating new categories + EDragAndDropType dad_type); + + // limited to 8 characters + const char *mTypeName; + // human readable form. Put as many printable characters you want in each one. + // (c.f. llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES). + const char *mHumanName; + const char *mCategoryName; + EDragAndDropType mDadType; +}; -struct asset_info_t +class LLAssetDictionary : public LLSingleton, + public LLDictionary { - LLAssetType::EType type; - const char* desc; +public: + LLAssetDictionary(); }; -asset_info_t asset_types[] = +LLAssetDictionary::LLAssetDictionary() { - { LLAssetType::AT_TEXTURE, "TEXTURE" }, - { LLAssetType::AT_SOUND, "SOUND" }, - { LLAssetType::AT_CALLINGCARD, "CALLINGCARD" }, - { LLAssetType::AT_LANDMARK, "LANDMARK" }, - { LLAssetType::AT_SCRIPT, "SCRIPT" }, - { LLAssetType::AT_CLOTHING, "CLOTHING" }, - { LLAssetType::AT_OBJECT, "OBJECT" }, - { LLAssetType::AT_NOTECARD, "NOTECARD" }, - { LLAssetType::AT_CATEGORY, "CATEGORY" }, - { LLAssetType::AT_ROOT_CATEGORY, "ROOT_CATEGORY" }, - { LLAssetType::AT_LSL_TEXT, "LSL_TEXT" }, - { LLAssetType::AT_LSL_BYTECODE, "LSL_BYTECODE" }, - { LLAssetType::AT_TEXTURE_TGA, "TEXTURE_TGA" }, - { LLAssetType::AT_BODYPART, "BODYPART" }, - { LLAssetType::AT_TRASH, "TRASH" }, - { LLAssetType::AT_SNAPSHOT_CATEGORY, "SNAPSHOT_CATEGORY" }, - { LLAssetType::AT_LOST_AND_FOUND, "LOST_AND_FOUND" }, - { LLAssetType::AT_SOUND_WAV, "SOUND_WAV" }, - { LLAssetType::AT_IMAGE_TGA, "IMAGE_TGA" }, - { LLAssetType::AT_IMAGE_JPEG, "IMAGE_JPEG" }, - { LLAssetType::AT_ANIMATION, "ANIMATION" }, - { LLAssetType::AT_GESTURE, "GESTURE" }, - { LLAssetType::AT_SIMSTATE, "SIMSTATE" }, - { LLAssetType::AT_NONE, "NONE" }, + addEntry(LLAssetType::AT_TEXTURE, new AssetEntry("TEXTURE", "texture", "texture", "Textures", DAD_TEXTURE)); + addEntry(LLAssetType::AT_SOUND, new AssetEntry("SOUND", "sound", "sound", "Sounds", DAD_SOUND)); + addEntry(LLAssetType::AT_CALLINGCARD, new AssetEntry("CALLINGCARD", "callcard", "calling card", "Calling Cards", DAD_CALLINGCARD)); + addEntry(LLAssetType::AT_LANDMARK, new AssetEntry("LANDMARK", "landmark", "landmark", "Landmarks", DAD_LANDMARK)); + addEntry(LLAssetType::AT_SCRIPT, new AssetEntry("SCRIPT", "script", "legacy script", "Scripts", DAD_NONE)); + addEntry(LLAssetType::AT_CLOTHING, new AssetEntry("CLOTHING", "clothing", "clothing", "Clothing", DAD_CLOTHING)); + addEntry(LLAssetType::AT_OBJECT, new AssetEntry("OBJECT", "object", "object", "Objects", DAD_OBJECT)); + addEntry(LLAssetType::AT_NOTECARD, new AssetEntry("NOTECARD", "notecard", "note card", "Notecards", DAD_NOTECARD)); + addEntry(LLAssetType::AT_CATEGORY, new AssetEntry("CATEGORY", "category", "folder", "New Folder", DAD_CATEGORY)); + addEntry(LLAssetType::AT_ROOT_CATEGORY, new AssetEntry("ROOT_CATEGORY", "root", "root", "Inventory", DAD_ROOT_CATEGORY)); + addEntry(LLAssetType::AT_LSL_TEXT, new AssetEntry("LSL_TEXT", "lsltext", "lsl2 script", "Scripts", DAD_SCRIPT)); + addEntry(LLAssetType::AT_LSL_BYTECODE, new AssetEntry("LSL_BYTECODE", "lslbyte", "lsl bytecode", "Scripts", DAD_NONE)); + addEntry(LLAssetType::AT_TEXTURE_TGA, new AssetEntry("TEXTURE_TGA", "txtr_tga", "tga texture", "Uncompressed Images", DAD_NONE)); + addEntry(LLAssetType::AT_BODYPART, new AssetEntry("BODYPART", "bodypart", "body part", "Body Parts", DAD_BODYPART)); + addEntry(LLAssetType::AT_TRASH, new AssetEntry("TRASH", "trash", "trash", "Trash", DAD_NONE)); + addEntry(LLAssetType::AT_SNAPSHOT_CATEGORY, new AssetEntry("SNAPSHOT_CATEGORY", "snapshot", "snapshot", "Photo Album", DAD_NONE)); + addEntry(LLAssetType::AT_LOST_AND_FOUND, new AssetEntry("LOST_AND_FOUND", "lstndfnd", "lost and found", "Lost And Found", DAD_NONE)); + addEntry(LLAssetType::AT_SOUND_WAV, new AssetEntry("SOUND_WAV", "snd_wav", "sound", "Uncompressed Sounds", DAD_NONE)); + addEntry(LLAssetType::AT_IMAGE_TGA, new AssetEntry("IMAGE_TGA", "img_tga", "targa image", "Uncompressed Images", DAD_NONE)); + addEntry(LLAssetType::AT_IMAGE_JPEG, new AssetEntry("IMAGE_JPEG", "jpeg", "jpeg image", "Uncompressed Images", DAD_NONE)); + addEntry(LLAssetType::AT_ANIMATION, new AssetEntry("ANIMATION", "animatn", "animation", "Animations", DAD_ANIMATION)); + addEntry(LLAssetType::AT_GESTURE, new AssetEntry("GESTURE", "gesture", "gesture", "Gestures", DAD_GESTURE)); + addEntry(LLAssetType::AT_SIMSTATE, new AssetEntry("SIMSTATE", "simstate", "simstate", "New Folder", DAD_NONE)); + addEntry(LLAssetType::AT_LINK, new AssetEntry("LINK", "link", "symbolic link", "New Folder", DAD_NONE)); + addEntry(LLAssetType::AT_FAVORITE, new AssetEntry("FAVORITE", "favorite", "favorite", "favorite", DAD_NONE)); + addEntry(LLAssetType::AT_NONE, new AssetEntry("NONE", "-1", NULL, "New Folder", DAD_NONE)); }; -LLAssetType::EType LLAssetType::getType(const std::string& sin) +AssetEntry::AssetEntry(const char *desc_name, + const char *type_name, + const char *human_name, + const char *category_name, + EDragAndDropType dad_type) : + LLDictionaryEntry(desc_name), + mTypeName(type_name), + mHumanName(human_name), + mCategoryName(category_name), + mDadType(dad_type) { - std::string s = sin; - LLStringUtil::toUpper(s); - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (info->type == LLAssetType::AT_NONE) - break; - if (s == info->desc) - return info->type; - } - return LLAssetType::AT_NONE; + llassert(strlen(mTypeName) <= 8); } -std::string LLAssetType::getDesc(LLAssetType::EType type) +// static +LLAssetType::EType LLAssetType::getType(const std::string& desc_name) { - for (S32 idx = 0; ;idx++) - { - asset_info_t* info = asset_types + idx; - if (type == info->type) - return info->desc; - if (info->type == LLAssetType::AT_NONE) - break; - } - return "BAD TYPE"; + std::string s = desc_name; + LLStringUtil::toUpper(s); + return LLAssetDictionary::getInstance()->lookup(s); } -//============================================================================ - -// The asset type names are limited to 8 characters. // static -const char* LLAssetType::mAssetTypeNames[LLAssetType::AT_COUNT] = -{ - "texture", - "sound", - "callcard", - "landmark", - "script", - "clothing", - "object", - "notecard", - "category", - "root", - "lsltext", - "lslbyte", - "txtr_tga",// Intentionally spelled this way. Limited to eight characters. - "bodypart", - "trash", - "snapshot", - "lstndfnd", - "snd_wav", - "img_tga", - "jpeg", - "animatn", - "gesture", - "simstate" -}; - -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also llinventory.cpp INVENTORY_TYPE_HUMAN_NAMES -const char* LLAssetType::mAssetTypeHumanNames[LLAssetType::AT_COUNT] = +const std::string &LLAssetType::getDesc(LLAssetType::EType asset_type) +{ + const AssetEntry *entry = LLAssetDictionary::getInstance()->lookup(asset_type); + if (entry) { - "texture", - "sound", - "calling card", - "landmark", - "legacy script", - "clothing", - "object", - "note card", - "folder", - "root", - "lsl2 script", - "lsl bytecode", - "tga texture", - "body part", - "trash", - "snapshot", - "lost and found", - "sound", - "targa image", - "jpeg image", - "animation", - "gesture", - "simstate" -}; - -///---------------------------------------------------------------------------- -/// class LLAssetType -///---------------------------------------------------------------------------- + return entry->mName; + } + else + { + static const std::string error_string = "BAD TYPE"; + return error_string; + } +} // static -const char* LLAssetType::lookup( LLAssetType::EType type ) +const char *LLAssetType::lookup(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeNames[ S32( type ) ]; + return entry->mTypeName; } else { @@ -185,25 +152,30 @@ LLAssetType::EType LLAssetType::lookup( const char* name ) return lookup(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookup( const std::string& name ) +LLAssetType::EType LLAssetType::lookup(const std::string& type_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeNames[i] ) + const AssetEntry *entry = iter->second; + if (type_name == entry->mTypeName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } // static -const char* LLAssetType::lookupHumanReadable(LLAssetType::EType type) +const char *LLAssetType::lookupHumanReadable(LLAssetType::EType asset_type) { - if( (type >= 0) && (type < AT_COUNT )) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - return mAssetTypeHumanNames[S32(type)]; + return entry->mHumanName; } else { @@ -217,44 +189,51 @@ LLAssetType::EType LLAssetType::lookupHumanReadable( const char* name ) return lookupHumanReadable(ll_safe_string(name)); } -LLAssetType::EType LLAssetType::lookupHumanReadable( const std::string& name ) +LLAssetType::EType LLAssetType::lookupHumanReadable(const std::string& readable_name) { - for( S32 i = 0; i < AT_COUNT; i++ ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + for (LLAssetDictionary::const_iterator iter = dict->begin(); + iter != dict->end(); + iter++) { - if( name == mAssetTypeHumanNames[i] ) + const AssetEntry *entry = iter->second; + if (readable_name == entry->mHumanName) { - // match - return (EType)i; + return iter->first; } } return AT_NONE; } -EDragAndDropType LLAssetType::lookupDragAndDropType( EType asset ) +// static +const char *LLAssetType::lookupCategoryName(LLAssetType::EType asset_type) { - switch( asset ) + const LLAssetDictionary *dict = LLAssetDictionary::getInstance(); + const AssetEntry *entry = dict->lookup(asset_type); + if (entry) { - case AT_TEXTURE: return DAD_TEXTURE; - case AT_SOUND: return DAD_SOUND; - case AT_CALLINGCARD: return DAD_CALLINGCARD; - case AT_LANDMARK: return DAD_LANDMARK; - case AT_SCRIPT: return DAD_NONE; - case AT_CLOTHING: return DAD_CLOTHING; - case AT_OBJECT: return DAD_OBJECT; - case AT_NOTECARD: return DAD_NOTECARD; - case AT_CATEGORY: return DAD_CATEGORY; - case AT_ROOT_CATEGORY: return DAD_ROOT_CATEGORY; - case AT_LSL_TEXT: return DAD_SCRIPT; - case AT_BODYPART: return DAD_BODYPART; - case AT_ANIMATION: return DAD_ANIMATION; - case AT_GESTURE: return DAD_GESTURE; - default: return DAD_NONE; - }; + return entry->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. Generate a good default description -void LLAssetType::generateDescriptionFor(LLAssetType::EType type, - std::string& desc) +void LLAssetType::generateDescriptionFor(LLAssetType::EType asset_type, + std::string& description) { const S32 BUF_SIZE = 30; char time_str[BUF_SIZE]; /* Flawfinder: ignore */ @@ -262,6 +241,6 @@ void LLAssetType::generateDescriptionFor(LLAssetType::EType type, time(&now); memset(time_str, '\0', BUF_SIZE); strftime(time_str, BUF_SIZE - 1, "%Y-%m-%d %H:%M:%S ", localtime(&now)); - desc.assign(time_str); - desc.append(LLAssetType::lookupHumanReadable(type)); + description.assign(time_str); + description.append(LLAssetType::lookupHumanReadable(asset_type)); } diff --git a/indra/llcommon/llassettype.h b/indra/llcommon/llassettype.h index 4077b8d2c1..2f54031688 100644 --- a/indra/llcommon/llassettype.h +++ b/indra/llcommon/llassettype.h @@ -30,8 +30,8 @@ * $/LicenseInfo$ */ -#ifndef LL_LLASSETTYPE -#define LL_LLASSETTYPE +#ifndef LL_LLASSETTYPE_H +#define LL_LLASSETTYPE_H #include @@ -42,137 +42,142 @@ class LLAssetType public: enum EType { - // Used for painting the faces of geometry. - // Stored in typical j2c stream format AT_TEXTURE = 0, + // Used for painting the faces of geometry. + // Stored in typical j2c stream format. - // Used to fill the aural spectrum. AT_SOUND = 1, + // Used to fill the aural spectrum. - // Links instant message access to the user on the card. eg, a - // card for yourself, a card for linden support, a card for - // the guy you were talking to in the coliseum. AT_CALLINGCARD = 2, + // Links instant message access to the user on the card. + // : E.G. A card for yourself, for linden support, for + // : the guy you were talking to in the coliseum. - // Links to places in the world with location and a screen - // shot or image saved. eg, home, linden headquarters, the - // coliseum, or destinations where we want to increase - // traffic. AT_LANDMARK = 3, + // Links to places in the world with location and a screen shot or image saved. + // : E.G. Home, linden headquarters, the coliseum, destinations where + // : we want to increase traffic. - // Valid scripts that can be attached to an object. eg. open a - // door, jump into the air. AT_SCRIPT = 4, + // Valid scripts that can be attached to an object. + // : E.G. Open a door, jump into the air. - // A collection of textures and parameters that can be worn - // by an avatar. AT_CLOTHING = 5, + // A collection of textures and parameters that can be worn by an avatar. - // Any combination of textures, sounds, and scripts that are - // associated with a fixed piece of geometry. eg, a hot tub, a - // house with working door. AT_OBJECT = 6, + // Any combination of textures, sounds, and scripts that are + // associated with a fixed piece of geometry. + // : E.G. A hot tub, a house with working door. - // Just text AT_NOTECARD = 7, + // Just text. - // A category holds a collection of inventory items. It's - // treated as an item in the inventory, and therefore needs a - // type. AT_CATEGORY = 8, + // Holds a collection of inventory items. + // It's treated as an item in the inventory and therefore needs a type. - // A root category is a user's root inventory category. We - // decided to expose it visually, so it seems logical to fold - // it into the asset types. AT_ROOT_CATEGORY = 9, + // A user's root inventory category. + // We decided to expose it visually, so it seems logical to fold + // it into the asset types. - // The LSL is the brand spanking new scripting language. We've - // split it into a text and bytecode representation. AT_LSL_TEXT = 10, AT_LSL_BYTECODE = 11, + // The LSL is the scripting language. + // We've split it into a text and bytecode representation. - // uncompressed TGA texture AT_TEXTURE_TGA = 12, + // Uncompressed TGA texture. - // A collection of textures and parameters that can be worn - // by an avatar. AT_BODYPART = 13, + // A collection of textures and parameters that can be worn by an avatar. - // This asset type is meant to only be used as a marker for a - // category preferred type. Using this, we can throw things in - // the trash before completely deleting. AT_TRASH = 14, + // Only to be used as a marker for a category preferred type. + // Using this, we can throw things in the trash before completely deleting. - // This is a marker for a folder meant for snapshots. No - // actual assets will be snapshots, though if there were, you - // could interpret them as textures. AT_SNAPSHOT_CATEGORY = 15, + // A marker for a folder meant for snapshots. + // No actual assets will be snapshots, though if there were, you + // could interpret them as textures. - // This is used to stuff lost&found items into AT_LOST_AND_FOUND = 16, + // Used to stuff lost&found items into. - // uncompressed sound AT_SOUND_WAV = 17, + // Uncompressed sound. - // uncompressed image, non-square, and not appropriate for use - // as a texture. AT_IMAGE_TGA = 18, + // Uncompressed image, non-square. + // Not appropriate for use as a texture. - // compressed image, non-square, and not appropriate for use - // as a texture. AT_IMAGE_JPEG = 19, + // Compressed image, non-square. + // Not appropriate for use as a texture. - // animation AT_ANIMATION = 20, + // Animation. - // gesture, sequence of animations, sounds, chat, wait steps AT_GESTURE = 21, + // Gesture, sequence of animations, sounds, chat, wait steps. - // simstate file AT_SIMSTATE = 22, + // Simstate file. + + AT_LINK = 23, + // Inventory symbolic link + + AT_FAVORITE = 24, + // favorite items // +*********************************************+ // | TO ADD AN ELEMENT TO THIS ENUM: | - // +*********************************************+ + // +************************************************+ // | 1. INSERT BEFORE AT_COUNT | // | 2. INCREMENT AT_COUNT BY 1 | // | 3. ADD TO LLAssetType::mAssetTypeNames | // | 4. ADD TO LLAssetType::mAssetTypeHumanNames | // +*********************************************+ - AT_COUNT = 23, + AT_COUNT = 25, AT_NONE = -1 }; // machine transation between type and strings static EType lookup(const char* name); // safe conversion to std::string, *TODO: deprecate - static EType lookup(const std::string& name); - static const char* lookup(EType type); + static EType lookup(const std::string& type_name); + static const char* lookup(EType asset_type); // translation from a type to a human readable form. - static EType lookupHumanReadable( const char* name ); // safe conversion to std::string, *TODO: deprecate - static EType lookupHumanReadable( const std::string& name ); - static const char* lookupHumanReadable(EType type); + static EType lookupHumanReadable(const char* desc_name); // safe conversion to std::string, *TODO: deprecate + static EType lookupHumanReadable(const std::string& readable_name); + static const char* lookupHumanReadable(EType asset_type); - static EDragAndDropType lookupDragAndDropType( EType ); + static const char* lookupCategoryName(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 type, - std::string& desc); - - static EType getType(const std::string& sin); - static std::string getDesc(EType type); + 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); + + /* 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 ) {} - -private: - static const char* mAssetTypeNames[]; - static const char* mAssetTypeHumanNames[]; + LLAssetType() {} + ~LLAssetType() {} }; -#endif // LL_LLASSETTYPE +#endif // LL_LLASSETTYPE_H diff --git a/indra/llcommon/llboost.h b/indra/llcommon/llboost.h index 4df9dbf3bd..f4bfc2bfa2 100644 --- a/indra/llcommon/llboost.h +++ b/indra/llcommon/llboost.h @@ -46,4 +46,19 @@ */ typedef boost::tokenizer > boost_tokenizer; +// Useful combiner for boost signals that retturn a vool (e.g. validation) +// returns false if any of the callbacks return false +struct boost_boolean_combiner +{ + typedef bool result_type; + template + bool operator()(InputIterator first, InputIterator last) const + { + bool res = true; + while (first != last) + res &= *first++; + return res; + } +}; + #endif // LL_LLBOOST_H diff --git a/indra/llcommon/llcommon.cpp b/indra/llcommon/llcommon.cpp index 2cbb71855f..36a0018995 100644 --- a/indra/llcommon/llcommon.cpp +++ b/indra/llcommon/llcommon.cpp @@ -32,6 +32,8 @@ #include "linden_common.h" #include "llcommon.h" + +#include "llmemory.h" #include "llthread.h" //static diff --git a/indra/llcommon/llcommon.h b/indra/llcommon/llcommon.h index 5f77988336..a1808e8a6c 100644 --- a/indra/llcommon/llcommon.h +++ b/indra/llcommon/llcommon.h @@ -32,9 +32,8 @@ #ifndef LL_COMMON_H #define LL_COMMON_H -#include "llmemory.h" +// *TODO: remove these? #include "llapr.h" -// #include "llframecallbackmanager.h" #include "lltimer.h" #include "llfile.h" diff --git a/indra/llcommon/lldate.cpp b/indra/llcommon/lldate.cpp index 41a3af398f..7bc9e16bc9 100644 --- a/indra/llcommon/lldate.cpp +++ b/indra/llcommon/lldate.cpp @@ -38,10 +38,13 @@ #include "apr_time.h" #include +#include +#include #include #include #include "lltimer.h" +#include "llstring.h" static const F64 DATE_EPOCH = 0.0; @@ -88,45 +91,36 @@ std::string LLDate::asString() const // is one of the standards used and the prefered format std::string LLDate::asRFC1123() const { - std::ostringstream stream; - toHTTPDateStream(stream); - return stream.str(); + return toHTTPDateString (std::string ("%A, %d %b %Y %H:%M:%S GMT")); } -void LLDate::toHTTPDateStream(std::ostream& s) const +std::string LLDate::toHTTPDateString (std::string fmt) const { - // http://apr.apache.org/docs/apr/0.9/group__apr__time.html - apr_time_t time = (apr_time_t)(mSecondsSinceEpoch * LL_APR_USEC_PER_SEC); + std::ostringstream stream; + time_t locSeconds = (time_t) mSecondsSinceEpoch; + struct tm * gmt = gmtime (&locSeconds); - apr_time_exp_t exp_time ; //Apache time module + stream.imbue (std::locale(LLStringUtil::getLocale().c_str())); + toHTTPDateStream (stream, gmt, fmt); + return stream.str(); +} - if (apr_time_exp_gmt(&exp_time, time) != APR_SUCCESS) - { - // Return Epoch UTC date - s << "Thursday, 01 Jan 1970 00:00:00 GMT" ; - return; - } +std::string LLDate::toHTTPDateString (tm * gmt, std::string fmt) +{ + std::ostringstream stream; + stream.imbue (std::locale(LLStringUtil::getLocale().c_str())); + toHTTPDateStream (stream, gmt, fmt); + return stream.str(); +} - s << std::dec << std::setfill('0'); -#if( LL_WINDOWS || __GNUC__ > 2) - s << std::right ; -#else - s.setf(ios::right); -#endif - std::string day = weekdays[exp_time.tm_wday]; - std::string month = months[exp_time.tm_mon]; - - s << std::setw(day.length()) << (day) - << ", " << std::setw(2) << (exp_time.tm_mday) - << ' ' << std::setw(month.length()) << (month) - << ' ' << std::setw(4) << (exp_time.tm_year + 1900) - << ' ' << std::setw(2) << (exp_time.tm_hour) - << ':' << std::setw(2) << (exp_time.tm_min) - << ':' << std::setw(2) << (exp_time.tm_sec) - << " GMT"; +void LLDate::toHTTPDateStream(std::ostream& s, tm * gmt, std::string fmt) +{ + using namespace std; - // RFC 1123 date does not use microseconds - //llinfos << "Date in RFC 1123 format is " << s << llendl; + const char * pBeg = fmt.c_str(); + const char * pEnd = pBeg + fmt.length(); + const time_put& tp = use_facet >(s.getloc()); + tp.put (s, s, s.fill(), gmt, pBeg, pEnd); } void LLDate::toStream(std::ostream& s) const diff --git a/indra/llcommon/lldate.h b/indra/llcommon/lldate.h index 7cc9c8aceb..23d3b900f8 100644 --- a/indra/llcommon/lldate.h +++ b/indra/llcommon/lldate.h @@ -84,7 +84,9 @@ public: std::string asString() const; std::string asRFC1123() const; void toStream(std::ostream&) const; - void toHTTPDateStream(std::ostream&) const; + std::string toHTTPDateString (std::string fmt) const; + static std::string toHTTPDateString (tm * gmt, std::string fmt); + static void toHTTPDateStream(std::ostream&, tm *, std::string); /** * @brief Set the date from an ISO-8601 string. * diff --git a/indra/llcommon/lldeleteutils.h b/indra/llcommon/lldeleteutils.h new file mode 100644 index 0000000000..d6a0945e46 --- /dev/null +++ b/indra/llcommon/lldeleteutils.h @@ -0,0 +1,53 @@ +/** + * @file lldeleteutils.h + * @brief Utility functions to simplify some common pointer-munging idioms. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LL_DELETE_UTILS_H +#define LL_DELETE_UTILS_H + +// Simple utility functions to eventually replace the common 2-line +// idiom scattered throughout the viewer codebase. Note that where +// possible we would rather be using smart pointers of some sort. + +template +inline void deleteAndClear(T*& ptr) +{ + delete ptr; + ptr = NULL; +} + +template +inline void deleteAndClearArray(T*& array_ptr) +{ + delete[] array_ptr; + array_ptr = NULL; +} + +#endif diff --git a/indra/llcommon/lldictionary.h b/indra/llcommon/lldictionary.h new file mode 100644 index 0000000000..856947def8 --- /dev/null +++ b/indra/llcommon/lldictionary.h @@ -0,0 +1,102 @@ +/** + * @file lldictionary.h + * @brief Lldictionary class header file + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2007, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlife.com/developers/opensource/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at http://secondlife.com/developers/opensource/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLDICTIONARY_H +#define LL_LLDICTIONARY_H + +#include + +struct LLDictionaryEntry +{ + LLDictionaryEntry(const std::string &name) : + mName(name) + { + mNameCapitalized = mName; + LLStringUtil::replaceChar(mNameCapitalized, '-', ' '); + LLStringUtil::replaceChar(mNameCapitalized, '_', ' '); + for (U32 i=0; i < mNameCapitalized.size(); i++) + { + if (i == 0 || mNameCapitalized[i-1] == ' ') // don't change ordering of this statement or crash + { + mNameCapitalized[i] = toupper(mNameCapitalized[i]); + } + } + } + virtual ~LLDictionaryEntry() {} + const std::string mName; + std::string mNameCapitalized; +}; + +template +class LLDictionary : public std::map +{ +public: + typedef std::map map_t; + typedef typename map_t::iterator iterator_t; + typedef typename map_t::const_iterator const_iterator_t; + + LLDictionary() {} + virtual ~LLDictionary() + { + for (iterator_t iter = map_t::begin(); iter != map_t::end(); ++iter) + delete (iter->second); + } + + const Entry *lookup(Index index) const + { + const_iterator_t dictionary_iter = map_t::find(index); + if (dictionary_iter == map_t::end()) return NULL; + return dictionary_iter->second; + } + const Index lookup(const std::string &name) const + { + for (const_iterator_t dictionary_iter = map_t::begin(); + dictionary_iter != map_t::end(); + dictionary_iter++) + { + const Entry *entry = dictionary_iter->second; + if (entry->mName == name) + { + return dictionary_iter->first; + } + } + llassert(false); + return Index(-1); + } + +protected: + void addEntry(Index index, Entry *entry) + { + (*this)[index] = entry; + } +}; + +#endif // LL_LLDICTIONARY_H diff --git a/indra/llcommon/lldoubledispatch.h b/indra/llcommon/lldoubledispatch.h new file mode 100755 index 0000000000..60678d44fb --- /dev/null +++ b/indra/llcommon/lldoubledispatch.h @@ -0,0 +1,332 @@ +/** + * @file lldoubledispatch.h + * @author Nat Goodspeed + * @date 2008-11-11 + * @brief function calls virtual on more than one parameter + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLDOUBLEDISPATCH_H) +#define LL_LLDOUBLEDISPATCH_H + +#include +#include +#include +#include +#include + +/** + * This class supports function calls which are virtual on the dynamic type of + * more than one parameter. Specifically, we address a limited but useful + * subset of that problem: function calls which accept two parameters, and + * select which particular function to call depending on the dynamic type of + * both. + * + * Scott Meyers, in More Effective C++ (Item 31), talks about some of the perils + * and pitfalls lurking down this pathway. He discusses and dismisses the + * straightforward approaches of using single-dispatch virtual functions twice, + * and of using a family of single-dispatch virtual functions which each examine + * RTTI for their other parameter. He advocates using a registry in which you + * look up the actual types of both parameters (he uses the classes' string names, + * via typeid(param).name()) to obtain a pointer to a free (non-member) function + * that will accept this pair of parameters. + * + * He does point out that his approach doesn't handle inheritance. If you have a + * registry entry for SpaceShip, and you have in hand a MilitaryShip (subclass of + * SpaceShip) and an Asteroid, you'd like to call the function appropriate for + * SpaceShips and Asteroids -- but alas, his lookup fails because the class name + * for your MilitaryShip subclass isn't in the registry. + * + * This class extends his idea to build a registry whose entries can examine the + * dynamic type of the parameter in a more flexible way -- using dynamic_cast<> + * -- thereby supporting inheritance relationships. + * + * Of course we must allow for the ambiguity this permits. We choose to use a + * sequence container rather than a map, and require that the client code + * specify the order in which dispatch-table entries should be searched. The + * result resembles the semantics of the catch clauses for a try/catch block: + * you must code catch clauses in decreasing order of specificity, because if + * you catch ErrorBaseClass before you catch ErrorSubclass, then any + * ErrorSubclass exceptions thrown by the protected code will always match + * ErrorBaseClass, and you will never reach your catch(ErrorSubclass) clause. + * + * So, in a similar way, if you have a specific routine to process + * MilitaryShip and Asteroid, you'd better place that in the table @em before + * your more general routine that processes SpaceShip and Asteroid, or else + * the MilitaryShip variant will never be called. + * + * @todo This implementation doesn't attempt to deal with + * const-correctness of arguments. Our container stores templated + * objects into which the specific parameter types have been "frozen." But to + * store all these in the same container, they are all instances of a base + * class with a virtual invocation method. Naturally the base-class virtual + * method definition cannot know the const-ness of the particular + * types with which its template subclass is instantiated. + * + * One is tempted to suggest four different virtual methods, one for each + * combination of @c const and non-const arguments. Then the client + * will select the particular virtual method that best fits the + * const-ness of the arguments in hand. The trouble with that idea is + * that in order to instantiate the subclass instance, we must compile all + * four of its virtual method overrides, which means we must be prepared to + * pass all four combinations of @c const and non-const arguments to + * the registered callable. That only works when the registered callable + * accepts both parameters as @c const. + * + * Of course the virtual method overrides could use @c const_cast to force + * them to compile correctly regardless of the const-ness of the + * registered callable's parameter declarations. But if we're going to force + * the issue with @c const_cast anyway, why bother with the four different + * virtual methods? Why not just require canonical parameter + * const-ness for any callables used with this mechanism? + * + * We therefore require that your callable accept both params as + * non-const. (This is more general than @c const: you can perform @c + * const operations on a non-const parameter, but you can't perform + * non-const operations on a @c const parameter.) + * + * For ease of use, though, our invocation method accepts both params as @c + * const. Again, you can pass a non-const object to a @c const param, + * but not the other way around. We take care of the @c const_cast for you. + */ +// LLDoubleDispatch is a template because we have to assume that all parameter +// types are subclasses of some common base class -- but we don't have to +// impose that base class on client code. Instead, we let IT tell US the +// common parameter base class. +template +class LLDoubleDispatch +{ + typedef LLDoubleDispatch self_type; + +public: + LLDoubleDispatch() {} + + /** + * Call the first matching entry. If there's no registered Functor + * appropriate for this pair of parameter types, this call will do + * @em nothing! (If you want notification in this case, simply add a new + * Functor for (ParamBaseType&, ParamBaseType&) at the end of the table. + * The two base-class entries should match anything that isn't matched by + * any more specific entry.) + * + * See note in class documentation about const-correctness. + */ + inline + ReturnType operator()(const ParamBaseType& param1, const ParamBaseType& param2) const; + + // Borrow a trick from Alexandrescu: use a Type class to "wrap" a type + // for purposes of passing the type itself into a template method. + template + struct Type {}; + + /** + * Add a new Entry for a given @a Functor. As mentioned above, the order + * in which you add these entries is very important. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(const Type& t1, const Type& t2, Functor func, bool symmetrical=false) + { + insert(t1, t2, func); + if (symmetrical) + { + // Use boost::bind() to construct a param-swapping thunk. Don't + // forget to reverse the parameters too. + insert(t2, t1, boost::bind(func, _2, _1)); + } + } + + /** + * Add a new Entry for a given @a Functor, explicitly passing instances of + * the Functor's leaf param types to help us figure out where to insert. + * Because it can use RTTI, this add() method isn't order-sensitive like + * the other one. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(const Type1& prototype1, const Type2& prototype2, Functor func, bool symmetrical=false) + { + // Because we expect our caller to pass leaf param types, we can just + // perform an ordinary search to find the first matching iterator. If + // we find an existing Entry that matches both params, either the + // param types are the same, or the existing Entry uses the base class + // for one or both params, and the new Entry must precede that. Assume + // our client won't register two callables with exactly the SAME set + // of types; in that case we'll insert the new one before any earlier + // ones, meaning the last one registered will "win." Note that if + // find() doesn't find any matching Entry, it will return end(), + // meaning the new Entry will be last, which is fine. + typename DispatchTable::iterator insertion = find(prototype1, prototype2); + insert(Type(), Type(), func, insertion); + if (symmetrical) + { + insert(Type(), Type(), boost::bind(func, _2, _1), insertion); + } + } + + /** + * Add a new Entry for a given @a Functor, specifying the Functor's leaf + * param types as explicit template arguments. This will instantiate + * temporary objects of each of these types, which requires that they have + * a lightweight default constructor. + * + * If you want symmetrical entries -- that is, if a B and an A can call + * the same Functor as an A and a B -- then pass @c true for the last + * parameter, and we'll add a (B, A) entry as well as an (A, B) entry. But + * your @a Functor can still be written to expect exactly the pair of types + * you've explicitly specified, because the Entry with the reversed params + * will call a special thunk that swaps params before calling your @a + * Functor. + */ + template + void add(Functor func, bool symmetrical=false) + { + // This is a convenience wrapper for the add() variant taking explicit + // instances. + add(Type1(), Type2(), func, symmetrical); + } + +private: + /// This is the base class for each entry in our dispatch table. + struct EntryBase + { + virtual ~EntryBase() {} + virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const = 0; + virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const = 0; + }; + + /// Here's the template subclass that actually creates each entry. + template + class Entry: public EntryBase + { + public: + Entry(Functor func): mFunc(func) {} + /// Is this entry appropriate for these arguments? + virtual bool matches(const ParamBaseType& param1, const ParamBaseType& param2) const + { + return (dynamic_cast(¶m1) && + dynamic_cast(¶m2)); + } + /// invocation + virtual ReturnType operator()(ParamBaseType& param1, ParamBaseType& param2) const + { + // We perform the downcast so callable can accept leaf param + // types, instead of accepting ParamBaseType and downcasting + // explicitly. + return mFunc(dynamic_cast(param1), dynamic_cast(param2)); + } + private: + /// Bind whatever function or function object the instantiator passed. + Functor mFunc; + }; + + /// shared_ptr manages Entry lifespan for us + typedef boost::shared_ptr EntryPtr; + /// use a @c list to make it easy to insert + typedef std::list DispatchTable; + DispatchTable mDispatch; + + /// Look up the location of the first matching entry. + typename DispatchTable::const_iterator find(const ParamBaseType& param1, const ParamBaseType& param2) const + { + // We assert that it's safe to call the non-const find() method on a + // const LLDoubleDispatch instance. Cast away the const-ness of 'this'. + return const_cast(this)->find(param1, param2); + } + + /// Look up the location of the first matching entry. + typename DispatchTable::iterator find(const ParamBaseType& param1, const ParamBaseType& param2) + { + return std::find_if(mDispatch.begin(), mDispatch.end(), + boost::bind(&EntryBase::matches, _1, + boost::ref(param1), boost::ref(param2))); + } + + /// Look up the first matching entry. + EntryPtr lookup(const ParamBaseType& param1, const ParamBaseType& param2) const + { + typename DispatchTable::const_iterator found = find(param1, param2); + if (found != mDispatch.end()) + { + // Dereferencing the list iterator gets us an EntryPtr + return *found; + } + // not found + return EntryPtr(); + } + + // Break out the actual insert operation so the public add() template + // function can avoid calling itself recursively. See add() comments. + template + void insert(const Type& param1, const Type& param2, Functor func) + { + insert(param1, param2, func, mDispatch.end()); + } + + // Break out the actual insert operation so the public add() template + // function can avoid calling itself recursively. See add() comments. + template + void insert(const Type&, const Type&, Functor func, + typename DispatchTable::iterator where) + { + mDispatch.insert(where, EntryPtr(new Entry(func))); + } + + /// Don't implement the copy ctor. Everyone will be happier if the + /// LLDoubleDispatch object isn't copied. + LLDoubleDispatch(const LLDoubleDispatch& src); +}; + +template +ReturnType LLDoubleDispatch::operator()(const ParamBaseType& param1, + const ParamBaseType& param2) const +{ + EntryPtr found = lookup(param1, param2); + if (found.get() == 0) + return ReturnType(); // bogus return value + + // otherwise, call the Functor we found + return (*found)(const_cast(param1), const_cast(param2)); +} + +#endif /* ! defined(LL_LLDOUBLEDISPATCH_H) */ diff --git a/indra/llcommon/llerrorthread.cpp b/indra/llcommon/llerrorthread.cpp index 4c779c58c8..f0e46ae78d 100644 --- a/indra/llcommon/llerrorthread.cpp +++ b/indra/llcommon/llerrorthread.cpp @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llerrorthread.h" + #include "llapp.h" +#include "lltimer.h" // ms_sleep() LLErrorThread::LLErrorThread() : LLThread("Error"), diff --git a/indra/llcommon/llevent.h b/indra/llcommon/llevent.h index a74ddbd091..2cc8577219 100644 --- a/indra/llcommon/llevent.h +++ b/indra/llcommon/llevent.h @@ -35,7 +35,7 @@ #define LL_EVENT_H #include "llsd.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" namespace LLOldEvents diff --git a/indra/llcommon/llevents.h b/indra/llcommon/llevents.h index f70d532e4c..2f6515a4cb 100644 --- a/indra/llcommon/llevents.h +++ b/indra/llcommon/llevents.h @@ -38,7 +38,7 @@ #include #include #include "llsd.h" -#include "llmemory.h" +#include "llsingleton.h" #include "lldependencies.h" // override this to allow binding free functions with more parameters diff --git a/indra/llcommon/llfasttimer.h b/indra/llcommon/llfasttimer.h index 94b51119e4..612068b202 100644 --- a/indra/llcommon/llfasttimer.h +++ b/indra/llcommon/llfasttimer.h @@ -30,229 +30,323 @@ * $/LicenseInfo$ */ -#ifndef LL_LLFASTTIMER_H -#define LL_LLFASTTIMER_H +#ifndef LL_FASTTIMER_H +#define LL_FASTTIMER_H + +#include "llinstancetracker.h" #define FAST_TIMER_ON 1 U64 get_cpu_clock_count(); +class LLMutex; + +#include +#include "llsd.h" + + class LLFastTimer { public: - enum EFastTimerType + // stores a "named" timer instance to be reused via multiple LLFastTimer stack instances + class NamedTimer + : public LLInstanceTracker { - // high level - FTM_FRAME, - FTM_UPDATE, - FTM_RENDER, - FTM_SWAP, - FTM_CLIENT_COPY, - FTM_IDLE, - FTM_SLEEP, - - // common messaging components - FTM_PUMP, - FTM_CURL, - - // common simulation components - FTM_UPDATE_ANIMATION, - FTM_UPDATE_TERRAIN, - FTM_UPDATE_PRIMITIVES, - FTM_UPDATE_PARTICLES, - FTM_SIMULATE_PARTICLES, - FTM_UPDATE_SKY, - FTM_UPDATE_TEXTURES, - FTM_UPDATE_WLPARAM, - FTM_UPDATE_WATER, - FTM_UPDATE_CLOUDS, - FTM_UPDATE_GRASS, - FTM_UPDATE_TREE, - FTM_UPDATE_AVATAR, - - // common render components - FTM_SHADOW_GEOMETRY, - FTM_SHADOW_RENDER, - FTM_SHADOW_TERRAIN, - FTM_SHADOW_AVATAR, - FTM_SHADOW_SIMPLE, - FTM_SHADOW_ALPHA, - FTM_SHADOW_TREE, - - FTM_RENDER_GEOMETRY, - FTM_RENDER_TERRAIN, - FTM_RENDER_SIMPLE, - FTM_RENDER_FULLBRIGHT, - FTM_RENDER_GLOW, - FTM_RENDER_GRASS, - FTM_RENDER_INVISIBLE, - FTM_RENDER_SHINY, - FTM_RENDER_BUMP, - FTM_RENDER_TREES, - FTM_RENDER_CHARACTERS, - FTM_RENDER_OCCLUSION, - FTM_RENDER_ALPHA, - FTM_RENDER_CLOUDS, - FTM_RENDER_HUD, - FTM_RENDER_PARTICLES, - FTM_RENDER_WATER, - FTM_RENDER_WL_SKY, - FTM_RENDER_FAKE_VBO_UPDATE, - FTM_RENDER_TIMER, - FTM_RENDER_UI, - FTM_RENDER_BLOOM, - FTM_RENDER_BLOOM_FBO, - FTM_RENDER_FONTS, - - // newview specific - FTM_MESSAGES, - FTM_MOUSEHANDLER, - FTM_KEYHANDLER, - FTM_REBUILD, - FTM_STATESORT, - FTM_STATESORT_DRAWABLE, - FTM_STATESORT_POSTSORT, - FTM_REBUILD_VBO, - FTM_REBUILD_VOLUME_VB, - FTM_REBUILD_BRIDGE_VB, - FTM_REBUILD_HUD_VB, - FTM_REBUILD_TERRAIN_VB, - FTM_REBUILD_WATER_VB, - FTM_REBUILD_TREE_VB, - FTM_REBUILD_PARTICLE_VB, - FTM_REBUILD_CLOUD_VB, - FTM_REBUILD_GRASS_VB, - FTM_REBUILD_NONE_VB, - FTM_REBUILD_OCCLUSION_VB, - FTM_POOLS, - FTM_POOLRENDER, - FTM_IDLE_CB, - FTM_WORLD_UPDATE, - FTM_UPDATE_MOVE, - FTM_OCTREE_BALANCE, - FTM_UPDATE_LIGHTS, - FTM_CULL, - FTM_CULL_REBOUND, - FTM_FRUSTUM_CULL, - FTM_GEO_UPDATE, - FTM_GEO_RESERVE, - FTM_GEO_LIGHT, - FTM_GEO_SHADOW, - FTM_GEO_SKY, - FTM_GEN_VOLUME, - FTM_GEN_TRIANGLES, - FTM_GEN_FLEX, - FTM_AUDIO_UPDATE, - FTM_RESET_DRAWORDER, - FTM_OBJECTLIST_UPDATE, - FTM_AVATAR_UPDATE, - FTM_JOINT_UPDATE, - FTM_ATTACHMENT_UPDATE, - FTM_LOD_UPDATE, - FTM_REGION_UPDATE, - FTM_CLEANUP, - FTM_NETWORK, - FTM_IDLE_NETWORK, - FTM_CREATE_OBJECT, - FTM_LOAD_AVATAR, - FTM_PROCESS_MESSAGES, - FTM_PROCESS_OBJECTS, - FTM_PROCESS_IMAGES, - FTM_IMAGE_UPDATE, - FTM_IMAGE_CREATE, - FTM_IMAGE_DECODE, - FTM_IMAGE_MARK_DIRTY, - FTM_PIPELINE, - FTM_VFILE_WAIT, - FTM_FLEXIBLE_UPDATE, - FTM_OCCLUSION_READBACK, - FTM_HUD_EFFECTS, - FTM_HUD_UPDATE, - FTM_INVENTORY, - FTM_AUTO_SELECT, - FTM_ARRANGE, - FTM_FILTER, - FTM_REFRESH, - FTM_SORT, - FTM_PICK, - - // Temp - FTM_TEMP1, - FTM_TEMP2, - FTM_TEMP3, - FTM_TEMP4, - FTM_TEMP5, - FTM_TEMP6, - FTM_TEMP7, - FTM_TEMP8, - - FTM_OTHER, // Special, used by display code + public: + ~NamedTimer(); + + enum { HISTORY_NUM = 60 }; + + const std::string& getName() { return mName; } + NamedTimer* getParent() { return mParent; } + void setParent(NamedTimer* parent); + S32 getDepth(); + std::string getToolTip(S32 history_index = -1); + + typedef std::vector::const_iterator child_const_iter; + child_const_iter beginChildren(); + child_const_iter endChildren(); + std::vector& getChildren(); + + void setCollapsed(bool collapsed) { mCollapsed = collapsed; } + bool getCollapsed() { return mCollapsed; } + + U64 getCountAverage() { return mCountAverage; } + U64 getCallAverage() { return mCallAverage; } + + U64 getHistoricalCount(S32 history_index = 0); + U64 getHistoricalCalls(S32 history_index = 0); + + static NamedTimer& getRootNamedTimer(); + + struct FrameState + { + FrameState(NamedTimer* timerp); + + U64 mSelfTimeCounter; + U64 mLastStartTime; // most recent time when this timer was started + U32 mCalls; + FrameState* mParent; // info for caller timer + FrameState* mLastCaller; // used to bootstrap tree construction + NamedTimer* mTimer; + U16 mActiveCount; // number of timers with this ID active on stack + bool mMoveUpTree; // needs to be moved up the tree of timers at the end of frame + }; + + FrameState& getFrameStateFast() const + { + return (*sTimerInfos)[mFrameStateIndex]; + } + + S32 getFrameStateIndex() const { return mFrameStateIndex; } + + FrameState& getFrameState() const; + + + private: + friend class LLFastTimer; + friend class NamedTimerFactory; + + // + // methods + // + NamedTimer(const std::string& name); + // recursive call to gather total time from children + static void accumulateTimings(); + + // called once per frame by LLFastTimer + static void processFrame(); + + static void buildHierarchy(); + static void resetFrame(); + static void reset(); + + typedef std::vector info_list_t; + static info_list_t& getFrameStateList(); + static void createFrameStateList(); // must call before any call to getFrameStateList() - FTM_NUM_TYPES + // + // members + // + S32 mFrameStateIndex; + + std::string mName; + + U64 mTotalTimeCounter; + + U64 mCountAverage; + U64 mCallAverage; + + U64* mCountHistory; + U64* mCallHistory; + + // tree structure + NamedTimer* mParent; // NamedTimer of caller(parent) + std::vector mChildren; + bool mCollapsed; // don't show children + bool mNeedsSorting; // sort children whenever child added + + static info_list_t* sTimerInfos; }; - enum { FTM_HISTORY_NUM = 60 }; - enum { FTM_MAX_DEPTH = 64 }; - + + // used to statically declare a new named timer + class DeclareTimer + { + public: + DeclareTimer(const std::string& name, bool open); + DeclareTimer(const std::string& name); + + // convertable to NamedTimer::FrameState for convenient usage of LLFastTimer(declared_timer) + operator NamedTimer::FrameState&() { return mNamedTimer.getFrameStateFast(); } + private: + NamedTimer& mNamedTimer; + }; + + static DeclareTimer FTM_ARRANGE; + static DeclareTimer FTM_ATTACHMENT_UPDATE; + static DeclareTimer FTM_AUDIO_UPDATE; + static DeclareTimer FTM_AUTO_SELECT; + static DeclareTimer FTM_AVATAR_UPDATE; + static DeclareTimer FTM_CLEANUP; + static DeclareTimer FTM_CLIENT_COPY; + static DeclareTimer FTM_CREATE_OBJECT; + static DeclareTimer FTM_CULL; + static DeclareTimer FTM_CULL_REBOUND; + static DeclareTimer FTM_FILTER; + static DeclareTimer FTM_FLEXIBLE_UPDATE; + static DeclareTimer FTM_FRAME; + static DeclareTimer FTM_FRUSTUM_CULL; + static DeclareTimer FTM_GEN_FLEX; + static DeclareTimer FTM_GEN_TRIANGLES; + static DeclareTimer FTM_GEN_VOLUME; + static DeclareTimer FTM_GEO_SKY; + static DeclareTimer FTM_GEO_UPDATE; + static DeclareTimer FTM_HUD_EFFECTS; + static DeclareTimer FTM_HUD_UPDATE; + static DeclareTimer FTM_IDLE; + static DeclareTimer FTM_IDLE_CB; + static DeclareTimer FTM_IDLE_NETWORK; + static DeclareTimer FTM_IMAGE_CREATE; + static DeclareTimer FTM_IMAGE_MARK_DIRTY; + static DeclareTimer FTM_IMAGE_UPDATE; + static DeclareTimer FTM_INVENTORY; + static DeclareTimer FTM_JOINT_UPDATE; + static DeclareTimer FTM_KEYHANDLER; + static DeclareTimer FTM_LOAD_AVATAR; + static DeclareTimer FTM_LOD_UPDATE; + static DeclareTimer FTM_MESSAGES; + static DeclareTimer FTM_MOUSEHANDLER; + static DeclareTimer FTM_NETWORK; + static DeclareTimer FTM_OBJECTLIST_UPDATE; + static DeclareTimer FTM_OCCLUSION_READBACK; + static DeclareTimer FTM_OCTREE_BALANCE; + static DeclareTimer FTM_PICK; + static DeclareTimer FTM_PIPELINE; + static DeclareTimer FTM_POOLRENDER; + static DeclareTimer FTM_POOLS; + static DeclareTimer FTM_PROCESS_IMAGES; + static DeclareTimer FTM_PROCESS_MESSAGES; + static DeclareTimer FTM_PROCESS_OBJECTS; + static DeclareTimer FTM_PUMP; + static DeclareTimer FTM_REBUILD_GRASS_VB; + static DeclareTimer FTM_REBUILD_PARTICLE_VB; + static DeclareTimer FTM_REBUILD_TERRAIN_VB; + static DeclareTimer FTM_REBUILD_VBO; + static DeclareTimer FTM_REBUILD_VOLUME_VB; + static DeclareTimer FTM_REFRESH; + static DeclareTimer FTM_REGION_UPDATE; + static DeclareTimer FTM_RENDER; + static DeclareTimer FTM_RENDER_ALPHA; + static DeclareTimer FTM_RENDER_BLOOM; + static DeclareTimer FTM_RENDER_BLOOM_FBO; + static DeclareTimer FTM_RENDER_BUMP; + static DeclareTimer FTM_RENDER_CHARACTERS; + static DeclareTimer FTM_RENDER_FAKE_VBO_UPDATE; + static DeclareTimer FTM_RENDER_FONTS; + static DeclareTimer FTM_RENDER_FULLBRIGHT; + static DeclareTimer FTM_RENDER_GEOMETRY; + static DeclareTimer FTM_RENDER_GLOW; + static DeclareTimer FTM_RENDER_GRASS; + static DeclareTimer FTM_RENDER_INVISIBLE; + static DeclareTimer FTM_RENDER_OCCLUSION; + static DeclareTimer FTM_RENDER_SHINY; + static DeclareTimer FTM_RENDER_SIMPLE; + static DeclareTimer FTM_RENDER_TERRAIN; + static DeclareTimer FTM_RENDER_TREES; + static DeclareTimer FTM_RENDER_UI; + static DeclareTimer FTM_RENDER_WATER; + static DeclareTimer FTM_RENDER_WL_SKY; + static DeclareTimer FTM_RESET_DRAWORDER; + static DeclareTimer FTM_SHADOW_ALPHA; + static DeclareTimer FTM_SHADOW_AVATAR; + static DeclareTimer FTM_SHADOW_RENDER; + static DeclareTimer FTM_SHADOW_SIMPLE; + static DeclareTimer FTM_SHADOW_TERRAIN; + static DeclareTimer FTM_SHADOW_TREE; + static DeclareTimer FTM_SIMULATE_PARTICLES; + static DeclareTimer FTM_SLEEP; + static DeclareTimer FTM_SORT; + static DeclareTimer FTM_STATESORT; + static DeclareTimer FTM_STATESORT_DRAWABLE; + static DeclareTimer FTM_STATESORT_POSTSORT; + static DeclareTimer FTM_SWAP; + static DeclareTimer FTM_TEMP1; + static DeclareTimer FTM_TEMP2; + static DeclareTimer FTM_TEMP3; + static DeclareTimer FTM_TEMP4; + static DeclareTimer FTM_TEMP5; + static DeclareTimer FTM_TEMP6; + static DeclareTimer FTM_TEMP7; + static DeclareTimer FTM_TEMP8; + static DeclareTimer FTM_UPDATE_ANIMATION; + static DeclareTimer FTM_UPDATE_AVATAR; + static DeclareTimer FTM_UPDATE_CLOUDS; + static DeclareTimer FTM_UPDATE_GRASS; + static DeclareTimer FTM_UPDATE_MOVE; + static DeclareTimer FTM_UPDATE_PARTICLES; + static DeclareTimer FTM_UPDATE_PRIMITIVES; + static DeclareTimer FTM_UPDATE_SKY; + static DeclareTimer FTM_UPDATE_TERRAIN; + static DeclareTimer FTM_UPDATE_TEXTURES; + static DeclareTimer FTM_UPDATE_TREE; + static DeclareTimer FTM_UPDATE_WATER; + static DeclareTimer FTM_UPDATE_WLPARAM; + static DeclareTimer FTM_VFILE_WAIT; + static DeclareTimer FTM_WORLD_UPDATE; + public: - static LLFastTimer::EFastTimerType sCurType; + enum RootTimerMarker { ROOT }; + + static LLMutex* sLogLock; + static std::queue sLogQueue; + static BOOL sLog; + static BOOL sMetricLog; + + LLFastTimer(RootTimerMarker); - LLFastTimer(EFastTimerType type) + LLFastTimer(NamedTimer::FrameState& timer) + : mFrameState(&timer) { -#if FAST_TIMER_ON - mType = type; - sCurType = type; - // These don't get counted, because they use CPU clockticks - //gTimerBins[gCurTimerBin]++; - //LLTimer::sNumTimerCalls++; + NamedTimer::FrameState* frame_state = mFrameState; + frame_state->mLastStartTime = get_cpu_clock_count(); + mStartSelfTime = frame_state->mLastStartTime; - U64 cpu_clocks = get_cpu_clock_count(); + frame_state->mActiveCount++; + frame_state->mCalls++; + // keep current parent as long as it is active when we are + frame_state->mMoveUpTree |= (frame_state->mParent->mActiveCount == 0); + + mLastTimer = sCurTimer; + sCurTimer = this; + } - sStart[sCurDepth] = cpu_clocks; - sCurDepth++; -#endif - }; ~LLFastTimer() { #if FAST_TIMER_ON - U64 end,delta; - int i; - - // These don't get counted, because they use CPU clockticks - //gTimerBins[gCurTimerBin]++; - //LLTimer::sNumTimerCalls++; - end = get_cpu_clock_count(); - - sCurDepth--; - delta = end - sStart[sCurDepth]; - sCounter[mType] += delta; - sCalls[mType]++; - // Subtract delta from parents - for (i=0; imSelfTimeCounter += cur_time - mStartSelfTime; + + frame_state->mActiveCount--; + LLFastTimer* last_timer = mLastTimer; + sCurTimer = last_timer; + + // store last caller to bootstrap tree creation + 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; + last_timer->mStartSelfTime += total_time; #endif } + + // call this once a frame to reset timers + static void nextFrame(); + + // call this to reset timer hierarchy, averages, etc. static void reset(); + static U64 countsPerSecond(); + static S32 getLastFrameIndex() { return sLastFrameIndex; } + static S32 getCurFrameIndex() { return sCurFrameIndex; } + + static void writeLog(std::ostream& os); public: - static int sCurDepth; - static U64 sStart[FTM_MAX_DEPTH]; - static U64 sCounter[FTM_NUM_TYPES]; - static U64 sCalls[FTM_NUM_TYPES]; - static U64 sCountAverage[FTM_NUM_TYPES]; - static U64 sCallAverage[FTM_NUM_TYPES]; - static U64 sCountHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES]; - static U64 sCallHistory[FTM_HISTORY_NUM][FTM_NUM_TYPES]; - static S32 sCurFrameIndex; - static S32 sLastFrameIndex; - static int sPauseHistory; - static int sResetHistory; - static F64 sCPUClockFrequency; + static bool sPauseHistory; + static bool sResetHistory; private: - EFastTimerType mType; -}; + typedef std::vector timer_stack_t; + static LLFastTimer* sCurTimer; + static S32 sCurFrameIndex; + static S32 sLastFrameIndex; + static F64 sCPUClockFrequency; + U64 mStartSelfTime; // start time + time of all child timers + NamedTimer::FrameState* mFrameState; + LLFastTimer* mLastTimer; +}; #endif // LL_LLFASTTIMER_H diff --git a/indra/llcommon/llinstancetracker.h b/indra/llcommon/llinstancetracker.h new file mode 100644 index 0000000000..ea50acbbc5 --- /dev/null +++ b/indra/llcommon/llinstancetracker.h @@ -0,0 +1,121 @@ +/** + * @file llinstancetracker.h + * @brief LLInstanceTracker is a mixin class that automatically tracks object + * instances with or without an associated key + * + * $LicenseInfo:firstyear=2000&license=viewergpl$ + * + * Copyright (c) 2000-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLINSTANCETRACKER_H +#define LL_LLINSTANCETRACKER_H + +#include + +#include "string_table.h" +#include + +// This mix-in class adds support for tracking all instances of the specified class parameter T +// The (optional) key associates a value of type KEY with a given instance of T, for quick lookup +// If KEY is not provided, then instances are stored in a simple set +// *NOTE: see explicit specialization below for default KEY==T* case +template +class LLInstanceTracker : boost::noncopyable +{ +public: + typedef typename std::map::iterator instance_iter; + typedef typename std::map::const_iterator instance_const_iter; + + static T* getInstance(const KEY& k) { instance_iter found = getMap().find(k); return (found == getMap().end()) ? NULL : found->second; } + + static instance_iter beginInstances() { return getMap().begin(); } + static instance_iter endInstances() { return getMap().end(); } + static S32 instanceCount() { return getMap().size(); } +protected: + LLInstanceTracker(KEY key) { add(key); } + virtual ~LLInstanceTracker() { remove(); } + virtual void setKey(KEY key) { remove(); add(key); } + virtual const KEY& getKey() const { return mKey; } + +private: + void add(KEY key) + { + mKey = key; + getMap()[key] = static_cast(this); + } + void remove() { getMap().erase(mKey); } + + static std::map& getMap() + { + if (! sInstances) + { + sInstances = new std::map; + } + return *sInstances; + } + +private: + + KEY mKey; + static std::map* sInstances; +}; + +// explicit specialization for default case where KEY is T* +// use a simple std::set +template +class LLInstanceTracker +{ +public: + typedef typename std::set::iterator instance_iter; + typedef typename std::set::const_iterator instance_const_iter; + + static instance_iter beginInstances() { return getSet().begin(); } + static instance_iter endInstances() { return getSet().end(); } + static S32 instanceCount() { return getSet().size(); } + +protected: + LLInstanceTracker() { getSet().insert(static_cast(this)); } + virtual ~LLInstanceTracker() { getSet().erase(static_cast(this)); } + + LLInstanceTracker(const LLInstanceTracker& other) { getSet().insert(static_cast(this)); } + + static std::set& getSet() // called after getReady() but before go() + { + if (! sInstances) + { + sInstances = new std::set; + } + return *sInstances; + } + + static std::set* sInstances; +}; + +template std::map* LLInstanceTracker::sInstances = NULL; +template std::set* LLInstanceTracker::sInstances = NULL; + +#endif diff --git a/indra/llcommon/llmd5.cpp b/indra/llcommon/llmd5.cpp index 14b4f9f4b0..da9cb94e13 100644 --- a/indra/llcommon/llmd5.cpp +++ b/indra/llcommon/llmd5.cpp @@ -83,6 +83,7 @@ documentation and/or software. #include "llmd5.h" #include +#include // cerr // how many bytes to grab at a time when checking files const int LLMD5::BLOCK_LEN = 4096; diff --git a/indra/llcommon/llmemory.cpp b/indra/llcommon/llmemory.cpp index a6de3d2d69..2a8015e26d 100644 --- a/indra/llcommon/llmemory.cpp +++ b/indra/llcommon/llmemory.cpp @@ -44,7 +44,6 @@ #endif #include "llmemory.h" -#include "llmemtype.h" //---------------------------------------------------------------------------- @@ -74,162 +73,6 @@ void LLMemory::freeReserve() reserveMem = NULL; } - -//---------------------------------------------------------------------------- - -//static -#if MEM_TRACK_TYPE -S32 LLMemType::sCurDepth = 0; -S32 LLMemType::sCurType = LLMemType::MTYPE_INIT; -S32 LLMemType::sType[LLMemType::MTYPE_MAX_DEPTH]; -S32 LLMemType::sMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 }; -S32 LLMemType::sMaxMemCount[LLMemType::MTYPE_NUM_TYPES] = { 0 }; -S32 LLMemType::sNewCount[LLMemType::MTYPE_NUM_TYPES] = { 0 }; -S32 LLMemType::sOverheadMem = 0; - -const char* LLMemType::sTypeDesc[LLMemType::MTYPE_NUM_TYPES] = -{ - "INIT", - "STARTUP", - "MAIN", - - "IMAGEBASE", - "IMAGERAW", - "IMAGEFORMATTED", - - "APPFMTIMAGE", - "APPRAWIMAGE", - "APPAUXRAWIMAGE", - - "DRAWABLE", - "OBJECT", - "PIPELINE", - "AVATAR", - "PARTICLES", - "REGIONS", - "INVENTORY", - "ANIMATION", - "NETWORK", - "PHYSICS", - "INTERESTLIST", - - "SCRIPT", - "SCRIPT_RUN", - "SCRIPT_BYTECODE", - - "IO_PUMP", - "IO_TCP", - "IO_BUFFER", - "IO_HTTP_SERVER" - "IO_SD_SERVER", - "IO_SD_CLIENT", - "IO_URL_REQUEST", - - "TEMP1", - "TEMP2", - "TEMP3", - "TEMP4", - "TEMP5", - "TEMP6", - "TEMP7", - "TEMP8", - "TEMP9" -}; - -#endif -S32 LLMemType::sTotalMem = 0; -S32 LLMemType::sMaxTotalMem = 0; - -//static -void LLMemType::printMem() -{ - S32 misc_mem = sTotalMem; -#if MEM_TRACK_TYPE - for (S32 i=0; i>20,sMaxMemCount[i]>>20, sNewCount[i]) << llendl; - } - misc_mem -= sMemCount[i]; - } -#endif - llinfos << llformat("MEM: % 20s %03d MB","MISC",misc_mem>>20) << llendl; - llinfos << llformat("MEM: % 20s %03d MB (Max=%d MB)","TOTAL",sTotalMem>>20,sMaxTotalMem>>20) << llendl; -} - -#if MEM_TRACK_MEM - -void* ll_allocate (size_t size) -{ - if (size == 0) - { - llwarns << "Null allocation" << llendl; - } - - size = (size+3)&~3; - S32 alloc_size = size + 4; -#if MEM_TRACK_TYPE - alloc_size += 4; -#endif - char* p = (char*)malloc(alloc_size); - if (p == NULL) - { - LLMemory::freeReserve(); - llerrs << "Out of memory Error" << llendl; - } - LLMemType::sTotalMem += size; - LLMemType::sMaxTotalMem = llmax(LLMemType::sTotalMem, LLMemType::sMaxTotalMem); - LLMemType::sOverheadMem += 4; - *(size_t*)p = size; - p += 4; -#if MEM_TRACK_TYPE - if (LLMemType::sCurType < 0 || LLMemType::sCurType >= LLMemType::MTYPE_NUM_TYPES) - { - llerrs << "Memory Type Error: new" << llendl; - } - LLMemType::sOverheadMem += 4; - *(S32*)p = LLMemType::sCurType; - p += 4; - LLMemType::sMemCount[LLMemType::sCurType] += size; - if (LLMemType::sMemCount[LLMemType::sCurType] > LLMemType::sMaxMemCount[LLMemType::sCurType]) - { - LLMemType::sMaxMemCount[LLMemType::sCurType] = LLMemType::sMemCount[LLMemType::sCurType]; - } - LLMemType::sNewCount[LLMemType::sCurType]++; -#endif - return (void*)p; -} - -void ll_release (void *pin) -{ - if (!pin) - { - return; - } - char* p = (char*)pin; -#if MEM_TRACK_TYPE - p -= 4; - S32 type = *(S32*)p; - if (type < 0 || type >= LLMemType::MTYPE_NUM_TYPES) - { - llerrs << "Memory Type Error: delete" << llendl; - } -#endif - p -= 4; - S32 size = *(size_t*)p; - LLMemType::sOverheadMem -= 4; -#if MEM_TRACK_TYPE - LLMemType::sMemCount[type] -= size; - LLMemType::sOverheadMem -= 4; - LLMemType::sNewCount[type]--; -#endif - LLMemType::sTotalMem -= size; - free(p); -} - -#else - void* ll_allocate (size_t size) { if (size == 0) @@ -250,52 +93,11 @@ void ll_release (void *p) free(p); } -#endif - -#if MEM_TRACK_MEM - -void* operator new (size_t size) -{ - return ll_allocate(size); -} - -void* operator new[] (size_t size) -{ - return ll_allocate(size); -} - -void operator delete (void *p) -{ - ll_release(p); -} - -void operator delete[] (void *p) -{ - ll_release(p); -} - -#endif - -//---------------------------------------------------------------------------- - -LLRefCount::LLRefCount() : - mRef(0) -{ -} - -LLRefCount::~LLRefCount() -{ - if (mRef != 0) - { - llerrs << "deleting non-zero reference" << llendl; - } -} - //---------------------------------------------------------------------------- #if defined(LL_WINDOWS) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { HANDLE self = GetCurrentProcess(); PROCESS_MEMORY_COUNTERS counters; @@ -333,7 +135,7 @@ U64 getCurrentRSS() // } // } -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { U64 residentSize = 0; task_basic_info_data_t basicInfo; @@ -357,7 +159,7 @@ U64 getCurrentRSS() #elif defined(LL_LINUX) -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { static const char statPath[] = "/proc/self/stat"; LLFILE *fp = LLFile::fopen(statPath, "r"); @@ -396,7 +198,7 @@ bail: #define _STRUCTURED_PROC 1 #include -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { char path [LL_MAX_PATH]; /* Flawfinder: ignore */ @@ -419,7 +221,7 @@ U64 getCurrentRSS() } #else -U64 getCurrentRSS() +U64 LLMemory::getCurrentRSS() { return 0; } diff --git a/indra/llcommon/llmemory.h b/indra/llcommon/llmemory.h index b5c0711484..f41da37ba6 100644 --- a/indra/llcommon/llmemory.h +++ b/indra/llcommon/llmemory.h @@ -29,21 +29,17 @@ * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ -#ifndef LL_MEMORY_H -#define LL_MEMORY_H +#ifndef LLMEMORY_H +#define LLMEMORY_H -#include -#include -#include "llerror.h" extern S32 gTotalDAlloc; extern S32 gTotalDAUse; extern S32 gDACount; -const U32 LLREFCOUNT_SENTINEL_VALUE = 0xAAAAAAAA; - -//---------------------------------------------------------------------------- +extern void* ll_allocate (size_t size); +extern void ll_release (void *p); class LLMemory { @@ -51,422 +47,19 @@ public: static void initClass(); static void cleanupClass(); static void freeReserve(); + // Return the resident set size of the current process, in bytes. + // Return value is zero if not known. + static U64 getCurrentRSS(); private: static char* reserveMem; }; -//---------------------------------------------------------------------------- -// RefCount objects should generally only be accessed by way of LLPointer<>'s -// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE -// if LLFoo::LLFoo() does anything like put itself in an update queue. -// The queue may get accessed before it gets assigned to x. -// The correct implementation is: -// LLPointer x = new LLFoo; // constructor does not do anything interesting -// x->instantiate(); // does stuff like place x into an update queue - -// see llthread.h for LLThreadSafeRefCount - -//---------------------------------------------------------------------------- - -class LLRefCount -{ -protected: - LLRefCount(const LLRefCount&); // not implemented -private: - LLRefCount&operator=(const LLRefCount&); // not implemented - -protected: - virtual ~LLRefCount(); // use unref() - -public: - LLRefCount(); - - void ref() - { - mRef++; - } - - S32 unref() - { - llassert(mRef >= 1); - if (0 == --mRef) - { - delete this; - return 0; - } - return mRef; - } - - S32 getNumRefs() const - { - return mRef; - } - -private: - S32 mRef; -}; - -//---------------------------------------------------------------------------- - -// Note: relies on Type having ref() and unref() methods -template class LLPointer -{ -public: - - LLPointer() : - mPointer(NULL) - { - } - - LLPointer(Type* ptr) : - mPointer(ptr) - { - ref(); - } - - LLPointer(const LLPointer& ptr) : - mPointer(ptr.mPointer) - { - ref(); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer(const LLPointer& ptr) : - mPointer(ptr.get()) - { - ref(); - } - - ~LLPointer() - { - unref(); - } - - Type* get() const { return mPointer; } - const Type* operator->() const { return mPointer; } - Type* operator->() { return mPointer; } - const Type& operator*() const { return *mPointer; } - Type& operator*() { return *mPointer; } - - operator BOOL() const { return (mPointer != NULL); } - operator bool() const { return (mPointer != NULL); } - bool operator!() const { return (mPointer == NULL); } - bool isNull() const { return (mPointer == NULL); } - bool notNull() const { return (mPointer != NULL); } - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } - - LLPointer& operator =(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - - return *this; - } - - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.mPointer ) - { - unref(); - mPointer = ptr.mPointer; - ref(); - } - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLPointer& operator =(const LLPointer& ptr) - { - if( mPointer != ptr.get() ) - { - unref(); - mPointer = ptr.get(); - ref(); - } - return *this; - } - - // Just exchange the pointers, which will not change the reference counts. - static void swap(LLPointer& a, LLPointer& b) - { - Type* temp = a.mPointer; - a.mPointer = b.mPointer; - b.mPointer = temp; - } - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - -protected: - Type* mPointer; -}; - -//template -//class LLPointerTraits -//{ -// static Type* null(); -//}; -// -// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. -// This is useful in instances where operations on NULL pointers are semantically safe and/or -// when error checking occurs at a different granularity or in a different part of the code -// than when referencing an object via a LLSafeHandle. -// - -template -class LLSafeHandle -{ -public: - LLSafeHandle() : - mPointer(NULL) - { - } - - LLSafeHandle(Type* ptr) : - mPointer(NULL) - { - assign(ptr); - } - - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.mPointer); - } - - // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle(const LLSafeHandle& ptr) : - mPointer(NULL) - { - assign(ptr.get()); - } - - ~LLSafeHandle() - { - unref(); - } - - const Type* operator->() const { return nonNull(mPointer); } - Type* operator->() { return nonNull(mPointer); } - - Type* get() const { return mPointer; } - // we disallow these operations as they expose our null objects to direct manipulation - // and bypass the reference counting semantics - //const Type& operator*() const { return *nonNull(mPointer); } - //Type& operator*() { return *nonNull(mPointer); } - - operator BOOL() const { return mPointer != NULL; } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool isNull() const { return mPointer == NULL; } - bool notNull() const { return mPointer != NULL; } - - - operator Type*() const { return mPointer; } - operator const Type*() const { return mPointer; } - bool operator !=(Type* ptr) const { return (mPointer != ptr); } - bool operator ==(Type* ptr) const { return (mPointer == ptr); } - bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } - bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } - bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } - - LLSafeHandle& operator =(Type* ptr) - { - assign(ptr); - return *this; - } - - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.mPointer); - return *this; - } - - // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. - template - LLSafeHandle& operator =(const LLSafeHandle& ptr) - { - assign(ptr.get()); - return *this; - } - -public: - typedef Type* (*NullFunc)(); - static const NullFunc sNullFunc; - -protected: - void ref() - { - if (mPointer) - { - mPointer->ref(); - } - } - - void unref() - { - if (mPointer) - { - Type *tempp = mPointer; - mPointer = NULL; - tempp->unref(); - if (mPointer != NULL) - { - llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; - unref(); - } - } - } - - void assign(Type* ptr) - { - if( mPointer != ptr ) - { - unref(); - mPointer = ptr; - ref(); - } - } - - static Type* nonNull(Type* ptr) - { - return ptr == NULL ? sNullFunc() : ptr; - } - -protected: - Type* mPointer; -}; - -// LLInitializedPointer is just a pointer with a default constructor that initializes it to NULL -// NOT a smart pointer like LLPointer<> -// Useful for example in std::map > -// (std::map uses the default constructor for creating new entries) -template class LLInitializedPointer -{ -public: - LLInitializedPointer() : mPointer(NULL) {} - ~LLInitializedPointer() { delete mPointer; } - - const T* operator->() const { return mPointer; } - T* operator->() { return mPointer; } - const T& operator*() const { return *mPointer; } - T& operator*() { return *mPointer; } - operator const T*() const { return mPointer; } - operator T*() { return mPointer; } - T* operator=(T* x) { return (mPointer = x); } - operator bool() const { return mPointer != NULL; } - bool operator!() const { return mPointer == NULL; } - bool operator==(T* rhs) { return mPointer == rhs; } - bool operator==(const LLInitializedPointer* rhs) { return mPointer == rhs.mPointer; } - -protected: - T* mPointer; -}; - -//---------------------------------------------------------------------------- +// LLRefCount moved to llrefcount.h -// LLSingleton implements the getInstance() method part of the Singleton -// pattern. It can't make the derived class constructors protected, though, so -// you have to do that yourself. -// -// There are two ways to use LLSingleton. The first way is to inherit from it -// while using the typename that you'd like to be static as the template -// parameter, like so: -// -// class Foo: public LLSingleton{}; -// -// Foo& instance = Foo::instance(); -// -// The second way is to use the singleton class directly, without inheritance: -// -// typedef LLSingleton FooSingleton; -// -// Foo& instance = FooSingleton::instance(); -// -// In this case, the class being managed as a singleton needs to provide an -// initSingleton() method since the LLSingleton virtual method won't be -// available -// -// As currently written, it is not thread-safe. -template -class LLSingleton -{ -public: - virtual ~LLSingleton() {} -#ifdef LL_MSVC7 -// workaround for VC7 compiler bug -// adapted from http://www.codeproject.com/KB/tips/VC2003MeyersSingletonBug.aspx -// our version doesn't introduce a nested struct so that you can still declare LLSingleton -// a friend and hide your constructor - static T* getInstance() - { - LLSingleton singleton; - return singleton.vsHack(); - } - - T* vsHack() -#else - static T* getInstance() -#endif - { - static T instance; - static bool needs_init = true; - if (needs_init) - { - needs_init = false; - instance.initSingleton(); - } - return &instance; - } - - static T& instance() - { - return *getInstance(); - } - -private: - virtual void initSingleton() {} -}; +// LLPointer moved to llpointer.h -//---------------------------------------------------------------------------- +// LLSafeHandle moved to llsafehandle.h -// Return the resident set size of the current process, in bytes. -// Return value is zero if not known. -U64 getCurrentRSS(); +// LLSingleton moved to llsingleton.h #endif diff --git a/indra/llcommon/llmemtype.cpp b/indra/llcommon/llmemtype.cpp new file mode 100644 index 0000000000..4e33439711 --- /dev/null +++ b/indra/llcommon/llmemtype.cpp @@ -0,0 +1,237 @@ +/** + * @file llmemtype.cpp + * @brief Simple memory allocation/deallocation tracking stuff here + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llmemtype.h" +#include "llallocator.h" + +std::vector LLMemType::DeclareMemType::mNameList; + +LLMemType::DeclareMemType LLMemType::MTYPE_INIT("Init"); +LLMemType::DeclareMemType LLMemType::MTYPE_STARTUP("Startup"); +LLMemType::DeclareMemType LLMemType::MTYPE_MAIN("Main"); +LLMemType::DeclareMemType LLMemType::MTYPE_FRAME("Frame"); + +LLMemType::DeclareMemType LLMemType::MTYPE_GATHER_INPUT("GatherInput"); +LLMemType::DeclareMemType LLMemType::MTYPE_JOY_KEY("JoyKey"); + +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE("Idle"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_PUMP("IdlePump"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_NETWORK("IdleNetwork"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_REGIONS("IdleUpdateRegions"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_VIEWER_REGION("IdleUpdateViewerRegion"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_SURFACE("IdleUpdateSurface"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_UPDATE_PARCEL_OVERLAY("IdleUpdateParcelOverlay"); +LLMemType::DeclareMemType LLMemType::MTYPE_IDLE_AUDIO("IdleAudio"); + +LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING("CacheProcessPending"); +LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS("CacheProcessPendingAsks"); +LLMemType::DeclareMemType LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES("CacheProcessPendingReplies"); + +LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_CHECK_ALL("MessageCheckAll"); +LLMemType::DeclareMemType LLMemType::MTYPE_MESSAGE_PROCESS_ACKS("MessageProcessAcks"); + +LLMemType::DeclareMemType LLMemType::MTYPE_RENDER("Render"); +LLMemType::DeclareMemType LLMemType::MTYPE_SLEEP("Sleep"); + +LLMemType::DeclareMemType LLMemType::MTYPE_NETWORK("Network"); +LLMemType::DeclareMemType LLMemType::MTYPE_PHYSICS("Physics"); +LLMemType::DeclareMemType LLMemType::MTYPE_INTERESTLIST("InterestList"); + +LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEBASE("ImageBase"); +LLMemType::DeclareMemType LLMemType::MTYPE_IMAGERAW("ImageRaw"); +LLMemType::DeclareMemType LLMemType::MTYPE_IMAGEFORMATTED("ImageFormatted"); + +LLMemType::DeclareMemType LLMemType::MTYPE_APPFMTIMAGE("AppFmtImage"); +LLMemType::DeclareMemType LLMemType::MTYPE_APPRAWIMAGE("AppRawImage"); +LLMemType::DeclareMemType LLMemType::MTYPE_APPAUXRAWIMAGE("AppAuxRawImage"); + +LLMemType::DeclareMemType LLMemType::MTYPE_DRAWABLE("Drawable"); + +LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT("Object"); +LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE("ObjectProcessUpdate"); +LLMemType::DeclareMemType LLMemType::MTYPE_OBJECT_PROCESS_UPDATE_CORE("ObjectProcessUpdateCore"); + +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY("Display"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE("DisplayUpdate"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_CAMERA("DisplayUpdateCam"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_GEOM("DisplayUpdateGeom"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SWAP("DisplaySwap"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_UPDATE_HUD("DisplayUpdateHud"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_GEN_REFLECTION("DisplayGenRefl"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_IMAGE_UPDATE("DisplayImageUpdate"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_STATE_SORT("DisplayStateSort"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_SKY("DisplaySky"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_GEOM("DisplayRenderGeom"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_FLUSH("DisplayRenderFlush"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_UI("DisplayRenderUI"); +LLMemType::DeclareMemType LLMemType::MTYPE_DISPLAY_RENDER_ATTACHMENTS("DisplayRenderAttach"); + +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DATA("VertexData"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CONSTRUCTOR("VertexConstr"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTRUCTOR("VertexDestr"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_VERTICES("VertexCreateVerts"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CREATE_INDICES("VertexCreateIndices"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_BUFFER("VertexDestroyBuff"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_DESTROY_INDICES("VertexDestroyIndices"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_VERTS("VertexUpdateVerts"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UPDATE_INDICES("VertexUpdateIndices"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER("VertexAllocateBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_RESIZE_BUFFER("VertexResizeBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER("VertexMapBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES("VertexMapBufferVerts"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES("VertexMapBufferIndices"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_UNMAP_BUFFER("VertexUnmapBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_STRIDE("VertexSetStride"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SET_BUFFER("VertexSetBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER("VertexSetupVertBuff"); +LLMemType::DeclareMemType LLMemType::MTYPE_VERTEX_CLEANUP_CLASS("VertexCleanupClass"); + +LLMemType::DeclareMemType LLMemType::MTYPE_SPACE_PARTITION("SpacePartition"); + +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE("Pipeline"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_INIT("PipelineInit"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_BUFFERS("PipelineCreateBuffs"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RESTORE_GL("PipelineRestroGL"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UNLOAD_SHADERS("PipelineUnloadShaders"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_LIGHTING_DETAIL("PipelineLightingDetail"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GET_POOL_TYPE("PipelineGetPoolType"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_POOL("PipelineAddPool"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ALLOCATE_DRAWABLE("PipelineAllocDrawable"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_ADD_OBJECT("PipelineAddObj"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_CREATE_OBJECTS("PipelineCreateObjs"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_MOVE("PipelineUpdateMove"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_GEOM("PipelineUpdateGeom"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_VISIBLE("PipelineMarkVisible"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_MOVED("PipelineMarkMoved"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_SHIFT("PipelineMarkShift"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_SHIFT_OBJECTS("PipelineShiftObjs"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_TEXTURED("PipelineMarkTextured"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_MARK_REBUILD("PipelineMarkRebuild"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_UPDATE_CULL("PipelineUpdateCull"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_STATE_SORT("PipelineStateSort"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_POST_SORT("PipelinePostSort"); + +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HUD_ELS("PipelineHudEls"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_HL("PipelineRenderHL"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM("PipelineRenderGeom"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED("PipelineRenderGeomDef"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_POST_DEF("PipelineRenderGeomPostDef"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_GEOM_SHADOW("PipelineRenderGeomShadow"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_SELECT("PipelineRenderSelect"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_REBUILD_POOLS("PipelineRebuildPools"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_QUICK_LOOKUP("PipelineQuickLookup"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_OBJECTS("PipelineRenderObjs"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_GENERATE_IMPOSTOR("PipelineGenImpostors"); +LLMemType::DeclareMemType LLMemType::MTYPE_PIPELINE_RENDER_BLOOM("PipelineRenderBloom"); + +LLMemType::DeclareMemType LLMemType::MTYPE_UPKEEP_POOLS("UpkeepPools"); + +LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR("Avatar"); +LLMemType::DeclareMemType LLMemType::MTYPE_AVATAR_MESH("AvatarMesh"); +LLMemType::DeclareMemType LLMemType::MTYPE_PARTICLES("Particles"); +LLMemType::DeclareMemType LLMemType::MTYPE_REGIONS("Regions"); + +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY("Inventory"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DRAW("InventoryDraw"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_BUILD_NEW_VIEWS("InventoryBuildNewViews"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_DO_FOLDER("InventoryDoFolder"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_POST_BUILD("InventoryPostBuild"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_FROM_XML("InventoryFromXML"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_CREATE_NEW_ITEM("InventoryCreateNewItem"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_INIT("InventoryViewInit"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_SHOW("InventoryViewShow"); +LLMemType::DeclareMemType LLMemType::MTYPE_INVENTORY_VIEW_TOGGLE("InventoryViewToggle"); + +LLMemType::DeclareMemType LLMemType::MTYPE_ANIMATION("Animation"); +LLMemType::DeclareMemType LLMemType::MTYPE_VOLUME("Volume"); +LLMemType::DeclareMemType LLMemType::MTYPE_PRIMITIVE("Primitive"); + +LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT("Script"); +LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_RUN("ScriptRun"); +LLMemType::DeclareMemType LLMemType::MTYPE_SCRIPT_BYTECODE("ScriptByteCode"); + +LLMemType::DeclareMemType LLMemType::MTYPE_IO_PUMP("IoPump"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_TCP("IoTCP"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_BUFFER("IoBuffer"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_HTTP_SERVER("IoHttpServer"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_SERVER("IoSDServer"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_SD_CLIENT("IoSDClient"); +LLMemType::DeclareMemType LLMemType::MTYPE_IO_URL_REQUEST("IOUrlRequest"); + +LLMemType::DeclareMemType LLMemType::MTYPE_DIRECTX_INIT("DirectXInit"); + +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP1("Temp1"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP2("Temp2"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP3("Temp3"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP4("Temp4"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP5("Temp5"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP6("Temp6"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP7("Temp7"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP8("Temp8"); +LLMemType::DeclareMemType LLMemType::MTYPE_TEMP9("Temp9"); + +LLMemType::DeclareMemType LLMemType::MTYPE_OTHER("Other"); + + +LLMemType::DeclareMemType::DeclareMemType(char const * st) +{ + mID = (S32)mNameList.size(); + mName = st; + + mNameList.push_back(mName); +} + +LLMemType::DeclareMemType::~DeclareMemType() +{ +} + +LLMemType::LLMemType(LLMemType::DeclareMemType& dt) +{ + mTypeIndex = dt.mID; + LLAllocator::pushMemType(dt.mID); +} + +LLMemType::~LLMemType() +{ + LLAllocator::popMemType(); +} + +char const * LLMemType::getNameFromID(S32 id) +{ + if (id < 0 || id >= (S32)DeclareMemType::mNameList.size()) + { + return "INVALID"; + } + + return DeclareMemType::mNameList[id]; +} + diff --git a/indra/llcommon/llmemtype.h b/indra/llcommon/llmemtype.h index a9ebc2062f..12310fcdb4 100644 --- a/indra/llcommon/llmemtype.h +++ b/indra/llcommon/llmemtype.h @@ -36,128 +36,210 @@ //---------------------------------------------------------------------------- //---------------------------------------------------------------------------- -class LLMemType; - -extern void* ll_allocate (size_t size); -extern void ll_release (void *p); +//---------------------------------------------------------------------------- -#define MEM_TRACK_MEM 0 -#define MEM_TRACK_TYPE (1 && MEM_TRACK_MEM) +#include "linden_common.h" +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// WARNING: Never commit with MEM_TRACK_MEM == 1 +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +#define MEM_TRACK_MEM (0 && LL_WINDOWS) -#if MEM_TRACK_TYPE -#define MEM_DUMP_DATA 1 -#define MEM_TYPE_NEW(T) \ -static void* operator new(size_t s) { LLMemType mt(T); return ll_allocate(s); } \ -static void operator delete(void* p) { ll_release(p); } +#include -#else #define MEM_TYPE_NEW(T) -#endif // MEM_TRACK_TYPE - - -//---------------------------------------------------------------------------- class LLMemType { public: - // Also update sTypeDesc in llmemory.cpp - enum EMemType - { - MTYPE_INIT, - MTYPE_STARTUP, - MTYPE_MAIN, - MTYPE_IMAGEBASE, - MTYPE_IMAGERAW, - MTYPE_IMAGEFORMATTED, - - MTYPE_APPFMTIMAGE, - MTYPE_APPRAWIMAGE, - MTYPE_APPAUXRAWIMAGE, - - MTYPE_DRAWABLE, - MTYPE_OBJECT, - MTYPE_VERTEX_DATA, - MTYPE_SPACE_PARTITION, - MTYPE_PIPELINE, - MTYPE_AVATAR, - MTYPE_AVATAR_MESH, - MTYPE_PARTICLES, - MTYPE_REGIONS, - MTYPE_INVENTORY, - MTYPE_ANIMATION, - MTYPE_VOLUME, - MTYPE_PRIMITIVE, - - MTYPE_NETWORK, - MTYPE_PHYSICS, - MTYPE_INTERESTLIST, - - MTYPE_SCRIPT, - MTYPE_SCRIPT_RUN, - MTYPE_SCRIPT_BYTECODE, - - MTYPE_IO_PUMP, - MTYPE_IO_TCP, - MTYPE_IO_BUFFER, - MTYPE_IO_HTTP_SERVER, - MTYPE_IO_SD_SERVER, - MTYPE_IO_SD_CLIENT, - MTYPE_IO_URL_REQUEST, - - MTYPE_TEMP1, - MTYPE_TEMP2, - MTYPE_TEMP3, - MTYPE_TEMP4, - MTYPE_TEMP5, - MTYPE_TEMP6, - MTYPE_TEMP7, - MTYPE_TEMP8, - MTYPE_TEMP9, - - MTYPE_OTHER, // Special, used by display code + // class we'll initialize all instances of as + // static members of MemType. Then use + // to construct any new mem type. + class DeclareMemType + { + public: + DeclareMemType(char const * st); + ~DeclareMemType(); + + S32 mID; + char const * mName; - MTYPE_NUM_TYPES + // array so we can map an index ID to Name + static std::vector mNameList; }; - enum { MTYPE_MAX_DEPTH = 64 }; - -public: - LLMemType(EMemType type) - { -#if MEM_TRACK_TYPE - if (type < 0 || type >= MTYPE_NUM_TYPES) - llerrs << "LLMemType error" << llendl; - if (sCurDepth < 0 || sCurDepth >= MTYPE_MAX_DEPTH) - llerrs << "LLMemType error" << llendl; - sType[sCurDepth] = sCurType; - sCurDepth++; - sCurType = type; -#endif - } - ~LLMemType() - { -#if MEM_TRACK_TYPE - sCurDepth--; - sCurType = sType[sCurDepth]; -#endif - } - static void reset(); - static void printMem(); + LLMemType(DeclareMemType& dt); + ~LLMemType(); + + static char const * getNameFromID(S32 id); + + static DeclareMemType MTYPE_INIT; + static DeclareMemType MTYPE_STARTUP; + static DeclareMemType MTYPE_MAIN; + static DeclareMemType MTYPE_FRAME; + + static DeclareMemType MTYPE_GATHER_INPUT; + static DeclareMemType MTYPE_JOY_KEY; + + static DeclareMemType MTYPE_IDLE; + static DeclareMemType MTYPE_IDLE_PUMP; + static DeclareMemType MTYPE_IDLE_NETWORK; + static DeclareMemType MTYPE_IDLE_UPDATE_REGIONS; + static DeclareMemType MTYPE_IDLE_UPDATE_VIEWER_REGION; + static DeclareMemType MTYPE_IDLE_UPDATE_SURFACE; + static DeclareMemType MTYPE_IDLE_UPDATE_PARCEL_OVERLAY; + static DeclareMemType MTYPE_IDLE_AUDIO; + + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_ASKS; + static DeclareMemType MTYPE_CACHE_PROCESS_PENDING_REPLIES; + + static DeclareMemType MTYPE_MESSAGE_CHECK_ALL; + static DeclareMemType MTYPE_MESSAGE_PROCESS_ACKS; + + static DeclareMemType MTYPE_RENDER; + static DeclareMemType MTYPE_SLEEP; + + static DeclareMemType MTYPE_NETWORK; + static DeclareMemType MTYPE_PHYSICS; + static DeclareMemType MTYPE_INTERESTLIST; + + static DeclareMemType MTYPE_IMAGEBASE; + static DeclareMemType MTYPE_IMAGERAW; + static DeclareMemType MTYPE_IMAGEFORMATTED; -public: -#if MEM_TRACK_TYPE - static S32 sCurDepth; - static S32 sCurType; - static S32 sType[MTYPE_MAX_DEPTH]; - static S32 sMemCount[MTYPE_NUM_TYPES]; - static S32 sMaxMemCount[MTYPE_NUM_TYPES]; - static S32 sNewCount[MTYPE_NUM_TYPES]; - static S32 sOverheadMem; - static const char* sTypeDesc[MTYPE_NUM_TYPES]; -#endif - static S32 sTotalMem; - static S32 sMaxTotalMem; + static DeclareMemType MTYPE_APPFMTIMAGE; + static DeclareMemType MTYPE_APPRAWIMAGE; + static DeclareMemType MTYPE_APPAUXRAWIMAGE; + + static DeclareMemType MTYPE_DRAWABLE; + + static DeclareMemType MTYPE_OBJECT; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE; + static DeclareMemType MTYPE_OBJECT_PROCESS_UPDATE_CORE; + + static DeclareMemType MTYPE_DISPLAY; + static DeclareMemType MTYPE_DISPLAY_UPDATE; + static DeclareMemType MTYPE_DISPLAY_UPDATE_CAMERA; + static DeclareMemType MTYPE_DISPLAY_UPDATE_GEOM; + static DeclareMemType MTYPE_DISPLAY_SWAP; + static DeclareMemType MTYPE_DISPLAY_UPDATE_HUD; + static DeclareMemType MTYPE_DISPLAY_GEN_REFLECTION; + static DeclareMemType MTYPE_DISPLAY_IMAGE_UPDATE; + static DeclareMemType MTYPE_DISPLAY_STATE_SORT; + static DeclareMemType MTYPE_DISPLAY_SKY; + static DeclareMemType MTYPE_DISPLAY_RENDER_GEOM; + static DeclareMemType MTYPE_DISPLAY_RENDER_FLUSH; + static DeclareMemType MTYPE_DISPLAY_RENDER_UI; + static DeclareMemType MTYPE_DISPLAY_RENDER_ATTACHMENTS; + + static DeclareMemType MTYPE_VERTEX_DATA; + static DeclareMemType MTYPE_VERTEX_CONSTRUCTOR; + static DeclareMemType MTYPE_VERTEX_DESTRUCTOR; + static DeclareMemType MTYPE_VERTEX_CREATE_VERTICES; + static DeclareMemType MTYPE_VERTEX_CREATE_INDICES; + static DeclareMemType MTYPE_VERTEX_DESTROY_BUFFER; + static DeclareMemType MTYPE_VERTEX_DESTROY_INDICES; + static DeclareMemType MTYPE_VERTEX_UPDATE_VERTS; + static DeclareMemType MTYPE_VERTEX_UPDATE_INDICES; + static DeclareMemType MTYPE_VERTEX_ALLOCATE_BUFFER; + static DeclareMemType MTYPE_VERTEX_RESIZE_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_VERTICES; + static DeclareMemType MTYPE_VERTEX_MAP_BUFFER_INDICES; + static DeclareMemType MTYPE_VERTEX_UNMAP_BUFFER; + static DeclareMemType MTYPE_VERTEX_SET_STRIDE; + static DeclareMemType MTYPE_VERTEX_SET_BUFFER; + static DeclareMemType MTYPE_VERTEX_SETUP_VERTEX_BUFFER; + static DeclareMemType MTYPE_VERTEX_CLEANUP_CLASS; + + static DeclareMemType MTYPE_SPACE_PARTITION; + + static DeclareMemType MTYPE_PIPELINE; + static DeclareMemType MTYPE_PIPELINE_INIT; + static DeclareMemType MTYPE_PIPELINE_CREATE_BUFFERS; + static DeclareMemType MTYPE_PIPELINE_RESTORE_GL; + static DeclareMemType MTYPE_PIPELINE_UNLOAD_SHADERS; + static DeclareMemType MTYPE_PIPELINE_LIGHTING_DETAIL; + static DeclareMemType MTYPE_PIPELINE_GET_POOL_TYPE; + static DeclareMemType MTYPE_PIPELINE_ADD_POOL; + static DeclareMemType MTYPE_PIPELINE_ALLOCATE_DRAWABLE; + static DeclareMemType MTYPE_PIPELINE_ADD_OBJECT; + static DeclareMemType MTYPE_PIPELINE_CREATE_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_UPDATE_MOVE; + static DeclareMemType MTYPE_PIPELINE_UPDATE_GEOM; + static DeclareMemType MTYPE_PIPELINE_MARK_VISIBLE; + static DeclareMemType MTYPE_PIPELINE_MARK_MOVED; + static DeclareMemType MTYPE_PIPELINE_MARK_SHIFT; + static DeclareMemType MTYPE_PIPELINE_SHIFT_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_MARK_TEXTURED; + static DeclareMemType MTYPE_PIPELINE_MARK_REBUILD; + static DeclareMemType MTYPE_PIPELINE_UPDATE_CULL; + static DeclareMemType MTYPE_PIPELINE_STATE_SORT; + static DeclareMemType MTYPE_PIPELINE_POST_SORT; + + static DeclareMemType MTYPE_PIPELINE_RENDER_HUD_ELS; + static DeclareMemType MTYPE_PIPELINE_RENDER_HL; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_DEFFERRED; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_POST_DEF; + static DeclareMemType MTYPE_PIPELINE_RENDER_GEOM_SHADOW; + static DeclareMemType MTYPE_PIPELINE_RENDER_SELECT; + static DeclareMemType MTYPE_PIPELINE_REBUILD_POOLS; + static DeclareMemType MTYPE_PIPELINE_QUICK_LOOKUP; + static DeclareMemType MTYPE_PIPELINE_RENDER_OBJECTS; + static DeclareMemType MTYPE_PIPELINE_GENERATE_IMPOSTOR; + static DeclareMemType MTYPE_PIPELINE_RENDER_BLOOM; + + static DeclareMemType MTYPE_UPKEEP_POOLS; + + static DeclareMemType MTYPE_AVATAR; + static DeclareMemType MTYPE_AVATAR_MESH; + static DeclareMemType MTYPE_PARTICLES; + static DeclareMemType MTYPE_REGIONS; + + static DeclareMemType MTYPE_INVENTORY; + static DeclareMemType MTYPE_INVENTORY_DRAW; + static DeclareMemType MTYPE_INVENTORY_BUILD_NEW_VIEWS; + static DeclareMemType MTYPE_INVENTORY_DO_FOLDER; + static DeclareMemType MTYPE_INVENTORY_POST_BUILD; + static DeclareMemType MTYPE_INVENTORY_FROM_XML; + static DeclareMemType MTYPE_INVENTORY_CREATE_NEW_ITEM; + static DeclareMemType MTYPE_INVENTORY_VIEW_INIT; + static DeclareMemType MTYPE_INVENTORY_VIEW_SHOW; + static DeclareMemType MTYPE_INVENTORY_VIEW_TOGGLE; + + static DeclareMemType MTYPE_ANIMATION; + static DeclareMemType MTYPE_VOLUME; + static DeclareMemType MTYPE_PRIMITIVE; + + static DeclareMemType MTYPE_SCRIPT; + static DeclareMemType MTYPE_SCRIPT_RUN; + static DeclareMemType MTYPE_SCRIPT_BYTECODE; + + static DeclareMemType MTYPE_IO_PUMP; + static DeclareMemType MTYPE_IO_TCP; + static DeclareMemType MTYPE_IO_BUFFER; + static DeclareMemType MTYPE_IO_HTTP_SERVER; + static DeclareMemType MTYPE_IO_SD_SERVER; + static DeclareMemType MTYPE_IO_SD_CLIENT; + static DeclareMemType MTYPE_IO_URL_REQUEST; + + static DeclareMemType MTYPE_DIRECTX_INIT; + + static DeclareMemType MTYPE_TEMP1; + static DeclareMemType MTYPE_TEMP2; + static DeclareMemType MTYPE_TEMP3; + static DeclareMemType MTYPE_TEMP4; + static DeclareMemType MTYPE_TEMP5; + static DeclareMemType MTYPE_TEMP6; + static DeclareMemType MTYPE_TEMP7; + static DeclareMemType MTYPE_TEMP8; + static DeclareMemType MTYPE_TEMP9; + + static DeclareMemType MTYPE_OTHER; // Special; used by display code + + S32 mTypeIndex; }; //---------------------------------------------------------------------------- diff --git a/indra/llcommon/llpointer.h b/indra/llcommon/llpointer.h new file mode 100644 index 0000000000..2c37eadcc6 --- /dev/null +++ b/indra/llcommon/llpointer.h @@ -0,0 +1,177 @@ +/** + * @file llpointer.h + * @brief A reference-counted pointer for objects derived from LLRefCount + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLPOINTER_H +#define LLPOINTER_H + +#include "llerror.h" // *TODO: consider eliminating this + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// NOTE: LLPointer x = new LLFoo(); MAY NOT BE THREAD SAFE +// if LLFoo::LLFoo() does anything like put itself in an update queue. +// The queue may get accessed before it gets assigned to x. +// The correct implementation is: +// LLPointer x = new LLFoo; // constructor does not do anything interesting +// x->instantiate(); // does stuff like place x into an update queue + +// see llthread.h for LLThreadSafeRefCount + +//---------------------------------------------------------------------------- + +// Note: relies on Type having ref() and unref() methods +template class LLPointer +{ +public: + + LLPointer() : + mPointer(NULL) + { + } + + LLPointer(Type* ptr) : + mPointer(ptr) + { + ref(); + } + + LLPointer(const LLPointer& ptr) : + mPointer(ptr.mPointer) + { + ref(); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer(const LLPointer& ptr) : + mPointer(ptr.get()) + { + ref(); + } + + ~LLPointer() + { + unref(); + } + + Type* get() const { return mPointer; } + const Type* operator->() const { return mPointer; } + Type* operator->() { return mPointer; } + const Type& operator*() const { return *mPointer; } + Type& operator*() { return *mPointer; } + + operator BOOL() const { return (mPointer != NULL); } + operator bool() const { return (mPointer != NULL); } + bool operator!() const { return (mPointer == NULL); } + bool isNull() const { return (mPointer == NULL); } + bool notNull() const { return (mPointer != NULL); } + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLPointer& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLPointer& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLPointer& ptr) const { return (mPointer > ptr.mPointer); } + + LLPointer& operator =(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + + return *this; + } + + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.mPointer ) + { + unref(); + mPointer = ptr.mPointer; + ref(); + } + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLPointer& operator =(const LLPointer& ptr) + { + if( mPointer != ptr.get() ) + { + unref(); + mPointer = ptr.get(); + ref(); + } + return *this; + } + + // Just exchange the pointers, which will not change the reference counts. + static void swap(LLPointer& a, LLPointer& b) + { + Type* temp = a.mPointer; + a.mPointer = b.mPointer; + b.mPointer = temp; + } + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llptrto.cpp b/indra/llcommon/llptrto.cpp new file mode 100644 index 0000000000..ce93f09489 --- /dev/null +++ b/indra/llcommon/llptrto.cpp @@ -0,0 +1,108 @@ +/** + * @file llptrto.cpp + * @author Nat Goodspeed + * @date 2008-08-20 + * @brief Test for llptrto.h + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llptrto.h" +// STL headers +// std headers +// external library headers +#include +#include +// other Linden headers +#include "llmemory.h" + +// a refcounted class +class RCFoo: public LLRefCount +{ +public: + RCFoo() {} +}; + +// a refcounted subclass +class RCSubFoo: public RCFoo +{ +public: + RCSubFoo() {} +}; + +// a refcounted class using the other refcount base class +class TSRCFoo: public LLThreadSafeRefCount +{ +public: + TSRCFoo() {} +}; + +// a non-refcounted class +class Bar +{ +public: + Bar() {} +}; + +// a non-refcounted subclass +class SubBar: public Bar +{ +public: + SubBar() {} +}; + +int main(int argc, char *argv[]) +{ + // test LLPtrTo<> + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, LLPointer >::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, Bar*>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, SubBar*>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, int*>::value)); + + // Test LLRemovePointer<>. Note that we remove both pointer variants from + // each kind of type, regardless of whether the variant makes sense. + BOOST_STATIC_ASSERT((boost::is_same::type, RCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, RCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, RCSubFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, RCSubFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, TSRCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, TSRCFoo>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, Bar>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, Bar>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, SubBar>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, SubBar>::value)); + BOOST_STATIC_ASSERT((boost::is_same::type, int>::value)); + BOOST_STATIC_ASSERT((boost::is_same >::type, int>::value)); + + return 0; +} diff --git a/indra/llcommon/llptrto.h b/indra/llcommon/llptrto.h new file mode 100644 index 0000000000..74c117a7f6 --- /dev/null +++ b/indra/llcommon/llptrto.h @@ -0,0 +1,93 @@ +/** + * @file llptrto.h + * @author Nat Goodspeed + * @date 2008-08-19 + * @brief LLPtrTo is a template helper to pick either TARGET* or -- when + * TARGET is a subclass of LLRefCount or LLThreadSafeRefCount -- + * LLPointer. LLPtrTo<> chooses whichever pointer type is best. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLPTRTO_H) +#define LL_LLPTRTO_H + +#include "llpointer.h" +#include "llrefcount.h" // LLRefCount +#include "llthread.h" // LLThreadSafeRefCount +#include +#include +#include + +/** + * LLPtrTo::type is either of two things: + * + * * When TARGET is a subclass of either LLRefCount or LLThreadSafeRefCount, + * LLPtrTo::type is LLPointer. + * * Otherwise, LLPtrTo::type is TARGET*. + * + * This way, a class template can use LLPtrTo::type to select an + * appropriate pointer type to store. + */ +template +struct LLPtrTo +{ + typedef T* type; +}; + +/// specialize for subclasses of LLRefCount +template +struct LLPtrTo >::type> +{ + typedef LLPointer type; +}; + +/// specialize for subclasses of LLThreadSafeRefCount +template +struct LLPtrTo >::type> +{ + typedef LLPointer type; +}; + +/** + * LLRemovePointer::type gets you the underlying (pointee) type. + */ +template +struct LLRemovePointer +{ + typedef typename boost::remove_pointer::type type; +}; + +/// specialize for LLPointer +template +struct LLRemovePointer< LLPointer > +{ + typedef SOMECLASS type; +}; + +#endif /* ! defined(LL_LLPTRTO_H) */ diff --git a/indra/llcommon/llqueuedthread.cpp b/indra/llcommon/llqueuedthread.cpp index cd53e701d2..3db5c36545 100644 --- a/indra/llcommon/llqueuedthread.cpp +++ b/indra/llcommon/llqueuedthread.cpp @@ -31,7 +31,9 @@ #include "linden_common.h" #include "llqueuedthread.h" + #include "llstl.h" +#include "lltimer.h" // ms_sleep() //============================================================================ diff --git a/indra/llcommon/llrefcount.cpp b/indra/llcommon/llrefcount.cpp new file mode 100644 index 0000000000..33b6875fb0 --- /dev/null +++ b/indra/llcommon/llrefcount.cpp @@ -0,0 +1,49 @@ +/** + * @file llrefcount.cpp + * @brief Base class for reference counted objects for use with LLPointer + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +#include "llrefcount.h" + +#include "llerror.h" + +LLRefCount::LLRefCount() : + mRef(0) +{ +} + +LLRefCount::~LLRefCount() +{ + if (mRef != 0) + { + llerrs << "deleting non-zero reference" << llendl; + } +} diff --git a/indra/llcommon/llrefcount.h b/indra/llcommon/llrefcount.h new file mode 100644 index 0000000000..540a18b8a0 --- /dev/null +++ b/indra/llcommon/llrefcount.h @@ -0,0 +1,78 @@ +/** + * @file llrefcount.h + * @brief Base class for reference counted objects for use with LLPointer + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLREFCOUNT_H +#define LLREFCOUNT_H + +//---------------------------------------------------------------------------- +// RefCount objects should generally only be accessed by way of LLPointer<>'s +// see llthread.h for LLThreadSafeRefCount +//---------------------------------------------------------------------------- + +class LLRefCount +{ +protected: + LLRefCount(const LLRefCount&); // not implemented +private: + LLRefCount&operator=(const LLRefCount&); // not implemented + +protected: + virtual ~LLRefCount(); // use unref() + +public: + LLRefCount(); + + void ref() + { + mRef++; + } + + S32 unref() + { + llassert(mRef >= 1); + if (0 == --mRef) + { + delete this; + return 0; + } + return mRef; + } + + S32 getNumRefs() const + { + return mRef; + } + +private: + S32 mRef; +}; + +#endif diff --git a/indra/llcommon/llsafehandle.h b/indra/llcommon/llsafehandle.h new file mode 100644 index 0000000000..1f7c682fd1 --- /dev/null +++ b/indra/llcommon/llsafehandle.h @@ -0,0 +1,167 @@ +/** + * @file llsafehandle.h + * @brief Reference-counted object where Object() is valid, not NULL. + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLSAFEHANDLE_H +#define LLSAFEHANDLE_H + +#include "llerror.h" // *TODO: consider eliminating this + +// Expands LLPointer to return a pointer to a special instance of class Type instead of NULL. +// This is useful in instances where operations on NULL pointers are semantically safe and/or +// when error checking occurs at a different granularity or in a different part of the code +// than when referencing an object via a LLSafeHandle. + +template +class LLSafeHandle +{ +public: + LLSafeHandle() : + mPointer(NULL) + { + } + + LLSafeHandle(Type* ptr) : + mPointer(NULL) + { + assign(ptr); + } + + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.mPointer); + } + + // support conversion up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle(const LLSafeHandle& ptr) : + mPointer(NULL) + { + assign(ptr.get()); + } + + ~LLSafeHandle() + { + unref(); + } + + const Type* operator->() const { return nonNull(mPointer); } + Type* operator->() { return nonNull(mPointer); } + + Type* get() const { return mPointer; } + // we disallow these operations as they expose our null objects to direct manipulation + // and bypass the reference counting semantics + //const Type& operator*() const { return *nonNull(mPointer); } + //Type& operator*() { return *nonNull(mPointer); } + + operator BOOL() const { return mPointer != NULL; } + operator bool() const { return mPointer != NULL; } + bool operator!() const { return mPointer == NULL; } + bool isNull() const { return mPointer == NULL; } + bool notNull() const { return mPointer != NULL; } + + + operator Type*() const { return mPointer; } + operator const Type*() const { return mPointer; } + bool operator !=(Type* ptr) const { return (mPointer != ptr); } + bool operator ==(Type* ptr) const { return (mPointer == ptr); } + bool operator ==(const LLSafeHandle& ptr) const { return (mPointer == ptr.mPointer); } + bool operator < (const LLSafeHandle& ptr) const { return (mPointer < ptr.mPointer); } + bool operator > (const LLSafeHandle& ptr) const { return (mPointer > ptr.mPointer); } + + LLSafeHandle& operator =(Type* ptr) + { + assign(ptr); + return *this; + } + + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.mPointer); + return *this; + } + + // support assignment up the type hierarchy. See Item 45 in Effective C++, 3rd Ed. + template + LLSafeHandle& operator =(const LLSafeHandle& ptr) + { + assign(ptr.get()); + return *this; + } + +public: + typedef Type* (*NullFunc)(); + static const NullFunc sNullFunc; + +protected: + void ref() + { + if (mPointer) + { + mPointer->ref(); + } + } + + void unref() + { + if (mPointer) + { + Type *tempp = mPointer; + mPointer = NULL; + tempp->unref(); + if (mPointer != NULL) + { + llwarns << "Unreference did assignment to non-NULL because of destructor" << llendl; + unref(); + } + } + } + + void assign(Type* ptr) + { + if( mPointer != ptr ) + { + unref(); + mPointer = ptr; + ref(); + } + } + + static Type* nonNull(Type* ptr) + { + return ptr == NULL ? sNullFunc() : ptr; + } + +protected: + Type* mPointer; +}; + +#endif diff --git a/indra/llcommon/llsdserialize.cpp b/indra/llcommon/llsdserialize.cpp index 7a66d70d3f..cf337be161 100644 --- a/indra/llcommon/llsdserialize.cpp +++ b/indra/llcommon/llsdserialize.cpp @@ -34,7 +34,7 @@ #include "linden_common.h" #include "llsdserialize.h" -#include "llmemory.h" +#include "llpointer.h" #include "llstreamtools.h" // for fullread #include diff --git a/indra/llcommon/llsdserialize.h b/indra/llcommon/llsdserialize.h index bb38b75d8f..7463d1e5dd 100644 --- a/indra/llcommon/llsdserialize.h +++ b/indra/llcommon/llsdserialize.h @@ -36,8 +36,9 @@ #define LL_LLSDSERIALIZE_H #include +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" -#include "llmemory.h" /** * @class LLSDParser diff --git a/indra/llcommon/llsdutil.cpp b/indra/llcommon/llsdutil.cpp index aa0e0f3696..0202a033c3 100644 --- a/indra/llcommon/llsdutil.cpp +++ b/indra/llcommon/llsdutil.cpp @@ -171,6 +171,15 @@ char* ll_print_sd(const LLSD& sd) return buffer; } +char* ll_pretty_print_sd_ptr(const LLSD* sd) +{ + if (sd) + { + return ll_pretty_print_sd(*sd); + } + return NULL; +} + char* ll_pretty_print_sd(const LLSD& sd) { const U32 bufferSize = 10 * 1024; diff --git a/indra/llcommon/llsdutil.h b/indra/llcommon/llsdutil.h index b67ad521ea..501600f1d9 100644 --- a/indra/llcommon/llsdutil.h +++ b/indra/llcommon/llsdutil.h @@ -89,6 +89,7 @@ LLSD ll_binary_from_string(const LLSD& sd); 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); //compares the structure of an LLSD to a template LLSD and stores the diff --git a/indra/llcommon/llsecondlifeurls.cpp b/indra/llcommon/llsecondlifeurls.cpp index 36d8e8870f..6323d9d36b 100644 --- a/indra/llcommon/llsecondlifeurls.cpp +++ b/indra/llcommon/llsecondlifeurls.cpp @@ -32,57 +32,59 @@ #include "linden_common.h" #include "llsecondlifeurls.h" - +/* const std::string CREATE_ACCOUNT_URL ( "http://secondlife.com/registration/"); const std::string MANAGE_ACCOUNT ( - "http://secondlife.com/account/"); + "http://secondlife.com/account/"); // *TODO: NOT USED const std::string AUCTION_URL ( "http://secondlife.com/auctions/auction-detail.php?id="); const std::string EVENTS_URL ( "http://secondlife.com/events/"); - +*/ const std::string TIER_UP_URL ( - "http://secondlife.com/app/landtier"); + "http://secondlife.com/app/landtier"); // *TODO: Translate (simulator) +const std::string DIRECTX_9_URL ( + "http://secondlife.com/support/"); // *TODO: NOT USED +/* const std::string LAND_URL ( - "http://secondlife.com/app/landtier"); + "http://secondlife.com/app/landtier"); // *TODO: NOT USED const std::string UPGRADE_TO_PREMIUM_URL ( - "http://secondlife.com/app/upgrade/"); - -const std::string DIRECTX_9_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/app/upgrade/"); // *TODO: NOT USED const std::string AMD_AGP_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string VIA_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string SUPPORT_URL ( "http://secondlife.com/support/"); const std::string INTEL_CHIPSET_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string SIS_CHIPSET_URL ( - "http://secondlife.com/support/"); + "http://secondlife.com/support/"); // *TODO: NOT USED const std::string BLOGS_URL ( - "http://blog.secondlife.com/"); + "http://blog.secondlife.com/"); // *TODO: NOT USED const std::string BUY_CURRENCY_URL ( "http://secondlife.com/app/currency/"); const std::string LSL_DOC_URL ( - "http://secondlife.com/app/lsldoc/"); + "http://secondlife.com/app/lsldoc/"); // *TODO: NOT USED const std::string SL_KB_URL ( - "http://secondlife.com/knowledgebase/"); + "http://secondlife.com/knowledgebase/"); // *TODO: NOT USED const std::string RELEASE_NOTES_BASE_URL ( "http://secondlife.com/app/releasenotes/"); +*/ + diff --git a/indra/llcommon/llsecondlifeurls.h b/indra/llcommon/llsecondlifeurls.h index 9fd75c363b..a2e5f0b9c6 100644 --- a/indra/llcommon/llsecondlifeurls.h +++ b/indra/llcommon/llsecondlifeurls.h @@ -32,7 +32,7 @@ #ifndef LL_LLSECONDLIFEURLS_H #define LL_LLSECONDLIFEURLS_H - +/* // Account registration web page extern const std::string CREATE_ACCOUNT_URL; @@ -42,18 +42,21 @@ extern const std::string MANAGE_ACCOUNT; extern const std::string AUCTION_URL; extern const std::string EVENTS_URL; - +*/ // Tier up to a new land level. extern const std::string TIER_UP_URL; + // Tier up to a new land level. extern const std::string LAND_URL; +// How to get DirectX 9 +extern const std::string DIRECTX_9_URL; + +/* // Upgrade from basic membership to premium membership extern const std::string UPGRADE_TO_PREMIUM_URL; -// How to get DirectX 9 -extern const std::string DIRECTX_9_URL; // Out of date VIA chipset extern const std::string VIA_URL; @@ -75,5 +78,5 @@ extern const std::string SL_KB_URL; // Release Notes Redirect URL for Server and Viewer extern const std::string RELEASE_NOTES_BASE_URL; - +*/ #endif diff --git a/indra/llcommon/llsingleton.h b/indra/llcommon/llsingleton.h new file mode 100644 index 0000000000..dc1457e4f7 --- /dev/null +++ b/indra/llcommon/llsingleton.h @@ -0,0 +1,158 @@ +/** + * @file llsingleton.h + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLSINGLETON_H +#define LLSINGLETON_H + +#include "llerror.h" // *TODO: eliminate this + +#include + +// LLSingleton implements the getInstance() method part of the Singleton +// pattern. It can't make the derived class constructors protected, though, so +// you have to do that yourself. +// +// There are two ways to use LLSingleton. The first way is to inherit from it +// while using the typename that you'd like to be static as the template +// parameter, like so: +// +// class Foo: public LLSingleton{}; +// +// Foo& instance = Foo::instance(); +// +// The second way is to use the singleton class directly, without inheritance: +// +// typedef LLSingleton FooSingleton; +// +// Foo& instance = FooSingleton::instance(); +// +// In this case, the class being managed as a singleton needs to provide an +// initSingleton() method since the LLSingleton virtual method won't be +// available +// +// As currently written, it is not thread-safe. + +template +class LLSingleton : private boost::noncopyable +{ + +private: + typedef enum e_init_state + { + UNINITIALIZED, + CONSTRUCTING, + INITIALIZING, + INITIALIZED, + DELETED + } EInitState; + + static void deleteSingleton() + { + delete getData().mSingletonInstance; + getData().mSingletonInstance = NULL; + } + + // stores pointer to singleton instance + // and tracks initialization state of singleton + struct SingletonInstanceData + { + EInitState mInitState; + DERIVED_TYPE* mSingletonInstance; + + SingletonInstanceData() + : mSingletonInstance(NULL), + mInitState(UNINITIALIZED) + {} + + ~SingletonInstanceData() + { + deleteSingleton(); + } + }; + +public: + virtual ~LLSingleton() + { + SingletonInstanceData& data = getData(); + data.mSingletonInstance = NULL; + data.mInitState = DELETED; + } + + static SingletonInstanceData& getData() + { + static SingletonInstanceData data; + return data; + } + + static DERIVED_TYPE* getInstance() + { + SingletonInstanceData& data = getData(); + + if (data.mInitState == CONSTRUCTING) + { + llerrs << "Tried to access singleton " << typeid(DERIVED_TYPE).name() << " from singleton constructor!" << llendl; + } + + if (data.mInitState == DELETED) + { + llwarns << "Trying to access deleted singleton " << typeid(DERIVED_TYPE).name() << " creating new instance" << llendl; + } + + if (!data.mSingletonInstance) + { + data.mInitState = CONSTRUCTING; + data.mSingletonInstance = new DERIVED_TYPE(); + data.mInitState = INITIALIZING; + data.mSingletonInstance->initSingleton(); + data.mInitState = INITIALIZED; + } + + return data.mSingletonInstance; + } + + // Reference version of getInstance() + // Preferred over getInstance() as it disallows checking for NULL + static DERIVED_TYPE& instance() + { + return *getInstance(); + } + + // Has this singleton already been deleted? + // Use this to avoid accessing singletons from a static object's destructor + static bool destroyed() + { + return getData().mInitState == DELETED; + } + +private: + virtual void initSingleton() {} +}; + +#endif diff --git a/indra/llcommon/llstacktrace.cpp b/indra/llcommon/llstacktrace.cpp new file mode 100644 index 0000000000..4be91b5b11 --- /dev/null +++ b/indra/llcommon/llstacktrace.cpp @@ -0,0 +1,141 @@ +/** + * @file llstacktrace.cpp + * @brief stack tracing functionality + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "llstacktrace.h" + +#ifdef LL_WINDOWS + +#include +#include + +#include "windows.h" +#include "Dbghelp.h" + +typedef USHORT NTAPI RtlCaptureStackBackTrace_Function( + IN ULONG frames_to_skip, + IN ULONG frames_to_capture, + OUT PVOID *backtrace, + OUT PULONG backtrace_hash); + +static RtlCaptureStackBackTrace_Function* const RtlCaptureStackBackTrace_fn = + (RtlCaptureStackBackTrace_Function*) + GetProcAddress(GetModuleHandleA("ntdll.dll"), "RtlCaptureStackBackTrace"); + +bool ll_get_stack_trace(std::vector& lines) +{ + const S32 MAX_STACK_DEPTH = 32; + const S32 STRING_NAME_LENGTH = 200; + const S32 FRAME_SKIP = 2; + static BOOL symbolsLoaded = false; + static BOOL firstCall = true; + + HANDLE hProc = GetCurrentProcess(); + + // load the symbols if they're not loaded + if(!symbolsLoaded && firstCall) + { + symbolsLoaded = SymInitialize(hProc, NULL, true); + firstCall = false; + } + + // if loaded, get the call stack + if(symbolsLoaded) + { + // create the frames to hold the addresses + void* frames[MAX_STACK_DEPTH]; + memset(frames, 0, sizeof(void*)*MAX_STACK_DEPTH); + S32 depth = 0; + + // get the addresses + depth = RtlCaptureStackBackTrace_fn(FRAME_SKIP, MAX_STACK_DEPTH, frames, NULL); + + IMAGEHLP_LINE64 line; + memset(&line, 0, sizeof(IMAGEHLP_LINE64)); + line.SizeOfStruct = sizeof(IMAGEHLP_LINE64); + + // create something to hold address info + PIMAGEHLP_SYMBOL64 pSym; + pSym = (PIMAGEHLP_SYMBOL64)malloc(sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + memset(pSym, 0, sizeof(IMAGEHLP_SYMBOL64) + STRING_NAME_LENGTH); + pSym->MaxNameLength = STRING_NAME_LENGTH; + pSym->SizeOfStruct = sizeof(IMAGEHLP_SYMBOL64); + + // get address info for each address frame + // and store + for(S32 i=0; i < depth; i++) + { + std::stringstream stack_line; + BOOL ret; + + DWORD64 addr = (DWORD64)frames[i]; + ret = SymGetSymFromAddr64(hProc, addr, 0, pSym); + if(ret) + { + stack_line << pSym->Name << " "; + } + + DWORD dummy; + ret = SymGetLineFromAddr64(hProc, addr, &dummy, &line); + if(ret) + { + std::string file_name = line.FileName; + std::string::size_type index = file_name.rfind("\\"); + stack_line << file_name.substr(index + 1, file_name.size()) << ":" << line.LineNumber; + } + + lines.push_back(stack_line.str()); + } + + free(pSym); + + // TODO: figure out a way to cleanup symbol loading + // Not hugely necessary, however. + //SymCleanup(hProc); + return true; + } + else + { + lines.push_back("Stack Trace Failed. PDB symbol info not loaded"); + } + + return false; +} + +#else + +bool ll_get_stack_trace(std::vector& lines) +{ + return false; +} + +#endif + diff --git a/indra/llcommon/llstacktrace.h b/indra/llcommon/llstacktrace.h new file mode 100644 index 0000000000..609b934a97 --- /dev/null +++ b/indra/llcommon/llstacktrace.h @@ -0,0 +1,44 @@ +/** + * @file llstacktrace.h + * @brief stack trace functions + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + + +#ifndef LL_LLSTACKTRACE_H +#define LL_LLSTACKTRACE_H + +#include "stdtypes.h" +#include +#include + +bool ll_get_stack_trace(std::vector& lines); + +#endif + diff --git a/indra/llcommon/llstat.cpp b/indra/llcommon/llstat.cpp index 291b019616..90dae11793 100644 --- a/indra/llcommon/llstat.cpp +++ b/indra/llcommon/llstat.cpp @@ -46,6 +46,7 @@ BOOL LLPerfBlock::sStatsEnabled = FALSE; // Flag for detailed information LLPerfBlock::stat_map_t LLPerfBlock::sStatMap; // Map full path string to LLStatTime objects, tracks all active objects std::string LLPerfBlock::sCurrentStatPath = ""; // Something like "/total_time/physics/physics step" +LLStat::stat_map_t LLStat::sStatList; //------------------------------------------------------------------------ // Live config file to trigger stats logging @@ -725,28 +726,48 @@ void LLPerfBlock::addStatsToLLSDandReset( LLSD & stats, LLTimer LLStat::sTimer; LLFrameTimer LLStat::sFrameTimer; -LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) +void LLStat::init() { - llassert(num_bins > 0); - U32 i; - mUseFrameTimer = use_frame_timer; + llassert(mNumBins > 0); mNumValues = 0; mLastValue = 0.f; mLastTime = 0.f; - mNumBins = num_bins; mCurBin = (mNumBins-1); mNextBin = 0; mBins = new F32[mNumBins]; mBeginTime = new F64[mNumBins]; mTime = new F64[mNumBins]; mDT = new F32[mNumBins]; - for (i = 0; i < mNumBins; i++) + for (U32 i = 0; i < mNumBins; i++) { mBins[i] = 0.f; mBeginTime[i] = 0.0; mTime[i] = 0.0; mDT[i] = 0.f; } + + if (!mName.empty()) + { + stat_map_t::iterator iter = sStatList.find(mName); + if (iter != sStatList.end()) + llwarns << "LLStat with duplicate name: " << mName << llendl; + sStatList.insert(std::make_pair(mName, this)); + } +} + +LLStat::LLStat(const U32 num_bins, const BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins) +{ + init(); +} + +LLStat::LLStat(std::string name, U32 num_bins, BOOL use_frame_timer) + : mUseFrameTimer(use_frame_timer), + mNumBins(num_bins), + mName(name) +{ + init(); } LLStat::~LLStat() @@ -755,6 +776,15 @@ LLStat::~LLStat() delete[] mBeginTime; delete[] mTime; delete[] mDT; + + if (!mName.empty()) + { + // handle multiple entries with the same name + stat_map_t::iterator iter = sStatList.find(mName); + while (iter != sStatList.end() && iter->second != this) + ++iter; + sStatList.erase(iter); + } } void LLStat::reset() diff --git a/indra/llcommon/llstat.h b/indra/llcommon/llstat.h index 61aaac45bf..bad18f46a0 100644 --- a/indra/llcommon/llstat.h +++ b/indra/llcommon/llstat.h @@ -258,8 +258,15 @@ private: // ---------------------------------------------------------------------------- class LLStat { +private: + typedef std::multimap stat_map_t; + static stat_map_t sStatList; + + void init(); + public: - LLStat(const U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(U32 num_bins = 32, BOOL use_frame_timer = FALSE); + LLStat(std::string name, U32 num_bins = 32, BOOL use_frame_timer = FALSE); ~LLStat(); void reset(); @@ -322,8 +329,22 @@ private: F32 *mDT; S32 mCurBin; S32 mNextBin; + + std::string mName; + static LLTimer sTimer; static LLFrameTimer sFrameTimer; + +public: + static LLStat* getStat(const std::string& name) + { + // return the first stat that matches 'name' + stat_map_t::iterator iter = sStatList.find(name); + if (iter != sStatList.end()) + return iter->second; + else + return NULL; + } }; - + #endif // LL_STAT_ diff --git a/indra/llcommon/llstring.cpp b/indra/llcommon/llstring.cpp index 1f653c159c..ec1718a8cb 100644 --- a/indra/llcommon/llstring.cpp +++ b/indra/llcommon/llstring.cpp @@ -71,6 +71,24 @@ U8 hex_as_nybble(char hex) return 0; // uh - oh, not hex any more... } +bool iswindividual(llwchar elem) +{ + U32 cur_char = (U32)elem; + bool result = false; + if (0x2E80<= cur_char && cur_char <= 0x9FFF) + { + result = true; + } + else if (0xAC00<= cur_char && cur_char <= 0xD7A0 ) + { + result = true; + } + else if (0xF900<= cur_char && cur_char <= 0xFA60 ) + { + result = true; + } + return result; +} bool _read_file_into_string(std::string& str, const std::string& filename) { @@ -650,6 +668,11 @@ std::string ll_convert_wide_to_string(const wchar_t* in) } #endif // LL_WINDOWS +long LLStringOps::sltOffset; +long LLStringOps::localTimeOffset; +bool LLStringOps::daylightSavings; +std::map LLStringOps::datetimeToCodes; + S32 LLStringOps::collate(const llwchar* a, const llwchar* b) { #if LL_WINDOWS @@ -661,6 +684,59 @@ S32 LLStringOps::collate(const llwchar* a, const llwchar* b) #endif } +void LLStringOps::setupDatetimeInfo (bool daylight) +{ + time_t nowT, localT, gmtT; + struct tm * tmpT; + + nowT = time (NULL); + + tmpT = localtime (&nowT); + localT = mktime (tmpT); + + tmpT = gmtime (&nowT); + gmtT = mktime (tmpT); + + localTimeOffset = (long) (gmtT - localT); + + + daylightSavings = daylight; + sltOffset = (daylightSavings? 7 : 8 ) * 60 * 60; + + datetimeToCodes["wkday"] = "%a"; // Thu + datetimeToCodes["weekday"] = "%A"; // Thursday + datetimeToCodes["year4"] = "%Y"; // 2009 + datetimeToCodes["year"] = "%Y"; // 2009 + datetimeToCodes["year2"] = "%y"; // 09 + datetimeToCodes["mth"] = "%b"; // Aug + datetimeToCodes["month"] = "%B"; // August + datetimeToCodes["mthnum"] = "%m"; // 08 + datetimeToCodes["day"] = "%d"; // 31 + datetimeToCodes["hour24"] = "%H"; // 14 + datetimeToCodes["hour"] = "%H"; // 14 + datetimeToCodes["hour12"] = "%I"; // 02 + datetimeToCodes["min"] = "%M"; // 59 + datetimeToCodes["ampm"] = "%p"; // AM + datetimeToCodes["second"] = "%S"; // 59 + datetimeToCodes["timezone"] = "%Z"; // PST +} + +std::string LLStringOps::getDatetimeCode (std::string key) +{ + std::map::iterator iter; + + iter = datetimeToCodes.find (key); + if (iter != datetimeToCodes.end()) + { + return iter->second; + } + else + { + return std::string(""); + } +} + + namespace LLStringFn { // NOTE - this restricts output to ascii diff --git a/indra/llcommon/llstring.h b/indra/llcommon/llstring.h index 6ba665b8d2..91b706a5be 100644 --- a/indra/llcommon/llstring.h +++ b/indra/llcommon/llstring.h @@ -34,6 +34,10 @@ #define LL_LLSTRING_H #include +#include +#include +#include +#include "llsd.h" #if LL_LINUX || LL_SOLARIS #include @@ -145,6 +149,12 @@ struct char_traits class LLStringOps { +private: + static long sltOffset; + static long localTimeOffset; + static bool daylightSavings; + static std::map datetimeToCodes; + public: static char toUpper(char elem) { return toupper((unsigned char)elem); } static llwchar toUpper(llwchar elem) { return towupper(elem); } @@ -172,6 +182,12 @@ 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 std::string getDatetimeCode (std::string key); }; /** @@ -201,6 +217,9 @@ private: template class LLStringUtilBase { +private: + static std::string sLocale; + public: typedef typename std::basic_string::size_type size_type; @@ -211,7 +230,14 @@ public: static std::basic_string null; typedef std::map format_map_t; + static void getTokens (std::basic_string input, std::vector >& tokens); + static void formatNumber(std::basic_string& numStr, std::basic_string decimals); + static bool formatDatetime(std::basic_string& replacement, std::basic_string token, std::basic_string param, const LLSD& substitutions); + static S32 format(std::basic_string& s, const LLSD& substitutions); static S32 format(std::basic_string& s, const format_map_t& fmt_map); + static bool simpleReplacement(std::basic_string& replacement, std::basic_string token, const LLSD& substitutions); + static void setLocale (std::string inLocale) {sLocale = inLocale;}; + static std::string getLocale (void) {return sLocale;}; static bool isValidIndex(const std::basic_string& string, size_type i) { @@ -317,6 +343,7 @@ public: }; template std::basic_string LLStringUtilBase::null; +template std::string LLStringUtilBase::sLocale; typedef LLStringUtilBase LLStringUtil; typedef LLStringUtilBase LLWStringUtil; @@ -378,6 +405,7 @@ U8 hex_as_nybble(char hex); * @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); /** * Unicode support @@ -564,63 +592,215 @@ namespace LLStringFn //////////////////////////////////////////////////////////// -// LLStringBase::format() -// -// This function takes a string 's' and a map 'fmt_map' of strings-to-strings. -// All occurances of strings in 's' from the left-hand side of 'fmt_map' are -// then replaced with the corresponding right-hand side of 'fmt_map', non- -// recursively. The function returns the number of substitutions made. +//static +template +void LLStringUtilBase::getTokens (std::basic_string input, std::vector >& tokens) +{ + const std::basic_string delims (","); + std::basic_string currToken; + size_type begIdx, endIdx; + + begIdx = input.find_first_not_of (delims); + while (begIdx != std::basic_string::npos) + { + endIdx = input.find_first_of (delims, begIdx); + if (endIdx == std::basic_string::npos) + { + endIdx = input.length(); + } + + currToken = input.substr(begIdx, endIdx - begIdx); + trim (currToken); + tokens.push_back(currToken); + begIdx = input.find_first_not_of (delims, endIdx); + } +} // static template S32 LLStringUtilBase::format(std::basic_string& s, const format_map_t& fmt_map) { - typedef typename std::basic_string::size_type string_size_type_t; - string_size_type_t scanstart = 0; + LLSD llsdMap; + + for (format_map_t::const_iterator iter = fmt_map.begin(); + iter != fmt_map.end(); + ++iter) + { + llsdMap[iter->first] = iter->second; + } + + return format (s, llsdMap); +} + +//static +template +S32 LLStringUtilBase::format(std::basic_string& s, const LLSD& substitutions) +{ S32 res = 0; - // Look for the first match of any keyword, replace that keyword, - // repeat from the end of the replacement string. This avoids - // accidentally performing substitution on a substituted string. - while (1) + if (!substitutions.isMap()) + { + return res; + } + + std::basic_ostringstream output; + // match strings like [NAME,number,3] + const boost::regex key("\\[((\\s)*([0-9_A-Za-z]+)((\\s)*,(\\s)*[0-9_A-Za-z\\s]*){0,2}(\\s)*)]"); + + + typename std::basic_string::const_iterator start = s.begin(); + typename std::basic_string::const_iterator end = s.end(); + boost::smatch match; + + + while (boost::regex_search(start, end, match, key, boost::match_default)) { - string_size_type_t first_match_pos = scanstart; - string_size_type_t first_match_str_length = 0; - std::basic_string first_match_str_replacement; + bool found_replacement = false; + std::vector > tokens; + std::basic_string replacement; - for (format_map_t::const_iterator iter = fmt_map.begin(); - iter != fmt_map.end(); - ++iter) + getTokens (std::basic_string(match[1].first, match[1].second), tokens); + + if (tokens.size() == 1) { - string_size_type_t n = s.find(iter->first, scanstart); - if (n != std::basic_string::npos && - (n < first_match_pos || - 0 == first_match_str_length)) - { - first_match_pos = n; - first_match_str_length = iter->first.length(); - first_match_str_replacement = iter->second; - } + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); } + else if (tokens[1] == "number") + { + std::basic_string param = "0"; - if (0 == first_match_str_length) + if (tokens.size() > 2) param = tokens[2]; + found_replacement = simpleReplacement (replacement, tokens[0], substitutions); + if (found_replacement) formatNumber (replacement, param); + } + else if (tokens[1] == "datetime") { - // no more keys found to substitute from this point - // in the string forward. - break; + std::basic_string param; + if (tokens.size() > 2) param = tokens[2]; + + found_replacement = formatDatetime (replacement, tokens[0], param, substitutions); + } + + if (found_replacement) + { + output << std::basic_string(start, match[0].first) << replacement; + res++; } else { - s.erase(first_match_pos, first_match_str_length); - s.insert(first_match_pos, first_match_str_replacement); - scanstart = first_match_pos + - first_match_str_replacement.length(); - ++res; + // we had no replacement, so leave the string we searched for so that it gets noticed by QA + // "hello [NAME_NOT_FOUND]" is output + output << std::basic_string(start, match[0].second); } + + // update search position + start = match[0].second; } + // send the remainder of the string (with no further matches for bracketed names) + output << std::basic_string(start, end); + s = output.str(); return res; } +// static +template +bool LLStringUtilBase::simpleReplacement(std::basic_string &replacement, std::basic_string token, const LLSD &substitutions) +{ + // see if we have a replacement for the bracketed string (without the brackets) + // test first using has() because if we just look up with operator[] we get back an + // empty string even if the value is missing. We want to distinguish between + // missing replacements and deliberately empty replacement strings. + if (substitutions.has(token)) + { + replacement = substitutions[token].asString(); + return true; + } + // if not, see if there's one WITH brackets + else if (substitutions.has(std::basic_string("[" + token + "]"))) + { + replacement = substitutions[std::basic_string("[" + token + "]")].asString(); + return true; + } + + return false; +} + +// static +template +void LLStringUtilBase::formatNumber(std::basic_string& numStr, std::basic_string decimals) +{ + typedef typename std::basic_string::size_type string_size_type_t; + std::basic_stringstream strStream; + S32 intDecimals = 0; + + convertToS32 (decimals, intDecimals); + if (!sLocale.empty()) + { + strStream.imbue (std::locale(sLocale.c_str())); + } + + if (!intDecimals) + { + S32 intStr; + + if (convertToS32(numStr, intStr)) + { + strStream << intStr; + numStr = strStream.str(); + } + } + else + { + F32 floatStr; + + if (convertToF32(numStr, floatStr)) + { + strStream << std::fixed << std::showpoint << std::setprecision(intDecimals) << floatStr; + numStr = strStream.str(); + } + } +} + +// static +template +bool LLStringUtilBase::formatDatetime(std::basic_string& replacement, std::basic_string token, + std::basic_string param, const LLSD& substitutions) +{ + S32 secFromEpoch = (long) substitutions["datetime"].asInteger(); + + if (param == "local") // local + { + secFromEpoch -= LLStringOps::getLocalTimeOffset(); + } + else if (param != "utc") // slt + { + secFromEpoch -= LLStringOps::getSltOffset(); + } + + // if never fell into those two ifs above, param must be utc + if (secFromEpoch < 0) secFromEpoch = 0; + + LLDate * datetime = new LLDate((F64)secFromEpoch); + std::string code = LLStringOps::getDatetimeCode (token); + + // special case to handle timezone + if (code == "%Z") { + if (param == "utc") replacement = "GMT"; + else if (param != "local") replacement = LLStringOps::getDaylightSavings()? "PDT" : "PST"; + return true; + } + + replacement = datetime->toHTTPDateString(code); + if (code.empty()) + { + return false; + } + else + { + return true; + } +} + // static template S32 LLStringUtilBase::compareStrings(const T* lhs, const T* rhs) diff --git a/indra/llcommon/llthread.h b/indra/llcommon/llthread.h index c8c9fd4eec..f25339f48d 100644 --- a/indra/llcommon/llthread.h +++ b/indra/llcommon/llthread.h @@ -35,7 +35,6 @@ #include "llapr.h" #include "llapp.h" -#include "llmemory.h" #include "apr_thread_cond.h" diff --git a/indra/llcommon/lltimer.cpp b/indra/llcommon/lltimer.cpp index fa6efaf38e..ea5b0c03ef 100644 --- a/indra/llcommon/lltimer.cpp +++ b/indra/llcommon/lltimer.cpp @@ -561,32 +561,27 @@ void secondsToTimecodeString(F32 current_time, std::string& tcstring) // ////////////////////////////////////////////////////////////////////////////// -std::list LLEventTimer::sActiveList; - LLEventTimer::LLEventTimer(F32 period) : mEventTimer() { mPeriod = period; - sActiveList.push_back(this); } LLEventTimer::LLEventTimer(const LLDate& time) : mEventTimer() { mPeriod = (F32)(time.secondsSinceEpoch() - LLDate::now().secondsSinceEpoch()); - sActiveList.push_back(this); } -LLEventTimer::~LLEventTimer() +LLEventTimer::~LLEventTimer() { - sActiveList.remove(this); } void LLEventTimer::updateClass() { std::list completed_timers; - for (std::list::iterator iter = sActiveList.begin(); iter != sActiveList.end(); ) + for (instance_iter iter = beginInstances(); iter != endInstances(); ) { LLEventTimer* timer = *iter++; F32 et = timer->mEventTimer.getElapsedTimeF32(); diff --git a/indra/llcommon/lltimer.h b/indra/llcommon/lltimer.h index e2cf1c7689..0319bec45b 100644 --- a/indra/llcommon/lltimer.h +++ b/indra/llcommon/lltimer.h @@ -40,6 +40,7 @@ #include "stdtypes.h" #include "lldate.h" +#include "llinstancetracker.h" #include #include @@ -171,13 +172,13 @@ void microsecondsToTimecodeString(U64 current_time, std::string& tcstring); void secondsToTimecodeString(F32 current_time, std::string& tcstring); // class for scheduling a function to be called at a given frequency (approximate, inprecise) -class LLEventTimer +class LLEventTimer : protected LLInstanceTracker { public: LLEventTimer(F32 period); // period is the amount of time between each call to tick() in seconds LLEventTimer(const LLDate& time); virtual ~LLEventTimer(); - + //function to be called at the supplied frequency // Normally return FALSE; TRUE will delete the timer after the function returns. virtual BOOL tick() = 0; @@ -187,10 +188,6 @@ public: protected: LLTimer mEventTimer; F32 mPeriod; - -private: - //list of active timers - static std::list sActiveList; // TODO should this be a vector }; #endif diff --git a/indra/llcommon/lltreeiterators.h b/indra/llcommon/lltreeiterators.h new file mode 100644 index 0000000000..c946566e84 --- /dev/null +++ b/indra/llcommon/lltreeiterators.h @@ -0,0 +1,711 @@ +/** + * @file lltreeiterators.h + * @author Nat Goodspeed + * @date 2008-08-19 + * @brief This file defines iterators useful for traversing arbitrary node + * classes, potentially polymorphic, linked into strict tree + * structures. + * + * Dereferencing any one of these iterators actually yields a @em + * pointer to the node in question. For example, given an + * LLLinkedIter li, *li gets you a pointer + * to MyNode, and **li gets you the MyNode instance itself. + * More commonly, instead of writing li->member, you write + * (*li)->member -- as you would if you were traversing an + * STL container of MyNode pointers. + * + * It would certainly be possible to build these iterators so that + * *iterator would return a reference to the node itself + * rather than a pointer to the node, and for many purposes it would + * even be more convenient. However, that would be insufficiently + * flexible. If you want to use an iterator range to (e.g.) initialize + * a std::vector collecting results -- you rarely want to actually @em + * copy the nodes in question. You're much more likely to want to copy + * pointers to the traversed nodes. Hence these iterators + * produce pointers. + * + * Though you specify the actual NODE class as the template parameter, + * these iterators internally use LLPtrTo<> to discover whether to + * store and return an LLPointer or a simple NODE*. + * + * By strict tree structures, we mean that each child must have + * exactly one parent. This forbids a child claiming any ancestor as a + * child of its own. Child nodes with multiple parents will be visited + * once for each parent. Cycles in the graph will result in either an + * infinite loop or an out-of-memory crash. You Have Been Warned. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLTREEITERATORS_H) +#define LL_LLTREEITERATORS_H + +#include "llptrto.h" +#include +#include +#include +#include +#include + +namespace LLTreeIter +{ + /// Discriminator between LLTreeUpIter and LLTreeDownIter + enum RootIter { UP, DOWN }; + /// Discriminator between LLTreeDFSIter, LLTreeDFSPostIter and LLTreeBFSIter + enum WalkIter { DFS_PRE, DFS_POST, BFS }; +} + +/** + * LLBaseIter defines some machinery common to all these iterators. We use + * boost::iterator_facade to define the iterator boilerplate: the conventional + * operators and methods necessary to implement a standards-conforming + * iterator. That allows us to specify the actual iterator semantics in terms + * of equal(), dereference() and increment() methods. + */ +template +class LLBaseIter: public boost::iterator_facade::type, + boost::forward_traversal_tag> +{ +protected: + /// LLPtrTo::type is either NODE* or LLPointer, as appropriate + typedef typename LLPtrTo::type ptr_type; + /// function that advances from this node to next accepts a node pointer + /// and returns another + typedef boost::function func_type; + typedef SELFTYPE self_type; +}; + +/// Functor returning NULL, suitable for an end-iterator's 'next' functor +template +typename LLPtrTo::type LLNullNextFunctor(const typename LLPtrTo::type&) +{ + return typename LLPtrTo::type(); +} + +/** + * LLLinkedIter is an iterator over an intrusive singly-linked list. The + * beginning of the list is represented by LLLinkedIter(list head); the end is + * represented by LLLinkedIter(). + * + * The begin LLLinkedIter must be instantiated with a functor to extract the + * 'next' pointer from the current node. Supposing that the link pointer is @c + * public, something like: + * + * @code + * NODE* mNext; + * @endcode + * + * you can use (e.g.) boost::bind(&NODE::mNext, _1) for the purpose. + * Alternatively, you can bind whatever accessor method is normally used to + * advance to the next node, e.g. for: + * + * @code + * NODE* next() const; + * @endcode + * + * you can use boost::bind(&NODE::next, _1). + */ +template +class LLLinkedIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; +protected: + /// some methods need to return a reference to self + typedef typename super::self_type self_type; + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +public: + /// Instantiate an LLLinkedIter to start a range, or to end a range before + /// a particular list entry. Pass a functor to extract the 'next' pointer + /// from the current node. + LLLinkedIter(const ptr_type& entry, const func_type& nextfunc): + mCurrent(entry), + mNextFunc(nextfunc) + {} + /// Instantiate an LLLinkedIter to end a range at the end of the list + LLLinkedIter(): + mCurrent(), + mNextFunc(LLNullNextFunctor) + {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mCurrent = mNextFunc(mCurrent); + } + /// equality + bool equal(const self_type& that) const { return this->mCurrent == that.mCurrent; } + /// dereference + ptr_type& dereference() const { return const_cast(mCurrent); } + + ptr_type mCurrent; + func_type mNextFunc; +}; + +/** + * LLTreeUpIter walks from the node in hand to the root of the tree. The term + * "up" is applied to a tree visualized with the root at the top. + * + * LLTreeUpIter is an alias for LLLinkedIter, since any linked tree that you + * can navigate that way at all contains parent pointers. + */ +template +class LLTreeUpIter: public LLLinkedIter +{ + typedef LLLinkedIter super; +public: + /// Instantiate an LLTreeUpIter to start from a particular tree node, or + /// to end a parent traversal before reaching a particular ancestor. Pass + /// a functor to extract the 'parent' pointer from the current node. + LLTreeUpIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// Instantiate an LLTreeUpIter to end a range at the root of the tree + LLTreeUpIter(): + super() + {} +}; + +/** + * LLTreeDownIter walks from the root of the tree to the node in hand. The + * term "down" is applied to a tree visualized with the root at the top. + * + * Though you instantiate the begin() LLTreeDownIter with a pointer to some + * node at an arbitrary location in the tree, the root will be the first node + * you dereference and the passed node will be the last node you dereference. + * + * On construction, LLTreeDownIter walks from the current node to the root, + * capturing the path. Then in use, it replays that walk in reverse. As with + * all traversals of interesting data structures, it is actively dangerous to + * modify the tree during an LLTreeDownIter walk. + */ +template +class LLTreeDownIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + typedef typename super::func_type func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDownIter to end at a particular tree node. Pass a + /// functor to extract the 'parent' pointer from the current node. + LLTreeDownIter(const ptr_type& node, + const func_type& parentfunc) + { + for (ptr_type n = node; n; n = parentfunc(n)) + mParents.push_back(n); + } + /// Instantiate an LLTreeDownIter representing "here", the end of the loop + LLTreeDownIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + void increment() + { + mParents.pop_back(); + } + /// equality + bool equal(const self_type& that) const { return this->mParents == that.mParents; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mParents.back()); } + + list_type mParents; +}; + +/** + * When you want to select between LLTreeUpIter and LLTreeDownIter with a + * compile-time discriminator, use LLTreeRootIter with an LLTreeIter::RootIter + * template arg. + */ +template +class LLTreeRootIter +{ + enum { use_a_valid_LLTreeIter_RootIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeRootIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } + LLTreeRootIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_RootIter_value); + } +}; + +/// Specialize for LLTreeIter::UP +template +class LLTreeRootIter: public LLTreeUpIter +{ + typedef LLTreeUpIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DOWN +template +class LLTreeRootIter: public LLTreeDownIter +{ + typedef LLTreeDownIter super; +public: + /// forward begin ctor + LLTreeRootIter(const typename super::ptr_type& node, + const typename super::func_type& parentfunc): + super(node, parentfunc) + {} + /// forward end ctor + LLTreeRootIter(): + super() + {} +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSIter "flattens" + * a depth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeDFSIter must be instantiated with functors to obtain from + * a given node begin() and end() iterators for that node's children. For this + * reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + typedef std::vector list_type; +public: + /// Instantiate an LLTreeDFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc), + mSkipChildren(false) + { + // Only push back this node if it's non-NULL! + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeDFSIter to mark the end of the walk + LLTreeDFSIter() {} + + /// flags iterator logic to skip traversing children of current node on next increment + void skipDescendants(bool skip = true) { mSkipChildren = skip; } + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.back(); + // Remove it from mPending so we don't process it again later + mPending.pop_back(); + if (!mSkipChildren) + { + // Add all its children to mPending + addChildren(current); + } + // reset flag after each step + mSkipChildren = false; + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back()); } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // reverse-copy the children into the newly-expanded space + std::copy(chi, chend, mPending.rbegin()); + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; + /// flag which controls traversal of children (skip children of current node if true) + bool mSkipChildren; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeDFSPostIter + * "flattens" a depth-first tree walk through that node and all its + * descendants. Whereas LLTreeDFSIter visits each node before visiting any of + * its children, LLTreeDFSPostIter visits all of a node's children before + * visiting the node itself. + * + * The begin() LLTreeDFSPostIter must be instantiated with functors to obtain + * from a given node begin() and end() iterators for that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeDFSPostIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeDFSPostIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // Upon reaching a given node in our pending list, we need to know whether + // we've already pushed that node's children, so we must associate a bool + // with each node pointer. + typedef std::vector< std::pair > list_type; +public: + /// Instantiate an LLTreeDFSPostIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeDFSPostIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc), + mSkipAncestors(false) + { + if (! node) + return; + mPending.push_back(typename list_type::value_type(node, false)); + makeCurrent(); + } + /// Instantiate an LLTreeDFSPostIter to mark the end of the walk + LLTreeDFSPostIter() {} + + /// flags iterator logic to skip traversing ancestors of current node on next increment + void skipAncestors(bool skip = true) { mSkipAncestors = skip; } + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Depth-first_search + void increment() + { + // Pop the previous current node + mPending.pop_back(); + makeCurrent(); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.back().first); } + + struct isOpen + { + bool operator()(const typename list_type::value_type& item) + { + return item.second; + } + }; + + /// Call this each time we change mPending.back() -- that is, every time + /// we're about to change the value returned by dereference(). If we + /// haven't yet pushed the new node's children, do so now. + void makeCurrent() + { + if (mSkipAncestors) + { + mPending.erase(std::remove_if(mPending.begin(), mPending.end(), isOpen()), mPending.end()); + mSkipAncestors = false; + } + + // Once we've popped the last node, this becomes a no-op. + if (mPending.empty()) + return; + // Here mPending.back() holds the node pointer we're proposing to + // dereference next. Have we pushed that node's children yet? + if (mPending.back().second) + return; // if so, it's okay to visit this node now + // We haven't yet pushed this node's children. Do so now. Remember + // that we did -- while the node in question is still back(). + mPending.back().second = true; + addChildren(mPending.back().first); + // Now, because we've just changed mPending.back(), make that new node + // current. + makeCurrent(); + } + + /// Add the direct children of the specified node to mPending + void addChildren(const ptr_type& node) + { + // If we just use push_back() for each child in turn, we'll end up + // processing children in reverse order. We don't want to assume + // CHILDITER is reversible: some of the linked trees we'll be + // processing manage their children using singly-linked lists. So + // figure out how many children there are, grow mPending by that size + // and reverse-copy the children into the new space. + CHILDITER chi = mBeginFunc(node), chend = mEndFunc(node); + // grow mPending by the number of children + mPending.resize(mPending.size() + std::distance(chi, chend)); + // Reverse-copy the children into the newly-expanded space. We can't + // just use std::copy() because the source is a ptr_type, whereas the + // dest is a pair of (ptr_type, bool). + for (typename list_type::reverse_iterator pi = mPending.rbegin(); chi != chend; ++chi, ++pi) + { + pi->first = *chi; // copy the child pointer + pi->second = false; // we haven't yet pushed this child's chldren + } + } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; + /// flags logic to skip traversal of ancestors of current node + bool mSkipAncestors; +}; + +/** + * Instantiated with a tree node, typically the root, LLTreeBFSIter "flattens" + * a breadth-first tree walk through that node and all its descendants. + * + * The begin() LLTreeBFSIter must be instantiated with functors to obtain from + * a given node the begin() and end() iterators of that node's children. For + * this reason, you must specify the type of the node's child iterator as an + * additional template parameter. + * + * Specifically, the begin functor must return an iterator whose dereferenced + * value is a @em pointer to a child tree node. For instance, if each node + * tracks its children in an STL container of node* pointers, you can simply + * return that container's begin() iterator. + * + * Alternatively, if a node tracks its children with a classic linked list, + * write a functor returning LLLinkedIter. + * + * The end() LLTreeBFSIter must, of course, match the begin() iterator's + * template parameters, but is constructed without runtime parameters. + */ +template +class LLTreeBFSIter: public LLBaseIter, NODE> +{ + typedef LLBaseIter, NODE> super; + typedef typename super::self_type self_type; +protected: + typedef typename super::ptr_type ptr_type; + // The func_type is different for this: from a NODE pointer, we must + // obtain a CHILDITER. + typedef boost::function func_type; +private: + // We need a FIFO queue rather than a LIFO stack. Use a deque rather than + // a vector, since vector can't implement pop_front() efficiently. + typedef std::deque list_type; +public: + /// Instantiate an LLTreeBFSIter to start a depth-first walk. Pass + /// functors to extract the 'child begin' and 'child end' iterators from + /// each node. + LLTreeBFSIter(const ptr_type& node, const func_type& beginfunc, const func_type& endfunc): + mBeginFunc(beginfunc), + mEndFunc(endfunc) + { + if (node) + mPending.push_back(node); + } + /// Instantiate an LLTreeBFSIter to mark the end of the walk + LLTreeBFSIter() {} + +private: + /// leverage boost::iterator_facade + friend class boost::iterator_core_access; + + /// advance + /// This implementation is due to http://en.wikipedia.org/wiki/Breadth-first_search + void increment() + { + // Capture the node we were just looking at + ptr_type current = mPending.front(); + // Remove it from mPending so we don't process it again later + mPending.pop_front(); + // Add all its children to mPending + CHILDITER chend = mEndFunc(current); + for (CHILDITER chi = mBeginFunc(current); chi != chend; ++chi) + mPending.push_back(*chi); + } + /// equality + bool equal(const self_type& that) const { return this->mPending == that.mPending; } + /// implement dereference/indirection operators + ptr_type& dereference() const { return const_cast(mPending.front()); } + + /// list of the nodes yet to be processed + list_type mPending; + /// functor to extract begin() child iterator + func_type mBeginFunc; + /// functor to extract end() child iterator + func_type mEndFunc; +}; + +/** + * When you want to select between LLTreeDFSIter, LLTreeDFSPostIter and + * LLTreeBFSIter with a compile-time discriminator, use LLTreeWalkIter with an + * LLTreeIter::WalkIter template arg. + */ +template +class LLTreeWalkIter +{ + enum { use_a_valid_LLTreeIter_WalkIter_value = false }; +public: + /// Bogus constructors for default (unrecognized discriminator) case + template + LLTreeWalkIter(TYPE1, TYPE2) + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } + LLTreeWalkIter() + { + BOOST_STATIC_ASSERT(use_a_valid_LLTreeIter_WalkIter_value); + } +}; + +/// Specialize for LLTreeIter::DFS_PRE +template +class LLTreeWalkIter: + public LLTreeDFSIter +{ + typedef LLTreeDFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::DFS_POST +template +class LLTreeWalkIter: + public LLTreeDFSPostIter +{ + typedef LLTreeDFSPostIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +/// Specialize for LLTreeIter::BFS +template +class LLTreeWalkIter: + public LLTreeBFSIter +{ + typedef LLTreeBFSIter super; +public: + /// forward begin ctor + LLTreeWalkIter(const typename super::ptr_type& node, + const typename super::func_type& beginfunc, + const typename super::func_type& endfunc): + super(node, beginfunc, endfunc) + {} + /// forward end ctor + LLTreeWalkIter(): + super() + {} +}; + +#endif /* ! defined(LL_LLTREEITERATORS_H) */ diff --git a/indra/llcommon/llversionviewer.h b/indra/llcommon/llversionviewer.h index a28d0f7268..45810a101d 100644 --- a/indra/llcommon/llversionviewer.h +++ b/indra/llcommon/llversionviewer.h @@ -33,11 +33,11 @@ #ifndef LL_LLVERSIONVIEWER_H #define LL_LLVERSIONVIEWER_H -const S32 LL_VERSION_MAJOR = 1; -const S32 LL_VERSION_MINOR = 24; -const S32 LL_VERSION_PATCH = 2; +const S32 LL_VERSION_MAJOR = 2; +const S32 LL_VERSION_MINOR = 0; +const S32 LL_VERSION_PATCH = 0; const S32 LL_VERSION_BUILD = 0; -const char * const LL_CHANNEL = "Second Life Release"; +const char * const LL_CHANNEL = "Second Life 2009"; #endif diff --git a/indra/llcommon/tests/llallocator_heap_profile_test.cpp b/indra/llcommon/tests/llallocator_heap_profile_test.cpp new file mode 100644 index 0000000000..7369fdc8bc --- /dev/null +++ b/indra/llcommon/tests/llallocator_heap_profile_test.cpp @@ -0,0 +1,150 @@ +/** + * @file llallocator_heap_profile_test.cpp + * @author Brad Kittenbrink + * @date 2008-02- + * @brief Test for llallocator_heap_profile.cpp. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../llallocator_heap_profile.h" +#include "../test/lltut.h" + +namespace tut +{ + struct llallocator_heap_profile_data + { + LLAllocatorHeapProfile prof; + + static char const * const sample_win_profile; + // *TODO - get test output from mac/linux tcmalloc + static char const * const sample_mac_profile; + static char const * const sample_lin_profile; + + static char const * const crash_testcase; + }; + typedef test_group factory; + typedef factory::object object; +} +namespace +{ + tut::factory llallocator_heap_profile_test_factory("LLAllocatorHeapProfile"); +} + +namespace tut +{ + template<> template<> + void object::test<1>() + { + prof.parse(sample_win_profile); + + ensure_equals("count lines", prof.mLines.size() , 5); + ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 2131854U); + ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 2245710106ULL); + ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 14069198U); + ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 4295177308ULL); + ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0); + ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0); + ensure_equals("count markers", prof.mLines[2].mTrace.size(), 4); + ensure_equals("count markers", prof.mLines[3].mTrace.size(), 6); + ensure_equals("count markers", prof.mLines[4].mTrace.size(), 7); + + //prof.dump(std::cout); + } + + template<> template<> + void object::test<2>() + { + prof.parse(crash_testcase); + + ensure_equals("count lines", prof.mLines.size(), 2); + ensure_equals("alloc counts", prof.mLines[0].mLiveCount, 3U); + ensure_equals("alloc counts", prof.mLines[0].mLiveSize, 1049652ULL); + ensure_equals("alloc counts", prof.mLines[0].mTotalCount, 8U); + ensure_equals("alloc counts", prof.mLines[0].mTotalSize, 1049748ULL); + ensure_equals("count markers", prof.mLines[0].mTrace.size(), 0); + ensure_equals("count markers", prof.mLines[1].mTrace.size(), 0); + + //prof.dump(std::cout); + } + + template<> template<> + void object::test<3>() + { + // test that we don't crash on edge case data + prof.parse(""); + ensure("emtpy on error", prof.mLines.empty()); + + prof.parse("heap profile:"); + ensure("emtpy on error", prof.mLines.empty()); + } + +char const * const llallocator_heap_profile_data::sample_win_profile = +"heap profile: 2131854: 2245710106 [14069198: 4295177308] @\n" +"308592: 1073398388 [966564: 1280998739] @\n" +"462651: 375969538 [1177377: 753561247] @ 2 3 6 1\n" +"314744: 206611283 [2008722: 570934755] @ 2 3 3 7 21 32\n" +"277152: 82862770 [621961: 168503640] @ 2 3 3 7 21 32 87\n" +"\n" +"MAPPED_LIBRARIES:\n" +"00400000-02681000 r-xp 00000000 00:00 0 c:\\proj\\tcmalloc-eval-9\\indra\\build-vc80\\newview\\RelWithDebInfo\\secondlife-bin.exe\n" +"77280000-773a7000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ntdll.dll\n" +"76df0000-76ecb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\kernel32.dll\n" +"76000000-76073000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\comdlg32.dll\n" +"75ee0000-75f8a000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\msvcrt.dll\n" +"76c30000-76c88000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHLWAPI.dll\n" +"75f90000-75fdb000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\GDI32.dll\n" +"77420000-774bd000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\USER32.dll\n" +"75e10000-75ed6000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\ADVAPI32.dll\n" +"75b00000-75bc2000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\RPCRT4.dll\n" +"72ca0000-72d25000 r-xp 00000000 00:00 0 C:\\Windows\\WinSxS\\x86_microsoft.windows.common-controls_6595b64144ccf1df_5.82.6001.18000_none_886786f450a74a05\\COMCTL32.dll\n" +"76120000-76c30000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\SHELL32.dll\n" +"71ce0000-71d13000 r-xp 00000000 00:00 0 C:\\Windows\\system32\\DINPUT8.dll\n"; + + +char const * const llallocator_heap_profile_data::crash_testcase = +"heap profile: 3: 1049652 [ 8: 1049748] @\n" +" 3: 1049652 [ 8: 1049748] @\n" +"\n" +"MAPPED_LIBRARIES:\n" +"00400000-004d5000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\llallocator_test.exe\n" +"7c900000-7c9af000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ntdll.dll\n" +"7c800000-7c8f6000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\kernel32.dll\n" +"77dd0000-77e6b000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\ADVAPI32.dll\n" +"77e70000-77f02000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\RPCRT4.dll\n" +"77fe0000-77ff1000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\Secur32.dll\n" +"71ab0000-71ac7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2_32.dll\n" +"77c10000-77c68000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\msvcrt.dll\n" +"71aa0000-71aa8000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\WS2HELP.dll\n" +"76bf0000-76bfb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\PSAPI.DLL\n" +"5b860000-5b8b5000 r-xp 00000000 00:00 0 C:\\WINDOWS\\system32\\NETAPI32.dll\n" +"10000000-10041000 r-xp 00000000 00:00 0 c:\\code\\linden\\tcmalloc\\indra\\build-vc80\\llcommon\\RelWithDebInfo\\libtcmalloc_minimal.dll\n" +"7c420000-7c4a7000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCP80.dll\n" +"78130000-781cb000 r-xp 00000000 00:00 0 C:\\WINDOWS\\WinSxS\\x86_Microsoft.VC80.CRT_1fc8b3b9a1e18e3b_8.0.50727.1433_x-ww_5cf844d2\\MSVCR80.dll\n"; + +} diff --git a/indra/llcommon/tests/llallocator_test.cpp b/indra/llcommon/tests/llallocator_test.cpp new file mode 100644 index 0000000000..9db95f4273 --- /dev/null +++ b/indra/llcommon/tests/llallocator_test.cpp @@ -0,0 +1,86 @@ +/** + * @file llallocator_test.cpp + * @author Brad Kittenbrink + * @date 2008-02- + * @brief Test for llallocator.cpp. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../llallocator.h" +#include "../test/lltut.h" + +namespace tut +{ + struct llallocator_data + { + LLAllocator llallocator; + }; + typedef test_group factory; + typedef factory::object object; +} +namespace +{ + tut::factory llallocator_test_factory("LLAllocator"); +} + +namespace tut +{ + template<> template<> + void object::test<1>() + { + llallocator.setProfilingEnabled(false); + ensure("Profiler disable", !llallocator.isProfiling()); + } + +#if LL_USE_TCMALLOC + template<> template<> + void object::test<2>() + { + llallocator.setProfilingEnabled(true); + ensure("Profiler enable", llallocator.isProfiling()); + } + + template <> template <> + void object::test<3>() + { + llallocator.setProfilingEnabled(true); + + char * test_alloc = new char[1024]; + + llallocator.getProfile(); + + delete [] test_alloc; + + llallocator.getProfile(); + + // *NOTE - this test isn't ensuring anything right now other than no + // exceptions are thrown. + } +#endif // LL_USE_TCMALLOC +}; diff --git a/indra/llcommon/tests/llmemtype_test.cpp b/indra/llcommon/tests/llmemtype_test.cpp new file mode 100644 index 0000000000..6cc5ce01ce --- /dev/null +++ b/indra/llcommon/tests/llmemtype_test.cpp @@ -0,0 +1,123 @@ +/** + * @file llmemtype_test.cpp + * @author Palmer Truelson + * @date 2008-03- + * @brief Test for llmemtype.cpp. + * + * $LicenseInfo:firstyear=2009&license=viewergpl$ + * + * Copyright (c) 2009-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "../llmemtype.h" +#include "../test/lltut.h" +#include "../llallocator.h" + + +#include + +std::stack memTypeStack; + +void LLAllocator::pushMemType(S32 i) +{ + memTypeStack.push(i); +} + +S32 LLAllocator::popMemType(void) +{ + S32 ret = memTypeStack.top(); + memTypeStack.pop(); + return ret; +} + +namespace tut +{ + struct llmemtype_data + { + }; + + typedef test_group factory; + typedef factory::object object; +} +namespace +{ + tut::factory llmemtype_test_factory("LLMemType"); +} + +namespace tut +{ + template<> template<> + void object::test<1>() + { + ensure("Simplest test ever", true); + } + + // test with no scripts + template<> template<> + void object::test<2>() + { + { + LLMemType m1(LLMemType::MTYPE_INIT); + } + ensure("Test that you can construct and destruct the mem type"); + } + + // test creation and stack testing + template<> template<> + void object::test<3>() + { + { + ensure("Test that creation and destruction properly inc/dec the stack"); + ensure_equals(memTypeStack.size(), 0); + { + LLMemType m1(LLMemType::MTYPE_INIT); + ensure_equals(memTypeStack.size(), 1); + LLMemType m2(LLMemType::MTYPE_STARTUP); + ensure_equals(memTypeStack.size(), 2); + } + ensure_equals(memTypeStack.size(), 0); + } + } + + // test with no scripts + template<> template<> + void object::test<4>() + { + // catch the begining and end + std::string test_name = LLMemType::getNameFromID(LLMemType::MTYPE_INIT.mID); + ensure_equals("Init name", test_name, "Init"); + + std::string test_name2 = LLMemType::getNameFromID(LLMemType::MTYPE_VOLUME.mID); + ensure_equals("Volume name", test_name2, "Volume"); + + std::string test_name3 = LLMemType::getNameFromID(LLMemType::MTYPE_OTHER.mID); + ensure_equals("Other name", test_name3, "Other"); + + std::string test_name4 = LLMemType::getNameFromID(-1); + ensure_equals("Invalid name", test_name4, "INVALID"); + } + +}; diff --git a/indra/llcrashlogger/llcrashlogger.cpp b/indra/llcrashlogger/llcrashlogger.cpp index 2fd37e848e..c1022c1195 100755 --- a/indra/llcrashlogger/llcrashlogger.cpp +++ b/indra/llcrashlogger/llcrashlogger.cpp @@ -86,6 +86,7 @@ void LLCrashLoggerText::updateApplication(const std::string& message) LLCrashLogger::LLCrashLogger() : mCrashBehavior(CRASH_BEHAVIOR_ASK), mCrashInPreviousExec(false), + mCrashSettings("CrashSettings"), mSentCrashLogs(false), mCrashHost("") { @@ -208,7 +209,10 @@ void LLCrashLogger::gatherFiles() mFileMap["SettingsXml"] = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS,"settings.xml"); } +#if !LL_DARWIN if(mCrashInPreviousExec) +#else +#endif { // Replace the log file ext with .old, since the // instance that launched this process has overwritten diff --git a/indra/llimage/llimage.cpp b/indra/llimage/llimage.cpp index 93ddc65f32..488f3bf78d 100644 --- a/indra/llimage/llimage.cpp +++ b/indra/llimage/llimage.cpp @@ -152,7 +152,7 @@ void LLImageBase::deleteData() // virtual U8* LLImageBase::allocateData(S32 size) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); if (size < 0) { @@ -188,7 +188,7 @@ U8* LLImageBase::allocateData(S32 size) // virtual U8* LLImageBase::reallocateData(S32 size) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); U8 *new_datap = new U8[size]; if (!new_datap) { @@ -332,7 +332,7 @@ BOOL LLImageRaw::resize(U16 width, U16 height, S8 components) U8 * LLImageRaw::getSubImage(U32 x_pos, U32 y_pos, U32 width, U32 height) const { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); U8 *data = new U8[width*height*getComponents()]; // Should do some simple bounds checking @@ -415,7 +415,7 @@ void LLImageRaw::clear(U8 r, U8 g, U8 b, U8 a) // Reverses the order of the rows in the image void LLImageRaw::verticalFlip() { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); S32 row_bytes = getWidth() * getComponents(); llassert(row_bytes > 0); std::vector line_buffer(row_bytes); @@ -548,7 +548,7 @@ void LLImageRaw::composite( LLImageRaw* src ) // Src and dst can be any size. Src has 4 components. Dst has 3 components. void LLImageRaw::compositeScaled4onto3(LLImageRaw* src) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); llinfos << "compositeScaled4onto3" << llendl; LLImageRaw* dst = this; // Just for clarity. @@ -787,7 +787,7 @@ void LLImageRaw::copyUnscaled3onto4( LLImageRaw* src ) // Src and dst can be any size. Src and dst have same number of components. void LLImageRaw::copyScaled( LLImageRaw* src ) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); LLImageRaw* dst = this; // Just for clarity. llassert_always( (1 == src->getComponents()) || (3 == src->getComponents()) || (4 == src->getComponents()) ); @@ -819,7 +819,7 @@ void LLImageRaw::copyScaled( LLImageRaw* src ) BOOL LLImageRaw::scale( S32 new_width, S32 new_height, BOOL scale_image_data ) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); llassert((1 == getComponents()) || (3 == getComponents()) || (4 == getComponents()) ); S32 old_width = getWidth(); diff --git a/indra/llimage/llimage.h b/indra/llimage/llimage.h index bd609b638c..8108553107 100644 --- a/indra/llimage/llimage.h +++ b/indra/llimage/llimage.h @@ -35,8 +35,9 @@ #include "lluuid.h" #include "llstring.h" -#include "llmemory.h" +//#include "llmemory.h" #include "llthread.h" +#include "llmemtype.h" const S32 MIN_IMAGE_MIP = 2; // 4x4, only used for expand/contract power of 2 const S32 MAX_IMAGE_MIP = 11; // 2048x2048 @@ -155,7 +156,7 @@ private: BOOL mBadBufferAllocation ; public: - S16 mMemType; // debug + LLMemType::DeclareMemType& mMemType; // debug static BOOL sSizeOverride; }; diff --git a/indra/llimage/llimagedxt.h b/indra/llimage/llimagedxt.h index bc2d6522d2..1a297536b4 100644 --- a/indra/llimage/llimagedxt.h +++ b/indra/llimage/llimagedxt.h @@ -33,6 +33,7 @@ #define LL_LLIMAGEDXT_H #include "llimage.h" +#include "llpointer.h" // This class decodes and encodes LL DXT files (which may unclude uncompressed RGB or RGBA mipped data) diff --git a/indra/llimage/llimagej2c.cpp b/indra/llimage/llimagej2c.cpp index 1b93c21982..363486fb9c 100644 --- a/indra/llimage/llimagej2c.cpp +++ b/indra/llimage/llimagej2c.cpp @@ -279,7 +279,7 @@ BOOL LLImageJ2C::decode(LLImageRaw *raw_imagep, F32 decode_time) BOOL LLImageJ2C::decodeChannels(LLImageRaw *raw_imagep, F32 decode_time, S32 first_channel, S32 max_channel_count ) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); BOOL res = TRUE; @@ -329,7 +329,7 @@ BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, F32 encode_time) BOOL LLImageJ2C::encode(const LLImageRaw *raw_imagep, const char* comment_text, F32 encode_time) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); resetLastError(); BOOL res = mImpl->encodeImpl(*this, *raw_imagep, comment_text, encode_time, mReversible); if (!mLastError.empty()) @@ -462,7 +462,7 @@ BOOL LLImageJ2C::loadAndValidate(const std::string &filename) BOOL LLImageJ2C::validate(U8 *data, U32 file_size) { - LLMemType mt1((LLMemType::EMemType)mMemType); + LLMemType mt1(mMemType); resetLastError(); diff --git a/indra/llimage/llimagetga.cpp b/indra/llimage/llimagetga.cpp index a6721bfa0f..d8f8003593 100644 --- a/indra/llimage/llimagetga.cpp +++ b/indra/llimage/llimagetga.cpp @@ -31,10 +31,12 @@ #include "linden_common.h" -#include "lldir.h" #include "llimagetga.h" + +#include "lldir.h" #include "llerror.h" #include "llmath.h" +#include "llpointer.h" // For expanding 5-bit pixel values to 8-bit with best rounding // static diff --git a/indra/llimage/llimageworker.h b/indra/llimage/llimageworker.h index 879fcf5565..0d66695d6e 100644 --- a/indra/llimage/llimageworker.h +++ b/indra/llimage/llimageworker.h @@ -34,6 +34,7 @@ #define LL_LLIMAGEWORKER_H #include "llimage.h" +#include "llpointer.h" #include "llworkerthread.h" class LLImageWorker : public LLWorkerClass diff --git a/indra/llimagej2coj/llimagej2coj.cpp b/indra/llimagej2coj/llimagej2coj.cpp index be6b6c817b..ec6264dcf5 100644 --- a/indra/llimagej2coj/llimagej2coj.cpp +++ b/indra/llimagej2coj/llimagej2coj.cpp @@ -37,7 +37,7 @@ #include "openjpeg.h" #include "lltimer.h" -#include "llmemory.h" +//#include "llmemory.h" const char* fallbackEngineInfoLLImageJ2CImpl() { diff --git a/indra/llinventory/lleconomy.h b/indra/llinventory/lleconomy.h index 2e2adc4d45..e480085453 100644 --- a/indra/llinventory/lleconomy.h +++ b/indra/llinventory/lleconomy.h @@ -32,7 +32,7 @@ #ifndef LL_LLECONOMY_H #define LL_LLECONOMY_H -#include "llmemory.h" +#include "llsingleton.h" class LLMessageSystem; class LLVector3; diff --git a/indra/llinventory/llinventory.cpp b/indra/llinventory/llinventory.cpp index 2823cf7be9..adc80b2ed3 100644 --- a/indra/llinventory/llinventory.cpp +++ b/indra/llinventory/llinventory.cpp @@ -705,8 +705,8 @@ BOOL LLInventoryItem::exportFile(LLFILE* fp, BOOL include_asset_key) const fprintf(fp, "\t\tasset_id\t%s\n", uuid_str.c_str()); } fprintf(fp, "\t\ttype\t%s\n", LLAssetType::lookup(mType)); - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str); + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) fprintf(fp, "\t\tinv_type\t%s\n", inv_type_str.c_str()); fprintf(fp, "\t\tflags\t%08x\n", mFlags); mSaleInfo.exportFile(fp); fprintf(fp, "\t\tname\t%s|\n", mName.c_str()); @@ -908,8 +908,8 @@ BOOL LLInventoryItem::exportLegacyStream(std::ostream& output_stream, BOOL inclu output_stream << "\t\tasset_id\t" << uuid_str << "\n"; } output_stream << "\t\ttype\t" << LLAssetType::lookup(mType) << "\n"; - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) output_stream << "\t\tinv_type\t" << inv_type_str << "\n"; std::string buffer; buffer = llformat( "\t\tflags\t%08x\n", mFlags); @@ -951,8 +951,8 @@ void LLInventoryItem::asLLSD( LLSD& sd ) const } sd[INV_ASSET_TYPE_LABEL] = LLAssetType::lookup(mType); sd[INV_INVENTORY_TYPE_LABEL] = mInventoryType; - const char* inv_type_str = LLInventoryType::lookup(mInventoryType); - if(inv_type_str) + const std::string inv_type_str = LLInventoryType::lookup(mInventoryType); + if(!inv_type_str.empty()) { sd[INV_INVENTORY_TYPE_LABEL] = inv_type_str; } @@ -1097,109 +1097,8 @@ fail: } -LLXMLNode *LLInventoryItem::exportFileXML(BOOL include_asset_key) const -{ - LLMemType m1(LLMemType::MTYPE_INVENTORY); - LLXMLNode *ret = new LLXMLNode("item", FALSE); - - ret->createChild("uuid", TRUE)->setUUIDValue(1, &mUUID); - ret->createChild("parent_uuid", TRUE)->setUUIDValue(1, &mParentUUID); - - mPermissions.exportFileXML()->setParent(ret); - - // Check for permissions to see the asset id, and if so write it - // out as an asset id. Otherwise, apply our cheesy encryption. - if(include_asset_key) - { - U32 mask = mPermissions.getMaskBase(); - if(((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED) - || (mAssetUUID.isNull())) - { - ret->createChild("asset_id", FALSE)->setUUIDValue(1, &mAssetUUID); - } - else - { - LLUUID shadow_id(mAssetUUID); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.encrypt(shadow_id.mData, UUID_BYTES); - - ret->createChild("shadow_id", FALSE)->setUUIDValue(1, &shadow_id); - } - } - - std::string type_str = LLAssetType::lookup(mType); - std::string inv_type_str = LLInventoryType::lookup(mInventoryType); - - ret->createChild("asset_type", FALSE)->setStringValue(type_str); - ret->createChild("inventory_type", FALSE)->setStringValue(inv_type_str); - S32 tmp_flags = (S32) mFlags; - ret->createChild("flags", FALSE)->setByteValue(4, (U8*)(&tmp_flags), LLXMLNode::ENCODING_HEX); - - mSaleInfo.exportFileXML()->setParent(ret); - - std::string temp; - temp.assign(mName); - ret->createChild("name", FALSE)->setStringValue(temp); - temp.assign(mDescription); - ret->createChild("description", FALSE)->setStringValue(temp); - S32 date = mCreationDate; - ret->createChild("creation_date", FALSE)->setIntValue(1, &date); - - return ret; -} - -BOOL LLInventoryItem::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("uuid", sub_node)) - success = (1 == sub_node->getUUIDValue(1, &mUUID)); - if (node->getChild("parent_uuid", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mParentUUID)); - if (node->getChild("permissions", sub_node)) - success = success && mPermissions.importXML(sub_node); - if (node->getChild("asset_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - if (node->getChild("shadow_id", sub_node)) - { - success = success && (1 == sub_node->getUUIDValue(1, &mAssetUUID)); - LLXORCipher cipher(MAGIC_ID.mData, UUID_BYTES); - cipher.decrypt(mAssetUUID.mData, UUID_BYTES); - } - if (node->getChild("asset_type", sub_node)) - mType = LLAssetType::lookup(sub_node->getValue()); - if (node->getChild("inventory_type", sub_node)) - mInventoryType = LLInventoryType::lookup(sub_node->getValue()); - if (node->getChild("flags", sub_node)) - { - S32 tmp_flags = 0; - success = success && (1 == sub_node->getIntValue(1, &tmp_flags)); - mFlags = (U32) tmp_flags; - } - if (node->getChild("sale_info", sub_node)) - success = success && mSaleInfo.importXML(sub_node); - if (node->getChild("name", sub_node)) - mName = sub_node->getValue(); - if (node->getChild("description", sub_node)) - mDescription = sub_node->getValue(); - if (node->getChild("creation_date", sub_node)) - { - S32 date = 0; - success = success && (1 == sub_node->getIntValue(1, &date)); - mCreationDate = date; - } - - if (!success) - { - lldebugs << "LLInventory::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLInventoryItem::exportFileXML() and LLInventoryItem::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC S32 LLInventoryItem::packBinaryBucket(U8* bin_bucket, LLPermissions* perm_override) const { diff --git a/indra/llinventory/llinventory.h b/indra/llinventory/llinventory.h index d34046c310..3f79cedc23 100644 --- a/indra/llinventory/llinventory.h +++ b/indra/llinventory/llinventory.h @@ -40,6 +40,7 @@ #include "llinventorytype.h" #include "llmemtype.h" #include "llpermissions.h" +#include "llrefcount.h" #include "llsaleinfo.h" #include "llsd.h" #include "lluuid.h" @@ -91,9 +92,9 @@ public: // accessors virtual const LLUUID& getUUID() const; const LLUUID& getParentUUID() const; - const std::string& getName() const; - LLAssetType::EType getType() const; - + virtual const std::string& getName() const; + virtual LLAssetType::EType getType() const; + LLAssetType::EType getActualType() const { return mType; } // mutators - will not call updateServer(); void setUUID(const LLUUID& new_uuid); void rename(const std::string& new_name); @@ -216,6 +217,7 @@ protected: ~LLInventoryItem(); // ref counted public: + MEM_TYPE_NEW(LLMemType::MTYPE_INVENTORY); LLInventoryItem(const LLUUID& uuid, const LLUUID& parent_uuid, @@ -240,7 +242,7 @@ public: // accessors const LLPermissions& getPermissions() const; const LLUUID& getCreatorUUID() const; - const LLUUID& getAssetUUID() const; + virtual const LLUUID& getAssetUUID() const; const std::string& getDescription() const; const LLSaleInfo& getSaleInfo() const; LLInventoryType::EType getInventoryType() const; @@ -273,9 +275,6 @@ public: virtual BOOL importLegacyStream(std::istream& input_stream); virtual BOOL exportLegacyStream(std::ostream& output_stream, BOOL include_asset_key = TRUE) const; - virtual LLXMLNode *exportFileXML(BOOL include_asset_key = TRUE) const; - BOOL importXML(LLXMLNode* node); - // helper functions // pack all information needed to reconstruct this item into the given binary bucket. diff --git a/indra/llinventory/llinventorytype.cpp b/indra/llinventory/llinventorytype.cpp index a161a0ee00..ff9c698943 100644 --- a/indra/llinventory/llinventorytype.cpp +++ b/indra/llinventory/llinventorytype.cpp @@ -33,66 +33,59 @@ #include "linden_common.h" #include "llinventorytype.h" +#include "lldictionary.h" +#include "llmemory.h" +#include "llsingleton.h" + +static const std::string empty_string; ///---------------------------------------------------------------------------- /// Class LLInventoryType ///---------------------------------------------------------------------------- - -// Unlike asset type names, not limited to 8 characters. -// Need not match asset type names. -static const char* INVENTORY_TYPE_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "callcard", - "landmark", - NULL, - NULL, // 5 - "object", - "notecard", - "category", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attach", - "wearable", - "animation", - "gesture", // 20 +struct InventoryEntry : public LLDictionaryEntry +{ + InventoryEntry(const std::string &name, + const std::string &human_name, + int num_asset_types = 0, ...); + const std::string mHumanName; + typedef std::vector asset_vec_t; + asset_vec_t mAssetTypes; }; -// This table is meant for decoding to human readable form. Put any -// and as many printable characters you want in each one. -// See also LLAssetType::mAssetTypeHumanNames -static const char* INVENTORY_TYPE_HUMAN_NAMES[LLInventoryType::IT_COUNT] = -{ - "texture", // 0 - "sound", - "calling card", - "landmark", - NULL, - NULL, // 5 - "object", - "note card", - "folder", - "root", - "script", // 10 - NULL, - NULL, - NULL, - NULL, - "snapshot", // 15 - NULL, - "attachment", - "wearable", - "animation", - "gesture", // 20 +class LLInventoryDictionary : public LLSingleton, + public LLDictionary +{ +public: + LLInventoryDictionary(); }; +LLInventoryDictionary::LLInventoryDictionary() +{ + addEntry(LLInventoryType::IT_TEXTURE, new InventoryEntry("texture", "texture", 1, LLAssetType::AT_TEXTURE)); + addEntry(LLInventoryType::IT_SOUND, new InventoryEntry("sound", "sound", 1, LLAssetType::AT_SOUND)); + addEntry(LLInventoryType::IT_CALLINGCARD, new InventoryEntry("callcard", "calling card", 1, LLAssetType::AT_CALLINGCARD)); + addEntry(LLInventoryType::IT_LANDMARK, new InventoryEntry("landmark", "landmark", 1, LLAssetType::AT_LANDMARK)); + //addEntry(LLInventoryType::IT_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)); +} + + // Maps asset types to the default inventory type for that kind of asset. // Thus, "Lost and Found" is a "Category" static const LLInventoryType::EType @@ -120,76 +113,48 @@ DEFAULT_ASSET_FOR_INV_TYPE[LLAssetType::AT_COUNT] = LLInventoryType::IT_NONE, // AT_IMAGE_JPEG LLInventoryType::IT_ANIMATION, // AT_ANIMATION LLInventoryType::IT_GESTURE, // AT_GESTURE + LLInventoryType::IT_NONE, // AT_LINK + LLInventoryType::IT_FAVORITE, // AT_FAVORITE }; -static const int MAX_POSSIBLE_ASSET_TYPES = 2; -static const LLAssetType::EType -INVENTORY_TO_ASSET_TYPE[LLInventoryType::IT_COUNT][MAX_POSSIBLE_ASSET_TYPES] = +InventoryEntry::InventoryEntry(const std::string &name, + const std::string &human_name, + int num_asset_types, ...) : + LLDictionaryEntry(name), + mHumanName(human_name) { - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_TEXTURE - { LLAssetType::AT_SOUND, LLAssetType::AT_NONE }, // IT_SOUND - { LLAssetType::AT_CALLINGCARD, LLAssetType::AT_NONE }, // IT_CALLINGCARD - { LLAssetType::AT_LANDMARK, LLAssetType::AT_NONE }, // IT_LANDMARK - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_OBJECT - { LLAssetType::AT_NOTECARD, LLAssetType::AT_NONE }, // IT_NOTECARD - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_CATEGORY - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, // IT_ROOT_CATEGORY - { LLAssetType::AT_LSL_TEXT, LLAssetType::AT_LSL_BYTECODE }, // IT_LSL - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_TEXTURE, LLAssetType::AT_NONE }, // IT_SNAPSHOT - { LLAssetType::AT_NONE, LLAssetType::AT_NONE }, - { LLAssetType::AT_OBJECT, LLAssetType::AT_NONE }, // IT_ATTACHMENT - { LLAssetType::AT_CLOTHING, LLAssetType::AT_BODYPART }, // IT_WEARABLE - { LLAssetType::AT_ANIMATION, LLAssetType::AT_NONE }, // IT_ANIMATION - { LLAssetType::AT_GESTURE, LLAssetType::AT_NONE }, // IT_GESTURE -}; + va_list argp; + va_start(argp, num_asset_types); + // Read in local textures + for (U8 i=0; i < num_asset_types; i++) + { + LLAssetType::EType t = (LLAssetType::EType)va_arg(argp,int); + mAssetTypes.push_back(t); + } +} // static -const char* LLInventoryType::lookup(EType type) +const std::string &LLInventoryType::lookup(EType type) { - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_NAMES[S32(type)]; - } - else - { - return NULL; - } + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type); + if (!entry) return empty_string; + return entry->mName; } // static LLInventoryType::EType LLInventoryType::lookup(const std::string& name) { - for(S32 i = 0; i < IT_COUNT; ++i) - { - if((INVENTORY_TYPE_NAMES[i]) - && (name == INVENTORY_TYPE_NAMES[i])) - { - // match - return (EType)i; - } - } - return IT_NONE; + return LLInventoryDictionary::getInstance()->lookup(name); } // XUI:translate // translation from a type to a human readable form. // static -const char* LLInventoryType::lookupHumanReadable(EType type) +const std::string &LLInventoryType::lookupHumanReadable(EType type) { - if((type >= 0) && (type < IT_COUNT)) - { - return INVENTORY_TYPE_HUMAN_NAMES[S32(type)]; - } - else - { - return NULL; - } + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(type); + if (!entry) return empty_string; + return entry->mHumanName; } // return the default inventory for the given asset type. @@ -206,21 +171,21 @@ LLInventoryType::EType LLInventoryType::defaultForAssetType(LLAssetType::EType a } } -bool inventory_and_asset_types_match( - LLInventoryType::EType inventory_type, - LLAssetType::EType asset_type) +bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type, + LLAssetType::EType asset_type) { - bool rv = false; - if((inventory_type >= 0) && (inventory_type < LLInventoryType::IT_COUNT)) + const InventoryEntry *entry = LLInventoryDictionary::getInstance()->lookup(inventory_type); + if (!entry) return false; + + for (InventoryEntry::asset_vec_t::const_iterator iter = entry->mAssetTypes.begin(); + iter != entry->mAssetTypes.end(); + iter++) { - for(S32 i = 0; i < MAX_POSSIBLE_ASSET_TYPES; ++i) + const LLAssetType::EType type = (*iter); + if(type == asset_type) { - if(INVENTORY_TO_ASSET_TYPE[inventory_type][i] == asset_type) - { - rv = true; - break; - } + return true; } } - return rv; + return false; } diff --git a/indra/llinventory/llinventorytype.h b/indra/llinventory/llinventorytype.h index d3effc0e6d..1aad90d51b 100644 --- a/indra/llinventory/llinventorytype.h +++ b/indra/llinventory/llinventorytype.h @@ -67,32 +67,32 @@ public: IT_WEARABLE = 18, IT_ANIMATION = 19, IT_GESTURE = 20, - IT_COUNT = 21, + IT_FAVORITE = 21, + IT_COUNT = 22, IT_NONE = -1 }; // machine transation between type and strings static EType lookup(const std::string& name); - static const char* lookup(EType type); + static const std::string &lookup(EType type); // translation from a type to a human readable form. - static const char* lookupHumanReadable(EType type); + static const std::string &lookupHumanReadable(EType type); // return the default inventory for the given asset type. static EType defaultForAssetType(LLAssetType::EType asset_type); private: // don't instantiate or derive one of these objects - LLInventoryType( void ); - ~LLInventoryType( void ); + LLInventoryType() {} + ~LLInventoryType() {} }; -// helper function which returns true if inventory type and asset type +// helper function that returns true if inventory type and asset type // are potentially compatible. For example, an attachment must be an // object, but a wearable can be a bodypart or clothing asset. -bool inventory_and_asset_types_match( - LLInventoryType::EType inventory_type, - LLAssetType::EType asset_type); +bool inventory_and_asset_types_match(LLInventoryType::EType inventory_type, + LLAssetType::EType asset_type); #endif diff --git a/indra/llinventory/lllandmark.cpp b/indra/llinventory/lllandmark.cpp index 13a63bc7d6..83b6392ca8 100644 --- a/indra/llinventory/lllandmark.cpp +++ b/indra/llinventory/lllandmark.cpp @@ -40,7 +40,7 @@ std::pair LLLandmark::mLocalRegion; LLLandmark::region_map_t LLLandmark::mRegions; -LLLandmark::region_callback_t LLLandmark::mRegionCallback; +LLLandmark::region_callback_map_t LLLandmark::sRegionCallbackMap; LLLandmark::LLLandmark() : mGlobalPositionKnown(false) @@ -177,7 +177,7 @@ void LLLandmark::requestRegionHandle( LLMessageSystem* msg, const LLHost& upstream_host, const LLUUID& region_id, - LLRegionHandleCallback* callback) + region_handle_callback_t callback) { if(region_id.isNull()) { @@ -186,7 +186,7 @@ void LLLandmark::requestRegionHandle( if(callback) { const U64 U64_ZERO = 0; - callback->dataReady(region_id, U64_ZERO); + callback(region_id, U64_ZERO); } } else @@ -196,7 +196,7 @@ void LLLandmark::requestRegionHandle( lldebugs << "requestRegionHandle: local" << llendl; if(callback) { - callback->dataReady(region_id, mLocalRegion.second); + callback(region_id, mLocalRegion.second); } } else @@ -207,8 +207,8 @@ void LLLandmark::requestRegionHandle( lldebugs << "requestRegionHandle: upstream" << llendl; if(callback) { - region_callback_t::value_type vt(region_id, callback); - mRegionCallback.insert(vt); + region_callback_map_t::value_type vt(region_id, callback); + sRegionCallbackMap.insert(vt); } lldebugs << "Landmark requesting information about: " << region_id << llendl; @@ -221,7 +221,7 @@ void LLLandmark::requestRegionHandle( { // we have the answer locally - just call the callack. lldebugs << "requestRegionHandle: ready" << llendl; - callback->dataReady(region_id, (*it).second.mRegionHandle); + callback(region_id, (*it).second.mRegionHandle); } } } @@ -259,11 +259,11 @@ void LLLandmark::processRegionIDAndHandle(LLMessageSystem* msg, void**) #endif // make all the callbacks here. - region_callback_t::iterator it; - while((it = mRegionCallback.find(region_id)) != mRegionCallback.end()) + region_callback_map_t::iterator it; + while((it = sRegionCallbackMap.find(region_id)) != sRegionCallbackMap.end()) { - (*it).second->dataReady(region_id, info.mRegionHandle); - mRegionCallback.erase(it); + (*it).second(region_id, info.mRegionHandle); + sRegionCallbackMap.erase(it); } } diff --git a/indra/llinventory/lllandmark.h b/indra/llinventory/lllandmark.h index cb0c11ab87..feaf1a0e9c 100644 --- a/indra/llinventory/lllandmark.h +++ b/indra/llinventory/lllandmark.h @@ -35,6 +35,7 @@ #define LL_LLLANDMARK_H #include +#include #include "llframetimer.h" #include "lluuid.h" #include "v3dmath.h" @@ -42,24 +43,12 @@ class LLMessageSystem; class LLHost; -// virutal base class used for calling back interested parties when a -// region handle comes back. -class LLRegionHandleCallback -{ -public: - LLRegionHandleCallback() {} - virtual ~LLRegionHandleCallback() {} - virtual bool dataReady( - const LLUUID& region_id, - const U64& region_handle) - { - return true; - } -}; - class LLLandmark { public: + // for calling back interested parties when a region handle comes back. + typedef boost::function region_handle_callback_t; + ~LLLandmark() {} // returns true if the position is known. @@ -90,7 +79,7 @@ public: LLMessageSystem* msg, const LLHost& upstream_host, const LLUUID& region_id, - LLRegionHandleCallback* callback); + region_handle_callback_t callback); // Call this method to create a lookup for this region. This // simplifies a lot of the code. @@ -118,8 +107,8 @@ private: static std::pair mLocalRegion; typedef std::map region_map_t; static region_map_t mRegions; - typedef std::multimap region_callback_t; - static region_callback_t mRegionCallback; + typedef std::multimap region_callback_map_t; + static region_callback_map_t sRegionCallbackMap; }; #endif diff --git a/indra/llinventory/llnotecard.h b/indra/llinventory/llnotecard.h index b903f1fdb0..092ab2ce35 100644 --- a/indra/llinventory/llnotecard.h +++ b/indra/llinventory/llnotecard.h @@ -33,7 +33,7 @@ #ifndef LL_NOTECARD_H #define LL_NOTECARD_H -#include "llmemory.h" +#include "llpointer.h" #include "llinventory.h" class LLNotecard diff --git a/indra/llinventory/llparcel.cpp b/indra/llinventory/llparcel.cpp index a0b27c788f..e115c0ef81 100644 --- a/indra/llinventory/llparcel.cpp +++ b/indra/llinventory/llparcel.cpp @@ -85,13 +85,13 @@ static const std::string PARCEL_CATEGORY_UI_STRING[LLParcel::C_COUNT + 1] = "None", "Linden Location", "Adult", - "Arts & Culture", + "Arts and Culture", "Business", "Educational", "Gaming", "Hangout", "Newcomer Friendly", - "Parks & Nature", + "Parks and Nature", "Residential", "Shopping", "Stage", diff --git a/indra/llinventory/llparcel.h b/indra/llinventory/llparcel.h index 40bbb7b2e0..7b7896f74f 100644 --- a/indra/llinventory/llparcel.h +++ b/indra/llinventory/llparcel.h @@ -38,6 +38,7 @@ #include "lluuid.h" #include "llparcelflags.h" #include "llpermissions.h" +#include "lltimer.h" #include "v3math.h" diff --git a/indra/llinventory/llpermissions.cpp b/indra/llinventory/llpermissions.cpp index 328ed4588b..559a5631dc 100644 --- a/indra/llinventory/llpermissions.cpp +++ b/indra/llinventory/llpermissions.cpp @@ -831,67 +831,8 @@ BOOL LLPermissions::exportLegacyStream(std::ostream& output_stream) const return TRUE; } - -LLXMLNode *LLPermissions::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("permissions", FALSE); - - ret->createChild("group_owned", TRUE)->setBoolValue(mIsGroupOwned); - - ret->createChild("base_mask", FALSE)->setByteValue(4, (U8*)&mMaskBase, LLXMLNode::ENCODING_HEX); - ret->createChild("owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskOwner, LLXMLNode::ENCODING_HEX); - ret->createChild("group_mask", FALSE)->setByteValue(4, (U8*)&mMaskGroup, LLXMLNode::ENCODING_HEX); - ret->createChild("everyone_mask", FALSE)->setByteValue(4, (U8*)&mMaskEveryone, LLXMLNode::ENCODING_HEX); - ret->createChild("next_owner_mask", FALSE)->setByteValue(4, (U8*)&mMaskNextOwner, LLXMLNode::ENCODING_HEX); - - ret->createChild("creator_id", FALSE)->setUUIDValue(1, &mCreator); - ret->createChild("owner_id", FALSE)->setUUIDValue(1, &mOwner); - ret->createChild("last_owner_id", FALSE)->setUUIDValue(1, &mLastOwner); - ret->createChild("group_id", FALSE)->setUUIDValue(1, &mGroup); - - return ret; -} - -bool LLPermissions::importXML(LLXMLNode* node) -{ - bool success = false; - if (node) - { - success = true; - LLXMLNodePtr sub_node; - if (node->getChild("base_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskBase)); - if (node->getChild("owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskOwner)); - if (node->getChild("group_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskGroup)); - if (node->getChild("everyone_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskEveryone)); - if (node->getChild("next_owner_mask", sub_node)) - success = success && (4 == sub_node->getByteValue(4, (U8*)&mMaskNextOwner)); - - if (node->getChild("creator_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mCreator)); - if (node->getChild("owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mOwner)); - if (node->getChild("last_owner_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mLastOwner)); - if (node->getChild("group_id", sub_node)) - success = success && (1 == sub_node->getUUIDValue(1, &mGroup)); - if (node->getChild("group_owned", sub_node)) - { - BOOL tmpbool = FALSE; - success = success && (1 == sub_node->getBoolValue(1, &tmpbool)); - mIsGroupOwned = (bool)tmpbool; - } - if (!success) - { - lldebugs << "LLPermissions::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLPermissions::exportFileXML() and LLPermissions::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC bool LLPermissions::operator==(const LLPermissions &rhs) const { diff --git a/indra/llinventory/llpermissions.h b/indra/llinventory/llpermissions.h index 5587f8c3c8..2035b57f5c 100644 --- a/indra/llinventory/llpermissions.h +++ b/indra/llinventory/llpermissions.h @@ -314,9 +314,6 @@ public: BOOL importLegacyStream(std::istream& input_stream); BOOL exportLegacyStream(std::ostream& output_stream) const; - LLXMLNode *exportFileXML() const; - bool importXML(LLXMLNode* node); - bool operator==(const LLPermissions &rhs) const; bool operator!=(const LLPermissions &rhs) const; diff --git a/indra/llinventory/llsaleinfo.cpp b/indra/llinventory/llsaleinfo.cpp index b7afb28adf..930901f309 100644 --- a/indra/llinventory/llsaleinfo.cpp +++ b/indra/llinventory/llsaleinfo.cpp @@ -135,38 +135,8 @@ bool LLSaleInfo::fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask) return true; } -LLXMLNode *LLSaleInfo::exportFileXML() const -{ - LLXMLNode *ret = new LLXMLNode("sale_info", FALSE); - std::string type_str = ll_safe_string( lookup(mSaleType)); - ret->createChild("type", TRUE)->setStringValue(1, &type_str); - ret->createChild("price", TRUE)->setIntValue(1, &mSalePrice); - return ret; -} - -BOOL LLSaleInfo::importXML(LLXMLNode* node) -{ - BOOL success = FALSE; - if (node) - { - success = TRUE; - LLXMLNodePtr sub_node; - if (node->getChild("type", sub_node)) - { - mSaleType = lookup(sub_node->getValue().c_str()); - } - if (node->getChild("price", sub_node)) - { - success &= (1 == sub_node->getIntValue(1, &mSalePrice)); - } - if (!success) - { - lldebugs << "LLSaleInfo::importXML() failed for node named '" - << node->getName() << "'" << llendl; - } - } - return success; -} +// Deleted LLSaleInfo::exportFileXML() and LLSaleInfo::importXML() +// because I can't find any non-test code references to it. 2009-05-04 JC BOOL LLSaleInfo::importFile(LLFILE* fp, BOOL& has_perm_mask, U32& perm_mask) { diff --git a/indra/llinventory/llsaleinfo.h b/indra/llinventory/llsaleinfo.h index d546c49fd7..3461a128be 100644 --- a/indra/llinventory/llsaleinfo.h +++ b/indra/llinventory/llsaleinfo.h @@ -101,9 +101,6 @@ public: bool fromLLSD(const LLSD& sd, BOOL& has_perm_mask, U32& perm_mask); BOOL importLegacyStream(std::istream& input_stream, BOOL& has_perm_mask, U32& perm_mask); - LLXMLNode *exportFileXML() const; - BOOL importXML(LLXMLNode* node); - LLSD packMessage() const; void unpackMessage(LLSD sales); diff --git a/indra/llmath/llmath.h b/indra/llmath/llmath.h index 66451b1a27..f85c4f39f4 100644 --- a/indra/llmath/llmath.h +++ b/indra/llmath/llmath.h @@ -36,8 +36,8 @@ #include #include #include "lldefs.h" -#include "llstl.h" // *TODO: Remove when LLString is gone -#include "llstring.h" // *TODO: Remove when LLString is gone +//#include "llstl.h" // *TODO: Remove when LLString is gone +//#include "llstring.h" // *TODO: Remove when LLString is gone // lltut.h uses is_approx_equal_fraction(). This was moved to its own header // file in llcommon so we can use lltut.h for llcommon tests without making // llcommon depend on llmath. diff --git a/indra/llmath/llrect.h b/indra/llmath/llrect.h index 9eb58dbbe9..98aceb0597 100644 --- a/indra/llmath/llrect.h +++ b/indra/llmath/llrect.h @@ -271,8 +271,8 @@ public: << " W " << rect.getWidth() << " H " << rect.getHeight() << " }"; return s; } - - bool operator==(const LLRectBase &b) + + bool operator==(const LLRectBase &b) const { return ((mLeft == b.mLeft) && (mTop == b.mTop) && @@ -280,7 +280,7 @@ public: (mBottom == b.mBottom)); } - bool operator!=(const LLRectBase &b) + bool operator!=(const LLRectBase &b) const { return ((mLeft != b.mLeft) || (mTop != b.mTop) || diff --git a/indra/llmath/llsdutil_math.cpp b/indra/llmath/llsdutil_math.cpp index 073cb2e3bd..c5176681ce 100644 --- a/indra/llmath/llsdutil_math.cpp +++ b/indra/llmath/llsdutil_math.cpp @@ -165,9 +165,6 @@ LLSD ll_sd_from_color4(const LLColor4& c) LLColor4 ll_color4_from_sd(const LLSD& sd) { LLColor4 c; - c.mV[0] = (F32)sd[0].asReal(); - c.mV[1] = (F32)sd[1].asReal(); - c.mV[2] = (F32)sd[2].asReal(); - c.mV[3] = (F32)sd[3].asReal(); + c.setValue(sd); return c; } diff --git a/indra/llmath/llvolume.h b/indra/llmath/llvolume.h index e55fe52c91..af46da05d8 100644 --- a/indra/llmath/llvolume.h +++ b/indra/llmath/llvolume.h @@ -52,7 +52,7 @@ class LLVolume; #include "llquaternion.h" #include "llstrider.h" #include "v4coloru.h" -#include "llmemory.h" +#include "llrefcount.h" #include "llfile.h" //============================================================================ diff --git a/indra/llmath/llvolumemgr.h b/indra/llmath/llvolumemgr.h index e10ad94dba..a78ea76a1a 100644 --- a/indra/llmath/llvolumemgr.h +++ b/indra/llmath/llvolumemgr.h @@ -36,7 +36,7 @@ #include #include "llvolume.h" -#include "llmemory.h" +#include "llpointer.h" #include "llthread.h" class LLVolumeParams; @@ -92,8 +92,8 @@ public: // whatever calls getVolume() never owns the LLVolume* and // cannot keep references for long since it may be deleted // later. For best results hold it in an LLPointer. - LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); - void unrefVolume(LLVolume *volumep); + virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail); + virtual void unrefVolume(LLVolume *volumep); void dump(); diff --git a/indra/llmath/v3color.cpp b/indra/llmath/v3color.cpp index fa7b61cd75..e76607a91f 100644 --- a/indra/llmath/v3color.cpp +++ b/indra/llmath/v3color.cpp @@ -75,6 +75,42 @@ std::ostream& operator<<(std::ostream& s, const LLColor3 &a) return s; } +static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) +{ + if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; + if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; + if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); + if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); + if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); + return ( val1In ); +} + +void LLColor3::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn) +{ + if ( sValIn < 0.00001f ) + { + mV[VRED] = lValIn; + mV[VGREEN] = lValIn; + mV[VBLUE] = lValIn; + } + else + { + F32 interVal1; + F32 interVal2; + + if ( lValIn < 0.5f ) + interVal2 = lValIn * ( 1.0f + sValIn ); + else + interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); + + interVal1 = 2.0f * lValIn - interVal2; + + mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); + mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); + mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); + } +} + void LLColor3::calcHSL(F32* hue, F32* saturation, F32* luminance) const { F32 var_R = mV[VRED]; diff --git a/indra/llmath/v3color.h b/indra/llmath/v3color.h index 179687a32e..1915d80502 100644 --- a/indra/llmath/v3color.h +++ b/indra/llmath/v3color.h @@ -79,6 +79,7 @@ public: mV[2] = (F32) sd[2].asReal();; } + void setHSL(F32 hue, F32 saturation, F32 luminance); void calcHSL(F32* hue, F32* saturation, F32* luminance) const; const LLColor3& setToBlack(); // Clears LLColor3 to (0, 0, 0) diff --git a/indra/llmath/v4color.cpp b/indra/llmath/v4color.cpp index 0cbfce07c9..219b06ec74 100644 --- a/indra/llmath/v4color.cpp +++ b/indra/llmath/v4color.cpp @@ -227,6 +227,40 @@ const LLColor4& LLColor4::setVec(const LLColor3 &vec, F32 a) return (*this); } +void LLColor4::setValue(const LLSD& sd) +{ +#if 0 + // Clamping on setValue from LLSD is inconsistent with other set behavior + F32 val; + bool out_of_range = false; + val = sd[0].asReal(); + mV[0] = llclamp(val, 0.f, 1.f); + out_of_range = mV[0] != val; + + val = sd[1].asReal(); + mV[1] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[1] != val; + + val = sd[2].asReal(); + mV[2] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[2] != val; + + val = sd[3].asReal(); + mV[3] = llclamp(val, 0.f, 1.f); + out_of_range |= mV[3] != val; + + if (out_of_range) + { + llwarns << "LLSD color value out of range!" << llendl; + } +#else + mV[0] = (F32) sd[0].asReal(); + mV[1] = (F32) sd[1].asReal(); + mV[2] = (F32) sd[2].asReal(); + mV[3] = (F32) sd[3].asReal(); +#endif +} + const LLColor4& LLColor4::operator=(const LLColor3 &a) { mV[VX] = a.mV[VX]; @@ -271,6 +305,42 @@ LLColor4 vec3to4(const LLColor3 &vec) return temp; } +static F32 hueToRgb ( F32 val1In, F32 val2In, F32 valHUeIn ) +{ + if ( valHUeIn < 0.0f ) valHUeIn += 1.0f; + if ( valHUeIn > 1.0f ) valHUeIn -= 1.0f; + if ( ( 6.0f * valHUeIn ) < 1.0f ) return ( val1In + ( val2In - val1In ) * 6.0f * valHUeIn ); + if ( ( 2.0f * valHUeIn ) < 1.0f ) return ( val2In ); + if ( ( 3.0f * valHUeIn ) < 2.0f ) return ( val1In + ( val2In - val1In ) * ( ( 2.0f / 3.0f ) - valHUeIn ) * 6.0f ); + return ( val1In ); +} + +void LLColor4::setHSL ( F32 hValIn, F32 sValIn, F32 lValIn) +{ + if ( sValIn < 0.00001f ) + { + mV[VRED] = lValIn; + mV[VGREEN] = lValIn; + mV[VBLUE] = lValIn; + } + else + { + F32 interVal1; + F32 interVal2; + + if ( lValIn < 0.5f ) + interVal2 = lValIn * ( 1.0f + sValIn ); + else + interVal2 = ( lValIn + sValIn ) - ( sValIn * lValIn ); + + interVal1 = 2.0f * lValIn - interVal2; + + mV[VRED] = hueToRgb ( interVal1, interVal2, hValIn + ( 1.f / 3.f ) ); + mV[VGREEN] = hueToRgb ( interVal1, interVal2, hValIn ); + mV[VBLUE] = hueToRgb ( interVal1, interVal2, hValIn - ( 1.f / 3.f ) ); + } +} + void LLColor4::calcHSL(F32* hue, F32* saturation, F32* luminance) const { F32 var_R = mV[VRED]; diff --git a/indra/llmath/v4color.h b/indra/llmath/v4color.h index 785b47dd37..7414c38847 100644 --- a/indra/llmath/v4color.h +++ b/indra/llmath/v4color.h @@ -72,14 +72,9 @@ class LLColor4 return ret; } - void setValue(const LLSD& sd) - { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); - mV[3] = (F32) sd[3].asReal(); - } + void setValue(const LLSD& sd); + void setHSL(F32 hue, F32 saturation, F32 luminance); void calcHSL(F32* hue, F32* saturation, F32* luminance) const; const LLColor4& setToBlack(); // zero LLColor4 to (0, 0, 0, 1) @@ -249,7 +244,7 @@ inline LLColor4::LLColor4(void) inline LLColor4::LLColor4(const LLSD& sd) { - *this = sd; + this->setValue(sd); } inline LLColor4::LLColor4(F32 r, F32 g, F32 b) @@ -641,10 +636,7 @@ void LLColor4::clamp() inline const LLColor4& LLColor4::operator=(const LLSD& sd) { - mV[0] = (F32) sd[0].asReal(); - mV[1] = (F32) sd[1].asReal(); - mV[2] = (F32) sd[2].asReal(); - mV[3] = (F32) sd[3].asReal(); + setValue(sd); return *this; } diff --git a/indra/llmath/v4coloru.h b/indra/llmath/v4coloru.h index 082d0efbb1..c0390fa0b2 100644 --- a/indra/llmath/v4coloru.h +++ b/indra/llmath/v4coloru.h @@ -138,6 +138,12 @@ public: static BOOL parseColor4U(const std::string& buf, LLColor4U* value); + // conversion + operator const LLColor4() const + { + return LLColor4(*this); + } + static LLColor4U white; static LLColor4U black; static LLColor4U red; diff --git a/indra/llmessage/llares.h b/indra/llmessage/llares.h index 96d7f6dd31..c709a08499 100644 --- a/indra/llmessage/llares.h +++ b/indra/llmessage/llares.h @@ -45,7 +45,8 @@ # include #endif -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "lluri.h" class LLQueryResponder; diff --git a/indra/llmessage/llcachename.cpp b/indra/llmessage/llcachename.cpp index 799bc83e20..b42c5237f7 100644 --- a/indra/llmessage/llcachename.cpp +++ b/indra/llmessage/llcachename.cpp @@ -42,11 +42,7 @@ #include "llsdserialize.h" #include "lluuid.h" #include "message.h" - -// Constants -static const std::string CN_WAITING("(Loading...)"); // *TODO: translate -static const std::string CN_NOBODY("(nobody)"); // *TODO: translate -static const std::string CN_NONE("(none)"); // *TODO: translate +#include "llmemtype.h" // llsd serialization constants static const std::string AGENTS("agents"); @@ -65,6 +61,7 @@ const S32 CN_FILE_VERSION = 2; // Globals LLCacheName* gCacheName = NULL; +std::map LLCacheName::sCacheName; /// --------------------------------------------------------------------------- /// class LLCacheNameEntry @@ -92,17 +89,19 @@ class PendingReply { public: LLUUID mID; - LLCacheNameCallback mCallback; + LLCacheNameSignal mSignal; LLHost mHost; - void* mData; - PendingReply(const LLUUID& id, LLCacheNameCallback callback, void* data = NULL) - : mID(id), mCallback(callback), mData(data) - { } - + PendingReply(const LLUUID& id, const LLHost& host) - : mID(id), mCallback(0), mHost(host) - { } - + : mID(id), mHost(host) + { + } + + boost::signals::connection setCallback(const LLCacheNameCallback& cb) + { + return mSignal.connect(cb); + } + void done() { mID.setNull(); } bool isDone() const { return mID.isNull() != FALSE; } }; @@ -187,10 +186,9 @@ void ReplySender::flush() typedef std::set AskQueue; -typedef std::vector ReplyQueue; +typedef std::list ReplyQueue; typedef std::map PendingQueue; typedef std::map Cache; -typedef std::vector Observers; class LLCacheName::Impl { @@ -211,13 +209,16 @@ public: ReplyQueue mReplyQueue; // requests awaiting replies from us - Observers mObservers; + LLCacheNameSignal mSignal; LLFrameTimer mProcessTimer; Impl(LLMessageSystem* msg); ~Impl(); - + + boost::signals::connection addPending(const LLUUID& id, const LLCacheNameCallback& callback); + void addPending(const LLUUID& id, const LLHost& host); + void processPendingAsks(); void processPendingReplies(); void sendRequest(const char* msg_name, const AskQueue& queue); @@ -231,8 +232,6 @@ public: static void handleUUIDNameReply(LLMessageSystem* msg, void** userdata); static void handleUUIDGroupNameRequest(LLMessageSystem* msg, void** userdata); static void handleUUIDGroupNameReply(LLMessageSystem* msg, void** userdata); - - void notifyObservers(const LLUUID& id, const std::string& first, const std::string& last, BOOL group); }; @@ -247,6 +246,9 @@ LLCacheName::LLCacheName(LLMessageSystem* msg) LLCacheName::LLCacheName(LLMessageSystem* msg, const LLHost& upstream_host) : impl(* new Impl(msg)) { + sCacheName["waiting"] = "(Loading...)"; + sCacheName["nobody"] = "(nobody)"; + sCacheName["none"] = "(none)"; setUpstream(upstream_host); } @@ -272,52 +274,31 @@ LLCacheName::Impl::Impl(LLMessageSystem* msg) LLCacheName::Impl::~Impl() { for_each(mCache.begin(), mCache.end(), DeletePairedPointer()); + for_each(mReplyQueue.begin(), mReplyQueue.end(), DeletePointer()); } - -void LLCacheName::setUpstream(const LLHost& upstream_host) +boost::signals::connection LLCacheName::Impl::addPending(const LLUUID& id, const LLCacheNameCallback& callback) { - impl.mUpstreamHost = upstream_host; + PendingReply* reply = new PendingReply(id, LLHost()); + boost::signals::connection res = reply->setCallback(callback); + mReplyQueue.push_back(reply); + return res; } -void LLCacheName::addObserver(LLCacheNameCallback callback) +void LLCacheName::Impl::addPending(const LLUUID& id, const LLHost& host) { - impl.mObservers.push_back(callback); + PendingReply* reply = new PendingReply(id, host); + mReplyQueue.push_back(reply); } -void LLCacheName::removeObserver(LLCacheNameCallback callback) +void LLCacheName::setUpstream(const LLHost& upstream_host) { - Observers::iterator it = impl.mObservers.begin(); - Observers::iterator end = impl.mObservers.end(); - - for ( ; it != end; ++it) - { - const LLCacheNameCallback& cb = (*it); - if (cb == callback) - { - impl.mObservers.erase(it); - return; - } - } + impl.mUpstreamHost = upstream_host; } -void LLCacheName::cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data) +boost::signals::connection LLCacheName::addObserver(const LLCacheNameCallback& callback) { - ReplyQueue::iterator it = impl.mReplyQueue.begin(); - ReplyQueue::iterator end = impl.mReplyQueue.end(); - - for(; it != end; ++it) - { - const PendingReply& reply = (*it); - - if ((callback == reply.mCallback) - && (id == reply.mID) - && (user_data == reply.mData) ) - { - impl.mReplyQueue.erase(it); - return; - } - } + return impl.mSignal.connect(callback); } void LLCacheName::importFile(LLFILE* fp) @@ -493,7 +474,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las { if(id.isNull()) { - first = CN_NOBODY; + first = sCacheName["nobody"]; last.clear(); return FALSE; } @@ -507,7 +488,7 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las } else { - first = CN_WAITING; + first = sCacheName["waiting"]; last.clear(); if (!impl.isRequestPending(id)) { @@ -517,6 +498,14 @@ BOOL LLCacheName::getName(const LLUUID& id, std::string& first, std::string& las } } +// static +void LLCacheName::LocalizeCacheName(std::string key, std::string value) +{ + if (key!="" && value!= "" ) + sCacheName[key]=value; + else + llwarns<< " Error localizing cache key " << key << " To "<< value<mIsGroup) { - callback(id, entry->mGroupName, "", entry->mIsGroup, user_data); + signal(id, entry->mGroupName, "", entry->mIsGroup); } else { - callback(id, entry->mFirstName, entry->mLastName, entry->mIsGroup, user_data); + signal(id, entry->mFirstName, entry->mLastName, entry->mIsGroup); } } else @@ -597,12 +596,19 @@ void LLCacheName::get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callb impl.mAskNameQueue.insert(id); } } - impl.mReplyQueue.push_back(PendingReply(id, callback, user_data)); + res = impl.addPending(id, callback); } + return res; +} + +boost::signals::connection LLCacheName::get(const LLUUID& id, BOOL is_group, old_callback_t callback, void* user_data) +{ + return get(id, is_group, boost::bind(callback, _1, _2, _3, _4, user_data)); } void LLCacheName::processPending() { + LLMemType mt_pp(LLMemType::MTYPE_CACHE_PROCESS_PENDING); const F32 SECS_BETWEEN_PROCESS = 0.1f; if(!impl.mProcessTimer.checkExpirationAndReset(SECS_BETWEEN_PROCESS)) { @@ -684,18 +690,19 @@ void LLCacheName::dumpStats() << " AskGroup=" << impl.mAskGroupQueue.size() << " Pending=" << impl.mPendingQueue.size() << " Reply=" << impl.mReplyQueue.size() - << " Observers=" << impl.mObservers.size() +// << " Observers=" << impl.mSignal.size() << llendl; } //static std::string LLCacheName::getDefaultName() { - return CN_WAITING; + return sCacheName["waiting"]; } void LLCacheName::Impl::processPendingAsks() { + LLMemType mt_ppa(LLMemType::MTYPE_CACHE_PROCESS_PENDING_ASKS); sendRequest(_PREHASH_UUIDNameRequest, mAskNameQueue); sendRequest(_PREHASH_UUIDGroupNameRequest, mAskGroupQueue); mAskNameQueue.clear(); @@ -704,50 +711,50 @@ void LLCacheName::Impl::processPendingAsks() void LLCacheName::Impl::processPendingReplies() { - ReplyQueue::iterator it = mReplyQueue.begin(); - ReplyQueue::iterator end = mReplyQueue.end(); - + LLMemType mt_ppr(LLMemType::MTYPE_CACHE_PROCESS_PENDING_REPLIES); // First call all the callbacks, because they might send messages. - for(; it != end; ++it) + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it) { - LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID); + PendingReply* reply = *it; + LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID); if(!entry) continue; - if (it->mCallback) + if (!entry->mIsGroup) { - if (!entry->mIsGroup) - { - (it->mCallback)(it->mID, - entry->mFirstName, entry->mLastName, - FALSE, it->mData); - } - else { - (it->mCallback)(it->mID, - entry->mGroupName, "", - TRUE, it->mData); - } + (reply->mSignal)(reply->mID, entry->mFirstName, entry->mLastName, FALSE); + } + else + { + (reply->mSignal)(reply->mID, entry->mGroupName, "", TRUE); } } // Forward on all replies, if needed. ReplySender sender(mMsg); - for (it = mReplyQueue.begin(); it != end; ++it) + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ++it) { - LLCacheNameEntry* entry = get_ptr_in_map(mCache, it->mID); + PendingReply* reply = *it; + LLCacheNameEntry* entry = get_ptr_in_map(mCache, reply->mID); if(!entry) continue; - if (it->mHost.isOk()) + if (reply->mHost.isOk()) { - sender.send(it->mID, *entry, it->mHost); + sender.send(reply->mID, *entry, reply->mHost); } - it->done(); + reply->done(); + } + + for(ReplyQueue::iterator it = mReplyQueue.begin(); it != mReplyQueue.end(); ) + { + ReplyQueue::iterator curit = it++; + PendingReply* reply = *curit; + if (reply->isDone()) + { + delete reply; + mReplyQueue.erase(curit); + } } - - mReplyQueue.erase( - remove_if(mReplyQueue.begin(), mReplyQueue.end(), - std::mem_fun_ref(&PendingReply::isDone)), - mReplyQueue.end()); } @@ -785,18 +792,6 @@ void LLCacheName::Impl::sendRequest( } } -void LLCacheName::Impl::notifyObservers(const LLUUID& id, - const std::string& first, const std::string& last, BOOL is_group) -{ - for (Observers::const_iterator i = mObservers.begin(), - end = mObservers.end(); - i != end; - ++i) - { - (**i)(id, first, last, is_group, NULL); - } -} - bool LLCacheName::Impl::isRequestPending(const LLUUID& id) { U32 now = (U32)time(NULL); @@ -863,7 +858,7 @@ void LLCacheName::Impl::processUUIDRequest(LLMessageSystem* msg, bool isGroup) } } - mReplyQueue.push_back(PendingReply(id, fromHost)); + addPending(id, fromHost); } } } @@ -901,11 +896,11 @@ void LLCacheName::Impl::processUUIDReply(LLMessageSystem* msg, bool isGroup) if (!isGroup) { - notifyObservers(id, entry->mFirstName, entry->mLastName, FALSE); + mSignal(id, entry->mFirstName, entry->mLastName, FALSE); } else { - notifyObservers(id, entry->mGroupName, "", TRUE); + mSignal(id, entry->mGroupName, "", TRUE); } } } diff --git a/indra/llmessage/llcachename.h b/indra/llmessage/llcachename.h index 2757b86a7c..414b6590f6 100644 --- a/indra/llmessage/llcachename.h +++ b/indra/llmessage/llcachename.h @@ -33,12 +33,22 @@ #ifndef LL_LLCACHENAME_H #define LL_LLCACHENAME_H +#include +#include + class LLMessageSystem; class LLHost; class LLUUID; -// agent_id/group_id, first_name, last_name, is_group, user_data -typedef void (*LLCacheNameCallback)(const LLUUID&, const std::string&, const std::string&, BOOL, void*); + +typedef boost::signal LLCacheNameSignal; +typedef LLCacheNameSignal::slot_type LLCacheNameCallback; + +// Old callback with user data for compatability +typedef void (*old_callback_t)(const LLUUID&, const std::string&, const std::string&, BOOL, void*); // Here's the theory: // If you request a name that isn't in the cache, it returns "waiting" @@ -59,10 +69,7 @@ public: // for simulators, this is the data server void setUpstream(const LLHost& upstream_host); - void addObserver(LLCacheNameCallback callback); - void removeObserver(LLCacheNameCallback callback); - - void cancelCallback(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL); + boost::signals::connection addObserver(const LLCacheNameCallback& callback); // janky old format. Remove after a while. Phoenix. 2008-01-30 void importFile(LLFILE* fp); @@ -89,11 +96,10 @@ public: // If the data is currently available, may call the callback immediatly // otherwise, will request the data, and will call the callback when // available. There is no garuntee the callback will ever be called. - void get(const LLUUID& id, BOOL is_group, LLCacheNameCallback callback, void* user_data = NULL); + boost::signals::connection get(const LLUUID& id, BOOL is_group, const LLCacheNameCallback& callback); // LEGACY - void getName(const LLUUID& id, LLCacheNameCallback callback, void* user_data = NULL) - { get(id, FALSE, callback, user_data); } + boost::signals::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. @@ -107,7 +113,8 @@ public: void dumpStats(); // Dumps the sizes of the cache and associated queues. static std::string getDefaultName(); - + static void LocalizeCacheName(std::string key, std::string value); + static std::map sCacheName; private: class Impl; diff --git a/indra/llmessage/llhttpclientadapter.cpp b/indra/llmessage/llhttpclientadapter.cpp index bbb56960df..b6988224ce 100644 --- a/indra/llmessage/llhttpclientadapter.cpp +++ b/indra/llmessage/llhttpclientadapter.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 @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llmessage/llhttpclientadapter.h b/indra/llmessage/llhttpclientadapter.h index d5f3aeaf2c..7f76390d0c 100644 --- a/indra/llmessage/llhttpclientadapter.h +++ b/indra/llmessage/llhttpclientadapter.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -33,7 +34,7 @@ #define LL_HTTPCLIENTADAPTER_H #include "llhttpclientinterface.h" -#include "llmemory.h" // LLSingleton<> +#include "llsingleton.h" // LLSingleton<> class LLHTTPClientAdapter : public LLHTTPClientInterface, public LLSingleton { diff --git a/indra/llmessage/llhttpclientinterface.h b/indra/llmessage/llhttpclientinterface.h index 1f13d46447..42a8e5cd0a 100644 --- a/indra/llmessage/llhttpclientinterface.h +++ b/indra/llmessage/llhttpclientinterface.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llmessage/llhttpnode.h b/indra/llmessage/llhttpnode.h index 17ffd66e8f..3f4da69a1d 100644 --- a/indra/llmessage/llhttpnode.h +++ b/indra/llmessage/llhttpnode.h @@ -33,7 +33,8 @@ #ifndef LL_LLHTTPNODE_H #define LL_LLHTTPNODE_H -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "llsd.h" class LLChainIOFactory; diff --git a/indra/llmessage/llhttpnodeadapter.h b/indra/llmessage/llhttpnodeadapter.h index 08b5664162..7c3e9d81d1 100644 --- a/indra/llmessage/llhttpnodeadapter.h +++ b/indra/llmessage/llhttpnodeadapter.h @@ -3,26 +3,27 @@ * @brief Declaration of llhttpnode adapter classes * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * + * * Copyright (c) 2009, Linden Research, Inc. - * + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/llinstantmessage.cpp b/indra/llmessage/llinstantmessage.cpp index 3205ddfaeb..7c63625004 100644 --- a/indra/llmessage/llinstantmessage.cpp +++ b/indra/llmessage/llinstantmessage.cpp @@ -41,7 +41,7 @@ #include "llsd.h" #include "llsdserialize.h" #include "llsdutil.h" -#include "llmemory.h" +#include "llpointer.h" #include "message.h" #include "message.h" diff --git a/indra/llmessage/llinstantmessage.h b/indra/llmessage/llinstantmessage.h index 9ce6a10c80..272e753f3c 100644 --- a/indra/llmessage/llinstantmessage.h +++ b/indra/llmessage/llinstantmessage.h @@ -36,7 +36,8 @@ #include "llhost.h" #include "lluuid.h" #include "llsd.h" -#include "llmemory.h" +#include "llrefcount.h" +#include "llpointer.h" #include "v3math.h" class LLMessageSystem; diff --git a/indra/llmessage/llmessagesenderinterface.h b/indra/llmessage/llmessagesenderinterface.h index 4082666339..119eb1d7f7 100644 --- a/indra/llmessage/llmessagesenderinterface.h +++ b/indra/llmessage/llmessagesenderinterface.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llmessage/llregionpresenceverifier.cpp b/indra/llmessage/llregionpresenceverifier.cpp index 552cf4cbdb..0527d5cb8d 100644 --- a/indra/llmessage/llregionpresenceverifier.cpp +++ b/indra/llmessage/llregionpresenceverifier.cpp @@ -4,14 +4,25 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * - * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of - * this source code is governed by the Linden Lab Source Code Disclosure - * Agreement ("Agreement") previously entered between you and Linden - * Lab. By accessing, using, copying, modifying or distributing this - * software, you acknowledge that you have been informed of your - * obligations under the Agreement and agree to abide by those obligations. + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, diff --git a/indra/llmessage/llregionpresenceverifier.h b/indra/llmessage/llregionpresenceverifier.h index d1de608ec6..10602450d8 100644 --- a/indra/llmessage/llregionpresenceverifier.h +++ b/indra/llmessage/llregionpresenceverifier.h @@ -4,14 +4,25 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * - * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of - * this source code is governed by the Linden Lab Source Code Disclosure - * Agreement ("Agreement") previously entered between you and Linden - * Lab. By accessing, using, copying, modifying or distributing this - * software, you acknowledge that you have been informed of your - * obligations under the Agreement and agree to abide by those obligations. + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, diff --git a/indra/llmessage/llstoredmessage.cpp b/indra/llmessage/llstoredmessage.cpp index 615eff405d..32cbb15cb3 100644 --- a/indra/llmessage/llstoredmessage.cpp +++ b/indra/llmessage/llstoredmessage.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 diff --git a/indra/llmessage/llstoredmessage.h b/indra/llmessage/llstoredmessage.h index e817f19bd2..5069c2cb2e 100644 --- a/indra/llmessage/llstoredmessage.h +++ b/indra/llmessage/llstoredmessage.h @@ -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 diff --git a/indra/llmessage/lltemplatemessagedispatcher.cpp b/indra/llmessage/lltemplatemessagedispatcher.cpp index 3bbf3a058d..ab1beb362b 100644 --- a/indra/llmessage/lltemplatemessagedispatcher.cpp +++ b/indra/llmessage/lltemplatemessagedispatcher.cpp @@ -3,26 +3,27 @@ * @brief LLTemplateMessageDispatcher class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/lltemplatemessagedispatcher.h b/indra/llmessage/lltemplatemessagedispatcher.h index b1e74f47bb..fa861e4e42 100644 --- a/indra/llmessage/lltemplatemessagedispatcher.h +++ b/indra/llmessage/lltemplatemessagedispatcher.h @@ -3,26 +3,27 @@ * @brief LLTemplateMessageDispatcher class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/lltransfersourceasset.cpp b/indra/llmessage/lltransfersourceasset.cpp index a4d59275b9..059c1bdfa1 100644 --- a/indra/llmessage/lltransfersourceasset.cpp +++ b/indra/llmessage/lltransfersourceasset.cpp @@ -270,6 +270,7 @@ 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: @@ -292,6 +293,7 @@ bool is_asset_id_knowable(LLAssetType::EType type) case LLAssetType::AT_BODYPART: case LLAssetType::AT_ANIMATION: case LLAssetType::AT_GESTURE: + case LLAssetType::AT_FAVORITE: rv = true; break; default: diff --git a/indra/llmessage/lltrustedmessageservice.cpp b/indra/llmessage/lltrustedmessageservice.cpp index c1a6c437a7..505ece57b0 100644 --- a/indra/llmessage/lltrustedmessageservice.cpp +++ b/indra/llmessage/lltrustedmessageservice.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService implementation * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/lltrustedmessageservice.h b/indra/llmessage/lltrustedmessageservice.h index bc824565f1..dc37702471 100644 --- a/indra/llmessage/lltrustedmessageservice.h +++ b/indra/llmessage/lltrustedmessageservice.h @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService class * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/message.cpp b/indra/llmessage/message.cpp index 78af35bf65..e56d818d65 100644 --- a/indra/llmessage/message.cpp +++ b/indra/llmessage/message.cpp @@ -86,6 +86,7 @@ #include "v3math.h" #include "v4math.h" #include "lltransfertargetvfile.h" +#include "llmemtype.h" // Constants //const char* MESSAGE_LOG_FILENAME = "message.log"; @@ -794,6 +795,7 @@ S32 LLMessageSystem::getReceiveBytes() const void LLMessageSystem::processAcks() { + LLMemType mt_pa(LLMemType::MTYPE_MESSAGE_PROCESS_ACKS); F64 mt_sec = getMessageTimeSeconds(); { gTransferManager.updateTransfers(); @@ -4020,6 +4022,7 @@ void LLMessageSystem::setTimeDecodesSpamThreshold( F32 seconds ) // TODO: babbage: move gServicePump in to LLMessageSystem? bool LLMessageSystem::checkAllMessages(S64 frame_count, LLPumpIO* http_pump) { + LLMemType mt_cam(LLMemType::MTYPE_MESSAGE_CHECK_ALL); if(checkMessages(frame_count)) { return true; diff --git a/indra/llmessage/message.h b/indra/llmessage/message.h index 0f3576732d..27482ca1af 100644 --- a/indra/llmessage/message.h +++ b/indra/llmessage/message.h @@ -59,10 +59,10 @@ #include "llhttpclient.h" #include "llhttpnode.h" #include "llpacketack.h" +#include "llsingleton.h" #include "message_prehash.h" #include "llstl.h" #include "llmsgvariabletype.h" -#include "llmsgvariabletype.h" #include "llmessagesenderinterface.h" #include "llstoredmessage.h" diff --git a/indra/llmessage/message_prehash.cpp b/indra/llmessage/message_prehash.cpp index 43b5f8e224..4e657067cd 100644 --- a/indra/llmessage/message_prehash.cpp +++ b/indra/llmessage/message_prehash.cpp @@ -405,7 +405,7 @@ char* _PREHASH_GlobalX = LLMessageStringTable::getInstance()->getString("GlobalX char* _PREHASH_GlobalY = LLMessageStringTable::getInstance()->getString("GlobalY"); char* _PREHASH_CopyRotates = LLMessageStringTable::getInstance()->getString("CopyRotates"); char* _PREHASH_KickUserAck = LLMessageStringTable::getInstance()->getString("KickUserAck"); -char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); +char* _PREHASH_TopPick = LLMessageStringTable::getInstance()->getString("TopPick"); //legacy var need to be deleted -angela char* _PREHASH_SessionID = LLMessageStringTable::getInstance()->getString("SessionID"); char* _PREHASH_GlobalZ = LLMessageStringTable::getInstance()->getString("GlobalZ"); char* _PREHASH_DeclineFriendship = LLMessageStringTable::getInstance()->getString("DeclineFriendship"); diff --git a/indra/llmessage/tests/commtest.h b/indra/llmessage/tests/commtest.h index 7360230451..cf1461ed2b 100644 --- a/indra/llmessage/tests/commtest.h +++ b/indra/llmessage/tests/commtest.h @@ -5,7 +5,30 @@ * @brief * * $LicenseInfo:firstyear=2009&license=viewergpl$ + * * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ diff --git a/indra/llmessage/tests/llcurl_stub.cpp b/indra/llmessage/tests/llcurl_stub.cpp index 93653e345e..d6be54336a 100644 --- a/indra/llmessage/tests/llcurl_stub.cpp +++ b/indra/llmessage/tests/llcurl_stub.cpp @@ -3,16 +3,16 @@ * @brief stub class to allow unit testing * * $LicenseInfo:firstyear=2008&license=viewergpl$ - * - * Copyright (c) 2008, Linden Research, Inc. - * + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of * this source code is governed by the Linden Lab Source Code Disclosure - * Agreement ("Agreement") { } + * 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. diff --git a/indra/llmessage/tests/llhttpclientadapter_test.cpp b/indra/llmessage/tests/llhttpclientadapter_test.cpp index bde76db08b..250fa100b6 100644 --- a/indra/llmessage/tests/llhttpclientadapter_test.cpp +++ b/indra/llmessage/tests/llhttpclientadapter_test.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2001-2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp index a6f5659352..d57f17f270 100644 --- a/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp +++ b/indra/llmessage/tests/lltemplatemessagedispatcher_test.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService unit tests * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/tests/lltesthttpclientadapter.cpp b/indra/llmessage/tests/lltesthttpclientadapter.cpp index 41ce36f345..0cea4b57c2 100644 --- a/indra/llmessage/tests/lltesthttpclientadapter.cpp +++ b/indra/llmessage/tests/lltesthttpclientadapter.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of * this source code is governed by the Linden Lab Source Code Disclosure diff --git a/indra/llmessage/tests/lltesthttpclientadapter.h b/indra/llmessage/tests/lltesthttpclientadapter.h index cd93bcc8c1..6f252e8510 100644 --- a/indra/llmessage/tests/lltesthttpclientadapter.h +++ b/indra/llmessage/tests/lltesthttpclientadapter.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of * this source code is governed by the Linden Lab Source Code Disclosure diff --git a/indra/llmessage/tests/lltestmessagesender.cpp b/indra/llmessage/tests/lltestmessagesender.cpp index 240813a4a3..3d1876ec36 100644 --- a/indra/llmessage/tests/lltestmessagesender.cpp +++ b/indra/llmessage/tests/lltestmessagesender.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of * this source code is governed by the Linden Lab Source Code Disclosure diff --git a/indra/llmessage/tests/lltestmessagesender.h b/indra/llmessage/tests/lltestmessagesender.h index 00641d1913..d3aaee8f69 100644 --- a/indra/llmessage/tests/lltestmessagesender.h +++ b/indra/llmessage/tests/lltestmessagesender.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * The following source code is PROPRIETARY AND CONFIDENTIAL. Use of * this source code is governed by the Linden Lab Source Code Disclosure diff --git a/indra/llmessage/tests/lltrustedmessageservice_test.cpp b/indra/llmessage/tests/lltrustedmessageservice_test.cpp index 44595391df..0a3da4b467 100644 --- a/indra/llmessage/tests/lltrustedmessageservice_test.cpp +++ b/indra/llmessage/tests/lltrustedmessageservice_test.cpp @@ -3,26 +3,27 @@ * @brief LLTrustedMessageService unit tests * * $LicenseInfo:firstyear=2009&license=viewergpl$ - * - * Copyright (c) 2001-2009, Linden Research, Inc. - * + * + * Copyright (c) 2009, Linden Research, Inc. + * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 - * + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception - * + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, * and agree to abide by those obligations. - * + * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, * COMPLETENESS OR PERFORMANCE. diff --git a/indra/llmessage/tests/networkio.h b/indra/llmessage/tests/networkio.h index 11c5cc07fc..0ebe369ea2 100644 --- a/indra/llmessage/tests/networkio.h +++ b/indra/llmessage/tests/networkio.h @@ -5,7 +5,30 @@ * @brief * * $LicenseInfo:firstyear=2009&license=viewergpl$ + * * Copyright (c) 2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. * $/LicenseInfo$ */ diff --git a/indra/llprimitive/llmaterialtable.cpp b/indra/llprimitive/llmaterialtable.cpp index 4c22203eb9..18787c47c5 100644 --- a/indra/llprimitive/llmaterialtable.cpp +++ b/indra/llprimitive/llmaterialtable.cpp @@ -124,6 +124,17 @@ LLMaterialTable::~LLMaterialTable() mMaterialInfoList.clear(); } +void LLMaterialTable::initTableTransNames(std::map namemap) +{ + for (info_list_t::iterator iter = mMaterialInfoList.begin(); + iter != mMaterialInfoList.end(); ++iter) + { + LLMaterialInfo *infop = *iter; + std::string name = infop->mName; + infop->mName = namemap[name]; + } +} + void LLMaterialTable::initBasicTable() { // *TODO: Translate diff --git a/indra/llprimitive/llmaterialtable.h b/indra/llprimitive/llmaterialtable.h index ca9017abd0..2c0b046fa7 100644 --- a/indra/llprimitive/llmaterialtable.h +++ b/indra/llprimitive/llmaterialtable.h @@ -147,6 +147,8 @@ public: void initBasicTable(); + void initTableTransNames(std::map namemap); + BOOL add(U8 mcode, const std::string& name, const LLUUID &uuid); BOOL addCollisionSound(U8 mcode, U8 mcode2, const LLUUID &uuid); BOOL addSlidingSound(U8 mcode, U8 mcode2, const LLUUID &uuid); diff --git a/indra/llprimitive/llprimitive.cpp b/indra/llprimitive/llprimitive.cpp index 13facc0d58..33807e7545 100644 --- a/indra/llprimitive/llprimitive.cpp +++ b/indra/llprimitive/llprimitive.cpp @@ -132,7 +132,7 @@ void LLPrimitive::setVolumeManager( LLVolumeMgr* volume_manager ) { if ( !volume_manager || sVolumeManager ) { - llerrs << "Unable to set LLPrimitive::sVolumeManager to NULL" << llendl; + llerrs << "LLPrimitive::sVolumeManager attempting to be set to NULL or it already has been set." << llendl; } sVolumeManager = volume_manager; } diff --git a/indra/llprimitive/llprimitive.h b/indra/llprimitive/llprimitive.h index c25df0a40f..b3a337ce5d 100644 --- a/indra/llprimitive/llprimitive.h +++ b/indra/llprimitive/llprimitive.h @@ -37,7 +37,7 @@ #include "v3math.h" #include "xform.h" #include "message.h" -#include "llmemory.h" +#include "llpointer.h" #include "llvolume.h" #include "lltextureentry.h" #include "llprimtexturelist.h" diff --git a/indra/llprimitive/llprimtexturelist.cpp b/indra/llprimitive/llprimtexturelist.cpp index c9632ebdad..d03150fc78 100644 --- a/indra/llprimitive/llprimtexturelist.cpp +++ b/indra/llprimitive/llprimtexturelist.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2007, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llprimitive/llprimtexturelist.h b/indra/llprimitive/llprimtexturelist.h index 61285bd1bf..6254878b99 100644 --- a/indra/llprimitive/llprimtexturelist.h +++ b/indra/llprimitive/llprimtexturelist.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008-2007, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llprimitive/tests/llmessagesystem_stub.cpp b/indra/llprimitive/tests/llmessagesystem_stub.cpp new file mode 100644 index 0000000000..62504be3b0 --- /dev/null +++ b/indra/llprimitive/tests/llmessagesystem_stub.cpp @@ -0,0 +1,42 @@ +/** + * @file llmessagesystem_stub.cpp + * @brief stub class to allow unit testing + * + * $LicenseInfo:firstyear=2008&license=internal$ + * + * 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") { } + * Lab. By accessing, using, copying, modifying or distributing this + * software, you acknowledge that you have been informed of your + * obligations under the Agreement and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#include "linden_common.h" + +char * _PREHASH_TextureEntry; + +S32 LLMessageSystem::getSizeFast(char const*, char const*) const +{ + return 0; +} + +S32 LLMessageSystem::getSizeFast(char const*, int, char const*) const +{ + return 0; +} + +void LLMessageSystem::getBinaryDataFast(char const*, char const*, void*, int, int, int) +{ +} + +void LLMessageSystem::addBinaryDataFast(char const*, void const*, int) +{ +} + diff --git a/indra/llprimitive/tests/llprimitive_test.cpp b/indra/llprimitive/tests/llprimitive_test.cpp new file mode 100644 index 0000000000..1805a9e968 --- /dev/null +++ b/indra/llprimitive/tests/llprimitive_test.cpp @@ -0,0 +1,214 @@ +/** + * @file llprimitive_test.cpp + * @brief llprimitive tests + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * Copyright (c) 2001-2009, Linden Research, Inc. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "../test/lltut.h" + +#include "../llprimitive.h" + +#include "../../llmath/llvolumemgr.h" + +class DummyVolumeMgr : public LLVolumeMgr +{ +public: + DummyVolumeMgr() : LLVolumeMgr(), mVolumeTest(NULL), mCurrDetailTest(0) {} + ~DummyVolumeMgr() + { + } + + + virtual LLVolume *refVolume(const LLVolumeParams &volume_params, const S32 detail) + { + if (mVolumeTest.isNull() || volume_params != mCurrParamsTest || detail != mCurrDetailTest) + { + F32 volume_detail = LLVolumeLODGroup::getVolumeScaleFromDetail(detail); + mVolumeTest = new LLVolume(volume_params, volume_detail, FALSE, FALSE); + mCurrParamsTest = volume_params; + mCurrDetailTest = detail; + return mVolumeTest; + } + else + { + return mVolumeTest; + } + } + + virtual void unrefVolume(LLVolume *volumep) + { + if (mVolumeTest == volumep) + { + mVolumeTest = NULL; + } + } + +private: + LLPointer mVolumeTest; + LLVolumeParams mCurrParamsTest; + S32 mCurrDetailTest; +}; + +class PRIMITIVE_TEST_SETUP +{ +public: + PRIMITIVE_TEST_SETUP() + { + volume_manager_test = new DummyVolumeMgr(); + LLPrimitive::setVolumeManager(volume_manager_test); + } + + ~PRIMITIVE_TEST_SETUP() + { + LLPrimitive::cleanupVolumeManager(); + } + DummyVolumeMgr * volume_manager_test; +}; + +namespace tut +{ + struct llprimitive + { + PRIMITIVE_TEST_SETUP setup_class; + }; + + typedef test_group llprimitive_t; + typedef llprimitive_t::object llprimitive_object_t; + tut::llprimitive_t tut_llprimitive("llprimitive"); + + template<> template<> + void llprimitive_object_t::test<1>() + { + set_test_name("Test LLPrimitive Instantiation"); + LLPrimitive test; + } + + template<> template<> + void llprimitive_object_t::test<2>() + { + set_test_name("Test LLPrimitive PCode setter and getter."); + LLPrimitive test; + ensure_equals(test.getPCode(), 0); + LLPCode code = 1; + test.setPCode(code); + ensure_equals(test.getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<3>() + { + set_test_name("Test llprimitive constructor and initer."); + LLPCode code = 1; + LLPrimitive primitive; + primitive.init_primitive(code); + ensure_equals(primitive.getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<4>() + { + set_test_name("Test Static llprimitive constructor and initer."); + LLPCode code = 1; + LLPrimitive * primitive = LLPrimitive::createPrimitive(code); + ensure(primitive != NULL); + ensure_equals(primitive->getPCode(), code); + } + + template<> template<> + void llprimitive_object_t::test<5>() + { + set_test_name("Test setVolume creation of new unique volume."); + LLPrimitive primitive; + LLVolumeParams params; + + // Make sure volume starts off null + ensure(primitive.getVolume() == NULL); + + // Make sure we have no texture entries before setting the volume + ensure_equals(primitive.getNumTEs(), 0); + + // Test that GEOMETRY has not been flagged as changed. + ensure(!primitive.isChanged(LLXform::GEOMETRY)); + + // Make sure setVolume returns true + ensure(primitive.setVolume(params, 0, true) == TRUE); + LLVolume* new_volume = primitive.getVolume(); + + // make sure new volume was actually created + ensure(new_volume != NULL); + + // Make sure that now that we've set the volume we have texture entries + ensure_not_equals(primitive.getNumTEs(), 0); + + // Make sure that the number of texture entries equals the number of faces in the volume (should be 6) + ensure_equals(new_volume->getNumFaces(), 6); + ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces()); + + // Test that GEOMETRY has been flagged as changed. + ensure(primitive.isChanged(LLXform::GEOMETRY)); + + // Run it twice to make sure it doesn't create a different one if params are the same + ensure(primitive.setVolume(params, 0, true) == FALSE); + ensure(new_volume == primitive.getVolume()); + + // Change the param definition and try setting it again. + params.setRevolutions(4); + ensure(primitive.setVolume(params, 0, true) == TRUE); + + // Ensure that we now have a different volume + ensure(new_volume != primitive.getVolume()); + } + + template<> template<> + void llprimitive_object_t::test<6>() + { + set_test_name("Test setVolume creation of new NOT-unique volume."); + LLPrimitive primitive; + LLVolumeParams params; + + // Make sure volume starts off null + ensure(primitive.getVolume() == NULL); + + // Make sure we have no texture entries before setting the volume + ensure_equals(primitive.getNumTEs(), 0); + + // Test that GEOMETRY has not been flagged as changed. + ensure(!primitive.isChanged(LLXform::GEOMETRY)); + + // Make sure setVolume returns true + ensure(primitive.setVolume(params, 0, false) == TRUE); + + LLVolume* new_volume = primitive.getVolume(); + + // make sure new volume was actually created + ensure(new_volume != NULL); + + // Make sure that now that we've set the volume we have texture entries + ensure_not_equals(primitive.getNumTEs(), 0); + + // Make sure that the number of texture entries equals the number of faces in the volume (should be 6) + ensure_equals(new_volume->getNumFaces(), 6); + ensure_equals(primitive.getNumTEs(), new_volume->getNumFaces()); + + // Test that GEOMETRY has been flagged as changed. + ensure(primitive.isChanged(LLXform::GEOMETRY)); + + // Run it twice to make sure it doesn't create a different one if params are the same + ensure(primitive.setVolume(params, 0, false) == FALSE); + ensure(new_volume == primitive.getVolume()); + + // Change the param definition and try setting it again. + params.setRevolutions(4); + ensure(primitive.setVolume(params, 0, false) == TRUE); + + // Ensure that we now have a different volume + ensure(new_volume != primitive.getVolume()); + } +} + +#include "llmessagesystem_stub.cpp" diff --git a/indra/llrender/llfontbitmapcache.cpp b/indra/llrender/llfontbitmapcache.cpp index f6321b0534..052510e6ed 100644 --- a/indra/llrender/llfontbitmapcache.cpp +++ b/indra/llrender/llfontbitmapcache.cpp @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llrender/llfontbitmapcache.h b/indra/llrender/llfontbitmapcache.h index e5c09f8826..4beea0d026 100644 --- a/indra/llrender/llfontbitmapcache.h +++ b/indra/llrender/llfontbitmapcache.h @@ -4,7 +4,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -12,12 +12,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, diff --git a/indra/llrender/llfontgl.cpp b/indra/llrender/llfontgl.cpp index beecb6b7c1..048bfe8e0d 100644 --- a/indra/llrender/llfontgl.cpp +++ b/indra/llrender/llfontgl.cpp @@ -32,16 +32,20 @@ #include "linden_common.h" -#include +#include "llfontgl.h" +// Linden library includes #include "llfont.h" -#include "llfontgl.h" #include "llfontbitmapcache.h" #include "llfontregistry.h" #include "llgl.h" +#include "llimagegl.h" #include "llrender.h" -#include "v4color.h" #include "llstl.h" +#include "v4color.h" + +// Third party library includes +#include const S32 BOLD_OFFSET = 1; @@ -102,14 +106,6 @@ U8 LLFontGL::getStyleFromString(const std::string &style) { ret |= UNDERLINE; } - if (style.find("SHADOW") != style.npos) - { - ret |= DROP_SHADOW; - } - if (style.find("SOFT_SHADOW") != style.npos) - { - ret |= DROP_SHADOW_SOFT; - } return ret; } @@ -215,11 +211,11 @@ bool findOrCreateFont(LLFontGL*& fontp, const LLFontDescriptor& desc) } // static -BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, +void LLFontGL::initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, - const std::vector& xui_paths) + const std::vector& xui_paths, + bool create_gl_textures) { - bool succ = true; sVertDPI = (F32)llfloor(screen_dpi * y_scale); sHorizDPI = (F32)llfloor(screen_dpi * x_scale); sScaleX = x_scale; @@ -229,24 +225,30 @@ BOOL LLFontGL::initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, // Font registry init if (!sFontRegistry) { - sFontRegistry = new LLFontRegistry(xui_paths); + sFontRegistry = new LLFontRegistry(xui_paths, create_gl_textures); sFontRegistry->parseFontInfo("fonts.xml"); } else { sFontRegistry->reset(); } +} - // Force standard fonts to get generated up front. - // This is primarily for error detection purposes. - succ &= (NULL != getFontSansSerifSmall()); - succ &= (NULL != getFontSansSerif()); - succ &= (NULL != getFontSansSerifBig()); - succ &= (NULL != getFontSansSerifHuge()); - succ &= (NULL != getFontSansSerifBold()); - succ &= (NULL != getFontMonospace()); +// Force standard fonts to get generated up front. +// This is primarily for error detection purposes. +// Don't do this during initClass because it can be slow and we want to get +// the viewer window on screen first. JC +// static +bool LLFontGL::loadDefaultFonts() +{ + bool succ = true; + succ &= (NULL != getFontSansSerifSmall()); + succ &= (NULL != getFontSansSerif()); + succ &= (NULL != getFontSansSerifBig()); + succ &= (NULL != getFontSansSerifHuge()); + succ &= (NULL != getFontSansSerifBold()); + succ &= (NULL != getFontMonospace()); succ &= (NULL != getFontExtChar()); - return succ; } @@ -341,6 +343,34 @@ LLFontGL* LLFontGL::getFont(const LLFontDescriptor& desc) return sFontRegistry->getFont(desc); } +//static +LLFontGL* LLFontGL::getFontByName(const std::string& name) +{ + // check for most common fonts first + if (name == "SANSSERIF") + { + return getFontSansSerif(); + } + else if (name == "SANSSERIF_SMALL") + { + return getFontSansSerifSmall(); + } + else if (name == "SANSSERIF_BIG") + { + return getFontSansSerifBig(); + } + else if (name == "SMALL" || name == "OCRA") + { + // *BUG: Should this be "MONOSPACE"? Do we use "OCRA" anymore? + // Does "SMALL" mean "SERIF"? + return getFontMonospace(); + } + else + { + return NULL; + } +} + BOOL LLFontGL::addChar(const llwchar wch) const { if (!LLFont::addChar(wch)) @@ -364,12 +394,13 @@ S32 LLFontGL::renderUTF8(const std::string &text, const S32 offset, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, + ShadowType shadow, const S32 max_chars, const S32 max_pixels, F32* right_x, BOOL use_ellipses) const { LLWString wstr = utf8str_to_wstring(text); - return render(wstr, offset, x, y, color, halign, valign, style, max_chars, max_pixels, right_x, FALSE, use_ellipses); + return render(wstr, offset, x, y, color, halign, valign, style, shadow, max_chars, max_pixels, right_x, FALSE, use_ellipses); } S32 LLFontGL::render(const LLWString &wstr, @@ -378,6 +409,7 @@ S32 LLFontGL::render(const LLWString &wstr, const LLColor4 &color, const HAlign halign, const VAlign valign, U8 style, + ShadowType shadow, const S32 max_chars, S32 max_pixels, F32* right_x, BOOL use_embedded, @@ -401,14 +433,14 @@ S32 LLFontGL::render(const LLWString &wstr, style = style & (~getFontDesc().getStyle()); F32 drop_shadow_strength = 0.f; - if (style & (DROP_SHADOW | DROP_SHADOW_SOFT)) + if (shadow != NO_SHADOW) { F32 luminance; color.calcHSL(NULL, NULL, &luminance); drop_shadow_strength = clamp_rescale(luminance, 0.35f, 0.6f, 0.f, 1.f); if (luminance < 0.35f) { - style = style & ~(DROP_SHADOW | DROP_SHADOW_SOFT); + shadow = NO_SHADOW; } } @@ -547,7 +579,7 @@ S32 LLFontGL::render(const LLWString &wstr, LLRectf uv_rect(0.f, 1.f, 1.f, 0.f); LLRectf screen_rect(ext_x, ext_y + ext_height, ext_x + ext_width, ext_y); - drawGlyph(screen_rect, uv_rect, LLColor4::white, style, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, LLColor4::white, style, shadow, drop_shadow_strength); if (!label.empty()) { @@ -559,7 +591,7 @@ S32 LLFontGL::render(const LLWString &wstr, /*llfloor*/((ext_x + (F32)ext_image->getWidth() + EXT_X_BEARING) / sScaleX), /*llfloor*/(cur_y / sScaleY), color, - halign, BASELINE, NORMAL, S32_MAX, S32_MAX, NULL, + halign, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, TRUE ); gGL.popMatrix(); } @@ -613,7 +645,7 @@ S32 LLFontGL::render(const LLWString &wstr, llround(cur_render_x + (F32)fgi->mXBearing) + (F32)fgi->mWidth, llround(cur_render_y + (F32)fgi->mYBearing) - (F32)fgi->mHeight); - drawGlyph(screen_rect, uv_rect, color, style, drop_shadow_strength); + drawGlyph(screen_rect, uv_rect, color, style, shadow, drop_shadow_strength); chars_drawn++; cur_x += fgi->mXAdvance; @@ -671,6 +703,7 @@ S32 LLFontGL::render(const LLWString &wstr, color, LEFT, valign, style, + shadow, S32_MAX, max_pixels, right_x, FALSE); @@ -838,13 +871,28 @@ S32 LLFontGL::maxDrawableChars(const llwchar* wchars, F32 max_pixels, S32 max_ch { if (iswspace(wch)) { - in_word = FALSE; + if(wch !=(0x00A0)) + { + in_word = FALSE; + } + } + if (iswindividual(wch)) + { + if (iswpunct(wchars[i+1])) + { + in_word=TRUE; + } + else + { + in_word=FALSE; + start_of_last_word = i; + } } } else { start_of_last_word = i; - if (!iswspace(wch)) + if (!iswspace(wch)||!iswindividual(wch)) { in_word = TRUE; } @@ -1108,7 +1156,7 @@ void LLFontGL::renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F3 llfont_round_y(screen_rect.mBottom)); } -void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_strength) const +void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_strength) const { F32 slant_offset; slant_offset = ((style & ITALIC) ? ( -mAscender * 0.2f) : 0.f); @@ -1128,7 +1176,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con renderQuad(screen_rect_offset, uv_rect, slant_offset); } } - else if (style & DROP_SHADOW_SOFT) + else if (shadow == DROP_SHADOW_SOFT) { LLColor4 shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength * DROP_SHADOW_SOFT_STRENGTH; @@ -1161,7 +1209,7 @@ void LLFontGL::drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, con gGL.color4fv(color.mV); renderQuad(screen_rect, uv_rect, slant_offset); } - else if (style & DROP_SHADOW) + else if (shadow == DROP_SHADOW) { LLColor4 shadow_color = LLFontGL::sShadowColor; shadow_color.mV[VALPHA] = color.mV[VALPHA] * drop_shadow_strength; diff --git a/indra/llrender/llfontgl.h b/indra/llrender/llfontgl.h index 6cb1727ff4..204c6908af 100644 --- a/indra/llrender/llfontgl.h +++ b/indra/llrender/llfontgl.h @@ -34,16 +34,15 @@ #ifndef LL_LLFONTGL_H #define LL_LLFONTGL_H -#include "llfont.h" -#include "llimagegl.h" -#include "v2math.h" #include "llcoord.h" -#include "llrect.h" - +#include "llfont.h" #include "llfontregistry.h" +#include "llpointer.h" +#include "llrect.h" +#include "v2math.h" class LLColor4; - +class LLImageGL; // Key used to request a font. class LLFontDescriptor; @@ -73,12 +72,18 @@ public: enum StyleFlags { // text style to render. May be combined (these are bit flags) + // TODO:: Maybe change the value to 0x01 << 0 for 1 0x01 << 1 for 2, 0x01 << 2 for 4 NORMAL = 0, BOLD = 1, ITALIC = 2, - UNDERLINE = 4, - DROP_SHADOW = 8, - DROP_SHADOW_SOFT = 16 + UNDERLINE = 4 + }; + + enum ShadowType + { + NO_SHADOW, + DROP_SHADOW, + DROP_SHADOW_SOFT }; // Takes a string with potentially several flags, i.e. "NORMAL|BOLD|ITALIC" @@ -93,10 +98,14 @@ public: LLFontGL &operator=(const LLFontGL &source); - static BOOL initDefaultFonts(F32 screen_dpi, F32 x_scale, F32 y_scale, + static void initClass(F32 screen_dpi, F32 x_scale, F32 y_scale, const std::string& app_dir, - const std::vector& xui_paths); + const std::vector& xui_paths, + bool create_gl_textures = true); + // Load sans-serif, sans-serif-small, etc. + // Slow, requires multiple seconds to load fonts. + static bool loadDefaultFonts(); static void destroyDefaultFonts(); static void destroyAllGL(); void destroyGL(); @@ -111,17 +120,17 @@ public: const LLColor4 &color) const { return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - LEFT, BASELINE, NORMAL, - S32_MAX, S32_MAX, NULL, FALSE); + LEFT, BASELINE, NORMAL, NO_SHADOW, + S32_MAX, S32_MAX, NULL, FALSE); } S32 renderUTF8(const std::string &text, const S32 begin_offset, S32 x, S32 y, const LLColor4 &color, - HAlign halign, VAlign valign, U8 style = NORMAL) const + HAlign halign, VAlign valign, U8 style = NORMAL, ShadowType shadow = NO_SHADOW) const { return renderUTF8(text, begin_offset, (F32)x, (F32)y, color, - halign, valign, style, + halign, valign, style, shadow, S32_MAX, S32_MAX, NULL, FALSE); } @@ -133,6 +142,7 @@ public: HAlign halign, VAlign valign, U8 style, + ShadowType shadow, S32 max_chars, S32 max_pixels, F32* right_x, @@ -143,7 +153,7 @@ public: const LLColor4 &color) const { return render(text, begin_offset, x, y, color, - LEFT, BASELINE, NORMAL, + LEFT, BASELINE, NORMAL, NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE, FALSE); } @@ -155,6 +165,7 @@ public: HAlign halign = LEFT, VAlign valign = BASELINE, U8 style = NORMAL, + ShadowType shadow = NO_SHADOW, S32 max_chars = S32_MAX, S32 max_pixels = S32_MAX, F32* right_x=NULL, @@ -220,7 +231,7 @@ protected: F32 getEmbeddedCharAdvance(const embedded_data_t* ext_data) const; void clearEmbeddedChars(); void renderQuad(const LLRectf& screen_rect, const LLRectf& uv_rect, F32 slant_amt) const; - void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, F32 drop_shadow_fade) const; + void drawGlyph(const LLRectf& screen_rect, const LLRectf& uv_rect, const LLColor4& color, U8 style, ShadowType shadow, F32 drop_shadow_fade) const; public: static F32 sVertDPI; @@ -238,6 +249,8 @@ public: static LLFontGL* getFontSansSerifBold(); static LLFontGL* getFontExtChar(); static LLFontGL* getFont(const LLFontDescriptor& desc); + // Use with legacy names like "SANSSERIF_SMALL" or "OCRA" + static LLFontGL* getFontByName(const std::string& name); static LLColor4 sShadowColor; diff --git a/indra/llrender/llfontregistry.cpp b/indra/llrender/llfontregistry.cpp index 9b5bc5d0af..18e4a6915d 100644 --- a/indra/llrender/llfontregistry.cpp +++ b/indra/llrender/llfontregistry.cpp @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,12 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -167,7 +168,9 @@ LLFontDescriptor LLFontDescriptor::normalize() const return LLFontDescriptor(new_name,new_size,new_style,getFileNames()); } -LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths) +LLFontRegistry::LLFontRegistry(const string_vec_t& xui_paths, + bool create_gl_textures) +: mCreateGLTextures(create_gl_textures) { // Propagate this down from LLUICtrlFactory so LLRender doesn't // need an upstream dependency on LLUI. @@ -215,8 +218,8 @@ bool LLFontRegistry::parseFontInfo(const std::string& xml_filename) success = success || init_succ; } } - if (success) - dump(); + //if (success) + // dump(); return success; } @@ -426,7 +429,9 @@ LLFontGL *LLFontRegistry::createFont(const LLFontDescriptor& desc) { LLFontGL *fontp = new LLFontGL; std::string font_path = local_path + *file_name_it; - BOOL is_fallback = !is_first_found; + // *HACK: Fallback fonts don't render, so we can use that to suppress + // creation of OpenGL textures for test apps. JC + BOOL is_fallback = !is_first_found || !mCreateGLTextures; F32 extra_scale = (is_fallback)?fallback_scale:1.0; if (!fontp->loadFace(font_path, extra_scale * point_size, LLFontGL::sVertDPI, LLFontGL::sHorizDPI, 2, is_fallback)) diff --git a/indra/llrender/llfontregistry.h b/indra/llrender/llfontregistry.h index ed775eeed0..198ca0b920 100644 --- a/indra/llrender/llfontregistry.h +++ b/indra/llrender/llfontregistry.h @@ -5,7 +5,7 @@ * * $LicenseInfo:firstyear=2008&license=viewergpl$ * - * Copyright (c) 2008, Linden Research, Inc. + * Copyright (c) 2008-2009, Linden Research, Inc. * * Second Life Viewer Source Code * The source code in this file ("Source Code") is provided by Linden Lab @@ -13,12 +13,13 @@ * ("GPL"), unless you have obtained a separate licensing agreement * ("Other License"), formally executed by you and Linden Lab. Terms of * the GPL can be found in doc/GPL-license.txt in this distribution, or - * online at http://secondlife.com/developers/opensource/gplv2 + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 * * There are special exceptions to the terms and conditions of the GPL as * it is applied to this Source Code. View the full text of the exception * in the file doc/FLOSS-exception.txt in this software distribution, or - * online at http://secondlife.com/developers/opensource/flossexception + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception * * By copying, modifying or distributing this software, you acknowledge * that you have read and understood your obligations described above, @@ -70,7 +71,10 @@ private: class LLFontRegistry { public: - LLFontRegistry(const string_vec_t& xui_paths); + // create_gl_textures - set to false for test apps with no OpenGL window, + // such as llui_libtest + LLFontRegistry(const string_vec_t& xui_paths, + bool create_gl_textures); ~LLFontRegistry(); // Load standard font info from XML file(s). @@ -108,6 +112,7 @@ private: string_vec_t mUltimateFallbackList; string_vec_t mXUIPaths; + bool mCreateGLTextures; }; #endif // LL_LLFONTREGISTRY_H diff --git a/indra/llrender/llgl.cpp b/indra/llrender/llgl.cpp index 61194c4ecf..7e1df0e565 100644 --- a/indra/llrender/llgl.cpp +++ b/indra/llrender/llgl.cpp @@ -45,10 +45,13 @@ #include "llrender.h" #include "llerror.h" +#include "llerrorcontrol.h" #include "llquaternion.h" #include "llmath.h" #include "m4math.h" #include "llstring.h" +#include "llmemtype.h" +#include "llstacktrace.h" #include "llglheaders.h" @@ -56,9 +59,49 @@ //#define GL_STATE_VERIFY #endif + +BOOL gDebugSession = FALSE; BOOL gDebugGL = FALSE; BOOL gClothRipple = FALSE; BOOL gNoRender = FALSE; + +std::ofstream gFailLog; + +void ll_init_fail_log(std::string filename) +{ + gFailLog.open(filename.c_str()); +} + + +void ll_fail(std::string msg) +{ + + if (gDebugSession) + { + std::vector lines; + + gFailLog << LLError::utcTime() << " " << msg << std::endl; + + gFailLog << "Stack Trace:" << std::endl; + + ll_get_stack_trace(lines); + + for(size_t i = 0; i < lines.size(); ++i) + { + gFailLog << lines[i] << std::endl; + } + + gFailLog << "End of Stack Trace." << std::endl << std::endl; + + gFailLog.flush(); + } +}; + +void ll_close_fail_log() +{ + gFailLog.close(); +} + LLMatrix4 gGLObliqueProjectionInverse; #define LL_GL_NAME_POOLING 0 @@ -596,6 +639,7 @@ void LLGLManager::initExtensions() mHasShaderObjects = FALSE; mHasVertexShader = FALSE; mHasFragmentShader = FALSE; + mHasTextureRectangle = FALSE; #else // LL_MESA_HEADLESS mHasMultitexture = glh_init_extensions("GL_ARB_multitexture"); mHasMipMapGeneration = glh_init_extensions("GL_SGIS_generate_mipmap"); @@ -612,6 +656,7 @@ void LLGLManager::initExtensions() && ExtensionExists("GL_EXT_packed_depth_stencil", gGLHExts.mSysExts); mHasFramebufferMultisample = mHasFramebufferObject && ExtensionExists("GL_EXT_framebuffer_multisample", gGLHExts.mSysExts); mHasDrawBuffers = ExtensionExists("GL_ARB_draw_buffers", gGLHExts.mSysExts); + mHasTextureRectangle = ExtensionExists("GL_ARB_texture_rectangle", gGLHExts.mSysExts); #if !LL_DARWIN mHasPointParameters = !mIsATI && ExtensionExists("GL_ARB_point_parameters", gGLHExts.mSysExts); #endif @@ -685,6 +730,7 @@ void LLGLManager::initExtensions() if (strchr(blacklist,'q')) mHasFramebufferObject = FALSE;//S if (strchr(blacklist,'r')) mHasDrawBuffers = FALSE;//S if (strchr(blacklist,'s')) mHasFramebufferMultisample = FALSE; + if (strchr(blacklist,'t')) mHasTextureRectangle = FALSE; } #endif // LL_LINUX || LL_SOLARIS @@ -971,6 +1017,7 @@ void assert_glerror() { return; } + if (!gGLManager.mInited) { LL_ERRS("RenderInit") << "GL not initialized" << LL_ENDL; @@ -988,12 +1035,22 @@ void assert_glerror() { LL_WARNS("RenderState") << "GL Error:" << error<< LL_ENDL; LL_WARNS("RenderState") << "GL Error String:" << gl_error_msg << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error:" << gl_error_msg << std::endl; + } } else { // gluErrorString returns NULL for some extensions' error codes. // you'll probably have to grep for the number in glext.h. LL_WARNS("RenderState") << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "GL Error: UNKNOWN 0x" << std::hex << error << std::dec << std::endl; + } } error = glGetError(); #endif @@ -1001,7 +1058,14 @@ void assert_glerror() if (quit) { - llerrs << "One or more unhandled GL errors." << llendl; + if (gDebugSession) + { + ll_fail("assert_glerror failed"); + } + else + { + llerrs << "One or more unhandled GL errors." << llendl; + } } } @@ -1087,9 +1151,19 @@ void LLGLState::checkStates(const std::string& msg) glGetIntegerv(GL_BLEND_SRC, &src); glGetIntegerv(GL_BLEND_DST, &dst); + BOOL error = FALSE; + if (src != GL_SRC_ALPHA || dst != GL_ONE_MINUS_SRC_ALPHA) { - LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << "Blend function corrupted: " << std::hex << src << " " << std::hex << dst << " " << msg << std::dec << LL_ENDL; + } } for (std::map::iterator iter = sStateMap.begin(); @@ -1101,10 +1175,22 @@ void LLGLState::checkStates(const std::string& msg) if(cur_state != gl_state) { dumpStates(); - LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + if (gDebugSession) + { + gFailLog << llformat("LLGLState error. State: 0x%04x",state) << std::endl; + error = TRUE; + } + else + { + LL_GL_ERRS << llformat("LLGLState error. State: 0x%04x",state) << LL_ENDL; + } } } + if (error) + { + ll_fail("LLGLState::checkStates failed."); + } stop_glerror(); } @@ -1115,9 +1201,12 @@ void LLGLState::checkTextureChannels(const std::string& msg) return; } + stop_glerror(); + GLint activeTexture; glGetIntegerv(GL_ACTIVE_TEXTURE_ARB, &activeTexture); - + stop_glerror(); + BOOL error = FALSE; if (activeTexture == GL_TEXTURE0_ARB) @@ -1125,15 +1214,22 @@ void LLGLState::checkTextureChannels(const std::string& msg) GLint tex_env_mode = 0; glGetTexEnviv(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, &tex_env_mode); + stop_glerror(); + if (tex_env_mode != GL_MODULATE) { error = TRUE; LL_WARNS("RenderState") << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL_TEXTURE_ENV_MODE invalid: " << std::hex << tex_env_mode << std::dec << std::endl; + } } } - GLint maxTextureUnits; + GLint maxTextureUnits = 0; glGetIntegerv(GL_MAX_TEXTURE_UNITS_ARB, &maxTextureUnits); + stop_glerror(); static const char* label[] = { @@ -1169,30 +1265,48 @@ void LLGLState::checkTextureChannels(const std::string& msg) { gGL.getTexUnit(i)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB+i); - + stop_glerror(); glGetIntegerv(GL_TEXTURE_STACK_DEPTH, &stackDepth); + stop_glerror(); if (stackDepth != 1) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix stack corrupted." << LL_ENDL; + + if (gDebugSession) + { + gFailLog << "Texture matrix stack corrupted." << std::endl; + } } glGetFloatv(GL_TEXTURE_MATRIX, (GLfloat*) matrix.mMatrix); + stop_glerror(); if (matrix != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix in channel " << i << " corrupt." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix in channel " << i << " corrupt." << std::endl; + } } - for (S32 j = (i == 0 ? 1 : 0); j < 9; j++) + + for (S32 j = (i == 0 ? 1 : 0); + j < (gGLManager.mHasTextureRectangle ? 9 : 8); j++) { if (glIsEnabled(value[j])) { error = TRUE; LL_WARNS("RenderState") << "Texture channel " << i << " still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture channel " << i << " still has " << label[j] << " enabled." << std::endl; + } } + stop_glerror(); } glh::matrix4f mat; @@ -1200,20 +1314,33 @@ void LLGLState::checkTextureChannels(const std::string& msg) identity.identity(); glGetFloatv(GL_TEXTURE_MATRIX, mat.m); + stop_glerror(); if (mat != identity) { error = TRUE; LL_WARNS("RenderState") << "Texture matrix " << i << " is not identity." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "Texture matrix " << i << " is not identity." << std::endl; + } } } gGL.getTexUnit(0)->activate(); glClientActiveTextureARB(GL_TEXTURE0_ARB); + stop_glerror(); if (error) { - LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + if (gDebugSession) + { + ll_fail("LLGLState::checkTextureChannels failed."); + } + else + { + LL_GL_ERRS << "GL texture state corruption detected. " << msg << LL_ENDL; + } } } @@ -1233,6 +1360,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Client active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Client active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1240,6 +1371,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) if (active_texture != GL_TEXTURE0_ARB) { llwarns << "Active texture corrupted: " << active_texture << llendl; + if (gDebugSession) + { + gFailLog << "Active texture corrupted: " << active_texture << std::endl; + } error = TRUE; } @@ -1276,6 +1411,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has " << label[j] << " enabled." << std::endl; + } } } else @@ -1284,6 +1423,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have " << label[j] << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have " << label[j] << " enabled." << std::endl; + } } } } @@ -1296,6 +1439,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } else @@ -1304,6 +1451,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_COORD_ARRAY enabled on channel 1." << std::endl; + } } } @@ -1313,6 +1464,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } else @@ -1321,6 +1476,10 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL does not have GL_TEXTURE_2D enabled on channel 1." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL does not have GL_TEXTURE_2D enabled on channel 1." << std::endl; + } } } @@ -1339,13 +1498,24 @@ void LLGLState::checkClientArrays(const std::string& msg, U32 data_mask) { error = TRUE; LL_WARNS("RenderState") << "GL still has vertex attrib array " << i << " enabled." << LL_ENDL; + if (gDebugSession) + { + gFailLog << "GL still has vertex attrib array " << i << " enabled." << std::endl; + } } } } if (error) { - LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; + if (gDebugSession) + { + ll_fail("LLGLState::checkClientArrays failed."); + } + else + { + LL_GL_ERRS << "GL client array corruption detected. " << msg << LL_ENDL; + } } } @@ -1396,7 +1566,17 @@ LLGLState::~LLGLState() { if (gDebugGL) { - llassert_always(sStateMap[mState] == glIsEnabled(mState)); + if (!gDebugSession) + { + llassert_always(sStateMap[mState] == glIsEnabled(mState)); + } + else + { + if (sStateMap[mState] != glIsEnabled(mState)) + { + ll_fail("GL enabled state does not match expected"); + } + } } if (mIsEnabled != mWasEnabled) @@ -1708,6 +1888,7 @@ void LLGLNamePool::release(GLuint name) //static void LLGLNamePool::upkeepPools() { + LLMemType mt(LLMemType::MTYPE_UPKEEP_POOLS); for (pool_list_t::iterator iter = sInstances.begin(); iter != sInstances.end(); ++iter) { LLGLNamePool* pool = *iter; diff --git a/indra/llrender/llgl.h b/indra/llrender/llgl.h index 00ff1e2f53..34dd982259 100644 --- a/indra/llrender/llgl.h +++ b/indra/llrender/llgl.h @@ -50,9 +50,17 @@ #include "glh/glh_linear.h" extern BOOL gDebugGL; +extern BOOL gDebugSession; +extern std::ofstream gFailLog; #define LL_GL_ERRS LL_ERRS("RenderState") +void ll_init_fail_log(std::string filename); + +void ll_fail(std::string msg); + +void ll_close_fail_log(); + class LLSD; // Manage GL extensions... @@ -88,6 +96,7 @@ public: BOOL mHasOcclusionQuery; BOOL mHasPointParameters; BOOL mHasDrawBuffers; + BOOL mHasTextureRectangle; // Other extensions. BOOL mHasAnisotropic; diff --git a/indra/llrender/llglslshader.cpp b/indra/llrender/llglslshader.cpp index 9e34144658..830617063b 100644 --- a/indra/llrender/llglslshader.cpp +++ b/indra/llrender/llglslshader.cpp @@ -408,7 +408,15 @@ S32 LLGLSLShader::disableTexture(S32 uniform, LLTexUnit::eTextureType mode) { if (gDebugGL && gGL.getTexUnit(index)->getCurrType() != mode) { - llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + if (gDebugSession) + { + gFailLog << "Texture channel " << index << " texture type corrupted." << std::endl; + ll_fail("LLGLSLShader::disableTexture failed"); + } + else + { + llerrs << "Texture channel " << index << " texture type corrupted." << llendl; + } } gGL.getTexUnit(index)->disable(); } diff --git a/indra/llrender/llimagegl.cpp b/indra/llrender/llimagegl.cpp index cdf626e16f..e1231eeeb4 100644 --- a/indra/llrender/llimagegl.cpp +++ b/indra/llrender/llimagegl.cpp @@ -54,8 +54,8 @@ LLGLuint LLImageGL::sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS] = { 0 }; U32 LLImageGL::sUniqueCount = 0; U32 LLImageGL::sBindCount = 0; -S32 LLImageGL::sGlobalTextureMemory = 0; -S32 LLImageGL::sBoundTextureMemory = 0; +S32 LLImageGL::sGlobalTextureMemoryInBytes = 0; +S32 LLImageGL::sBoundTextureMemoryInBytes = 0; S32 LLImageGL::sCurBoundTextureMemory = 0; S32 LLImageGL::sCount = 0; @@ -63,6 +63,7 @@ BOOL LLImageGL::sGlobalUseAnisotropic = FALSE; F32 LLImageGL::sLastFrameTime = 0.f; std::set LLImageGL::sImageList; + //************************************************************************************** //below are functions for debug use //do not delete them even though they are not currently being used. @@ -87,9 +88,18 @@ void LLImageGL::checkTexSize() const { GLint texname; glGetIntegerv(GL_TEXTURE_BINDING_2D, &texname); + BOOL error = FALSE; if (texname != mTexName) { - llerrs << "Invalid texture bound!" << llendl; + error = TRUE; + if (gDebugSession) + { + gFailLog << "Invalid texture bound!" << std::endl; + } + else + { + llerrs << "Invalid texture bound!" << llendl; + } } stop_glerror() ; LLGLint x = 0, y = 0 ; @@ -102,7 +112,20 @@ void LLImageGL::checkTexSize() const } if(x != (mWidth >> mCurrentDiscardLevel) || y != (mHeight >> mCurrentDiscardLevel)) { - llerrs << "wrong texture size and discard level!" << llendl ; + error = TRUE; + if (gDebugSession) + { + gFailLog << "wrong texture size and discard level!" << std::endl; + } + else + { + llerrs << "wrong texture size and discard level!" << llendl ; + } + } + + if (error) + { + ll_fail("LLImageGL::checkTexSize failed."); } } } @@ -174,7 +197,7 @@ S32 LLImageGL::dataFormatComponents(S32 dataformat) void LLImageGL::updateStats(F32 current_time) { sLastFrameTime = current_time; - sBoundTextureMemory = sCurBoundTextureMemory; + sBoundTextureMemoryInBytes = sCurBoundTextureMemory; sCurBoundTextureMemory = 0; } @@ -453,10 +476,20 @@ void LLImageGL::updateBindStats(void) const sUniqueCount++; updateBoundTexMem(mTextureMemory); mLastBindTime = sLastFrameTime; + + if(LLFastTimer::sMetricLog) + { + updateTestStats() ; + } } } } +//virtual +void LLImageGL::updateTestStats(void) const +{ +} + //virtual bool LLImageGL::bindError(const S32 stage) const { @@ -680,7 +713,6 @@ void LLImageGL::setImage(const U8* data_in, BOOL data_hasmips) } else { -// LLFastTimer t2(LLFastTimer::FTM_TEMP5); S32 w = getWidth(); S32 h = getHeight(); if (is_compressed) @@ -1013,13 +1045,13 @@ BOOL LLImageGL::createGLTexture(S32 discard_level, const U8* data_in, BOOL data_ if (old_name != 0) { - sGlobalTextureMemory -= mTextureMemory; + sGlobalTextureMemoryInBytes -= mTextureMemory; LLImageGL::deleteTextures(1, &old_name); stop_glerror(); } mTextureMemory = getMipBytes(discard_level); - sGlobalTextureMemory += mTextureMemory; + sGlobalTextureMemoryInBytes += mTextureMemory; setActive() ; // mark this as bound at this point, so we don't throw it out immediately @@ -1096,7 +1128,7 @@ BOOL LLImageGL::isValidForSculpt(S32 discard_level, S32 image_width, S32 image_h return glwidth >= image_width && glheight >= image_height && (GL_RGB8 == glcomponents || GL_RGBA8 == glcomponents) ; } -BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) +BOOL LLImageGL::readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const { llpushcallstacks ; if (discard_level < 0) @@ -1220,7 +1252,7 @@ void LLImageGL::destroyGLTexture() } } - sGlobalTextureMemory -= mTextureMemory; + sGlobalTextureMemoryInBytes -= mTextureMemory; mTextureMemory = 0; LLImageGL::deleteTextures(1, &mTexName); @@ -1377,7 +1409,6 @@ void LLImageGL::analyzeAlpha(const void* data_in, S32 w, S32 h) stride = 4; break; default: - llwarns << "Cannot analyze alpha of image with primary format " << std::hex << mFormatPrimary << std::dec << llendl; return; } diff --git a/indra/llrender/llimagegl.h b/indra/llrender/llimagegl.h index 4f737bcaae..1775ae7de9 100644 --- a/indra/llrender/llimagegl.h +++ b/indra/llrender/llimagegl.h @@ -37,11 +37,15 @@ #include "llimage.h" #include "llgltypes.h" -#include "llmemory.h" +#include "llpointer.h" +#include "llrefcount.h" #include "v2math.h" #include "llrender.h" +#define BYTES_TO_MEGA_BYTES(x) ((x) >> 20) +#define MEGA_BYTES_TO_BYTES(x) ((x) << 20) + //============================================================================ class LLImageGL : public LLRefCount @@ -54,6 +58,7 @@ public: static S32 dataFormatComponents(S32 dataformat); void updateBindStats(void) const; + virtual void updateTestStats(void) const; // needs to be called every frame static void updateStats(F32 current_time); @@ -107,7 +112,7 @@ public: BOOL setSubImageFromFrameBuffer(S32 fb_x, S32 fb_y, S32 x_pos, S32 y_pos, S32 width, S32 height); BOOL setDiscardLevel(S32 discard_level); // Read back a raw image for this discard level, if it exists - BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok); + BOOL readBackRaw(S32 discard_level, LLImageRaw* imageraw, bool compressed_ok) const; void destroyGLTexture(); void setExplicitFormat(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format = 0, BOOL swap_bytes = FALSE); @@ -238,12 +243,13 @@ public: static LLGLuint sCurrentBoundTextures[MAX_GL_TEXTURE_UNITS]; // Currently bound texture ID // Global memory statistics - static S32 sGlobalTextureMemory; // Tracks main memory texmem - static S32 sBoundTextureMemory; // Tracks bound texmem for last completed frame + static S32 sGlobalTextureMemoryInBytes; // Tracks main memory texmem + static S32 sBoundTextureMemoryInBytes; // Tracks bound texmem for last completed frame static S32 sCurBoundTextureMemory; // Tracks bound texmem for current frame static U32 sBindCount; // Tracks number of texture binds for current frame static U32 sUniqueCount; // Tracks number of unique texture binds for current frame static BOOL sGlobalUseAnisotropic; + #if DEBUG_MISS BOOL mMissed; // Missed on last bind? BOOL getMissed() const { return mMissed; }; diff --git a/indra/llrender/llrender.cpp b/indra/llrender/llrender.cpp index 6bb217a9c2..d3a230b37b 100644 --- a/indra/llrender/llrender.cpp +++ b/indra/llrender/llrender.cpp @@ -189,7 +189,7 @@ bool LLTexUnit::bind(LLImageGL* texture, bool forceBind) llwarns << "NULL LLTexUnit::bind texture" << llendl; return false; } - + if (!texture->getTexName()) //if texture does not exist { //if deleted, will re-generate it immediately @@ -785,6 +785,9 @@ void LLRender::setSceneBlendType(eBlendType type) case BT_MULT: glBlendFunc(GL_DST_COLOR, GL_ZERO); break; + case BT_MULT_ALPHA: + glBlendFunc(GL_DST_ALPHA, GL_ZERO); + break; case BT_MULT_X2: glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); break; diff --git a/indra/llrender/llrender.h b/indra/llrender/llrender.h index 437c715c2f..31083d8286 100644 --- a/indra/llrender/llrender.h +++ b/indra/llrender/llrender.h @@ -44,7 +44,7 @@ #include "v3math.h" #include "v4coloru.h" #include "llstrider.h" -#include "llmemory.h" +#include "llpointer.h" #include "llglheaders.h" class LLVertexBuffer; @@ -252,6 +252,7 @@ public: BT_ADD, BT_ADD_WITH_ALPHA, // Additive blend modulated by the fragment's alpha. BT_MULT, + BT_MULT_ALPHA, BT_MULT_X2, BT_REPLACE } eBlendType; diff --git a/indra/llrender/llrendertarget.cpp b/indra/llrender/llrendertarget.cpp index b7f31779ca..dc052851ca 100644 --- a/indra/llrender/llrendertarget.cpp +++ b/indra/llrender/llrendertarget.cpp @@ -36,6 +36,9 @@ #include "llrender.h" #include "llgl.h" +LLRenderTarget* LLRenderTarget::sBoundTarget = NULL; + + void check_framebuffer_status() { @@ -46,11 +49,9 @@ void check_framebuffer_status() { case GL_FRAMEBUFFER_COMPLETE_EXT: break; - case GL_FRAMEBUFFER_UNSUPPORTED_EXT: - llerrs << "WTF?" << llendl; - break; default: - llerrs << "WTF?" << llendl; + ll_fail("check_framebuffer_status failed"); + break; } } } @@ -273,6 +274,7 @@ void LLRenderTarget::release() } mSampleBuffer = NULL; + sBoundTarget = NULL; } void LLRenderTarget::bindTarget() @@ -311,6 +313,7 @@ void LLRenderTarget::bindTarget() } glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } // static @@ -320,6 +323,7 @@ void LLRenderTarget::unbindTarget() { glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0); } + sBoundTarget = NULL; } void LLRenderTarget::clear(U32 mask_in) @@ -532,6 +536,7 @@ void LLMultisampleBuffer::bindTarget(LLRenderTarget* ref) glViewport(0, 0, mResX, mResY); + sBoundTarget = this; } void LLMultisampleBuffer::allocate(U32 resx, U32 resy, U32 color_fmt, BOOL depth, BOOL stencil, LLTexUnit::eTextureType usage, BOOL use_fbo ) diff --git a/indra/llrender/llrendertarget.h b/indra/llrender/llrendertarget.h index d5d809b791..98b608f834 100644 --- a/indra/llrender/llrendertarget.h +++ b/indra/llrender/llrendertarget.h @@ -140,6 +140,8 @@ public: //one renderable attachment (i.e. color buffer, depth buffer). BOOL isComplete() const; + static LLRenderTarget* getCurrentBoundTarget() { return sBoundTarget; } + protected: friend class LLMultisampleBuffer; U32 mResX; @@ -153,6 +155,8 @@ protected: LLTexUnit::eTextureType mUsage; U32 mSamples; LLMultisampleBuffer* mSampleBuffer; + + static LLRenderTarget* sBoundTarget; }; diff --git a/indra/llrender/llvertexbuffer.cpp b/indra/llrender/llvertexbuffer.cpp index 5d88ea464d..db4189dfea 100644 --- a/indra/llrender/llvertexbuffer.cpp +++ b/indra/llrender/llvertexbuffer.cpp @@ -37,7 +37,6 @@ #include "llvertexbuffer.h" // #include "llrender.h" #include "llglheaders.h" -#include "llmemory.h" #include "llmemtype.h" #include "llrender.h" @@ -117,6 +116,7 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) GL_COLOR_ARRAY, }; + BOOL error = FALSE; for (U32 i = 0; i < 4; ++i) { if (sLastMask & mask[i]) @@ -129,7 +129,15 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) { //needs to be enabled, make sure it was (DEBUG TEMPORARY) if (i > 0 && !glIsEnabled(array[i])) { - llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " disabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " disabled." << llendl; + } } } } @@ -141,11 +149,24 @@ void LLVertexBuffer::setupClientArrays(U32 data_mask) } else if (gDebugGL && glIsEnabled(array[i])) { //needs to be disabled, make sure it was (DEBUG TEMPORARY) - llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Bad client state! " << array[i] << " enabled." << std::endl; + } + else + { + llerrs << "Bad client state! " << array[i] << " enabled." << llendl; + } } } } + if (error) + { + ll_fail("LLVertexBuffer::setupClientArrays failed"); + } + U32 map_tc[] = { MAP_TEXCOORD1, @@ -315,7 +336,7 @@ void LLVertexBuffer::unbind() //static void LLVertexBuffer::cleanupClass() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_CLEANUP_CLASS); unbind(); clientCopy(); // deletes GL buffers } @@ -342,7 +363,7 @@ LLVertexBuffer::LLVertexBuffer(U32 typemask, S32 usage) : mResized(FALSE), mDynamicSize(FALSE) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_CONSTRUCTOR); if (!sEnableVBOs) { mUsage = 0 ; @@ -379,7 +400,7 @@ S32 LLVertexBuffer::calcStride(const U32& typemask, S32* offsets) //virtual LLVertexBuffer::~LLVertexBuffer() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTRUCTOR); destroyGLBuffer(); destroyGLIndices(); sCount--; @@ -459,8 +480,8 @@ void LLVertexBuffer::releaseIndices() void LLVertexBuffer::createGLBuffer() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); - + LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_VERTICES); + U32 size = getSize(); if (mGLBuffer) { @@ -491,7 +512,7 @@ void LLVertexBuffer::createGLBuffer() void LLVertexBuffer::createGLIndices() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_CREATE_INDICES); U32 size = getIndicesSize(); if (mGLIndices) @@ -523,7 +544,7 @@ void LLVertexBuffer::createGLIndices() void LLVertexBuffer::destroyGLBuffer() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_BUFFER); if (mGLBuffer) { if (useVBOs()) @@ -550,7 +571,7 @@ void LLVertexBuffer::destroyGLBuffer() void LLVertexBuffer::destroyGLIndices() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_DESTROY_INDICES); if (mGLIndices) { if (useVBOs()) @@ -577,7 +598,7 @@ void LLVertexBuffer::destroyGLIndices() void LLVertexBuffer::updateNumVerts(S32 nverts) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_VERTS); if (nverts >= 65535) { @@ -606,7 +627,7 @@ void LLVertexBuffer::updateNumVerts(S32 nverts) void LLVertexBuffer::updateNumIndices(S32 nindices) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_UPDATE_INDICES); mRequestedNumIndices = nindices; if (!mDynamicSize) { @@ -627,7 +648,7 @@ void LLVertexBuffer::updateNumIndices(S32 nindices) void LLVertexBuffer::allocateBuffer(S32 nverts, S32 nindices, bool create) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_ALLOCATE_BUFFER); updateNumVerts(nverts); updateNumIndices(nindices); @@ -650,7 +671,7 @@ void LLVertexBuffer::resizeBuffer(S32 newnverts, S32 newnindices) mRequestedNumVerts = newnverts; mRequestedNumIndices = newnindices; - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_RESIZE_BUFFER); mDynamicSize = TRUE; if (mUsage == GL_STATIC_DRAW_ARB) { //always delete/allocate static buffers on resize @@ -779,7 +800,7 @@ BOOL LLVertexBuffer::useVBOs() const // Map for data access U8* LLVertexBuffer::mapBuffer(S32 access) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_MAP_BUFFER); if (mFinal) { llerrs << "LLVertexBuffer::mapBuffer() called on a finalized buffer." << llendl; @@ -791,13 +812,19 @@ U8* LLVertexBuffer::mapBuffer(S32 access) if (!mLocked && useVBOs()) { - setBuffer(0); - mLocked = TRUE; - stop_glerror(); - mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - stop_glerror(); - mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); - stop_glerror(); + { + LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_VERTICES); + setBuffer(0); + mLocked = TRUE; + stop_glerror(); + mMappedData = (U8*) glMapBufferARB(GL_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + stop_glerror(); + } + { + LLMemType mt_v(LLMemType::MTYPE_VERTEX_MAP_BUFFER_INDICES); + mMappedIndexData = (U8*) glMapBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, GL_WRITE_ONLY_ARB); + stop_glerror(); + } if (!mMappedData) { @@ -840,7 +867,7 @@ U8* LLVertexBuffer::mapBuffer(S32 access) void LLVertexBuffer::unmapBuffer() { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_UNMAP_BUFFER); if (mMappedData || mMappedIndexData) { if (useVBOs() && mLocked) @@ -962,7 +989,7 @@ bool LLVertexBuffer::getClothWeightStrider(LLStrider& strider, S32 in void LLVertexBuffer::setStride(S32 type, S32 new_stride) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_STRIDE); if (mNumVerts) { llerrs << "LLVertexBuffer::setOffset called with mNumVerts = " << mNumVerts << llendl; @@ -984,7 +1011,7 @@ void LLVertexBuffer::setStride(S32 type, S32 new_stride) // Set for rendering void LLVertexBuffer::setBuffer(U32 data_mask) { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_SET_BUFFER); //set up pointers if the data mask is different ... BOOL setup = (sLastMask != data_mask); @@ -1016,19 +1043,36 @@ void LLVertexBuffer::setBuffer(U32 data_mask) sIBOActive = TRUE; } + BOOL error = FALSE; if (gDebugGL) { GLint buff; glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: " << buff << std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } @@ -1040,13 +1084,29 @@ void LLVertexBuffer::setBuffer(U32 data_mask) glGetIntegerv(GL_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLBuffer) { - llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL vertex buffer bound: " << std::endl; + } + else + { + llerrs << "Invalid GL vertex buffer bound: " << buff << llendl; + } } glGetIntegerv(GL_ELEMENT_ARRAY_BUFFER_BINDING_ARB, &buff); if ((GLuint)buff != mGLIndices) { - llerrs << "Invalid GL index buffer bound: " << buff << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Invalid GL index buffer bound: "<< std::endl; + } + else + { + llerrs << "Invalid GL index buffer bound: " << buff << llendl; + } } } @@ -1068,10 +1128,22 @@ void LLVertexBuffer::setBuffer(U32 data_mask) if (data_mask != 0) { - llerrs << "Buffer set for rendering before being filled after resize." << llendl; + if (gDebugSession) + { + error = TRUE; + gFailLog << "Buffer set for rendering before being filled after resize." << std::endl; + } + else + { + llerrs << "Buffer set for rendering before being filled after resize." << llendl; + } } } + if (error) + { + ll_fail("LLVertexBuffer::mapBuffer failed"); + } unmapBuffer(); } else @@ -1122,7 +1194,7 @@ void LLVertexBuffer::setBuffer(U32 data_mask) // virtual (default) void LLVertexBuffer::setupVertexBuffer(U32 data_mask) const { - LLMemType mt(LLMemType::MTYPE_VERTEX_DATA); + LLMemType mt2(LLMemType::MTYPE_VERTEX_SETUP_VERTEX_BUFFER); stop_glerror(); U8* base = useVBOs() ? NULL : mMappedData; S32 stride = mStride; diff --git a/indra/llrender/llvertexbuffer.h b/indra/llrender/llvertexbuffer.h index aad948e17f..b785a22976 100644 --- a/indra/llrender/llvertexbuffer.h +++ b/indra/llrender/llvertexbuffer.h @@ -39,7 +39,6 @@ #include "v4math.h" #include "v4coloru.h" #include "llstrider.h" -#include "llmemory.h" #include "llrender.h" #include #include diff --git a/indra/llui/CMakeLists.txt b/indra/llui/CMakeLists.txt index 5de8dc76af..117e8e28ab 100644 --- a/indra/llui/CMakeLists.txt +++ b/indra/llui/CMakeLists.txt @@ -31,17 +31,25 @@ set(llui_SOURCE_FILES llcheckboxctrl.cpp llclipboard.cpp llcombobox.cpp + llconsole.cpp + llcontainerview.cpp llctrlselectioninterface.cpp lldraghandle.cpp lleditmenuhandler.cpp + llf32uictrl.cpp llfloater.cpp + llfloaterreg.cpp + llflyoutbutton.cpp llfocusmgr.cpp llfunctorregistry.cpp lliconctrl.cpp + llinitparam.cpp llkeywords.cpp + lllayoutstack.cpp lllineeditor.cpp llmenugl.cpp llmodaldialog.cpp + llmultifloater.cpp llmultislider.cpp llmultisliderctrl.cpp llnotifications.cpp @@ -51,27 +59,36 @@ set(llui_SOURCE_FILES llresizebar.cpp llresizehandle.cpp llresmgr.cpp - llrootview.cpp llscrollbar.cpp llscrollcontainer.cpp llscrollingpanellist.cpp + llscrolllistcell.cpp + llscrolllistcolumn.cpp llscrolllistctrl.cpp + llscrolllistitem.cpp + llsdparam.cpp + llsearcheditor.cpp llslider.cpp llsliderctrl.cpp llspinctrl.cpp + llstatbar.cpp + llstatgraph.cpp + llstatview.cpp llstyle.cpp lltabcontainer.cpp - lltabcontainervertical.cpp lltextbox.cpp lltexteditor.cpp lltextparser.cpp + lltrans.cpp llui.cpp + lluicolortable.cpp lluictrl.cpp lluictrlfactory.cpp + lluiimage.cpp lluistring.cpp - lluitrans.cpp llundo.cpp llviewborder.cpp + llviewmodel.cpp llview.cpp llviewquery.cpp ) @@ -85,52 +102,69 @@ set(llui_HEADER_FILES llcheckboxctrl.h llclipboard.h llcombobox.h + llconsole.h + llcontainerview.h llctrlselectioninterface.h lldraghandle.h lleditmenuhandler.h + llf32uictrl.h llfloater.h + llfloaterreg.h + llflyoutbutton.h llfocusmgr.h llfunctorregistry.h llhtmlhelp.h lliconctrl.h + llinitparam.h llkeywords.h + lllayoutstack.h + lllazyvalue.h lllineeditor.h - llmemberlistener.h llmenugl.h llmodaldialog.h + llmultifloater.h llmultisliderctrl.h llmultislider.h llnotifications.h llpanel.h llprogressbar.h llradiogroup.h + llregistry.h llresizebar.h llresizehandle.h llresmgr.h - llrootview.h + llsearcheditor.h llscrollbar.h llscrollcontainer.h llscrollingpanellist.h + llscrolllistcell.h + llscrolllistcolumn.h llscrolllistctrl.h + llscrolllistitem.h + llsdparam.h llsliderctrl.h llslider.h llspinctrl.h + llstatbar.h + llstatgraph.h + llstatview.h llstyle.h lltabcontainer.h - lltabcontainervertical.h lltextbox.h lltexteditor.h lltextparser.h + lltrans.h + lluicolortable.h lluiconstants.h lluictrlfactory.h lluictrl.h lluifwd.h llui.h + lluiimage.h lluistring.h - lluitrans.h - lluixmltags.h llundo.h llviewborder.h + llviewmodel.h llview.h llviewquery.h ) diff --git a/indra/llui/llbutton.cpp b/indra/llui/llbutton.cpp index 2c2c1c25d8..110ad82763 100644 --- a/indra/llui/llbutton.cpp +++ b/indra/llui/llbutton.cpp @@ -32,6 +32,7 @@ #include "linden_common.h" +#define INSTANTIATE_GETCHILD_BUTTON #include "llbutton.h" // Linden library includes @@ -45,183 +46,171 @@ #include "lluiconstants.h" #include "llresmgr.h" #include "llcriticaldamp.h" +#include "llfloater.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llwindow.h" #include "llrender.h" +#include "lluictrlfactory.h" -static LLRegisterWidget r("button"); +static LLDefaultWidgetRegistry::Register r("button"); // globals loaded from settings.xml -S32 LLBUTTON_ORIG_H_PAD = 6; // Pre-zoomable UI S32 LLBUTTON_H_PAD = 0; S32 LLBUTTON_V_PAD = 0; S32 BTN_HEIGHT_SMALL= 0; S32 BTN_HEIGHT = 0; -S32 BTN_GRID = 12; -S32 BORDER_SIZE = 1; - -LLButton::LLButton( const std::string& name, const LLRect& rect, const std::string& control_name, void (*click_callback)(void*), void *callback_data) -: LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), - mMouseDownFrame( 0 ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), - mBorderEnabled( FALSE ), - mFlashing( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mHoverGlowStrength(0.15f), - mCurGlowStrength(0.f), - mNeedsHighlight(FALSE), - mCommitOnReturn(TRUE), - mImagep( NULL ) +template LLButton* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; + +LLButton::Params::Params() +: label_selected("label_selected"), // requires is_toggle true + label_dropshadow("label_shadow", true), + auto_resize("auto_resize", false), + image_unselected("image_unselected"), + image_selected("image_selected"), + image_hover_selected("image_hover_selected"), + image_hover_unselected("image_hover_unselected"), + image_disabled_selected("image_disabled_selected"), + image_disabled("image_disabled"), + image_overlay("image_overlay"), + image_overlay_alignment("image_overlay_alignment", std::string("center")), + label_color("label_color"), + label_color_selected("label_color_selected"), // requires is_toggle true + label_color_disabled("label_color_disabled"), + label_color_disabled_selected("label_color_disabled_selected"), + highlight_color("highlight_color"), + image_color("image_color"), + image_color_disabled("image_color_disabled"), + image_overlay_color("image_overlay_color", LLColor4::white), + flash_color("flash_color"), + pad_right("pad_right", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), + pad_left("pad_left", LLUI::sSettingGroups["config"]->getS32("ButtonHPad")), + click_callback("click_callback"), + mouse_down_callback("mouse_down_callback"), + mouse_up_callback("mouse_up_callback"), + mouse_held_callback("mouse_held_callback"), + is_toggle("is_toggle", false), + scale_image("scale_image", true), + help_url("help_url"), + hover_glow_amount("hover_glow_amount"), + commit_on_return("commit_on_return", true), + picture_style("picture_style", false) { - mUnselectedLabel = name; - mSelectedLabel = name; - - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); - - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - - init(click_callback, callback_data, NULL, control_name); -} - - -LLButton::LLButton(const std::string& name, const LLRect& rect, - const std::string &unselected_image_name, - const std::string &selected_image_name, - const std::string& control_name, - void (*click_callback)(void*), - void *callback_data, - const LLFontGL *font, - const std::string& unselected_label, - const std::string& selected_label ) -: LLUICtrl(name, rect, TRUE, NULL, NULL), - mClickedCallback( click_callback ), - mMouseDownCallback( NULL ), - mMouseUpCallback( NULL ), - mHeldDownCallback( NULL ), - mGLFont( NULL ), - mMouseDownFrame( 0 ), - mHeldDownDelay( 0.5f ), // seconds until held-down callback is called - mHeldDownFrameDelay( 0 ), - mImageUnselected( NULL ), - mImageSelected( NULL ), - mImageHoverSelected( NULL ), - mImageHoverUnselected( NULL ), - mImageDisabled( NULL ), - mImageDisabledSelected( NULL ), - mToggleState( FALSE ), - mIsToggle( FALSE ), - mScaleImage( TRUE ), - mDropShadowedText( TRUE ), + addSynonym(is_toggle, "toggle"); + held_down_delay.seconds = 0.5f; + initial_value.set(LLSD(false), false); +} + + +LLButton::LLButton(const LLButton::Params& p) +: LLUICtrl(p), + mMouseDownFrame(0), + mMouseHeldDownCount(0), mBorderEnabled( FALSE ), mFlashing( FALSE ), - mHAlign( LLFontGL::HCENTER ), - mLeftHPad( LLBUTTON_H_PAD ), - mRightHPad( LLBUTTON_H_PAD ), - mHoverGlowStrength(0.25f), mCurGlowStrength(0.f), mNeedsHighlight(FALSE), - mCommitOnReturn(TRUE), - mImagep( NULL ) + mImagep( NULL ), + mUnselectedLabel(p.label()), + mSelectedLabel(p.label_selected()), + mGLFont(p.font), + mHeldDownDelay(p.held_down_delay.seconds), // seconds until held-down callback is called + mHeldDownFrameDelay(p.held_down_delay.frames), + mImageUnselected(p.image_unselected), + mImageSelected(p.image_selected), + mImageDisabled(p.image_disabled), + mImageDisabledSelected(p.image_disabled_selected), + mImageHoverSelected(p.image_hover_selected), + mImageHoverUnselected(p.image_hover_unselected), + mUnselectedLabelColor(p.label_color()), + mSelectedLabelColor(p.label_color_selected()), + mDisabledLabelColor(p.label_color_disabled()), + mDisabledSelectedLabelColor(p.label_color_disabled_selected()), + mHighlightColor(p.highlight_color()), + mImageColor(p.image_color()), + mFlashBgColor(p.flash_color()), + mDisabledImageColor(p.image_color_disabled()), + mImageOverlay(p.image_overlay()), + mImageOverlayColor(p.image_overlay_color()), + mImageOverlayAlignment(LLFontGL::hAlignFromName(p.image_overlay_alignment)), + mIsToggle(p.is_toggle), + mScaleImage(p.scale_image), + mDropShadowedText(p.label_dropshadow), + mAutoResize(p.auto_resize), + mHAlign(p.font_halign), + mLeftHPad(p.pad_left), + mRightHPad(p.pad_right), + mHoverGlowStrength(p.hover_glow_amount), + mCommitOnReturn(p.commit_on_return), + mFadeWhenDisabled(FALSE) { - mUnselectedLabel = unselected_label; - mSelectedLabel = selected_label; - - // by default, disabled color is same as enabled - mImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - mDisabledImageColor = LLUI::sColorsGroup->getColor( "ButtonImageColor" ); - - if( unselected_image_name != "" ) - { - // user-specified image - don't use fixed borders unless requested - setImageUnselected(unselected_image_name); - setImageDisabled(unselected_image_name); - - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else - { - setImageUnselected(std::string("button_enabled_32x128.tga")); - setImageDisabled(std::string("button_disabled_32x128.tga")); - } + static LLUICachedControl llbutton_orig_h_pad ("UIButtonOrigHPad", 0); + static LLButton::Params default_params(LLUICtrlFactory::getDefaultParams()); - if( selected_image_name != "" ) + //if we aren't a picture_style button set label as name if not provided + if (!p.picture_style.isProvided() || !p.picture_style) { - // user-specified image - don't use fixed borders unless requested - setImageSelected(selected_image_name); - setImageDisabledSelected(selected_image_name); - - mDisabledImageColor.mV[VALPHA] = 0.5f; - mScaleImage = FALSE; - } - else - { - setImageSelected(std::string("button_enabled_selected_32x128.tga")); - setImageDisabledSelected(std::string("button_disabled_32x128.tga")); + if (!p.label.isProvided()) + { + mUnselectedLabel = p.name(); + } + if (!p.label_selected.isProvided()) + { + mSelectedLabel = mUnselectedLabel.getString(); + } } - init(click_callback, callback_data, font, control_name); -} - -void LLButton::init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name) -{ - mGLFont = ( font ? font : LLFontGL::getFontSansSerif()); - // Hack to make sure there is space for at least one character if (getRect().getWidth() - (mRightHPad + mLeftHPad) < mGLFont->getWidth(std::string(" "))) { // Use old defaults - mLeftHPad = LLBUTTON_ORIG_H_PAD; - mRightHPad = LLBUTTON_ORIG_H_PAD; + mLeftHPad = llbutton_orig_h_pad; + mRightHPad = llbutton_orig_h_pad; } - mCallbackUserData = callback_data; mMouseDownTimer.stop(); - setControlName(control_name, NULL); - - mUnselectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelColor" ) ); - mSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedColor" ) ); - mDisabledLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelDisabledColor" ) ); - mDisabledSelectedLabelColor = ( LLUI::sColorsGroup->getColor( "ButtonLabelSelectedDisabledColor" ) ); - mHighlightColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedFgColor" ) ); - mUnselectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonUnselectedBgColor" ) ); - mSelectedBgColor = ( LLUI::sColorsGroup->getColor( "ButtonSelectedBgColor" ) ); - mFlashBgColor = ( LLUI::sColorsGroup->getColor( "ButtonFlashBgColor" ) ); + if (p.help_url.isProvided()) + { + setHelpURLCallback(p.help_url); + } - mImageOverlayAlignment = LLFontGL::HCENTER; - mImageOverlayColor = LLColor4::white; -} + // if custom unselected button image provided... + if (p.image_unselected != default_params.image_unselected) + { + //...fade it out for disabled image by default... + if (p.image_disabled() == default_params.image_disabled() ) + { + mImageDisabled = p.image_unselected; + mFadeWhenDisabled = TRUE; + } + } -LLButton::~LLButton() -{ - if( hasMouseCapture() ) + // if custom selected button image provided... + if (p.image_selected != default_params.image_selected) { - gFocusMgr.setMouseCapture( NULL ); + //...fade it out for disabled image by default... + if (p.image_disabled_selected() == default_params.image_disabled_selected()) + { + mImageDisabledSelected = p.image_selected; + mFadeWhenDisabled = TRUE; + } + } + + if (mImageUnselected.isNull()) + { + llwarns << "Button: " << getName() << " with no image!" << llendl; } + + if (p.click_callback.isProvided()) + initCommitCallback(p.click_callback, mCommitSignal); // alias -> commit_callback + if (p.mouse_down_callback.isProvided()) + initCommitCallback(p.mouse_down_callback, mMouseDownSignal); + if (p.mouse_up_callback.isProvided()) + initCommitCallback(p.mouse_up_callback, mMouseUpSignal); + if (p.mouse_held_callback.isProvided()) + initCommitCallback(p.mouse_held_callback, mHeldDownSignal); } // HACK: Committing a button is the same as instantly clicking it. @@ -229,19 +218,12 @@ LLButton::~LLButton() void LLButton::onCommit() { // WARNING: Sometimes clicking a button destroys the floater or - // panel containing it. Therefore we need to call mClickedCallback + // panel containing it. Therefore we need to call LLUICtrl::onCommit() // LAST, otherwise this becomes deleted memory. - LLUICtrl::onCommit(); - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + mMouseDownSignal(this, LLSD()); - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + mMouseUpSignal(this, LLSD()); if (getSoundFlags() & MOUSE_DOWN) { @@ -259,14 +241,55 @@ void LLButton::onCommit() } // do this last, as it can result in destroying this button - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); +} + +boost::signals::connection LLButton::setClickedCallback( const commit_signal_t::slot_type& cb ) +{ + return mCommitSignal.connect(cb); +} +boost::signals::connection LLButton::setMouseDownCallback( const commit_signal_t::slot_type& cb ) +{ + return mMouseDownSignal.connect(cb); +} +boost::signals::connection LLButton::setMouseUpCallback( const commit_signal_t::slot_type& cb ) +{ + return mMouseUpSignal.connect(cb); +} +boost::signals::connection LLButton::setHeldDownCallback( const commit_signal_t::slot_type& cb ) +{ + return mHeldDownSignal.connect(cb); +} + +boost::signals::connection LLButton::setRightClickedCallback( const commit_signal_t::slot_type& cb ) +{ + return mRightClickSignal.connect(cb); } +// *TODO: Deprecate (for backwards compatability only) +boost::signals::connection LLButton::setClickedCallback( button_callback_t cb, void* data ) +{ + return setClickedCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setMouseDownCallback( button_callback_t cb, void* data ) +{ + return setMouseDownCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setMouseUpCallback( button_callback_t cb, void* data ) +{ + return setMouseUpCallback(boost::bind(cb, data)); +} +boost::signals::connection LLButton::setHeldDownCallback( button_callback_t cb, void* data ) +{ + return setHeldDownCallback(boost::bind(cb, data)); +} +BOOL LLButton::postBuild() +{ + autoResize(); + return TRUE; +} BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) { BOOL handled = FALSE; @@ -278,10 +301,8 @@ BOOL LLButton::handleUnicodeCharHere(llwchar uni_char) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); + handled = TRUE; } return handled; @@ -299,10 +320,7 @@ BOOL LLButton::handleKeyHere(KEY key, MASK mask ) handled = TRUE; - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } return handled; } @@ -318,13 +336,11 @@ BOOL LLButton::handleMouseDown(S32 x, S32 y, MASK mask) setFocus(TRUE); } - if (mMouseDownCallback) - { - (*mMouseDownCallback)(mCallbackUserData); - } + mMouseDownSignal(this, LLSD()); mMouseDownTimer.start(); mMouseDownFrame = (S32) LLFrameTimer::getFrameCount(); + mMouseHeldDownCount = 0; if (getSoundFlags() & MOUSE_DOWN) { @@ -344,13 +360,9 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) gFocusMgr.setMouseCapture( NULL ); // Regardless of where mouseup occurs, handle callback - if (mMouseUpCallback) - { - (*mMouseUpCallback)(mCallbackUserData); - } + mMouseUpSignal(this, LLSD()); - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + resetMouseDownTimer(); // DO THIS AT THE VERY END to allow the button to be destroyed as a result of being clicked. // If mouseup in the widget, it's been clicked @@ -366,31 +378,65 @@ BOOL LLButton::handleMouseUp(S32 x, S32 y, MASK mask) toggleState(); } - if (mClickedCallback) - { - (*mClickedCallback)( mCallbackUserData ); - } + LLUICtrl::onCommit(); } } return TRUE; } +BOOL LLButton::handleRightMouseDown(S32 x, S32 y, MASK mask) +{ + // Route future Mouse messages here preemptively. (Release on mouse up.) + gFocusMgr.setMouseCapture( this ); -BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) + if (hasTabStop() && !getIsChrome()) + { + setFocus(TRUE); + } + + + return TRUE; +} + +BOOL LLButton::handleRightMouseUp(S32 x, S32 y, MASK mask) { - LLMouseHandler* other_captor = gFocusMgr.getMouseCapture(); - mNeedsHighlight = other_captor == NULL || - other_captor == this || - // this following bit is to support modal dialogs - (other_captor->isView() && hasAncestor((LLView*)other_captor)); + // We only handle the click if the click both started and ended within us + if( hasMouseCapture() ) + { + // Always release the mouse + gFocusMgr.setMouseCapture( NULL ); - if (mMouseDownTimer.getStarted() && NULL != mHeldDownCallback) + if (pointInView(x, y)) + { + mRightClickSignal(this, getValue()); + } + } + return TRUE; +} + + +void LLButton::onMouseEnter(S32 x, S32 y, MASK mask) +{ + if (getEnabled()) + mNeedsHighlight = TRUE; +} + +void LLButton::onMouseLeave(S32 x, S32 y, MASK mask) +{ + mNeedsHighlight = FALSE; +} + +BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) +{ + if (mMouseDownTimer.getStarted()) { F32 elapsed = getHeldDownTime(); if( mHeldDownDelay <= elapsed && mHeldDownFrameDelay <= (S32)LLFrameTimer::getFrameCount() - mMouseDownFrame) { - mHeldDownCallback( mCallbackUserData ); + LLSD param; + param["count"] = mMouseHeldDownCount++; + mHeldDownSignal(this, param); } } @@ -406,12 +452,15 @@ BOOL LLButton::handleHover(S32 x, S32 y, MASK mask) void LLButton::draw() { BOOL flash = FALSE; + static LLUICachedControl button_flash_rate("ButtonFlashRate", 0); + static LLUICachedControl button_flash_count("ButtonFlashCount", 0); + if( mFlashing ) { F32 elapsed = mFlashingTimer.getElapsedTimeF32(); - S32 flash_count = S32(elapsed * LLUI::sConfigGroup->getF32("ButtonFlashRate") * 2.f); + S32 flash_count = S32(elapsed * button_flash_rate * 2.f); // flash on or off? - flash = (flash_count % 2 == 0) || flash_count > S32((F32)LLUI::sConfigGroup->getS32("ButtonFlashCount") * 2.f); + flash = (flash_count % 2 == 0) || flash_count > S32((F32)button_flash_count * 2.f); } BOOL pressed_by_keyboard = FALSE; @@ -427,7 +476,7 @@ void LLButton::draw() BOOL pressed = pressed_by_keyboard || (hasMouseCapture() && pointInView(local_mouse_x, local_mouse_y)) - || mToggleState; + || getToggleState(); BOOL use_glow_effect = FALSE; LLColor4 glow_color = LLColor4::white; @@ -470,12 +519,14 @@ void LLButton::draw() if (mFlashing) { + LLColor4 flash_color = mFlashBgColor.get(); use_glow_effect = TRUE; glow_type = LLRender::BT_ALPHA; // blend the glow + if (mNeedsHighlight) // highlighted AND flashing - glow_color = (glow_color*0.5f + mFlashBgColor*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity + glow_color = (glow_color*0.5f + flash_color*0.5f) % 2.0f; // average between flash and highlight colour, with sum of the opacity else - glow_color = mFlashBgColor; + glow_color = flash_color; } // Override if more data is available @@ -508,31 +559,31 @@ void LLButton::draw() // label changes when button state changes, not when pressed if ( getEnabled() ) { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mSelectedLabelColor; + label_color = mSelectedLabelColor.get(); } else { - label_color = mUnselectedLabelColor; + label_color = mUnselectedLabelColor.get(); } } else { - if ( mToggleState ) + if ( getToggleState() ) { - label_color = mDisabledSelectedLabelColor; + label_color = mDisabledSelectedLabelColor.get(); } else { - label_color = mDisabledLabelColor; + label_color = mDisabledLabelColor.get(); } } // Unselected label assignments LLWString label; - if( mToggleState ) + if( getToggleState() ) { if( getEnabled() || mDisabledSelectedLabel.empty() ) { @@ -578,9 +629,11 @@ void LLButton::draw() // Otherwise draw basic rectangular button. if (mImagep.notNull()) { + // apply automatic 50% alpha fade to disabled image + LLColor4 disabled_color = mFadeWhenDisabled ? mDisabledImageColor.get() % 0.5f : mDisabledImageColor.get(); if ( mScaleImage) { - mImagep->draw(getLocalRect(), getEnabled() ? mImageColor : mDisabledImageColor ); + mImagep->draw(getLocalRect(), getEnabled() ? mImageColor.get() : disabled_color ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); @@ -590,7 +643,7 @@ void LLButton::draw() } else { - mImagep->draw(0, 0, getEnabled() ? mImageColor : mDisabledImageColor ); + mImagep->draw(0, 0, getEnabled() ? mImageColor.get() : disabled_color ); if (mCurGlowStrength > 0.01f) { gGL.setSceneBlendType(glow_type); @@ -602,7 +655,7 @@ void LLButton::draw() else { // no image - llwarns << "No image for button " << getName() << llendl; + lldebugs << "No image for button " << getName() << llendl; // draw it in pink so we can find it gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4::pink1, FALSE); } @@ -634,7 +687,7 @@ void LLButton::draw() } // fade out overlay images on disabled buttons - LLColor4 overlay_color = mImageOverlayColor; + LLColor4 overlay_color = mImageOverlayColor.get(); if (!getEnabled()) { overlay_color.mV[VALPHA] = 0.5f; @@ -707,23 +760,18 @@ void LLButton::draw() mGLFont->render(label, 0, (F32)x, (F32)(LLBUTTON_V_PAD + y_offset), label_color, mHAlign, LLFontGL::BOTTOM, - mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NORMAL, + LLFontGL::NORMAL, + mDropShadowedText ? LLFontGL::DROP_SHADOW_SOFT : LLFontGL::NO_SHADOW, U32_MAX, text_width, NULL, FALSE, FALSE); } - if (sDebugRects - || (LLView::sEditingUI && this == LLView::sEditingUIView)) - { - drawDebugRect(); - } - - // reset hover status for next frame - mNeedsHighlight = FALSE; + LLView::draw(); } void LLButton::drawBorder(const LLColor4& color, S32 size) { + if (mImagep.isNull()) return; if (mScaleImage) { mImagep->drawBorder(getLocalRect(), color, size); @@ -734,22 +782,19 @@ void LLButton::drawBorder(const LLColor4& color, S32 size) } } -void LLButton::setClickedCallback(void (*cb)(void*), void* userdata) +BOOL LLButton::getToggleState() const { - mClickedCallback = cb; - if (userdata) - { - mCallbackUserData = userdata; - } + return getValue().asBoolean(); } - void LLButton::setToggleState(BOOL b) { - if( b != mToggleState ) + if( b != getToggleState() ) { setControlValue(b); // will fire LLControlVariable callbacks (if any) - mToggleState = b; // may or may not be redundant + setValue(b); // may or may not be redundant + // Unselected label assignments + autoResize(); } } @@ -764,19 +809,11 @@ void LLButton::setFlashing( BOOL b ) BOOL LLButton::toggleState() -{ - setToggleState( !mToggleState ); - return mToggleState; -} - -void LLButton::setValue(const LLSD& value ) { - mToggleState = value.asBoolean(); -} + bool flipped = ! getToggleState(); + setToggleState(flipped); -LLSD LLButton::getValue() const -{ - return mToggleState == TRUE; + return flipped; } void LLButton::setLabel( const LLStringExplicit& label ) @@ -816,8 +853,55 @@ void LLButton::setDisabledSelectedLabel( const LLStringExplicit& label ) void LLButton::setImageUnselected(LLPointer image) { mImageUnselected = image; + if (mImageUnselected.isNull()) + { + llwarns << "Setting default button image for: " << getName() << " to NULL" << llendl; + } } +void LLButton::autoResize() +{ + LLUIString label; + if(getToggleState()) + { + if( getEnabled() || mDisabledSelectedLabel.empty() ) + { + label = mSelectedLabel; + } + else + { + label = mDisabledSelectedLabel; + } + } + else + { + if( getEnabled() || mDisabledLabel.empty() ) + { + label = mUnselectedLabel; + } + else + { + label = mDisabledLabel; + } + } + resize(label); +} + +void LLButton::resize(LLUIString label) +{ + // get label length + S32 label_width = mGLFont->getWidth(label.getString()); + // get current btn length + S32 btn_width =getRect().getWidth(); + // check if it need resize + if (mAutoResize == TRUE) + { + if (btn_width - (mRightHPad + mLeftHPad) < label_width) + { + setRect(LLRect( getRect().mLeft, getRect().mTop, getRect().mLeft + label_width + mLeftHPad + mRightHPad , getRect().mBottom)); + } + } +} void LLButton::setImages( const std::string &image_name, const std::string &selected_name ) { setImageUnselected(image_name); @@ -845,14 +929,20 @@ void LLButton::setImageDisabled(LLPointer image) { mImageDisabled = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; + mFadeWhenDisabled = TRUE; } void LLButton::setImageDisabledSelected(LLPointer image) { mImageDisabledSelected = image; mDisabledImageColor = mImageColor; - mDisabledImageColor.mV[VALPHA] *= 0.5f; + mFadeWhenDisabled = TRUE; +} + +void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name) +{ + setDisabledImages( image_name, selected_name, mImageColor.get()); + mFadeWhenDisabled = TRUE; } void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name, const LLColor4& c ) @@ -867,13 +957,6 @@ void LLButton::setImageHoverSelected(LLPointer image) mImageHoverSelected = image; } -void LLButton::setDisabledImages( const std::string &image_name, const std::string &selected_name) -{ - LLColor4 clr = mImageColor; - clr.mV[VALPHA] *= .5f; - setDisabledImages( image_name, selected_name, clr ); -} - void LLButton::setImageHoverUnselected(LLPointer image) { mImageHoverUnselected = image; @@ -899,11 +982,9 @@ void LLButton::setImageOverlay(const std::string& image_name, LLFontGL::HAlign a } } - void LLButton::onMouseCaptureLost() { - mMouseDownTimer.stop(); - mMouseDownTimer.reset(); + resetMouseDownTimer(); } //------------------------------------------------------------------------- @@ -975,28 +1056,6 @@ void LLButton::addImageAttributeToXML(LLXMLNodePtr node, } } -// virtual -LLXMLNodePtr LLButton::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->createChild("label", TRUE)->setStringValue(getLabelUnselected()); - node->createChild("label_selected", TRUE)->setStringValue(getLabelSelected()); - node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mGLFont)); - node->createChild("halign", TRUE)->setStringValue(LLFontGL::nameFromHAlign(mHAlign)); - - addImageAttributeToXML(node,mImageUnselectedName,mImageUnselectedID,std::string("image_unselected")); - addImageAttributeToXML(node,mImageSelectedName,mImageSelectedID,std::string("image_selected")); - addImageAttributeToXML(node,mImageHoverSelectedName,mImageHoverSelectedID,std::string("image_hover_selected")); - addImageAttributeToXML(node,mImageHoverUnselectedName,mImageHoverUnselectedID,std::string("image_hover_unselected")); - addImageAttributeToXML(node,mImageDisabledName,mImageDisabledID,std::string("image_disabled")); - addImageAttributeToXML(node,mImageDisabledSelectedName,mImageDisabledSelectedID,std::string("image_disabled_selected")); - - node->createChild("scale_image", TRUE)->setBoolValue(mScaleImage); - - return node; -} - void clicked_help(void* data) { LLButton* self = (LLButton*)data; @@ -1010,114 +1069,53 @@ void clicked_help(void* data) LLUI::sHtmlHelp->show(self->getHelpURL()); } -// static -LLView* LLButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +void LLButton::setHelpURLCallback(const std::string &help_url) { - std::string name("button"); - node->getAttributeString("name", name); - - std::string label = name; - node->getAttributeString("label", label); - - std::string label_selected = label; - node->getAttributeString("label_selected", label_selected); - - LLFontGL* font = selectFont(node); - - std::string image_unselected; - if (node->hasAttribute("image_unselected")) node->getAttributeString("image_unselected",image_unselected); - - std::string image_selected; - if (node->hasAttribute("image_selected")) node->getAttributeString("image_selected",image_selected); - - std::string image_hover_selected; - if (node->hasAttribute("image_hover_selected")) node->getAttributeString("image_hover_selected",image_hover_selected); - - std::string image_hover_unselected; - if (node->hasAttribute("image_hover_unselected")) node->getAttributeString("image_hover_unselected",image_hover_unselected); - - std::string image_disabled_selected; - if (node->hasAttribute("image_disabled_selected")) node->getAttributeString("image_disabled_selected",image_disabled_selected); - - std::string image_disabled; - if (node->hasAttribute("image_disabled")) node->getAttributeString("image_disabled",image_disabled); - - std::string image_overlay; - node->getAttributeString("image_overlay", image_overlay); - - LLFontGL::HAlign image_overlay_alignment = LLFontGL::HCENTER; - std::string image_overlay_alignment_string; - if (node->hasAttribute("image_overlay_alignment")) - { - node->getAttributeString("image_overlay_alignment", image_overlay_alignment_string); - image_overlay_alignment = LLFontGL::hAlignFromName(image_overlay_alignment_string); - } - - - LLButton *button = new LLButton(name, - LLRect(), - image_unselected, - image_selected, - LLStringUtil::null, - NULL, - parent, - font, - label, - label_selected); - - node->getAttributeS32("pad_right", button->mRightHPad); - node->getAttributeS32("pad_left", button->mLeftHPad); + mHelpURL = help_url; + setClickedCallback(clicked_help,this); +} - BOOL is_toggle = button->getIsToggle(); - node->getAttributeBOOL("toggle", is_toggle); - button->setIsToggle(is_toggle); +// static +void LLButton::toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname) +{ + bool floater_vis = LLFloaterReg::toggleInstance(sdname.asString()); + LLButton* button = dynamic_cast(ctrl); + if (button) + button->setToggleState(floater_vis); +} - if(image_hover_selected != LLStringUtil::null) button->setImageHoverSelected(image_hover_selected); - - if(image_hover_unselected != LLStringUtil::null) button->setImageHoverUnselected(image_hover_unselected); - - if(image_disabled_selected != LLStringUtil::null) button->setImageDisabledSelected(image_disabled_selected ); - - if(image_disabled != LLStringUtil::null) button->setImageDisabled(image_disabled); - - if(image_overlay != LLStringUtil::null) button->setImageOverlay(image_overlay, image_overlay_alignment); +// static +// Gets called once +void LLButton::setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname) +{ + LLButton* button = dynamic_cast(ctrl); + if (!button) + return; + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the button control value (toggle state) to the floater visibility control (Sets the value as well) + button->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name)); + // Set the clicked callback to toggle the floater + button->setClickedCallback(boost::bind(&LLFloaterReg::toggleFloaterInstance, sdname)); +} - if (node->hasAttribute("halign")) - { - LLFontGL::HAlign halign = selectFontHAlign(node); - button->setHAlign(halign); - } +void LLButton::resetMouseDownTimer() +{ + mMouseDownTimer.stop(); + mMouseDownTimer.reset(); +} - if (node->hasAttribute("scale_image")) - { - BOOL needsScale = FALSE; - node->getAttributeBOOL("scale_image",needsScale); - button->setScaleImage( needsScale ); - } - if(label.empty()) - { - button->setLabelUnselected(node->getTextContents()); - } - if (label_selected.empty()) - { - button->setLabelSelected(node->getTextContents()); - } - - if (node->hasAttribute("help_url")) +// *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()) { - std::string help_url; - node->getAttributeString("help_url",help_url); - button->setHelpURLCallback(help_url); + //if our label is empty this is a picture style button + p.picture_style = true; } - button->initFromXML(node, parent); - - return button; -} - -void LLButton::setHelpURLCallback(const std::string &help_url) -{ - mHelpURL = help_url; - setClickedCallback(clicked_help,this); + LLUICtrl::setupParamsForExport(p, parent); } diff --git a/indra/llui/llbutton.h b/indra/llui/llbutton.h index 724b77541a..c7969e260d 100644 --- a/indra/llui/llbutton.h +++ b/indra/llui/llbutton.h @@ -39,7 +39,7 @@ #include "v4color.h" #include "llframetimer.h" #include "llfontgl.h" -#include "llimage.h" +#include "lluiimage.h" #include "lluistring.h" // @@ -53,9 +53,6 @@ extern S32 LLBUTTON_V_PAD; extern S32 BTN_HEIGHT_SMALL; extern S32 BTN_HEIGHT; -// All button widths should be rounded up to this size -extern S32 BTN_GRID; - // // Helpful functions // @@ -72,36 +69,81 @@ class LLButton : public LLUICtrl { public: - // simple button with text label - LLButton(const std::string& name, const LLRect &rect, const std::string& control_name = std::string(), - void (*on_click)(void*) = NULL, void *data = NULL); - - LLButton(const std::string& name, const LLRect& rect, - const std::string &unselected_image, - const std::string &selected_image, - const std::string& control_name, - void (*click_callback)(void*), - void *callback_data = NULL, - const LLFontGL* mGLFont = NULL, - const std::string& unselected_label = LLStringUtil::null, - const std::string& selected_label = LLStringUtil::null ); - - virtual ~LLButton(); - void init(void (*click_callback)(void*), void *callback_data, const LLFontGL* font, const std::string& control_name); - + struct Params + : public LLInitParam::Block + { + // text label + Optional label_selected; + Optional label_dropshadow; + Optional auto_resize; + + // images + Optional image_unselected, + image_selected, + image_hover_selected, + image_hover_unselected, + image_disabled_selected, + image_disabled, + image_overlay; + + Optional image_overlay_alignment; + + // colors + Optional label_color, + label_color_selected, + label_color_disabled, + label_color_disabled_selected, + highlight_color, + image_color, + image_color_disabled, + image_overlay_color, + flash_color; + + // layout + Optional pad_right; + Optional pad_left; + + // callbacks + Optional click_callback, // alias -> commit_callback + mouse_down_callback, + mouse_up_callback, + mouse_held_callback; + + // misc + Optional is_toggle, + scale_image, + commit_on_return, + picture_style; //if true, don't display label + + Optional help_url; + Optional hover_glow_amount; + Optional held_down_delay; + + Params(); + }; +protected: + friend class LLUICtrlFactory; + LLButton(const Params&); + +public: + // For backward compatability only + typedef boost::function button_callback_t; + void addImageAttributeToXML(LLXMLNodePtr node, const std::string& imageName, const LLUUID& imageID,const std::string& xmlTagName) const; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - virtual BOOL handleUnicodeCharHere(llwchar uni_char); virtual BOOL handleKeyHere(KEY key, MASK mask); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseDown(S32 x, S32 y, MASK mask); + virtual BOOL handleRightMouseUp(S32 x, S32 y, MASK mask); virtual void draw(); + /*virtual*/ BOOL postBuild(); + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); virtual void onMouseCaptureLost(); virtual void onCommit(); @@ -109,18 +151,27 @@ public: void setUnselectedLabelColor( const LLColor4& c ) { mUnselectedLabelColor = c; } void setSelectedLabelColor( const LLColor4& c ) { mSelectedLabelColor = c; } - void setClickedCallback( void (*cb)(void *data), void* data = NULL ); // mouse down and up within button - void setMouseDownCallback( void (*cb)(void *data) ) { mMouseDownCallback = cb; } // mouse down within button - void setMouseUpCallback( void (*cb)(void *data) ) { mMouseUpCallback = cb; } // mouse up, EVEN IF NOT IN BUTTON - void setHeldDownCallback( void (*cb)(void *data) ) { mHeldDownCallback = cb; } // Mouse button held down and in button - void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } + boost::signals::connection setClickedCallback( const commit_signal_t::slot_type& cb ); // mouse down and up within button + boost::signals::connection setMouseDownCallback( const commit_signal_t::slot_type& cb ); + boost::signals::connection setMouseUpCallback( const commit_signal_t::slot_type& cb ); // mouse up, EVEN IF NOT IN BUTTON + // Passes a 'count' parameter in the commit param payload, i.e. param["count"]) + boost::signals::connection setHeldDownCallback( const commit_signal_t::slot_type& cb ); // Mouse button held down and in button + boost::signals::connection setRightClickedCallback( const commit_signal_t::slot_type& cb ); // right mouse down and up within button + + + // *TODO: Deprecate (for backwards compatability only) + boost::signals::connection setClickedCallback( button_callback_t cb, void* data ); + boost::signals::connection setMouseDownCallback( button_callback_t cb, void* data ); + boost::signals::connection setMouseUpCallback( button_callback_t cb, void* data ); + boost::signals::connection setHeldDownCallback( button_callback_t cb, void* data ); + + void setHeldDownDelay( F32 seconds, S32 frames = 0) { mHeldDownDelay = seconds; mHeldDownFrameDelay = frames; } + F32 getHeldDownTime() const { return mMouseDownTimer.getElapsedTimeF32(); } - BOOL getIsToggle() const { return mIsToggle; } - void setIsToggle(BOOL is_toggle) { mIsToggle = is_toggle; } BOOL toggleState(); - BOOL getToggleState() const { return mToggleState; } + BOOL getToggleState() const; void setToggleState(BOOL b); void setFlashing( BOOL b ); @@ -150,11 +201,9 @@ public: void setImageOverlay(const std::string& image_name, LLFontGL::HAlign alignment = LLFontGL::HCENTER, const LLColor4& color = LLColor4::white); LLPointer getImageOverlay() { return mImageOverlay; } - - - virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; + void autoResize(); // resize with label of current btn state + void resize(LLUIString label); // resize with label input void setLabel( const LLStringExplicit& label); virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); void setLabelUnselected(const LLStringExplicit& label); @@ -172,8 +221,6 @@ public: void setBorderEnabled(BOOL b) { mBorderEnabled = b; } - static void onHeldDown(void *userdata); // to be called by gIdleCallbacks - void setHoverGlowStrength(F32 strength) { mHoverGlowStrength = strength; } void setImageUnselected(const std::string &image_name); @@ -198,6 +245,10 @@ public: void setHelpURLCallback(const std::string &help_url); const std::string& getHelpURL() const { return mHelpURL; } + static void onHeldDown(void *userdata); // to be called by gIdleCallbacks + static void toggleFloaterAndSetToggleState(LLUICtrl* ctrl, const LLSD& sdname); + static void setFloaterToggle(LLUICtrl* ctrl, const LLSD& sdname); + protected: virtual void drawBorder(const LLColor4& color, S32 size); @@ -212,45 +263,48 @@ protected: void setImageDisabledSelectedID(const LLUUID &image_id); const LLPointer& getImageUnselected() const { return mImageUnselected; } const LLPointer& getImageSelected() const { return mImageSelected; } + void resetMouseDownTimer(); LLFrameTimer mMouseDownTimer; -private: - - void (*mClickedCallback)(void* data ); - void (*mMouseDownCallback)(void *data); - void (*mMouseUpCallback)(void *data); - void (*mHeldDownCallback)(void *data); + // If the label is empty, set the picture_style attribute + static void setupParamsForExport(Params& p, LLView* parent); +private: + commit_signal_t mMouseDownSignal; + commit_signal_t mMouseUpSignal; + commit_signal_t mHeldDownSignal; + const LLFontGL *mGLFont; S32 mMouseDownFrame; - F32 mHeldDownDelay; // seconds, after which held-down callbacks get called + 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 - LLPointer mImageOverlay; - LLFontGL::HAlign mImageOverlayAlignment; - LLColor4 mImageOverlayColor; + LLPointer mImageOverlay; + LLFontGL::HAlign mImageOverlayAlignment; + LLUIColor mImageOverlayColor; - LLPointer mImageUnselected; - LLUIString mUnselectedLabel; - LLColor4 mUnselectedLabelColor; + LLPointer mImageUnselected; + LLUIString mUnselectedLabel; + LLUIColor mUnselectedLabelColor; - LLPointer mImageSelected; - LLUIString mSelectedLabel; - LLColor4 mSelectedLabelColor; + LLPointer mImageSelected; + LLUIString mSelectedLabel; + LLUIColor mSelectedLabelColor; - LLPointer mImageHoverSelected; + LLPointer mImageHoverSelected; - LLPointer mImageHoverUnselected; + LLPointer mImageHoverUnselected; - LLPointer mImageDisabled; - LLUIString mDisabledLabel; - LLColor4 mDisabledLabelColor; + LLPointer mImageDisabled; + LLUIString mDisabledLabel; + LLUIColor mDisabledLabelColor; - LLPointer mImageDisabledSelected; - LLUIString mDisabledSelectedLabel; - LLColor4 mDisabledSelectedLabelColor; + LLPointer mImageDisabledSelected; + LLUIString mDisabledSelectedLabel; + LLUIColor mDisabledSelectedLabelColor; LLUUID mImageUnselectedID; LLUUID mImageSelectedID; @@ -265,20 +319,17 @@ private: std::string mImageDisabledName; std::string mImageDisabledSelectedName; - LLColor4 mHighlightColor; - LLColor4 mUnselectedBgColor; - LLColor4 mSelectedBgColor; - LLColor4 mFlashBgColor; + LLUIColor mHighlightColor; + LLUIColor mFlashBgColor; - LLColor4 mImageColor; - LLColor4 mDisabledImageColor; + LLUIColor mImageColor; + LLUIColor mDisabledImageColor; BOOL mIsToggle; - BOOL mToggleState; BOOL mScaleImage; BOOL mDropShadowedText; - + BOOL mAutoResize; BOOL mBorderEnabled; BOOL mFlashing; @@ -292,6 +343,7 @@ private: BOOL mNeedsHighlight; BOOL mCommitOnReturn; + BOOL mFadeWhenDisabled; std::string mHelpURL; @@ -300,4 +352,11 @@ private: LLFrameTimer mFlashingTimer; }; +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_BUTTON +#pragma warning (disable : 4231) +extern template LLButton* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif + #endif // LL_LLBUTTON_H diff --git a/indra/llui/llcallbackmap.h b/indra/llui/llcallbackmap.h index eadb9c98f3..97b1e2fc50 100644 --- a/indra/llui/llcallbackmap.h +++ b/indra/llui/llcallbackmap.h @@ -30,11 +30,11 @@ * $/LicenseInfo$ */ -#ifndef LL_CALLBACK_MAP_H -#define LL_CALLBACK_MAP_H +#ifndef LLCALLBACKMAP_H +#define LLCALLBACKMAP_H #include -#include "llstring.h" +#include class LLCallbackMap { @@ -45,12 +45,19 @@ public: typedef std::map map_t; typedef map_t::iterator map_iter_t; typedef map_t::const_iterator map_const_iter_t; - + + template + static void* buildPanel(void* data) + { + T* panel = new T(); + return (void*)panel; + } + LLCallbackMap() : mCallback(NULL), mData(NULL) { } - LLCallbackMap(callback_t callback, void* data) : mCallback(callback), mData(data) { } + LLCallbackMap(callback_t callback, void* data = NULL) : mCallback(callback), mData(data) { } callback_t mCallback; void* mData; }; -#endif // LL_CALLBACK_MAP_H +#endif // LLCALLBACKMAP_H diff --git a/indra/llui/llcheckboxctrl.cpp b/indra/llui/llcheckboxctrl.cpp index eda9467d87..932a1b6297 100644 --- a/indra/llui/llcheckboxctrl.cpp +++ b/indra/llui/llcheckboxctrl.cpp @@ -31,6 +31,7 @@ */ // The mutants are coming! +#define INSTANTIATE_GETCHILD_CHECKBOX #include "linden_common.h" @@ -49,101 +50,88 @@ const U32 MAX_STRING_LENGTH = 10; -static LLRegisterWidget r("check_box"); - - -LLCheckBoxCtrl::LLCheckBoxCtrl(const std::string& name, const LLRect& rect, - const std::string& label, - const LLFontGL* font, - void (*commit_callback)(LLUICtrl* ctrl, void* userdata), - void* callback_user_data, - BOOL initial_value, - BOOL use_radio_style, - const std::string& control_which) -: LLUICtrl(name, rect, TRUE, commit_callback, callback_user_data, FOLLOWS_LEFT | FOLLOWS_TOP), - mTextEnabledColor( LLUI::sColorsGroup->getColor( "LabelTextColor" ) ), - mTextDisabledColor( LLUI::sColorsGroup->getColor( "LabelDisabledColor" ) ), - mRadioStyle( use_radio_style ), - mInitialValue( initial_value ), - mSetValue( initial_value ) +template LLCheckBoxCtrl* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; + +static LLDefaultWidgetRegistry::Register r("check_box"); + +LLCheckBoxCtrl::Params::Params() +: text_enabled_color("text_enabled_color"), + text_disabled_color("text_disabled_color"), + initial_value("initial_value", false), + label_text("label_text"), + check_button("check_button"), + radio_style("radio_style") +{} + + +LLCheckBoxCtrl::LLCheckBoxCtrl(const LLCheckBoxCtrl::Params& p) +: LLUICtrl(p), + mTextEnabledColor(p.text_enabled_color()), + mTextDisabledColor(p.text_disabled_color()), + mFont(p.font()) { - if (font) - { - mFont = font; - } - else - { - mFont = LLFontGL::getFontSansSerifSmall(); - } + mViewModel->setValue(LLSD(p.initial_value)); + mViewModel->resetDirty(); + static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); + static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); + static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); + static LLUICachedControl llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0); // must be big enough to hold all children setUseBoundingRect(TRUE); - mKeyboardFocusOnClick = TRUE; - // Label (add a little space to make sure text actually renders) const S32 FUDGE = 10; - S32 text_width = mFont->getWidth( label ) + FUDGE; + S32 text_width = mFont->getWidth( p.label ) + FUDGE; S32 text_height = llround(mFont->getLineHeight()); LLRect label_rect; label_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING, - LLCHECKBOXCTRL_VPAD + 1, // padding to get better alignment - text_width + LLCHECKBOXCTRL_HPAD, + llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing, + llcheckboxctrl_vpad + 1, // padding to get better alignment + text_width + llcheckboxctrl_hpad, text_height ); // *HACK Get rid of this with SL-55508... // this allows blank check boxes and radio boxes for now - std::string local_label = label; + std::string local_label = p.label; if(local_label.empty()) { local_label = " "; } - mLabel = new LLTextBox( std::string("CheckboxCtrl Label"), label_rect, local_label, mFont ); - mLabel->setFollowsLeft(); - mLabel->setFollowsBottom(); + LLTextBox::Params tbparams = p.label_text; + tbparams.rect(label_rect); + tbparams.text(local_label); + if (p.font.isProvided()) + { + tbparams.font(p.font); + } + mLabel = LLUICtrlFactory::create (tbparams); + addChild(mLabel); // Button // Note: button cover the label by extending all the way to the right. LLRect btn_rect; btn_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD, - LLCHECKBOXCTRL_VPAD, - LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width + LLCHECKBOXCTRL_HPAD, - llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) + LLCHECKBOXCTRL_VPAD); + llcheckboxctrl_hpad, + llcheckboxctrl_vpad, + llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width + llcheckboxctrl_hpad, + llmax( text_height, llcheckboxctrl_btn_size() ) + llcheckboxctrl_vpad); std::string active_true_id, active_false_id; std::string inactive_true_id, inactive_false_id; - if (mRadioStyle) - { - active_true_id = "UIImgRadioActiveSelectedUUID"; - active_false_id = "UIImgRadioActiveUUID"; - inactive_true_id = "UIImgRadioInactiveSelectedUUID"; - inactive_false_id = "UIImgRadioInactiveUUID"; - mButton = new LLButton(std::string("Radio control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } - else - { - active_false_id = "UIImgCheckboxActiveUUID"; - active_true_id = "UIImgCheckboxActiveSelectedUUID"; - inactive_true_id = "UIImgCheckboxInactiveSelectedUUID"; - inactive_false_id = "UIImgCheckboxInactiveUUID"; - mButton = new LLButton(std::string("Checkbox control button"), btn_rect, - active_false_id, active_true_id, control_which, - &LLCheckBoxCtrl::onButtonPress, this, LLFontGL::getFontSansSerif() ); - mButton->setDisabledImages( inactive_false_id, inactive_true_id ); - mButton->setHoverGlowStrength(0.35f); - } - mButton->setIsToggle(TRUE); - mButton->setToggleState( initial_value ); - mButton->setFollowsLeft(); - mButton->setFollowsBottom(); - mButton->setCommitOnReturn(FALSE); + + LLButton::Params params = p.check_button; + params.rect(btn_rect); + //params.control_name(p.control_name); + params.click_callback.function(boost::bind(&LLCheckBoxCtrl::onButtonPress, this, _2)); + params.commit_on_return(false); + // Checkboxes only allow boolean initial values, but buttons can + // take any LLSD. + params.initial_value(LLSD(p.initial_value)); + params.follows.flags(FOLLOWS_LEFT | FOLLOWS_BOTTOM); + + mButton = LLUICtrlFactory::create(params); addChild(mButton); } @@ -154,24 +142,14 @@ LLCheckBoxCtrl::~LLCheckBoxCtrl() // static -void LLCheckBoxCtrl::onButtonPress( void *userdata ) +void LLCheckBoxCtrl::onButtonPress( const LLSD& data ) { - LLCheckBoxCtrl* self = (LLCheckBoxCtrl*) userdata; - - if (self->mRadioStyle) - { - self->setValue(TRUE); - } - - self->setControlValue(self->getValue()); - // HACK: because buttons don't normally commit - self->onCommit(); + //if (mRadioStyle) + //{ + // setValue(TRUE); + //} - if (self->mKeyboardFocusOnClick) - { - self->setFocus( TRUE ); - self->onFocusReceived(); - } + onCommit(); } void LLCheckBoxCtrl::onCommit() @@ -179,6 +157,7 @@ void LLCheckBoxCtrl::onCommit() if( getEnabled() ) { setTentative(FALSE); + setControlValue(getValue()); LLUICtrl::onCommit(); } } @@ -187,6 +166,15 @@ void LLCheckBoxCtrl::setEnabled(BOOL b) { LLView::setEnabled(b); mButton->setEnabled(b); + + if (b) + { + mLabel->setColor( mTextEnabledColor.get() ); + } + else + { + mLabel->setColor( mTextDisabledColor.get() ); + } } void LLCheckBoxCtrl::clear() @@ -197,43 +185,33 @@ void LLCheckBoxCtrl::clear() void LLCheckBoxCtrl::reshape(S32 width, S32 height, BOOL called_from_parent) { //stretch or shrink bounding rectangle of label when rebuilding UI at new scale + static LLUICachedControl llcheckboxctrl_spacing ("UICheckboxctrlSpacing", 0); + static LLUICachedControl llcheckboxctrl_hpad ("UICheckboxctrlHPad", 0); + static LLUICachedControl llcheckboxctrl_vpad ("UICheckboxctrlVPad", 0); + static LLUICachedControl llcheckboxctrl_btn_size ("UICheckboxctrlBtnSize", 0); + const S32 FUDGE = 10; S32 text_width = mFont->getWidth( mLabel->getText() ) + FUDGE; S32 text_height = llround(mFont->getLineHeight()); LLRect label_rect; label_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD + LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING, - LLCHECKBOXCTRL_VPAD, + llcheckboxctrl_hpad + llcheckboxctrl_btn_size + llcheckboxctrl_spacing, + llcheckboxctrl_vpad, text_width, text_height ); mLabel->setRect(label_rect); LLRect btn_rect; btn_rect.setOriginAndSize( - LLCHECKBOXCTRL_HPAD, - LLCHECKBOXCTRL_VPAD, - LLCHECKBOXCTRL_BTN_SIZE + LLCHECKBOXCTRL_SPACING + text_width, - llmax( text_height, LLCHECKBOXCTRL_BTN_SIZE ) ); + llcheckboxctrl_hpad, + llcheckboxctrl_vpad, + llcheckboxctrl_btn_size + llcheckboxctrl_spacing + text_width, + llmax( text_height, llcheckboxctrl_btn_size() ) ); mButton->setRect( btn_rect ); LLUICtrl::reshape(width, height, called_from_parent); } -void LLCheckBoxCtrl::draw() -{ - if (getEnabled()) - { - mLabel->setColor( mTextEnabledColor ); - } - else - { - mLabel->setColor( mTextDisabledColor ); - } - - // Draw children - LLUICtrl::draw(); -} - //virtual void LLCheckBoxCtrl::setValue(const LLSD& value ) { @@ -246,6 +224,18 @@ LLSD LLCheckBoxCtrl::getValue() const return mButton->getValue(); } +//virtual +void LLCheckBoxCtrl::setTentative(BOOL b) +{ + mButton->setTentative(b); +} + +//virtual +BOOL LLCheckBoxCtrl::getTentative() const +{ + return mButton->getTentative(); +} + void LLCheckBoxCtrl::setLabel( const LLStringExplicit& label ) { mLabel->setText( label ); @@ -264,12 +254,6 @@ BOOL LLCheckBoxCtrl::setLabelArg( const std::string& key, const LLStringExplicit return res; } -//virtual -std::string LLCheckBoxCtrl::getControlName() const -{ - return mButton->getControlName(); -} - // virtual void LLCheckBoxCtrl::setControlName(const std::string& control_name, LLView* context) { @@ -282,7 +266,7 @@ BOOL LLCheckBoxCtrl::isDirty() const { if ( mButton ) { - return (mSetValue != mButton->getToggleState()); + return mButton->isDirty(); } return FALSE; // Shouldn't get here } @@ -293,78 +277,6 @@ void LLCheckBoxCtrl::resetDirty() { if ( mButton ) { - mSetValue = mButton->getToggleState(); - } -} - - - -// virtual -LLXMLNodePtr LLCheckBoxCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - node->createChild("label", TRUE)->setStringValue(mLabel->getText()); - - std::string control_name = mButton->getControlName(); - - node->createChild("initial_value", TRUE)->setBoolValue(mInitialValue); - - node->createChild("font", TRUE)->setStringValue(LLFontGL::nameFromFont(mFont)); - - node->createChild("radio_style", TRUE)->setBoolValue(mRadioStyle); - - return node; -} - -// static -LLView* LLCheckBoxCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name("checkbox"); - node->getAttributeString("name", name); - - std::string label(""); - node->getAttributeString("label", label); - - LLFontGL* font = LLView::selectFont(node); - - BOOL radio_style = FALSE; - node->getAttributeBOOL("radio_style", radio_style); - - LLUICtrlCallback callback = NULL; - - if (label.empty()) - { - label.assign(node->getTextContents()); + mButton->resetDirty(); } - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLCheckBoxCtrl* checkbox = new LLCheckboxCtrl(name, - rect, - label, - font, - callback, - NULL, - FALSE, - radio_style); // if true, draw radio button style icons - - BOOL initial_value = checkbox->getValue().asBoolean(); - node->getAttributeBOOL("initial_value", initial_value); - - LLColor4 color; - color = LLUI::sColorsGroup->getColor( "LabelTextColor" ); - LLUICtrlFactory::getAttributeColor(node,"text_enabled_color", color); - checkbox->setEnabledColor(color); - - color = LLUI::sColorsGroup->getColor( "LabelDisabledColor" ); - LLUICtrlFactory::getAttributeColor(node,"text_disabled_color", color); - checkbox->setDisabledColor(color); - - checkbox->setValue(initial_value); - - checkbox->initFromXML(node, parent); - - return checkbox; } diff --git a/indra/llui/llcheckboxctrl.h b/indra/llui/llcheckboxctrl.h index ff867f5193..fe719e3b6a 100644 --- a/indra/llui/llcheckboxctrl.h +++ b/indra/llui/llcheckboxctrl.h @@ -33,24 +33,14 @@ #ifndef LL_LLCHECKBOXCTRL_H #define LL_LLCHECKBOXCTRL_H - -#include "stdtypes.h" #include "lluictrl.h" #include "llbutton.h" +#include "lltextbox.h" #include "v4color.h" -#include "llrect.h" // // Constants // -const S32 LLCHECKBOXCTRL_BTN_SIZE = 13; -const S32 LLCHECKBOXCTRL_VPAD = 2; -const S32 LLCHECKBOXCTRL_HPAD = 2; -const S32 LLCHECKBOXCTRL_SPACING = 5; -const S32 LLCHECKBOXCTRL_HEIGHT = 16; - -// Deprecated, don't use. -#define CHECKBOXCTRL_HEIGHT LLCHECKBOXCTRL_HEIGHT const BOOL RADIO_STYLE = TRUE; const BOOL CHECK_STYLE = FALSE; @@ -59,30 +49,38 @@ const BOOL CHECK_STYLE = FALSE; // Classes // class LLFontGL; -class LLTextBox; class LLViewBorder; class LLCheckBoxCtrl : public LLUICtrl { public: - LLCheckBoxCtrl(const std::string& name, const LLRect& rect, const std::string& label, - const LLFontGL* font = NULL, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void* callback_userdata = NULL, - BOOL initial_value = FALSE, - BOOL use_radio_style = FALSE, // if true, draw radio button style icons - const std::string& control_which = LLStringUtil::null); + struct Params + : public LLInitParam::Block + { + Optional text_enabled_color; + Optional text_disabled_color; + Optional initial_value; // override LLUICtrl initial_value + + Optional label_text; + Optional check_button; + + Deprecated radio_style; + + Params(); + }; + virtual ~LLCheckBoxCtrl(); - // LLView interface +protected: + LLCheckBoxCtrl(const Params&); + friend class LLUICtrlFactory; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); +public: + // LLView interface virtual void setEnabled( BOOL b ); - virtual void draw(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); // LLUICtrl interface @@ -91,8 +89,8 @@ public: BOOL get() { return (BOOL)getValue().asBoolean(); } void set(BOOL value) { setValue(value); } - virtual void setTentative(BOOL b) { mButton->setTentative(b); } - virtual BOOL getTentative() const { return mButton->getTentative(); } + virtual void setTentative(BOOL b); + virtual BOOL getTentative() const; virtual BOOL setLabelArg( const std::string& key, const LLStringExplicit& text ); @@ -108,10 +106,11 @@ public: void setLabel( const LLStringExplicit& label ); std::string getLabel() const; + void setFont( const LLFontGL* font ) { mFont = font; } + virtual void setControlName(const std::string& control_name, LLView* context); - virtual std::string getControlName() const; - static void onButtonPress(void *userdata); + void onButtonPress(const LLSD& data); virtual BOOL isDirty() const; // Returns TRUE if the user has modified this control. virtual void resetDirty(); // Clear dirty state @@ -121,19 +120,17 @@ protected: LLButton* mButton; LLTextBox* mLabel; const LLFontGL* mFont; - LLColor4 mTextEnabledColor; - LLColor4 mTextDisabledColor; - BOOL mRadioStyle; - BOOL mInitialValue; // Value set in constructor - BOOL mSetValue; // Value set programmatically - BOOL mKeyboardFocusOnClick; - LLViewBorder* mBorder; -}; + LLUIColor mTextEnabledColor; + LLUIColor mTextDisabledColor; +}; -// HACK: fix old capitalization problem -//typedef LLCheckBoxCtrl LLCheckboxCtrl; -#define LLCheckboxCtrl LLCheckBoxCtrl +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_CHECKBOX +#pragma warning (disable : 4231) +extern template LLCheckBoxCtrl* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif #endif // LL_LLCHECKBOXCTRL_H diff --git a/indra/llui/llcombobox.cpp b/indra/llui/llcombobox.cpp index 28a05c13f5..2197d5432b 100644 --- a/indra/llui/llcombobox.cpp +++ b/indra/llui/llcombobox.cpp @@ -33,6 +33,8 @@ // A control that displays the name of the chosen item, which when // clicked shows a scrolling box of options. +#define INSTANTIATE_GETCHILD_COMBOBOX + #include "linden_common.h" // file includes @@ -48,167 +50,129 @@ #include "llwindow.h" #include "llfloater.h" #include "llscrollbar.h" +#include "llscrolllistcell.h" +#include "llscrolllistitem.h" #include "llcontrol.h" #include "llfocusmgr.h" #include "lllineeditor.h" #include "v2math.h" +#include "lluictrlfactory.h" // Globals S32 LLCOMBOBOX_HEIGHT = 0; S32 LLCOMBOBOX_WIDTH = 0; S32 MAX_COMBO_WIDTH = 500; -static LLRegisterWidget r1("combo_box"); +template LLComboBox* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; -LLComboBox::LLComboBox( const std::string& name, const LLRect &rect, const std::string& label, - void (*commit_callback)(LLUICtrl*,void*), - void *callback_userdata - ) -: LLUICtrl(name, rect, TRUE, commit_callback, callback_userdata, - FOLLOWS_LEFT | FOLLOWS_TOP), - mTextEntry(NULL), - mArrowImage(NULL), - mAllowTextEntry(FALSE), - mMaxChars(20), - mTextEntryTentative(TRUE), - mListPosition(BELOW), - mPrearrangeCallback( NULL ), - mTextEntryCallback( NULL ), - mLabel(label) -{ - // Always use text box - // Text label button - mButton = new LLButton(mLabel, - LLRect(), - LLStringUtil::null, - NULL, this); - mButton->setImageUnselected(std::string("square_btn_32x128.tga")); - mButton->setImageSelected(std::string("square_btn_selected_32x128.tga")); - mButton->setImageDisabled(std::string("square_btn_32x128.tga")); - mButton->setImageDisabledSelected(std::string("square_btn_selected_32x128.tga")); - mButton->setScaleImage(TRUE); - - mButton->setMouseDownCallback(onButtonDown); - mButton->setFont(LLFontGL::getFontSansSerifSmall()); - mButton->setFollows(FOLLOWS_LEFT | FOLLOWS_BOTTOM | FOLLOWS_RIGHT); - mButton->setHAlign( LLFontGL::LEFT ); - mButton->setRightHPad(2); - addChild(mButton); +static LLDefaultWidgetRegistry::Register register_combo_box("combo_box"); - // disallow multiple selection - mList = new LLScrollListCtrl(std::string("ComboBox"), LLRect(), - &LLComboBox::onItemSelected, this, FALSE); - mList->setVisible(FALSE); - mList->setBgWriteableColor( LLColor4(1,1,1,1) ); - mList->setCommitOnKeyboardMovement(FALSE); - addChild(mList); - - mArrowImage = LLUI::sImageProvider->getUIImage("combobox_arrow.tga"); - mButton->setImageOverlay("combobox_arrow.tga", LLFontGL::RIGHT); +void LLComboBox::PreferredPositionValues::declareValues() +{ + declare("above", ABOVE); + declare("below", BELOW); +} - updateLayout(); +LLComboBox::ItemParams::ItemParams() +: label("label") +{ } -LLComboBox::~LLComboBox() +LLComboBox::Params::Params() +: allow_text_entry("allow_text_entry", false), + show_text_as_tentative("show_text_as_tentative", true), + max_chars("max_chars", 20), + arrow_image("arrow_image"), + list_position("list_position", BELOW), + items("item"), + combo_button("combo_button"), + combo_list("combo_list"), + combo_editor("combo_editor") { - // children automatically deleted, including mMenu, mButton + addSynonym(items, "combo_item"); } -// virtual -LLXMLNodePtr LLComboBox::getXML(bool save_children) const + +LLComboBox::LLComboBox(const LLComboBox::Params& p) +: LLUICtrl(p), + mTextEntry(NULL), + mTextEntryTentative(p.show_text_as_tentative), + mHasAutocompletedText(false), + mAllowTextEntry(p.allow_text_entry), + mMaxChars(p.max_chars), + mPrearrangeCallback(p.prearrange_callback()), + mTextEntryCallback(p.text_entry_callback()), + mSelectionCallback(p.selection_callback()), + mArrowImage(p.arrow_image), + mListPosition(p.list_position) { - LLXMLNodePtr node = LLUICtrl::getXML(); + // Text label button - // Attributes + LLButton::Params button_params = p.combo_button; + button_params.mouse_down_callback.function(boost::bind(&LLComboBox::onButtonDown, this)); + button_params.follows.flags(FOLLOWS_LEFT|FOLLOWS_BOTTOM|FOLLOWS_RIGHT); + button_params.rect(p.rect); + button_params.pad_right(2); - node->createChild("allow_text_entry", TRUE)->setBoolValue(mAllowTextEntry); + mButton = LLUICtrlFactory::create(button_params); + mButton->setRightHPad(2); //redo to compensate for button hack that leaves space for a character + addChild(mButton); - node->createChild("max_chars", TRUE)->setIntValue(mMaxChars); + LLScrollListCtrl::Params params = p.combo_list; + params.name("ComboBox"); + params.commit_callback.function(boost::bind(&LLComboBox::onItemSelected, this, _2)); + params.visible(false); + params.commit_on_keyboard_movement(false); - // Contents + mList = LLUICtrlFactory::create(params); + addChild(mList); - std::vector data_list = mList->getAllData(); - std::vector::iterator data_itor; - for (data_itor = data_list.begin(); data_itor != data_list.end(); ++data_itor) + for (LLInitParam::ParamIterator::const_iterator it = p.items().begin(); + it != p.items().end(); + ++it) { - LLScrollListItem* item = *data_itor; - LLScrollListCell* cell = item->getColumn(0); - if (cell) + LLScrollListItem::Params item_params = *it; + if (it->label.isProvided()) { - LLXMLNodePtr item_node = node->createChild("combo_item", FALSE); - LLSD value = item->getValue(); - item_node->createChild("value", TRUE)->setStringValue(value.asString()); - item_node->createChild("enabled", TRUE)->setBoolValue(item->getEnabled()); - item_node->setStringValue(cell->getValue().asString()); + item_params.cells.add().value(it->label()); } + + mList->addRow(item_params); } - return node; + createLineEditor(p); + + setTopLostCallback(boost::bind(&LLComboBox::hideList, this)); } -// static -LLView* LLComboBox::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +void LLComboBox::initFromParams(const LLComboBox::Params& p) { - std::string name("combo_box"); - node->getAttributeString("name", name); + LLUICtrl::initFromParams(p); - std::string label(""); - node->getAttributeString("label", label); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - BOOL allow_text_entry = FALSE; - node->getAttributeBOOL("allow_text_entry", allow_text_entry); - - S32 max_chars = 20; - node->getAttributeS32("max_chars", max_chars); - - LLUICtrlCallback callback = NULL; - - LLComboBox* combo_box = new LLComboBox(name, - rect, - label, - callback, - NULL); - combo_box->setAllowTextEntry(allow_text_entry, max_chars); - - combo_box->initFromXML(node, parent); - - const std::string& contents = node->getValue(); - - if (contents.find_first_not_of(" \n\t") != contents.npos) - { - llerrs << "Legacy combo box item format used! Please convert to tags!" << llendl; - } - else + if (!acceptsTextInput() && mLabel.empty()) { - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("combo_item")) - { - std::string label = child->getTextContents(); - - std::string value = label; - child->getAttributeString("value", value); - - combo_box->add(label, LLSD(value) ); - } - } + selectFirstItem(); } +} - // if providing user text entry or descriptive label - // don't select an item under the hood - if (!combo_box->acceptsTextInput() && combo_box->mLabel.empty()) +// virtual +BOOL LLComboBox::postBuild() +{ + if (mControlVariable) { - combo_box->selectFirstItem(); + setValue(mControlVariable->getValue()); // selects the appropriate item } + return TRUE; +} - return combo_box; + +LLComboBox::~LLComboBox() +{ + // children automatically deleted, including mMenu, mButton } + void LLComboBox::setEnabled(BOOL enabled) { LLView::setEnabled(enabled); @@ -237,6 +201,7 @@ void LLComboBox::onCommit() mTextEntry->setValue(getSimple()); mTextEntry->setTentative(FALSE); } + setControlValue(getValue()); LLUICtrl::onCommit(); } @@ -431,6 +396,7 @@ BOOL LLComboBox::remove(S32 index) if (index < mList->getItemCount()) { mList->deleteSingleItem(index); + setLabel(mList->getSelectedItemLabel()); return TRUE; } return FALSE; @@ -448,21 +414,17 @@ void LLComboBox::onFocusLost() LLUICtrl::onFocusLost(); } -void LLComboBox::onLostTop() -{ - hideList(); -} - - void LLComboBox::setButtonVisible(BOOL visible) { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); + mButton->setVisible(visible); if (mTextEntry) { LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); if (visible) { - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); + text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; } //mTextEntry->setRect(text_entry_rect); mTextEntry->reshape(text_entry_rect.getWidth(), text_entry_rect.getHeight(), TRUE); @@ -498,54 +460,47 @@ S32 LLComboBox::getCurrentIndex() const } -void LLComboBox::updateLayout() +void LLComboBox::createLineEditor(const LLComboBox::Params& p) { + static LLUICachedControl drop_shadow_button ("DropShadowButton", 0); LLRect rect = getLocalRect(); if (mAllowTextEntry) { - S32 shadow_size = LLUI::sConfigGroup->getS32("DropShadowButton"); + S32 shadow_size = drop_shadow_button; mButton->setRect(LLRect( getRect().getWidth() - llmax(8,mArrowImage->getWidth()) - 2 * shadow_size, rect.mTop, rect.mRight, rect.mBottom)); mButton->setTabStop(FALSE); + mButton->setHAlign(LLFontGL::HCENTER); - if (!mTextEntry) - { - LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); - text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * LLUI::sConfigGroup->getS32("DropShadowButton"); - // clear label on button - std::string cur_label = mButton->getLabelSelected(); - mTextEntry = new LLLineEditor(std::string("combo_text_entry"), - text_entry_rect, - LLStringUtil::null, - LLFontGL::getFontSansSerifSmall(), - mMaxChars, - onTextCommit, - onTextEntry, - NULL, - this); - mTextEntry->setSelectAllonFocusReceived(TRUE); - mTextEntry->setHandleEditKeysDirectly(TRUE); - mTextEntry->setCommitOnFocusLost(FALSE); - mTextEntry->setText(cur_label); - mTextEntry->setIgnoreTab(TRUE); - mTextEntry->setFollowsAll(); - addChild(mTextEntry); - } - else - { - mTextEntry->setVisible(TRUE); - mTextEntry->setMaxTextLength(mMaxChars); - } + LLRect text_entry_rect(0, getRect().getHeight(), getRect().getWidth(), 0); + text_entry_rect.mRight -= llmax(8,mArrowImage->getWidth()) + 2 * drop_shadow_button; + // clear label on button + std::string cur_label = mButton->getLabelSelected(); + LLLineEditor::Params params = p.combo_editor; + params.rect(text_entry_rect); + params.default_text(LLStringUtil::null); + params.max_length_bytes(mMaxChars); + params.commit_callback.function(boost::bind(&LLComboBox::onTextCommit, this, _2)); + params.keystroke_callback(boost::bind(&LLComboBox::onTextEntry, this, _1)); + params.focus_lost_callback(NULL); + params.handle_edit_keys_directly(true); + params.commit_on_focus_lost(false); + params.follows.flags(FOLLOWS_ALL); + mTextEntry = LLUICtrlFactory::create (params); + mTextEntry->setText(cur_label); + mTextEntry->setIgnoreTab(TRUE); + addChild(mTextEntry); // clear label on button setLabel(LLStringUtil::null); mButton->setFollows(FOLLOWS_BOTTOM | FOLLOWS_TOP | FOLLOWS_RIGHT); } - else if (!mAllowTextEntry) + else { mButton->setRect(rect); mButton->setTabStop(TRUE); + mButton->setHAlign(LLFontGL::LEFT); if (mTextEntry) { @@ -672,7 +627,7 @@ void LLComboBox::hideList() mButton->setToggleState(FALSE); mList->setVisible(FALSE); - mList->highlightNthItem(-1); + mList->mouseOverHighlightNthItem(-1); setUseBoundingRect(FALSE); if( gFocusMgr.getTopCtrl() == this ) @@ -681,74 +636,71 @@ void LLComboBox::hideList() } } -//------------------------------------------------------------------ -// static functions -//------------------------------------------------------------------ - -// static -void LLComboBox::onButtonDown(void *userdata) +void LLComboBox::onButtonDown() { - LLComboBox *self = (LLComboBox *)userdata; - - if (!self->mList->getVisible()) + if (!mList->getVisible()) { - LLScrollListItem* last_selected_item = self->mList->getLastSelectedItem(); + LLScrollListItem* last_selected_item = mList->getLastSelectedItem(); if (last_selected_item) { // highlight the original selection before potentially selecting a new item - self->mList->highlightNthItem(self->mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } - if( self->mPrearrangeCallback ) - { - self->mPrearrangeCallback( self, self->mCallbackUserData ); - } + prearrangeList(); - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } - self->setFocus( TRUE ); + setFocus( TRUE ); // pass mouse capture on to list if button is depressed - if (self->mButton->hasMouseCapture()) + if (mButton->hasMouseCapture()) { - gFocusMgr.setMouseCapture(self->mList); + gFocusMgr.setMouseCapture(mList); } } else { - self->hideList(); + hideList(); } } -// static -void LLComboBox::onItemSelected(LLUICtrl* item, void *userdata) -{ - // Note: item is the LLScrollListCtrl - LLComboBox *self = (LLComboBox *) userdata; - const std::string name = self->mList->getSelectedItemLabel(); +//------------------------------------------------------------------ +// static functions +//------------------------------------------------------------------ + +void LLComboBox::onItemSelected(const LLSD& data) +{ + const std::string name = mList->getSelectedItemLabel(); - S32 cur_id = self->getCurrentIndex(); + S32 cur_id = getCurrentIndex(); if (cur_id != -1) { - self->setLabel(name); + setLabel(name); - if (self->mAllowTextEntry) + if (mAllowTextEntry) { - gFocusMgr.setKeyboardFocus(self->mTextEntry); - self->mTextEntry->selectAll(); + gFocusMgr.setKeyboardFocus(mTextEntry); + mTextEntry->selectAll(); } } // hiding the list reasserts the old value stored in the text editor/dropdown button - self->hideList(); + hideList(); // commit does the reverse, asserting the value in the list - self->onCommit(); + onCommit(); + + // call the callback if it exists + if(mSelectionCallback) + { + mSelectionCallback(this, data); + } } BOOL LLComboBox::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_screen) @@ -804,7 +756,7 @@ BOOL LLComboBox::handleKeyHere(KEY key, MASK mask) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleKeyHere(key, mask); @@ -838,7 +790,7 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) if (last_selected_item) { // highlight the original selection before potentially selecting a new item - mList->highlightNthItem(mList->getItemIndex(last_selected_item)); + mList->mouseOverHighlightNthItem(mList->getItemIndex(last_selected_item)); } result = mList->handleUnicodeCharHere(uni_char); if (mList->getLastSelectedItem() != last_selected_item) @@ -850,46 +802,35 @@ BOOL LLComboBox::handleUnicodeCharHere(llwchar uni_char) return result; } -void LLComboBox::setAllowTextEntry(BOOL allow, S32 max_chars, BOOL set_tentative) -{ - mAllowTextEntry = allow; - mTextEntryTentative = set_tentative; - mMaxChars = max_chars; - - updateLayout(); -} - void LLComboBox::setTextEntry(const LLStringExplicit& text) { if (mTextEntry) { mTextEntry->setText(text); + mHasAutocompletedText = FALSE; updateSelection(); } } -//static -void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) +void LLComboBox::onTextEntry(LLLineEditor* line_editor) { - LLComboBox* self = (LLComboBox*)user_data; - - if (self->mTextEntryCallback) + if (mTextEntryCallback != NULL) { - (*self->mTextEntryCallback)(line_editor, self->mCallbackUserData); + (mTextEntryCallback)(line_editor, LLSD()); } KEY key = gKeyboard->currentKey(); if (key == KEY_BACKSPACE || key == KEY_DELETE) { - if (self->mList->selectItemByLabel(line_editor->getText(), FALSE)) + if (mList->selectItemByLabel(line_editor->getText(), FALSE)) { line_editor->setTentative(FALSE); } else { - line_editor->setTentative(self->mTextEntryTentative); - self->mList->deselectAllItems(); + line_editor->setTentative(mTextEntryTentative); + mList->deselectAllItems(); } return; } @@ -902,17 +843,14 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) if (key == KEY_DOWN) { - self->setCurrentByIndex(llmin(self->getItemCount() - 1, self->getCurrentIndex() + 1)); - if (!self->mList->getVisible()) + setCurrentByIndex(llmin(getItemCount() - 1, getCurrentIndex() + 1)); + if (!mList->getVisible()) { - if( self->mPrearrangeCallback ) - { - self->mPrearrangeCallback( self, self->mCallbackUserData ); - } + prearrangeList(); - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } } line_editor->selectAll(); @@ -920,17 +858,14 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) } else if (key == KEY_UP) { - self->setCurrentByIndex(llmax(0, self->getCurrentIndex() - 1)); - if (!self->mList->getVisible()) + setCurrentByIndex(llmax(0, getCurrentIndex() - 1)); + if (!mList->getVisible()) { - if( self->mPrearrangeCallback ) - { - self->mPrearrangeCallback( self, self->mCallbackUserData ); - } + prearrangeList(); - if (self->mList->getItemCount() != 0) + if (mList->getItemCount() != 0) { - self->showList(); + showList(); } } line_editor->selectAll(); @@ -939,7 +874,7 @@ void LLComboBox::onTextEntry(LLLineEditor* line_editor, void* user_data) else { // RN: presumably text entry - self->updateSelection(); + updateSelection(); } } @@ -948,7 +883,7 @@ void LLComboBox::updateSelection() LLWString left_wstring = mTextEntry->getWText().substr(0, mTextEntry->getCursor()); // user-entered portion of string, based on assumption that any selected // text was a result of auto-completion - LLWString user_wstring = mTextEntry->hasSelection() ? left_wstring : mTextEntry->getWText(); + LLWString user_wstring = mHasAutocompletedText ? left_wstring : mTextEntry->getWText(); std::string full_string = mTextEntry->getText(); // go ahead and arrange drop down list on first typed character, even @@ -956,23 +891,14 @@ void LLComboBox::updateSelection() // callback to populate content if( mTextEntry->getWText().size() == 1 ) { - if (mPrearrangeCallback) - { - mPrearrangeCallback( this, mCallbackUserData ); - } + prearrangeList(mTextEntry->getText()); } if (mList->selectItemByLabel(full_string, FALSE)) { mTextEntry->setTentative(FALSE); } - else if (!mList->selectItemByPrefix(left_wstring, FALSE)) - { - mList->deselectAllItems(); - mTextEntry->setText(wstring_to_utf8str(user_wstring)); - mTextEntry->setTentative(mTextEntryTentative); - } - else + else if (mList->selectItemByPrefix(left_wstring, FALSE)) { LLWString selected_item = utf8str_to_wstring(mList->getSelectedItemLabel()); LLWString wtext = left_wstring + selected_item.substr(left_wstring.size(), selected_item.size()); @@ -980,17 +906,23 @@ void LLComboBox::updateSelection() mTextEntry->setSelection(left_wstring.size(), mTextEntry->getWText().size()); mTextEntry->endSelection(); mTextEntry->setTentative(FALSE); + mHasAutocompletedText = TRUE; + } + else // no matching items found + { + mList->deselectAllItems(); + mTextEntry->setText(wstring_to_utf8str(user_wstring)); // removes text added by autocompletion + mTextEntry->setTentative(mTextEntryTentative); + mHasAutocompletedText = FALSE; } } -//static -void LLComboBox::onTextCommit(LLUICtrl* caller, void* user_data) +void LLComboBox::onTextCommit(const LLSD& data) { - LLComboBox* self = (LLComboBox*)user_data; - std::string text = self->mTextEntry->getText(); - self->setSimple(text); - self->onCommit(); - self->mTextEntry->selectAll(); + std::string text = mTextEntry->getText(); + setSimple(text); + onCommit(); + mTextEntry->selectAll(); } void LLComboBox::setFocus(BOOL b) @@ -1007,6 +939,14 @@ void LLComboBox::setFocus(BOOL b) } } +void LLComboBox::prearrangeList(std::string filter) +{ + if (mPrearrangeCallback) + { + mPrearrangeCallback(this, LLSD(filter)); + } +} + //============================================================================ // LLCtrlListInterface functions @@ -1114,155 +1054,3 @@ BOOL LLComboBox::selectItemRange( S32 first, S32 last ) { return mList->selectItemRange(first, last); } - - -// -// LLFlyoutButton -// - -static LLRegisterWidget r2("flyout_button"); - -const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; - -LLFlyoutButton::LLFlyoutButton( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) , - void *callback_userdata) -: LLComboBox(name, rect, LLStringUtil::null, commit_callback, callback_userdata), - mToggleState(FALSE), - mActionButton(NULL) -{ - // Always use text box - // Text label button - mActionButton = new LLButton(label, - LLRect(), LLStringUtil::null, NULL, this); - mActionButton->setScaleImage(TRUE); - - mActionButton->setClickedCallback(onActionButtonClick); - mActionButton->setFollowsAll(); - mActionButton->setHAlign( LLFontGL::HCENTER ); - mActionButton->setLabel(label); - addChild(mActionButton); - - mActionButtonImage = LLUI::getUIImage("flyout_btn_left.tga"); - mExpanderButtonImage = LLUI::getUIImage("flyout_btn_right.tga"); - mActionButtonImageSelected = LLUI::getUIImage("flyout_btn_left_selected.tga"); - mExpanderButtonImageSelected = LLUI::getUIImage("flyout_btn_right_selected.tga"); - mActionButtonImageDisabled = LLUI::getUIImage("flyout_btn_left_disabled.tga"); - mExpanderButtonImageDisabled = LLUI::getUIImage("flyout_btn_right_disabled.tga"); - - mActionButton->setImageSelected(mActionButtonImageSelected); - mActionButton->setImageUnselected(mActionButtonImage); - mActionButton->setImageDisabled(mActionButtonImageDisabled); - mActionButton->setImageDisabledSelected(LLPointer(NULL)); - - mButton->setImageSelected(mExpanderButtonImageSelected); - mButton->setImageUnselected(mExpanderButtonImage); - mButton->setImageDisabled(mExpanderButtonImageDisabled); - mButton->setImageDisabledSelected(LLPointer(NULL)); - mButton->setRightHPad(6); - - updateLayout(); -} - -//static -LLView* LLFlyoutButton::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name = "flyout_button"; - node->getAttributeString("name", name); - - std::string label(""); - node->getAttributeString("label", label); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - LLUICtrlCallback callback = NULL; - - LLFlyoutButton* flyout_button = new LLFlyoutButton(name, - rect, - label, - callback, - NULL); - - std::string list_position; - node->getAttributeString("list_position", list_position); - if (list_position == "below") - { - flyout_button->mListPosition = BELOW; - } - else if (list_position == "above") - { - flyout_button->mListPosition = ABOVE; - } - - - flyout_button->initFromXML(node, parent); - - LLXMLNodePtr child; - for (child = node->getFirstChild(); child.notNull(); child = child->getNextSibling()) - { - if (child->hasName("flyout_button_item")) - { - std::string label = child->getTextContents(); - - std::string value = label; - child->getAttributeString("value", value); - - flyout_button->add(label, LLSD(value) ); - } - } - - flyout_button->updateLayout(); - - return flyout_button; -} - -void LLFlyoutButton::updateLayout() -{ - LLComboBox::updateLayout(); - - mButton->setOrigin(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0); - mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); - mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); - mButton->setTabStop(FALSE); - mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT); - - mActionButton->setOrigin(0, 0); - mActionButton->reshape(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); -} - -//static -void LLFlyoutButton::onActionButtonClick(void *user_data) -{ - LLFlyoutButton* buttonp = (LLFlyoutButton*)user_data; - // remember last list selection? - buttonp->mList->deselect(); - buttonp->onCommit(); -} - -void LLFlyoutButton::draw() -{ - mActionButton->setToggleState(mToggleState); - mButton->setToggleState(mToggleState); - - //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or - // the label reflects the last selected item, for now we have to manually remove the label - mButton->setLabel(LLStringUtil::null); - LLComboBox::draw(); -} - -void LLFlyoutButton::setEnabled(BOOL enabled) -{ - mActionButton->setEnabled(enabled); - LLComboBox::setEnabled(enabled); -} - - -void LLFlyoutButton::setToggleState(BOOL state) -{ - mToggleState = state; -} - diff --git a/indra/llui/llcombobox.h b/indra/llui/llcombobox.h index 33e1baa748..bc98690a01 100644 --- a/indra/llui/llcombobox.h +++ b/indra/llui/llcombobox.h @@ -41,14 +41,13 @@ #include "llctrlselectioninterface.h" #include "llimagegl.h" #include "llrect.h" +#include "llscrolllistctrl.h" +#include "lllineeditor.h" +#include // Classes class LLFontGL; -class LLButton; -class LLSquareButton; -class LLScrollListCtrl; -class LLLineEditor; class LLViewBorder; extern S32 LLCOMBOBOX_HEIGHT; @@ -57,30 +56,62 @@ extern S32 LLCOMBOBOX_WIDTH; class LLComboBox : public LLUICtrl, public LLCtrlListInterface { -public: +public: typedef enum e_preferred_position { ABOVE, BELOW } EPreferredPosition; - LLComboBox( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void *callback_userdata = NULL - ); - virtual ~LLComboBox(); + struct PreferredPositionValues : public LLInitParam::TypeValuesHelper + { + static void declareValues(); + }; - // LLView interface - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + struct ItemParams : public LLInitParam::Block + { + Optional label; + ItemParams(); + }; + + struct Params + : public LLInitParam::Block + { + Optional allow_text_entry, + show_text_as_tentative; + Optional max_chars; + Optional prearrange_callback, + text_entry_callback, + selection_callback; + Optional arrow_image; + + Optional list_position; + + // components + Optional combo_button; + Optional combo_list; + Optional combo_editor; + + Multiple items; + + Params(); + }; + + virtual ~LLComboBox(); + /*virtual*/ BOOL postBuild(); + +protected: + friend class LLUICtrlFactory; + LLComboBox(const Params&); + void initFromParams(const Params&); + void prearrangeList(std::string filter = ""); + +public: + // LLView interface virtual void draw(); virtual void onFocusLost(); - virtual void onLostTop(); virtual void setEnabled(BOOL enabled); @@ -105,7 +136,6 @@ public: // items, this is just the label. virtual LLSD getValue() const; - void setAllowTextEntry(BOOL allow, S32 max_chars = 50, BOOL make_tentative = TRUE); void setTextEntry(const LLStringExplicit& text); LLScrollListItem* add(const std::string& name, EAddPosition pos = ADD_BOTTOM, BOOL enabled = TRUE); // add item "name" to menu @@ -134,7 +164,7 @@ public: BOOL setCurrentByIndex( S32 index ); S32 getCurrentIndex() const; - virtual void updateLayout(); + void createLineEditor(const Params&); //======================================================================== LLCtrlSelectionInterface* getSelectionInterface() { return (LLCtrlSelectionInterface*)this; }; @@ -170,66 +200,45 @@ public: void* getCurrentUserdata(); - void setPrearrangeCallback( void (*cb)(LLUICtrl*,void*) ) { mPrearrangeCallback = cb; } - void setTextEntryCallback( void (*cb)(LLLineEditor*, void*) ) { mTextEntryCallback = cb; } + void setPrearrangeCallback( commit_callback_t cb ) { mPrearrangeCallback = cb; } + void setTextEntryCallback( commit_callback_t cb ) { mTextEntryCallback = cb; } + void setSelectionCallback( commit_callback_t cb ) { mSelectionCallback = cb; } void setButtonVisible(BOOL visible); - static void onButtonDown(void *userdata); - static void onItemSelected(LLUICtrl* item, void *userdata); - static void onTextEntry(LLLineEditor* line_editor, void* user_data); - static void onTextCommit(LLUICtrl* caller, void* user_data); + void onButtonDown(); + void onItemSelected(const LLSD& data); + void onTextCommit(const LLSD& data); void updateSelection(); virtual void showList(); virtual void hideList(); - + + virtual void onTextEntry(LLLineEditor* line_editor); + protected: LLButton* mButton; + LLLineEditor* mTextEntry; LLScrollListCtrl* mList; EPreferredPosition mListPosition; LLPointer mArrowImage; - std::string mLabel; + LLUIString mLabel; + BOOL mHasAutocompletedText; private: - S32 mButtonPadding; - LLLineEditor* mTextEntry; BOOL mAllowTextEntry; S32 mMaxChars; BOOL mTextEntryTentative; - void (*mPrearrangeCallback)(LLUICtrl*,void*); - void (*mTextEntryCallback)(LLLineEditor*, void*); + commit_callback_t mPrearrangeCallback; + commit_callback_t mTextEntryCallback; + commit_callback_t mSelectionCallback; }; -class LLFlyoutButton : public LLComboBox -{ -public: - LLFlyoutButton( - const std::string& name, - const LLRect &rect, - const std::string& label, - void (*commit_callback)(LLUICtrl*, void*) = NULL, - void *callback_userdata = NULL); - - virtual void updateLayout(); - virtual void draw(); - virtual void setEnabled(BOOL enabled); - - void setToggleState(BOOL state); - - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - static void onActionButtonClick(void *userdata); - static void onSelectAction(LLUICtrl* ctrl, void *userdata); - -protected: - LLButton* mActionButton; - LLPointer mActionButtonImage; - LLPointer mExpanderButtonImage; - LLPointer mActionButtonImageSelected; - LLPointer mExpanderButtonImageSelected; - LLPointer mActionButtonImageDisabled; - LLPointer mExpanderButtonImageDisabled; - BOOL mToggleState; -}; +#ifdef LL_WINDOWS +#ifndef INSTANTIATE_GETCHILD_COMBOBOX +#pragma warning (disable : 4231) +extern template LLComboBox* LLView::getChild( const std::string& name, BOOL recurse, BOOL create_if_missing ) const; +#endif +#endif #endif diff --git a/indra/llui/llconsole.cpp b/indra/llui/llconsole.cpp new file mode 100644 index 0000000000..f1fc3d8f43 --- /dev/null +++ b/indra/llui/llconsole.cpp @@ -0,0 +1,393 @@ +/** + * @file llconsole.cpp + * @brief a scrolling console output device + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +#include "llconsole.h" + +// linden library includes +#include "llmath.h" +//#include "llviewercontrol.h" +#include "llcriticaldamp.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llui.h" +#include "lluiimage.h" +//#include "llviewerimage.h" +//#include "llviewerimagelist.h" +//#include "llviewerwindow.h" +#include "llsd.h" +#include "llfontgl.h" +#include "llmath.h" + +//#include "llstartup.h" + +// Used for LCD display +extern void AddNewDebugConsoleToLCD(const LLWString &newLine); + +LLConsole* gConsole = NULL; // Created and destroyed in LLViewerWindow. + +const F32 FADE_DURATION = 2.f; +const S32 MIN_CONSOLE_WIDTH = 200; + +LLConsole::LLConsole(const LLConsole::Params& p) +: LLView(p), + LLFixedBuffer(p.max_lines), + mLinePersistTime(p.persist_time), // seconds + mFont(p.font) +{ + if (p.font_size_index.isProvided()) + { + setFontSize(p.font_size_index); + } + mFadeTime = mLinePersistTime - FADE_DURATION; + setMaxLines(LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")); +} + +void LLConsole::setLinePersistTime(F32 seconds) +{ + mLinePersistTime = seconds; + mFadeTime = mLinePersistTime - FADE_DURATION; +} + +void LLConsole::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + S32 new_width = llmax(50, llmin(getRect().getWidth(), width)); + S32 new_height = llmax(llfloor(mFont->getLineHeight()) + 15, llmin(getRect().getHeight(), height)); + + if ( mConsoleWidth == new_width + && mConsoleHeight == new_height ) + { + return; + } + + mConsoleWidth = new_width; + mConsoleHeight= new_height; + + LLView::reshape(new_width, new_height, called_from_parent); + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } +} + +void LLConsole::setFontSize(S32 size_index) +{ + if (-1 == size_index) + { + mFont = LLFontGL::getFontMonospace(); + } + else if (0 == size_index) + { + mFont = LLFontGL::getFontSansSerif(); + } + else if (1 == size_index) + { + mFont = LLFontGL::getFontSansSerifBig(); + } + else + { + mFont = LLFontGL::getFontSansSerifHuge(); + } + + for(paragraph_t::iterator paragraph_it = mParagraphs.begin(); paragraph_it != mParagraphs.end(); paragraph_it++) + { + (*paragraph_it).updateLines((F32)getRect().getWidth(), mFont, true); + } +} + +void LLConsole::draw() +{ + LLGLSUIDefault gls_ui; + + // skip lines added more than mLinePersistTime ago + F32 cur_time = mTimer.getElapsedTimeF32(); + + F32 skip_time = cur_time - mLinePersistTime; + F32 fade_time = cur_time - mFadeTime; + + if (mParagraphs.empty()) //No text to draw. + { + return; + } + + U32 num_lines=0; + + paragraph_t::reverse_iterator paragraph_it; + paragraph_it = mParagraphs.rbegin(); + U32 paragraph_num=mParagraphs.size(); + + while (!mParagraphs.empty() && paragraph_it != mParagraphs.rend()) + { + num_lines += (*paragraph_it).mLines.size(); + if(num_lines > mMaxLines + || ( (mLinePersistTime > (F32)0.f) && ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime) <= (F32)0.f)) + { //All lines above here are done. Lose them. + for (U32 i=0;igetF32("ConsoleBackgroundOpacity"), 0.f, 1.f); +// LLColor4 color = gSavedSkinSettings.getColor("ConsoleBackground"); + LLColor4 color = LLUI::sSettingGroups["color"]->getColor("ConsoleBackground"); + color.mV[VALPHA] *= console_opacity; + + F32 line_height = mFont->getLineHeight(); + + for(paragraph_it = mParagraphs.rbegin(); paragraph_it != mParagraphs.rend(); paragraph_it++) + { + S32 target_height = llfloor( (*paragraph_it).mLines.size() * line_height + 8); + S32 target_width = llfloor( (*paragraph_it).mMaxWidth +15); + + y_pos += ((*paragraph_it).mLines.size()) * line_height; + imagep->drawSolid(-14, (S32)(y_pos + line_height - target_height), target_width, target_height, color); + + F32 y_off=0; + + F32 alpha; + + if ((mLinePersistTime > 0.f) && ((*paragraph_it).mAddTime < fade_time)) + { + alpha = ((*paragraph_it).mAddTime - skip_time)/(mLinePersistTime - mFadeTime); + } + else + { + alpha = 1.0f; + } + + if( alpha > 0.f ) + { + for (lines_t::iterator line_it=(*paragraph_it).mLines.begin(); + line_it != (*paragraph_it).mLines.end(); + line_it ++) + { + for (line_color_segments_t::iterator seg_it = (*line_it).mLineColorSegments.begin(); + seg_it != (*line_it).mLineColorSegments.end(); + seg_it++) + { + mFont->render((*seg_it).mText, 0, (*seg_it).mXPosition - 8, y_pos - y_off, + LLColor4( + (*seg_it).mColor.mV[VRED], + (*seg_it).mColor.mV[VGREEN], + (*seg_it).mColor.mV[VBLUE], + (*seg_it).mColor.mV[VALPHA]*alpha), + LLFontGL::LEFT, + LLFontGL::BASELINE, + LLFontGL::NORMAL, + LLFontGL::DROP_SHADOW, + S32_MAX, + target_width + ); + } + y_off += line_height; + } + } + y_pos += 8; + } +} + +void LLConsole::addLine(const std::string& utf8line) +{ + LLWString wline = utf8str_to_wstring(utf8line); + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); +} + +void LLConsole::addLine(const LLWString& wline) +{ + addLine(wline, 0.f, LLColor4(1.f, 1.f, 1.f, 1.f)); +} + +void LLConsole::addLine(const std::string& utf8line, F32 size, const LLColor4 &color) +{ + LLWString wline = utf8str_to_wstring(utf8line); + addLine(wline, size, color); +} + +//Generate highlight color segments for this paragraph. Pass in default color of paragraph. +void LLConsole::Paragraph::makeParagraphColorSegments (const LLColor4 &color) +{ + LLSD paragraph_color_segments; + LLColor4 lcolor=color; + + paragraph_color_segments[0]["text"] =wstring_to_utf8str(mParagraphText); + LLSD color_sd = color.getValue(); + paragraph_color_segments[0]["color"]=color_sd; + + for(LLSD::array_const_iterator color_segment_it = paragraph_color_segments.beginArray(); + color_segment_it != paragraph_color_segments.endArray(); + ++color_segment_it) + { + LLSD color_llsd = (*color_segment_it)["color"]; + std::string color_str = (*color_segment_it)["text"].asString(); + + ParagraphColorSegment color_segment; + + color_segment.mColor.setValue(color_llsd); + color_segment.mNumChars = color_str.length(); + + mParagraphColorSegments.push_back(color_segment); + } +} + +//Called when a paragraph is added to the console or window is resized. +void LLConsole::Paragraph::updateLines(F32 screen_width, const LLFontGL* font, bool force_resize) +{ + if ( !force_resize ) + { + if ( mMaxWidth >= 0.0f + && mMaxWidth < screen_width ) + { + return; //No resize required. + } + } + + screen_width = screen_width - 30; //Margin for small windows. + + if ( mParagraphText.empty() + || mParagraphColorSegments.empty() + || font == NULL) + { + return; //Not enough info to complete. + } + + mLines.clear(); //Chuck everything. + mMaxWidth = 0.0f; + + paragraph_color_segments_t::iterator current_color = mParagraphColorSegments.begin(); + U32 current_color_length = (*current_color).mNumChars; + + S32 paragraph_offset = 0; //Offset into the paragraph text. + + // Wrap lines that are longer than the view is wide. + while( paragraph_offset < (S32)mParagraphText.length() ) + { + S32 skip_chars; // skip '\n' + // Figure out if a word-wrapped line fits here. + LLWString::size_type line_end = mParagraphText.find_first_of(llwchar('\n'), paragraph_offset); + if (line_end != LLWString::npos) + { + skip_chars = 1; // skip '\n' + } + else + { + line_end = mParagraphText.size(); + skip_chars = 0; + } + + U32 drawable = font->maxDrawableChars(mParagraphText.c_str()+paragraph_offset, screen_width, line_end - paragraph_offset, TRUE); + + if (drawable != 0) + { + F32 x_position = 0; //Screen X position of text. + + mMaxWidth = llmax( mMaxWidth, (F32)font->getWidth( mParagraphText.substr( paragraph_offset, drawable ).c_str() ) ); + Line line; + + U32 left_to_draw = drawable; + U32 drawn = 0; + + while (left_to_draw >= current_color_length + && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, current_color_length ); + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + x_position += font->getWidth( color_text.c_str() ); //Set up next screen position. + + drawn += current_color_length; + left_to_draw -= current_color_length; + + current_color++; //Goto next paragraph color record. + + if (current_color != mParagraphColorSegments.end()) + { + current_color_length = (*current_color).mNumChars; + } + } + + if (left_to_draw > 0 && current_color != mParagraphColorSegments.end() ) + { + LLWString color_text = mParagraphText.substr( paragraph_offset + drawn, left_to_draw ); + + line.mLineColorSegments.push_back( LineColorSegment( color_text, //Append segment to line. + (*current_color).mColor, + x_position ) ); + + current_color_length -= left_to_draw; + } + mLines.push_back(line); //Append line to paragraph line list. + } + paragraph_offset += (drawable + skip_chars); + } +} + +//Pass in the string and the default color for this block of text. +LLConsole::Paragraph::Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width) + : mParagraphText(str), mAddTime(add_time), mMaxWidth(-1) +{ + makeParagraphColorSegments(color); + updateLines( screen_width, font ); +} + +void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) +{ + Paragraph paragraph(wline, color, mTimer.getElapsedTimeF32(), mFont, (F32)getRect().getWidth() ); + + mParagraphs.push_back ( paragraph ); + +#if LL_WINDOWS && LL_LCD_COMPILE + // add to LCD screen + AddNewDebugConsoleToLCD(wline); +#endif +} diff --git a/indra/llui/llconsole.h b/indra/llui/llconsole.h new file mode 100644 index 0000000000..65149b217f --- /dev/null +++ b/indra/llui/llconsole.h @@ -0,0 +1,162 @@ +/** + * @file llconsole.h + * @brief a simple console-style output device + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONSOLE_H +#define LL_LLCONSOLE_H + +#include "llfixedbuffer.h" +#include "llview.h" +#include "v4color.h" +#include + +class LLFontGL; +class LLSD; + +class LLConsole : public LLFixedBuffer, public LLView +{ +public: + typedef enum e_font_size + { + MONOSPACE = -1, + SMALL = 0, + BIG = 1 + } EFontSize; + + struct Params : public LLInitParam::Block + { + Optional max_lines; + Optional persist_time; + Optional font_size_index; + Params() + : max_lines("max_lines", LLUI::sSettingGroups["config"]->getS32("ConsoleMaxLines")), + persist_time("persist_time", 0.f) // forever + { + mouse_opaque(false); + } + }; +protected: + LLConsole(const Params&); + friend class LLUICtrlFactory; + +public: + //A paragraph color segment defines the color of text in a line + //of text that was received for console display. It has no + //notion of line wraps, screen position, or the text it contains. + //It is only the number of characters that are a color and the + //color. + struct ParagraphColorSegment + { + S32 mNumChars; + LLColor4 mColor; + }; + + //A line color segment is a chunk of text, the color associated + //with it, and the X Position it was calculated to begin at + //on the screen. X Positions are re-calculated if the + //screen changes size. + class LineColorSegment + { + public: + LineColorSegment(LLWString text, LLColor4 color, F32 xpos) : mText(text), mColor(color), mXPosition(xpos) {} + public: + LLWString mText; + LLColor4 mColor; + F32 mXPosition; + }; + + typedef std::list line_color_segments_t; + + //A line is composed of one or more color segments. + class Line + { + public: + line_color_segments_t mLineColorSegments; + }; + + typedef std::list lines_t; + typedef std::list paragraph_color_segments_t; + + //A paragraph is a processed element containing the entire text of the + //message (used for recalculating positions on screen resize) + //The time this message was added to the console output + //The visual screen width of the longest line in this block + //And a list of one or more lines which are used to display this message. + class Paragraph + { + public: + Paragraph (LLWString str, const LLColor4 &color, F32 add_time, const LLFontGL* font, F32 screen_width); + void makeParagraphColorSegments ( const LLColor4 &color); + void updateLines ( F32 screen_width, const LLFontGL* font, bool force_resize=false ); + public: + LLWString mParagraphText; //The entire text of the paragraph + paragraph_color_segments_t mParagraphColorSegments; + F32 mAddTime; //Time this paragraph was added to the display. + F32 mMaxWidth; //Width of the widest line of text in this paragraph. + lines_t mLines; + + }; + + //The console contains a deque of paragraphs which represent the individual messages. + typedef std::deque paragraph_t; + paragraph_t mParagraphs; + + ~LLConsole(){}; + + // each line lasts this long after being added + void setLinePersistTime(F32 seconds); + + void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + + // -1 = monospace, 0 means small, font size = 1 means big + void setFontSize(S32 size_index); + + void addLine(const std::string& utf8line, F32 size, const LLColor4 &color); + void addLine(const LLWString& wline, F32 size, const LLColor4 &color); + + // Overrides + /*virtual*/ void draw(); + /*virtual*/ void addLine(const std::string& utf8line); + /*virtual*/ void addLine(const LLWString& line); +private: + F32 mLinePersistTime; // Age at which to stop drawing. + F32 mFadeTime; // Age at which to start fading + const LLFontGL* mFont; + S32 mLastBoxHeight; + S32 mLastBoxWidth; + S32 mConsoleWidth; + S32 mConsoleHeight; + +}; + +extern LLConsole* gConsole; + +#endif diff --git a/indra/llui/llcontainerview.cpp b/indra/llui/llcontainerview.cpp new file mode 100644 index 0000000000..40cc430e25 --- /dev/null +++ b/indra/llui/llcontainerview.cpp @@ -0,0 +1,301 @@ +/** + * @file llcontainerview.cpp + * @brief Container for all statistics info + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +#include "llcontainerview.h" + +#include "llerror.h" +#include "llfontgl.h" +#include "llgl.h" +#include "llui.h" +#include "llstring.h" +#include "llscrollcontainer.h" +#include "lluictrlfactory.h" + +static LLDefaultWidgetRegistry::Register r("container_view"); + +LLContainerView::LLContainerView(const LLContainerView::Params& p) +: LLView(p), + mShowLabel(p.show_label), + mLabel(p.label), + mDisplayChildren(p.display_children) +{ + mCollapsible = TRUE; + mScrollContainer = NULL; +} + +LLContainerView::~LLContainerView() +{ + // Children all cleaned up by default view destructor. +} + +BOOL LLContainerView::postBuild() +{ + setDisplayChildren(mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + return TRUE; +} + +bool LLContainerView::addChild(LLView* child, S32 tab_group) +{ + bool res = LLView::addChild(child, tab_group); + if (res) + { + sendChildToBack(child); + } + return res; +} + +BOOL LLContainerView::handleMouseDown(S32 x, S32 y, MASK mask) +{ + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseDown(x, y, mask) != NULL); + } + if (!handled) + { + if( mCollapsible && mShowLabel && (y >= getRect().getHeight() - 10) ) + { + setDisplayChildren(!mDisplayChildren); + reshape(getRect().getWidth(), getRect().getHeight(), FALSE); + handled = TRUE; + } + } + return handled; +} + +BOOL LLContainerView::handleMouseUp(S32 x, S32 y, MASK mask) +{ + BOOL handled = FALSE; + if (mDisplayChildren) + { + handled = (LLView::childrenHandleMouseUp(x, y, mask) != NULL); + } + return handled; +} + + +void LLContainerView::draw() +{ + { + gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); + + gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0, LLColor4(0.f, 0.f, 0.f, 0.25f)); + } + + // Draw the label + if (mShowLabel) + { + LLFontGL::getFontMonospace()->renderUTF8( + mLabel, 0, 2, getRect().getHeight() - 2, LLColor4(1,1,1,1), LLFontGL::LEFT, LLFontGL::TOP); + } + + LLView::draw(); +} + + +void LLContainerView::reshape(S32 width, S32 height, BOOL called_from_parent) +{ + S32 desired_width = width; + S32 desired_height = height; + + if (mScrollContainer) + { + BOOL dum_bool; + mScrollContainer->calcVisibleSize(&desired_width, &desired_height, &dum_bool, &dum_bool); + } + else + { + // if we're uncontained - make height as small as possible + desired_height = 0; + } + + arrange(desired_width, desired_height, called_from_parent); + + // sometimes, after layout, our container will change size (scrollbars popping in and out) + // if so, attempt another layout + if (mScrollContainer) + { + S32 new_container_width; + S32 new_container_height; + BOOL dum_bool; + mScrollContainer->calcVisibleSize(&new_container_width, &new_container_height, &dum_bool, &dum_bool); + + if ((new_container_width != desired_width) || + (new_container_height != desired_height)) // the container size has changed, attempt to arrange again + { + arrange(new_container_width, new_container_height, called_from_parent); + } + } +} + +void LLContainerView::arrange(S32 width, S32 height, BOOL called_from_parent) +{ + // Determine the sizes and locations of all contained views + S32 total_height = 0; + S32 top, left, right, bottom; + //LLView *childp; + + // These will be used for the children + left = 4; + top = getRect().getHeight() - 4; + right = width - 2; + bottom = top; + + // Leave some space for the top label/grab handle + if (mShowLabel) + { + total_height += 20; + } + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + if (!childp->getVisible()) + { + llwarns << "Incorrect visibility!" << llendl; + } + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + total_height += child_height; + } + + if (total_height < height) + total_height = height; + + if (followsTop()) + { + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mBottom = getRect().mTop - total_height; + } + else + { + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mTop = getRect().mBottom + total_height; + } + // HACK: casting away const. Should use setRect or some helper function instead. + const_cast(getRect()).mRight = getRect().mLeft + width; + + top = total_height; + if (mShowLabel) + { + top -= 20; + } + + bottom = top; + + if (mDisplayChildren) + { + // Iterate through all children, and put in container from top down. + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + bottom -= child_rect.getHeight(); + LLRect r(left, bottom + child_rect.getHeight(), right, bottom); + childp->setRect(r); + childp->reshape(right - left, top - bottom); + top = bottom - 2; + bottom = top; + } + } + + if (!called_from_parent) + { + if (getParent()) + { + getParent()->reshape(getParent()->getRect().getWidth(), getParent()->getRect().getHeight(), FALSE); + } + } + +} + +LLRect LLContainerView::getRequiredRect() +{ + LLRect req_rect; + //LLView *childp; + U32 total_height = 0; + + // Determine the sizes and locations of all contained views + + // Leave some space for the top label/grab handle + + if (mShowLabel) + { + total_height = 20; + } + + + if (mDisplayChildren) + { + // Determine total height + U32 child_height = 0; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + LLRect child_rect = childp->getRequiredRect(); + child_height += child_rect.getHeight(); + child_height += 2; + } + + total_height += child_height; + } + req_rect.mTop = total_height; + return req_rect; +} + +void LLContainerView::setLabel(const std::string& label) +{ + mLabel = label; +} + +void LLContainerView::setDisplayChildren(const BOOL displayChildren) +{ + mDisplayChildren = displayChildren; + for (child_list_const_iter_t child_iter = getChildList()->begin(); + child_iter != getChildList()->end(); ++child_iter) + { + LLView *childp = *child_iter; + childp->setVisible(mDisplayChildren); + } +} diff --git a/indra/llui/llcontainerview.h b/indra/llui/llcontainerview.h new file mode 100644 index 0000000000..9f3d1ac7ad --- /dev/null +++ b/indra/llui/llcontainerview.h @@ -0,0 +1,92 @@ +/** + * @file llcontainerview.h + * @brief Container for all statistics info. + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLCONTAINERVIEW_H +#define LL_LLCONTAINERVIEW_H + +#include "stdtypes.h" +#include "lltextbox.h" +#include "llstatbar.h" + +class LLScrollContainer; + +class LLContainerView : public LLView +{ +public: + struct Params : public LLInitParam::Block + { + Optional label; + Optional show_label; + Optional display_children; + Params() + : label("label"), + show_label("show_label", FALSE), + display_children("display_children", TRUE) + { + mouse_opaque(false); + } + }; +protected: + LLContainerView(const Params& p); + friend class LLUICtrlFactory; +public: + ~LLContainerView(); + + /*virtual*/ BOOL postBuild(); + /*virtual*/ bool addChild(LLView* view, S32 tab_group = 0); + + /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); + + /*virtual*/ void draw(); + /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); + /*virtual*/ LLRect getRequiredRect(); // Return the height of this object, given the set options. + + void setLabel(const std::string& label); + void showLabel(BOOL show) { mShowLabel = show; } + void setDisplayChildren(const BOOL displayChildren); + BOOL getDisplayChildren() { return mDisplayChildren; } + void setScrollContainer(LLScrollContainer* scroll) {mScrollContainer = scroll;} + + private: + LLScrollContainer* mScrollContainer; + void arrange(S32 width, S32 height, BOOL called_from_parent = TRUE); + BOOL mShowLabel; + +protected: + BOOL mDisplayChildren; + std::string mLabel; +public: + BOOL mCollapsible; + +}; +#endif // LL_CONTAINERVIEW_ diff --git a/indra/llui/lldraghandle.cpp b/indra/llui/lldraghandle.cpp index 6c92ea1ff7..8ecbdb98e1 100644 --- a/indra/llui/lldraghandle.cpp +++ b/indra/llui/lldraghandle.cpp @@ -43,10 +43,10 @@ #include "llmenugl.h" #include "lltextbox.h" #include "llcontrol.h" -#include "llresmgr.h" #include "llfontgl.h" #include "llwindow.h" #include "llfocusmgr.h" +#include "lluictrlfactory.h" const S32 LEADING_PAD = 5; const S32 TITLE_PAD = 8; @@ -56,21 +56,33 @@ const S32 RIGHT_PAD = BORDER_PAD + 32; // HACK: space for close btn and minimize S32 LLDragHandle::sSnapMargin = 5; -LLDragHandle::LLDragHandle( const std::string& name, const LLRect& rect, const std::string& title ) -: LLView( name, rect, TRUE ), +LLDragHandle::LLDragHandle(const LLDragHandle::Params& p) +: LLView(p), mDragLastScreenX( 0 ), mDragLastScreenY( 0 ), mLastMouseScreenX( 0 ), mLastMouseScreenY( 0 ), - mDragHighlightColor( LLUI::sColorsGroup->getColor( "DefaultHighlightLight" ) ), - mDragShadowColor( LLUI::sColorsGroup->getColor( "DefaultShadowDark" ) ), mTitleBox( NULL ), mMaxTitleWidth( 0 ), - mForeground( TRUE ) + mForeground( TRUE ), + mDragHighlightColor(p.drag_highlight_color()), + mDragShadowColor(p.drag_shadow_color()) + { - sSnapMargin = LLUI::sConfigGroup->getS32("SnapMargin"); + static LLUICachedControl snap_margin ("SnapMargin", 0); + sSnapMargin = snap_margin; +} - setSaveToXML(false); +LLDragHandle::~LLDragHandle() +{ + removeChild(mTitleBox); + delete mTitleBox; +} + +void LLDragHandle::initFromParams(const LLDragHandle::Params& p) +{ + LLView::initFromParams(p); + setTitle( p.label ); } void LLDragHandle::setTitleVisible(BOOL visible) @@ -81,58 +93,47 @@ void LLDragHandle::setTitleVisible(BOOL visible) } } -void LLDragHandle::setTitleBox(LLTextBox* titlebox) -{ +void LLDragHandleTop::setTitle(const std::string& title) +{ + std::string trimmed_title = title; + LLStringUtil::trim(trimmed_title); + if( mTitleBox ) { - removeChild(mTitleBox); - delete mTitleBox; + mTitleBox->setText(trimmed_title); } - mTitleBox = titlebox; - if(mTitleBox) + else { + const LLFontGL* font = LLFontGL::getFontSansSerif(); + LLTextBox::Params params; + params.name("Drag Handle Title"); + params.rect(getRect()); + params.text(trimmed_title); + params.font(font); + params.follows.flags(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); + params.font_shadow(LLFontGL::DROP_SHADOW_SOFT); + mTitleBox = LLUICtrlFactory::create (params); addChild( mTitleBox ); } -} - -LLDragHandleTop::LLDragHandleTop(const std::string& name, const LLRect &rect, const std::string& title) -: LLDragHandle(name, rect, title) -{ - setFollowsAll(); - setTitle( title ); -} - -LLDragHandleLeft::LLDragHandleLeft(const std::string& name, const LLRect &rect, const std::string& title) -: LLDragHandle(name, rect, title) -{ - setFollowsAll(); - setTitle( title ); -} - -void LLDragHandleTop::setTitle(const std::string& title) -{ - std::string trimmed_title = title; - LLStringUtil::trim(trimmed_title); - - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); - LLTextBox* titlebox = new LLTextBox( std::string("Drag Handle Title"), getRect(), trimmed_title, font ); - titlebox->setFollows(FOLLOWS_TOP | FOLLOWS_LEFT | FOLLOWS_RIGHT); - titlebox->setFontStyle(LLFontGL::DROP_SHADOW_SOFT); - setTitleBox(titlebox); reshapeTitleBox(); } const std::string& LLDragHandleTop::getTitle() const { - return getTitleBox() == NULL ? LLStringUtil::null : getTitleBox()->getText(); + return mTitleBox == NULL ? LLStringUtil::null : mTitleBox->getText(); } void LLDragHandleLeft::setTitle(const std::string& ) { - setTitleBox(NULL); + if( mTitleBox ) + { + removeChild(mTitleBox); + delete mTitleBox; + mTitleBox = NULL; + } /* no title on left edge */ } @@ -184,9 +185,9 @@ void LLDragHandleTop::draw() */ // Colorize the text to match the frontmost state - if (getTitleBox()) + if (mTitleBox) { - getTitleBox()->setEnabled(getForeground()); + mTitleBox->setEnabled(getForeground()); } LLView::draw(); @@ -229,9 +230,9 @@ void LLDragHandleLeft::draw() */ // Colorize the text to match the frontmost state - if (getTitleBox()) + if (mTitleBox) { - getTitleBox()->setEnabled(getForeground()); + mTitleBox->setEnabled(getForeground()); } LLView::draw(); @@ -239,12 +240,12 @@ void LLDragHandleLeft::draw() void LLDragHandleTop::reshapeTitleBox() { - if( ! getTitleBox()) + if( ! mTitleBox) { return; } - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); - S32 title_width = font->getWidth( getTitleBox()->getText() ) + TITLE_PAD; + const LLFontGL* font = LLFontGL::getFontSansSerif(); + S32 title_width = font->getWidth( mTitleBox->getText() ) + TITLE_PAD; if (getMaxTitleWidth() > 0) title_width = llmin(title_width, getMaxTitleWidth()); S32 title_height = llround(font->getLineHeight()); @@ -255,7 +256,7 @@ void LLDragHandleTop::reshapeTitleBox() getRect().getWidth() - LEFT_PAD - RIGHT_PAD, title_height); - getTitleBox()->setRect( title_rect ); + mTitleBox->setRect( title_rect ); } void LLDragHandleTop::reshape(S32 width, S32 height, BOOL called_from_parent) @@ -337,14 +338,14 @@ BOOL LLDragHandle::handleHover(S32 x, S32 y, MASK mask) LLView* snap_view = getParent()->findSnapRect(new_rect, mouse_dir, SNAP_PARENT_AND_SIBLINGS, sSnapMargin); - getParent()->snappedTo(snap_view); + getParent()->setSnappedTo(snap_view); delta_x = new_rect.mLeft - pre_snap_x; delta_y = new_rect.mBottom - pre_snap_y; translated_rect.translate(delta_x, delta_y); // restore original rect so delta are detected, then call user reshape method to handle snapped floaters, etc getParent()->setRect(original_rect); - getParent()->userSetShape(translated_rect); + getParent()->setShape(translated_rect, true); mDragLastScreenX += delta_x; mDragLastScreenY += delta_y; diff --git a/indra/llui/lldraghandle.h b/indra/llui/lldraghandle.h index 9eb3e55a6c..8b53c46ae9 100644 --- a/indra/llui/lldraghandle.h +++ b/indra/llui/lldraghandle.h @@ -45,8 +45,24 @@ class LLTextBox; class LLDragHandle : public LLView { public: - LLDragHandle(const std::string& name, const LLRect& rect, const std::string& title ); - virtual ~LLDragHandle() { setTitleBox(NULL); } + struct Params + : public LLInitParam::Block + { + Optional label; + Optional drag_highlight_color; + Optional drag_shadow_color; + + Params() + : drag_highlight_color("", LLUI::getCachedColorFunctor("DefaultHighlightLight")), + drag_shadow_color("", LLUI::getCachedColorFunctor("DefaultShadowDark")) + { + mouse_opaque(true); + follows.flags(FOLLOWS_ALL); + } + }; + void initFromParams(const Params&); + + virtual ~LLDragHandle(); virtual void setValue(const LLSD& value); @@ -64,18 +80,20 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); protected: - LLTextBox* getTitleBox() const { return mTitleBox; } - void setTitleBox(LLTextBox*); - + LLDragHandle(const Params&); + friend class LLUICtrlFactory; + +protected: + LLTextBox* mTitleBox; + private: S32 mDragLastScreenX; S32 mDragLastScreenY; S32 mLastMouseScreenX; S32 mLastMouseScreenY; LLCoordGL mLastMouseDir; - LLColor4 mDragHighlightColor; - LLColor4 mDragShadowColor; - LLTextBox* mTitleBox; + LLUIColor mDragHighlightColor; + LLUIColor mDragShadowColor; S32 mMaxTitleWidth; BOOL mForeground; @@ -88,9 +106,10 @@ private: class LLDragHandleTop : public LLDragHandle { +protected: + LLDragHandleTop(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - LLDragHandleTop(const std::string& name, const LLRect& rect, const std::string& title ); - virtual void setTitle( const std::string& title ); virtual const std::string& getTitle() const; virtual void draw(); @@ -105,9 +124,10 @@ private: class LLDragHandleLeft : public LLDragHandle { +protected: + LLDragHandleLeft(const Params& p) : LLDragHandle(p) {} + friend class LLUICtrlFactory; public: - LLDragHandleLeft(const std::string& name, const LLRect& rect, const std::string& title ); - virtual void setTitle( const std::string& title ); virtual const std::string& getTitle() const; virtual void draw(); diff --git a/indra/llui/llf32uictrl.cpp b/indra/llui/llf32uictrl.cpp new file mode 100644 index 0000000000..0978005b78 --- /dev/null +++ b/indra/llui/llf32uictrl.cpp @@ -0,0 +1,57 @@ +/** + * @file llf32uictrl.cpp + * @author Nat Goodspeed + * @date 2008-09-08 + * @brief Implementation for llf32uictrl. + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Precompiled header +#include "linden_common.h" +// associated header +#include "llf32uictrl.h" +// STL headers +// std headers +// external library headers +// other Linden headers + +LLF32UICtrl::LLF32UICtrl(const Params& p) +: LLUICtrl(p), + mInitialValue(p.initial_value().asReal()), + mMinValue(p.min_value), + mMaxValue(p.max_value), + mIncrement(p.increment) +{ + mViewModel->setValue(p.initial_value); +} + +F32 LLF32UICtrl::getValueF32() const +{ + return mViewModel->getValue().asReal(); +} diff --git a/indra/llui/llf32uictrl.h b/indra/llui/llf32uictrl.h new file mode 100644 index 0000000000..0a54fe761b --- /dev/null +++ b/indra/llui/llf32uictrl.h @@ -0,0 +1,83 @@ +/** + * @file llf32uictrl.h + * @author Nat Goodspeed + * @date 2008-09-08 + * @brief Base class for float-valued LLUICtrl widgets + * + * $LicenseInfo:firstyear=2008&license=viewergpl$ + * + * Copyright (c) 2008-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#if ! defined(LL_LLF32UICTRL_H) +#define LL_LLF32UICTRL_H + +#include "lluictrl.h" + +class LLF32UICtrl: public LLUICtrl +{ +public: + struct Params: public LLInitParam::Block + { + Optional min_value, + max_value, + increment; + + Params() + : min_value("min_val", 0.f), + max_value("max_val", 1.f), + increment("increment", 0.1f) + {} + }; + +protected: + LLF32UICtrl(const Params& p); + +public: + virtual F32 getValueF32() const; + + virtual void setValue(const LLSD& value ) { mViewModel->setValue(value); } + virtual LLSD getValue() const { return LLSD(getValueF32()); } + + virtual void setMinValue(const LLSD& min_value) { setMinValue((F32)min_value.asReal()); } + virtual void setMaxValue(const LLSD& max_value) { setMaxValue((F32)max_value.asReal()); } + + virtual F32 getInitialValue() const { return mInitialValue; } + virtual F32 getMinValue() const { return mMinValue; } + virtual F32 getMaxValue() const { return mMaxValue; } + virtual F32 getIncrement() const { return mIncrement; } + virtual void setMinValue(F32 min_value) { mMinValue = min_value; } + virtual void setMaxValue(F32 max_value) { mMaxValue = max_value; } + virtual void setIncrement(F32 increment) { mIncrement = increment;} + +protected: + F32 mInitialValue; + F32 mMinValue; + F32 mMaxValue; + F32 mIncrement; +}; + +#endif /* ! defined(LL_LLF32UICTRL_H) */ diff --git a/indra/llui/llfloater.cpp b/indra/llui/llfloater.cpp index 21f8f6e5f7..a14b99eeb7 100644 --- a/indra/llui/llfloater.cpp +++ b/indra/llui/llfloater.cpp @@ -43,11 +43,13 @@ #include "llbutton.h" #include "llcheckboxctrl.h" #include "lldraghandle.h" +#include "llfloaterreg.h" #include "llfocusmgr.h" #include "llresizebar.h" #include "llresizehandle.h" #include "llkeyboard.h" #include "llmenugl.h" // MENU_BAR_HEIGHT +#include "llmodaldialog.h" #include "lltextbox.h" #include "llresmgr.h" #include "llui.h" @@ -56,37 +58,37 @@ #include "llcontrol.h" #include "lltabcontainer.h" #include "v2math.h" +#include "lltrans.h" +#include "llmultifloater.h" -const S32 MINIMIZED_WIDTH = 160; -const S32 CLOSE_BOX_FROM_TOP = 1; // use this to control "jumping" behavior when Ctrl-Tabbing const S32 TABBED_FLOATER_OFFSET = 0; std::string LLFloater::sButtonActiveImageNames[BUTTON_COUNT] = { - "UIImgBtnCloseActiveUUID", //BUTTON_CLOSE - "UIImgBtnRestoreActiveUUID", //BUTTON_RESTORE - "UIImgBtnMinimizeActiveUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffActiveUUID", //BUTTON_TEAR_OFF - "UIImgBtnCloseActiveUUID", //BUTTON_EDIT + "closebox.tga", //BUTTON_CLOSE + "restore.tga", //BUTTON_RESTORE + "minimize.tga", //BUTTON_MINIMIZE + "tearoffbox.tga", //BUTTON_TEAR_OFF + "closebox.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonInactiveImageNames[BUTTON_COUNT] = { - "UIImgBtnCloseInactiveUUID", //BUTTON_CLOSE - "UIImgBtnRestoreInactiveUUID", //BUTTON_RESTORE - "UIImgBtnMinimizeInactiveUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffInactiveUUID", //BUTTON_TEAR_OFF - "UIImgBtnCloseInactiveUUID", //BUTTON_EDIT + "close_inactive_blue.tga", //BUTTON_CLOSE + "restore_inactive.tga", //BUTTON_RESTORE + "minimize_inactive.tga", //BUTTON_MINIMIZE + "tearoffbox.tga", //BUTTON_TEAR_OFF + "close_inactive_blue.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonPressedImageNames[BUTTON_COUNT] = { - "UIImgBtnClosePressedUUID", //BUTTON_CLOSE - "UIImgBtnRestorePressedUUID", //BUTTON_RESTORE - "UIImgBtnMinimizePressedUUID", //BUTTON_MINIMIZE - "UIImgBtnTearOffPressedUUID", //BUTTON_TEAR_OFF - "UIImgBtnClosePressedUUID", //BUTTON_EDIT + "close_in_blue.tga", //BUTTON_CLOSE + "restore_pressed.tga", //BUTTON_RESTORE + "minimize_pressed.tga", //BUTTON_MINIMIZE + "tearoff_pressed.tga", //BUTTON_TEAR_OFF + "close_in_blue.tga", //BUTTON_EDIT }; std::string LLFloater::sButtonNames[BUTTON_COUNT] = @@ -98,17 +100,20 @@ std::string LLFloater::sButtonNames[BUTTON_COUNT] = "llfloater_edit_btn", //BUTTON_EDIT }; -std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = +std::string LLFloater::sButtonToolTips[BUTTON_COUNT] = {}; + + +std::string LLFloater::sButtonToolTipsIndex[BUTTON_COUNT]= { #ifdef LL_DARWIN - "Close (Cmd-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_DARWIN",//LLTrans::getString("BUTTON_CLOSE_DARWIN"), //"Close (Cmd-W)", //BUTTON_CLOSE #else - "Close (Ctrl-W)", //BUTTON_CLOSE + "BUTTON_CLOSE_WIN", //LLTrans::getString("BUTTON_CLOSE_WIN"), //"Close (Ctrl-W)", //BUTTON_CLOSE #endif - "Restore", //BUTTON_RESTORE - "Minimize", //BUTTON_MINIMIZE - "Tear Off", //BUTTON_TEAR_OFF - "Edit", //BUTTON_EDIT + "BUTTON_RESTORE",//LLTrans::getString("BUTTON_RESTORE"), //"Restore", //BUTTON_RESTORE + "BUTTON_MINIMIZE",//LLTrans::getString("BUTTON_MINIMIZE"), //"Minimize", //BUTTON_MINIMIZE + "BUTTON_TEAR_OFF",//LLTrans::getString("BUTTON_TEAR_OFF"), //"Tear Off", //BUTTON_TEAR_OFF + "BUTTON_EDIT", //LLTrans::getString("BUTTON_EDIT"), // "Edit", //BUTTON_EDIT }; LLFloater::click_callback LLFloater::sButtonCallbacks[BUTTON_COUNT] = @@ -126,59 +131,118 @@ LLFloater::handle_map_t LLFloater::sFloaterMap; LLFloaterView* gFloaterView = NULL; -LLFloater::LLFloater() : - //FIXME: we should initialize *all* member variables here - LLPanel(), mAutoFocus(TRUE), - mResizable(FALSE), - mDragOnLeft(FALSE), - mMinWidth(0), - mMinHeight(0) -{ - // automatically take focus when opened - mAutoFocus = TRUE; +//static +bool LLFloater::KeyCompare::compare(const LLSD& a, const LLSD& b) +{ + if (a.type() != b.type()) + { + //llerrs << "Mismatched LLSD types: (" << a << ") mismatches (" << b << ")" << llendl; + return false; + } + else if (a.isUndefined()) + return false; + else if (a.isInteger()) + return a.asInteger() < b.asInteger(); + else if (a.isReal()) + return a.asReal() < b.asReal(); + else if (a.isString()) + return a.asString() < b.asString(); + else if (a.isUUID()) + return a.asUUID() < b.asUUID(); + else if (a.isDate()) + return a.asDate() < b.asDate(); + else if (a.isURI()) + return a.asString() < b.asString(); // compare URIs as strings + else if (a.isBoolean()) + return a.asBoolean() < b.asBoolean(); + else + return false; // no valid operation for Binary +} + +bool LLFloater::KeyCompare::equate(const LLSD& a, const LLSD& b) +{ + 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 +} + +//************************************ + +LLFloater::LLFloater(const LLSD& key, const LLFloater::Params& p) + : LLPanel(), + mDragHandle(NULL), + mTitle(p.title), + mShortTitle(p.short_title), + mSingleInstance(p.single_instance), + mKey(key), + mAutoTile(p.auto_tile), + mCanTearOff(p.can_tear_off), + mCanMinimize(p.can_minimize), + mCanClose(p.can_close), + mDragOnLeft(p.can_drag_on_left), + mResizable(p.can_resize), + mMinWidth(p.min_width), + mMinHeight(p.min_height), + mMinimized(FALSE), + mForeground(FALSE), + mFirstLook(TRUE), + mEditing(FALSE), + mButtonScale(1.0f), + mAutoFocus(TRUE), // automatically take focus when opened + mHasBeenDraggedWhileMinimized(FALSE), + mPreviousMinimizedBottom(0), + mPreviousMinimizedLeft(0), + mNotificationContext(NULL) +{ + static LLUICachedControl default_background_color ("FloaterDefaultBackgroundColor", *(new LLColor4)); + static LLUICachedControl focus_background_color ("FloaterFocusBackgroundColor", *(new LLColor4)); + for (S32 i = 0; i < BUTTON_COUNT; i++) { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; + sButtonToolTips[i] =LLTrans::getString( sButtonToolTipsIndex[i]); } - for (S32 i = 0; i < 4; i++) - { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; - } - mDragHandle = NULL; + mHandle.bind(this); mNotificationContext = new LLFloaterNotificationContext(getHandle()); -} + mBgColorAlpha = default_background_color; + mBgColorOpaque = focus_background_color; -LLFloater::LLFloater(const std::string& name) -: LLPanel(name), mAutoFocus(TRUE) // automatically take focus when opened -{ - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } for (S32 i = 0; i < 4; i++) { - mResizeBar[i] = NULL; + mResizeBar[i] = NULL; mResizeHandle[i] = NULL; } - std::string title; // null string - initFloater(title, FALSE, DEFAULT_MIN_WIDTH, DEFAULT_MIN_HEIGHT, FALSE, TRUE, TRUE); // defaults -} + // Clicks stop here. + setMouseOpaque(TRUE); + + // Floaters always draw their background, unlike every other panel. + setBackgroundVisible(TRUE); -LLFloater::LLFloater(const std::string& name, const LLRect& rect, const std::string& title, - BOOL resizable, - S32 min_width, - S32 min_height, - BOOL drag_on_left, - BOOL minimizable, - BOOL close_btn, - BOOL bordered) -: LLPanel(name, rect, bordered), mAutoFocus(TRUE) // automatically take focus when opened -{ + // Floaters start not minimized. When minimized, they save their + // prior rectangle to be used on restore. + mExpandedRect.set(0,0,0,0); + for (S32 i = 0; i < BUTTON_COUNT; i++) { mButtonsEnabled[i] = FALSE; @@ -189,259 +253,176 @@ LLFloater::LLFloater(const std::string& name, const LLRect& rect, const std::str mResizeBar[i] = NULL; mResizeHandle[i] = NULL; } - initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn); -} + + initFromParams(p); + + // chrome floaters don't take focus at all + setFocusRoot(!getIsChrome()); -LLFloater::LLFloater(const std::string& name, const std::string& rect_control, const std::string& title, - BOOL resizable, - S32 min_width, - S32 min_height, - BOOL drag_on_left, - BOOL minimizable, - BOOL close_btn, - BOOL bordered) -: LLPanel(name, rect_control, bordered), mAutoFocus(TRUE) // automatically take focus when opened -{ - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - mButtons[i] = NULL; - } - for (S32 i = 0; i < 4; i++) - { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; - } - initFloater( title, resizable, min_width, min_height, drag_on_left, minimizable, close_btn); + initFloater(); } - // Note: Floaters constructed from XML call init() twice! -void LLFloater::initFloater(const std::string& title, - BOOL resizable, S32 min_width, S32 min_height, - BOOL drag_on_left, BOOL minimizable, BOOL close_btn) +void LLFloater::initFloater() { - mHandle.bind(this); - mNotificationContext = new LLFloaterNotificationContext(getHandle()); - - // Init function can be called more than once, so clear out old data. - for (S32 i = 0; i < BUTTON_COUNT; i++) - { - mButtonsEnabled[i] = FALSE; - if (mButtons[i] != NULL) - { - removeChild(mButtons[i]); - delete mButtons[i]; - mButtons[i] = NULL; - } - } - mButtonScale = 1.f; + addDragHandle(); + + addResizeCtrls(); - //sjb: Thia is a bit of a hack: - BOOL need_border = hasBorder(); - // remove the border since deleteAllChildren() will also delete the border (but not clear mBorder) - removeBorder(); - // this will delete mBorder too - deleteAllChildren(); - // add the border back if we want it - if (need_border) + // Close button. + if (mCanClose) { - addBorder(); + mButtonsEnabled[BUTTON_CLOSE] = TRUE; } - // chrome floaters don't take focus at all - setFocusRoot(!getIsChrome()); - - // Reset cached pointers - mDragHandle = NULL; - for (S32 i = 0; i < 4; i++) + // Minimize button only for top draggers + if ( !mDragOnLeft && mCanMinimize ) { - mResizeBar[i] = NULL; - mResizeHandle[i] = NULL; + mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; } - mCanTearOff = TRUE; - mEditing = FALSE; - // Clicks stop here. - setMouseOpaque(TRUE); + buildButtons(); - mFirstLook = TRUE; - mForeground = FALSE; - mDragOnLeft = drag_on_left == TRUE; + // Floaters are created in the invisible state + setVisible(FALSE); - // Floaters always draw their background, unlike every other panel. - setBackgroundVisible(TRUE); + // add self to handle->floater map + sFloaterMap[mHandle] = this; - // Floaters start not minimized. When minimized, they save their - // prior rectangle to be used on restore. - mMinimized = FALSE; - mExpandedRect.set(0,0,0,0); - - S32 close_pad; // space to the right of close box - S32 close_box_size; // For layout purposes, how big is the close box? - if (close_btn) - { - close_box_size = LLFLOATER_CLOSE_BOX_SIZE; - close_pad = 0; - } - else + if (!getParent()) { - close_box_size = 0; - close_pad = 0; + gFloaterView->addChild(this); } +} - S32 minimize_box_size; - S32 minimize_pad; - if (minimizable && !drag_on_left) - { - minimize_box_size = LLFLOATER_CLOSE_BOX_SIZE; - minimize_pad = 0; - } - else +void LLFloater::addDragHandle() +{ + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + S32 close_box_size = mCanClose ? floater_close_box_size : 0; + + if (!mDragHandle) { - minimize_box_size = 0; - minimize_pad = 0; + if (mDragOnLeft) + { + LLDragHandleLeft::Params p; + p.name("drag"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + else // drag on top + { + LLDragHandleTop::Params p; + p.name("Drag Handle"); + p.follows.flags(FOLLOWS_ALL); + p.label(mTitle); + mDragHandle = LLUICtrlFactory::create(p); + } + addChild(mDragHandle); } - - // Drag Handle - // Add first so it's in the background. -// const S32 drag_pad = 2; - if (drag_on_left) + LLRect rect; + if (mDragOnLeft) { - LLRect drag_handle_rect; - drag_handle_rect.setOriginAndSize( - 0, 0, - DRAG_HANDLE_WIDTH, - getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); - mDragHandle = new LLDragHandleLeft(std::string("drag"), drag_handle_rect, title ); + rect.setLeftTopAndSize(0, 0, DRAG_HANDLE_WIDTH, getRect().getHeight() - LLPANEL_BORDER_WIDTH - close_box_size); } else // drag on top { - LLRect drag_handle_rect( 0, getRect().getHeight(), getRect().getWidth(), 0 ); - mDragHandle = new LLDragHandleTop( std::string("Drag Handle"), drag_handle_rect, title ); - } - addChild(mDragHandle); - - // Resize Handle - mResizable = resizable; - mMinWidth = min_width; - mMinHeight = min_height; - - if( mResizable ) - { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[LLResizeBar::LEFT] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - min_width, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[LLResizeBar::TOP] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - min_height, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[LLResizeBar::RIGHT] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - min_width, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[LLResizeBar::BOTTOM] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - min_height, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - min_width, - min_height, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( - std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - min_width, - min_height, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - min_width, - min_height, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - min_width, - min_height, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); + rect = getLocalRect(); } + mDragHandle->setRect(rect); + updateButtons(); + applyTitle(); +} - // Close button. - if (close_btn) +void LLFloater::addResizeCtrls() +{ + for (S32 i = 0; i < 4; i++) { - mButtonsEnabled[BUTTON_CLOSE] = TRUE; + if (mResizeBar[i]) + { + removeChild(mResizeBar[i]); + delete mResizeBar[i]; + mResizeBar[i] = NULL; + } + if (mResizeHandle[i]) + { + removeChild(mResizeHandle[i]); + delete mResizeHandle[i]; + mResizeHandle[i] = NULL; + } } - - // Minimize button only for top draggers - if ( !drag_on_left && minimizable ) + if( !mResizable ) { - mButtonsEnabled[BUTTON_MINIMIZE] = TRUE; + 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(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); + + mResizeBar[LLResizeBar::TOP] = LLUICtrlFactory::create(p); + 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); + + mResizeBar[LLResizeBar::RIGHT] = LLUICtrlFactory::create(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(p); + addChild( mResizeBar[LLResizeBar::BOTTOM] ); + + // Resize handles (corners) + LLResizeHandle::Params handle_p; + 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(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(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(handle_p); + addChild(mResizeHandle[2]); - // Keep track of whether this window has ever been dragged while it - // was minimized. If it has, we'll remember its position for the - // next time it's minimized. - mHasBeenDraggedWhileMinimized = FALSE; - mPreviousMinimizedLeft = 0; - mPreviousMinimizedBottom = 0; - - buildButtons(); - - // JC - Don't do this here, because many floaters first construct themselves, - // then show themselves. Put it in setVisibleAndFrontmost. - // make_ui_sound("UISndWindowOpen"); - - // RN: floaters are created in the invisible state - setVisible(FALSE); - - // add self to handle->floater map - sFloaterMap[mHandle] = this; - - if (!getParent()) - { - gFloaterView->addChild(this); - } + 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(handle_p); + addChild(mResizeHandle[3]); } // virtual LLFloater::~LLFloater() { + LLFloaterReg::removeInstance(mInstanceName, mKey); + delete mNotificationContext; mNotificationContext = NULL; - control_map_t::iterator itor; - for (itor = mFloaterControls.begin(); itor != mFloaterControls.end(); ++itor) - { - delete itor->second; - } - mFloaterControls.clear(); - //// am I not hosted by another floater? //if (mHostHandle.isDead()) //{ @@ -469,8 +450,27 @@ LLFloater::~LLFloater() delete mResizeBar[i]; delete mResizeHandle[i]; } + + storeRectControl(); + setVisible(false); // We're not visible if we're destroyed + storeVisibilityControl(); +} + +void LLFloater::storeRectControl() +{ + if( mRectControl.size() > 1 ) + { + LLUI::sSettingGroups["floater"]->setRect( mRectControl, getRect() ); + } } +void LLFloater::storeVisibilityControl() +{ + if( mVisibilityControl.size() > 1 ) + { + LLUI::sSettingGroups["floater"]->setBOOL( mVisibilityControl, getVisible() ); + } +} void LLFloater::setVisible( BOOL visible ) { @@ -504,10 +504,25 @@ void LLFloater::setVisible( BOOL visible ) } ++dependent_it; } + + storeVisibilityControl(); +} + +// virtual +void LLFloater::onVisibilityChange ( BOOL new_visibility ) +{ + if (new_visibility) + { + if (getHost()) + getHost()->setFloaterFlashing(this, FALSE); + } + LLPanel::onVisibilityChange ( new_visibility ); } -void LLFloater::open() /* Flawfinder: ignore */ +void LLFloater::openFloater(const LLSD& key) { + mKey = key; // in case we need to open ourselves again + if (getSoundFlags() != SILENT // don't play open sound for hosted (tabbed) windows && !getHost() @@ -525,9 +540,11 @@ void LLFloater::open() /* Flawfinder: ignore */ // only select tabs if window they are hosted in is visible getFloaterHost()->addFloater(this, getFloaterHost()->getVisible()); } - else if (getHost() != NULL) + + if (getHost() != NULL) { - // already hosted + getHost()->setMinimized(FALSE); + getHost()->setVisibleAndFrontmost(mAutoFocus); getHost()->showFloater(this); } else @@ -536,10 +553,10 @@ void LLFloater::open() /* Flawfinder: ignore */ setVisibleAndFrontmost(mAutoFocus); } - onOpen(); + onOpen(key); } -void LLFloater::close(bool app_quitting) +void LLFloater::closeFloater(bool app_quitting) { // Always unminimize before trying to close. // Most of the time the user will never see this state. @@ -570,7 +587,7 @@ void LLFloater::close(bool app_quitting) if (floaterp) { ++dependent_it; - floaterp->close(); + floaterp->closeFloater(app_quitting); } else { @@ -597,7 +614,7 @@ void LLFloater::close(bool app_quitting) } } } - + // Let floater do cleanup. onClose(app_quitting); } @@ -607,6 +624,7 @@ void LLFloater::close(bool app_quitting) void LLFloater::reshape(S32 width, S32 height, BOOL called_from_parent) { LLPanel::reshape(width, height, called_from_parent); + storeRectControl(); } void LLFloater::releaseFocus() @@ -664,15 +682,23 @@ void LLFloater::center() centerWithin(gFloaterView->getRect()); } +LLMultiFloater* LLFloater::getHost() +{ + return (LLMultiFloater*)mHostHandle.get(); +} + void LLFloater::applyRectControl() { - if (!getRectControl().empty()) + if (mRectControl.size() > 1) { - const LLRect& rect = LLUI::sConfigGroup->getRect(getRectControl()); - translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom); - if (mResizable) + const LLRect& rect = LLUI::sSettingGroups["floater"]->getRect(mRectControl); + if (rect.getWidth() > 0 && rect.getHeight() > 0) { - reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + translate( rect.mLeft - getRect().mLeft, rect.mBottom - getRect().mBottom); + if (mResizable) + { + reshape(llmax(mMinWidth, rect.getWidth()), llmax(mMinHeight, rect.getHeight())); + } } } } @@ -763,7 +789,7 @@ BOOL LLFloater::canSnapTo(const LLView* other_view) return LLPanel::canSnapTo(other_view); } -void LLFloater::snappedTo(const LLView* snap_view) +void LLFloater::setSnappedTo(const LLView* snap_view) { if (!snap_view || snap_view == getParent()) { @@ -778,10 +804,10 @@ void LLFloater::snappedTo(const LLView* snap_view) } } -void LLFloater::userSetShape(const LLRect& new_rect) +void LLFloater::handleReshape(const LLRect& new_rect, bool by_user) { const LLRect old_rect = getRect(); - LLView::userSetShape(new_rect); + LLView::handleReshape(new_rect, by_user); // if not minimized, adjust all snapped dependents to new shape if (!isMinimized()) @@ -816,7 +842,7 @@ void LLFloater::userSetShape(const LLRect& new_rect) delta_y += new_rect.mBottom - old_rect.mBottom; dependent_rect.translate(delta_x, delta_y); - floaterp->userSetShape(dependent_rect); + floaterp->setShape(dependent_rect, by_user); } } } @@ -834,6 +860,9 @@ void LLFloater::userSetShape(const LLRect& new_rect) void LLFloater::setMinimized(BOOL minimize) { + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); + if (minimize == mMinimized) return; if (minimize) @@ -902,7 +931,7 @@ void LLFloater::setMinimized(BOOL minimize) mMinimized = TRUE; // Reshape *after* setting mMinimized - reshape( MINIMIZED_WIDTH, LLFLOATER_HEADER_SIZE, TRUE); + reshape( minimized_width, floater_header_size, TRUE); } else { @@ -995,6 +1024,13 @@ void LLFloater::setFocus( BOOL b ) } } +// virtual +void LLFloater::setRect(const LLRect &rect) +{ + LLPanel::setRect(rect); + addDragHandle(); // re-add drag handle, sized based on rect +} + // virtual void LLFloater::setIsChrome(BOOL is_chrome) { @@ -1276,19 +1312,18 @@ void LLFloater::setEditModeEnabled(BOOL enable) // static -void LLFloater::onClickMinimize(void *userdata) +void LLFloater::onClickMinimize(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + if (!self) + return; self->setMinimized( !self->isMinimized() ); } -void LLFloater::onClickTearOff(void *userdata) +void LLFloater::onClickTearOff(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + if (!self) + return; LLMultiFloater* host_floater = self->getHost(); if (host_floater) //Tear off { @@ -1297,12 +1332,12 @@ void LLFloater::onClickTearOff(void *userdata) // reparent to floater view gFloaterView->addChild(self); - self->open(); /* Flawfinder: ignore */ + self->openFloater(self->getKey()); // only force position for floaters that don't have that data saved - if (self->getRectControl().empty()) + if (self->mRectControl.size() <= 1) { - new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - LLFLOATER_HEADER_SIZE - 5, self->getRect().getWidth(), self->getRect().getHeight()); + new_rect.setLeftTopAndSize(host_floater->getRect().mLeft + 5, host_floater->getRect().mTop - floater_header_size - 5, self->getRect().getWidth(), self->getRect().getHeight()); self->setRect(new_rect); } gFloaterView->adjustToFitScreen(self, FALSE); @@ -1317,17 +1352,16 @@ void LLFloater::onClickTearOff(void *userdata) self->setMinimized(FALSE); // to reenable minimize button if it was minimized new_host->showFloater(self); // make sure host is visible - new_host->open(); + new_host->openFloater(new_host->getKey()); } } } // static -void LLFloater::onClickEdit(void *userdata) +void LLFloater::onClickEdit(LLFloater* self) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - + if (!self) + return; self->mEditing = self->mEditing ? FALSE : TRUE; } @@ -1373,7 +1407,7 @@ void LLFloater::closeFocusedFloater() LLFloater* floater_to_close = LLFloater::getClosableFloaterFromFocus(); if(floater_to_close) { - floater_to_close->close(); + floater_to_close->closeFloater(); } // if nothing took focus after closing focused floater @@ -1388,12 +1422,11 @@ void LLFloater::closeFocusedFloater() // static -void LLFloater::onClickClose( void* userdata ) +void LLFloater::onClickClose( LLFloater* self ) { - LLFloater* self = (LLFloater*) userdata; - if (!self) return; - - self->close(); + if (!self) + return; + self->closeFloater(false); } @@ -1408,8 +1441,11 @@ void LLFloater::draw() S32 right = getRect().getWidth() - LLPANEL_BORDER_WIDTH; S32 bottom = LLPANEL_BORDER_WIDTH; - LLColor4 shadow_color = LLUI::sColorsGroup->getColor("ColorDropShadow"); - F32 shadow_offset = (F32)LLUI::sConfigGroup->getS32("DropShadowFloater"); + static LLUICachedControl shadow_offset_S32 ("DropShadowFloater", 0); + static LLUICachedControl shadow_color_cached ("ColorDropShadow", *(new LLColor4)); + LLColor4 shadow_color = shadow_color_cached; + F32 shadow_offset = (F32)shadow_offset_S32; + if (!isBackgroundOpaque()) { shadow_offset *= 0.2f; @@ -1422,20 +1458,21 @@ void LLFloater::draw() // No transparent windows in simple UI if (isBackgroundOpaque()) { - gl_rect_2d( left, top, right, bottom, getBackgroundColor() ); + gl_rect_2d( left, top, right, bottom, mBgColorOpaque ); } else { - gl_rect_2d( left, top, right, bottom, getTransparentColor() ); + gl_rect_2d( left, top, right, bottom, mBgColorAlpha ); } if(gFocusMgr.childHasKeyboardFocus(this) && !getIsChrome() && !getCurrentTitle().empty()) { + static LLUICachedControl titlebar_focus_color ("TitleBarFocusColor", *(new LLColor4)); // draw highlight on title bar to indicate focus. RDW - const LLFontGL* font = LLResMgr::getInstance()->getRes( LLFONT_SANSSERIF ); + const LLFontGL* font = LLFontGL::getFontSansSerif(); LLRect r = getRect(); gl_rect_2d_offset_local(0, r.getHeight(), r.getWidth(), r.getHeight() - (S32)font->getLineHeight() - 1, - LLUI::sColorsGroup->getColor("TitleBarFocusColor"), 0, TRUE); + titlebar_focus_color, 0, TRUE); } } @@ -1489,8 +1526,10 @@ void LLFloater::draw() { // 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 LLUICachedControl focus_border_color ("FloaterFocusBorderColor", *(new LLColor4)); + static LLUICachedControl unfocus_border_color ("FloaterUnfocusBorderColor", *(new LLColor4)); LLUI::setLineWidth(1.5f); - LLColor4 outlineColor = gFocusMgr.childHasKeyboardFocus(this) ? LLUI::sColorsGroup->getColor("FloaterFocusBorderColor") : LLUI::sColorsGroup->getColor("FloaterUnfocusBorderColor"); + 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, -LLPANEL_BORDER_WIDTH, FALSE); LLUI::setLineWidth(1.f); } @@ -1511,6 +1550,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) { // if removing minimize/restore button programmatically, // go ahead and unminimize floater + mCanMinimize = can_minimize; if (!can_minimize) { setMinimized(FALSE); @@ -1524,6 +1564,7 @@ void LLFloater::setCanMinimize(BOOL can_minimize) void LLFloater::setCanClose(BOOL can_close) { + mCanClose = can_close; mButtonsEnabled[BUTTON_CLOSE] = can_close; updateButtons(); @@ -1538,83 +1579,10 @@ void LLFloater::setCanTearOff(BOOL can_tear_off) } -void LLFloater::setCanResize(BOOL can_resize) +void LLFloater::setCanResize(BOOL can_resize) { - if (mResizable && !can_resize) - { - for (S32 i = 0; i < 4; i++) - { - removeChild(mResizeBar[i], TRUE); - mResizeBar[i] = NULL; - - removeChild(mResizeHandle[i], TRUE); - mResizeHandle[i] = NULL; - } - } - else if (!mResizable && can_resize) - { - // Resize bars (sides) - const S32 RESIZE_BAR_THICKNESS = 3; - mResizeBar[0] = new LLResizeBar( - std::string("resizebar_left"), - this, - LLRect( 0, getRect().getHeight(), RESIZE_BAR_THICKNESS, 0), - mMinWidth, S32_MAX, LLResizeBar::LEFT ); - addChild( mResizeBar[0] ); - - mResizeBar[1] = new LLResizeBar( - std::string("resizebar_top"), - this, - LLRect( 0, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_BAR_THICKNESS), - mMinHeight, S32_MAX, LLResizeBar::TOP ); - addChild( mResizeBar[1] ); - - mResizeBar[2] = new LLResizeBar( - std::string("resizebar_right"), - this, - LLRect( getRect().getWidth() - RESIZE_BAR_THICKNESS, getRect().getHeight(), getRect().getWidth(), 0), - mMinWidth, S32_MAX, LLResizeBar::RIGHT ); - addChild( mResizeBar[2] ); - - mResizeBar[3] = new LLResizeBar( - std::string("resizebar_bottom"), - this, - LLRect( 0, RESIZE_BAR_THICKNESS, getRect().getWidth(), 0), - mMinHeight, S32_MAX, LLResizeBar::BOTTOM ); - addChild( mResizeBar[3] ); - - - // Resize handles (corners) - mResizeHandle[0] = new LLResizeHandle( - std::string("Resize Handle"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, RESIZE_HANDLE_HEIGHT, getRect().getWidth(), 0), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_BOTTOM); - addChild(mResizeHandle[0]); - - mResizeHandle[1] = new LLResizeHandle( std::string("resize"), - LLRect( getRect().getWidth() - RESIZE_HANDLE_WIDTH, getRect().getHeight(), getRect().getWidth(), getRect().getHeight() - RESIZE_HANDLE_HEIGHT), - mMinWidth, - mMinHeight, - LLResizeHandle::RIGHT_TOP ); - addChild(mResizeHandle[1]); - - mResizeHandle[2] = new LLResizeHandle( std::string("resize"), - LLRect( 0, RESIZE_HANDLE_HEIGHT, RESIZE_HANDLE_WIDTH, 0 ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_BOTTOM ); - addChild(mResizeHandle[2]); - - mResizeHandle[3] = new LLResizeHandle( std::string("resize"), - LLRect( 0, getRect().getHeight(), RESIZE_HANDLE_WIDTH, getRect().getHeight() - RESIZE_HANDLE_HEIGHT ), - mMinWidth, - mMinHeight, - LLResizeHandle::LEFT_TOP ); - addChild(mResizeHandle[3]); - } mResizable = can_resize; + addResizeCtrls(); } void LLFloater::setCanDrag(BOOL can_drag) @@ -1633,6 +1601,8 @@ void LLFloater::setCanDrag(BOOL can_drag) void LLFloater::updateButtons() { + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); S32 button_count = 0; for (S32 i = 0; i < BUTTON_COUNT; i++) { @@ -1652,17 +1622,17 @@ void LLFloater::updateButtons() { btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH, - getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count, - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * button_count, + llround((F32)floater_close_box_size * mButtonScale), + llround((F32)floater_close_box_size * mButtonScale)); } else { btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * button_count, - getRect().getHeight() - CLOSE_BOX_FROM_TOP, - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround((F32)LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * button_count, + getRect().getHeight() - close_box_from_top, + llround((F32)floater_close_box_size * mButtonScale), + llround((F32)floater_close_box_size * mButtonScale)); } mButtons[i]->setRect(btn_rect); @@ -1676,50 +1646,56 @@ void LLFloater::updateButtons() } } if (mDragHandle) - mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (LLFLOATER_CLOSE_BOX_SIZE + 1))); + mDragHandle->setMaxTitleWidth(getRect().getWidth() - (button_count * (floater_close_box_size + 1))); } void LLFloater::buildButtons() { + static LLUICachedControl floater_close_box_size ("UIFloaterCloseBoxSize", 0); + static LLUICachedControl close_box_from_top ("UICloseBoxFromTop", 0); for (S32 i = 0; i < BUTTON_COUNT; i++) { + if (mButtons[i]) + { + removeChild(mButtons[i]); + delete mButtons[i]; + mButtons[i] = NULL; + } + LLRect btn_rect; if (mDragOnLeft) { btn_rect.setLeftTopAndSize( LLPANEL_BORDER_WIDTH, - getRect().getHeight() - CLOSE_BOX_FROM_TOP - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); + getRect().getHeight() - close_box_from_top - (floater_close_box_size + 1) * (i + 1), + llround(floater_close_box_size * mButtonScale), + llround(floater_close_box_size * mButtonScale)); } else { btn_rect.setLeftTopAndSize( - getRect().getWidth() - LLPANEL_BORDER_WIDTH - (LLFLOATER_CLOSE_BOX_SIZE + 1) * (i + 1), - getRect().getHeight() - CLOSE_BOX_FROM_TOP, - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale), - llround(LLFLOATER_CLOSE_BOX_SIZE * mButtonScale)); - } - - LLButton* buttonp = new LLButton( - sButtonNames[i], - btn_rect, - sButtonActiveImageNames[i], - sButtonPressedImageNames[i], - LLStringUtil::null, - sButtonCallbacks[i], - this, - LLFontGL::getFontSansSerif()); - - buttonp->setTabStop(FALSE); - buttonp->setFollowsTop(); - buttonp->setFollowsRight(); - buttonp->setToolTip( sButtonToolTips[i] ); - buttonp->setImageColor(LLUI::sColorsGroup->getColor("FloaterButtonImageColor")); - buttonp->setHoverImages(sButtonPressedImageNames[i], - sButtonPressedImageNames[i]); - buttonp->setScaleImage(TRUE); - buttonp->setSaveToXML(false); + getRect().getWidth() - LLPANEL_BORDER_WIDTH - (floater_close_box_size + 1) * (i + 1), + getRect().getHeight() - close_box_from_top, + llround(floater_close_box_size * mButtonScale), + llround(floater_close_box_size * mButtonScale)); + } + + LLButton::Params p; + p.name(sButtonNames[i]); + p.rect(btn_rect); + p.label(""); + p.image_unselected.name(sButtonActiveImageNames[i]); + p.image_selected.name(sButtonPressedImageNames[i]); + p.image_hover_selected.name(sButtonPressedImageNames[i]); + p.image_hover_unselected.name(sButtonPressedImageNames[i]); + p.click_callback.function(boost::bind(sButtonCallbacks[i], this)); + p.tab_stop(false); + p.follows.flags(FOLLOWS_TOP|FOLLOWS_RIGHT); + p.tool_tip(sButtonToolTips[i]); + p.image_color(LLUI::getCachedColorFunctor("FloaterButtonImageColor")); + p.scale_image(true); + + LLButton* buttonp = LLUICtrlFactory::create(p); addChild(buttonp); mButtons[i] = buttonp; } @@ -1730,13 +1706,12 @@ void LLFloater::buildButtons() ///////////////////////////////////////////////////// // LLFloaterView -LLFloaterView::LLFloaterView( const std::string& name, const LLRect& rect ) -: LLUICtrl( name, rect, FALSE, NULL, NULL, FOLLOWS_ALL ), +LLFloaterView::LLFloaterView (const Params& p) +: LLUICtrl (p), mFocusCycleMode(FALSE), mSnapOffsetBottom(0) + ,mSnapOffsetRight(0) { - setTabStop(FALSE); - resetStartingFloaterPosition(); } // By default, adjust vertical. @@ -1830,69 +1805,6 @@ void LLFloaterView::restoreAll() } -void LLFloaterView::getNewFloaterPosition(S32* left,S32* top) -{ - // Workaround: mRect may change between when this object is created and the first time it is used. - static BOOL first = TRUE; - if( first ) - { - resetStartingFloaterPosition(); - first = FALSE; - } - - const S32 FLOATER_PAD = 16; - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - LLRect full_window(0, window_size.mY, window_size.mX, 0); - LLRect floater_creation_rect( - 160, - full_window.getHeight() - 2 * MENU_BAR_HEIGHT, - full_window.getWidth() * 2 / 3, - 130 ); - floater_creation_rect.stretch( -FLOATER_PAD ); - - *left = mNextLeft; - *top = mNextTop; - - const S32 STEP = 25; - S32 bottom = floater_creation_rect.mBottom + 2 * STEP; - S32 right = floater_creation_rect.mRight - 4 * STEP; - - mNextTop -= STEP; - mNextLeft += STEP; - - if( (mNextTop < bottom ) || (mNextLeft > right) ) - { - mColumn++; - mNextTop = floater_creation_rect.mTop; - mNextLeft = STEP * mColumn; - - if( (mNextTop < bottom) || (mNextLeft > right) ) - { - // Advancing the column didn't work, so start back at the beginning - resetStartingFloaterPosition(); - } - } -} - -void LLFloaterView::resetStartingFloaterPosition() -{ - const S32 FLOATER_PAD = 16; - LLCoordWindow window_size; - getWindow()->getSize(&window_size); - LLRect full_window(0, window_size.mY, window_size.mX, 0); - LLRect floater_creation_rect( - 160, - full_window.getHeight() - 2 * MENU_BAR_HEIGHT, - full_window.getWidth() * 2 / 3, - 130 ); - floater_creation_rect.stretch( -FLOATER_PAD ); - - mNextLeft = floater_creation_rect.mLeft; - mNextTop = floater_creation_rect.mTop; - mColumn = 0; -} - LLRect LLFloaterView::findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ) { LLRect base_rect = reference_floater->getRect(); @@ -2104,15 +2016,17 @@ void LLFloaterView::focusFrontFloater() void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) { + static LLUICachedControl floater_header_size ("UIFloaterHeaderSize", 0); + static LLUICachedControl minimized_width ("UIMinimizedWidth", 0); S32 col = 0; LLRect snap_rect_local = getLocalSnapRect(); for(S32 row = snap_rect_local.mBottom; - row < snap_rect_local.getHeight() - LLFLOATER_HEADER_SIZE; - row += LLFLOATER_HEADER_SIZE ) //loop rows + row < snap_rect_local.getHeight() - floater_header_size; + row += floater_header_size ) //loop rows { for(col = snap_rect_local.mLeft; - col < snap_rect_local.getWidth() - MINIMIZED_WIDTH; - col += MINIMIZED_WIDTH) + col < snap_rect_local.getWidth() - minimized_width; + col += minimized_width) { bool foundGap = TRUE; for(child_list_const_iter_t child_it = getChildList()->begin(); @@ -2124,10 +2038,10 @@ void LLFloaterView::getMinimizePosition(S32 *left, S32 *bottom) if(floater->isMinimized()) { LLRect r = floater->getRect(); - if((r.mBottom < (row + LLFLOATER_HEADER_SIZE)) - && (r.mBottom > (row - LLFLOATER_HEADER_SIZE)) - && (r.mLeft < (col + MINIMIZED_WIDTH)) - && (r.mLeft > (col - MINIMIZED_WIDTH))) + if((r.mBottom < (row + floater_header_size)) + && (r.mBottom > (row - floater_header_size)) + && (r.mLeft < (col + minimized_width)) + && (r.mLeft > (col - minimized_width))) { // needs the check for off grid. can't drag, // but window resize makes them off @@ -2179,7 +2093,7 @@ void LLFloaterView::closeAllChildren(bool app_quitting) // dialogs to appear. if (floaterp->canClose() && !floaterp->isDead()) { - floaterp->close(app_quitting); + floaterp->closeFloater(app_quitting); } } } @@ -2202,14 +2116,13 @@ BOOL LLFloaterView::allChildrenClosed() return true; } - void LLFloaterView::refresh() { // Constrain children to be entirely on the screen for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; - if( floaterp->getVisible() ) + LLFloater* floaterp = dynamic_cast(*child_it); + if (floaterp && floaterp->getVisible() ) { // minimized floaters are kept fully onscreen adjustToFitScreen(floaterp, !floaterp->isMinimized()); @@ -2302,11 +2215,12 @@ LLRect LLFloaterView::getSnapRect() const { LLRect snap_rect = getRect(); snap_rect.mBottom += mSnapOffsetBottom; + snap_rect.mRight -= mSnapOffsetRight; return snap_rect; } -LLFloater *LLFloaterView::getFocusedFloater() +LLFloater *LLFloaterView::getFocusedFloater() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2319,7 +2233,7 @@ LLFloater *LLFloaterView::getFocusedFloater() return NULL; } -LLFloater *LLFloaterView::getFrontmost() +LLFloater *LLFloaterView::getFrontmost() const { for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { @@ -2332,7 +2246,7 @@ LLFloater *LLFloaterView::getFrontmost() return NULL; } -LLFloater *LLFloaterView::getBackmost() +LLFloater *LLFloaterView::getBackmost() const { LLFloater* back_most = NULL; for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) @@ -2348,18 +2262,51 @@ LLFloater *LLFloaterView::getBackmost() void LLFloaterView::syncFloaterTabOrder() { - // bring focused floater to front - for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) + // look for a visible modal dialog, starting from first (should be only one) + LLModalDialog* modal_dialog = NULL; + for ( child_list_const_iter_t child_it = getChildList()->begin(); child_it != getChildList()->end(); ++child_it) { - LLFloater* floaterp = (LLFloater*)*child_it; - if (gFocusMgr.childHasKeyboardFocus(floaterp)) + LLModalDialog* dialog = dynamic_cast(*child_it); + if (dialog && dialog->isModal() && dialog->getVisible()) { - bringToFront(floaterp, FALSE); + modal_dialog = dialog; break; } } - // then sync draw order to tab order + if (modal_dialog) + { + // If we have a visible modal dialog, make sure that it has focus + if( gFocusMgr.getTopCtrl() != modal_dialog ) + { + gFocusMgr.setTopCtrl( modal_dialog ); + } + + if( !gFocusMgr.childHasKeyboardFocus( modal_dialog ) ) + { + modal_dialog->setFocus(TRUE); + } + + if( !gFocusMgr.childHasMouseCapture( modal_dialog ) ) + { + gFocusMgr.setMouseCapture( modal_dialog ); + } + } + else + { + // otherwise, make sure the focused floater is in the front of the child list + for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) + { + LLFloater* floaterp = (LLFloater*)*child_it; + if (gFocusMgr.childHasKeyboardFocus(floaterp)) + { + bringToFront(floaterp, FALSE); + break; + } + } + } + + // sync draw order to tab order for ( child_list_const_reverse_iter_t child_it = getChildList()->rbegin(); child_it != getChildList()->rend(); ++child_it) { LLFloater* floaterp = (LLFloater*)*child_it; @@ -2367,7 +2314,7 @@ void LLFloaterView::syncFloaterTabOrder() } } -LLFloater* LLFloaterView::getParentFloater(LLView* viewp) +LLFloater* LLFloaterView::getParentFloater(LLView* viewp) const { LLView* parentp = viewp->getParent(); @@ -2426,641 +2373,166 @@ void LLFloaterView::popVisibleAll(const skip_list_t& skip_list) } } -// -// LLMultiFloater -// - -LLMultiFloater::LLMultiFloater() : - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(TRUE), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - -} - -LLMultiFloater::LLMultiFloater(LLTabContainer::TabPosition tab_pos) : - mTabContainer(NULL), - mTabPos(tab_pos), - mAutoResize(TRUE), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - -} - -LLMultiFloater::LLMultiFloater(const std::string &name) : - LLFloater(name), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(FALSE), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ -} - -LLMultiFloater::LLMultiFloater( - const std::string& name, - const LLRect& rect, - LLTabContainer::TabPosition tab_pos, - BOOL auto_resize) : - LLFloater(name, rect, name), - mTabContainer(NULL), - mTabPos(LLTabContainer::TOP), - mAutoResize(auto_resize), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - mTabContainer = new LLTabContainer(std::string("Preview Tabs"), - LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0), - mTabPos, - FALSE, - FALSE); - mTabContainer->setFollowsAll(); - if (isResizable()) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - - addChild(mTabContainer); -} - -LLMultiFloater::LLMultiFloater( - const std::string& name, - const std::string& rect_control, - LLTabContainer::TabPosition tab_pos, - BOOL auto_resize) : - LLFloater(name, rect_control, name), - mTabContainer(NULL), - mTabPos(tab_pos), - mAutoResize(auto_resize), - mOrigMinWidth(0), - mOrigMinHeight(0) -{ - mTabContainer = new LLTabContainer(std::string("Preview Tabs"), - LLRect(LLPANEL_BORDER_WIDTH, getRect().getHeight() - LLFLOATER_HEADER_SIZE, getRect().getWidth() - LLPANEL_BORDER_WIDTH, 0), - mTabPos, - FALSE, - FALSE); - mTabContainer->setFollowsAll(); - if (isResizable() && mTabPos == LLTabContainer::BOTTOM) - { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - - addChild(mTabContainer); - -} - - -void LLMultiFloater::open() /* Flawfinder: ignore */ -{ - if (mTabContainer->getTabCount() > 0) - { - LLFloater::open(); /* Flawfinder: ignore */ - } - else - { - // for now, don't allow multifloaters - // without any child floaters - close(); - } -} - -void LLMultiFloater::onClose(bool app_quitting) +void LLFloater::setInstanceName(const std::string& name) { - if(closeAllFloaters() == TRUE) - { - LLFloater::onClose(app_quitting); - }//else not all tabs could be closed... -} - -void LLMultiFloater::draw() -{ - if (mTabContainer->getTabCount() == 0) - { - //RN: could this potentially crash in draw hierarchy? - close(); - } - else + if (name == mInstanceName) + return; + llassert_always(mInstanceName.empty()); + mInstanceName = name; + if (!mInstanceName.empty()) { - for (S32 i = 0; i < mTabContainer->getTabCount(); i++) + // save_rect and save_visibility only apply to registered floaters + if (!mRectControl.empty()) { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(i); - if (floaterp->getShortTitle() != mTabContainer->getPanelTitle(i)) - { - mTabContainer->setPanelTitle(i, floaterp->getShortTitle()); - } + mRectControl = LLFloaterReg::declareRectControl(mInstanceName); } - LLFloater::draw(); - } -} - -BOOL LLMultiFloater::closeAllFloaters() -{ - S32 tabToClose = 0; - S32 lastTabCount = mTabContainer->getTabCount(); - while (tabToClose < mTabContainer->getTabCount()) - { - LLFloater* first_floater = (LLFloater*)mTabContainer->getPanelByIndex(tabToClose); - first_floater->close(); - if(lastTabCount == mTabContainer->getTabCount()) - { - //Tab did not actually close, possibly due to a pending Save Confirmation dialog.. - //so try and close the next one in the list... - tabToClose++; - }else + if (!mVisibilityControl.empty()) { - //Tab closed ok. - lastTabCount = mTabContainer->getTabCount(); + mVisibilityControl = LLFloaterReg::declareVisibilityControl(mInstanceName); } } - if( mTabContainer->getTabCount() != 0 ) - return FALSE; // Couldn't close all the tabs (pending save dialog?) so return FALSE. - return TRUE; //else all tabs were successfully closed... } -void LLMultiFloater::growToFit(S32 content_width, S32 content_height) +void LLFloater::setKey(const LLSD& newkey) { - S32 new_width = llmax(getRect().getWidth(), content_width + LLPANEL_BORDER_WIDTH * 2); - S32 new_height = llmax(getRect().getHeight(), content_height + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); - - if (isMinimized()) - { - LLRect newrect; - newrect.setLeftTopAndSize(getExpandedRect().mLeft, getExpandedRect().mTop, new_width, new_height); - setExpandedRect(newrect); - } - else - { - S32 old_height = getRect().getHeight(); - reshape(new_width, new_height); - // keep top left corner in same position - translate(0, old_height - new_height); - } + // Note: We don't have to do anything special with registration when we change keys + mKey = newkey; } -/** - void addFloater(LLFloater* floaterp, BOOL select_added_floater) - - Adds the LLFloater pointed to by floaterp to this. - If floaterp is already hosted by this, then it is re-added to get - new titles, etc. - If select_added_floater is true, the LLFloater pointed to by floaterp will - become the selected tab in this - - Affects: mTabContainer, floaterp -**/ -void LLMultiFloater::addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point) +//static +void LLFloater::setupParamsForExport(Params& p, LLView* parent) { - if (!floaterp) - { - return; - } - - if (!mTabContainer) - { - llerrs << "Tab Container used without having been initialized." << llendl; - return; - } - - if (floaterp->getHost() == this) - { - // already hosted by me, remove - // do this so we get updated title, etc. - mFloaterDataMap.erase(floaterp->getHandle()); - mTabContainer->removeTabPanel(floaterp); - } - else if (floaterp->getHost()) - { - // floaterp is hosted by somebody else and - // this is adding it, so remove it from it's old host - floaterp->getHost()->removeFloater(floaterp); - } - else if (floaterp->getParent() == gFloaterView) - { - // rehost preview floater as child panel - gFloaterView->removeChild(floaterp); - } - - // store original configuration - LLFloaterData floater_data; - floater_data.mWidth = floaterp->getRect().getWidth(); - floater_data.mHeight = floaterp->getRect().getHeight(); - floater_data.mCanMinimize = floaterp->isMinimizeable(); - floater_data.mCanResize = floaterp->isResizable(); + // Do rectangle munging to topleft layout first + LLPanel::setupParamsForExport(p, parent); - // remove minimize and close buttons - floaterp->setCanMinimize(FALSE); - floaterp->setCanResize(FALSE); - floaterp->setCanDrag(FALSE); - floaterp->storeRectControl(); - // avoid double rendering of floater background (makes it more opaque) - floaterp->setBackgroundVisible(FALSE); - - if (mAutoResize) - { - growToFit(floater_data.mWidth, floater_data.mHeight); - } + // Copy the rectangle out to apply layout constraints + LLRect rect = p.rect; - //add the panel, add it to proper maps - mTabContainer->addTabPanel(floaterp, floaterp->getShortTitle(), FALSE, onTabSelected, this, 0, FALSE, insertion_point); - mFloaterDataMap[floaterp->getHandle()] = floater_data; + // Null out other settings + p.rect.left.setProvided(false); + p.rect.top.setProvided(false); + p.rect.right.setProvided(false); + p.rect.bottom.setProvided(false); - updateResizeLimits(); + // Explicitly set width/height + p.rect.width.set( rect.getWidth(), true ); + p.rect.height.set( rect.getHeight(), true ); - if ( select_added_floater ) - { - mTabContainer->selectTabPanel(floaterp); - } - else + // If you can't resize this floater, don't export min_height + // and min_width + bool can_resize = p.can_resize; + if (!can_resize) { - // reassert visible tab (hiding new floater if necessary) - mTabContainer->selectTab(mTabContainer->getCurrentPanelIndex()); - } - - floaterp->setHost(this); - if (isMinimized()) - { - floaterp->setVisible(FALSE); + p.min_height.setProvided(false); + p.min_width.setProvided(false); } } -/** - BOOL selectFloater(LLFloater* floaterp) - - If the LLFloater pointed to by floaterp is hosted by this, - then its tab is selected and returns true. Otherwise returns false. - - Affects: mTabContainer -**/ -BOOL LLMultiFloater::selectFloater(LLFloater* floaterp) +void LLFloater::initFromParams(const LLFloater::Params& p) { - return mTabContainer->selectTabPanel(floaterp); -} + // control_name, tab_stop, focus_lost_callback, initial_value, rect, enabled, visible + LLPanel::initFromParams(p); -// virtual -void LLMultiFloater::selectNextFloater() -{ - mTabContainer->selectNextTab(); -} + mTitle = p.title; + mShortTitle = p.short_title; + applyTitle(); -// virtual -void LLMultiFloater::selectPrevFloater() -{ - mTabContainer->selectPrevTab(); -} + setCanTearOff(p.can_tear_off); + setCanMinimize(p.can_minimize); + setCanClose(p.can_close); + + mDragOnLeft = p.can_drag_on_left; + mResizable = p.can_resize; + mMinWidth = p.min_width; + mMinHeight = p.min_height; + mSingleInstance = p.single_instance; + mAutoTile = p.auto_tile; -void LLMultiFloater::showFloater(LLFloater* floaterp) -{ - // we won't select a panel that already is selected - // it is hard to do this internally to tab container - // as tab selection is handled via index and the tab at a given - // index might have changed - if (floaterp != mTabContainer->getCurrentPanel() && - !mTabContainer->selectTabPanel(floaterp)) + if (p.save_rect) { - addFloater(floaterp, TRUE); + mRectControl = "t"; // flag to build mRectControl name once mInstanceName is set } -} - -void LLMultiFloater::removeFloater(LLFloater* floaterp) -{ - if ( floaterp->getHost() != this ) - return; - - floater_data_map_t::iterator found_data_it = mFloaterDataMap.find(floaterp->getHandle()); - if (found_data_it != mFloaterDataMap.end()) + if (p.save_visibility) { - LLFloaterData& floater_data = found_data_it->second; - floaterp->setCanMinimize(floater_data.mCanMinimize); - if (!floater_data.mCanResize) - { - // restore original size - floaterp->reshape(floater_data.mWidth, floater_data.mHeight); - } - floaterp->setCanResize(floater_data.mCanResize); - mFloaterDataMap.erase(found_data_it); + mVisibilityControl = "t"; // flag to build mVisibilityControl name once mInstanceName is set } - mTabContainer->removeTabPanel(floaterp); - floaterp->setBackgroundVisible(TRUE); - floaterp->setCanDrag(TRUE); - floaterp->setHost(NULL); - floaterp->applyRectControl(); - - updateResizeLimits(); - - tabOpen((LLFloater*)mTabContainer->getCurrentPanel(), false); } -void LLMultiFloater::tabOpen(LLFloater* opened_floater, bool from_click) +void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floater, LLXMLNodePtr output_node) { - // default implementation does nothing -} + Params params(LLUICtrlFactory::getDefaultParams()); + LLXUIParser::instance().readXUI(node, params); -void LLMultiFloater::tabClose() -{ - if (mTabContainer->getTabCount() == 0) + if (output_node) { - // no more children, close myself - close(); + Params output_params(params); + setupParamsForExport(output_params, parent); + Params default_params(LLUICtrlFactory::getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); } -} -void LLMultiFloater::setVisible(BOOL visible) -{ - // *FIX: shouldn't have to do this, fix adding to minimized multifloater - LLFloater::setVisible(visible); + setupParams(params, parent); + initFromParams(params); + + initFloater(); - if (mTabContainer) + LLMultiFloater* last_host = LLFloater::getFloaterHost(); + if (node->hasName("multi_floater")) { - LLPanel* cur_floaterp = mTabContainer->getCurrentPanel(); + LLFloater::setFloaterHost((LLMultiFloater*) this); + } - if (cur_floaterp) - { - cur_floaterp->setVisible(visible); - } + LLUICtrlFactory::createChildren(this, node, output_node); - // if no tab selected, and we're being shown, - // select last tab to be added - if (visible && !cur_floaterp) - { - mTabContainer->selectLastTab(); - } + if (node->hasName("multi_floater")) + { + LLFloater::setFloaterHost(last_host); } -} + + BOOL result = postBuild(); -BOOL LLMultiFloater::handleKeyHere(KEY key, MASK mask) -{ - if (key == 'W' && mask == MASK_CONTROL) + if (!result) { - LLFloater* floater = getActiveFloater(); - // is user closeable and is system closeable - if (floater && floater->canClose() && floater->isCloseable()) - { - floater->close(); - } - return TRUE; + llerrs << "Failed to construct floater " << getName() << llendl; } - return LLFloater::handleKeyHere(key, mask); -} - -LLFloater* LLMultiFloater::getActiveFloater() -{ - return (LLFloater*)mTabContainer->getCurrentPanel(); -} - -S32 LLMultiFloater::getFloaterCount() -{ - return mTabContainer->getTabCount(); -} - -/** - BOOL isFloaterFlashing(LLFloater* floaterp) - - Returns true if the LLFloater pointed to by floaterp - is currently in a flashing state and is hosted by this. - False otherwise. - - Requires: floaterp != NULL -**/ -BOOL LLMultiFloater::isFloaterFlashing(LLFloater* floaterp) -{ - if ( floaterp && floaterp->getHost() == this ) - return mTabContainer->getTabPanelFlashing(floaterp); - - return FALSE; -} - -/** - BOOL setFloaterFlashing(LLFloater* floaterp, BOOL flashing) - - Sets the current flashing state of the LLFloater pointed - to by floaterp to be the BOOL flashing if the LLFloater pointed - to by floaterp is hosted by this. - - Requires: floaterp != NULL -**/ -void LLMultiFloater::setFloaterFlashing(LLFloater* floaterp, BOOL flashing) -{ - if ( floaterp && floaterp->getHost() == this ) - mTabContainer->setTabPanelFlashing(floaterp, flashing); -} - -//static -void LLMultiFloater::onTabSelected(void* userdata, bool from_click) -{ - LLMultiFloater* floaterp = (LLMultiFloater*)userdata; - - floaterp->tabOpen((LLFloater*)floaterp->mTabContainer->getCurrentPanel(), from_click); -} + applyRectControl(); // If we have a saved rect control, apply it + gFloaterView->adjustToFitScreen(this, FALSE); // Floaters loaded from XML should all fit on screen -void LLMultiFloater::setCanResize(BOOL can_resize) -{ - LLFloater::setCanResize(can_resize); - if (isResizable() && mTabContainer->getTabPosition() == LLTabContainer::BOTTOM) + if (open_floater) { - mTabContainer->setRightTabBtnOffset(RESIZE_HANDLE_WIDTH); - } - else - { - mTabContainer->setRightTabBtnOffset(0); + this->openFloater(getKey()); } + + moveResizeHandlesToFront(); } -BOOL LLMultiFloater::postBuild() +// visibility methods +bool VisibilityPolicy::visible(LLFloater* instance, const LLSD& key) { - // remember any original xml minimum size - getResizeLimits(&mOrigMinWidth, &mOrigMinHeight); - - if (mTabContainer) - { - return TRUE; - } - - requires("Preview Tabs"); - if (checkRequirements()) + if (instance) { - mTabContainer = getChild("Preview Tabs"); - return TRUE; + return !instance->isMinimized() && instance->isInVisibleChain(); } - return FALSE; } -void LLMultiFloater::updateResizeLimits() +void VisibilityPolicy::show(LLFloater* instance, const LLSD& key) { - // initialize minimum size constraint to the original xml values. - S32 new_min_width = mOrigMinWidth; - S32 new_min_height = mOrigMinHeight; - // possibly increase minimum size constraint due to children's minimums. - for (S32 tab_idx = 0; tab_idx < mTabContainer->getTabCount(); ++tab_idx) + if (instance) { - LLFloater* floaterp = (LLFloater*)mTabContainer->getPanelByIndex(tab_idx); - if (floaterp) + instance->openFloater(key); + if (instance->getHost()) { - new_min_width = llmax(new_min_width, floaterp->getMinWidth() + LLPANEL_BORDER_WIDTH * 2); - new_min_height = llmax(new_min_height, floaterp->getMinHeight() + LLFLOATER_HEADER_SIZE + TABCNTR_HEADER_HEIGHT); + instance->getHost()->openFloater(key); } } - setResizeLimits(new_min_width, new_min_height); - - S32 cur_height = getRect().getHeight(); - S32 new_width = llmax(getRect().getWidth(), new_min_width); - S32 new_height = llmax(getRect().getHeight(), new_min_height); - - if (isMinimized()) - { - const LLRect& expanded = getExpandedRect(); - LLRect newrect; - newrect.setLeftTopAndSize(expanded.mLeft, expanded.mTop, llmax(expanded.getWidth(), new_width), llmax(expanded.getHeight(), new_height)); - setExpandedRect(newrect); - } - else - { - reshape(new_width, new_height); - - // make sure upper left corner doesn't move - translate(0, cur_height - getRect().getHeight()); - - // make sure this window is visible on screen when it has been modified - // (tab added, etc) - gFloaterView->adjustToFitScreen(this, TRUE); - } } -// virtual -LLXMLNodePtr LLFloater::getXML(bool save_children) const +void VisibilityPolicy::hide(LLFloater* instance, const LLSD& key) { - LLXMLNodePtr node = LLPanel::getXML(); - - node->createChild("title", TRUE)->setStringValue(getCurrentTitle()); - - node->createChild("can_resize", TRUE)->setBoolValue(isResizable()); - - node->createChild("can_minimize", TRUE)->setBoolValue(isMinimizeable()); - - node->createChild("can_close", TRUE)->setBoolValue(isCloseable()); - - node->createChild("can_drag_on_left", TRUE)->setBoolValue(isDragOnLeft()); - - node->createChild("min_width", TRUE)->setIntValue(getMinWidth()); - - node->createChild("min_height", TRUE)->setIntValue(getMinHeight()); - - node->createChild("can_tear_off", TRUE)->setBoolValue(mCanTearOff); - - return node; -} - -// static -LLView* LLFloater::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - std::string name("floater"); - node->getAttributeString("name", name); - - LLFloater *floaterp = new LLFloater(name); - - std::string filename; - node->getAttributeString("filename", filename); - - if (filename.empty()) - { - // Load from node - floaterp->initFloaterXML(node, parent, factory); - } - else - { - // Load from file - factory->buildFloater(floaterp, filename); - } - - return floaterp; + if (instance) instance->closeFloater(); } -void LLFloater::initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open) /* Flawfinder: ignore */ -{ - std::string name(getName()); - std::string title(getCurrentTitle()); - std::string short_title(getShortTitle()); - std::string rect_control(""); - BOOL resizable = isResizable(); - S32 min_width = getMinWidth(); - S32 min_height = getMinHeight(); - BOOL drag_on_left = isDragOnLeft(); - BOOL minimizable = isMinimizeable(); - BOOL close_btn = isCloseable(); - LLRect rect; - - node->getAttributeString("name", name); - node->getAttributeString("title", title); - node->getAttributeString("short_title", short_title); - node->getAttributeString("rect_control", rect_control); - node->getAttributeBOOL("can_resize", resizable); - node->getAttributeBOOL("can_minimize", minimizable); - node->getAttributeBOOL("can_close", close_btn); - node->getAttributeBOOL("can_drag_on_left", drag_on_left); - node->getAttributeS32("min_width", min_width); - node->getAttributeS32("min_height", min_height); - - if (! rect_control.empty()) - { - setRectControl(rect_control); - } - - createRect(node, rect, parent, LLRect()); - - setRect(rect); - setName(name); - - initFloater(title, - resizable, - min_width, - min_height, - drag_on_left, - minimizable, - close_btn); - - setTitle(title); - applyTitle (); - - setShortTitle(short_title); - - BOOL can_tear_off; - if (node->getAttributeBOOL("can_tear_off", can_tear_off)) - { - setCanTearOff(can_tear_off); - } - - initFromXML(node, parent); - - LLMultiFloater* last_host = LLFloater::getFloaterHost(); - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost((LLMultiFloater*) this); - } - - initChildrenXML(node, factory); - - if (node->hasName("multi_floater")) - { - LLFloater::setFloaterHost(last_host); - } - - BOOL result = postBuild(); - - if (!result) - { - llerrs << "Failed to construct floater " << name << llendl; - } - - applyRectControl(); - if (open) /* Flawfinder: ignore */ - { - this->open(); /* Flawfinder: ignore */ - } - - moveResizeHandlesToFront(); -} diff --git a/indra/llui/llfloater.h b/indra/llui/llfloater.h index 0e3d148b09..421b7f3ec1 100644 --- a/indra/llui/llfloater.h +++ b/indra/llui/llfloater.h @@ -39,7 +39,6 @@ #include "llpanel.h" #include "lluuid.h" -#include "lltabcontainer.h" #include "llnotifications.h" #include @@ -50,17 +49,10 @@ class LLButton; class LLMultiFloater; class LLFloater; -const S32 LLFLOATER_VPAD = 6; -const S32 LLFLOATER_HPAD = 6; -const S32 LLFLOATER_CLOSE_BOX_SIZE = 16; -const S32 LLFLOATER_HEADER_SIZE = 18; const BOOL RESIZE_YES = TRUE; const BOOL RESIZE_NO = FALSE; -const S32 DEFAULT_MIN_WIDTH = 100; -const S32 DEFAULT_MIN_HEIGHT = 100; - const BOOL DRAG_ON_TOP = FALSE; const BOOL DRAG_ON_LEFT = TRUE; @@ -87,11 +79,22 @@ private: LLHandle mFloaterHandle; }; - class LLFloater : public LLPanel { friend class LLFloaterView; +friend class LLFloaterReg; +friend class LLMultiFloater; public: + struct KeyCompare + { + 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 { BUTTON_CLOSE, @@ -102,49 +105,66 @@ public: BUTTON_COUNT }; - LLFloater(); - LLFloater(const std::string& name); //simple constructor for data-driven initialization - LLFloater( const std::string& name, const LLRect& rect, const std::string& title, - BOOL resizable = FALSE, - S32 min_width = DEFAULT_MIN_WIDTH, - S32 min_height = DEFAULT_MIN_HEIGHT, - BOOL drag_on_left = FALSE, - BOOL minimizable = TRUE, - BOOL close_btn = TRUE, - BOOL bordered = BORDER_NO); - - LLFloater( const std::string& name, const std::string& rect_control, const std::string& title, - BOOL resizable = FALSE, - S32 min_width = DEFAULT_MIN_WIDTH, - S32 min_height = DEFAULT_MIN_HEIGHT, - BOOL drag_on_left = FALSE, - BOOL minimizable = TRUE, - BOOL close_btn = TRUE, - BOOL bordered = BORDER_NO); + struct Params + : public LLInitParam::Block + { + Optional title, + short_title; + + Optional single_instance, + auto_tile, + can_resize, + can_minimize, + can_close, + can_drag_on_left, + can_tear_off, + save_rect, + save_visibility; + + Params() : + title("title"), + short_title("short_title"), + single_instance("single_instance", false), + auto_tile("auto_tile", false), + can_resize("can_resize", false), + can_minimize("can_minimize", true), + can_close("can_close", true), + can_drag_on_left("can_drag_on_left", false), + can_tear_off("can_tear_off", true), + save_rect("save_rect", false), + save_visibility("save_visibility", false) + { + name = "floater"; + // defaults that differ from LLPanel: + background_visible = true; + visible = false; + } + }; + + LLFloater(const LLSD& key = LLSD(), const LLFloater::Params& params = LLFloater::Params()); virtual ~LLFloater(); - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - void initFloaterXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory, BOOL open = TRUE); + // Don't export top/left for rect, only height/width + static void setupParamsForExport(Params& p, LLView* parent); + + void initFromParams(const LLFloater::Params& p); + void initFloaterXML(LLXMLNodePtr node, LLView *parent, BOOL open_floater = TRUE, LLXMLNodePtr output_node = NULL); - /*virtual*/ void userSetShape(const LLRect& new_rect); + /*virtual*/ void handleReshape(const LLRect& new_rect, bool by_user = false); /*virtual*/ BOOL canSnapTo(const LLView* other_view); - /*virtual*/ void snappedTo(const LLView* snap_view); + /*virtual*/ void setSnappedTo(const LLView* snap_view); /*virtual*/ void setFocus( BOOL b ); /*virtual*/ void setIsChrome(BOOL is_chrome); + /*virtual*/ void setRect(const LLRect &rect); - // Can be called multiple times to reset floater parameters. - // Deletes all children of the floater. - virtual void initFloater(const std::string& title, BOOL resizable, - S32 min_width, S32 min_height, BOOL drag_on_left, - BOOL minimizable, BOOL close_btn); + void initFloater(); - virtual void open(); /* Flawfinder: ignore */ + void openFloater(const LLSD& key = LLSD()); // If allowed, close the floater cleanly, releasing focus. // app_quitting is passed to onClose() below. - virtual void close(bool app_quitting = false); + void closeFloater(bool app_quitting = false); /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); @@ -153,11 +173,8 @@ public: // moves to center of gFloaterView void center(); - // applies rectangle stored in mRectControl, if any - void applyRectControl(); - - LLMultiFloater* getHost() { return (LLMultiFloater*)mHostHandle.get(); } + LLMultiFloater* getHost(); void applyTitle(); const std::string& getCurrentTitle() const; @@ -185,9 +202,8 @@ public: void setResizeLimits( S32 min_width, S32 min_height ); void getResizeLimits( S32* min_width, S32* min_height ) { *min_width = mMinWidth; *min_height = mMinHeight; } - bool isMinimizeable() const{ return mButtonsEnabled[BUTTON_MINIMIZE]; } - // Does this window have a close button, NOT can we close it right now. - bool isCloseable() const{ return (mButtonsEnabled[BUTTON_CLOSE]); } + bool isMinimizeable() const{ return mCanMinimize; } + bool isCloseable() const{ return mCanClose; } bool isDragOnLeft() const{ return mDragOnLeft; } S32 getMinWidth() const{ return mMinWidth; } S32 getMinHeight() const{ return mMinHeight; } @@ -198,7 +214,7 @@ public: virtual BOOL handleMiddleMouseDown(S32 x, S32 y, MASK mask); virtual void draw(); - virtual void onOpen() {} + virtual void onOpen(const LLSD& key) {} // Call destroy() to free memory, or setVisible(FALSE) to keep it // If app_quitting, you might not want to save your visibility. @@ -210,8 +226,10 @@ public: virtual BOOL canClose() { return TRUE; } virtual void setVisible(BOOL visible); + virtual void onVisibilityChange ( BOOL curVisibilityIn ); + void setFrontmost(BOOL take_focus = TRUE); - + // Defaults to false. virtual BOOL canSaveAs() const { return FALSE; } @@ -222,6 +240,8 @@ public: LLHandle getSnapTarget() const { return mSnappedTo; } LLHandle getHandle() const { return mHandle; } + const LLSD& getKey() { return mKey; } + BOOL matchesKey(const LLSD& key) { return mSingleInstance || KeyCompare::equate(key, mKey); } // Return a closeable floater, if any, given the current focus. static LLFloater* getClosableFloaterFromFocus(); @@ -235,22 +255,30 @@ public: return LLNotification::Params(name).context(mNotificationContext); } - static void onClickClose(void *userdata); - static void onClickMinimize(void *userdata); - static void onClickTearOff(void *userdata); - static void onClickEdit(void *userdata); + static void onClickClose(LLFloater* floater); + static void onClickMinimize(LLFloater* floater); + static void onClickTearOff(LLFloater* floater); + static void onClickEdit(LLFloater* floater); static void setFloaterHost(LLMultiFloater* hostp) {sHostp = hostp; } static void setEditModeEnabled(BOOL enable); static BOOL getEditModeEnabled() { return sEditModeEnabled; } - static LLMultiFloater* getFloaterHost() {return sHostp; } - + static LLMultiFloater* getFloaterHost() {return sHostp; } + protected: + void setRectControl(const std::string& rectname) { mRectControl = rectname; }; + void applyRectControl(); + void storeRectControl(); + void storeVisibilityControl(); + + void setKey(const LLSD& key); + void setInstanceName(const std::string& name); + virtual void bringToFront(S32 x, S32 y); virtual void setVisibleAndFrontmost(BOOL take_focus=TRUE); - void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized + void setExpandedRect(const LLRect& rect) { mExpandedRect = rect; } // size when not minimized const LLRect& getExpandedRect() const { return mExpandedRect; } void setAutoFocus(BOOL focus) { mAutoFocus = focus; } // whether to automatically take focus when opened @@ -266,31 +294,48 @@ private: void updateButtons(); void buildButtons(); BOOL offerClickToButton(S32 x, S32 y, MASK mask, EFloaterButtons index); - + void addResizeCtrls(); + void addDragHandle(); + +protected: + std::string mRectControl; + std::string mVisibilityControl; + + LLSD mKey; // Key used for retrieving instances; set (for now) by LLFLoaterReg + +private: LLRect mExpandedRect; LLDragHandle* mDragHandle; LLResizeBar* mResizeBar[4]; LLResizeHandle* mResizeHandle[4]; - LLButton *mMinimizeButton; + + LLUIString mTitle; + LLUIString mShortTitle; + + BOOL mSingleInstance; // TRUE if there is only ever one instance of the floater + std::string mInstanceName; // Store the instance name so we can remove ourselves from the list + BOOL mAutoTile; // TRUE if placement of new instances tiles + BOOL mCanTearOff; + BOOL mCanMinimize; + BOOL mCanClose; + BOOL mDragOnLeft; + BOOL mResizable; + + S32 mMinWidth; + S32 mMinHeight; + BOOL mMinimized; BOOL mForeground; LLHandle mDependeeHandle; - std::string mTitle; - std::string mShortTitle; + BOOL mFirstLook; // TRUE if the _next_ time this floater is visible will be the first time in the session that it is visible. - - BOOL mResizable; - S32 mMinWidth; - S32 mMinHeight; - BOOL mEditing; typedef std::set > handle_set_t; typedef std::set >::iterator handle_set_iter_t; handle_set_t mDependents; - bool mDragOnLeft; BOOL mButtonsEnabled[BUTTON_COUNT]; LLButton* mButtons[BUTTON_COUNT]; @@ -308,7 +353,9 @@ private: static std::string sButtonPressedImageNames[BUTTON_COUNT]; static std::string sButtonNames[BUTTON_COUNT]; static std::string sButtonToolTips[BUTTON_COUNT]; - typedef void (*click_callback)(void *); + static std::string sButtonToolTipsIndex[BUTTON_COUNT]; + + typedef void(*click_callback)(LLFloater*); static click_callback sButtonCallbacks[BUTTON_COUNT]; typedef std::map, LLFloater*> handle_map_t; @@ -320,7 +367,10 @@ private: BOOL mHasBeenDraggedWhileMinimized; S32 mPreviousMinimizedBottom; S32 mPreviousMinimizedLeft; - + + LLColor4 mBgColorAlpha; + LLColor4 mBgColorOpaque; + LLFloaterNotificationContext* mNotificationContext; LLRootHandle mHandle; }; @@ -331,18 +381,18 @@ private: class LLFloaterView : public LLUICtrl { -public: - LLFloaterView( const std::string& name, const LLRect& rect ); +protected: + LLFloaterView (const Params& p); + friend class LLUICtrlFactory; +public: /*virtual*/ void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); void reshapeFloater(S32 width, S32 height, BOOL called_from_parent, BOOL adjust_vertical); /*virtual*/ void draw(); /*virtual*/ LLRect getSnapRect() const; - void refresh(); + /*virtual*/ void refresh(); - void getNewFloaterPosition( S32* left, S32* top ); - void resetStartingFloaterPosition(); LLRect findNeighboringPosition( LLFloater* reference_floater, LLFloater* neighbor ); // Given a child of gFloaterView, make sure this view can fit entirely onscreen. @@ -365,10 +415,10 @@ public: void closeAllChildren(bool app_quitting); BOOL allChildrenClosed(); - LLFloater* getFrontmost(); - LLFloater* getBackmost(); - LLFloater* getParentFloater(LLView* viewp); - LLFloater* getFocusedFloater(); + LLFloater* getFrontmost() const; + LLFloater* getBackmost() const; + LLFloater* getParentFloater(LLView* viewp) const; + LLFloater* getFocusedFloater() const; void syncFloaterTabOrder(); // Returns z order of child provided. 0 is closest, larger numbers @@ -377,6 +427,7 @@ public: S32 getZOrder(LLFloater* child); void setSnapOffsetBottom(S32 offset) { mSnapOffsetBottom = offset; } + void setSnapOffsetRight(S32 offset) { mSnapOffsetRight = offset; } private: S32 mColumn; @@ -384,101 +435,26 @@ private: S32 mNextTop; BOOL mFocusCycleMode; S32 mSnapOffsetBottom; + S32 mSnapOffsetRight; }; -// https://wiki.lindenlab.com/mediawiki/index.php?title=LLMultiFloater&oldid=81376 -class LLMultiFloater : public LLFloater -{ -public: - LLMultiFloater(); - LLMultiFloater(LLTabContainer::TabPosition tab_pos); - LLMultiFloater(const std::string& name); - LLMultiFloater(const std::string& name, const LLRect& rect, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); - LLMultiFloater(const std::string& name, const std::string& rect_control, LLTabContainer::TabPosition tab_pos = LLTabContainer::TOP, BOOL auto_resize = TRUE); - virtual ~LLMultiFloater() {}; - - virtual BOOL postBuild(); - /*virtual*/ void open(); /* Flawfinder: ignore */ - /*virtual*/ void onClose(bool app_quitting); - /*virtual*/ void draw(); - /*virtual*/ void setVisible(BOOL visible); - /*virtual*/ BOOL handleKeyHere(KEY key, MASK mask); - - virtual void setCanResize(BOOL can_resize); - virtual void growToFit(S32 content_width, S32 content_height); - virtual void addFloater(LLFloater* floaterp, BOOL select_added_floater, LLTabContainer::eInsertionPoint insertion_point = LLTabContainer::END); - - virtual void showFloater(LLFloater* floaterp); - virtual void removeFloater(LLFloater* floaterp); - - virtual void tabOpen(LLFloater* opened_floater, bool from_click); - virtual void tabClose(); - - virtual BOOL selectFloater(LLFloater* floaterp); - virtual void selectNextFloater(); - virtual void selectPrevFloater(); - - virtual LLFloater* getActiveFloater(); - virtual BOOL isFloaterFlashing(LLFloater* floaterp); - virtual S32 getFloaterCount(); - - virtual void setFloaterFlashing(LLFloater* floaterp, BOOL flashing); - virtual BOOL closeAllFloaters(); //Returns FALSE if the floater could not be closed due to pending confirmation dialogs - void setTabContainer(LLTabContainer* tab_container) { if (!mTabContainer) mTabContainer = tab_container; } - static void onTabSelected(void* userdata, bool); - - virtual void updateResizeLimits(); - -protected: - struct LLFloaterData - { - S32 mWidth; - S32 mHeight; - BOOL mCanMinimize; - BOOL mCanResize; - }; - - LLTabContainer* mTabContainer; - - typedef std::map, LLFloaterData> floater_data_map_t; - floater_data_map_t mFloaterDataMap; - - LLTabContainer::TabPosition mTabPos; - BOOL mAutoResize; - S32 mOrigMinWidth, mOrigMinHeight; // logically const but initialized late -}; +// singleton implementation for floaters +// https://wiki.lindenlab.com/mediawiki/index.php?title=LLFloaterSingleton&oldid=164990 +//******************************************************* +//* TO BE DEPRECATED +//******************************************************* // visibility policy specialized for floaters template<> class VisibilityPolicy { public: // visibility methods - static bool visible(LLFloater* instance, const LLSD& key) - { - if (instance) - { - return !instance->isMinimized() && instance->isInVisibleChain(); - } - return FALSE; - } + static bool visible(LLFloater* instance, const LLSD& key); - static void show(LLFloater* instance, const LLSD& key) - { - if (instance) - { - instance->open(); - if (instance->getHost()) - { - instance->getHost()->open(); - } - } - } + static void show(LLFloater* instance, const LLSD& key); - static void hide(LLFloater* instance, const LLSD& key) - { - if (instance) instance->close(); - } + static void hide(LLFloater* instance, const LLSD& key); }; @@ -489,6 +465,10 @@ template class LLFloaterSingleton : public LLUISingleton LLFloaterReg::sGroupMap; + +//******************************************************* + +//static +void LLFloaterReg::add(const std::string& name, const std::string& filename, const LLFloaterBuildFunc& func, const std::string& groupname) +{ + sBuildMap[name].mFunc = func; + sBuildMap[name].mFile = filename; + sGroupMap[name] = groupname.empty() ? name : groupname; + sGroupMap[groupname] = groupname; // for referencing directly by group name +} + +//static +LLRect LLFloaterReg::getFloaterRect(const std::string& name) +{ + LLRect rect; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + if (!list.empty()) + { + static LLUICachedControl floater_offset ("UIFloaterOffset", 16); + LLFloater* last_floater = list.back(); + if (last_floater->getHost()) + { + rect = last_floater->getHost()->getRect(); + } + else + { + rect = last_floater->getRect(); + } + rect.translate(floater_offset, -floater_offset); + } + } + return rect; +} + +//static +LLFloater* LLFloaterReg::findInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + break; + } + } + } + return res; +} + +//static +LLFloater* LLFloaterReg::getInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = findInstance(name, key); + if (!res) + { + const LLFloaterBuildFunc& build_func = sBuildMap[name].mFunc; + const std::string& xui_file = sBuildMap[name].mFile; + if (build_func) + { + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + int index = list.size(); + + res = build_func(key); + + const bool DONT_OPEN_FLOATER = false; + LLUICtrlFactory::getInstance()->buildFloater(res, xui_file, DONT_OPEN_FLOATER); + + // 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 + if (res->mAutoTile && !res->getHost() && index > 0) + { + const LLRect& cur_rect = res->getRect(); + LLRect next_rect = getFloaterRect(groupname); + next_rect.setLeftTopAndSize(next_rect.mLeft, next_rect.mTop, cur_rect.getWidth(), cur_rect.getHeight()); + res->setRect(next_rect); + res->setRectControl(LLStringUtil::null); // don't save rect of tiled floaters + gFloaterView->adjustToFitScreen(res, true); + } + else + { + gFloaterView->adjustToFitScreen(res, false); + } + list.push_back(res); + } + } + if (!res) + { + llwarns << "Floater type: '" << name << "' not registered." << llendl; + } + } + return res; +} + +//static +LLFloater* LLFloaterReg::removeInstance(const std::string& name, const LLSD& key) +{ + LLFloater* res = NULL; + const std::string& groupname = sGroupMap[name]; + if (!groupname.empty()) + { + instance_list_t& list = sInstanceMap[groupname]; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* inst = *iter; + if (inst->matchesKey(key)) + { + res = inst; + list.erase(iter); + break; + } + } + } + return res; +} + +//static +// returns true if the instance existed +bool LLFloaterReg::destroyInstance(const std::string& name, const LLSD& key) +{ + LLFloater* inst = removeInstance(name, key); + if (inst) + { + delete inst; + return true; + } + else + { + return false; + } +} + +// Iterators +//static +LLFloaterReg::const_instance_list_t& LLFloaterReg::getFloaterList(const std::string& name) +{ + instance_map_t::iterator iter = sInstanceMap.find(name); + if (iter != sInstanceMap.end()) + { + return iter->second; + } + else + { + return sNullInstanceList; + } +} + +// Visibility Management + +//static +LLFloater* LLFloaterReg::showInstance(const std::string& name, const LLSD& key, BOOL focus) +{ + LLFloater* instance = getInstance(name, key); + if (instance) + { + instance->openFloater(key); + if (focus) + instance->setFocus(TRUE); + } + return instance; +} + +//static +// returns true if the instance exists +bool LLFloaterReg::hideInstance(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance) + { + // When toggling *visibility*, close the host instead of the floater when hosted + if (instance->getHost()) + instance->getHost()->closeFloater(); + else + instance->closeFloater(); + return true; + } + else + { + return false; + } +} + +//static +// returns true if the instance is visible when completed +bool LLFloaterReg::toggleInstance(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance && !instance->isMinimized() && instance->isInVisibleChain()) + { + // When toggling *visibility*, close the host instead of the floater when hosted + if (instance->getHost()) + instance->getHost()->closeFloater(); + else + instance->closeFloater(); + return false; + } + else + { + return showInstance(name, key, TRUE) ? true : false; + } +} + +//static +// returns true if the instance exists and is visible +bool LLFloaterReg::instanceVisible(const std::string& name, const LLSD& key) +{ + LLFloater* instance = findInstance(name, key); + if (instance && !instance->isMinimized() && instance->isInVisibleChain()) + { + return true; + } + else + { + return false; + } +} + +//static +void LLFloaterReg::showInitialVisibleInstances() +{ + // Iterate through alll registered instance names and show any with a save visible state + for (build_map_t::iterator iter = sBuildMap.begin(); iter != sBuildMap.end(); ++iter) + { + const std::string& name = iter->first; + std::string controlname = getVisibilityControlName(name); + if (LLUI::sSettingGroups["floater"]->controlExists(controlname)) + { + BOOL isvis = LLUI::sSettingGroups["floater"]->getBOOL(controlname); + if (isvis) + { + showInstance(name, LLSD()); // keyed floaters shouldn't set save_vis to true + } + } + } +} + +//static +void LLFloaterReg::hideVisibleInstances(const std::set& exceptions) +{ + // Iterate through alll active instances and hide them + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + const std::string& name = iter->first; + if (exceptions.find(name) != exceptions.end()) + continue; + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->pushVisible(FALSE); + } + } +} + +//static +void LLFloaterReg::restoreVisibleInstances() +{ + // Iterate through all active instances and restore visibility + for (instance_map_t::iterator iter = sInstanceMap.begin(); iter != sInstanceMap.end(); ++iter) + { + instance_list_t& list = iter->second; + for (instance_list_t::iterator iter = list.begin(); iter != list.end(); ++iter) + { + LLFloater* floater = *iter; + floater->popVisible(); + } + } +} + +//static +std::string LLFloaterReg::getRectControlName(const std::string& name) +{ + std::string res = std::string("floater_rect_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; +} + +//static +std::string LLFloaterReg::declareRectControl(const std::string& name) +{ + std::string controlname = getRectControlName(name); + LLUI::sSettingGroups["floater"]->declareRect(controlname, LLRect(), + llformat("Window Position and Size for %s", name.c_str()), + TRUE); + return controlname; +} + +//static +std::string LLFloaterReg::getVisibilityControlName(const std::string& name) +{ + std::string res = std::string("floater_vis_") + name; + LLStringUtil::replaceChar( res, ' ', '_' ); + return res; +} + +//static +std::string LLFloaterReg::declareVisibilityControl(const std::string& name) +{ + std::string controlname = getVisibilityControlName(name); + LLUI::sSettingGroups["floater"]->declareBOOL(controlname, FALSE, + llformat("Window Visibility for %s", name.c_str()), + TRUE); + return controlname; +} + +// Callbacks + +// static +// Call once (i.e use for init callbacks) +void LLFloaterReg::initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname) +{ + // Get the visibility control name for the floater + std::string vis_control_name = LLFloaterReg::declareVisibilityControl(sdname.asString()); + // Set the control value to the floater visibility control (Sets the value as well) + ctrl->setControlVariable(LLUI::sSettingGroups["floater"]->getControl(vis_control_name)); +} + +// callback args may use "floatername.key" format +static void parse_name_key(std::string& name, LLSD& key) +{ + std::string instname = name; + std::size_t dotpos = instname.find("."); + if (dotpos != std::string::npos) + { + name = instname.substr(0, dotpos); + key = LLSD(instname.substr(dotpos+1, std::string::npos)); + } +} + +//static +void LLFloaterReg::showFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + showInstance(name, key, TRUE); +} +//static +void LLFloaterReg::hideFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + hideInstance(name, key); +} +//static +void LLFloaterReg::toggleFloaterInstance(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + toggleInstance(name, key); +} + +//static +bool LLFloaterReg::floaterInstanceVisible(const LLSD& sdname) +{ + LLSD key; + std::string name = sdname.asString(); + parse_name_key(name, key); + return instanceVisible(name, key); +} + diff --git a/indra/llui/llfloaterreg.h b/indra/llui/llfloaterreg.h new file mode 100644 index 0000000000..ef2f71ad18 --- /dev/null +++ b/indra/llui/llfloaterreg.h @@ -0,0 +1,152 @@ +/** + * @file llfloaterreg.h + * @brief LLFloaterReg Floater Registration Class + * + * $LicenseInfo:firstyear=2002&license=viewergpl$ + * + * Copyright (c) 2002-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ +#ifndef LLFLOATERREG_H +#define LLFLOATERREG_H + +/// llcommon +#include "llboost.h" +#include "llrect.h" +#include "llstl.h" +#include "llsd.h" + +/// llui +#include "lluictrl.h" + +#include + +//******************************************************* +// +// Floater Class Registry +// + +class LLFloater; + +typedef boost::function LLFloaterBuildFunc; + +class LLFloaterReg +{ +public: + // We use a list of LLFloater's instead of a set for two reasons: + // 1) With a list we have a predictable ordering, useful for finding the last opened floater of a given type. + // 2) We can change the key of a floater without altering the list. + typedef std::list instance_list_t; + typedef const instance_list_t const_instance_list_t; + typedef std::map instance_map_t; + + struct BuildData + { + LLFloaterBuildFunc mFunc; + std::string mFile; + }; + typedef std::map build_map_t; + +private: + static instance_list_t sNullInstanceList; + static instance_map_t sInstanceMap; + static build_map_t sBuildMap; + static std::map sGroupMap; + +public: + // Registration + + // usage: LLFloaterClassRegistry::add("foo", (LLFloaterBuildFunc)&LLFloaterClassRegistry::build); + template + static LLFloater* build(const LLSD& key) + { + T* floater = new T(key); + return floater; + } + + static void add(const std::string& name, const std::string& file, const LLFloaterBuildFunc& func, + const std::string& groupname = LLStringUtil::null); + + // Helpers + static LLRect getFloaterRect(const std::string& name); + + // Find / get (create) / remove / destroy + static LLFloater* findInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* getInstance(const std::string& name, const LLSD& key = LLSD()); + static LLFloater* removeInstance(const std::string& name, const LLSD& key = LLSD()); + static bool destroyInstance(const std::string& name, const LLSD& key = LLSD()); + + // Iterators + static const_instance_list_t& getFloaterList(const std::string& name); + + // Visibility Management + // return NULL if instance not found or can't create instance (no builder) + static LLFloater* showInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE); + // Close a floater (may destroy or set invisible) + // return false if can't find instance + static bool hideInstance(const std::string& name, const LLSD& key = LLSD()); + // return true if instance is visible: + static bool toggleInstance(const std::string& name, const LLSD& key = LLSD()); + static bool instanceVisible(const std::string& name, const LLSD& key = LLSD()); + + static void showInitialVisibleInstances(); + static void hideVisibleInstances(const std::set& exceptions = std::set()); + static void restoreVisibleInstances(); + + // Control Variables + static std::string getRectControlName(const std::string& name); + static std::string declareRectControl(const std::string& name); + static std::string getVisibilityControlName(const std::string& name); + static std::string declareVisibilityControl(const std::string& name); + + // Callback wrappers + static void initUICtrlToFloaterVisibilityControl(LLUICtrl* ctrl, const LLSD& sdname); + static void showFloaterInstance(const LLSD& sdname); + static void hideFloaterInstance(const LLSD& sdname); + static void toggleFloaterInstance(const LLSD& sdname); + static bool floaterInstanceVisible(const LLSD& sdname); + + // Typed find / get / show + template + static T* findTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(findInstance(name, key)); + } + + template + static T* getTypedInstance(const std::string& name, const LLSD& key = LLSD()) + { + return dynamic_cast(getInstance(name, key)); + } + + template + static T* showTypedInstance(const std::string& name, const LLSD& key = LLSD(), BOOL focus = FALSE) + { + return dynamic_cast(showInstance(name, key, focus)); + } + +}; + +#endif diff --git a/indra/llui/llflyoutbutton.cpp b/indra/llui/llflyoutbutton.cpp new file mode 100644 index 0000000000..62a321dc02 --- /dev/null +++ b/indra/llui/llflyoutbutton.cpp @@ -0,0 +1,94 @@ +/** + * @file llflyoutbutton.cpp + * @brief LLFlyoutButton base class + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#include "linden_common.h" + +// file includes +#include "llflyoutbutton.h" + +static LLDefaultWidgetRegistry::Register r2("flyout_button"); + +const S32 FLYOUT_BUTTON_ARROW_WIDTH = 24; + +LLFlyoutButton::LLFlyoutButton(const Params& p) +: LLComboBox(p), + mToggleState(FALSE), + mActionButton(NULL) +{ + // Always use text box + // Text label button + LLButton::Params bp(p.action_button); + bp.name(p.label); + bp.rect.left(0).bottom(0).width(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH).height(getRect().getHeight()); + bp.click_callback.function(boost::bind(&LLFlyoutButton::onActionButtonClick, this, _2)); + bp.follows.flags(FOLLOWS_ALL); + + mActionButton = LLUICtrlFactory::create(bp); + addChild(mActionButton); + + mButton->setOrigin(getRect().getWidth() - FLYOUT_BUTTON_ARROW_WIDTH, 0); + mButton->reshape(FLYOUT_BUTTON_ARROW_WIDTH, getRect().getHeight()); + mButton->setFollows(FOLLOWS_RIGHT | FOLLOWS_TOP | FOLLOWS_BOTTOM); + mButton->setImageOverlay(mListPosition == BELOW ? "down_arrow.tga" : "up_arrow.tga", LLFontGL::RIGHT); +} + +void LLFlyoutButton::onActionButtonClick(const LLSD& data) +{ + // remember last list selection? + mList->deselect(); + onCommit(); +} + +void LLFlyoutButton::draw() +{ + mActionButton->setToggleState(mToggleState); + mButton->setToggleState(mToggleState); + + //FIXME: this should be an attribute of comboboxes, whether they have a distinct label or + // the label reflects the last selected item, for now we have to manually remove the label + mButton->setLabel(LLStringUtil::null); + LLComboBox::draw(); +} + +void LLFlyoutButton::setEnabled(BOOL enabled) +{ + mActionButton->setEnabled(enabled); + LLComboBox::setEnabled(enabled); +} + + +void LLFlyoutButton::setToggleState(BOOL state) +{ + mToggleState = state; +} + + diff --git a/indra/llui/llflyoutbutton.h b/indra/llui/llflyoutbutton.h new file mode 100644 index 0000000000..f60fe1eb35 --- /dev/null +++ b/indra/llui/llflyoutbutton.h @@ -0,0 +1,71 @@ +/** + * @file llflyoutbutton.h + * @brief LLFlyoutButton base class + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// A control that displays the name of the chosen item, which when clicked +// shows a scrolling box of choices. + +#ifndef LL_LLFLYOUTBUTTON_H +#define LL_LLFLYOUTBUTTON_H + +#include "llcombobox.h" + +// Classes + +class LLFlyoutButton : public LLComboBox +{ +public: + struct Params : public LLInitParam::Block + { + Optional action_button; + + Params() + : action_button("action_button") + {} + + }; +protected: + LLFlyoutButton(const Params&); + friend class LLUICtrlFactory; +public: + virtual void draw(); + virtual void setEnabled(BOOL enabled); + + void setToggleState(BOOL state); + + void onActionButtonClick(const LLSD& data); + +protected: + LLButton* mActionButton; + BOOL mToggleState; +}; + +#endif // LL_LLFLYOUTBUTTON_H diff --git a/indra/llui/llfocusmgr.cpp b/indra/llui/llfocusmgr.cpp index 661ffdd467..9a4ec7627e 100644 --- a/indra/llui/llfocusmgr.cpp +++ b/indra/llui/llfocusmgr.cpp @@ -220,24 +220,19 @@ void LLFocusMgr::setMouseCapture( LLMouseHandler* new_captor ) { LLMouseHandler* old_captor = mMouseCaptor; mMouseCaptor = new_captor; - /* - if (new_captor) + + if (LLView::sDebugMouseHandling) { - if ( new_captor->getName() == "Stickto") + if (new_captor) { llinfos << "New mouse captor: " << new_captor->getName() << llendl; } else { - llinfos << "New mouse captor: " << new_captor->getName() << llendl; + llinfos << "New mouse captor: NULL" << llendl; } } - else - { - llinfos << "New mouse captor: NULL" << llendl; - } - */ - + if( old_captor ) { old_captor->onMouseCaptureLost(); @@ -295,7 +290,7 @@ void LLFocusMgr::setTopCtrl( LLUICtrl* new_top ) if (old_top) { - old_top->onLostTop(); + old_top->onTopLost(); } } } @@ -328,7 +323,8 @@ F32 LLFocusMgr::getFocusFlashAmt() const LLColor4 LLFocusMgr::getFocusColor() const { - LLColor4 focus_color = lerp(LLUI::sColorsGroup->getColor( "FocusColor" ), LLColor4::white, getFocusFlashAmt()); + static LLUICachedControl focus_color_cached ("FocusColor", *(new LLColor4)); + LLColor4 focus_color = lerp(focus_color_cached, LLColor4::white, getFocusFlashAmt()); // de-emphasize keyboard focus when app has lost focus (to avoid typing into wrong window problem) if (!mAppHasFocus) { diff --git a/indra/llui/llfunctorregistry.h b/indra/llui/llfunctorregistry.h index 8864f7af15..2c0bcc6012 100644 --- a/indra/llui/llfunctorregistry.h +++ b/indra/llui/llfunctorregistry.h @@ -40,7 +40,7 @@ #include #include "llsd.h" -#include "llmemory.h" +#include "llsingleton.h" /** * @class LLFunctorRegistry diff --git a/indra/llui/lliconctrl.cpp b/indra/llui/lliconctrl.cpp index cb3b2a3a62..eddfc71284 100644 --- a/indra/llui/lliconctrl.cpp +++ b/indra/llui/lliconctrl.cpp @@ -40,65 +40,33 @@ #include "llcontrol.h" #include "llui.h" #include "lluictrlfactory.h" +#include "lluiimage.h" -const F32 RESOLUTION_BUMP = 1.f; +static LLDefaultWidgetRegistry::Register r("icon"); -static LLRegisterWidget r("icon"); - -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id) -: LLUICtrl(name, - rect, - FALSE, // mouse opaque - NULL, NULL, - FOLLOWS_LEFT | FOLLOWS_TOP), - mColor( LLColor4::white ) -{ - setImage( image_id ); - setTabStop(FALSE); -} - -LLIconCtrl::LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name) -: LLUICtrl(name, - rect, - FALSE, // mouse opaque - NULL, NULL, - FOLLOWS_LEFT | FOLLOWS_TOP), - mColor( LLColor4::white ), - mImageName(image_name) -{ - setImage( image_name ); - setTabStop(FALSE); -} - - -LLIconCtrl::~LLIconCtrl() +LLIconCtrl::Params::Params() +: image("image_name"), + color("color"), + scale_image("scale_image") { - mImagep = NULL; + tab_stop = false; + mouse_opaque = false; } - -void LLIconCtrl::setImage(const std::string& image_name) +LLIconCtrl::LLIconCtrl(const LLIconCtrl::Params& p) +: LLUICtrl(p), + mColor(p.color()), + mImagep(p.image) { - //RN: support UUIDs masquerading as strings - if (LLUUID::validate(image_name)) - { - mImageID = LLUUID(image_name); - - setImage(mImageID); - } - else + if (mImagep.notNull()) { - mImageName = image_name; - mImagep = LLUI::sImageProvider->getUIImage(image_name); - mImageID.setNull(); + LLUICtrl::setValue(mImagep->getName()); } } -void LLIconCtrl::setImage(const LLUUID& image_id) +LLIconCtrl::~LLIconCtrl() { - mImageName.clear(); - mImagep = LLUI::sImageProvider->getUIImageByID(image_id); - mImageID = image_id; + mImagep = NULL; } @@ -106,69 +74,37 @@ void LLIconCtrl::draw() { if( mImagep.notNull() ) { - mImagep->draw(getLocalRect(), mColor ); + mImagep->draw(getLocalRect(), mColor.get() ); } LLUICtrl::draw(); } // virtual +// value might be a string or a UUID void LLIconCtrl::setValue(const LLSD& value ) { - if (value.isUUID()) + LLSD tvalue(value); + if (value.isString() && LLUUID::validate(value.asString())) { - setImage(value.asUUID()); + //RN: support UUIDs masquerading as strings + tvalue = LLSD(LLUUID(value.asString())); } - else + LLUICtrl::setValue(tvalue); + if (tvalue.isUUID()) { - setImage(value.asString()); + mImagep = LLUI::getUIImageByID(tvalue.asUUID()); } -} - -// virtual -LLSD LLIconCtrl::getValue() const -{ - LLSD ret = getImage(); - return ret; -} - -// virtual -LLXMLNodePtr LLIconCtrl::getXML(bool save_children) const -{ - LLXMLNodePtr node = LLUICtrl::getXML(); - - if (mImageName != "") + else { - node->createChild("image_name", TRUE)->setStringValue(mImageName); + mImagep = LLUI::getUIImage(tvalue.asString()); } - - node->createChild("color", TRUE)->setFloatValue(4, mColor.mV); - - return node; } -LLView* LLIconCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) +std::string LLIconCtrl::getImageName() const { - std::string name("icon"); - node->getAttributeString("name", name); - - LLRect rect; - createRect(node, rect, parent, LLRect()); - - std::string image_name; - if (node->hasAttribute("image_name")) - { - node->getAttributeString("image_name", image_name); - } - - LLColor4 color(LLColor4::white); - LLUICtrlFactory::getAttributeColor(node,"color", color); - - LLIconCtrl* icon = new LLIconCtrl(name, rect, image_name); - - icon->setColor(color); - - icon->initFromXML(node, parent); - - return icon; + if (getValue().isString()) + return getValue().asString(); + else + return std::string(); } diff --git a/indra/llui/lliconctrl.h b/indra/llui/lliconctrl.h index 50778cf226..ad0f6f563f 100644 --- a/indra/llui/lliconctrl.h +++ b/indra/llui/lliconctrl.h @@ -45,35 +45,37 @@ class LLUICtrlFactory; // // Classes // + +// class LLIconCtrl : public LLUICtrl { public: - LLIconCtrl(const std::string& name, const LLRect &rect, const LLUUID &image_id); - LLIconCtrl(const std::string& name, const LLRect &rect, const std::string &image_name); + struct Params : public LLInitParam::Block + { + Optional image; + Optional color; + Deprecated scale_image; + Params(); + }; +protected: + LLIconCtrl(const Params&); + friend class LLUICtrlFactory; +public: virtual ~LLIconCtrl(); // llview overrides virtual void draw(); - void setImage(const std::string& image_name); - void setImage(const LLUUID& image_name); - const LLUUID &getImage() const { return mImageID; } - std::string getImageName() const { return mImageName; } - - // Takes a UUID, wraps get/setImage + // lluictrl overrides virtual void setValue(const LLSD& value ); - virtual LLSD getValue() const; - void setColor(const LLColor4& color) { mColor = color; } + std::string getImageName() const; - virtual LLXMLNodePtr getXML(bool save_children = true) const; - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); + void setColor(const LLColor4& color) { mColor = color; } private: - LLColor4 mColor; - std::string mImageName; - LLUUID mImageID; + LLUIColor mColor; LLPointer mImagep; }; diff --git a/indra/llui/llkeywords.cpp b/indra/llui/llkeywords.cpp index 51ef3dbacf..30796a5ab9 100644 --- a/indra/llui/llkeywords.cpp +++ b/indra/llui/llkeywords.cpp @@ -223,8 +223,8 @@ LLColor3 LLKeywords::readColor( const std::string& s ) { F32 r, g, b; r = g = b = 0.0f; - S32 read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); - if( read != 3 ) /* Flawfinder: ignore */ + S32 values_read = sscanf(s.c_str(), "%f, %f, %f]", &r, &g, &b ); + if( values_read != 3 ) { llinfos << " poorly formed color in keyword file" << llendl; } diff --git a/indra/llui/lllayoutstack.cpp b/indra/llui/lllayoutstack.cpp new file mode 100644 index 0000000000..39dac296ea --- /dev/null +++ b/indra/llui/lllayoutstack.cpp @@ -0,0 +1,740 @@ +/** + * @file lllayoutstack.cpp + * @brief LLLayout class - dynamic stacking of UI elements + * + * $LicenseInfo:firstyear=2001&license=viewergpl$ + * + * Copyright (c) 2001-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Opaque view with a background and a border. Can contain LLUICtrls. + +#include "linden_common.h" + +#include "lllayoutstack.h" +#include "llresizebar.h" +#include "llcriticaldamp.h" + +static LLDefaultWidgetRegistry::Register register_layout_stack("layout_stack", &LLLayoutStack::fromXML); + + +// +// LLLayoutStack +// +struct LLLayoutStack::LayoutPanel +{ + LayoutPanel(LLPanel* panelp, ELayoutOrientation orientation, S32 min_width, S32 min_height, BOOL auto_resize, BOOL user_resize) : mPanel(panelp), + mMinWidth(min_width), + mMinHeight(min_height), + mAutoResize(auto_resize), + mUserResize(user_resize), + mOrientation(orientation), + mCollapsed(FALSE), + mCollapseAmt(0.f), + mVisibleAmt(1.f), // default to fully visible + mResizeBar(NULL) + { + LLResizeBar::Side side = (orientation == HORIZONTAL) ? LLResizeBar::RIGHT : LLResizeBar::BOTTOM; + LLRect resize_bar_rect = panelp->getRect(); + + S32 min_dim; + if (orientation == HORIZONTAL) + { + min_dim = mMinHeight; + } + else + { + min_dim = mMinWidth; + } + LLResizeBar::Params p; + p.name("resize"); + p.resizing_view(mPanel); + p.min_size(min_dim); + p.side(side); + p.snapping_enabled(false); + mResizeBar = LLUICtrlFactory::create(p); + // panels initialized as hidden should not start out partially visible + if (!mPanel->getVisible()) + { + mVisibleAmt = 0.f; + } + } + + ~LayoutPanel() + { + // probably not necessary, but... + delete mResizeBar; + mResizeBar = NULL; + } + + F32 getCollapseFactor() + { + if (mOrientation == HORIZONTAL) + { + F32 collapse_amt = + clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, (F32)mMinWidth / (F32)llmax(1, mPanel->getRect().getWidth())); + return mVisibleAmt * collapse_amt; + } + else + { + F32 collapse_amt = + clamp_rescale(mCollapseAmt, 0.f, 1.f, 1.f, llmin(1.f, (F32)mMinHeight / (F32)llmax(1, mPanel->getRect().getHeight()))); + return mVisibleAmt * collapse_amt; + } + } + + LLPanel* mPanel; + S32 mMinWidth; + S32 mMinHeight; + BOOL mAutoResize; + BOOL mUserResize; + BOOL mCollapsed; + LLResizeBar* mResizeBar; + ELayoutOrientation mOrientation; + F32 mVisibleAmt; + F32 mCollapseAmt; +}; + +LLLayoutStack::Params::Params() +: orientation("orientation", std::string("vertical")), + animate("animate", TRUE), + border_size("border_size", LLCachedControl(*LLUI::sSettingGroups["config"], "UIResizeBarHeight", 0)) +{ + name="stack"; +} + +LLLayoutStack::LLLayoutStack(const LLLayoutStack::Params& p) +: LLView(p), + mMinWidth(0), + mMinHeight(0), + mPanelSpacing(p.border_size), + mOrientation((p.orientation() == "vertical") ? VERTICAL : HORIZONTAL), + mAnimate(p.animate) +{} + +LLLayoutStack::~LLLayoutStack() +{ + e_panel_list_t panels = mPanels; // copy list of panel pointers + mPanels.clear(); // clear so that removeChild() calls don't cause trouble + std::for_each(panels.begin(), panels.end(), DeletePointer()); +} + +void LLLayoutStack::draw() +{ + updateLayout(); + + e_panel_list_t::iterator panel_it; + for (panel_it = mPanels.begin(); panel_it != mPanels.end(); ++panel_it) + { + // clip to layout rectangle, not bounding rectangle + LLRect clip_rect = (*panel_it)->mPanel->getRect(); + // scale clipping rectangle by visible amount + if (mOrientation == HORIZONTAL) + { + clip_rect.mRight = clip_rect.mLeft + llround((F32)clip_rect.getWidth() * (*panel_it)->getCollapseFactor()); + } + else + { + clip_rect.mBottom = clip_rect.mTop - llround((F32)clip_rect.getHeight() * (*panel_it)->getCollapseFactor()); + } + + LLPanel* panelp = (*panel_it)->mPanel; + + LLLocalClipRect clip(clip_rect); + // only force drawing invisible children if visible amount is non-zero + drawChild(panelp, 0, 0, !clip_rect.isNull()); + } +} + +void LLLayoutStack::removeChild(LLView* view) +{ + LayoutPanel* embedded_panelp = findEmbeddedPanel(dynamic_cast(view)); + + if (embedded_panelp) + { + mPanels.erase(std::find(mPanels.begin(), mPanels.end(), embedded_panelp)); + delete embedded_panelp; + } + + // need to update resizebars + + calcMinExtents(); + + LLView::removeChild(view); +} + +BOOL LLLayoutStack::postBuild() +{ + updateLayout(); + return TRUE; +} + +static void get_attribute_s32_and_write(LLXMLNodePtr node, + const char* name, + S32 *value, + S32 default_value, + LLXMLNodePtr output_child) +{ + BOOL has_attr = node->getAttributeS32(name, *value); + if (has_attr && *value != default_value && output_child) + { + // create an attribute child node + LLXMLNodePtr child_attr = output_child->createChild(name, TRUE); + child_attr->setIntValue(*value); + } +} + +static void get_attribute_bool_and_write(LLXMLNodePtr node, + const char* name, + BOOL *value, + BOOL default_value, + LLXMLNodePtr output_child) +{ + BOOL has_attr = node->getAttributeBOOL(name, *value); + if (has_attr && *value != default_value && output_child) + { + LLXMLNodePtr child_attr = output_child->createChild(name, TRUE); + child_attr->setBoolValue(*value); + } +} +//static +LLView* LLLayoutStack::fromXML(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) +{ + LLLayoutStack::Params p(LLUICtrlFactory::getDefaultParams()); + LLXUIParser::instance().readXUI(node, p); + + // Export must happen before setupParams() mungles rectangles and before + // this item gets added to parent (otherwise screws up last_child_rect + // logic). JC + if (output_node) + { + Params output_params(p); + setupParamsForExport(output_params, parent); + LLLayoutStack::Params default_params(LLUICtrlFactory::getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); + } + + setupParams(p, parent); + LLLayoutStack* layout_stackp = LLUICtrlFactory::create(p); + + if (parent && layout_stackp) + { + S32 tab_group = p.tab_group.isProvided() ? p.tab_group() : parent->getLastTabGroup(); + + parent->addChild(layout_stackp, tab_group); + } + + for (LLXMLNodePtr child_node = node->getFirstChild(); child_node.notNull(); child_node = child_node->getNextSibling()) + { + const S32 DEFAULT_MIN_WIDTH = 0; + const S32 DEFAULT_MIN_HEIGHT = 0; + const BOOL DEFAULT_AUTO_RESIZE = TRUE; + + S32 min_width = DEFAULT_MIN_WIDTH; + S32 min_height = DEFAULT_MIN_HEIGHT; + BOOL auto_resize = DEFAULT_AUTO_RESIZE; + + LLXMLNodePtr output_child; + if (output_node) + { + output_child = output_node->createChild("", FALSE); + } + + // Layout stack allows child nodes to acquire additional attributes, + // such as "min_width" in: " + // which equates to the following nesting: + // button + // param + // nested_param1 + // nested_param2 + // nested_param3 + mCurReadDepth++; + for(LLXMLNodePtr childp = nodep->getFirstChild(); childp.notNull();) + { + std::string child_name(childp->getName()->mString); + S32 num_tokens_pushed = 0; + + // for non "dotted" child nodes check to see if child node maps to another widget type + // and if not, treat as a child element of the current node + // e.g. will interpret as "button.rect" + // since there is no widget named "rect" + if (child_name.find(".") == std::string::npos) + { + mNameStack.push_back(std::make_pair(child_name, newParseGeneration())); + num_tokens_pushed++; + } + else + { + // parse out "dotted" name into individual tokens + tokenizer name_tokens(child_name, sep); + + tokenizer::iterator name_token_it = name_tokens.begin(); + if(name_token_it == name_tokens.end()) + { + childp = childp->getNextSibling(); + continue; + } + + // check for proper nesting + if(!scope.empty() && *name_token_it != scope) + { + childp = childp->getNextSibling(); + continue; + } + + // now ignore first token + ++name_token_it; + + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_token_it; token_to_push != name_tokens.end(); ++token_to_push) + { + mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); + num_tokens_pushed++; + } + } + + // recurse and visit children XML nodes + if(readXUIImpl(childp, mNameStack.empty() ? scope : mNameStack.back().first, block)) { - continue; + // child node successfully parsed, remove from DOM + + values_parsed = true; + LLXMLNodePtr node_to_remove = childp; + childp = childp->getNextSibling(); + + nodep->deleteChild(node_to_remove); + } + else + { + childp = childp->getNextSibling(); } - llinfos << "Rebuilding UI panel " << panelp->getName() - << " from " << filename - << llendl; - BOOL visible = panelp->getVisible(); - panelp->setVisible(FALSE); - panelp->setFocus(FALSE); - panelp->deleteAllChildren(); - buildPanel(panelp, filename.c_str(), &panelp->getFactoryMap()); - panelp->setVisible(visible); + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } } + mCurReadDepth--; + return values_parsed; +} + +bool LLXUIParser::readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block) +{ + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("."); + + bool any_parsed = false; - built_floater_t::iterator built_floater_it; - for (built_floater_it = mBuiltFloaters.begin(); - built_floater_it != mBuiltFloaters.end(); - ++built_floater_it) + for(LLXMLAttribList::const_iterator attribute_it = nodep->mAttributes.begin(); + attribute_it != nodep->mAttributes.end(); + ++attribute_it) { - LLFloater* floaterp = built_floater_it->first.get(); - if (!floaterp) + S32 num_tokens_pushed = 0; + std::string attribute_name(attribute_it->first->mString); + mCurReadNode = attribute_it->second; + + tokenizer name_tokens(attribute_name, sep); + // copy remaining tokens on to our running token list + for(tokenizer::iterator token_to_push = name_tokens.begin(); token_to_push != name_tokens.end(); ++token_to_push) { - continue; + mNameStack.push_back(std::make_pair(*token_to_push, newParseGeneration())); + num_tokens_pushed++; } - std::string filename = built_floater_it->second; - llinfos << "Rebuilding UI floater " << floaterp->getName() - << " from " << filename - << llendl; - BOOL visible = floaterp->getVisible(); - floaterp->setVisible(FALSE); - floaterp->setFocus(FALSE); - floaterp->deleteAllChildren(); - gFloaterView->removeChild(floaterp); - buildFloater(floaterp, filename, &floaterp->getFactoryMap()); - floaterp->setVisible(visible); + // child nodes are not necessarily valid attributes, so don't complain once we've recursed + bool silent = mCurReadDepth > 0; + any_parsed |= block.submitValue(mNameStack, *this, silent); + + while(num_tokens_pushed-- > 0) + { + mNameStack.pop_back(); + } } + + return any_parsed; } -//----------------------------------------------------------------------------- -//----------------------------------------------------------------------------- +bool LLXUIParser::readBoolValue(void* val_ptr) +{ + S32 value; + bool success = mCurReadNode->getBoolValue(1, &value); + *((bool*)val_ptr) = (value != FALSE); + return success; +} -LLView *LLUICtrlFactory::createCtrlWidget(LLPanel *parent, LLXMLNodePtr node) +bool LLXUIParser::writeBoolValue(const void* val_ptr, const name_stack_t& stack) { - std::string ctrl_type = node->getName()->mString; - LLStringUtil::toLower(ctrl_type); - - LLWidgetClassRegistry::factory_func_t func = LLWidgetClassRegistry::getInstance()->getCreatorFunc(ctrl_type); + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setBoolValue(*((bool*)val_ptr)); + return true; + } + return false; +} - if (func == NULL) +bool LLXUIParser::readStringValue(void* val_ptr) +{ + *((std::string*)val_ptr) = mCurReadNode->getSanitizedValue(); + return true; +} + +bool LLXUIParser::writeStringValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - llwarns << "Unknown control type " << ctrl_type << llendl; - return NULL; + node->setStringValue(*((std::string*)val_ptr)); + return true; } + return false; +} - if (parent == NULL) +bool LLXUIParser::readU8Value(void* val_ptr) +{ + return mCurReadNode->getByteValue(1, (U8*)val_ptr); +} + +bool LLXUIParser::writeU8Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - if (mDummyPanel == NULL) - { - mDummyPanel = new LLPanel; - } - parent = mDummyPanel; + node->setUnsignedValue(*((U8*)val_ptr)); + return true; } - LLView *ctrl = func(node, parent, this); + return false; +} - return ctrl; +bool LLXUIParser::readS8Value(void* val_ptr) +{ + S32 value; + if(mCurReadNode->getIntValue(1, &value)) + { + *((S8*)val_ptr) = value; + return true; + } + return false; } -LLView* LLUICtrlFactory::createWidget(LLPanel *parent, LLXMLNodePtr node) +bool LLXUIParser::writeS8Value(const void* val_ptr, const name_stack_t& stack) { - LLView* view = createCtrlWidget(parent, node); + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setIntValue(*((S8*)val_ptr)); + return true; + } + return false; +} - S32 tab_group = parent->getLastTabGroup(); - node->getAttributeS32("tab_group", tab_group); +bool LLXUIParser::readU16Value(void* val_ptr) +{ + U32 value; + if(mCurReadNode->getUnsignedValue(1, &value)) + { + *((U16*)val_ptr) = value; + return true; + } + return false; +} - if (view) +bool LLXUIParser::writeU16Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - parent->addChild(view, tab_group); + node->setUnsignedValue(*((U16*)val_ptr)); + return true; } + return false; +} - return view; +bool LLXUIParser::readS16Value(void* val_ptr) +{ + S32 value; + if(mCurReadNode->getIntValue(1, &value)) + { + *((S16*)val_ptr) = value; + return true; + } + return false; } -//----------------------------------------------------------------------------- -// createFactoryPanel() -//----------------------------------------------------------------------------- -LLPanel* LLUICtrlFactory::createFactoryPanel(const std::string& name) +bool LLXUIParser::writeS16Value(const void* val_ptr, const name_stack_t& stack) { - std::deque::iterator itor; - for (itor = mFactoryStack.begin(); itor != mFactoryStack.end(); ++itor) + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - const LLCallbackMap::map_t* factory_map = *itor; + node->setIntValue(*((S16*)val_ptr)); + return true; + } + return false; +} - // Look up this panel's name in the map. - LLCallbackMap::map_const_iter_t iter = factory_map->find( name ); - if (iter != factory_map->end()) - { - // Use the factory to create the panel, instead of using a default LLPanel. - LLPanel *ret = (LLPanel*) iter->second.mCallback( iter->second.mData ); - return ret; - } +bool LLXUIParser::readU32Value(void* val_ptr) +{ + return mCurReadNode->getUnsignedValue(1, (U32*)val_ptr); +} + +bool LLXUIParser::writeU32Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setUnsignedValue(*((U32*)val_ptr)); + return true; } - return NULL; + return false; } -//----------------------------------------------------------------------------- +bool LLXUIParser::readS32Value(void* val_ptr) +{ + return mCurReadNode->getIntValue(1, (S32*)val_ptr); +} -//static -BOOL LLUICtrlFactory::getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color) +bool LLXUIParser::writeS32Value(const void* val_ptr, const name_stack_t& stack) { - std::string colorstring; - BOOL res = node->getAttributeString(name.c_str(), colorstring); - if (res && LLUI::sColorsGroup) + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - if (LLUI::sColorsGroup->controlExists(colorstring)) - { - color.setVec(LLUI::sColorsGroup->getColor(colorstring)); - } - else - { - res = FALSE; - } + node->setIntValue(*((S32*)val_ptr)); + return true; } - if (!res) + return false; +} + +bool LLXUIParser::readF32Value(void* val_ptr) +{ + return mCurReadNode->getFloatValue(1, (F32*)val_ptr); +} + +bool LLXUIParser::writeF32Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - res = LLColor4::parseColor(colorstring, &color); - } - if (!res) + node->setFloatValue(*((F32*)val_ptr)); + return true; + } + return false; +} + +bool LLXUIParser::readF64Value(void* val_ptr) +{ + return mCurReadNode->getDoubleValue(1, (F64*)val_ptr); +} + +bool LLXUIParser::writeF64Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) { - res = node->getAttributeColor(name.c_str(), color); + node->setDoubleValue(*((F64*)val_ptr)); + return true; } - return res; + return false; } +bool LLXUIParser::readColor4Value(void* val_ptr) +{ + LLColor4* colorp = (LLColor4*)val_ptr; + if(mCurReadNode->getFloatValue(4, colorp->mV) >= 3) + { + return true; + } + + return false; +} + +bool LLXUIParser::writeColor4Value(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + LLColor4 color = *((LLColor4*)val_ptr); + node->setFloatValue(4, color.mV); + return true; + } + return false; +} + +bool LLXUIParser::readUIColorValue(void* val_ptr) +{ + LLUIColor* param = (LLUIColor*)val_ptr; + LLColor4 color; + bool success = mCurReadNode->getFloatValue(4, color.mV) >= 3; + if (success) + { + param->set(color); + return true; + } + return false; +} + +bool LLXUIParser::writeUIColorValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + LLUIColor color = *((LLUIColor*)val_ptr); + //RN: don't write out the color that is represented by a function + // rely on param block exporting to get the reference to the color settings + if (color.isUsingFunction()) return false; + node->setFloatValue(4, color.get().mV); + return true; + } + return false; +} + +bool LLXUIParser::readUUIDValue(void* val_ptr) +{ + LLUUID temp_id; + // LLUUID::set is destructive, so use temporary value + if (temp_id.set(mCurReadNode->getSanitizedValue())) + { + *(LLUUID*)(val_ptr) = temp_id; + return true; + } + return false; +} + +bool LLXUIParser::writeUUIDValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLUUID*)val_ptr)->asString()); + return true; + } + return false; +} + +bool LLXUIParser::readSDValue(void* val_ptr) +{ + *((LLSD*)val_ptr) = LLSD(mCurReadNode->getSanitizedValue()); + return true; +} + +bool LLXUIParser::writeSDValue(const void* val_ptr, const name_stack_t& stack) +{ + LLXMLNodePtr node = getNode(stack); + if (node.notNull()) + { + node->setStringValue(((LLSD*)val_ptr)->asString()); + return true; + } + return false; +} + +/*virtual*/ std::string LLXUIParser::getCurrentElementName() +{ + std::string full_name; + for (name_stack_t::iterator it = mNameStack.begin(); + it != mNameStack.end(); + ++it) + { + full_name += it->first + "."; // build up dotted names: "button.param.nestedparam." + } + + return full_name; +} + +void LLXUIParser::parserWarning(const std::string& message) +{ +#ifdef LL_WINDOWS + // use Visual Studo friendly formatting of output message for easy access to originating xml + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserWarning(message); +#endif +} + +void LLXUIParser::parserError(const std::string& message) +{ +#ifdef LL_WINDOWS + llutf16string utf16str = utf8str_to_utf16str(llformat("%s(%d):\t%s", LLUICtrlFactory::getInstance()->getCurFileName().c_str(), mCurReadNode->getLineNumber(), message.c_str()).c_str()); + utf16str += '\n'; + OutputDebugString(utf16str.c_str()); +#else + Parser::parserError(message); +#endif +} diff --git a/indra/llui/lluictrlfactory.h b/indra/llui/lluictrlfactory.h index 5e7c24efc0..4045022c8e 100644 --- a/indra/llui/lluictrlfactory.h +++ b/indra/llui/lluictrlfactory.h @@ -33,68 +33,418 @@ #ifndef LLUICTRLFACTORY_H #define LLUICTRLFACTORY_H +#include "llcallbackmap.h" +#include "llinitparam.h" +#include "llxmlnode.h" +#include "llfasttimer.h" + +#include #include #include -#include "llcallbackmap.h" -#include "llfloater.h" - -class LLView; class LLPanel; +class LLFloater; +class LLView; -class LLUICtrlFactory : public LLSingleton +class LLXUIParser : public LLInitParam::Parser, public LLSingleton { +LOG_CLASS(LLXUIParser); + +protected: + LLXUIParser(); + friend class LLSingleton; public: + typedef LLInitParam::Parser::name_stack_t name_stack_t; + + /*virtual*/ std::string getCurrentElementName(); + /*virtual*/ void parserWarning(const std::string& message); + /*virtual*/ void parserError(const std::string& message); + + void readXUI(LLXMLNodePtr node, LLInitParam::BaseBlock& block, bool silent=false); + void writeXUI(LLXMLNodePtr node, const LLInitParam::BaseBlock& block, const LLInitParam::BaseBlock* diff_block = NULL); + +private: + typedef std::list > token_list_t; + + bool readXUIImpl(LLXMLNodePtr node, const std::string& scope, LLInitParam::BaseBlock& block); + bool readAttributes(LLXMLNodePtr nodep, LLInitParam::BaseBlock& block); + + //reader helper functions + bool readBoolValue(void* val_ptr); + bool readStringValue(void* val_ptr); + bool readU8Value(void* val_ptr); + bool readS8Value(void* val_ptr); + bool readU16Value(void* val_ptr); + bool readS16Value(void* val_ptr); + bool readU32Value(void* val_ptr); + bool readS32Value(void* val_ptr); + bool readF32Value(void* val_ptr); + bool readF64Value(void* val_ptr); + bool readColor4Value(void* val_ptr); + bool readUIColorValue(void* val_ptr); + bool readUUIDValue(void* val_ptr); + bool readSDValue(void* val_ptr); + + //writer helper functions + bool writeBoolValue(const void* val_ptr, const name_stack_t&); + bool writeStringValue(const void* val_ptr, const name_stack_t&); + bool writeU8Value(const void* val_ptr, const name_stack_t&); + bool writeS8Value(const void* val_ptr, const name_stack_t&); + bool writeU16Value(const void* val_ptr, const name_stack_t&); + bool writeS16Value(const void* val_ptr, const name_stack_t&); + bool writeU32Value(const void* val_ptr, const name_stack_t&); + bool writeS32Value(const void* val_ptr, const name_stack_t&); + bool writeF32Value(const void* val_ptr, const name_stack_t&); + bool writeF64Value(const void* val_ptr, const name_stack_t&); + bool writeColor4Value(const void* val_ptr, const name_stack_t&); + bool writeUIColorValue(const void* val_ptr, const name_stack_t&); + bool writeUUIDValue(const void* val_ptr, const name_stack_t&); + bool writeSDValue(const void* val_ptr, const name_stack_t&); + + LLXMLNodePtr getNode(const name_stack_t& stack); + +private: + Parser::name_stack_t mNameStack; + LLXMLNodePtr mCurReadNode; + // Root of the widget XML sub-tree, for example, "line_editor" + LLXMLNodePtr mWriteRootNode; + S32 mLastWriteGeneration; + LLXMLNodePtr mLastWrittenChild; + S32 mCurReadDepth; +}; + +// global static instance for registering all widget types +typedef boost::function LLWidgetCreatorFunc; + +typedef LLRegistry widget_registry_t; + +template +class LLWidgetRegistry : public LLRegistrySingleton +{ +public: + typedef LLRegistrySingleton super_t; + // local static instance for registering a particular widget + template + class Register : public super_t::StaticRegistrar + { + public: + // register with either the provided builder, or the generic templated builder + Register(const char* tag, LLWidgetCreatorFunc func = NULL); + }; + +protected: + LLWidgetRegistry() {} +}; + +class LLDefaultWidgetRegistry : public LLWidgetRegistry +{ +protected: + LLDefaultWidgetRegistry() {} + friend class LLSingleton; +}; + +struct LLCompareTypeID +{ + bool operator()(const std::type_info* lhs, const std::type_info* rhs) const + { + return lhs->before(*rhs); + } +}; + + +class LLWidgetTemplateRegistry +: public LLRegistrySingleton +{ + +}; + +extern LLFastTimer::DeclareTimer FTM_WIDGET_SETUP; +extern LLFastTimer::DeclareTimer FTM_WIDGET_CONSTRUCTION; +extern LLFastTimer::DeclareTimer FTM_INIT_FROM_PARAMS; + +class LLUICtrlFactory : public LLSingleton +{ +private: + friend class LLSingleton; LLUICtrlFactory(); - // do not call! needs to be public so run-time can clean up the singleton - virtual ~LLUICtrlFactory(); + ~LLUICtrlFactory(); + + // only partial specialization allowed in inner classes, so use extra dummy parameter + template + class ParamDefaults : public LLSingleton > + { + public: + ParamDefaults() + { + // recursively initialize from base class param block + ((typename T::base_block_t&)mPrototype).fillFrom(ParamDefaults::instance().get()); + // after initializing base classes, look up template file for this param block + std::string* param_block_tag = LLWidgetTemplateRegistry::instance().getValue(&typeid(T)); + if (param_block_tag) + { + LLUICtrlFactory::loadWidgetTemplate(*param_block_tag, mPrototype); + } + } + + const T& get() { return mPrototype; } - void setupPaths(); + private: + T mPrototype; + }; - void buildFloater(LLFloater* floaterp, const std::string &filename, - const LLCallbackMap::map_t* factory_map = NULL, BOOL open = TRUE); - BOOL buildPanel(LLPanel* panelp, const std::string &filename, - const LLCallbackMap::map_t* factory_map = NULL); + // base case for recursion, there are NO base classes of LLInitParam::BaseBlock + template + class ParamDefaults : public LLSingleton > + { + public: + const LLInitParam::BaseBlock& get() { return mBaseBlock; } + private: + LLInitParam::BaseBlock mBaseBlock; + }; - void removePanel(LLPanel* panelp) { mBuiltPanels.erase(panelp->getHandle()); } - void removeFloater(LLFloater* floaterp) { mBuiltFloaters.erase(floaterp->getHandle()); } +public: + + template + static const T& getDefaultParams() + { + //#pragma message("Generating ParamDefaults") + return ParamDefaults::instance().get(); + } - class LLMenuGL *buildMenu(const std::string &filename, LLView* parentp); - class LLPieMenu *buildPieMenu(const std::string &filename, LLView* parentp); + void buildFloater(LLFloater* floaterp, const std::string &filename, BOOL open_floater = TRUE, LLXMLNodePtr output_node = NULL); + LLFloater* buildFloaterFromXML(const std::string& filename, BOOL open_floater = TRUE); + BOOL buildPanel(LLPanel* panelp, const std::string &filename, LLXMLNodePtr output_node = NULL); // Does what you want for LLFloaters and LLPanels // Returns 0 on success S32 saveToXML(LLView* viewp, const std::string& filename); - // Rebuilds all currently built panels. - void rebuild(); + std::string getCurFileName() { return mFileNames.empty() ? "" : mFileNames.back(); } static BOOL getAttributeColor(LLXMLNodePtr node, const std::string& name, LLColor4& color); LLPanel* createFactoryPanel(const std::string& name); - virtual LLView* createCtrlWidget(LLPanel *parent, LLXMLNodePtr node); - virtual LLView* createWidget(LLPanel *parent, LLXMLNodePtr node); + void pushFactoryFunctions(const LLCallbackMap::map_t* map); + void popFactoryFunctions(); + + template + static T* create(typename T::Params& params, LLView* parent = NULL) + { + //#pragma message("Generating LLUICtrlFactory::create") + params.fillFrom(ParamDefaults::instance().get()); + //S32 foo = "test"; + + if (!params.validateBlock()) + { + llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; + } + T* widget = new T(params); + widget->initFromParams(params); + if (parent) + widget->setParent(parent); + return widget; + } + + LLView* createFromXML(LLXMLNodePtr node, LLView* parent, const std::string& filename, LLXMLNodePtr output_node, const widget_registry_t& ); + + static const widget_registry_t& getWidgetRegistry(LLView*); + + template + static T* createFromFile(const std::string &filename, LLView *parent, LLXMLNodePtr output_node = NULL) + { + //#pragma message("Generating LLUICtrlFactory::createFromFile") + T* widget = NULL; + + std::string skinned_filename = findSkinnedFilename(filename); + getInstance()->mFileNames.push_back(skinned_filename); + { + LLXMLNodePtr root_node; + + //if exporting, only load the language being exported, + //instead of layering localized version on top of english + if (output_node) + { + if (!LLUICtrlFactory::getLocalizedXMLNode(filename, root_node)) + { + llwarns << "Couldn't parse XUI file: " << filename << llendl; + goto fail; + } + } + else if (!LLUICtrlFactory::getLayeredXMLNode(filename, root_node)) + { + llwarns << "Couldn't parse XUI file: " << skinned_filename << llendl; + goto fail; + } + + LLView* view = getInstance()->createFromXML(root_node, parent, filename, output_node, getWidgetRegistry(parent)); + if (view) + { + widget = dynamic_cast(view); + // not of right type, so delete it + if (!widget) + { + delete view; + view = NULL; + } + + } + } +fail: + getInstance()->mFileNames.pop_back(); + return widget; + } + + template + static T* createDummyWidget(const std::string& name) + { + //#pragma message("Generating LLUICtrlFactory::createDummyWidget") + typename T::Params params; + params.name(name); + + return create(params); + } + + template + static T* defaultBuilder(LLXMLNodePtr node, LLView *parent, LLXMLNodePtr output_node) + { + LLFastTimer timer(FTM_WIDGET_SETUP); + + //#pragma message("Generating LLUICtrlFactory::defaultBuilder") + PARAM_BLOCK params(getDefaultParams()); + + LLXUIParser::instance().readXUI(node, params); + + if (output_node) + { + // We always want to output top-left coordinates + PARAM_BLOCK output_params(params); + T::setupParamsForExport(output_params, parent); + // Export only the differences between this any default params + PARAM_BLOCK default_params(getDefaultParams()); + output_node->setName(node->getName()->mString); + LLXUIParser::instance().writeXUI( + output_node, output_params, &default_params); + } + + // Apply layout transformations, usually munging rect + T::setupParams(params, parent); + + if (!params.validateBlock()) + { + llwarns << getInstance()->getCurFileName() << ": Invalid parameter block for " << typeid(T).name() << llendl; + } + T* widget; + { + LLFastTimer timer(FTM_WIDGET_CONSTRUCTION); + widget = new T(params); + } + { + LLFastTimer timer(FTM_INIT_FROM_PARAMS); + widget->initFromParams(params); + } + + if (parent) + { + S32 tab_group = params.tab_group.isProvided() ? params.tab_group() : -1; + setCtrlParent(widget, parent, tab_group); + } + + createChildren(widget, node, output_node); + + if (!widget->postBuild()) + { + delete widget; + return NULL; + } + + return widget; + } + + static void createChildren(LLView* viewp, LLXMLNodePtr node, LLXMLNodePtr output_node = NULL); static bool getLayeredXMLNode(const std::string &filename, LLXMLNodePtr& root); + + static bool getLocalizedXMLNode(const std::string &xui_filename, LLXMLNodePtr& root); - static const std::vector& getXUIPaths(); + static void loadWidgetTemplate(const std::string& widget_tag, LLInitParam::BaseBlock& block); private: - bool getLayeredXMLNodeImpl(const std::string &filename, LLXMLNodePtr& root); + //static void setCtrlValue(LLView* view, LLXMLNodePtr node); + static void setCtrlParent(LLView* view, LLView* parent, S32 tab_group); + + // Avoid directly using LLUI and LLDir in the template code + static std::string findSkinnedFilename(const std::string& filename); + + typedef std::deque factory_stack_t; + factory_stack_t mFactoryStack; + + LLPanel* mDummyPanel; + std::vector mFileNames; +}; + +// this is here to make gcc happy with reference to LLUICtrlFactory +template +template +LLWidgetRegistry::Register::Register(const char* tag, LLWidgetCreatorFunc func) +: LLWidgetRegistry::StaticRegistrar(tag, func.empty() ? (LLWidgetCreatorFunc)&LLUICtrlFactory::defaultBuilder : func) +{ + //FIXME: inventory_panel will register itself with LLPanel::Params but it does have its own params...:( + LLWidgetTemplateRegistry::instance().defaultRegistrar().add(&typeid(PARAM_BLOCK), tag); +} + + +typedef boost::function LLPannelClassCreatorFunc; - typedef std::map, std::string> built_panel_t; - built_panel_t mBuiltPanels; +// local static instance for registering a particular panel class - typedef std::map, std::string> built_floater_t; - built_floater_t mBuiltFloaters; +class LLRegisterPanelClass +: public LLSingleton< LLRegisterPanelClass > +{ +public: + // reigister with either the provided builder, or the generic templated builder + void addPanelClass(const std::string& tag,LLPannelClassCreatorFunc func) + { + mPannelClassesNames[tag] = func; + } + + LLPanel* createPanelClass(const std::string& tag) + { + param_name_map_t::iterator iT = mPannelClassesNames.find(tag); + if(iT == mPannelClassesNames.end()) + return 0; + return iT->second(); + } + template + static T* defaultPanelClassBuilder() + { + T* pT = new T(); + return pT; + } - std::deque mFactoryStack; +private: + typedef std::map< std::string, LLPannelClassCreatorFunc> param_name_map_t; + + param_name_map_t mPannelClassesNames; +}; - static std::vector sXUIPaths; - LLPanel* mDummyPanel; +// local static instance for registering a particular panel class +template +class LLRegisterPanelClassWrapper +: public LLRegisterPanelClass +{ +public: + // reigister with either the provided builder, or the generic templated builder + LLRegisterPanelClassWrapper(const std::string& tag); }; +template +LLRegisterPanelClassWrapper::LLRegisterPanelClassWrapper(const std::string& tag) +{ + LLRegisterPanelClass::instance().addPanelClass(tag,&LLRegisterPanelClass::defaultPanelClassBuilder); +} + + #endif //LLUICTRLFACTORY_H diff --git a/indra/llui/lluifwd.h b/indra/llui/lluifwd.h index 32d5c9b44f..f99bb39fdd 100644 --- a/indra/llui/lluifwd.h +++ b/indra/llui/lluifwd.h @@ -53,7 +53,6 @@ class LLSlider; class LLSliderCtrl; class LLSpinCtrl; class LLTabContainer; -class LLTabContainerVertical; class LLTextBox; class LLTextEditor; class LLTextureCtrl; diff --git a/indra/llui/lluiimage.cpp b/indra/llui/lluiimage.cpp new file mode 100644 index 0000000000..8e0de0cb0c --- /dev/null +++ b/indra/llui/lluiimage.cpp @@ -0,0 +1,166 @@ +/** + * @file lluiimage.cpp + * @brief UI implementation + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +// Utilities functions the user interface needs + +//#include "llviewerprecompiledheaders.h" +#include "linden_common.h" + +// Project includes +#include "lluiimage.h" +#include "llui.h" + +LLUIImage::LLUIImage(const std::string& name, LLPointer image) : + mName(name), + mImage(image), + mScaleRegion(0.f, 1.f, 1.f, 0.f), + mClipRegion(0.f, 1.f, 1.f, 0.f), + mUniformScaling(TRUE), + mNoClip(TRUE) +{ +} + +LLUIImage::~LLUIImage() +{ +} + +void LLUIImage::setClipRegion(const LLRectf& region) +{ + mClipRegion = region; + mNoClip = mClipRegion.mLeft == 0.f + && mClipRegion.mRight == 1.f + && mClipRegion.mBottom == 0.f + && mClipRegion.mTop == 1.f; +} + +void LLUIImage::setScaleRegion(const LLRectf& region) +{ + mScaleRegion = region; + mUniformScaling = mScaleRegion.mLeft == 0.f + && mScaleRegion.mRight == 1.f + && mScaleRegion.mBottom == 0.f + && mScaleRegion.mTop == 1.f; +} + +//TODO: move drawing implementation inside class +void LLUIImage::draw(S32 x, S32 y, const LLColor4& color) const +{ + gl_draw_image(x, y, mImage, color, mClipRegion); +} + +void LLUIImage::draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + if (mUniformScaling) + { + gl_draw_scaled_image(x, y, width, height, mImage, color, mClipRegion); + } + else + { + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + FALSE, + mClipRegion, + mScaleRegion); + } +} + +void LLUIImage::drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const +{ + gl_draw_scaled_image_with_border( + x, y, + width, height, + mImage, + color, + TRUE, + mClipRegion, + mScaleRegion); +} + +void LLUIImage::drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const +{ + LLRect border_rect; + border_rect.setOriginAndSize(x, y, width, height); + border_rect.stretch(border_width, border_width); + drawSolid(border_rect, color); +} + +S32 LLUIImage::getWidth() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getWidth(0) * mClipRegion.getWidth()); +} + +S32 LLUIImage::getHeight() const +{ + // return clipped dimensions of actual image area + return llround((F32)mImage->getHeight(0) * mClipRegion.getHeight()); +} + +S32 LLUIImage::getTextureWidth() const +{ + return mImage->getWidth(0); +} + +S32 LLUIImage::getTextureHeight() const +{ + return mImage->getHeight(0); +} + +namespace LLInitParam +{ + LLUIImage* TypedParam::getValueFromBlock() const + { + LLUIImage* imagep = LLUI::getUIImage(name()); + if (!imagep) + { + // default to current value + imagep = mData.mValue; + } + return imagep; + } + + + template<> + bool ParamCompare::equals( + LLUIImage* const &a, + LLUIImage* const &b) + { + // force all LLUIImages for XML UI export to be "non-default" + if (!a && !b) + return false; + else + return (a == b); + } +} diff --git a/indra/llui/lluiimage.h b/indra/llui/lluiimage.h new file mode 100644 index 0000000000..e35026cd3d --- /dev/null +++ b/indra/llui/lluiimage.h @@ -0,0 +1,114 @@ +/** + * @file lluiimage.h + * @brief wrapper for images used in the UI that handles smart scaling, etc. + * + * $LicenseInfo:firstyear=2007&license=viewergpl$ + * + * Copyright (c) 2007-2009, Linden Research, Inc. + * + * Second Life Viewer Source Code + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed by you and Linden Lab. Terms of + * the GPL can be found in doc/GPL-license.txt in this distribution, or + * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2 + * + * There are special exceptions to the terms and conditions of the GPL as + * it is applied to this Source Code. View the full text of the exception + * in the file doc/FLOSS-exception.txt in this software distribution, or + * online at + * http://secondlifegrid.net/programs/open_source/licensing/flossexception + * + * By copying, modifying or distributing this software, you acknowledge + * that you have read and understood your obligations described above, + * and agree to abide by those obligations. + * + * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO + * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, + * COMPLETENESS OR PERFORMANCE. + * $/LicenseInfo$ + */ + +#ifndef LL_LLUIIMAGE_H +#define LL_LLUIIMAGE_H + +//#include "llgl.h" +#include "llimagegl.h" +#include "llrefcount.h" +#include "llrect.h" +#include +#include "llinitparam.h" + +extern const LLColor4 UI_VERTEX_COLOR; + +class LLUIImage : public LLRefCount +{ +public: + LLUIImage(const std::string& name, LLPointer image); + virtual ~LLUIImage(); + + void setClipRegion(const LLRectf& region); + void setScaleRegion(const LLRectf& region); + + LLPointer getImage() { return mImage; } + const LLPointer& getImage() const { return mImage; } + + void draw(S32 x, S32 y, S32 width, S32 height, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(S32 x, S32 y, const LLColor4& color = UI_VERTEX_COLOR) const; + void draw(const LLRect& rect, const LLColor4& color = UI_VERTEX_COLOR) const { draw(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + + void drawSolid(S32 x, S32 y, S32 width, S32 height, const LLColor4& color) const; + void drawSolid(const LLRect& rect, const LLColor4& color) const { drawSolid(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color); } + void drawSolid(S32 x, S32 y, const LLColor4& color) const { drawSolid(x, y, mImage->getWidth(0), mImage->getHeight(0), color); } + + void drawBorder(S32 x, S32 y, S32 width, S32 height, const LLColor4& color, S32 border_width) const; + void drawBorder(const LLRect& rect, const LLColor4& color, S32 border_width) const { drawBorder(rect.mLeft, rect.mBottom, rect.getWidth(), rect.getHeight(), color, border_width); } + void drawBorder(S32 x, S32 y, const LLColor4& color, S32 border_width) const { drawBorder(x, y, mImage->getWidth(0), mImage->getHeight(0), color, border_width); } + + const std::string& getName() const { return mName; } + + virtual S32 getWidth() const; + virtual S32 getHeight() const; + + // returns dimensions of underlying textures, which might not be equal to ui image portion + S32 getTextureWidth() const; + S32 getTextureHeight() const; + +protected: + std::string mName; + LLRectf mScaleRegion; + LLRectf mClipRegion; + LLPointer mImage; + BOOL mUniformScaling; + BOOL mNoClip; +}; + +namespace LLInitParam +{ + template<> + class TypedParam, false> + : public BlockValue + { + typedef boost::add_reference::type>::type T_const_ref; + typedef BlockValue super_t; + public: + Optional name; + + TypedParam(BlockDescriptor& descriptor, const char* name, super_t::value_assignment_t value, ParamDescriptor::validation_func_t func) + : super_t(descriptor, name, value, func) + { + } + + LLUIImage* getValueFromBlock() const; + }; + + // Need custom comparison function for our test app, which only loads + // LLUIImage* as NULL. + template<> + bool ParamCompare::equals( + LLUIImage* const &a, LLUIImage* const &b); +} + +typedef LLPointer LLUIImagePtr; +#endif diff --git a/indra/llui/lluistring.cpp b/indra/llui/lluistring.cpp index 0b76b8e814..7ce0fd7a88 100644 --- a/indra/llui/lluistring.cpp +++ b/indra/llui/lluistring.cpp @@ -33,6 +33,7 @@ #include "linden_common.h" #include "lluistring.h" #include "llsd.h" +#include "lltrans.h" const LLStringUtil::format_map_t LLUIString::sNullArgs; @@ -111,7 +112,18 @@ void LLUIString::clear() void LLUIString::format() { + // optimize for empty strings (don't attempt string replacement) + if (mOrig.empty()) + { + mResult.clear(); + mWResult.clear(); + return; + } mResult = mOrig; - LLStringUtil::format(mResult, mArgs); + + // get the defailt args + local args + LLStringUtil::format_map_t combined_args = LLTrans::getDefaultArgs(); + combined_args.insert(mArgs.begin(), mArgs.end()); + LLStringUtil::format(mResult, combined_args); mWResult = utf8str_to_wstring(mResult); } diff --git a/indra/llui/llview.cpp b/indra/llui/llview.cpp index 8ec681fcaf..2e2ef4d79f 100644 --- a/indra/llui/llview.cpp +++ b/indra/llui/llview.cpp @@ -56,19 +56,18 @@ #include "lltexteditor.h" #include "lltextbox.h" -using namespace LLOldEvents; - -//HACK: this allows you to instantiate LLView from xml with "" which we don't want -static LLRegisterWidget r("view"); - BOOL LLView::sDebugRects = FALSE; BOOL LLView::sDebugKeys = FALSE; S32 LLView::sDepth = 0; BOOL LLView::sDebugMouseHandling = FALSE; std::string LLView::sMouseHandlerMessage; -BOOL LLView::sEditingUI = FALSE; +//BOOL LLView::sEditingUI = FALSE; BOOL LLView::sForceReshape = FALSE; -LLView* LLView::sEditingUIView = NULL; +//LLView* LLView::sEditingUIView = NULL; +std::set LLView::sPreviewHighlightedElements; +BOOL LLView::sHighlightingDiffs = FALSE; +LLView* LLView::sPreviewClickedElement = NULL; +BOOL LLView::sDrawPreviewHighlights = FALSE; S32 LLView::sLastLeftXML = S32_MIN; S32 LLView::sLastBottomXML = S32_MIN; @@ -76,77 +75,78 @@ S32 LLView::sLastBottomXML = S32_MIN; BOOL LLView::sIsDrawing = FALSE; #endif -LLView::LLView() : - mParentView(NULL), - mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(TRUE), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) -{ -} - -LLView::LLView(const std::string& name, BOOL mouse_opaque) : +LLView::Params::Params() +: name("name", std::string("unnamed")), + enabled("enabled", true), + visible("visible", true), + mouse_opaque("mouse_opaque", true), + follows("follows"), + hover_cursor("hover_cursor", "UI_CURSOR_ARROW"), + use_bounding_rect("use_bounding_rect", false), + tab_group("tab_group", 0), + default_tab_group("default_tab_group"), + tool_tip("tool_tip"), + sound_flags("sound_flags", MOUSE_UP), + font("font", LLFontGL::getFontSansSerif()), + font_halign("halign"), + font_valign("valign"), + layout("layout"), + rect("rect"), + bottom_delta("bottom_delta", S32_MAX), + top_pad("top_pad"), + top_delta("top_delta", S32_MAX), + left_pad("left_pad"), + left_delta("left_delta", S32_MAX), + center_horiz("center_horiz", false), + center_vert("center_vert", false), + serializable("", false), + user_resize("user_resize"), + auto_resize("auto_resize"), + needs_translate("translate") +{ + addSynonym(rect, ""); +} + +LLView::LLView(const LLView::Params& p) +: mName(p.name), mParentView(NULL), - mName(name), mReshapeFlags(FOLLOWS_NONE), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), - mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), - mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) -{ -} - - -LLView::LLView( - const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 reshape) : - mParentView(NULL), - mName(name), - mRect(rect), - mBoundingRect(rect), - mReshapeFlags(reshape), - mDefaultTabGroup(0), - mEnabled(TRUE), - mMouseOpaque(mouse_opaque), - mSoundFlags(MOUSE_UP), // default to only make sound on mouse up - mSaveToXML(TRUE), + mSaveToXML(p.serializable), mIsFocusRoot(FALSE), - mLastVisible(TRUE), - mUseBoundingRect(FALSE), - mVisible(TRUE), + mLastVisible(FALSE), mNextInsertionOrdinal(0), - mHoverCursor(UI_CURSOR_ARROW) + mHoverCursor(getCursorFromString(p.hover_cursor)), + mEnabled(p.enabled), + mVisible(p.visible), + mMouseOpaque(p.mouse_opaque), + mSoundFlags(p.sound_flags), + mUseBoundingRect(p.use_bounding_rect), + mDefaultTabGroup(p.default_tab_group), + mLastTabGroup(0), + mToolTipMsg((LLStringExplicit)p.tool_tip()), + mDummyWidgets(NULL) { + // create rect first, as this will supply initial follows flags + setShape(p.rect); + parseFollowsFlags(p); } - LLView::~LLView() { //llinfos << "Deleting view " << mName << ":" << (void*) this << llendl; // llassert(LLView::sIsDrawing == FALSE); + +// llassert_always(sDepth == 0); // avoid deleting views while drawing! It can subtly break list iterators + if( gFocusMgr.getKeyboardFocus() == this ) { - llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; + //llwarns << "View holding keyboard focus deleted: " << getName() << ". Keyboard focus removed." << llendl; gFocusMgr.removeKeyboardFocusWithoutCallback( this ); } if( hasMouseCapture() ) { - llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; + //llwarns << "View holding mouse capture deleted: " << getName() << ". Mouse capture removed." << llendl; gFocusMgr.removeMouseCaptureWithoutCallback( this ); } @@ -157,16 +157,13 @@ LLView::~LLView() mParentView->removeChild(this); } - dispatch_list_t::iterator itor; - for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor) + if (mDummyWidgets) { - (*itor).second->clearDispatchers(); + std::for_each(mDummyWidgets->begin(), mDummyWidgets->end(), + DeletePairedPointer()); + delete mDummyWidgets; + mDummyWidgets = NULL; } - - std::for_each(mFloaterControls.begin(), mFloaterControls.end(), - DeletePairedPointer()); - std::for_each(mDummyWidgets.begin(), mDummyWidgets.end(), - DeletePairedPointer()); } // virtual @@ -187,7 +184,6 @@ BOOL LLView::isPanel() const return FALSE; } -// virtual void LLView::setToolTip(const LLStringExplicit& msg) { mToolTipMsg = msg; @@ -234,19 +230,31 @@ const std::string& LLView::getName() const void LLView::sendChildToFront(LLView* child) { +// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child && child->getParent() == this) { - mChildList.remove( child ); - mChildList.push_front(child); + // minor optimization, but more importantly, + // won't temporarily create an empty list + if (child != mChildList.front()) + { + mChildList.remove( child ); + mChildList.push_front(child); + } } } void LLView::sendChildToBack(LLView* child) { +// llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child && child->getParent() == this) { - mChildList.remove( child ); - mChildList.push_back(child); + // minor optimization, but more importantly, + // won't temporarily create an empty list + if (child != mChildList.back()) + { + mChildList.remove( child ); + mChildList.push_back(child); + } } } @@ -266,12 +274,18 @@ void LLView::moveChildToBackOfTabGroup(LLUICtrl* child) } } -void LLView::addChild(LLView* child, S32 tab_group) +// virtual +bool LLView::addChild(LLView* child, S32 tab_group) { + if (!child) + { + return false; + } if (mParentView == child) { llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; } + // remove from current parent if (child->mParentView) { @@ -284,55 +298,46 @@ void LLView::addChild(LLView* child, S32 tab_group) // add to ctrl list if is LLUICtrl if (child->isCtrl()) { - // controls are stored in reverse order from render order - addCtrlAtEnd((LLUICtrl*) child, tab_group); + LLUICtrl* ctrl = static_cast(child); + mCtrlOrder.insert(tab_order_pair_t(ctrl, + tab_order_t(tab_group, mNextInsertionOrdinal))); + + mNextInsertionOrdinal++; } child->mParentView = this; updateBoundingRect(); + mLastTabGroup = tab_group; + return true; } -void LLView::addChildAtEnd(LLView* child, S32 tab_group) +bool LLView::addChildInBack(LLView* child, S32 tab_group) { - if (mParentView == child) - { - llerrs << "Adding view " << child->getName() << " as child of itself" << llendl; - } - // remove from current parent - if (child->mParentView) + if(addChild(child, tab_group)) { - child->mParentView->removeChild(child); + sendChildToBack(child); + return true; } - // add to back of child list - mChildList.push_back(child); - - // add to ctrl list if is LLUICtrl - if (child->isCtrl()) - { - // controls are stored in reverse order from render order - addCtrl((LLUICtrl*) child, tab_group); - } - - child->mParentView = this; - updateBoundingRect(); + return false; } // remove the specified child from the view, and set it's parent to NULL. -void LLView::removeChild(LLView* child, BOOL deleteIt) +void LLView::removeChild(LLView* child) { + //llassert_always(sDepth == 0); // Avoid re-ordering while drawing; it can cause subtle iterator bugs if (child->mParentView == this) { mChildList.remove( child ); child->mParentView = NULL; if (child->isCtrl()) { - removeCtrl((LLUICtrl*)child); - } - if (deleteIt) - { - delete child; + child_tab_order_t::iterator found = mCtrlOrder.find(static_cast(child)); + if(found != mCtrlOrder.end()) + { + mCtrlOrder.erase(found); + } } } else @@ -342,28 +347,6 @@ void LLView::removeChild(LLView* child, BOOL deleteIt) updateBoundingRect(); } -void LLView::addCtrlAtEnd(LLUICtrl* ctrl, S32 tab_group) -{ - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, mNextInsertionOrdinal++))); -} - -void LLView::addCtrl( LLUICtrl* ctrl, S32 tab_group) -{ - // add to front of list by using negative ordinal, which monotonically increases - mCtrlOrder.insert(tab_order_pair_t(ctrl, - tab_order_t(tab_group, -1 * mNextInsertionOrdinal++))); -} - -void LLView::removeCtrl(LLUICtrl* ctrl) -{ - child_tab_order_t::iterator found = mCtrlOrder.find(ctrl); - if(found != mCtrlOrder.end()) - { - mCtrlOrder.erase(found); - } -} - LLView::ctrl_list_t LLView::getCtrlList() const { ctrl_list_t controls; @@ -653,7 +636,7 @@ BOOL LLView::canSnapTo(const LLView* other_view) } // virtual -void LLView::snappedTo(const LLView* snap_view) +void LLView::setSnappedTo(const LLView* snap_view) { } @@ -671,6 +654,17 @@ BOOL LLView::handleHover(S32 x, S32 y, MASK mask) return handled; } +void LLView::onMouseEnter(S32 x, S32 y, MASK mask) +{ + //llinfos << "Mouse entered " << getName() << llendl; +} + +void LLView::onMouseLeave(S32 x, S32 y, MASK mask) +{ + //llinfos << "Mouse left " << getName() << llendl; +} + + std::string LLView::getShowNamesToolTip() { LLView* view = getParent(); @@ -731,23 +725,14 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s // get our own tooltip tool_tip = mToolTipMsg.getString(); - if ( - LLUI::sShowXUINames + + if (LLUI::sShowXUINames && (tool_tip.find(".xml", 0) == std::string::npos) && (mName.find("Drag", 0) == std::string::npos)) { tool_tip = getShowNamesToolTip(); } - BOOL show_names_text_box = LLUI::sShowXUINames && dynamic_cast(this) != NULL; - - // don't allow any siblings to handle this event - // even if we don't have a tooltip - if (getMouseOpaque() || show_names_text_box) - { - handled = TRUE; - } - if(!tool_tip.empty()) { msg = tool_tip; @@ -759,7 +744,13 @@ BOOL LLView::handleToolTip(S32 x, S32 y, std::string& msg, LLRect* sticky_rect_s localPointToScreen( mRect.getWidth(), mRect.getHeight(), &(sticky_rect_screen->mRight), &(sticky_rect_screen->mTop) ); - + } + // don't allow any siblings to handle this event + // even if we don't have a tooltip + if (getMouseOpaque() || + (!tool_tip.empty() && + (!LLUI::sShowXUINames || dynamic_cast(this)))) + { handled = TRUE; } @@ -925,22 +916,22 @@ BOOL LLView::handleMouseDown(S32 x, S32 y, MASK mask) handled_view = this; } - // HACK If we're editing UI, select the leaf view that ate the click. - if (sEditingUI && handled_view) - { - // need to find leaf views, big hack - LLButton* buttonp = dynamic_cast(handled_view); - LLLineEditor* line_editorp = dynamic_cast(handled_view); - LLTextEditor* text_editorp = dynamic_cast(handled_view); - LLTextBox* text_boxp = dynamic_cast(handled_view); - if (buttonp - || line_editorp - || text_editorp - || text_boxp) - { - sEditingUIView = handled_view; - } - } + //// HACK If we're editing UI, select the leaf view that ate the click. + //if (sEditingUI && handled_view) + //{ + // // need to find leaf views, big hack + // LLButton* buttonp = dynamic_cast(handled_view); + // LLLineEditor* line_editorp = dynamic_cast(handled_view); + // LLTextEditor* text_editorp = dynamic_cast(handled_view); + // LLTextBox* text_boxp = dynamic_cast(handled_view); + // if (buttonp + // || line_editorp + // || text_editorp + // || text_boxp) + // { + // sEditingUIView = handled_view; + // } + //} return handled; } @@ -1166,6 +1157,7 @@ LLView* LLView::childrenHandleRightMouseDown(S32 x, S32 y, MASK mask) { sMouseHandlerMessage = std::string("->") + viewp->mName + sMouseHandlerMessage; } + handled_view = viewp; break; } @@ -1328,55 +1320,58 @@ void LLView::draw() } } - LLRect rootRect = getRootView()->getRect(); - LLRect screenRect; - - // draw focused control on top of everything else - LLView* focus_view = gFocusMgr.getKeyboardFocus(); - if (focus_view && focus_view->getParent() != this) + if (!mChildList.empty()) { - focus_view = NULL; - } + LLRect rootRect = getRootView()->getRect(); + LLRect screenRect; - ++sDepth; - for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend(); ++child_iter) - { - LLView *viewp = *child_iter; + // draw focused control on top of everything else + LLView* focus_view = gFocusMgr.getKeyboardFocus(); + if (focus_view && focus_view->getParent() != this) + { + focus_view = NULL; + } - if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) + ++sDepth; + + for (child_list_reverse_iter_t child_iter = mChildList.rbegin(); child_iter != mChildList.rend();) // ++child_iter) { - // Only draw views that are within the root view - localRectToScreen(viewp->getRect(),&screenRect); - if ( rootRect.rectInRect(&screenRect) ) + child_list_reverse_iter_t child = child_iter++; + LLView *viewp = *child; + + if (viewp->getVisible() && viewp != focus_view && viewp->getRect().isValid()) { - glMatrixMode(GL_MODELVIEW); - LLUI::pushMatrix(); + // Only draw views that are within the root view + localRectToScreen(viewp->getRect(),&screenRect); + if ( rootRect.rectInRect(&screenRect) ) { - LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); - viewp->draw(); + glMatrixMode(GL_MODELVIEW); + LLUI::pushMatrix(); + { + LLUI::translate((F32)viewp->getRect().mLeft, (F32)viewp->getRect().mBottom, 0.f); + viewp->draw(); + } + LLUI::popMatrix(); } - LLUI::popMatrix(); } - } - } - --sDepth; + } + --sDepth; - if (focus_view && focus_view->getVisible()) - { - drawChild(focus_view); + if (focus_view && focus_view->getVisible()) + { + drawChild(focus_view); + } } - // HACK - if (sEditingUI && this == sEditingUIView) - { - drawDebugRect(); - } + gGL.getTexUnit(0)->disable(); } //Draw a box for debugging. void LLView::drawDebugRect() { + std::set::iterator preview_iter = std::find(sPreviewHighlightedElements.begin(), sPreviewHighlightedElements.end(), this); // figure out if it's a previewed element + LLUI::pushMatrix(); { // drawing solids requires texturing be disabled @@ -1391,9 +1386,21 @@ void LLView::drawDebugRect() // draw red rectangle for the border LLColor4 border_color(0.f, 0.f, 0.f, 1.f); - if (sEditingUI) + //if (sEditingUI) + //{ + // border_color.mV[0] = 1.f; + //} + if(preview_iter != sPreviewHighlightedElements.end()) { - border_color.mV[0] = 1.f; + if(LLView::sPreviewClickedElement && this == sPreviewClickedElement) + { + border_color = LLColor4::red; + } + else + { + static LLUICachedControl scroll_highlighted_color ("ScrollHighlightedColor", *(new LLColor4)); + border_color = scroll_highlighted_color; + } } else { @@ -1416,8 +1423,8 @@ void LLView::drawDebugRect() gGL.vertex2i(0, debug_rect.getHeight() - 1); gGL.end(); - // Draw the name if it's not a leaf node - if (mChildList.size() && !sEditingUI) + // Draw the name if it's not a leaf node or not in editing or preview mode + if (mChildList.size() && preview_iter == sPreviewHighlightedElements.end()) { //char temp[256]; S32 x, y; @@ -1427,7 +1434,7 @@ void LLView::drawDebugRect() std::string debug_text = llformat("%s (%d x %d)", getName().c_str(), debug_rect.getWidth(), debug_rect.getHeight()); LLFontGL::getFontSansSerifSmall()->renderUTF8(debug_text, 0, (F32)x, (F32)y, border_color, - LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, + LLFontGL::HCENTER, LLFontGL::BASELINE, LLFontGL::NORMAL, LLFontGL::NO_SHADOW, S32_MAX, S32_MAX, NULL, FALSE); } } @@ -1583,15 +1590,28 @@ void LLView::updateBoundingRect() } } -LLRect LLView::getScreenRect() const +LLRect LLView::calcScreenRect() const { - // *FIX: check for one-off error LLRect screen_rect; localPointToScreen(0, 0, &screen_rect.mLeft, &screen_rect.mBottom); localPointToScreen(getRect().getWidth(), getRect().getHeight(), &screen_rect.mRight, &screen_rect.mTop); return screen_rect; } +LLRect LLView::calcScreenBoundingRect() const +{ + LLRect screen_rect; + // get bounding rect, if used + LLRect bounding_rect = mUseBoundingRect ? mBoundingRect : mRect; + + // convert to local coordinates, as defined by mRect + bounding_rect.translate(-mRect.mLeft, -mRect.mBottom); + + localPointToScreen(bounding_rect.mLeft, bounding_rect.mBottom, &screen_rect.mLeft, &screen_rect.mBottom); + localPointToScreen(bounding_rect.mRight, bounding_rect.mTop, &screen_rect.mRight, &screen_rect.mTop); + return screen_rect; +} + LLRect LLView::getLocalBoundingRect() const { LLRect local_bounding_rect = getBoundingRect(); @@ -1690,7 +1710,12 @@ LLView* LLView::getChildView(const std::string& name, BOOL recurse, BOOL create_ if (create_if_missing) { - return createDummyWidget(name); + LLView* view = getDummyWidget(name); + if (!view) + { + view = LLUICtrlFactory::createDummyWidget(name); + } + return view; } return NULL; } @@ -1779,12 +1804,32 @@ LLView* LLView::getRootView() return view; } -BOOL LLView::deleteViewByHandle(LLHandle handle) +LLView* LLView::findPrevSibling(LLView* child) +{ + child_list_t::iterator prev_it = std::find(mChildList.begin(), mChildList.end(), child); + if (prev_it != mChildList.end() && prev_it != mChildList.begin()) + { + return *(--prev_it); + } + return NULL; +} + +LLView* LLView::findNextSibling(LLView* child) +{ + child_list_t::iterator next_it = std::find(mChildList.begin(), mChildList.end(), child); + if (next_it != mChildList.end()) + { + next_it++; + } + + return (next_it != mChildList.end()) ? *next_it : NULL; +} + +void LLView::deleteViewByHandle(LLHandle handle) { LLView* viewp = handle.get(); delete viewp; - return viewp != NULL; } @@ -1945,132 +1990,6 @@ BOOL LLView::localRectToOtherView( const LLRect& local, LLRect* other, LLView* o return FALSE; } -// virtual -LLXMLNodePtr LLView::getXML(bool save_children) const -{ - //FIXME: need to provide actual derived type tag, probably outside this method - LLXMLNodePtr node = new LLXMLNode("view", FALSE); - - node->createChild("name", TRUE)->setStringValue(getName()); - node->createChild("width", TRUE)->setIntValue(getRect().getWidth()); - node->createChild("height", TRUE)->setIntValue(getRect().getHeight()); - - LLView* parent = getParent(); - S32 left = getRect().mLeft; - S32 bottom = getRect().mBottom; - if (parent) bottom -= parent->getRect().getHeight(); - - node->createChild("left", TRUE)->setIntValue(left); - node->createChild("bottom", TRUE)->setIntValue(bottom); - - U32 follows_flags = getFollows(); - if (follows_flags) - { - std::stringstream buffer; - bool pipe = false; - if (followsLeft()) - { - buffer << "left"; - pipe = true; - } - if (followsTop()) - { - if (pipe) buffer << "|"; - buffer << "top"; - pipe = true; - } - if (followsRight()) - { - if (pipe) buffer << "|"; - buffer << "right"; - pipe = true; - } - if (followsBottom()) - { - if (pipe) buffer << "|"; - buffer << "bottom"; - } - node->createChild("follows", TRUE)->setStringValue(buffer.str()); - } - // Export all widgets as enabled and visible - code must disable. - node->createChild("mouse_opaque", TRUE)->setBoolValue(mMouseOpaque ); - if (!mToolTipMsg.getString().empty()) - { - node->createChild("tool_tip", TRUE)->setStringValue(mToolTipMsg.getString()); - } - if (mSoundFlags != MOUSE_UP) - { - node->createChild("sound_flags", TRUE)->setIntValue((S32)mSoundFlags); - } - - node->createChild("enabled", TRUE)->setBoolValue(getEnabled()); - - if (!mControlName.empty()) - { - node->createChild("control_name", TRUE)->setStringValue(mControlName); - } - return node; -} - -//static -LLView* LLView::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory) -{ - LLView* viewp = new LLView(); - viewp->initFromXML(node, parent); - return viewp; -} - -// static -void LLView::addColorXML(LLXMLNodePtr node, const LLColor4& color, - const char* xml_name, const char* control_name) -{ - if (color != LLUI::sColorsGroup->getColor(ll_safe_string(control_name))) - { - node->createChild(xml_name, TRUE)->setFloatValue(4, color.mV); - } -} - -//static -std::string LLView::escapeXML(const std::string& xml, std::string& indent) -{ - std::string ret = indent + "\"" + LLXMLNode::escapeXML(xml); - - //replace every newline with a close quote, new line, indent, open quote - size_t index = ret.size()-1; - size_t fnd; - - while ((fnd = ret.rfind("\n", index)) != std::string::npos) - { - ret.replace(fnd, 1, "\"\n" + indent + "\""); - index = fnd-1; - } - - //append close quote - ret.append("\""); - - return ret; -} - -// static -LLWString LLView::escapeXML(const LLWString& xml) -{ - LLWString out; - for (LLWString::size_type i = 0; i < xml.size(); ++i) - { - llwchar c = xml[i]; - switch(c) - { - case '"': out.append(utf8string_to_wstring(""")); break; - case '\'': out.append(utf8string_to_wstring("'")); break; - case '&': out.append(utf8string_to_wstring("&")); break; - case '<': out.append(utf8string_to_wstring("<")); break; - case '>': out.append(utf8string_to_wstring(">")); break; - default: out.push_back(c); break; - } - } - return out; -} - // static const LLCtrlQuery & LLView::getTabOrderQuery() { @@ -2107,7 +2026,12 @@ const LLCtrlQuery & LLView::getFocusRootsQuery() } -void LLView::userSetShape(const LLRect& new_rect) +void LLView::setShape(const LLRect& new_rect, bool by_user) +{ + handleReshape(new_rect, by_user); +} + +void LLView::handleReshape(const LLRect& new_rect, bool by_user) { reshape(new_rect.getWidth(), new_rect.getHeight()); translate(new_rect.mLeft - getRect().mLeft, new_rect.mBottom - getRect().mBottom); @@ -2355,560 +2279,482 @@ LLView* LLView::findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESna // Listener dispatch functions //----------------------------------------------------------------------------- -void LLView::registerEventListener(std::string name, LLSimpleListener* function) -{ - mDispatchList.insert(std::pair(name, function)); -} -void LLView::deregisterEventListener(std::string name) +LLControlVariable *LLView::findControl(const std::string& name) { - dispatch_list_t::iterator itor = mDispatchList.find(name); - if (itor != mDispatchList.end()) + // parse the name to locate which group it belongs to + std::size_t key_pos= name.find("."); + if(key_pos!= std::string::npos ) { - mDispatchList.erase(itor); + std::string control_group_key = name.substr(0, key_pos); + LLControlVariable* control; + // check if it's in the control group that name indicated + if(LLUI::sSettingGroups[control_group_key]) + { + control = LLUI::sSettingGroups[control_group_key]->getControl(name); + if (control) + { + return control; + } + } } + + LLControlGroup& control_group = LLUI::getControlControlGroup(name); + return control_group.getControl(name); } -std::string LLView::findEventListener(LLSimpleListener *listener) const +const widget_registry_t& LLView::getChildRegistry() const { - dispatch_list_t::const_iterator itor; - for (itor = mDispatchList.begin(); itor != mDispatchList.end(); ++itor) - { - if (itor->second == listener) - { - return itor->first; - } - } - if (mParentView) - { - return mParentView->findEventListener(listener); - } - return LLStringUtil::null; + static widget_registry_t empty_registry; + return empty_registry; } -LLSimpleListener* LLView::getListenerByName(const std::string& callback_name) + +const S32 FLOATER_H_MARGIN = 15; +const S32 MIN_WIDGET_HEIGHT = 10; +const S32 VPAD = 4; + +void LLView::initFromParams(const LLView::Params& params) { - LLSimpleListener* callback = NULL; - dispatch_list_t::iterator itor = mDispatchList.find(callback_name); - if (itor != mDispatchList.end()) - { - callback = itor->second; - } - else if (mParentView) + LLRect required_rect = getRequiredRect(); + + S32 width = llmax(getRect().getWidth(), required_rect.getWidth()); + S32 height = llmax(getRect().getHeight(), required_rect.getHeight()); + + reshape(width, height); + + // call virtual methods with most recent data + // use getters because these values might not come through parameter block + setEnabled(getEnabled()); + setVisible(getVisible()); + + if (!params.name().empty()) { - callback = mParentView->getListenerByName(callback_name); + setName(params.name()); } - return callback; + + mLayout = params.layout(); } -LLControlVariable *LLView::findControl(const std::string& name) +void LLView::parseFollowsFlags(const LLView::Params& params) { - control_map_t::iterator itor = mFloaterControls.find(name); - if (itor != mFloaterControls.end()) + // preserve follows flags set by code if user did not override + if (!params.follows.isProvided()) { - return itor->second; + return; } - if (mParentView) + + // interpret either string or bitfield version of follows + if (params.follows.string.isChosen()) { - return mParentView->findControl(name); - } - return LLUI::sConfigGroup->getControl(name); -} + setFollows(FOLLOWS_NONE); -const S32 FLOATER_H_MARGIN = 15; -const S32 MIN_WIDGET_HEIGHT = 10; -const S32 VPAD = 4; + std::string follows = params.follows.string; -// static -U32 LLView::createRect(LLXMLNodePtr node, LLRect &rect, LLView* parent_view, const LLRect &required_rect) -{ - U32 follows = 0; - S32 x = rect.mLeft; - S32 y = rect.mBottom; - S32 w = rect.getWidth(); - S32 h = rect.getHeight(); + typedef boost::tokenizer > tokenizer; + boost::char_separator sep("|"); + tokenizer tokens(follows, sep); + tokenizer::iterator token_iter = tokens.begin(); - U32 last_x = 0; - U32 last_y = 0; - if (parent_view) - { - last_y = parent_view->getRect().getHeight(); - child_list_t::const_iterator itor = parent_view->getChildList()->begin(); - if (itor != parent_view->getChildList()->end()) + while(token_iter != tokens.end()) { - LLView *last_view = (*itor); - if (last_view->getSaveToXML()) + const std::string& token_str = *token_iter; + if (token_str == "left") + { + setFollowsLeft(); + } + else if (token_str == "right") + { + setFollowsRight(); + } + else if (token_str == "top") { - last_x = last_view->getRect().mLeft; - last_y = last_view->getRect().mBottom; + setFollowsTop(); } + else if (token_str == "bottom") + { + setFollowsBottom(); + } + else if (token_str == "all") + { + setFollowsAll(); + } + ++token_iter; } } - - std::string rect_control; - node->getAttributeString("rect_control", rect_control); - if (! rect_control.empty()) - { - LLRect rect = LLUI::sConfigGroup->getRect(rect_control); - x = rect.mLeft; - y = rect.mBottom; - w = rect.getWidth(); - h = rect.getHeight(); - } - - if (node->hasAttribute("left")) - { - node->getAttributeS32("left", x); - } - if (node->hasAttribute("bottom")) + else if (params.follows.flags.isChosen()) { - node->getAttributeS32("bottom", y); + setFollows(params.follows.flags); } +} - // Make your width the width of the containing - // view if you don't specify a width. - if (parent_view) - { - if(w == 0) - { - w = llmax(required_rect.getWidth(), parent_view->getRect().getWidth() - (FLOATER_H_MARGIN) - x); - } - if(h == 0) - { - h = llmax(MIN_WIDGET_HEIGHT, required_rect.getHeight()); +// static +//LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node) +//{ +// LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; +// +// if (node->hasAttribute("halign")) +// { +// std::string horizontal_align_name; +// node->getAttributeString("halign", horizontal_align_name); +// gl_hfont_align = LLFontGL::hAlignFromName(horizontal_align_name); +// } +// return gl_hfont_align; +//} + +// Return the rectangle of the last-constructed child, +// if present and a first-class widget (eg, not a close box or drag handle) +// Returns true if found +static bool get_last_child_rect(LLView* parent, LLRect *rect) +{ + if (!parent) return false; + + LLView::child_list_t::const_iterator itor = + parent->getChildList()->begin(); + for (;itor != parent->getChildList()->end(); ++itor) + { + LLView *last_view = (*itor); + if (last_view->getSaveToXML()) + { + *rect = last_view->getRect(); + return true; } } + return false; +} - if (node->hasAttribute("width")) - { - node->getAttributeS32("width", w); - } - if (node->hasAttribute("height")) +//static +void LLView::setupParams(LLView::Params& p, LLView* parent) +{ + const S32 VPAD = 4; + const S32 MIN_WIDGET_HEIGHT = 10; + + p.serializable(true); + + // *NOTE: This will confuse export of floater/panel coordinates unless + // the default is also "topleft". JC + if (p.layout().empty() && parent) { - node->getAttributeS32("height", h); + p.layout = parent->getLayout(); } - if (parent_view) + if (parent) { - if (node->hasAttribute("left_delta")) - { - S32 left_delta = 0; - node->getAttributeS32("left_delta", left_delta); - x = last_x + left_delta; - } - else if (node->hasAttribute("left") && node->hasAttribute("right")) + LLRect parent_rect = parent->getLocalRect(); + // overwrite uninitialized rect params, using context + LLRect last_rect = parent->getLocalRect(); + + bool layout_topleft = (p.layout() == "topleft"); + if (layout_topleft) { - // compute width based on left and right - S32 right = 0; - node->getAttributeS32("right", right); - if (right < 0) - { - right = parent_view->getRect().getWidth() + right; - } - w = right - x; + //invert top to bottom + if (p.rect.top.isProvided()) p.rect.top = parent_rect.getHeight() - p.rect.top; + if (p.rect.bottom.isProvided()) p.rect.bottom = parent_rect.getHeight() - p.rect.bottom; } - else if (node->hasAttribute("left")) + + // convert negative or centered coordinates to parent relative values + // Note: some of this logic matches the logic in TypedParam::getValueFromBlock() + + if (p.center_horiz) { - if (x < 0) + if (p.rect.left.isProvided() && p.rect.right.isProvided()) { - x = parent_view->getRect().getWidth() + x; - follows |= FOLLOWS_RIGHT; + S32 width = p.rect.right - p.rect.left; + width = llmax(width, 0); + S32 offset = parent_rect.getWidth()/2 - width/2; + p.rect.left = p.rect.left + offset; + p.rect.right = p.rect.right + offset; } else { - follows |= FOLLOWS_LEFT; + p.rect.left = p.rect.left + parent_rect.getWidth()/2 - p.rect.width/2; } } - else if (node->hasAttribute("width") && node->hasAttribute("right")) + else + { + if (p.rect.left < 0) p.rect.left = p.rect.left + parent_rect.getWidth(); + if (p.rect.right < 0) p.rect.right = p.rect.right + parent_rect.getWidth(); + } + if (p.center_vert) { - S32 right = 0; - node->getAttributeS32("right", right); - if (right < 0) + if (p.rect.bottom.isProvided() && p.rect.top.isProvided()) { - right = parent_view->getRect().getWidth() + right; + S32 height = p.rect.top - p.rect.bottom; + height = llmax(height, 0); + S32 offset = parent_rect.getHeight()/2 - height/2; + p.rect.bottom = p.rect.bottom + offset; + p.rect.top = p.rect.top + offset; + } + else + { + p.rect.bottom = p.rect.bottom + parent_rect.getHeight()/2 - p.rect.height/2; } - x = right - w; } else { - // left not specified, same as last - x = last_x; + if (p.rect.bottom < 0) p.rect.bottom = p.rect.bottom + parent_rect.getHeight(); + if (p.rect.top < 0) p.rect.top = p.rect.top + parent_rect.getHeight(); } - if (node->hasAttribute("bottom_delta")) + + // DEPRECATE: automatically fall back to height of MIN_WIDGET_HEIGHT pixels + if (!p.rect.height.isProvided() && !p.rect.top.isProvided()) { - S32 bottom_delta = 0; - node->getAttributeS32("bottom_delta", bottom_delta); - y = last_y + bottom_delta; + p.rect.height = MIN_WIDGET_HEIGHT; } - else if (node->hasAttribute("top")) + + last_rect.translate(0, last_rect.getHeight()); + + // If there was a recently constructed child, use its rectangle + get_last_child_rect(parent, &last_rect); + + if (layout_topleft) { - // compute height based on top - S32 top = 0; - node->getAttributeS32("top", top); - if (top < 0) + p.bottom_delta.setIfNotProvided(0, false); + + // Invert the sense of bottom_delta for topleft layout + if (p.bottom_delta.isProvided()) { - top = parent_view->getRect().getHeight() + top; + p.bottom_delta = -p.bottom_delta; } - h = top - y; - } - else if (node->hasAttribute("bottom")) - { - if (y < 0) + else if (p.top_pad.isProvided()) { - y = parent_view->getRect().getHeight() + y; - follows |= FOLLOWS_TOP; + p.bottom_delta = -(p.rect.height + p.top_pad); } - else + else if (p.top_delta.isProvided()) { - follows |= FOLLOWS_BOTTOM; + p.bottom_delta = + -(p.top_delta + p.rect.height - last_rect.getHeight()); } - } - else - { - // if bottom not specified, generate automatically - if (last_y == 0) + else if (!p.bottom_delta.isProvided() + && !p.left_delta.isProvided() + && !p.top_pad.isProvided() + && !p.left_pad.isProvided()) { - // treat first child as "bottom" - y = parent_view->getRect().getHeight() - (h + VPAD); - follows |= FOLLOWS_TOP; + // set default position is just below last rect + p.bottom_delta.set(-(p.rect.height + VPAD), false); } - else + + // default to same left edge + p.left_delta.setIfNotProvided(0, false); + if (p.left_pad.isProvided()) { - // treat subsequent children as "bottom_delta" - y = last_y - (h + VPAD); + // left_pad is based on prior widget's right edge + p.left_delta.set(p.left_pad + last_rect.getWidth(), false); } + + last_rect.translate(p.left_delta, p.bottom_delta); + } + else + { + // set default position is just below last rect + p.bottom_delta.setIfNotProvided(-(p.rect.height + VPAD), false); + p.left_delta.setIfNotProvided(0, false); + last_rect.translate(p.left_delta, p.bottom_delta); } - } - else - { - x = llmax(x, 0); - y = llmax(y, 0); - follows = FOLLOWS_LEFT | FOLLOWS_TOP; - } - rect.setOriginAndSize(x, y, w, h); - - return follows; -} - -void LLView::initFromXML(LLXMLNodePtr node, LLView* parent) -{ - // create rect first, as this will supply initial follows flags - LLRect view_rect; - U32 follows_flags = createRect(node, view_rect, parent, getRequiredRect()); - // call reshape in case there are any child elements that need to be layed out - reshape(view_rect.getWidth(), view_rect.getHeight()); - setRect(view_rect); - setFollows(follows_flags); - - parseFollowsFlags(node); - if (node->hasAttribute("control_name")) - { - std::string control_name; - node->getAttributeString("control_name", control_name); - setControlName(control_name, NULL); - } + // this handles case where *both* x and x_delta are provided + // ignore x in favor of default x + x_delta + if (p.bottom_delta.isProvided()) p.rect.bottom.set(0, false); + if (p.left_delta.isProvided()) p.rect.left.set(0, false); - if (node->hasAttribute("tool_tip")) - { - std::string tool_tip_msg; - node->getAttributeString("tool_tip", tool_tip_msg); - setToolTip(tool_tip_msg); + // selectively apply rectangle defaults, making sure that + // params are not flagged as having been "provided" + // as rect params are overconstrained and rely on provided flags + p.rect.left.setIfNotProvided(last_rect.mLeft, false); + p.rect.bottom.setIfNotProvided(last_rect.mBottom, false); + p.rect.top.setIfNotProvided(last_rect.mTop, false); + p.rect.right.setIfNotProvided(last_rect.mRight, false); + p.rect.width.setIfNotProvided(last_rect.getWidth(), false); + p.rect.height.setIfNotProvided(last_rect.getHeight(), false); } +} - if (node->hasAttribute("enabled")) - { - BOOL enabled; - node->getAttributeBOOL("enabled", enabled); - setEnabled(enabled); - } - - if (node->hasAttribute("visible")) +static S32 invert_vertical(S32 y, LLView* parent) +{ + if (y < 0) { - BOOL visible; - node->getAttributeBOOL("visible", visible); - setVisible(visible); + // already based on top-left, just invert + return -y; } - - if (node->hasAttribute("hover_cursor")) + else if (parent) { - std::string cursor_string; - node->getAttributeString("hover_cursor", cursor_string); - mHoverCursor = getCursorFromString(cursor_string); + // use parent to flip coordinate + S32 parent_height = parent->getRect().getHeight(); + return parent_height - y; } - - node->getAttributeBOOL("use_bounding_rect", mUseBoundingRect); - node->getAttributeBOOL("mouse_opaque", mMouseOpaque); - - node->getAttributeS32("default_tab_group", mDefaultTabGroup); - - reshape(view_rect.getWidth(), view_rect.getHeight()); -} - -void LLView::parseFollowsFlags(LLXMLNodePtr node) -{ - if (node->hasAttribute("follows")) + else { - setFollowsNone(); - - std::string follows; - node->getAttributeString("follows", follows); - - typedef boost::tokenizer > tokenizer; - boost::char_separator sep("|"); - tokenizer tokens(follows, sep); - tokenizer::iterator token_iter = tokens.begin(); - - while(token_iter != tokens.end()) - { - const std::string& token_str = *token_iter; - if (token_str == "left") + llwarns << "Attempting to convert layout to top-left with no parent" << llendl; + return y; + } +} + +// Assumes that input is in bottom-left coordinates, hence must call +// _before_ convert_coords_to_top_left(). +static void convert_to_relative_layout(LLView::Params& p, LLView* parent) +{ + // Use setupParams to get the final widget rectangle + // according to our wacky layout rules. + LLView::Params final = p; + LLView::setupParams(final, parent); + // Must actually extract the rectangle to get consistent + // right = left+width, top = bottom+height + LLRect final_rect = final.rect; + + // We prefer to write out top edge instead of bottom, regardless + // of whether we use relative positioning + bool converted_top = false; + + // Look for a last rectangle + LLRect last_rect; + if (get_last_child_rect(parent, &last_rect)) + { + // ...we have a previous widget to compare to + const S32 EDGE_THRESHOLD_PIXELS = 4; + S32 left_pad = final_rect.mLeft - last_rect.mRight; + S32 left_delta = final_rect.mLeft - last_rect.mLeft; + S32 top_pad = final_rect.mTop - last_rect.mBottom; + S32 top_delta = final_rect.mTop - last_rect.mTop; + // If my left edge is almost the same, or my top edge is + // almost the same... + if (llabs(left_delta) <= EDGE_THRESHOLD_PIXELS + || llabs(top_delta) <= EDGE_THRESHOLD_PIXELS) + { + // ...use relative positioning + // prefer top_pad if widgets are stacking vertically + // (coordinate system is still bottom-left here) + if (top_pad < 0) { - setFollowsLeft(); + p.top_pad = top_pad; + p.top_delta.setProvided(false); } - else if (token_str == "right") - { - setFollowsRight(); - } - else if (token_str == "top") + else { - setFollowsTop(); + p.top_pad.setProvided(false); + p.top_delta = top_delta; } - else if (token_str == "bottom") + // null out other vertical specifiers + p.rect.top.setProvided(false); + p.rect.bottom.setProvided(false); + p.bottom_delta.setProvided(false); + converted_top = true; + + // prefer left_pad if widgets are stacking horizontally + if (left_pad > 0) { - setFollowsBottom(); + p.left_pad = left_pad; + p.left_delta.setProvided(false); } - else if (token_str == "all") + else { - setFollowsAll(); + p.left_pad.setProvided(false); + p.left_delta = left_delta; } - ++token_iter; + p.rect.left.setProvided(false); + p.rect.right.setProvided(false); } } -} -// static -LLFontGL* LLView::selectFont(LLXMLNodePtr node) -{ - std::string font_name, font_size, font_style; - U8 style = 0; - - if (node->hasAttribute("font")) - { - node->getAttributeString("font", font_name); - } - - if (node->hasAttribute("font_size")) + if (!converted_top) { - node->getAttributeString("font_size", font_size); + // ...this is the first widget, or one that wasn't aligned + // prefer top/left specification + p.rect.top = final_rect.mTop; + p.rect.bottom.setProvided(false); + p.bottom_delta.setProvided(false); + p.top_pad.setProvided(false); + p.top_delta.setProvided(false); } - - if (node->hasAttribute("font_style")) - { - node->getAttributeString("font_style", font_style); - style = LLFontGL::getStyleFromString(font_style); - } - - if (node->hasAttribute("font-style")) - { - node->getAttributeString("font-style", font_style); - style = LLFontGL::getStyleFromString(font_style); - } - - if (font_name.empty()) - return NULL; - - LLFontDescriptor desc(font_name, font_size, style); - LLFontGL* gl_font = LLFontGL::getFont(desc); - - return gl_font; } -// static -LLFontGL::HAlign LLView::selectFontHAlign(LLXMLNodePtr node) +static void convert_coords_to_top_left(LLView::Params& p, LLView* parent) { - LLFontGL::HAlign gl_hfont_align = LLFontGL::LEFT; - - if (node->hasAttribute("halign")) + // Convert the coordinate system to be top-left based. + if (p.rect.top.isProvided()) { - std::string horizontal_align_name; - node->getAttributeString("halign", horizontal_align_name); - gl_hfont_align = LLFontGL::hAlignFromName(horizontal_align_name); + p.rect.top = invert_vertical(p.rect.top, parent); } - return gl_hfont_align; -} - -// static -LLFontGL::VAlign LLView::selectFontVAlign(LLXMLNodePtr node) -{ - LLFontGL::VAlign gl_vfont_align = LLFontGL::BASELINE; - - if (node->hasAttribute("valign")) + if (p.rect.bottom.isProvided()) { - std::string vert_align_name; - node->getAttributeString("valign", vert_align_name); - gl_vfont_align = LLFontGL::vAlignFromName(vert_align_name); + p.rect.bottom = invert_vertical(p.rect.bottom, parent); } - return gl_vfont_align; -} - -// static -LLFontGL::StyleFlags LLView::selectFontStyle(LLXMLNodePtr node) -{ - LLFontGL::StyleFlags gl_font_style = LLFontGL::NORMAL; - - if (node->hasAttribute("style")) + if (p.top_pad.isProvided()) { - std::string style_flags_name; - node->getAttributeString("style", style_flags_name); - - if (style_flags_name == "normal") - { - gl_font_style = LLFontGL::NORMAL; - } - else if (style_flags_name == "bold") - { - gl_font_style = LLFontGL::BOLD; - } - else if (style_flags_name == "italic") - { - gl_font_style = LLFontGL::ITALIC; - } - else if (style_flags_name == "underline") - { - gl_font_style = LLFontGL::UNDERLINE; - } - //else leave left + p.top_pad = -p.top_pad; } - return gl_font_style; -} - -bool LLView::setControlValue(const LLSD& value) -{ - std::string ctrlname = getControlName(); - if (!ctrlname.empty()) + if (p.top_delta.isProvided()) { - LLUI::sConfigGroup->setValue(ctrlname, value); - return true; + p.top_delta = -p.top_delta; } - return false; -} - -//virtual -void LLView::setControlName(const std::string& control_name, LLView *context) -{ - if (context == NULL) + if (p.bottom_delta.isProvided()) { - context = this; + p.bottom_delta = -p.bottom_delta; } + p.layout = "topleft"; +} - if (!mControlName.empty()) +//static +void LLView::setupParamsForExport(Params& p, LLView* parent) +{ + // Don't convert if already top-left based + if (p.layout() == "topleft") { - llwarns << "setControlName called twice on same control!" << llendl; - mControlConnection.disconnect(); // disconnect current signal - mControlName.clear(); + return; } - - // Register new listener - if (!control_name.empty()) - { - LLControlVariable *control = context->findControl(control_name); - if (control) - { - mControlName = control_name; - mControlConnection = control->getSignal()->connect(boost::bind(&controlListener, _1, getHandle(), std::string("value"))); - setValue(control->getValue()); - } - } -} -// static -bool LLView::controlListener(const LLSD& newvalue, LLHandle handle, std::string type) -{ - LLView* view = handle.get(); - if (view) + // heuristic: Many of our floaters and panels were bulk-exported. + // These specify exactly bottom/left and height/width. + // Others were done by hand using bottom_delta and/or left_delta. + // Some rely on not specifying left to mean align with left edge. + // Try to convert both to use relative layout, but using top-left + // coordinates. + // Avoid rectangles where top/bottom/left/right was specified. + if (p.rect.height.isProvided() && p.rect.width.isProvided()) { - if (type == "value") + if (p.rect.bottom.isProvided() && p.rect.left.isProvided()) { - view->setValue(newvalue); - return true; + // standard bulk export, convert it + convert_to_relative_layout(p, parent); } - else if (type == "enabled") + else if (p.rect.bottom.isProvided() && p.left_delta.isProvided()) { - view->setEnabled(newvalue.asBoolean()); - return true; + // hand layout with left_delta + convert_to_relative_layout(p, parent); } - else if (type == "visible") + else if (p.bottom_delta.isProvided()) { - view->setVisible(newvalue.asBoolean()); - return true; + // hand layout with bottom_delta + // don't check for p.rect.left or p.left_delta because sometimes + // this layout doesn't set it for widgets that are left-aligned + convert_to_relative_layout(p, parent); } } - return false; -} -void LLView::addBoolControl(const std::string& name, bool initial_value) -{ - mFloaterControls[name] = new LLControlVariable(name, TYPE_BOOLEAN, initial_value, std::string("Internal floater control")); -} - -LLControlVariable *LLView::getControl(const std::string& name) -{ - control_map_t::iterator itor = mFloaterControls.find(name); - if (itor != mFloaterControls.end()) - { - return itor->second; - } - return NULL; + convert_coords_to_top_left(p, parent); } -//virtual -void LLView::setValue(const LLSD& value) -{ -} - -//virtual -LLSD LLView::getValue() const -{ - return LLSD(); -} - -LLView* LLView::createWidget(LLXMLNodePtr xml_node) const -{ - // forward requests to ui ctrl factory - return LLUICtrlFactory::getInstance()->createCtrlWidget(NULL, xml_node); -} - -// -// LLWidgetClassRegistry -// - -LLWidgetClassRegistry::LLWidgetClassRegistry() +LLView::tree_iterator_t LLView::beginTree() { + return tree_iterator_t(this, + boost::bind(boost::mem_fn(&LLView::beginChild), _1), + boost::bind(boost::mem_fn(&LLView::endChild), _1)); } -void LLWidgetClassRegistry::registerCtrl(const std::string& tag, LLWidgetClassRegistry::factory_func_t function) +LLView::tree_iterator_t LLView::endTree() { - std::string lower_case_tag = tag; - LLStringUtil::toLower(lower_case_tag); - - mCreatorFunctions[lower_case_tag] = function; + // an empty iterator is an "end" iterator + return tree_iterator_t(); } -BOOL LLWidgetClassRegistry::isTagRegistered(const std::string &tag) -{ - return mCreatorFunctions.find(tag) != mCreatorFunctions.end(); -} - -LLWidgetClassRegistry::factory_func_t LLWidgetClassRegistry::getCreatorFunc(const std::string& ctrl_type) -{ - factory_map_t::const_iterator found_it = mCreatorFunctions.find(ctrl_type); - if (found_it == mCreatorFunctions.end()) +// only create maps on demand, as they incur heap allocation/deallocation cost +// when a view is constructed/deconstructed +LLView::dummy_widget_map_t& LLView::getDummyWidgetMap() const +{ + if (!mDummyWidgets) { - return NULL; + mDummyWidgets = new dummy_widget_map_t(); } - return found_it->second; + return *mDummyWidgets; } - diff --git a/indra/llui/llview.h b/indra/llui/llview.h index 721fe99f4a..458d02d001 100644 --- a/indra/llui/llview.h +++ b/indra/llui/llview.h @@ -37,6 +37,7 @@ // the HUD or a dialog box or a button. It can also contain sub-views // and child widgets +#include "stdtypes.h" #include "llcoord.h" #include "llfontgl.h" #include "llmortician.h" @@ -47,12 +48,14 @@ #include "llrect.h" #include "llui.h" #include "lluistring.h" -#include "lluixmltags.h" #include "llviewquery.h" -#include "llxmlnode.h" #include "stdenums.h" #include "lluistring.h" #include "llcursortypes.h" +#include "lluictrlfactory.h" +#include "lltreeiterators.h" + +#include const U32 FOLLOWS_NONE = 0x00; const U32 FOLLOWS_LEFT = 0x01; @@ -75,9 +78,6 @@ virtual BOOL isPanel(); LLPanel virtual void setRect(const LLRect &rect); LLLineEditor -virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); -virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); -virtual void removeCtrl( LLUICtrl* ctrl); LLPanel virtual BOOL canFocusChildren() const { return TRUE; } LLFolderView @@ -103,7 +103,7 @@ virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); LLUICtrl, et. al. virtual void translate( S32 x, S32 y ); LLMenuGL -virtual void userSetShape(const LLRect& new_rect); +virtual void setShape(const LLRect& new_rect, bool by_user); LLFloater, LLScrollLIstVtrl virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); @@ -121,10 +121,6 @@ virtual BOOL handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,EDragAndDropTy virtual void draw(); * - * -virtual LLXMLNodePtr getXML(bool save_children = true) const; - * -virtual void initFromXML(LLXMLNodePtr node, LLView* parent); * virtual void onFocusLost() {} LLUICtrl, LLScrollListCtrl, LLMenuGL, LLLineEditor, LLComboBox @@ -132,14 +128,8 @@ virtual void onFocusReceived() {} LLUICtrl, LLTextEditor, LLScrollListVtrl, LLMenuGL, LLLineEditor virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; LLTabContainer, LLPanel, LLMenuGL -virtual void setControlName(const std::string& control, LLView *context); - LLSliderCtrl, LLCheckBoxCtrl -virtual std::string getControlName() const { return mControlName; } - LLSliderCtrl, LLCheckBoxCtrl virtual bool handleEvent(LLPointer event, const LLSD& userdata); LLMenuItem -virtual void setValue(const LLSD& value); - * protected: virtual BOOL handleKeyHere(KEY key, MASK mask); @@ -148,67 +138,69 @@ virtual BOOL handleUnicodeCharHere(llwchar uni_char); * */ -class LLUICtrlFactory; - -// maps xml strings to widget classes -class LLWidgetClassRegistry : public LLSingleton +class LLView : public LLMouseHandler, public LLMortician { - friend class LLSingleton; public: - typedef LLView* (*factory_func_t)(LLXMLNodePtr node, LLView *parent, LLUICtrlFactory *factory); - typedef std::map factory_map_t; - - void registerCtrl(const std::string& xml_tag, factory_func_t function); - BOOL isTagRegistered(const std::string& xml_tag); - factory_func_t getCreatorFunc(const std::string& xml_tag); - - // get (first) xml tag for a given class - template std::string getTag() + struct Follows : public LLInitParam::Choice { - factory_map_t::iterator it; - for(it = mCreatorFunctions.begin(); it != mCreatorFunctions.end(); ++it) - { - if (it->second == T::fromXML) - { - return it->first; - } - } - - return ""; - } - -private: - LLWidgetClassRegistry(); - virtual ~LLWidgetClassRegistry() {}; - - typedef std::set ctrl_name_set_t; - ctrl_name_set_t mUICtrlNames; + Option string; + Option flags; - // map of xml tags to widget creator functions - factory_map_t mCreatorFunctions; -}; + Follows() + : string(""), + flags("flags", FOLLOWS_LEFT | FOLLOWS_TOP) + {} + }; -template -class LLRegisterWidget -{ -public: - LLRegisterWidget(const std::string& tag) + struct Params : public LLInitParam::Block { - LLWidgetClassRegistry* registry = LLWidgetClassRegistry::getInstance(); - if (registry->isTagRegistered(tag)) - { - //error! - llerrs << "Widget named " << tag << " already registered!" << llendl; - } - else - { - registry->registerCtrl(tag, T::fromXML); - } - } -}; + Mandatory name; + + Optional enabled, + visible; + Optional mouse_opaque; + Optional use_bounding_rect; + Optional tab_group, + default_tab_group; + Optional tool_tip; + + Optional sound_flags; + Optional serializable; + Optional follows; + Optional hover_cursor; + + // font params + Optional font; + Optional font_halign; + Optional font_valign; + + Optional layout; + Optional rect; + // Historical bottom-left layout used bottom_delta and left_delta + // for relative positioning. New layout "topleft" prefers specifying + // based on top edge. + Optional bottom_delta, // deprecated + top_pad, // from last bottom to my top + top_delta, // from last top to my top + left_pad, // from last right to my left + left_delta; // from last left to my left + + Optional center_horiz, + center_vert; + + // these are nested attributes for LLLayoutPanel + //FIXME: get parent context involved in parsing traversal + Deprecated user_resize, + auto_resize, + needs_translate; + + Params(); + }; + void initFromParams(const LLView::Params&); -class LLView : public LLMouseHandler, public LLMortician -{ +protected: + LLView(const LLView::Params&); + friend class LLUICtrlFactory; public: #if LL_DEBUG @@ -253,10 +245,6 @@ public: typedef child_tab_order_t::reverse_iterator child_tab_order_reverse_iter_t; typedef child_tab_order_t::const_reverse_iterator child_tab_order_const_reverse_iter_t; - LLView(); - LLView(const std::string& name, BOOL mouse_opaque); - LLView(const std::string& name, const LLRect& rect, BOOL mouse_opaque, U32 follows=FOLLOWS_NONE); - virtual ~LLView(); // Hack to support LLFocusMgr (from LLMouseHandler) @@ -300,15 +288,19 @@ public: void sendChildToBack(LLView* child); void moveChildToFrontOfTabGroup(LLUICtrl* child); void moveChildToBackOfTabGroup(LLUICtrl* child); + + virtual bool addChild(LLView* view, S32 tab_group = 0); + + // implemented in terms of addChild() + bool addChildInBack(LLView* view, S32 tab_group = 0); - void addChild(LLView* view, S32 tab_group = 0); - void addChildAtEnd(LLView* view, S32 tab_group = 0); // remove the specified child from the view, and set it's parent to NULL. - void removeChild(LLView* view, BOOL deleteIt = FALSE); + virtual void removeChild(LLView* view); + + // helper function for lluictrlfactory.h create<> template + void setParent(LLView* parent) { if (parent) parent->addChild(this); } - virtual void addCtrl( LLUICtrl* ctrl, S32 tab_group); - virtual void addCtrlAtEnd( LLUICtrl* ctrl, S32 tab_group); - virtual void removeCtrl( LLUICtrl* ctrl); + virtual BOOL postBuild() { return TRUE; } child_tab_order_t getCtrlOrder() const { return mCtrlOrder; } ctrl_list_t getCtrlList() const; @@ -316,6 +308,7 @@ public: void setDefaultTabGroup(S32 d) { mDefaultTabGroup = d; } S32 getDefaultTabGroup() const { return mDefaultTabGroup; } + S32 getLastTabGroup() { return mLastTabGroup; } BOOL isInVisibleChain() const; BOOL isInEnabledChain() const; @@ -347,7 +340,7 @@ public: virtual void onVisibilityChange ( BOOL curVisibilityIn ); void pushVisible(BOOL visible) { mLastVisible = mVisible; setVisible(visible); } - void popVisible() { setVisible(mLastVisible); mLastVisible = TRUE; } + void popVisible() { setVisible(mLastVisible); } LLHandle getHandle() { mHandle.bind(this); return mHandle; } @@ -361,11 +354,14 @@ public: const LLRect& getRect() const { return mRect; } const LLRect& getBoundingRect() const { return mBoundingRect; } LLRect getLocalBoundingRect() const; - LLRect getScreenRect() const; + LLRect calcScreenRect() const; + LLRect calcScreenBoundingRect() const; LLRect getLocalRect() const; virtual LLRect getSnapRect() const; LLRect getLocalSnapRect() const; + std::string getLayout() { return mLayout; } + // Override and return required size for this object. 0 for width/height means don't care. virtual LLRect getRequiredRect(); void updateBoundingRect(); @@ -373,12 +369,17 @@ public: LLView* getRootView(); LLView* getParent() const { return mParentView; } LLView* getFirstChild() const { return (mChildList.empty()) ? NULL : *(mChildList.begin()); } + LLView* findPrevSibling(LLView* child); + LLView* findNextSibling(LLView* child); S32 getChildCount() const { return (S32)mChildList.size(); } template void sortChildren(_Pr3 _Pred) { mChildList.sort(_Pred); } BOOL hasAncestor(const LLView* parentp) const; BOOL hasChild(const std::string& childname, BOOL recurse = FALSE) const; BOOL childHasKeyboardFocus( const std::string& childname ) const; - + + typedef LLTreeDFSIter tree_iterator_t; + tree_iterator_t beginTree(); + tree_iterator_t endTree(); // // UTILITIES @@ -391,13 +392,11 @@ public: BOOL translateIntoRect( const LLRect& constraint, BOOL allow_partial_outside ); void centerWithin(const LLRect& bounds); - virtual void userSetShape(const LLRect& new_rect); + void setShape(const LLRect& new_rect, bool by_user = false); virtual LLView* findSnapRect(LLRect& new_rect, const LLCoordGL& mouse_dir, LLView::ESnapType snap_type, S32 threshold, S32 padding = 0); virtual LLView* findSnapEdge(S32& new_edge_val, const LLCoordGL& mouse_dir, ESnapEdge snap_edge, ESnapType snap_type, S32 threshold, S32 padding = 0); - virtual BOOL canSnapTo(const LLView* other_view); - - virtual void snappedTo(const LLView* snap_view); + virtual void setSnappedTo(const LLView* snap_view); virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); @@ -407,15 +406,11 @@ public: EAcceptance* accept, std::string& tooltip_msg); - std::string getShowNamesToolTip(); + virtual std::string getShowNamesToolTip(); virtual void draw(); - virtual LLXMLNodePtr getXML(bool save_children = true) const; - //FIXME: make LLView non-instantiable from XML - static LLView* fromXML(LLXMLNodePtr node, LLView *parent, class LLUICtrlFactory *factory); - virtual void initFromXML(LLXMLNodePtr node, LLView* parent); - void parseFollowsFlags(LLXMLNodePtr node); + void parseFollowsFlags(const LLView::Params& params); // Some widgets, like close box buttons, don't need to be saved BOOL getSaveToXML() const { return mSaveToXML; } @@ -440,25 +435,16 @@ public: void screenRectToLocal( const LLRect& screen, LLRect* local ) const; void localRectToScreen( const LLRect& local, LLRect* screen ) const; - // Listener dispatching functions (Dispatcher deletes pointers to listeners on deregistration or destruction) - LLOldEvents::LLSimpleListener* getListenerByName(const std::string& callback_name); - void registerEventListener(std::string name, LLOldEvents::LLSimpleListener* function); - void deregisterEventListener(std::string name); - std::string findEventListener(LLOldEvents::LLSimpleListener *listener) const; - void addListenerToControl(LLOldEvents::LLEventDispatcher *observer, const std::string& name, LLSD filter, LLSD userdata); - - void addBoolControl(const std::string& name, bool initial_value); - LLControlVariable *getControl(const std::string& name); LLControlVariable *findControl(const std::string& name); - bool setControlValue(const LLSD& value); - virtual void setControlName(const std::string& control, LLView *context); - virtual std::string getControlName() const { return mControlName; } + // Moved setValue(), getValue(), setControlValue(), setControlName(), + // controlListener() to LLUICtrl because an LLView is NOT assumed to + // contain a value. If that's what you want, use LLUICtrl instead. // virtual bool handleEvent(LLPointer event, const LLSD& userdata); - virtual void setValue(const LLSD& value); - virtual LLSD getValue() const; const child_list_t* getChildList() const { return &mChildList; } + const child_list_const_iter_t beginChild() { return mChildList.begin(); } + const child_list_const_iter_t endChild() { return mChildList.end(); } // LLMouseHandler functions // Default behavior is to pass events to children @@ -479,26 +465,20 @@ 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; - template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const + // view-specific handlers + virtual void onMouseEnter(S32 x, S32 y, MASK mask); + virtual void onMouseLeave(S32 x, S32 y, MASK mask); + + + template T* findChild(const std::string& name, BOOL recurse = TRUE) const { LLView* child = getChildView(name, recurse, FALSE); T* result = dynamic_cast(child); - if (!result) - { - // did we find *something* with that name? - if (child) - { - llwarns << "Found child named " << name << " but of wrong type " << typeid(child).name() << ", expecting " << typeid(T).name() << llendl; - } - if (create_if_missing) - { - // create dummy widget instance here - result = createDummyWidget(name); - } - } return result; } + template T* getChild(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; + template T& getChildRef(const std::string& name, BOOL recurse = TRUE) const { return *getChild(name, recurse, TRUE); @@ -506,72 +486,24 @@ public: virtual LLView* getChildView(const std::string& name, BOOL recurse = TRUE, BOOL create_if_missing = TRUE) const; - template T* createDummyWidget(const std::string& name) const - { - T* widget = getDummyWidget(name); - if (!widget) - { - // get xml tag name corresponding to requested widget type (e.g. "button") - std::string xml_tag = LLWidgetClassRegistry::getInstance()->getTag(); - if (xml_tag.empty()) - { - llwarns << "No xml tag registered for this class " << llendl; - return NULL; - } - // create dummy xml node ( + + + + + + + + + If unchecked, viewer will display full-screen when logged in. + + + Window Size: + + + + + + + + + + Display Resolution: + + + + Aspect Ratio: + + + + + + + + + + + + Quality and + + + Performance: + + + Faster + + + Low + + + Mid + + + High + + + Ultra + + + Higher + + + Quality + + + + + + + + + + + + Shaders: + + + + + + + + + + + + + Reflection Detail: + + + + + + + + + Avatar Rendering: + + + + + + + + m + + + m + + + + + + + + + + Mesh Detail: + + + + + + + + + + + + + + + + + + + + + Low + + + Low + + + Low + + + Low + + + Low + + + Low + + + Low + + + Lighting Detail: + + + + + + + Terrain Detail: + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/panel_profile.xml b/indra/newview/skins/default/xui/en/panel_profile.xml new file mode 100644 index 0000000000..a4363d5858 --- /dev/null +++ b/indra/newview/skins/default/xui/en/panel_profile.xml @@ -0,0 +1,574 @@ + + + + [ACCTTYPE] [PAYMENTINFO] [AGEVERIFICATION] + + + Resident. + + + Trial + + + Charter Member + + + Linden Lab Employee + + + Payment Info Used + + + Payment Info On File + + + No Payment Info On File + + + Age-verified + + + Not Age-verified + + + + + + + Second Life photo: + + + + + + First Life photo: + + + + + + + + + + + + + Status: + + + + + + + + What're you up to? + + + Type a message about what you're doing in SL! + + + + Second Life description: + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. + + + First Life description: + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. + + + Second Life groups: + + + Lorem ipsum dolor sit amet, consectetur adipiscing elit. Aenean viverra orci et justo sagittis aliquet. Nullam malesuada mauris sit amet ipsum. + + + Homepage: + + + TODO + + + Member since: + + + 05/31/1976 + + + Account status: + + + Resident. No payment info on file. + + + + Update + + + My Account + + + + Partner: + + + + [FIRST] [LAST] + + + Edit + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/check_box.xml b/indra/newview/skins/default/xui/en/widgets/check_box.xml new file mode 100644 index 0000000000..ff01dcebd8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/check_box.xml @@ -0,0 +1,18 @@ + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/color_swatch.xml b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml new file mode 100644 index 0000000000..304eda2d97 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/color_swatch.xml @@ -0,0 +1,10 @@ + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/combo_box.xml b/indra/newview/skins/default/xui/en/widgets/combo_box.xml new file mode 100644 index 0000000000..8a8f3f7f2c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/combo_box.xml @@ -0,0 +1,22 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/drop_down.xml b/indra/newview/skins/default/xui/en/widgets/drop_down.xml new file mode 100644 index 0000000000..c35d15ec92 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/drop_down.xml @@ -0,0 +1,20 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/flyout_button.xml b/indra/newview/skins/default/xui/en/widgets/flyout_button.xml new file mode 100644 index 0000000000..e0033058c8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/flyout_button.xml @@ -0,0 +1,13 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/icon.xml b/indra/newview/skins/default/xui/en/widgets/icon.xml new file mode 100644 index 0000000000..adb743a628 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/icon.xml @@ -0,0 +1,7 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/line_editor.xml b/indra/newview/skins/default/xui/en/widgets/line_editor.xml new file mode 100644 index 0000000000..11081ae308 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/line_editor.xml @@ -0,0 +1,18 @@ + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/location_input.xml b/indra/newview/skins/default/xui/en/widgets/location_input.xml new file mode 100644 index 0000000000..32f5a18d1c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/location_input.xml @@ -0,0 +1,66 @@ + + + + + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/menu.xml b/indra/newview/skins/default/xui/en/widgets/menu.xml new file mode 100644 index 0000000000..10bc124ea3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu.xml @@ -0,0 +1,6 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml new file mode 100644 index 0000000000..24bda97f44 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu_item_call.xml @@ -0,0 +1,6 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml new file mode 100644 index 0000000000..f6b06cb50b --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu_item_check.xml @@ -0,0 +1,6 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml new file mode 100644 index 0000000000..e5cea476da --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/menu_item_separator.xml @@ -0,0 +1,6 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml new file mode 100644 index 0000000000..e0900b48f3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/multi_slider.xml @@ -0,0 +1,6 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml new file mode 100644 index 0000000000..04a2cd635c --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/multi_slider_bar.xml @@ -0,0 +1,10 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/name_editor.xml b/indra/newview/skins/default/xui/en/widgets/name_editor.xml new file mode 100644 index 0000000000..21ba5c77f8 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/name_editor.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/panel.xml b/indra/newview/skins/default/xui/en/widgets/panel.xml new file mode 100644 index 0000000000..b81a70b845 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/panel.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/progress_bar.xml b/indra/newview/skins/default/xui/en/widgets/progress_bar.xml new file mode 100644 index 0000000000..3344de06b0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/progress_bar.xml @@ -0,0 +1,21 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/radio_group.xml b/indra/newview/skins/default/xui/en/widgets/radio_group.xml new file mode 100644 index 0000000000..2d851042a5 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/radio_group.xml @@ -0,0 +1,6 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/radio_item.xml b/indra/newview/skins/default/xui/en/widgets/radio_item.xml new file mode 100644 index 0000000000..0a27ca509b --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/radio_item.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml new file mode 100644 index 0000000000..a6c9a56dfd --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/scroll_bar.xml @@ -0,0 +1,19 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_container.xml b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml new file mode 100644 index 0000000000..cb9ef04797 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/scroll_container.xml @@ -0,0 +1,3 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/scroll_list.xml b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml new file mode 100644 index 0000000000..9e2c52acca --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/scroll_list.xml @@ -0,0 +1,16 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/search_editor.xml b/indra/newview/skins/default/xui/en/widgets/search_editor.xml new file mode 100644 index 0000000000..10080e5e39 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/search_editor.xml @@ -0,0 +1,6 @@ + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/side_tray.xml b/indra/newview/skins/default/xui/en/widgets/side_tray.xml new file mode 100644 index 0000000000..e3b70ba6e2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/side_tray.xml @@ -0,0 +1,8 @@ + + + diff --git a/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml new file mode 100644 index 0000000000..20af3bb58f --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/simple_text_editor.xml @@ -0,0 +1,11 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/slider.xml b/indra/newview/skins/default/xui/en/widgets/slider.xml new file mode 100644 index 0000000000..f735d09476 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/slider.xml @@ -0,0 +1,16 @@ + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/slider_bar.xml b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml new file mode 100644 index 0000000000..ba9ad21cc0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/slider_bar.xml @@ -0,0 +1,7 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/spinner.xml b/indra/newview/skins/default/xui/en/widgets/spinner.xml new file mode 100644 index 0000000000..29bf1e8052 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/spinner.xml @@ -0,0 +1,5 @@ + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/tab_container.xml b/indra/newview/skins/default/xui/en/widgets/tab_container.xml new file mode 100644 index 0000000000..8245e5ff23 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/tab_container.xml @@ -0,0 +1,9 @@ + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/text.xml b/indra/newview/skins/default/xui/en/widgets/text.xml new file mode 100644 index 0000000000..3d98cd66f9 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/text.xml @@ -0,0 +1,16 @@ + + diff --git a/indra/newview/skins/default/xui/en/widgets/text_editor.xml b/indra/newview/skins/default/xui/en/widgets/text_editor.xml new file mode 100644 index 0000000000..dc4c430546 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/text_editor.xml @@ -0,0 +1,19 @@ + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/texture_picker.xml b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml new file mode 100644 index 0000000000..33c3475eb2 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/texture_picker.xml @@ -0,0 +1,9 @@ + + + + + + + diff --git a/indra/newview/skins/default/xui/en/widgets/view_border.xml b/indra/newview/skins/default/xui/en/widgets/view_border.xml new file mode 100644 index 0000000000..0b0a9beb95 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/view_border.xml @@ -0,0 +1,8 @@ + + \ No newline at end of file diff --git a/indra/newview/skins/default/xui/en/widgets/web_browser.xml b/indra/newview/skins/default/xui/en/widgets/web_browser.xml new file mode 100644 index 0000000000..118d63bbf0 --- /dev/null +++ b/indra/newview/skins/default/xui/en/widgets/web_browser.xml @@ -0,0 +1,2 @@ + + diff --git a/indra/newview/skins/default/xui/en/xui_version.xml b/indra/newview/skins/default/xui/en/xui_version.xml new file mode 100644 index 0000000000..0e777751d3 --- /dev/null +++ b/indra/newview/skins/default/xui/en/xui_version.xml @@ -0,0 +1,4 @@ + + + 1.0 + diff --git a/indra/newview/skins/default/xui/es/floater_animation_preview.xml b/indra/newview/skins/default/xui/es/floater_animation_preview.xml index a5b9847c4f..5a03aa6370 100644 --- a/indra/newview/skins/default/xui/es/floater_animation_preview.xml +++ b/indra/newview/skins/default/xui/es/floater_animation_preview.xml @@ -6,145 +6,72 @@ Descripción: - - - - + + + + Posición de las manos - - - Extendidas - - - Relajadas - - - Ambas señalan - - - Puño - - - La izquierda relajada - - - La izquierda señala - - - Puño en la izquierda - - - La derecha relajada - - - La derecha señala - - - Puño en la derecha - - - La derecha saluda - - - Escribiendo - - - Paz en la derecha - + + + + + + + + + + + + + + Expresión - - - [Nada] - - - Aaaaah - - - Con miedo - - - Enfadada - - - Gran sonrisa - - - Aburrida - - - Llorar - - - Desdén - - - Avergonzada - - - Fruncir el ceño - - - Besar - - - Reír - - - Sacar la lengua - - - Rechazo - - - Triste - - - Encogerse de hombros - - - Sonrisa - - - Sorpresa - - - Guiño - - - Preocupación - + + + + + + + + + + + + + + + + + + + + + - + Vista previa mientras - - - Estar de pie - - - Caminar - - - Estar sentado - - - Volar - + + + + + - - -