From 89fe5dab825a62a0e3fd8d248cbc91c65eb2a426 Mon Sep 17 00:00:00 2001 From: Jacek Antonelli Date: Fri, 15 Aug 2008 23:44:50 -0500 Subject: Second Life viewer sources 1.14.0.0 --- .../indra/newview/English.lproj/InfoPlist.strings | 4 +- linden/indra/newview/Info-SecondLife.plist | 2 +- linden/indra/newview/app_settings/keywords.ini | 4 + .../shaders/class1/lighting/lightF.glsl | 2 +- .../shaders/class1/objects/shinyF.glsl | 13 + .../shaders/class1/objects/shinyV.glsl | 27 + .../shaders/class2/environment/waterV.glsl | 2 +- .../shaders/class2/lighting/lightF.glsl | 2 +- .../shaders/class3/environment/groundF.glsl | 12 - .../shaders/class3/environment/groundV.glsl | 11 - .../shaders/class3/environment/scatterF.glsl | 25 - .../shaders/class3/environment/scatterV.glsl | 16 - .../shaders/class3/environment/waterF.glsl | 145 + linden/indra/newview/app_settings/viewerart.ini | 503 --- linden/indra/newview/app_settings/viewerart.xml | 388 -- linden/indra/newview/character/avatar_lad.xml | 4 +- linden/indra/newview/featuretable.txt | 23 +- linden/indra/newview/featuretable_mac.txt | 16 +- linden/indra/newview/files.lst | 12 +- linden/indra/newview/gpu_table.txt | 16 +- .../help/Advanced/Advanced_Second_Life_Skills.html | 46 - .../help/Advanced/Building_the_Lamp_Base.html | 68 - .../help/Advanced/Building_the_Lamp_Bulb.html | 43 - .../help/Advanced/Building_the_Lamp_Pole.html | 43 - .../help/Advanced/Clothing_Makes_the_Avatar.html | 73 - .../indra/newview/help/Advanced/Creation_101.html | 53 - .../newview/help/Advanced/Dangerous_Time.html | 37 - .../newview/help/Advanced/Getting_Around.html | 29 - linden/indra/newview/help/Advanced/Graduation.html | 29 - linden/indra/newview/help/Advanced/Home_Time.html | 29 - .../newview/help/Advanced/Installing_a_Script.html | 73 - .../newview/help/Advanced/Modifying_a_Script.html | 74 - .../help/Advanced/More_Ways_to_Communicate.html | 55 - linden/indra/newview/help/Advanced/Nesting.html | 74 - linden/indra/newview/help/Advanced/Party_Time.html | 23 - linden/indra/newview/help/Advanced/People.html | 40 - .../help/Advanced/Personalize_Your_Home.html | 56 - .../help/Advanced/Positioning_with_Numbers.html | 28 - .../indra/newview/help/Advanced/Shopping_201.html | 47 - .../indra/newview/help/Advanced/Simple_on_off.html | 30 - .../newview/help/Advanced/The_Lay_of_the_Land.html | 44 - .../help/Advanced/The_Second_Life_Economy.html | 18 - .../newview/help/Concepts/3D_Terminology.html | 30 - .../newview/help/Concepts/Building_Tools.html | 22 - .../newview/help/Concepts/Building_in_3D.html | 15 - .../newview/help/Concepts/Different_Views.html | 16 - .../newview/help/Concepts/Getting_Around.html | 15 - linden/indra/newview/help/Concepts/Hours.html | 13 - linden/indra/newview/help/Concepts/Inventory.html | 17 - .../help/Concepts/Many_Ways_to_Get_Help.html | 20 - linden/indra/newview/help/Concepts/Money.html | 19 - .../indra/newview/help/Concepts/Other_People.html | 18 - .../help/Concepts/Ownership_and_Permissions.html | 17 - .../newview/help/Concepts/Reporting_Errors.html | 27 - linden/indra/newview/help/Concepts/Scripting.html | 15 - .../help/Concepts/Second_Life_Concepts.html | 33 - linden/indra/newview/help/Concepts/Strengths.html | 17 - .../indra/newview/help/Concepts/Things_to_do.html | 26 - .../newview/help/Concepts/Tips_For_Newbies.html | 30 - linden/indra/newview/help/Concepts/Updates.html | 17 - linden/indra/newview/help/Concepts/World.html | 20 - .../indra/newview/help/Concepts/Your_Avatar.html | 20 - linden/indra/newview/help/LL_logo.jpg | Bin 890 -> 0 bytes linden/indra/newview/help/MAIN.css | 553 --- linden/indra/newview/help/basics/basic_skills.html | 23 - linden/indra/newview/help/basics/camera.html | 50 - linden/indra/newview/help/basics/chat.html | 20 - .../indra/newview/help/basics/congratulations.html | 16 - .../indra/newview/help/basics/customization.html | 59 - linden/indra/newview/help/basics/economy.html | 17 - linden/indra/newview/help/basics/im.html | 47 - linden/indra/newview/help/basics/inventory.html | 49 - linden/indra/newview/help/basics/keyboard.html | 58 - linden/indra/newview/help/basics/landmarks.html | 43 - linden/indra/newview/help/basics/leading.html | 26 - linden/indra/newview/help/basics/mouse.html | 36 - linden/indra/newview/help/basics/movement.html | 17 - linden/indra/newview/help/basics/profile.html | 28 - linden/indra/newview/help/basics/shopping.html | 53 - linden/indra/newview/help/bg_dots_grey.gif | Bin 44 -> 0 bytes linden/indra/newview/help/community_standards.html | 52 - .../indra/newview/help/graphics_driver_update.html | 12 - linden/indra/newview/help/grey_corner_bl.gif | Bin 98 -> 0 bytes linden/indra/newview/help/grey_corner_br.gif | Bin 99 -> 0 bytes linden/indra/newview/help/grey_corner_tl.gif | Bin 99 -> 0 bytes linden/indra/newview/help/grey_corner_tr.gif | Bin 98 -> 0 bytes linden/indra/newview/help/grey_pixel.gif | Bin 43 -> 0 bytes linden/indra/newview/help/header_banner.jpg | Bin 12489 -> 0 bytes linden/indra/newview/help/index.html | 18 - linden/indra/newview/help/sl_logo.gif | Bin 2288 -> 0 bytes linden/indra/newview/help/spacer.gif | Bin 43 -> 0 bytes linden/indra/newview/help/unable_to_connect.html | 149 - linden/indra/newview/help/unsupported_card.html | 58 - linden/indra/newview/help/welcome/avatar.html | 20 - linden/indra/newview/help/welcome/buttons.html | 33 - linden/indra/newview/help/welcome/chat.html | 20 - linden/indra/newview/help/welcome/graduation.html | 14 - linden/indra/newview/help/welcome/map.html | 25 - linden/indra/newview/help/welcome/menus.html | 21 - linden/indra/newview/help/welcome/screen.html | 19 - linden/indra/newview/help/welcome/welcome.html | 31 - linden/indra/newview/help/welcome/welcomeback.html | 32 - .../indra/newview/help/window_creation_error.html | 73 - linden/indra/newview/installer.vcproj | 184 - .../newview/installers/darwin/mac_image_DS_Store | Bin 0 -> 12292 bytes .../installers/darwin/mac_image_background.tga | Bin 0 -> 589868 bytes .../newview/installers/darwin/mac_image_hidden | 1 + .../installers/windows/installer_template.nsi | 862 +++++ linden/indra/newview/licenses-linux.txt | 65 + linden/indra/newview/licenses-mac.txt | 32 + linden/indra/newview/licenses-win32.txt | 32 + .../indra/newview/linux_tools/client-manifest-i686 | 48 - linden/indra/newview/linux_tools/client-readme.txt | 30 +- linden/indra/newview/linux_tools/package-client.sh | 133 - linden/indra/newview/linux_tools/wrapper.sh | 7 +- linden/indra/newview/llagent.cpp | 127 +- linden/indra/newview/llagent.h | 5 +- linden/indra/newview/llagentpilot.cpp | 9 +- linden/indra/newview/llagparray.h | 215 -- linden/indra/newview/llagparray.inl | 519 --- linden/indra/newview/llassetuploadresponders.cpp | 537 ++- linden/indra/newview/llassetuploadresponders.h | 90 +- linden/indra/newview/llasynchostbyname.h | 2 +- linden/indra/newview/llcallingcard.cpp | 12 +- linden/indra/newview/llcallingcard.h | 12 +- linden/indra/newview/llcameraview.cpp | 10 +- linden/indra/newview/llchatbar.cpp | 2 - linden/indra/newview/llcloud.cpp | 27 +- linden/indra/newview/llcloud.h | 4 +- linden/indra/newview/llcolorswatch.h | 1 + linden/indra/newview/llcompilequeue.cpp | 58 +- linden/indra/newview/llconsole.cpp | 73 +- linden/indra/newview/llconsole.h | 18 +- linden/indra/newview/llcontroldef.cpp | 59 +- linden/indra/newview/llcubemap.cpp | 20 +- linden/indra/newview/llcubemap.h | 2 +- linden/indra/newview/llcurrencyuimanager.cpp | 16 +- linden/indra/newview/llcylinder.cpp | 108 +- linden/indra/newview/llcylinder.h | 23 +- linden/indra/newview/lldebugmessagebox.cpp | 10 +- linden/indra/newview/lldirpicker.cpp | 2 +- linden/indra/newview/lldirpicker.h | 2 +- linden/indra/newview/lldrawable.cpp | 633 ++-- linden/indra/newview/lldrawable.h | 36 +- linden/indra/newview/lldrawpool.cpp | 1295 ++----- linden/indra/newview/lldrawpool.h | 336 +- linden/indra/newview/lldrawpoolalpha.cpp | 661 +--- linden/indra/newview/lldrawpoolalpha.h | 58 +- linden/indra/newview/lldrawpoolavatar.cpp | 631 ++-- linden/indra/newview/lldrawpoolavatar.h | 33 +- linden/indra/newview/lldrawpoolbump.cpp | 662 ++-- linden/indra/newview/lldrawpoolbump.h | 62 +- linden/indra/newview/lldrawpoolclouds.cpp | 21 +- linden/indra/newview/lldrawpoolclouds.h | 10 + linden/indra/newview/lldrawpoolground.cpp | 35 +- linden/indra/newview/lldrawpoolground.h | 10 +- linden/indra/newview/lldrawpoolhud.cpp | 565 --- linden/indra/newview/lldrawpoolhud.h | 75 - linden/indra/newview/lldrawpoolsimple.cpp | 234 +- linden/indra/newview/lldrawpoolsimple.h | 56 +- linden/indra/newview/lldrawpoolsky.cpp | 32 +- linden/indra/newview/lldrawpoolsky.h | 14 +- linden/indra/newview/lldrawpoolstars.cpp | 31 +- linden/indra/newview/lldrawpoolstars.h | 10 +- linden/indra/newview/lldrawpoolterrain.cpp | 98 +- linden/indra/newview/lldrawpoolterrain.h | 16 +- linden/indra/newview/lldrawpooltree.cpp | 125 +- linden/indra/newview/lldrawpooltree.h | 12 +- linden/indra/newview/lldrawpooltreenew.cpp | 200 - linden/indra/newview/lldrawpooltreenew.h | 55 - linden/indra/newview/lldrawpoolwater.cpp | 114 +- linden/indra/newview/lldrawpoolwater.h | 14 +- linden/indra/newview/lldynamictexture.cpp | 45 +- linden/indra/newview/lldynamictexture.h | 1 + linden/indra/newview/lleventinfo.cpp | 4 +- linden/indra/newview/llface.cpp | 1478 +++----- linden/indra/newview/llface.h | 194 +- linden/indra/newview/llfasttimerview.cpp | 78 +- linden/indra/newview/llfasttimerview.h | 4 +- linden/indra/newview/llfeaturemanager.cpp | 343 +- linden/indra/newview/llfeaturemanager.h | 3 +- linden/indra/newview/llfilepicker.cpp | 84 +- linden/indra/newview/llfilepicker.h | 5 +- linden/indra/newview/llflexibleobject.cpp | 314 +- linden/indra/newview/llflexibleobject.h | 36 +- linden/indra/newview/llfloaterabout.cpp | 9 +- linden/indra/newview/llfloateraccounthistory.cpp | 224 -- linden/indra/newview/llfloateraccounthistory.h | 83 - linden/indra/newview/llfloateranimpreview.cpp | 22 +- linden/indra/newview/llfloaterauction.cpp | 13 +- linden/indra/newview/llfloaterauction.h | 2 + linden/indra/newview/llfloateravatarinfo.cpp | 26 +- linden/indra/newview/llfloateravatarinfo.h | 2 - linden/indra/newview/llfloateravatarpicker.cpp | 8 +- linden/indra/newview/llfloateravatartextures.cpp | 10 +- linden/indra/newview/llfloaterbuildoptions.cpp | 4 +- linden/indra/newview/llfloaterbump.cpp | 2 +- linden/indra/newview/llfloaterbuy.cpp | 13 +- linden/indra/newview/llfloaterbuy.h | 2 + linden/indra/newview/llfloaterbuycontents.cpp | 15 +- linden/indra/newview/llfloaterbuycontents.h | 2 + linden/indra/newview/llfloaterbuycurrency.cpp | 2 +- linden/indra/newview/llfloaterbuyland.cpp | 96 +- linden/indra/newview/llfloaterbuyland.h | 4 +- linden/indra/newview/llfloaterchat.cpp | 2 +- linden/indra/newview/llfloatercolorpicker.cpp | 6 +- linden/indra/newview/llfloatercustomize.cpp | 2 + linden/indra/newview/llfloaterdirectory.cpp | 6 +- linden/indra/newview/llfloatereditui.cpp | 2 +- linden/indra/newview/llfloaterfriends.cpp | 23 +- linden/indra/newview/llfloatergesture.cpp | 4 +- linden/indra/newview/llfloatergodtools.cpp | 12 +- linden/indra/newview/llfloatergroupinfo.cpp | 2 +- linden/indra/newview/llfloatergroupinvite.cpp | 2 +- linden/indra/newview/llfloatergroups.cpp | 4 +- linden/indra/newview/llfloaterimagepreview.cpp | 17 +- linden/indra/newview/llfloaterimport.cpp | 23 +- linden/indra/newview/llfloaterinspect.cpp | 442 +-- linden/indra/newview/llfloaterinspect.h | 97 +- linden/indra/newview/llfloaterland.cpp | 360 +- linden/indra/newview/llfloaterland.h | 40 +- linden/indra/newview/llfloaterlandholdings.cpp | 30 +- linden/indra/newview/llfloatermap.cpp | 2 +- linden/indra/newview/llfloatermute.cpp | 2 +- linden/indra/newview/llfloaternamedesc.cpp | 2 +- linden/indra/newview/llfloaternewim.cpp | 5 +- linden/indra/newview/llfloateropenobject.cpp | 19 +- linden/indra/newview/llfloateropenobject.h | 7 +- linden/indra/newview/llfloaterpermissionsmgr.cpp | 4 +- linden/indra/newview/llfloaterpostcard.cpp | 48 +- linden/indra/newview/llfloaterpreference.cpp | 2 +- linden/indra/newview/llfloaterproperties.cpp | 30 +- linden/indra/newview/llfloaterrate.cpp | 14 +- linden/indra/newview/llfloaterrate.h | 2 + linden/indra/newview/llfloaterregioninfo.cpp | 141 +- linden/indra/newview/llfloaterreporter.cpp | 438 ++- linden/indra/newview/llfloaterreporter.h | 12 +- linden/indra/newview/llfloatersaveavatar.cpp | 2 +- linden/indra/newview/llfloaterscriptdebug.cpp | 4 +- linden/indra/newview/llfloatersellland.cpp | 104 +- linden/indra/newview/llfloatersellland.h | 4 +- linden/indra/newview/llfloatersnapshot.cpp | 27 +- linden/indra/newview/llfloatertelehub.cpp | 16 +- linden/indra/newview/llfloatertelehub.h | 3 + linden/indra/newview/llfloatertest.cpp | 2 +- linden/indra/newview/llfloatertools.cpp | 30 +- linden/indra/newview/llfloatertools.h | 11 +- linden/indra/newview/llfloatertopobjects.cpp | 6 +- linden/indra/newview/llfloatertos.cpp | 38 +- linden/indra/newview/llfloaterworldmap.cpp | 10 +- linden/indra/newview/llfloaterworldmap.h | 12 +- linden/indra/newview/llfolderview.cpp | 92 +- linden/indra/newview/llfolderview.h | 19 +- linden/indra/newview/llframestats.cpp | 16 +- linden/indra/newview/llframestatview.cpp | 8 +- linden/indra/newview/llframestatview.h | 2 +- linden/indra/newview/llgenepool.cpp | 6 +- linden/indra/newview/llgesturemgr.cpp | 8 +- linden/indra/newview/llgivemoney.cpp | 27 +- linden/indra/newview/llgivemoney.h | 4 + linden/indra/newview/llglsandbox.cpp | 142 +- linden/indra/newview/llgroupmgr.cpp | 24 +- linden/indra/newview/llgroupnotify.cpp | 7 +- linden/indra/newview/llhoverview.cpp | 20 +- linden/indra/newview/llhoverview.h | 1 - linden/indra/newview/llhudeffecttrail.cpp | 20 +- linden/indra/newview/llhudicon.cpp | 1 + linden/indra/newview/llhudobject.cpp | 2 +- linden/indra/newview/llimpanel.cpp | 9 +- linden/indra/newview/llimpanel.h | 2 +- linden/indra/newview/llimview.cpp | 6 +- linden/indra/newview/llimview.h | 2 +- linden/indra/newview/llinventoryactions.cpp | 36 +- linden/indra/newview/llinventorybridge.cpp | 34 +- linden/indra/newview/llinventorymodel.cpp | 68 +- linden/indra/newview/llinventoryview.cpp | 57 +- linden/indra/newview/llinventoryview.h | 29 +- linden/indra/newview/lljoystickbutton.h | 1 + linden/indra/newview/lllandmarklist.cpp | 2 +- linden/indra/newview/lllogchat.cpp | 19 +- linden/indra/newview/llmanip.cpp | 71 +- linden/indra/newview/llmanip.h | 12 +- linden/indra/newview/llmaniprotate.cpp | 128 +- linden/indra/newview/llmanipscale.cpp | 112 +- linden/indra/newview/llmanipscale.h | 2 +- linden/indra/newview/llmaniptranslate.cpp | 240 +- linden/indra/newview/llmaniptranslate.h | 4 + linden/indra/newview/llmapresponders.cpp | 161 +- linden/indra/newview/llmemoryview.cpp | 2 + linden/indra/newview/llmorphview.cpp | 2 +- linden/indra/newview/llmoveview.cpp | 4 +- linden/indra/newview/llmutelist.cpp | 47 +- linden/indra/newview/llnamebox.cpp | 6 +- linden/indra/newview/llnameeditor.cpp | 6 +- linden/indra/newview/llnamelistctrl.cpp | 16 +- linden/indra/newview/llnetmap.cpp | 4 +- linden/indra/newview/llnotify.cpp | 16 +- linden/indra/newview/llpanelavatar.cpp | 352 +- linden/indra/newview/llpanelavatar.h | 101 +- linden/indra/newview/llpanelclassified.cpp | 23 +- linden/indra/newview/llpanelcontents.cpp | 14 +- linden/indra/newview/llpaneldirbrowser.cpp | 40 +- linden/indra/newview/llpaneldirevents.cpp | 4 +- linden/indra/newview/llpaneldisplay.cpp | 51 +- linden/indra/newview/llpaneldisplay.h | 10 +- linden/indra/newview/llpanelevent.cpp | 12 +- linden/indra/newview/llpanelface.cpp | 21 +- linden/indra/newview/llpanelgroup.cpp | 2 +- linden/indra/newview/llpanelgroupgeneral.cpp | 6 +- linden/indra/newview/llpanelgrouplandmoney.cpp | 84 +- linden/indra/newview/llpanelgroupnotices.cpp | 15 +- linden/indra/newview/llpanelgrouproles.cpp | 14 +- linden/indra/newview/llpanelgroupvoting.cpp | 48 +- linden/indra/newview/llpanelinventory.cpp | 14 +- linden/indra/newview/llpanelland.cpp | 8 +- linden/indra/newview/llpanellogin.cpp | 7 +- linden/indra/newview/llpanellogin.h | 4 +- linden/indra/newview/llpanelmoney.cpp | 483 --- linden/indra/newview/llpanelmoney.h | 106 - linden/indra/newview/llpanelnetwork.cpp | 93 +- linden/indra/newview/llpanelnetwork.h | 9 +- linden/indra/newview/llpanelobject.cpp | 12 +- linden/indra/newview/llpanelpermissions.cpp | 57 +- linden/indra/newview/llpanelpick.cpp | 19 +- linden/indra/newview/llpanelplace.cpp | 20 +- linden/indra/newview/llpanelvolume.cpp | 6 +- linden/indra/newview/llpolymesh.cpp | 43 +- linden/indra/newview/llpolymesh.h | 1 + linden/indra/newview/llpolymorph.cpp | 4 +- linden/indra/newview/llpreview.cpp | 36 +- linden/indra/newview/llpreview.h | 13 +- linden/indra/newview/llpreviewgesture.cpp | 42 +- linden/indra/newview/llpreviewnotecard.cpp | 81 +- linden/indra/newview/llpreviewnotecard.h | 8 + linden/indra/newview/llpreviewscript.cpp | 539 +-- linden/indra/newview/llpreviewscript.h | 34 +- linden/indra/newview/llpreviewsound.cpp | 1 + linden/indra/newview/llpreviewtexture.cpp | 166 +- linden/indra/newview/llprogressview.cpp | 8 +- linden/indra/newview/llselectmgr.cpp | 1777 ++++----- linden/indra/newview/llselectmgr.h | 261 +- linden/indra/newview/llsky.cpp | 10 +- linden/indra/newview/llspatialpartition.cpp | 1899 ++++++---- linden/indra/newview/llspatialpartition.h | 327 +- linden/indra/newview/llsphere.cpp | 4 +- linden/indra/newview/llsprite.cpp | 42 +- linden/indra/newview/llstartup.cpp | 165 +- linden/indra/newview/llstartup.h | 4 + linden/indra/newview/llstatbar.cpp | 18 +- linden/indra/newview/llstatgraph.cpp | 8 +- linden/indra/newview/llstatusbar.cpp | 19 +- linden/indra/newview/llstatview.cpp | 4 +- linden/indra/newview/llsurface.cpp | 46 +- linden/indra/newview/llsurface.h | 5 +- linden/indra/newview/llsurfacepatch.cpp | 2 +- linden/indra/newview/lltexlayer.cpp | 263 +- linden/indra/newview/lltexlayer.h | 6 - linden/indra/newview/lltexturebar.cpp | 412 -- linden/indra/newview/lltexturebar.h | 75 - linden/indra/newview/lltexturecache.cpp | 1409 +++++++ linden/indra/newview/lltexturecache.h | 175 + linden/indra/newview/lltexturectrl.cpp | 127 +- linden/indra/newview/lltexturefetch.cpp | 2153 ++++++++--- linden/indra/newview/lltexturefetch.h | 73 +- linden/indra/newview/lltextureview.cpp | 636 +++- linden/indra/newview/lltextureview.h | 13 +- linden/indra/newview/lltool.cpp | 9 + linden/indra/newview/lltool.h | 2 + linden/indra/newview/lltoolbrush.cpp | 8 +- linden/indra/newview/lltoolcomp.cpp | 57 +- linden/indra/newview/lltoolcomp.h | 7 +- linden/indra/newview/lltooldraganddrop.cpp | 37 +- linden/indra/newview/lltoolface.cpp | 4 +- linden/indra/newview/lltoolfocus.cpp | 18 +- linden/indra/newview/lltoolfocus.h | 2 + linden/indra/newview/lltoolgrab.cpp | 2 +- linden/indra/newview/lltoolgrab.h | 2 +- linden/indra/newview/lltoolgun.cpp | 2 +- linden/indra/newview/lltoolgun.h | 1 + linden/indra/newview/lltoolindividual.cpp | 6 +- linden/indra/newview/lltoolmgr.cpp | 208 +- linden/indra/newview/lltoolmgr.h | 13 +- linden/indra/newview/lltoolmorph.cpp | 5 +- linden/indra/newview/lltoolpie.cpp | 41 +- linden/indra/newview/lltoolpie.h | 3 + linden/indra/newview/lltoolplacer.cpp | 3 +- linden/indra/newview/lltoolplacer.h | 1 - linden/indra/newview/lltoolselect.cpp | 9 +- linden/indra/newview/lltoolselect.h | 4 +- linden/indra/newview/lltoolselectland.cpp | 7 +- linden/indra/newview/lltoolselectland.h | 4 + linden/indra/newview/lltoolview.cpp | 5 +- linden/indra/newview/lltracker.cpp | 6 +- linden/indra/newview/lluploaddialog.cpp | 7 +- linden/indra/newview/llurl.cpp | 75 +- linden/indra/newview/llurl.h | 14 +- linden/indra/newview/llurlwhitelist.cpp | 24 +- linden/indra/newview/llurlwhitelist.h | 7 +- linden/indra/newview/lluserauth.cpp | 18 +- linden/indra/newview/llvelocitybar.cpp | 4 +- linden/indra/newview/llviewerassetstorage.cpp | 9 +- linden/indra/newview/llviewercamera.cpp | 68 +- linden/indra/newview/llviewercamera.h | 2 +- linden/indra/newview/llviewercontrol.cpp | 20 +- linden/indra/newview/llviewercontrol.h | 2 + linden/indra/newview/llviewerdisplay.cpp | 245 +- linden/indra/newview/llviewergesture.cpp | 12 +- linden/indra/newview/llviewerimage.cpp | 1593 ++------ linden/indra/newview/llviewerimage.h | 132 +- linden/indra/newview/llviewerimagelist.cpp | 1224 +++--- linden/indra/newview/llviewerimagelist.h | 41 +- linden/indra/newview/llviewerinventory.cpp | 22 +- linden/indra/newview/llviewerjoint.cpp | 150 +- linden/indra/newview/llviewerjoint.h | 12 +- linden/indra/newview/llviewerjointattachment.cpp | 39 +- linden/indra/newview/llviewerjointattachment.h | 4 +- linden/indra/newview/llviewerjointmesh.cpp | 824 +--- linden/indra/newview/llviewerjointmesh.h | 5 +- linden/indra/newview/llviewerjointshape.cpp | 2 +- linden/indra/newview/llviewerjointshape.h | 2 +- linden/indra/newview/llviewerkeyboard.cpp | 25 +- linden/indra/newview/llviewermenu.cpp | 1078 +++--- linden/indra/newview/llviewermenu.h | 15 +- linden/indra/newview/llviewermessage.cpp | 233 +- linden/indra/newview/llviewernetwork.cpp | 8 +- linden/indra/newview/llviewernetwork.h | 5 +- linden/indra/newview/llviewerobject.cpp | 262 +- linden/indra/newview/llviewerobject.h | 51 +- linden/indra/newview/llviewerobjectlist.cpp | 77 +- linden/indra/newview/llviewerobjectlist.h | 1 + linden/indra/newview/llviewerparcelmgr.cpp | 400 +- linden/indra/newview/llviewerparcelmgr.h | 147 +- linden/indra/newview/llviewerparceloverlay.cpp | 23 +- linden/indra/newview/llviewerpartsim.cpp | 305 +- linden/indra/newview/llviewerpartsim.h | 34 +- linden/indra/newview/llviewerpartsource.cpp | 180 +- linden/indra/newview/llviewerpartsource.h | 9 +- linden/indra/newview/llviewerprecompiledheaders.h | 3 - linden/indra/newview/llviewerregion.cpp | 69 +- linden/indra/newview/llviewerregion.h | 5 +- linden/indra/newview/llviewerreputation.cpp | 2 +- linden/indra/newview/llviewerstats.cpp | 8 +- linden/indra/newview/llviewerstats.h | 2 +- linden/indra/newview/llviewertexteditor.cpp | 20 +- linden/indra/newview/llviewertexteditor.h | 9 +- linden/indra/newview/llviewertextureanim.cpp | 25 +- linden/indra/newview/llviewertextureanim.h | 7 + linden/indra/newview/llviewerthrottle.h | 2 +- linden/indra/newview/llviewerwindow.cpp | 337 +- linden/indra/newview/llviewerwindow.h | 16 +- linden/indra/newview/llvoavatar.cpp | 760 ++-- linden/indra/newview/llvoavatar.h | 52 +- linden/indra/newview/llvoclouds.cpp | 177 +- linden/indra/newview/llvoclouds.h | 17 +- linden/indra/newview/llvograss.cpp | 211 +- linden/indra/newview/llvograss.h | 16 +- linden/indra/newview/llvoground.cpp | 84 +- linden/indra/newview/llvoground.h | 2 +- linden/indra/newview/llvopart.cpp | 1358 ------- linden/indra/newview/llvopart.h | 281 -- linden/indra/newview/llvopartgroup.cpp | 404 +- linden/indra/newview/llvopartgroup.h | 28 +- linden/indra/newview/llvosky.cpp | 186 +- linden/indra/newview/llvosky.h | 9 +- linden/indra/newview/llvostars.cpp | 22 +- linden/indra/newview/llvostars.h | 2 +- linden/indra/newview/llvosurfacepatch.cpp | 280 +- linden/indra/newview/llvosurfacepatch.h | 38 +- linden/indra/newview/llvotextbubble.cpp | 80 +- linden/indra/newview/llvotextbubble.h | 12 +- linden/indra/newview/llvotree.cpp | 106 +- linden/indra/newview/llvotree.h | 13 +- linden/indra/newview/llvotreenew.cpp | 1470 -------- linden/indra/newview/llvovolume.cpp | 1662 +++++--- linden/indra/newview/llvovolume.h | 46 +- linden/indra/newview/llvowater.cpp | 830 +--- linden/indra/newview/llvowater.h | 199 +- linden/indra/newview/llwearable.cpp | 86 +- linden/indra/newview/llwearablelist.cpp | 2 +- linden/indra/newview/llwebbrowserctrl.cpp | 172 +- linden/indra/newview/llwebbrowserctrl.h | 8 + linden/indra/newview/llworld.cpp | 27 +- linden/indra/newview/llworld.h | 3 +- linden/indra/newview/llworldmap.cpp | 21 +- linden/indra/newview/llworldmapview.cpp | 57 +- linden/indra/newview/llworldmapview.h | 7 +- linden/indra/newview/llxmlrpctransaction.cpp | 16 +- linden/indra/newview/lsl_guide.html | 1417 +++---- .../newview/macview.xcodeproj/project.pbxproj | 222 +- linden/indra/newview/macview_Prefix.h | 4 +- linden/indra/newview/moviemaker.cpp | 9 +- linden/indra/newview/moviemaker.h | 2 +- linden/indra/newview/newview.vcproj | 56 +- linden/indra/newview/newview_vc8.vcproj | 3957 ++++++++++++++++++++ linden/indra/newview/pipeline.cpp | 3727 ++++++++---------- linden/indra/newview/pipeline.h | 241 +- linden/indra/newview/releasenotes.txt | 681 +--- linden/indra/newview/res/newViewRes.rc | 10 +- linden/indra/newview/restore_login_page.bat | 22 - linden/indra/newview/rsyncfiles.txt | 22 - .../indra/newview/secondlife setup build aditi.bat | 5 +- .../indra/newview/secondlife setup build agni.bat | 9 +- .../indra/newview/secondlife setup build dmz.bat | 5 +- .../indra/newview/secondlife setup build durga.bat | 5 +- .../newview/secondlife setup build firstlook.bat | 9 +- .../indra/newview/secondlife setup build ganga.bat | 5 +- .../newview/secondlife setup build museum.bat | 7 - .../newview/secondlife setup build shakti.bat | 5 +- .../indra/newview/secondlife setup build siva.bat | 5 +- .../indra/newview/secondlife setup build soma.bat | 5 +- linden/indra/newview/secondlife setup build.bat | 58 +- linden/indra/newview/set_login_page.bat | 45 - linden/indra/newview/skins/textures/textures.xml | 391 ++ .../skins/xui/de/floater_account_history.xml | 4 - .../newview/skins/xui/de/panel_account_details.xml | 7 - .../skins/xui/de/panel_account_planning.xml | 2 - .../skins/xui/de/panel_account_transactions.xml | 7 - linden/indra/newview/skins/xui/en-us/alerts.xml | 109 +- .../newview/skins/xui/en-us/floater_about.xml | 6 +- .../skins/xui/en-us/floater_account_history.xml | 10 - .../skins/xui/en-us/floater_build_options.xml | 6 +- .../skins/xui/en-us/floater_instant_message.xml | 6 +- .../en-us/floater_preview_existing_landmark.xml | 9 +- .../xui/en-us/floater_preview_new_landmark.xml | 2 +- .../skins/xui/en-us/floater_price_for_listing.xml | 4 +- .../skins/xui/en-us/floater_settings_debug.xml | 5 +- .../newview/skins/xui/en-us/menu_inventory.xml | 8 +- .../indra/newview/skins/xui/en-us/menu_viewer.xml | 13 +- .../skins/xui/en-us/panel_account_details.xml | 17 - .../skins/xui/en-us/panel_account_planning.xml | 9 - .../skins/xui/en-us/panel_account_transactions.xml | 17 - .../indra/newview/skins/xui/en-us/panel_avatar.xml | 21 +- .../indra/newview/skins/xui/en-us/panel_group.xml | 4 +- .../skins/xui/en-us/panel_group_notices.xml | 14 +- .../newview/skins/xui/en-us/panel_group_roles.xml | 6 +- .../indra/newview/skins/xui/en-us/panel_login.xml | 2 +- .../xui/en-us/panel_preferences_graphics3.xml | 14 +- .../skins/xui/en-us/panel_preferences_network.xml | 68 +- .../newview/skins/xui/en-us/panel_status_bar.xml | 6 +- .../indra/newview/skins/xui/en-us/role_actions.xml | 2 +- .../skins/xui/es/floater_account_history.xml | 4 - .../newview/skins/xui/es/panel_account_details.xml | 7 - .../skins/xui/es/panel_account_planning.xml | 2 - .../skins/xui/es/panel_account_transactions.xml | 7 - .../skins/xui/fr/floater_account_history.xml | 5 - .../newview/skins/xui/fr/panel_account_details.xml | 7 - .../skins/xui/fr/panel_account_planning.xml | 2 - .../skins/xui/fr/panel_account_transactions.xml | 7 - .../skins/xui/ja/floater_account_history.xml | 5 - .../newview/skins/xui/ja/panel_account_details.xml | 7 - .../skins/xui/ja/panel_account_planning.xml | 2 - .../skins/xui/ja/panel_account_transactions.xml | 7 - .../skins/xui/ko/floater_account_history.xml | 5 - .../newview/skins/xui/ko/panel_account_details.xml | 7 - .../skins/xui/ko/panel_account_planning.xml | 2 - .../skins/xui/ko/panel_account_transactions.xml | 7 - .../skins/xui/pt/floater_account_history.xml | 4 - .../newview/skins/xui/pt/panel_account_details.xml | 7 - .../skins/xui/pt/panel_account_planning.xml | 2 - .../skins/xui/pt/panel_account_transactions.xml | 7 - .../skins/xui/zh/floater_account_history.xml | 4 - .../newview/skins/xui/zh/floater_god_tools.xml | 152 - .../skins/xui/zh/floater_inventory_view_finder.xml | 24 - .../newview/skins/xui/zh/floater_preferences.xml | 7 - linden/indra/newview/skins/xui/zh/floater_rate.xml | 44 - .../newview/skins/xui/zh/floater_sell_land.xml | 68 - .../skins/xui/zh/floater_settings_debug.xml | 15 - .../newview/skins/xui/zh/menu_pie_attachment.xml | 6 - .../indra/newview/skins/xui/zh/menu_pie_avatar.xml | 16 - .../indra/newview/skins/xui/zh/menu_pie_land.xml | 10 - .../indra/newview/skins/xui/zh/menu_pie_object.xml | 25 - .../indra/newview/skins/xui/zh/menu_pie_self.xml | 29 - linden/indra/newview/skins/xui/zh/menu_viewer.xml | 234 -- .../newview/skins/xui/zh/panel_account_details.xml | 7 - .../skins/xui/zh/panel_account_planning.xml | 2 - .../skins/xui/zh/panel_account_transactions.xml | 7 - linden/indra/newview/skins/xui/zh/panel_avatar.xml | 195 - linden/indra/newview/skins/xui/zh/panel_group.xml | 14 - .../newview/skins/xui/zh/panel_group_finder.xml | 9 - .../newview/skins/xui/zh/panel_group_general.xml | 74 - .../newview/skins/xui/zh/panel_group_invite.xml | 18 - .../skins/xui/zh/panel_group_land_money.xml | 82 - .../newview/skins/xui/zh/panel_group_notices.xml | 68 - .../newview/skins/xui/zh/panel_group_roles.xml | 153 - .../newview/skins/xui/zh/panel_group_voting.xml | 79 - .../newview/skins/xui/zh/panel_land_covenant.xml | 39 - .../skins/xui/zh/panel_preferences_audio.xml | 59 - .../skins/xui/zh/panel_preferences_chat.xml | 54 - .../newview/skins/xui/zh/panel_preferences_im.xml | 19 - .../skins/xui/zh/panel_preferences_popups.xml | 14 - .../newview/skins/xui/zh/panel_region_covenant.xml | 50 - .../newview/skins/xui/zh/panel_scrolling_param.xml | 12 - linden/indra/newview/skins/xui/zh/role_actions.xml | 187 - linden/indra/newview/skins/xui/zh/xui_version.xml | 4 - linden/indra/newview/viewer.cpp | 825 ++-- linden/indra/newview/viewer.h | 11 +- linden/indra/newview/viewer_manifest.py | 450 +++ 597 files changed, 29529 insertions(+), 35116 deletions(-) create mode 100644 linden/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/environment/groundF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/environment/groundV.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/environment/scatterF.glsl delete mode 100644 linden/indra/newview/app_settings/shaders/class3/environment/scatterV.glsl create mode 100644 linden/indra/newview/app_settings/shaders/class3/environment/waterF.glsl delete mode 100644 linden/indra/newview/app_settings/viewerart.ini delete mode 100644 linden/indra/newview/help/Advanced/Advanced_Second_Life_Skills.html delete mode 100644 linden/indra/newview/help/Advanced/Building_the_Lamp_Base.html delete mode 100644 linden/indra/newview/help/Advanced/Building_the_Lamp_Bulb.html delete mode 100644 linden/indra/newview/help/Advanced/Building_the_Lamp_Pole.html delete mode 100644 linden/indra/newview/help/Advanced/Clothing_Makes_the_Avatar.html delete mode 100644 linden/indra/newview/help/Advanced/Creation_101.html delete mode 100644 linden/indra/newview/help/Advanced/Dangerous_Time.html delete mode 100644 linden/indra/newview/help/Advanced/Getting_Around.html delete mode 100644 linden/indra/newview/help/Advanced/Graduation.html delete mode 100644 linden/indra/newview/help/Advanced/Home_Time.html delete mode 100644 linden/indra/newview/help/Advanced/Installing_a_Script.html delete mode 100644 linden/indra/newview/help/Advanced/Modifying_a_Script.html delete mode 100644 linden/indra/newview/help/Advanced/More_Ways_to_Communicate.html delete mode 100644 linden/indra/newview/help/Advanced/Nesting.html delete mode 100644 linden/indra/newview/help/Advanced/Party_Time.html delete mode 100644 linden/indra/newview/help/Advanced/People.html delete mode 100644 linden/indra/newview/help/Advanced/Personalize_Your_Home.html delete mode 100644 linden/indra/newview/help/Advanced/Positioning_with_Numbers.html delete mode 100644 linden/indra/newview/help/Advanced/Shopping_201.html delete mode 100644 linden/indra/newview/help/Advanced/Simple_on_off.html delete mode 100644 linden/indra/newview/help/Advanced/The_Lay_of_the_Land.html delete mode 100644 linden/indra/newview/help/Advanced/The_Second_Life_Economy.html delete mode 100644 linden/indra/newview/help/Concepts/3D_Terminology.html delete mode 100644 linden/indra/newview/help/Concepts/Building_Tools.html delete mode 100644 linden/indra/newview/help/Concepts/Building_in_3D.html delete mode 100644 linden/indra/newview/help/Concepts/Different_Views.html delete mode 100644 linden/indra/newview/help/Concepts/Getting_Around.html delete mode 100644 linden/indra/newview/help/Concepts/Hours.html delete mode 100644 linden/indra/newview/help/Concepts/Inventory.html delete mode 100644 linden/indra/newview/help/Concepts/Many_Ways_to_Get_Help.html delete mode 100644 linden/indra/newview/help/Concepts/Money.html delete mode 100644 linden/indra/newview/help/Concepts/Other_People.html delete mode 100644 linden/indra/newview/help/Concepts/Ownership_and_Permissions.html delete mode 100644 linden/indra/newview/help/Concepts/Reporting_Errors.html delete mode 100644 linden/indra/newview/help/Concepts/Scripting.html delete mode 100644 linden/indra/newview/help/Concepts/Second_Life_Concepts.html delete mode 100644 linden/indra/newview/help/Concepts/Strengths.html delete mode 100644 linden/indra/newview/help/Concepts/Things_to_do.html delete mode 100644 linden/indra/newview/help/Concepts/Tips_For_Newbies.html delete mode 100644 linden/indra/newview/help/Concepts/Updates.html delete mode 100644 linden/indra/newview/help/Concepts/World.html delete mode 100644 linden/indra/newview/help/Concepts/Your_Avatar.html delete mode 100644 linden/indra/newview/help/LL_logo.jpg delete mode 100644 linden/indra/newview/help/MAIN.css delete mode 100644 linden/indra/newview/help/basics/basic_skills.html delete mode 100644 linden/indra/newview/help/basics/camera.html delete mode 100644 linden/indra/newview/help/basics/chat.html delete mode 100644 linden/indra/newview/help/basics/congratulations.html delete mode 100644 linden/indra/newview/help/basics/customization.html delete mode 100644 linden/indra/newview/help/basics/economy.html delete mode 100644 linden/indra/newview/help/basics/im.html delete mode 100644 linden/indra/newview/help/basics/inventory.html delete mode 100644 linden/indra/newview/help/basics/keyboard.html delete mode 100644 linden/indra/newview/help/basics/landmarks.html delete mode 100644 linden/indra/newview/help/basics/leading.html delete mode 100644 linden/indra/newview/help/basics/mouse.html delete mode 100644 linden/indra/newview/help/basics/movement.html delete mode 100644 linden/indra/newview/help/basics/profile.html delete mode 100644 linden/indra/newview/help/basics/shopping.html delete mode 100644 linden/indra/newview/help/bg_dots_grey.gif delete mode 100644 linden/indra/newview/help/community_standards.html delete mode 100644 linden/indra/newview/help/graphics_driver_update.html delete mode 100644 linden/indra/newview/help/grey_corner_bl.gif delete mode 100644 linden/indra/newview/help/grey_corner_br.gif delete mode 100644 linden/indra/newview/help/grey_corner_tl.gif delete mode 100644 linden/indra/newview/help/grey_corner_tr.gif delete mode 100644 linden/indra/newview/help/grey_pixel.gif delete mode 100644 linden/indra/newview/help/header_banner.jpg delete mode 100644 linden/indra/newview/help/index.html delete mode 100644 linden/indra/newview/help/sl_logo.gif delete mode 100644 linden/indra/newview/help/spacer.gif delete mode 100644 linden/indra/newview/help/unable_to_connect.html delete mode 100644 linden/indra/newview/help/unsupported_card.html delete mode 100644 linden/indra/newview/help/welcome/avatar.html delete mode 100644 linden/indra/newview/help/welcome/buttons.html delete mode 100644 linden/indra/newview/help/welcome/chat.html delete mode 100644 linden/indra/newview/help/welcome/graduation.html delete mode 100644 linden/indra/newview/help/welcome/map.html delete mode 100644 linden/indra/newview/help/welcome/menus.html delete mode 100644 linden/indra/newview/help/welcome/screen.html delete mode 100644 linden/indra/newview/help/welcome/welcome.html delete mode 100644 linden/indra/newview/help/welcome/welcomeback.html delete mode 100644 linden/indra/newview/help/window_creation_error.html delete mode 100644 linden/indra/newview/installer.vcproj create mode 100644 linden/indra/newview/installers/darwin/mac_image_DS_Store create mode 100644 linden/indra/newview/installers/darwin/mac_image_background.tga create mode 100644 linden/indra/newview/installers/darwin/mac_image_hidden create mode 100644 linden/indra/newview/installers/windows/installer_template.nsi delete mode 100644 linden/indra/newview/linux_tools/client-manifest-i686 delete mode 100755 linden/indra/newview/linux_tools/package-client.sh delete mode 100644 linden/indra/newview/llagparray.h delete mode 100644 linden/indra/newview/llagparray.inl delete mode 100644 linden/indra/newview/lldrawpoolhud.cpp delete mode 100644 linden/indra/newview/lldrawpoolhud.h delete mode 100644 linden/indra/newview/lldrawpooltreenew.cpp delete mode 100644 linden/indra/newview/lldrawpooltreenew.h delete mode 100644 linden/indra/newview/llfloateraccounthistory.cpp delete mode 100644 linden/indra/newview/llfloateraccounthistory.h delete mode 100644 linden/indra/newview/llpanelmoney.cpp delete mode 100644 linden/indra/newview/llpanelmoney.h delete mode 100644 linden/indra/newview/lltexturebar.cpp delete mode 100644 linden/indra/newview/lltexturebar.h create mode 100644 linden/indra/newview/lltexturecache.cpp create mode 100644 linden/indra/newview/lltexturecache.h delete mode 100644 linden/indra/newview/llvopart.cpp delete mode 100644 linden/indra/newview/llvopart.h delete mode 100644 linden/indra/newview/llvotreenew.cpp create mode 100644 linden/indra/newview/newview_vc8.vcproj delete mode 100644 linden/indra/newview/restore_login_page.bat delete mode 100644 linden/indra/newview/rsyncfiles.txt delete mode 100644 linden/indra/newview/secondlife setup build museum.bat delete mode 100644 linden/indra/newview/set_login_page.bat create mode 100644 linden/indra/newview/skins/textures/textures.xml delete mode 100644 linden/indra/newview/skins/xui/de/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/de/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/de/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/de/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/en-us/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/en-us/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/en-us/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/en-us/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/es/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/es/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/es/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/es/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/fr/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/fr/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/fr/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/fr/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/ja/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/ja/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/ja/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/ja/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/ko/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/ko/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/ko/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/ko/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/pt/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/pt/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/pt/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/pt/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_account_history.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_god_tools.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_inventory_view_finder.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_preferences.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_rate.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_sell_land.xml delete mode 100644 linden/indra/newview/skins/xui/zh/floater_settings_debug.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_pie_attachment.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_pie_avatar.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_pie_land.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_pie_object.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_pie_self.xml delete mode 100644 linden/indra/newview/skins/xui/zh/menu_viewer.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_account_details.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_account_planning.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_account_transactions.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_avatar.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_finder.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_general.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_invite.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_land_money.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_notices.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_roles.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_group_voting.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_land_covenant.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_preferences_audio.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_preferences_chat.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_preferences_im.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_preferences_popups.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_region_covenant.xml delete mode 100644 linden/indra/newview/skins/xui/zh/panel_scrolling_param.xml delete mode 100644 linden/indra/newview/skins/xui/zh/role_actions.xml delete mode 100644 linden/indra/newview/skins/xui/zh/xui_version.xml create mode 100755 linden/indra/newview/viewer_manifest.py (limited to 'linden/indra/newview') diff --git a/linden/indra/newview/English.lproj/InfoPlist.strings b/linden/indra/newview/English.lproj/InfoPlist.strings index 6ef64e4..6efc60a 100644 --- a/linden/indra/newview/English.lproj/InfoPlist.strings +++ b/linden/indra/newview/English.lproj/InfoPlist.strings @@ -1,5 +1,5 @@ /* Localized versions of Info.plist keys */ CFBundleName = "Second Life"; -CFBundleShortVersionString = "Second Life version 1.13.3.2"; -CFBundleGetInfoString = "Second Life version 1.13.3.2, Copyright 2004-2006 Linden Research, Inc."; +CFBundleShortVersionString = "Second Life version 1.14.0.0"; +CFBundleGetInfoString = "Second Life version 1.14.0.0, Copyright 2004-2007 Linden Research, Inc."; diff --git a/linden/indra/newview/Info-SecondLife.plist b/linden/indra/newview/Info-SecondLife.plist index 6e1de8b..fbfd040 100644 --- a/linden/indra/newview/Info-SecondLife.plist +++ b/linden/indra/newview/Info-SecondLife.plist @@ -32,7 +32,7 @@ CFBundleVersion - 1.13.3.2 + 1.14.0.0 CSResourcesFileMapped diff --git a/linden/indra/newview/app_settings/keywords.ini b/linden/indra/newview/app_settings/keywords.ini index 0545c38..bf49c2c 100644 --- a/linden/indra/newview/app_settings/keywords.ini +++ b/linden/indra/newview/app_settings/keywords.ini @@ -468,6 +468,10 @@ PARCEL_DETAILS_OWNER Used with llGetParcelDetails to get the parcel owner id. PARCEL_DETAILS_GROUP Used with llGetParcelDetails to get the parcel group id. PARCEL_DETAILS_AREA Used with llGetParcelDetails to get the parcel area in square meters. +STRING_TRIM_HEAD Used with llStringTrim to trim leading spaces from a string. +STRING_TRIM_TAIL Used with llStringTrim to trim trailing spaces from a string. +STRING_TRIM Used with llStringTrim to trim both leading and trailing spaces from a string. + # string constants [word .1, .3, .5] NULL_KEY Indicates an empty key diff --git a/linden/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl b/linden/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl index b2a6d67..c169fce 100644 --- a/linden/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class1/lighting/lightF.glsl @@ -5,7 +5,7 @@ uniform sampler2D diffuseMap; void default_lighting() { vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); - applyScatter(color.rgb); + //applyScatter(color.rgb); gl_FragColor = color; } diff --git a/linden/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl b/linden/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl new file mode 100644 index 0000000..12c99a6 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/objects/shinyF.glsl @@ -0,0 +1,13 @@ +void applyScatter(inout vec3 col); + +uniform samplerCube environmentMap; + +void main() +{ + vec3 ref = textureCube(environmentMap, gl_TexCoord[0].xyz).rgb; + + applyScatter(ref); + + gl_FragColor.rgb = ref; + gl_FragColor.a = gl_Color.a; +} diff --git a/linden/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl b/linden/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl new file mode 100644 index 0000000..621ff6b --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class1/objects/shinyV.glsl @@ -0,0 +1,27 @@ +void default_scatter(vec3 viewVec, vec3 lightDir); + +uniform vec4 origin; + +void main() +{ + //transform vertex + gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; + + vec3 pos = (gl_ModelViewMatrix * gl_Vertex).xyz; + vec3 norm = normalize(gl_NormalMatrix * gl_Normal); + + gl_FrontColor = gl_Color; + + vec3 ref = reflect(pos, norm); + + vec3 d = pos - origin.xyz; + float dist = dot(normalize(d), ref); + vec3 e = d + (ref * max(origin.w-dist, 0.0)); + + ref = e - origin.xyz; + + gl_TexCoord[0] = gl_TextureMatrix[0]*vec4(ref,1.0); + + default_scatter(pos.xyz, gl_LightSource[0].position.xyz); +} + diff --git a/linden/indra/newview/app_settings/shaders/class2/environment/waterV.glsl b/linden/indra/newview/app_settings/shaders/class2/environment/waterV.glsl index 5f06aeb..25309fa 100644 --- a/linden/indra/newview/app_settings/shaders/class2/environment/waterV.glsl +++ b/linden/indra/newview/app_settings/shaders/class2/environment/waterV.glsl @@ -47,7 +47,7 @@ void main() gl_TexCoord[0].zw = littleWave1; gl_TexCoord[1].xy = littleWave2; gl_TexCoord[1].zw = bigWave; - gl_TexCoord[2] = oEyeVec; + gl_TexCoord[2].xyz = oEyeVec.xyz; gl_TexCoord[3].xyz = oRefCoord; gl_FrontColor = col; } diff --git a/linden/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl b/linden/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl index 0ef1129..6f732ed 100644 --- a/linden/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl +++ b/linden/indra/newview/app_settings/shaders/class2/lighting/lightF.glsl @@ -5,7 +5,7 @@ uniform sampler2D diffuseMap; void default_lighting() { vec4 color = gl_Color * texture2D(diffuseMap, gl_TexCoord[0].xy); - applyScatter(color.rgb); + //applyScatter(color.rgb); gl_FragColor = color; } diff --git a/linden/indra/newview/app_settings/shaders/class3/environment/groundF.glsl b/linden/indra/newview/app_settings/shaders/class3/environment/groundF.glsl deleted file mode 100644 index 8618dad..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/environment/groundF.glsl +++ /dev/null @@ -1,12 +0,0 @@ -vec4 getScatter(vec3 viewVec, vec3 lightDir); - -varying vec3 lightd; -varying vec3 viewVec; - -void main() -{ - vec4 color = gl_Color; - vec4 haze = getScatter(viewVec, lightd) * vec4(gl_Fog.color.rgb, 1.0); - color.rgb = haze.rgb + haze.a * color.rgb; - gl_FragColor = color; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/environment/groundV.glsl b/linden/indra/newview/app_settings/shaders/class3/environment/groundV.glsl deleted file mode 100644 index a6f5270..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/environment/groundV.glsl +++ /dev/null @@ -1,11 +0,0 @@ -varying vec3 lightd; -varying vec3 viewVec; - -void main() -{ - gl_Position = gl_ModelViewProjectionMatrix * gl_Vertex; - lightd = gl_LightSource[0].position.xyz; - viewVec = (gl_ModelViewMatrix * gl_Vertex).xyz; - - gl_FrontColor = gl_Color; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/environment/scatterF.glsl b/linden/indra/newview/app_settings/shaders/class3/environment/scatterF.glsl deleted file mode 100644 index 7a9245f..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/environment/scatterF.glsl +++ /dev/null @@ -1,25 +0,0 @@ -uniform sampler2D scatterMap; - -//for per-pixel scatter -vec4 getScatter(vec3 viewVec, vec3 lightDir) -{ - vec2 scatterCoord; - scatterCoord.x = length(viewVec); - vec3 normVec = viewVec / scatterCoord.x; - scatterCoord.y = dot(normVec, lightDir)*0.5 + 0.5; - scatterCoord.x = scatterCoord.x / gl_Fog.end; - scatterCoord.x *= scatterCoord.x; // HACK!! Remove this when we can push the view distance farther out - return texture2D(scatterMap, scatterCoord) * vec4(gl_Fog.color.rgb, 1.0); -} - -void applyScatter(inout vec3 color, vec4 haze) -{ - color.rgb = haze.rgb + haze.a * color.rgb; -} - -//for per-vertex scatter -void applyScatter(inout vec3 color) -{ - vec4 haze = texture2D(scatterMap, gl_TexCoord[5].xy) * vec4(gl_Fog.color.rgb, 1.0); - color.rgb = haze.rgb + haze.a * color.rgb; -} diff --git a/linden/indra/newview/app_settings/shaders/class3/environment/scatterV.glsl b/linden/indra/newview/app_settings/shaders/class3/environment/scatterV.glsl deleted file mode 100644 index c9ebd9e..0000000 --- a/linden/indra/newview/app_settings/shaders/class3/environment/scatterV.glsl +++ /dev/null @@ -1,16 +0,0 @@ - -vec2 getScatterCoord(vec3 viewVec, vec3 lightDir) -{ - vec2 scatterCoord; - scatterCoord.x = length(viewVec); - vec3 normVec = normalize(viewVec); - scatterCoord.y = dot(normVec, lightDir)*0.5 + 0.5; - scatterCoord.x = scatterCoord.x / gl_Fog.end; - scatterCoord.x *= scatterCoord.x; // HACK!! Remove this when we can push the view distance farther out - return scatterCoord; -} - -void default_scatter(vec3 viewVec, vec3 lightDir) -{ - gl_TexCoord[5].xy = getScatterCoord(viewVec, lightDir); -} diff --git a/linden/indra/newview/app_settings/shaders/class3/environment/waterF.glsl b/linden/indra/newview/app_settings/shaders/class3/environment/waterF.glsl new file mode 100644 index 0000000..3a117c5 --- /dev/null +++ b/linden/indra/newview/app_settings/shaders/class3/environment/waterF.glsl @@ -0,0 +1,145 @@ +void applyScatter(inout vec3 color); + +uniform sampler2D diffuseMap; +uniform sampler2D bumpMap; +uniform samplerCube environmentMap; //: TEXUNIT4, // Environment map texture +uniform sampler2D screenTex; // : TEXUNIT5 + +uniform vec3 lightDir; +uniform vec3 specular; +uniform float lightExp; +uniform vec2 fbScale; +uniform float refScale; + +float msin(float x) { + float k = sin(x)+1.0; + k *= 0.5; + k *= k; + return 2.0 * k; +} + +float mcos(float x) { + float k = cos(x)+1.0; + k *= 0.5; + k *= k; + return 2.0 * k; +} + +float waveS(vec2 v, float t, float a, float f, vec2 d, float s, sampler1D sinMap) +{ + return texture1D(sinMap, (dot(d, v)*f + t*s)*f).r*a; +} + +float waveC(vec2 v, float t, float a, float f, vec2 d, float s, sampler1D sinMap) +{ + return texture1D(sinMap, (dot(d, v)*f + t*s)*f).g*a*2.0-1.0; +} + +float magnitude(vec3 vec) { + return sqrt(dot(vec,vec)); +} + +vec3 mreflect(vec3 i, vec3 n) { + return i + n * 2.0 * abs(dot(n,i))+vec3(0.0,0.0,0.5); +} + +void main() +{ + vec2 texCoord = gl_TexCoord[0].xy; // Texture coordinates + vec2 littleWave1 = gl_TexCoord[0].zw; + vec2 littleWave2 = gl_TexCoord[1].xy; + vec2 bigWave = gl_TexCoord[1].zw; + vec3 viewVec = gl_TexCoord[2].xyz; + vec4 refCoord = gl_TexCoord[3]; + vec4 col = gl_Color; + vec4 color; + + //get color from alpha map (alpha denotes water depth), rgb denotes water color + vec4 wcol = texture2D(diffuseMap, texCoord.xy); + + float dist = length(viewVec); + + //store texture alpha + float da = wcol.a; + + //modulate by incoming water color + //wcol.a *= refCoord.w; + + //scale wcol.a (water depth) for steep transition + wcol.a *= wcol.a; + + //normalize view vector + viewVec = normalize(viewVec); + + //get bigwave normal + vec3 wavef = texture2D(bumpMap, bigWave).xyz*2.0; + + vec3 view = vec3(viewVec.x, viewVec.y, viewVec.z); + + float dx = 1.0-(dot(wavef*2.0-vec3(1.0), view))*da; + dx *= 0.274; + + //get detail normals + vec3 dcol = texture2D(bumpMap, littleWave1+dx*view.xy).rgb*0.75; + dcol += texture2D(bumpMap, littleWave2+view.xy*dx*0.1).rgb*1.25; + + //interpolate between big waves and little waves (big waves in deep water) + wavef = wavef*wcol.a + dcol*(1.0-wcol.a); + + //crunch normal to range [-1,1] + wavef -= vec3(1,1,1); + wavef = normalize(wavef); + //wavef = vec3(0.0, 0.0, 1.0); + + //get base fresnel component + float df = dot(viewVec,wavef); + //translate and flip fresnel + df = 1.0-clamp(-df,0.0,1.0); + + //set output alpha based on fresnel + color.a = clamp((1.0-df+da)*0.5,0.0,1.0); + + //calculate reflection vector + vec3 refnorm = vec3(wavef.x*0.5, wavef.y*0.5, wavef.z*2.0); + + //ramp normal towards eye for far view stuff + float ramp = dist/256.0; + refnorm -= viewVec * ramp; + vec3 ref = reflect(viewVec.xyz, normalize(refnorm)); + ref.z /= sqrt(dist); + + //get diffuse component + float diff = clamp(dot(ref, wavef),0.0,1.0)*0.9; + + //fudge diffuse for extra contrast and ambience + diff *= diff; + diff += 0.4; + + vec3 fog = gl_TexCoord[5].rgb*0.5; + + //read from reflection map + vec3 refcol = textureCube(environmentMap, ref).rgb; + //tint reflection by fresnal, bias by z component of view vec + color.rgb = refcol*(df*df*dcol.x*dcol.y); + + //add diffuse contribution (fake blue water, yay!) + vec3 blue = vec3(0.1, 0.3, 0.6); + color.rgb += (diff/(max(ramp, 1.0)))*vec3(fog.r*blue.r, fog.g*blue.g, fog.b*blue.b); + + //figure out distortion vector (ripply) + vec2 distort = clamp(((refCoord.xy/refCoord.z) * 0.5 + 0.5 + wavef.xy*refScale),0.0,0.99); + + //read from framebuffer (offset) + vec4 fb = texture2D(screenTex, distort*fbScale); + + //tint by framebuffer + color.rgb = da*color.rgb + (1.0-da)*fb.rgb; + + //render as solid (previous pixel color already present) + color.a = 1.0; + + //apply fog + applyScatter(color.rgb); + + gl_FragColor = color; +} diff --git a/linden/indra/newview/app_settings/viewerart.ini b/linden/indra/newview/app_settings/viewerart.ini deleted file mode 100644 index e3d7af4..0000000 --- a/linden/indra/newview/app_settings/viewerart.ini +++ /dev/null @@ -1,503 +0,0 @@ -version 101 -closebox.tga 47a8c844-cd2a-4b1a-be01-df8b1612fe5d -close_in_blue.tga e5821134-23c0-4bd0-af06-7fa95b9fb01a -tearoffbox.tga 74e1a96f-4833-a24d-a1bb-1bce1468b0e7 -tearoff_pressed.tga d2524c13-4ba6-af7c-e305-8ac6cc18d86a -resize_handle_bottom_right_blue.tga e3690e25-9690-4f6c-a745-e7dcd885285a -scrollbutton_up_out_blue.tga dad084d7-9a46-452a-b0ff-4b9f1cefdde9 -scrollbutton_up_in_blue.tga a93abdf3-27b5-4e22-a8fa-c48216cd2e3a -scrollbutton_down_out_blue.tga b4ecdecf-5c8d-44e7-b882-17a77e88ed55 -scrollbutton_down_in_blue.tga d2421bab-2eaf-4863-b8f6-5e4c52519247 -scrollbutton_left_out_blue.tga 43773e8d-49aa-48e0-80f3-a04715f4677a -scrollbutton_left_in_blue.tga ea137a32-6718-4d05-9c22-7d570d27b2cd -scrollbutton_right_out_blue.tga 3d700d19-e708-465d-87f2-46c8c0ee7938 -scrollbutton_right_in_blue.tga b749de64-e903-4c3c-ac0b-25fb6fa39cb5 -spin_up_out_blue.tga 56576e6e-6710-4e66-89f9-471b59122794 -spin_up_in_blue.tga c8450082-96a0-4319-8090-d3ff900b4954 -spin_down_out_blue.tga b6d240dd-5602-426f-b606-bbb49a30726d -spin_down_in_blue.tga a985ac71-052f-48e6-9c33-d931c813ac92 -radio_active_false.tga 7a1ba9b8-1047-4d1e-9cfc-bc478c80b63f -radio_active_true.tga 52f09e07-5816-4052-953c-94c6c10479b7 -radio_inactive_false.tga 90688481-67ff-4af0-be69-4aa084bcad1e -radio_inactive_true.tga 1975db39-aa29-4251-aea0-409ac09d414d -checkbox_enabled_false.tga 05bb64ee-96fd-4243-b74e-f40a41bc53ba -checkbox_enabled_true.tga cf4a2ed7-1533-4686-9dde-df9a37ddca55 -checkbox_disabled_false.tga 7d94cb59-32a2-49bf-a516-9e5a2045f9d9 -checkbox_disabled_true.tga c817c642-9abd-4236-9287-ae0513fe7d2b -tab_top_blue.tga 1ed83f57-41cf-4052-a3b4-2e8bb78d8191 -tab_top_selected_blue.tga 16d032e8-817b-4368-8a4e-b7b947ae3889 -tab_bottom_blue.tga bf0a8779-689b-48c3-bb9a-6af546366ef4 -tab_bottom_selected_blue.tga c001d8fd-a869-4b6f-86a1-fdcb106df9c7 -tab_left.tga 1097dcb3-aef9-8152-f471-431d840ea89e -tab_left_selected.tga bea77041-5835-1661-f298-47e2d32b7a70 -crosshairs.tga 6e1a3980-bf2d-4274-8970-91e60d85fb52 -move_backward_in.tga db11d956-5e7d-4aa5-b39d-7774d339fc5c -move_backward_out.tga 3ae8bb18-ed97-4cd3-ae5c-d54bc8479fe7 -move_down_in.tga b92a70b9-c841-4c94-b4b3-cee9eb460d48 -move_down_out.tga b5abc9fa-9e62-4e03-bc33-82c4c1b6b689 -move_forward_in.tga 54197a61-f5d1-4c29-95d2-c071d08849cb -move_forward_out.tga a0eb4021-1b20-4a53-892d-8faa9265a6f5 -move_left_in.tga 724996f5-b956-46f6-9844-4fcfce1d5e83 -move_left_out.tga 82476321-0374-4c26-9567-521535ab4cd7 -move_right_in.tga 7eeb57d2-3f37-454d-a729-8b217b8be443 -move_right_out.tga 1fbe4e60-0607-44d1-a50a-032eff56ae75 -move_turn_left_in.tga 95463c78-aaa6-464d-892d-3a805b6bb7bf -move_turn_left_out.tga 13a93910-6b44-45eb-ad3a-4d1324c59bac -move_turn_right_in.tga 5e616d0d-4335-476f-9977-560bccd009da -move_turn_right_out.tga 5a44fd04-f52b-4c30-8b00-4a31e27614bd -move_up_out.tga f887146d-829f-4e39-9211-cf872b78f97c -move_up_in.tga 49b4b357-e430-4b56-b9e0-05b8759c3c82 -cam_rotate_out.tga 88745b46-da05-11d5-8ac0-0003477c4611 -cam_rotate_in.tga 70bf2262-3eed-4996-88ac-076907e8921d -cam_zoom_out.tga bb02e941-cb3b-4dd3-892a-6841b5de6e45 -cam_zoom_plus_in.tga c7aefd32-ce13-4242-82cc-2631d44ff9d3 -cam_zoom_minus_in.tga deed3f4b-93e9-4183-a3b0-a5a98a6de1bb -cam_tracking_out.tga 95c4ea0e-e3c2-4904-b847-7d7676139ebb -cam_tracking_in.tga fe2fc73b-5a64-4a8e-aacc-46fa81faf96a -direction_arrow.tga 586383e8-4d9b-4fba-9196-2b5938e79c2c -minimize.tga 34c9398d-bb78-4643-9633-46a2fa3e9637 -minimize_inactive.tga 6e72abba-1378-437f-bf7a-f0c15f3e99a3 -minimize_pressed.tga 39801651-26cb-4926-af57-7af9352c273c -restore.tga 111b39de-8928-4690-b7b2-e17d5c960277 -restore_inactive.tga 0eafa471-70af-4882-b8c1-40a310929744 -restore_pressed.tga 90a0ed5c-2e7b-4845-9958-a64a1b30f312 -combobox_arrow.tga b31c1335-0e9c-4927-bc90-53277777d9c1 -white.tga 5748decc-f629-461c-9a36-a35a221fe21f -darkgray.tga 267e26d3-e0e1-41b8-91b1-3b337102928d -lightgray.tga c520bf46-cc5d-412b-a60b-9f1bd245189f -eyes.tga 6522e74d-1660-4e7f-b601-6f48c1659a77 -hair.tga 7ca39b4c-bd19-4699-aff7-f93fd03d3e7b -black.tga e2244626-f22f-4839-8123-1e7baddeb659 -close_inactive_blue.tga 779e4fa3-9b13-f74a-fba9-3886fe9c86ba -button_disabled_32x128.tga f8124d60-2875-c358-7847-2acb63e5400c -button_enabled_32x128.tga d8faf8cb-ee6e-b0b5-abd9-bde873ad3461 -button_enabled_selected_32x128.tga 1eddba75-b682-110a-104e-6cdcce616a25 -button_anim_play_selected.tga 119c37bb-24af-45fe-ae11-3a6bc3c85138 -button_anim_pause_selected.tga ad65d67a-777b-fbfa-693d-4bdcfca2acca -button_anim_pause.tga db2d9c2d-0bbd-21e2-e83a-103ea2def7a8 -button_anim_play.tga 2a7f6738-5d82-2ff3-d419-30ed09cbb72b -button_anim_stop.tga e10c9e36-d9f6-c8b4-de96-557dccce9205 -button_anim_stop_selected.tga b8c0e0aa-2771-439e-c919-d2f5dad69a1c -rounded_square.tga 38ce8b3c-fb30-5c59-9926-bd643613f606 -rounded_square_soft.tga 4c95e6bc-fe77-9cb4-b58a-909848042c1e -badge_ok.tga 211035a7-c313-378d-478c-e80bbd0fde63 -badge_note.tga 13f6e639-b3f9-28da-a1e6-e990a43052b6 -badge_warn.tga 0992d4bc-7af8-4a1f-f2e6-e6c4083b066e -badge_error.tga 00c50485-8491-ab70-2ea8-43f26fd028e2 -status_money.tga 5863eb7a-1546-6501-533a-6061f73a36b7 -status_health.tga 4330e8ce-b39b-1eb8-c2ec-a97c0b3947b5 -status_fly.tga 0e058115-5b8f-c3d7-dcaa-9623d92885d1 -status_build.tga 175a6b75-45c9-c2c2-4765-bf37a3909b53 -status_busy.tga beb0d821-6725-abdf-032d-1f70cdabde82 -status_scripts.tga 4cc1afcd-04dd-178f-e074-0f9dc730ab45 -status_buy_currency.tga f43a535a-59ac-26e3-84bc-c786735fabe4 -status_buy_currency_pressed.tga bfa5be70-37c7-8126-fecd-df55390954d5 -status_buy_land.tga 1a0edac5-3e50-fc9b-2752-70c1f69cb959 -status_buy_land_pressed.tga 257647b7-199f-99ff-8be9-f6753289a3aa -terrain_dirt.tga b8d3965a-ad78-bf43-699b-bff8eca6c975 -terrain_grass.tga abb783e6-3e93-26c0-248a-247666855da3 -terrain_mountain.tga 179cdabd-398a-9b6b-1391-4dc333ba321f -terrain_rock.tga beb169c7-11ea-fff2-efe5-0f24dc881df2 -terrain_dirt_detail.tga 0bc58228-74a0-7e83-89bc-5c23464bcec5 -terrain_grass_detail.tga 63338ede-0037-c4fd-855b-015d77112fc8 -terrain_mountain_detail.tga 303cd381-8560-7579-23f1-f0a880799740 -terrain_rock_detail.tga 53a2f406-4895-1d13-d541-d2e3b86bc19c -square_btn_32x128.tga b28df901-6b8d-d31c-7903-4eb9676d4bfc -square_btn_selected_32x128.tga c48c9e95-191b-96d3-08b2-6e8ada58b651 -tree_pine_1.tga 0187babf-6c0d-5891-ebed-4ecab1426683 -tree_oak.tga 8a515889-eac9-fb55-8eba-d2dc09eb32c8 -tree_tropical_1.tga 5bc11cd6-2f40-071e-a8da-0903394204f9 -tree_palm_1.tga ca4e8c27-473c-eb1c-2f5d-50ee3f07d85c -tree_dogwood.tga 64367bd1-697e-b3e6-0b65-3f862a577366 -tree_tropical_2.tga cdd9a9fc-6d0b-f90d-8416-c72b6019bca8 -tree_palm_2.tga 2d784476-d0db-9979-0cff-9408745a7cf3 -tree_cypress_1.tga fb2ae204-3fd1-df33-594f-c9f882830e66 -tree_cypress_2.tga 30047cec-269d-408e-0c30-b2603b887268 -tree_pine_2.tga d691a01c-13b7-578d-57c0-5caef0b4e7e1 -tree_plumeria.tga 6de37e4e-7029-61f5-54b8-f5e63f983f58 -winter_tree_aspen.tga 7c0cf89b-44b1-1ce2-dd74-07102a98ac2a -winter_tree_pine_1.tga 10d2a01a-0818-84b9-4b96-c2eb63256519 -winter_tree_pine_2.tga 67931331-0c02-4876-1255-28770896c6a2 -tree_eucalyptus.tga a6162133-724b-54df-a12f-51cd070ad6f3 -tree_fern.tga 8872f2b8-31db-42d8-580a-b3e4a91262de -tree_eelgrass.tga 96b4de31-f4fa-337d-ec78-451e3609769e -tree_sea_sword.tga 5894e2e7-ab8d-edfa-e61c-18cf16854ba3 -tree_kelp_1.tga 2caf1179-7861-6ff3-4b7d-46e17780bdfa -tree_kelp_2.tga 2a4880b6-b7a3-690a-2049-bfbe38eafb9f -tree_beach_grass_1.tga 18fb888b-e8f1-dce7-7da7-321d651ea6b0 -tool_dozer.tga d2a0d4d4-54eb-4d16-be4b-4eae43845c74 -tool_dozer_active.tga d4afdbbe-1550-4b7d-91de-95731f47e8e3 -tool_land.tga 86fe4df4-0ecb-4382-b9ae-475925a92388 -tool_land_active.tga 34e60587-0791-4a07-8918-f5995fcc22a3 -tool_zoom.tga 27eb8829-fe65-45ed-a49a-73aac42f4b38 -tool_zoom_active.tga 69445f58-5c8e-44e0-9d2e-47408bb43b39 -tool_orbit.tga 06964fe4-033f-448a-95c9-30dc41d1be8b -tool_orbit_active.tga ee4e07db-3f72-4098-bd4c-aef34515a7bc -tool_pan.tga a32aa302-0a15-48d2-b2b1-4d69f1161173 -tool_pan_active.tga 24d9ad33-0b42-4eb5-99a3-659d838bc5c0 -inv_folder_texture.tga 743f035b-a049-43f4-16c7-7ec8daa2c481 -inv_folder_sound.tga e10cb910-1e71-da47-bd12-8c53f7793714 -inv_folder_callingcard.tga a3735971-e2b2-d78a-580d-d265cd8f2484 -inv_folder_landmark.tga 9f921155-7c8c-e276-d5ec-03ac9340584d -inv_folder_script.tga baa5c310-6a6d-cc48-51eb-65196ba31d77 -inv_folder_object.tga 113e5133-fd0d-ee51-4a59-9d67ca10e8a7 -inv_folder_notecard.tga a9e75d84-5073-9cb7-10a9-1ca68ef5c7ba -inv_folder_clothing.tga f1427d3d-b2e8-97c4-69ab-1f36d4c0e8f0 -inv_folder_bodypart.tga 1fe05580-1d2f-0345-b28b-52b6e3a20e5d -inv_folder_trash.tga 88ad072e-ea0b-aabd-5ac0-b37862a6eb66 -inv_folder_plain_closed.tga 86f00960-c3e9-9680-145d-3beffd743e9c -inv_folder_plain_open.tga d15dc243-2d0b-47af-0ce1-ec376464bdc8 -inv_folder_snapshot.tga 6efe85e7-800f-1843-296c-a5b7adffe091 -inv_folder_lostandfound.tga 9a371a04-297d-bacf-0d16-5f49753efe1d -inv_folder_animation.tga 4d59b3ee-f29d-b912-2bcc-9bb1f8a07ec6 -inv_folder_gesture.tga 4de9129a-9fc1-d759-d739-364293906ba2 -inv_item_texture.tga 19f452d7-4eee-9f46-76cc-5497d17f1dd9 -inv_item_sound.tga eb414d69-c77d-d4e7-66e6-6c2e6f6c1976 -inv_item_callingcard_online.tga 672cc53e-8dc0-ba91-2a4e-574104cf071c -inv_item_callingcard_offline.tga d0afe86b-2489-7600-55b7-6abb0a63d9f9 -inv_item_landmark.tga bf25a2a0-85da-7fa0-0993-e461768d0221 -inv_item_landmark_visited.tga 229fac85-5428-4ab7-adeb-eb8389e91092 -inv_item_script.tga 59a3df81-ed76-06c9-7264-6dada535e7a3 -inv_item_clothing.tga 34dfe476-8e26-0e3a-11cf-76cc4a7126ce -inv_item_object.tga 0f0780a0-89c4-742a-ef28-26405a41cf85 -inv_item_notecard.tga 23ce8a2c-9ea2-d863-6572-806f0645b0c7 -inv_item_bodypart.tga d2a5362d-5c55-57dd-a9e9-5c814d1ddc16 -inv_item_attach.tga 5bcae41e-aa5d-02f8-edf1-605ebdd875ab -inv_item_snapshot.tga 3810d584-b092-7caa-57e0-010f192b9659 -inv_item_eyes.tga eaa5fd96-5c25-06ef-2280-7ef20203e167 -inv_item_gloves.tga 117b11cb-c04e-5081-13da-1a8846070fd0 -inv_item_hair.tga 6bca3bf4-ed6d-d438-63a0-2a7066d03a0b -inv_item_jacket.tga 8df59386-56e0-c811-0443-840da3acb3a5 -inv_item_pants.tga a87a58ca-f857-63b1-0acf-072711ed1bdb -inv_item_shape.tga 4463e433-4db5-79ef-c1b0-4821b03ddb07 -inv_item_shirt.tga e2ffb62b-6abc-22d6-952d-764759b4d636 -inv_item_shoes.tga cf384fa5-1edd-c37c-2134-283dd4fe3396 -inv_item_skirt.tga 0b43f826-2abc-2944-7d72-10777a51d19b -inv_item_socks.tga 22137c6d-6ec5-6eee-9a2e-2d7a9e6cbcd4 -inv_item_underpants.tga 2f15dc09-4385-526c-aa5d-d9d516ec7d99 -inv_item_undershirt.tga f72ab629-a3ab-de0c-35c0-5285e27478ce -inv_item_animation.tga b5cda0d6-d196-ce48-63db-d04323ef8931 -inv_item_gesture.tga 5579245d-d5bf-5f13-46b0-8624490de24c -pixiesmall.tga 168e6813-096e-07ea-97ae-fd416826f627 -legend.tga ca7609c6-6ec6-32d9-332e-0d8f437ef644 -propertyline.tga e3548c46-8d5e-03da-fcab-4fc36ad818bb -startup_logo.tga 66864f3c-e095-d9c8-058d-d6575e6ed1b8 -grass_texture_1.tga 79504bf5-c3ec-0763-6563-d843de66d0a1 -grass_texture_2.tga 6c4727b8-ac79-ba44-3b81-f9aa887b47eb -grass_texture_3.tga 99bd60a2-3250-efc9-2e39-2fbcadefbecc -grass_texture_4.tga 7a2b3a4a-53c2-53ac-5716-aac7d743c020 -undergrowth_1.tga 8f458549-173b-23ff-d4ff-bfaa5ea2371b -silhouette.tga da5d4079-7819-6b53-d2a4-dc9929381d7d -avatar_thumb_bkgrnd.tga 3a7f4f0d-be14-ee78-29e3-fc8b0b2a68d3 -missing_asset.tga 32dfd1c8-7ff6-5909-d983-6d4adfb4255d -alpha_gradient.tga e97cf410-8e61-7005-ec06-629eba4cd1fb -alpha_gradient_2d.tga 38b86f85-2575-52a9-a531-23108d8da837 -alpha_noise.tga b9e1cf8a-9660-c020-0c69-18f1ea27268a -alpha_sizzle.tga e121e2fc-7573-740f-edfd-0d45a9ba486e -bump_woodgrain.tga 058c75c0-a0d5-f2f8-43f3-e9699a89c2fc -bump_bark.tga 6c9fa78a-1c69-2168-325b-3e03ffa348ce -bump_bricks.tga b8eed5f0-64b7-6e12-b67f-43fa8e773440 -bump_checker.tga 9deab416-9c63-78d6-d558-9a156f12044c -bump_concrete.tga db9d39ec-a896-c287-1ced-64566217021e -bump_crustytile.tga f2d7b6f6-4200-1e9a-fd5b-96459e950f94 -bump_cutstone.tga d9258671-868f-7511-c321-7baef9e948a4 -bump_discs.tga d21e44ca-ff1c-a96e-b2ef-c0753426b7d9 -bump_gravel.tga 4726f13e-bd07-f2fb-feb0-bfa2ac58ab61 -bump_petridish.tga e569711a-27c2-aad4-9246-0c910239a179 -bump_siding.tga 073c9723-540c-5449-cdd4-0e87fdc159e3 -bump_stonetile.tga ae874d1a-93ef-54fb-5fd3-eb0cb156afc0 -bump_stucco.tga 92e66e00-f56f-598a-7997-048aa64cde18 -bump_suction.tga 83b77fc6-10b4-63ec-4de7-f40629f238c5 -bump_weave.tga 735198cf-6ea0-2550-e222-21d3c6a341ae -icon_avatar_online.tga 529ed15b-3d41-dcc1-79de-90bf21770b5b -icon_avatar_offline.tga 34648c67-5bfb-5790-e05e-8bd6600fd087 -icon_event.tga be235ae0-53cf-1d68-b3ae-cf375ed1fb58 -icon_event_mature.tga cc090999-1b3e-2e97-7a38-c9f4afd10297 -icon_group.tga 04237108-a879-5a95-9b0c-b18fd09bc447 -icon_place.tga ba0bac4e-815e-14e1-2895-5065b8c703b3 -icon_top_pick.tga 77ca91a2-4431-aeaf-6249-3dd99c7dd86d -icon_popular.tga bdd47da5-5b5b-c906-37ad-16aaa64f096f -icon_for_sale.tga f20728fd-1670-3771-2293-e0dd3f0bcaab -icon_auction.tga 96abf5b1-335c-6b76-61e3-74ada07f3cb8 -icon_land_for_landless.tga c421ddf2-b9d7-b373-503c-f4c423f37f1c -icon_day_cycle.tga 5b30a285-f1e3-92b1-dcd3-0d07366ced3e -icon_lock.tga 9beb8cdd-3dce-53c2-b28e-e1f3bc2ec0a4 -noentrylines.tga 5d3e196b-fd4d-ada7-e4c1-99f8e9f1cfbf -noentrypasslines.tga ac8f8627-6a30-8da8-d4bd-958668eea7a0 -notify_tip_icon.tga 74ba3584-58ea-9984-5b76-62d37942ab77 -notify_box_icon.tga b2ef2d31-9714-a07b-6ca7-31638166364b -notify_next.tga 07d0ea4c-af0c-aad1-dbbf-c24020ff2b80 -map_avatar_you_8.tga 02fbdc40-5e07-a6e1-228b-58e10f8335b7 -map_avatar_8.tga 0be58a91-8065-c02b-7a12-2cc14dddbc37 -map_avatar_16.tga db0dadd5-026a-88cf-f5c1-523a0a2daa3e -map_telehub.tga bf1b2bb0-13b1-40ae-3354-b1b93761bdb4 -map_infohub.tga 85b1a79a-7f6c-9df3-4d6c-17b1a4efb55a -map_home.tga ae9b8f5f-03a1-2e71-db77-6eb27a1ba181 -map_event.tga 6008be5e-9267-2a3a-9798-e81b076c22ca -map_event_mature.tga f9cdba28-a227-d613-2f16-ce06209314ae -map_track_8.tga bfdc7bf6-e2ee-1754-f4df-cc25887714ad -map_track_16.tga a3878395-ef00-a0e6-ee9a-f45ed6b9ce59 -object_cone.tga c2b8c90a-7dca-26e3-1a63-7aa4a0389cf9 -object_cone_active.tga cf69c64b-f19e-e1f3-a586-42fef31a23be -object_cube.tga 70c747ac-1de3-a8b9-514d-101753ca6ccb -object_cube_active.tga f9c5e213-1076-7a7d-7889-52388aad2c1a -object_cylinder.tga 13e35d95-5f6c-9a91-1766-49dedf9b1267 -object_cylinder_active.tga 3f3e4932-8412-e2a7-cfe9-92caf5978b1b -object_grass.tga 7ca8e672-920b-4653-3970-1abc91abef58 -object_grass_active.tga d0fc7cc9-646a-6860-cf7c-1d9e58cd6dab -object_hemi_cone.tga 69d5e60c-739a-40b1-b526-84072121e394 -object_hemi_cone_active.tga 2e0c5435-95bb-1c0d-5da1-42336fb1cfc0 -object_hemi_cylinder.tga f4be3e06-24a8-f86e-acc7-7daefc0572b7 -object_hemi_cylinder_active.tga 67279486-cfc1-3633-de42-85db65db373c -object_hemi_sphere.tga b67251ab-1716-b9fb-f911-967ba3fe027b -object_hemi_sphere_active.tga 6c489466-3058-6475-6b1b-e5fc1d49f1f3 -object_pyramid.tga 9dde8b56-2cc4-a932-b63a-38c3a83221ad -object_pyramid_active.tga e7217b1a-e3d8-e339-d28a-d7714d0b5bee -object_sphere.tga 7fa122c0-b994-460e-8636-cdc451d67268 -object_sphere_active.tga f2c3bcbc-2904-41a5-1c22-688f176fd1ee -object_tetrahedron.tga e17db404-9fc5-9534-1038-777c82b2771f -object_tetrahedron_active.tga 2792ea3b-c052-85fe-d168-a62b2f4e9d7c -object_tree.tga 710d1bec-fb33-28f1-e77e-ddbb5b51f5ed -object_tree_active.tga da4835c7-b12a-41dd-11db-dae452f040c2 -object_prism.tga 02935f3a-dcda-3b42-1874-da89d4c12870 -object_prism_active.tga 223aac97-bd2f-ec2e-ad45-5641b77c78f9 -object_torus.tga 19e1f4c9-6aa6-4414-981d-59a1343a6472 -object_torus_active.tga ef2bca77-5004-4547-b00a-3b96e463f89f -object_tube.tga 7ce81316-a478-480f-961c-435fcbdecaf0 -object_tube_active.tga 55c3e4d1-cfdc-48a8-af32-a34844b91832 -object_ring_active.tga 2c955a73-fa31-237b-a4a1-5c8ede3bae50 -object_ring.tga a7610e41-4647-16d8-0e0e-85a1211c1596 -container_animation.tga c4e657a1-4c86-0159-2da0-32ff948484e6 -container_bodypart.tga 770cb2df-758d-34d5-36c7-e3de06db5b5d -container_clothing.tga dd90406f-4c8f-a3f9-41df-d562f94f09e0 -container_gesture.tga 59cd31c0-2791-3c48-f740-f0a36c68653e -container_landmark.tga 24c63386-04f7-ce6f-4ff2-dfb215d2e21f -container_many_things.tga 849d3292-d9fa-7186-5465-dd7b5fc1ec48 -container_object.tga ad887ae1-2bee-f2c9-6786-5599de3c95c4 -container_script.tga b93bd494-c4bd-bcdf-4a59-35a9497d03f3 -container_sound.tga 5ddea031-cfa3-2776-43e3-c7146c1b4cd6 -container_texture.tga b3f95caf-bd62-bef3-0ded-dea752920629 -avatar_aim_l_bow.bvh 46bb4359-de38-4ed8-6a22-f1f52fe8f506 -avatar_aim_r_bazooka.bvh b5b4a67d-0aee-30d2-72cd-77b333e932ef -avatar_aim_r_handgun.bvh 3147d815-6338-b932-f011-16b56d9ac18b -avatar_aim_r_rifle.bvh ea633413-8006-180a-c3ba-96dd1d756720 -avatar_angry_fingerwag.bvh c1bc7f36-3ba0-d844-f93c-93be945d644f -avatar_angry_tantrum.bvh 11000694-3f41-adc2-606b-eee1d66f3724 -avatar_away.bvh fd037134-85d4-f241-72c6-4f42164fedee -avatar_backflip.bvh c4ca6188-9127-4f31-0158-23c4e2f93304 -avatar_blowkiss.bvh db84829b-462c-ee83-1e27-9bbee66bd624 -avatar_bow.bvh 82e99230-c906-1403-4d9c-3889dd98daba -avatar_brush.bvh 349a3801-54f9-bf2c-3bd0-1ac89772af01 -avatar_clap.bvh 9b0c1c4e-8ac7-7969-1494-28c874c4f668 -avatar_courtbow.bvh 9ba1c942-08be-e43a-fb29-16ad440efc50 -avatar_crouch.bvh 201f3fdf-cb1f-dbec-201f-7333e328ae7c -avatar_crouchwalk.bvh 47f5f6fb-22e5-ae44-f871-73aaaf4a6022 -avatar_dance1.bvh b68a3d7c-de9e-fc87-eec8-543d787e5b0d -avatar_dance2.bvh 928cae18-e31d-76fd-9cc9-2f55160ff818 -avatar_dance3.bvh 30047778-10ea-1af7-6881-4db7a3a5a114 -avatar_dance4.bvh 951469f4-c7b2-c818-9dee-ad7eea8c30b7 -avatar_dance5.bvh 4bd69a1d-1114-a0b4-625f-84e0a5237155 -avatar_dance6.bvh cd28b69b-9c95-bb78-3f94-8d605ff1bb12 -avatar_dance7.bvh a54d8ee2-28bb-80a9-7f0c-7afbbe24a5d6 -avatar_dance8.bvh b0dc417c-1f11-af36-2e80-7e7489fa7cdc -avatar_dead.bvh 57abaae6-1d17-7b1b-5f98-6d11a6411276 -avatar_drink.bvh 0f86e355-dd31-a61c-fdb0-3a96b9aad05f -avatar_express_afraid.bvh 6b61c8e8-4747-0d75-12d7-e49ff207a4ca -avatar_express_anger.bvh 5747a48e-073e-c331-f6f3-7c2149613d3e -avatar_express_bored.bvh b906c4ba-703b-1940-32a3-0c7f7d791510 -avatar_express_cry.bvh 92624d3e-1068-f1aa-a5ec-8244585193ed -avatar_express_embarrased.bvh 514af488-9051-044a-b3fc-d4dbf76377c6 -avatar_express_laugh.bvh 18b3a4b5-b463-bd48-e4b6-71eaac76c515 -avatar_express_repulsed.bvh 36f81a92-f076-5893-dc4b-7c3795e487cf -avatar_express_sad.bvh 0eb702e2-cc5a-9a88-56a5-661a55c0676a -avatar_express_shrug.bvh 70ea714f-3a97-d742-1b01-590a8fcd1db5 -avatar_express_surprise.bvh 313b9881-4302-73c0-c7d0-0e7a36b6c224 -avatar_express_wink.bvh 869ecdad-a44b-671e-3266-56aef2e3ac2e -avatar_express_worry.bvh 9f496bd2-589a-709f-16cc-69bf7df1d36c -avatar_falldown.bvh 666307d9-a860-572d-6fd4-c3ab8865c094 -avatar_female_walk.bvh f5fc7433-043d-e819-8298-f519a119b688 -avatar_fist_pump.bvh 7db00ccd-f380-f3ee-439d-61968ec69c8a -avatar_fly.bvh aec4610c-757f-bc4e-c092-c6e9caf18daf -avatar_flyslow.bvh 2b5a38b2-5e00-3a97-a495-4c826bc443e6 -avatar_hello.bvh 9b29cd61-c45b-5689-ded2-91756b8d76a9 -avatar_hold_l_bow.bvh 8b102617-bcba-037b-86c1-b76219f90c88 -avatar_hold_r_bazooka.bvh ef62d355-c815-4816-2474-b1acc21094a6 -avatar_hold_r_handgun.bvh efdc1727-8b8a-c800-4077-975fc27ee2f2 -avatar_hold_r_rifle.bvh 3d94bad0-c55b-7dcc-8763-033c59405d33 -avatar_hover.bvh 4ae8016b-31b9-03bb-c401-b1ea941db41d -avatar_hover_down.bvh 20f063ea-8306-2562-0b07-5c853b37b31e -avatar_hover_up.bvh 62c5de58-cb33-5743-3d07-9e4cd4352864 -avatar_impatient.bvh 5ea3991f-c293-392e-6860-91dfa01278a3 -avatar_jump.bvh 2305bd75-1ca9-b03b-1faa-b176b8a8c49e -avatar_jumpforjoy.bvh 709ea28e-1573-c023-8bf8-520c8bc637fa -avatar_kick_roundhouse_r.bvh 49aea43b-5ac3-8a44-b595-96100af0beda -avatar_kissmybutt.bvh 19999406-3a3a-d58c-a2ac-d72e555dcf51 -avatar_land.bvh 7a17b059-12b2-41b1-570a-186368b6aa6f -avatar_laugh_short.bvh ca5b3f14-3194-7a2b-c894-aa699b718d1f -avatar_motorcycle_sit.bvh 08464f78-3a8e-2944-cba5-0c94aff3af29 -avatar_musclebeach.bvh 315c3a41-a5f3-0ba4-27da-f893f769e69b -avatar_no_head.bvh 5a977ed9-7f72-44e9-4c4c-6e913df8ae74 -avatar_no_unhappy.bvh d83fa0e5-97ed-7eb2-e798-7bd006215cb4 -avatar_nyanya.bvh f061723d-0a18-754f-66ee-29a44795a32f -avatar_peace.bvh b312b10e-65ab-a0a4-8b3c-1326ea8e3ed9 -avatar_point_me.bvh 17c024cc-eef2-f6a0-3527-9869876d7752 -avatar_point_you.bvh ec952cca-61ef-aa3b-2789-4d1344f016de -avatar_prejump.bvh 7a4e87fe-de39-6fcb-6223-024b00893244 -avatar_punch_l.bvh f3300ad9-3462-1d07-2044-0fef80062da0 -avatar_punch_onetwo.bvh eefc79be-daae-a239-8c04-890f5d23654a -avatar_punch_r.bvh c8e42d32-7310-6906-c903-cab5d4a34656 -avatar_rps_countdown.bvh 35db4f7e-28c2-6679-cea9-3ee108f7fc7f -avatar_rps_paper.bvh 0836b67f-7f7b-f37b-c00a-460dc1521f5a -avatar_rps_rock.bvh 42dd95d5-0bc6-6392-f650-777304946c0f -avatar_rps_scissors.bvh 16803a9f-5140-e042-4d7b-d28ba247c325 -avatar_run.bvh 05ddbff8-aaa9-92a1-2b74-8fe77a29b445 -avatar_salute.bvh cd7668a6-7011-d7e2-ead8-fc69eff1a104 -avatar_shoot_l_bow.bvh e04d450d-fdb5-0432-fd68-818aaf5935f8 -avatar_shout.bvh 6bd01860-4ebd-127a-bb3d-d1427e8e0c42 -avatar_sit.bvh 1a5fe8ac-a804-8a5d-7cbd-56bd83184568 -avatar_sit_female.bvh b1709c8d-ecd3-54a1-4f28-d55ac0840782 -avatar_sit_generic.bvh 245f3c54-f1c0-bf2e-811f-46d8eeb386e7 -avatar_sit_ground.bvh 1c7600d6-661f-b87b-efe2-d7421eb93c86 -avatar_sit_ground_constrained.bvh 1a2bd58e-87ff-0df8-0b4c-53e047b0bb6e -avatar_sit_to_stand.bvh a8dee56f-2eae-9e7a-05a2-6fb92b97e21e -avatar_sleep.bvh f2bed5f9-9d44-39af-b0cd-257b2a17fe40 -avatar_smoke_idle.bvh d2f2ee58-8ad1-06c9-d8d3-3827ba31567a -avatar_smoke_inhale.bvh 6802d553-49da-0778-9f85-1599a2266526 -avatar_smoke_throw_down.bvh 0a9fb970-8b44-9114-d3a9-bf69cfe804d6 -avatar_snapshot.bvh eae8905b-271a-99e2-4c0e-31106afd100c -avatar_soft_land.bvh f4f00d6e-b9fe-9292-f4cb-0ae06ea58d57 -avatar_stand.bvh 2408fe9e-df1d-1d7d-f4ff-1384fa7b350f -avatar_stand_1.bvh 15468e00-3400-bb66-cecc-646d7c14458e -avatar_stand_2.bvh 370f3a20-6ca6-9971-848c-9a01bc42ae3c -avatar_stand_3.bvh 42b46214-4b44-79ae-deb8-0df61424ff4b -avatar_stand_4.bvh f22fed8b-a5ed-2c93-64d5-bdd8b93c889f -avatar_standup.bvh 3da1d753-028a-5446-24f3-9c9b856d9422 -avatar_stretch.bvh 80700431-74ec-a008-14f8-77575e73693f -avatar_stride.bvh 1cb562b0-ba21-2202-efb3-30f82cdf9595 -avatar_surf.bvh 41426836-7437-7e89-025d-0aa4d10f1d69 -avatar_sword_strike_r.bvh 85428680-6bf9-3e64-b489-6f81087c24bd -avatar_talk.bvh 5c682a95-6da4-a463-0bf6-0f5b7be129d1 -avatar_throw_r.bvh aa134404-7dac-7aca-2cba-435f9db875ca -avatar_tryon_shirt.bvh 83ff59fe-2346-f236-9009-4e3608af64c1 -avatar_turn_180.bvh 038fcec9-5ebd-8a8e-0e2e-6e71a0a1ac53 -avatar_turnback_180.bvh 6883a61a-b27b-5914-a61e-dda118a9ee2c -avatar_turnleft.bvh 56e0ba0d-4a9f-7f27-6117-32f2ebbf6135 -avatar_turnright.bvh 2d6daa51-3192-6794-8e2e-a15f8338ec30 -avatar_type.bvh c541c47f-e0c0-058b-ad1a-d6ae3a4584d9 -avatar_walk.bvh 6ed24bd8-91aa-4b12-ccc7-c97c857ab4e0 -avatar_whisper.bvh 7693f268-06c7-ea71-fa21-2b30d6533f8f -avatar_whistle.bvh b1ed7982-c68e-a982-7561-52a88a5298c0 -avatar_wink_hollywood.bvh c0c4030f-c02b-49de-24ba-2331f43fe41c -avatar_yes_happy.bvh b8c8b2a3-9008-1771-3bfc-90924955ab2d -avatar_yes_head.bvh 15dd911d-be82-2856-26db-27659b142875 -avatar_yoga_float.bvh 42ecd00b-9947-a97c-400a-bbc9174c7aeb -fringe.tga 8ac54e9d-ec09-d804-60ab-47404a9b4a36 -foot_shadow.tga 14e8a47d-1055-0a68-5d55-eafd9ad3da5b -img_smoke_poof.tga c734da52-f2ba-f0ba-d59e-15ea49f3d5e9 -img_shot.tga 173b05c7-53a9-4cf8-ce6b-5eec21c5c63f -folder_arrow.tga 09a324a8-acc1-d9cd-2cbd-7465d90d3a98 -color_swatch_alpha.tga f13db22f-c55c-8bdf-7b1c-221e56fde253 -script_error.tga e5a0ec29-f59e-d29e-2c59-ed66c187c26c -status_script_debug.tga 7775b5cc-93a5-6efd-0d9b-4e079afac217 -water_normal.tga 822ded49-9a6c-f61c-cb89-6df54f42cdf4 -icon_groupnotice.tga 21579c81-a85e-f11c-2d80-33a4c007d88c -icon_groupnoticeinventory.tga 8fcca699-08e7-3d58-2f05-86c9d52bbe82 -tab_background_lightgrey.tga c769e547-c307-43ca-2b6a-51cad6d1c527 -tab_background_purple.tga 0ae8a2e9-aff4-249c-fc4a-0f41f89847dd -tab_background_darkpurple.tga 38ff4f7e-3078-a749-8302-d6cc94b404c4 -smicon_warn.tga f47c17a3-8bfb-3c9f-22b8-77923de7eed9 -uv_test1.tga f43b75f5-9aa5-18ec-d5d9-e6d1b8442613 -uv_test2.tga 300ce95f-3d3f-7c1a-3a22-3fc48f873fb9 -eye_button_active.tga 2b42b375-f9b4-788e-46c7-7ef38762d0ba -eye_button_inactive.tga be1b7225-98b5-eb2a-2c86-ddaae3328a6e -account_id_blue.tga 6ab9179a-7308-58db-6c9d-893d3b52bece -account_id_orange.tga fbe89371-1251-4e77-d2d8-8eeccffe3ca8 -account_id_green.tga 3bf64d5a-38d3-b752-cf52-3d9f8fca353a -status_push.tga 07d1f523-e327-4d10-20d6-8bc22a6e8f56 -ff_visible_online.tga d609a41f-34c0-7aae-b2c6-2fc3ab26d916 -ff_visible_map.tga 20b52706-c1ab-414a-9dea-1cb788ad5689 -ff_edit_mine.tga 1baee0b9-4b89-39eb-8815-866d82300ab5 -ff_edit_theirs.tga 32e981cd-4700-da5a-7fc7-d573ec3742f4 -inv_item_script_dangerous.tga 0b502db8-6fcd-c442-ecfe-483a0dce875e -ff_visible_map_button.tga c1079bef-5cf9-90f3-6dcd-48989851c252 -ff_visible_online_button.tga 36749b47-93d6-2c5e-7ebd-d38d30311163 -ff_edit_theirs_button.tga ca229f65-d7e0-133e-1bc2-674abc33f3d5 -ff_edit_mine_button.tga 57f05b46-63d8-c3d5-66d6-8b915746b956 -ff_online_status_button.tga 3b1b6a53-9c8c-568a-22c5-2a8f3e5286f5 -oi_hud_cen_0_0.tga 3c650257-9caf-7cad-b26c-84c9eca560f1 -oi_hud_intro.tga 7611fb3d-9ff2-abd3-d98f-805c1c87e757 -oi_hud_underwater.tga cde61aea-83c2-3001-d598-6b348f7a8e0b -oi_hud_got_passport.tga 1271838d-d777-b811-7c4c-2a00308bd80a -oi_hud_texture_off_edge.tga 852be205-b1ea-6356-58c8-8c5ee5a841a6 -oi_hud_texture_on_edge.tga ab11e6ff-a732-be70-67df-c43131274562 -oi_hud_flyingabovewater.tga c9d150d6-2739-5f8b-cce6-3cf98242920a -oi_hud_walkingabovewater.tga 78284eeb-05f3-ff25-11a0-3cc9dbb30f0c -oi_hud_landmark.tga 6cd9c221-9d42-a283-256b-09a113a87271 -oi_hud_cus_5_3.tga 7c12f4fb-f502-26d1-a2f3-cdb6aff61663 -oi_hud_cus_5_2.tga c52c9c94-adc0-0f4e-6658-ed33d6ea8829 -oi_hud_cus_5_1.tga 9f6d5d11-6ca9-608c-e8a6-b77989350292 -oi_hud_cus_5_0.tga 2000cff1-119f-2023-66c0-ac5630d2f96e -oi_hud_cus_4_5.tga f302a935-ccd1-e2f5-3a38-e185cc262f3a -oi_hud_cus_4_3.tga af8d5b3c-b40f-cea5-b0b2-440fbd84a11a -oi_hud_cus_4_2.tga 11b26901-8207-12bc-5224-10a12ac4c651 -oi_hud_cus_4_1.tga 41baadb7-1b94-907e-9443-54e92bba77cd -oi_hud_cus_4_0.tga 9d627f8e-092c-5d32-6c12-ef76ab81cedc -oi_hud_cus_3_4.tga b196486e-d0d2-4fd7-529a-c84b4495fc74 -oi_hud_cus_3_2.tga 0b81c4bb-de33-e493-7bcb-e7221d97e5e7 -oi_hud_cus_3_1.tga 436dab74-25ae-8b60-c648-50663b7faa1d -oi_hud_cus_3_0.tga 6c1594de-1e66-273c-a2ab-8f0ffa8b4633 -oi_hud_cus_2_4.tga bb31fe48-8566-eec0-e96b-64025f832b63 -oi_hud_cus_2_2.tga c946959a-26ae-eb66-efa0-20154057789d -oi_hud_cus_2_1.tga c946959a-26ae-eb66-efa0-20154057789d -oi_hud_cus_2_0.tga d7833106-b4a8-7666-bde1-64886de289f9 -oi_hud_cus_1_0.tga 811ded22-5940-940c-4821-6fbbfb6611d6 -oi_hud_cus_1_1.tga eda8513b-a343-5109-1fd6-f1c7ad89b703 -oi_hud_cus_1_2.tga 7a4ce18c-e715-34d4-dfee-704c270a8ac8 -oi_hud_cus_1_4.tga d3771c15-ac03-b762-b992-d9fd2fedf38a -oi_hud_com_4_4.tga d9e1e90d-3cc3-6269-128e-67f7a2b32d26 -oi_hud_com_4_2.tga 0f649a26-6fdb-c73b-ffac-e50fc311d5ce -oi_hud_com_4_1.tga ae5b1ce6-a2d2-22d2-f532-6280b3bc6adb -oi_hud_com_4_0.tga 12cda3a0-58c7-dfa8-7f9b-380e5bb8baf9 -oi_hud_com_3_4.tga ff326257-0530-356a-e0f8-be535044e540 -oi_hud_com_3_2.tga 66740ddb-1d56-89f9-f0c9-ae5eb7bb9537 -oi_hud_com_3_1.tga 55d662f4-6a28-6388-7c75-af1c9fd33055 -oi_hud_com_3_0.tga de9d318f-b69e-82f9-0c61-43b868c5ca6b -oi_hud_com_2_4.tga 01d47e68-400a-d0e1-afb7-d6806d1d477e -oi_hud_com_2_0.tga 09c98850-27d4-6a12-abae-4af4bba23b6b -oi_hud_com_1_3.tga 5c2049b9-f797-6608-ca71-758f3716aa90 -oi_hud_com_1_1.tga 1116ff68-cdc4-1cfc-e137-30f8426afeda -oi_hud_com_1_0.tga bd847d31-f5af-95f7-2b9c-af47d8ba53bd -oi_hud_nav_4_5.tga 66194280-b087-db94-35d9-41e8f7518515 -oi_hud_nav_4_4.tga 180c4241-e309-4c05-13ee-9080ab69498d -oi_hud_nav_4_3.tga e98a6ba6-99c6-fa15-84b6-9afadea6c467 -oi_hud_nav_4_2.tga 2e19f352-1893-59a9-949b-4d2cfd3a8222 -oi_hud_nav_4_1.tga 13a1675b-fb5a-19b3-b5a3-74b0a6765f7d -oi_hud_nav_4_0.tga e7526e8d-b085-b26c-b0ae-2708ec231401 -oi_hud_nav_3_5.tga 5e67b0d0-29a2-6a08-c85e-b12d59e53d6e -oi_hud_nav_3_4.tga 2ed8fbc2-5c4d-53c2-b289-88baffceab1a -oi_hud_nav_3_3.tga e0a72f1a-282e-1c1a-2cb7-6423feb41759 -oi_hud_nav_3_2.tga 4bcebb23-da5e-47d9-eac1-e4453f762c8c -oi_hud_nav_3_1.tga 6ac87575-330e-3a2d-3b80-a34e7b277e50 -oi_hud_nav_3_0.tga f1451e8e-7310-9152-47d5-5d037c28fef3 -oi_hud_nav_2_6.tga c60b42ff-ee60-98e4-e603-ca2470141d4b -oi_hud_nav_2_5.tga a02b5a1a-bbdb-5556-ae5b-a2e68494755a -oi_hud_nav_2_4.tga 625535ab-8abf-b3e7-48fb-43f728b77c79 -oi_hud_nav_2_3.tga 00a609c3-5750-3b5a-3ce3-458bdf632203 -oi_hud_nav_2_2.tga 94903387-d37f-092c-e4d2-c190f68577b8 -oi_hud_nav_2_1.tga ee0cd82c-6ce8-8e73-307b-6d0dc77b19e8 -oi_hud_nav_2_0.tga 3e10b379-ed2c-7424-1fe7-bef3558c7536 -oi_hud_nav_1_4.tga bf8d0be8-2012-1664-3ea5-e69a71c206e9 -oi_hud_nav_1_2.tga 72100f87-18a7-fc4a-4793-de281e8b02cc -oi_hud_nav_1_1.tga b048faf3-60ce-c3a2-d034-36613449d377 -oi_hud_nav_1_0.tga 0ad45106-3b26-6448-0b90-feae8bd46c38 -oi_hud_mov_4_5.tga 7c4a45c2-37dd-312c-c6ab-20896dd0a5a6 -oi_hud_mov_4_3.tga 8a88da1c-3735-c71e-d48a-016df0798de4 -oi_hud_mov_4_2.tga f55ae4d3-7d6a-e6ac-4cf7-03014ce14390 -oi_hud_mov_4_1.tga 1cc3fcf1-35c0-e222-27d2-6905cf5c4cee -oi_hud_mov_4_0.tga 1ae592dc-46f4-616e-b7c6-0dff3e6f40e5 -oi_hud_mov_3_4.tga 831b39be-99fc-45bd-ba85-708f9dc93bfd -oi_hud_mov_3_2.tga 9f7e7373-92a9-d66a-ad5a-afb55ca6ac1f -oi_hud_mov_3_1.tga ab37ed0d-7e66-1f77-3acf-b0fe4b74dbe8 -oi_hud_mov_3_0.tga f5ff1f08-4c92-8606-1854-cc5b9d3e445c -oi_hud_mov_1_2.tga 1e3abeed-e893-c44e-1f9d-5ecc76d21e5d -oi_hud_mov_1_0.tga e300fc95-aa94-8e31-c501-ce903cac8b7c diff --git a/linden/indra/newview/app_settings/viewerart.xml b/linden/indra/newview/app_settings/viewerart.xml index dbd2227..d56efea 100644 --- a/linden/indra/newview/app_settings/viewerart.xml +++ b/linden/indra/newview/app_settings/viewerart.xml @@ -1,282 +1,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - @@ -391,114 +113,4 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/linden/indra/newview/character/avatar_lad.xml b/linden/indra/newview/character/avatar_lad.xml index 8038983..3b81fa2 100644 --- a/linden/indra/newview/character/avatar_lad.xml +++ b/linden/indra/newview/character/avatar_lad.xml @@ -1,7 +1,9 @@ + wearable_definition_version="22"> + + - - Advanced Second Life Skills - - - -
-You've learned the basics and spent a little time exploring Second Life. -

-To get the most out of this world, you'll want to learn a few more simple things and have a few more new experiences. -

-The different topics below are arranged to be easiest if you follow them in order, first to last. But it's your life. Do what you want. However you choose to proceed, take your time and play along the way. -

-The Lay of the Land -- Get an overview of the world where you live your Second Life, and find out where to go for a good time. -

-Getting Around: Navigation and Landmarks -- Learn some tricks for navigation around the world. -

-Nesting -- Find a place to call home and buy some land. -

-Home Time -- Buy a house, then decorate it. -

-Personalize Your Home -- A little paint and wallpaper goes a long way. -

-The Second Life Economy -- A little more information about how the money system works in Second Life. -

-Shopping 201 -- Pick up some furnishings for your new home. -

-People -- Find people you know and people and groups you may want to meet. -

-More Ways to Communicate -- Gestures, sounds and shortcuts will spruce up and speed up your conversations. -

-Clothing Makes the Avatar -- Go deeper into Avatar customization and create your own look. -

-Party Time -- Time to go dancing and meet some new people. -

-Dangerous Time -- Jessie is where you can play the deadliest game. -

-Creation 101 -- Some basics on creating and building new things in Second Life. -

-Graduation -- Congrats on a job well done, and where to go if you want to learn even more. -

-[ Next ] - - - - diff --git a/linden/indra/newview/help/Advanced/Building_the_Lamp_Base.html b/linden/indra/newview/help/Advanced/Building_the_Lamp_Base.html deleted file mode 100644 index 07edd57..0000000 --- a/linden/indra/newview/help/Advanced/Building_the_Lamp_Base.html +++ /dev/null @@ -1,68 +0,0 @@ - - - - Creation 101: Building the Lamp Base - - - -
-Let's start by building the lamp's base. -

-1. You should be at your home, or a nice, flat area, with the model lamp nearby. -

-2. Click on the ground near the model lamp. -

-3. When the pie menu opens, select Create. -

-A few things happen: the view focuses on the ground where you clicked, the cursor changes to the creation wand, and the Tool palette opens. -

-On the Tool palette are a number of shapes you can create. We want the box shape on the far left. -

-4. Click on the box shape in the tool palette. -

-5. Click on the ground to create a box. -

-The default box has been created. We'll want to change it. -

-6. Click on the box you just created to make sure it's selected. -

-7. Click on the More button in the Tool Palette. -

-The Tool Palette expands. -

-8. Click on the Object tab in the Tool Palette. -

-The Tool Palette now shows a lot of controls for changing the box. It looks complicated, but we'll only deal with a few of the controls at a time. -

-9. Find the Size (meters) controls. -

-10. Change the number in the Z Size control to 0.100. -

-You can do this with the arrows, or highlight the number that's there and type in a new one. -

-Now let's change the material that the box is made of. -

-11. Find the Material drop-down menu at the bottom of the Tool Palette. -

-12. Click on the Material menu and select Metal. -

-It looks like nothing has happened. That's OK. You've changed the material of the box, so it will act like metal, but it still has the wood texture. In Second Life, you can put any texture on any material. This gives you as much flexibility as possible. -

-So, let's make the metal box look like metal. -

-13. Click on the Texture tab in the Tool Palette. -

-14. Click on the picture of the wooden texture. -

-The Pick: Texture dialog opens. -

-15. Click on the drop-down menu (it should say Default), and choose Steel Plate, then click OK. -

-The look of the box now changes -

-Steel Plate is the texture used in the model lamp, but you can pick any other texture that you prefer. Take some time if you like and try out a few different textures. Once you pick one that you like, move on to the next step. -

-[ Advanced Skills Home | Creation 101 Home | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Building_the_Lamp_Bulb.html b/linden/indra/newview/help/Advanced/Building_the_Lamp_Bulb.html deleted file mode 100644 index 11e3537..0000000 --- a/linden/indra/newview/help/Advanced/Building_the_Lamp_Bulb.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - Creation 101: Building the Lamp Bulb - - - -
-Now let's build the bulb. -

-1. Click on the Create icon in the Tool Palette. -

-2. Click on the half-sphere icon (top row, far right). -

-3. Click on the ground near your lamp base and pole. -

-The default size will work just fine, so we won't have to change that, but we'll want to -change the material. -

-4. Click on the Edit icon in the Tool Palette, then make sure the new half-sphere is selected. -

-5. Click on the Object tab,then click on the Material drop-down, and then select Light. -

-Now you've got what looks like a glowing piece of wood. Let's change the texture to get something that looks more like a light bulb. -

-6. Click on the Texture tab, then click on the wood texture to open the Pick: Texture dialog. -

-7. Click on the White button, then click OK. -

-You now have a white, glowing bulb. -

-Now, let's move the bulb into place on top of the pole. -

-8. Click on the Edit icon, then on the bulb, then drag the three arrows and place the half-sphere on top of the pole. -

-Again, moving things around in 3-D is tricky. Be patient and don't be afraid to use the Focus tool and move the camera around so you can see things at different angles. -

-After futzing with placing the bulb for a while, it may occur to you that there has to be a more exact way to do this. There is: by using the Position controls in the Object tab. -

-[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Building_the_Lamp_Pole.html b/linden/indra/newview/help/Advanced/Building_the_Lamp_Pole.html deleted file mode 100644 index 80c600c..0000000 --- a/linden/indra/newview/help/Advanced/Building_the_Lamp_Pole.html +++ /dev/null @@ -1,43 +0,0 @@ - - - - Creation 101: Building the Lamp Pole - - - -
-Now we'll build the lamp's pole. -

-1. Click on the Create button in the Tool Palette. -

-2. Click on the Cylinder button (top row, 5th from the left). -

-3. Click on the ground near the lamp base you made. -

-4. Click on the Object tab in the Tool Palette. -

-5. Change the X Size to 0.100, change the Y Size to 0.100, and change the Z Size to 2.000. -

-6. Change the pole's Material to Metal. -

-7. Change the pole's texture to match the base. -

-Now we need to move the pole to the center of the base. Moving things in 3-D is tricky, so be patient. -

-You may find that you'll need to change your view at times. To change your view at any time, click on the Focus icon, and move the camera around until you can see what you want. (We learned how to do this earlier--it works just like using the Focus On feature from the pie menu.) -

-8. Click on the Edit icon in the Tool Palette. -

-9. Click on the pole. -

-Now you'll see red, green and blue arrows. These are axes (plural of axis). You can move things around be dragging these arrows. -

-10. Drag the up-pointing blue arrow until the pole is just resting on the ground (not half-buried). -

-11. Drag the red and green arrows to place the pole right in the middle of the base. -

- -[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Clothing_Makes_the_Avatar.html b/linden/indra/newview/help/Advanced/Clothing_Makes_the_Avatar.html deleted file mode 100644 index d370e01..0000000 --- a/linden/indra/newview/help/Advanced/Clothing_Makes_the_Avatar.html +++ /dev/null @@ -1,73 +0,0 @@ - - - Clothing Makes the Avatar - - - -
-Soon, we'll be going out for a party. We need a new outfit for the occasion. -

-1. Click on your avatar, then click on Appearance.... -

-2. Click on the Make Outfit button at the bottom of the Appearance dialog. -

-Another dialog opens. -

-3. Under Folder name: type in Everyday Clothes. -

-You'll notice that you can choose to include your avatar's Shape, Skin, Hair and Eyes in the new outfit as well as clothes. This lets you not only instantly change clothes, but also change the entire look of your avatar any time you want. -

-For now, let's only include Hair, Eyes, Shirt, Pants, Shoes, Socks and Jacket. You can always modify other things later. -

-4. Check the boxes next to Hair, Eyes, Shirt, Pants, Shoes, Socks and Jacket, then click Save. -

-We have now saved the complete current outfit that we're wearing, so we can return to it instantly at any time. -

-5. Click on the Make Outfit button again. -

-6. Under Folder name: type in Party Clothes and click Save. -

-Now, we have a duplicate set of clothes that we can modify. Let's create our new party outfit, starting with the jacket. -

-7. Click on the Shirt button on the left side of the Appearance dialog. -

-8. Click on the Upper Fabric square. -

-A small dialog opens, displaying a swatch of the current jacket fabric. -

-9. Click on the pop-up menu just below the swatch, and choose a new fabric for your jacket, then click OK. -

-10. Try on a few fabrics, then choose one to keep. -

-11. Choose a Fabric for the jacket's Lower Fabric. -

-It can be the same as the Upper Fabric, or different, depending on your personal preference. -

-12. Now play with the sliders to adjust the look and fit of the jacket. -

-13. Change your shirt, pants, shoes and socks in the same way. -

-14. Now, give yourself a new hairdo and a custom eye color. -

-15. When you're all done modifying your outfit, click on the Save All button. -

-You have now saved all of the recent modifications into your Inventory. -

-Let's see how easy it is to change. -

-16. Open the Inventory and then open the Clothing folder. -

-17. Drag the Everyday Clothes folder out of your Inventory and onto your avatar. -

-Everything should change -- even the hairstyle and eye color. -

-18. Drag the Party Clothes folder out of your Inventory and onto your avatar. -

-You've instantly changed back into your party clothes, and you're ready for a night on the town. - -

-[ Advanced Skills Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Advanced/Creation_101.html b/linden/indra/newview/help/Advanced/Creation_101.html deleted file mode 100644 index d2f26c7..0000000 --- a/linden/indra/newview/help/Advanced/Creation_101.html +++ /dev/null @@ -1,53 +0,0 @@ - - - Creation 101 - - - -
-Pretty soon, you'll want or need something that you can't find. Or maybe you'll just have an urge to make your mark in this life. Either way, you'll reach a point where you'll want to learn how to build things in Second Life. -

-In this, the last of the Advanced Second Life Skills, we'll create a simple floor lamp for your home. Then we'll use scripting to turn the light on and off in a couple of ways. -

-To help guide you as you build the lamp, we've put a model in your Inventory. -

-1. Go to your home, or find a nice, flat area to build your lamp. -

-You can build on your own land, or on public land. You can only build on someone else's land if they give you permission. -

-2. Open your Inventory. -

-3. Open the Objects folder. -

-4. Open the Household folder. -

-5. Find the Floor Lamp, and drag it out of your Inventory and onto the ground near you. -

-As you can see, the lamp is made of three parts, each of which is a different shape: a square base, a cylindrical pole, and a half-spherical globe (the part that lights up). -

-You'll also notice that the lamp isn't very beautiful -- but it's nice and simple, so it makes a good first project. -

-6. Click on the lamp's globe. -

-The light turns off. -

-7. Click on the lamp's globe again. -

-The light turns on. -

-8. Hit Enter (Return), type "off" then hit Enter again. -

-The light turns off. -

-9. Hit Enter (Return), type "on" then hit Enter again. -

-The light turns on. -

-As you can see, the lamp is reasonably functional. - -Click next to begin building your own version of the lamp. -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Dangerous_Time.html b/linden/indra/newview/help/Advanced/Dangerous_Time.html deleted file mode 100644 index 7793d6c..0000000 --- a/linden/indra/newview/help/Advanced/Dangerous_Time.html +++ /dev/null @@ -1,37 +0,0 @@ - - - Dangerous Time - - - -
-Now let's visit Jessie and see how much danger we can handle. -

-1. Navigate your way to the Jessie Wall and cross over. -

-Once you enter Jessie, you'll notice that your health rating appears in the lower-left corner of the screen. That means your avatar can be damaged or killed here. Be careful. -

- -

-2. Buy a gun or other weapon. -

-3. The use of your weapon will very from type to type -- most come with an instructional Notecard detailing proper operation. -

-The most efficient way to maneuver and fire weapons is in Mouselook. -

-4. Press the M key on your keyboard to enter Mouselook mode. -

-In general, you'll use the keyboard's W and S keys to move forward and backward, and use the mouse to steer. If you haven't moved around in Mouselook before, you may want to practice a little. -

-One more thing you'll need to know: you also aim the gun with the mouse, and press the left mouse button to fire. -

-5. Wander around in Mouselook and take some practice shots. -

-6. Once you feel secure that you can move, aim, and shoot, head deep into Jessie. -

-You can stay and play if you want, otherwise click Next below to leap from destruction to creation and learn how to build things in Second Life. -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Getting_Around.html b/linden/indra/newview/help/Advanced/Getting_Around.html deleted file mode 100644 index b100cfd..0000000 --- a/linden/indra/newview/help/Advanced/Getting_Around.html +++ /dev/null @@ -1,29 +0,0 @@ - - - Getting Around: Navigation and Landmarks - - - -
-Open the World Map and double-click any place the looks interesting; your avatar will teleport to the Telehub closest to your chosen location. -

-Fly down from the Telehub and choose a spot that you'd like to explore more in the future. -

-Now, let's make a landmark so that you can find your way back again later. -

-12. Open the World menu and select Create Landmark Here. -

-Your Inventory will open if (it's not already open), and a new landmark, called New Landmark, is there and highlighted. -

-13. Right-click on the New Landmark, and select Rename. -

-14. Type in a new name for the landmark, something the describes the place, and hit Enter (Return). -

-Now you have a new landmark to use any time you want. -

-When you use your landmark, you'll be teleported to the nearest Telehub location. From there, turn your avatar until you see the red beacon and follow it to the final destination. -[ Advanced Skills Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Advanced/Graduation.html b/linden/indra/newview/help/Advanced/Graduation.html deleted file mode 100644 index 15cd03f..0000000 --- a/linden/indra/newview/help/Advanced/Graduation.html +++ /dev/null @@ -1,29 +0,0 @@ - - - Graduation - - - -
-You've now absorbed the Advanced Second Life Skills. -

-For many, if not most, this is all you'll want or need to live our your Second Life. -

-But more information is available for those of you who really want to learn how to build things and write scripts: -

-Script Help ... in the Help menu provides a complete reference to the Second Life Scripting Language. -

-You can find even more scripting information in the Scripting Wiki, a document constantly updated and added to by Second Life resident scripters. -

-Even more information on various parts of the Second Life world can be found in the general Support Wiki at http://secondlife.com/help. -

-More documents in PDF format are available on the Second Life Members website, under the Downloads menu. -

-Possibly the best resources for learning are the Forums at Secondlife.com, where you can ask questions and get answers. You can also see what others have been asking about. -

-Have a nice life. -

-[ Advanced Skills Home | Previous ] - - - diff --git a/linden/indra/newview/help/Advanced/Home_Time.html b/linden/indra/newview/help/Advanced/Home_Time.html deleted file mode 100644 index feb44a9..0000000 --- a/linden/indra/newview/help/Advanced/Home_Time.html +++ /dev/null @@ -1,29 +0,0 @@ - - - Home Time - - - -
-Now that you have some land, you need a house to put there. -

-Fortunately, there's a cozy little basic cabin in your Inventory, ready to build. This cabin isn't very big or fancy. And you'll see a number of them around. -

-But you can do a lot of customizing to make it more original. And once you learn the ways of the world and as you participate more in the Second Life economy, you'll be able to afford to buy a much nicer house -- or design and build your own. -

-1. Open your Inventory and open the Objects folder. -

-2. Find the object called "Cabin, Little," and drag it out of your Inventory and onto your land. -

-Technically -- and this is an important point to understand -- the cabin itself wasn't in your inventory -- just the design for the cabin. When you pull that design out of your inventory and place it on the ground, it is then built. We'll discuss this in a minute. -

-3. Click on the cabin and select Edit from the pie menu. -

-4. Drag the cabin around by the arrows to place it exactly where you want it. (Don't forget to adjust it up and down.) -

-Once your new cabin is in place, click on next to take the next step -- customizing and personalizing your new home. -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Installing_a_Script.html b/linden/indra/newview/help/Advanced/Installing_a_Script.html deleted file mode 100644 index 7e8bc14..0000000 --- a/linden/indra/newview/help/Advanced/Installing_a_Script.html +++ /dev/null @@ -1,73 +0,0 @@ - - - Creation 101: Installing a Script - - - -
-The Second Life scripting language is very powerful. It lets you add more functionality and interactivity to everything you build. -

-If you're a programmer or are familiar with other scripting languages, you'll have no trouble learning the Second Life scripting language. A complete reference to the scripting language can be found in the Help menu. -

-Even if you're not a programmer and you have no interest in learning to write scripts, you can still make use of them in your creations. -

-If you need something complex or special scriptwise, there will be people to write it for you -- for a certain amount of Linden Dollars. -

-But for simple things -- especially common ones like turning lights on and off -- there are scripts available for the taking. A number of useful scripts can be found in your Inventory. -

-A good way to get scripts is to copy them from objects that already have them. As you travel through your Second Life, you'll find things that you like, some of which have scripts that you can take. -

-When someone creates something, with or without a script, they can set the permissions either so people can or can't copy any or all of it. You'll no doubt find cool things that you can't copy, but many of things can be copied and you'll have access to copy the scripts, as well. -

-Obviously, the model lamp has exactly the script you need for your lamp. Let's take the script out, then add it to our new lamp. -

-The script you want is actually attached to the bulb of the model lamp. To access that single part, we'll first have to Unlink the lamp's parts. -

-1. Click on the model lamp to select it. -

-2. Open the Tools menu (the Tools menu at the top of the screen, not the Tool Palette) and select Unlink. -

-3. Click on the ground near the model lamp to unselect it, then click on the bulb. -

-4. Click on the Content tab of the Tool Palette. -

-You should see a couple of button sounds and a script called LightScript in the contents. -

-5. Drag the script into the Scripts folder of your Inventory. -

-6. Now, click on the bulb of your new lamp. -

-You should see an empty Contents tab in the Tool Palette. -

-7. Drag LightScript from the Scripts folder of your Inventory into the Contents folder in the Tool Palette. -

-The script is installed. It's that simple. -

-This script also plays sounds -- button clicks -- when the lamp turns on and off. So we'll also add those two sounds to the Contents folder (so the script can access them). We could have copied them from the other lamp, but since they're common sounds used by a number of things, they're already in your Inventory in the Sounds folder. -

-8. In your Inventory, open the Sounds folder, and drag both Button_click_down and Button_click_up into the Contents folder. -

-9. Close the Tool Palette to get out of Edit view. -

-10. Click on the bulb of your new lamp. -

-The bulb should turn off. -

-11. Click on it again. -

-The bulb turns on. -

-12. Hit Enter (Return) and type "off", and hit Enter again. -

-Again, the light turns off. -

-13. Hit Enter (Return) and type "on", and hit Enter again. -

-And again, the light turns on. -

-Next, let's take a look at a script and learn how we can easily modify it. -

-[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Modifying_a_Script.html b/linden/indra/newview/help/Advanced/Modifying_a_Script.html deleted file mode 100644 index 9ae2137..0000000 --- a/linden/indra/newview/help/Advanced/Modifying_a_Script.html +++ /dev/null @@ -1,74 +0,0 @@ - - - Creation 101: Modifying a Script - - - -
-Now, we'll open up LightScript, look through it and make a small customization. -

-1. Right-click on your lamp's bulb, and select Edit from the pie menu. -

-The reason you have to right-click to select the bulb is because it has a script that has taken over the left click to turn the light on and off. -

-2. Look at the Content tab of the Tool Palette. -

-3. Double-click on LightScript. -

-A new window opens, showing the script. It may look complicated if you've never played with scripts before, but it's really not hard at all to understand enough to make a few useful changes. -

-4. Read through the script and see if any of it makes sense to you. -

-Lines of text that begin with // are comments. They aren't actually part of the code -- they're there to explain what's going on. A well-written script will have good, clear comments that explain how the script works. -

-5. Look for the lines that start with llListen. -

-Near the end of one, there's the word "on" and near the end of the other is the word "off". -

-These lines tell the light bulb to look for the words on and off to turn itself on and off. -

-One simple modification that we can do without understand the script at all is to change the words that turn the lamp on and off. -

-Why bother? For a light, there's not really much of a reason to change the activating words, but you could modify a script for a door in the same way, setting up a password for entry that only you and your friends will know. -

-6. In the lines that begin with llListen, change the word "on" to "light", and the word "off" to "dark". (You can use any other code words you want.) -

-There's one more place you have to modify: -

-7. Scroll down the script to the line that says if (text = "on"), and change "on" to "light" (or whatever other code word you chose). -

-8. Click the Save button. -

-9. Close the Script window and the Tool Palette. -

-10.Test your lamp with the new words for on and off. -

-Now that you've created a masterpiece, it's time to link it together and save it to your Inventory. -

-11. Right-click on one part of the lamp and select Edit from the pie menu. -

-12. Hold down the Shift key and click on the other two parts of the lamp,so they're all highlighted. -

-13. Open the Tools menu and select Link. -

-The lamp is now all linked together, so you can move the whole thing around instead of having to move each piece separately. -

-14. With the lamp still highlighted, open the Tools menu and select Take Copy of Object. -

-A copy of the lamp will be placed in the Objects folder of your Inventory. -

-15. Right-click on the new object (named Object) in your Inventory, and select Rename. -

-16. Type in a new name, like "My Floor Lamp". -

-17. Drag the newly named lamp from the Objects folder into the Furniture folder. -

-18. Now you can delete both the model lamp and the lamp you made. -

-You can pull them out of your Inventory any time you need them. -

- -[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/More_Ways_to_Communicate.html b/linden/indra/newview/help/Advanced/More_Ways_to_Communicate.html deleted file mode 100644 index 15c66c2..0000000 --- a/linden/indra/newview/help/Advanced/More_Ways_to_Communicate.html +++ /dev/null @@ -1,55 +0,0 @@ - - - More Ways to Communicate - - - -
-Chat is great. But it could be a little more flexible and a little more expressive. In Second life, it is. -

-You can expand your chat capabilities through shortcuts, gestures, sounds and even words. -

-1. Hold down the ALT key and click on your avatar to Focus on yourself. -

-2. Move the camera around so you can see yourself from the front. -

-3. Hit the F2 key. -

-What happened? -

-4. One at a time, hit the F3 through F12 keys. -

-5. Now, one at a time, hit shift-F2 through shift-F12. -

-6. And now hit ctrl-F2 through ctrl-F12. -

-All of these motions, expressions, sounds and chat are preset -- but they can easily be changed in any way you want. -

-You can delete the ones you don't want, to free up F-keys for ones you do want. You can set up your shortcuts to chat any text you want. You can even upload your own sounds -- even your own voice -- and have your avatar say anything you want. The Gesture Starter menu on the chat bar is another way to activate gestures. -

-Let's look behind the curtain and see how this works and how to change it. -

-7. Press CTRL-G to open the Gestures window -

-As you've seen, you can activate gestures (and sounds and text) either through the F-Keys or by typing things into Chat. -

-The left column is where you enter the Chat Input -- whatever you want to use as the trigger to set off the gesture. You can put your Chat Input shortcut in the middle of a regular chat sentence, or use it by itself. -

-Chat Input is case-sensitive. That means if you set "Hi" as the Chat Input for, "Hello there! I'm pleased to meet you," this message will not be sent if you type in "hi" or "HI." -

-Notice that some of the Chat Inputs begin with a forward slash (/). This stops your avatar from performing the Chat typing animation while you're typing in your message. When you're chatting, this animation lets others know that you're busily typing away. But there are times when you might not want to play the animation -- like while dancing. -

-You don't need to have a Chat Input if you have a Shortcut Key, but it doesn't hurt to have both. -

-Speaking of Shortcut Keys, the next two columns are for choosing them. Your choices are all the F-keys -- except F1, which is for Help -- by themselves, and with the shift keys and the control keys. -

-That's a total of 33 possible shortcut key combinations you can use. But with the Chat Input, you have an almost unlimited amount of shortcuts for animations, sounds and Chat Output. -

-You choose the sound you want to play with the Sound pop-up menu. All the sounds in your Inventory are listed here. If you record your own sounds and upload them, they'll automatically appear here. You can upload an unlimited number of sounds, but they need to be less than 10 seconds long. -

-Animations are also chosen with a drop-down menu. Many animations are supplied, and more will find their way into your Inventory over time, so check the list every so often to see if any new ones have appeared. -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Nesting.html b/linden/indra/newview/help/Advanced/Nesting.html deleted file mode 100644 index a2ab004..0000000 --- a/linden/indra/newview/help/Advanced/Nesting.html +++ /dev/null @@ -1,74 +0,0 @@ - - - Nesting - - - -
-It's time to find yourself a home. -

-You've flown all over the world and seen some of the sights. Think about all the places you've been. It makes sense to make your home near your favorite activities. That way, you'll spend less time commuting, and less money if you teleport. -

-You can always change your home later if you decide to move. -

-Look at the map and decide on a general area you'd like to call home. Using the "Land You Can Buy" selection from the Background pull down menu in the World Map window will help you find areas with available land. Premium Access members can own up to 512 square meters of land before incurring additional land fees; Basic Access users will be advised that they need to pay additional fees in order to own land. -

-Once you've found a likely area, find out what land is available. -

-Open the View menu at the top of your screen and activate the view Land Owners function. -

-Land that's owned by others will be marked with a brightly colored overlay. Land that isn't colored is open to you. -

-Wander around and pick a nice little spot that you like. -

-Land costs money to buy, so don't overextend yourself. Just pick out a nice little plot. -

-Click on the land you want to buy. -

-A pie menu will open. -

-Choose Edit Land ... -

-A small parcel of land -- 4 by 4 meters by default -- will be marked off, and a tool panel will open. -

-We'll want a little more land than what's marked, so: -

-Click and drag on the land to mark out a rectangle that's at least 12 by 12 meters. -

-Land is parceled out in 4 by 4 meter chunks, so if you make a rectangle that's 3 by 3 chunks, that'll be 12 by 12 meters. 12 by 12 is the minimum size you'll want to have room to place a small house and have a little room for a yard or garden. -

-Click on the Claim Land ... button in the tool panel to buy the land. -

-A dialog will open, giving details of the sale, including the cost to claim and any changes to your billing required to claim the land. -

-Click on the Claim button. -

-Your account will be deducted for the sale. If claiming the land changes your billing, you'll need to approve the transaction in a confirmation email before the land is added to your account. -

-YOu can locate your land at anytime using the My Land tool located in World menu at the top of your screen. -

-Now let's mark this land as your Home. -

-Hit Esc to close the tool panel, then move your avatar onto your land. -

-Open the World menu and select Set Home to Here. -

-Now your newly purchased land has been set as your home location. -

-Because this is your "official" home (at least for now), whenever you enter Second Life, you have the option to enter here (or enter at the last place you were last time you were in-world). -

-If the land isn't flat, let's flatten it to prepare it for a house. (If it is flat, skip to the next help screen.) -

-Fly your avatar up and position it so you can see your whole parcel of land. -

-Click on the land and select Edit Land ... in the pie menu. -

-In the tool panel, click on Flatten Land. -

-Slowly move the cursor over your land until it's fairly flat. -

-It doesn't have to be perfect, just "flattish," so you can plop down a house there. -

-[ Advanced Skills Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/Advanced/Party_Time.html b/linden/indra/newview/help/Advanced/Party_Time.html deleted file mode 100644 index b7d5130..0000000 --- a/linden/indra/newview/help/Advanced/Party_Time.html +++ /dev/null @@ -1,23 +0,0 @@ - - - Party Time - - - -
-Now it's time to find a party. -

-1. Open the Events window by clicking the Events button at the bottom of your screen. -

-2. Look at the events listed and find one that's happening now or is about to start. If there isn't an event going on right now, find one that you might want to attend later. -

-3. Once you've selected an event, you can select Teleport to get there quickly or you can select Map to have the event location tracked in the World Map window. -

-4. Depending on the type of event, you might need to find a seat and enjoy the show, or you could end up on stage performing! Take your lead from other attendees, and don't be afraid to ask your host if you have any questions. -

-Stay and enjoy the event until you're ready to move on, then click Next below to take a trip to Jessie. -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/People.html b/linden/indra/newview/help/Advanced/People.html deleted file mode 100644 index 5808753..0000000 --- a/linden/indra/newview/help/Advanced/People.html +++ /dev/null @@ -1,40 +0,0 @@ - - - People - - - -
-Spending time with other people is one of the joys of life. And it's just as true in your Second Life. -

-So how do you find people? -

-People who you've met -- and exchanged calling cards with -- are easy to find, if they're in-world. -

-1. Make sure the World Map window is open. -

-2. Click on the Person Tracking pull-down menu (just above the Landmark pull-down) on the right side of the window. -

-A list of people shows up. Names only show up here if they're on your Friends list, and only if that Resident is currently in-world. -

-3. Choose a name on the list, then look at the Map. -

-Your friend will be shown on the map as a red circle. -

-4. Back in the main Second Life window, fly up a ways and turn around until you see a red beacon. -

-This beacon works just like the landmark beacon. You can find it and follow it to your friend. You can also click on the Teleport or Fly button in the World Map window to get to your friend more quickly. -

-Finding people you already know is easy. So, how do you find new friends? Use the Finder. -

-5. Click the Find button at the top of your screen to open the Finder -

-The Finder helps you to locate people in Second Life, and many other things as well. -

-If only our first lives were this easy. -

-[ Advanced Skills Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Advanced/Personalize_Your_Home.html b/linden/indra/newview/help/Advanced/Personalize_Your_Home.html deleted file mode 100644 index 24f2852..0000000 --- a/linden/indra/newview/help/Advanced/Personalize_Your_Home.html +++ /dev/null @@ -1,56 +0,0 @@ - - - Personalize Your Home - - - -
-Now let's personalize the cabin a little, by changing the flooring and painting the walls. -

-1. Walk into your cabin and take a look around. -

-It's nice and quaint. But we could upgrade that floor a little. -

-2. Make sure your Inventory is open, then open the Textures folder. -

-3. Now, open the Building Materials folder, and find Spanish Tile. -

-4. Drag Spanish Tile out of your Inventory and onto the floor of your cabin. -

-The floor is instantly converted to tile. -

-Now, let's do something with the walls. We could change the textures of the walls in the same way as we changed the floor, but let's try something else. -

-Let's keep that rough stucco-like texture, but paint a bit of a tint over it. -

-5. Click on one of the walls of the house, and select Edit from the pie menu. -

-Because the house is all linked so it can be easily moved around in a single piece, if you perform an editing function, like painting a wall, the whole house will be affected. So what we'll do is first select a single wall then paint it. -

-6. Click on Select Individual in the Tool Palette, then click on the wall you want to paint. -

-7. Click on the More >> button on the tool palette to expand the palette, then click on the Texture tab in the Tool Palette, and then click on the Color box. -

-The Color dialog opens. -

-8. Choose a nice, bold color -- click on an orange square on the left side of the Color dialog, then click OK. -

-The wall keeps the stucco-like feel, but is now painted orange. -

-Before we continue, let's look at what we did. We changed two things: Texture and Color. -

-Changing texture is picking a graphic file to apply to the surface of an object. It's like applying wallpaper, but without the glue, mess or Laurel and Hardy hijinks. -

-Color lets you modify the texture by tinting it almost any color. If you want a solid color, then first apply the White texture, then apply the color. -

-There's no cost for painting or applying textures, so you can modify your home (or other possessions) all you want without charge. (There is, however, a small, one-time fee o fL$10 to upload your own textures into the system.) -

-You can take your time now and continue to redecorate your home as much as you want by painting other walls (and the ceiling) or changing any or all of the textures. -

-Later, you'll be able to gather up some furniture and customize your house in other ways. -

-[ Advanced Skills Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Advanced/Positioning_with_Numbers.html b/linden/indra/newview/help/Advanced/Positioning_with_Numbers.html deleted file mode 100644 index 8af704a..0000000 --- a/linden/indra/newview/help/Advanced/Positioning_with_Numbers.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - Creation 101: Positioning with Numbers - - - -
-Let's use Position to perfectly align our three parts. What we'll do is copy the X and Y Position values from the base, and paste them into the X and Y position values of both the pole and the bulb. -

-1. Click on the Edit icon, then on the base, then on the Object tab. -

-2. Highlight and copy the X Position value. -

-3. Click on the pole, then highlight the X Position and paste in the value from the base. -

-4. Click on the bulb, highlight the X Position and paste in the value from the base. -

-5. Repeat the last four steps, but this time copy and paste the Y Position value from the base to both the pole and the bulb. -

-Now the three parts are exactly lined up and centered. Of course, you don't want to copy and paste the Z Position value, because you want the three parts to be different heights. -

-6. Adjust the heights of the three parts as needed. -

-[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Shopping_201.html b/linden/indra/newview/help/Advanced/Shopping_201.html deleted file mode 100644 index b45c396..0000000 --- a/linden/indra/newview/help/Advanced/Shopping_201.html +++ /dev/null @@ -1,47 +0,0 @@ - - - Shopping 201 - - - -
-Let's get some furniture for your new home. -

-You don't need much for now, just a place for guests to sit, and maybe a lamp or two. -

-1. Use the World Map window to find your way to the shopping mall in Luna. -

-2. Wander around the place and find a few things that you think will go well in your new home. -

-3. Click on one of the things you want to buy, then select Buy. -

-A confirmation dialog will open, giving the details of the transaction and the permissions involved. You'll notice that you are buying a copy, not the original. You'll also find out if you'll be able to modify or copy the thing you buy. -

-4. Click Buy. -

-A copy of the item will be put into your Inventory. -

-5. Return to your home, and go inside. -

-6. Open your inventory. Drag your new purchases out of inventory and into your home. -

-7. Click on one of the items, and select Edit from the pie menu. -

-8. Drag the item around by the arrows to place it where it belongs. -

-Chances are, you'll also need to rotate it. -

-9. In the tool panel, click on Rotate. -

-The arrows turn into rounded axes surrounding the item. -

-10. Drag the rounded axes to rotate the item to the proper position. -

-11. Place the other items you bought where you want them. -

-So, now you have a party pad. How do you find people to invite over? -

-[ Advanced Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/Simple_on_off.html b/linden/indra/newview/help/Advanced/Simple_on_off.html deleted file mode 100644 index bfa3e7b..0000000 --- a/linden/indra/newview/help/Advanced/Simple_on_off.html +++ /dev/null @@ -1,30 +0,0 @@ - - - - Creation 101: Simple On/Off - - - -
-So, we have a lamp, but how do we turn it off -- and then on again? -

-The most basic way would be to change the bulb's texture from white to black. The black texture blocks the light's glow. -

-1. Highlight the bulb, then click on the Edit icon, then the Texture tab. -

-2. Find and click on the Color control. -

-The Color dialog opens. You've seen this before. -

-3. Select black in the Color dialog (lower-left corner of the basic colors) and click OK. -

-The bulb is now black -- basically, off. If we wanted to turn it back on, all we have to do is change the color. What a pain. -

-There has to be an easier -- and better -- way. -

-There is: with a script. -

-[ Advanced Skills Home | Creation 101 Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/The_Lay_of_the_Land.html b/linden/indra/newview/help/Advanced/The_Lay_of_the_Land.html deleted file mode 100644 index 3db0d76..0000000 --- a/linden/indra/newview/help/Advanced/The_Lay_of_the_Land.html +++ /dev/null @@ -1,44 +0,0 @@ - - - The Lay of the Land - - - -
-Before going anywhere, let's get an overview of the Second Life world, and locate a few important places. -

-1. If the World Map window isn't open, click the Mini Map or click the Map button at the bottom of the screen to open it. -

-The World Map window isn't static -- it changes with the world, so every change to the land, every new building and every person within your avatar's sight is on the map. -

-In addition, the map in the Map window can be zoomed in and out. -

-The Map window can be used to track people and find landmarks, but only the names of regions are labeled. -

-Let's see what the World Map window can do for us. -

-2. Find the Zoom slider at the bottom right of the World Map window. -

-3. Move and enlarge the Map window so it fills most of the screen. -

-4. Zoom the map so you can see the entire Second Life world. Left-clicking and holding on the map allows you slide the map and center in on places of interest. -

-5. Examine the map and find the following places: -

-- Welcome Area in Ahern -- this is where new residents enter Second Life.
-- The Sandbox in Cordova -- a place where any resident can freely build and experiment. (Sandboxes are cleared twice daily; any object left behind is deleted.)
-- Jessie -- a damage-enable area for wargaming.
-- Busy Ben's Hoverboard Ranch in Oak Grove -- A vehicle dealership with easy access to the Vehicle Recreation Area. -

-You can freely build in the Sandbox areas. If you want to build something (like a home) that will stay inworld permanently, you may want to own your own land. Be sure to check out http://secondlife.com/land/ for all the details behind land ownership. -

-As you travel across the world in the next steps, look over the areas you cross as potential homesites. You can use the tabs at the top of the Map to display land that has recently been marked For Sale. -

-6. Zoom the map smaller and shrink the Map window a bit, then close it. -

-7. Click Next to continue. -

-[ Advanced Skills Home | Next ] - - - diff --git a/linden/indra/newview/help/Advanced/The_Second_Life_Economy.html b/linden/indra/newview/help/Advanced/The_Second_Life_Economy.html deleted file mode 100644 index 2f483a3..0000000 --- a/linden/indra/newview/help/Advanced/The_Second_Life_Economy.html +++ /dev/null @@ -1,18 +0,0 @@ - - - The Second Life Economy - - - -
-Earning Money -Second Life is an entrepreneurial world. You can create your own segment of the economy; create new goods and services that other inhabitants will be willing to pay for. Your creativity in simulated business can be as important -- and fun -- as your creativity in other aspects of Second Life. -

-Every Second Life resident receives a basic weekly Linden Dollar grant. This will be enough to explore, have fun and participate in all sorts of events and practice building objects. If you need or want more money than your grant, you'll have to find a way to earn it. -

-Developer Incentives -Second Life's best attractions, creations, and entertaining diversions are created by Second Life's Residents. Developer Incentives acknowledge these hard-working Residents with real-world cash. US Dollars are awarded monthly to the creators, designers, hosts, and bon-vivants who make Second Life more than the sum of its parts. We'll use a variety of measures and mechanisms to seek out those worthy of rewards - not just traffic. Stay tuned for additional details about this exciting development. - - - - diff --git a/linden/indra/newview/help/Concepts/3D_Terminology.html b/linden/indra/newview/help/Concepts/3D_Terminology.html deleted file mode 100644 index b2771eb..0000000 --- a/linden/indra/newview/help/Concepts/3D_Terminology.html +++ /dev/null @@ -1,30 +0,0 @@ - - - 3D Terminology - - - -
-There are some terms in 3D technology that you'll run across in Second Life and in this document.

-OBJECTS
-An object is something created in Second Life. Objects are made out of primitives (see below) and can be just about any shape, material or appearance. Objects can have physics and/or scripts assigned to them for added functionality.

-PRIMITIVES
-Primitives are basic 3D shapes, like cubes, cones and cylinders. Primitives can be resized, reshaped, hollowed out and otherwise modified, then combined and connected to make more complex shapes and objects. All building starts with primitives.

-TEXTURES
-Textures are the visual patterns applied to sides, or faces of primitives or objects. Textures in Second Life need to be in the form of a graphic file in either .TGA (Targa) or .BMP (Bitmap) format, set to 24-bit color-depth.

-CAMERA
-In 3D graphics, scenes are generated from a particular viewpoint or location, known as the camera. Think of yourself as a movie director when building in Second Life, with the ability to move the camera around in the world to get the best shot.

-AXIS (PLURAL: AXES)
-Everything in a 3-D world-including the "real" world, can be located in space by three numbers, one on each of three axes.

-Remember making graphs in math class? This is just like that, but with depth.

-The x-axis goes from left to right on the computer screen.
-The y-axis goes from bottom to top of the computer screen.
-The z-axis goes from the screen straight back into the monitor, providing the illusion of depth.

-Sounds simple. But there's a little more to it.

-Since Second Life is full 3D, and you can look at anything from any angle, things get turned around. When a primitive is created, it is assigned X, Y and Z axes. These axes stay consistent with the primitive-not with the screen. If you rotate the primitive, its axes rotate along with it.

-Axes come into play for more than just positioning, especially when you get into joints (moveable connections like wheels or hinges).

- -[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Building_Tools.html b/linden/indra/newview/help/Concepts/Building_Tools.html deleted file mode 100644 index 22eed3e..0000000 --- a/linden/indra/newview/help/Concepts/Building_Tools.html +++ /dev/null @@ -1,22 +0,0 @@ - - - Building Tools - - - -
-The basic tools that you will use in Second Life to build things are:

-- Focus -- Take control of the camera to view objects from any angle.
-- Move -- move a primitive or object around.
-- Edit -- Move, resize, or rotate an object.
-- Create -- Make a new primitive.
-- Land -- Modify the land in Second Life, raising, lowering or flattening as needed to prepare it for building.
-- Link -- connect two or more primitives into a single object.
-- Make Joints -- connect two primitives with a moveable connection. -

-There are many variations and additions to these basic tools that we'll get to later on. But if you understand just these few simple tools, you've made a good start. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Building_in_3D.html b/linden/indra/newview/help/Concepts/Building_in_3D.html deleted file mode 100644 index 5c2dfe1..0000000 --- a/linden/indra/newview/help/Concepts/Building_in_3D.html +++ /dev/null @@ -1,15 +0,0 @@ - - - Building in 3-D - - - -
-Moving around in 3D can be tricky. Building things in 3D is trickier.

-When you first begin to build and move things around in 3D, it's not uncommon to accidentally bury things in the ground and lose them.

-Yes, it's a bit more complicated than building in 2-D, but the extra flexibility and power is worth the steeper learning curve. Work through the tutorials in the Advanced Skills part of this help system and you'll catch on quickly. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Different_Views.html b/linden/indra/newview/help/Concepts/Different_Views.html deleted file mode 100644 index e586450..0000000 --- a/linden/indra/newview/help/Concepts/Different_Views.html +++ /dev/null @@ -1,16 +0,0 @@ - - - Different Views - - - -
-There are different ways to look at the world while exploring Second Life.

-By default, you'll see the world in "Third Person," looking over your avatar's shoulder as you control it and move it through the world. You can use the scroll wheel on your mouse to zoom closer to or farther away from your avatar. If you zoom all the way in, you'll be in Mouselook.

-Mouselook lets you see through your avatar's eyes, and control where you look with the mouse. It's a good way to take a quick look up, down and around. It's also a great way to do some intricate flying if you move while in Mouselook.

-There are times when you need more control over your view, such as when you want to closely inspect something from different angles, or when you're building something. For this kind of viewing, you can use the Focus tool to take complete control of the "camera," and move it around and zoom it in and out as much as you want. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Getting_Around.html b/linden/indra/newview/help/Concepts/Getting_Around.html deleted file mode 100644 index 3ebc2db..0000000 --- a/linden/indra/newview/help/Concepts/Getting_Around.html +++ /dev/null @@ -1,15 +0,0 @@ - - - Getting Around in 3D - - - -
-Second Life is a true 3D world.

-This makes it much more flexible in many ways, but also makes it a little more of a challenge to move around than in a 2D world.

-If you're not already familiar with 3D navigation, just be patient. It gets easy after a little practice. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Hours.html b/linden/indra/newview/help/Concepts/Hours.html deleted file mode 100644 index df09237..0000000 --- a/linden/indra/newview/help/Concepts/Hours.html +++ /dev/null @@ -1,13 +0,0 @@ - - - Hours - - - -
-Second Life is available 24 hours a day, seven days a week. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Inventory.html b/linden/indra/newview/help/Concepts/Inventory.html deleted file mode 100644 index efcfb72..0000000 --- a/linden/indra/newview/help/Concepts/Inventory.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Inventory - - - -
-As you spend time in Second Life, you'll gather many possessions. These may include objects, textures, sounds, items of clothing, scripts and other things. -

-You can store, view and access your Inventory at any time. -

-By collecting and keeping things in your inventory, they'll always be handy when you need them -- and they'll be safe in case the original is deleted by accident. Also, regularly storing versions of things in your Inventory as you build is a good way to "undo" and go back to an earlier version of your project. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Many_Ways_to_Get_Help.html b/linden/indra/newview/help/Concepts/Many_Ways_to_Get_Help.html deleted file mode 100644 index e421fe6..0000000 --- a/linden/indra/newview/help/Concepts/Many_Ways_to_Get_Help.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Many Ways to Get Help - - - -
-There are several ways to learn more about Second Life:

-- This online help system,
-- The online Wiki at http://secondlife.com/help,
-- Downloadable documentation in PDF format,
-- The Second Life Forums
-- In-world classes

-To access the downloadable documentation, go to: http://www.secondlife.com/downloads and choose Guides and Tutorials

-To access the message board, go to http://www.secondlife.com/forums -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Money.html b/linden/indra/newview/help/Concepts/Money.html deleted file mode 100644 index 7153fc5..0000000 --- a/linden/indra/newview/help/Concepts/Money.html +++ /dev/null @@ -1,19 +0,0 @@ - - - Money - - - -
-The Second Life economy is based on Linden Dollars. The economy is evolving and will continue to evolve, depending on what Second Life residents want, and what they choose to do. -

-Everyone is given a basic weekly grant of Linden Dollars to spend any way they want. Residents who receive high ratings from their fellow Resident get a weekly reward. (Be nice and you make more money.) -

-If you want or need more than your grant, you'll need to find a way to earn more. You might start a business or, if you're skilled at architecture, clothing design, scripting or art creation, you can charge others for your time and skills. You can build an attraction and charge admission. You can give tours. You can invent other ways to earn money. Use your strengths and carve out a niche for yourself. -

- -[ Concepts Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Concepts/Other_People.html b/linden/indra/newview/help/Concepts/Other_People.html deleted file mode 100644 index f31309a..0000000 --- a/linden/indra/newview/help/Concepts/Other_People.html +++ /dev/null @@ -1,18 +0,0 @@ - - - Other People: Meeting and Communicating - - - -
-A big part of the Second Life culture is communicating and sharing with others. -

-There's an open chat system for communicating with others nearby, and a built-in instant messaging system for private and group conversations. -

-You can also use sounds, animations and gestures to add to your communications.

-There's also a powerful search tool that lets you find other people or groups with similar interests. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Ownership_and_Permissions.html b/linden/indra/newview/help/Concepts/Ownership_and_Permissions.html deleted file mode 100644 index 7e32f14..0000000 --- a/linden/indra/newview/help/Concepts/Ownership_and_Permissions.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Ownership and Permissions - - - -
-Objects can be public or owned by a particular person. When you build something, by default it is your personal property. You have the option to Deed it to a group you belong to if you want. -

-Ownership of personal property comes with rights, responsibilities, and costs. As the owner, you can set permissions to allow others to move, copy or delete your property -- if you wish. Otherwise nobody but you can mess with your stuff. -

-You can also set permissions for things you sell or give away. You can determine whether the next owner can copy, modify, or give away your object. Be careful when giving away original copies of your creations... once the object trades hands and the permissions are taken away, they're permanent! You can't reset a no-modify object so you can modify it, even if you give it back to the creator. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Reporting_Errors.html b/linden/indra/newview/help/Concepts/Reporting_Errors.html deleted file mode 100644 index 58f9021..0000000 --- a/linden/indra/newview/help/Concepts/Reporting_Errors.html +++ /dev/null @@ -1,27 +0,0 @@ - - - Reporting Errors, Problems, and Asking Questions - - - -
-The software behind Second Life is, as you might imagine, extremely complicated and much of technology is very new and is constantly being improved, updated, and expanded. As a result, it may not work perfectly all the time. -

-If you have any problems with Second Life, please let us know. Tell us about bugs, problems and anything else that makes Second Life less than wonderful. -

-If you're having little problems that aren't preventing you from playing Second Life (little things aren't working right), tell us about them using the Bug Reporter tool located under the Help menu at the top of your screen. Bug Reports are always read, and we'll use your report to help make Second Life better. However, you may not receive a response to a Bug Report, so it's not a good choice for a problem you need help with. -

-If you're having a big problem with Second Life that you need help with, you can contact Support at support@secondlife.com or through the phone number listed on our Contact page at secondlife.com. -

-If you need help with something inworld, you can contact Live Help, a group of volunteer residents who can answer many questions about things in Second Life. Simply open the Help menu and select Live Help, then type your question into the group IM session that opens up. (Be sure to leave the group IM open so you can receive a response!) -

-Problems can also be discussed in the Second Life Forums. Feature suggestions are welcome, and there's a special discussion board in the Forums for suggesting and discussing new features. -

-That's it for the Second Life Concepts. -

-If you're still thirsty for knowledge, you can jump ahead to the Advanced Second Life Skills. -

-[ Concepts Home | Previous ] - - - diff --git a/linden/indra/newview/help/Concepts/Scripting.html b/linden/indra/newview/help/Concepts/Scripting.html deleted file mode 100644 index dc41317..0000000 --- a/linden/indra/newview/help/Concepts/Scripting.html +++ /dev/null @@ -1,15 +0,0 @@ - - - Scripting - - - -
-A very powerful feature of Second Life is the ability to add a script, or small program, to an object. Scripts can turn simple objects into interactive experiences that impart information, play sounds, move or ... just about anything. -

-The scripting language has been designed so even non-programmers can make simple modifications and customizations. (For instance, a door may have a script so it opens with a password. It will be easy to modify the door script to the password of your choice.) -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Second_Life_Concepts.html b/linden/indra/newview/help/Concepts/Second_Life_Concepts.html deleted file mode 100644 index fee49e0..0000000 --- a/linden/indra/newview/help/Concepts/Second_Life_Concepts.html +++ /dev/null @@ -1,33 +0,0 @@ - - - Second Life Concepts - - - -
-Here are a few basic concepts that will help you understand and get the most out of Second Life. -

-The World, the Play, the Reason for Being -
Use Your Strengths -
Updates -
Hours -
Things to do in Second Life -
Your Avatar -
Other People: Meeting and Communicating -
Tips For Newbies -
Money -
Ownership and Permissions -
Getting Around in 3-D -
Different Views -
Inventory -
Building in 3-D -
3D Terminology -
Building Tools -
Scripting -
Many Ways to Get Help -
Reporting Errors, Problems and Asking Questions -

-[ Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Strengths.html b/linden/indra/newview/help/Concepts/Strengths.html deleted file mode 100644 index 738252b..0000000 --- a/linden/indra/newview/help/Concepts/Strengths.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Use Your Strengths - - - -
-Everyone is different. Everyone has their own strengths, skills and creative prowess. Some people excel in architecture. Others in scripting. Others in creating textures. Others in avatar fashion design, sound design, social design (organizing events and throwin' parties) or new areas that we haven't thought of yet. -

- -You are a part of the creation of a new world. We value your strengths and personality, and expect them to help us grow and develop Second Life. Stretch a little, challenge yourself and learn new things from the others. But use your own strengths. -

-[ Concepts Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Concepts/Things_to_do.html b/linden/indra/newview/help/Concepts/Things_to_do.html deleted file mode 100644 index 06cc043..0000000 --- a/linden/indra/newview/help/Concepts/Things_to_do.html +++ /dev/null @@ -1,26 +0,0 @@ - - - Things to do in Second Life - - - -
-Right now, when the world is fresh and new the main things to do in Second Life are: -

-- Explore -
- Meet others with similar (or new) interests, network, make friends -
- Participate in social events -
- Participate in deadly battles in the Jessie or Rausch combat regions -
- Participate in various games and contests -
- Create things and places others will want to explore -
- Experiment with scripting -
- Create textures and sounds out-of-world, and upload them -
- Collaborate with others to build something big -
- Start businesses that charge for products or services -
- Much more that we haven't even thought of yet -- but you will. -

-[ Concepts Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Concepts/Tips_For_Newbies.html b/linden/indra/newview/help/Concepts/Tips_For_Newbies.html deleted file mode 100644 index 3165dc1..0000000 --- a/linden/indra/newview/help/Concepts/Tips_For_Newbies.html +++ /dev/null @@ -1,30 +0,0 @@ - - - Tips For Newbies - - - -
-As with any society, Second Life has it's own set of cultural norms that you should be aware of so you can progress quickly while avoiding making any faux pas and causing yourself or others problems: -

-1. It's OK to learn by emulation: look at other people's work, copy free textures, analyze others' scripts, etc. -

-2. Don't litter! Delete your unused objects. -

-3. Use physics, light, and scripted objects sparingly, they put a heavy toll on processing power and can slow the game for others. -

-4. Avoid uploading copyrighted textures, graphics, characters or text. (No movie posters, pictures of Elvis, etc.) Second Life Residents favor original content. -

-5. Don't build malicious objects. Guns and shooting aren't permitted in most areas. (Head to the regions Jessie or Rausch if you're looking for that sort of action.) Objects that follow other people around are cute-but annoying after a while. -

-6. Use sound sparingly. Don't be the neighbor with the annoying barking dog. -

-7. Know the difference between public chat and Instant Messaging. Keep private conversations private; don't copy chat and paste it somewhere else. Most of all, don't ever reveal private information (like passwords) to anyone. -

-8. Use your Inventory to store things you may want later. It doesn't cost anything to store things there, and it's almost unlimited in size. -

-[ Concepts Home | Previous | Next ] - - - - diff --git a/linden/indra/newview/help/Concepts/Updates.html b/linden/indra/newview/help/Concepts/Updates.html deleted file mode 100644 index f6bfab8..0000000 --- a/linden/indra/newview/help/Concepts/Updates.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Updates - - - -
-There will occasionally be updates to the viewer program. When there's an update, you'll be notified when you try to log on, and instructed to go to the Second Life Website, sign in and download the latest version of the player. -

-Your possessions, Inventory, ratings and avatar designs will automatically be updated into the new viewer. -

-If you have any problems downloading an update, you can always download the latest version of Second Life at http://secondlife.com/download. -

-[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/World.html b/linden/indra/newview/help/Concepts/World.html deleted file mode 100644 index f8d105c..0000000 --- a/linden/indra/newview/help/Concepts/World.html +++ /dev/null @@ -1,20 +0,0 @@ - - - The World, the Play, the Reason for Being - - - -
-Second Life is an open-ended world where you can do nearly anything that you can imagine. If you’re thinking about what to do next, here are some suggestions: -

-

  • Use the “Find people” feature to check who else is online -
  • Find a game, or somewhere to go shopping. -
  • Customize your avatar to look like a famous person and see if other Residents can guess who you are -
  • Visit the Second Life forums at www.secondlife.com and see what people are talking about -
  • Build a replica of your favorite childhood toy -
  • Click the Events button at the top of your screen to see what’s going on inworld -

    -[ Concepts Home | Next ] - - - diff --git a/linden/indra/newview/help/Concepts/Your_Avatar.html b/linden/indra/newview/help/Concepts/Your_Avatar.html deleted file mode 100644 index fb35eaa..0000000 --- a/linden/indra/newview/help/Concepts/Your_Avatar.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Your Avatar - - - -
    -Your avatar is your representative in Second Life. -

    -Your avatar may be male or female, and you can customize it in almost limitless ways. -When you see other avatars, their names will appear above their heads. When others see you, they'll see your name above your head. -

    -You can attach things to your avatar, to make it even more original (and functional). The objects that you attach may be scripted, so they can function in different ways, for instance, jet packs for faster travel, guns for games, etc. -

    -Your avatar has a health rating (it will appear, when needed, in the lower left corner of your screen) only while in the Damage Enabled areas where the dangerous games are played. If your health rating reaches 0%, then your avatar is (temporarily) dead, and will be teleported to your home location and healed. -

    -[ Concepts Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/LL_logo.jpg b/linden/indra/newview/help/LL_logo.jpg deleted file mode 100644 index 272bd3d..0000000 Binary files a/linden/indra/newview/help/LL_logo.jpg and /dev/null differ diff --git a/linden/indra/newview/help/MAIN.css b/linden/indra/newview/help/MAIN.css deleted file mode 100644 index a981505..0000000 --- a/linden/indra/newview/help/MAIN.css +++ /dev/null @@ -1,553 +0,0 @@ -/* GLOBAL STYLES: text, links, form elements, etc */ - -body { - margin : 0px; - font-family:verdana, helvetica, sans-serif; - font-size:11px; - background-color: #ffffff; - color:#546368; - } - -.body_community { - margin : 0px; - font-family:verdana, helvetica, sans-serif; - font-size:11px; - background-color: #d5e3ec; - color:#546368; - } - -option.sl, input.sl, radio.sl, .S1 -{ - font-family:verdana, courier, courier new, sans-serif; - font-size: 8pt; - color: white; - background-color: #4378a4; - border-color:#bcbbbb; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; -} - - -submit.resident -{ - font-family:verdana, courier, courier new, sans-serif; - font-size: 8pt; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; -} - -select.resident -{ - font-family:verdana, courier, courier new, sans-serif; - font-size: 8pt; - color: white; - background-color: #4378a4; - border-color:#bcbbbb; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; -} - -textarea.resident -{ - font-family:verdana, courier, courier new, sans-serif; - font-size: 10px; - color:white; - background-color: #4378a4; - border-color:#bcbbbb; - border-top-width: 1px; - border-right-width: 1px; - border-bottom-width: 1px; - border-left-width: 1px; -} - -a {color:#4378a4; text-decoration:underline;} -a:active {color:#50607C; text-decoration:underline;} -a:hover {color:#ff7900;text-decoration:underline;} - -a.promolink {color:#4378a4; text-decoration:none;} -a.promolink:active {color:#50607C; text-decoration:none;} -a.promolink:hover {color:#ff7900;text-decoration:none;} - -a img {border: 0px #FFFFFF none;} -a:active img {border: 0px #FFFFFF none;} -a:hover img {border: 0px #FFFFFF none;} - -a.fansite {font-weight:bold;} - -.headline {color:#346080; font-size:12px; font-weight:bold;} - -.header {color:#346080; font-size:12px; font-weight:bold;} - -.subheader {color:#346080; font-size:11px; font-weight:bold;} - -.fineprint {color:#346080; font-size:10px;} - -.topheader {color:#346080; font-size:13pt; font-weight:bold; font-family:verdana, helvetica, sans-serif;} - -.super {font-size: 9px; vertical-align:super;} - -.copyright {text-align: right; margin:0px 6px 0px 0px; color:#666666; font-family:verdana, helvetica, sans-serif; font-size:x-small; -} - - - -/* DEFAULT TEMPLATE PAGE POSITIONING */ - -#DEFAULT_container { - width:890px; - margin:0px 5px 5px 5px; - text-align:left; - background-color: #ffffff; - } - -#DEFAULT_container_community { - width:900px; - margin:0px 5px 5px 5px; - text-align:center; - background-color: #ffffff; - - } - -#DEFAULT_header { - width: 890px; - height: 85px; - background-image: url('header_banner.jpg'); - background-position: center 50%; - background-repeat: no-repeat; margin-left:0px; margin-right:0px; margin-top:0px; margin-bottom:3px - } - -#DEFAULT_header_nav { - left: 0px; - top: 87px; - width: 890px; - height: 23px; - z-index: 9001; - margin: 0px; - } - -#DEFAULT_container_mid { - position:relative; - left:0px; - width: 890px; - margin: 0px; - } - -#DEFAULT_left { - width: 190px; - float:left; - margin: 0px; - } - -#DEFAULT_menu_outside { - background-color:#376283; - } - -#DEFAULT_menu_inside { - padding: 1px 6px 10px 6px; - } - -#DEFAULT_mid_outside { - vertical-align: top; - float:left; - margin: 0px 10px 10px 10px; - padding: 0px; - } - -#DEFAULT_mid_inside { - width: 440px; - margin: 0px; - padding: 0px 0px 1px 0px; - } - -#DEFAULT_2column { - vertical-align: top; - float:left; - margin: 0px 0px 10px 10px; - padding: 0px; - overflow:auto; - } - -#DEFAULT_2column_inside { - width: 690px; - margin: 0px; - padding: 0px 0px 10px 0px; - overflow-x:auto; - } - -#DEFAULT_content_header { - padding:10px ; - margin: 0px; - background-image: url('/_img/backgrounds/bg_skyheader.jpg'); - background-repeat: no-repeat} - -#DEFAULT_content_header_2column { - padding:10px ; - margin: 0px; - background-image: url('/_img/backgrounds/bg_skyheader_2col.jpg'); - background-repeat: no-repeat -} - -#DEFAULT_content_divider { - margin: 0px; - background-image: url('/_img/backgrounds/bg_dots_grey.gif'); - background-repeat: repeat-x -} - -#DEFAULT_right { - width: 225px; - float:right; - margin: 0px; - } - -#DEFAULT_module { - width: 215px; - padding: 1px 5px 1px 5px; - margin: 0px 0px 0px 0px; - } - -#DEFAULT_footer { - width: 890px; - height: 40px; - margin: 10px 0px 0px 0px; - float: left; - } - -/* EMBEDDED ALTERATIONS FROM DEFAULT */ - -#embedded_container_outer { - width:640px; - margin:0px 5px 5px 5px; - text-align:center; - background-color: #ffffff; - - } - -#embedded_mid_inside { - width: 540px; - margin: 0px; - padding: 0px 0px 1px 0px; - } - -#embedded_content_header { - padding:10px ; - margin: 0px; - background-image: url('/_img/backgrounds/bg_skyheader.jpg'); - background-position: right 50%; - background-repeat: no-repeat} - - -/* COMMUNITY MAIN PAGE */ - -#comm_index_container { - width: 690px; - vertical-align: top; - float:left; - margin: 0px 0px 0px 10px; - padding: 0px; - } - -#comm_index_top_outside { - width: 690px; - height: 182px; - margin: 0px; - padding: 0px; - background-image: url('/_img/backgrounds/bg_community.jpg'); - background-repeat: no-repeat - } - -#comm_index_top_inside { - width: 680px; - height: 182px; - margin: 0px 0px 0px 0px; - padding: 0px; - } - -#comm_mid_outside { - vertical-align: top; - float:left; - margin: 0px 10px 0px 0px; - padding: 10px 0px 0px 0px; - } - -#comm_mid_inside { - width: 430px; - margin: 0px 10px 10px 10px; - padding: 10px 0px 10px 0px; - } - -#comm_right { - width: 225px; - float:right; - margin: 0px 0px 0px 0px; - } - -#comm_promo { - width: 225px; - height: 85px; - margin: 10px 0px 5px 0px; - } - -#comm_quicklinks_outside { - width: 225px; - background-color:#376283; - } - -#comm_quicklinks_inside { - margin: 0px 10px 0px 10px; - padding: 10px 0px 10px 0px; - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 10px; - color: #FFFFFF; - } - -#comm_quicklinks_inside a { - font-size: 11px; - font-weight: bold; - text-decoration: underline; - color: #FFFFFF; - } -#comm_quicklinks_inside a:hover { - text-decoration: none; - } -#comm_quicklinks_inside .pad { padding: 5px 0px 5px 0px;} - - -#comm_latest { - background-image: url('/_img/backgrounds/bg_topfade.gif'); - background-position: left top; - background-repeat: repeat-x; - border-top: 1px solid #CCCCCC; - border-bottom: 1px solid #CCCCCC; - border-left: 1px solid #CCCCCC; - width: 420px; - height: 461px; - overflow:auto; - padding-left:8px; padding-right:3px; padding-top:0px; padding-bottom:3px -} - - -TBODY.RandomContainer TR.RandomItem { - display: none; - } - - - - -/* LEFT MENU STYLES */ - -.menu_topsection { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - font-weight: bold; - color: #FFFFFF; - background-color:#376283; - padding: 3px 5px 3px 5px; - - } - -.menu_subsection { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - background-image: url('/_img/backgrounds/bg_submenu.jpg'); - padding-left:5px; padding-right:3px; padding-top:3px; padding-bottom:3px - } - -.menu_toplink { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - font-weight: bold; - color: #FFFFFF; - text-decoration: none; - } - -.menu_sublink { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - color:#eeeeee; - text-decoration: none; - } - -.menu_toplink:hover { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - font-weight: bold; - color: #e8eff5; - text-decoration: underline; - } - -.menu_sublink:hover { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - text-decoration: underline; - } - -.menu_toplink_active { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - font-weight: bold; - color: #ff9933; - } - -.menu_sublink_active { - font-family: Verdana, Arial, Helvetica, sans-serif; - font-size: 11px; - color: #ff9933; - } - - -.menu_border { - background-image: url('/_img/backgrounds/bg_dots_white.gif'); - color: #FFFFFF; - margin: 0px - } - -.menu_border_sublink { -background-image: url('/_img/backgrounds/bg_submenu_dots_blue.jpg'); -margin: 0px -} - -/* ERROR HANDLING: */ - -#display_errors {color:#000000; border-style: solid; border-color:#aaaaaa; border-width:1px; padding:5px; background-color:#FEF7D7; margin-right:5px;} - -/* END ERROR HANDLING: */ - - -/* BOXES: */ -div.box_grey_t {background-image: url('grey_pixel.gif'); background-position: left top; background-repeat: repeat-x} -div.box_grey_r {background-image: url('grey_pixel.gif'); background-position: right top; background-repeat: repeat-y} -div.box_grey_b {background-image: url('grey_pixel.gif'); background-position: left bottom; background-repeat: repeat-x} -div.box_grey_l {background-image: url('grey_pixel.gif'); background-position: left top; background-repeat: repeat-y} -div.box_grey_tl {background-image: url('grey_corner_tl.gif'); background-position: left top; background-repeat: no-repeat} -div.box_grey_tr {background-image: url('grey_corner_tr.gif'); background-position: right top; background-repeat: no-repeat} -div.box_grey_bl {background-image: url('grey_corner_bl.gif'); background-position: left bottom; background-repeat: no-repeat} -div.box_grey_br {background-image: url('grey_corner_br.gif'); background-position: right bottom; background-repeat: no-repeat} - -div.box_light_t {background-image: url('/_img/boxes/white_bdr_top.gif'); background-position: left top; background-repeat: repeat-x} -div.box_light_r {background-image: url('/_img/boxes/white_bdr_right.gif'); background-position: right top; background-repeat: repeat-y} -div.box_light_b {background-image: url('/_img/boxes/white_bdr_bot.gif'); background-position: left bottom; background-repeat: repeat-x} -div.box_light_l {background-image: url('/_img/boxes/white_bdr_left.gif'); background-position: left top; background-repeat: repeat-y} -div.box_light_tl {background-image: url('/_img/boxes/white_corner_tl.gif'); background-position: left top; background-repeat: no-repeat} -div.box_light_tr {background-image: url('/_img/boxes/white_corner_tr.gif'); background-position: right top; background-repeat: no-repeat} -div.box_light_bl {background-image: url('/_img/boxes/white_corner_bl.gif'); background-position: left bottom; background-repeat: no-repeat} -div.box_light_br {background-image: url('/_img/boxes/white_corner_br.gif'); background-position: right bottom; background-repeat: no-repeat} - -div.box_lblue_t {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left top; background-repeat: repeat-x} -div.box_lblue_r {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: right top; background-repeat: repeat-y} -div.box_lblue_b {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left bottom; background-repeat: repeat-x} -div.box_lblue_l {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left top; background-repeat: repeat-y} -div.box_lblue_tl {background-image: url('/_img/boxes/lblue_corner_tl.gif');background-position: left top; background-repeat: no-repeat} -div.box_lblue_tr {background-image: url('/_img/boxes/lblue_corner_tr.gif');background-position: right top; background-repeat: no-repeat} -div.box_lblue_bl {background-image: url('/_img/boxes/lblue_corner_bl.gif');background-position: left bottom; background-repeat: no-repeat} -div.box_lblue_br {background-image: url('/_img/boxes/lblue_corner_br.gif');background-position: right bottom; background-repeat: no-repeat} - -div.box_mblue_t {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left top; background-repeat: repeat-x} -div.box_mblue_r {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: right top; background-repeat: repeat-y} -div.box_mblue_b {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left bottom; background-repeat: repeat-x} -div.box_mblue_l {background-image: url('/_img/boxes/grey_pixel.gif'); background-position: left top; background-repeat: repeat-y} -div.box_mblue_tl {background-image: url('/_img/boxes/mblue_corner_tl.gif');background-position: left top; background-repeat: no-repeat} -div.box_mblue_tr {background-image: url('/_img/boxes/mblue_corner_tr.gif');background-position: right top; background-repeat: no-repeat} -div.box_mblue_bl {background-image: url('/_img/boxes/mblue_corner_bl.gif');background-position: left bottom; background-repeat: no-repeat} -div.box_mblue_br {background-image: url('/_img/boxes/mblue_corner_br.gif');background-position: right bottom; background-repeat: no-repeat} - -div.box_dblue_noborder_tl {background-image: url('/_img/boxes/dblue_corner_tl.gif');background-position: left top; background-repeat: no-repeat} -div.box_dblue_noborder_tr {background-image: url('/_img/boxes/dblue_corner_tr.gif');background-position: right top; background-repeat: no-repeat} -div.box_dblue_noborder_bl {background-image: url('/_img/boxes/dblue_corner_bl.gif');background-position: left bottom; background-repeat: no-repeat} -div.box_dblue_noborder_br {background-image: url('/_img/boxes/dblue_corner_br.gif');background-position: right bottom; background-repeat: no-repeat} - -div.comm_corner_bl {background-image: url('/_img/boxes/comm_corner_bl.gif'); background-position: left bottom; background-repeat: no-repeat} -div.comm_corner_br {background-image: url('/_img/boxes/comm_corner_br.gif'); background-position: right bottom; background-repeat: no-repeat} - - - -#MEDIA_NEWS {background-color:#e9f1f8; background-position: top left;} -#SL_news { - background-image: url('/_img/backgrounds/bg_topfade.gif'); - background-repeat: repeat-x; - text-align:left; - font-family:verdana, helvetica, sans-serif; - font-size:x-small; - border-left: 1px solid #CCCCCC; - border-top: 1px solid #CCCCCC; - border-bottom: 1px solid #CCCCCC; - width: 179px; - height: 130px; - overflow:auto; background-position-y:50% -} -#SL_news .row1 { background-color:#FFFFFF; padding: 5px 5px 5px 5px;} -#SL_news .row2 { background-color:#e9f1f8; padding: 0px;} -#SL_news a { font-size:x-small;} - - -/* If we don't explicitly choose a size for H2, H3, Firefox and IE - choose sizes that are very different. - */ -h2 { font-size: 18px } -h3 { font-size: 14px; padding:0px; margin: 12px 0 8px 0 } - -/* table cells */ -td.heading { border-bottom: 1px dotted black } -td.title { font-weight: bold } -td.right { text-align: right } -td.center { text-align: center } -td.ledger-shade { background-color: #eeeeee } - -/* _COPIED_ "required" over from registration b/c other forms may have required fields */ -.required -{ - font-size: 10px; - color: #CC0000; - background-color: #FFFFCC; - font-weight: normal; -} - -/* Known Issues format and display */ -#known_issues { - background-image: url('/_img/backgrounds/bg_topfade.gif'); - background-position: left top; - background-repeat: repeat-x; - border: 1px solid #CCC; - width: 650px; - padding-left:8px; padding-right:3px; padding-top:0px; padding-bottom:3px -} - -#bug { - border-bottom: 1px dashed #CCC; - padding: 12px 0px; -} - -.bugrepro{ - border: 1px solid #CCC; - display: none; - height: 300px; - width: 600px; - overflow: auto; - padding: 3px; -} - -.whenupdated { - text-align: center; - font-weight: bold; - font-size: large; - padding: 2px; -} - -.key, .buglabel { - padding: 0px 4px 0px 0px; - font-weight: bold; -} - -.versionlist{ - padding: 0px 8px 0px 0px; - font-style: italic; -} - -.bugsummary{ - font-weight: bold; -} \ No newline at end of file diff --git a/linden/indra/newview/help/basics/basic_skills.html b/linden/indra/newview/help/basics/basic_skills.html deleted file mode 100644 index 68dcc4e..0000000 --- a/linden/indra/newview/help/basics/basic_skills.html +++ /dev/null @@ -1,23 +0,0 @@ - - - Basic Second Life Skills - - -
    -WELCOME TO BASIC SECOND LIFE SKILLS -

    -TOPICS -
    -Basic Movement
    -Chat
    -Instant Messaging
    -Inventory Basics
    -Basic Avatar Customization
    -Your Profile
    -Shopping 101
    -An Introduction to Camera Control
    - -

    -[ Next ] - - diff --git a/linden/indra/newview/help/basics/camera.html b/linden/indra/newview/help/basics/camera.html deleted file mode 100644 index e7a7b1e..0000000 --- a/linden/indra/newview/help/basics/camera.html +++ /dev/null @@ -1,50 +0,0 @@ - - Camera Control - - -
    -Get a new perspective on your Second Life. -

    - -Because Second Life is 3-D, you have total and infinite control over where you place the camera (your eyes). -

    -Camera control is a little tricky to get the hang of, but once you do, you'll really enjoy it. -

    -1. Hold down the ALT key to activate Focus mode. -

    -The cursor changes to a magnifying glass. -

    -3. With ALT held down, click and release on various spots on the landscape. -

    -Notice that the view re-centers on the place where you clicked. -

    -4. Click on your avatar and drag the mouse SLOWLY around. -

    -As you move the mouse forward and backward and side to side, the view zooms in and out and around your avatar. -

    -5. Now hold down the ATL and CTRL keys at the same time. -

    -The cursor changes again to indicate Orbit mode. -

    -6. With both ALT and CTRL held down, click and drag SLOWLY on the avatar again. -

    -Now, as you move the mouse, the view stays approximately the same distance from your avatar, but the camera orbits around it in all directions. -

    -7. Now hold down ALT, CTRL, and Shift at the same time. -

    -The cursor changes to indicate Pan mode. -

    -8. Click and drag SLOWLY on the avatar again. -

    -Now, as you move the mouse, the camera slides across the landscape. It looks like you're dragging the ground around. -

    -9. Hit the Esc key to return to normal view. -

    -You'll also find a Camera Control panel under the View menu at the top of the screen. -

    -Mastering camera control will take some practice. One you have a feel for it, it's not only fun, but very useful when you start to build things and need to see them from all angles. -

    -[ Basic Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/basics/chat.html b/linden/indra/newview/help/basics/chat.html deleted file mode 100644 index 59cf64a..0000000 --- a/linden/indra/newview/help/basics/chat.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Chat - - -
    -Time to learn how to chat. -

    -The first step is to find someone to chat with. Use the Mini Map or World Map to locate other Second Life Residents. -

    -Once you've located someone to chat with, get only as close to then as you would to chat in real life. -

    -1. Press the Enter (or Return) key, type a message, then hit Enter (Return) again to say your message.

    -Everyone within a certain range will hear you. -

    -2. By default, you'll automatically stay in chat mode as long as you're talking. (You can change this later in Preferences.) When you're done with your conversation, hit the ESC key to exit chat mode. -

    -[ Basic Skills Home | Previous | Next ] - - \ No newline at end of file diff --git a/linden/indra/newview/help/basics/congratulations.html b/linden/indra/newview/help/basics/congratulations.html deleted file mode 100644 index 1ff33bf..0000000 --- a/linden/indra/newview/help/basics/congratulations.html +++ /dev/null @@ -1,16 +0,0 @@ - - - Congratulations! - - -

    -When you're ready to learn more, take a quick look through Second Life Concepts, where you'll gain some background in how things work around here. -

    -Or, if you prefer, you can jump right into the Advanced Second Life Skills. -

    - - -

    -[ Previous ] - - diff --git a/linden/indra/newview/help/basics/customization.html b/linden/indra/newview/help/basics/customization.html deleted file mode 100644 index e3e46af..0000000 --- a/linden/indra/newview/help/basics/customization.html +++ /dev/null @@ -1,59 +0,0 @@ - - - Basic Avatar Customization - - -
    -Turn yourself into a work of art. -

    -1. Open the Edit menu and select Appearance.... -

    -You'll see a large dialog box and a close-up of your avatar's face. -

    -Along the left side of the dialog are a number of tabs that divide up the job into various body parts or articles of clothing. -

    -2. Click on the Shape tab on the left. -

    -You're now ready to change your avatar's shape. -

    -Within the Shape tab are a number of other choices: Face, Torso, Legs and Body. Plus, you can change your avatar's gender with a single click. -

    -3. If your avatar is male, click on female. If it's female, click on male. -

    -Your avatar will instantly change from one gender to another. The clothing will stay the same, but there will be a number of easy-to-notice changes. Go back and forth, then pick whichever one you want for now. -

    -4. Click on the Face button. -

    -Now it's time to play. -

    -Take your time and go through all the face sliders. Don't be afraid to giggle; you can't hurt your avatar's feelings. -

    -Use the left- and right-arrow keys to rotate your avatar and see it from all sides as you play. -

    -When you've finished with the face: -

    -5. Click on the Torso button, and play with the sliders. -

    -6. Click on the Legs button, and play with the sliders. -

    -7. Click on the Body button, and play with the sliders. -

    -Once you've played with the adjustments for a while and want to keep what you've got: -

    -8. Click on Save As.... -

    -A dialog box will open asking you to choose a name for your new shape. It will appear in your Clothing folder of your Inventory. -

    -You can create as many shapes as you want, and instantly change between them just by double-clicking on their name in the Inventory box. -

    -So far, you've only played with the Shape tab. There's a lot more you can do to your avatar on the Skin, Hair and Eyes Tabs -- and even more with the clothing tabs. -

    -If you want, stay and play. Try the other tabs and see what you can come up with. - -

    -When you're ready to move on, click Next below. - -

    -[ Basic Skills Home | Previous | Next ] - - \ No newline at end of file diff --git a/linden/indra/newview/help/basics/economy.html b/linden/indra/newview/help/basics/economy.html deleted file mode 100644 index f68b990..0000000 --- a/linden/indra/newview/help/basics/economy.html +++ /dev/null @@ -1,17 +0,0 @@ - - - The Second Life Economy - - -
    -Second Life features a vibrant inworld economy that's a lot different than many other online worlds. -

    -Every week, you'll receive a weekly stipend of ingame currency, or L$. This amount is determined by your membership (Basic or Premium) as well as a bonus amount based on your inworld reputation (as rated by other residents). -

    -There are many ways to make money in Second Life; generally, if it works (and is legal) in the real world, it may be possible in Second Life. You can create objects, clothing, etc. and sell them. If you own land, you can create any number of businesses--dance club, arcade, coffee house, chicken ranch, space station, roller coaster, etc.--and earn rewards for the time other people spend at your build. You can even charge admission. If you're skilled, other residents may hire you to help them with their own builds, businesses, and creations. -

    -If you prefer not to work, or need more cash fast, you can even purchase L$ with USD$ dollars. On the other hand, if you're rolling in the L$ dough, you can sell L$ and make real-world cash! (See http://secondlife.com/help for more information.) -

    -[ Basic Skills Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/basics/im.html b/linden/indra/newview/help/basics/im.html deleted file mode 100644 index 182bb6a..0000000 --- a/linden/indra/newview/help/basics/im.html +++ /dev/null @@ -1,47 +0,0 @@ - - - Instant Messaging - - -
    -Read on to learn how to use Instant Messaging. -

    - -Instant Messaging is private, and only the Residents you send an Instant Message to can hear it. -

    -Let's take a look at the Instant Messaging box. -

    -1. Click on the IM button in the lower-left corner of the screen. -

    -The New Instant Messaging box opens. -

    -Until you meet some people and add them to your Friends list, there won't be anyone listed for Instant Messaging. Instead, you can find someone to IM using the Find menu or Right-Clicking another Resident near you and selecting "Send IM". -

    -Let's send an IM to someone to see how IM works. -

    -2. Select a name in the New IM menu (if you've collected any calling cards) or use the Find menu to locate another Resident and select "Send IM". -

    -The IM box changes. The title now says Instant Message with the Resident you selected. -

    -Also, now there are two tabs a the bottom of the box, one to return to New IM (your list of people you can IM), plus one where you're now ready to carry on an IM conversation. -

    -3. Type in an appropriate message and press Enter (Return). -

    -Your message will be sent. -

    -IM is a great way to leave messages for others even when they're not in-world. And once you have a number of Friends, you can carry on multiple IM conversations at once. -

    -If you find someone who you want to add to your Friends list: -

    -4. Click on their avatar, and from the pie menu, select Add Friend. -

    -They'll get a dialog asking them if they want to accept your offer of Friendship. If they say "no," then they won't appear on your Friends list.. -

    -If someone clicks on your avatar and wants to become your Friend, you'll be given the chance to say yes or no before it happens. -

    -If you decide at a later time that you no longer want to be Friends with a particular person, you can remove them from your Friends list, and you will automatically be removed from theirs. - -

    -[ Basic Skills Home |Previous | Next ] - - diff --git a/linden/indra/newview/help/basics/inventory.html b/linden/indra/newview/help/basics/inventory.html deleted file mode 100644 index bcbda45..0000000 --- a/linden/indra/newview/help/basics/inventory.html +++ /dev/null @@ -1,49 +0,0 @@ - - - Inventory - - -

    -Your Inventory is your treasure chest. It holds everything that you build, own and need. There's even a Library that contains objects, clothing, outfits, textures, and more for you to use. -

    -Let's take a quick look at it: -

    -1. Click on the Inventory button in the lower-right corner of the screen.

    -The Inventory box is set up like a filing cabinet, with folders and files. You can have folders inside other folders to help organize things as you gather more and more stuff. -

    -Think of your Inventory as a huge electronic closet. -

    -2. Look at the name of all the folders in your Inventory, then go ahead and look through them. -

    -3. Click on the small "+" next to a folder to open it, then click on the "-" to close it. -

    -The main folders are: -

    -Body Parts -- here's a place to store different body parts. The ones that are in bold text are currently worn by your avatar. Double-click on a body part to wear it. -

    -Calling Cards -- here's where the calling cards that you gather are stored, plus your own. Double-click on a calling card to find out more information about the person behind the card. -

    -Clothing -- this is a folder where you can keep assorted pieces of clothing, plus whole outfits, so you can change your avatar's looks as often as you like. Outfits can even hold body parts and shapes, so when you change, you really change. Clothes that you're currently wearing are shown in bold text. -

    -Landmarks -- this folder holds all of your landmarks, including the ones you make yourself. -

    -Note Cards -- this folder holds note cards, which are like sticky notes: a place to keep text notes to yourself. -

    -Objects -- this is a folder that holds various things that you make or buy in Second Life. They can range from small toys to whole houses. -

    -Photo Album -- this is where the screenshots you take are stored. You can take screenshots by selecting Take Screenshot in the File menu. -

    -Scripts -- this folder holds a number of useful scripts that can be attached to objects to make them more interactive. You can write your own scripts if you choose, or use scripts created by others and just modify them. For instance, you can use a Door script on the door to your house and easily modify the password. -

    -Sounds -- this folder holds sounds that you can play or attach to avatar gestures (we'll do this later). You can record your own sounds and upload them into your Inventory. -

    -Textures -- this folder is for graphics that you can use to decorate your walls, to add flair to anything you build, and even create new items of clothing. -

    -Trash -- this is where everything you delete from your Inventory goes until you empty the trash. It's a safety feature that helps you get back things you may have accidentally deleted. -

    -5. Click on the X button to close the Inventory box. -

    -[ Basic Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/basics/keyboard.html b/linden/indra/newview/help/basics/keyboard.html deleted file mode 100644 index 2963a1b..0000000 --- a/linden/indra/newview/help/basics/keyboard.html +++ /dev/null @@ -1,58 +0,0 @@ - - - Walking and Flying with the Keyboard - - -
    -As you learn to move around in Second Life, you may find that you may want to use one hand on the keyboard to move around while you're using the mouse to do other things. As a result, it's easiest to learn how to move with the mouse and keyboard. -

    -Follow the instructions below to learn how to move your avatar with the keyboard. -

    -1. Take a look at this chart: -

    -W = Forward
    -S = Backward -

    -A = Left
    -D = Right -

    -E = Fly Up (Jump)
    -C = Fly Down (Duck) -

    -F = Fly toggle -

    -2. Play around with these keys and walk around until you get the hang of it. -

    -If your avatar starts typing instead of walking, press ESC a few times to get out of Chat. -

    -Notice that you can press two keys at a time. For instance, while pressing W to move forward, tap on the D or A keys to turn without stopping. -

    -If you'd rather use your right hand, you can also use the arrow keys: -

    -Up Arrow = Forward
    -Down Arrow = Backward -

    -Left Arrow = Left
    -Right Arrow = Right -

    -PageUp = Fly Up (Jump)
    -PageDown = Fly Down (Duck) -

    -Home = Fly toggle -

    -

    -3. Press the F key. -

    -Your avatar flies. -

    -4. Fly around using the keyboard. -

    -Again, take some time to get the hang of it. -

    -5. Press the F key to stop flying. -

    -If you were up very high, your landing might not be very pretty, but don't worry ... it won't hurt. -

    -[ Basic Skills Home | Previous | Next ] - - \ No newline at end of file diff --git a/linden/indra/newview/help/basics/landmarks.html b/linden/indra/newview/help/basics/landmarks.html deleted file mode 100644 index 5842080..0000000 --- a/linden/indra/newview/help/basics/landmarks.html +++ /dev/null @@ -1,43 +0,0 @@ - - - Using Landmarks - - -
    -Landmarks help you find your way to new places, or find your way back to a place you liked. You have a number of useful, ready-to-use landmarks at your disposal. Later, you'll be making your own. -

    -1. Look at the Mini-Map. (Click on the "Mini-Map" button if you don't see it.) -

    -In addition to showing an overview of the world, the Mini-Map also helps you find your way around. -

    -2. Click on Mini Map to open the World Map window. -

    -The World Map shows more of the Second Life world. Some extra controls appear on the right side of the map, including a pull-down list of landmarks. -

    -3. Click on Landmark pull-down -

    -4. Select a Landmark that sounds interesting to you. -

    -Once you select a landmark in this list, a couple of things happen: the landmark appears on the map as a red square, and a large beacon appears in the world at the landmark's location. -

    -You only see beacons while a landmark is selected, and only you can see it. So don't tell someone to go to the big red beacon, because they won't see it unless they have the same landmark selected. -

    -If you've wandered a ways from your starting point, you may not be able to see the landmark on the map. If that's the case: -

    -5. Slide the Zoom slider to shrink the map until you can see the red square that marks the landmark. -

    -Once you see the landmark on the map: -

    -6. Click the Teleport button on the World Map. -

    -Your avatar will teleport to a Telehub. This is a central teleport location that's close to your landmark. You'll need to fly the rest of the way. -

    -7. Use the A and D keys, or left and right arrow keys, to turn your avatar until the red arrow inworld points in front of you (the center of the screen). -

    -At this point, your avatar is facing the landmark. You should be able to see a tall red beacon marking the landmark in-world. -

    -8. Go to the landmark. -

    -[ Basic Skills Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/basics/leading.html b/linden/indra/newview/help/basics/leading.html deleted file mode 100644 index fc78729..0000000 --- a/linden/indra/newview/help/basics/leading.html +++ /dev/null @@ -1,26 +0,0 @@ - - - Leading the Avatar - - -
    -There are multiple ways to move around, but first, we'll learn the basic mouse movement methods. The easiest way to move your avatar is to lead it around by pointing to where you want it to go. -

    -1. Right-click on the ground close to the avatar.

    -A pie menu opens. -

    -2. Move the cursor up and click on "Go Here."

    -The avatar walks to the place where you clicked. -

    -3. Click on the ground far away from the avatar. -

    -4. When the pie menu opens, move the cursor up and click on "Go Here." -

    -If the distance was far enough, your avatar flew to the spot.
    -Take some time now lead your avatar around for a while. - -

    -[ Basic Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/basics/mouse.html b/linden/indra/newview/help/basics/mouse.html deleted file mode 100644 index aff23a0..0000000 --- a/linden/indra/newview/help/basics/mouse.html +++ /dev/null @@ -1,36 +0,0 @@ - - - Walking and Flying with the Mouse - - -
    -The point-and-go method is fine if you know where you want to go, but if you want to just wander around, there's a better way to go. -

    -1. Click on your avatar. -

    -2. When the pie menu opens, move the cursor up and click on "Go...".

    -A small box with arrows in it opens near the bottom of the screen. -

    -3. Click (or click and hold) on all of the arrows, one at a time.

    -If you play with these for a while, you'll get the hang of moving forward and backward, turning left and right, side-walking left and right, and even jumping and crouching. -

    -Now we'll try a shortcut: -

    -4. Click and hold on the forward arrow, then, while still holding, slide the cursor out of the box, left and right, forward and backward. -

    -Take some time and practice guiding your avatar around in this way. -

    -5. Click on the Fly button. -

    -Your avatar rises into the air. -

    -6. Use the arrows as before to fly around. Don't forget to try the up and down arrows. -

    -Take your time and practice a little before you move on. -

    -7. Click on the Fly button again to return to the ground. -

    -[ Basic Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/basics/movement.html b/linden/indra/newview/help/basics/movement.html deleted file mode 100644 index a2d9d06..0000000 --- a/linden/indra/newview/help/basics/movement.html +++ /dev/null @@ -1,17 +0,0 @@ - - - Basic Movement - - - -
    -Click on the first topic below to get moving. -

    -Walking and Flying with the Keyboard
    -Using Landmarks
    - -

    -[ Basic Skills Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/basics/profile.html b/linden/indra/newview/help/basics/profile.html deleted file mode 100644 index ea08be4..0000000 --- a/linden/indra/newview/help/basics/profile.html +++ /dev/null @@ -1,28 +0,0 @@ - - - Your Profile - - - - -
    -Your avatar's appearance tells people something about you (the person behind the avatar). There's also another way to let others know about yourself: your Profile. -

    -1. Click on your avatar. -

    -2. From the pie menu, select My Profile ... -

    -Your Profile opens. It has your screen name and some checkboxes and spaces to supply informaiton about yourself. It also shows how others have rated you and how many others you have rated. -

    -There's also a place to put an image. The image can be your (human) picture, your avatar's picture, a logo, or anything else (or nothing) that you want. To change the image, click on it. An Image Picking dialog will open and let you select from all the images at your disposal. -

    -The information in your Profile is public. The Find feature searches through profiles to help you find others with similar interests (and others find you). -

    -3. Take some time and tell us about yourself. You can always come back and change or add to this information later. -

    -When you're ready to move on, click Next below. - -

    -[ Basic Skills Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/basics/shopping.html b/linden/indra/newview/help/basics/shopping.html deleted file mode 100644 index 4e0bbcc..0000000 --- a/linden/indra/newview/help/basics/shopping.html +++ /dev/null @@ -1,53 +0,0 @@ - - - Shopping 101 - - -
    -Let's go shopping. -

    -In Second Life, there are "official" stores and vending machines where you can buy things, but you can also buy (or take a free copy of) many things that aren't in stores. In fact, you can put a price on anything you build and if people want it, they can buy it and you get the money. -

    -You can use the Find window to look up a variety of places, selling virtually anything imaginable. Whatever your interest, there's probably a store selling it somewhere in Second Life. When you've selected a store in the Find window, you can teleport to it or mark it on your Map. -

    -"Window shopping" in Second Life is actually quite simple. -

    -1. Find an object that interests you, and point to it. -

    -After a second or so some information about the object will pop up. The information will include whether it's for sale and how much it costs. If the object is not listed as For Sale, try left-clicking it to see if it's a scripted vendor instead. (If so, it'll tell you in chat how much the item costs.) -

    -Once you find something that interests you: -

    -2. Right-click on the object. -

    -A pie menu opens. -

    -3. Select Buy on the left of the pie menu. -

    -A confirmation dialog will open giving you the details of the transaction, including the price. If you want it: -

    -4. Click on Buy. -

    -If the object's popup doesn't list it as For Sale, but clicking it tells you the price, then the Buy menu choice probably isn't available. In this case, we're going to Pay the vendor, and it'll give us the item: -

    -4. Right-click on the vendor and choose Pay. Enter the cost of the item you're trying to buy, and click OK. When a blue box comes up offering you the item you just bought, click Accept. -

    -You've just made your first financial transaction. The object you just bought is placed in your Inventory. Notice that its name may include (no copy), (no modify), or (no transfer); this means that you can't copy the object, can't edit the object, or can't give the object away, respectively. -

    -6. If you bought clothing, drag it from Inventory onto your avatar. If you bought an object, drag it from Inventory to some location inworld. -

    -If you bought clothing, your avatar will wear the clothing when you drag it onto yourself. If you bought an object, it'll appear inworld at the place you drop it. -

    -If you thought you bought clothing, but end up with a box on your head when you drag it onto yourself, don't worry! Right-click the box and Detach it, then drag in somewhere else (just like an object). Right-click the box and choose Edit, then click More, then finally choose its Contents. You should find the clothing you bought in there; drag it from the box's Contents into your Inventory. You can then wear your new clothing. -

    -If the object you bought is (no copy), notice how it disappears from inventory when you bring it inworld. If you lose track of a no-copy object when it's inworld, it may be very hard to find it again! You can right-click your object and choose Take to put it back in your inventory. If the object isn't (no copy), notice how it remains in your Inventory even when you bring it inworld. You'll always have a copy of this object (unless you manually delete the Inventory copy, of course!) -

    -7. To take back an object inworld, right-click on the object you created, and choose Take. To delete the object, right-click it, and press the Del key on your keyboard. -

    -You should only delete an object if you still have a copy in Inventory! If you don't have a copy in your Inventory, be sure and Take it instead. -

    -You can go on a shopping binge now, or click Next to move on. -

    -[ Basic Skills Home | Previous | Next ] - - \ No newline at end of file diff --git a/linden/indra/newview/help/bg_dots_grey.gif b/linden/indra/newview/help/bg_dots_grey.gif deleted file mode 100644 index f9ec608..0000000 Binary files a/linden/indra/newview/help/bg_dots_grey.gif and /dev/null differ diff --git a/linden/indra/newview/help/community_standards.html b/linden/indra/newview/help/community_standards.html deleted file mode 100644 index cf94cc6..0000000 --- a/linden/indra/newview/help/community_standards.html +++ /dev/null @@ -1,52 +0,0 @@ - - - Second Life Community Standards - - -
    -Second Life(TM): Community Standards
    -
    -Welcome to Second Life. We hope you'll have a richly rewarding experience, filled with creativity, self expression and fun. The goals of the Community Standards are simple: treat each other with respect and without harassment, adhere to local standards as indicated by simulator ratings, and refrain from any hate activity which slurs a real-world individual or real-world community. -

    -The Big Six
    -Within Second Life, we want to support Residents in shaping their specific experiences and making their own choices. The Community Standards sets out six behaviors, the "Big Six", that will result in suspension or, with repeated violations, expulsion from the Second Life Community. All Second Life Community Standards apply to all areas of Second Life, the Second Life Forums, and the Second Life Website. -

    -1. Intolerance
    -Combating intolerance is a cornerstone of Second Life's Community Standards. Actions that marginalize, belittle, or defame individuals or groups inhibit the satisfying exchange of ideas and diminish the Second Life community as whole. The use of derogatory or demeaning language or images in reference to another Resident's race, ethnicity, gender, religion, or sexual preference is never allowed in Second Life. -

    -2. Harassment
    -Given the myriad capabilities of Second Life, harassment can take many forms. Communicating or behaving in a manner which is offensively coarse, intimidating or threatening, constitutes unwelcome sexual advances or requests for sexual favors, or is otherwise likely to cause annoyance or alarm is Harassment. -

    -3. Assault
    -Most areas in Second Life are identified as Safe. Assault in Second Life means: shooting, pushing, or shoving another Resident in a Safe Area (see Global Standards below); creating or using scripted objects which singularly or persistently target another Resident in a manner which prevents their enjoyment of Second Life. -

    -4. Disclosure
    -Residents are entitled to a reasonable level of privacy with regard to their Second Lives. Sharing personal information about a fellow Resident --including gender, religion, age, marital status, race, sexual preference, and real-world location beyond what is provided by the Resident in the First Life page of their Resident profile is a violation of that Resident's privacy. Remotely monitoring conversations, posting conversation logs, or sharing conversation logs without consent are all prohibited in Second Life and on the Second Life Forums. -

    -5. Indecency
    -Second Life is an adult community, but Mature material is not necessarily appropriate in all areas (see Global Standards below). Content, communication, or behavior which involves intense strong language or expletives, nudity or sexual content, the depiction of sex or strong violence, or anything else broadly offensive must be contained within private land in areas rated Mature (M). Names of Residents, objects, places and groups are broadly viewable in Second Life directories and on the Second Life website, and must adhere to PG guidelines. -

    -6. Disturbing the Peace
    -Every Resident has a right to live their Second Life. Disrupting scheduled events, repeated transmission of undesired advertising content, the use of repetitive sounds, following or self-spawning items, or other objects that intentionally slow server performance or inhibit another Resident's ability to enjoy Second Life are examples of Disturbing the Peace. -

    -Policies and Policing
    -
    -Global Standards, Local Ratings
    -All areas of Second Life, including the www.secondlife.com website and the Second Life Forums, adhere to the same Community Standards. Locations within Second Life are noted as Safe or Unsafe and rated Mature (M) or non-Mature (PG), and behavior must conform to the local ratings. Any unrated area of Second Life or the Second Life website should be considered non-Mature (PG). -

    -Warning, Suspension, Banishment
    -Second Life is a complex society, and it can take some time for new Residents to gain a full understanding of local customs and mores. Generally, violations of the Community Standards will first result in a Warning, followed by Suspension and eventual Banishment from Second Life. In-World Representatives, called Liaisons, may occasionally address disciplinary problems with a temporary removal from Second Life. -

    -Global Attacks
    -Community Standards violations which broadly interfere with or disrupt the Second Life community, the Second Life servers or other systems related to Second Life cannot be tolerated in any form. Such actions will result in a minimum two-week suspension and a review of your account for probable removal from Second Life. -

    -Alternate Accounts
    -While Residents may choose to play Second Life with more than one account, specifically or consistently using an alternate account to harass other Residents or violate the Community Standards is not acceptable. Alternate accounts are generally treated as separate from a Resident's principal account, but misuse of alternate accounts can and will result in disciplinary action on the principal account. -

    -Buyer Beware
    -Linden Lab does not exercise editorial control over the content of Second Life, and will make no specific efforts to review the textures, objects, sounds or other content created within Second Life. Additionally, Linden Lab does not certify or endorse the operation of in-world games, vending machines, or retail locations; refunds must be requested from the owners of these objects. -

    -Reporting Abuse
    -Residents should report violations of the Community Standards using the Abuse Reporter tool located under the Help menu in the in-world tool bar. Every Abuse Report is individually investigated, and the identity of the reporter is kept strictly confidential. If you need immediate assistance, in-world Liaisons may be available to help. Look for Residents with the last name Linden. - - diff --git a/linden/indra/newview/help/graphics_driver_update.html b/linden/indra/newview/help/graphics_driver_update.html deleted file mode 100644 index 3a3b25c..0000000 --- a/linden/indra/newview/help/graphics_driver_update.html +++ /dev/null @@ -1,12 +0,0 @@ - - - - - Second Life: Graphics Driver Update - - - -

    Taking you to the Second Life Support page at -http://www.secondlife.com/support/.

    - - diff --git a/linden/indra/newview/help/grey_corner_bl.gif b/linden/indra/newview/help/grey_corner_bl.gif deleted file mode 100644 index 14e076a..0000000 Binary files a/linden/indra/newview/help/grey_corner_bl.gif and /dev/null differ diff --git a/linden/indra/newview/help/grey_corner_br.gif b/linden/indra/newview/help/grey_corner_br.gif deleted file mode 100644 index f4520fc..0000000 Binary files a/linden/indra/newview/help/grey_corner_br.gif and /dev/null differ diff --git a/linden/indra/newview/help/grey_corner_tl.gif b/linden/indra/newview/help/grey_corner_tl.gif deleted file mode 100644 index ef7434d..0000000 Binary files a/linden/indra/newview/help/grey_corner_tl.gif and /dev/null differ diff --git a/linden/indra/newview/help/grey_corner_tr.gif b/linden/indra/newview/help/grey_corner_tr.gif deleted file mode 100644 index d53c4d8..0000000 Binary files a/linden/indra/newview/help/grey_corner_tr.gif and /dev/null differ diff --git a/linden/indra/newview/help/grey_pixel.gif b/linden/indra/newview/help/grey_pixel.gif deleted file mode 100644 index 491eec6..0000000 Binary files a/linden/indra/newview/help/grey_pixel.gif and /dev/null differ diff --git a/linden/indra/newview/help/header_banner.jpg b/linden/indra/newview/help/header_banner.jpg deleted file mode 100644 index 3e37c65..0000000 Binary files a/linden/indra/newview/help/header_banner.jpg and /dev/null differ diff --git a/linden/indra/newview/help/index.html b/linden/indra/newview/help/index.html deleted file mode 100644 index 197cbed..0000000 --- a/linden/indra/newview/help/index.html +++ /dev/null @@ -1,18 +0,0 @@ - - - - Second Life Help - - -
    -Choose your topic: -

    -Welcome to Second Life Orientation
    -Welcome Back to Second Life
    -Basic Second Life Skills
    -Second Life Concepts
    -Advanced Second Life Skills -

    -Second Life Community Standards - - diff --git a/linden/indra/newview/help/sl_logo.gif b/linden/indra/newview/help/sl_logo.gif deleted file mode 100644 index 037ec80..0000000 Binary files a/linden/indra/newview/help/sl_logo.gif and /dev/null differ diff --git a/linden/indra/newview/help/spacer.gif b/linden/indra/newview/help/spacer.gif deleted file mode 100644 index 35d42e8..0000000 Binary files a/linden/indra/newview/help/spacer.gif and /dev/null differ diff --git a/linden/indra/newview/help/unable_to_connect.html b/linden/indra/newview/help/unable_to_connect.html deleted file mode 100644 index a8973a1..0000000 --- a/linden/indra/newview/help/unable_to_connect.html +++ /dev/null @@ -1,149 +0,0 @@ - - - - - - -Second Life | Unable to Connect - -
    - -
    - -
    -
    -
    -
    -
    -
    - - - - - - -
    - - -
    - -
    -
    -
    -
    -
    -
    - - - - - - - -
    -

     

    - - - - - -

    Second Life - Unable to Connect to Server.

    - - - - -
    - - - - -
    -
    -

    Second Life has failed to connect to its server. This -message can appear because you are not connected to the Internet; because -your router or firewall is blocking Second Life network access; because -third-party software (such as firewall or internet security software) is -blocking Second Life; or because the Second Life servers are offline.
    -

    -

    First, make sure you can reach a common web site like Google. If you cannot connect to -Google, the problem is probably with your network or your Internet -Service Provider.
    -

    -

    Next, check the Second Life Status web -page to make sure the servers are up.
    -

    -

    If the servers are up but you are still having -problems, please visit Second Life Help for assistance:
    -

    -

    http://www.secondlife.com/help/

    -
    - -
    -
    -
    -

    - For additional details about system upgrades, maintenance, outages, or other known problems please read - the Official Linden Blog. -

    - - - - -
    - - - - - -
    -
    \ No newline at end of file diff --git a/linden/indra/newview/help/unsupported_card.html b/linden/indra/newview/help/unsupported_card.html deleted file mode 100644 index 2d58b75..0000000 --- a/linden/indra/newview/help/unsupported_card.html +++ /dev/null @@ -1,58 +0,0 @@ - - - - Second Life Error - - - -

    - - - - - - -
    - - - - - - - - - -
    - - - - - - -
    -

    -

    Unsupported Graphics -Card

    -
    -

    If you are receiving this message, your graphics card may not be compatible with Second Life. -Attempting to use Second Life with your current system configuration may cause the program to crash -or become unresponsive. Minimum system requirements are listed on the Second Life Support web site:

    -

    http://secondlife.com/support/

    -

    If you are using a supported video card, contact the -manufacturer to obtain video driver updates. Video driver -updates for ATI and Nvidia graphics products are available for download -from the following web sites:

    -

    http://www.ati.com/
    - http://www.nvidia.com/

    -

    Finally, try setting your display to "True Color -(32-bit)" under Control Panels, Display before running Second Life.

    -
    -
    -
    -
    - - diff --git a/linden/indra/newview/help/welcome/avatar.html b/linden/indra/newview/help/welcome/avatar.html deleted file mode 100644 index 2a272eb..0000000 --- a/linden/indra/newview/help/welcome/avatar.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Your Avatar - - -
    -Your avatar is your representative in Second Life. -

    -It's been randomly created to get you started, but you'll be able to customize it to look almost any way you want -- and you can change it as often as you like. -

    -You can create and save complete outfits consisting of clothing, body shape, attachments and more, and change the total look of your avatar with a simple drag and drop. -

    -Avatars can be male or female, and can be just about any size or shape you can imagine. Avatars can wear layers of clothes, and can have accessories -- ranging from jet packs to jewelry -- attached to a number of places. -

    -All around your avatar is Second Life, filled with hills, valleys, trees, grass, bodies of water, buildings, all sorts of objects, and people. Don't worry, you'll be exploring it soon. -

    -[Welcome Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/welcome/buttons.html b/linden/indra/newview/help/welcome/buttons.html deleted file mode 100644 index 7936862..0000000 --- a/linden/indra/newview/help/welcome/buttons.html +++ /dev/null @@ -1,33 +0,0 @@ - - - The Buttons - - -
    -Along the bottom of the screen, you'll see a number of buttons. -

    -IM lets you Instant Message friends, groups, and people you meet. -

    -Chat opens a chat bar you can use to talk to people nearby. -

    -Friends pulls up your Friends list, so you can add people you know, view their profile, etc. -

    -Fly lets your avatar take flight. (You can also use F or the Home key when you're not chatting.) -

    -Snapshot takes a snapshot of the current screen, which you can save to Inventory or disk, or mail as a postcard to someone else. -

    -Events allows you to view upcoming events. -

    -Find opens a dialog to help you find people, places, groups, events, and other things in Second Life. -

    -Mini-Map shows or hides the small map in the upper-right corner of your screen. -

    -Map opens the World Map window to give you a bigger picture of where you are. -

    -There's one more button to look at, in the lower-right corner of the screen: Inventory. -

    -Inventory opens your Inventory -- your storage "bag" for everything from Friends' contact information, to landmarks, to outfits for your avatar. -

    -[Welcome Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/welcome/chat.html b/linden/indra/newview/help/welcome/chat.html deleted file mode 100644 index 5143dc4..0000000 --- a/linden/indra/newview/help/welcome/chat.html +++ /dev/null @@ -1,20 +0,0 @@ - - - Chat and Instant Messaging - - -
    -The bottom of the screen is dedicated to communication: Chat and Instant Messaging. -

    -Chat is the quickest and easiest way to communicate with anyone who's nearby. -

    -Instant Messaging is a more private way to talk to people you already know. -

    -To chat, hit Enter (Return), type your message, then hit Enter (Return) again. -

    -We'll talk more about Instant Messaging soon. -

    -[Welcome Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/welcome/graduation.html b/linden/indra/newview/help/welcome/graduation.html deleted file mode 100644 index b7cd673..0000000 --- a/linden/indra/newview/help/welcome/graduation.html +++ /dev/null @@ -1,14 +0,0 @@ - - - Graduation - - - -
    -Congratulations! You've finished your first session. -

    -Click Next to continue your journey. -

    -[Welcome Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/welcome/map.html b/linden/indra/newview/help/welcome/map.html deleted file mode 100644 index 2f92870..0000000 --- a/linden/indra/newview/help/welcome/map.html +++ /dev/null @@ -1,25 +0,0 @@ - - - The Map Window - - -
    -The Mini Map window shows you an overhead view of the part of the world near you. It will help you find people and places, as well as navigate your way around the world. -

    -Each Region (a named area also called a "simulator") on the map is shown as a square tile, representing about 16 acres of the world. -

    -The mini-map doesn't display the whole world -- only the nearest few Regions. (For a view of the whole world, Click on the Mini Map to view the World Map.) The map moves as you move, with new regions appearing as you approach them. -

    -In both the Mini Map and World Map, water is shown on the map as dark blue, and the ground is green, brown or white, depending on the alitude. Gray blocks indicate buildings or other human-made structures to investigate. Your avatar always appears in the center of the Map window as a white dot, with a faint gray triangle indicating your 3D field of view. Other avatars appear as green dots. -

    -In the World Map, if you select a landmark with the Landmark Tracking pull-down, the landmark will be shown on the map as a red dot. (If the landmark isn't within view, a red arrow will point in its direction.) Active landmarks also appear in the world as a red "beacon" that only you can see. -

    -People on your Friends list can be displayed on the map using the Resident Tracking pull-down. While you're tracking them, a red "beacon" (that only you can see) will mark their location in the world. -

    -The World Map window can be enlarged, resized and moved. The map itself can be enlarged or shrunk within the window, with the Zoom slider. -

    -Finally, the Background pull-down menu allows to set the World Map to display terrain, new places, popular places, items for sale, and available land. -

    -[Welcome Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/welcome/menus.html b/linden/indra/newview/help/welcome/menus.html deleted file mode 100644 index b9def09..0000000 --- a/linden/indra/newview/help/welcome/menus.html +++ /dev/null @@ -1,21 +0,0 @@ - - - The Menus - - -
    -The menus along the top of the screen work like menus in most programs: Click on a menu to open it, then click on the menu item to select it. -

    -Open each menu and look over the different menu items as you read the descriptions. -

    -- The File menu handles uploading audio clips and textures, taking screenshots and quitting.
    -- The Edit menu lets you do the usual Edit menu tasks like cut, copy, paste and find, plus edit some Second Life specific things, like your avatar, groups and preferences.
    -- The View menu handles what you see on your screen, and lets you display things like flying controls and your Linden Dollar account history.
    -- The World menu creates landmarks, lets you set your home location and enables you to teleport home.
    -- The Tools menu provides access to many of the advanced creation tools that you can use to build your own objects -- or even a home.
    -- The Help menu lets you access this and other help screens. -

    -[Welcome Home | Previous | Next ] - - - diff --git a/linden/indra/newview/help/welcome/screen.html b/linden/indra/newview/help/welcome/screen.html deleted file mode 100644 index 5d931a8..0000000 --- a/linden/indra/newview/help/welcome/screen.html +++ /dev/null @@ -1,19 +0,0 @@ - - - The Screen - - -
    -When you first enter Second Life you see a few things: -

    -- You, standing in your Second Life.
    -- This Help window.
    -- A Menu bar at the top of the screen on the left.
    -- Some buttons across the bottom of the screen.
    -- The Mini Map window near the upper-right corner of the screen.
    -- Chat and Instant Messaging along the bottom of the screen.
    -- Your bank account balance upper-right corner. -

    -[Welcome Home | Previous | Next ] - - diff --git a/linden/indra/newview/help/welcome/welcome.html b/linden/indra/newview/help/welcome/welcome.html deleted file mode 100644 index 2632f0a..0000000 --- a/linden/indra/newview/help/welcome/welcome.html +++ /dev/null @@ -1,31 +0,0 @@ - - - - Welcome - - -
    -WELCOME TO SECOND LIFE ORIENTATION ISLAND -

    You are in a safe, protected place where you can explore, learn and -progress at your own pace. -

    -

    Press the arrow keys on your keyboard to walk -and look around. -

    -

    Follow the path to the help stations.  At -each station, click on the spinning Second Life hand to learn what to -do.
    -

    -

    The person you see in front of you is your avatar -- your -representative in Second Life. You'll be able to change how it looks -soon. -

    -

    You can close this help window now to unclutter your view. You can -always bring it back by hitting F1 or selecting Basic Help in the Help -menu. -

    -

    If you've already finished your orientation and moved on to the -mainland, click here. -

    - - diff --git a/linden/indra/newview/help/welcome/welcomeback.html b/linden/indra/newview/help/welcome/welcomeback.html deleted file mode 100644 index 1a674b4..0000000 --- a/linden/indra/newview/help/welcome/welcomeback.html +++ /dev/null @@ -1,32 +0,0 @@ - - - Welcome Back! - - - -
    -WELCOME BACK TO SECOND LIFE -

    -If you haven't finished your orientation yet, then click here. -

    -If you have finished your orientation and are now on the Second Life mainland, you're ready to explore a whole new world. -

    -This help system will walk you through a series of topics that will build on your orientation experience and teach you everything you need to begin your Second Life. -

    -You don't have to plow through the whole thing in one sitting -- you can close the help system and return to it at any time. Just hit F1 or select Basic Help from the Help menu. -

    -Click on the first topic below to get started. -

    -TOPICS
    -The Screen
    -Your Avatar and the World
    -The Menus
    -The Buttons
    -The Map Window
    -Chat and Instant Messaging -

    -[ Next ] - - - - diff --git a/linden/indra/newview/help/window_creation_error.html b/linden/indra/newview/help/window_creation_error.html deleted file mode 100644 index e6d155e..0000000 --- a/linden/indra/newview/help/window_creation_error.html +++ /dev/null @@ -1,73 +0,0 @@ - - - - Second Life Error - - - -

    - - - - - - -
    - - - - - - - - - -
    - - - - - - -
    -

    -

    Unable to Configure -Display

    -
    -

    Second Life tries to create a display window at a resolution of 1024x768 pixels at a color depth of 32-bit. This -message indicates that Windows is unable to create that window. This message often appears when your graphics hardware does not meet Second Life's Minimum System Requirements; however, it may also appear if your current Windows display settings aren't high enough.

    -

    Suggestions:
    -Set your monitor to True Color (32-bit). -

      -
    1. Click Start, point to Settings, -click Control Panel
    2. -
    3. Click Display
    4. -
    5. On the Settings tab, under Color Quality, -select Highest (32 bit).
    6. -
    7. Make sure the display resolution is 1024x768 or higher.
    8. -
    9. Click OK
    10. -
    11. When you are prompted to keep this setting, click Yes.
    12. -
    -

    -

    If the problem continues, contact your video card -manufacturer to obtain video driver updates. Video driver -updates for ATI and Nvidia graphics products are available for download -from the following websites:

    -

    http://www.ati.com/support/driver.html
    - http://www.nvidia.com/content/drivers/drivers.asp

    -

    For help with identifying supported video cards, -please visit Second Life Help:
    -

    -

    http://www.secondlife.com/help/

    -
    -
    -
    -
    - - diff --git a/linden/indra/newview/installer.vcproj b/linden/indra/newview/installer.vcproj deleted file mode 100644 index 86bac7d..0000000 --- a/linden/indra/newview/installer.vcproj +++ /dev/null @@ -1,184 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/linden/indra/newview/installers/darwin/mac_image_DS_Store b/linden/indra/newview/installers/darwin/mac_image_DS_Store new file mode 100644 index 0000000..ac44787 Binary files /dev/null and b/linden/indra/newview/installers/darwin/mac_image_DS_Store differ diff --git a/linden/indra/newview/installers/darwin/mac_image_background.tga b/linden/indra/newview/installers/darwin/mac_image_background.tga new file mode 100644 index 0000000..2539366 Binary files /dev/null and b/linden/indra/newview/installers/darwin/mac_image_background.tga differ diff --git a/linden/indra/newview/installers/darwin/mac_image_hidden b/linden/indra/newview/installers/darwin/mac_image_hidden new file mode 100644 index 0000000..a39bde4 --- /dev/null +++ b/linden/indra/newview/installers/darwin/mac_image_hidden @@ -0,0 +1 @@ +background.tga diff --git a/linden/indra/newview/installers/windows/installer_template.nsi b/linden/indra/newview/installers/windows/installer_template.nsi new file mode 100644 index 0000000..8ab7c4f --- /dev/null +++ b/linden/indra/newview/installers/windows/installer_template.nsi @@ -0,0 +1,862 @@ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; @file viewer_manifest.py +;;; @author James Cook, Don Kjer +;;; @brief NSIS script for creating a Windows installer. +;;; This file has variables expanded by viewer_manifest.py +;;; to produce the complete nsi script file. +;;; For info, see http://www.nullsoft.com/free/nsis/ +;;; NSIS 2.02 or higher required +;;; +;;; Copyright (c) 2006-$CurrentYear$, Linden Research, Inc. +;;; $License$ +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Compiler flags +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +;;; Detect NSIS compiler version +!define "NSIS${NSIS_VERSION}" +!ifdef "NSISv2.02" | "NSISv2.03" | "NSISv2.04" | "NSISv2.05" | "NSISv2.06" + ;;; before 2.07 defaulted lzma to solid (whole file) + SetCompressor lzma +!else + ;;; after 2.07 required /solid for whole file compression + SetCompressor /solid lzma +!endif + +SetOverwrite on ; overwrite files +SetCompress auto ; compress iff saves space +SetDatablockOptimize off ; only saves us 0.1%, not worth it +XPStyle on ; add an XP manifest to the installer + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Project flags +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +%%VERSION%% + +;;; Tweak for different servers/builds (this placeholder is replaced by viewer_manifest.py) +%%GRID_VARS%% + +Name ${INSTNAME} + +SubCaption 0 " Setup" ; override "license agreement" text + +BrandingText " " ; bottom of window text +Icon res\install_icon.ico ; our custom icon +UninstallIcon res\uninstall_icon.ico ; our custom icon +WindowIcon on ; show our icon in left corner +BGGradient off ; no big background window +CRCCheck on ; make sure CRC is OK +InstProgressFlags smooth colored ; new colored smooth look +ShowInstDetails nevershow ; no details, no "show" button +SetOverwrite on ; stomp files by default +AutoCloseWindow true ; after all files install, close window + +!ifdef UPDATE +LicenseText "This package will update Second Life to version ${VERSION_LONG}." "Next >" +!else +LicenseText "This package will install Second Life on your computer." "Next >" +!endif + +LicenseData "releasenotes.txt" + +InstallDir "$PROGRAMFILES\${INSTNAME}" +InstallDirRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\${INSTNAME}" "" +!ifdef UPDATE +DirText "Installation Directory" "Select the Second Life directory to update:" +!else +DirText "Installation Directory" "Select the directory to install Second Life in:" +!endif + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Variables +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Var INSTPROG +Var INSTEXE +Var INSTFLAGS +Var INSTSHORTCUT + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Sections +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Section "" ; (default section) + +SetShellVarContext all ; install for all users (if you change this, change it in the uninstall as well) + + +; Start with some default values. +StrCpy $INSTFLAGS "${INSTFLAGS}" +StrCpy $INSTPROG "${INSTNAME}" +StrCpy $INSTEXE "${INSTEXE}" +StrCpy $INSTSHORTCUT "${SHORTCUT}" + +IfSilent +2 +Goto NOT_SILENT + Call CheckStartupParams ; Figure out where, what and how to install. +NOT_SILENT: +Call CheckWindowsVersion ; warn if on Windows 98/ME +Call CheckIfAdministrator ; Make sure the user can install/uninstall +Call CheckIfAlreadyCurrent ; Make sure that we haven't already installed this version +Call CloseSecondLife ; Make sure we're not running +Call RemoveNSIS ; Check for old NSIS install to remove + +;;; Don't remove cache files during a regular install, removing the inventory cache on upgrades results in lots of damage to the servers. +;Call RemoveCacheFiles ; Installing over removes potentially corrupted + ; VFS and cache files. + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Files +;;; +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;; This placeholder is replaced by the complete list of all the files in the installer, by viewer_manifest.py +%%INSTALL_FILES%% + +; If this is a silent update, we don't need to re-create these shortcuts or registry entries. +IfSilent POST_INSTALL + +; Shortcuts in start menu +CreateDirectory "$SMPROGRAMS\$INSTSHORTCUT" +SetOutPath "$INSTDIR" +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT.lnk" \ + "$INSTDIR\$INSTEXE" "$INSTFLAGS" + +!ifdef MUSEUM +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT Museum.lnk" \ + + "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple" +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\$INSTSHORTCUT Museum Spanish.lnk" \ + + "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple -spanish" +!endif + +WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Create Trial Account.url" \ + "InternetShortcut" "URL" \ + "http://www.secondlife.com/registration/" +WriteINIStr "$SMPROGRAMS\$INSTSHORTCUT\SL Your Account.url" \ + "InternetShortcut" "URL" \ + "http://www.secondlife.com/account/" +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\SL Release Notes.lnk" \ + "$INSTDIR\releasenotes.txt" +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\SL Scripting Language Help.lnk" \ + "$INSTDIR\lsl_guide.html" +CreateShortCut "$SMPROGRAMS\$INSTSHORTCUT\Uninstall $INSTSHORTCUT.lnk" \ + '"$INSTDIR\uninst.exe"' '/P="$INSTPROG"' + +; Other shortcuts +SetOutPath "$INSTDIR" +CreateShortCut "$DESKTOP\$INSTSHORTCUT.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS" +CreateShortCut "$INSTDIR\$INSTSHORTCUT.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS" +CreateShortCut "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" \ + '"$INSTDIR\uninst.exe"' '/P="$INSTPROG"' + +!ifdef MUSEUM +CreateShortCut "$DESKTOP\$INSTSHORTCUT Museum.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple" + +CreateShortCut "$DESKTOP\$INSTSHORTCUT Museum Spanish.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple -spanish" + +CreateShortCut "$INSTDIR\$INSTSHORTCUT Museum.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple" + +CreateShortCut "$INSTDIR\$INSTSHORTCUT Museum Spanish.lnk" "$INSTDIR\$INSTEXE" "$INSTFLAGS -simple -spanish" + +!endif + +; Write registry +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" "$INSTDIR" +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" "${VERSION_LONG}" +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Flags" "$INSTFLAGS" +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" "$INSTSHORTCUT" +WriteRegStr HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" "$INSTEXE" +WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "DisplayName" "$INSTPROG (remove only)" +WriteRegStr HKEY_LOCAL_MACHINE "Software\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" "UninstallString" '"$INSTDIR\uninst.exe" /P="$INSTPROG"' + +; Write URL registry info +WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "(default)" "URL:Second Life" +WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}" "URL Protocol" "" +WriteRegStr HKEY_CLASSES_ROOT "${URLNAME}\DefaultIcon" "" '"$INSTDIR\$INSTEXE"' +WriteRegExpandStr HKEY_CLASSES_ROOT "${URLNAME}\shell\open\command" "" '"$INSTDIR\$INSTEXE" $INSTFLAGS -url "%1"' + +Goto WRITE_UNINST + +POST_INSTALL: +; Run a post-executable script if necessary. +Call PostInstallExe + +WRITE_UNINST: +; write out uninstaller +WriteUninstaller "$INSTDIR\uninst.exe" + +; end of default section +SectionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; PostInstallExe +; This just runs any post installation scripts. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function PostInstallExe +push $0 + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "PostInstallExe" + ;MessageBox MB_OK '$0' + ExecWait '$0' +pop $0 +FunctionEnd + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; CheckStartupParameters +; Sets INSTFLAGS, INSTPROG, and INSTEXE. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CheckStartupParams +push $0 +push $R0 + + ; Look for a registry entry with info about where to update. + Call GetProgramName + pop $R0 + StrCpy $INSTPROG "$R0" + StrCpy $INSTEXE "$R0.exe" + + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" + ; If key doesn't exist, skip install + IfErrors ABORT + StrCpy $INSTDIR "$0" + + ; We now have a directory to install to. Get the startup parameters and shortcut as well. + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Flags" + IfErrors +2 + StrCpy $INSTFLAGS "$0" + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" + IfErrors +2 + StrCpy $INSTSHORTCUT "$0" + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" + IfErrors +2 + StrCpy $INSTEXE "$0" + Goto FINISHED + +ABORT: + MessageBox MB_OK "Could not find the program '$INSTPROG'. Silent update failed." + Quit + +FINISHED: + ;MessageBox MB_OK "INSTPROG: $INSTPROG, INSTEXE: $INSTEXE, INSTFLAGS: $INSTFLAGS" +pop $R0 +pop $0 +FunctionEnd + +Function un.CheckStartupParams +push $0 +push $R0 + + ; Look for a registry entry with info about where to update. + Call un.GetProgramName + pop $R0 + StrCpy $INSTPROG "$R0" + StrCpy $INSTEXE "$R0.exe" + + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" + ; If key doesn't exist, skip install + IfErrors ABORT + StrCpy $INSTDIR "$0" + + ; We now have a directory to install to. Get the startup parameters and shortcut as well. + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Flags" + IfErrors +2 + StrCpy $INSTFLAGS "$0" + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Shortcut" + IfErrors +2 + StrCpy $INSTSHORTCUT "$0" + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Exe" + IfErrors +2 + StrCpy $INSTEXE "$0" + Goto FINISHED + +ABORT: + MessageBox MB_OK "Could not find the program '$INSTPROG'. Silent update failed." + Quit + +FINISHED: + ;MessageBox MB_OK "INSTPROG: $INSTPROG, INSTEXE: $INSTEXE, INSTFLAGS: $INSTFLAGS" +pop $R0 +pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; After install completes, offer readme file +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function .onInstSuccess + MessageBox MB_YESNO \ + "Start Second Life now?" /SD IDYES IDNO NoReadme + ; Assumes SetOutPath $INSTDIR + Exec '"$INSTDIR\$INSTEXE" $INSTFLAGS' + NoReadme: +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Remove old NSIS version. Modifies no variables. +; Does NOT delete the LindenWorld directory, or any +; user files in that directory. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function RemoveNSIS + Push $0 + ; Grab the installation directory of the old version + DetailPrint "Checking for old version..." + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "" + + ; If key doesn't exist, skip uninstall + IfErrors NO_NSIS + + ; Clean up legacy beta shortcuts + Delete "$SMPROGRAMS\Second Life Beta.lnk" + Delete "$DESKTOP\Second Life Beta.lnk" + Delete "$SMPROGRAMS\Second Life.lnk" + + ; Clean up old newview.exe file + Delete "$INSTDIR\newview.exe" + + ; Intentionally don't delete the stuff in + ; Documents and Settings, so we keep the user's settings + + NO_NSIS: + Pop $0 +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Make sure we're not on Windows 98 / ME +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CheckWindowsVersion + DetailPrint "Checking Windows version..." + Call GetWindowsVersion + Pop $R0 + ; Just get first two characters, ignore 4.0 part of "NT 4.0" + StrCpy $R0 $R0 2 + ; Blacklist certain OS versions + StrCmp $R0 "95" win_ver_bad + StrCmp $R0 "98" win_ver_bad + StrCmp $R0 "ME" win_ver_bad + StrCmp $R0 "NT" win_ver_bad + Return +win_ver_bad: + MessageBox MB_YESNO 'Second Life only supports Windows XP, Windows 2000, and Mac OS X.$\n$\nAttempting to install on Windows $R0 can result in crashes and data loss.$\n$\nInstall anyway?' IDNO win_ver_abort + Return +win_ver_abort: + Quit +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Make sure the user can install/uninstall +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CheckIfAdministrator + DetailPrint "Checking for permission to install..." + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" is_admin + MessageBox MB_OK 'You appear to be using a "limited" account.$\nYou must be an "administrator" to install Second Life.' + Quit +is_admin: + Return +FunctionEnd + +Function un.CheckIfAdministrator + DetailPrint "Checking for permission to uninstall..." + UserInfo::GetAccountType + Pop $R0 + StrCmp $R0 "Admin" is_admin + MessageBox MB_OK 'You appear to be using a "limited" account.$\nYou must be an "administrator" to uninstall Second Life.' + Quit +is_admin: + Return +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Checks to see if the current version has already been installed (according to the registry). +; If it has, allow user to bail out of install process. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CheckIfAlreadyCurrent + Push $0 + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" "Version" + StrCmp $0 ${VERSION_LONG} 0 DONE + MessageBox MB_OKCANCEL "It appears that Second Life ${VERSION_LONG} is already installed.$\n$\nWould you like to install it again?" /SD IDOK IDOK DONE + Quit + + DONE: + Pop $0 + Return +FunctionEnd + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Close the program, if running. Modifies no variables. +; Allows user to bail out of install process. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function CloseSecondLife + Push $0 + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + MessageBox MB_OKCANCEL "Second Life can't be installed while it is already running.$\n$\nFinish what you're doing then select OK to close Second Life and continue.$\nSelect CANCEL to cancel installation." IDOK CLOSE IDCANCEL CANCEL_INSTALL + + CANCEL_INSTALL: + Quit + + CLOSE: + DetailPrint "Waiting for Second Life to shut down..." + SendMessage $0 16 0 0 + + LOOP: + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP + + DONE: + Pop $0 + Return +FunctionEnd + + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Delete files in Documents and Settings\\SecondLife\cache +; Delete files in Documents and Settings\All Users\SecondLife\cache +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function RemoveCacheFiles + +; Delete files in Documents and Settings\\SecondLife +Push $0 +Push $1 +Push $2 + DetailPrint "Deleting cache files in Documents and Settings folder" + + StrCpy $0 0 ; Index number used to iterate via EnumRegKey + + LOOP: + EnumRegKey $1 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $0 + StrCmp $1 "" DONE ; no more users + + ReadRegStr $2 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$1" "ProfileImagePath" + StrCmp $2 "" CONTINUE 0 ; "ProfileImagePath" value is missing + + ; Required since ProfileImagePath is of type REG_EXPAND_SZ + ExpandEnvStrings $2 $2 + + ; When explicitly uninstalling, everything goes away + RMDir /r "$2\Application Data\SecondLife\cache" + + CONTINUE: + IntOp $0 $0 + 1 + Goto LOOP + DONE: +Pop $2 +Pop $1 +Pop $0 + +; Delete files in Documents and Settings\All Users\SecondLife +Push $0 + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "Common AppData" + StrCmp $0 "" +2 + RMDir /r "$0\SecondLife\cache" +Pop $0 + +; Delete filse in C:\Windows\Application Data\SecondLife +; If the user is running on a pre-NT system, Application Data lives here instead of +; in Documents and Settings. +RMDir /r "$WINDIR\Application Data\SecondLife\cache" + +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Delete files in Documents and Settings\\SecondLife +; Delete files in Documents and Settings\All Users\SecondLife +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function un.DocumentsAndSettingsFolder + +; Delete files in Documents and Settings\\SecondLife +Push $0 +Push $1 +Push $2 + + DetailPrint "Deleting files in Documents and Settings folder" + + StrCpy $0 0 ; Index number used to iterate via EnumRegKey + + LOOP: + EnumRegKey $1 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList" $0 + StrCmp $1 "" DONE ; no more users + + ReadRegStr $2 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows NT\CurrentVersion\ProfileList\$1" "ProfileImagePath" + StrCmp $2 "" CONTINUE 0 ; "ProfileImagePath" value is missing + + ; Required since ProfileImagePath is of type REG_EXPAND_SZ + ExpandEnvStrings $2 $2 + + ; If uninstalling a normal install remove everything + ; Otherwise (preview/dmz etc) just remove cache + StrCmp $INSTFLAGS "" RM_ALL RM_CACHE + RM_ALL: + RMDir /r "$2\Application Data\SecondLife" + GoTo CONTINUE + RM_CACHE: + RMDir /r "$2\Application Data\SecondLife\Cache" + + CONTINUE: + IntOp $0 $0 + 1 + Goto LOOP + DONE: + +Pop $2 +Pop $1 +Pop $0 + +; Delete files in Documents and Settings\All Users\SecondLife +Push $0 + ReadRegStr $0 HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Explorer\Shell Folders" "Common AppData" + StrCmp $0 "" +2 + RMDir /r "$0\SecondLife" +Pop $0 + +; Delete filse in C:\Windows\Application Data\SecondLife +; If the user is running on a pre-NT system, Application Data lives here instead of +; in Documents and Settings. +RMDir /r "$WINDIR\Application Data\SecondLife" + +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; Close the program, if running. Modifies no variables. +; Allows user to bail out of uninstall process. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function un.CloseSecondLife + Push $0 + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + MessageBox MB_OKCANCEL "Second Life can't be uninstalled while it is already running.$\n$\nFinish what you're doing then select OK to close Second Life and continue.$\nSelect CANCEL to cancel installation." IDOK CLOSE IDCANCEL CANCEL_UNINSTALL + + CANCEL_UNINSTALL: + Quit + + CLOSE: + DetailPrint "Waiting for Second Life to shut down..." + SendMessage $0 16 0 0 + + LOOP: + FindWindow $0 "Second Life" "" + IntCmp $0 0 DONE + Sleep 500 + Goto LOOP + + DONE: + Pop $0 + Return +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Delete the installed files +;;; This deletes the uninstall executable, but it works +;;; because it is copied to temp directory before running +;;; +;;; Note: You must list all files here, because we only +;;; want to delete our files, not things users left in the +;;; application directories. +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Function un.ProgramFiles + +;; Remove mozilla file first so recursive directory deletion doesn't get hung up +Delete "$INSTDIR\app_settings\mozilla\components" + +;; This placeholder is replaced by the complete list of files to uninstall by viewer_manifest.py +%%DELETE_FILES%% + +;; Optional/obsolete files. Delete won't fail if they don't exist. +Delete "$INSTDIR\dronesettings.ini" +Delete "$INSTDIR\message_template.msg" +Delete "$INSTDIR\newview.pdb" +Delete "$INSTDIR\newview.map" +Delete "$INSTDIR\SecondLife.pdb" +Delete "$INSTDIR\SecondLife.map" +Delete "$INSTDIR\comm.dat" +Delete "$INSTDIR\*.glsl" +Delete "$INSTDIR\motions\*.lla" +Delete "$INSTDIR\trial\*.html" +Delete "$INSTDIR\newview.exe" +;; Remove entire help directory +Delete "$INSTDIR\help\Advanced\*" +RMDir "$INSTDIR\help\Advanced" +Delete "$INSTDIR\help\basics\*" +RMDir "$INSTDIR\help\basics" +Delete "$INSTDIR\help\Concepts\*" +RMDir "$INSTDIR\help\Concepts" +Delete "$INSTDIR\help\welcome\*" +RMDir "$INSTDIR\help\welcome" +Delete "$INSTDIR\help\*" +RMDir "$INSTDIR\help" + +Delete "$INSTDIR\uninst.exe" +RMDir "$INSTDIR" + +IfFileExists "$INSTDIR" FOLDERFOUND NOFOLDER + +FOLDERFOUND: + MessageBox MB_YESNO "There are still files in your SecondLife program directory.$\n$\nThese are possibly files you created or moved to:$\n$INSTDIR$\n$\nDo you want to remove them?" IDNO NOFOLDER + RMDir /r "$INSTDIR" + +NOFOLDER: + +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Uninstall settings +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +UninstallText "This will uninstall Second Life ${VERSION_LONG} from your system." +ShowUninstDetails show + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +;;; Uninstall section +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +Section Uninstall + +; Start with some default values. +StrCpy $INSTFLAGS "${INSTFLAGS}" +StrCpy $INSTPROG "${INSTNAME}" +StrCpy $INSTEXE "${INSTEXE}" +StrCpy $INSTSHORTCUT "${SHORTCUT}" +Call un.CheckStartupParams ; Figure out where, what and how to uninstall. +Call un.CheckIfAdministrator ; Make sure the user can install/uninstall + +; uninstall for all users (if you change this, change it in the install as well) +SetShellVarContext all + +; Make sure we're not running +Call un.CloseSecondLife + +; Clean up registry keys +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Linden Research, Inc.\$INSTPROG" +DeleteRegKey HKEY_LOCAL_MACHINE "SOFTWARE\Microsoft\Windows\CurrentVersion\Uninstall\$INSTPROG" + +; Clean up shortcuts +Delete "$SMPROGRAMS\$INSTSHORTCUT\*.*" +RMDir "$SMPROGRAMS\$INSTSHORTCUT" + +Delete "$DESKTOP\$INSTSHORTCUT.lnk" +Delete "$INSTDIR\$INSTSHORTCUT.lnk" +Delete "$INSTDIR\Uninstall $INSTSHORTCUT.lnk" + +; Clean up cache and log files. +; Leave them in-place for non AGNI installs. + +!ifdef UNINSTALL_SETTINGS +Call un.DocumentsAndSettingsFolder +!endif + +Call un.ProgramFiles + +SectionEnd ; end of uninstall section + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; (From the NSIS wiki, DK) +; GetParameterValue +; +; Usage: +; !insertmacro GetParameterValue "/L=" "1033" +; pop $R0 +; +; Returns on top of stack +; +; Example command lines: +; foo.exe /S /L=1033 /D=C:\Program Files\Foo +; or: +; foo.exe /S "/L=1033" /D="C:\Program Files\Foo" +; gpv "/L=" "1033" +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + + !macro GetParameterValue SWITCH DEFAULT + Push $0 + Push $1 + Push $2 + Push $3 + Push $4 + + ;$CMDLINE='"My Setup\Setup.exe" /L=1033 /S' + Push "$CMDLINE" + Push '${SWITCH}"' + !insertmacro StrStr + Pop $0 + StrCmp "$0" "" gpv_notquoted + ;$0='/L="1033" /S' + StrLen $2 "$0" + Strlen $1 "${SWITCH}" + IntOp $1 $1 + 1 + StrCpy $0 "$0" $2 $1 + ;$0='1033" /S' + Push "$0" + Push '"' + !insertmacro StrStr + Pop $1 + StrLen $2 "$0" + StrLen $3 "$1" + IntOp $4 $2 - $3 + StrCpy $0 $0 $4 0 + Goto gpv_done + + gpv_notquoted: + Push "$CMDLINE" + Push "${SWITCH}" + !insertmacro StrStr + Pop $0 + StrCmp "$0" "" gpv_done + ;$0='/L="1033" /S' + StrLen $2 "$0" + Strlen $1 "${SWITCH}" + StrCpy $0 "$0" $2 $1 + ;$0=1033 /S' + Push "$0" + Push ' ' + !insertmacro StrStr + Pop $1 + StrLen $2 "$0" + StrLen $3 "$1" + IntOp $4 $2 - $3 + StrCpy $0 $0 $4 0 + Goto gpv_done + + gpv_done: + StrCmp "$0" "" 0 +2 + StrCpy $0 "${DEFAULT}" + + Pop $4 + Pop $3 + Pop $2 + Pop $1 + Exch $0 + !macroend + +; And I had to modify StrStr a tiny bit. +; Possible upgrade switch the goto's to use ${__LINE__} + +!macro STRSTR + Exch $R1 ; st=haystack,old$R1, $R1=needle + Exch ; st=old$R1,haystack + Exch $R2 ; st=old$R1,old$R2, $R2=haystack + Push $R3 + Push $R4 + Push $R5 + StrLen $R3 $R1 + StrCpy $R4 0 + ; $R1=needle + ; $R2=haystack + ; $R3=len(needle) + ; $R4=cnt + ; $R5=tmp + ; loop; + StrCpy $R5 $R2 $R3 $R4 + StrCmp $R5 $R1 +4 + StrCmp $R5 "" +3 + IntOp $R4 $R4 + 1 + Goto -4 + ; done; + StrCpy $R1 $R2 "" $R4 + Pop $R5 + Pop $R4 + Pop $R3 + Pop $R2 + Exch $R1 +!macroend + +Function GetProgramName + !insertmacro GetParameterValue "/P=" "SecondLife" +FunctionEnd + +Function un.GetProgramName + !insertmacro GetParameterValue "/P=" "SecondLife" +FunctionEnd + +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; +; (From the NSIS documentation, JC) +; GetWindowsVersion +; +; Based on Yazno's function, http://yazno.tripod.com/powerpimpit/ +; Updated by Joost Verburg +; +; Returns on top of stack +; +; Windows Version (95, 98, ME, NT x.x, 2000, XP, 2003) +; or +; '' (Unknown Windows Version) +; +; Usage: +; Call GetWindowsVersion +; Pop $R0 +; ; at this point $R0 is "NT 4.0" or whatnot +;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; + +Function GetWindowsVersion + + Push $R0 + Push $R1 + + ReadRegStr $R0 HKLM \ + "SOFTWARE\Microsoft\Windows NT\CurrentVersion" CurrentVersion + + IfErrors 0 lbl_winnt + + ; we are not NT + ReadRegStr $R0 HKLM \ + "SOFTWARE\Microsoft\Windows\CurrentVersion" VersionNumber + + StrCpy $R1 $R0 1 + StrCmp $R1 '4' 0 lbl_error + + StrCpy $R1 $R0 3 + + StrCmp $R1 '4.0' lbl_win32_95 + StrCmp $R1 '4.9' lbl_win32_ME lbl_win32_98 + + lbl_win32_95: + StrCpy $R0 '95' + Goto lbl_done + + lbl_win32_98: + StrCpy $R0 '98' + Goto lbl_done + + lbl_win32_ME: + StrCpy $R0 'ME' + Goto lbl_done + + lbl_winnt: + + StrCpy $R1 $R0 1 + + StrCmp $R1 '3' lbl_winnt_x + StrCmp $R1 '4' lbl_winnt_x + + StrCpy $R1 $R0 3 + + StrCmp $R1 '5.0' lbl_winnt_2000 + StrCmp $R1 '5.1' lbl_winnt_XP + StrCmp $R1 '5.2' lbl_winnt_2003 lbl_error + + lbl_winnt_x: + StrCpy $R0 "NT $R0" 6 + Goto lbl_done + + lbl_winnt_2000: + Strcpy $R0 '2000' + Goto lbl_done + + lbl_winnt_XP: + Strcpy $R0 'XP' + Goto lbl_done + + lbl_winnt_2003: + Strcpy $R0 '2003' + Goto lbl_done + + lbl_error: + Strcpy $R0 '' + lbl_done: + + Pop $R1 + Exch $R0 + +FunctionEnd diff --git a/linden/indra/newview/licenses-linux.txt b/linden/indra/newview/licenses-linux.txt index f7ccf27..20b76c8 100644 --- a/linden/indra/newview/licenses-linux.txt +++ b/linden/indra/newview/licenses-linux.txt @@ -16,6 +16,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +============== +Base32 License +============== + + * Copyright (c) 2006 Christian Biere + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + ========== Cg License ========== @@ -404,6 +436,39 @@ Subject to the following 3 conditions, Epinions, Inc. permits you, free of charg 3) IN NO EVENT SHALL EPINIONS, INC. BE LIABLE FOR ANY DIRECT, INDIRECT, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES OR LOST PROFITS ARISING OUT OF OR IN CONNECTION WITH THE SOFTWARE (HOWEVER ARISING, INCLUDING NEGLIGENCE), EVEN IF EPINIONS, INC. IS AWARE OF THE POSSIBILITY OF SUCH DAMAGES. +=============== +libuuid License +=============== + +Copyright (C) 1999, 2000, 2003, 2004 by Theodore Ts'o + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, and the entire permission notice in its entirety, + including the disclaimer of warranties. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the author may not be used to endorse or promote + products derived from this software without specific prior + written permission. + +THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED +WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE, ALL OF +WHICH ARE HEREBY DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE +LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR +CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT +OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR +BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF +LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE +USE OF THIS SOFTWARE, EVEN IF NOT ADVISED OF THE POSSIBILITY OF SUCH +DAMAGE. + + ============ zlib License ============ diff --git a/linden/indra/newview/licenses-mac.txt b/linden/indra/newview/licenses-mac.txt index f761ed6..77541ba 100644 --- a/linden/indra/newview/licenses-mac.txt +++ b/linden/indra/newview/licenses-mac.txt @@ -16,6 +16,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +============== +Base32 License +============== + + * Copyright (c) 2006 Christian Biere + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + ========== Cg License ========== diff --git a/linden/indra/newview/licenses-win32.txt b/linden/indra/newview/licenses-win32.txt index f761ed6..77541ba 100644 --- a/linden/indra/newview/licenses-win32.txt +++ b/linden/indra/newview/licenses-win32.txt @@ -16,6 +16,38 @@ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. +============== +Base32 License +============== + + * Copyright (c) 2006 Christian Biere + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the authors nor the names of its contributors + * may be used to endorse or promote products derived from this software + * without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHORS AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + ========== Cg License ========== diff --git a/linden/indra/newview/linux_tools/client-manifest-i686 b/linden/indra/newview/linux_tools/client-manifest-i686 deleted file mode 100644 index 04ab1f6..0000000 --- a/linden/indra/newview/linux_tools/client-manifest-i686 +++ /dev/null @@ -1,48 +0,0 @@ -# This file defines which files to include in the linux tarball. -# Each line is a comma-separated definition of source,destination -# pairs. The packaging script will read all source files -# from indra/newview/, and place them in the package -# located at /. -# -# If no comma is used, the destination name is assumed to be -# the same as the source name. -# -# A 'file' ending with a '/' defines an empty directory to create. -# A '*' wildcard in the source will recursively copy everything -# in that directory (except CVS directories) - -featuretable.txt -licenses-linux.txt,licenses.txt -releasenotes.txt -lsl_guide.html -gpu_table.txt -res/ll_icon.ico,secondlife.ico -linux_tools/client-readme.txt,README-linux.txt -linux_tools/wrapper.sh,secondlife -secondlife-i686-bin-stripped,bin/do-not-directly-run-secondlife-bin -#../../libraries/i686-linux/lib_release_client/libllkdu.so,bin/libllkdu.so -#../linux_crash_logger/linux-crash-logger-i686-bin-stripped,linux-crash-logger.bin -linux_tools/unicode.ttf,unicode.ttf -linux_tools/launch_url.sh,launch_url.sh -app_settings/* -character/* -fonts/* -help/* -skins/* -res-sdl/* -../../scripts/messages/message_template.msg,app_settings/message_template.msg -#../../libraries/i686-linux/lib_release_client/libkdu_v42R.so,lib/libkdu_v42R.so -../../libraries/i686-linux/lib_release_client/libfmod-3.75.so,lib/libfmod-3.75.so -../../libraries/i686-linux/lib_release_client/libapr-1.so.0,lib/libapr-1.so.0 -../../libraries/i686-linux/lib_release_client/libaprutil-1.so.0,lib/libaprutil-1.so.0 -../../libraries/i686-linux/lib_release_client/libdb-4.2.so,lib/libdb-4.2.so -../../libraries/i686-linux/lib_release_client/libogg.so.0,lib/libogg.so.0 -../../libraries/i686-linux/lib_release_client/libvorbis.so.0,lib/libvorbis.so.0 -../../libraries/i686-linux/lib_release_client/libvorbisfile.so.0,lib/libvorbisfile.so.0 -../../libraries/i686-linux/lib_release_client/libvorbisenc.so.0,lib/libvorbisenc.so.0 -../../libraries/i686-linux/lib_release_client/libcurl.so.3,lib/libcurl.so.3 -../../libraries/i686-linux/lib_release_client/libcrypto.so.0.9.7,lib/libcrypto.so.0.9.7 -../../libraries/i686-linux/lib_release_client/libssl.so.0.9.7,lib/libssl.so.0.9.7 -../../libraries/i686-linux/lib_release_client/libexpat.so.1,lib/libexpat.so.1 -#../../libraries/i686-linux/lib_release_client/libstdc++.so.6,lib/libstdc++.so.6 -../../libraries/i686-linux/lib_release_client/libelfio.so,lib/libelfio.so diff --git a/linden/indra/newview/linux_tools/client-readme.txt b/linden/indra/newview/linux_tools/client-readme.txt index 4748eaf..7c972bb 100644 --- a/linden/indra/newview/linux_tools/client-readme.txt +++ b/linden/indra/newview/linux_tools/client-readme.txt @@ -71,29 +71,31 @@ you wish. 4. KNOWN ISSUES -=-=-=-=-=-=-=- -The following user-visible features are currently not fully implemented on -the Linux client and are therefore known not to work properly: +These are the most commonly-encountered known issues which are specific to +the Alpha release of the Linux client. + +* VISUAL EFFECTS AND PERFORMANCE - many Linux graphics drivers are not as + robust as their counterparts for other operating systems, so some advanced + Second Life graphical features have been DISABLED by default to aid + stability. See PROBLEM 3 in the TROUBLESHOOTING section if you wish to + turn these on to possibly enhance your experience. + +* MISC - The following user-visible features are not currently fully + implemented on the Linux client and are therefore known not to work properly + at this time: * QuickTime movie playback and movie recording - * F1 Help - * Embedded Web Profiles and HTML Login Screen * Video memory detection * Full Unicode font rendering * Auto-updater +* UPLOAD / SAVE / COLOR-PICKER DIALOGS - These only appear when the client + is in 'windowed' mode, not 'fullscreen' mode. + * UPDATING - when the client detects that a new version of Second Life is available, it will ask you if you wish to download the new version. This option is not implemented; to upgrade, you should manually download a new version from the Second Life web site, . -* UPLOAD / SAVE / COLOR-PICKER DIALOGS - These only function when the client - is in 'windowed' mode, not 'fullscreen' mode. - -* GRAPHICAL SPEED/QUALITY - as many Linux graphics drivers are not as robust - as their counterparts for some other operating systems, advanced Second Life - graphical features have been disabled to aid stability. See PROBLEM 3 in the - TROUBLESHOOTING section if you wish to turn these on to enhance your - experience. - 5. TROUBLESHOOTING -=-=-=-=-=-=-=-=-= @@ -132,8 +134,8 @@ SOLUTION:- As a last resort, you can disable most of Second Life's advanced from the line which reads '#export LL_GL_NOEXT=x' PROBLEM 3:- Performance or graphical quality are not as high as I expect. +PROBLEM:- 'SHINY' doesn't work. PROBLEM:- I can't turn on Anisotropic Filtering, Ripple Water, or AGP. -PROBLEM:- 'Shiny' doesn't work. SOLUTION:- Some graphics performance features in Second Life are disabled by default for the Linux version due to stability issues with some common Linux graphic drivers. You can re-enable these features at the slight diff --git a/linden/indra/newview/linux_tools/package-client.sh b/linden/indra/newview/linux_tools/package-client.sh deleted file mode 100755 index b054386..0000000 --- a/linden/indra/newview/linux_tools/package-client.sh +++ /dev/null @@ -1,133 +0,0 @@ -#!/bin/sh -MANIFEST=$1 -PACKAGE_NAME=$2 -GRID=$3 - -# Check that the entire client manifest is there. -cd newview -echo Checking manifest... - -# Strip out comment lines and empty lines -# Replace anything with a source,dest pairs with just source filename -if ! ls -d `cat "$MANIFEST" | \ - grep -v ^# | grep -v ^$ | \ - sed 's/,.*//'` 1>/dev/null -then - echo Client manifest defined in newview/$MANIFEST is not complete. - exit 1 -fi -echo "Done." - -# See if the package already exists. -BUILD_PACKAGE=YES -if [ -a $PACKAGE_NAME ] -then - echo The directory "newview/$PACKAGE_NAME" already exists. - echo Checking for complete client manifest... - - cd $PACKAGE_NAME - - # Strip out comment lines and empty lines - # Replace source,dest pairs with just dest filename - if ls -d `cat "../$MANIFEST" | \ - grep -v ^# | grep -v ^$ | \ - sed 's/.*,\(.*\)/\1/'` 1>/dev/null - then - echo "Done." - echo Package at "newview/$PACKAGE_NAME" looks complete. - cd .. - BUILD_PACKAGE=NO - else - echo Incomplete package at "newview/$PACKAGE_NAME"! - echo Removing corrupt package... - cd .. - rm -rf $PACKAGE_NAME - echo Done. - fi -fi - -echo Building newview/$PACKAGE_NAME directory... -## First read all directories mentioned in the manifest, and create a package skeleton. - -# Strip out comment lines and empty lines -# Replace source,dest pairs with just dest filename -# Strip out and line that does not include a directory in its path (ie contains a '/') -# Extract everything up to the last '/' and prefix with $PACKAGE_NAME -# Print out just the unique directores, and make them. -mkdir -p `cat $MANIFEST | \ - grep -v ^# | \ - grep -v ^$ | \ - sed 's/.*,\(.*\)/\1/' | \ - grep \/ | \ - sed "s/\(^.*\)\/[^\/]*/$PACKAGE_NAME\/\1/" | \ - sort | uniq` - -## Copy the manifest. - -# Strip out comment lines and empty lines -# Strip out empty directories -# Replace any line without a ',' with 'line,line' -for pair in `cat $MANIFEST | \ - grep -v ^# | \ - grep -v ^$ | \ - grep -v \/$ | \ - sed 's/\(^[^,]*$\)/\1,\1/' ` -do - # $pair is 'source,dest' ... split it up - SOURCE=`echo "$pair" | awk -F, '{ print $1; }'` - DEST=`echo "$pair" | awk -F, '{ print $2; }'` - # If this is a wildcard copy (pair contains a '*'), then remove the wildcard from $DEST - # and make the copy recursive - RECURSE="" - if [ ! x == x`echo "$SOURCE" | grep \*$` ] - then - DEST=`echo "$DEST" | sed 's/\*$//'` - RECURSE="-R" - fi - # The -a makes us copy links as links, plus timestamps etc. - cp -a $RECURSE $SOURCE "$PACKAGE_NAME/$DEST" -done - -echo Done. - -## Clean up any CVS directories that might have been recursively included. -echo Pruning CVS directories from newview/$PACKAGE_NAME directory... -find $PACKAGE_NAME -type d -name CVS -exec rm -rf {} \; 2>/dev/null -echo "Done removing CVS directories." - -## Clean up any SVN directories that might have been recursively included. -echo Pruning .svn directories from newview/$PACKAGE_NAME directory... -find $PACKAGE_NAME -type d -name \.svn -exec rm -rf {} \; 2>/dev/null -echo "Done removing .svn directories." - -# Create an appropriate gridargs.dat for this package, denoting required grid. -if [ X$GRID == X'default' ] -then - echo 'Default grid - creating empty gridargs.dat' - echo " " > $PACKAGE_NAME/gridargs.dat -else - if [ X$GRID == X'firstlook' ] - then - # firstlook is a special case... it's not really a grid. - echo "Creating gridargs.dat for firstlook" - echo "-settings settings_firstlook.xml" > $PACKAGE_NAME/gridargs.dat - else - echo "Creating gridargs.dat for package, grid $GRID" - echo "-settings settings_beta.xml --${GRID} -helperuri http://preview-${GRID}.secondlife.com/helpers/" > $PACKAGE_NAME/gridargs.dat - fi -fi - -TARBALL=$PACKAGE_NAME.tar.bz2 - -# See if the tarball already exists. -if [ -a $TARBALL ] -then - echo Tarball "newview/$TARBALL" already exists. Skipping tarball creation. - exit 0 -fi - -echo Creating tarball "newview/$TARBALL"... -# --numeric-owner hides the username of the builder for security etc. -tar --numeric-owner -cjf $TARBALL $PACKAGE_NAME -echo Done. - diff --git a/linden/indra/newview/linux_tools/wrapper.sh b/linden/indra/newview/linux_tools/wrapper.sh index 222ce98..cdc36a8 100755 --- a/linden/indra/newview/linux_tools/wrapper.sh +++ b/linden/indra/newview/linux_tools/wrapper.sh @@ -13,8 +13,9 @@ #export LL_BAD_ALSA=x ## - Avoids the optional OpenGL extensions which have proven most problematic -## on some hardware. Disabling this option may cause crashes and hangs on -## some unstable combinations of drivers and hardware. +## on some hardware. Disabling this option may cause BETTER PERFORMANCE but +## may also cause CRASHES and hangs on some unstable combinations of drivers +## and hardware. export LL_GL_BASICEXT=x ## - Avoids *all* optional OpenGL extensions. This is the safest and least- @@ -38,7 +39,7 @@ export SDL_VIDEO_X11_DGAMOUSE=0 RUN_PATH=`dirname "$0" || echo .` cd "${RUN_PATH}" -LD_LIBRARY_PATH="`pwd`"/lib:"${LD_LIBRARY_PATH}" bin/do-not-directly-run-secondlife-bin `cat gridargs.dat` $@ | cat +LD_LIBRARY_PATH="`pwd`"/lib:"`pwd`"/app_settings/mozilla-runtime-linux-i686:"${LD_LIBRARY_PATH}" bin/do-not-directly-run-secondlife-bin `cat gridargs.dat` $@ | cat echo echo '*********************************************************' diff --git a/linden/indra/newview/llagent.cpp b/linden/indra/newview/llagent.cpp index 6d9137d..a6ec948 100644 --- a/linden/indra/newview/llagent.cpp +++ b/linden/indra/newview/llagent.cpp @@ -122,7 +122,6 @@ // end Ventrella extern LLMenuBarGL* gMenuBarView; -extern F32 gMinObjectDistance; extern U8 gLastPickAlpha; extern F32 gFrameDTClamped; @@ -481,17 +480,20 @@ void LLAgent::resetView(BOOL reset_camera) if (!gNoRender) { - gSelectMgr->deselectAll(); gSelectMgr->unhighlightAll(); // By popular request, keep land selection while walking around. JC // gParcelMgr->deselectLand(); + // force deselect when walking and attachment is selected + // this is so people don't wig out when their avatar moves without animating + if (gSelectMgr->getSelection()->isAttachment()) + { + gSelectMgr->deselectAll(); + } + // Hide all popup menus - gPieSelf->hide(FALSE); - gPieAvatar->hide(FALSE); - gPieObject->hide(FALSE); - gPieLand->hide(FALSE); + gMenuHolder->hideMenus(); } if (reset_camera && !gSavedSettings.getBOOL("FreezeTime")) @@ -787,7 +789,7 @@ void LLAgent::setRegion(LLViewerRegion *regionp) // char host_name[MAX_STRING]; // regionp->getHost().getHostName(host_name, MAX_STRING); - char ip[MAX_STRING]; + char ip[MAX_STRING]; /*Flawfinder: ignore*/ regionp->getHost().getString(ip, MAX_STRING); llinfos << "Moving agent into region: " << regionp->getName() << " located at " << ip << llendl; @@ -850,6 +852,8 @@ void LLAgent::setRegion(LLViewerRegion *regionp) // we could trake this at the dataserver side, but that's harder U64 handle = regionp->getHandle(); mRegionsVisited.insert(handle); + + gSelectMgr->updateSelectionCenter(); } @@ -1584,7 +1588,8 @@ F32 LLAgent::getCameraZoomFraction() { // 0.f -> camera zoomed all the way out // 1.f -> camera zoomed all the way in - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // already [0,1] return mAvatarObject->mHUDTargetZoom; @@ -1631,7 +1636,9 @@ void LLAgent::setCameraZoomFraction(F32 fraction) { // 0.f -> camera zoomed all the way out // 1.f -> camera zoomed all the way in - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { mAvatarObject->mHUDTargetZoom = fraction; } @@ -1681,7 +1688,8 @@ void LLAgent::setCameraZoomFraction(F32 fraction) //----------------------------------------------------------------------------- void LLAgent::cameraOrbitAround(const F32 radians) { - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // do nothing for hud selection } @@ -1703,7 +1711,8 @@ void LLAgent::cameraOrbitAround(const F32 radians) //----------------------------------------------------------------------------- void LLAgent::cameraOrbitOver(const F32 angle) { - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // do nothing for hud selection } @@ -1737,7 +1746,8 @@ void LLAgent::cameraZoomIn(const F32 fraction) return; } - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { // just update hud zoom level mAvatarObject->mHUDTargetZoom /= fraction; @@ -2256,11 +2266,9 @@ void LLAgent::stopAutoPilot(BOOL user_cancel) resetAxes(mAutoPilotTargetFacing); } //NB: auto pilot can terminate for a reason other than reaching the destination - //TODO: enforce rotation constraint here as well - if (mAutoPilotFinishedCallback && - ((mAutoPilotTargetDist < mAutoPilotStopDistance) || (mAutoPilotNoProgressFrameCount > AUTOPILOT_MAX_TIME_NO_PROGRESS * gFPSClamped))) + if (mAutoPilotFinishedCallback) { - mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotTargetDist, mAutoPilotCallbackData); + mAutoPilotFinishedCallback(!user_cancel && dist_vec(gAgent.getPositionGlobal(), mAutoPilotTargetGlobal) < mAutoPilotStopDistance, mAutoPilotCallbackData); } mLeaderID = LLUUID::null; @@ -2731,8 +2739,8 @@ U8 LLAgent::getRenderState() stopTyping(); } - if ((!gSelectMgr->isEmpty() && gSelectMgr->shouldShowSelection()) - || gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) )->isEditing() ) + if ((!gSelectMgr->getSelection()->isEmpty() && gSelectMgr->shouldShowSelection()) + || gToolMgr->getCurrentTool()->isEditing() ) { setRenderState(AGENT_STATE_EDITING); } @@ -2774,8 +2782,7 @@ void LLAgent::endAnimationUpdateUI() gMenuBarView->setVisible(TRUE); gStatusBar->setVisibleForMouselook(true); - gCurrentToolset = gBasicToolset; - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); // Only pop if we have pushed... if (TRUE == mViewsPushed) @@ -2823,8 +2830,7 @@ void LLAgent::endAnimationUpdateUI() { // make sure we ask to save changes - gCurrentToolset = gBasicToolset; - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); // HACK: If we're quitting, and we were in customize avatar, don't // let the mini-map go visible again. JC @@ -2861,8 +2867,7 @@ void LLAgent::endAnimationUpdateUI() // JC - Added for always chat in third person option gFocusMgr.setKeyboardFocus(NULL, NULL); - gCurrentToolset = gMouselookToolset; - gToolMgr->useSelectedTool( gMouselookToolset ); + gToolMgr->setCurrentToolset(gMouselookToolset); mViewsPushed = TRUE; @@ -2920,8 +2925,7 @@ void LLAgent::endAnimationUpdateUI() } else if (mCameraMode == CAMERA_MODE_CUSTOMIZE_AVATAR) { - gCurrentToolset = gFaceEditToolset; - gToolMgr->useSelectedTool( gFaceEditToolset ); + gToolMgr->setCurrentToolset(gFaceEditToolset); gFloaterMap->pushVisible(FALSE); /* @@ -3336,7 +3340,7 @@ void LLAgent::updateCamera() attachment; attachment = mAvatarObject->mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); + LLViewerObject *attached_object = attachment->getObject(); if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull()) { // clear any existing "early" movements of attachment @@ -3446,21 +3450,26 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal() { LLDrawable* drawablep = mFocusObject->mDrawable; - if (mTrackFocusObject && drawablep && drawablep->isActive()) + if (mTrackFocusObject && + drawablep && + drawablep->isActive()) { - if (mFocusObject->isSelected()) + if (!mFocusObject->isAvatar()) { - gPipeline.updateMoveNormalAsync(drawablep); - } - else - { - if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + if (mFocusObject->isSelected()) { gPipeline.updateMoveNormalAsync(drawablep); } else { - gPipeline.updateMoveDampedAsync(drawablep); + if (drawablep->isState(LLDrawable::MOVE_UNDAMPED)) + { + gPipeline.updateMoveNormalAsync(drawablep); + } + else + { + gPipeline.updateMoveDampedAsync(drawablep); + } } } } @@ -3471,11 +3480,6 @@ LLVector3d LLAgent::calcFocusPositionTargetGlobal() } LLVector3 focus_agent = mFocusObject->getRenderPosition() + mFocusObjectOffset; mFocusTargetGlobal.setVec(getPosGlobalFromAgent(focus_agent)); - // *FIX: get camera pointat behavior working - //if (mTrackFocusObject) - //{ - // mCameraFocusOffset = gAgent.getPosGlobalFromAgent(gCamera->getOrigin()) - mFocusTargetGlobal; - //} } return mFocusTargetGlobal; } @@ -3840,8 +3844,6 @@ LLVector3d LLAgent::calcCameraPositionTargetGlobal(BOOL *hit_limit) if (camera_position_global.mdV[VZ] < camera_land_height + camera_min_off_ground) { camera_position_global.mdV[VZ] = camera_land_height + camera_min_off_ground; - - gMinObjectDistance = MIN_NEAR_PLANE; isConstrained = TRUE; } @@ -3873,6 +3875,7 @@ void LLAgent::handleScrollWheel(S32 clicks) } else { + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); const F32 ROOT_ROOT_TWO = sqrt(F_SQRT2); // Block if camera is animating @@ -3881,7 +3884,7 @@ void LLAgent::handleScrollWheel(S32 clicks) return; } - if (gSelectMgr->getObjectCount() && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (selection->getObjectCount() && selection->getSelectType() == SELECT_TYPE_HUD) { F32 zoom_factor = (F32)pow(0.8, -clicks); cameraZoomIn(zoom_factor); @@ -3952,9 +3955,7 @@ void LLAgent::changeCameraToMouselook(BOOL animate) // unpause avatar animation mPauseRequest = NULL; - gCurrentToolset = gMouselookToolset; - gCurrentToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gMouselookToolset); gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); gSavedSettings.setBOOL("MouselookBtnState", TRUE); @@ -4036,9 +4037,7 @@ void LLAgent::changeCameraToFollow(BOOL animate) if (gBasicToolset) { - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); } if (mAvatarObject) @@ -4111,9 +4110,7 @@ void LLAgent::changeCameraToThirdPerson(BOOL animate) { if (gBasicToolset) { - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); } mCameraLag.clearVec(); @@ -4176,9 +4173,7 @@ void LLAgent::changeCameraToCustomizeAvatar(BOOL animate) if (gFaceEditToolset) { - gCurrentToolset = gFaceEditToolset; - gCurrentToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gFaceEditToolset); } gSavedSettings.setBOOL("FirstPersonBtnState", FALSE); @@ -4673,14 +4668,26 @@ void LLAgent::requestStopMotion( LLMotion* motion ) // Notify all avatars that a motion has stopped. // This is needed to clear the animation state bits LLUUID anim_state = motion->getID(); + onAnimStop(motion->getID()); // if motion is not looping, it could have stopped by running out of time // so we need to tell the server this // llinfos << "Sending stop for motion " << motion->getName() << llendl; sendAnimationRequest( anim_state, ANIM_REQUEST_STOP ); +} +void LLAgent::onAnimStop(const LLUUID& id) +{ // handle automatic state transitions (based on completion of animation playback) - if (anim_state == ANIM_AGENT_STANDUP) + if (id == ANIM_AGENT_STAND) + { + stopFidget(); + } + else if (id == ANIM_AGENT_AWAY) + { + clearAFK(); + } + else if (id == ANIM_AGENT_STANDUP) { // send stand up command setControlFlags(AGENT_CONTROL_FINISH_ANIM); @@ -4689,7 +4696,7 @@ void LLAgent::requestStopMotion( LLMotion* motion ) if (mAvatarObject.notNull() && !mAvatarObject->mBelowWater && rand() % 3 == 0) sendAnimationRequest( ANIM_AGENT_BRUSH, ANIM_REQUEST_START ); } - else if (anim_state == ANIM_AGENT_PRE_JUMP || anim_state == ANIM_AGENT_LAND || anim_state == ANIM_AGENT_MEDIUM_LAND) + else if (id == ANIM_AGENT_PRE_JUMP || id == ANIM_AGENT_LAND || id == ANIM_AGENT_MEDIUM_LAND) { setControlFlags(AGENT_CONTROL_FINISH_ANIM); } @@ -5184,7 +5191,7 @@ void LLAgent::processAgentGroupDataUpdate(LLMessageSystem *msg, void **) LLGroupData group; S32 index = -1; bool need_floater_update = false; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ for(S32 i = 0; i < count; ++i) { msg->getUUIDFast(_PREHASH_GroupData, _PREHASH_GroupID, group.mID, i); @@ -6593,7 +6600,7 @@ void LLAgent::makeNewOutfit( S32 attachment_pt = attachments_to_include[i]; LLViewerJointAttachment* attachment = mAvatarObject->mAttachmentPoints.getIfThere( attachment_pt ); if(!attachment) continue; - LLViewerObject* attached_object = attachment->getObject(0); + LLViewerObject* attached_object = attachment->getObject(); if(!attached_object) continue; const LLUUID& item_id = attachment->getItemID(); if(item_id.isNull()) continue; @@ -7216,7 +7223,7 @@ void LLAgent::userRemoveAllAttachments( void* userdata ) attachment; attachment = avatarp->mAttachmentPoints.getNextData()) { - LLViewerObject* objectp = attachment->getObject(0); + LLViewerObject* objectp = attachment->getObject(); if (objectp) { gMessageSystem->nextBlockFast(_PREHASH_ObjectData); diff --git a/linden/indra/newview/llagent.h b/linden/indra/newview/llagent.h index b86ab69..faf94ab 100644 --- a/linden/indra/newview/llagent.h +++ b/linden/indra/newview/llagent.h @@ -350,6 +350,7 @@ public: // Animation functions void requestStopMotion( LLMotion* motion ); + void onAnimStop(const LLUUID& id); void sendAnimationRequests(LLDynamicArray &anim_ids, EAnimRequest request); void sendAnimationRequest(const LLUUID &anim_id, EAnimRequest request); @@ -667,8 +668,8 @@ public: U8 mAccess; // SIM_ACCESS_MATURE or SIM_ACCESS_PG U64 mGroupPowers; BOOL mHideGroupTitle; - char mGroupTitle[DB_GROUP_TITLE_BUF_SIZE]; // honorific, like "Sir" - char mGroupName[DB_GROUP_NAME_BUF_SIZE]; + char mGroupTitle[DB_GROUP_TITLE_BUF_SIZE]; /*Flawfinder: ignore*/ // honorific, like "Sir" + char mGroupName[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLUUID mGroupID; //LLUUID mGroupInsigniaID; LLUUID mInventoryRootID; diff --git a/linden/indra/newview/llagentpilot.cpp b/linden/indra/newview/llagentpilot.cpp index 45c1770..45d29cc 100644 --- a/linden/indra/newview/llagentpilot.cpp +++ b/linden/indra/newview/llagentpilot.cpp @@ -55,13 +55,14 @@ LLAgentPilot::~LLAgentPilot() void LLAgentPilot::load(const char *filename) { - llifstream file; + if(!filename) return; - file.open(filename); + llifstream file(filename); if (!file) { - llinfos << "Couldn't open " << filename << ", aborting agentpilot load!" << llendl; + lldebugs << "Couldn't open " << filename + << ", aborting agentpilot load!" << llendl; return; } else @@ -90,7 +91,7 @@ void LLAgentPilot::load(const char *filename) void LLAgentPilot::save(const char *filename) { llofstream file; - file.open(filename); + file.open(filename); /*Flawfinder: ignore*/ if (!file) { diff --git a/linden/indra/newview/llagparray.h b/linden/indra/newview/llagparray.h deleted file mode 100644 index 2569d95..0000000 --- a/linden/indra/newview/llagparray.h +++ /dev/null @@ -1,215 +0,0 @@ -/** - * @file llagparray.h - * @brief LLAGPArray - arrays used for rendering w/ AGP memory (if on) - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLAGPARRAY_H -#define LL_LLAGPARRAY_H - -#include -#include "llagpmempool.h" - -class LLAGPMemBlock; - -template class LLAGPArray -{ -public: - enum - { - OKAY = 0, - FAIL = -1 - }; - - inline LLAGPArray(const S32 size=0, const U32 target=0); - inline ~LLAGPArray(); - - inline void init(); - inline void destroy(); - - inline void flushAGP(); - inline void setDirty() { mDirty = TRUE; } - inline BOOL isDirty() const { return mDirty; } - - inline BOOL setUseAGP(const BOOL on = TRUE); // Returns false if AGP memory is not available - inline BOOL isAGP() const { return mAGPp ? TRUE : FALSE; } - LLAGPMemBlock *getAGPMemBlock() const { return mAGPp; } - - inline BOOL realloc(U32 newsize); - inline S32 getMax() const { return mMaxObj; } - inline S32 count() const; - inline S32 shrinkTo(S32 newcount); - inline void reset(S32 reserve_count); - - inline S32 find (const Type &obj) const; - inline S32 fastRemove(const S32 i); - inline S32 safeRemove(const S32 r); - inline S32 remove (const S32 i); - inline S32 removeObj (const Type &obj); - inline S32 removeLast() { return (mNumObj > 0 ? mNumObj-- : 0); } - - inline Type* reserve_block(const U32 num); - - inline S32 put(const Type &obj); - inline const Type& get(const S32 i) const; - inline Type& get(const S32 i); - - inline BOOL sync (); - inline BOOL syncColor(); - - inline const Type* getMem () const; - inline const S32 getIndex(const Type *objp) const { return objp - mMemp; } - inline const Type& operator[](const S32 i) const; - inline Type& operator[](const S32 i); - - void bindGLVertexPointer(const U32 stride, const U32 offset); - void bindGLTexCoordPointer(const U32 stride, const U32 offset); - void bindGLNormalPointer(const U32 stride, const U32 offset); - void bindGLBinormalPointer(const S32 index, const U32 stride, const U32 offset); - void bindGLColorPointer(const U32 stride, const U32 offset); - void bindGLVertexWeightPointer(const S32 index, const U32 stride, const U32 offset); - void bindGLVertexClothingWeightPointer(const S32 index, const U32 stride, const U32 offset); - - void copyToMem(const S32 offset, const U8 *source, const S32 size); - - U8* getScratchMemory(); - - U32 createFence() { return (mAGPp ? mAGPp->createFence() : 0); } - void deleteFence(const U32 fence) { if (mAGPp) { mAGPp->deleteFence(fence); } } - void sendFence(U32 fence) { if (mAGPp) mAGPp->sendFence(fence); } - void waitFence(U32 fence) { if (mAGPp) mAGPp->waitFence(fence); } - - S32 getSysMemUsage() { return sizeof(Type)*mMaxObj; } - -protected: - BOOL mDirty; - BOOL mUseAGP; - U32 mNumObj; - U32 mMaxObj; - U8 *mUnalignedMemp; - Type *mMemp; - U32 mTarget; //for VBO implementations of this class, store the type of buffer this is - - LLAGPMemBlock *mAGPp; - -public: - BOOL mSynced; // for graph only -- not critical - -public: - static S32 sNumRealloced; - static S32 sBytesRealloced; - static char* sTypeName; -}; - -template S32 LLAGPArray::sNumRealloced = 0; -template S32 LLAGPArray::sBytesRealloced = 0; - -// constructor is in .inl file because it calls realloc() -// which access gPipeline (yuck!) - -template -LLAGPArray::~LLAGPArray() -{ - destroy(); -} - -template void -LLAGPArray::destroy() -{ - realloc(0); - delete mAGPp; - mAGPp = NULL; -} - -template -const Type *LLAGPArray::getMem() const -{ - return mMemp; -} - -template -const Type& LLAGPArray::get(const S32 i) const -{ - llassert(i < (S32)mNumObj); - return mMemp[i]; -} - -template -Type& LLAGPArray::get(const S32 i) -{ - setDirty(); - llassert(i < (S32)mNumObj); - return mMemp[i]; -} - -template -const Type& LLAGPArray::operator[](const S32 i) const -{ - return get(i); -} - -template -Type& LLAGPArray::operator[](const S32 i) -{ - return get(i); -} - -template -S32 LLAGPArray::fastRemove(const S32 i) -{ - if (i < 0 || mNumObj <= 0) return FAIL; - setDirty(); - mMemp[i] = mMemp[--mNumObj]; - - return OKAY; -} - -template -S32 LLAGPArray::remove(const S32 i) -{ - setDirty(); - return fastRemove(i); -} - -template -S32 LLAGPArray::removeObj(const Type& obj) -{ - setDirty(); - - S32 ind = find(obj); - if (ind >= 0) - { - return fastRemove(ind); - } - return FAIL; -} - -template -S32 LLAGPArray::count() const -{ - return mNumObj; -} - - -#endif // LL_LLAGPARRAY_H diff --git a/linden/indra/newview/llagparray.inl b/linden/indra/newview/llagparray.inl deleted file mode 100644 index 418f7d9..0000000 --- a/linden/indra/newview/llagparray.inl +++ /dev/null @@ -1,519 +0,0 @@ -/** - * @file llagparray.inl - * @brief LLAGPArray - arrays used for rendering w/ AGP memory (if on) - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llagpmempool.h" -#include "llglheaders.h" -#include "pipeline.h" // for gPipeline -#include "v4math.h" - -template -void LLAGPArray::flushAGP() -{ - delete mAGPp; - mAGPp = NULL; - - setDirty(); -} - -template -void LLAGPArray::reset(S32 reserve_count) -{ - mNumObj = 0; - realloc(reserve_count); - setDirty(); -} - -template -S32 LLAGPArray::find(const Type &obj) const -{ - for ( S32 i = 0; i < (S32)mNumObj; i++ ) - { - if (mMemp[i] == obj) - { - return i; - } - } - return FAIL; -} - -template -Type* LLAGPArray::reserve_block(const U32 num) -{ - if (!num) - { - return NULL; - } - - setDirty(); - - U32 new_count = mNumObj + num; - if (new_count >= mMaxObj) - { - if (!realloc(new_count)) - { - llwarns << "Unable to realloc " << num << " objects in LLAGPArray!" << llendl; - return NULL; - } - } - - if (mMemp) - { - Type *ret = &mMemp[mNumObj]; - mNumObj += num; - return ret; - } - - return NULL; -} - -template -S32 LLAGPArray::put(const Type &obj) -{ - if (mNumObj >= mMaxObj) - { - if (!mMaxObj) - { - mMaxObj = 1; - } - if (!realloc(mMaxObj*2)) - { - llwarns << "Unable to put in AGPArray due to realloc!" << llendl; - return FAIL; - } - } - - mMemp[mNumObj] = obj; - mNumObj++; - setDirty(); - return OKAY; -} - -template -S32 LLAGPArray::shrinkTo(S32 newcount) -{ - mNumObj = newcount; - return mNumObj; -} - -template -LLAGPArray::LLAGPArray(const S32 size, const U32 target) -{ - if (!target) - { - mTarget = GL_ARRAY_BUFFER_ARB; - } - else - { - mTarget = target; - } - - mSynced = FALSE; - mMaxObj = 0; - mNumObj = 0; - mMemp = NULL; - mUnalignedMemp = NULL; - mUseAGP = FALSE; - mAGPp = NULL; - mDirty = TRUE; - - if (size) - { - if (!realloc(size)) - { - llerrs << "Unable to allocate AGP array of size: " << size << llendl; - } - } -} - -template -BOOL LLAGPArray::realloc(U32 new_count) -{ - const U32 min_count = 1024; - U32 max_count = llmax(min_count, mMaxObj); - if (new_count == 0) - { - delete[] mUnalignedMemp; - mUnalignedMemp = NULL; - mMemp = NULL; - - delete mAGPp; - mAGPp = NULL; - - mNumObj = 0; - mMaxObj = 0; - - return TRUE; - } - if (new_count < min_count) - { - new_count = min_count; - } - else if (new_count < max_count>>1) - { - new_count = new_count + (new_count>>1); - } - else - { - while (max_count < new_count) - { - max_count += max_count>>1; - } - new_count = max_count; - } - if (new_count != mMaxObj) - { - //Type *new_obj_array = new Type[new_count]; - const size_t ALIGN_BYTES = 64; - U8* new_unaligned_obj_array = new U8[ sizeof(Type) * new_count + ALIGN_BYTES - 1]; - if (!new_unaligned_obj_array) - { - llerrs << "Out of system memory in LLAGPArray::realloc - tried to alloc " << new_count << llendl; - return FALSE; - } - - Type* new_obj_array; - // Use size_t to avoid warning -- size_t should be the same size as a pointer - // for 32 and 64 bit architectures. JC - size_t offset = (size_t)new_unaligned_obj_array; - S32 skip_bytes = (S32)(offset % ALIGN_BYTES); - if( skip_bytes ) - { - new_obj_array = (Type*) (new_unaligned_obj_array + ALIGN_BYTES - skip_bytes); - } - else - { - new_obj_array = (Type*) new_unaligned_obj_array; - } - - delete mAGPp; - mAGPp = NULL; - - if (mUseAGP) - { - mAGPp = gPipeline.allocAGPFromPool(new_count * sizeof(Type), mTarget); - setDirty(); - } - - if (!mAGPp && mUseAGP) - { -#ifdef DEBUG_AGP - llwarns << "Failed AGP allocation in realloc!" << llendl; -#endif - } - - // Copying data from previous array to new array. - if (new_count < mNumObj) - { - mNumObj = new_count; - } - - if (mNumObj > 0 && mMemp) - { - memcpy(new_obj_array, mMemp, mNumObj*sizeof(Type)); - } - - delete[] mUnalignedMemp; - mUnalignedMemp = new_unaligned_obj_array; - mMemp = new_obj_array; - - mMaxObj = new_count; - } - - return TRUE; -} - -template -void LLAGPArray::copyToMem(const S32 offset, const U8 *source, const S32 size) -{ - llassert(mMemp); - memcpy((mMemp + offset), source, size*sizeof(Type)); -} - -template -BOOL LLAGPArray::sync() -{ - if (mUseAGP && !mAGPp && !mDirty) - { - llwarns << "No AGP, yet not dirty!" << llendl; - } - - if (mUseAGP && mDirty && mNumObj) - { - if (!mAGPp) - { - mAGPp = gPipeline.allocAGPFromPool(mMaxObj * sizeof(Type), mTarget); - if (!mAGPp) - { -#ifdef DEBUG_AGP - llwarns << "Failure to allocate AGP in sync!" << llendl; -#endif - mUseAGP = FALSE; - } - else - { - mAGPp->copy(mMemp, mNumObj * sizeof(Type)); - } - } - else - { - mAGPp->copy(mMemp, mNumObj * sizeof(Type)); - } - mSynced = TRUE; - } - mDirty = FALSE; - return mSynced; -} - -template -BOOL LLAGPArray::syncColor() -{ - if (mUseAGP && mDirty && mNumObj) - { - if (!mAGPp) - { - mAGPp = gPipeline.allocAGPFromPool(mMaxObj * sizeof(Type), mTarget); - if (!mAGPp) - { -#ifdef DEBUG_AGP - llwarns << "Failure to allocate AGP in synccolor!" << llendl; -#endif - mUseAGP = FALSE; - } - else - { - mAGPp->copyColor(mMemp, mNumObj * sizeof(Type)); - } - } - else - { - mAGPp->copyColor(mMemp, mNumObj * sizeof(Type)); - } - mSynced = TRUE; - } - mDirty = FALSE; - return mSynced; -} - -template -BOOL LLAGPArray::setUseAGP(const BOOL on) -{ - if (on == mUseAGP) - { - return TRUE; - } - - mUseAGP = on; - if (!on) - { - delete mAGPp; - mAGPp = NULL; - } - else if (on) - { - mAGPp = gPipeline.allocAGPFromPool(mMaxObj * sizeof(Type), mTarget); - setDirty(); - if (!mAGPp) - { -#ifdef DEBUG_AGP - llwarns << "Failure to allocate AGP in setUseAGP! Block size = " << (mMaxObj * sizeof(Type)) << llendl; -#endif - mUseAGP = FALSE; - return FALSE; - } - } - return TRUE; -} - -extern U8* gAGPVertices; -extern U8* gAGPNormals; - -template -U8* LLAGPArray::getScratchMemory() -{ - U8* memp = NULL; - - if (mAGPp && gPipeline.isAGPBound()) - { - memp = mAGPp->getMappedMem(); - } - if (!memp) - { - memp = ((U8*)mMemp); - } - - return memp; -} - -template -void LLAGPArray::bindGLVertexPointer(const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLVertexPointer(stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llerrs << "Binding non-AGP vertex pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty vertex array" << llendl; - } - llassert(mMemp); - glVertexPointer(3, GL_FLOAT, stride, ((U8 *)mMemp) + offset); - } -} - -template -void LLAGPArray::bindGLTexCoordPointer(const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLTexCoordPointer(stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP texture coords pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty tex coord array" << llendl; - } - glTexCoordPointer(2, GL_FLOAT, stride, ((U8 *)mMemp) + offset); - } -} - -template -void LLAGPArray::bindGLNormalPointer(const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLNormalPointer(stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP normals pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty normal array" << llendl; - } - glNormalPointer(GL_FLOAT, stride, ((U8 *)mMemp) + offset); - } -} - -template -void LLAGPArray::bindGLBinormalPointer(const S32 index, const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLBinormalPointer(index, stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP binormal pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty binormal array" << llendl; - } - set_binormals(index, stride, (LLVector3 *)(((U8 *)mMemp) + offset)); - } -} - - -template -void LLAGPArray::bindGLColorPointer(const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLColorPointer(stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP color pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty color array" << llendl; - } - glColorPointer(4, GL_UNSIGNED_BYTE, stride, ((U8 *)mMemp) + offset); - } -} - -template -void LLAGPArray::bindGLVertexWeightPointer(const S32 index, const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLVertexWeightPointer(index, stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP vertex weight pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty vertex weight array" << llendl; - } - set_vertex_weights(index, (F32 *)(((U8 *)mMemp) + offset)); - } -} - -template -void LLAGPArray::bindGLVertexClothingWeightPointer(const S32 index, const U32 stride, const U32 offset) -{ - if (mAGPp && gPipeline.isAGPBound()) - { - mAGPp->bindGLVertexClothingWeightPointer(index, stride, offset); - } - else - { - if (gPipeline.isAGPBound()) - { - llwarns << "Binding non-AGP vertex weight pointer when AGP enabled" << llendl; - } - if (!mMemp) - { - llerrs << "Binding empty vertex weight array" << llendl; - } - set_vertex_clothing_weights(index, stride, (LLVector4 *)(((U8 *)mMemp) + offset)); - } -} - diff --git a/linden/indra/newview/llassetuploadresponders.cpp b/linden/indra/newview/llassetuploadresponders.cpp index 1c094bb..7c615dd 100644 --- a/linden/indra/newview/llassetuploadresponders.cpp +++ b/linden/indra/newview/llassetuploadresponders.cpp @@ -1,29 +1,6 @@ -/** - * @file llmapresponders.h - * @brief Processes responses received for asset upload requests. - * - * Copyright (c) 2006-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ +// llassetuploadresponders.cpp +// Copyright 2006, Linden Research, Inc. +// Processes responses received for asset upload requests. #include "llviewerprecompiledheaders.h" @@ -38,39 +15,71 @@ #include "llinventorymodel.h" #include "llinventoryview.h" #include "llpermissionsflags.h" +#include "llpreviewnotecard.h" +#include "llpreviewscript.h" +#include "llscrolllistctrl.h" #include "lluploaddialog.h" -#include "llviewermenu.h" // for upload_new_resource() +#include "llviewerobject.h" +#include "llviewerobjectlist.h" +#include "llviewermenu.h" #include "llviewerwindow.h" #include "viewer.h" -LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLUUID& uuid, - const LLSD &post_data) - : LLHTTPClient::Responder() +void dialog_refresh_all(); + +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) + : LLHTTPClient::Responder(), + mPostData(post_data), + mVFileID(vfile_id), + mAssetType(asset_type) +{ + if (!gVFS->getExists(vfile_id, asset_type)) + { + llwarns << "LLAssetUploadResponder called with nonexistant vfile_id" << llendl; + mVFileID.setNull(); + mAssetType = LLAssetType::AT_NONE; + return; + } +} + +LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data, + const std::string& file_name) + : LLHTTPClient::Responder(), + mPostData(post_data), + mFileName(file_name) +{ +} + +LLAssetUploadResponder::~LLAssetUploadResponder() { - mUUID = uuid; - mPostData = post_data; + if (!mFileName.empty()) + { + // Delete temp file + LLFile::remove(mFileName.c_str()); + } } // virtual -void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reason) +void LLAssetUploadResponder::error(U32 statusNum, const std::string& reason) { - llinfos << "LLNewAgentInventoryResponder::error " << statusNum << llendl; + llinfos << "LLAssetUploadResponder::error " << statusNum + << " reason: " << reason << llendl; LLStringBase::format_map_t args; switch(statusNum) { case 400: - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "invalid parameters in upload request"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = "Error in upload request. Please contact " + "support@lindenlab.com for help fixing this problem."; gViewerWindow->alertXml("CannotUploadReason", args); break; - case 402: - //(result["message"].asString() == "insufficient funds") - LLFloaterBuyCurrency::buyCurrency("Uploading costs", gGlobalEconomy->getPriceUpload()); - break; case 500: default: - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "the server is experiencing unexpected difficulties"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = "The server is experiencing unexpected " + "difficulties. Please try again later."; gViewerWindow->alertXml("CannotUploadReason", args); break; } @@ -78,139 +87,373 @@ void LLNewAgentInventoryResponder::error(U32 statusNum, const std::string& reaso } //virtual -void LLNewAgentInventoryResponder::result(const LLSD& result) +void LLAssetUploadResponder::result(const LLSD& content) { - lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; + lldebugs << "LLAssetUploadResponder::result from capabilities" << llendl; - if (!result["success"]) + std::string state = content["state"]; + if (state == "upload") + { + uploadUpload(content); + } + else if (state == "complete") + { + // rename file in VFS with new asset id + if (mFileName.empty()) + { + // rename the file in the VFS to the actual asset id + gVFS->renameFile(mVFileID, mAssetType, content["new_asset"].asUUID(), mAssetType); + } + uploadComplete(content); + } + else + { + uploadFailure(content); + } +} + +void LLAssetUploadResponder::uploadUpload(const LLSD& content) +{ + std::string uploader = content["uploader"]; + if (mFileName.empty()) + { + LLHTTPClient::postFile(uploader, mVFileID, mAssetType, this); + } + else + { + LLHTTPClient::postFile(uploader, mFileName, this); + } +} + +void LLAssetUploadResponder::uploadFailure(const LLSD& content) +{ + std::string reason = content["state"]; + // deal with money errors + if (reason == "insufficient funds") + { + LLFloaterBuyCurrency::buyCurrency("Uploading costs", gGlobalEconomy->getPriceUpload()); + } + else { LLStringBase::format_map_t args; - args["[FILE]"] = mPostData["inventory_type"].asString(); - args["[REASON]"] = "the server is experiencing unexpected difficulties"; + args["[FILE]"] = (mFileName.empty() ? mVFileID.asString() : mFileName); + args["[REASON]"] = content["message"].asString(); gViewerWindow->alertXml("CannotUploadReason", args); - return; } +} + +void LLAssetUploadResponder::uploadComplete(const LLSD& content) +{ +} + +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} + +LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content) +{ + lldebugs << "LLNewAgentInventoryResponder::result from capabilities" << llendl; - std::string uploader = result["uploader"]; LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString().c_str()); LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString().c_str()); - // request succeeded - if (!uploader.empty()) + + // Update money and ownership credit information + // since it probably changed on the server + if (asset_type == LLAssetType::AT_TEXTURE || + asset_type == LLAssetType::AT_SOUND || + asset_type == LLAssetType::AT_ANIMATION) { - LLHTTPClient::postFile(uploader, mUUID, asset_type, this); + gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gMessageSystem->nextBlockFast(_PREHASH_MoneyData); + gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); + gAgent.sendReliableMessage(); + + LLString::format_map_t args; + args["[AMOUNT]"] = llformat("%d",gGlobalEconomy->getPriceUpload()); + LLNotifyBox::showXml("UploadPayment", args); } - // upload succeeded - else - { - // rename the file in the VFS to the actual asset id - gVFS->renameFile(mUUID, asset_type, result["new_asset"].asUUID(), asset_type); - // TODO: only request for textures, sound, and animation uploads - // Update money and ownership credit information - // since it probably changed on the server - if (mPostData["asset_type"].asString() == "texture" || - mPostData["asset_type"].asString() == "sound" || - mPostData["asset_type"].asString() == "animatn") + // Actually add the upload to viewer inventory + llinfos << "Adding " << content["new_inventory_item"].asUUID() << " " + << content["new_asset"].asUUID() << " to inventory." << llendl; + if(mPostData["folder_id"].asUUID().notNull()) + { + LLPermissions perm; + U32 next_owner_perm; + perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); + if (mPostData["inventory_type"].asString() == "snapshot") { - gMessageSystem->newMessageFast(_PREHASH_MoneyBalanceRequest); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_MoneyData); - gMessageSystem->addUUIDFast(_PREHASH_TransactionID, LLUUID::null ); - gAgent.sendReliableMessage(); - - LLString::format_map_t args; - args["[AMOUNT]"] = llformat("%d",gGlobalEconomy->getPriceUpload()); - LLNotifyBox::showXml("UploadPayment", args); + next_owner_perm = PERM_ALL; } - // Actually add the upload to viewer inventory - llinfos << "Adding " << result["new_inventory_item"].asUUID() << " " - << result["new_asset"].asUUID() << " to inventory." << llendl; - if(mPostData["folder_id"].asUUID().notNull()) + else { - LLPermissions perm; - U32 next_owner_perm; - perm.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null); - if (mPostData["inventory_type"].asString() == "snapshot") + next_owner_perm = PERM_MOVE | PERM_TRANSFER; + } + perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); + S32 creation_date_now = time_corrected(); + LLPointer item + = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(), + mPostData["folder_id"].asUUID(), + perm, + content["new_asset"].asUUID(), + asset_type, + inventory_type, + mPostData["name"].asString(), + mPostData["description"].asString(), + LLSaleInfo::DEFAULT, + LLInventoryItem::II_FLAGS_NONE, + creation_date_now); + gInventory.updateItem(item); + gInventory.notifyObservers(); + + // Show the preview panel for textures and sounds to let + // user know that the image (or snapshot) arrived intact. + LLInventoryView* view = LLInventoryView::getActiveInventory(); + if(view) + { + LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); + LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); + + view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); + if((LLAssetType::AT_TEXTURE == asset_type) + || (LLAssetType::AT_SOUND == asset_type)) { - next_owner_perm = PERM_ALL; + view->getPanel()->openSelected(); } - else + //LLInventoryView::dumpSelectionInformation((void*)view); + // restore keyboard focus + gFocusMgr.setKeyboardFocus(focus_ctrl, callback); + } + } + else + { + llwarns << "Can't find a folder to put it in" << llendl; + } + + // remove the "Uploading..." message + LLUploadDialog::modalUploadFinished(); + + // *FIX: This is a pretty big hack. What this does is check the + // file picker if there are any more pending uploads. If so, + // upload that file. + const char* next_file = LLFilePicker::instance().getNextFile(); + if(next_file) + { + const char* name = LLFilePicker::instance().getDirname(); + + LLString asset_name = name; + LLString::replaceNonstandardASCII( asset_name, '?' ); + LLString::replaceChar(asset_name, '|', '?'); + LLString::stripNonprintable(asset_name); + LLString::trim(asset_name); + + char* asset_name_str = (char*)asset_name.c_str(); + char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists + if( !end_p ) + { + end_p = asset_name_str + strlen( asset_name_str ); /*Flawfinder: ignore*/ + } + + S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); + + asset_name = asset_name.substr( 0, len ); + + upload_new_resource(next_file, asset_name, asset_name, + 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); + } +} + + +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} + +LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(const LLSD& post_data, + const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLUpdateAgentInventoryResponder::uploadComplete(const LLSD& content) +{ + llinfos << "LLUpdateAgentInventoryResponder::result from capabilities" << llendl; + LLUUID item_id = mPostData["item_id"]; + + LLViewerInventoryItem* item = (LLViewerInventoryItem*)gInventory.getItem(item_id); + if(!item) + { + llwarns << "Inventory item for " << mVFileID + << " is no longer in agent inventory." << llendl; + return; + } + + // Update viewer inventory item + LLPointer new_item = new LLViewerInventoryItem(item); + new_item->setAssetUUID(content["new_asset"].asUUID()); + gInventory.updateItem(new_item); + gInventory.notifyObservers(); + + llinfos << "Inventory item " << item->getName() << " saved into " + << content["new_asset"].asString() << llendl; + + LLInventoryType::EType inventory_type = new_item->getInventoryType(); + switch(inventory_type) + { + case LLInventoryType::IT_NOTECARD: { - next_owner_perm = PERM_MOVE | PERM_TRANSFER; + + // Update the UI with the new asset. + LLPreviewNotecard* nc; + nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID()); + if(nc) + { + // *HACK: we have to delete the asset in the VFS so + // that the viewer will redownload it. This is only + // really necessary if the asset had to be modified by + // the uploader, so this can be optimized away in some + // cases. A better design is to have a new uuid if the + // script actually changed the asset. + if(nc->hasEmbeddedInventory()) + { + gVFS->removeFile( + content["new_asset"].asUUID(), + LLAssetType::AT_NOTECARD); + } + nc->refreshFromInventory(); + } } - perm.initMasks(PERM_ALL, PERM_ALL, PERM_NONE, PERM_NONE, next_owner_perm); - S32 creation_date_now = time_corrected(); - LLPointer item - = new LLViewerInventoryItem(result["new_inventory_item"].asUUID(), - mPostData["folder_id"].asUUID(), - perm, - result["new_asset"].asUUID(), - asset_type, - inventory_type, - mPostData["name"].asString(), - mPostData["description"].asString(), - LLSaleInfo::DEFAULT, - LLInventoryItem::II_FLAGS_NONE, - creation_date_now); - gInventory.updateItem(item); - gInventory.notifyObservers(); - - // Show the preview panel for textures and sounds to let - // user know that the image (or snapshot) arrived intact. - LLInventoryView* view = LLInventoryView::getActiveInventory(); - if(view) + break; + case LLInventoryType::IT_LSL: { - LLUICtrl* focus_ctrl = gFocusMgr.getKeyboardFocus(); - LLFocusMgr::FocusLostCallback callback = gFocusMgr.getFocusCallback(); - - view->getPanel()->setSelection(result["new_inventory_item"].asUUID(), TAKE_FOCUS_NO); - if((LLAssetType::AT_TEXTURE == asset_type) - || (LLAssetType::AT_SOUND == asset_type)) + // Find our window and close it if requested. + LLPreviewLSL* preview = (LLPreviewLSL*)LLPreview::find(item_id); + if (preview) { - view->getPanel()->openSelected(); + // Bytecode save completed + if (content["compiled"]) + { + preview->callbackLSLCompileSucceeded(); + } + else + { + preview->callbackLSLCompileFailed(content["errors"]); + } } - //LLInventoryView::dumpSelectionInformation((void*)view); - // restore keyboard focus - gFocusMgr.setKeyboardFocus(focus_ctrl, callback); } - } - else - { - llwarns << "Can't find a folder to put it in" << llendl; - } + break; + case LLInventoryType::IT_WEARABLE: + default: + break; + } +} - // remove the "Uploading..." message - LLUploadDialog::modalUploadFinished(); - - // *NOTE: This is a pretty big hack. What this does is check - // the file picker if there are any more pending uploads. If - // so, upload that file. - const char* next_file = LLFilePicker::instance().getNextFile(); - if(next_file) - { - const char* name = LLFilePicker::instance().getDirname(); - LLString asset_name = name; - LLString::replaceNonstandardASCII( asset_name, '?' ); - LLString::replaceChar(asset_name, '|', '?'); - LLString::stripNonprintable(asset_name); - LLString::trim(asset_name); +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type) +: LLAssetUploadResponder(post_data, vfile_id, asset_type) +{ +} - char* asset_name_str = (char*)asset_name.c_str(); - char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists - if( !end_p ) +LLUpdateTaskInventoryResponder::LLUpdateTaskInventoryResponder(const LLSD& post_data, + const std::string& file_name) +: LLAssetUploadResponder(post_data, file_name) +{ +} + +//virtual +void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content) +{ + llinfos << "LLUpdateTaskInventoryResponder::result from capabilities" << llendl; + LLUUID item_id = mPostData["item_id"]; + LLUUID task_id = mPostData["task_id"]; + + LLViewerObject* object = gObjectList.findObject(task_id); + if (!object) + { + llwarns << "LLUpdateTaskInventoryResponder::uploadComplete task " << task_id + << " no longer exist." << llendl; + return; + } + LLViewerInventoryItem* item = (LLViewerInventoryItem*)object->getInventoryObject(item_id); + if (!item) + { + llwarns << "LLUpdateTaskInventoryResponder::uploadComplete item " + << item_id << " is no longer in task " << task_id + << "'s inventory." << llendl; + return; + } + LLPointer new_item = new LLViewerInventoryItem(item); + // Update Viewer inventory + object->updateViewerInventoryAsset(new_item, content["new_asset"]); + dialog_refresh_all(); + + LLInventoryType::EType inventory_type = new_item->getInventoryType(); + switch(inventory_type) + { + case LLInventoryType::IT_NOTECARD: { - end_p = asset_name_str + strlen( asset_name_str ); - } - - S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); - asset_name = asset_name.substr( 0, len ); + // Update the UI with the new asset. + LLPreviewNotecard* nc; + nc = (LLPreviewNotecard*)LLPreview::find(new_item->getUUID()); + if(nc) + { + // *HACK: we have to delete the asset in the VFS so + // that the viewer will redownload it. This is only + // really necessary if the asset had to be modified by + // the uploader, so this can be optimized away in some + // cases. A better design is to have a new uuid if the + // script actually changed the asset. + if(nc->hasEmbeddedInventory()) + { + gVFS->removeFile( + content["new_asset"].asUUID(), + LLAssetType::AT_NOTECARD); + } - upload_new_resource(next_file, asset_name, asset_name, - 0, LLAssetType::AT_NONE, LLInventoryType::IT_NONE); - } + nc->refreshFromInventory(); + } + } + break; + case LLInventoryType::IT_LSL: + { + LLLiveLSLEditor* preview = LLLiveLSLEditor::find(item_id, task_id); + if (preview) + { + // Bytecode save completed + if (content["compiled"]) + { + preview->callbackLSLCompileSucceeded( + task_id, + item_id, + mPostData["is_script_running"]); + } + else + { + preview->callbackLSLCompileFailed(content["errors"]); + } + } + } + break; + case LLInventoryType::IT_WEARABLE: + default: + break; } } diff --git a/linden/indra/newview/llassetuploadresponders.h b/linden/indra/newview/llassetuploadresponders.h index 13d535e..ef8cd38 100644 --- a/linden/indra/newview/llassetuploadresponders.h +++ b/linden/indra/newview/llassetuploadresponders.h @@ -1,45 +1,65 @@ -/** - * @file llmapresponders.h - * @brief Processes responses received for asset upload requests. - * - * Copyright (c) 2006-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLNEWAGENTINVENTORYRESPONDER_H -#define LL_LLNEWAGENTINVENTORYRESPONDER_H +// llassetuploadresponders.h +// Copyright 2006, Linden Research, Inc. +// Processes responses received for asset upload requests. + +#ifndef LL_LLASSETUPLOADRESPONDER_H +#define LL_LLASSETUPLOADRESPONDER_H #include "llhttpclient.h" -class LLNewAgentInventoryResponder : public LLHTTPClient::Responder +// Abstract class for supporting asset upload +// via capabilities +class LLAssetUploadResponder : public LLHTTPClient::Responder { public: - LLNewAgentInventoryResponder(const LLUUID& uuid, const LLSD& post_data); - void error(U32 statusNum, const std::string& reason); + LLAssetUploadResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLAssetUploadResponder(const LLSD& post_data, const std::string& file_name); + ~LLAssetUploadResponder(); + virtual void error(U32 statusNum, const std::string& reason); virtual void result(const LLSD& content); + virtual void uploadUpload(const LLSD& content); + virtual void uploadComplete(const LLSD& content); + virtual void uploadFailure(const LLSD& content); -private: - LLUUID mUUID; +protected: LLSD mPostData; + LLUUID mVFileID; + LLAssetType::EType mAssetType; + std::string mFileName; +}; + +class LLNewAgentInventoryResponder : public LLAssetUploadResponder +{ +public: + LLNewAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLNewAgentInventoryResponder(const LLSD& post_data, const std::string& file_name); + virtual void uploadComplete(const LLSD& content); +}; + +class LLUpdateAgentInventoryResponder : public LLAssetUploadResponder +{ +public: + LLUpdateAgentInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLUpdateAgentInventoryResponder(const LLSD& post_data, + const std::string& file_name); + virtual void uploadComplete(const LLSD& content); +}; + +class LLUpdateTaskInventoryResponder : public LLAssetUploadResponder +{ +public: + LLUpdateTaskInventoryResponder(const LLSD& post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type); + LLUpdateTaskInventoryResponder(const LLSD& post_data, + const std::string& file_name); + virtual void uploadComplete(const LLSD& content); }; -#endif // LL_LLNEWAGENTINVENTORYRESPONDER_H +#endif // LL_LLASSETUPLOADRESPONDER_H diff --git a/linden/indra/newview/llasynchostbyname.h b/linden/indra/newview/llasynchostbyname.h index 39f1b82..351fc2a 100644 --- a/linden/indra/newview/llasynchostbyname.h +++ b/linden/indra/newview/llasynchostbyname.h @@ -52,7 +52,7 @@ public: static void handleMessageCallback(const MSG& msg); private: HANDLE mRequestHandle; - char mOutputBuffer[ MAXGETHOSTSTRUCT ]; + char mOutputBuffer[ MAXGETHOSTSTRUCT ]; /*Flawfinder: ignore*/ LLAsyncHostByNameCallback mCallback; void* mUserdata; diff --git a/linden/indra/newview/llcallingcard.cpp b/linden/indra/newview/llcallingcard.cpp index 83a5fac..d1fdda6 100644 --- a/linden/indra/newview/llcallingcard.cpp +++ b/linden/indra/newview/llcallingcard.cpp @@ -262,8 +262,8 @@ S32 LLAvatarTracker::addBuddyList(const LLAvatarTracker::buddy_map_t& buds) using namespace std; U32 new_buddy_count = 0; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLUUID agent_id; for(buddy_map_t::const_iterator itr = buds.begin(); itr != buds.end(); ++itr) { @@ -560,8 +560,8 @@ void LLAvatarTracker::processChange(LLMessageSystem* msg) { if((mBuddyInfo[agent_id]->getRightsGrantedFrom() ^ new_rights) & LLRelationship::GRANT_MODIFY_OBJECTS) { - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLStringBase::format_map_t args; if(gCacheName->getName(agent_id, first, last)) { @@ -617,8 +617,8 @@ void LLAvatarTracker::processNotify(LLMessageSystem* msg, bool online) setBuddyOnline(agent_id,online); if(chat_notify) { - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if(gCacheName->getName(agent_id, first, last)) { notify = TRUE; diff --git a/linden/indra/newview/llcallingcard.h b/linden/indra/newview/llcallingcard.h index 75d06ee..1b2a643 100644 --- a/linden/indra/newview/llcallingcard.h +++ b/linden/indra/newview/llcallingcard.h @@ -208,8 +208,8 @@ public: virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy); typedef std::map buddy_map_t; buddy_map_t mMappable; - char mFirst[DB_FIRST_NAME_BUF_SIZE]; - char mLast[DB_LAST_NAME_BUF_SIZE]; + char mFirst[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char mLast[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ }; // collect dictionary sorted map of name -> agent_id for every online buddy @@ -221,8 +221,8 @@ public: virtual bool operator()(const LLUUID& buddy_id, LLRelationship* buddy); typedef std::map buddy_map_t; buddy_map_t mOnline; - char mFirst[DB_FIRST_NAME_BUF_SIZE]; - char mLast[DB_LAST_NAME_BUF_SIZE]; + char mFirst[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char mLast[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ }; // collect dictionary sorted map of name -> agent_id for every buddy, @@ -236,8 +236,8 @@ public: typedef std::map buddy_map_t; buddy_map_t mOnline; buddy_map_t mOffline; - char mFirst[DB_FIRST_NAME_BUF_SIZE]; - char mLast[DB_LAST_NAME_BUF_SIZE]; + char mFirst[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char mLast[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ }; #endif // LL_LLCALLINGCARD_H diff --git a/linden/indra/newview/llcameraview.cpp b/linden/indra/newview/llcameraview.cpp index c510823..6c63359 100644 --- a/linden/indra/newview/llcameraview.cpp +++ b/linden/indra/newview/llcameraview.cpp @@ -124,17 +124,11 @@ void LLFloaterCamera::onClose(bool app_quitting) // static void LLFloaterCamera::show(void*) { - if (gFloaterCamera) - { - gFloaterCamera->open(); - } - else + if(!gFloaterCamera) { gFloaterCamera = new LLFloaterCamera("camera floater"); - - gFloaterCamera->open(); } - + gFloaterCamera->open(); /* Flawfinder: ignore */ gSavedSettings.setBOOL("ShowCameraControls", TRUE); } diff --git a/linden/indra/newview/llchatbar.cpp b/linden/indra/newview/llchatbar.cpp index e62e0cb..394399e 100644 --- a/linden/indra/newview/llchatbar.cpp +++ b/linden/indra/newview/llchatbar.cpp @@ -599,8 +599,6 @@ void LLChatBar::onInputEditorKeystroke( LLLineEditor* caller, void* userdata ) // << " outlen " << out_str.getLength() // << llendl; } - // make sure we don't do UI-only render as it is apparent avatar isn't animating - gViewerWindow->finishFastFrame(); } // static diff --git a/linden/indra/newview/llcloud.cpp b/linden/indra/newview/llcloud.cpp index ca05562..b14f6d5 100644 --- a/linden/indra/newview/llcloud.cpp +++ b/linden/indra/newview/llcloud.cpp @@ -116,16 +116,14 @@ void LLCloudGroup::updatePuffs(const F32 dt) mVOCloudsp->setPositionRegion(mCenterRegion); mVOCloudsp->setScale(LLVector3(256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, 256.f/CLOUD_GROUPS_PER_EDGE + CLOUD_PUFF_WIDTH, - CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)); + CLOUD_HEIGHT_RANGE + CLOUD_PUFF_HEIGHT)*0.5f); gPipeline.addObject(mVOCloudsp); } - S32 i; - LLVector3 velocity; LLVector3d vel_d; // Update the positions of all of the clouds - for (i = 0; i < mCloudPuffs.count(); i++) + for (U32 i = 0; i < mCloudPuffs.size(); i++) { LLCloudPuff &puff = mCloudPuffs[i]; velocity = mCloudLayerp->getRegion()->mWind.getCloudVelocity(mCloudLayerp->getRegion()->getPosRegionFromGlobal(puff.mPositionGlobal)); @@ -140,8 +138,8 @@ void LLCloudGroup::updatePuffs(const F32 dt) void LLCloudGroup::updatePuffOwnership() { - S32 i = 0; - while (i < mCloudPuffs.count()) + U32 i = 0; + while (i < mCloudPuffs.size()) { if (mCloudPuffs[i].getLifeState() == LL_PUFF_DYING) { @@ -165,10 +163,11 @@ void LLCloudGroup::updatePuffOwnership() continue; } //llinfos << "Puff handed off!" << llendl; - LLCloudPuff *puffp = new_cgp->mCloudPuffs.reserve_block(1); - puffp->mPositionGlobal = mCloudPuffs[i].mPositionGlobal; - puffp->mAlpha = mCloudPuffs[i].mAlpha; - mCloudPuffs.remove(i); + LLCloudPuff puff; + puff.mPositionGlobal = mCloudPuffs[i].mPositionGlobal; + puff.mAlpha = mCloudPuffs[i].mAlpha; + mCloudPuffs.erase(mCloudPuffs.begin() + i); + new_cgp->mCloudPuffs.push_back(puff); } //llinfos << "Puff count: " << LLCloudPuff::sPuffCount << llendl; @@ -184,7 +183,7 @@ void LLCloudGroup::updatePuffCount() S32 target_puff_count = llround(CLOUD_DENSITY * mDensity); target_puff_count = llmax(0, target_puff_count); target_puff_count = llmin(CLOUD_COUNT_MAX, target_puff_count); - S32 current_puff_count = mCloudPuffs.count(); + S32 current_puff_count = (S32) mCloudPuffs.size(); // Create a new cloud if we need one if (current_puff_count < target_puff_count) { @@ -205,7 +204,7 @@ void LLCloudGroup::updatePuffCount() // Count the number of live puffs S32 live_puff_count = 0; - for (i = 0; i < mCloudPuffs.count(); i++) + for (i = 0; i < (S32) mCloudPuffs.size(); i++) { if (mCloudPuffs[i].getLifeState() != LL_PUFF_DYING) { @@ -231,12 +230,12 @@ void LLCloudGroup::updatePuffCount() // Remove fully dead puffs i = 0; - while (i < mCloudPuffs.count()) + while (i < (S32) mCloudPuffs.size()) { if (mCloudPuffs[i].isDead()) { //llinfos << "Removing dead puff!" << llendl; - mCloudPuffs.remove(i); + mCloudPuffs.erase(mCloudPuffs.begin() + i); LLCloudPuff::sPuffCount--; } else diff --git a/linden/indra/newview/llcloud.h b/linden/indra/newview/llcloud.h index 8567792..0b670ee 100644 --- a/linden/indra/newview/llcloud.h +++ b/linden/indra/newview/llcloud.h @@ -129,7 +129,7 @@ public: BOOL inGroup(const LLCloudPuff &puff) const; F32 getDensity() const { return mDensity; } - S32 getNumPuffs() const { return mCloudPuffs.count(); } + S32 getNumPuffs() const { return (S32) mCloudPuffs.size(); } const LLCloudPuff &getPuff(const S32 i) { return mCloudPuffs[i]; } protected: LLCloudLayer *mCloudLayerp; @@ -137,7 +137,7 @@ protected: F32 mDensity; S32 mTargetPuffCount; - LLDynamicArray mCloudPuffs; + std::vector mCloudPuffs; LLPointer mVOCloudsp; }; diff --git a/linden/indra/newview/llcolorswatch.h b/linden/indra/newview/llcolorswatch.h index 98bc85e..b52d6ac 100644 --- a/linden/indra/newview/llcolorswatch.h +++ b/linden/indra/newview/llcolorswatch.h @@ -31,6 +31,7 @@ #include "lluictrl.h" #include "v4color.h" #include "llfloater.h" +#include "llviewerimage.h" // // Classes diff --git a/linden/indra/newview/llcompilequeue.cpp b/linden/indra/newview/llcompilequeue.cpp index e42677d..c5ad2b9 100644 --- a/linden/indra/newview/llcompilequeue.cpp +++ b/linden/indra/newview/llcompilequeue.cpp @@ -197,8 +197,8 @@ void LLFloaterScriptQueue::addObject(const LLUUID& id) BOOL LLFloaterScriptQueue::start() { //llinfos << "LLFloaterCompileQueue::start()" << llendl; - char buffer[MAX_STRING]; - sprintf(buffer, "Starting %s of %d items.", mStartString, mObjectIDs.count()); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Starting %s of %d items.", mStartString, mObjectIDs.count()); /*Flawfinder: ignore*/ LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output"); list->addSimpleItem(buffer); @@ -237,8 +237,8 @@ BOOL LLFloaterScriptQueue::nextObject() LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output"); mDone = TRUE; - char buffer[MAX_STRING]; - sprintf(buffer, "Done."); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Done."); /*Flawfinder: ignore*/ list->addSimpleItem(buffer); childSetEnabled("close",TRUE); } @@ -287,7 +287,7 @@ LLFloaterCompileQueue* LLFloaterCompileQueue::create() rect.translate(left - rect.mLeft, top - rect.mTop); LLFloaterCompileQueue* new_queue = new LLFloaterCompileQueue("queue", rect); - new_queue->open(); + new_queue->open(); /*Flawfinder: ignore*/ return new_queue; } @@ -372,25 +372,25 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, if(!data) return; LLFloaterCompileQueue* queue = static_cast (LLFloaterScriptQueue::findInstance(data->mQueueID)); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ buffer[0] = '\0'; if(queue && (0 == status)) { //llinfos << "ITEM NAME 3: " << data->mScriptName << llendl; // Dump this into a file on the local disk so we can compile it. - char filename[LL_MAX_PATH] = ""; + char filename[LL_MAX_PATH] = ""; /*Flawfinder: ignore*/ LLVFile file(vfs, asset_id, type); - char uuid_str[UUID_STR_LENGTH]; + char uuid_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ asset_id.toString(uuid_str); - sprintf(filename,"%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type)); + snprintf(filename, sizeof(filename), "%s.%s",gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_str).c_str(),LLAssetType::lookup(type)); /*Flawfinder: ignore*/ - FILE *fp = LLFile::fopen(filename, "wb"); + FILE *fp = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ if (fp) { const S32 buf_size = 65536; U8 copy_buf[buf_size]; - while (file.read(copy_buf, buf_size)) + while (file.read(copy_buf, buf_size)) /*Flawfinder: ignore*/ { if (fwrite(copy_buf, file.getLastBytesRead(), 1, fp) < 1) { @@ -403,7 +403,7 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, } // It's now in the file, now compile it. - sprintf(buffer, "Downloaded, now compiling '%s'.", data->mScriptName.c_str()); + snprintf(buffer, sizeof(buffer), "Downloaded, now compiling '%s'.", data->mScriptName.c_str()); /*Flawfinder: ignore*/ queue->compile(filename, asset_id); // Delete it after we're done compiling? @@ -420,19 +420,19 @@ void LLFloaterCompileQueue::scriptArrived(LLVFS *vfs, const LLUUID& asset_id, { LLChat chat("Script not found on server."); LLFloaterChat::addChat(chat); - sprintf(buffer, "Problem downloading %s.", + snprintf(buffer, sizeof(buffer), "Problem downloading %s.", /*Flawfinder: ignore*/ data->mScriptName.c_str()); } else if (LL_ERR_INSUFFICIENT_PERMISSIONS == status) { LLChat chat("Insufficient permissions to download a script."); LLFloaterChat::addChat(chat); - sprintf(buffer, "Insufficient permissions for '%s'.", + snprintf(buffer, sizeof(buffer), "Insufficient permissions for '%s'.", /*Flawfinder: ignore*/ data->mScriptName.c_str()); } else { - sprintf(buffer, "Unknown failure to download %s.", + snprintf(buffer, sizeof(buffer), "Unknown failure to download %s.", /*Flawfinder: ignore*/ data->mScriptName.c_str()); } @@ -493,12 +493,12 @@ void LLFloaterCompileQueue::compile(const char* filename, tid.generate(); new_asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); - char uuid_string[UUID_STR_LENGTH]; + char uuid_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ new_asset_id.toString(uuid_string); - char dst_filename[LL_MAX_PATH]; - sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - char err_filename[LL_MAX_PATH]; - sprintf(err_filename, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); + char dst_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf(dst_filename, sizeof(dst_filename), "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ + char err_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf(err_filename, sizeof(err_filename), "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ gAssetStorage->storeAssetData(filename, tid, LLAssetType::AT_LSL_TEXT, @@ -590,7 +590,7 @@ LLFloaterResetQueue* LLFloaterResetQueue::create() rect.translate(left - rect.mLeft, top - rect.mTop); LLFloaterResetQueue* new_queue = new LLFloaterResetQueue("queue", rect); - new_queue->open(); + new_queue->open(); /*Flawfinder: ignore*/ return new_queue; } @@ -621,8 +621,8 @@ void LLFloaterResetQueue::handleInventory(LLViewerObject* viewer_obj, { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output"); - char buffer[MAX_STRING]; - sprintf(buffer, "Resetting '%s'.", item->getName().c_str()); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Resetting '%s'.", item->getName().c_str()); /*Flawfinder: ignore*/ list->addSimpleItem(buffer); LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_ScriptReset); @@ -653,7 +653,7 @@ LLFloaterRunQueue* LLFloaterRunQueue::create() rect.translate(left - rect.mLeft, top - rect.mTop); LLFloaterRunQueue* new_queue = new LLFloaterRunQueue("queue", rect); - new_queue->open(); + new_queue->open(); /*Flawfinder: ignore*/ return new_queue; } @@ -684,8 +684,8 @@ void LLFloaterRunQueue::handleInventory(LLViewerObject* viewer_obj, { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output"); - char buffer[MAX_STRING]; - sprintf(buffer, "Running '%s'.", item->getName().c_str()); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Running '%s'.", item->getName().c_str()); /*Flawfinder: ignore*/ list->addSimpleItem(buffer); LLMessageSystem* msg = gMessageSystem; @@ -718,7 +718,7 @@ LLFloaterNotRunQueue* LLFloaterNotRunQueue::create() rect.translate(left - rect.mLeft, top - rect.mTop); LLFloaterNotRunQueue* new_queue = new LLFloaterNotRunQueue("queue", rect); - new_queue->open(); + new_queue->open(); /*Flawfinder: ignore*/ return new_queue; } @@ -749,8 +749,8 @@ void LLFloaterNotRunQueue::handleInventory(LLViewerObject* viewer_obj, { LLInventoryItem* item = (LLInventoryItem*)((LLInventoryObject*)(*it)); LLScrollListCtrl* list = LLUICtrlFactory::getScrollListByName(this, "queue output"); - char buffer[MAX_STRING]; - sprintf(buffer, "Not running '%s'.", item->getName().c_str()); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Not running '%s'.", item->getName().c_str()); /*Flawfinder: ignore*/ list->addSimpleItem(buffer); LLMessageSystem* msg = gMessageSystem; diff --git a/linden/indra/newview/llconsole.cpp b/linden/indra/newview/llconsole.cpp index 1ed0e17..ce092a7 100644 --- a/linden/indra/newview/llconsole.cpp +++ b/linden/indra/newview/llconsole.cpp @@ -118,6 +118,8 @@ void LLConsole::draw() { LLGLSUIDefault gls_ui; + addQueuedLines(); + // skip lines added more than mLinePersistTime ago F32 cur_time = mTimer.getElapsedTimeF32(); @@ -243,38 +245,57 @@ void LLConsole::addLine(const LLString& utf8line, F32 size, const LLColor4 &colo void LLConsole::addLine(const LLWString& wline, F32 size, const LLColor4 &color) { - if (!wline.empty() && mFont != NULL) + while (mLineQueue.size() >= mMaxLines) + { + mLineQueue.pop_front(); + } + mLineQueue.push_back(LineInfo(wline, size, color, mTimer.getElapsedTimeF32())); +} + +void LLConsole::addQueuedLines() +{ + for (line_queue_t::iterator iter = mLineQueue.begin(); + iter != mLineQueue.end(); ++iter) { - // Wrap lines that are longer than the view is wide. - S32 offset = 0; - while( offset < (S32)wline.length() ) + LineInfo& line_info = *iter; + LLWString wline = line_info.wline; + //F32 size = line_info.size; + LLColor4 color = line_info.color; + if (!wline.empty() && mFont != NULL) { - S32 skip_chars; // skip '\n' - // Figure out if a word-wrapped line fits here. - LLWString::size_type line_end = wline.find_first_of(llwchar('\n'), offset); - if (line_end != LLWString::npos) - { - skip_chars = 1; // skip '\n' - } - else - { - line_end = wline.size(); - skip_chars = 0; - } - U32 drawable = mFont->maxDrawableChars(wline.c_str()+offset, (F32)mRect.getWidth(), line_end-offset, TRUE); - if (drawable != 0) - { - LLFixedBuffer::addLine(wline.substr(offset, drawable)); - } - else + // Wrap lines that are longer than the view is wide. + S32 offset = 0; + while( offset < (S32)wline.length() ) { - // force a blank line - LLFixedBuffer::addLine(" "); + S32 skip_chars; // skip '\n' + // Figure out if a word-wrapped line fits here. + LLWString::size_type line_end = wline.find_first_of(llwchar('\n'), offset); + if (line_end != LLWString::npos) + { + skip_chars = 1; // skip '\n' + } + else + { + line_end = wline.size(); + skip_chars = 0; + } + U32 drawable = mFont->maxDrawableChars(wline.c_str()+offset, (F32)mRect.getWidth(), line_end-offset, TRUE); + if (drawable != 0) + { + LLFixedBuffer::addLine(wline.substr(offset, drawable)); + mAddTimes[mAddTimes.size()-1] = line_info.add_time; + } + else + { + // force a blank line + LLFixedBuffer::addLine(" "); + } + mColors.push_back(color); + offset += (drawable + skip_chars); } - mColors.push_back(color); - offset += (drawable + skip_chars); } } + mLineQueue.clear(); } void LLConsole::removeExtraLines() diff --git a/linden/indra/newview/llconsole.h b/linden/indra/newview/llconsole.h index 2a072f9..525cab3 100644 --- a/linden/indra/newview/llconsole.h +++ b/linden/indra/newview/llconsole.h @@ -45,6 +45,21 @@ private: S32 mLastBoxHeight; S32 mLastBoxWidth; + struct LineInfo + { + LineInfo(const LLWString &wln, F32 sz, const LLColor4& clr, F32 time) + : wline(wln), size(sz), color(clr), add_time(time) + { + + } + LLWString wline; + F32 size; + LLColor4 color; + F32 add_time; + }; + typedef std::list line_queue_t; + line_queue_t mLineQueue; + public: // Font size: // -1 = monospace, 0 means small, font size = 1 means big @@ -65,7 +80,8 @@ public: void addLine(const LLString& utf8line, F32 size, const LLColor4 &color); void addLine(const LLWString& wline, F32 size, const LLColor4 &color); - + void addQueuedLines(); + // Overrides /*virtual*/ void draw(); /*virtual*/ void addLine(const LLString& utf8line); diff --git a/linden/indra/newview/llcontroldef.cpp b/linden/indra/newview/llcontroldef.cpp index 850b5bf..cd4cf4d 100644 --- a/linden/indra/newview/llcontroldef.cpp +++ b/linden/indra/newview/llcontroldef.cpp @@ -186,7 +186,12 @@ void declare_settings() gSavedSettings.declareString("FontMonospace", "profontwindows.ttf", "Name of monospace font (Truetype file name)"); gSavedSettings.declareString("FontSansSerif", "MtBkLfRg.ttf", "Name of san-serif font (Truetype file name)"); #if LL_WINDOWS - gSavedSettings.declareString("FontSansSerifFallback", "ArialUni.ttf", "Name of fallback san-serif font (Truetype file name)"); + // Lists Japanese, Korean, and Chinese sanserif fonts available in + // Windows XP and Vista, as well as "Arial Unicode MS". + gSavedSettings.declareString( + "FontSansSerifFallback", + "MSGOTHIC.TTC;gulim.ttc;simhei.ttf;ArialUni.ttf", + "Name of fallback san-serif font (Truetype file name)"); #elif LL_DARWIN // This is a fairly complete Japanese font that ships with Mac OS X. // The first filename is in UTF8, but it shows up in the font menu as "Hiragino Kaku Gothic Pro W3". @@ -654,7 +659,6 @@ void declare_settings() gSavedSettings.declareF32( "RenderFarClip", 256.f, "Distance of far clip plane from camera (meters)" ); gSavedSettings.declareF32( "RenderFogRatio", 2.0f, "Distance from camera where fog reaches maximum density (fraction or multiple of far clip distance)"); gSavedSettings.declareBOOL("RenderAnisotropic", FALSE, "Render textures using anisotropic filtering" ); - gSavedSettings.declareBOOL("RenderLightGlows", FALSE, "Render glow sprites on top of light sources" ); gSavedSettings.declareBOOL("ShowXUINames", FALSE, "Display XUI Names as Tooltips" ); gSavedSettings.declareS32("RenderLightingDetail", 1, "Amount of detail for lighting objects/avatars/terrain (0=sun/moon only, 1=enable local lights)" ); gSavedSettings.declareS32("RenderTerrainDetail", 2, "Detail applied to terrain texturing (0 = none, 1 or 2 = full)" ); @@ -664,13 +668,13 @@ void declare_settings() gSavedSettings.declareF32( "RenderAvatarLODFactor", 0.5f, "Controls level of detail of avatars (multiplier for current screen area when calculated level of detail)" ); gSavedSettings.declareF32( "RenderBumpmapMinDistanceSquared", 100.f, "Maximum distance at which to render bumpmapped primitives (distance in meters, squared)" ); gSavedSettings.declareS32( "RenderMaxPartCount", 4096, "Maximum number of particles to display on screen"); - gSavedSettings.declareBOOL("RenderUseAGP", TRUE, "Used AGP for fast transfer of data to graphics card" ); - gSavedSettings.declareBOOL("RenderUseVBO", FALSE, "Use GL Vertex Buffer Objects" ); + gSavedSettings.declareBOOL("RenderVBOEnable", TRUE, "Use GL Vertex Buffer Objects" ); //gSavedSettings.declareBOOL("RenderUseTriStrips", FALSE, "[NOT USED]"); //gSavedSettings.declareBOOL("RenderCullBySize", FALSE, "[NOT USED]" ); gSavedSettings.declareF32("RenderTerrainScale", 12.f, "Terrain detail texture scale"); gSavedSettings.declareBOOL("VertexShaderEnable", FALSE, "Enable/disable all GLSL shaders (debug)"); gSavedSettings.declareBOOL("RenderRippleWater", FALSE, "Display more realistic water, with refraction (requires pixel shader support on your video card)"); + gSavedSettings.declareBOOL("RenderDynamicReflections", FALSE, "Generate a dynamic cube map for reflections (objects reflect their environment, experimental)."); gSavedSettings.declareBOOL("RenderObjectBump", TRUE, "Show bumpmapping on primitives"); gSavedSettings.declareS32("RenderAvatarMode", 1, "Controls how avatars are rendered (0 = normal, 1 = bump mapped, 2 = bump mapped and wavy cloth)"); gSavedSettings.declareBOOL("RenderAvatarVP", TRUE, "Use vertex programs to perform hardware skinning of avatar"); @@ -683,6 +687,7 @@ void declare_settings() gSavedSettings.declareBOOL("RenderUIInSnapshot", FALSE, "Display user interface in snapshot" ); gSavedSettings.declareBOOL("RenderHUDInSnapshot", FALSE, "Display HUD attachments in snapshot" ); gSavedSettings.declareBOOL("HighResSnapshot", FALSE, "Double resolution of snapshot from current window resolution" ); + gSavedSettings.declareBOOL("CompressSnapshotsToDisk", FALSE, "Compress snapshots saved to disk (Using JPEG 2000)" ); gSavedSettings.declareBOOL("FreezeTime", FALSE, "", FALSE ); gSavedSettings.declareBOOL("UseFreezeFrame", FALSE, "Freeze time when taking snapshots."); gSavedSettings.declareBOOL("CloseSnapshotOnKeep", TRUE, "Close snapshot window after saving snapshot" ); @@ -711,6 +716,10 @@ void declare_settings() //gSavedSettings.declareS32("ImageRadioTexMem", 0, "Texture memory allocation (0 = <512 megabytes system RAM, 1 = >512 megabytes system RAM)"); //gSavedSettings.declareS32("ImageRadioVidCardMem", 1, "Video card onboard memory (0 = 16MB, 1 = 32MB, 2 = 64MB, 3 = 128MB, 4 = 256MB, 5 = 512MB)"); //gSavedSettings.declareU32("LastRAMDetected", 0, "[DO NOT MODIFY] Detected system memory (bytes)"); // used to detect RAM changes + gSavedSettings.declareBOOL("ImagePipelineUseHTTP", FALSE, "If TRUE use HTTP GET to fetch textures from the server"); + + // Threading + gSavedSettings.declareBOOL("RunMultipleThreads", FALSE, "If TRUE keep background threads active during render"); // Camera control gSavedSettings.declareBOOL("AutoPilotLocksCamera", FALSE, "Keep camera position locked when avatar walks to selected position"); @@ -746,6 +755,9 @@ void declare_settings() // Currently matches BW_PRESET_300 gSavedSettings.declareF32("ThrottleBandwidthKBPS", 500.f, "Maximum allowable downstream bandwidth (kilo bits per second)"); + gSavedSettings.declareBOOL("ConnectionPortEnabled", FALSE, "Use the custom connection port?"); + gSavedSettings.declareU32("ConnectionPort", 13000, "Custom connection port number"); + // File xfer throttle gSavedSettings.declareF32("XferThrottle", 150000.f, "Maximum allowable downstream bandwidth for asset transfers (bits per second)"); @@ -884,6 +896,8 @@ void declare_settings() gSavedSettings.declareF32 ("GridDrawSize", 12.0f, "Visible extent of 2D snap grid (meters)"); gSavedSettings.declareBOOL("GridSubUnit", FALSE, "Display fractional grid steps, relative to grid size"); gSavedSettings.declareF32("GridOpacity", 0.7f, "Grid line opacity (0.0 = completely transparent, 1.0 = completely opaque)"); + gSavedSettings.declareBOOL("GridCrossSections", FALSE, "Highlight cross sections of prims with grid manipulation plane."); + gSavedSettings.declareS32("GridMode", 0, "Snap grid reference frame (0 = world, 1 = local, 2 = reference object)"); //gSavedSettings.declareBOOL("GridIsLocal", FALSE, "[NOT USED]"); gSavedSettings.declareS32("GridSubdivision", 32, "Maximum number of times to divide single snap grid unit when GridSubUnit is true"); @@ -1027,10 +1041,17 @@ void declare_settings() gSavedSettings.declareColor3("SkyNightColorShift", LLColor3(0.7f, 0.7f, 1.0f), "Controls moonlight color (base color applied to moon as light source)"); gSavedSettings.declareBOOL("FixedWeather", FALSE, "Weather effects do not change over time"); - // VFS stuff + // Cache Stuff gSavedSettings.declareU32("VFSSalt", 1, "[DO NOT MODIFY] Controls local file caching behavior"); - gSavedSettings.declareU32("VFSOldSize", 2, "[DO NOT MODIFY] Controls resizing of local file cache"); - gSavedSettings.declareU32("VFSSize", 2, "Controls amount of hard drive space reserved for local file caching (0 = 50MB, 1 = 200MB, 2 = 500MB, 3 = 1000MB)"); + gSavedSettings.declareU32("VFSOldSize", 0, "[DO NOT MODIFY] Controls resizing of local file cache"); +// gSavedSettings.declareU32("VFSSize", 2, "Controls amount of hard drive space reserved for local file caching (0 = 50MB, 1 = 200MB, 2 = 500MB, 3 = 1000MB)"); + gSavedSettings.declareU32("CacheSize", 500, "Controls amount of hard drive space reserved for local file caching in MB"); + gSavedSettings.declareString("CacheLocation", "", "Controls the location of the local disk cache"); + gSavedSettings.declareString("NewCacheLocation", "", "Change the location of the local disk cache to this"); + gSavedSettings.declareU32("CacheValidateCounter", 0, "Used to distribute cache validation"); + // Delete all files in cache directory on startup + gSavedSettings.declareBOOL("PurgeCacheOnStartup", FALSE, "Clear local file cache every time viewer is run"); + gSavedSettings.declareBOOL("PurgeCacheOnNextStartup", FALSE, "Clear local file cache next time viewer is run"); // Used for special titles such as "Second Life - Special E3 2003 Beta" gSavedSettings.declareBOOL("ShowOverlayTitle", FALSE, "Prints watermark text message on screen"); @@ -1060,6 +1081,8 @@ void declare_settings() // The last version that was run with this prefs file. Default to a version that will never be current, // and update after the setting is used in the startup sequence. gSavedSettings.declareString("LastRunVersion", "0.0.0", "Version number of last instance of the viewer that you ran"); + // Local cache version (change if format changes) + gSavedSettings.declareS32("LocalCacheVersion", 0, "Version number of cache"); // cached mean collision values gSavedSettings.declareBOOL("MeanCollisionBump", FALSE, "You have experienced an abuse of being bumped by an object or avatar" ); @@ -1072,7 +1095,7 @@ void declare_settings() gSavedSettings.declareBOOL("LeftClickShowMenu", FALSE, "Left click opens pie menu (FALSE = left click touches or grabs object)"); gSavedSettings.declareF32("MouseSensitivity", 3.f, "Controls responsiveness of mouse when in mouselook mode (fraction or multiple of default mouse sensitivity)"); - + gSavedSettings.declareBOOL("MouseSmooth", FALSE, "Smooths out motion of mouse when in mouselook mode."); gSavedSettings.declareBOOL("InvertMouse", FALSE, "When in mouselook, moving mouse up looks down and vice verse (FALSE = moving up looks up)"); gSavedSettings.declareBOOL("EditCameraMovement", FALSE, "When entering build mode, camera moves up above avatar"); @@ -1145,8 +1168,8 @@ void declare_settings() // Checkboxes in Find -> Popular // Should these all be the same? I imagine we might want a single "show mature." - bbc - gSavedSettings.declareBOOL("ShowMatureFindAll",TRUE, "Display results of find all that are in mature sims"); - gSavedSettings.declareBOOL("ShowMatureSims", TRUE, "Display results of find places or find popular that are in mature sims"); + gSavedSettings.declareBOOL("ShowMatureFindAll",FALSE, "Display results of find all that are in mature sims"); + gSavedSettings.declareBOOL("ShowMatureSims", FALSE, "Display results of find places or find popular that are in mature sims"); gSavedSettings.declareBOOL("ShowMatureEvents", FALSE, "Display results of find events that are flagged as mature"); gSavedSettings.declareBOOL("ShowMatureClassifieds", FALSE, "Display results of find classifieds that are flagged as mature"); @@ -1185,10 +1208,6 @@ void declare_settings() gSavedSettings.declareBOOL("ShowLandHoverTip", FALSE, "Show descriptive tooltip when mouse hovers over land"); gSavedSettings.declareBOOL("ShowAllObjectHoverTip", FALSE, "Show descriptive tooltip when mouse hovers over non-interactive and interactive objects."); - // Delete all files in cache directory on startup - gSavedSettings.declareBOOL("PurgeCacheOnStartup", FALSE, "Clear local file cache every time viewer is run"); - gSavedSettings.declareBOOL("PurgeCacheOnNextStartup", FALSE, "Clear local file cache next time viewer is run"); - // Use an external web browser (Firefox, Internet Explorer) // CP: making this TRUE by default since there is no internal Web browser // now and other components may interrogate this setting @@ -1223,3 +1242,15 @@ void declare_settings() gCrashSettings.declareS32(CRASH_BEHAVIOR_SETTING, CRASH_BEHAVIOR_ASK, "Controls behavior when viewer crashes " "(0 = ask before sending crash report, 1 = always send crash report, 2 = never send crash report)"); } + +void settings_version_fixup() +{ +#if LL_RELEASE_FOR_DOWNLOAD + if (gCurrentVersion == "1.13.3" || gCurrentVersion == "1.13.4") + { + // In case these were set to true in an early 'First Look' version: + gSavedSettings.setBOOL("RenderDynamicReflections", FALSE); + gSavedSettings.setBOOL("ImagePipelineUseHTTP", FALSE); + } +#endif +} diff --git a/linden/indra/newview/llcubemap.cpp b/linden/indra/newview/llcubemap.cpp index 4406bc8..415b849 100644 --- a/linden/indra/newview/llcubemap.cpp +++ b/linden/indra/newview/llcubemap.cpp @@ -176,8 +176,6 @@ void LLCubeMap::bind() glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MAG_FILTER, GL_LINEAR); glTexParameteri(GL_TEXTURE_CUBE_MAP_ARB, GL_TEXTURE_MIN_FILTER, (use_cube_mipmaps? GL_LINEAR_MIPMAP_LINEAR : GL_LINEAR)); - - glTexEnvi (GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } else { @@ -220,11 +218,23 @@ void LLCubeMap::setMatrix(S32 stage) { mMatrixStage = stage; glActiveTextureARB(GL_TEXTURE0_ARB+stage); + + F32 mat[16]; + + glGetFloatv(GL_MODELVIEW_MATRIX, mat); + + LLVector3 x(mat); + LLVector3 y(mat+4); + LLVector3 z(mat+8); + + LLMatrix3 mat3; + mat3.setRows(x,y,z); + LLMatrix4 trans(mat3); + trans.transpose(); + glMatrixMode(GL_TEXTURE); glPushMatrix(); - LLMatrix4 tmat; - gCamera->getRotMatrixToParent(tmat); - glLoadMatrixf((F32 *)tmat.mMatrix); + glLoadMatrixf((F32 *)trans.mMatrix); glMatrixMode(GL_MODELVIEW); } diff --git a/linden/indra/newview/llcubemap.h b/linden/indra/newview/llcubemap.h index 6596257..7be6706 100644 --- a/linden/indra/newview/llcubemap.h +++ b/linden/indra/newview/llcubemap.h @@ -36,7 +36,7 @@ class LLVector3; // Environment map hack! -class LLCubeMap +class LLCubeMap : public LLRefCount { public: LLCubeMap(); diff --git a/linden/indra/newview/llcurrencyuimanager.cpp b/linden/indra/newview/llcurrencyuimanager.cpp index 5893836..615d9fb 100644 --- a/linden/indra/newview/llcurrencyuimanager.cpp +++ b/linden/indra/newview/llcurrencyuimanager.cpp @@ -144,10 +144,10 @@ void LLCurrencyUIManager::Impl::updateCurrencyInfo() } LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); - keywordArgs.appendString("agentId", - gAgent.getID().getString()); - keywordArgs.appendString("secureSessionId", - gAgent.getSecureSessionID().getString()); + keywordArgs.appendString("agentId", gAgent.getID().asString()); + keywordArgs.appendString( + "secureSessionId", + gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); LLXMLRPCValue params = LLXMLRPCValue::createArray(); @@ -191,10 +191,10 @@ void LLCurrencyUIManager::Impl::startCurrencyBuy(const std::string& password) mCurrencyChanged = false; LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); - keywordArgs.appendString("agentId", - gAgent.getID().getString()); - keywordArgs.appendString("secureSessionId", - gAgent.getSecureSessionID().getString()); + keywordArgs.appendString("agentId", gAgent.getID().asString()); + keywordArgs.appendString( + "secureSessionId", + gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("currencyBuy", mUserCurrencyBuy); keywordArgs.appendInt("estimatedCost", mSiteCurrencyEstimatedCost); keywordArgs.appendString("confirm", mSiteConfirm); diff --git a/linden/indra/newview/llcylinder.cpp b/linden/indra/newview/llcylinder.cpp index b3eaa44..9f76648 100644 --- a/linden/indra/newview/llcylinder.cpp +++ b/linden/indra/newview/llcylinder.cpp @@ -34,7 +34,7 @@ #include "llmath.h" #include "noise.h" #include "v3math.h" - +#include "llvertexbuffer.h" #include "llgl.h" #include "llglheaders.h" @@ -43,6 +43,10 @@ LLCone gCone; GLUquadricObj* gQuadObj = NULL; +static const GLint SLICES[] = { 30, 20, 12, 6 }; // same as sphere slices +static const GLint STACKS = 2; +static const GLfloat RADIUS = 0.5f; + // draws a cylinder or cone // returns approximate number of triangles required U32 draw_cylinder_side(GLint slices, GLint stacks, GLfloat base_radius, GLfloat top_radius) @@ -106,46 +110,27 @@ U32 draw_cylinder_cap(GLint slices, GLfloat base_radius, BOOL is_top) return triangles; } +void LLCylinder::drawSide(S32 detail) +{ + draw_cylinder_side(SLICES[detail], STACKS, RADIUS, RADIUS); +} -void LLCylinder::prerender() +void LLCylinder::drawTop(S32 detail) { - GLint stacks = 2; - GLfloat radius = 0.5f; - GLint slices[CYLINDER_LEVELS_OF_DETAIL] = { 30, 20, 12, 6 }; // same as sphere slices + draw_cylinder_cap(SLICES[detail], RADIUS, TOP); +} - for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) - { - mTriangleCount[detail] = 0; - - mDisplayListSide[detail] = glGenLists(1); - glNewList(mDisplayListSide[detail], GL_COMPILE); - mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, radius ); - glEndList(); - - mDisplayListTop[detail] = glGenLists(1); - glNewList( mDisplayListTop[detail], GL_COMPILE); - mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, TOP ); - glEndList(); - - mDisplayListBottom[detail] = glGenLists(1); - glNewList( mDisplayListBottom[detail], GL_COMPILE); - mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM ); - glEndList(); - } +void LLCylinder::drawBottom(S32 detail) +{ + draw_cylinder_cap(SLICES[detail], RADIUS, BOTTOM); } -void LLCylinder::cleanupGL() +void LLCylinder::prerender() { - for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) - { - glDeleteLists(mDisplayListSide[detail], 1); - mDisplayListSide[detail] = 0; - glDeleteLists(mDisplayListTop[detail], 1); - mDisplayListTop[detail] = 0; - glDeleteLists(mDisplayListBottom[detail], 1); - mDisplayListBottom[detail] = 0; - } +} +void LLCylinder::cleanupGL() +{ if (gQuadObj) { gluDeleteQuadric(gQuadObj); @@ -197,19 +182,21 @@ void LLCylinder::renderface(F32 pixel_area, S32 face) return; } + LLVertexBuffer::unbind(); + switch(face) { case 0: glTranslatef(0.f, 0.f, -0.5f); - glCallList(mDisplayListSide[level_of_detail]); + drawSide(level_of_detail); break; case 1: glTranslatef(0.0f, 0.f, 0.5f); - glCallList(mDisplayListTop[level_of_detail]); + drawTop(level_of_detail); break; case 2: glTranslatef(0.0f, 0.f, -0.5f); - glCallList(mDisplayListBottom[level_of_detail]); + drawBottom(level_of_detail); break; default: llerror("LLCylinder::renderface() fell out of switch", 0); @@ -227,37 +214,10 @@ void LLCylinder::renderface(F32 pixel_area, S32 face) void LLCone::prerender() { - GLint stacks = 2; - GLfloat radius = 0.5f; - GLint slices[CONE_LEVELS_OF_DETAIL] = { 32, 18, 12, 6 }; - - for (S32 detail = 0; detail < CONE_LEVELS_OF_DETAIL; detail++) - { - mTriangleCount[detail] = 0; - - mDisplayListSide[detail] = glGenLists(1); - glNewList(mDisplayListSide[detail], GL_COMPILE); - mTriangleCount[detail] += draw_cylinder_side( slices[detail], stacks, radius, 0.f ); - glEndList(); - - mDisplayListBottom[detail] = glGenLists(1); - glNewList( mDisplayListBottom[detail], GL_COMPILE); - mTriangleCount[detail] += draw_cylinder_cap( slices[detail], radius, BOTTOM ); - glEndList(); - } } void LLCone::cleanupGL() { - for (S32 detail = 0; detail < CYLINDER_LEVELS_OF_DETAIL; detail++) - { - glDeleteLists(mDisplayListSide[detail], 1); - mDisplayListSide[detail] = 0; - - glDeleteLists(mDisplayListBottom[detail], 1); - mDisplayListBottom[detail] = 0; - } - if (gQuadObj) { gluDeleteQuadric(gQuadObj); @@ -265,6 +225,15 @@ void LLCone::cleanupGL() } } +void LLCone::drawSide(S32 detail) +{ + draw_cylinder_side( SLICES[detail], STACKS, RADIUS, 0.f ); +} + +void LLCone::drawBottom(S32 detail) +{ + draw_cylinder_cap( SLICES[detail], RADIUS, BOTTOM ); +} void LLCone::render(S32 level_of_detail) { @@ -282,8 +251,9 @@ void LLCone::render(S32 level_of_detail) // center object at 0 glTranslatef(0.f, 0.f, - height / 2.0f); - glCallList(mDisplayListSide[level_of_detail]); - glCallList(mDisplayListBottom[level_of_detail]); + LLVertexBuffer::unbind(); + drawSide(level_of_detail); + drawBottom(level_of_detail); glMatrixMode(GL_MODELVIEW); glPopMatrix(); @@ -307,15 +277,17 @@ void LLCone::renderface(S32 level_of_detail, S32 face) glMatrixMode(GL_MODELVIEW); glPushMatrix(); + LLVertexBuffer::unbind(); + switch(face) { case 0: glTranslatef(0.f, 0.f, -0.5f); - glCallList(mDisplayListSide[level_of_detail]); + drawSide(level_of_detail); break; case 1: glTranslatef(0.f, 0.f, -0.5f); - glCallList(mDisplayListBottom[level_of_detail]); + drawBottom(level_of_detail); break; default: llerror("LLCylinder::renderface() fell out of switch", 0); diff --git a/linden/indra/newview/llcylinder.h b/linden/indra/newview/llcylinder.h index b9e0a0e..fbd1298 100644 --- a/linden/indra/newview/llcylinder.h +++ b/linden/indra/newview/llcylinder.h @@ -39,20 +39,15 @@ const S32 CYLINDER_FACES = 3; class LLCylinder { -protected: - U32 mDisplayListSide[CYLINDER_LEVELS_OF_DETAIL]; - U32 mDisplayListTop[CYLINDER_LEVELS_OF_DETAIL]; - U32 mDisplayListBottom[CYLINDER_LEVELS_OF_DETAIL]; - U32 mTriangleCount[CYLINDER_LEVELS_OF_DETAIL]; - public: void prerender(); + void drawTop(S32 detail); + void drawSide(S32 detail); + void drawBottom(S32 detail); void cleanupGL(); void render(F32 pixel_area); void renderface(F32 pixel_area, S32 face); - - U32 getTriangleCount(S32 level_of_detail) { return mTriangleCount[level_of_detail]; } }; @@ -65,20 +60,14 @@ const S32 CONE_LEVELS_OF_DETAIL = 4; const S32 CONE_FACES = 2; class LLCone -{ -protected: - U32 mDisplayListSide[CONE_LEVELS_OF_DETAIL]; - U32 mDisplayListBottom[CONE_LEVELS_OF_DETAIL]; - U32 mTriangleCount[CONE_LEVELS_OF_DETAIL]; - +{ public: void prerender(); void cleanupGL(); - + void drawSide(S32 detail); + void drawBottom(S32 detail); void render(S32 level_of_detail); void renderface(S32 level_of_detail, S32 face); - - U32 getTriangleCount(S32 level_of_detail) { return mTriangleCount[level_of_detail]; } }; extern LLCylinder gCylinder; diff --git a/linden/indra/newview/lldebugmessagebox.cpp b/linden/indra/newview/lldebugmessagebox.cpp index 46dffdf..e6c1bf1 100644 --- a/linden/indra/newview/lldebugmessagebox.cpp +++ b/linden/indra/newview/lldebugmessagebox.cpp @@ -163,7 +163,7 @@ LLDebugVarMessageBox* LLDebugVarMessageBox::show(const std::string& title, EDebu sInstances[title_string] = box; gFloaterView->addChild(box); box->reshape(200,150); - box->open(); + box->open(); /*Flawfinder: ignore*/ box->mTitle = title_string; } @@ -206,18 +206,18 @@ void LLDebugVarMessageBox::onClose(bool app_quitting) void LLDebugVarMessageBox::draw() { - char text[128]; + char text[128]; /*Flawfinder: ignore*/ switch(mVarType) { case VAR_TYPE_F32: - sprintf(text, "%.3f", *((F32*)mVarData)); + snprintf(text, sizeof(text), "%.3f", *((F32*)mVarData)); /*Flawfinder: ignore*/ break; case VAR_TYPE_S32: - sprintf(text, "%d", *((S32*)mVarData)); + snprintf(text, sizeof(text), "%d", *((S32*)mVarData)); /*Flawfinder: ignore*/ break; case VAR_TYPE_VEC3: LLVector3* vec_p = (LLVector3*)mVarData; - sprintf(text, "%.3f %.3f %.3f", vec_p->mV[VX], vec_p->mV[VY], vec_p->mV[VZ]); + snprintf(text, sizeof(text), "%.3f %.3f %.3f", vec_p->mV[VX], vec_p->mV[VY], vec_p->mV[VZ]); /*Flawfinder: ignore*/ break; } mText->setText(text); diff --git a/linden/indra/newview/lldirpicker.cpp b/linden/indra/newview/lldirpicker.cpp index 38a008c..75f8056 100644 --- a/linden/indra/newview/lldirpicker.cpp +++ b/linden/indra/newview/lldirpicker.cpp @@ -203,7 +203,7 @@ OSStatus LLDirPicker::doNavChooseDialog() AEKeyword theAEKeyword; DescType typeCode; Size actualSize = 0; - char path[LL_MAX_PATH]; + char path[LL_MAX_PATH]; /*Flawfinder: ignore*/ memset(&fsRef, 0, sizeof(fsRef)); error = AEGetNthPtr(&navReply.selection, 1, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize); diff --git a/linden/indra/newview/lldirpicker.h b/linden/indra/newview/lldirpicker.h index 72b5675..71a65fd 100644 --- a/linden/indra/newview/lldirpicker.h +++ b/linden/indra/newview/lldirpicker.h @@ -83,7 +83,7 @@ private: #endif - char mDirs[DIRNAME_BUFFER_SIZE]; + char mDirs[DIRNAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ LLString* mFileName; LLString mDir; BOOL mLocked; diff --git a/linden/indra/newview/lldrawable.cpp b/linden/indra/newview/lldrawable.cpp index af4f205..4d9083e 100644 --- a/linden/indra/newview/lldrawable.cpp +++ b/linden/indra/newview/lldrawable.cpp @@ -33,8 +33,6 @@ #include "material_codes.h" // viewer includes -#include "llagparray.h" -#include "llagparray.inl" #include "llcriticaldamp.h" #include "llface.h" #include "lllightconstants.h" @@ -77,6 +75,8 @@ U32 LLDrawable::sNumZombieDrawables = 0; F32 LLDrawable::sCurPixelAngle = 0; LLDynamicArrayPtr > LLDrawable::sDeadList; +#define FORCE_INVISIBLE_AREA 16.f + // static void LLDrawable::incrementVisible() { @@ -127,12 +127,11 @@ void LLDrawable::destroy() std::for_each(mFaces.begin(), mFaces.end(), DeletePointer()); mFaces.clear(); - /* - if (!(sNumZombieDrawables % 10)) + + /*if (!(sNumZombieDrawables % 10)) { llinfos << "- Zombie drawables: " << sNumZombieDrawables << llendl; - } - */ + }*/ } void LLDrawable::markDead() @@ -269,7 +268,7 @@ void LLDrawable::removeFace(const S32 i) } #endif -LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BOOL shared_geom) +LLFace* LLDrawable::addFace(LLFacePool *poolp, LLViewerImage *texturep) { LLMemType mt(LLMemType::MTYPE_DRAWABLE); @@ -278,16 +277,12 @@ LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BO if (face) { mFaces.push_back(face); - face->setPool(poolp, texturep); - if (shared_geom) + if (poolp) { - face->setState(LLFace::SHARED_GEOM); - } - else if (!isVisible()) - { - face->setState(LLFace::BACKLIST); + face->setPool(poolp, texturep); } + if (isState(UNLIT)) { face->setState(LLFace::FULLBRIGHT); @@ -296,7 +291,27 @@ LLFace* LLDrawable::addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BO return face; } -void LLDrawable::setNumFaces(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep) +LLFace* LLDrawable::addFace(const LLTextureEntry *te, LLViewerImage *texturep) +{ + LLMemType mt(LLMemType::MTYPE_DRAWABLE); + + LLFace *face = new LLFace(this, mVObjp); + + face->setTEOffset(mFaces.size()); + face->setTexture(texturep); + face->setPoolType(gPipeline.getPoolTypeFromTE(te, texturep)); + mFaces.push_back(face); + + if (isState(UNLIT)) + { + face->setState(LLFace::FULLBRIGHT); + } + + return face; + +} + +void LLDrawable::setNumFaces(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep) { if (newFaces == (S32)mFaces.size()) { @@ -317,7 +332,7 @@ void LLDrawable::setNumFaces(const S32 newFaces, LLDrawPool *poolp, LLViewerImag } } -void LLDrawable::setNumFacesFast(const S32 newFaces, LLDrawPool *poolp, LLViewerImage *texturep) +void LLDrawable::setNumFacesFast(const S32 newFaces, LLFacePool *poolp, LLViewerImage *texturep) { if (newFaces <= (S32)mFaces.size() && newFaces >= (S32)mFaces.size()/2) { @@ -372,21 +387,43 @@ void LLDrawable::updateMaterial() void LLDrawable::makeActive() { +#if !LL_RELEASE_FOR_DOWNLOAD + if (mVObjp.notNull()) + { + U32 pcode = mVObjp->getPCode(); + if (pcode == LLViewerObject::LL_VO_WATER || + pcode == LLViewerObject::LL_VO_SURFACE_PATCH || + pcode == LLViewerObject::LL_VO_PART_GROUP || + pcode == LLViewerObject::LL_VO_CLOUDS || + pcode == LLViewerObject::LL_VO_STARS || + pcode == LLViewerObject::LL_VO_GROUND || + pcode == LLViewerObject::LL_VO_SKY) + { + llerrs << "Static viewer object has active drawable!" << llendl; + } + } +#endif + if (!isState(ACTIVE)) // && mGeneration > 0) { setState(ACTIVE); + //parent must be made active first if (!isRoot() && !mParent->isActive()) { mParent->makeActive(); } - + gPipeline.setActive(this, TRUE); //all child objects must also be active for (U32 i = 0; i < getChildCount(); i++) { - getChild(i)->makeActive(); + LLDrawable* drawable = getChild(i); + if (drawable) + { + drawable->makeActive(); + } } if (mVObjp->getPCode() == LL_PCODE_VOLUME) @@ -403,7 +440,15 @@ void LLDrawable::makeActive() gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); } } - mQuietCount = 0; + updatePartition(); + if (isRoot()) + { + mQuietCount = 0; + } + else + { + getParent()->mQuietCount = 0; + } } @@ -416,7 +461,7 @@ void LLDrawable::makeStatic() if (mParent.notNull() && mParent->isActive()) { - llerrs << "Drawable became static with active parent!" << llendl; + llwarns << "Drawable becamse static with active parent!" << llendl; } S32 child_count = mVObjp->mChildList.size(); @@ -425,6 +470,10 @@ void LLDrawable::makeStatic() LLDrawable* child_drawable = mVObjp->mChildList[child_num]->mDrawable; if (child_drawable) { + if (child_drawable->getParent() != this) + { + llwarns << "Child drawable has unknown parent." << llendl; + } child_drawable->makeStatic(); } } @@ -441,6 +490,7 @@ void LLDrawable::makeStatic() setSpatialBridge(NULL); } } + updatePartition(); } // Returns "distance" between target destination and resulting xfrom @@ -499,9 +549,8 @@ F32 LLDrawable::updateXform(BOOL undamped) if (scaled >= MIN_INTERPOLATE_DISTANCE_SQUARED) { //scaling requires an immediate rebuild - gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); + gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } - } else { @@ -517,20 +566,6 @@ F32 LLDrawable::updateXform(BOOL undamped) mXform.updateMatrix(); mCurrentScale = target_scale; - - if (!getVOVolume()) - { - movePartition(); - } - else if (mSpatialBridge) - { - gPipeline.markMoved(mSpatialBridge, FALSE); - } - else - { - //a child prim moved and needs its verts regenerated - gPipeline.markRebuild(this, LLDrawable::REBUILD_VOLUME, TRUE); - } return dist_squared; } @@ -540,11 +575,6 @@ void LLDrawable::setRadius(F32 radius) if (mRadius != radius) { mRadius = radius; - updateBinRadius(); - if (!getVOVolume()) - { - movePartition(); - } } } @@ -573,13 +603,10 @@ void LLDrawable::moveUpdatePipeline(BOOL moved) void LLDrawable::movePartition() { - if (getSpatialGroup() || getVOVolume()) + LLSpatialPartition* part = getSpatialPartition(); + if (part) { - LLSpatialPartition* part = getSpatialPartition(); - if (part) - { - part->move(this, getSpatialGroup()); - } + part->move(this, getSpatialGroup()); } } @@ -625,10 +652,27 @@ BOOL LLDrawable::updateMoveUndamped() } mVObjp->clearChanged(LLXform::MOVED); - + return TRUE; } +void LLDrawable::updatePartition() +{ + if (!getVOVolume()) + { + movePartition(); + } + else if (mSpatialBridge) + { + gPipeline.markMoved(mSpatialBridge, FALSE); + } + else + { + //a child prim moved and needs its verts regenerated + gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); + } +} + BOOL LLDrawable::updateMoveDamped() { F32 dist_squared = updateXform(FALSE); @@ -654,25 +698,42 @@ BOOL LLDrawable::updateMoveDamped() void LLDrawable::updateDistance(LLCamera& camera) { - if (mVObjp->isHUDAttachment()) - { - mDistanceWRTCamera = 1.0f; - if (sCurVisible % 16 == 0) - { - mVObjp->updateLOD(); - } - return; - } - - LLVector3 pos(getPositionGroup()); - - pos -= camera.getOrigin(); - mDistanceWRTCamera = pos.magVec(); - //switch LOD with the spatial group to avoid artifacts LLSpatialGroup* sg = getSpatialGroup(); + + LLVector3 pos; + if (!sg || sg->changeLOD()) { + LLVOVolume* volume = getVOVolume(); + if (volume) + { + volume->updateRelativeXform(); + pos = LLVector3(0,0,0) * volume->getRelativeXform(); + + for (S32 i = 0; i < getNumFaces(); i++) + { + LLFace* facep = getFace(i); + if (facep->getPoolType() == LLDrawPool::POOL_ALPHA) + { + LLVector3 box = (facep->mExtents[1] - facep->mExtents[0]) * 0.25f; + LLVector3 v = (facep->mCenterLocal-camera.getOrigin()); + LLVector3 at = camera.getAtAxis(); + for (U32 j = 0; j < 3; j++) + { + v.mV[j] -= box.mV[j] * at.mV[j]; + } + facep->mDistance = v * camera.getAtAxis(); + } + } + } + else + { + pos = LLVector3(getPositionGroup()); + } + + pos -= camera.getOrigin(); + mDistanceWRTCamera = llround(pos.magVec(), 0.01f); mVObjp->updateLOD(); } } @@ -687,67 +748,33 @@ void LLDrawable::updateTexture() return; } - // *FIX: this updates textures on all faces in this drawable, not - // just the viewer object we care about - if (mVObjp->getNumTEs()) + if (getNumFaces() != mVObjp->getNumTEs()) + { //drawable is transitioning its face count + return; + } + + if (getVOVolume()) { - // For each face in this drawable, change the drawpool if necessary. - for (S32 i = 0; i < getNumFaces(); i++) + if (!isActive()) + { + gPipeline.markMoved(this); + } + else { - LLFace *facep = mFaces[i]; - U32 pool_type = facep->getPool()->getType(); - - if ((pool_type == LLDrawPool::POOL_SIMPLE) || - (pool_type == LLDrawPool::POOL_ALPHA) || - (pool_type == LLDrawPool::POOL_HUD) || - (pool_type == LLDrawPool::POOL_MEDIA) || - (pool_type == LLDrawPool::POOL_BUMP)) + if (isRoot()) { - LLViewerObject* objp = facep->getViewerObject(); - S32 te_offset = facep->getTEOffset(); - - if (te_offset >= objp->getNumTEs()) // Shouldn't happen - { - llwarns << "TE offsets don't match!" << llendl; - facep->setTEOffset(-1); - continue; - } - - LLDrawPool* poolp = NULL; - LLViewerImage* imagep = (te_offset >= 0) ? objp->getTEImage(te_offset) : facep->getTexture(); - if (facep->isState(LLFace::HUD_RENDER)) - { - poolp = gPipeline.getPool(LLDrawPool::POOL_HUD); - } - else if (te_offset >= 0) - { - // This face actually uses texture entries... - const LLTextureEntry* te = facep->getTextureEntry(); - poolp = LLPipeline::getPoolFromTE(te, imagep); - } - else - { - // No texture entry for this face. - if (!imagep) - { - poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, NULL); - } - else if ((imagep->getComponents() == 4) || (imagep->getComponents() == 2)) - { - poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - } - else - { - poolp = gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep); - } - } - facep->setPool(poolp, imagep); + mQuietCount = 0; + } + else + { + getParent()->mQuietCount = 0; } } + + gPipeline.markRebuild(this, LLDrawable::REBUILD_MATERIAL, TRUE); } } - BOOL LLDrawable::updateGeometry(BOOL priority) { llassert(mVObjp.notNull()); @@ -788,12 +815,9 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) mXform.setScale(1,1,1); mXform.updateMatrix(); - if (isStatic() || // *FIX: don't know why this is happening, but - // some terrain patches are becoming active - // (earth quake, maybe?) DP - getRenderType() == LLPipeline::RENDER_TYPE_TERRAIN) + if (isStatic()) { - LLStrider verticesp; + gPipeline.markRebuild(this, LLDrawable::REBUILD_GEOMETRY, TRUE); for (S32 i = 0; i < getNumFaces(); i++) { @@ -802,34 +826,13 @@ void LLDrawable::shiftPos(const LLVector3 &shift_vector) facep->mExtents[0] += shift_vector; facep->mExtents[1] += shift_vector; - if (facep->hasGeometry() && !facep->isState(LLFace::SHARED_GEOM)) + if (facep->hasGeometry()) { - S32 index = facep->getVertices(verticesp); - if (index >= 0) - { - S32 vertex_count = facep->getGeomCount(); - for (S32 j = 0; j < vertex_count; j++) - { - *verticesp += shift_vector; - verticesp++; - } - } + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; } } - } - else - { - // Update the face centers. - for (S32 i = 0; i < getNumFaces(); i++) - { - LLFace *facep = getFace(i); - facep->mCenterAgent += shift_vector; - } - } - - //update spatial extents - if (!getVOVolume() || isStatic()) - { + mExtents[0] += shift_vector; mExtents[1] += shift_vector; mPositionGroup += LLVector3d(shift_vector); @@ -874,6 +877,8 @@ void LLDrawable::updateSpatialExtents() mVObjp->updateSpatialExtents(mExtents[0], mExtents[1]); } + updateBinRadius(); + if (mSpatialBridge.notNull()) { mPositionGroup.setVec(0,0,0); @@ -883,11 +888,14 @@ void LLDrawable::updateSpatialExtents() void LLDrawable::updateBinRadius() { - S32 binLOD = mVObjp ? mVObjp->getLOD() : 2; - static F64 detail_bins[] = { 8, 4, 2, 1 }; - F32 radius = getVOVolume() && isStatic() ? - (mExtents[1]-mExtents[0]).magVec() : getRadius(); - mBinRadius = detail_bins[binLOD] * llmax((F64) radius, (3-binLOD)*0.25); + if (mVObjp.notNull()) + { + mBinRadius = mVObjp->getBinRadius(); + } + else + { + mBinRadius = getRadius()*4.f; + } } void LLDrawable::updateLightSet() @@ -898,6 +906,7 @@ void LLDrawable::updateLightSet() return; } + LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME); LLVOVolume* light = getVOVolume(); if (isLight() && light) { @@ -907,7 +916,7 @@ void LLDrawable::updateLightSet() gPipeline.markRelight(*iter); } mLightSet.clear(); - gPipeline.mObjectPartition->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet); + part->getObjects(getPositionAgent(), light->getLightRadius(), mLightSet); for (drawable_set_t::iterator iter = mLightSet.begin(); iter != mLightSet.end(); iter++) { gPipeline.markRelight(*iter); @@ -917,9 +926,9 @@ void LLDrawable::updateLightSet() { // mLightSet points to nearby lights mLightSet.clear(); - gPipeline.mObjectPartition->getLights(getPositionAgent(), getRadius(), mLightSet); - const U32 max_lights = 16; - if (mLightSet.size() > max_lights) + part->getLights(getPositionAgent(), getRadius(), mLightSet); + const drawable_set_t::size_type MAX_LIGHTS = 16; + if (mLightSet.size() > MAX_LIGHTS) { typedef std::set > > sorted_pair_set_t; sorted_pair_set_t sorted_set; @@ -1053,28 +1062,28 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() { LLSpatialPartition* retval = NULL; - if (mVObjp->isHUDAttachment()) - { //HUD attachments don't get space partitioned - return NULL; - } - if (!mVObjp || !getVOVolume() || isStatic()) { - retval = gPipeline.mObjectPartition; + retval = gPipeline.getSpatialPartition((LLViewerObject*) mVObjp); } - - //must be an active volume - if (!retval && isRoot()) - { + else if (isRoot()) + { //must be an active volume if (!mSpatialBridge) { - setSpatialBridge(new LLSpatialBridge(this)); + if (mVObjp->isHUDAttachment()) + { + setSpatialBridge(new LLHUDBridge(this)); + } + else + { + setSpatialBridge(new LLVolumeBridge(this)); + } } return mSpatialBridge->asPartition(); } - else if (!retval) + else { retval = getParent()->getSpatialPartition(); } @@ -1088,27 +1097,73 @@ LLSpatialPartition* LLDrawable::getSpatialPartition() return retval; } + +BOOL LLDrawable::isVisible() const +{ + if (mVisible == sCurVisible) + { + return TRUE; + } + + if (isActive()) + { + if (isRoot()) + { + LLSpatialGroup* group = mSpatialBridge.notNull() ? mSpatialBridge->getSpatialGroup() : + getSpatialGroup(); + if (!group || group->isVisible()) + { + mVisible = sCurVisible; + return TRUE; + } + } + else + { + if (getParent()->isVisible()) + { + mVisible = sCurVisible; + return TRUE; + } + } + } + else + { + LLSpatialGroup* group = getSpatialGroup(); + if (!group || group->isVisible()) + { + mVisible = sCurVisible; + return TRUE; + } + } + + return FALSE; +} + //======================================= // Spatial Partition Bridging Drawable //======================================= -LLSpatialBridge::LLSpatialBridge(LLDrawable* root) +LLSpatialBridge::LLSpatialBridge(LLDrawable* root, U32 data_mask) +: LLSpatialPartition(data_mask, FALSE) { mDrawable = root; root->setSpatialBridge(this); - mRenderType = mDrawable->mRenderType; //w00! magic! - + mRenderType = mDrawable->mRenderType; + mDrawableType = mDrawable->mRenderType; + + mPartitionType = LLPipeline::PARTITION_VOLUME; + mOctree->balance(); - gPipeline.mObjectPartition->put(this); + gPipeline.getSpatialPartition(mPartitionType)->put(this); } LLSpatialBridge::~LLSpatialBridge() { if (getSpatialGroup()) { - gPipeline.mObjectPartition->remove(this, getSpatialGroup()); + gPipeline.getSpatialPartition(mPartitionType)->remove(this, getSpatialGroup()); } } @@ -1116,7 +1171,6 @@ void LLSpatialBridge::updateSpatialExtents() { LLSpatialGroup* root = (LLSpatialGroup*) mOctree->getListener(0); - if (mOctree->getChildCount() > 0) { LLFastTimer ftm(LLFastTimer::FTM_CULL_REBOUND); root->rebound(); @@ -1164,6 +1218,9 @@ void LLSpatialBridge::updateSpatialExtents() } } } + + LLVector3 diagonal = newMax - newMin; + mRadius = diagonal.magVec() * 0.5f; mPositionGroup.setVec((newMin + newMax) * 0.5f); updateBinRadius(); @@ -1171,9 +1228,7 @@ void LLSpatialBridge::updateSpatialExtents() void LLSpatialBridge::updateBinRadius() { - F32 rad = ((mExtents[1]-mExtents[0])*0.5f).magVec(); - mBinRadius = llmax(rad, 2.f); - mRadius = rad; + mBinRadius = llmin((F32) mOctree->getSize().mdV[0]*0.5f, 256.f); } LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) @@ -1181,39 +1236,123 @@ LLCamera LLSpatialBridge::transformCamera(LLCamera& camera) LLCamera ret = camera; LLXformMatrix* mat = mDrawable->getXform(); LLVector3 center = LLVector3(0,0,0) * mat->getWorldMatrix(); - //LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); + LLQuaternion rotation = LLQuaternion(mat->getWorldMatrix()); - //ret.rotate(~mat->getRotation()); LLVector3 delta = ret.getOrigin() - center; - delta *= ~mat->getRotation(); - ret.setOrigin(delta); + LLQuaternion rot = ~mat->getRotation(); + + delta *= rot; + LLVector3 lookAt = ret.getAtAxis(); + LLVector3 up_axis = ret.getUpAxis(); + LLVector3 left_axis = ret.getLeftAxis(); + lookAt *= rot; + up_axis *= rot; + left_axis *= rot; + + ret.setOrigin(delta); + ret.setAxes(lookAt, left_axis, up_axis); + return ret; } void LLDrawable::setVisible(LLCamera& camera, std::vector* results, BOOL for_select) { mVisible = sCurVisible; + +#if 0 && !LL_RELEASE_FOR_DOWNLOAD + //crazy paranoid rules checking + if (getVOVolume()) + { + if (!isRoot()) + { + if (isActive() && !mParent->isActive()) + { + llerrs << "Active drawable has static parent!" << llendl; + } + + if (isStatic() && !mParent->isStatic()) + { + llerrs << "Static drawable has active parent!" << llendl; + } + + if (mSpatialBridge) + { + llerrs << "Child drawable has spatial bridge!" << llendl; + } + } + else if (isActive() && !mSpatialBridge) + { + llerrs << "Active root drawable has no spatial bridge!" << llendl; + } + else if (isStatic() && mSpatialBridge.notNull()) + { + llerrs << "Static drawable has spatial bridge!" << llendl; + } + } +#endif } +class LLOctreeMarkNotCulled: public LLOctreeTraveler +{ +public: + LLCamera* mCamera; + + LLOctreeMarkNotCulled(LLCamera* camera_in) : mCamera(camera_in) { } + + virtual void traverse(const LLOctreeNode* node) + { + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + group->clearState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED); + LLOctreeTraveler::traverse(node); + } + + void visit(const LLOctreeState* branch) + { + gPipeline.markNotCulled((LLSpatialGroup*) branch->getListener(0), *mCamera, TRUE); + } +}; + void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector* results, BOOL for_select) { + if (!gPipeline.hasRenderType(mDrawableType)) + { + return; + } + + LLViewerObject *vobj = mDrawable->getVObj(); + if (vobj && vobj->isAttachment() && !vobj->isHUDAttachment()) + { + LLVOAvatar* av; + LLDrawable* parent = mDrawable->getParent(); + + if (parent) + { + av = (LLVOAvatar*) parent->getVObj(); + + if (!av->isVisible()) + { + return; + } + } + } + + + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); + LLVector3 center = (mExtents[0] + mExtents[1]) * 0.5f; LLVector3 size = (mExtents[1]-mExtents[0]) * 0.5f; if (camera_in.AABBInFrustum(center, size)) { - LLVector3 lookAt = center - camera_in.getOrigin(); - F32 distSqr = lookAt.magVecSquared(); - F32 objRad = size.magVecSquared(); - - if (objRad/distSqr < SG_MIN_DIST_RATIO*4) + if (LLPipeline::calcPixelArea(center, size, camera_in) < FORCE_INVISIBLE_AREA) { return; } LLDrawable::setVisible(camera_in); - + if (for_select) { results->push_back(mDrawable); @@ -1222,42 +1361,36 @@ void LLSpatialBridge::setVisible(LLCamera& camera_in, std::vector* results->push_back(mDrawable->getChild(i)); } } - else + else { - const LLVector3* extents = mDrawable->getSpatialExtents(); - objRad = mDrawable->getRadius(); - objRad *= objRad; - - if (objRad/distSqr > SG_MIN_DIST_RATIO) - { - gPipeline.markNotCulled(mDrawable, camera_in); - } - - for (U32 i = 0; i < mDrawable->getChildCount(); i++) - { - LLDrawable* child = mDrawable->getChild(i); - extents = child->getSpatialExtents(); - objRad = child->getRadius(); - objRad *= objRad; - - if (objRad/distSqr > SG_MIN_DIST_RATIO) - { - gPipeline.markNotCulled(mDrawable->getChild(i), camera_in); - } - } - } + LLCamera trans_camera = transformCamera(camera_in); + LLOctreeMarkNotCulled culler(&trans_camera); + culler.traverse(mOctree); + } } } void LLSpatialBridge::updateDistance(LLCamera& camera_in) { + if (mDrawable == NULL) + { + markDead(); + return; + } + LLCamera camera = transformCamera(camera_in); mDrawable->updateDistance(camera); for (U32 i = 0; i < mDrawable->getChildCount(); ++i) { - mDrawable->getChild(i)->updateDistance(camera); + LLDrawable* child = mDrawable->getChild(i); + if (!child) + { + llwarns << "Corrupt drawable found while updating spatial bridge distance." << llendl; + continue; + } + child->updateDistance(camera); } } @@ -1280,7 +1413,7 @@ void LLSpatialBridge::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL imm BOOL LLSpatialBridge::updateMove() { mOctree->balance(); - gPipeline.mObjectPartition->move(this, getSpatialGroup(), TRUE); + gPipeline.getSpatialPartition(mPartitionType)->move(this, getSpatialGroup(), TRUE); return TRUE; } @@ -1338,3 +1471,81 @@ const LLVector3 LLDrawable::getPositionAgent() const } } +BOOL LLDrawable::isAnimating() const +{ + if (!getVObj()) + { + return TRUE; + } + + if (getScale() != mVObjp->getScale()) + { + return TRUE; + } + + if (mVObjp->isFlexible()) + { + return TRUE; + } + + if (mVObjp->getPCode() == LLViewerObject::LL_VO_PART_GROUP) + { + return TRUE; + } + + if (mVObjp->getPCode() == LLViewerObject::LL_VO_CLOUDS) + { + return TRUE; + } + + LLVOVolume* vol = getVOVolume(); + if (vol && vol->mTextureAnimp) + { + return TRUE; + } + + if (!isRoot() && !mVObjp->getAngularVelocity().isExactlyZero()) + { + return TRUE; + } + + return FALSE; +} + +void LLDrawable::updateFaceSize(S32 idx) +{ + if (mVObjp.notNull()) + { + mVObjp->updateFaceSize(idx); + } +} + +LLBridgePartition::LLBridgePartition() +: LLSpatialPartition(0, TRUE) +{ + mRenderByGroup = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_AVATAR; + mPartitionType = LLPipeline::PARTITION_BRIDGE; + mLODPeriod = 1; + mSlopRatio = 0.f; +} + +LLHUDBridge::LLHUDBridge(LLDrawable* drawablep) +: LLVolumeBridge(drawablep) +{ + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mPartitionType = LLPipeline::PARTITION_HUD; + mSlopRatio = 0.0f; +} + +F32 LLHUDBridge::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) +{ + return 1024.f; +} + + +void LLHUDBridge::shiftPos(const LLVector3& vec) +{ + //don't shift hud bridges on region crossing +} + diff --git a/linden/indra/newview/lldrawable.h b/linden/indra/newview/lldrawable.h index 062427e..6ff4d1e 100644 --- a/linden/indra/newview/lldrawable.h +++ b/linden/indra/newview/lldrawable.h @@ -38,8 +38,8 @@ #include "v4coloru.h" #include "llquaternion.h" #include "xform.h" +#include "llmemtype.h" #include "llprimitive.h" -#include "llviewerimage.h" #include "lldarray.h" #include "llstat.h" #include "llviewerobject.h" @@ -52,6 +52,7 @@ class LLSpatialGroup; class LLSpatialBridge; class LLSpatialPartition; class LLVOVolume; +class LLViewerImage; extern F32 gFrameTimeSeconds; @@ -74,7 +75,7 @@ public: BOOL isLight() const; - BOOL isVisible() const { return (mVisible == sCurVisible); } + BOOL isVisible() const; virtual void setVisible(LLCamera& camera_in, std::vector* results = NULL, BOOL for_select = FALSE); @@ -121,10 +122,11 @@ public: inline S32 getNumFaces() const; //void removeFace(const S32 i); // SJB: Avoid using this, it's slow - LLFace* addFace(LLDrawPool *poolp, LLViewerImage *texturep, const BOOL shared_geom = FALSE); + LLFace* addFace(LLFacePool *poolp, LLViewerImage *texturep); + LLFace* addFace(const LLTextureEntry *te, LLViewerImage *texturep); void deleteFaces(S32 offset, S32 count); - void setNumFaces(const S32 numFaces, LLDrawPool *poolp, LLViewerImage *texturep); - void setNumFacesFast(const S32 numFaces, LLDrawPool *poolp, LLViewerImage *texturep); + void setNumFaces(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep); + void setNumFacesFast(const S32 numFaces, LLFacePool *poolp, LLViewerImage *texturep); void mergeFaces(LLDrawable* src); void init(); @@ -138,6 +140,8 @@ public: BOOL isActive() const { return isState(ACTIVE); } BOOL isStatic() const { return !isActive(); } + BOOL isAnimating() const; + virtual BOOL updateMove(); virtual void movePartition(); @@ -146,6 +150,7 @@ public: virtual void updateDistance(LLCamera& camera); BOOL updateGeometry(BOOL priority); BOOL updateLighting(BOOL priority); + void updateFaceSize(S32 idx); void updateLightSet(); F32 getSunShadowFactor() const { return mSunShadowFactor; } @@ -195,6 +200,7 @@ public: protected: virtual ~LLDrawable() { destroy(); } void moveUpdatePipeline(BOOL moved); + void updatePartition(); BOOL updateMoveDamped(); BOOL updateMoveUndamped(); @@ -206,6 +212,7 @@ public: typedef std::set > drawable_set_t; typedef std::vector > drawable_vector_t; typedef std::list > drawable_list_t; + typedef std::queue > drawable_queue_t; struct CompareDistanceGreater { @@ -246,11 +253,14 @@ public: UNLIT = 0x00000200, LIGHT = 0x00000400, LIGHTING_BUILT = 0x00000800, - REBUILD_VOLUME = 0x00001000, - REBUILD_TCOORD = 0x00002000, - REBUILD_GEOMETRY= REBUILD_VOLUME|REBUILD_TCOORD, - REBUILD_LIGHTING= 0x00008000, - REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_LIGHTING, + REBUILD_VOLUME = 0x00001000, //volume changed LOD or parameters, or vertex buffer changed + REBUILD_TCOORD = 0x00002000, //texture coordinates changed + REBUILD_COLOR = 0x00004000, //color changed + REBUILD_LIGHTING= 0x00008000, //lighting information changed + REBUILD_POSITION= 0x00010000, //vertex positions/normals changed + REBUILD_GEOMETRY= REBUILD_POSITION|REBUILD_TCOORD|REBUILD_COLOR, + REBUILD_MATERIAL= REBUILD_TCOORD|REBUILD_COLOR, + REBUILD_ALL = REBUILD_GEOMETRY|REBUILD_LIGHTING|REBUILD_VOLUME, ON_SHIFT_LIST = 0x00100000, // NO_INTERP_COLOR = 0x00200000, BLOCKER = 0x00400000, @@ -285,6 +295,8 @@ public: void setSpatialBridge(LLSpatialBridge* bridge) { mSpatialBridge = (LLDrawable*) bridge; } LLSpatialBridge* getSpatialBridge() { return (LLSpatialBridge*) (LLDrawable*) mSpatialBridge; } + static F32 sCurPixelAngle; //current pixels per radian + protected: typedef std::vector face_list_t; @@ -296,7 +308,7 @@ protected: LLPointer mSpatialBridge; S32 mSpatialGroupOffset; - U32 mVisible; + mutable U32 mVisible; F32 mRadius; LLVector3 mExtents[2]; LLVector3d mPositionGroup; @@ -308,7 +320,6 @@ protected: LLVector3 mCurrentScale; static U32 sCurVisible; // Counter for what value of mVisible means currently visible - static F32 sCurPixelAngle; //current pixels per radian static U32 sNumZombieDrawables; static LLDynamicArrayPtr > sDeadList; @@ -318,6 +329,7 @@ protected: inline LLFace* LLDrawable::getFace(const S32 i) const { llassert((U32)i < mFaces.size()); + llassert(mFaces[i]); return mFaces[i]; } diff --git a/linden/indra/newview/lldrawpool.cpp b/linden/indra/newview/lldrawpool.cpp index 18d6000..dc2e6ba 100644 --- a/linden/indra/newview/lldrawpool.cpp +++ b/linden/indra/newview/lldrawpool.cpp @@ -32,7 +32,6 @@ #include "llfasttimer.h" #include "llviewercontrol.h" -#include "llagparray.h" #include "lldrawable.h" #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" @@ -43,53 +42,38 @@ #include "lldrawpoolsky.h" #include "lldrawpoolstars.h" #include "lldrawpooltree.h" -#include "lldrawpooltreenew.h" #include "lldrawpoolterrain.h" #include "lldrawpoolwater.h" -#include "lldrawpoolhud.h" #include "llface.h" #include "llviewerobjectlist.h" // For debug listing. -#include "llvotreenew.h" #include "pipeline.h" -#include "llagparray.inl" - -U32 LLDrawPool::sDataSizes[LLDrawPool::DATA_MAX_TYPES] = -{ - 12, // DATA_VERTICES - 8, // DATA_TEX_COORDS0 - 8, // DATA_TEX_COORDS1 - 8, // DATA_TEX_COORDS2 - 8, // DATA_TEX_COORDS3 - 12, // DATA_NORMALS - 4, // DATA_VERTEX_WEIGHTS, - 16, // DATA_CLOTHING_WEIGHTS - 12, // DATA_BINORMALS - 4, // DATA_COLORS -}; - S32 LLDrawPool::sNumDrawPools = 0; + +//============================= +// Draw Pool Implementation +//============================= LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) { LLDrawPool *poolp = NULL; switch (type) { case POOL_SIMPLE: - poolp = new LLDrawPoolSimple(tex0); + poolp = new LLDrawPoolSimple(); break; case POOL_ALPHA: poolp = new LLDrawPoolAlpha(); break; + case POOL_ALPHA_POST_WATER: + poolp = new LLDrawPoolAlphaPostWater(); + break; case POOL_AVATAR: poolp = new LLDrawPoolAvatar(); break; case POOL_TREE: poolp = new LLDrawPoolTree(tex0); break; - case POOL_TREE_NEW: - poolp = new LLDrawPoolTreeNew(tex0); - break; case POOL_TERRAIN: poolp = new LLDrawPoolTerrain(tex0); break; @@ -99,9 +83,6 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) case POOL_STARS: poolp = new LLDrawPoolStars(); break; - case POOL_CLOUDS: - poolp = new LLDrawPoolClouds(); - break; case POOL_WATER: poolp = new LLDrawPoolWater(); break; @@ -109,10 +90,7 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) poolp = new LLDrawPoolGround(); break; case POOL_BUMP: - poolp = new LLDrawPoolBump(tex0); - break; - case POOL_HUD: - poolp = new LLDrawPoolHUD(); + poolp = new LLDrawPoolBump(); break; default: llerrs << "Unknown draw pool type!" << llendl; @@ -123,183 +101,86 @@ LLDrawPool *LLDrawPool::createPool(const U32 type, LLViewerImage *tex0) return poolp; } -LLDrawPool::LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil) +LLDrawPool::LLDrawPool(const U32 type) { - llassert(data_mask_il & DATA_VERTICES_MASK); - S32 i; mType = type; sNumDrawPools++; mId = sNumDrawPools; - - mDataMaskIL = data_mask_il; - mDataMaskNIL = data_mask_nil; - - U32 cur_mask = 0x01; - U32 cur_offset = 0; - for (i = 0; i < DATA_MAX_TYPES; i++) - { - mDataOffsets[i] = cur_offset; - if (cur_mask & mDataMaskIL) - { - cur_offset += sDataSizes[i]; - } - cur_mask <<= 1; - } - - mStride = cur_offset; - - mCleanupUnused = FALSE; + mVertexShaderLevel = 0; mIndicesDrawn = 0; - mRebuildFreq = 128 + rand() % 5; - mRebuildTime = 0; - mGeneration = 1; - mSkippedVertices = 0; - - resetDrawOrders(); - resetVertexData(0); - - if (gGLManager.mHasATIVAO && !gGLManager.mIsRadeon9700) - { - // ATI 8500 doesn't like indices > 15 bit. - mMaxVertices = DEFAULT_MAX_VERTICES/2; - } - else - { - mMaxVertices = DEFAULT_MAX_VERTICES; - } +} - // JC: This must happen last, as setUseAGP reads many of the - // above variables. - mUseAGP = FALSE; - setUseAGP(gPipeline.usingAGP()); +LLDrawPool::~LLDrawPool() +{ - for (i=0; i mMaxVertices && use_agp) - { -#ifdef DEBUG_AGP - llwarns << "Allocating " << vertex_count << " vertices in pool type " << getType() << ", disabling AGP!" << llendl -#endif - use_agp = FALSE; - ok = FALSE; - } - - if (mUseAGP != use_agp) - { - mUseAGP = use_agp; - - BOOL ok = TRUE; - ok &= mMemory.setUseAGP(use_agp); - - if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK) - { - ok &= mWeights.setUseAGP(use_agp); - } - if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) - { - ok &= mClothingWeights.setUseAGP(use_agp); - } - - if (!ok) - { - // Disable AGP if any one of these doesn't have AGP, we don't want to try - // mixing AGP and non-agp arrays in a single pool. -#ifdef DEBUG_AGP - llinfos << "Aborting using AGP because set failed on a mem block!" << llendl; -#endif - setUseAGP(FALSE); - ok = FALSE; - } - } - return ok; + glDisableClientState ( GL_TEXTURE_COORD_ARRAY ); + glDisableClientState ( GL_COLOR_ARRAY ); + glDisableClientState ( GL_NORMAL_ARRAY ); } -void LLDrawPool::flushAGP() +U32 LLDrawPool::getTrianglesDrawn() const { - mMemory.flushAGP(); - - if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK) - { - mWeights.flushAGP(); - } - if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) - { - mClothingWeights.flushAGP(); - } + return mIndicesDrawn / 3; } -void LLDrawPool::syncAGP() +void LLDrawPool::resetTrianglesDrawn() { - if (!getVertexCount()) - { - return; - } - setUseAGP(gPipeline.usingAGP()); + mIndicesDrawn = 0; +} - BOOL all_agp_on = TRUE; - mMemory.sync(); - all_agp_on &= mMemory.isAGP(); +void LLDrawPool::addIndicesDrawn(const U32 indices) +{ + mIndicesDrawn += indices; +} - if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK) - { - mWeights.sync(); - all_agp_on &= mWeights.isAGP(); - } +//============================= +// Face Pool Implementation +//============================= +LLFacePool::LLFacePool(const U32 type) +: LLDrawPool(type) +{ + resetDrawOrders(); +} - if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) - { - mClothingWeights.sync(); - all_agp_on &= mClothingWeights.isAGP(); - } +LLFacePool::~LLFacePool() +{ + destroy(); +} - // Since sometimes AGP allocation is done during syncs, we need - // to make sure that if AGP allocation fails, we fallback to non-agp. - if (mUseAGP && !all_agp_on) +void LLFacePool::destroy() +{ + if (!mReferences.empty()) { -#ifdef DEBUG_AGP - llinfos << "setUseAGP false because of AGP sync failure!" << llendl; -#endif - setUseAGP(FALSE); + llinfos << mReferences.size() << " references left on deletion of draw pool!" << llendl; } } -void LLDrawPool::dirtyTexture(const LLViewerImage *imagep) +void LLFacePool::dirtyTextures(const std::set& textures) { } -BOOL LLDrawPool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) +BOOL LLFacePool::moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data) { return TRUE; } // static -S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array) +S32 LLFacePool::drawLoop(face_array_t& face_list) { S32 res = 0; if (!face_list.empty()) @@ -308,19 +189,15 @@ S32 LLDrawPool::drawLoop(face_array_t& face_list, const U32* index_array) iter != face_list.end(); iter++) { LLFace *facep = *iter; - if (facep->mSkipRender) - { - continue; - } - facep->enableLights(); - res += facep->renderIndexed(index_array); + //facep->enableLights(); + res += facep->renderIndexed(); } } return res; } // static -S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage) +S32 LLFacePool::drawLoopSetTex(face_array_t& face_list, S32 stage) { S32 res = 0; if (!face_list.empty()) @@ -329,117 +206,30 @@ S32 LLDrawPool::drawLoopSetTex(face_array_t& face_list, const U32* index_array, iter != face_list.end(); iter++) { LLFace *facep = *iter; - if (facep->mSkipRender) - { - continue; - } facep->bindTexture(stage); facep->enableLights(); - res += facep->renderIndexed(index_array); + res += facep->renderIndexed(); } } return res; } -void LLDrawPool::drawLoop() +void LLFacePool::drawLoop() { - const U32* index_array = getRawIndices(); if (!mDrawFace.empty()) { - mIndicesDrawn += drawLoop(mDrawFace, index_array); + mIndicesDrawn += drawLoop(mDrawFace); } } -BOOL LLDrawPool::getVertexStrider(LLStrider &vertices, const U32 index) -{ - llassert(mDataMaskIL & LLDrawPool::DATA_VERTICES_MASK); - vertices = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride); - vertices.setStride(mStride); - return TRUE; -} - -BOOL LLDrawPool::getTexCoordStrider(LLStrider &tex_coords, const U32 index, const U32 pass) -{ - llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass)); - tex_coords = (LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride); - tex_coords.setStride(mStride); - return TRUE; -} - - -BOOL LLDrawPool::getVertexWeightStrider(LLStrider &vertex_weights, const U32 index) -{ - llassert(mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK); - - vertex_weights = &mWeights[index]; - vertex_weights.setStride( 0 ); - return TRUE; -} - -BOOL LLDrawPool::getClothingWeightStrider(LLStrider &clothing_weights, const U32 index) -{ - llassert(mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK); - - clothing_weights= &mClothingWeights[index]; - clothing_weights.setStride( 0 ); - - return TRUE; -} - -BOOL LLDrawPool::getNormalStrider(LLStrider &normals, const U32 index) -{ - llassert((mDataMaskIL) & LLDrawPool::DATA_NORMALS_MASK); - - normals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride); - - normals.setStride( mStride ); - - return TRUE; -} - - -BOOL LLDrawPool::getBinormalStrider(LLStrider &binormals, const U32 index) -{ - llassert((mDataMaskIL) & LLDrawPool::DATA_BINORMALS_MASK); - - binormals = (LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride); - - binormals.setStride( mStride ); - - return TRUE; -} - -BOOL LLDrawPool::getColorStrider(LLStrider &colors, const U32 index) -{ - llassert((mDataMaskIL) & LLDrawPool::DATA_COLORS_MASK); - - colors = (LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride); - - colors.setStride( mStride ); - - return TRUE; -} - -//virtual -void LLDrawPool::beginRenderPass( S32 pass ) -{ -} - -//virtual -void LLDrawPool::endRenderPass( S32 pass ) -{ - glDisableClientState ( GL_TEXTURE_COORD_ARRAY ); - glDisableClientState ( GL_COLOR_ARRAY ); - glDisableClientState ( GL_NORMAL_ARRAY ); -} -void LLDrawPool::renderFaceSelected(LLFace *facep, +void LLFacePool::renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color, const S32 index_offset, const S32 index_count) { } -void LLDrawPool::renderVisibility() +void LLFacePool::renderVisibility() { if (mDrawFace.empty()) { @@ -525,893 +315,284 @@ void LLDrawPool::renderVisibility() } -void LLDrawPool::enqueue(LLFace* facep) +void LLFacePool::enqueue(LLFace* facep) { - if (facep->isState(LLFace::BACKLIST)) - { - mMoveFace.put(facep); - } - else - { -#if ENABLE_FACE_LINKING - facep->mSkipRender = FALSE; - facep->mNextFace = NULL; - - if (mDrawFace.size() > 0) - { - LLFace* last_face = mDrawFace[mDrawFace.size()-1]; - if (match(last_face, facep)) - { - last_face->link(facep); - } - } -#endif - mDrawFace.put(facep); - } + mDrawFace.push_back(facep); } -void LLDrawPool::bindGLVertexPointer() +// virtual +BOOL LLFacePool::addFace(LLFace *facep) { - mMemory.bindGLVertexPointer(getStride(DATA_VERTICES), mDataOffsets[DATA_VERTICES]); + addFaceReference(facep); + return TRUE; } -void LLDrawPool::bindGLTexCoordPointer(const U32 pass) +// virtual +BOOL LLFacePool::removeFace(LLFace *facep) { - mMemory.bindGLTexCoordPointer(getStride(DATA_TEX_COORDS0+pass), mDataOffsets[DATA_TEX_COORDS0+pass]); -} + removeFaceReference(facep); -void LLDrawPool::bindGLNormalPointer() -{ - mMemory.bindGLNormalPointer(getStride(DATA_NORMALS), mDataOffsets[DATA_NORMALS]); -} + vector_replace_with_last(mDrawFace, facep); -void LLDrawPool::bindGLBinormalPointer(S32 index) -{ - mMemory.bindGLBinormalPointer(index, getStride(DATA_BINORMALS), mDataOffsets[DATA_BINORMALS]); + return TRUE; } -void LLDrawPool::bindGLColorPointer() +// Not absolutely sure if we should be resetting all of the chained pools as well - djs +void LLFacePool::resetDrawOrders() { - mMemory.bindGLColorPointer(getStride(DATA_COLORS), mDataOffsets[DATA_COLORS]); + mDrawFace.resize(0); } -void LLDrawPool::bindGLVertexWeightPointer(S32 index) +LLViewerImage *LLFacePool::getTexture() { - mWeights.bindGLVertexWeightPointer(index, 0, 0); + return NULL; } -void LLDrawPool::bindGLVertexClothingWeightPointer(S32 index) +void LLFacePool::removeFaceReference(LLFace *facep) { - mClothingWeights.bindGLVertexClothingWeightPointer(index, 0, 0); + if (facep->getReferenceIndex() != -1) + { + if (facep->getReferenceIndex() != (S32)mReferences.size()) + { + LLFace *back = mReferences.back(); + mReferences[facep->getReferenceIndex()] = back; + back->setReferenceIndex(facep->getReferenceIndex()); + } + mReferences.pop_back(); + } + facep->setReferenceIndex(-1); } - -U32* LLDrawPool::getIndices(S32 index) +void LLFacePool::addFaceReference(LLFace *facep) { - return &mIndices[index]; + if (-1 == facep->getReferenceIndex()) + { + facep->setReferenceIndex(mReferences.size()); + mReferences.push_back(facep); + } } -const LLVector3& LLDrawPool::getVertex(const S32 index) +BOOL LLFacePool::verify() const { - llassert(mDataMaskIL & DATA_VERTICES_MASK); - llassert(index < mMemory.count()); - llassert(mMemory.getMem()); - return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_VERTICES] + index * mStride); -} + BOOL ok = TRUE; + + for (std::vector::const_iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + const LLFace* facep = *iter; + if (facep->getPool() != this) + { + llinfos << "Face in wrong pool!" << llendl; + facep->printDebugInfo(); + ok = FALSE; + } + else if (!facep->verify()) + { + ok = FALSE; + } + } -const LLVector2& LLDrawPool::getTexCoord(const S32 index, const U32 pass) -{ - llassert(mDataMaskIL & (LLDrawPool::DATA_TEX_COORDS0_MASK << pass)); - llassert(index < mMemory.count()); - return *(LLVector2*)(mMemory.getMem() + mDataOffsets[DATA_TEX_COORDS0 + pass] + index * mStride); + return ok; } -const LLVector3& LLDrawPool::getNormal(const S32 index) +void LLFacePool::printDebugInfo() const { - llassert(mDataMaskIL & DATA_NORMALS_MASK); - llassert(index < mMemory.count()); - return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_NORMALS] + index * mStride); + llinfos << "Pool " << this << " Type: " << getType() << llendl; } -const LLVector3& LLDrawPool::getBinormal(const S32 index) +BOOL LLFacePool::LLOverrideFaceColor::sOverrideFaceColor = FALSE; + +void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4& color) { - llassert(mDataMaskIL & DATA_BINORMALS_MASK); - llassert(index < mMemory.count()); - return *(LLVector3*)(mMemory.getMem() + mDataOffsets[DATA_BINORMALS] + index * mStride); + if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0) + { + glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV); + } + else + { + glColor4fv(color.mV); + } } -const LLColor4U& LLDrawPool::getColor(const S32 index) +void LLFacePool::LLOverrideFaceColor::setColor(const LLColor4U& color) { - llassert(mDataMaskIL & DATA_COLORS_MASK); - llassert(index < mMemory.count()); - return *(LLColor4U*)(mMemory.getMem() + mDataOffsets[DATA_COLORS] + index * mStride); + if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0) + { + glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV); + } + else + { + glColor4ubv(color.mV); + } } -const F32& LLDrawPool::getVertexWeight(const S32 index) +void LLFacePool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) { - llassert(mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK); - llassert(index < mWeights.count()); - llassert(mWeights.getMem()); - return mWeights[index]; + if (mPool->getVertexShaderLevel() > 0 && mPool->getMaterialAttribIndex() > 0) + { + glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a); + } + else + { + glColor4f(r,g,b,a); + } } -const LLVector4& LLDrawPool::getClothingWeight(const S32 index) + +//============================= +// Render Pass Implementation +//============================= +LLRenderPass::LLRenderPass(const U32 type) +: LLDrawPool(type) { - llassert(mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK); - llassert(index < mClothingWeights.count()); - llassert(mClothingWeights.getMem()); - return mClothingWeights[index]; + } -////////////////////////////////////////////////////////////////////////////// +LLRenderPass::~LLRenderPass() +{ -#define USE_FREE_LIST 0 -#define DEBUG_FREELIST 0 +} -struct tFreeListNode +LLDrawPool* LLRenderPass::instancePool() { - U32 count; - S32 next; -}; +#if LL_RELEASE_FOR_DOWNLOAD + llwarns << "Attempting to instance a render pass. Invalid operation." << llendl; +#else + llerrs << "Attempting to instance a render pass. Invalid operation." << llendl; +#endif + return NULL; +} -#if DEBUG_FREELIST -static void check_list(U8 *pool, S32 stride, S32 head, S32 max) -{ - int count = 0; +void LLRenderPass::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) +{ + std::vector& draw_info = group->mDrawMap[type]; - while (head >= 0) + for (std::vector::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - tFreeListNode *node = (tFreeListNode *)(pool + head*stride); - count++; - if ((count > max) || ((node->count>>20) != 0xabc) || ((node->count&0xfffff) < 2)) - llerrs << "Bad Ind List" << llendl; - head = node->next; + LLDrawInfo& params = **k; + pushBatch(params, mask, texture); } } -#define CHECK_LIST(x) check_list##x -#else -#define CHECK_LIST(x) -#endif -// DEBUG! -void LLDrawPool::CheckIntegrity() +void LLRenderPass::renderInvisible(U32 mask) { -#if DEBUG_FREELIST - int bucket; - for (bucket=0; bucket& draw_info = gPipeline.mRenderMap[LLRenderPass::PASS_INVISIBLE]; + + U32* indices_pointer = NULL; + for (std::vector::iterator i = draw_info.begin(); i != draw_info.end(); ++i) { - CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[bucket], mMemory.count() / mStride)); - CHECK_LIST(((U8 *)mIndices.getMem(), 4, mFreeListIndHead[bucket], mIndices.count())); + LLDrawInfo& params = **i; + params.mVertexBuffer->setBuffer(mask); + indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + gPipeline.mTrianglesDrawn += params.mCount/3; } -#endif } -int LLDrawPool::freeListBucket(U32 count) +void LLRenderPass::renderTexture(U32 type, U32 mask) { - int bucket; +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif - // llassert(NUM_BUCKETS == 8) - - if (count & ~511) // >= 512 - bucket = 7; - else if (count & 256) // 256-511 - bucket = 6; - else if (count & 128) - bucket = 5; - else if (count & 64) - bucket = 4; - else if (count & 32) - bucket = 3; - else if (count & 16) - bucket = 2; - else if (count & 8) // 8-15 - bucket = 1; - else // 0-7 - bucket = 0; - return bucket; -} + std::vector& draw_info = gPipeline.mRenderMap[type]; -void remove_node(int nodeidx, int pidx, U8 *membase, int stride, int *head) -{ - LLDrawPool::FreeListNode *node = (LLDrawPool::FreeListNode *)(membase + nodeidx*stride); - if (pidx >= 0) - { - LLDrawPool::FreeListNode *pnode = (LLDrawPool::FreeListNode *)(membase + pidx*stride); - pnode->next = node->next; - } - else + for (std::vector::iterator i = draw_info.begin(); i != draw_info.end(); ++i) { - *head = node->next; + LLDrawInfo& params = **i; + pushBatch(params, mask, TRUE); } } -void LLDrawPool::freeListAddGeom(S32 index, U32 count) +void LLRenderPass::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { -#if USE_FREE_LIST - int i; - U8 *membase = (U8*)mMemory.getMem(); - // See if next block or previous block is free, if so combine them - for (i=0; i= 0) - { - int change = 0; - FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride); - int nodecount = node->count & 0xffff; - // Check for prev block - if (nodeidx + nodecount == index) - { - remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]); - // Combine nodes - index = nodeidx; - count += nodecount; - i = 0; // start over ; i = NUM_BUCKETS // done - change = 1; - //break; - } - // Check for next block - if (nodeidx == index + count) - { - remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]); - // Combine nodes - count += nodecount; - i = 0; // start over ; i = NUM_BUCKETS // done - change = 1; - //break; - } - if (change) - break; - pidx = nodeidx; - nodeidx = node->next; - } - } - // Add (extended) block to free list - if (count >= 2) // need 2 words to store free list (theoreticly mStride could = 4) - { - CheckIntegrity(); - if ((index + count)*mStride >= mMemory.count()) - { - mMemory.shrinkTo(index*mStride); - } - else - { - int bucket = freeListBucket(count); - FreeListNode *node = (FreeListNode *)(membase + index*mStride); - node->count = count | (0xabc<<20); - node->next = mFreeListGeomHead[bucket]; - mFreeListGeomHead[bucket] = index; - } - CheckIntegrity(); + return; } -#endif -} -void LLDrawPool::freeListAddInd(S32 index, U32 count) -{ -#if USE_FREE_LIST - int i; - const U32 *membase = mIndices.getMem(); - // See if next block or previous block is free, if so combine them - for (i=0; i= 0) + if (params.mTexture.notNull()) { - int change = 0; - FreeListNode *node = (FreeListNode *)(membase + nodeidx); - int nodecount = node->count & 0xffff; - // Check for prev block - if (nodeidx + nodecount == index) - { - remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]); - // Combine nodes - index = nodeidx; - count += nodecount; - i = 0; // start over ; i = NUM_BUCKETS // done - change = 1; - //break; - } - // Check for next block - if (nodeidx == index + count) + params.mTexture->bind(); + if (params.mTextureMatrix) { - remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]); - // Combine nodes - count += nodecount; - i = 0; // start over ; i = NUM_BUCKETS // done - change = 1; - //break; + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); } - if (change) - break; - pidx = nodeidx; - nodeidx = node->next; - } - } - // Add (extended) block to free list - if (count >= 2) // need 2 words to store free list - { - CheckIntegrity(); - if (index + count >= mIndices.count()) - { - mIndices.shrinkTo(index); + params.mTexture->addTextureStats(params.mVSize); } else { - int bucket = freeListBucket(count); - FreeListNode *node = (FreeListNode *)(membase + index); - node->count = count | (0xabc<<20); - node->next = mFreeListIndHead[bucket]; - mFreeListIndHead[bucket] = index; - } - CheckIntegrity(); - } -#endif -} - -S32 LLDrawPool::freeListFindGeom(U32 count) -{ -#if USE_FREE_LIST - int i, nodeidx, pidx; - int firstbucket = freeListBucket(count); - U8 *membase = (U8*)mMemory.getMem(); - for (i=firstbucket; i= 0) - { - FreeListNode *node = (FreeListNode *)(membase + nodeidx*mStride); - int nodecount = node->count & 0xffff; - llassert((node->count>>20) == 0xabc); - if (nodecount >= count) - { - remove_node(nodeidx, pidx, membase, mStride, &mFreeListGeomHead[i]); -#if 1 - if (nodecount > count) - { - int leftover = nodecount - count; - freeListAddGeom(nodeidx + count, leftover); - } -#endif - return nodeidx; - } - pidx = nodeidx; - nodeidx = node->next; - } - } -#endif // USE_FREE_LIST - return -1; -} - -S32 LLDrawPool::freeListFindInd(U32 count) -{ -#if USE_FREE_LIST - int i, nodeidx, pidx; - int firstbucket = freeListBucket(count); - U32 *membase = (U32 *)mIndices.getMem(); - for (i=firstbucket; i= 0) - { - FreeListNode *node = (FreeListNode *)(membase + nodeidx); - int nodecount = node->count & 0xffff; - llassert((node->count>>20) == 0xabc); - if (nodecount >= count) - { - remove_node(nodeidx, pidx, (U8*)membase, 4, &mFreeListIndHead[i]); -#if 1 - if (nodecount > count) - { - int leftover = nodecount - count; - freeListAddInd(nodeidx + count, leftover); - } -#endif - return nodeidx; - } - pidx = nodeidx; - nodeidx = node->next; + LLImageGL::unbindTexture(0); } } -#endif // USE_FREE_LIST - return -1; -} - -////////////////////////////////////////////////////////////////////////////// - -S32 LLDrawPool::reserveGeom(const U32 geom_count) -{ - LLFastTimer t(LLFastTimer::FTM_GEO_RESERVE); - S32 index; - index = freeListFindGeom(geom_count); - if (index < 0) - { - index = mMemory.count() / mStride; - if (!geom_count) - { - llwarns << "Attempting to reserve zero bytes!" << llendl; - return index; - } - - S32 bytes = geom_count * mStride; - - if ((index + (S32)geom_count) > (S32)mMaxVertices) - { - // - // Various drivers have issues with the number of indices being greater than a certain number. - // if you're using AGP. Disable AGP if we've got more vertices than in the pool. - // -#ifdef DEBUG_AGP - llinfos << "setUseAGP false because of large vertex count in reserveGeom" << llendl; -#endif - setUseAGP(FALSE); - } - - mMemory.reserve_block(bytes); - if (mDataMaskNIL & DATA_VERTEX_WEIGHTS_MASK) - { - mWeights.reserve_block(geom_count); - } - if (mDataMaskNIL & DATA_CLOTHING_WEIGHTS_MASK) - { - mClothingWeights.reserve_block(geom_count); - } - } - CHECK_LIST(((U8 *)mMemory.getMem(), mStride, mFreeListGeomHead[0], mMemory.count() / mStride)); - return index; -} - -S32 LLDrawPool::reserveInd(U32 indCount) -{ - S32 index; - index = freeListFindInd(indCount); - if (index < 0) - { - index = mIndices.count(); - - if (indCount) - { - mIndices.reserve_block(indCount); - } - } - for (U32 i=0;isetBuffer(mask); + U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + gPipeline.mTrianglesDrawn += params.mCount/3; - freeListAddGeom(index, count); - -#if 0 - int i; - S32 bytes,words; - U32 *memp; - // Fill mem with bad data (for testing only) - bytes = count * mStride; - bytes -= sizeof(FreeListNode); - memp = (U32*)(mMemory.getMem() + index * mStride); - memp += sizeof(FreeListNode)>>2; - words = bytes >> 2; - for (i=0; iunReserve(); - - return TRUE; -} - -// Not absolutely sure if we should be resetting all of the chained pools as well - djs -void LLDrawPool::resetDrawOrders() -{ - mDrawFace.resize(0); -} -void LLDrawPool::resetIndices(S32 indices_count) -{ - mIndices.reset(indices_count); - for (S32 i=0; i 0.75f*DEFAULT_MAX_VERTICES) + LLSpatialGroup* group = *i; + if (!group->isDead() && + gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) { - if (mRebuildTime > 8) - { - needs_rebuild = TRUE; - } -#ifdef DEBUG_AGP - llwarns << "More than " << DEFAULT_MAX_VERTICES << " in pool type " << (S32)mType << " at rebuild!" << llendl; -#endif - } - } - - // rebuild de-allocates 'stale' objects, so we still need to do a rebuild periodically - if (mRebuildFreq > 0 && mRebuildTime >= mRebuildFreq) - { - needs_rebuild = TRUE; - } - - if (needs_rebuild) - { - mGeneration++; - - if (mReferences.empty()) - { - resetIndices(0); - resetVertexData(0); - } - else - { - for (std::vector::iterator iter = mReferences.begin(); - iter != mReferences.end(); iter++) - { - LLFace *facep = *iter; - if (facep->hasGeometry() && !facep->isState(LLFace::BACKLIST | LLFace::SHARED_GEOM)) - { - facep->backup(); - } - } - S32 tot_verts = 0; - S32 tot_indices = 0; - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) + LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition; + if (bridge != last_bridge) { - LLFace *facep = *iter; - if (facep->isState(LLFace::BACKLIST)) - { - tot_verts += facep->getGeomCount(); - tot_indices += facep->getIndicesCount(); - } + glPopMatrix(); + glPushMatrix(); + glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); + last_bridge = bridge; } - for (std::vector::iterator iter = mMoveFace.begin(); - iter != mMoveFace.end(); iter++) - { - LLFace *facep = *iter; - if (facep->isState(LLFace::BACKLIST)) - { - tot_verts += facep->getGeomCount(); - tot_indices += facep->getIndicesCount(); - } - } - - resetIndices(tot_indices); - flushAGP(); - resetVertexData(tot_verts); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - llassert(facep->getPool() == this); - facep->restore(); - } - } - mRebuildTime = 0; - setDirty(); - } - - if (!mMoveFace.empty()) - { - for (std::vector::iterator iter = mMoveFace.begin(); - iter != mMoveFace.end(); iter++) - { - LLFace *facep = *iter; - facep->restore(); - enqueue(facep); - } - setDirty(); - mMoveFace.reset(); - rebuild_cost++; - } - return rebuild_cost; -} - -LLViewerImage *LLDrawPool::getTexture() -{ - return NULL; -} - -LLViewerImage *LLDrawPool::getDebugTexture() -{ - return NULL; -} -void LLDrawPool::removeFaceReference(LLFace *facep) -{ - if (facep->getReferenceIndex() != -1) - { - if (facep->getReferenceIndex() != (S32)mReferences.size()) - { - LLFace *back = mReferences.back(); - mReferences[facep->getReferenceIndex()] = back; - back->setReferenceIndex(facep->getReferenceIndex()); + renderGroup(group,type,mask,texture); } - mReferences.pop_back(); - } - facep->setReferenceIndex(-1); -} - -void LLDrawPool::addFaceReference(LLFace *facep) -{ - if (-1 == facep->getReferenceIndex()) - { - facep->setReferenceIndex(mReferences.size()); - mReferences.push_back(facep); } + + glPopMatrix(); } -U32 LLDrawPool::getTrianglesDrawn() const -{ - return mIndicesDrawn / 3; -} - -void LLDrawPool::resetTrianglesDrawn() -{ - mIndicesDrawn = 0; -} - -void LLDrawPool::addIndicesDrawn(const U32 indices) -{ - mIndicesDrawn += indices; -} - -BOOL LLDrawPool::verify() const +void LLRenderPass::renderStatic(U32 type, U32 mask, BOOL texture) { - BOOL ok = TRUE; - // Verify all indices in the pool are in the right range - const U32 *indicesp = getRawIndices(); - for (U32 i = 0; i < getIndexCount(); i++) - { - if (indicesp[i] > getVertexCount()) - { - ok = FALSE; - llinfos << "Bad index in tree pool!" << llendl; - } - } +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif - for (std::vector::const_iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) + for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mVisibleGroups.begin(); i != gPipeline.mVisibleGroups.end(); ++i) { - const LLFace* facep = *iter; - if (facep->getPool() != this) + LLSpatialGroup* group = *i; + if (!group->isDead() && + gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) { - llinfos << "Face in wrong pool!" << llendl; - facep->printDebugInfo(); - ok = FALSE; - } - else if (!facep->verify()) - { - ok = FALSE; + renderGroup(group,type,mask,texture); } } - - return ok; -} - -void LLDrawPool::printDebugInfo() const -{ - llinfos << "Pool " << this << " Type: " << getType() << llendl; - llinfos << "--------------------" << llendl; - llinfos << "Vertex count: " << getVertexCount() << llendl; - llinfos << "Normal count: " << getNormalCount() << llendl; - llinfos << "Indices count: " << getIndexCount() << llendl; - llinfos << llendl; -} - - -S32 LLDrawPool::getMemUsage(const BOOL print) -{ - S32 mem_usage = 0; - - mem_usage += sizeof(this); - - // Usage beyond the pipeline allocated data (color and mMemory) - mem_usage += mIndices.getMax() * sizeof(U32); - mem_usage += mDrawFace.capacity() * sizeof(LLFace *); - mem_usage += mMoveFace.capacity() * sizeof(LLFace *); - mem_usage += mReferences.capacity() * sizeof(LLFace *); - - mem_usage += mMemory.getSysMemUsage(); - mem_usage += mWeights.getSysMemUsage(); - mem_usage += mClothingWeights.getSysMemUsage(); - - return mem_usage; -} - -LLColor3 LLDrawPool::getDebugColor() const -{ - return LLColor3(0.f, 0.f, 0.f); -} - -void LLDrawPool::setDirty() -{ - mMemory.setDirty(); - mWeights.setDirty(); - mClothingWeights.setDirty(); } - -BOOL LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor = FALSE; - -void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4& color) -{ - if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0) - { - glVertexAttrib4fvARB(mPool->getMaterialAttribIndex(), color.mV); - } - else - { - glColor4fv(color.mV); - } -} - -void LLDrawPool::LLOverrideFaceColor::setColor(const LLColor4U& color) -{ - if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0) - { - glVertexAttrib4ubvARB(mPool->getMaterialAttribIndex(), color.mV); - } - else - { - glColor4ubv(color.mV); - } -} - -void LLDrawPool::LLOverrideFaceColor::setColor(F32 r, F32 g, F32 b, F32 a) -{ - if (mPool->mVertexShaderLevel > 0 && mPool->getMaterialAttribIndex() > 0) - { - glVertexAttrib4fARB(mPool->getMaterialAttribIndex(), r,g,b,a); - } - else - { - glColor4f(r,g,b,a); - } -} - -// virtual -void LLDrawPool::enableShade() -{ } - -// virtual -void LLDrawPool::disableShade() -{ } - -// virtual -void LLDrawPool::setShade(F32 shade) -{ } diff --git a/linden/indra/newview/lldrawpool.h b/linden/indra/newview/lldrawpool.h index 2ce13fb..6cd5f8e 100644 --- a/linden/indra/newview/lldrawpool.h +++ b/linden/indra/newview/lldrawpool.h @@ -28,270 +28,168 @@ #ifndef LL_LLDRAWPOOL_H #define LL_LLDRAWPOOL_H -#include "llagparray.h" -#include "lldarray.h" -#include "lldlinked.h" -#include "llstrider.h" -#include "llviewerimage.h" #include "v4coloru.h" #include "v2math.h" #include "v3math.h" -#include "llstrider.h" +#include "llvertexbuffer.h" class LLFace; class LLImageGL; class LLViewerImage; +class LLSpatialGroup; +class LLDrawInfo; #define DEFAULT_MAX_VERTICES 65535 class LLDrawPool { public: - typedef LLDynamicArray face_array_t; - + static S32 sNumDrawPools; + enum { - SHADER_LEVEL_SCATTERING = 2 + // Correspond to LLPipeline render type + POOL_SKY = 1, + POOL_STARS, + POOL_GROUND, + POOL_TERRAIN, + POOL_SIMPLE, + POOL_BUMP, + POOL_AVATAR, + POOL_TREE, + POOL_ALPHA, + POOL_WATER, + POOL_ALPHA_POST_WATER, + NUM_POOL_TYPES, }; - -public: - LLDrawPool(const U32 type, const U32 data_mask_il, const U32 data_mask_nil); + + LLDrawPool(const U32 type); virtual ~LLDrawPool(); - static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL); + virtual BOOL isDead() = 0; - void flushAGP(); // Flush the AGP buffers so they can be repacked and reallocated. - void syncAGP(); + S32 getId() const { return mId; } + U32 getType() const { return mType; } - virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool. + virtual LLViewerImage *getDebugTexture(); virtual void beginRenderPass( S32 pass ); virtual void endRenderPass( S32 pass ); virtual S32 getNumPasses() { return 1; } virtual void render(S32 pass = 0) = 0; + virtual void prerender() = 0; + virtual S32 getMaterialAttribIndex() = 0; + virtual U32 getVertexDataMask() = 0; + virtual BOOL verify() const { return TRUE; } // Verify that all data in the draw pool is correct! + virtual S32 getVertexShaderLevel() const { return mVertexShaderLevel; } + + static LLDrawPool* createPool(const U32 type, LLViewerImage *tex0 = NULL); + virtual LLDrawPool *instancePool() = 0; // Create an empty new instance of the pool. + virtual LLViewerImage* getTexture() = 0; + virtual BOOL isFacePool() { return FALSE; } + virtual void resetDrawOrders() = 0; + + U32 getTrianglesDrawn() const; + void resetTrianglesDrawn(); + void addIndicesDrawn(const U32 indices); + +protected: + S32 mVertexShaderLevel; + S32 mId; + U32 mType; // Type of draw pool + S32 mIndicesDrawn; +}; + +class LLRenderPass : public LLDrawPool +{ +public: + enum + { + PASS_SIMPLE = NUM_POOL_TYPES, + PASS_FULLBRIGHT, + PASS_GLOW, + PASS_INVISIBLE, + PASS_SHINY, + PASS_BUMP, + PASS_GRASS, + PASS_ALPHA, + NUM_RENDER_TYPES, + }; + + LLRenderPass(const U32 type); + virtual ~LLRenderPass(); + /*virtual*/ LLDrawPool* instancePool(); + /*vritual*/ S32 getMaterialAttribIndex() { return -1; } + /*virtual*/ LLViewerImage* getDebugTexture() { return NULL; } + LLViewerImage* getTexture() { return NULL; } + BOOL isDead() { return FALSE; } + void resetDrawOrders() { } + + virtual void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + virtual void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); + virtual void renderStatic(U32 type, U32 mask, BOOL texture = TRUE); + virtual void renderActive(U32 type, U32 mask, BOOL texture = TRUE); + virtual void renderInvisible(U32 mask); + virtual void renderTexture(U32 type, U32 mask); + +}; + +class LLFacePool : public LLDrawPool +{ +public: + typedef std::vector face_array_t; + + enum + { + SHADER_LEVEL_SCATTERING = 2 + }; + +public: + LLFacePool(const U32 type); + virtual ~LLFacePool(); + virtual void renderForSelect() = 0; - virtual BOOL match(LLFace* last_face, LLFace* facep) { return FALSE; } + BOOL isDead() { return mReferences.empty(); } virtual void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color, const S32 index_offset = 0, const S32 index_count = 0); - virtual void prerender() = 0; - virtual S32 rebuild(); - - virtual S32 getMaterialAttribIndex() = 0; - virtual LLViewerImage *getTexture(); - virtual LLViewerImage *getDebugTexture(); - virtual void dirtyTexture(const LLViewerImage* texturep); + virtual void dirtyTextures(const std::set& textures); virtual void enqueue(LLFace *face); virtual BOOL addFace(LLFace *face); virtual BOOL removeFace(LLFace *face); virtual BOOL verify() const; // Verify that all data in the draw pool is correct! - virtual LLColor3 getDebugColor() const; // For AGP debug display - + virtual void resetDrawOrders(); - virtual void resetVertexData(S32 reserve_count); - virtual void resetIndices(S32 num_indices); void resetAll(); BOOL moveFace(LLFace *face, LLDrawPool *poolp, BOOL copy_data = FALSE); - - S32 getId() const { return mId; } - U32 getType() const { return mType; } - - const U32 getStride() const; - inline const U32 getStride(const U32 data_type) const; - inline const U32 getOffset(const U32 data_type) const; - - S32 reserveGeom(U32 count); - S32 reserveInd (U32 count); - S32 unReserveGeom(const S32 index, const U32 count); - S32 unReserveInd(const S32 index, const U32 count); - - void bindGLVertexPointer(); - void bindGLTexCoordPointer(const U32 pass=0); - void bindGLNormalPointer(); - void bindGLBinormalPointer(S32 index); - void bindGLColorPointer(); - void bindGLVertexWeightPointer(S32 index); - void bindGLVertexClothingWeightPointer(S32 index); - - const U32 getIndexCount() const; - const U32 getTexCoordCount(const U32 pass=0) const; - const U32 getVertexCount() const; - const U32 getNormalCount() const; - const U32 getBinormalCount() const; - const U32 getColorCount() const; - const U32 getVertexWeightCount() const; - - void setDirty(); - void setDirtyMemory() { mMemory.setDirty(); } - void setDirtyWeights() { mWeights.setDirty(); } - - const U32* getRawIndices() const { return mIndices.getMem(); } - - U32 getIndex(const S32 index) { return mIndices[index]; } // Use to get one index - U32 *getIndices(const S32 index); // Used to get an array of indices for reading/writing - void CheckIntegrity(); // DEBUG - - const LLVector3& getVertex(const S32 index); - const LLVector2& getTexCoord(const S32 index, const U32 pass); - const LLVector3& getNormal(const S32 index); - const LLVector3& getBinormal(const S32 index); - const LLColor4U& getColor(const S32 index); - const F32& getVertexWeight(const S32 index); - const LLVector4& getClothingWeight(const S32 index); - - void setRebuild(const BOOL rebuild); - void destroy(); void buildEdges(); - static S32 drawLoop(face_array_t& face_list, const U32* index_array); - static S32 drawLoopSetTex(face_array_t& face_list, const U32* index_array, S32 stage); + static S32 drawLoop(face_array_t& face_list); + static S32 drawLoopSetTex(face_array_t& face_list, S32 stage); void drawLoop(); void renderVisibility(); void addFaceReference(LLFace *facep); void removeFaceReference(LLFace *facep); - U32 getTrianglesDrawn() const; - void resetTrianglesDrawn(); - void addIndicesDrawn(const U32 indices); void printDebugInfo() const; - S32 getMemUsage(const BOOL print = FALSE); - BOOL setUseAGP(BOOL use_agp); - BOOL canUseAGP() const { return mMemory.isAGP(); } // Return TRUE if this pool can use AGP + BOOL isFacePool() { return TRUE; } - S32 getMaxVertices() const { return mMaxVertices; } - S32 getVertexShaderLevel() const { return mVertexShaderLevel; } - friend class LLFace; friend class LLPipeline; public: - - enum - { - // Correspond to LLPipeline render type - POOL_SKY = 1, - POOL_STARS, - POOL_GROUND, - POOL_TERRAIN, - POOL_SIMPLE, - POOL_MEDIA, // unused - POOL_BUMP, - POOL_AVATAR, - POOL_TREE, - POOL_TREE_NEW, - POOL_WATER, - POOL_CLOUDS, - POOL_ALPHA, - POOL_HUD, - }; - - - // If you change the order or add params to these, you also need to adjust the sizes in the - // mDataSizes array defined in lldrawpool.cpp - typedef enum e_data_type - { - DATA_VERTICES = 0, - DATA_TEX_COORDS0 = 1, - DATA_TEX_COORDS1 = 2, - DATA_TEX_COORDS2 = 3, - DATA_TEX_COORDS3 = 4, - DATA_NORMALS = 5, - DATA_VERTEX_WEIGHTS = 6, - DATA_CLOTHING_WEIGHTS = 7, - DATA_BINORMALS = 8, - DATA_COLORS = 9, - DATA_MAX_TYPES = 10 - } EDataType; - - typedef enum e_data_mask - { - DATA_VERTICES_MASK = 1 << DATA_VERTICES, - DATA_TEX_COORDS0_MASK = 1 << DATA_TEX_COORDS0, - DATA_TEX_COORDS1_MASK = 1 << DATA_TEX_COORDS1, - DATA_TEX_COORDS2_MASK = 1 << DATA_TEX_COORDS2, - DATA_TEX_COORDS3_MASK = 1 << DATA_TEX_COORDS3, - DATA_NORMALS_MASK = 1 << DATA_NORMALS, - DATA_VERTEX_WEIGHTS_MASK = 1 << DATA_VERTEX_WEIGHTS, - DATA_CLOTHING_WEIGHTS_MASK = 1 << DATA_CLOTHING_WEIGHTS, - DATA_BINORMALS_MASK = 1 << DATA_BINORMALS, - DATA_COLORS_MASK = 1 << DATA_COLORS, - - // Masks for standard types. - // IL for interleaved, NIL for non-interleaved. - DATA_SIMPLE_IL_MASK = DATA_VERTICES_MASK | DATA_TEX_COORDS0_MASK | DATA_NORMALS_MASK, - DATA_SIMPLE_NIL_MASK = 0, - DATA_BUMP_IL_MASK = DATA_SIMPLE_IL_MASK | DATA_BINORMALS_MASK | DATA_TEX_COORDS1_MASK, - } EDataMask; - face_array_t mDrawFace; face_array_t mMoveFace; face_array_t mReferences; - U32 mDataMaskIL; // Interleaved data - U32 mDataMaskNIL; // Non-interleaved data - U32 mDataOffsets[DATA_MAX_TYPES]; - S32 mStride; - - S32 mRebuildFreq; - S32 mRebuildTime; - S32 mGeneration; - - - S32 mSkippedVertices; - - static U32 sDataSizes[DATA_MAX_TYPES]; - static S32 sNumDrawPools; - -protected: - LLAGPArray mMemory; - LLAGPArray mWeights; - LLAGPArray mClothingWeights; - LLAGPArray mIndices; - -public: - - BOOL getVertexStrider (LLStrider &vertices, const U32 index = 0); - BOOL getTexCoordStrider (LLStrider &tex_coords, const U32 index = 0, const U32 pass=0); - BOOL getNormalStrider (LLStrider &normals, const U32 index = 0); - BOOL getBinormalStrider (LLStrider &binormals, const U32 index = 0); - BOOL getColorStrider (LLStrider &colors, const U32 index = 0); - BOOL getVertexWeightStrider(LLStrider &vertex_weights, const U32 index = 0); - BOOL getClothingWeightStrider(LLStrider &clothing_weights, const U32 index = 0); - -public: - enum { NUM_BUCKETS = 8 }; // Need to change freeListBucket() if NUM_BUCKETS changes - struct FreeListNode - { - U32 count; - S32 next; - }; -protected: - int freeListBucket(U32 count); - void freeListAddGeom(S32 index, U32 count); - void freeListAddInd(S32 index, U32 count); - S32 freeListFindGeom(U32 count); - S32 freeListFindInd(U32 count); - -protected: - BOOL mUseAGP; - S32 mVertexShaderLevel; - S32 mId; - U32 mType; // Type of draw pool - S32 mMaxVertices; - S32 mIndicesDrawn; - BOOL mCleanupUnused; // Cleanup unused data when too full - - S32 mFreeListGeomHead[8]; - S32 mFreeListIndHead[8]; - public: class LLOverrideFaceColor { @@ -330,38 +228,6 @@ public: LLDrawPool* mPool; static BOOL sOverrideFaceColor; }; - - virtual void enableShade(); - virtual void disableShade(); - virtual void setShade(F32 shade); - }; -inline const U32 LLDrawPool::getStride() const -{ - return mStride; -} - -inline const U32 LLDrawPool::getOffset(const U32 data_type) const -{ - return mDataOffsets[data_type]; -} - -inline const U32 LLDrawPool::getStride(const U32 data_type) const -{ - if (mDataMaskIL & (1 << data_type)) - { - return mStride; - } - else if (mDataMaskNIL & (1 << data_type)) - { - return 0; - } - else - { - llerrs << "Getting stride for unsupported data type " << data_type << llendl; - return 0; - } -} - #endif //LL_LLDRAWPOOL_H diff --git a/linden/indra/newview/lldrawpoolalpha.cpp b/linden/indra/newview/lldrawpoolalpha.cpp index c62db17..b50be95 100644 --- a/linden/indra/newview/lldrawpoolalpha.cpp +++ b/linden/indra/newview/lldrawpoolalpha.cpp @@ -29,11 +29,11 @@ #include "lldrawpoolalpha.h" +#include "llglheaders.h" #include "llviewercontrol.h" #include "llcriticaldamp.h" #include "llfasttimer.h" -#include "llagparray.h" #include "llcubemap.h" #include "llsky.h" #include "llagent.h" @@ -44,104 +44,25 @@ #include "llviewerobjectlist.h" // For debugging #include "llviewerwindow.h" #include "pipeline.h" - -const F32 MAX_DIST = 512.f; -const F32 ALPHA_FALLOFF_START_DISTANCE = 0.8f; +#include "llviewerregion.h" BOOL LLDrawPoolAlpha::sShowDebugAlpha = FALSE; -LLDrawPoolAlpha::LLDrawPoolAlpha() : - LLDrawPool(POOL_ALPHA, - DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK, - DATA_SIMPLE_NIL_MASK) +LLDrawPoolAlpha::LLDrawPoolAlpha(U32 type) : + LLRenderPass(type) { - mRebuiltLastFrame = FALSE; - mMinDistance = 0.f; - mMaxDistance = MAX_DIST; - mInvBinSize = NUM_ALPHA_BINS/(mMaxDistance - mMinDistance); - mCleanupUnused = TRUE; - //mRebuildFreq = -1 ; // Only rebuild if nearly full - -// for (S32 i = 0; i < NUM_ALPHA_BINS; i++) -// { -// mDistanceBins[i].realloc(200); -// } -} -LLDrawPoolAlpha::~LLDrawPoolAlpha() -{ } -LLDrawPool *LLDrawPoolAlpha::instancePool() +LLDrawPoolAlphaPostWater::LLDrawPoolAlphaPostWater() +: LLDrawPoolAlpha(POOL_ALPHA_POST_WATER) { - llerrs << "Should never be calling instancePool on an alpha pool!" << llendl; - return NULL; } -void LLDrawPoolAlpha::enqueue(LLFace *facep) +LLDrawPoolAlpha::~LLDrawPoolAlpha() { - if (!facep->isState(LLFace::GLOBAL)) - { - facep->mCenterAgent = facep->mCenterLocal * facep->getRenderMatrix(); - } - facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis(); - - if (facep->isState(LLFace::BACKLIST)) - { - mMoveFace.put(facep); - } - else - { - mDrawFace.put(facep); - } - - { - S32 dist_bin = lltrunc( (mMaxDistance - (facep->mDistance+32))*mInvBinSize ); - - if (dist_bin >= NUM_ALPHA_BINS) - { - mDistanceBins[NUM_ALPHA_BINS-1].put(facep); - //mDistanceBins[NUM_ALPHA_BINS-1].push(facep, (U32)(void*)facep->getTexture()); - } - else if (dist_bin > 0) - { - mDistanceBins[dist_bin].put(facep); - //mDistanceBins[dist_bin].push(facep, (U32)(void*)facep->getTexture()); - } - else - { - mDistanceBins[0].put(facep); - //mDistanceBins[0].push(facep, (U32)(void*)facep->getTexture()); - } - } } -BOOL LLDrawPoolAlpha::removeFace(LLFace *facep) -{ - BOOL removed = FALSE; - - LLDrawPool::removeFace(facep); - - { - for (S32 i = 0; i < NUM_ALPHA_BINS; i++) - { - if (mDistanceBins[i].removeObj(facep) != -1) - { - if (removed) - { - llerrs << "Warning! " << "Face in multiple distance bins on removal" << llendl; - } - removed = TRUE; - } - } - } - if (removed) - { - return TRUE; - } - - return FALSE; -} void LLDrawPoolAlpha::prerender() { @@ -150,454 +71,270 @@ void LLDrawPoolAlpha::prerender() void LLDrawPoolAlpha::beginRenderPass(S32 pass) { - if (mDrawFace.empty()) - { - // No alpha objects, early exit. - return; - } - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - if (gPipeline.getLightingDetail() >= 2) - { - glEnableClientState(GL_COLOR_ARRAY); - } + glEnableClientState(GL_COLOR_ARRAY); } - -void LLDrawPoolAlpha::render(S32 pass) +void setup_clip_plane(BOOL pre_water) { - LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + F32 height = gAgent.getRegion()->getWaterHeight(); + BOOL above = gCamera->getOrigin().mV[2] > height ? TRUE : FALSE; - if (mDrawFace.empty()) - { - // No alpha objects, early exit. - return; - } - - GLfloat shiny[4] = - { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - - GLint specularIndex = (mVertexShaderLevel > 0) ? - gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR] : 0; + F64 plane[4]; + + plane[0] = 0; + plane[1] = 0; + plane[2] = above == pre_water ? -1.0 : 1.0; + plane[3] = -plane[2] * height; + + glClipPlane(GL_CLIP_PLANE0, plane); +} - S32 diffTex = 0; - S32 envTex = -1; +void LLDrawPoolAlphaPostWater::render(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); - if (mVertexShaderLevel > 0) //alpha pass uses same shader as shiny/bump + if (gPipeline.hasRenderType(LLDrawPool::POOL_ALPHA)) { - envTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (envTex >= 0 && cube_map) - { - cube_map->bind(); - cube_map->setMatrix(1); - } - - if (specularIndex > 0) - { - glVertexAttrib4fARB(specularIndex, 0, 0, 0, 0); - } - - S32 scatterTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - - diffTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); + LLGLEnable clip(GL_CLIP_PLANE0); + setup_clip_plane(FALSE); + LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater); } - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); - if (gPipeline.getLightingDetail() >= 2) + else { - bindGLColorPointer(); + LLDrawPoolAlpha::render(gPipeline.mAlphaGroupsPostWater); } +} - S32 i, j; - glAlphaFunc(GL_GREATER,0.01f); - // This needs to be turned off or there will be lots of artifacting with the clouds - djs - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); +void LLDrawPoolAlpha::render(S32 pass) +{ + LLFastTimer t(LLFastTimer::FTM_RENDER_ALPHA); + + LLGLEnable clip(GL_CLIP_PLANE0); + setup_clip_plane(TRUE); + render(gPipeline.mAlphaGroups); +} +void LLDrawPoolAlpha::render(std::vector& groups) +{ + LLGLDepthTest gls_depth(GL_TRUE); LLGLSPipelineAlpha gls_pipeline_alpha; - LLDynamicArray* distance_bins; - distance_bins = mDistanceBins; - - S32 num_bins_no_alpha_test = ((gPickAlphaThreshold != 0.f) && gUsePickAlpha) ? - (NUM_ALPHA_BINS - llmax(2, (S32)(ALPHA_FALLOFF_START_DISTANCE * mInvBinSize))) : - NUM_ALPHA_BINS; - - typedef std::vector face_list_t; + gPipeline.enableLightsDynamic(1.f); + renderAlpha(getVertexDataMask(), groups); - for (i = 0; i < num_bins_no_alpha_test; i++) + if (sShowDebugAlpha) { - S32 obj_count = distance_bins[i].count(); - - if (!obj_count) - { - continue; - } - else if (i > (NUM_ALPHA_BINS / 2) && obj_count < 100) - { - face_list_t pri_queue; - pri_queue.reserve(distance_bins[i].count()); - for (j = 0; j < distance_bins[i].count(); j++) - { - pri_queue.push_back(distance_bins[i][j]); - } - std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater()); - - for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++) - { - const LLFace &face = *(*iter); - face.enableLights(); - face.bindTexture(diffTex); - if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0) - { - U8 s = face.getTextureEntry()->getShiny(); - glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]); - } - face.renderIndexed(getRawIndices()); - mIndicesDrawn += face.getIndicesCount(); - } - } - else - { - S32 count = distance_bins[i].count(); - for (j = 0; j < count; j++) - { - const LLFace &face = *distance_bins[i][j]; - face.enableLights(); - face.bindTexture(diffTex); - if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0) - { - U8 s = face.getTextureEntry()->getShiny(); - glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]); - } - face.renderIndexed(getRawIndices()); - mIndicesDrawn += face.getIndicesCount(); - } - } + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + glColor4f(1,0,0,1); + LLViewerImage::sSmokeImagep->addTextureStats(1024.f*1024.f); + LLViewerImage::sSmokeImagep->bind(); + renderAlphaHighlight(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD, groups); } +} - GLfloat ogl_matrix[16]; - gCamera->getOpenGLTransform(ogl_matrix); +void LLDrawPoolAlpha::renderAlpha(U32 mask, std::vector& groups) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif - for (i = num_bins_no_alpha_test; i < NUM_ALPHA_BINS; i++) - { - BOOL use_pri_queue = distance_bins[i].count() < 100; + LLSpatialBridge* last_bridge = NULL; + LLSpatialPartition* last_part = NULL; + glPushMatrix(); + LLGLDepthTest depth(GL_TRUE, GL_FALSE); - face_list_t pri_queue; - - if (use_pri_queue) - { - pri_queue.reserve(distance_bins[i].count()); - for (j = 0; j < distance_bins[i].count(); j++) - { - pri_queue.push_back(distance_bins[i][j]); - } - std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater()); - } - - S32 count = distance_bins[i].count(); - for (j = 0; j < count; j++) + for (std::vector::iterator i = groups.begin(); i != groups.end(); ++i) + { + LLSpatialGroup* group = *i; + if (group->mSpatialPartition->mRenderByGroup && + !group->isDead()) { - const LLFace &face = use_pri_queue ? *pri_queue[j] : *distance_bins[i][j]; - F32 fade_value = face.mAlphaFade * gPickAlphaThreshold; - - face.enableLights(); - - if (fade_value < 1.f) + LLSpatialPartition* part = group->mSpatialPartition; + if (part != last_part) { + LLSpatialBridge* bridge = part->asBridge(); + if (bridge != last_bridge) { - LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - glAlphaFunc(GL_LESS, fade_value); - glBlendFunc(GL_ZERO, GL_ONE); - LLViewerImage::bindTexture(gPipeline.mAlphaSizzleImagep, diffTex); - LLVector4 s_params(ogl_matrix[2], ogl_matrix[6], ogl_matrix[10], ogl_matrix[14]); - LLVector4 t_params(ogl_matrix[1], ogl_matrix[5], ogl_matrix[9], ogl_matrix[13]); - - LLGLEnable gls_texgen_s(GL_TEXTURE_GEN_S); - LLGLEnable gls_texgen_t(GL_TEXTURE_GEN_T); - glTexGeni(GL_S, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGeni(GL_T, GL_TEXTURE_GEN_MODE, GL_OBJECT_LINEAR); - glTexGenfv(GL_S, GL_OBJECT_PLANE, s_params.mV); - glTexGenfv(GL_T, GL_OBJECT_PLANE, t_params.mV); - if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0) + glPopMatrix(); + glPushMatrix(); + if (bridge) { - U8 s = face.getTextureEntry()->getShiny(); - glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]); + glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); } - face.renderIndexed(getRawIndices()); + last_bridge = bridge; } - { - // should get GL_GREATER to work, as it's faster - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_LESS); - glAlphaFunc(GL_GEQUAL, fade_value); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - face.bindTexture(diffTex); - if ((mVertexShaderLevel > 0) && face.getTextureEntry() && specularIndex > 0) - { - U8 s = face.getTextureEntry()->getShiny(); - glVertexAttrib4fARB(specularIndex, shiny[s], shiny[s], shiny[s], shiny[s]); - } - face.renderIndexed(getRawIndices()); - } +// if (!last_part || part->mDepthMask != last_part->mDepthMask) +// { +// glDepthMask(part->mDepthMask); +// } + last_part = part; } - // render opaque portion of actual texture - glAlphaFunc(GL_GREATER, 0.98f); - - face.bindTexture(diffTex); - face.renderIndexed(getRawIndices()); - - glAlphaFunc(GL_GREATER, 0.01f); - - mIndicesDrawn += face.getIndicesCount(); + renderGroupAlpha(group,LLRenderPass::PASS_ALPHA,mask,TRUE); } } + + glPopMatrix(); +} - if (mVertexShaderLevel > 0) //single pass shader driven shiny/bump - { - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (envTex >= 0 && cube_map) - { - cube_map->restoreMatrix(); - } - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); - } +void LLDrawPoolAlpha::renderAlphaHighlight(U32 mask, std::vector& groups) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif - if (sShowDebugAlpha) + LLSpatialBridge* last_bridge = NULL; + LLSpatialPartition* last_part = NULL; + glPushMatrix(); + + for (std::vector::iterator i = groups.begin(); i != groups.end(); ++i) { - gPipeline.disableLights(); - if ((mVertexShaderLevel > 0)) + LLSpatialGroup* group = *i; + if (group->mSpatialPartition->mRenderByGroup && + !group->isDead()) { - gPipeline.mHighlightProgram.bind(); - } - - LLViewerImage::sSmokeImagep->bind(); - LLOverrideFaceColor override_color(this, 1.f, 0.f, 0.f, 1.f); - glColor4f(1.f, 0.f, 0.f, 1.f); // in case vertex shaders are enabled - glDisableClientState(GL_COLOR_ARRAY); - - for (S32 i = 0; i < NUM_ALPHA_BINS; i++) - { - if (distance_bins[i].count() < 100) + LLSpatialPartition* part = group->mSpatialPartition; + if (part != last_part) { - face_list_t pri_queue; - pri_queue.reserve(distance_bins[i].count()); - for (j = 0; j < distance_bins[i].count(); j++) + LLSpatialBridge* bridge = part->asBridge(); + if (bridge != last_bridge) { - pri_queue.push_back(distance_bins[i][j]); - } - std::sort(pri_queue.begin(), pri_queue.end(), LLFace::CompareDistanceGreater()); - - for (face_list_t::iterator iter = pri_queue.begin(); iter != pri_queue.end(); iter++) - { - const LLFace &face = *(*iter); - face.renderIndexed(getRawIndices()); - mIndicesDrawn += face.getIndicesCount(); + glPopMatrix(); + glPushMatrix(); + if (bridge) + { + glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); + } + last_bridge = bridge; } + + last_part = part; } - else + + std::vector& draw_info = group->mDrawMap[LLRenderPass::PASS_ALPHA]; + + for (std::vector::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - for (j = 0; j < distance_bins[i].count(); j++) + LLDrawInfo& params = **k; + + if (params.mParticle) { - const LLFace &face = *distance_bins[i][j]; - face.renderIndexed(getRawIndices()); - mIndicesDrawn += face.getIndicesCount(); + continue; } + params.mVertexBuffer->setBuffer(mask); + U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + + addIndicesDrawn(params.mCount); } } + } + glPopMatrix(); +} - if ((mVertexShaderLevel > 0)) - { - gPipeline.mHighlightProgram.unbind(); - } +void LLDrawPoolAlpha::renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture) +{ + BOOL light_enabled = TRUE; - } + std::vector& draw_info = group->mDrawMap[type]; + + U32 prim_type = GL_TRIANGLES; -} + //F32 width = (F32) gViewerWindow->getWindowDisplayWidth(); -void LLDrawPoolAlpha::renderForSelect() -{ - if (mDrawFace.empty() || !mMemory.count()) + //F32 view = gCamera->getView(); + + if (group->mSpatialPartition->mDrawableType == LLPipeline::RENDER_TYPE_CLOUDS) { - return; + glAlphaFunc(GL_GREATER, 0.f); } - - // force faces on focus object to proper alpha cutoff based on object bbox distance - if (gAgent.getFocusObject()) + else { - LLDrawable* drawablep = gAgent.getFocusObject()->mDrawable; - - if (drawablep) - { - const S32 num_faces = drawablep->getNumFaces(); - - for (S32 f = 0; f < num_faces; f++) - { - LLFace* facep = drawablep->getFace(f); - facep->mDistance = gAgent.getFocusObjectDist(); - } - } + glAlphaFunc(GL_GREATER, 0.01f); } - glEnableClientState (GL_VERTEX_ARRAY); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - - LLGLSObjectSelectAlpha gls_alpha; - - glBlendFunc(GL_ONE, GL_ZERO); - glAlphaFunc(gPickTransparent ? GL_GEQUAL : GL_GREATER, 0.f); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); + /*LLGLEnable point_sprite(GL_POINT_SPRITE_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA); - - LLDynamicArray* distance_bins; - distance_bins = mDistanceBins; - - S32 j; - S32 num_bins_no_alpha_test = (gPickAlphaThreshold != 0.f) ? - (NUM_ALPHA_BINS - llmax(2, (S32)(ALPHA_FALLOFF_START_DISTANCE * mInvBinSize))) : - NUM_ALPHA_BINS; + if (gGLManager.mHasPointParameters) + { + glTexEnvi(GL_POINT_SPRITE_ARB, GL_COORD_REPLACE_ARB, TRUE); + glPointParameterfARB(GL_POINT_SIZE_MIN_ARB, 0.f); + glPointParameterfARB(GL_POINT_SIZE_MAX_ARB, width*16.f); + glPointSize(width/(view*view)); + }*/ - S32 i; - for (i = 0; i < num_bins_no_alpha_test; i++) + for (std::vector::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - S32 distance_bin_size = distance_bins[i].count(); - for (j = 0; j < distance_bin_size; j++) + LLDrawInfo& params = **k; + if (texture && params.mTexture.notNull()) { - const LLFace &face = *distance_bins[i][j]; - if (face.getDrawable() && !face.getDrawable()->isDead() && (face.getViewerObject()->mGLName)) + params.mTexture->bind(); + params.mTexture->addTextureStats(params.mVSize); + if (params.mTextureMatrix) { - face.bindTexture(); - face.renderForSelect(); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); } } - } - - for (i = num_bins_no_alpha_test; i < NUM_ALPHA_BINS; i++) - { - S32 distance_bin_size = distance_bins[i].count(); - if (distance_bin_size) + + if (params.mFullbright) { - for (j = 0; j < distance_bin_size; j++) + if (light_enabled) { - const LLFace &face = *distance_bins[i][j]; - - glAlphaFunc(GL_GEQUAL, face.mAlphaFade * gPickAlphaTargetThreshold); - - if (face.getDrawable() && !face.getDrawable()->isDead() && (face.getViewerObject()->mGLName)) - { - face.bindTexture(); - face.renderForSelect(); - } + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + light_enabled = FALSE; } } - } - - glAlphaFunc(GL_GREATER, 0.01f); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - glDisableClientState (GL_TEXTURE_COORD_ARRAY); -} - - -void LLDrawPoolAlpha::renderFaceSelected(LLFace *facep, - LLImageGL *image, - const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ - facep->renderSelected(image, color, index_offset, index_count); -} - + else if (!light_enabled) + { + gPipeline.enableLightsDynamic(1.f); + light_enabled = TRUE; + } -void LLDrawPoolAlpha::resetDrawOrders() -{ - LLDrawPool::resetDrawOrders(); + /*if (params.mParticle) + { + F32 size = params.mPartSize; + size *= size; + float param[] = { 0, 0, 0.01f/size*view*view }; + prim_type = GL_POINTS; + glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param); + } + else*/ + { + prim_type = GL_TRIANGLES; + } - for (S32 i = 0; i < NUM_ALPHA_BINS; i++) - { - mDistanceBins[i].resize(0); - } -} + params.mVertexBuffer->setBuffer(mask); + U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(prim_type, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + + addIndicesDrawn(params.mCount); -BOOL LLDrawPoolAlpha::verify() const -{ - S32 i, j; - BOOL ok; - ok = LLDrawPool::verify(); - for (i = 0; i < NUM_ALPHA_BINS; i++) - { - for (j = 0; j < mDistanceBins[i].count(); j++) + if (params.mTextureMatrix && texture && params.mTexture.notNull()) { - const LLFace &face = *mDistanceBins[i][j]; - if (!face.verify()) - { - ok = FALSE; - } + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); } } - return ok; -} - -LLViewerImage *LLDrawPoolAlpha::getDebugTexture() -{ - return LLViewerImage::sSmokeImagep; -} - - -LLColor3 LLDrawPoolAlpha::getDebugColor() const -{ - return LLColor3(1.f, 0.f, 0.f); -} -S32 LLDrawPoolAlpha::getMaterialAttribIndex() -{ - return gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; -} + if (!light_enabled) + { + gPipeline.enableLightsDynamic(1.f); + } -// virtual -void LLDrawPoolAlpha::enableShade() -{ - glDisableClientState(GL_COLOR_ARRAY); -} + /*glPointSize(1.f); -// virtual -void LLDrawPoolAlpha::disableShade() -{ - glEnableClientState(GL_COLOR_ARRAY); -} - -// virtual -void LLDrawPoolAlpha::setShade(F32 shade) -{ - glColor4f(0,0,0,shade); -} + if (gGLManager.mHasPointParameters) + { + float param[] = {1, 0, 0 }; + glPointParameterfvARB(GL_POINT_DISTANCE_ATTENUATION_ARB, param); + }*/ +} diff --git a/linden/indra/newview/lldrawpoolalpha.h b/linden/indra/newview/lldrawpoolalpha.h index ba58a7f..f7012d6 100644 --- a/linden/indra/newview/lldrawpoolalpha.h +++ b/linden/indra/newview/lldrawpoolalpha.h @@ -29,55 +29,43 @@ #define LL_LLDRAWPOOLALPHA_H #include "lldrawpool.h" -#include "llviewerimage.h" #include "llframetimer.h" class LLFace; class LLColor4; -class LLDrawPoolAlpha: public LLDrawPool +class LLDrawPoolAlpha: public LLRenderPass { public: - LLDrawPoolAlpha(); - /*virtual*/ ~LLDrawPoolAlpha(); - - /*virtual*/ LLDrawPool *instancePool(); - - /*virtual*/ void beginRenderPass(S32 pass = 0); - /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0); - /*virtual*/ void prerender(); - /*virtual*/ void renderForSelect(); - - /*virtual*/ void enqueue(LLFace *face); - /*virtual*/ BOOL removeFace(LLFace *face); - /*virtual*/ void resetDrawOrders(); - - /*virtual*/ void enableShade(); - /*virtual*/ void disableShade(); - /*virtual*/ void setShade(F32 shade); - - - virtual S32 getMaterialAttribIndex(); - - BOOL mRebuiltLastFrame; enum { - NUM_ALPHA_BINS = 1024 + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_COLOR | + LLVertexBuffer::MAP_TEXCOORD }; + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + LLDrawPoolAlpha(U32 type = LLDrawPool::POOL_ALPHA); + /*virtual*/ ~LLDrawPoolAlpha(); - /*virtual*/ BOOL verify() const; - /*virtual*/ LLViewerImage *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display + /*virtual*/ void beginRenderPass(S32 pass = 0); + virtual void render(S32 pass = 0); + void render(std::vector& groups); + /*virtual*/ void prerender(); + void renderGroupAlpha(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE); + void renderAlpha(U32 mask, std::vector& groups); + void renderAlphaHighlight(U32 mask, std::vector& groups); + static BOOL sShowDebugAlpha; -protected: - F32 mMinDistance; - F32 mMaxDistance; - F32 mInvBinSize; +}; - LLDynamicArray mDistanceBins[NUM_ALPHA_BINS]; +class LLDrawPoolAlphaPostWater : public LLDrawPoolAlpha +{ +public: + LLDrawPoolAlphaPostWater(); + virtual void render(S32 pass = 0); }; #endif // LL_LLDRAWPOOLALPHA_H diff --git a/linden/indra/newview/lldrawpoolavatar.cpp b/linden/indra/newview/lldrawpoolavatar.cpp index abf154c..fc4f64b 100644 --- a/linden/indra/newview/lldrawpoolavatar.cpp +++ b/linden/indra/newview/lldrawpoolavatar.cpp @@ -32,7 +32,6 @@ #include "llvoavatar.h" #include "m3math.h" -#include "llagparray.h" #include "llagent.h" #include "lldrawable.h" #include "llface.h" @@ -42,6 +41,11 @@ #include "noise.h" #include "pipeline.h" +static U32 sDataMask = LLDrawPoolAvatar::VERTEX_DATA_MASK; +static U32 sBufferUsage = GL_STREAM_DRAW_ARB; +static U32 sShaderLevel = 0; +static LLGLSLShader* sVertexProgram = NULL; + extern F32 gFrameDTClamped; extern BOOL gUseGLPick; @@ -75,53 +79,13 @@ S32 AVATAR_VERTEX_BYTES = 48; BOOL gAvatarEmbossBumpMap = FALSE; +static BOOL sRenderingSkinned = FALSE; LLDrawPoolAvatar::LLDrawPoolAvatar() : -LLDrawPool(POOL_AVATAR, - DATA_SIMPLE_IL_MASK, - DATA_VERTEX_WEIGHTS_MASK | DATA_CLOTHING_WEIGHTS_MASK ) +LLFacePool(POOL_AVATAR) { - mCleanupUnused = FALSE; - - // Overide the data layout - mDataMaskIL = 0; - mStride = 0; - for (S32 i = 0; i < DATA_MAX_TYPES; i++) - { - mDataOffsets[i] = 0; - } - - // Note: padding is to speed up SSE code - mDataMaskIL |= DATA_VERTICES_MASK; - mDataOffsets[DATA_VERTICES] = mStride; - mStride += sDataSizes[DATA_VERTICES]; - - mStride += 4; - - mDataMaskIL |= DATA_NORMALS_MASK; - mDataOffsets[DATA_NORMALS] = mStride; - mStride += sDataSizes[DATA_NORMALS]; - - mStride += 4; - - // Note: binormals are stripped off in software blending - mDataMaskIL |= DATA_BINORMALS_MASK; - mDataOffsets[DATA_BINORMALS] = mStride; - mStride += sDataSizes[DATA_BINORMALS]; - - mStride += 4; // To keep the structure 16-byte aligned (for SSE happiness) - - mDataMaskIL |= DATA_TEX_COORDS0_MASK; - mDataOffsets[DATA_TEX_COORDS0] = mStride; - mStride += sDataSizes[DATA_TEX_COORDS0]; - - mDataMaskIL |= DATA_TEX_COORDS1_MASK; - mDataOffsets[DATA_TEX_COORDS1] = mStride; - mStride += sDataSizes[DATA_TEX_COORDS1]; - //LLDebugVarMessageBox::show("acceleration", &CLOTHING_ACCEL_FORCE_FACTOR, 10.f, 0.1f); - //LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f); - + //LLDebugVarMessageBox::show("gravity", &CLOTHING_GRAVITY_EFFECT, 10.f, 0.1f); } //----------------------------------------------------------------------------- @@ -132,41 +96,194 @@ LLDrawPool *LLDrawPoolAvatar::instancePool() return new LLDrawPoolAvatar(); } +BOOL gRenderAvatar = TRUE; +static LLMatrix4 sModelViewMatrix = LLMatrix4(); -S32 LLDrawPoolAvatar::rebuild() +S32 LLDrawPoolAvatar::getVertexShaderLevel() const { - mRebuildTime++; - if (mRebuildTime > mRebuildFreq) - { - flushAGP(); - - mRebuildTime = 0; - } - - return 0; + return (S32) gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR); } -BOOL gRenderAvatar = TRUE; - void LLDrawPoolAvatar::prerender() { mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR); + sShaderLevel = mVertexShaderLevel; + + if (sShaderLevel > 0) + { + sBufferUsage = GL_STATIC_DRAW_ARB; + } + else + { + sBufferUsage = GL_STREAM_DRAW_ARB; + } +} + +LLMatrix4& LLDrawPoolAvatar::getModelView() +{ + return sModelViewMatrix; } //----------------------------------------------------------------------------- // render() //----------------------------------------------------------------------------- + +S32 LLDrawPoolAvatar::getNumPasses() +{ + return 3; +} + void LLDrawPoolAvatar::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_CHARACTERS); - renderAvatars(NULL); // render all avatars + renderAvatars(NULL, pass); // render all avatars +} + +void LLDrawPoolAvatar::beginRenderPass(S32 pass) +{ + //reset vertex buffer mappings + LLVertexBuffer::unbind(); + + switch (pass) + { + case 0: + beginFootShadow(); + break; + case 1: + glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) sModelViewMatrix.mMatrix); + beginRigid(); + break; + case 2: + beginSkinned(); + break; + } +} + +void LLDrawPoolAvatar::endRenderPass(S32 pass) +{ + switch (pass) + { + case 0: + endFootShadow(); + break; + case 1: + endRigid(); + break; + case 2: + endSkinned(); + } +} + +void LLDrawPoolAvatar::beginFootShadow() +{ + glDepthMask(GL_FALSE); + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void LLDrawPoolAvatar::endFootShadow() +{ + gPipeline.enableLightsDynamic(1.f); + glDepthMask(GL_TRUE); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void LLDrawPoolAvatar::beginRigid() +{ + sVertexProgram = &gPipeline.mAvatarEyeballProgram; + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + if (sShaderLevel > 0) + { //eyeballs render with the specular shader + gPipeline.mAvatarEyeballProgram.bind(); + gPipeline.mMaterialIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; + gPipeline.mSpecularIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR]; + } +} + +void LLDrawPoolAvatar::endRigid() +{ + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + +void LLDrawPoolAvatar::beginSkinned() +{ + glEnableClientState(GL_NORMAL_ARRAY); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + + sVertexProgram = &gPipeline.mAvatarProgram; + + if (sShaderLevel > 0) // for hardware blending + { + sRenderingSkinned = TRUE; + glClientActiveTextureARB(GL_TEXTURE1_ARB); + if (sShaderLevel >= SHADER_LEVEL_BUMP) + { + gPipeline.mMaterialIndex = sVertexProgram->mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; + gPipeline.mSpecularIndex = sVertexProgram->mAttribute[LLPipeline::GLSL_SPECULAR_COLOR]; + } + sVertexProgram->bind(); + if (sShaderLevel >= SHADER_LEVEL_CLOTH) + { + enable_cloth_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]); + } + enable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); + + if (sShaderLevel >= SHADER_LEVEL_BUMP) + { + enable_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL]); + } + + sVertexProgram->enableTexture(LLPipeline::GLSL_BUMP_MAP); + glActiveTextureARB(GL_TEXTURE0_ARB); + } } -void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders) +void LLDrawPoolAvatar::endSkinned() { - if (no_shaders) + // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done + if (sShaderLevel > 0) { - mVertexShaderLevel = 0; + sRenderingSkinned = FALSE; + sVertexProgram->disableTexture(LLPipeline::GLSL_BUMP_MAP); + glActiveTextureARB(GL_TEXTURE0_ARB); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + disable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); + if (sShaderLevel >= SHADER_LEVEL_BUMP) + { + disable_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL]); + } + if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) + { + disable_cloth_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]); + } + + sVertexProgram->unbind(); + } + + glActiveTextureARB(GL_TEXTURE0_ARB); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); +} + + +void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, S32 pass) +{ + if (pass == -1) + { + for (S32 i = 1; i < getNumPasses(); i++) + { //skip foot shadows + prerender(); + beginRenderPass(i); + renderAvatars(single_avatar, i); + endRenderPass(i); + } + + return; } if (!gRenderAvatar) @@ -195,13 +312,95 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders) avatarp = (LLVOAvatar *)(facep->getDrawable()->getVObj()); } - if (avatarp->isDead() || avatarp->mDrawable.isNull()) + if (avatarp->isDead() || avatarp->mDrawable.isNull()) { return; } LLOverrideFaceColor color(this, 1.0f, 1.0f, 1.0f, 1.0f); + if (pass == 0) + { + if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS)) + { + mIndicesDrawn += avatarp->renderFootShadows(); + } + return; + } + + if (avatarp->mSpecialRenderMode == 0) // normal + { + gPipeline.enableLightsAvatar(avatarp->mDrawable->getSunShadowFactor()); + } + else if (avatarp->mSpecialRenderMode == 1) // anim preview + { + gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); + } + else // 2=image preview, 3=morph view + { + gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f)); + } + + if (pass == 1) + { + // render rigid meshes (eyeballs) first + mIndicesDrawn += avatarp->renderRigid(); + + if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest) + { + LLVector3 orig_pos_root = avatarp->mRoot.getPosition(); + LLVector3 next_pos_root = orig_pos_root; + for (S32 i = 0; i < NUM_TEST_AVATARS; i++) + { + next_pos_root.mV[VX] += 1.f; + if (i % 5 == 0) + { + next_pos_root.mV[VY] += 1.f; + next_pos_root.mV[VX] = orig_pos_root.mV[VX]; + } + + avatarp->mRoot.setPosition(next_pos_root); // avatar load test + avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test + + mIndicesDrawn += avatarp->renderRigid(); + } + avatarp->mRoot.setPosition(orig_pos_root); // avatar load test + avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test + } + return; + } + + + if (sShaderLevel > 0) + { + gPipeline.mAvatarMatrixParam = sVertexProgram->mUniform[LLPipeline::GLSL_AVATAR_MATRIX]; + } + + if ((sShaderLevel >= SHADER_LEVEL_CLOTH)) + { + LLMatrix4 rot_mat; + gCamera->getMatrixToLocal(rot_mat); + LLMatrix4 cfr(OGL_TO_CFR_ROTATION); + rot_mat *= cfr; + + LLVector4 wind; + wind.setVec(avatarp->mWindVec); + wind.mV[VW] = 0; + wind = wind * rot_mat; + wind.mV[VW] = avatarp->mWindVec.mV[VW]; + + sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_WIND, wind.mV); + F32 phase = -1.f * (avatarp->mRipplePhase); + + F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); + LLVector4 sin_params(freq, freq, freq, phase); + sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_SINWAVE, sin_params.mV); + + LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); + gravity = gravity * rot_mat; + sVertexProgram->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_GRAVITY, gravity.mV); + } + if( !single_avatar || (avatarp == single_avatar) ) { if (LLVOAvatar::sShowCollisionVolumes) @@ -210,8 +409,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders) avatarp->renderCollisionVolumes(); } - LLGLEnable normalize(GL_NORMALIZE); - if (avatarp->mIsSelf && LLAgent::sDebugDisplayTarget) { LLGLSNoTexture gls_no_texture; @@ -267,171 +464,8 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders) color.setColor(1.0f, 1.0f, 1.0f, 1.0f); } - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - LLGLSLShader* vertex_program = &gPipeline.mAvatarProgram; - if (mVertexShaderLevel > 0) - { - gPipeline.mAvatarMatrixParam = vertex_program->mUniform[LLPipeline::GLSL_AVATAR_MATRIX]; - } - - //-------------------------------------------------------------------------------- - // this is where we first hit the software blending path - // if enabled, we need to set up the proper buffers and avoid setting other state - //-------------------------------------------------------------------------------- - if (!(mVertexShaderLevel > 0)) - { - - // performance could be increased by better utilizing the buffers, for example, only using 1k buffers for lo-res - // avatars. But the only problem with using fewer buffers is that we're more likely to wait for a fence to complete - - // vertex format: - // vertices 12 - // texcoords 8 - // normals 12 - // binormals 12 - // padding 4 - // total 48 - - // Rotate to the next buffer, round-robin. - gPipeline.bufferRotate(); - - // Wait until the hardware is done reading the last set of vertices from the buffer before writing the next set. - gPipeline.bufferWaitFence(); - - // Need to do this because we may be rendering without AGP even in AGP mode - U8* buffer_offset_start = gPipeline.bufferGetScratchMemory(); - glVertexPointer( 3, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_POS); - glTexCoordPointer(2, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_TEX0); - glNormalPointer( GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_NORMAL); - - } - - if ((mVertexShaderLevel > 0)) // for hardware blending - { - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(0); - } - - if ((mVertexShaderLevel > 0)) - { //eyeballs render with the specular shader - gPipeline.mAvatarEyeballProgram.bind(); - gPipeline.mMaterialIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; - gPipeline.mSpecularIndex = gPipeline.mAvatarEyeballProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR]; - - S32 index = gPipeline.mAvatarEyeballProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - gSky.mVOSkyp->getScatterMap()->bind(index); - - glActiveTextureARB(GL_TEXTURE0_ARB); - } - - if (avatarp->mSpecialRenderMode == 0) // normal - { - gPipeline.enableLightsAvatar(avatarp->mDrawable->getSunShadowFactor()); - } - else if (avatarp->mSpecialRenderMode == 1) // anim preview - { - gPipeline.enableLightsAvatarEdit(LLColor4(0.7f, 0.6f, 0.3f, 1.f)); - } - else // 2=image preview, 3=morph view - { - gPipeline.enableLightsAvatarEdit(LLColor4(.5f, .5f, .5f, 1.f)); - } - - // render rigid meshes (eyeballs) first - mIndicesDrawn += avatarp->renderRigid(); - - if ((mVertexShaderLevel > 0)) - { - gPipeline.mAvatarEyeballProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - glActiveTextureARB(GL_TEXTURE0_ARB); - } - - if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest) - { - LLVector3 orig_pos_root = avatarp->mRoot.getPosition(); - LLVector3 next_pos_root = orig_pos_root; - for (S32 i = 0; i < NUM_TEST_AVATARS; i++) - { - next_pos_root.mV[VX] += 1.f; - if (i % 5 == 0) - { - next_pos_root.mV[VY] += 1.f; - next_pos_root.mV[VX] = orig_pos_root.mV[VX]; - } - - avatarp->mRoot.setPosition(next_pos_root); // avatar load test - avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test - - mIndicesDrawn += avatarp->renderRigid(); - } - avatarp->mRoot.setPosition(orig_pos_root); // avatar load test - avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test - } - - if ((mVertexShaderLevel > 0)) // for hardware blending - { - glClientActiveTextureARB(GL_TEXTURE1_ARB); - if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP)) - { - bindGLTexCoordPointer(1); - - bindGLBinormalPointer(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]); - gPipeline.mMaterialIndex = vertex_program->mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; - gPipeline.mSpecularIndex = vertex_program->mAttribute[LLPipeline::GLSL_SPECULAR_COLOR]; - } - glClientActiveTextureARB(GL_TEXTURE0_ARB); - bindGLTexCoordPointer(0); - vertex_program->bind(); - bindGLVertexWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); - if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH)) - { - bindGLVertexClothingWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]); - enable_cloth_weights(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]); - } - enable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); - - if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP)) - { - enable_binormals(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]); - } - - vertex_program->enableTexture(LLPipeline::GLSL_BUMP_MAP); - S32 index = vertex_program->enableTexture(LLPipeline::GLSL_SCATTER_MAP); - gSky.mVOSkyp->getScatterMap()->bind(index); - glActiveTextureARB(GL_TEXTURE0_ARB); - } - - if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH)) - { - LLMatrix4 rot_mat; - gCamera->getMatrixToLocal(rot_mat); - LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - rot_mat *= cfr; - - LLVector4 wind; - wind.setVec(avatarp->mWindVec); - wind.mV[VW] = 0; - wind = wind * rot_mat; - wind.mV[VW] = avatarp->mWindVec.mV[VW]; - - vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_WIND, wind.mV); - F32 phase = -1.f * (avatarp->mRipplePhase); - - F32 freq = 7.f + (noise1(avatarp->mRipplePhase) * 2.f); - LLVector4 sin_params(freq, freq, freq, phase); - vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_SINWAVE, sin_params.mV); - - LLVector4 gravity(0.f, 0.f, -CLOTHING_GRAVITY_EFFECT, 0.f); - gravity = gravity * rot_mat; - vertex_program->vertexAttrib4fv(LLPipeline::GLSL_AVATAR_GRAVITY, gravity.mV); - } - mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); - + if (!gRenderForSelect && avatarp->mIsSelf && LLVOAvatar::sAvatarLoadTest) { LLVector3 orig_pos_root = avatarp->mRoot.getPosition(); @@ -453,31 +487,6 @@ void LLDrawPoolAvatar::renderAvatars(LLVOAvatar* single_avatar, BOOL no_shaders) avatarp->mRoot.setPosition(orig_pos_root); // avatar load test avatarp->mRoot.updateWorldMatrixChildren(); // avatar load test } - - // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - if (!(mVertexShaderLevel > 0)) - { - // want for the previously bound fence to finish - gPipeline.bufferSendFence(); - } - else - { - vertex_program->disableTexture(LLPipeline::GLSL_BUMP_MAP); - vertex_program->disableTexture(LLPipeline::GLSL_SCATTER_MAP); - glActiveTextureARB(GL_TEXTURE0_ARB); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - disable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); - if ((mVertexShaderLevel >= SHADER_LEVEL_BUMP)) - { - disable_binormals(vertex_program->mAttribute[LLPipeline::GLSL_BINORMAL]); - } - if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH)) - { - disable_cloth_weights(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING]); - } - - vertex_program->unbind(); - } } } @@ -490,14 +499,13 @@ void LLDrawPoolAvatar::renderForSelect() { return; } - //gGLSObjectSelectDepthAlpha.set(); - + if (!gRenderAvatar) { return; } - if (mDrawFace.empty() || !mMemory.count()) + if (mDrawFace.empty()) { return; } @@ -517,80 +525,38 @@ void LLDrawPoolAvatar::renderForSelect() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - LLGLSLShader* vertex_program = &gPipeline.mAvatarPickProgram; - if (mVertexShaderLevel > 0) + glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) sModelViewMatrix.mMatrix); + sVertexProgram = &gPipeline.mAvatarPickProgram; + if (sShaderLevel > 0) { - gPipeline.mAvatarMatrixParam = vertex_program->mUniform[LLPipeline::GLSL_AVATAR_MATRIX]; + gPipeline.mAvatarMatrixParam = sVertexProgram->mUniform[LLPipeline::GLSL_AVATAR_MATRIX]; } glAlphaFunc(GL_GEQUAL, 0.2f); glBlendFunc(GL_ONE, GL_ZERO); - //-------------------------------------------------------------------------------- - // this is where we first hit the software blending path - // if enabled, we need to set up the proper buffers and avoid setting other state - //-------------------------------------------------------------------------------- - if (!(mVertexShaderLevel > 0) || gUseGLPick) - { - - // Rotate to the next buffer, round-robin. - gPipeline.bufferRotate(); - - // Wait until the hardware is done reading the last set of vertices from the buffer before writing the next set. - gPipeline.bufferWaitFence(); - - // Need to do this because we may be rendering without AGP even in AGP mode - U8* buffer_offset_start = gPipeline.bufferGetScratchMemory(); - glVertexPointer( 3, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_POS); - glTexCoordPointer(2, GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_TEX0); - glNormalPointer( GL_FLOAT, AVATAR_VERTEX_BYTES, buffer_offset_start + AVATAR_OFFSET_NORMAL); - } - S32 name = avatarp->mDrawable->getVObj()->mGLName; LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name); glColor4ubv(color.mV); - if ((mVertexShaderLevel > 0) && !gUseGLPick) // for hardware blending - { - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(0); - } - // render rigid meshes (eyeballs) first - mIndicesDrawn += avatarp->renderRigid(); + //mIndicesDrawn += avatarp->renderRigid(); - if ((mVertexShaderLevel > 0) && !gUseGLPick) // for hardware blending + if ((sShaderLevel > 0) && !gUseGLPick) // for hardware blending { glClientActiveTextureARB(GL_TEXTURE0_ARB); - bindGLTexCoordPointer(0); - vertex_program->bind(); - bindGLVertexWeightPointer(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); - /*if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH)) - { - bindGLVertexClothingWeightPointer(); - enable_cloth_weights(); - }*/ - enable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); + sRenderingSkinned = TRUE; + sVertexProgram->bind(); + enable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); } - + mIndicesDrawn += avatarp->renderSkinned(AVATAR_RENDER_PASS_SINGLE); // if we're in software-blending, remember to set the fence _after_ we draw so we wait till this rendering is done - if (!(mVertexShaderLevel > 0) || gUseGLPick) + if ((sShaderLevel > 0) && !gUseGLPick) { - // want for the previously bound fence to finish - gPipeline.bufferSendFence(); - } - else - { - vertex_program->unbind(); - disable_vertex_weighting(vertex_program->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); - - /*if ((mVertexShaderLevel >= SHADER_LEVEL_CLOTH)) - { - disable_cloth_weights(); - }*/ + sRenderingSkinned = FALSE; + sVertexProgram->unbind(); + disable_vertex_weighting(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT]); } glAlphaFunc(GL_GREATER, 0.01f); @@ -627,3 +593,46 @@ LLColor3 LLDrawPoolAvatar::getDebugColor() const { return LLColor3(0.f, 1.f, 0.f); } + +LLVertexBufferAvatar::LLVertexBufferAvatar() +: LLVertexBuffer(sDataMask, + gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR) > 0 ? + GL_STATIC_DRAW_ARB : + GL_STREAM_DRAW_ARB) +{ + +} + + +void LLVertexBufferAvatar::setupVertexBuffer(U32 data_mask) const +{ + if (sRenderingSkinned) + { + U8* base = useVBOs() ? NULL : mMappedData; + + glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); + glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); + + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD])); + + set_vertex_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_WEIGHT], mStride, (F32*)(base + mOffsets[TYPE_WEIGHT])); + + if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_BUMP) + { + set_binormals(sVertexProgram->mAttribute[LLPipeline::GLSL_BINORMAL], mStride, (LLVector3*)(base + mOffsets[TYPE_BINORMAL])); + } + + if (sShaderLevel >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH) + { + set_vertex_clothing_weights(sVertexProgram->mAttribute[LLPipeline::GLSL_AVATAR_CLOTHING], mStride, (LLVector4*)(base + mOffsets[TYPE_CLOTHWEIGHT])); + } + } + else + { + LLVertexBuffer::setupVertexBuffer(data_mask); + } +} + diff --git a/linden/indra/newview/lldrawpoolavatar.h b/linden/indra/newview/lldrawpoolavatar.h index 52a7fe4..32c02b5 100644 --- a/linden/indra/newview/lldrawpoolavatar.h +++ b/linden/indra/newview/lldrawpoolavatar.h @@ -32,7 +32,7 @@ class LLVOAvatar; -class LLDrawPoolAvatar : public LLDrawPool +class LLDrawPoolAvatar : public LLFacePool { protected: S32 mNumFaces; @@ -43,21 +43,48 @@ public: SHADER_LEVEL_CLOTH = 3 }; + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_WEIGHT | + LLVertexBuffer::MAP_CLOTHWEIGHT | + LLVertexBuffer::MAP_BINORMAL + + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + + virtual S32 getVertexShaderLevel() const; + LLDrawPoolAvatar(); + static LLMatrix4& getModelView(); + /*virtual*/ LLDrawPool *instancePool(); + /*virtual*/ S32 getNumPasses(); + /*virtual*/ void beginRenderPass(S32 pass); + /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ void prerender(); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void renderForSelect(); - /*virtual*/ S32 rebuild(); + void beginRigid(); + void beginFootShadow(); + void beginSkinned(); + + void endRigid(); + void endFootShadow(); + void endSkinned(); + /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display virtual S32 getMaterialAttribIndex() { return 0; } - void renderAvatars(LLVOAvatar *single_avatar, BOOL no_shaders = FALSE); // renders only one avatar if single_avatar is not null. + void renderAvatars(LLVOAvatar *single_avatar, S32 pass = -1); // renders only one avatar if single_avatar is not null. }; diff --git a/linden/indra/newview/lldrawpoolbump.cpp b/linden/indra/newview/lldrawpoolbump.cpp index befcc70..916454c 100644 --- a/linden/indra/newview/lldrawpoolbump.cpp +++ b/linden/indra/newview/lldrawpoolbump.cpp @@ -37,12 +37,10 @@ #include "m4math.h" #include "llagent.h" -#include "llagparray.h" #include "llcubemap.h" #include "lldrawable.h" #include "lldrawpoolsimple.h" #include "llface.h" -#include "llgl.h" #include "llsky.h" #include "lltextureentry.h" #include "llviewercamera.h" @@ -64,9 +62,11 @@ LLBumpImageList gBumpImageList; const S32 STD_BUMP_LATEST_FILE_VERSION = 1; -S32 LLDrawPoolBump::sBumpTex = -1; -S32 LLDrawPoolBump::sDiffTex = -1; -S32 LLDrawPoolBump::sEnvTex = -1; +const U32 VERTEX_MASK_SHINY = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_COLOR; +const U32 VERTEX_MASK_BUMP = LLVertexBuffer::MAP_VERTEX |LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_TEXCOORD2; + +U32 LLDrawPoolBump::sVertexMask = VERTEX_MASK_SHINY; +static LLCubeMap* sCubeMap = NULL; // static void LLStandardBumpmap::init() @@ -89,7 +89,7 @@ void LLStandardBumpmap::restoreGL() gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount++] = LLStandardBumpmap("Darkness"); // BE_DARKNESS std::string file_name = gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "std_bump.ini" ); - FILE* file = LLFile::fopen( file_name.c_str(), "rt" ); + FILE* file = LLFile::fopen( file_name.c_str(), "rt" ); /*Flawfinder: ignore*/ if( !file ) { llwarns << "Could not open std_bump <" << file_name << ">" << llendl; @@ -114,9 +114,10 @@ void LLStandardBumpmap::restoreGL() while( !feof(file) && (LLStandardBumpmap::sStandardBumpmapCount < (U32)TEM_BUMPMAP_COUNT) ) { // *NOTE: This buffer size is hard coded into scanf() below. - char label[2048] = ""; - char bump_file[2048] = ""; - fields_read = fscanf( file, "\n%2047s %2047s", label, bump_file); + char label[2048] = ""; /* Flawfinder: ignore */ + char bump_file[2048] = ""; /* Flawfinder: ignore */ + fields_read = fscanf( /* Flawfinder: ignore */ + file, "\n%2047s %2047s", label, bump_file); if( EOF == fields_read ) { break; @@ -127,7 +128,7 @@ void LLStandardBumpmap::restoreGL() return; } - llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; +// llinfos << "Loading bumpmap: " << bump_file << " from viewerart" << llendl; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mLabel = label; gStandardBumpmapList[LLStandardBumpmap::sStandardBumpmapCount].mImage = gImageList.getImage( LLUUID(gViewerArt.getString(bump_file)) ); LLStandardBumpmap::sStandardBumpmapCount++; @@ -151,15 +152,9 @@ void LLStandardBumpmap::destroyGL() //////////////////////////////////////////////////////////////// -LLDrawPoolBump::LLDrawPoolBump(LLViewerImage *texturep) : - LLDrawPool(POOL_BUMP, DATA_BUMP_IL_MASK | DATA_COLORS_MASK, DATA_SIMPLE_NIL_MASK), - mTexturep(texturep) -{ -} - -LLDrawPool *LLDrawPoolBump::instancePool() +LLDrawPoolBump::LLDrawPoolBump() +: LLRenderPass(LLDrawPool::POOL_BUMP) { - return new LLDrawPoolBump(mTexturep); } @@ -168,51 +163,16 @@ void LLDrawPoolBump::prerender() mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT); } -BOOL LLDrawPoolBump::match(LLFace* last_face, LLFace* facep) -{ - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES) && - !last_face->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) && - !facep->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) && - facep->getIndicesStart() == last_face->getIndicesStart()+last_face->getIndicesCount() && - facep->getRenderColor() == last_face->getRenderColor() && - facep->getTextureEntry()->getShiny() == last_face->getTextureEntry()->getShiny() && - facep->getTextureEntry()->getBumpmap() == last_face->getTextureEntry()->getBumpmap()) - { - if (facep->isState(LLFace::GLOBAL)) - { - if (last_face->isState(LLFace::GLOBAL)) - { - return TRUE; - } - } - else - { - if (!last_face->isState(LLFace::GLOBAL)) - { - if (last_face->getRenderMatrix() == facep->getRenderMatrix()) - { - return TRUE; - } - } - } - } - - return FALSE; -} - // static S32 LLDrawPoolBump::numBumpPasses() { - if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) + if (gSavedSettings.getBOOL("RenderObjectBump")) { - return 1; // single pass for shaders + return 2; } - else + else { - if (gSavedSettings.getBOOL("RenderObjectBump")) - return 3; - else - return 1; + return 0; } } @@ -226,13 +186,10 @@ void LLDrawPoolBump::beginRenderPass(S32 pass) switch( pass ) { case 0: - beginPass0(this); + beginShiny(); break; case 1: - beginPass1(); - break; - case 2: - beginPass2(); + beginBump(); break; default: llassert(0); @@ -243,66 +200,17 @@ void LLDrawPoolBump::beginRenderPass(S32 pass) void LLDrawPoolBump::render(S32 pass) { LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); - if (!mTexturep) - { - return; - } - - if (mDrawFace.empty()) - { - return; - } - - const U32* index_array = getRawIndices(); - S32 indices = 0; switch( pass ) { case 0: { - stop_glerror(); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); - if (gPipeline.getLightingDetail() >= 2) - { - bindGLColorPointer(); - } - - stop_glerror(); - - LLGLState alpha_test(GL_ALPHA_TEST, FALSE); - LLGLState blend(GL_BLEND, FALSE); - LLViewerImage* tex = getTexture(); - if (tex && tex->getPrimaryFormat() == GL_ALPHA) - { - // Enable Invisibility Hack - alpha_test.enable(); - blend.enable(); - } - indices += renderPass0(this, mDrawFace, index_array, mTexturep); + renderShiny(); break; } case 1: { - bindGLVertexPointer(); - bindGLNormalPointer(); - indices += renderPass1(mDrawFace, index_array, mTexturep); - break; - } - case 2: - { - bindGLVertexPointer(); - // Texture unit 0 - glActiveTextureARB(GL_TEXTURE0_ARB); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - bindGLTexCoordPointer(); - // Texture unit 1 - glActiveTextureARB(GL_TEXTURE1_ARB); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - bindGLTexCoordPointer(1); - indices += renderPass2(mDrawFace, index_array, mTexturep); + renderBump(); break; } default: @@ -311,7 +219,6 @@ void LLDrawPoolBump::render(S32 pass) break; } } - mIndicesDrawn += indices; } void LLDrawPoolBump::endRenderPass(S32 pass) @@ -319,13 +226,10 @@ void LLDrawPoolBump::endRenderPass(S32 pass) switch( pass ) { case 0: - endPass0(this); + endShiny(); break; case 1: - endPass1(); - break; - case 2: - endPass2(); + endBump(); break; default: llassert(0); @@ -334,252 +238,171 @@ void LLDrawPoolBump::endRenderPass(S32 pass) } //static -void LLDrawPoolBump::beginPass0(LLDrawPool* pool) +void LLDrawPoolBump::beginShiny() { - stop_glerror(); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); + sVertexMask = VERTEX_MASK_SHINY; + // Second pass: environment map glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - if (gPipeline.getLightingDetail() >= 2) - { - glEnableClientState(GL_COLOR_ARRAY); - } + glEnableClientState(GL_COLOR_ARRAY); - if (pool->getVertexShaderLevel() > 0) + LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); + if( cube_map ) { - enable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]); + cube_map->enable(0); + cube_map->setMatrix(0); + cube_map->bind(); - sEnvTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (sEnvTex >= 0 && cube_map) + if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) { - cube_map->bind(); - cube_map->setMatrix(1); + LLMatrix4 mat; + glGetFloatv(GL_MODELVIEW_MATRIX, (F32*) mat.mMatrix); + gPipeline.mObjectShinyProgram.bind(); + LLVector3 vec = LLVector3(gPipeline.mShinyOrigin) * mat; + LLVector4 vec4(vec, gPipeline.mShinyOrigin.mV[3]); + glUniform4fvARB(gPipeline.mObjectShinyProgram.mUniform[LLPipeline::GLSL_SHINY_ORIGIN], 1, + vec4.mV); + } + else + { + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + + //use RGB from texture + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); + + // use alpha from color + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); } - - sBumpTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP); - sDiffTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - S32 scatterTex = gPipeline.mObjectBumpProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); } - stop_glerror(); } -//static -S32 LLDrawPoolBump::renderPass0(LLDrawPool* pool, face_array_t& face_list, const U32* index_array, LLViewerImage* tex) +void LLDrawPoolBump::renderShiny() { - if (!tex) - { - return 0; - } + LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (face_list.empty()) + sCubeMap = NULL; + + if( gSky.mVOSkyp->getCubeMap() ) { - return 0; + LLGLEnable blend_enable(GL_BLEND); + renderStatic(LLRenderPass::PASS_SHINY, sVertexMask); + renderActive(LLRenderPass::PASS_SHINY, sVertexMask); } +} - stop_glerror(); +void LLDrawPoolBump::renderActive(U32 type, U32 mask, BOOL texture) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif - S32 res = 0; - if (pool->getVertexShaderLevel() > 0) + LLSpatialBridge* last_bridge = NULL; + glPushMatrix(); + + for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i) { - LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); - pool->bindGLBinormalPointer(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]); - - LLViewerImage::bindTexture(tex, sDiffTex); - - //single pass shader driven shiny/bump - LLGLDisable(GL_ALPHA_TEST); - - LLViewerImage::sWhiteImagep->bind(sBumpTex); - - GLfloat alpha[4] = + LLSpatialGroup* group = *i; + if (!group->isDead() && + gPipeline.hasRenderType(group->mSpatialPartition->mDrawableType) && + group->mDrawMap.find(type) != group->mDrawMap.end()) { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - - LLImageGL* last_bump = NULL; - - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - if (facep->mSkipRender) - { - continue; - } - - const LLTextureEntry* te = facep->getTextureEntry(); - if (te) + LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition; + if (bridge != last_bridge) { - U8 index = te->getShiny(); - LLColor4 col = te->getColor(); - - gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR, - col.mV[0], col.mV[1], col.mV[2], alpha[index]); - gPipeline.mObjectBumpProgram.vertexAttrib4f(LLPipeline::GLSL_SPECULAR_COLOR, - alpha[index], alpha[index], alpha[index], alpha[index]); - - LLImageGL* bump = getBumpMap(te, tex); - if (bump != last_bump) + glPopMatrix(); + glPushMatrix(); + glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); + last_bridge = bridge; + + if (LLPipeline::sDynamicReflections) { - if (bump) + LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME); + LLSpatialGroup::OctreeNode* node = part->mOctree->getNodeAt(LLVector3d(bridge->mDrawable->getPositionAgent()), 32.0); + if (node) { - bump->bind(sBumpTex); - } - else - { - LLViewerImage::sWhiteImagep->bind(sBumpTex); + sCubeMap = ((LLSpatialGroup*) node->getListener(0))->mReflectionMap; } } - last_bump = bump; - - // Draw the geometry - facep->enableLights(); - res += facep->renderIndexed(index_array); - stop_glerror(); - } - else - { - llwarns << "DrawPoolBump has face with invalid texture entry." << llendl; } - } - } - else - { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); - LLViewerImage::bindTexture(tex); - res = LLDrawPool::drawLoop(face_list, index_array); - } - return res; -} - -//static -void LLDrawPoolBump::endPass0(LLDrawPool* pool) -{ - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_COLOR_ARRAY); - if (pool->getVertexShaderLevel() > 0) - { - gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (sEnvTex >= 0 && cube_map) - { - cube_map->restoreMatrix(); + renderGroup(group,type,mask,texture); } - - gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP); - gPipeline.mObjectBumpProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - - disable_binormals(gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_BINORMAL]); - - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); } + + glPopMatrix(); } -//static -void LLDrawPoolBump::beginPass1() -{ - // Second pass: environment map - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if( cube_map ) - { - cube_map->enable(0); - cube_map->setMatrix(0); - cube_map->bind(); - } -} - -//static -S32 LLDrawPoolBump::renderPass1(face_array_t& face_list, const U32* index_array, LLViewerImage* tex) -{ - LLFastTimer t(LLFastTimer::FTM_RENDER_SHINY); - if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0 - { - return 0; - } - - S32 res = 0; - if( gSky.mVOSkyp->getCubeMap() ) +void LLDrawPoolBump::renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture = TRUE) +{ + std::vector& draw_info = group->mDrawMap[type]; + + for (std::vector::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) { - //LLGLSPipelineAlpha gls; - //LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL); - LLGLEnable blend_enable(GL_BLEND); - - GLfloat alpha[4] = + LLDrawInfo& params = **k; + if (LLPipeline::sDynamicReflections) { - 0.00f, - 0.25f, - 0.5f, - 0.75f - }; - - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - if (facep->mSkipRender) + if (params.mReflectionMap.notNull()) { - continue; + params.mReflectionMap->bind(); } - - const LLTextureEntry* te = facep->getTextureEntry(); - if (te) + else { - U8 index = te->getShiny(); - if( index > 0 ) + if (sCubeMap) { - LLOverrideFaceColor override_color(facep->getPool(), 1, 1, 1, alpha[index]); - - // Draw the geometry - facep->enableLights(); - res += facep->renderIndexed(index_array); - stop_glerror(); + sCubeMap->bind(); + } + else + { + gSky.mVOSkyp->getCubeMap()->bind(); } - } - else - { - llwarns << "DrawPoolBump has face with invalid texture entry." << llendl; } } + + params.mVertexBuffer->setBuffer(mask); + U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + gPipeline.mTrianglesDrawn += params.mCount/3; } - return res; } -//static -void LLDrawPoolBump::endPass1() +void LLDrawPoolBump::endShiny() { LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); if( cube_map ) { cube_map->disable(); cube_map->restoreMatrix(); + + if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) + { + gPipeline.mObjectShinyProgram.unbind(); + } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); } // static -LLImageGL* LLDrawPoolBump::getBumpMap(const LLTextureEntry* te, LLViewerImage* tex) +BOOL LLDrawPoolBump::bindBumpMap(LLDrawInfo& params) { - U32 bump_code = te->getBumpmap(); LLImageGL* bump = NULL; + U8 bump_code = params.mBump; + LLViewerImage* tex = params.mTexture; + switch( bump_code ) { case BE_NO_BUMP: @@ -597,28 +420,33 @@ LLImageGL* LLDrawPoolBump::getBumpMap(const LLTextureEntry* te, LLViewerImage* t if( bump_code < LLStandardBumpmap::sStandardBumpmapCount ) { bump = gStandardBumpmapList[bump_code].mImage; + gBumpImageList.addTextureStats(bump_code, tex->getID(), params.mVSize, 1, 1); } break; } - return bump; + if (bump) + { + bump->bind(1); + bump->bind(0); + return TRUE; + } + return FALSE; } //static -void LLDrawPoolBump::beginPass2() +void LLDrawPoolBump::beginBump() { + sVertexMask = VERTEX_MASK_BUMP; LLFastTimer t(LLFastTimer::FTM_RENDER_BUMP); - // Optional third pass: emboss bump map + // Optional second pass: emboss bump map stop_glerror(); // TEXTURE UNIT 0 // Output.rgb = texture at texture coord 0 glActiveTextureARB(GL_TEXTURE0_ARB); glClientActiveTextureARB(GL_TEXTURE0_ARB); - - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); @@ -631,14 +459,10 @@ void LLDrawPoolBump::beginPass2() glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - // TEXTURE UNIT 1 glActiveTextureARB(GL_TEXTURE1_ARB); glClientActiveTextureARB(GL_TEXTURE1_ARB); - - glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); glEnable(GL_TEXTURE_2D); // Texture unit 1 @@ -668,68 +492,25 @@ void LLDrawPoolBump::beginPass2() // = dst.rgb + dst.rgb * (bump0 - bump1) glBlendFunc(GL_DST_COLOR, GL_SRC_COLOR); // glBlendFunc(GL_ONE, GL_ZERO); // temp - + glActiveTextureARB(GL_TEXTURE0_ARB); stop_glerror(); } //static -S32 LLDrawPoolBump::renderPass2(face_array_t& face_list, const U32* index_array, LLViewerImage* tex) +void LLDrawPoolBump::renderBump() { - if (gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) > 0) //everything happens in pass0 - { - return 0; - } - + LLFastTimer ftm(LLFastTimer::FTM_RENDER_BUMP); LLGLDisable fog(GL_FOG); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_EQUAL); LLGLEnable tex2d(GL_TEXTURE_2D); LLGLEnable blend(GL_BLEND); - S32 res = 0; - - LLImageGL* last_bump = NULL; - - for (std::vector::iterator iter = face_list.begin(); - iter != face_list.end(); iter++) - { - LLFace *facep = *iter; - if (facep->mSkipRender) - { - continue; - } - LLOverrideFaceColor override_color(facep->getPool(), 1,1,1,1); - - const LLTextureEntry* te = facep->getTextureEntry(); - LLImageGL* bump = getBumpMap(te, tex); - - if( bump ) - { - if( bump != last_bump ) - { - last_bump = bump; - - // Texture unit 0 - bump->bind(0); - stop_glerror(); - - // Texture unit 1 - bump->bind(1); - stop_glerror(); - } - - // Draw the geometry - res += facep->renderIndexed(index_array); - stop_glerror(); - } - else - { -// llwarns << "Skipping invalid bump code " << (S32) te->getBumpmap() << llendl; - } - } - return res; + glColor4f(1,1,1,1); + renderBump(LLRenderPass::PASS_BUMP, sVertexMask); + renderBumpActive(LLRenderPass::PASS_BUMP, sVertexMask); } //static -void LLDrawPoolBump::endPass2() +void LLDrawPoolBump::endBump() { // Disable texture unit 1 glActiveTextureARB(GL_TEXTURE1_ARB); @@ -747,67 +528,6 @@ void LLDrawPoolBump::endPass2() glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } - -void LLDrawPoolBump::renderForSelect() -{ - if (mDrawFace.empty() || !mMemory.count()) - { - return; - } - - glEnableClientState ( GL_VERTEX_ARRAY ); - - bindGLVertexPointer(); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - if (facep->getDrawable() && !facep->getDrawable()->isDead() && (facep->getViewerObject()->mGLName)) - { - facep->renderForSelect(); - } - } -} - - -void LLDrawPoolBump::renderFaceSelected(LLFace *facep, - LLImageGL *image, - const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ - facep->renderSelected(image, color, index_offset, index_count); -} - - -void LLDrawPoolBump::dirtyTexture(const LLViewerImage *texturep) -{ - if (mTexturep == texturep) - { - for (std::vector::iterator iter = mReferences.begin(); - iter != mReferences.end(); iter++) - { - LLFace *facep = *iter; - gPipeline.markTextured(facep->getDrawable()); - } - } -} - -LLViewerImage *LLDrawPoolBump::getTexture() -{ - return mTexturep; -} - -LLViewerImage *LLDrawPoolBump::getDebugTexture() -{ - return mTexturep; -} - -LLColor3 LLDrawPoolBump::getDebugColor() const -{ - return LLColor3(1.f, 1.f, 0.f); -} - //////////////////////////////////////////////////////////////// // List of one-component bump-maps created from other texures. @@ -1131,25 +851,93 @@ void LLBumpImageList::onSourceLoaded( BOOL success, LLViewerImage *src_vi, LLIma } } -S32 LLDrawPoolBump::getMaterialAttribIndex() +void LLDrawPoolBump::renderBumpActive(U32 type, U32 mask) { - return gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif + + LLSpatialBridge* last_bridge = NULL; + glPushMatrix(); + + for (LLSpatialGroup::sg_vector_t::iterator i = gPipeline.mActiveGroups.begin(); i != gPipeline.mActiveGroups.end(); ++i) + { + LLSpatialGroup* group = *i; + if (!group->isDead() && + group->mSpatialPartition->mRenderByGroup && + group->mDrawMap.find(type) != group->mDrawMap.end()) + { + LLSpatialBridge* bridge = (LLSpatialBridge*) group->mSpatialPartition; + if (bridge != last_bridge) + { + glPopMatrix(); + glPushMatrix(); + glMultMatrixf((F32*) bridge->mDrawable->getRenderMatrix().mMatrix); + last_bridge = bridge; + } + + renderGroupBump(group,type,mask); + } + } + + glPopMatrix(); } -// virtual -void LLDrawPoolBump::enableShade() -{ - glDisableClientState(GL_COLOR_ARRAY); +void LLDrawPoolBump::renderBump(U32 type, U32 mask) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(mask); +#endif + + std::vector& draw_info = gPipeline.mRenderMap[type]; + + for (std::vector::iterator i = draw_info.begin(); i != draw_info.end(); ++i) + { + LLDrawInfo& params = **i; + + if (LLDrawPoolBump::bindBumpMap(params)) + { + pushBatch(params, mask, FALSE); + } + } } -// virtual -void LLDrawPoolBump::disableShade() -{ - glEnableClientState(GL_COLOR_ARRAY); +void LLDrawPoolBump::renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask) +{ + const std::vector& draw_info = group->mDrawMap[type]; + + for (std::vector::const_iterator k = draw_info.begin(); k != draw_info.end(); ++k) + { + LLDrawInfo& params = **k; + + if (LLDrawPoolBump::bindBumpMap(params)) + { + pushBatch(params, mask, FALSE); + } + } } -// virtual -void LLDrawPoolBump::setShade(F32 shade) +void LLDrawPoolBump::pushBatch(LLDrawInfo& params, U32 mask, BOOL texture) { - glColor4f(0,0,0,shade); + if (params.mTextureMatrix) + { + glActiveTextureARB(GL_TEXTURE1_ARB); + glMatrixMode(GL_TEXTURE); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + glActiveTextureARB(GL_TEXTURE0_ARB); + glLoadMatrixf((GLfloat*) params.mTextureMatrix->mMatrix); + } + params.mVertexBuffer->setBuffer(mask); + U32* indices_pointer = (U32*) params.mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(GL_TRIANGLES, params.mStart, params.mEnd, params.mCount, + GL_UNSIGNED_INT, indices_pointer+params.mOffset); + gPipeline.mTrianglesDrawn += params.mCount/3; + if (params.mTextureMatrix) + { + glActiveTextureARB(GL_TEXTURE1_ARB); + glLoadIdentity(); + glActiveTextureARB(GL_TEXTURE0_ARB); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + } } diff --git a/linden/indra/newview/lldrawpoolbump.h b/linden/indra/newview/lldrawpoolbump.h index 4f181bc..bb8de40 100644 --- a/linden/indra/newview/lldrawpoolbump.h +++ b/linden/indra/newview/lldrawpoolbump.h @@ -34,57 +34,41 @@ #include "lluuid.h" class LLImageRaw; +class LLSpatialGroup; +class LLDrawInfo; -class LLDrawPoolBump : public LLDrawPool +class LLDrawPoolBump : public LLRenderPass { -protected: - LLPointer mTexturep; // The primary texture, not the bump texture - public: - LLDrawPoolBump(LLViewerImage *texturep); + static U32 sVertexMask; + + virtual U32 getVertexDataMask() { return sVertexMask; } - /*virtual*/ LLDrawPool *instancePool(); + LLDrawPoolBump(); /*virtual*/ void render(S32 pass = 0); /*virtual*/ void beginRenderPass( S32 pass ); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ S32 getNumPasses(); - /*virtual*/ void renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0); /*virtual*/ void prerender(); - /*virtual*/ void renderForSelect(); - /*virtual*/ void dirtyTexture(const LLViewerImage *texturep); - /*virtual*/ LLViewerImage *getTexture(); - /*virtual*/ LLViewerImage *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - /*virtual*/ BOOL match(LLFace* last_face, LLFace* facep); + /*virtual*/ void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture); + + void renderBump(U32 type, U32 mask); + void renderBumpActive(U32 type, U32 mask); + void renderGroup(LLSpatialGroup* group, U32 type, U32 mask, BOOL texture); + void renderGroupBump(LLSpatialGroup* group, U32 type, U32 mask); - virtual S32 getMaterialAttribIndex(); - static S32 numBumpPasses(); + S32 numBumpPasses(); - static void beginPass0(LLDrawPool* pool); - static S32 renderPass0(LLDrawPool* pool, face_array_t& face_list, const U32* index_array, LLViewerImage* tex); - static void endPass0(LLDrawPool* pool); - - static void beginPass1(); - static S32 renderPass1(face_array_t& face_list, const U32* index_array, LLViewerImage* tex); - static void endPass1(); - - static void beginPass2(); - static S32 renderPass2(face_array_t& face_list, const U32* index_array, LLViewerImage* tex); - static void endPass2(); - - /*virtual*/ void enableShade(); - /*virtual*/ void disableShade(); - /*virtual*/ void setShade(F32 shade); - -protected: - static LLImageGL* getBumpMap(const LLTextureEntry* te, LLViewerImage* tex); - -public: - static S32 sBumpTex; - static S32 sDiffTex; - static S32 sEnvTex; + void beginShiny(); + void renderShiny(); + void endShiny(); + void renderActive(U32 type, U32 mask, BOOL texture = TRUE); + + void beginBump(); + void renderBump(); + void endBump(); + BOOL bindBumpMap(LLDrawInfo& params); }; enum EBumpEffect diff --git a/linden/indra/newview/lldrawpoolclouds.cpp b/linden/indra/newview/lldrawpoolclouds.cpp index 7d877ee..83ef2b3 100644 --- a/linden/indra/newview/lldrawpoolclouds.cpp +++ b/linden/indra/newview/lldrawpoolclouds.cpp @@ -36,7 +36,7 @@ #include "pipeline.h" LLDrawPoolClouds::LLDrawPoolClouds() : - LLDrawPool(POOL_CLOUDS, DATA_SIMPLE_IL_MASK, 0) + LLDrawPool(POOL_CLOUDS) { } @@ -45,16 +45,15 @@ LLDrawPool *LLDrawPoolClouds::instancePool() return new LLDrawPoolClouds(); } +BOOL LLDrawPoolClouds::addFace(LLFace* face) +{ + llerrs << "WTF?" << llendl; + return FALSE; +} + void LLDrawPoolClouds::enqueue(LLFace *facep) { - if (facep->isState(LLFace::BACKLIST)) - { - mMoveFace.put(facep); - } - else - { - mDrawFace.push_back(facep); - } + mDrawFace.push_back(facep); facep->mDistance = (facep->mCenterAgent - gCamera->getOrigin()) * gCamera->getAtAxis(); } @@ -90,10 +89,6 @@ void LLDrawPoolClouds::render(S32 pass) gPipeline.enableLightsFullbright(LLColor4(1.f,1.f,1.f)); mDrawFace[0]->bindTexture(); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); diff --git a/linden/indra/newview/lldrawpoolclouds.h b/linden/indra/newview/lldrawpoolclouds.h index e47f66d..795b0a6 100644 --- a/linden/indra/newview/lldrawpoolclouds.h +++ b/linden/indra/newview/lldrawpoolclouds.h @@ -33,6 +33,16 @@ class LLDrawPoolClouds : public LLDrawPool { public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD + }; + + BOOL addFace(LLFace* face); + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolClouds(); /*virtual*/ void prerender(); diff --git a/linden/indra/newview/lldrawpoolground.cpp b/linden/indra/newview/lldrawpoolground.cpp index f2f2002..bc66757 100644 --- a/linden/indra/newview/lldrawpoolground.cpp +++ b/linden/indra/newview/lldrawpoolground.cpp @@ -31,7 +31,6 @@ #include "llviewercontrol.h" -#include "llagparray.h" #include "lldrawable.h" #include "llface.h" #include "llsky.h" @@ -39,9 +38,11 @@ #include "llviewerwindow.h" #include "llworld.h" #include "pipeline.h" +#include "llagent.h" +#include "llviewerregion.h" LLDrawPoolGround::LLDrawPoolGround() : - LLDrawPool(POOL_GROUND, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK) + LLFacePool(POOL_GROUND) { } @@ -60,42 +61,38 @@ void LLDrawPoolGround::render(S32 pass) if (mDrawFace.empty()) { return; - } - + } + glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); LLGLSPipelineSkyBox gls_skybox; + LLGLDisable tex(GL_TEXTURE_2D); LLGLDepthTest gls_depth(GL_FALSE, GL_FALSE); glMatrixMode( GL_PROJECTION ); - + glPushMatrix(); - gViewerWindow->setup3DRender(); + //gViewerWindow->setup3DRender(); glMatrixMode(GL_MODELVIEW); - LLGLState tex2d(GL_TEXTURE_2D, (mVertexShaderLevel > 0) ? TRUE : FALSE); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), 0); + F32 water_height = gAgent.getRegion()->getWaterHeight(); + glPushMatrix(); + LLVector3 origin = gCamera->getOrigin(); + glTranslatef(origin.mV[0], origin.mV[1], llmax(origin.mV[2], water_height)); LLFace *facep = mDrawFace[0]; - if (!(mVertexShaderLevel > 0)) - { - gPipeline.disableLights(); - } - - glColor4fv(facep->getFaceColor().mV); + gPipeline.disableLights(); - facep->renderIndexed(getRawIndices()); + LLOverrideFaceColor col(this, gSky.mVOSkyp->getGLFogColor()); + facep->renderIndexed(); glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); } void LLDrawPoolGround::renderForSelect() diff --git a/linden/indra/newview/lldrawpoolground.h b/linden/indra/newview/lldrawpoolground.h index 1866746..6bf358e 100644 --- a/linden/indra/newview/lldrawpoolground.h +++ b/linden/indra/newview/lldrawpoolground.h @@ -31,9 +31,17 @@ #include "lldrawpool.h" -class LLDrawPoolGround : public LLDrawPool +class LLDrawPoolGround : public LLFacePool { public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolGround(); /*virtual*/ LLDrawPool *instancePool(); diff --git a/linden/indra/newview/lldrawpoolhud.cpp b/linden/indra/newview/lldrawpoolhud.cpp deleted file mode 100644 index e2bb1bf..0000000 --- a/linden/indra/newview/lldrawpoolhud.cpp +++ /dev/null @@ -1,565 +0,0 @@ -/** - * @file lldrawpoolhud.cpp - * @brief LLDrawPoolHUD class implementation - * - * Copyright (c) 2006-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "lldrawpoolhud.h" - -#include "llagparray.h" -#include "llagent.h" -#include "llbbox.h" -#include "llcubemap.h" -#include "lldrawable.h" -#include "lldrawpoolalpha.h" -#include "lldrawpoolbump.h" -#include "llface.h" -#include "llhudtext.h" -#include "llsky.h" -#include "lltoolmgr.h" -#include "llvoavatar.h" -#include "llviewercamera.h" -#include "llviewerobjectlist.h" -#include "llviewerwindow.h" -#include "pipeline.h" - -BOOL LLDrawPoolHUD::sShowHUDAttachments = TRUE; - -LLDrawPoolHUD::LLDrawPoolHUD() : - LLDrawPool(POOL_HUD, - DATA_BUMP_IL_MASK | DATA_COLORS_MASK, // HUD objects may be bumpmapped - DATA_SIMPLE_NIL_MASK), - mRenderMode(POOL_SIMPLE) -{ -} - -LLDrawPool* LLDrawPoolHUD::instancePool() -{ - return new LLDrawPoolHUD(); -} - - -void LLDrawPoolHUD::prerender() -{ - mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT); -} - -void LLDrawPoolHUD::beginRenderPass(S32 pass) -{ -} - -static BOOL setup_matrices(BOOL for_select) -{ - LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); - if (my_avatarp && my_avatarp->hasHUDAttachment()) - { - if (!for_select) - { - // clamp target zoom level to reasonable values - my_avatarp->mHUDTargetZoom = llclamp(my_avatarp->mHUDTargetZoom, 0.1f, 1.f); - // smoothly interpolate current zoom level - my_avatarp->mHUDCurZoom = lerp(my_avatarp->mHUDCurZoom, my_avatarp->mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); - } - - F32 zoom_level = my_avatarp->mHUDCurZoom; - // clear z buffer and set up transform for hud - if (!for_select) - { - glClear(GL_DEPTH_BUFFER_BIT); - } - LLBBox hud_bbox = my_avatarp->getHUDBBox(); - - // set up transform to encompass bounding box of HUD - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); - if (for_select) - { - //RN: reset viewport to window extents so ortho screen is calculated with proper reference frame - gViewerWindow->setupViewport(); - } - glOrtho(-0.5f * gCamera->getAspect(), 0.5f * gCamera->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); - - // apply camera zoom transform (for high res screenshots) - F32 zoom_factor = gCamera->getZoomFactor(); - S16 sub_region = gCamera->getZoomSubRegion(); - if (zoom_factor > 1.f) - { - float offset = zoom_factor - 1.f; - int pos_y = sub_region / llceil(zoom_factor); - int pos_x = sub_region - (pos_y*llceil(zoom_factor)); - glTranslatef(gCamera->getAspect() * 0.5f * (offset - (F32)pos_x * 2.f), 0.5f * (offset - (F32)pos_y * 2.f), 0.f); - glScalef(zoom_factor, zoom_factor, 1.f); - } - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame - glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f); - glScalef(zoom_level, zoom_level, zoom_level); - - return TRUE; - } - else - { - return FALSE; - } -} - -static void restore_matrices() -{ - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - - -void LLDrawPoolHUD::render(S32 pass) -{ - LLFastTimer ftm(LLFastTimer::FTM_RENDER_HUD); - if (!sShowHUDAttachments) - { - return; - } - - if (mDrawFace.empty() && mAlphaFace.empty() && mBumpFaces.empty()) - { - return; - } - - if (!setup_matrices(FALSE)) - { - return; - } - - const U32* index_array = getRawIndices(); - - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(); - - S32 diffTex = 0; - S32 envTex = -1; - // Non alpha faces - if (!mDrawFace.empty()) - { - mRenderMode = POOL_SIMPLE; - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectSimpleProgram.bind(); - S32 scatterTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - diffTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - } - - LLGLEnable blend(GL_BLEND); // for invisi-prim hack, I think - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glActiveTextureARB(GL_TEXTURE0_ARB); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - // Render - mIndicesDrawn += drawLoopSetTex(mDrawFace, index_array, diffTex); - - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - } - } - - // Bump Mapped Faces - if (!mBumpFaces.empty()) - { - mRenderMode = POOL_BUMP; - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectBumpProgram.bind(); - } - - S32 bump_passes = LLDrawPoolBump::numBumpPasses(); - if (bump_passes >= 1) - { - // Texture unit 0 - LLDrawPoolBump::beginPass0(this); - for (bump_face_map_t::iterator iter = mBumpFaces.begin(); - iter != mBumpFaces.end(); iter++) - { - LLViewerImage* tex = iter->first; - face_array_t& faces = iter->second; - mIndicesDrawn += LLDrawPoolBump::renderPass0(this, faces, index_array, tex); - } - LLDrawPoolBump::endPass0(this); - } - - if (bump_passes >= 2) - { - LLDrawPoolBump::beginPass1(); - for (bump_face_map_t::iterator iter = mBumpFaces.begin(); - iter != mBumpFaces.end(); iter++) - { - LLViewerImage* tex = iter->first; - face_array_t& faces = iter->second; - mIndicesDrawn += LLDrawPoolBump::renderPass1(faces, index_array, tex); - } - LLDrawPoolBump::endPass1(); - } - - if (bump_passes >= 3) - { - bindGLVertexPointer(); - // Texture unit 0 - glActiveTextureARB(GL_TEXTURE0_ARB); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - bindGLTexCoordPointer(); - // Texture unit 1 - glActiveTextureARB(GL_TEXTURE1_ARB); - glClientActiveTextureARB(GL_TEXTURE1_ARB); - bindGLTexCoordPointer(1); - LLDrawPoolBump::beginPass2(); - for (bump_face_map_t::iterator iter = mBumpFaces.begin(); - iter != mBumpFaces.end(); iter++) - { - LLViewerImage* tex = iter->first; - face_array_t& faces = iter->second; - mIndicesDrawn += LLDrawPoolBump::renderPass2(faces, index_array, tex); - } - LLDrawPoolBump::endPass2(); - } - } - - // Alpha faces - if (!mAlphaFace.empty()) - { - // Sort - std::sort(mAlphaFace.begin(), mAlphaFace.end(), LLFace::CompareDistanceGreater()); - - // Render - mRenderMode = POOL_ALPHA; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - glActiveTextureARB(GL_TEXTURE0_ARB); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectAlphaProgram.bind(); - envTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (envTex >= 0 && cube_map) - { - cube_map->bind(); - cube_map->setMatrix(1); - } - - GLint specularIndex = gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_SPECULAR_COLOR]; - if (specularIndex > 0) - { - glVertexAttrib4fARB(specularIndex, 0, 0, 0, 0); - } - - S32 scatterTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - - diffTex = gPipeline.mObjectAlphaProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - } - - LLGLEnable blend(GL_BLEND); - LLGLSPipelineAlpha alphastate; - mIndicesDrawn += drawLoopSetTex(mAlphaFace, index_array, diffTex); - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); - LLCubeMap* cube_map = gSky.mVOSkyp->getCubeMap(); - if (envTex >= 0 && cube_map) - { - cube_map->restoreMatrix(); - } - - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectAlphaProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); - } - - if (LLDrawPoolAlpha::sShowDebugAlpha) - { - gPipeline.disableLights(); - if ((mVertexShaderLevel > 0)) - { - gPipeline.mHighlightProgram.bind(); - gPipeline.mHighlightProgram.vertexAttrib4f(LLPipeline::GLSL_MATERIAL_COLOR,1,0,0,1); - } - - LLViewerImage::sSmokeImagep->bind(); - LLOverrideFaceColor override_color(this, 1.f, 0.f, 0.f, 1.f); - glDisableClientState(GL_COLOR_ARRAY); - - for (std::vector::iterator iter = mAlphaFace.begin(); - iter != mAlphaFace.end(); iter++) - { - LLFace *facep = *iter; - facep->renderIndexed(index_array); - } - - if ((mVertexShaderLevel > 0)) - { - gPipeline.mHighlightProgram.unbind(); - } - } - } - - glDisableClientState(GL_NORMAL_ARRAY); - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); - glClientActiveTextureARB(GL_TEXTURE0_ARB); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - if ((mVertexShaderLevel > 0)) - { - glUseProgramObjectARB(0); - } - - LLHUDText::renderAllHUD(); - restore_matrices(); -} - -void LLDrawPoolHUD::endRenderPass(S32 pass) -{ -} - -void LLDrawPoolHUD::renderForSelect() -{ - if (!sShowHUDAttachments) - { - return; - } - - if (!gToolMgr->inEdit() && (gKeyboard->currentMask(TRUE) & MASK_ALT)) - { - return; - } - - if ((mDrawFace.empty() && mAlphaFace.empty() && mBumpFaces.empty()) || !mMemory.count()) - { - return; - } - - if (!setup_matrices(TRUE)) - { - return; - } - - glEnableClientState ( GL_VERTEX_ARRAY ); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - bindGLVertexPointer(); - - LLGLSObjectSelect gls_objectselect; - LLGLDepthTest gls_depth(GL_TRUE); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - LLDrawable *drawable = facep->getDrawable(); - if (drawable && !drawable->isDead() && facep->getViewerObject() && facep->getViewerObject()->mGLName) - { - facep->renderForSelect(); - } - } - - for (bump_face_map_t::iterator iter = mBumpFaces.begin(); - iter != mBumpFaces.end(); iter++) - { - face_array_t& faces = iter->second; - for (std::vector::iterator iter = faces.begin(); - iter != faces.end(); iter++) - { - LLFace *facep = *iter; - LLDrawable *drawable = facep->getDrawable(); - if (drawable && !drawable->isDead() && facep->getViewerObject() && facep->getViewerObject()->mGLName) - { - facep->renderForSelect(); - } - } - } - - // ALPHA - { - glEnableClientState (GL_VERTEX_ARRAY); - glEnableClientState (GL_TEXTURE_COORD_ARRAY); - - LLGLSObjectSelectAlpha* gls_selectalpha = NULL; - if (!LLDrawPoolAlpha::sShowDebugAlpha) - { - gls_selectalpha = new LLGLSObjectSelectAlpha; - } - - glBlendFunc(GL_ONE, GL_ZERO); - glAlphaFunc(gPickTransparent ? GL_GEQUAL : GL_GREATER, 0.0f); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); - glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - - glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PREVIOUS); - glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA); - - for (std::vector::iterator iter = mAlphaFace.begin(); - iter != mAlphaFace.end(); iter++) - { - LLFace *facep = *iter; - LLDrawable *drawable = facep->getDrawable(); - if (drawable && !drawable->isDead() && facep->getViewerObject() && facep->getViewerObject()->mGLName) - { - facep->bindTexture(); - facep->renderForSelect(); - } - } - - glAlphaFunc(GL_GREATER, 0.01f); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - - glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); - - glDisableClientState (GL_VERTEX_ARRAY); - glDisableClientState (GL_TEXTURE_COORD_ARRAY); - - delete gls_selectalpha; - } - - restore_matrices(); -} - - -void LLDrawPoolHUD::renderFaceSelected(LLFace *facep, LLImageGL *image, const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ - facep->renderSelected(image, color, index_offset, index_count); -} - -void LLDrawPoolHUD::resetDrawOrders() -{ - LLDrawPool::resetDrawOrders(); - mBumpFaces.clear(); - mAlphaFace.clear(); -} - -void LLDrawPoolHUD::dirtyTexture(const LLViewerImage *texturep) -{ - for (std::vector::iterator iter = mReferences.begin(); - iter != mReferences.end(); iter++) - { - LLFace *facep = *iter; - if (facep->getTexture() == texturep) - { - gPipeline.markTextured(facep->getDrawable()); - } - } -} - -void LLDrawPoolHUD::enqueue(LLFace *facep) -{ - if (facep->isState(LLFace::BACKLIST)) - { - mMoveFace.put(facep); - } - else - { - const LLTextureEntry* te = facep->getTextureEntry(); - LLViewerImage* imagep = facep->getTexture(); - bool alpha = te->getColor().mV[3] < 0.999f; - alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2); - if (alpha) - { - mAlphaFace.push_back(facep); - } - else if ((te->getBumpmap() || te->getShiny())) - { - mBumpFaces[imagep].push_back(facep); - } - else - { - mDrawFace.push_back(facep); - } - } - facep->mDistance = facep->mCenterAgent[VX]; -} - -// virtual -BOOL LLDrawPoolHUD::addFace(LLFace *facep) -{ - facep->setState(LLFace::HUD_RENDER); - return LLDrawPool::addFace(facep); -} - -// virtual -BOOL LLDrawPoolHUD::removeFace(LLFace *facep) -{ - facep->clearState(LLFace::HUD_RENDER); - return LLDrawPool::removeFace(facep); -} - -LLColor3 LLDrawPoolHUD::getDebugColor() const -{ - return LLColor3(1.f, 0.5f, 0.5f); -} - -S32 LLDrawPoolHUD::getMaterialAttribIndex() -{ - switch (mRenderMode) - { - case POOL_BUMP: - return gPipeline.mObjectBumpProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; - case POOL_ALPHA: - return gPipeline.mObjectAlphaProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; - case POOL_SIMPLE: - return gPipeline.mObjectSimpleProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; - default: - return 0; - break; - } -} diff --git a/linden/indra/newview/lldrawpoolhud.h b/linden/indra/newview/lldrawpoolhud.h deleted file mode 100644 index 3f57bf7..0000000 --- a/linden/indra/newview/lldrawpoolhud.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file lldrawpoolhud.h - * @brief LLDrawPoolHUD class definition - * - * Copyright (c) 2006-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLDRAWPOOLHUD_H -#define LL_LLDRAWPOOLHUD_H - -#include "lldrawpool.h" - -class LLDrawPoolHUD : public LLDrawPool -{ -public: - LLDrawPoolHUD(); -// /*virtual*/ ~LLDrawPoolHUD(); - - /*virtual*/ LLDrawPool *instancePool(); - - /*virtual*/ void prerender(); - /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void endRenderPass( S32 pass ); - /*virtual*/ void renderForSelect(); - /*virtual*/ void renderFaceSelected(LLFace* facep, LLImageGL* image, const LLColor4& color, - const S32 index_offset = 0, const S32 index_count = 0); -// /*virtual*/ S32 rebuild(); - -// /*virtual*/ LLViewerImage *getTexture(); -// /*virtual*/ LLViewerImage *getDebugTexture(); - /*virtual*/ void dirtyTexture(const LLViewerImage *texturep); - - /*virtual*/ void resetDrawOrders(); - - /*virtual*/ void enqueue(LLFace *face); - /*virtual*/ BOOL addFace(LLFace *face); - /*virtual*/ BOOL removeFace(LLFace *face); - - virtual S32 getMaterialAttribIndex(); - -// /*virtual*/ BOOL verify() const; // Verify that all data in the draw pool is correct! - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - -public: - static BOOL sShowHUDAttachments; - -protected: - typedef std::map bump_face_map_t; - bump_face_map_t mBumpFaces; - face_array_t mAlphaFace; - S32 mRenderMode; // RENDER_TYPE_VOLUME, RENDER_TYPE_BUMP, or RENDER_TYPE_ALPHA -}; - -#endif // LL_LLDRAWPOOLHUD_H diff --git a/linden/indra/newview/lldrawpoolsimple.cpp b/linden/indra/newview/lldrawpoolsimple.cpp index 031c170..ec8929e 100644 --- a/linden/indra/newview/lldrawpoolsimple.cpp +++ b/linden/indra/newview/lldrawpoolsimple.cpp @@ -30,55 +30,45 @@ #include "lldrawpoolsimple.h" #include "llagent.h" -#include "llagparray.h" #include "lldrawable.h" #include "llface.h" #include "llsky.h" #include "pipeline.h" -S32 LLDrawPoolSimple::sDiffTex = 0; - -LLDrawPoolSimple::LLDrawPoolSimple(LLViewerImage *texturep) : - LLDrawPool(POOL_SIMPLE, - DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK, - DATA_SIMPLE_NIL_MASK), // ady temp - mTexturep(texturep) +class LLRenderPassGlow : public LLRenderPass { -} +public: + LLRenderPassGlow(): LLRenderPass(LLRenderPass::PASS_GLOW) { } + + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD + }; -LLDrawPool *LLDrawPoolSimple::instancePool() -{ - return new LLDrawPoolSimple(mTexturep); -} + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } -BOOL LLDrawPoolSimple::match(LLFace* last_face, LLFace* facep) -{ - if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES) && - !last_face->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) && - !facep->isState(LLFace::LIGHT | LLFace::FULLBRIGHT) && - facep->getIndicesStart() == last_face->getIndicesStart()+last_face->getIndicesCount() && - facep->getRenderColor() == last_face->getRenderColor()) + virtual void prerender() { } + + void render(S32 pass = 0) { - if (facep->isState(LLFace::GLOBAL)) - { - if (last_face->isState(LLFace::GLOBAL)) - { - return TRUE; - } - } - else - { - if (!last_face->isState(LLFace::GLOBAL)) - { - if (last_face->getRenderMatrix() == facep->getRenderMatrix()) - { - return TRUE; - } - } - } + LLGLEnable blend(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + renderTexture(LLRenderPass::PASS_GLOW, getVertexDataMask()); + renderActive(LLRenderPass::PASS_GLOW, getVertexDataMask()); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); } - - return FALSE; + + void pushBatch(LLDrawInfo& params, U32 mask, BOOL texture = TRUE) + { + glColor4ubv(params.mGlowColor.mV); + LLRenderPass::pushBatch(params, mask, texture); + } +}; + +LLDrawPoolSimple::LLDrawPoolSimple() : + LLRenderPass(POOL_SIMPLE) +{ } void LLDrawPoolSimple::prerender() @@ -91,156 +81,56 @@ void LLDrawPoolSimple::beginRenderPass(S32 pass) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - if (gPipeline.getLightingDetail() >= 2) - { - glEnableClientState(GL_COLOR_ARRAY); - } - - if (mVertexShaderLevel > 0) - { - S32 scatterTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - sDiffTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - } + glEnableClientState(GL_COLOR_ARRAY); } - void LLDrawPoolSimple::render(S32 pass) { - LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); - if (mDrawFace.empty()) - { - return; - } - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); - if (gPipeline.getLightingDetail() >= 2) + LLGLDisable blend(GL_BLEND); + LLGLDisable alpha_test(GL_ALPHA_TEST); + { - bindGLColorPointer(); + LLFastTimer t(LLFastTimer::FTM_RENDER_SIMPLE); + gPipeline.enableLightsDynamic(1.f); + renderTexture(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); + renderActive(LLRenderPass::PASS_SIMPLE, getVertexDataMask()); } - LLViewerImage* tex = getTexture(); - LLGLState alpha_test(GL_ALPHA_TEST, FALSE); - LLGLState blend(GL_BLEND, FALSE); - - if (tex) { - LLViewerImage::bindTexture(tex,sDiffTex); - if (tex->getPrimaryFormat() == GL_ALPHA) - { - // Enable Invisibility Hack - alpha_test.enable(); - blend.enable(); - } + LLFastTimer t(LLFastTimer::FTM_RENDER_GRASS); + LLGLEnable blend(GL_BLEND); + LLGLEnable alpha_test(GL_ALPHA_TEST); + glAlphaFunc(GL_GREATER, 0.5f); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + //render grass + LLRenderPass::renderTexture(LLRenderPass::PASS_GRASS, getVertexDataMask()); + glAlphaFunc(GL_GREATER, 0.01f); } - else + { - LLImageGL::unbindTexture(sDiffTex, GL_TEXTURE_2D); + LLFastTimer t(LLFastTimer::FTM_RENDER_FULLBRIGHT); + U32 fullbright_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD | LLVertexBuffer::MAP_COLOR; + gPipeline.enableLightsFullbright(LLColor4(1,1,1,1)); + glDisableClientState(GL_NORMAL_ARRAY); + renderTexture(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); + renderActive(LLRenderPass::PASS_FULLBRIGHT, fullbright_mask); } - drawLoop(); -} - -void LLDrawPoolSimple::endRenderPass(S32 pass) -{ - if (mVertexShaderLevel > 0) - { - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); - } - - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - if (gPipeline.getLightingDetail() >= 2) { + LLFastTimer t(LLFastTimer::FTM_RENDER_GLOW); glDisableClientState(GL_COLOR_ARRAY); + LLRenderPassGlow glow; + glow.render(); } -} - -void LLDrawPoolSimple::renderForSelect() -{ - if (mDrawFace.empty() || !mMemory.count()) - { - return; - } - - glEnableClientState ( GL_VERTEX_ARRAY ); - - bindGLVertexPointer(); - - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *facep = *iter; - LLDrawable *drawable = facep->getDrawable(); - if (drawable && !drawable->isDead() && (facep->getViewerObject()->mGLName)) - { - facep->renderForSelect(); - } - } -} - -void LLDrawPoolSimple::renderFaceSelected(LLFace *facep, - LLImageGL *image, - const LLColor4 &color, - const S32 index_offset, const S32 index_count) -{ - facep->renderSelected(image, color, index_offset, index_count); -} - - -void LLDrawPoolSimple::dirtyTexture(const LLViewerImage *texturep) -{ - if (mTexturep == texturep) { - for (std::vector::iterator iter = mReferences.begin(); - iter != mReferences.end(); iter++) - { - LLFace *facep = *iter; - gPipeline.markTextured(facep->getDrawable()); - } + LLFastTimer t(LLFastTimer::FTM_RENDER_INVISIBLE); + U32 invisi_mask = LLVertexBuffer::MAP_VERTEX; + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + renderInvisible(invisi_mask); + renderActive(LLRenderPass::PASS_INVISIBLE, invisi_mask); + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); } } -LLViewerImage *LLDrawPoolSimple::getTexture() -{ - return mTexturep; -} - -LLViewerImage *LLDrawPoolSimple::getDebugTexture() -{ - return mTexturep; -} - -LLColor3 LLDrawPoolSimple::getDebugColor() const -{ - return LLColor3(1.f, 1.f, 1.f); -} - -S32 LLDrawPoolSimple::getMaterialAttribIndex() -{ - return gPipeline.mObjectSimpleProgram.mAttribute[LLPipeline::GLSL_MATERIAL_COLOR]; -} - -// virtual -void LLDrawPoolSimple::enableShade() -{ - glDisableClientState(GL_COLOR_ARRAY); -} - -// virtual -void LLDrawPoolSimple::disableShade() -{ - glEnableClientState(GL_COLOR_ARRAY); -} - -// virtual -void LLDrawPoolSimple::setShade(F32 shade) -{ - glColor4f(0,0,0,shade); -} diff --git a/linden/indra/newview/lldrawpoolsimple.h b/linden/indra/newview/lldrawpoolsimple.h index 32fd320..85dcacf 100644 --- a/linden/indra/newview/lldrawpoolsimple.h +++ b/linden/indra/newview/lldrawpoolsimple.h @@ -30,64 +30,24 @@ #include "lldrawpool.h" -class LLFRInfo +class LLDrawPoolSimple : public LLRenderPass { public: - U32 mPrimType; - U32 mGeomIndex; - U32 mGeomIndexEnd; - U32 mNumIndices; - U32 mIndicesStart; - - LLFRInfo() - { - } - - LLFRInfo(const U32 pt, const U32 gi, const U32 gc, const U32 ni, const U32 is) : - mPrimType(pt), - mGeomIndex(gi), - mGeomIndexEnd(gi+gc), - mNumIndices(ni), - mIndicesStart(is) - { - } -}; - -class LLDrawPoolSimple : public LLDrawPool -{ - LLPointer mTexturep; -public: enum { - SHADER_LEVEL_LOCAL_LIGHTS = 2 + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_COLOR }; - - LLDrawPoolSimple(LLViewerImage *texturep); - - /*virtual*/ LLDrawPool *instancePool(); + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolSimple(); + /*virtual*/ void beginRenderPass(S32 pass); - /*virtual*/ void endRenderPass(S32 pass); /*virtual*/ void render(S32 pass = 0); - /*virtual*/ void renderFaceSelected(LLFace *facep, - LLImageGL *image, - const LLColor4 &color, - const S32 index_offset = 0, const S32 index_count = 0); /*virtual*/ void prerender(); - /*virtual*/ void renderForSelect(); - /*virtual*/ void dirtyTexture(const LLViewerImage *texturep); - /*virtual*/ LLViewerImage *getTexture(); - /*virtual*/ LLViewerImage *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - /*virtual*/ BOOL match(LLFace* last_face, LLFace* facep); - - /*virtual*/ void enableShade(); - /*virtual*/ void disableShade(); - /*virtual*/ void setShade(F32 shade); - - virtual S32 getMaterialAttribIndex(); - static S32 sDiffTex; }; #endif // LL_LLDRAWPOOLSIMPLE_H diff --git a/linden/indra/newview/lldrawpoolsky.cpp b/linden/indra/newview/lldrawpoolsky.cpp index 52f9f16..8266892 100644 --- a/linden/indra/newview/lldrawpoolsky.cpp +++ b/linden/indra/newview/lldrawpoolsky.cpp @@ -31,7 +31,6 @@ #include "imageids.h" -#include "llagparray.h" #include "llagent.h" #include "lldrawable.h" #include "llface.h" @@ -45,7 +44,7 @@ #include "pipeline.h" LLDrawPoolSky::LLDrawPoolSky() : - LLDrawPool(POOL_SKY, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK) + LLFacePool(POOL_SKY) { } @@ -81,15 +80,17 @@ void LLDrawPoolSky::render(S32 pass) glMatrixMode( GL_PROJECTION ); glPushMatrix(); - gViewerWindow->setup3DRender(); + //gViewerWindow->setup3DRender(); + + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + LLVector3 origin = gCamera->getOrigin(); + glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]); glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLTexCoordPointer(); - S32 face_count = (S32)mDrawFace.size(); for (S32 i = 0; i < llmin(6, face_count); ++i) @@ -97,13 +98,13 @@ void LLDrawPoolSky::render(S32 pass) renderSkyCubeFace(i); } - const LLFace *hbfaces[3]; + LLFace *hbfaces[3]; hbfaces[0] = NULL; hbfaces[1] = NULL; hbfaces[2] = NULL; for (S32 curr_face = 0; curr_face < face_count; curr_face++) { - const LLFace* facep = mDrawFace[curr_face]; + LLFace* facep = mDrawFace[curr_face]; if (voskyp->isSameFace(LLVOSky::FACE_SUN, facep)) { hbfaces[0] = facep; @@ -137,11 +138,12 @@ void LLDrawPoolSky::render(S32 pass) glMatrixMode( GL_PROJECTION ); glPopMatrix(); glMatrixMode( GL_MODELVIEW ); + glPopMatrix(); } void LLDrawPoolSky::renderSkyCubeFace(U8 side) { - const LLFace &face = *mDrawFace[LLVOSky::FACE_SIDE0 + side]; + LLFace &face = *mDrawFace[LLVOSky::FACE_SIDE0 + side]; if (!face.getGeomCount()) { return; @@ -149,20 +151,20 @@ void LLDrawPoolSky::renderSkyCubeFace(U8 side) mSkyTex[side].bindTexture(TRUE); - face.renderIndexed(getRawIndices()); + face.renderIndexed(); if (LLSkyTex::doInterpolate()) { LLGLEnable blend(GL_BLEND); mSkyTex[side].bindTexture(FALSE); glColor4f(1, 1, 1, LLSkyTex::getInterpVal()); // lighting is disabled - face.renderIndexed(getRawIndices()); + face.renderIndexed(); } mIndicesDrawn += face.getIndicesCount(); } -void LLDrawPoolSky::renderHeavenlyBody(U8 hb, const LLFace* face) +void LLDrawPoolSky::renderHeavenlyBody(U8 hb, LLFace* face) { if ( !mHB[hb]->getDraw() ) return; if (! face->getGeomCount()) return; @@ -171,13 +173,13 @@ void LLDrawPoolSky::renderHeavenlyBody(U8 hb, const LLFace* face) tex->bind(); LLColor4 color(mHB[hb]->getInterpColor()); LLOverrideFaceColor override(this, color); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } -void LLDrawPoolSky::renderSunHalo(const LLFace* face) +void LLDrawPoolSky::renderSunHalo(LLFace* face) { if (! mHB[0]->getDraw()) return; if (! face->getGeomCount()) return; @@ -188,7 +190,7 @@ void LLDrawPoolSky::renderSunHalo(const LLFace* face) color.mV[3] = llclamp(mHB[0]->getHaloBrighness(), 0.f, 1.f); LLOverrideFaceColor override(this, color); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } diff --git a/linden/indra/newview/lldrawpoolsky.h b/linden/indra/newview/lldrawpoolsky.h index d65fc9f..b9c1dda 100644 --- a/linden/indra/newview/lldrawpoolsky.h +++ b/linden/indra/newview/lldrawpoolsky.h @@ -33,13 +33,21 @@ class LLSkyTex; class LLHeavenBody; -class LLDrawPoolSky : public LLDrawPool +class LLDrawPoolSky : public LLFacePool { private: LLSkyTex *mSkyTex; LLHeavenBody *mHB[2]; // Sun and Moon public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolSky(); /*virtual*/ LLDrawPool *instancePool(); @@ -52,8 +60,8 @@ public: void setMoon(LLHeavenBody* moon) { mHB[1] = moon; } void renderSkyCubeFace(U8 side); - void renderHeavenlyBody(U8 hb, const LLFace* face); - void renderSunHalo(const LLFace* face); + void renderHeavenlyBody(U8 hb, LLFace* face); + void renderSunHalo(LLFace* face); virtual S32 getMaterialAttribIndex() { return 0; } }; diff --git a/linden/indra/newview/lldrawpoolstars.cpp b/linden/indra/newview/lldrawpoolstars.cpp index a0eedb8..3d4eebb 100644 --- a/linden/indra/newview/lldrawpoolstars.cpp +++ b/linden/indra/newview/lldrawpoolstars.cpp @@ -33,9 +33,10 @@ #include "llsky.h" #include "llvostars.h" #include "pipeline.h" +#include "llviewercamera.h" LLDrawPoolStars::LLDrawPoolStars() : - LLDrawPool(POOL_STARS, DATA_VERTICES_MASK | DATA_COLORS_MASK, 0) + LLFacePool(POOL_STARS) { } @@ -72,28 +73,42 @@ void LLDrawPoolStars::render(S32 pass) gPipeline.disableLights(); - glPointSize(2.0); + GLint viewport[4]; - bindGLVertexPointer(); + glGetIntegerv(GL_VIEWPORT, viewport); + + if (viewport[2] > 512 && viewport[3] > 512) + { + glPointSize(2.f); + } + + LLVector3 origin = gCamera->getOrigin(); + glPushMatrix(); + glTranslatef(origin.mV[0], origin.mV[1], origin.mV[2]); glEnableClientState(GL_COLOR_ARRAY); - bindGLColorPointer(); S32 face_count = (S32)mDrawFace.size(); for (S32 curr_face = 0; curr_face < face_count; curr_face++) { - const LLFace* face = mDrawFace[curr_face]; + LLFace* face = mDrawFace[curr_face]; if (!face->getGeomCount()) { continue; } // render the stars as a sphere centered at viewer camera - - face->renderIndexed(getRawIndices()); - mIndicesDrawn += face->getIndicesCount(); + if (face->mVertexBuffer.notNull()) + { + face->mVertexBuffer->setBuffer(getVertexDataMask()); + U32* indicesp = (U32*) face->mVertexBuffer->getIndicesPointer(); + glDrawElements(GL_POINTS, face->getIndicesCount(), GL_UNSIGNED_INT, indicesp); + mIndicesDrawn += face->getIndicesCount(); + } } glDisableClientState(GL_COLOR_ARRAY); + glPointSize(1.f); + glPopMatrix(); } diff --git a/linden/indra/newview/lldrawpoolstars.h b/linden/indra/newview/lldrawpoolstars.h index 6343a93..1eade29 100644 --- a/linden/indra/newview/lldrawpoolstars.h +++ b/linden/indra/newview/lldrawpoolstars.h @@ -30,9 +30,17 @@ #include "lldrawpool.h" -class LLDrawPoolStars : public LLDrawPool +class LLDrawPoolStars : public LLFacePool { public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_COLOR + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolStars(); /*virtual*/ LLDrawPool *instancePool(); diff --git a/linden/indra/newview/lldrawpoolterrain.cpp b/linden/indra/newview/lldrawpoolterrain.cpp index 1390fc9..8ac053c 100644 --- a/linden/indra/newview/lldrawpoolterrain.cpp +++ b/linden/indra/newview/lldrawpoolterrain.cpp @@ -32,7 +32,6 @@ #include "llfasttimer.h" #include "llagent.h" -#include "llagparray.h" #include "llviewercontrol.h" #include "lldrawable.h" #include "llface.h" @@ -56,7 +55,7 @@ S32 LLDrawPoolTerrain::sDetailMode = 1; F32 LLDrawPoolTerrain::sDetailScale = DETAIL_SCALE; LLDrawPoolTerrain::LLDrawPoolTerrain(LLViewerImage *texturep) : - LLDrawPool(POOL_TERRAIN, DATA_SIMPLE_IL_MASK | DATA_COLORS_MASK | DATA_TEX_COORDS1_MASK, DATA_SIMPLE_NIL_MASK), + LLFacePool(POOL_TERRAIN), mTexturep(texturep) { // Hack! @@ -94,6 +93,13 @@ void LLDrawPoolTerrain::prerender() #if 0 // 1.9.2 mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT); #endif + sDetailMode = gSavedSettings.getS32("RenderTerrainDetail"); +} + +//static +S32 LLDrawPoolTerrain::getDetailMode() +{ + return sDetailMode; } void LLDrawPoolTerrain::render(S32 pass) @@ -105,6 +111,15 @@ void LLDrawPoolTerrain::render(S32 pass) return; } + // Hack! Get the region that this draw pool is rendering from! + LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); + LLVLComposition *compp = regionp->getComposition(); + for (S32 i = 0; i < 4; i++) + { + compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); + compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area + } + if (!gGLManager.mHasMultitexture) { // No mulititexture, render simple land. @@ -171,25 +186,16 @@ void LLDrawPoolTerrain::renderFull4TUShader() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); if (gPipeline.getLightingDetail() >= 2) { glEnableClientState(GL_COLOR_ARRAY); - bindGLColorPointer(); } - + glBlendFunc(GL_ONE_MINUS_SRC_ALPHA, GL_SRC_ALPHA); // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - for (S32 i = 0; i < 4; i++) - { - compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); - compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area - } - LLViewerImage *detail_texture0p = compp->mDetailTextures[0]; LLViewerImage *detail_texture1p = compp->mDetailTextures[1]; LLViewerImage *detail_texture2p = compp->mDetailTextures[2]; @@ -219,8 +225,7 @@ void LLDrawPoolTerrain::renderFull4TUShader() S32 detailTex0 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0); S32 detailTex1 = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1); S32 rampTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP); - S32 scatterTex = gPipeline.mTerrainProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - + LLViewerImage::bindTexture(detail_texture0p,detailTex0); glClientActiveTextureARB(GL_TEXTURE0_ARB); @@ -241,7 +246,6 @@ void LLDrawPoolTerrain::renderFull4TUShader() glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // // Stage 2: Interpolate detail1 with existing based on ramp @@ -258,9 +262,6 @@ void LLDrawPoolTerrain::renderFull4TUShader() glTexGenfv(GL_S, GL_OBJECT_PLANE, tp0.mV); glTexGenfv(GL_T, GL_OBJECT_PLANE, tp1.mV); - // Stage 4: Haze - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - // // Stage 3: Modulate with primary color for lighting // @@ -297,7 +298,6 @@ void LLDrawPoolTerrain::renderFull4TUShader() glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); glActiveTextureARB(GL_TEXTURE1_ARB); - bindGLTexCoordPointer(1); // Set the texture matrix glMatrixMode(GL_TEXTURE); @@ -329,7 +329,6 @@ void LLDrawPoolTerrain::renderFull4TUShader() glClientActiveTextureARB(GL_TEXTURE3_ARB); glActiveTextureARB(GL_TEXTURE3_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Set the texture matrix glMatrixMode(GL_TEXTURE); @@ -342,7 +341,6 @@ void LLDrawPoolTerrain::renderFull4TUShader() } // Disable multitexture - gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_ALPHARAMP); gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL0); gPipeline.mTerrainProgram.disableTexture(LLPipeline::GLSL_TERRAIN_DETAIL1); @@ -396,18 +394,9 @@ void LLDrawPoolTerrain::renderFull4TU() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); - // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - for (S32 i = 0; i < 4; i++) - { - compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); - compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area - } - LLViewerImage *detail_texture0p = compp->mDetailTextures[0]; LLViewerImage *detail_texture1p = compp->mDetailTextures[1]; LLViewerImage *detail_texture2p = compp->mDetailTextures[2]; @@ -430,6 +419,7 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 0: detail texture 0 // + glActiveTextureARB(GL_TEXTURE0_ARB); LLViewerImage::bindTexture(detail_texture0p,0); glClientActiveTextureARB(GL_TEXTURE0_ARB); @@ -451,12 +441,12 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 1: Generate alpha ramp for detail0/detail1 transition // + glActiveTextureARB(GL_TEXTURE1_ARB); LLViewerImage::bindTexture(m2DAlphaRampImagep,1); glEnable(GL_TEXTURE_2D); // Texture unit 1 glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Care about alpha only glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); @@ -471,6 +461,7 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 2: Interpolate detail1 with existing based on ramp // + glActiveTextureARB(GL_TEXTURE2_ARB); LLViewerImage::bindTexture(detail_texture1p,2); glEnable(GL_TEXTURE_2D); // Texture unit 2 glClientActiveTextureARB(GL_TEXTURE2_ARB); @@ -496,6 +487,7 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 3: Modulate with primary (vertex) color for lighting // + glActiveTextureARB(GL_TEXTURE3_ARB); LLViewerImage::bindTexture(detail_texture1p,3); // bind any texture glEnable(GL_TEXTURE_2D); // Texture unit 3 glClientActiveTextureARB(GL_TEXTURE3_ARB); @@ -517,6 +509,7 @@ void LLDrawPoolTerrain::renderFull4TU() // Stage 0: Write detail3 into base // + glActiveTextureARB(GL_TEXTURE0_ARB); LLViewerImage::bindTexture(detail_texture3p,0); glClientActiveTextureARB(GL_TEXTURE0_ARB); @@ -538,14 +531,13 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 1: Generate alpha ramp for detail2/detail3 transition // + glActiveTextureARB(GL_TEXTURE1_ARB); LLViewerImage::bindTexture(m2DAlphaRampImagep,1); glEnable(GL_TEXTURE_2D); // Texture unit 1 glClientActiveTextureARB(GL_TEXTURE1_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); - // Set the texture matrix glMatrixMode(GL_TEXTURE); @@ -566,6 +558,7 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 2: Interpolate detail2 with existing based on ramp // + glActiveTextureARB(GL_TEXTURE2_ARB); LLViewerImage::bindTexture(detail_texture2p,2); glEnable(GL_TEXTURE_2D); // Texture unit 2 glClientActiveTextureARB(GL_TEXTURE2_ARB); @@ -592,19 +585,19 @@ void LLDrawPoolTerrain::renderFull4TU() // // Stage 3: Generate alpha ramp for detail1/detail2 transition // + glActiveTextureARB(GL_TEXTURE3_ARB); LLViewerImage::bindTexture(m2DAlphaRampImagep,3); glEnable(GL_TEXTURE_2D); // Texture unit 3 glClientActiveTextureARB(GL_TEXTURE3_ARB); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Set the texture matrix glMatrixMode(GL_TEXTURE); glLoadIdentity(); glTranslatef(-1.f, 0.f, 0.f); - + // Set alpha texture and do lighting modulation glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); @@ -675,18 +668,9 @@ void LLDrawPoolTerrain::renderFull2TU() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); - // Hack! Get the region that this draw pool is rendering from! LLViewerRegion *regionp = mDrawFace[0]->getDrawable()->getVObj()->getRegion(); LLVLComposition *compp = regionp->getComposition(); - for (S32 i = 0; i < 4; i++) - { - compp->mDetailTextures[i]->setBoostLevel(LLViewerImage::BOOST_TERRAIN); - compp->mDetailTextures[i]->addTextureStats(1024.f*1024.f); // assume large pixel area - } - LLViewerImage *detail_texture0p = compp->mDetailTextures[0]; LLViewerImage *detail_texture1p = compp->mDetailTextures[1]; LLViewerImage *detail_texture2p = compp->mDetailTextures[2]; @@ -743,7 +727,6 @@ void LLDrawPoolTerrain::renderFull2TU() glDisable(GL_TEXTURE_GEN_S); glDisable(GL_TEXTURE_GEN_T); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Care about alpha only glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); @@ -800,7 +783,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTranslatef(-1.f, 0.f, 0.f); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Care about alpha only glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); @@ -858,7 +840,6 @@ void LLDrawPoolTerrain::renderFull2TU() glTranslatef(-2.f, 0.f, 0.f); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - bindGLTexCoordPointer(1); // Care about alpha only glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); @@ -938,9 +919,6 @@ void LLDrawPoolTerrain::renderSimple() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); - LLVector4 tp0, tp1; //---------------------------------------------------------------------------- @@ -1018,9 +996,6 @@ void LLDrawPoolTerrain::renderOwnership() glEnableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLTexCoordPointer(0); - LLViewerImage::bindTexture(texturep); glClientActiveTextureARB(GL_TEXTURE0_ARB); @@ -1036,12 +1011,12 @@ void LLDrawPoolTerrain::renderOwnership() const F32 TEXTURE_FUDGE = 257.f / 256.f; glScalef( TEXTURE_FUDGE, TEXTURE_FUDGE, 1.f ); - const U32* index_array = getRawIndices(); for (std::vector::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) { LLFace *facep = *iter; - facep->renderIndexed(index_array); + facep->renderIndexed(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD); } glMatrixMode(GL_TEXTURE); @@ -1055,14 +1030,13 @@ void LLDrawPoolTerrain::renderOwnership() void LLDrawPoolTerrain::renderForSelect() { - if (mDrawFace.empty() || !mMemory.count()) + if (mDrawFace.empty()) { return; } - glEnableClientState ( GL_VERTEX_ARRAY ); - - bindGLVertexPointer(); + + LLImageGL::unbindTexture(0); for (std::vector::iterator iter = mDrawFace.begin(); iter != mDrawFace.end(); iter++) @@ -1070,14 +1044,14 @@ void LLDrawPoolTerrain::renderForSelect() LLFace *facep = *iter; if (!facep->getDrawable()->isDead() && (facep->getDrawable()->getVObj()->mGLName)) { - facep->renderForSelect(); + facep->renderForSelect(LLVertexBuffer::MAP_VERTEX); } } } -void LLDrawPoolTerrain::dirtyTexture(const LLViewerImage *texturep) +void LLDrawPoolTerrain::dirtyTextures(const std::set& textures) { - if (mTexturep == texturep) + if (textures.find(mTexturep) != textures.end()) { for (std::vector::iterator iter = mReferences.begin(); iter != mReferences.end(); iter++) diff --git a/linden/indra/newview/lldrawpoolterrain.h b/linden/indra/newview/lldrawpoolterrain.h index b75d7cf..57fab9e 100644 --- a/linden/indra/newview/lldrawpoolterrain.h +++ b/linden/indra/newview/lldrawpoolterrain.h @@ -30,10 +30,22 @@ #include "lldrawpool.h" -class LLDrawPoolTerrain : public LLDrawPool +class LLDrawPoolTerrain : public LLFacePool { LLPointer mTexturep; public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD | + LLVertexBuffer::MAP_TEXCOORD2 | + LLVertexBuffer::MAP_COLOR + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + static S32 getDetailMode(); + LLDrawPoolTerrain(LLViewerImage *texturep); virtual ~LLDrawPoolTerrain(); @@ -43,7 +55,7 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void prerender(); /*virtual*/ void renderForSelect(); - /*virtual*/ void dirtyTexture(const LLViewerImage *texturep); + /*virtual*/ void dirtyTextures(const std::set& textures); /*virtual*/ LLViewerImage *getTexture(); /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display diff --git a/linden/indra/newview/lldrawpooltree.cpp b/linden/indra/newview/lldrawpooltree.cpp index ad05d9a..36a4393 100644 --- a/linden/indra/newview/lldrawpooltree.cpp +++ b/linden/indra/newview/lldrawpooltree.cpp @@ -29,7 +29,6 @@ #include "lldrawpooltree.h" -#include "llagparray.h" #include "lldrawable.h" #include "llface.h" #include "llsky.h" @@ -41,7 +40,7 @@ S32 LLDrawPoolTree::sDiffTex = 0; LLDrawPoolTree::LLDrawPoolTree(LLViewerImage *texturep) : - LLDrawPool(POOL_TREE, DATA_SIMPLE_IL_MASK, 0), + LLFacePool(POOL_TREE), mTexturep(texturep) { mTexturep->bind(0); @@ -55,7 +54,7 @@ LLDrawPool *LLDrawPoolTree::instancePool() void LLDrawPoolTree::prerender() { - mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT); + mVertexShaderLevel = 0; } void LLDrawPoolTree::beginRenderPass(S32 pass) @@ -63,13 +62,7 @@ void LLDrawPoolTree::beginRenderPass(S32 pass) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); glEnableClientState(GL_TEXTURE_COORD_ARRAY); - - if ((mVertexShaderLevel > 0)) - { - S32 scatterTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - sDiffTex = gPipeline.mObjectSimpleProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - } + glAlphaFunc(GL_GREATER, 0.5f); } void LLDrawPoolTree::render(S32 pass) @@ -83,34 +76,21 @@ void LLDrawPoolTree::render(S32 pass) gPipeline.enableLightsDynamic(1.f); LLGLSPipelineAlpha gls_pipeline_alpha; - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); - LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); renderTree(); - } void LLDrawPoolTree::endRenderPass(S32 pass) { - if ((mVertexShaderLevel > 0)) - { - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - gPipeline.mObjectSimpleProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - glActiveTextureARB(GL_TEXTURE0_ARB); - glEnable(GL_TEXTURE_2D); - } - + glAlphaFunc(GL_GREATER, 0.01f); glDisableClientState(GL_NORMAL_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); } void LLDrawPoolTree::renderForSelect() { - if (mDrawFace.empty() || !mMemory.count()) + if (mDrawFace.empty()) { return; } @@ -123,10 +103,7 @@ void LLDrawPoolTree::renderForSelect() LLGLSObjectSelectAlpha gls_alpha; glBlendFunc(GL_ONE, GL_ZERO); - glAlphaFunc(gPickTransparent ? GL_GEQUAL : GL_GREATER, 0.f); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); + glAlphaFunc(GL_GREATER, 0.5f); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); @@ -166,6 +143,8 @@ void LLDrawPoolTree::renderTree(BOOL selecting) } } + U32 indices_drawn = 0; + glMatrixMode(GL_MODELVIEW); for (std::vector::iterator iter = mDrawFace.begin(); @@ -174,11 +153,14 @@ void LLDrawPoolTree::renderTree(BOOL selecting) LLFace *face = *iter; LLDrawable *drawablep = face->getDrawable(); - if (drawablep->isDead()) + if (drawablep->isDead() || face->mVertexBuffer.isNull()) { continue; } + face->mVertexBuffer->setBuffer(LLDrawPoolTree::VERTEX_DATA_MASK); + U32* indicesp = (U32*) face->mVertexBuffer->getIndicesPointer(); + // Render each of the trees LLVOTree *treep = (LLVOTree *)drawablep->getVObj(); @@ -236,55 +218,26 @@ void LLDrawPoolTree::renderTree(BOOL selecting) } } - if (app_angle > (THRESH_ANGLE_FOR_BILLBOARD + BLEND_RANGE_FOR_BILLBOARD)) - { - // - // Draw only the full geometry tree - // - //stop_depth = (app_angle < THRESH_ANGLE_FOR_RECURSION_REDUCTION); - glAlphaFunc(GL_GREATER, 0.5f); - LLDrawPool::LLOverrideFaceColor clr(this, color); - treep->drawBranchPipeline(this, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha); - } - else if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD)) + if (app_angle < (THRESH_ANGLE_FOR_BILLBOARD - BLEND_RANGE_FOR_BILLBOARD)) { // // Draw only the billboard // // Only the billboard, can use closer to normal alpha func. stop_depth = -1; - glAlphaFunc(GL_GREATER, 0.4f); - LLDrawPool::LLOverrideFaceColor clr(this, color); - treep->drawBranchPipeline(this, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha); + LLFacePool::LLOverrideFaceColor clr(this, color); + indices_drawn += treep->drawBranchPipeline(indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha); } - else + else // if (app_angle > (THRESH_ANGLE_FOR_BILLBOARD + BLEND_RANGE_FOR_BILLBOARD)) { // - // Draw a blended version including both billboard and full tree - // - alpha = (app_angle - THRESH_ANGLE_FOR_BILLBOARD)/BLEND_RANGE_FOR_BILLBOARD; - BOOL billboard_depth = TRUE; // billboard gets alpha - if (alpha > 0.5f) - { - billboard_depth = FALSE; - } - alpha = alpha/2.f + 0.5f; - - glAlphaFunc(GL_GREATER, alpha*0.5f); - { - LLGLDepthTest gls_depth(GL_TRUE, billboard_depth ? GL_FALSE : GL_TRUE); - color.mV[3] = (U8) (llclamp(alpha, 0.0f, 1.0f) * 255); - LLDrawPool::LLOverrideFaceColor clr(this, color); - treep->drawBranchPipeline(this, trunk_LOD, 0, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha); - } - { - LLGLDepthTest gls_depth(GL_TRUE, billboard_depth ? GL_TRUE : GL_FALSE); - glAlphaFunc(GL_GREATER, (1.f - alpha)*0.1f); - color.mV[3] = (U8) (llclamp(1.f-alpha, 0.0f, 1.0f) * 255); - LLDrawPool::LLOverrideFaceColor clr(this, color); - treep->drawBranchPipeline(this, trunk_LOD, -1, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, 1.f - alpha); - } + // Draw only the full geometry tree + // + //stop_depth = (app_angle < THRESH_ANGLE_FOR_RECURSION_REDUCTION); + LLFacePool::LLOverrideFaceColor clr(this, color); + indices_drawn += treep->drawBranchPipeline(indicesp, trunk_LOD, stop_depth, treep->mDepth, treep->mTrunkDepth, 1.0, treep->mTwist, droop, treep->mBranches, alpha); } + glPopMatrix(); } } @@ -298,45 +251,21 @@ void LLDrawPoolTree::renderTree(BOOL selecting) glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); } } - glAlphaFunc(GL_GREATER, 0.01f); -} - - -S32 LLDrawPoolTree::rebuild() -{ - mRebuildTime++; - if (mRebuildTime > mRebuildFreq) - { - // Flush AGP to force an AGP realloc and reduce AGP fragmentation - flushAGP(); - mRebuildTime = 0; - } - return 0; + addIndicesDrawn(indices_drawn); } BOOL LLDrawPoolTree::verify() const { - BOOL ok = TRUE; - - // shared geometry. Just verify that it's there and correct. +/* BOOL ok = TRUE; - // Verify all indices in the pool are in the right range - const U32 *indicesp = getRawIndices(); - for (U32 i = 0; i < getIndexCount(); i++) - { - if (indicesp[i] > getVertexCount()) - { - ok = FALSE; - llinfos << "Bad index in tree pool!" << llendl; - } - } - if (!ok) { printDebugInfo(); } - return ok; + return ok;*/ + + return TRUE; } LLViewerImage *LLDrawPoolTree::getTexture() diff --git a/linden/indra/newview/lldrawpooltree.h b/linden/indra/newview/lldrawpooltree.h index 5b4eb67..6e00460 100644 --- a/linden/indra/newview/lldrawpooltree.h +++ b/linden/indra/newview/lldrawpooltree.h @@ -30,10 +30,19 @@ #include "lldrawpool.h" -class LLDrawPoolTree : public LLDrawPool +class LLDrawPoolTree : public LLFacePool { LLPointer mTexturep; public: + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + LLDrawPoolTree(LLViewerImage *texturep); /*virtual*/ LLDrawPool *instancePool(); @@ -43,7 +52,6 @@ public: /*virtual*/ void render(S32 pass = 0); /*virtual*/ void endRenderPass( S32 pass ); /*virtual*/ void renderForSelect(); - /*virtual*/ S32 rebuild(); /*virtual*/ BOOL verify() const; /*virtual*/ LLViewerImage *getTexture(); /*virtual*/ LLViewerImage *getDebugTexture(); diff --git a/linden/indra/newview/lldrawpooltreenew.cpp b/linden/indra/newview/lldrawpooltreenew.cpp deleted file mode 100644 index 326ab5f..0000000 --- a/linden/indra/newview/lldrawpooltreenew.cpp +++ /dev/null @@ -1,200 +0,0 @@ -/** - * @file lldrawpooltreenew.cpp - * @brief LLDrawPoolTreeNew class implementation - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "lldrawpooltreenew.h" - -#include "llagparray.h" -#include "lldrawable.h" -#include "llface.h" -#include "llsky.h" -#include "llvotreenew.h" -#include "pipeline.h" - -LLDrawPoolTreeNew::LLDrawPoolTreeNew(LLViewerImage *texturep) : - LLDrawPool(POOL_TREE_NEW, - DATA_VERTICES_MASK | DATA_TEX_COORDS0_MASK | DATA_NORMALS_MASK, - 0), - mTexturep(texturep) -{ -} - -LLDrawPool *LLDrawPoolTreeNew::instancePool() -{ - return new LLDrawPoolTreeNew(mTexturep); -} - - -void LLDrawPoolTreeNew::prerender() -{ - mVertexShaderLevel = gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT); -} - -void LLDrawPoolTreeNew::render( S32 pass ) -{ - if (mDrawFace.empty()) - { - return; - } - - LLGLSPipelineAlpha gls_pipeline_alpha; - - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - - bindGLVertexPointer(); - bindGLTexCoordPointer(); - bindGLNormalPointer(); - - LLOverrideFaceColor color(this, 1.f, 1.f, 1.f, 1.f); - - renderTree(); -} - - -void LLDrawPoolTreeNew::renderForSelect() -{ - if (mDrawFace.empty()) - { - return; - } - - LLGLSPipelineAlpha gls_pipeline_alpha; - - glEnableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); - - bindGLVertexPointer(); - - renderTree(TRUE); - - glDisableClientState(GL_VERTEX_ARRAY); - -} - - - - -void LLDrawPoolTreeNew::renderTree(BOOL selecting) -{ - - // Bind the texture for this tree. - LLViewerImage::bindTexture(mTexturep); - - glMatrixMode(GL_MODELVIEW); - for (std::vector::iterator iter = mDrawFace.begin(); - iter != mDrawFace.end(); iter++) - { - LLFace *face = *iter; - LLDrawable *drawablep = face->getDrawable(); - - if (drawablep->isDead()) - { - continue; - } - // Render each of the trees - LLVOTreeNew *treep = (LLVOTreeNew *)drawablep->getVObj(); - if (!selecting || treep->mGLName != 0) - { - glPushMatrix(); - - // Translate to tree base HACK - adjustment in Z plants tree underground - const LLVector3 &pos_agent = treep->getPositionAgent(); - glTranslatef(pos_agent.mV[VX], pos_agent.mV[VY], pos_agent.mV[VZ] - 0.1f); - - // Rotate to tree position - F32 angle_radians, x, y, z; - treep->getRotation().getAngleAxis(&angle_radians, &x, &y, &z); - glRotatef(angle_radians * RAD_TO_DEG, x, y, z); - - //glAlphaFunc(GL_GREATER, 0.5f); - - treep->drawTree(*this); - glPopMatrix(); - } - } - - glAlphaFunc(GL_GREATER, 0.01f); -} - - -S32 LLDrawPoolTreeNew::rebuild() -{ - mRebuildTime++; - if (mRebuildTime > mRebuildFreq) - { - // Flush AGP to force an AGP realloc and reduce AGP fragmentation - flushAGP(); - mRebuildTime = 0; - } - - return 0; -} - -BOOL LLDrawPoolTreeNew::verify() const -{ - BOOL ok = TRUE; - - // shared geometry. Just verify that it's there and correct. - - // Verify all indices in the pool are in the right range - const U32 *indicesp = getRawIndices(); - U32 i; - for (i = 0; i < getIndexCount(); i++) - { - if (indicesp[i] > getVertexCount()) - { - ok = FALSE; - llinfos << "Bad index in tree pool!" << llendl; - } - } - - if (!ok) - { - printDebugInfo(); - } - return ok; -} - -LLViewerImage *LLDrawPoolTreeNew::getTexture() -{ - return mTexturep; -} - -LLViewerImage *LLDrawPoolTreeNew::getDebugTexture() -{ - return mTexturep; -} - - -LLColor3 LLDrawPoolTreeNew::getDebugColor() const -{ - return LLColor3(1.f, 0.f, 1.f); -} diff --git a/linden/indra/newview/lldrawpooltreenew.h b/linden/indra/newview/lldrawpooltreenew.h deleted file mode 100644 index 9150331..0000000 --- a/linden/indra/newview/lldrawpooltreenew.h +++ /dev/null @@ -1,55 +0,0 @@ -/** - * @file lldrawpooltreenew.h - * @brief LLDrawPoolTreeNew class definition - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLDRAWPOOLTREENEW_H -#define LL_LLDRAWPOOLTREENEW_H - -#include "lldrawpool.h" - -class LLDrawPoolTreeNew : public LLDrawPool -{ - LLPointer mTexturep; -public: - LLDrawPoolTreeNew(LLViewerImage *texturep); - - /*virtual*/ LLDrawPool *instancePool(); - - /*virtual*/ void prerender(); - /*virtual*/ void render( S32 pass ); - /*virtual*/ void renderForSelect(); - /*virtual*/ S32 rebuild(); - /*virtual*/ BOOL verify() const; - /*virtual*/ LLViewerImage *getTexture(); - /*virtual*/ LLViewerImage *getDebugTexture(); - /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - virtual S32 getMaterialAttribIndex() { return 0; } - -private: - void renderTree(BOOL selecting = FALSE); -}; - -#endif // LL_LLDRAWPOOLTREE_H diff --git a/linden/indra/newview/lldrawpoolwater.cpp b/linden/indra/newview/lldrawpoolwater.cpp index e3802a1..cd2a615 100644 --- a/linden/indra/newview/lldrawpoolwater.cpp +++ b/linden/indra/newview/lldrawpoolwater.cpp @@ -35,7 +35,6 @@ #include "m3math.h" #include "llagent.h" // for gAgent for getRegion for getWaterHeight -#include "llagparray.h" #include "llcubemap.h" #include "lldrawable.h" #include "llface.h" @@ -63,11 +62,11 @@ int nhpo2(int v) } static GLuint sScreenTex = 0; +BOOL LLDrawPoolWater::sSkipScreenCopy = FALSE; LLDrawPoolWater::LLDrawPoolWater() : - LLDrawPool(POOL_WATER, DATA_SIMPLE_IL_MASK, DATA_SIMPLE_NIL_MASK) + LLFacePool(POOL_WATER) { - mCleanupUnused = TRUE; mHBTex[0] = gImageList.getImage(gSunTextureID, TRUE, TRUE); mHBTex[0]->bind(); mHBTex[0]->setClamp(TRUE, TRUE); @@ -135,11 +134,21 @@ extern LLColor4U MAX_WATER_COLOR; void LLDrawPoolWater::render(S32 pass) { LLFastTimer ftm(LLFastTimer::FTM_RENDER_WATER); - if (mDrawFace.empty()) + if (mDrawFace.empty() || LLDrawable::getCurrentFrame() <= 1) { return; } + //do a quick 'n dirty depth sort + for (std::vector::iterator iter = mDrawFace.begin(); + iter != mDrawFace.end(); iter++) + { + LLFace* facep = *iter; + facep->mDistance = -facep->mCenterLocal.mV[2]; + } + + std::sort(mDrawFace.begin(), mDrawFace.end(), LLFace::CompareDistanceGreater()); + LLGLSPipelineAlpha alphaState; if ((mVertexShaderLevel >= SHADER_LEVEL_RIPPLE)) @@ -164,7 +173,7 @@ void LLDrawPoolWater::render(S32 pass) return; } - const LLFace* refl_face = voskyp->getReflFace(); + LLFace* refl_face = voskyp->getReflFace(); gPipeline.disableLights(); @@ -176,10 +185,6 @@ void LLDrawPoolWater::render(S32 pass) glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(); - // Set up second pass first glActiveTextureARB(GL_TEXTURE1_ARB); mWaterImagep->addTextureStats(1024.f*1024.f); @@ -246,7 +251,7 @@ void LLDrawPoolWater::render(S32 pass) continue; } face->bindTexture(); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } @@ -307,7 +312,7 @@ void LLDrawPoolWater::render(S32 pass) if (face->getGeomCount() > 0) { - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } } @@ -354,7 +359,7 @@ void LLDrawPoolWater::renderShaderSimple() return; } - const LLFace* refl_face = voskyp->getReflFace(); + LLFace* refl_face = voskyp->getReflFace(); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -364,10 +369,6 @@ void LLDrawPoolWater::renderShaderSimple() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(); - // Set up second pass first S32 bumpTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_BUMP_MAP); mWaterImagep->addTextureStats(1024.f*1024.f); @@ -432,9 +433,6 @@ void LLDrawPoolWater::renderShaderSimple() glMatrixMode(GL_MODELVIEW); } - S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); gPipeline.mWaterProgram.bind(); @@ -448,7 +446,7 @@ void LLDrawPoolWater::renderShaderSimple() continue; } face->bindTexture(diffTex); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } @@ -469,8 +467,7 @@ void LLDrawPoolWater::renderShaderSimple() glDisable(GL_TEXTURE_GEN_T); //texture unit 1 gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); - gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); - + // Disable texture coordinate and color arrays LLImageGL::unbindTexture(diffTex, GL_TEXTURE_2D); @@ -496,7 +493,7 @@ void LLDrawPoolWater::renderShaderSimple() glDisableClientState(GL_NORMAL_ARRAY); } -void LLDrawPoolWater::renderReflection(const LLFace* face) +void LLDrawPoolWater::renderReflection(LLFace* face) { LLVOSky *voskyp = gSky.mVOSkyp; @@ -524,7 +521,7 @@ void LLDrawPoolWater::renderReflection(const LLFace* face) LLViewerImage::bindTexture(mHBTex[dr]); LLOverrideFaceColor override(this, face->getFaceColor().mV); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); glDisableClientState(GL_TEXTURE_COORD_ARRAY); @@ -532,36 +529,44 @@ void LLDrawPoolWater::renderReflection(const LLFace* face) void bindScreenToTexture() { - GLint viewport[4]; - glGetIntegerv(GL_VIEWPORT, viewport); - GLuint resX = nhpo2(viewport[2]); - GLuint resY = nhpo2(viewport[3]); - - glBindTexture(GL_TEXTURE_2D, sScreenTex); - GLint cResX; - GLint cResY; - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX); - glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY); - - if (cResX != (GLint)resX || cResY != (GLint)resY) + if (LLDrawPoolWater::sSkipScreenCopy) { - glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL); - gImageList.updateMaxResidentTexMem(-1, resX*resY*3); + glBindTexture(GL_TEXTURE_2D, 0); } + else + { - glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); + GLint viewport[4]; + glGetIntegerv(GL_VIEWPORT, viewport); + GLuint resX = nhpo2(viewport[2]); + GLuint resY = nhpo2(viewport[3]); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + glBindTexture(GL_TEXTURE_2D, sScreenTex); + GLint cResX; + GLint cResY; + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &cResX); + glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_HEIGHT, &cResY); + + if (cResX != (GLint)resX || cResY != (GLint)resY) + { + glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, resX, resY, 0, GL_RGB, GL_FLOAT, NULL); + gImageList.updateMaxResidentTexMem(-1, resX*resY*3); + } - float scale[2]; - scale[0] = (float) viewport[2]/resX; - scale[1] = (float) viewport[3]/resY; - glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale); + glCopyTexSubImage2D(GL_TEXTURE_2D, 0, viewport[0], viewport[1], 0, 0, viewport[2], viewport[3]); - LLImageGL::sBoundTextureMemory += resX * resY * 3; + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); + + float scale[2]; + scale[0] = (float) viewport[2]/resX; + scale[1] = (float) viewport[3]/resY; + glUniform2fvARB(gPipeline.mWaterProgram.mUniform[LLPipeline::GLSL_WATER_FBSCALE], 1, scale); + + LLImageGL::sBoundTextureMemory += resX * resY * 3; + } } void LLDrawPoolWater::shade() @@ -596,9 +601,6 @@ void LLDrawPoolWater::shade() glEnableClientState(GL_VERTEX_ARRAY); glEnableClientState(GL_NORMAL_ARRAY); LLGLDisable blend(GL_BLEND); - bindGLVertexPointer(); - bindGLNormalPointer(); - bindGLTexCoordPointer(); LLColor3 light_diffuse(0,0,0); F32 light_exp = 0.0f; @@ -649,9 +651,6 @@ void LLDrawPoolWater::shade() bindScreenToTexture(); - S32 scatterTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_SCATTER_MAP); - LLViewerImage::bindTexture(gSky.mVOSkyp->getScatterMap(), scatterTex); - S32 diffTex = gPipeline.mWaterProgram.enableTexture(LLPipeline::GLSL_DIFFUSE_MAP); LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); @@ -697,7 +696,7 @@ void LLDrawPoolWater::shade() } face->bindTexture(diffTex); - face->renderIndexed(getRawIndices()); + face->renderIndexed(); mIndicesDrawn += face->getIndicesCount(); } } @@ -705,7 +704,6 @@ void LLDrawPoolWater::shade() gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_ENVIRONMENT_MAP, GL_TEXTURE_CUBE_MAP_ARB); gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_WATER_SCREENTEX); gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_BUMP_MAP); - gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_SCATTER_MAP); gPipeline.mWaterProgram.disableTexture(LLPipeline::GLSL_DIFFUSE_MAP); glActiveTextureARB(GL_TEXTURE0_ARB); @@ -714,10 +712,6 @@ void LLDrawPoolWater::shade() glClientActiveTextureARB(GL_TEXTURE0_ARB); glDisableClientState(GL_TEXTURE_COORD_ARRAY); - - /*glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY);*/ } void LLDrawPoolWater::renderForSelect() diff --git a/linden/indra/newview/lldrawpoolwater.h b/linden/indra/newview/lldrawpoolwater.h index 38bf6cf..2e45868 100644 --- a/linden/indra/newview/lldrawpoolwater.h +++ b/linden/indra/newview/lldrawpoolwater.h @@ -35,7 +35,7 @@ class LLFace; class LLHeavenBody; class LLWaterSurface; -class LLDrawPoolWater: public LLDrawPool +class LLDrawPoolWater: public LLFacePool { protected: LLPointer mHBTex[2]; @@ -44,6 +44,16 @@ protected: const LLWaterSurface *mWaterSurface; public: + static BOOL sSkipScreenCopy; + enum + { + VERTEX_DATA_MASK = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD + }; + + virtual U32 getVertexDataMask() { return VERTEX_DATA_MASK; } + enum { SHADER_LEVEL_RIPPLE = 2, @@ -64,7 +74,7 @@ public: /*virtual*/ LLViewerImage *getDebugTexture(); /*virtual*/ LLColor3 getDebugColor() const; // For AGP debug display - void renderReflection(const LLFace* face); + void renderReflection(LLFace* face); void shade(); void renderShaderSimple(); diff --git a/linden/indra/newview/lldynamictexture.cpp b/linden/indra/newview/lldynamictexture.cpp index 6111e36..90ebd74 100644 --- a/linden/indra/newview/lldynamictexture.cpp +++ b/linden/indra/newview/lldynamictexture.cpp @@ -35,6 +35,8 @@ #include "llviewercamera.h" #include "llviewercontrol.h" #include "llviewerimage.h" +#include "llvertexbuffer.h" + // static LLLinkedList LLDynamicTexture::sInstances[ LLDynamicTexture::ORDER_COUNT ]; @@ -64,6 +66,7 @@ LLDynamicTexture::LLDynamicTexture(S32 width, S32 height, S32 components, EOrder //----------------------------------------------------------------------------- LLDynamicTexture::~LLDynamicTexture() { + releaseGLTexture(); for( S32 order = 0; order < ORDER_COUNT; order++ ) { LLDynamicTexture::sInstances[order].removeData(this); // will fail in all but one case. @@ -71,19 +74,23 @@ LLDynamicTexture::~LLDynamicTexture() } //----------------------------------------------------------------------------- -// generateGLTexture() +// releaseGLTexture() //----------------------------------------------------------------------------- -void LLDynamicTexture::generateGLTexture() +void LLDynamicTexture::releaseGLTexture() { - if (mComponents < 1 || mComponents > 4) + if (mTexture.notNull()) { - llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl; +// llinfos << "RELEASING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; + mTexture = NULL; } +} - LLPointer raw_image = new LLImageRaw(mWidth, mHeight, mComponents); - mTexture = new LLImageGL(mWidth, mHeight, mComponents, FALSE); - mTexture->createGLTexture(0, raw_image); - mTexture->setClamp(mClamp, mClamp); +//----------------------------------------------------------------------------- +// generateGLTexture() +//----------------------------------------------------------------------------- +void LLDynamicTexture::generateGLTexture() +{ + generateGLTexture(-1, 0, 0, FALSE); } void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes) @@ -92,10 +99,14 @@ void LLDynamicTexture::generateGLTexture(LLGLint internal_format, LLGLenum prima { llerrs << "Bad number of components in dynamic texture: " << mComponents << llendl; } - + releaseGLTexture(); LLPointer raw_image = new LLImageRaw(mWidth, mHeight, mComponents); mTexture = new LLImageGL(mWidth, mHeight, mComponents, FALSE); - mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); + if (internal_format >= 0) + { + mTexture->setExplicitFormat(internal_format, primary_format, type_format, swap_bytes); + } +// llinfos << "ALLOCATING " << (mWidth*mHeight*mComponents)/1024 << "K" << llendl; mTexture->createGLTexture(0, raw_image); mTexture->setClamp(mClamp, mClamp); } @@ -193,6 +204,8 @@ BOOL LLDynamicTexture::updateAllInstances() return TRUE; } + BOOL started = FALSE; + BOOL result = FALSE; for( S32 order = 0; order < ORDER_COUNT; order++ ) { @@ -202,11 +215,16 @@ BOOL LLDynamicTexture::updateAllInstances() { if (dynamicTexture->needsRender()) { + if (!started) + { + started = TRUE; + LLVertexBuffer::startRender(); + } + dynamicTexture->preRender(); if (dynamicTexture->render()) { result = TRUE; - gViewerWindow->finishFastFrame(); sNumRenders++; } dynamicTexture->postRender(result); @@ -214,6 +232,11 @@ BOOL LLDynamicTexture::updateAllInstances() } } + if (started) + { + LLVertexBuffer::stopRender(); + } + return result; } diff --git a/linden/indra/newview/lldynamictexture.h b/linden/indra/newview/lldynamictexture.h index fda424c..b11bed3 100644 --- a/linden/indra/newview/lldynamictexture.h +++ b/linden/indra/newview/lldynamictexture.h @@ -66,6 +66,7 @@ public: static void restoreGL(); protected: + void releaseGLTexture(); void generateGLTexture(); void generateGLTexture(LLGLint internal_format, LLGLenum primary_format, LLGLenum type_format, BOOL swap_bytes = FALSE); diff --git a/linden/indra/newview/lleventinfo.cpp b/linden/indra/newview/lleventinfo.cpp index 02ac3ed..103450e 100644 --- a/linden/indra/newview/lleventinfo.cpp +++ b/linden/indra/newview/lleventinfo.cpp @@ -71,7 +71,7 @@ void LLEventInfo::unpack(LLMessageSystem *msg) msg->getU32("EventData", "EventID", event_id); mID = event_id; - char buffer[MAX_DESC_LENGTH]; + char buffer[MAX_DESC_LENGTH]; /*Flawfinder: ignore*/ msg->getString("EventData", "Name", MAX_DESC_LENGTH, buffer); mName = buffer; @@ -106,7 +106,7 @@ void LLEventInfo::unpack(LLMessageSystem *msg) mCover = cover; } - char sim_name[256]; + char sim_name[256]; /*Flawfinder: ignore*/ msg->getString("EventData", "SimName", 256, sim_name); mSimName.assign(sim_name); diff --git a/linden/indra/newview/llface.cpp b/linden/indra/newview/llface.cpp index a6de94b..e46fcd3 100644 --- a/linden/indra/newview/llface.cpp +++ b/linden/indra/newview/llface.cpp @@ -29,13 +29,13 @@ #include "lldrawable.h" // lldrawable needs to be included before llface #include "llface.h" +#include "llviewertextureanim.h" #include "llviewercontrol.h" #include "llvolume.h" #include "m3math.h" #include "v3color.h" -#include "llagparray.h" #include "lldrawpoolsimple.h" #include "lldrawpoolbump.h" #include "llgl.h" @@ -47,8 +47,6 @@ #include "llvovolume.h" #include "pipeline.h" -#include "llagparray.inl" - #define LL_MAX_INDICES_COUNT 1000000 extern BOOL gPickFaces; @@ -137,25 +135,23 @@ void cylindricalProjection(LLVector2 &tc, const LLVolumeFace::VertexData &vd, co void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) { - mGeneration = DIRTY; + mLastUpdateTime = gFrameTimeSeconds; + mVSize = 0.f; + mPixelArea = 1024.f; mState = GLOBAL; mDrawPoolp = NULL; + mPoolType = 0; mGeomIndex = -1; - mSkipRender = FALSE; - mNextFace = NULL; // mCenterLocal // mCenterAgent mDistance = 0.f; - mPrimType = LLTriangles; mGeomCount = 0; mIndicesCount = 0; mIndicesIndex = -1; mTexture = NULL; mTEOffset = -1; - mBackupMem = NULL; - setDrawable(drawablep); mVObjp = objp; @@ -163,6 +159,12 @@ void LLFace::init(LLDrawable* drawablep, LLViewerObject* objp) mAlphaFade = 0.f; mFaceColor = LLColor4(1,0,0,1); + + mLastVertexBuffer = mVertexBuffer; + mLastGeomCount = mGeomCount; + mLastGeomIndex = mGeomIndex; + mLastIndicesCount = mIndicesCount; + mLastIndicesIndex = mIndicesIndex; } @@ -176,11 +178,6 @@ void LLFace::destroy() mDrawPoolp->removeFace(this); mDrawPoolp = NULL; } - - // Remove light and blocker list references - - delete[] mBackupMem; - mBackupMem = NULL; } @@ -194,13 +191,7 @@ void LLFace::setWorldMatrix(const LLMatrix4 &mat) llerrs << "Faces on this drawable are not independently modifiable\n" << llendl; } - -void LLFace::setDirty() -{ - mGeneration = DIRTY; -} - -void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep) +void LLFace::setPool(LLFacePool* new_pool, LLViewerImage *texturep) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); @@ -215,22 +206,12 @@ void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep) if (mDrawPoolp) { mDrawPoolp->removeFace(this); - mSkipRender = FALSE; - mNextFace = NULL; - // Invalidate geometry (will get rebuilt next frame) - setDirty(); if (mDrawablep) { gPipeline.markRebuild(mDrawablep, LLDrawable::REBUILD_ALL, TRUE); } } - if (isState(BACKLIST)) - { - delete[] mBackupMem; - mBackupMem = NULL; - clearState(BACKLIST); - } mGeomIndex = -1; // Add to new pool @@ -239,7 +220,6 @@ void LLFace::setPool(LLDrawPool* new_pool, LLViewerImage *texturep) new_pool->addFace(this); } mDrawPoolp = new_pool; - } mTexture = texturep; } @@ -268,91 +248,12 @@ void LLFace::setDrawable(LLDrawable *drawable) mXform = &drawable->mXform; } -S32 LLFace::allocBackupMem() -{ - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - - S32 size = 0; - size += mIndicesCount * 4; - size += mGeomCount * mDrawPoolp->getStride(); - - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) - { - size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_VERTEX_WEIGHTS]; - } - - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) - { - size += mGeomCount * mDrawPoolp->sDataSizes[LLDrawPool::DATA_CLOTHING_WEIGHTS]; - } - - delete[] mBackupMem; - mBackupMem = new U8[size]; - return size; -} - - void LLFace::setSize(const S32 num_vertices, const S32 num_indices) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - if (getState() & SHARED_GEOM) - { - mGeomCount = num_vertices; - mIndicesCount = num_indices; - return; // Shared, don't allocate or do anything with memory - } - if (num_vertices != (S32)mGeomCount || num_indices != (S32)mIndicesCount) - { - setDirty(); - - delete[] mBackupMem; - mBackupMem = NULL; - clearState(BACKLIST); - - mGeomCount = num_vertices; - mIndicesCount = num_indices; - } - -} - -BOOL LLFace::reserveIfNeeded() -{ - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - - if (getDirty()) - { - if (isState(BACKLIST)) - { - llwarns << "Reserve on backlisted object!" << llendl; - } - - if (0 == mGeomCount) - { - //llwarns << "Reserving zero bytes for face!" << llendl; - mGeomCount = 0; - mIndicesCount = 0; - return FALSE; - } - - mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount); - // (reserveGeom() always returns a valid index) - mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount); - mGeneration = mDrawPoolp->mGeneration; - } - - return TRUE; -} - -void LLFace::unReserve() -{ - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - - if (!(isState(SHARED_GEOM))) - { - mGeomIndex = mDrawPoolp->unReserveGeom(mGeomIndex, mGeomCount); - mIndicesIndex = mDrawPoolp->unReserveInd(mIndicesIndex, mIndicesCount); - } + mGeomCount = num_vertices; + mIndicesCount = num_indices; } //============================================================================ @@ -366,55 +267,22 @@ S32 LLFace::getGeometryAvatar( LLStrider &clothing_weights) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - - if (mGeomCount <= 0) - { - return -1; - } - - if (isState(BACKLIST)) - { - if (!mBackupMem) - { - llerrs << "No backup memory for backlist" << llendl; - } - - vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); - normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); - binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]); - tex_coords = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); - clothing_weights = (LLVector4*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_CLOTHING_WEIGHTS]); - vertex_weights = (F32*)(mBackupMem + (4 * mIndicesCount) + (mGeomCount * mDrawPoolp->getStride())); - tex_coords.setStride( mDrawPoolp->getStride()); - vertices.setStride( mDrawPoolp->getStride()); - normals.setStride( mDrawPoolp->getStride()); - binormals.setStride( mDrawPoolp->getStride()); - clothing_weights.setStride( mDrawPoolp->getStride()); - return 0; + if (mVertexBuffer.notNull()) + { + mVertexBuffer->getVertexStrider (vertices, mGeomIndex); + mVertexBuffer->getNormalStrider (normals, mGeomIndex); + mVertexBuffer->getBinormalStrider (binormals, mGeomIndex); + mVertexBuffer->getTexCoordStrider (tex_coords, mGeomIndex); + mVertexBuffer->getWeightStrider(vertex_weights, mGeomIndex); + mVertexBuffer->getClothWeightStrider(clothing_weights, mGeomIndex); } else { - if (!reserveIfNeeded()) - { - return -1; - } - - llassert(mGeomIndex >= 0); - llassert(mIndicesIndex >= 0); - - mDrawPoolp->getVertexStrider (vertices, mGeomIndex); - mDrawPoolp->getNormalStrider (normals, mGeomIndex); - mDrawPoolp->getBinormalStrider (binormals, mGeomIndex); - mDrawPoolp->getTexCoordStrider (tex_coords, mGeomIndex); - mDrawPoolp->getVertexWeightStrider(vertex_weights, mGeomIndex); - mDrawPoolp->getClothingWeightStrider(clothing_weights, mGeomIndex); - - mDrawPoolp->setDirty(); - - llassert(mGeomIndex >= 0); - return mGeomIndex; + mGeomIndex = -1; } + + return mGeomIndex; } S32 LLFace::getGeometryTerrain( @@ -423,64 +291,29 @@ S32 LLFace::getGeometryTerrain( LLStrider &colors, LLStrider &texcoords0, LLStrider &texcoords1, - U32 *&indicesp) + LLStrider &indicesp) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - if (mGeomCount <= 0) - { - return -1; - } - - if (isState(BACKLIST)) + if (mVertexBuffer.notNull()) { - if (!mBackupMem) - { - printDebugInfo(); - llerrs << "No backup memory for face" << llendl; - } - vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); - normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); - colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]); - texcoords0= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); - texcoords1= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]); - texcoords0.setStride(mDrawPoolp->getStride()); - texcoords1.setStride(mDrawPoolp->getStride()); - vertices.setStride( mDrawPoolp->getStride()); - normals.setStride( mDrawPoolp->getStride()); - colors.setStride( mDrawPoolp->getStride()); - indicesp = (U32*)mBackupMem; - - return 0; + mVertexBuffer->getVertexStrider(vertices, mGeomIndex); + mVertexBuffer->getNormalStrider(normals, mGeomIndex); + mVertexBuffer->getColorStrider(colors, mGeomIndex); + mVertexBuffer->getTexCoordStrider(texcoords0, mGeomIndex); + mVertexBuffer->getTexCoord2Strider(texcoords1, mGeomIndex); + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); } else { - if (!reserveIfNeeded()) - { - llinfos << "Get geometry failed!" << llendl; - return -1; - } - - llassert(mGeomIndex >= 0); - llassert(mIndicesIndex >= 0); - - mDrawPoolp->getVertexStrider(vertices, mGeomIndex); - mDrawPoolp->getNormalStrider(normals, mGeomIndex); - mDrawPoolp->getColorStrider(colors, mGeomIndex); - mDrawPoolp->getTexCoordStrider(texcoords0, mGeomIndex, 0); - mDrawPoolp->getTexCoordStrider(texcoords1, mGeomIndex, 1); - - indicesp = mDrawPoolp->getIndices(mIndicesIndex); - - mDrawPoolp->setDirty(); - - llassert(mGeomIndex >= 0); - return mGeomIndex; + mGeomIndex = -1; } + + return mGeomIndex; } S32 LLFace::getGeometry(LLStrider &vertices, LLStrider &normals, - LLStrider &tex_coords, U32 *&indicesp) + LLStrider &tex_coords, LLStrider &indicesp) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); @@ -489,55 +322,31 @@ S32 LLFace::getGeometry(LLStrider &vertices, LLStrider &no return -1; } - if (isState(BACKLIST)) + if (mVertexBuffer.notNull()) { - if (!mBackupMem) + mVertexBuffer->getVertexStrider(vertices, mGeomIndex); + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_NORMAL)) { - printDebugInfo(); - llerrs << "No backup memory for face" << llendl; + mVertexBuffer->getNormalStrider(normals, mGeomIndex); + } + if (mVertexBuffer->hasDataType(LLVertexBuffer::TYPE_TEXCOORD)) + { + mVertexBuffer->getTexCoordStrider(tex_coords, mGeomIndex); } - vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); - normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); - tex_coords= (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); - tex_coords.setStride(mDrawPoolp->getStride()); - vertices.setStride( mDrawPoolp->getStride()); - normals.setStride( mDrawPoolp->getStride()); - indicesp = (U32*)mBackupMem; - return 0; + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); } else { - if (!reserveIfNeeded()) - { - return -1; - } - - llassert(mGeomIndex >= 0); - llassert(mIndicesIndex >= 0); - - mDrawPoolp->getVertexStrider(vertices, mGeomIndex); - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK) - { - mDrawPoolp->getNormalStrider(normals, mGeomIndex); - } - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK) - { - mDrawPoolp->getTexCoordStrider(tex_coords, mGeomIndex); - } - - indicesp =mDrawPoolp->getIndices (mIndicesIndex); - - mDrawPoolp->setDirty(); - - llassert(mGeomIndex >= 0); - return mGeomIndex; + mGeomIndex = -1; } + + return mGeomIndex; } S32 LLFace::getGeometryColors(LLStrider &vertices, LLStrider &normals, LLStrider &tex_coords, LLStrider &colors, - U32 *&indicesp) + LLStrider &indicesp) { S32 res = getGeometry(vertices, normals, tex_coords, indicesp); if (res >= 0) @@ -547,95 +356,25 @@ S32 LLFace::getGeometryColors(LLStrider &vertices, LLStrider &vertices, - LLStrider &normals, - LLStrider &binormals, - LLStrider &tex_coords0, - LLStrider &tex_coords1, - U32 *&indicesp) +void LLFace::updateCenterAgent() { - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - - if (mGeomCount <= 0) + if (mDrawablep->isActive()) { - return -1; - } - - if (isState(BACKLIST)) - { - if (!mBackupMem) - { - printDebugInfo(); - llerrs << "No backup memory for face" << llendl; - } - vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); - normals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_NORMALS]); - tex_coords0 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS0]); - tex_coords0.setStride( mDrawPoolp->getStride() ); - vertices.setStride( mDrawPoolp->getStride() ); - normals.setStride( mDrawPoolp->getStride() ); - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) - { - binormals = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_BINORMALS]); - binormals.setStride( mDrawPoolp->getStride() ); - } - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK) - { - tex_coords1 = (LLVector2*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_TEX_COORDS1]); - tex_coords1.setStride( mDrawPoolp->getStride() ); - } - indicesp = (U32*)mBackupMem; - - return 0; + mCenterAgent = mCenterLocal * getRenderMatrix(); } else { - if (!reserveIfNeeded()) - { - return -1; - } - - llassert(mGeomIndex >= 0); - llassert(mIndicesIndex >= 0); - - mDrawPoolp->getVertexStrider(vertices, mGeomIndex); - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_NORMALS_MASK) - { - mDrawPoolp->getNormalStrider(normals, mGeomIndex); - } - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS0_MASK) - { - mDrawPoolp->getTexCoordStrider(tex_coords0, mGeomIndex); - } - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) - { - mDrawPoolp->getBinormalStrider(binormals, mGeomIndex); - } - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_TEX_COORDS1_MASK) - { - mDrawPoolp->getTexCoordStrider(tex_coords1, mGeomIndex, 1); - } - indicesp = mDrawPoolp->getIndices(mIndicesIndex); - - mDrawPoolp->setDirty(); - - llassert(mGeomIndex >= 0); - return mGeomIndex; + mCenterAgent = mCenterLocal; } } -void LLFace::updateCenterAgent() -{ - mCenterAgent = mCenterLocal * getRenderMatrix(); -} - -void LLFace::renderForSelect() const +void LLFace::renderForSelect(U32 data_mask) { - if(mGeomIndex < 0 || mDrawablep.isNull()) + if(mGeomIndex < 0 || mDrawablep.isNull() || mVertexBuffer.isNull()) { return; } + if (mVObjp->mGLName) { S32 name = mVObjp->mGLName; @@ -649,47 +388,25 @@ void LLFace::renderForSelect() const #endif glColor4ubv(color.mV); - if (mVObjp->getPCode() == LL_PCODE_VOLUME) + if (!getPool()) { - LLVOVolume *volp; - volp = (LLVOVolume *)(LLViewerObject*)mVObjp; - if (volp->getNumFaces() == 1 && !volp->getVolumeChanged()) + switch (getPoolType()) { - // We need to special case the coalesced face model. - S32 num_vfs = volp->getVolume()->getNumFaces(); - S32 offset = 0; - S32 i; - - for (i = 0; i < num_vfs; i++) - { - if (gPickFaces) - { - // mask off high 4 bits (16 total possible faces) - color.mV[0] &= 0x0f; - color.mV[0] |= (i & 0x0f) << 4; - glColor4ubv(color.mV); - } - S32 count = volp->getVolume()->getVolumeFace(i).mIndices.size(); - if (isState(GLOBAL)) - { - glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); - } - else - { - glPushMatrix(); - glMultMatrixf((float*)getRenderMatrix().mMatrix); - glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); - glPopMatrix(); - } - offset += count; - } - // We're done, return. - return; + case LLDrawPool::POOL_ALPHA: + getTexture()->bind(); + break; + default: + LLImageGL::unbindTexture(0); + break; } - - // We don't have coalesced faces, do this the normal way. } + mVertexBuffer->setBuffer(data_mask); +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(data_mask); +#endif + U32* indicesp = (U32*) mVertexBuffer->getIndicesPointer() + mIndicesIndex; + if (gPickFaces && mTEOffset != -1) { // mask off high 4 bits (16 total possible faces) @@ -702,13 +419,13 @@ void LLFace::renderForSelect() const { if (isState(GLOBAL)) { - glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); + glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp); } else { glPushMatrix(); glMultMatrixf((float*)getRenderMatrix().mMatrix); - glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); + glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp); glPopMatrix(); } } @@ -716,13 +433,13 @@ void LLFace::renderForSelect() const { if (isState(GLOBAL)) { - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); + glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); } else { glPushMatrix(); glMultMatrixf((float*)getRenderMatrix().mMatrix); - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); + glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); glPopMatrix(); } } @@ -731,11 +448,12 @@ void LLFace::renderForSelect() const void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 offset, const S32 count) { - if(mGeomIndex < 0 || mDrawablep.isNull()) + if(mGeomIndex < 0 || mDrawablep.isNull() || mVertexBuffer.isNull()) { return; } - if (mGeomCount > 0) + + if (mGeomCount > 0 && mIndicesCount > 0) { LLGLSPipelineAlpha gls_pipeline_alpha; glColor4fv(color.mV); @@ -748,110 +466,27 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 glMultMatrixf((float*)getRenderMatrix().mMatrix); } - if (sSafeRenderSelect) - { - glBegin(mPrimType); - if (count) - { - for (S32 i = offset; i < offset + count; i++) - { - LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); - glTexCoord2fv(tc.mV); - LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); - glNormal3fv(normal.mV); - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv(vertex.mV); - } - } - else - { - for (U32 i = 0; i < getIndicesCount(); i++) - { - LLVector2 tc = mDrawPoolp->getTexCoord(mDrawPoolp->getIndex(getIndicesStart() + i), 0); - glTexCoord2fv(tc.mV); - LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); - glNormal3fv(normal.mV); - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv(vertex.mV); - } - } - glEnd(); - - if( gSavedSettings.getBOOL("ShowTangentBasis") ) - { - S32 start; - S32 end; - if (count) - { - start = offset; - end = offset + count; - } - else - { - start = 0; - end = getIndicesCount(); - } + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + glEnableClientState(GL_VERTEX_ARRAY); + glEnableClientState(GL_NORMAL_ARRAY); - LLGLSNoTexture gls_no_texture; - glColor4f(1, 1, 1, 1); - glBegin(GL_LINES); - for (S32 i = start; i < end; i++) - { - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv(vertex.mV); - LLVector3 normal = mDrawPoolp->getNormal(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv( (vertex + normal * 0.1f).mV ); - } - glEnd(); + mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD); +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_NORMAL | LLVertexBuffer::MAP_TEXCOORD); +#endif + U32* indicesp = ((U32*) mVertexBuffer->getIndicesPointer()) + mIndicesIndex; - if (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK) - { - glColor4f(0, 1, 0, 1); - glBegin(GL_LINES); - for (S32 i = start; i < end; i++) - { - LLVector3 vertex = mDrawPoolp->getVertex(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv(vertex.mV); - LLVector3 binormal = mDrawPoolp->getBinormal(mDrawPoolp->getIndex(getIndicesStart() + i)); - glVertex3fv( (vertex + binormal * 0.1f).mV ); - } - glEnd(); - } - } + if (count) + { + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indicesp + offset); } else { - glEnableClientState(GL_TEXTURE_COORD_ARRAY); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_NORMAL_ARRAY); - if (count) - { - if (mIndicesCount > 0) - { - glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); - } - else - { - llerrs << "Rendering non-indexed volume face!" << llendl; - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); - } - } - else - { - if (mIndicesCount > 0) - { - glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); - } - else - { - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); - } - } - glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_NORMAL_ARRAY); + glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, indicesp); } - + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_NORMAL_ARRAY); + if (!isState(GLOBAL)) { // Restore the tranform for non-global objects @@ -862,6 +497,7 @@ void LLFace::renderSelected(LLImageGL *imagep, const LLColor4& color, const S32 void LLFace::renderSelectedUV(const S32 offset, const S32 count) { +#if 0 LLUUID uv_img_red_blue_id(gViewerArt.getString("uv_test1.tga")); LLUUID uv_img_green_id(gViewerArt.getString("uv_test2.tga")); LLViewerImage* red_blue_imagep = gImageList.getImage(uv_img_red_blue_id, TRUE, TRUE); @@ -911,7 +547,7 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count) glPolygonOffset(factor, bias); if (sSafeRenderSelect) { - glBegin(mPrimType); + glBegin(GL_TRIANGLES); if (count) { for (S32 i = offset; i < offset + count; i++) @@ -943,7 +579,7 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count) { if (mIndicesCount > 0) { - glDrawElements(mPrimType, count, GL_UNSIGNED_INT, getRawIndices() + offset); + glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, getRawIndices() + offset); } else { @@ -955,15 +591,14 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count) { if (mIndicesCount > 0) { - glDrawElements(mPrimType, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); + glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, getRawIndices()); } else { - glDrawArrays(mPrimType, mGeomIndex, mGeomCount); + glDrawArrays(GL_TRIANGLES, mGeomIndex, mGeomCount); } } glDisableClientState(GL_TEXTURE_COORD_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); } glDisable(GL_POLYGON_OFFSET_FILL); @@ -984,12 +619,13 @@ void LLFace::renderSelectedUV(const S32 offset, const S32 count) //restore blend func glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +#endif } void LLFace::printDebugInfo() const { - LLDrawPool *poolp = getPool(); + LLFacePool *poolp = getPool(); llinfos << "Object: " << getViewerObject()->mID << llendl; if (getDrawable()) { @@ -1005,10 +641,6 @@ void LLFace::printDebugInfo() const } llinfos << "Face: " << this << llendl; - if (isState(BACKLIST)) - { - llinfos << "Backlisted!" << llendl; - } llinfos << "State: " << getState() << llendl; llinfos << "Geom Index Data:" << llendl; llinfos << "--------------------" << llendl; @@ -1037,7 +669,7 @@ void LLFace::printDebugInfo() const llinfos << "Incorrect number of pool references!" << llendl; } - +#if 0 llinfos << "Indices:" << llendl; llinfos << "--------------------" << llendl; @@ -1058,222 +690,231 @@ void LLFace::printDebugInfo() const llinfos << mGeomIndex + i << ":" << poolp->getVertex(mGeomIndex + i) << llendl; } llinfos << llendl; +#endif +} + +// Transform the texture coordinates for this face. +static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 offT, F32 magS, F32 magT) +{ + // New, good way + F32 s = tex_coord.mV[0]; + F32 t = tex_coord.mV[1]; + + // Texture transforms are done about the center of the face. + s -= 0.5; + t -= 0.5; + + // Handle rotation + F32 temp = s; + s = s * cosAng + t * sinAng; + t = -temp * sinAng + t * cosAng; + + // Then scale + s *= magS; + t *= magT; + + // Then offset + s += offS + 0.5f; + t += offT + 0.5f; + + tex_coord.mV[0] = s; + tex_coord.mV[1] = t; } -S32 LLFace::backup() + +BOOL LLFace::genVolumeBBoxes(const LLVolume &volume, S32 f, + const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL global_volume) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); + + const LLVolumeFace &face = volume.getVolumeFace(f); - if (isState(BACKLIST)) - { - llwarns << "Face is already backed up in LLFace::backup!" << llendl; - return mGeomCount; - } - if (mGeomIndex < 0) - { - // flexible objects can cause this - //llwarns << "No geometry to back-up" << llendl; - return 0; - } - - S32 size = 0; - if (!mBackupMem) - { - size = allocBackupMem(); - } - else + //get bounding box + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) { - llerrs << "Memory already backed up!" << llendl; - } + if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + { //vertex buffer no longer valid + mVertexBuffer = NULL; + mLastVertexBuffer = NULL; + } - // Need to flag this, because we can allocate a non-zero backup mem if we have indices and no geometry. + LLVector3 min,max; + + min = face.mExtents[0]; + max = face.mExtents[1]; - if (mGeomCount || mIndicesCount) - { - setState(BACKLIST); -#if !RELEASE_FOR_DOWNLOAD - if (mGeomIndex < 0 || mIndicesIndex < 0) + //min, max are in volume space, convert to drawable render space + LLVector3 center = ((min + max) * 0.5f)*mat_vert; + LLVector3 size = ((max-min) * 0.5f); + if (!global_volume) { - llerrs << "LLFace::backup" << llendl; + size.scaleVec(mDrawablep->getVObj()->getScale()); } -#endif + LLQuaternion rotation = LLQuaternion(mat_normal); - U32 *backup = (U32*)mBackupMem; - S32 stride = mDrawPoolp->getStride(); + LLVector3 v[4]; + //get 4 corners of bounding box + v[0] = (size * rotation); + v[1] = (LLVector3(-size.mV[0], -size.mV[1], size.mV[2]) * rotation); + v[2] = (LLVector3(size.mV[0], -size.mV[1], -size.mV[2]) * rotation); + v[3] = (LLVector3(-size.mV[0], size.mV[1], -size.mV[2]) * rotation); + + LLVector3& newMin = mExtents[0]; + LLVector3& newMax = mExtents[1]; - U32 *index = mDrawPoolp->getIndices(mIndicesIndex); - for (U32 i=0;imMemory.getMem() + mGeomIndex * stride), mGeomCount * stride); - backup += mGeomCount * stride / 4; - - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) - { - memcpy(backup, &mDrawPoolp->getClothingWeight(mGeomIndex), mGeomCount * sizeof(LLVector4)); - backup += mGeomCount*4; - } - - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) + newMin = newMax = center; + + for (U32 i = 0; i < 4; i++) { - memcpy(backup, &mDrawPoolp->getVertexWeight(mGeomIndex), mGeomCount * sizeof(F32)); - backup += mGeomCount; + for (U32 j = 0; j < 3; j++) + { + F32 delta = fabsf(v[i].mV[j]); + F32 min = center.mV[j] - delta; + F32 max = center.mV[j] + delta; + + if (min < newMin.mV[j]) + { + newMin.mV[j] = min; + } + + if (max > newMax.mV[j]) + { + newMax.mV[j] = max; + } + } } - llassert((U8*)backup - mBackupMem == size); - - unReserve(); + mCenterLocal = (newMin+newMax)*0.5f; + updateCenterAgent(); } - return mGeomCount; + + return TRUE; } -void LLFace::restore() + +BOOL LLFace::getGeometryVolume(const LLVolume& volume, + S32 f, + LLStrider& vertices, + LLStrider& normals, + LLStrider& tex_coords, + LLStrider& tex_coords2, + LLStrider& colors, + LLStrider& indicesp, + const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, + U32& index_offset) { - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); + const LLVolumeFace &vf = volume.getVolumeFace(f); + S32 num_vertices = (S32)vf.mVertices.size(); + S32 num_indices = (S32)vf.mIndices.size(); - if (!isState(BACKLIST)) - { - // flexible objects can cause this -// printDebugInfo(); -// llwarns << "not backlisted for restore" << llendl; - return; - } - if (!mGeomCount || !mBackupMem) - { - if (!mBackupMem) - { - printDebugInfo(); - llwarns << "no backmem for restore" << llendl; - } - - clearState(BACKLIST); - return; - } + LLStrider old_verts; + LLStrider old_texcoords; + LLStrider old_texcoords2; + LLStrider old_normals; + LLStrider old_colors; - S32 stride = mDrawPoolp->getStride(); - mGeomIndex = mDrawPoolp->reserveGeom(mGeomCount); - mIndicesIndex = mDrawPoolp->reserveInd (mIndicesCount); - mGeneration = mDrawPoolp->mGeneration; + BOOL full_rebuild = mDrawablep->isState(LLDrawable::REBUILD_VOLUME); + BOOL moved = TRUE; - llassert(mGeomIndex >= 0); - llassert(mIndicesIndex >= 0); - - U32 *backup = (U32*)mBackupMem; - U32 *index = mDrawPoolp->getIndices(mIndicesIndex); - - for (U32 i=0;igetVOVolume()->isVolumeGlobal(); + LLVector3 scale; + if (global_volume) { - S32 ind = mGeomIndex + *backup; - index[i] = ind; - backup++; + scale.setVec(1,1,1); } - - mDrawPoolp->mMemory.copyToMem(mGeomIndex * stride, (U8 *)backup, mGeomCount * stride); - backup += mGeomCount * stride / 4; - - // - // Don't change the order of these unles you change the corresponding getGeometry calls that read out of - // backup memory, and also the other of the backup/restore pair! - // - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_CLOTHING_WEIGHTS_MASK) - { - mDrawPoolp->mClothingWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount); - backup += mGeomCount*4; - } - - if (mDrawPoolp->mDataMaskNIL & LLDrawPool::DATA_VERTEX_WEIGHTS_MASK) + else { - mDrawPoolp->mWeights.copyToMem(mGeomIndex, (U8 *)backup, mGeomCount); - backup += mGeomCount; + scale = mVObjp->getScale(); } - delete[] mBackupMem; - mBackupMem = NULL; - clearState(BACKLIST); -} - -// Transform the texture coordinates for this face. -static void xform(LLVector2 &tex_coord, F32 cosAng, F32 sinAng, F32 offS, F32 offT, F32 magS, F32 magT) -{ - // New, good way - F32 s = tex_coord.mV[0]; - F32 t = tex_coord.mV[1]; - - // Texture transforms are done about the center of the face. - s -= 0.5; - t -= 0.5; - - // Handle rotation - F32 temp = s; - s = s * cosAng + t * sinAng; - t = -temp * sinAng + t * cosAng; - - // Then scale - s *= magS; - t *= magT; - - // Then offset - s += offS + 0.5f; - t += offT + 0.5f; + if (!full_rebuild) + { + if (mLastVertexBuffer == mVertexBuffer && + !mVertexBuffer->isEmpty()) + { //this face really doesn't need to be regenerated, try real hard not to do so + if (mLastGeomCount == mGeomCount && + mLastGeomIndex == mGeomIndex && + mLastIndicesCount == mIndicesCount && + mLastIndicesIndex == mIndicesIndex) + { //data is in same location in vertex buffer + moved = FALSE; + } - tex_coord.mV[0] = s; - tex_coord.mV[1] = t; -} + if (!moved && !mDrawablep->isState(LLDrawable::REBUILD_ALL)) + { //nothing needs to be done + vertices += mGeomCount; + normals += mGeomCount; + tex_coords += mGeomCount; + colors += mGeomCount; + tex_coords2 += mGeomCount; + index_offset += mGeomCount; + indicesp += mIndicesCount; + return FALSE; + } + if (mLastGeomCount == mGeomCount) + { + if (mLastGeomIndex >= mGeomIndex && + mLastGeomIndex + mGeomCount+1 < mVertexBuffer->getNumVerts()) + { + //copy from further down the buffer + mVertexBuffer->getVertexStrider(old_verts, mLastGeomIndex); + mVertexBuffer->getTexCoordStrider(old_texcoords, mLastGeomIndex); + mVertexBuffer->getTexCoord2Strider(old_texcoords2, mLastGeomIndex); + mVertexBuffer->getNormalStrider(old_normals, mLastGeomIndex); + mVertexBuffer->getColorStrider(old_colors, mLastGeomIndex); + + if (!mDrawablep->isState(LLDrawable::REBUILD_ALL)) + { + //quick copy + for (S32 i = 0; i < mGeomCount; i++) + { + *vertices++ = *old_verts++; + *tex_coords++ = *old_texcoords++; + *tex_coords2++ = *old_texcoords2++; + *colors++ = *old_colors++; + *normals++ = *old_normals++; + } -BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 f, - const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume) -{ - const LLVolumeFace &vf = volume.getVolumeFace(f); - S32 num_vertices = (S32)vf.mVertices.size(); - S32 num_indices = (S32)vf.mIndices.size(); - setSize(num_vertices, num_indices); - - return genVolumeTriangles(volume, f, f, mat, inv_trans_mat, global_volume); -} + for (U32 i = 0; i < mIndicesCount; i++) + { + *indicesp++ = vf.mIndices[i] + index_offset; + } -BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, const BOOL global_volume) -{ - LLMemType mt1(LLMemType::MTYPE_DRAWABLE); + index_offset += mGeomCount; + mLastGeomIndex = mGeomIndex; + mLastIndicesCount = mIndicesCount; + mLastIndicesIndex = mIndicesIndex; - if (!mDrawablep) + return TRUE; + } + } + else + { + full_rebuild = TRUE; + } + } + } + else + { + full_rebuild = TRUE; + } + } + else { - return TRUE; + mLastUpdateTime = gFrameTimeSeconds; } - S32 index_offset; - F32 r, os, ot, ms, mt, cos_ang, sin_ang; - LLStrider vertices; - LLStrider normals; - LLStrider binormals; - LLStrider tex_coords; - LLStrider tex_coords2; - U32 *indicesp = NULL; - BOOL bump = mDrawPoolp && (mDrawPoolp->mDataMaskIL & LLDrawPool::DATA_BINORMALS_MASK); + BOOL rebuild_pos = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_POSITION); + BOOL rebuild_color = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_COLOR); + BOOL rebuild_tcoord = full_rebuild || mDrawablep->isState(LLDrawable::REBUILD_TCOORD); + + F32 r = 0, os = 0, ot = 0, ms = 0, mt = 0, cos_ang = 0, sin_ang = 0; + BOOL is_static = mDrawablep->isStatic(); BOOL is_global = is_static; - - if (bump) - { - index_offset = getGeometryMultiTexture(vertices, normals, binormals, tex_coords, tex_coords2, indicesp); - } - else - { - index_offset = getGeometry(vertices, normals, tex_coords, indicesp); - } + if (-1 == index_offset) { return TRUE; @@ -1281,16 +922,6 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, LLVector3 center_sum(0.f, 0.f, 0.f); - LLVector3 render_pos; - - if (mDrawablep->isState(LLDrawable::REBUILD_TCOORD) && - global_volume) - { - render_pos = mVObjp->getRenderPosition(); - } - - setPrimType(LLTriangles); - if (is_global) { setState(GLOBAL); @@ -1299,26 +930,16 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, { clearState(GLOBAL); } - - LLVector3 min, max; + LLVector2 tmin, tmax; - BOOL grab_first_vert = TRUE; - BOOL grab_first_tcoord = TRUE; - - for (S32 vol_face = fstart; vol_face <= fend; vol_face++) + const LLTextureEntry *tep = mVObjp->getTE(f); + U8 bump_code = tep ? bump_code = tep->getBumpmap() : 0; + + if (rebuild_tcoord) { - const LLVolumeFace &vf = volume.getVolumeFace(vol_face); - S32 num_vertices = (S32)vf.mVertices.size(); - S32 num_indices = (S32)vf.mIndices.size(); - llassert(num_indices > 0); - - U8 bump_code; - const LLTextureEntry *tep = mVObjp->getTE(vol_face); - if (tep) { - bump_code = tep->getBumpmap(); r = tep->getRotation(); os = tep->mOffsetS; ot = tep->mOffsetT; @@ -1329,7 +950,6 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, } else { - bump_code = 0; cos_ang = 1.0f; sin_ang = 0.0f; os = 0.0f; @@ -1337,209 +957,235 @@ BOOL LLFace::genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, ms = 1.0f; mt = 1.0f; } + } - if (mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + if (isState(TEXTURE_ANIM)) + { + LLVOVolume* vobj = (LLVOVolume*) (LLViewerObject*) mVObjp; + U8 mode = vobj->mTexAnimMode; + if (!mode) { - // VERTICES & NORMALS - for (S32 i = 0; i < num_vertices; i++) + clearState(TEXTURE_ANIM); + } + else + { + //if (mode & LLViewerTextureAnim::TRANSLATE) { - LLVector3 v; - v = vf.mVertices[i].mPosition * mat_vert; - - LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; - normal.normVec(); - *normals++ = normal; - - *vertices++ = v; - - if (grab_first_vert) - { - grab_first_vert = FALSE; - min = max = v; - } - else - { - for (U32 j = 0; j < 3; j++) - { - if (v.mV[j] < min.mV[j]) - { - min.mV[j] = v.mV[j]; - } - if (v.mV[j] > max.mV[j]) - { - max.mV[j] = v.mV[j]; - } - } - } + os = ot = 0.f; } - for (S32 i = 0; i < num_indices; i++) + //if (mode & LLViewerTextureAnim::ROTATE) { - S32 index = vf.mIndices[i] + index_offset; - llassert(index >= 0 && (i != 1 || *(indicesp-1)!=(U32)index)); - *indicesp++ = index; + r = 0.f; + cos_ang = 1.f; + sin_ang = 0.f; + } + //if (mode & LLViewerTextureAnim::SCALE) + { + ms = mt = 1.f; } } + } - if ((mDrawablep->isState(LLDrawable::REBUILD_TCOORD)) || - ((bump || getTextureEntry()->getTexGen() != 0) && mDrawablep->isState(LLDrawable::REBUILD_VOLUME))) + LLColor4U color = tep->getColor(); + + if (rebuild_color) + { + GLfloat alpha[4] = { - // TEX COORDS AND BINORMALS - LLVector3 binormal_dir( -sin_ang, cos_ang, 0 ); - LLVector3 bump_s_primary_light_ray; - LLVector3 bump_t_primary_light_ray; - if (bump) - { - F32 offset_multiple; - switch( bump_code ) - { - case BE_NO_BUMP: - offset_multiple = 0.f; - break; - case BE_BRIGHTNESS: - case BE_DARKNESS: - if( mTexture.notNull() && mTexture->getHasGLTexture()) - { - // Offset by approximately one texel - S32 cur_discard = mTexture->getDiscardLevel(); - S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); - max_size <<= cur_discard; - const F32 ARTIFICIAL_OFFSET = 2.f; - offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; - } - else - { - offset_multiple = 1.f/256; - } - break; + 0.00f, + 0.25f, + 0.5f, + 0.75f + }; - default: // Standard bumpmap textures. Assumed to be 256x256 - offset_multiple = 1.f / 256; - break; - } + if (gPipeline.getPoolTypeFromTE(tep, getTexture()) == LLDrawPool::POOL_BUMP) + { + color.mV[3] = U8 (alpha[tep->getShiny()] * 255); + } + } - F32 s_scale = 1.f; - F32 t_scale = 1.f; - if( tep ) - { - tep->getScale( &s_scale, &t_scale ); - } - LLVector3 sun_ray = gSky.getSunDirection(); - LLVector3 moon_ray = gSky.getMoonDirection(); - LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; - bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray; - bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray; + // INDICES + if (full_rebuild || moved) + { + for (S32 i = 0; i < num_indices; i++) + { + *indicesp++ = vf.mIndices[i] + index_offset; + } + } + else + { + indicesp += num_indices; + } + + //bump setup + LLVector3 binormal_dir( -sin_ang, cos_ang, 0 ); + LLVector3 bump_s_primary_light_ray; + LLVector3 bump_t_primary_light_ray; + + if (bump_code) + { + F32 offset_multiple; + switch( bump_code ) + { + case BE_NO_BUMP: + offset_multiple = 0.f; + break; + case BE_BRIGHTNESS: + case BE_DARKNESS: + if( mTexture.notNull() && mTexture->getHasGLTexture()) + { + // Offset by approximately one texel + S32 cur_discard = mTexture->getDiscardLevel(); + S32 max_size = llmax( mTexture->getWidth(), mTexture->getHeight() ); + max_size <<= cur_discard; + const F32 ARTIFICIAL_OFFSET = 2.f; + offset_multiple = ARTIFICIAL_OFFSET / (F32)max_size; } - - for (S32 i = 0; i < num_vertices; i++) + else { - LLVector2 tc = vf.mVertices[i].mTexCoord; + offset_multiple = 1.f/256; + } + break; - U8 texgen = getTextureEntry()->getTexGen(); - if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) - { + default: // Standard bumpmap textures. Assumed to be 256x256 + offset_multiple = 1.f / 256; + break; + } - LLVector3 vec = vf.mVertices[i].mPosition; //-vf.mCenter; - - if (global_volume) - { - vec -= render_pos; - } - else - { - vec.scaleVec(mVObjp->getScale()); - } + F32 s_scale = 1.f; + F32 t_scale = 1.f; + if( tep ) + { + tep->getScale( &s_scale, &t_scale ); + } + LLVector3 sun_ray = gSky.getSunDirection(); + LLVector3 moon_ray = gSky.getMoonDirection(); + LLVector3& primary_light_ray = (sun_ray.mV[VZ] > 0) ? sun_ray : moon_ray; + bump_s_primary_light_ray = offset_multiple * s_scale * primary_light_ray; + bump_t_primary_light_ray = offset_multiple * t_scale * primary_light_ray; + } + + U8 texgen = getTextureEntry()->getTexGen(); - switch (texgen) - { - case LLTextureEntry::TEX_GEN_PLANAR: - planarProjection(tc, vf.mVertices[i], vf.mCenter, vec); - break; - case LLTextureEntry::TEX_GEN_SPHERICAL: - sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec); - break; - case LLTextureEntry::TEX_GEN_CYLINDRICAL: - cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec); - break; - default: - break; - } - } - xform(tc, cos_ang, sin_ang, os, ot, ms, mt); - *tex_coords++ = tc; - if (grab_first_tcoord) - { - grab_first_tcoord = FALSE; - tmin = tmax = tc; - } - else - { - for (U32 j = 0; j < 2; j++) - { - if (tmin.mV[j] > tc.mV[j]) - { - tmin.mV[j] = tc.mV[j]; - } - else if (tmax.mV[j] < tc.mV[j]) - { - tmax.mV[j] = tc.mV[j]; - } - } - } - if (bump) + for (S32 i = 0; i < num_vertices; i++) + { + if (rebuild_tcoord) + { + LLVector2 tc = vf.mVertices[i].mTexCoord; + + if (texgen != LLTextureEntry::TEX_GEN_DEFAULT) + { + LLVector3 vec = vf.mVertices[i].mPosition; + + vec.scaleVec(scale); + + switch (texgen) { - LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; - LLMatrix3 tangent_to_object; - tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal); - LLVector3 binormal = binormal_dir * tangent_to_object; + case LLTextureEntry::TEX_GEN_PLANAR: + planarProjection(tc, vf.mVertices[i], vf.mCenter, vec); + break; + case LLTextureEntry::TEX_GEN_SPHERICAL: + sphericalProjection(tc, vf.mVertices[i], vf.mCenter, vec); + break; + case LLTextureEntry::TEX_GEN_CYLINDRICAL: + cylindricalProjection(tc, vf.mVertices[i], vf.mCenter, vec); + break; + default: + break; + } + } - if (!global_volume) - { - binormal = binormal * mat_normal; - } - binormal.normVec(); - tangent.normVec(); - - tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal ); - *tex_coords2++ = tc; + xform(tc, cos_ang, sin_ang, os, ot, ms, mt); + *tex_coords++ = tc; + + if (bump_code) + { + LLVector3 tangent = vf.mVertices[i].mBinormal % vf.mVertices[i].mNormal; + LLMatrix3 tangent_to_object; + tangent_to_object.setRows(tangent, vf.mVertices[i].mBinormal, vf.mVertices[i].mNormal); + LLVector3 binormal = binormal_dir * tangent_to_object; - *binormals++ = binormal; - } + binormal = binormal * mat_normal; + binormal.normVec(); + + tc += LLVector2( bump_s_primary_light_ray * tangent, bump_t_primary_light_ray * binormal ); + *tex_coords2++ = tc; + } + } + else if (moved) + { + *tex_coords++ = *old_texcoords++; + if (bump_code) + { + *tex_coords2++ = *old_texcoords2++; } } + + if (rebuild_pos) + { + *vertices++ = vf.mVertices[i].mPosition * mat_vert; - index_offset += num_vertices; + LLVector3 normal = vf.mVertices[i].mNormal * mat_normal; + normal.normVec(); + + *normals++ = normal; + } + else if (moved) + { + *normals++ = *old_normals++; + *vertices++ = *old_verts++; + } + + if (rebuild_color) + { + *colors++ = color; + } + else if (moved) + { + *colors++ = *old_colors++; + } + } - center_sum += vf.mCenter * mat_vert; + if (!rebuild_pos && !moved) + { + vertices += num_vertices; } - - center_sum /= (F32)(fend-fstart+1); - - if (is_static) + + if (!rebuild_tcoord && !moved) { - mCenterAgent = center_sum; - mCenterLocal = mCenterAgent - mDrawablep->getPositionAgent(); + tex_coords2 += num_vertices; + tex_coords += num_vertices; } - else + else if (!bump_code) { - mCenterLocal = center_sum; - updateCenterAgent(); + tex_coords2 += num_vertices; } - - if (!grab_first_vert && mDrawablep->isState(LLDrawable::REBUILD_VOLUME)) + + if (!rebuild_color && !moved) { - mExtents[0] = min; - mExtents[1] = max; + colors += num_vertices; } - - if (!grab_first_tcoord && mDrawablep->isState(LLDrawable::REBUILD_TCOORD)) + + if (rebuild_tcoord) { - mTexExtents[0] = tmin; - mTexExtents[1] = tmax; + mTexExtents[0].setVec(0,0); + mTexExtents[1].setVec(1,1); + xform(mTexExtents[0], cos_ang, sin_ang, os, ot, ms, mt); + xform(mTexExtents[1], cos_ang, sin_ang, os, ot, ms, mt); } - + + index_offset += num_vertices; + + mLastVertexBuffer = mVertexBuffer; + mLastGeomCount = mGeomCount; + mLastGeomIndex = mGeomIndex; + mLastIndicesCount = mIndicesCount; + mLastIndicesIndex = mIndicesIndex; + return TRUE; } +#if 0 BOOL LLFace::genLighting(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend, const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL do_lighting) { @@ -1662,21 +1308,20 @@ BOOL LLFace::genShadows(const LLVolume* volume, const LLDrawable* drawablep, S32 } return TRUE; } +#endif BOOL LLFace::verify(const U32* indices_array) const { BOOL ok = TRUE; // First, check whether the face data fits within the pool's range. - if ((mGeomIndex < 0) || (mGeomIndex + mGeomCount) > (S32)getPool()->getVertexCount()) + if ((mGeomIndex < 0) || (mGeomIndex + mGeomCount) > mVertexBuffer->getNumVerts()) { ok = FALSE; llinfos << "Face not within pool range!" << llendl; } S32 indices_count = (S32)getIndicesCount(); - S32 geom_start = getGeomStart(); - S32 geom_count = mGeomCount; - + if (!indices_count) { return TRUE; @@ -1688,6 +1333,10 @@ BOOL LLFace::verify(const U32* indices_array) const llinfos << "Face has bogus indices count" << llendl; } +#if 0 + S32 geom_start = getGeomStart(); + S32 geom_count = mGeomCount; + const U32 *indicesp = indices_array ? indices_array + mIndicesIndex : getRawIndices(); for (S32 i = 0; i < indices_count; i++) @@ -1706,6 +1355,7 @@ BOOL LLFace::verify(const U32* indices_array) const ok = FALSE; } } +#endif if (!ok) { @@ -1756,7 +1406,7 @@ const LLColor4& LLFace::getRenderColor() const void LLFace::renderSetColor() const { - if (!LLDrawPool::LLOverrideFaceColor::sOverrideFaceColor) + if (!LLFacePool::LLOverrideFaceColor::sOverrideFaceColor) { const LLColor4* color = &(getRenderColor()); @@ -1773,61 +1423,21 @@ void LLFace::renderSetColor() const S32 LLFace::pushVertices(const U32* index_array) const { - U32 indices_count = mIndicesCount; - S32 ret = 0; -#if ENABLE_FACE_LINKING - LLFace* next = mNextFace; -#endif - - if (mGeomCount < gGLManager.mGLMaxVertexRange && (S32) indices_count < gGLManager.mGLMaxIndexRange) + if (mIndicesCount) { - LLFace* current = (LLFace*) this; - S32 geom_count = mGeomCount; -#if ENABLE_FACE_LINKING - while (current) + if (mGeomCount <= gGLManager.mGLMaxVertexRange && + mIndicesCount <= (U32) gGLManager.mGLMaxIndexRange) { - //chop up batch into implementation recommended sizes - while (next && - (current == next || - ((S32) (indices_count + next->mIndicesCount) < gGLManager.mGLMaxIndexRange && - geom_count + next->mGeomCount < gGLManager.mGLMaxVertexRange))) - { - indices_count += next->mIndicesCount; - geom_count += next->mGeomCount; - next = next->mNextFace; - } -#endif - if (indices_count) - { - glDrawRangeElements(mPrimType, current->mGeomIndex, current->mGeomIndex + geom_count, indices_count, - GL_UNSIGNED_INT, index_array + current->mIndicesIndex); - } - ret += (S32) indices_count; - indices_count = 0; - geom_count = 0; -#if ENABLE_FACE_LINKING - current = next; + glDrawRangeElements(GL_TRIANGLES, mGeomIndex, mGeomIndex + mGeomCount-1, mIndicesCount, + GL_UNSIGNED_INT, index_array + mIndicesIndex); } -#endif - } - else - { -#if ENABLE_FACE_LINKING - while (next) - { - indices_count += next->mIndicesCount; - next = next->mNextFace; - } -#endif - if (indices_count) + else { - glDrawElements(mPrimType, indices_count, GL_UNSIGNED_INT, index_array + mIndicesIndex); + glDrawElements(GL_TRIANGLES, mIndicesCount, GL_UNSIGNED_INT, index_array+mIndicesIndex); } - ret += (S32) indices_count; } - return ret; - + return mIndicesCount; } const LLMatrix4& LLFace::getRenderMatrix() const @@ -1854,19 +1464,25 @@ S32 LLFace::renderElements(const U32 *index_array) const return ret; } -S32 LLFace::renderIndexed(const U32 *index_array) const +S32 LLFace::renderIndexed() { - if (mSkipRender) + if(mGeomIndex < 0 || mDrawablep.isNull() || mDrawPoolp == NULL) { return 0; } + + return renderIndexed(mDrawPoolp->getVertexDataMask()); +} - if(mGeomIndex < 0 || mDrawablep.isNull()) +S32 LLFace::renderIndexed(U32 mask) +{ + if (mVertexBuffer.isNull()) { return 0; } - - renderSetColor(); + + mVertexBuffer->setBuffer(mask); + U32* index_array = (U32*) mVertexBuffer->getIndicesPointer(); return renderElements(index_array); } @@ -1879,26 +1495,13 @@ S32 LLFace::getVertices(LLStrider &vertices) { return -1; } - if (isState(BACKLIST)) - { - if (!mBackupMem) - { - printDebugInfo(); - llerrs << "No backup memory for face" << llendl; - } - vertices = (LLVector3*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_VERTICES]); - vertices.setStride( mDrawPoolp->getStride()); - return 0; - } - else + + if (mGeomIndex >= 0) // flexible objects may not have geometry { - if (mGeomIndex >= 0) // flexible objects may not have geometry - { - mDrawPoolp->getVertexStrider(vertices, mGeomIndex); - mDrawPoolp->setDirty(); - } - return mGeomIndex; + mVertexBuffer->getVertexStrider(vertices, mGeomIndex); + } + return mGeomIndex; } S32 LLFace::getColors(LLStrider &colors) @@ -1907,42 +1510,17 @@ S32 LLFace::getColors(LLStrider &colors) { return -1; } - if (isState(BACKLIST)) - { - llassert(mBackupMem); - colors = (LLColor4U*)(mBackupMem + (4 * mIndicesCount) + mDrawPoolp->mDataOffsets[LLDrawPool::DATA_COLORS]); - colors.setStride( mDrawPoolp->getStride()); - return 0; - } - else - { - llassert(mGeomIndex >= 0); - mDrawPoolp->getColorStrider(colors, mGeomIndex); - return mGeomIndex; - } -} - -S32 LLFace::getIndices(U32* &indicesp) -{ - if (isState(BACKLIST)) - { - indicesp = (U32*)mBackupMem; - return 0; - } - else - { - indicesp = mDrawPoolp->getIndices(mIndicesIndex); - llassert(mGeomIndex >= 0 && indicesp[0] != indicesp[1]); - return mGeomIndex; - } + + llassert(mGeomIndex >= 0); + mVertexBuffer->getColorStrider(colors, mGeomIndex); + return mGeomIndex; } -void LLFace::link(LLFace* facep) +S32 LLFace::getIndices(LLStrider &indicesp) { -#if ENABLE_FACE_LINKING - mNextFace = facep; - facep->mSkipRender = TRUE; -#endif + mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex); + llassert(mGeomIndex >= 0 && indicesp[0] != indicesp[1]); + return mIndicesIndex; } LLVector3 LLFace::getPositionAgent() const diff --git a/linden/indra/newview/llface.h b/linden/indra/newview/llface.h index cb3b705..b265b3a 100644 --- a/linden/indra/newview/llface.h +++ b/linden/indra/newview/llface.h @@ -38,18 +38,19 @@ #include "llquaternion.h" #include "xform.h" #include "lldarrayptr.h" +#include "llvertexbuffer.h" +#include "llviewerimage.h" #include "llpagemem.h" #include "llstat.h" #include "lldrawable.h" -#define ENABLE_FACE_LINKING 1 // Causes problems with snapshot rendering - -class LLDrawPool; +class LLFacePool; class LLVolume; class LLViewerImage; class LLTextureEntry; class LLVertexProgram; class LLViewerImage; +class LLGeometryManager; class LLFace { @@ -57,26 +58,12 @@ public: enum EMasks { - SHARED_GEOM = 0x0001, - LIGHT = 0x0002, - REBUILD = 0x0004, - GLOBAL = 0x0008, - VISIBLE = 0x0010, - BACKLIST = 0x0020, - INTERP = 0x0040, - FULLBRIGHT = 0x0080, - HUD_RENDER = 0x0100, - USE_FACE_COLOR = 0x0200, - - POINT_SPRITE = 0x10000, - BOARD_SPRITE = 0x20000, - FIXED_SPRITE = 0x40000, - DEPTH_SPRITE = 0x80000 - }; - - enum EDirty - { - DIRTY = -2 + LIGHT = 0x0001, + GLOBAL = 0x0002, + FULLBRIGHT = 0x0004, + HUD_RENDER = 0x0008, + USE_FACE_COLOR = 0x0010, + TEXTURE_ANIM = 0x0020, }; static void initClass(); @@ -93,54 +80,64 @@ public: const S32 getGeomIndex() const { return mGeomIndex; } // index into draw pool const U32 getGeomStart() const { return mGeomIndex; } // index into draw pool LLViewerImage* getTexture() const { return mTexture; } + void setTexture(LLViewerImage* tex) { mTexture = tex; } LLXformMatrix* getXform() const { return mXform; } BOOL hasGeometry() const { return mGeomCount > 0; } LLVector3 getPositionAgent() const; - void setPrimType(U32 primType) { mPrimType = primType; } - const U32 getPrimType() const { return mPrimType; } - + U32 getState() const { return mState; } void setState(U32 state) { mState |= state; } void clearState(U32 state) { mState &= ~state; } - BOOL isState(U32 state) const { return ((mState & state) != 0); } - + BOOL isState(U32 state) const { return ((mState & state) != 0) ? TRUE : FALSE; } + void setVirtualSize(F32 size) { mVSize = size; } + void setPixelArea(F32 area) { mPixelArea = area; } + F32 getVirtualSize() const { return mVSize; } + F32 getPixelArea() const { return mPixelArea; } void bindTexture(S32 stage = 0) const { LLViewerImage::bindTexture(mTexture, stage); } void enableLights() const; void renderSetColor() const; S32 renderElements(const U32 *index_array) const; - S32 renderIndexed (const U32 *index_array) const; + S32 renderIndexed (); + S32 renderIndexed (U32 mask); S32 pushVertices(const U32* index_array) const; void setWorldMatrix(const LLMatrix4& mat); const LLTextureEntry* getTextureEntry() const { return mVObjp->getTE(mTEOffset); } - LLDrawPool* getPool() const { return mDrawPoolp; } - S32 getStride() const { return mDrawPoolp->getStride(); } - const U32* getRawIndices() const { return &mDrawPoolp->mIndices[mIndicesIndex]; } + LLFacePool* getPool() const { return mDrawPoolp; } + U32 getPoolType() const { return mPoolType; } LLDrawable* getDrawable() const { return mDrawablep; } LLViewerObject* getViewerObject() const { return mVObjp; } - - void clearDirty() { mGeneration = mDrawPoolp->mGeneration; }; - - S32 backup(); - void restore(); + S32 getLOD() const { return mVObjp.notNull() ? mVObjp->getLOD() : 0; } + LLVertexBuffer* getVertexBuffer() const { return mVertexBuffer; } + void setPoolType(U32 type) { mPoolType = type; } + S32 getTEOffset() { return mTEOffset; } void setViewerObject(LLViewerObject* object); - void setPool(LLDrawPool *pool, LLViewerImage *texturep); + void setPool(LLFacePool *pool, LLViewerImage *texturep); + void setDrawable(LLDrawable *drawable); void setTEOffset(const S32 te_offset); - S32 getTEOffset() { return mTEOffset; } + void setFaceColor(const LLColor4& color); // override material color void unsetFaceColor(); // switch back to material color const LLColor4& getFaceColor() const { return mFaceColor; } const LLColor4& getRenderColor() const; - void unReserve(); // Set Removed from pool - - BOOL reserveIfNeeded(); // Reserves data if dirty. - + //for volumes + S32 getGeometryVolume(const LLVolume& volume, + S32 f, + LLStrider& vertices, + LLStrider& normals, + LLStrider& texcoords, + LLStrider& texcoords2, + LLStrider& colors, + LLStrider& indices, + const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, + U32& index_offset); + // For avatar S32 getGeometryAvatar( LLStrider &vertices, @@ -156,69 +153,51 @@ public: LLStrider &colors, LLStrider &texCoords0, LLStrider &texCoords1, - U32* &indices); + LLStrider &indices); // For volumes, etc. S32 getGeometry(LLStrider &vertices, LLStrider &normals, LLStrider &texCoords, - U32* &indices); + LLStrider &indices); S32 getGeometryColors(LLStrider &vertices, LLStrider &normals, LLStrider &texCoords, LLStrider &colors, - U32* &indices); + LLStrider &indices); - S32 getGeometryMultiTexture(LLStrider &vertices, - LLStrider &normals, - LLStrider &binormals, - LLStrider &texCoords0, - LLStrider &texCoords1, - U32* &indices); - - - S32 getVertices (LLStrider &vertices); - S32 getColors (LLStrider &colors); - S32 getIndices (U32* &indices); + S32 getVertices(LLStrider &vertices); + S32 getColors(LLStrider &colors); + S32 getIndices(LLStrider &indices); void setSize(const S32 numVertices, const S32 num_indices = 0); - BOOL getDirty() const { return (mGeneration != mDrawPoolp->mGeneration); } - - BOOL genVolumeTriangles(const LLVolume &volume, S32 f, - const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE); - BOOL genVolumeTriangles(const LLVolume &volume, S32 fstart, S32 fend, + + BOOL genVolumeBBoxes(const LLVolume &volume, S32 f, const LLMatrix4& mat, const LLMatrix3& inv_trans_mat, BOOL global_volume = FALSE); - BOOL genLighting(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL do_lighting); - - BOOL genShadows(const LLVolume* volume, const LLDrawable* drawablep, S32 fstart, S32 fend, - const LLMatrix4& mat_vert, const LLMatrix3& mat_normal, BOOL use_shadow_factor); - + void init(LLDrawable* drawablep, LLViewerObject* objp); void destroy(); void update(); void updateCenterAgent(); // Update center when xform has changed. - void renderSelectedUV(const S32 offset = 0, const S32 count = 0); + void renderSelectedUV(const S32 offset = 0, const S32 count = 0); - void renderForSelect() const; + void renderForSelect(U32 data_mask = LLVertexBuffer::MAP_VERTEX | LLVertexBuffer::MAP_TEXCOORD); void renderSelected(LLImageGL *image, const LLColor4 &color, const S32 offset = 0, const S32 count = 0); F32 getKey() const { return mDistance; } - S32 getGeneration() const { return mGeneration; } S32 getReferenceIndex() const { return mReferenceIndex; } void setReferenceIndex(const S32 index) { mReferenceIndex = index; } BOOL verify(const U32* indices_array = NULL) const; void printDebugInfo() const; - void link(LLFace* facep); + void setGeomIndex(S32 idx) { mGeomIndex = idx; } + void setIndicesIndex(S32 idx) { mIndicesIndex = idx; } protected: - S32 allocBackupMem(); // Allocate backup memory based on the draw pool information. - void setDirty(); public: LLVector3 mCenterLocal; @@ -227,30 +206,40 @@ public: LLVector2 mTexExtents[2]; F32 mDistance; F32 mAlphaFade; - LLFace* mNextFace; - BOOL mSkipRender; - + LLPointer mVertexBuffer; + LLPointer mLastVertexBuffer; + F32 mLastUpdateTime; + LLMatrix4 mTextureMatrix; + protected: - S32 mGeneration; + friend class LLGeometryManager; + friend class LLVolumeGeometryManager; + U32 mState; - LLDrawPool* mDrawPoolp; - S32 mGeomIndex; // index into draw pool + LLFacePool* mDrawPoolp; + U32 mPoolType; LLColor4 mFaceColor; // overrides material color if state |= USE_FACE_COLOR - U32 mPrimType; S32 mGeomCount; // vertex count for this face + S32 mGeomIndex; // index into draw pool U32 mIndicesCount; S32 mIndicesIndex; // index into draw pool for indices (yeah, I know!) - LLXformMatrix* mXform; - LLPointer mTexture; - U8 *mBackupMem; + //previous rebuild's geometry info + S32 mLastGeomCount; + S32 mLastGeomIndex; + U32 mLastIndicesCount; + S32 mLastIndicesIndex; + LLXformMatrix* mXform; + LLPointer mTexture; LLPointer mDrawablep; LLPointer mVObjp; S32 mTEOffset; S32 mReferenceIndex; + F32 mVSize; + F32 mPixelArea; protected: static BOOL sSafeRenderSelect; @@ -264,6 +253,43 @@ public: } }; + struct CompareTexture + { + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + return lhs->getTexture() < rhs->getTexture(); + } + }; + + struct CompareTextureAndGeomCount + { + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + return lhs->getTexture() == rhs->getTexture() ? + lhs->getGeomCount() < rhs->getGeomCount() : + lhs->getTexture() > rhs->getTexture(); + } + }; + + struct CompareTextureAndLOD + { + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + return lhs->getTexture() == rhs->getTexture() ? + lhs->getLOD() < rhs->getLOD() : + lhs->getTexture() < rhs->getTexture(); + } + }; + + struct CompareTextureAndTime + { + bool operator()(const LLFace* const& lhs, const LLFace* const& rhs) + { + return lhs->getTexture() == rhs->getTexture() ? + lhs->mLastUpdateTime < rhs->mLastUpdateTime : + lhs->getTexture() < rhs->getTexture(); + } + }; }; #endif // LL_LLFACE_H diff --git a/linden/indra/newview/llfasttimerview.cpp b/linden/indra/newview/llfasttimerview.cpp index e147e3f..5038ed9 100644 --- a/linden/indra/newview/llfasttimerview.cpp +++ b/linden/indra/newview/llfasttimerview.cpp @@ -86,31 +86,41 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_RESET_DRAWORDER, " ResetDrawOrder", &LLColor4::pink1, 0 }, { LLFastTimer::FTM_WORLD_UPDATE, " World Update", &LLColor4::blue1, 1 }, { LLFastTimer::FTM_UPDATE_MOVE, " Move Objects", &LLColor4::pink2, 0 }, - { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 }, - { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 0 }, - { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 }, + { LLFastTimer::FTM_OCTREE_BALANCE, " Octree Balance", &LLColor4::red3, 0 }, +// { LLFastTimer::FTM_TEMP1, " Blur", &LLColor4::red1, 0 }, + { LLFastTimer::FTM_CULL, " Object Cull", &LLColor4::blue2, 1 }, + { LLFastTimer::FTM_CULL_REBOUND, " Rebound", &LLColor4::blue3, 0 }, + { LLFastTimer::FTM_FRUSTUM_CULL, " Frustum Cull", &LLColor4::blue4, 0 }, + { LLFastTimer::FTM_OCCLUSION, " Object Occlude", &LLColor4::pink1, 0 }, + { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read", &LLColor4::red2, 0 }, { LLFastTimer::FTM_HUD_EFFECTS, " HUD Effects", &LLColor4::orange1, 0 }, { LLFastTimer::FTM_HUD_UPDATE, " HUD Update", &LLColor4::orange2, 0 }, - { LLFastTimer::FTM_OCCLUSION, " Object Occlude",&LLColor4::pink1, 0 }, - { LLFastTimer::FTM_OCCLUSION_READBACK, " Occlusion Read",&LLColor4::red2, 0 }, { LLFastTimer::FTM_GEO_UPDATE, " Geo Update", &LLColor4::blue3, 0 }, { LLFastTimer::FTM_UPDATE_PRIMITIVES, " Volumes", &LLColor4::blue4, 0 }, { LLFastTimer::FTM_GEN_VOLUME, " Gen Volume", &LLColor4::yellow3, 0 }, { LLFastTimer::FTM_GEN_FLEX, " Flexible", &LLColor4::yellow4, 0 }, { LLFastTimer::FTM_GEN_TRIANGLES, " Triangles", &LLColor4::yellow5, 0 }, + { LLFastTimer::FTM_UPDATE_AVATAR, " Avatar", &LLColor4::yellow1, 0 }, + { LLFastTimer::FTM_UPDATE_TREE, " Tree", &LLColor4::yellow2, 0 }, + { LLFastTimer::FTM_UPDATE_TERRAIN, " Terrain", &LLColor4::yellow6, 0 }, + { LLFastTimer::FTM_UPDATE_CLOUDS, " Clouds", &LLColor4::yellow7, 0 }, + { LLFastTimer::FTM_UPDATE_GRASS, " Grass", &LLColor4::yellow8, 0 }, + { LLFastTimer::FTM_UPDATE_WATER, " Water", &LLColor4::yellow9, 0 }, { LLFastTimer::FTM_GEO_LIGHT, " Lighting", &LLColor4::yellow1, 0 }, { LLFastTimer::FTM_GEO_SHADOW, " Shadow", &LLColor4::black, 0 }, { LLFastTimer::FTM_UPDATE_PARTICLES, " Particles", &LLColor4::blue5, 0 }, + { LLFastTimer::FTM_SIMULATE_PARTICLES, " Particle Sim", &LLColor4::blue4, 0 }, { LLFastTimer::FTM_GEO_RESERVE, " Reserve", &LLColor4::blue6, 0 }, { LLFastTimer::FTM_UPDATE_LIGHTS, " Lights", &LLColor4::yellow2, 0 }, { LLFastTimer::FTM_UPDATE_SKY, " Sky Update", &LLColor4::cyan1, 0 }, - { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 1 }, + { LLFastTimer::FTM_OBJECTLIST_UPDATE, " Object Update", &LLColor4::purple1, 0 }, { LLFastTimer::FTM_AVATAR_UPDATE, " Avatars", &LLColor4::purple2, 0 }, { LLFastTimer::FTM_JOINT_UPDATE, " Joints", &LLColor4::purple3, 0 }, { LLFastTimer::FTM_ATTACHMENT_UPDATE, " Attachments", &LLColor4::purple4, 0 }, { LLFastTimer::FTM_UPDATE_ANIMATION, " Animation", &LLColor4::purple5, 0 }, { LLFastTimer::FTM_FLEXIBLE_UPDATE, " Flex Update", &LLColor4::pink2, 0 }, { LLFastTimer::FTM_LOD_UPDATE, " LOD Update", &LLColor4::magenta1, 0 }, +// { LLFastTimer::FTM_TEMP5, " Check", &LLColor4::red1, 1}, { LLFastTimer::FTM_REGION_UPDATE, " Region Update", &LLColor4::cyan2, 0 }, { LLFastTimer::FTM_NETWORK, " Network", &LLColor4::orange1, 1 }, { LLFastTimer::FTM_IDLE_NETWORK, " Decode Msgs", &LLColor4::orange2, 0 }, @@ -125,17 +135,36 @@ static struct ft_display_info ft_display_table[] = { LLFastTimer::FTM_IMAGE_UPDATE, " Image Update", &LLColor4::yellow4, 1 }, { LLFastTimer::FTM_IMAGE_CREATE, " Image CreateGL",&LLColor4::yellow5, 0 }, { LLFastTimer::FTM_IMAGE_DECODE, " Image Decode", &LLColor4::yellow6, 0 }, + { LLFastTimer::FTM_IMAGE_MARK_DIRTY, " Dirty Textures",&LLColor4::red1, 0 }, { LLFastTimer::FTM_VFILE_WAIT, " VFile Wait", &LLColor4::cyan6, 0 }, // { LLFastTimer::FTM_IDLE_CB, " Callbacks", &LLColor4::pink1, 0 }, - { LLFastTimer::FTM_RENDER, " Render", &green0, 0 }, + { LLFastTimer::FTM_RENDER, " Render", &green0, 1 }, { LLFastTimer::FTM_REBUILD, " Rebuild", &LLColor4::green1, 1 }, { LLFastTimer::FTM_STATESORT, " State Sort", &LLColor4::orange1, 1 }, + { LLFastTimer::FTM_STATESORT_DRAWABLE, " Drawable", &LLColor4::orange2, 0 }, + { LLFastTimer::FTM_STATESORT_POSTSORT, " Post Sort", &LLColor4::orange3, 0 }, + { LLFastTimer::FTM_REBUILD_OCCLUSION_VB," Occlusion", &LLColor4::cyan5, 0 }, + { LLFastTimer::FTM_REBUILD_VBO, " VBO Rebuild", &LLColor4::red4, 0 }, + { LLFastTimer::FTM_REBUILD_VOLUME_VB, " Volume", &LLColor4::blue1, 0 }, + { LLFastTimer::FTM_REBUILD_NONE_VB, " Unknown", &LLColor4::cyan5, 0 }, + { LLFastTimer::FTM_REBUILD_BRIDGE_VB, " Bridge", &LLColor4::blue2, 0 }, + { LLFastTimer::FTM_REBUILD_HUD_VB, " HUD", &LLColor4::blue3, 0 }, + { LLFastTimer::FTM_REBUILD_TERRAIN_VB, " Terrain", &LLColor4::blue4, 0 }, + { LLFastTimer::FTM_REBUILD_WATER_VB, " Water", &LLColor4::blue5, 0 }, + { LLFastTimer::FTM_REBUILD_TREE_VB, " Tree", &LLColor4::cyan1, 0 }, + { LLFastTimer::FTM_REBUILD_PARTICLE_VB, " Particle", &LLColor4::cyan2, 0 }, + { LLFastTimer::FTM_REBUILD_CLOUD_VB, " Cloud", &LLColor4::cyan3, 0 }, + { LLFastTimer::FTM_REBUILD_GRASS_VB, " Grass", &LLColor4::cyan4, 0 }, { LLFastTimer::FTM_RENDER_GEOMETRY, " Geometry", &LLColor4::green2, 1 }, - { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 0 }, - { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 0 }, + { LLFastTimer::FTM_POOLS, " Pools", &LLColor4::green3, 1 }, + { LLFastTimer::FTM_POOLRENDER, " RenderPool", &LLColor4::green4, 1 }, { LLFastTimer::FTM_RENDER_TERRAIN, " Terrain", &LLColor4::green6, 0 }, { LLFastTimer::FTM_RENDER_CHARACTERS, " Avatars", &LLColor4::yellow1, 0 }, { LLFastTimer::FTM_RENDER_SIMPLE, " Simple", &LLColor4::yellow2, 0 }, + { LLFastTimer::FTM_RENDER_FULLBRIGHT, " Fullbright", &LLColor4::yellow5, 0 }, + { LLFastTimer::FTM_RENDER_GLOW, " Glow", &LLColor4::orange1, 0 }, + { LLFastTimer::FTM_RENDER_GRASS, " Grass", &LLColor4::yellow6, 0 }, + { LLFastTimer::FTM_RENDER_INVISIBLE, " Invisible", &LLColor4::red2, 0 }, { LLFastTimer::FTM_RENDER_SHINY, " Shiny", &LLColor4::yellow3, 0 }, { LLFastTimer::FTM_RENDER_BUMP, " Bump", &LLColor4::yellow4, 0 }, { LLFastTimer::FTM_RENDER_TREES, " Trees", &LLColor4::yellow8, 0 }, @@ -149,15 +178,16 @@ static struct ft_display_info ft_display_table[] = // { LLFastTimer::FTM_RENDER_FONTS, " Fonts", &LLColor4::pink1, 0 }, // { LLFastTimer::FTM_UPDATE_TEXTURES, " Textures", &LLColor4::pink2, 0 }, { LLFastTimer::FTM_SWAP, " Swap", &LLColor4::pink1, 0 }, + { LLFastTimer::FTM_CLIENT_COPY, " Client Copy", &LLColor4::red1, 1}, -// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 }, -// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 }, -// { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 }, -// { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 }, -// { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 }, -// { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 }, -// { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 }, -// { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 }, +// { LLFastTimer::FTM_TEMP1, " Temp1", &LLColor4::red1, 0 }, +// { LLFastTimer::FTM_TEMP2, " Temp2", &LLColor4::magenta1, 0 }, +// { LLFastTimer::FTM_TEMP3, " Temp3", &LLColor4::red2, 0 }, +// { LLFastTimer::FTM_TEMP4, " Temp4", &LLColor4::magenta2, 0 }, +// { LLFastTimer::FTM_TEMP5, " Temp5", &LLColor4::red3, 0 }, +// { LLFastTimer::FTM_TEMP6, " Temp6", &LLColor4::magenta3, 0 }, +// { LLFastTimer::FTM_TEMP7, " Temp7", &LLColor4::red4, 0 }, +// { LLFastTimer::FTM_TEMP8, " Temp8", &LLColor4::magenta4, 0 }, { LLFastTimer::FTM_OTHER, " Other", &red0 } }; @@ -167,7 +197,7 @@ static const int FTV_DISPLAY_NUM = (sizeof(ft_display_table)/sizeof(ft_display_ S32 ft_display_idx[FTV_DISPLAY_NUM]; // line of table entry for display purposes (for collapse) LLFastTimerView::LLFastTimerView(const std::string& name, const LLRect& rect) -: LLView(name, rect, TRUE) + : LLFloater(name, rect, "Fast Timers") { setVisible(FALSE); mDisplayMode = 0; @@ -910,7 +940,10 @@ void LLFastTimerView::draw() F32 ms = (F32)((F64)max_ticks * iclock_freq); //display y-axis range - LLString tdesc = llformat("%4.2f ms", ms); + LLString tdesc = mDisplayCalls ? + llformat("%d calls", max_ticks) : + llformat("%4.2f ms", ms); + x = graph_rect.mRight - LLFontGL::sMonospace->getWidth(tdesc)-5; y = graph_rect.mTop - ((S32)LLFontGL::sMonospace->getLineHeight()); @@ -976,6 +1009,13 @@ void LLFastTimerView::draw() for (U32 j = 0; j < LLFastTimer::FTM_HISTORY_NUM; j++) { U64 ticks = ticks_sum[j+1][idx]; + if (mDisplayCalls) + { + S32 tidx = ft_display_table[idx].timer; + S32 hidx = (LLFastTimer::sLastFrameIndex + j) % LLFastTimer::FTM_HISTORY_NUM; + ticks = (S32)LLFastTimer::sCallHistory[hidx][tidx]; + } + if (alpha == 1.f) { //normalize to highlighted timer cur_max = llmax(cur_max, ticks); diff --git a/linden/indra/newview/llfasttimerview.h b/linden/indra/newview/llfasttimerview.h index b20c8eb..11a8887 100644 --- a/linden/indra/newview/llfasttimerview.h +++ b/linden/indra/newview/llfasttimerview.h @@ -28,10 +28,10 @@ #ifndef LL_LLFASTTIMERVIEW_H #define LL_LLFASTTIMERVIEW_H -#include "llview.h" +#include "llfloater.h" #include "llframetimer.h" -class LLFastTimerView : public LLView +class LLFastTimerView : public LLFloater { public: LLFastTimerView(const std::string& name, const LLRect& rect); diff --git a/linden/indra/newview/llfeaturemanager.cpp b/linden/indra/newview/llfeaturemanager.cpp index 061b343..c0fd96b 100644 --- a/linden/indra/newview/llfeaturemanager.cpp +++ b/linden/indra/newview/llfeaturemanager.cpp @@ -156,7 +156,7 @@ BOOL LLFeatureList::maskList(LLFeatureList &mask) } #if 0 && !LL_RELEASE_FOR_DOWNLOAD - llinfos << "After appling mask " << mask.mName << llendl; + llinfos << "After applying mask " << mask.mName << llendl; dump(); #endif return TRUE; @@ -208,12 +208,12 @@ BOOL LLFeatureManager::loadFeatureTables() data_path += FEATURE_TABLE_FILENAME; - char name[MAX_STRING+1]; + char name[MAX_STRING+1]; /*Flawfinder: ignore*/ llifstream file; U32 version; - file.open(data_path.c_str()); + file.open(data_path.c_str()); /*Flawfinder: ignore*/ if (!file) { @@ -235,12 +235,12 @@ BOOL LLFeatureManager::loadFeatureTables() LLFeatureList *flp = NULL; while (!file.eof()) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ name[0] = 0; file >> name; - if (strlen(name) >= 2 && + if (strlen(name) >= 2 && /*Flawfinder: ignore*/ name[0] == '/' && name[1] == '/') { @@ -249,7 +249,7 @@ BOOL LLFeatureManager::loadFeatureTables() continue; } - if (strlen(name) == 0) + if (strlen(name) == 0) /*Flawfinder: ignore*/ { // This is a blank line file.getline(buffer, MAX_STRING); @@ -295,7 +295,6 @@ BOOL LLFeatureManager::loadFeatureTables() } } file.close(); - //flp->dump(); return TRUE; } @@ -314,7 +313,7 @@ void LLFeatureManager::loadGPUClass() llifstream file; - file.open(data_path.c_str()); + file.open(data_path.c_str()); /*Flawfinder: ignore*/ if (!file) { @@ -330,12 +329,12 @@ void LLFeatureManager::loadGPUClass() while (!file.eof()) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ buffer[0] = 0; file.getline(buffer, MAX_STRING); - if (strlen(buffer) >= 2 && + if (strlen(buffer) >= 2 && /*Flawfinder: ignore*/ buffer[0] == '/' && buffer[1] == '/') { @@ -343,7 +342,7 @@ void LLFeatureManager::loadGPUClass() continue; } - if (strlen(buffer) == 0) + if (strlen(buffer) == 0) /*Flawfinder: ignore*/ { // This is a blank line continue; @@ -360,7 +359,7 @@ void LLFeatureManager::loadGPUClass() continue; } - for (U32 i = 0; i < strlen(expr); i++) + for (U32 i = 0; i < strlen(expr); i++) /*Flawfinder: ignore*/ { expr[i] = tolower(expr[i]); } @@ -380,10 +379,11 @@ void LLFeatureManager::loadGPUClass() llinfos << "GPU is " << label << llendl; mGPUString = label; mGPUClass = (S32) strtol(cls, NULL, 10); + file.close(); + return; } } file.close(); - //flp->dump(); llwarns << "Couldn't match GPU to a class: " << gGLManager.getRawGLString() << llendl; } @@ -401,11 +401,7 @@ void LLFeatureManager::initCPUFeatureMasks() { maskFeatures("RAM256MB"); } - else if (gSysMemory.getPhysicalMemory() <= 512*1024*1024) - { - //maskFeatures("RAM512MB"); - } - + if (gSysCPU.getMhz() < 1100) { maskFeatures("CPUSlow"); @@ -468,7 +464,11 @@ void LLFeatureManager::initGraphicsFeatureMasks() } if (gGLManager.mIsIntel) { - maskFeatures("Brookdale"); + maskFeatures("Intel"); + } + if (gGLManager.mGLVersion < 1.5f) + { + maskFeatures("OpenGLPre15"); } if (gGLManager.mIsMobilityRadeon9000) @@ -483,303 +483,6 @@ void LLFeatureManager::initGraphicsFeatureMasks() extern LLOSInfo gSysOS; - -BOOL bad_hardware_dialog(const LLString &info_str, const LLString &url) -{ - if (!gSavedSettings.getWarning("AboutBadPCI")) - { - return FALSE; - } - - // XUI:translate - std::string msg = llformat( - "[SECOND_LIFE] has detected that there may be a problem with.\n" - "hardware or drivers on your computer. Often resolving these\n" - "issues can result in enhanced stability and performance.\n" - " \n" - "%s\n" - " \n" - "Would you like to view a web page with more detailed\n" - "information on this problem?\n", info_str.c_str()); - - // Warn them that runnin without DirectX 9 will - // not allow us to tell them about driver issues - S32 button = OSMessageBox(msg.c_str(), - "Warning", - OSMB_YESNO); - if (OSBTN_YES== button) - { - llinfos << "User quitting after detecting bad drivers" << llendl; - spawn_web_browser(url.c_str()); - return TRUE; - } - else - { - // Don't warn about bad PCI stuff again, they've clicked past it. - gSavedSettings.setWarning("AboutBadPCI", FALSE); - } - return FALSE; -} - -BOOL LLFeatureManager::initPCIFeatureMasks() -{ -#if LL_WINDOWS - BOOL exit_after_bad = FALSE; - - BOOL is_2000 = FALSE; - BOOL is_xp = FALSE; - - if (gSysOS.mMajorVer != 5) - { - // Unknown windows version number, exit!" - llwarns << "Unknown Windows major version " << gSysOS.mMajorVer << ", aborting detection!" << llendl; - return FALSE; - } - if (gSysOS.mMinorVer == 0) - { - is_2000 = TRUE; - } - else if (gSysOS.mMinorVer == 1) - { - is_xp = TRUE; - } - else - { - llwarns << "Unknown Windows minor version " << gSysOS.mMinorVer << ", aborting detection!" << llendl; - return FALSE; - } - - // This only works on Win32, as it relies on DX9 hardware detection - // The PCI masks are actually the inverse of the normal masks - // We actually look through the masks,and see if any hardware matches it. - // This is because the masks encode logic about - - // Check for the broken AMD AGP controllers (751, 761, 762) - - // Horrible cruddy fixed lookup table. - // Figure out what OS we're on, the version numbers are different. Sigh... - - LLDXDriverFile *dfilep = NULL; - LLDXDevice *devp = NULL; - - // AMD(1022) AGP controllers - // 7007 AMD-751 AGP Controller - // 700F AMD-761 AGP Controller - // 700D AMD-762 AGP Controller - devp = gDXHardware.findDevice("VEN_1022", "DEV_7007|DEV_700F|DEV_700D"); - if (devp) - { - // We're just pretty much screwed here, there are big problems with this hardware - // We've got trouble with the most recent nVidia drivers. Check for this and warn. - - // Note: Need to detect that we're running with older nVidia hardware, probably - exit_after_bad |= bad_hardware_dialog("AMD AGP Controller", - AMD_AGP_URL); - } - - // VIA(1106) AGP Controllers - // These need upgrading on both Win2K and WinXP - // - // 8305 VT8363/8365 CPU to AGP - Apollo KT133/KM133 - // 8598 VT82C598MVP/694X CPU to AGP - Apollo MVP3/Pro133A - // 8605 VT8605 CPU to AGP - Apollo PM133 - // B091 VT8633 CPU to AGP - Apollo Pro 266 - // B099 VT8366/A/T CPU to AGP - Apollo KT266/A/333 - // B168 VT8235 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X333 chipset - // B188 VT8237 CPU to AGP (AGP 2.0/3.0) - K8T800 - // B198 VT8237 CPU to AGP (AGP 2.0/3.0) - ProSavageDDR P4X600 chipset - - devp = gDXHardware.findDevice("VEN_1106", - "DEV_8305|DEV_8598|DEV_8605|DEV_B091|" - "DEV_B099|DEV_B168|DEV_B188|DEV_B198"); - if (devp) - { - BOOL out_of_date = FALSE; - // Wanted driver: VIAAGP1.SYS - // Version Format: M.mm.0000.vvvv - // M.mm - Major/minor OS version (5.0 for Win2000, 5.1 for WinXP) - // vvvv - driver version number - // - // Notes: - // 3442 is most recent as of 2/25/04, probably want at least 3430 (seems to be a common version) - - // These are DELIBERATE assignments inside if statements, blech. - if (dfilep = devp->findDriver("pci.sys")) - { - // Old driver: pci.sys - // Version: 5.01.2600.xxxx - // - // Notes: - // Default WinXP driver for B168, B198? - - // Old driver: pci.sys - // Version: 5.01.2195.xxxx - // - // Notes: - // Default Win2K driver for 8305? - - llwarns << "Detected pci.sys" << llendl; - write_debug("Old driver (pci.sys) for VIA detected!"); - out_of_date = TRUE; - } - else if (dfilep = devp->findDriver("VIAAGP.SYS")) - { - // Old driver: VIAAGP.SYS - // Version: 5.01.2600.xxxx - // - // Notes: - // Default WinXP driver for B09x? - - llwarns << "Detected VIAAGP.SYS" << llendl; - write_debug("Old driver (VIAAGP.SYS) for VIA detected!"); - out_of_date = TRUE; - } - else if (dfilep = devp->findDriver("VIAAGP1.SYS")) - { - if (dfilep->mVersion.getField(3) < 3430) - { - // They're using a pretty old version of the VIA AGP drivers - // Maybe they want to upgrade? - llwarns << "Detected VIAAGP1.SYS" << llendl; - write_debug("Old driver (VIAAGP1.SYS) for VIA detected!"); - out_of_date = TRUE; - } - } - if (out_of_date) - { - exit_after_bad |= bad_hardware_dialog("Out of date VIA AGP chipset driver", - VIA_URL); - } - } - - // Intel(8086) AGP controllers (Win2K) - // These particular controllers only may need drivers on Win2K - // - // 1A31 82845[MP|MZ] Processor to AGP Controller - // 2532 82850/860 Processor to AGP Controller - if (is_2000) - { - devp = gDXHardware.findDevice("VEN_8086", - "DEV_1A31"); - if (devp) - { - if (dfilep = devp->findDriver("pci.sys")) - { - // Old driver: pci.sys - // Version 5.01.21[9|6]5.xxxx - // - // Notes: - // Default driver for Win2K? Not sure what the "correct" driver is - - // maybe some variant of AGP440.SYS? - llwarns << "Detected pci.sys" << llendl; - write_debug("Old driver (pci.sys) for Intel 82845/850 on Win2K detected!"); - exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver", - INTEL_CHIPSET_URL); - } - } - } - - /* Removed 4/3/2006 by JC - After talking with Doug, we don't know what the proper driver - and/or version number should be for Intel 865. Regardless, this - code would _always_ complain if you had that chipset. - - // Intel(8086) AGP controllers (All) - // These particular controllers may need drivers on both Win2K and WinXP - // - // 2561 82845G/GL/GE/PE/GV Processor to AGP Controller - // 2571 82865G/PE/P/GV/28248P Processor to AGP Controller - devp = gDXHardware.findDevice("VEN_8086", - "DEV_2571"); - if (devp) - { - // Wanted driver: AGP440.SYS(?) - // - // Notes: - // Not sure, need to verify with an actual 82865/75 (Dell 8300?) - - // Old driver: pci.sys - // Version 5.01.21[9|6]5.xxxx - // - // Notes: - // Default driver for Win2K? Not sure what the "correct" driver is - - // maybe some variant of AGP440.SYS? - exit_after_bad |= bad_hardware_dialog("Out of date Intel chipset driver", - INTEL_CHIPSET_URL); - } - */ - - - // SiS(1039) AGP controllers (All) - // These particular controllers may need drivers on both Win2K and WinXP - // - // 0001 SiS 530 - // 0002 SiS SG86C202(???) - // 0003 SiS 648FX - devp = gDXHardware.findDevice("VEN_1039", - "DEV_0001|DEV_0002|DEV_0003"); - if (devp) - { - BOOL out_of_date = FALSE; - // Wanted driver: SISAGPX.SYS - // - // Notes: - // Not sure, need to verify with an actual 82865/75 (Dell 8300?) - - // Old driver: pci.sys - // Version 5.01.21[9|6]5.xxxx - // - // Notes: - // Default driver for Win2K? Not sure what the "correct" driver is - - // maybe some variant of AGP440.SYS? - if (dfilep = devp->findDriver("pci.sys")) - { - // Old driver: pci.sys - // Version 5.01.21[9|6]5.xxxx - // - llwarns << "Detected pci.sys" << llendl; - write_debug("Old driver (pci.sys) for SiS detected!"); - out_of_date = TRUE; - } - - if (dfilep = devp->findDriver("sisagp.sys")) - { - // Old driver: pci.sys - // Version 5.01.21[9|6]5.xxxx - // - llwarns << "Detected sisagp.sys" << llendl; - write_debug("Old driver (sisagp.sys) for SiS detected!"); - out_of_date = TRUE; - } - - if (dfilep = devp->findDriver("sisagpx.sys")) - { - // Old driver: pci.sys - // Version 7.02.0000.xxxx - // - // Notes: - // Default driver for Win2K? Not sure what the "correct" driver is - - // maybe some variant of AGP440.SYS? - if (dfilep->mVersion.getField(3) < 1160) - { - out_of_date = TRUE; - llwarns << "Detected sisagpx.sys" << llendl; - write_debug("Old driver (sisagpx.sys) for SiS detected!"); - } - } - if (out_of_date) - { - exit_after_bad |= bad_hardware_dialog("Out of date SiS chipset driver", - SIS_CHIPSET_URL); - } - } - - return exit_after_bad; -#else - return TRUE; -#endif -} - void LLFeatureManager::applyRecommendedFeatures() { // see featuretable.txt @@ -789,14 +492,14 @@ void LLFeatureManager::applyRecommendedFeatures() dump(); #endif - // Enabling AGP - if (getRecommendedLevel("RenderAGP")) + // Enabling VBO + if (getRecommendedLevel("RenderVBO")) { - gSavedSettings.setBOOL("RenderUseAGP", TRUE); + gSavedSettings.setBOOL("RenderVBOEnable", TRUE); } else { - gSavedSettings.setBOOL("RenderUseAGP", FALSE); + gSavedSettings.setBOOL("RenderVBOEnable", FALSE); } // Anisotropic rendering diff --git a/linden/indra/newview/llfeaturemanager.h b/linden/indra/newview/llfeaturemanager.h index a24f06f..a3800da 100644 --- a/linden/indra/newview/llfeaturemanager.h +++ b/linden/indra/newview/llfeaturemanager.h @@ -100,8 +100,7 @@ public: void initCPUFeatureMasks(); void initGraphicsFeatureMasks(); - BOOL initPCIFeatureMasks(); - + void applyRecommendedFeatures(); protected: diff --git a/linden/indra/newview/llfilepicker.cpp b/linden/indra/newview/llfilepicker.cpp index 6b56df6..d3938e0 100644 --- a/linden/indra/newview/llfilepicker.cpp +++ b/linden/indra/newview/llfilepicker.cpp @@ -36,6 +36,10 @@ #include "lldir.h" #include "llframetimer.h" +#if LL_SDL +#include "llwindowsdl.h" // for some X/GTK utils to help with filepickers +#endif // LL_SDL + // // Globals // @@ -164,7 +168,7 @@ BOOL LLFilePicker::getOpenFile(ELoadFilter filter) if (success) { LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW)); - memcpy(mFiles, tstr.c_str(), tstr.size()+1); + memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/ mCurrentFile = mFiles; } send_agent_resume(); @@ -204,12 +208,12 @@ BOOL LLFilePicker::getMultipleOpenFiles(ELoadFilter filter) // The getopenfilename api doesn't tell us if we got more than // one file, so we have to test manually by checking string // lengths. - if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) + if( wcslen(mOFN.lpstrFile) > mOFN.nFileOffset ) /*Flawfinder: ignore*/ { mMultiFile = FALSE; mCurrentFile = mFiles; LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW)); - memcpy(mFiles, tstr.c_str(), tstr.size()+1); + memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/ } else { @@ -252,7 +256,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) if (filename) { llutf16string tstring = utf8str_to_utf16str(filename); - wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } + wcsncpy(mFilesW, tstring.c_str(), FILENAME_BUFFER_SIZE); } /*Flawfinder: ignore*/ else { mFilesW[0] = '\0'; @@ -272,7 +276,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_WAV: if (!filename) { - wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.wav", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"wav"; L"WAV Sounds (*.wav)\0*.wav\0" \ @@ -281,7 +285,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_TGA: if (!filename) { - wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.tga", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"tga"; mOFN.lpstrFilter = @@ -291,7 +295,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_BMP: if (!filename) { - wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.bmp", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"bmp"; mOFN.lpstrFilter = @@ -301,7 +305,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_AVI: if (!filename) { - wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.avi", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"avi"; mOFN.lpstrFilter = @@ -311,7 +315,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_ANIM: if (!filename) { - wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.xaf", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"xaf"; mOFN.lpstrFilter = @@ -322,7 +326,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_GEOMETRY: if (!filename) { - wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.slg", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"slg"; mOFN.lpstrFilter = @@ -333,7 +337,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_XML: if (!filename) { - wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.xml", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"xml"; @@ -344,7 +348,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_COLLADA: if (!filename) { - wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.collada", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"collada"; mOFN.lpstrFilter = @@ -354,12 +358,22 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) case FFSAVE_RAW: if (!filename) { - wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); + wcsncpy( mFilesW,L"untitled.raw", FILENAME_BUFFER_SIZE); /*Flawfinder: ignore*/ } mOFN.lpstrDefExt = L"raw"; mOFN.lpstrFilter = RAW_FILTER \ L"\0"; break; + case FFSAVE_J2C: + if (!filename) + { + wcsncpy( mFilesW,L"untitled.j2c", FILENAME_BUFFER_SIZE); + } + mOFN.lpstrDefExt = L"j2c"; + mOFN.lpstrFilter = + L"Compressed Images (*.j2c)\0*.j2c\0" \ + L"\0"; + break; default: return FALSE; } @@ -376,7 +390,7 @@ BOOL LLFilePicker::getSaveFile(ESaveFilter filter, const char* filename) if (success) { LLString tstr = utf16str_to_utf8str(llutf16string(mFilesW)); - memcpy(mFiles, tstr.c_str(), tstr.size()+1); + memcpy(mFiles, tstr.c_str(), tstr.size()+1); /*Flawfinder: ignore*/ mCurrentFile = mFiles; } gKeyboard->resetKeys(); @@ -402,7 +416,7 @@ const char* LLFilePicker::getNextFile() { if(mMultiFile) { - mCurrentFile += strlen(mCurrentFile) + 1; + mCurrentFile += strlen(mCurrentFile) + 1; /*Flawfinder: ignore*/ if( '\0' != mCurrentFile[0] ) { buildFilename(); @@ -435,11 +449,11 @@ void LLFilePicker::reset() void LLFilePicker::buildFilename( void ) { - strncpy( mFilename, mFiles, LL_MAX_PATH ); - S32 len = strlen( mFilename ); + strncpy( mFilename, mFiles, LL_MAX_PATH ); /*Flawfinder: ignore*/ + S32 len = strlen( mFilename ); /*Flawfinder: ignore*/ - strcat(mFilename,gDirUtilp->getDirDelimiter().c_str()); - len += strlen(gDirUtilp->getDirDelimiter().c_str()); + strncat(mFilename,gDirUtilp->getDirDelimiter().c_str(), sizeof(mFilename)-len+1); /*Flawfinder: ignore*/ + len += strlen(gDirUtilp->getDirDelimiter().c_str()); /*Flawfinder: ignore*/ // mFilename[len++] = '\\'; LLString::copy( mFilename + len, mCurrentFile, LL_MAX_PATH - len ); @@ -601,7 +615,7 @@ OSStatus LLFilePicker::doNavChooseDialog(ELoadFilter filter) AEKeyword theAEKeyword; DescType typeCode; Size actualSize = 0; - char path[MAX_PATH]; + char path[MAX_PATH]; /*Flawfinder: ignore*/ memset(&fsRef, 0, sizeof(fsRef)); error = AEGetNthPtr(&navReply.selection, index, typeFSRef, &theAEKeyword, &typeCode, &fsRef, sizeof(fsRef), &actualSize); @@ -675,6 +689,12 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename) extension = CFSTR(".raw"); break; + case FFSAVE_J2C: + type = '\?\?\?\?'; + creator = 'prvw'; + extension = CFSTR(".j2c"); + break; + case FFSAVE_ALL: default: type = '\?\?\?\?'; @@ -750,8 +770,8 @@ OSStatus LLFilePicker::doNavSaveDialog(ESaveFilter filter, const char* filename) if (error == noErr) { - char path[PATH_MAX]; - char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; + char path[PATH_MAX]; /*Flawfinder: ignore*/ + char newFileName[SINGLE_FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ error = FSRefMakePath(&fsRef, (UInt8*)path, PATH_MAX); if (error == noErr) @@ -836,7 +856,7 @@ void LLFilePicker::getFilePath(SInt32 index) { mFiles[0] = 0; if (mFileVector.size()) - strcpy(mFiles, mFileVector[index].c_str()); + strncpy(mFiles, mFileVector[index].c_str(), sizeof(mFiles)); /*Flawfinder: ignore*/ } void LLFilePicker::getFileName(SInt32 index) @@ -846,7 +866,7 @@ void LLFilePicker::getFileName(SInt32 index) { char *start = strrchr(mFileVector[index].c_str(), '/'); if (start && ((start + 1 - mFileVector[index].c_str()) < (mFileVector[index].size()))) - strcpy(mFilename, start + 1); + strncpy(mFilename, start + 1, sizeof(mFilename)); /*Flawfinder: ignore*/ } } @@ -973,8 +993,7 @@ static void store_filenames(GtkWidget *widget, gpointer user_data) { GtkWindow* LLFilePicker::buildFilePicker(void) { - gtk_disable_setlocale(); - if (gtk_init_check(NULL, NULL) && + if (ll_try_gtk_init() && ! gViewerWindow->getWindow()->getFullscreen()) { GtkWidget *win = NULL; @@ -986,18 +1005,17 @@ GtkWindow* LLFilePicker::buildFilePicker(void) // Make GTK tell the window manager to associate this // dialog with our non-GTK raw X11 window, which should try // to keep it on top etc. - Window *XWindowID_ptr = (Window*) gViewerWindow-> - getWindow()->getPlatformWindow(); - if (XWindowID_ptr && None != *XWindowID_ptr) + Window XWindowID = get_SDL_XWindowID(); + if (None != XWindowID) { gtk_widget_realize(GTK_WIDGET(win)); // so we can get its gdkwin - GdkWindow *gdkwin = gdk_window_foreign_new(*XWindowID_ptr); + GdkWindow *gdkwin = gdk_window_foreign_new(XWindowID); gdk_window_set_transient_for(GTK_WIDGET(win)->window, gdkwin); } else { - llwarns << "Hmm, couldn't get xwid from LLWindow." << llendl; + llwarns << "Hmm, couldn't get xwid to use for transient." << llendl; } # endif //LL_X11 @@ -1080,6 +1098,10 @@ BOOL LLFilePicker::getSaveFile( ESaveFilter filter, const char* filename ) caption += "RAW File (*.raw)"; suggest_ext += ".raw"; break; + case FFSAVE_J2C: + caption += "Compressed Images (*.j2c)"; + suggest_ext += ".j2c"; + break; default:; break; } diff --git a/linden/indra/newview/llfilepicker.h b/linden/indra/newview/llfilepicker.h index 88530f6..c284a42 100644 --- a/linden/indra/newview/llfilepicker.h +++ b/linden/indra/newview/llfilepicker.h @@ -106,6 +106,7 @@ public: FFSAVE_XML = 9, FFSAVE_COLLADA = 10, FFSAVE_RAW = 11, + FFSAVE_J2C = 12, }; // open the dialog. This is a modal operation @@ -169,8 +170,8 @@ private: U32 mNextFileIndex; #endif - char mFiles[FILENAME_BUFFER_SIZE]; - char mFilename[LL_MAX_PATH]; + char mFiles[FILENAME_BUFFER_SIZE]; /*Flawfinder: ignore*/ + char mFilename[LL_MAX_PATH]; /*Flawfinder: ignore*/ char* mCurrentFile; BOOL mLocked; BOOL mMultiFile; diff --git a/linden/indra/newview/llflexibleobject.cpp b/linden/indra/newview/llflexibleobject.cpp index 7e37c4c..4ce1614 100644 --- a/linden/indra/newview/llflexibleobject.cpp +++ b/linden/indra/newview/llflexibleobject.cpp @@ -44,11 +44,6 @@ #include "llviewerregion.h" #include "llworld.h" -/*static*/ LLVolumeImplFlexible::lodset_t LLVolumeImplFlexible::sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ]; -/*static*/ U64 LLVolumeImplFlexible::sCurrentUpdateFrame = 0; -/*static*/ U32 LLVolumeImplFlexible::sDebugInserted = 0; -/*static*/ U32 LLVolumeImplFlexible::sDebugVisible = 0; - /*static*/ F32 LLVolumeImplFlexible::sUpdateFactor = 1.0f; // LLFlexibleObjectData::pack/unpack now in llprimitive.cpp @@ -59,14 +54,13 @@ LLVolumeImplFlexible::LLVolumeImplFlexible(LLViewerObject* vo, LLFlexibleObjectData* attributes) : mVO(vo), mAttributes(attributes) { + static U32 seed = 0; + mID = seed++; mInitialized = FALSE; mUpdated = FALSE; - mJustShifted = FALSE; mInitializedRes = -1; mSimulateRes = 0; mFrameNum = 0; - mLastUpdate = 0; - }//----------------------------------------------- LLVector3 LLVolumeImplFlexible::getFramePosition() const @@ -94,7 +88,6 @@ void LLVolumeImplFlexible::onShift(const LLVector3 &shift_vector) { mSection[section].mPosition += shift_vector; } - mVO->getVolume()->mBounds[0] += shift_vector; } //----------------------------------------------------------------------------------------------- @@ -107,7 +100,7 @@ void LLVolumeImplFlexible::setParentPositionAndRotationDirectly( LLVector3 p, LL void LLVolumeImplFlexible::remapSections(LLFlexibleObjectSection *source, S32 source_sections, LLFlexibleObjectSection *dest, S32 dest_sections) -{ +{ S32 num_output_sections = 1<mDrawable->getScale(); F32 source_section_length = scale.mV[VZ] / (F32)(1<mDrawable.notNull()) { gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); gPipeline.markMoved(mVO->mDrawable); - } + }*/ } //--------------------------------------------------------------------------------- @@ -257,6 +250,13 @@ void LLVolumeImplFlexible::onSetVolume(const LLVolumeParams &volume_params, cons //--------------------------------------------------------------------------------- BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { + if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) + { + return TRUE; + } + + LLFastTimer ftm(LLFastTimer::FTM_FLEXIBLE_UPDATE); + if (mVO->mDrawable.isNull()) { // Don't do anything until we have a drawable @@ -267,46 +267,17 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 mVO->mDrawable->mQuietCount = 0; if (!mVO->mDrawable->isRoot()) { - mVO->mDrawable->getParent()->mQuietCount = 0; + LLViewerObject* parent = (LLViewerObject*) mVO->getParent(); + parent->mDrawable->mQuietCount = 0; } - - if (((LLVOVolume*)mVO)->mLODChanged || - mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1)) - { - mLastUpdate = 0; // Force an immediate update - } - // Relegate invisible objects to the lowest priority bin - S32 lod = 0; - F32 app_angle = mVO->getAppAngle()*DEG_TO_RAD/gCamera->getView(); - if (mVO->mDrawable->isVisible()) - { - sDebugVisible++; - if (mVO->isSelected()) - { - // Force selected objects to update *every* frame - lod = FLEXIBLE_OBJECT_MAX_LOD-1; - } - else - { - if (app_angle > 0) - { - lod = 5 - (S32)(1.0f/sqrtf(app_angle)); - if (lod < 1) - { - lod = 1; - } - } + + S32 new_res = mAttributes->getSimulateLOD(); - if (mVO->isAttachment()) - { - lod += 3; - } - } - } + //number of segments only cares about z axis + F32 app_angle = llround((F32) atan2( mVO->getScale().mV[2]*2.f, mVO->mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); - S32 new_res = mAttributes->getSimulateLOD(); // Rendering sections increases with visible angle on the screen - mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle); + mRenderRes = (S32)(FLEXIBLE_OBJECT_MAX_SECTIONS*4*app_angle*DEG_TO_RAD/gCamera->getView()); if (mRenderRes > FLEXIBLE_OBJECT_MAX_SECTIONS) { mRenderRes = FLEXIBLE_OBJECT_MAX_SECTIONS; @@ -329,22 +300,32 @@ BOOL LLVolumeImplFlexible::doIdleUpdate(LLAgent &agent, LLWorld &world, const F6 mInitialized = TRUE; } - sLODBins[lod].insert(this); - sDebugInserted++; - return TRUE; -} - -// static -void LLVolumeImplFlexible::resetUpdateBins() -{ - U32 lod; - for (lod=0; lodmDrawable->isVisible() && + !mVO->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) && + mVO->getPixelArea() > 256.f) { - sLODBins[lod].clear(); + U32 id; + F32 pixel_area = mVO->getPixelArea(); + + if (mVO->isRootEdit()) + { + id = mID; + } + else + { + LLVOVolume* parent = (LLVOVolume*) mVO->getParent(); + id = parent->getVolumeInterfaceID(); + } + + U32 update_period = (U32) (gCamera->getScreenPixelArea()*0.01f/(pixel_area*(sUpdateFactor+1.f)))+1; + + if ((LLDrawable::getCurrentFrame()+id)%update_period == 0) + { + gPipeline.markRebuild(mVO->mDrawable, LLDrawable::REBUILD_POSITION, FALSE); + } } - ++sCurrentUpdateFrame; - sDebugInserted = 0; - sDebugVisible = 0; + + return TRUE; } inline S32 log2(S32 x) @@ -358,80 +339,15 @@ inline S32 log2(S32 x) return ret; } -// static -void LLVolumeImplFlexible::doFlexibleUpdateBins() -{ - U32 lod; - U32 updated = 0; - U32 regen = 0; - U32 newflexies = 0; - F32 time_alloc[FLEXIBLE_OBJECT_MAX_LOD]; - F32 total_time_alloc = 0; - - bool new_objects_only = false; - - if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE)) - { - new_objects_only = true; - } - - for (lod=0; lod 0) - { - time_alloc[lod] = (F32)((lod+1)*(log2(count))); - } - else - { - time_alloc[lod] = 0; - } - total_time_alloc += time_alloc[lod]; - } - total_time_alloc = FLEXIBLE_OBJECT_TIMESLICE * (sUpdateFactor+0.01f) / total_time_alloc; - - { - LLFastTimer t(LLFastTimer::FTM_FLEXIBLE_UPDATE); - LLTimer timer; - for (lod=0; loddoFlexibleUpdate(); - ++updated; - (*itor)->doFlexibleRebuild(); - ++bin_count; - ++regen; - if (timer.getElapsedTimeF64() > end_time) - { - break; - } - } - } - for (; itor != sLODBins[lod].end(); ++itor) - { - if ((*itor)->getLastUpdate() == 0) - { - // *Always* update newly-created objects, or objects which have changed LOD - (*itor)->doFlexibleUpdate(); - (*itor)->doFlexibleRebuild(); - ++newflexies; - } - } - } - } -} - void LLVolumeImplFlexible::doFlexibleUpdate() { LLPath *path = &mVO->getVolume()->getPath(); + if (mSimulateRes == 0) + { + mVO->markForUpdate(TRUE); + doIdleUpdate(gAgent, *gWorldp, 0.0); + } + S32 num_sections = 1 << mSimulateRes; F32 secondsThisFrame = mTimer.getElapsedTimeAndResetF32(); @@ -603,6 +519,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() // calculate velocity //------------------------------------------------------------------------------------------ mSection[i].mVelocity = mSection[i].mPosition - lastPosition; + if (mSection[i].mVelocity.magVecSquared() > 1.f) + { + mSection[i].mVelocity.normVec(); + } } // Calculate derivatives (not necessary until normals are automagically generated) @@ -643,11 +563,38 @@ void LLVolumeImplFlexible::doFlexibleUpdate() LLFlexibleObjectSection newSection[ (1<mPath[i]; - new_point->mPos = newSection[i].mPosition; - new_point->mRot = mSection[i].mAxisRotation * newSection[i].mRotation; + LLVector3 pos = newSection[i].mPosition * rel_xform; + LLQuaternion rot = mSection[i].mAxisRotation * newSection[i].mRotation * delta_rot; + + if (!mUpdated || (new_point->mPos-pos).magVecSquared() > 0.000001f) + { + new_point->mPos = newSection[i].mPosition * rel_xform; + mUpdated = FALSE; + } + + new_point->mRot = rot; new_point->mScale = newSection[i].mScale; new_point->mTexT = ((F32)i)/(num_render_sections); } @@ -658,13 +605,10 @@ void LLVolumeImplFlexible::doFlexibleUpdate() void LLVolumeImplFlexible::doFlexibleRebuild() { mVO->getVolume()->regen(); - - mVO->markForUpdate(TRUE); - mUpdated = TRUE; +} - mLastUpdate = sCurrentUpdateFrame; -}//------------------------------------------------------------------ +//------------------------------------------------------------------ void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped) { @@ -673,8 +617,6 @@ void LLVolumeImplFlexible::onSetScale(const LLVector3& scale, BOOL damped) BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) { - BOOL compiled = FALSE; - LLVOVolume *volume = (LLVOVolume*)mVO; if (volume->mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -682,60 +624,36 @@ BOOL LLVolumeImplFlexible::doUpdateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } - volume->calcAllTEsSame(); - - if (volume->mVolumeChanged || volume->mFaceMappingChanged) + if (volume->mLODChanged) { - compiled = TRUE; - volume->regenFaces(); - } - else if (volume->mLODChanged) - { - LLPointer old_volumep, new_volumep; - F32 old_lod, new_lod; - - old_volumep = volume->getVolume(); - old_lod = old_volumep->getDetail(); - - LLVolumeParams volume_params = volume->getVolume()->getParams(); + LLVolumeParams volume_params = volume->getVolume()->getParams(); volume->setVolume(volume_params, 0); - doFlexibleUpdate(); - volume->getVolume()->regen(); - - new_volumep = volume->getVolume(); - new_lod = new_volumep->getDetail(); - - if (new_lod != old_lod) - { - compiled = TRUE; - if (new_volumep->getNumFaces() != old_volumep->getNumFaces()) - { - volume->regenFaces(); - } - } + mUpdated = FALSE; } - if (mUpdated) + volume->updateRelativeXform(); + doFlexibleUpdate(); + + if (volume->mLODChanged || volume->mFaceMappingChanged || + volume->mVolumeChanged) { - compiled = TRUE; - mUpdated = FALSE; + volume->regenFaces(); + volume->mDrawable->setState(LLDrawable::REBUILD_VOLUME); } - if(compiled) + if (!mUpdated || volume->mFaceMappingChanged || volume->mVolumeChanged) { - volume->updateRelativeXform(isVolumeGlobal()); - volume->genTriangles(isVolumeGlobal()); - LLPipeline::sCompiles++; + doFlexibleRebuild(); + volume->genBBoxes(isVolumeGlobal()); } - + volume->mVolumeChanged = FALSE; volume->mLODChanged = FALSE; volume->mFaceMappingChanged = FALSE; + // clear UV flag drawable->clearState(LLDrawable::UV); - - drawable->movePartition(); return TRUE; } @@ -811,42 +729,32 @@ LLQuaternion LLVolumeImplFlexible::getEndRotation() }//------------------------------------------------------------------ -void LLVolumeImplFlexible::updateRelativeXform(BOOL global_volume) +void LLVolumeImplFlexible::updateRelativeXform() { - LLVOVolume* vo = (LLVOVolume*) mVO; - - LLVector3 delta_scale = LLVector3(1,1,1); - LLVector3 delta_pos; LLQuaternion delta_rot; + LLVector3 delta_pos, delta_scale; + LLVOVolume* vo = (LLVOVolume*) mVO; + + //matrix from local space to parent relative/global space + delta_rot = vo->mDrawable->isSpatialRoot() ? LLQuaternion() : vo->mDrawable->getRotation(); + delta_pos = vo->mDrawable->isSpatialRoot() ? LLVector3(0,0,0) : vo->mDrawable->getPosition(); + delta_scale = LLVector3(1,1,1); - if (!mVO->mDrawable->isRoot()) - { //global to parent relative - LLViewerObject* parent = (LLViewerObject*) vo->getParent(); - delta_rot = ~parent->getRenderRotation(); - delta_pos = -parent->getRenderPosition()*delta_rot; - } - else - { //global to local - delta_rot = ~getFrameRotation(); - delta_pos = -getFramePosition()*delta_rot; - } - // Vertex transform (4x4) LLVector3 x_axis = LLVector3(delta_scale.mV[VX], 0.f, 0.f) * delta_rot; LLVector3 y_axis = LLVector3(0.f, delta_scale.mV[VY], 0.f) * delta_rot; LLVector3 z_axis = LLVector3(0.f, 0.f, delta_scale.mV[VZ]) * delta_rot; vo->mRelativeXform.initRows(LLVector4(x_axis, 0.f), - LLVector4(y_axis, 0.f), - LLVector4(z_axis, 0.f), - LLVector4(delta_pos, 1.f)); + LLVector4(y_axis, 0.f), + LLVector4(z_axis, 0.f), + LLVector4(delta_pos, 1.f)); x_axis.normVec(); y_axis.normVec(); z_axis.normVec(); vo->mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); - } const LLMatrix4& LLVolumeImplFlexible::getWorldMatrix(LLXformMatrix* xform) const diff --git a/linden/indra/newview/llflexibleobject.h b/linden/indra/newview/llflexibleobject.h index c028adb..9772c57 100644 --- a/linden/indra/newview/llflexibleobject.h +++ b/linden/indra/newview/llflexibleobject.h @@ -76,6 +76,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface LLVolumeImplFlexible(LLViewerObject* volume, LLFlexibleObjectData* attributes); // Implements LLVolumeInterface + U32 getID() const { return mID; } LLVector3 getFramePosition() const; LLQuaternion getFrameRotation() const; LLVolumeInterfaceType getInterfaceType() const { return INTERFACE_FLEXIBLE; } @@ -90,12 +91,10 @@ class LLVolumeImplFlexible : public LLVolumeInterface bool isVolumeGlobal() const { return true; } bool isActive() const { return true; } const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; - void updateRelativeXform(BOOL global_volume = FALSE); + void updateRelativeXform(); void doFlexibleUpdate(); // Called to update the simulation void doFlexibleRebuild(); // Called to rebuild the geometry - static void resetUpdateBins(); - static void doFlexibleUpdateBins(); - + //void setAttributes( LLFlexibleObjectData ); void setParentPositionAndRotationDirectly( LLVector3 p, LLQuaternion r ); void setUsingCollisionSphere( bool u ); @@ -128,10 +127,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface U32 mFrameNum; LLVector3 mCollisionSpherePosition; F32 mCollisionSphereRadius; - - U64 mLastUpdate; - - BOOL mJustShifted; + U32 mID; //-------------------------------------- // private methods @@ -140,29 +136,7 @@ class LLVolumeImplFlexible : public LLVolumeInterface void remapSections(LLFlexibleObjectSection *source, S32 source_sections, LLFlexibleObjectSection *dest, S32 dest_sections); - - U64 getLastUpdate() const { return mLastUpdate; } - - // LOD Bins - struct FlexCompare - { - bool operator()(LLVolumeImplFlexible* a, LLVolumeImplFlexible* b) const - { - U64 a_update = a->getLastUpdate(); - U64 b_update = b->getLastUpdate(); - if (a_update == b_update) - { - return a < b; // compare pointers - } - return a_update < b_update; - } - }; - typedef std::set lodset_t; - static lodset_t sLODBins[ FLEXIBLE_OBJECT_MAX_LOD ]; - static U64 sCurrentUpdateFrame; - static U32 sDebugInserted; - static U32 sDebugVisible; - + public: // Global setting for update rate static F32 sUpdateFactor; diff --git a/linden/indra/newview/llfloaterabout.cpp b/linden/indra/newview/llfloaterabout.cpp index 54168dc..cbac9f3 100644 --- a/linden/indra/newview/llfloaterabout.cpp +++ b/linden/indra/newview/llfloaterabout.cpp @@ -45,7 +45,10 @@ #include "llvieweruictrlfactory.h" #include "viewer.h" // for gViewerDigest +#if LL_LIBXUL_ENABLED #include "llmozlib.h" +#endif // LL_LIBXUL_ENABLED + #include "llglheaders.h" extern LLCPUInfo gSysCPU; @@ -98,7 +101,7 @@ LLFloaterAbout::LLFloaterAbout() gAgent.getRegion()->getName().c_str()); support.append(region_text); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ gAgent.getRegion()->getHost().getHostName(buffer, MAX_STRING); support.append(buffer); support.append(" ("); @@ -154,7 +157,7 @@ LLFloaterAbout::LLFloaterAbout() // MD5 digest of executable support.append("Viewer Digest: "); - char viewer_digest_string[UUID_STR_LENGTH]; + char viewer_digest_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ gViewerDigest.toString( viewer_digest_string ); support.append(viewer_digest_string); @@ -182,5 +185,5 @@ void LLFloaterAbout::show(void*) sInstance = new LLFloaterAbout(); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } diff --git a/linden/indra/newview/llfloateraccounthistory.cpp b/linden/indra/newview/llfloateraccounthistory.cpp deleted file mode 100644 index a28c4c3..0000000 --- a/linden/indra/newview/llfloateraccounthistory.cpp +++ /dev/null @@ -1,224 +0,0 @@ -/** - * @file llfloateraccounthistory.cpp - * @brief LLFloaterAccountHistory class implementation - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -/** - * The user's account history, including all Linden$ transactions from - * the transaction table. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llfloateraccounthistory.h" - -#include "llfontgl.h" -#include "message.h" -#include "llsecondlifeurls.h" -#include "lltransactiontypes.h" - -#include "llagent.h" -#include "llalertdialog.h" -#include "llpanel.h" -#include "llbutton.h" -#include "llviewercontrol.h" -#include "llviewertexteditor.h" -#include "lluiconstants.h" -#include "llresizehandle.h" -#include "llstatusbar.h" -#include "lltabcontainervertical.h" -#include "llvieweruictrlfactory.h" -#include "llviewerwindow.h" -#include "llweb.h" - -static const char MONEY_HX_TITLE[] = "Account History"; -static const S32 MONEY_HX_WIDTH = 500; -static const S32 MONEY_HX_HEIGHT = 350; -static const S32 INSET = 4; - - -LLMap LLFloaterAccountHistory::sInstances; - - - - -//--------------------------------------------------------------------------- -// LLFloaterAccountHistory -// The container panel for all the panel views. -//--------------------------------------------------------------------------- -// private -LLFloaterAccountHistory::LLFloaterAccountHistory() -: LLFloater("money history floater") -{ - // Unique ID for transactions - mFloaterID.generate(); - - // Instance management - LLFloaterAccountHistory::sInstances.addData(mFloaterID, this); - - // User interface construction - gUICtrlFactory->buildFloater(this, "floater_account_history.xml"); - center(); - - // Put resize handle on top - removeChild(mResizeHandle[0]); - addChild(mResizeHandle[0]); - - LLTabContainerCommon* tab = LLUICtrlFactory::getTabContainerByName(this, "tab"); - if (tab) - { - mPlanningPanel = new LLPanelAccountPlanning(mFloaterID); - tab->addTabPanel( mPlanningPanel, "Planning" ); - - mDetailsPanel = new LLPanelAccountDetails(mFloaterID); - tab->addTabPanel( mDetailsPanel, "Details" ); - - mTransactionsPanel = new LLPanelAccountTransactions(mFloaterID); - tab->addTabPanel( mTransactionsPanel, "Sales/Gifts" ); - - tab->selectFirstTab(); - } - - LLButton* btn = LLUICtrlFactory::getButtonByName(this, "details_btn"); - if (btn) btn->setClickedCallback(onClickDetails, this); -} - - -// private virtual -LLFloaterAccountHistory::~LLFloaterAccountHistory() -{ - LLFloaterAccountHistory::sInstances.removeData(mFloaterID); -} - - -// public static -void LLFloaterAccountHistory::show(void*) -{ - // Make sure the mouse is available for clicking - if( gAgent.cameraMouselook() ) - { - gAgent.changeCameraToDefault(); - } - - // Create the dialog and center on screen - // This will show a default "computing..." message - new LLFloaterAccountHistory(); -} - -// static -void LLFloaterAccountHistory::processMoneySummaryReply(LLMessageSystem* msg, void** data) -{ - LLUUID agent_id; - LLUUID floater_id; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - msg->getUUIDFast(_PREHASH_MoneyData, _PREHASH_RequestID, floater_id ); - - if (agent_id != gAgent.getID()) - { - llwarns << "Received money summary for wrong agent " << agent_id << llendl; - return; - } - - LLFloaterAccountHistory* floater = LLFloaterAccountHistory::sInstances.getIfThere(floater_id); - if (!floater) - { - llwarns << "Received money summary for unknown window " << floater_id << llendl; - return; - } - - floater->open(); - floater->mPlanningPanel->processReply(msg, data); -} - -// static -void LLFloaterAccountHistory::processMoneyDetailsReply(LLMessageSystem* msg, void** data) -{ - LLUUID agent_id; - LLUUID floater_id; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - msg->getUUIDFast(_PREHASH_MoneyData, _PREHASH_RequestID, floater_id ); - - if (agent_id != gAgent.getID()) - { - llwarns << "Received money details for wrong agent " << agent_id << llendl; - return; - } - - LLFloaterAccountHistory* floater = LLFloaterAccountHistory::sInstances.getIfThere(floater_id); - if (!floater) - { - llwarns << "Received money details for unknown window " << floater_id << llendl; - return; - } - - floater->open(); - - floater->mDetailsPanel->processReply(msg, data); -} - -// static -void LLFloaterAccountHistory::processMoneyTransactionsReply(LLMessageSystem* msg, void** data) -{ - LLUUID agent_id; - LLUUID floater_id; - - msg->getUUIDFast(_PREHASH_AgentData, _PREHASH_AgentID, agent_id ); - msg->getUUIDFast(_PREHASH_MoneyData, _PREHASH_RequestID, floater_id ); - - if (agent_id != gAgent.getID()) - { - llwarns << "Received money transactions for wrong agent " << agent_id << llendl; - return; - } - - LLFloaterAccountHistory* floater = LLFloaterAccountHistory::sInstances.getIfThere(floater_id); - if (!floater) - { - llwarns << "Received money transactions for unknown window " << floater_id << llendl; - return; - } - - floater->open(); - floater->mTransactionsPanel->processReply(msg, data); -} - -void callback_load_url_account_transactions(S32 option, void*) -{ - if (option == 0) - { - LLWeb::loadURL(ACCOUNT_TRANSACTIONS_URL); - } -} - -// static -void LLFloaterAccountHistory::onClickDetails(void*) -{ - std::map args; - args["[URL]"] = ACCOUNT_TRANSACTIONS_URL; - gViewerWindow->alertXml("LoadAccountTransactions", args, - callback_load_url_account_transactions, NULL); -} diff --git a/linden/indra/newview/llfloateraccounthistory.h b/linden/indra/newview/llfloateraccounthistory.h deleted file mode 100644 index ae4ae24..0000000 --- a/linden/indra/newview/llfloateraccounthistory.h +++ /dev/null @@ -1,83 +0,0 @@ -/** - * @file llfloateraccounthistory.h - * @brief LLFloaterAccountHistory class definition - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -/** - * The user's account history, including all Linden$ transactions from - * the transaction table. - */ - -#ifndef LL_LLFLOATERACCOUNTHISTORY_H -#define LL_LLFLOATERACCOUNTHISTORY_H - -#include "llfloater.h" -#include "llmap.h" -#include "lluuid.h" -#include "llpanelmoney.h" - -class LLMessageSystem; -class LLTabContainer; -class LLTabContainerVertical; -class LLTextEditor; -class LLButton; - -class LLFloaterAccountHistory -: public LLFloater -{ -public: - static void show(void*); - - // Message system callbacks - static void processMoneySummaryReply(LLMessageSystem* msg, void**); - static void processMoneyDetailsReply(LLMessageSystem* msg, void**); - static void processMoneyTransactionsReply(LLMessageSystem* msg, void**); - -private: - // Must construct by calling show(). - LLFloaterAccountHistory(); - virtual ~LLFloaterAccountHistory(); - - static void onClickDetails(void*); - -private: - // Each money history window has its own id, which it uses - // for transactions and to allow more than one window to - // be open. - LLUUID mFloaterID; - - // The actual information is encoded in panels in this - // tab container. - LLTabContainerVertical* mTab; - - LLPanelAccountPlanning* mPlanningPanel; - LLPanelAccountDetails* mDetailsPanel; - LLPanelAccountTransactions* mTransactionsPanel; - LLButton* mBtnDetails; - - static LLMap sInstances; -}; - -#endif diff --git a/linden/indra/newview/llfloateranimpreview.cpp b/linden/indra/newview/llfloateranimpreview.cpp index ced7a0e..3661ea2 100644 --- a/linden/indra/newview/llfloateranimpreview.cpp +++ b/linden/indra/newview/llfloateranimpreview.cpp @@ -280,8 +280,8 @@ BOOL LLFloaterAnimPreview::postBuild() childSetValue("ease_in_time", LLSD(motionp->getEaseInDuration())); childSetValue("ease_out_time", LLSD(motionp->getEaseOutDuration())); mEnabled = TRUE; - char seconds_string[128]; - sprintf(seconds_string, " - %.2f seconds", motionp->getDuration()); + char seconds_string[128]; /*Flawfinder: ignore*/ + snprintf(seconds_string, sizeof(seconds_string), " - %.2f seconds", motionp->getDuration()); /*Flawfinder: ignore*/ setTitle(mFilename + LLString(seconds_string)); } @@ -301,9 +301,9 @@ BOOL LLFloaterAnimPreview::postBuild() { if (loaderp->getDuration() > MAX_ANIM_DURATION) { - char output_str[256]; + char output_str[256]; /*Flawfinder: ignore*/ - sprintf(output_str, "Animation file is %.1f seconds in length.\n\nMaximum animation length is %.1f seconds.\n", + snprintf(output_str, sizeof(output_str), "Animation file is %.1f seconds in length.\n\nMaximum animation length is %.1f seconds.\n", /*Flawfinder: ignore*/ loaderp->getDuration(), MAX_ANIM_DURATION); childSetValue("bad_animation_text", LLSD(output_str)); } @@ -1016,7 +1016,7 @@ LLPreviewAnimation::LLPreviewAnimation(S32 width, S32 height) : LLDynamicTexture mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); mDummyAvatar->startMotion(ANIM_AGENT_STAND, 5.f); mDummyAvatar->mSkirtLOD.setVisible(FALSE, TRUE); - gPipeline.markVisible(mDummyAvatar->mDrawable); + gPipeline.markVisible(mDummyAvatar->mDrawable, *gCamera); // stop extraneous animations mDummyAvatar->stopMotion( ANIM_AGENT_HEAD_ROT, TRUE ); @@ -1092,6 +1092,10 @@ BOOL LLPreviewAnimation::render() avatarp->updateMotion(); } + LLVertexBuffer::stopRender(); + avatarp->updateLOD(); + LLVertexBuffer::startRender(); + avatarp->mRoot.updateWorldMatrixChildren(); stop_glerror(); @@ -1101,13 +1105,7 @@ BOOL LLPreviewAnimation::render() if (avatarp->mDrawable.notNull()) { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - gPipeline.unbindAGP(); - avatarPoolp->syncAGP(); - if (avatarPoolp->canUseAGP() && gPipeline.usingAGP()) - { - gPipeline.bindAGP(); - } - avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders) + avatarPoolp->renderAvatars(avatarp); // renders only one avatar } return TRUE; diff --git a/linden/indra/newview/llfloaterauction.cpp b/linden/indra/newview/llfloaterauction.cpp index db169a8..8e7124a 100644 --- a/linden/indra/newview/llfloaterauction.cpp +++ b/linden/indra/newview/llfloaterauction.cpp @@ -102,26 +102,27 @@ void LLFloaterAuction::show() sInstance->setFocus(TRUE); } sInstance->initialize(); - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } void LLFloaterAuction::initialize() { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + mParcelp = gParcelMgr->getParcelSelection(); LLViewerRegion* region = gParcelMgr->getSelectionRegion(); - if(parcel && region && !parcel->getForSale()) + LLParcel* parcelp = mParcelp->getParcel(); + if(parcelp && region && !parcelp->getForSale()) { mParcelHost = region->getHost(); - mParcelID = parcel->getLocalID(); + mParcelID = parcelp->getLocalID(); - childSetText("parcel_text", parcel->getName()); + childSetText("parcel_text", parcelp->getName()); childEnable("snapshot_btn"); childEnable("ok_btn"); } else { mParcelHost.invalidate(); - if(parcel && parcel->getForSale()) + if(parcelp && parcelp->getForSale()) { childSetText("parcel_text", childGetText("already for sale")); } diff --git a/linden/indra/newview/llfloaterauction.h b/linden/indra/newview/llfloaterauction.h index e9d9c65..7ff932f 100644 --- a/linden/indra/newview/llfloaterauction.h +++ b/linden/indra/newview/llfloaterauction.h @@ -39,6 +39,7 @@ // // Class which holds the functionality to start auctions. //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class LLParcelSelection; class LLFloaterAuction : public LLFloater { @@ -64,6 +65,7 @@ private: LLTransactionID mTransactionID; LLAssetID mImageID; LLPointer mImage; + LLHandle mParcelp; S32 mParcelID; LLHost mParcelHost; }; diff --git a/linden/indra/newview/llfloateravatarinfo.cpp b/linden/indra/newview/llfloateravatarinfo.cpp index 959967a..ef34542 100644 --- a/linden/indra/newview/llfloateravatarinfo.cpp +++ b/linden/indra/newview/llfloateravatarinfo.cpp @@ -104,17 +104,8 @@ void* LLFloaterAvatarInfo::createPanelAvatar(void* data) //---------------------------------------------------------------------------- -// static -void LLFloaterAvatarInfo::onCommitNotes(LLUICtrl*, void* userdata) -{ - LLFloaterAvatarInfo* self = (LLFloaterAvatarInfo*)userdata; - - self->mPanelAvatarp->sendAvatarNotesUpdate(); -} - BOOL LLFloaterAvatarInfo::postBuild() { - return TRUE; } @@ -164,7 +155,9 @@ void LLFloaterAvatarInfo::resetGroupList() // Open profile to a certian tab. // static -void LLFloaterAvatarInfo::showFromObject(const LLUUID &avatar_id, std::string tab_name) +void LLFloaterAvatarInfo::showFromObject( + const LLUUID& avatar_id, + std::string tab_name) { if(avatar_id.isNull()) { @@ -185,9 +178,8 @@ void LLFloaterAvatarInfo::showFromObject(const LLUUID &avatar_id, std::string ta floater->mPanelAvatarp->setAvatarID(avatar_id, "", ONLINE_STATUS_NO); } - floater->mPanelAvatarp->selectTabByName(tab_name); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } // static @@ -203,7 +195,7 @@ void LLFloaterAvatarInfo::showFromDirectory(const LLUUID &avatar_id) { // ...bring that window to front floater = gAvatarInfoInstances.getData(avatar_id); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } else { @@ -211,7 +203,7 @@ void LLFloaterAvatarInfo::showFromDirectory(const LLUUID &avatar_id) avatar_id); floater->center(); floater->mPanelAvatarp->setAvatarID(avatar_id, "", ONLINE_STATUS_NO); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } if(floater) { @@ -227,14 +219,14 @@ void LLFloaterAvatarInfo::showFromAvatar(LLViewerObject *avatar) { // ...bring that window to front LLFloaterAvatarInfo *f = gAvatarInfoInstances.getData(avatar->getID()); - f->open(); + f->open(); /*Flawfinder: ignore*/ } else { LLFloaterAvatarInfo *floater = new LLFloaterAvatarInfo("avatarinfo", FAI_RECT, avatar->getID() ); floater->center(); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } } @@ -250,7 +242,7 @@ void LLFloaterAvatarInfo::showFromFriend(const LLUUID& agent_id, BOOL online) { // ...bring that window to front LLFloaterAvatarInfo *f = gAvatarInfoInstances.getData( agent_id ); - f->open(); + f->open(); /*Flawfinder: ignore*/ } else { diff --git a/linden/indra/newview/llfloateravatarinfo.h b/linden/indra/newview/llfloateravatarinfo.h index ee7cebb..4879309 100644 --- a/linden/indra/newview/llfloateravatarinfo.h +++ b/linden/indra/newview/llfloateravatarinfo.h @@ -62,8 +62,6 @@ public: static void* createPanelAvatar(void* data); virtual BOOL postBuild(); - static void onCommitNotes(LLUICtrl*, void* userdata); - LLFloaterAvatarInfo(const std::string& name, const LLRect &rect, const LLUUID &avatar_id ); /*virtual*/ ~LLFloaterAvatarInfo(); diff --git a/linden/indra/newview/llfloateravatarpicker.cpp b/linden/indra/newview/llfloateravatarpicker.cpp index c95ac6b..cb9af67 100644 --- a/linden/indra/newview/llfloateravatarpicker.cpp +++ b/linden/indra/newview/llfloateravatarpicker.cpp @@ -61,13 +61,13 @@ LLFloaterAvatarPicker* LLFloaterAvatarPicker::show(callback_t callback, sInstance->mCallbackUserdata = userdata; sInstance->mCloseOnSelect = FALSE; - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ sInstance->center(); sInstance->setAllowMultiple(allow_multiple); } else { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->mCallback = callback; sInstance->mCallbackUserdata = userdata; sInstance->setAllowMultiple(allow_multiple); @@ -285,8 +285,8 @@ void LLFloaterAvatarPicker::processAvatarPickerReply(LLMessageSystem* msg, void* LLUUID agent_id; LLUUID query_id; LLUUID avatar_id; - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_LAST_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last_name[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ msg->getUUID("AgentData", "AgentID", agent_id); msg->getUUID("AgentData", "QueryID", query_id); diff --git a/linden/indra/newview/llfloateravatartextures.cpp b/linden/indra/newview/llfloateravatartextures.cpp index 8ff65ab..d7d7dfc 100644 --- a/linden/indra/newview/llfloateravatartextures.cpp +++ b/linden/indra/newview/llfloateravatartextures.cpp @@ -54,7 +54,7 @@ LLFloaterAvatarTextures* LLFloaterAvatarTextures::show(const LLUUID &id) gUICtrlFactory->buildFloater(floaterp, "floater_avatar_textures.xml"); gFloaterView->addChild(floaterp); - floaterp->open(); + floaterp->open(); /*Flawfinder: ignore*/ gFloaterView->adjustToFitScreen(floaterp, FALSE); @@ -110,7 +110,7 @@ static void update_texture_ctrl(LLVOAvatar* avatarp, else { ctrl->setImageAssetID(id); - ctrl->setToolTip(id.getString()); + ctrl->setToolTip(id.asString()); } } @@ -138,8 +138,8 @@ void LLFloaterAvatarTextures::refresh() LLVOAvatar *avatarp = find_avatar(mID); if (avatarp) { - char firstname[DB_FIRST_NAME_BUF_SIZE]; - char lastname[DB_LAST_NAME_BUF_SIZE]; + char firstname[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char lastname[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if (gCacheName->getName(avatarp->getID(), firstname, lastname)) { LLString name; @@ -175,7 +175,7 @@ void LLFloaterAvatarTextures::refresh() } else { - setTitle(mTitle + ": INVALID AVATAR (" + mID.getString() + ")"); + setTitle(mTitle + ": INVALID AVATAR (" + mID.asString() + ")"); } #endif } diff --git a/linden/indra/newview/llfloaterbuildoptions.cpp b/linden/indra/newview/llfloaterbuildoptions.cpp index f93483a..be5cd4e 100644 --- a/linden/indra/newview/llfloaterbuildoptions.cpp +++ b/linden/indra/newview/llfloaterbuildoptions.cpp @@ -69,14 +69,14 @@ void LLFloaterBuildOptions::show(void*) { if (sInstance) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } else { LLFloaterBuildOptions* floater = new LLFloaterBuildOptions(); gUICtrlFactory->buildFloater(floater, "floater_build_options.xml"); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } } diff --git a/linden/indra/newview/llfloaterbump.cpp b/linden/indra/newview/llfloaterbump.cpp index 265970f..ead50e8 100644 --- a/linden/indra/newview/llfloaterbump.cpp +++ b/linden/indra/newview/llfloaterbump.cpp @@ -96,7 +96,7 @@ void LLFloaterBump::show(void *contents) } } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } void LLFloaterBump::add(LLScrollListCtrl* list, LLMeanCollisionData* mcd) diff --git a/linden/indra/newview/llfloaterbuy.cpp b/linden/indra/newview/llfloaterbuy.cpp index 04b56bf..2266845 100644 --- a/linden/indra/newview/llfloaterbuy.cpp +++ b/linden/indra/newview/llfloaterbuy.cpp @@ -63,8 +63,6 @@ LLFloaterBuy::LLFloaterBuy() LLFloaterBuy::~LLFloaterBuy() { - gSelectMgr->deselectAll(); - sInstance = NULL; } @@ -80,7 +78,9 @@ void LLFloaterBuy::reset() // static void LLFloaterBuy::show(const LLSaleInfo& sale_info) { - if (gSelectMgr->getRootObjectCount() != 1) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + + if (selection->getRootObjectCount() != 1) { gViewerWindow->alertXml("BuyOneObjectOnly"); return; @@ -97,9 +97,10 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info) sInstance = new LLFloaterBuy(); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->setFocus(TRUE); sInstance->mSaleInfo = sale_info; + sInstance->mObjectSelection = gSelectMgr->getEditSelection(); // Always center the dialog. User can change the size, // but purchases are important and should be center screen. @@ -107,7 +108,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info) // mid-session and the saved rect is off-center. sInstance->center(); - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = selection->getFirstRootNode(); if (!node) return; // Set title based on sale type @@ -181,7 +182,7 @@ void LLFloaterBuy::show(const LLSaleInfo& sale_info) // Must do this after the floater is created, because // sometimes the inventory is already there and // the callback is called immediately. - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); + LLViewerObject* obj = selection->getFirstRootObject(); sInstance->registerVOInventoryListener(obj,NULL); sInstance->requestVOInventory(); } diff --git a/linden/indra/newview/llfloaterbuy.h b/linden/indra/newview/llfloaterbuy.h index fd1ffd2..1642aaa 100644 --- a/linden/indra/newview/llfloaterbuy.h +++ b/linden/indra/newview/llfloaterbuy.h @@ -41,6 +41,7 @@ class LLViewerObject; class LLSaleInfo; +class LLObjectSelection; class LLFloaterBuy : public LLFloater, public LLVOInventoryListener @@ -66,6 +67,7 @@ protected: private: static LLFloaterBuy* sInstance; + LLHandle mObjectSelection; LLSaleInfo mSaleInfo; }; diff --git a/linden/indra/newview/llfloaterbuycontents.cpp b/linden/indra/newview/llfloaterbuycontents.cpp index 4f6f52e..1deb1ab 100644 --- a/linden/indra/newview/llfloaterbuycontents.cpp +++ b/linden/indra/newview/llfloaterbuycontents.cpp @@ -68,8 +68,6 @@ LLFloaterBuyContents::LLFloaterBuyContents() LLFloaterBuyContents::~LLFloaterBuyContents() { - gSelectMgr->deselectAll(); - sInstance = NULL; } @@ -77,7 +75,9 @@ LLFloaterBuyContents::~LLFloaterBuyContents() // static void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) { - if (gSelectMgr->getRootObjectCount() != 1) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + + if (selection->getRootObjectCount() != 1) { gViewerWindow->alertXml("BuyContentsOneOnly"); return; @@ -94,8 +94,9 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) sInstance = new LLFloaterBuyContents(); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->setFocus(TRUE); + sInstance->mObjectSelection = gSelectMgr->getEditSelection(); // Always center the dialog. User can change the size, // but purchases are important and should be center screen. @@ -115,11 +116,11 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) sInstance->mSaleInfo = sale_info; // Update the display - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = selection->getFirstRootNode(); if (!node) return; if(node->mPermissions->isGroupOwned()) { - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getGroupName(owner_id, group_name); owner_name.assign(group_name); } @@ -131,7 +132,7 @@ void LLFloaterBuyContents::show(const LLSaleInfo& sale_info) // Must do this after the floater is created, because // sometimes the inventory is already there and // the callback is called immediately. - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); + LLViewerObject* obj = selection->getFirstRootObject(); sInstance->registerVOInventoryListener(obj,NULL); sInstance->requestVOInventory(); } diff --git a/linden/indra/newview/llfloaterbuycontents.h b/linden/indra/newview/llfloaterbuycontents.h index 2c643f5..a30de0e 100644 --- a/linden/indra/newview/llfloaterbuycontents.h +++ b/linden/indra/newview/llfloaterbuycontents.h @@ -39,6 +39,7 @@ #include "llinventory.h" class LLViewerObject; +class LLObjectSelection; class LLFloaterBuyContents : public LLFloater, public LLVOInventoryListener @@ -62,6 +63,7 @@ protected: protected: static LLFloaterBuyContents* sInstance; + LLHandle mObjectSelection; LLSaleInfo mSaleInfo; }; diff --git a/linden/indra/newview/llfloaterbuycurrency.cpp b/linden/indra/newview/llfloaterbuycurrency.cpp index 3ecffd5..388a8aa 100644 --- a/linden/indra/newview/llfloaterbuycurrency.cpp +++ b/linden/indra/newview/llfloaterbuycurrency.cpp @@ -185,7 +185,7 @@ BOOL LLFloaterBuyCurrencyUI::canClose() void LLFloaterBuyCurrencyUI::onClose(bool app_quitting) { LLFloater::onClose(app_quitting); - delete this; + destroy(); } void LLFloaterBuyCurrencyUI::updateUI() diff --git a/linden/indra/newview/llfloaterbuyland.cpp b/linden/indra/newview/llfloaterbuyland.cpp index ca5f677..1b72d4e 100644 --- a/linden/indra/newview/llfloaterbuyland.cpp +++ b/linden/indra/newview/llfloaterbuyland.cpp @@ -75,7 +75,7 @@ private: virtual ~LLFloaterBuyLandUI(); LLViewerRegion* mRegion; - LLParcel* mParcel; + LLParcelSelectionHandle mParcel; bool mIsClaim; bool mIsForGroup; @@ -146,7 +146,7 @@ public: static LLFloaterBuyLandUI* soleInstance(bool createIfNeeded); void setForGroup(bool is_for_group); - void setParcel(LLViewerRegion* region, LLParcel* parcel); + void setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel); void updateAgentInfo(); void updateParcelInfo(); @@ -205,7 +205,7 @@ static void cacheNameUpdateRefreshesBuyLand(const LLUUID&, // static void LLFloaterBuyLand::buyLand( - LLViewerRegion* region, LLParcel* parcel, bool is_for_group) + LLViewerRegion* region, LLParcelSelectionHandle parcel, bool is_for_group) { if(is_for_group && !gAgent.hasPowerInActiveGroup(GP_LAND_DEED)) { @@ -216,7 +216,7 @@ void LLFloaterBuyLand::buyLand( LLFloaterBuyLandUI* ui = LLFloaterBuyLandUI::soleInstance(true); ui->setForGroup(is_for_group); ui->setParcel(region, parcel); - ui->open(); + ui->open(); /*Flawfinder: ignore*/ } // static @@ -350,7 +350,7 @@ void LLFloaterBuyLandUI::SelectionObserver::changed() else { ui->setParcel( gParcelMgr->getSelectionRegion(), - gParcelMgr->getSelectedParcel()); + gParcelMgr->getParcelSelection()); } } } @@ -368,7 +368,8 @@ void LLFloaterBuyLandUI::updateAgentInfo() void LLFloaterBuyLandUI::updateParcelInfo() { - mParcelValid = mParcel && mRegion; + LLParcel* parcel = mParcel->getParcel(); + mParcelValid = parcel && mRegion; mParcelIsForSale = false; mParcelIsFirstLand = false; mParcelIsGroupLand = false; @@ -391,50 +392,61 @@ void LLFloaterBuyLandUI::updateParcelInfo() return; } - if (gParcelMgr->getMultipleOwners()) + if (mParcel->getMultipleOwners()) { mCannotBuyReason = childGetText("multiple_parcels_selected"); return; } + const LLUUID& parcelOwner = parcel->getOwnerID(); - const LLUUID& parcelOwner = mParcel->getOwnerID(); - - mIsClaim = mParcel->isPublic(); + mIsClaim = parcel->isPublic(); if (!mIsClaim) { - mParcelActualArea = mParcel->getArea(); - mParcelIsForSale = mParcel->getForSale(); - mParcelIsFirstLand = mParcel->getReservedForNewbie(); - mParcelIsGroupLand = mParcel->getIsGroupOwned(); - mParcelPrice = mParcelIsForSale ? mParcel->getSalePrice() : 0; + mParcelActualArea = parcel->getArea(); + mParcelIsForSale = parcel->getForSale(); + mParcelIsFirstLand = parcel->getReservedForNewbie(); + mParcelIsGroupLand = parcel->getIsGroupOwned(); + mParcelPrice = mParcelIsForSale ? parcel->getSalePrice() : 0; if (mParcelIsGroupLand) { - LLUUID group_id = mParcel->getGroupID(); + LLUUID group_id = parcel->getGroupID(); mParcelGroupContribution = gAgent.getGroupContribution(group_id); } } else { - mParcelActualArea = gParcelMgr->getClaimableArea(); + mParcelActualArea = mParcel->getClaimableArea(); mParcelIsForSale = true; - mParcelPrice = mParcelActualArea * mParcel->getClaimPricePerMeter(); + mParcelPrice = mParcelActualArea * parcel->getClaimPricePerMeter(); } mParcelBillableArea = llround(mRegion->getBillableFactor() * mParcelActualArea); - mParcelSupportedObjects = mParcel->getMaxPrimCapacity(); - mParcelSoldWithObjects = mParcel->getSellWithObjects(); + mParcelSupportedObjects = llround( + parcel->getMaxPrimCapacity() * parcel->getParcelPrimBonus()); + // Can't have more than region max tasks, regardless of parcel + // object bonus factor. + LLViewerRegion* region = gParcelMgr->getSelectionRegion(); + if(region) + { + S32 max_tasks_per_region = (S32)region->getMaxTasks(); + mParcelSupportedObjects = llmin( + mParcelSupportedObjects, max_tasks_per_region); + } + + mParcelSoldWithObjects = parcel->getSellWithObjects(); + - LLVector3 center = mParcel->getCenterpoint(); + LLVector3 center = parcel->getCenterpoint(); mParcelLocation = llformat("%s %d,%d", mRegion->getName().c_str(), (int)center[VX], (int)center[VY] ); - mParcelSnapshot = mParcel->getSnapshotID(); + mParcelSnapshot = parcel->getSnapshotID(); updateNames(); @@ -453,7 +465,7 @@ void LLFloaterBuyLandUI::updateParcelInfo() if (!mIsClaim) { - const LLUUID& authorizedBuyer = mParcel->getAuthorizedBuyerID(); + const LLUUID& authorizedBuyer = parcel->getAuthorizedBuyerID(); const LLUUID buyer = gAgent.getID(); const LLUUID newOwner = mIsForGroup ? gAgent.getGroupID() : buyer; @@ -492,7 +504,7 @@ void LLFloaterBuyLandUI::updateParcelInfo() return; } - if (gParcelMgr->hasOthersSelected()) + if (mParcel->hasOthersSelected()) { // Policy: Must not have someone else's land selected mCannotBuyReason = childGetText("not_owned_by_you"); @@ -511,7 +523,7 @@ void LLFloaterBuyLandUI::updateParcelInfo() } */ - if (mParcel->getReservedForNewbie()) + if (parcel->getReservedForNewbie()) { if (mIsForGroup) { @@ -684,9 +696,10 @@ void LLFloaterBuyLandUI::updateWebSiteInfo() #endif LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); - keywordArgs.appendString("agentId", gAgent.getID().getString()); - keywordArgs.appendString("secureSessionId", - gAgent.getSecureSessionID().getString()); + keywordArgs.appendString("agentId", gAgent.getID().asString()); + keywordArgs.appendString( + "secureSessionId", + gAgent.getSecureSessionID().asString()); keywordArgs.appendInt("billableArea", mPreflightAskBillableArea); keywordArgs.appendInt("currencyBuy", mPreflightAskCurrencyBuy); @@ -771,9 +784,10 @@ void LLFloaterBuyLandUI::runWebSitePrep(const std::string& password) } LLXMLRPCValue keywordArgs = LLXMLRPCValue::createStruct(); - keywordArgs.appendString("agentId", gAgent.getID().getString()); - keywordArgs.appendString("secureSessionId", - gAgent.getSecureSessionID().getString()); + keywordArgs.appendString("agentId", gAgent.getID().asString()); + keywordArgs.appendString( + "secureSessionId", + gAgent.getSecureSessionID().asString()); keywordArgs.appendString("levelId", newLevel); keywordArgs.appendInt("billableArea", mIsForGroup ? 0 : mParcelBillableArea); @@ -820,7 +834,9 @@ void LLFloaterBuyLandUI::sendBuyLand() void LLFloaterBuyLandUI::updateNames() { - if (!mParcelValid) + LLParcel* parcelp = mParcel->getParcel(); + + if (!parcelp) { mParcelSellerName = ""; return; @@ -830,19 +846,19 @@ void LLFloaterBuyLandUI::updateNames() { mParcelSellerName = "Linden Lab"; } - else if (mParcel->getIsGroupOwned()) + else if (parcelp->getIsGroupOwned()) { - char groupName[DB_LAST_NAME_BUF_SIZE]; + char groupName[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ - gCacheName->getGroupName(mParcel->getGroupID(), &groupName[0]); + gCacheName->getGroupName(parcelp->getGroupID(), &groupName[0]); mParcelSellerName = groupName; } else { - char firstName[DB_LAST_NAME_BUF_SIZE]; - char lastName[DB_LAST_NAME_BUF_SIZE]; + char firstName[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char lastName[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ - gCacheName->getName(mParcel->getOwnerID(), firstName, lastName); + gCacheName->getName(parcelp->getOwnerID(), firstName, lastName); mParcelSellerName = llformat("%s %s", firstName, lastName); } } @@ -939,7 +955,7 @@ BOOL LLFloaterBuyLandUI::postBuild() return TRUE; } -void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel) +void LLFloaterBuyLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel) { if (mTransaction && mTransactionType == TransactionBuy) { @@ -996,7 +1012,7 @@ BOOL LLFloaterBuyLandUI::canClose() void LLFloaterBuyLandUI::onClose(bool app_quitting) { LLFloater::onClose(app_quitting); - delete this; + destroy(); } diff --git a/linden/indra/newview/llfloaterbuyland.h b/linden/indra/newview/llfloaterbuyland.h index 016c1ec..a91c6d6 100644 --- a/linden/indra/newview/llfloaterbuyland.h +++ b/linden/indra/newview/llfloaterbuyland.h @@ -28,15 +28,15 @@ #ifndef LL_LLFLOATERBUYLAND_H #define LL_LLFLOATERBUYLAND_H -class LLParcel; class LLViewerRegion; class LLViewerTextEditor; +class LLParcelSelection; class LLFloaterBuyLand { public: static void buyLand(LLViewerRegion* region, - LLParcel* parcel, + LLHandle parcel, bool is_for_group); static void updateCovenantText(const std::string& string, const LLUUID& asset_id); static void updateEstateName(const std::string& name); diff --git a/linden/indra/newview/llfloaterchat.cpp b/linden/indra/newview/llfloaterchat.cpp index 0ffc518..2b27d15 100644 --- a/linden/indra/newview/llfloaterchat.cpp +++ b/linden/indra/newview/llfloaterchat.cpp @@ -135,7 +135,7 @@ void LLFloaterChat::onClose(bool app_quitting) // public void LLFloaterChat::show() { - open(); + open(); /*Flawfinder: ignore*/ } void add_timestamped_line(LLViewerTextEditor* edit, const LLString& line, const LLColor4& color) diff --git a/linden/indra/newview/llfloatercolorpicker.cpp b/linden/indra/newview/llfloatercolorpicker.cpp index f8d5cd4..84df754 100644 --- a/linden/indra/newview/llfloatercolorpicker.cpp +++ b/linden/indra/newview/llfloatercolorpicker.cpp @@ -181,7 +181,7 @@ showUI () { setVisible ( TRUE ); setFocus ( TRUE ); - open(); + open(); /*Flawfinder: ignore*/ // HACK: if system color picker is required - close the SL one we made and use default system dialog if ( gSavedSettings.getBOOL ( "UseDefaultColorPicker" ) ) @@ -635,7 +635,7 @@ void LLFloaterColorPicker::draw() } mPipetteBtn->setEnabled(gToolMgr != NULL); - mPipetteBtn->setToggleState(gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette); + mPipetteBtn->setToggleState(gToolMgr && gToolMgr->getCurrentTool() == gToolPipette); mApplyImmediateCheck->setEnabled(mActive && mCanApplyImmediately); mSelectBtn->setEnabled(mActive); @@ -1272,7 +1272,7 @@ void LLFloaterColorPicker::setActive(BOOL active) void LLFloaterColorPicker::stopUsingPipette() { - if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette) + if (gToolMgr && gToolMgr->getCurrentTool() == gToolPipette) { gToolMgr->clearTransientTool(); } diff --git a/linden/indra/newview/llfloatercustomize.cpp b/linden/indra/newview/llfloatercustomize.cpp index f564dad..7ac50ae 100644 --- a/linden/indra/newview/llfloatercustomize.cpp +++ b/linden/indra/newview/llfloatercustomize.cpp @@ -2162,6 +2162,8 @@ void LLFloaterCustomize::onTabChanged( void* userdata, bool from_click ) void LLFloaterCustomize::onClose(bool app_quitting) { + // since this window is potentially staying open, push to back to let next window take focus + gFloaterView->sendChildToBack(this); handle_reset_view(); // Calls askToSaveAllIfDirty } diff --git a/linden/indra/newview/llfloaterdirectory.cpp b/linden/indra/newview/llfloaterdirectory.cpp index ab2e873..846a2fb 100644 --- a/linden/indra/newview/llfloaterdirectory.cpp +++ b/linden/indra/newview/llfloaterdirectory.cpp @@ -379,7 +379,7 @@ void LLFloaterDirectory::show(void *) sInstance = new LLFloaterDirectory("directory"); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->focusCurrentPanel(); } @@ -415,7 +415,7 @@ void LLFloaterDirectory::toggleFind(void*) BOOL panel_visible = sInstance->getVisible(); if (!panel_visible) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->focusCurrentPanel(); } else @@ -436,7 +436,7 @@ void LLFloaterDirectory::toggleEvents(void*) BOOL panel_visible = sInstance->getVisible(); if (!panel_visible) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ sInstance->showEvents(0); } else diff --git a/linden/indra/newview/llfloatereditui.cpp b/linden/indra/newview/llfloatereditui.cpp index 21580d3..3af5741 100644 --- a/linden/indra/newview/llfloatereditui.cpp +++ b/linden/indra/newview/llfloatereditui.cpp @@ -319,7 +319,7 @@ void LLFloaterEditUI::show(void*) { LLFloaterEditUI* self = new LLFloaterEditUI(); self->center(); - self->open(); + self->open(); /*Flawfinder: ignore*/ } // static diff --git a/linden/indra/newview/llfloaterfriends.cpp b/linden/indra/newview/llfloaterfriends.cpp index 207454b..8a36620 100644 --- a/linden/indra/newview/llfloaterfriends.cpp +++ b/linden/indra/newview/llfloaterfriends.cpp @@ -113,12 +113,12 @@ void LLFloaterFriends::show(void*) { if(sInstance) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } else { LLFloaterFriends* self = new LLFloaterFriends; - self->open(); + self->open(); /*Flawfinder: ignore*/ } } @@ -505,12 +505,12 @@ void LLFloaterFriends::onClickIM(void* user_data) { LLUUID agent_id = ids[0]; const LLRelationship* info = LLAvatarTracker::instance().getBuddyInfo(agent_id); - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char last[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ if(info && gCacheName->getName(agent_id, first, last)) { - char buffer[MAX_STRING]; - snprintf(buffer, MAX_STRING, "%s %s", first, last); + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "%s %s", first, last); /* Flawfinder: ignore */ gIMView->setFloaterOpen(TRUE); gIMView->addSession( buffer, @@ -537,8 +537,7 @@ void LLFloaterFriends::requestFriendship(const LLUUID& target_id, const LLString { // HACK: folder id stored as "message" LLUUID calling_card_folder_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_CALLINGCARD); - std::string message = calling_card_folder_id.getString(); - + std::string message = calling_card_folder_id.asString(); send_improved_im(target_id, target_name.c_str(), message.c_str(), @@ -598,8 +597,8 @@ void LLFloaterFriends::onClickRemove(void* user_data) if(ids.size() == 1) { LLUUID agent_id = ids[0]; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if(gCacheName->getName(agent_id, first, last)) { args["[FIRST_NAME]"] = first; @@ -671,8 +670,8 @@ void LLFloaterFriends::onClickModifyStatus(LLUICtrl* ctrl, void* user_data) if(ids.size() == 1) { LLUUID agent_id = ids[0]; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if(gCacheName->getName(agent_id, first, last)) { args["[FIRST_NAME]"] = first; diff --git a/linden/indra/newview/llfloatergesture.cpp b/linden/indra/newview/llfloatergesture.cpp index e4425d1..313dccf 100644 --- a/linden/indra/newview/llfloatergesture.cpp +++ b/linden/indra/newview/llfloatergesture.cpp @@ -133,7 +133,7 @@ void LLFloaterGesture::show() { if (sInstance) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ return; } @@ -158,7 +158,7 @@ void LLFloaterGesture::show() // Update button labels onCommitList(NULL, self); - self->open(); + self->open(); /*Flawfinder: ignore*/ } // static diff --git a/linden/indra/newview/llfloatergodtools.cpp b/linden/indra/newview/llfloatergodtools.cpp index d2ce3fd..e1d12d2 100644 --- a/linden/indra/newview/llfloatergodtools.cpp +++ b/linden/indra/newview/llfloatergodtools.cpp @@ -86,7 +86,7 @@ LLFloaterGodTools* LLFloaterGodTools::instance() if (!sGodTools) { sGodTools = new LLFloaterGodTools(); - sGodTools->open(); + sGodTools->open(); /*Flawfinder: ignore*/ sGodTools->center(); sGodTools->setFocus(TRUE); } @@ -223,7 +223,7 @@ void LLFloaterGodTools::show(void *) void LLFloaterGodTools::showPanel(const LLString& panel_name) { childShowTab("GodTools Tabs", panel_name); - open(); + open(); /*Flawfinder: ignore*/ LLPanel *panel = childGetVisibleTab("GodTools Tabs"); if (panel) panel->setFocus(TRUE); } @@ -254,7 +254,7 @@ void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) U32 region_flags; U8 sim_access; U8 agent_limit; - char sim_name[MAX_STRING]; + char sim_name[MAX_STRING]; /*Flawfinder: ignore*/ U32 estate_id; U32 parent_estate_id; F32 water_height; @@ -990,7 +990,7 @@ void LLPanelGridTools::flushMapVisibilityCachesConfirm(S32 option, void* data) msg->addString("Method", "refreshmapvisibility"); msg->addUUID("Invoice", LLUUID::null); msg->nextBlock("ParamList"); - msg->addString("Parameter", gAgent.getID().getString()); + msg->addString("Parameter", gAgent.getID().asString()); gAgent.sendReliableMessage(); } @@ -1256,8 +1256,8 @@ void LLPanelObjectTools::onClickSetBySelection(void* data) LLPanelObjectTools* panelp = (LLPanelObjectTools*) data; if (!panelp) return; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); - if (!node) node = gSelectMgr->getFirstNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); + if (!node) node = gSelectMgr->getSelection()->getFirstNode(); if (!node) return; LLString owner_name; diff --git a/linden/indra/newview/llfloatergroupinfo.cpp b/linden/indra/newview/llfloatergroupinfo.cpp index 5fc999e..a807774 100644 --- a/linden/indra/newview/llfloatergroupinfo.cpp +++ b/linden/indra/newview/llfloatergroupinfo.cpp @@ -172,7 +172,7 @@ void LLFloaterGroupInfo::showFromUUID(const LLUUID& group_id, fgi->selectTabByName(tab_name); fgi->center(); - fgi->open(); + fgi->open(); /*Flawfinder: ignore*/ } // static diff --git a/linden/indra/newview/llfloatergroupinvite.cpp b/linden/indra/newview/llfloatergroupinvite.cpp index a727f22..0c8b526 100644 --- a/linden/indra/newview/llfloatergroupinvite.cpp +++ b/linden/indra/newview/llfloatergroupinvite.cpp @@ -132,6 +132,6 @@ void LLFloaterGroupInvite::showForGroup(const LLUUID& group_id) } fgi->center(); - fgi->open(); + fgi->open(); /*Flawfinder: ignore*/ fgi->mImpl->mInvitePanelp->update(); } diff --git a/linden/indra/newview/llfloatergroups.cpp b/linden/indra/newview/llfloatergroups.cpp index 05a6927..11b58d5 100644 --- a/linden/indra/newview/llfloatergroups.cpp +++ b/linden/indra/newview/llfloatergroups.cpp @@ -93,7 +93,7 @@ LLFloaterGroups* LLFloaterGroups::show(const LLUUID& id, EGroupDialog type) else { // Move the existing view to the front - instance->open(); + instance->open(); /* Flawfinder: ignore */ } } @@ -119,7 +119,7 @@ LLFloaterGroups* LLFloaterGroups::show(const LLUUID& id, EGroupDialog type) break; } instance->center(); - instance->open(); + instance->open(); /*Flawfinder: ignore*/ } } return instance; diff --git a/linden/indra/newview/llfloaterimagepreview.cpp b/linden/indra/newview/llfloaterimagepreview.cpp index c741bdb..9c68ca8 100644 --- a/linden/indra/newview/llfloaterimagepreview.cpp +++ b/linden/indra/newview/llfloaterimagepreview.cpp @@ -179,7 +179,6 @@ void LLFloaterImagePreview::onPreviewTypeCommit(LLUICtrl* ctrl, void* userdata) break; } fp->mAvatarPreview->refresh(); - //gViewerWindow->requestFastFrame(fp); } //----------------------------------------------------------------------------- @@ -489,7 +488,6 @@ BOOL LLFloaterImagePreview::handleHover(S32 x, S32 y, MASK mask) } LLUI::setCursorPositionLocal(this, mLastMouseX, mLastMouseY); - //gViewerWindow->requestFastFrame(this); } if (!mPreviewRect.pointInRect(x, y) || !mAvatarPreview) @@ -521,7 +519,6 @@ BOOL LLFloaterImagePreview::handleScrollWheel(S32 x, S32 y, S32 clicks) { mAvatarPreview->zoom((F32)clicks * -0.2f); mAvatarPreview->refresh(); - //gViewerWindow->requestFastFrame(this); } return TRUE; @@ -557,7 +554,7 @@ LLImagePreviewAvatar::LLImagePreviewAvatar(S32 width, S32 height) : LLDynamicTex mDummyAvatar->slamPosition(); mDummyAvatar->updateJointLODs(); mDummyAvatar->updateGeometry(mDummyAvatar->mDrawable); - gPipeline.markVisible(mDummyAvatar->mDrawable); + gPipeline.markVisible(mDummyAvatar->mDrawable, *gCamera); mTextureName = 0; } @@ -645,6 +642,10 @@ BOOL LLImagePreviewAvatar::render() gCamera->setView(gCamera->getDefaultFOV() / mCameraZoom); gCamera->setPerspective(FALSE, mOrigin.mX, mOrigin.mY, mWidth, mHeight, FALSE); + LLVertexBuffer::stopRender(); + avatarp->updateLOD(); + LLVertexBuffer::startRender(); + if (avatarp->mDrawable.notNull()) { LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); @@ -653,13 +654,7 @@ BOOL LLImagePreviewAvatar::render() LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); - gPipeline.unbindAGP(); - avatarPoolp->syncAGP(); - if (avatarPoolp->canUseAGP() && gPipeline.usingAGP()) - { - gPipeline.bindAGP(); - } - avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders) + avatarPoolp->renderAvatars(avatarp); // renders only one avatar } return TRUE; diff --git a/linden/indra/newview/llfloaterimport.cpp b/linden/indra/newview/llfloaterimport.cpp index b7255db..478b5d7 100644 --- a/linden/indra/newview/llfloaterimport.cpp +++ b/linden/indra/newview/llfloaterimport.cpp @@ -76,8 +76,9 @@ LLFloaterImport::LLFloaterImport(const std::string filename) { mFilenameAndPath = filename; - char file_path[256]; - strcpy(file_path, mFilenameAndPath.c_str()); + char file_path[256]; /*Flawfinder: ignore*/ + strncpy(file_path, mFilenameAndPath.c_str(), sizeof(file_path) -1); /*Flawfinder: ignore*/ + file_path[sizeof(file_path) -1] = '\0'; char *file_name = strrchr( file_path, gDirUtilp->getDirDelimiter()[0]); file_name[0] = 0; @@ -104,7 +105,7 @@ BOOL LLFloaterImport::postBuild() char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists if( !end_p ) { - end_p = asset_name_str + strlen( asset_name_str ); + end_p = asset_name_str + strlen( asset_name_str ); /*Flawfinder: ignore*/ } S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); @@ -182,8 +183,8 @@ BOOL LLFloaterImport::postBuild() LLScrollListItem *new_item = new LLScrollListItem(TRUE, task); new_item->addColumn("OBJECT", default_font, 60); LLString output_line; - char buffer[20]; - sprintf(buffer, "%d", (S32)tasks_list.size()); + char buffer[20]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "%d", (S32)tasks_list.size()); /*Flawfinder: ignore*/ output_line.append(buffer); output_line.append(" prims"); new_item->addColumn(output_line, default_font, 80); @@ -257,9 +258,9 @@ BOOL LLFloaterImport::postBuild() llinfos << "Getting hash for " << image_path << llendl; - char md5_hash_string[33]; - strcpy(md5_hash_string, "00000000000000000000000000000000"); - FILE *fCheck = LLFile::fopen(image_path.c_str(), "rb"); + char md5_hash_string[33]; /*Flawfinder: ignore*/ + strcpy(md5_hash_string, "00000000000000000000000000000000"); /*Flawfinder: ignore*/ + FILE* fCheck = LLFile::fopen(image_path.c_str(), "rb"); /*Flawfinder: ignore*/ if (fCheck) { LLMD5 my_md5_hash(fCheck); @@ -458,7 +459,7 @@ void LLFloaterImport::finishImport(ImportAssetInfo *info) { // Copy file into a local directory LLString new_file = "TEMP"; - new_file.append(new_file_id.getString()); + new_file.append(new_file_id.asString()); new_file.append(".slobject"); S32 length; @@ -509,7 +510,7 @@ void LLFloaterImport::asset_uploaded_callback(const LLUUID& uuid, void* user_dat LLResourceData *resource_data = (LLResourceData*)user_data; ImportAssetInfo *info = (ImportAssetInfo*)resource_data->mUserData; - info->NewImageIDList.push_back(resource_data->mAssetInfo.mUuid.getString()); + info->NewImageIDList.push_back(resource_data->mAssetInfo.mUuid.asString()); LLUploadDialog::modalUploadFinished(); if (info->ImageFileQueue.size() == 0) @@ -553,7 +554,7 @@ void LLFloaterImport::onBtnOK(void*userdata) LLString *image_id = (LLString *)(*itor)->getUserdata(); if (image_id) { - asset_info->OldImageIDList.push_back(id.getString()); + asset_info->OldImageIDList.push_back(id.asString()); LLString image_file = fp->mInventoryPath; image_file.append(gDirUtilp->getDirDelimiter()); image_file.append(*image_id); diff --git a/linden/indra/newview/llfloaterinspect.cpp b/linden/indra/newview/llfloaterinspect.cpp index 40132ce..8bb73e3 100644 --- a/linden/indra/newview/llfloaterinspect.cpp +++ b/linden/indra/newview/llfloaterinspect.cpp @@ -1,221 +1,221 @@ -#include "llviewerprecompiledheaders.h" -#include "llfloateravatarinfo.h" -#include "llfloaterinspect.h" -#include "llfloatertools.h" -#include "llcachename.h" -#include "llscrolllistctrl.h" -#include "llselectmgr.h" -#include "lltoolcomp.h" -#include "lltoolmgr.h" -#include "llviewercontrol.h" -#include "llviewerobject.h" -#include "llvieweruictrlfactory.h" - -LLFloaterInspect* LLFloaterInspect::sInstance = NULL; - -LLFloaterInspect::LLFloaterInspect(void) : - LLFloater("Inspect Object"), - mDirty(FALSE) -{ - sInstance = this; - gUICtrlFactory->buildFloater(this, "floater_inspect.xml"); -} - -LLFloaterInspect::~LLFloaterInspect(void) -{ - if(!gFloaterTools->getVisible()) - { - if(gToolMgr->getCurrentTool(MASK_NONE) == gToolInspect) - { - select_tool(gToolNull); - } - gSelectMgr->deselectAll(); - // Switch back to basic toolset - gCurrentToolset = gBasicToolset; - gBasicToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gBasicToolset ); - } - else - { - gFloaterTools->setFocus(TRUE); - } - sInstance = NULL; -} - -BOOL LLFloaterInspect::isVisible() -{ - return (!!sInstance); -} - -void LLFloaterInspect::show(void* ignored) -{ - if(sInstance) - { - sInstance->open(); - } - else - { - LLFloaterInspect* self = new LLFloaterInspect; - self->open(); - } - select_tool(gToolInspect); -} - -void LLFloaterInspect::onClickCreatorProfile(void* ctrl) -{ - if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = gSelectMgr->getFirstNode(); - LLUUID obj_id, creator_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) - { - if(obj_id == obj->getObject()->getID()) - { - creator_id = obj->mPermissions->getCreator(); - break; - } - obj = gSelectMgr->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(creator_id); - } -} - -void LLFloaterInspect::onClickOwnerProfile(void* ctrl) -{ - if(sInstance->mObjectList->getAllSelected().size() == 0) return; - LLSelectNode* obj = gSelectMgr->getFirstNode(); - LLUUID obj_id, owner_id; - obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); - while(obj) - { - if(obj_id == obj->getObject()->getID()) - { - owner_id = obj->mPermissions->getOwner(); - break; - } - obj = gSelectMgr->getNextNode(); - } - if(obj) - { - LLFloaterAvatarInfo::showFromDirectory(owner_id); - } -} - -BOOL LLFloaterInspect::postBuild() -{ - mObjectList = LLUICtrlFactory::getScrollListByName(this, "object_list"); - childSetAction("button owner",onClickOwnerProfile, this); - childSetAction("button creator",onClickCreatorProfile, this); - childSetCommitCallback("object_list", onSelectObject); - refresh(); - return TRUE; -} - -void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data) -{ - if(LLFloaterInspect::getSelectedUUID() != LLUUID::null) - { - sInstance->childSetEnabled("button owner", true); - sInstance->childSetEnabled("button creator", true); - } -} - -LLUUID LLFloaterInspect::getSelectedUUID() -{ - if(sInstance) - { - if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID(); - } - return LLUUID::null; -} - -void LLFloaterInspect::refresh() -{ - LLUUID creator_id; - LLString creator_name; - S32 pos = mObjectList->getScrollPos(); - childSetEnabled("button owner", false); - childSetEnabled("button creator", false); - LLUUID selected_uuid; - S32 selected_index = mObjectList->getFirstSelectedIndex(); - if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID(); - mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE); - //List all transient objects, then all linked objects - LLSelectNode* obj = gSelectMgr->getFirstNode(); - LLSD row; - while(obj) - { - char owner_first_name[MAX_STRING], owner_last_name[MAX_STRING]; - char creator_first_name[MAX_STRING], creator_last_name[MAX_STRING]; - char time[MAX_STRING]; - std::ostringstream owner_name, creator_name, date; - time_t timestamp = (time_t) (obj->mCreationDate/1000000); - LLString::copy(time, ctime(×tamp), MAX_STRING); - time[24] = '\0'; - date << obj->mCreationDate; - gCacheName->getName(obj->mPermissions->getOwner(), owner_first_name, owner_last_name); - owner_name << owner_first_name << " " << owner_last_name; - gCacheName->getName(obj->mPermissions->getCreator(), creator_first_name, creator_last_name); - creator_name << creator_first_name << " " << creator_last_name; - row["id"] = obj->getObject()->getID(); - row["columns"][0]["column"] = "object_name"; - row["columns"][0]["type"] = "text"; - // make sure we're either at the top of the link chain - // or top of the editable chain, for attachments - if(!(obj->getObject()->isRoot() || obj->getObject()->isRootEdit())) - { - row["columns"][0]["value"] = LLString(" ") + obj->mName; - } - else - { - row["columns"][0]["value"] = obj->mName; - } - row["columns"][1]["column"] = "owner_name"; - row["columns"][1]["type"] = "text"; - row["columns"][1]["value"] = owner_name.str().c_str(); - row["columns"][2]["column"] = "creator_name"; - row["columns"][2]["type"] = "text"; - row["columns"][2]["value"] = creator_name.str().c_str(); - row["columns"][3]["column"] = "creation_date"; - row["columns"][3]["type"] = "text"; - row["columns"][3]["value"] = time; - mObjectList->addElement(row, ADD_TOP); - obj = gSelectMgr->getNextNode(); - } - if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index) - { - mObjectList->selectNthItem(selected_index); - } - else - { - mObjectList->selectNthItem(0); - } - onSelectObject(this, NULL); - mObjectList->setScrollPos(pos); -} - -void LLFloaterInspect::onFocusReceived() -{ - select_tool(gToolInspect); -} - -void LLFloaterInspect::dirty() -{ - if(sInstance) - { - sInstance->setDirty(); - } -} - -void LLFloaterInspect::draw() -{ - if (mDirty) - { - refresh(); - mDirty = FALSE; - } - - LLFloater::draw(); -} \ No newline at end of file +#include "llviewerprecompiledheaders.h" +#include "llfloateravatarinfo.h" +#include "llfloaterinspect.h" +#include "llfloatertools.h" +#include "llcachename.h" +#include "llscrolllistctrl.h" +#include "llselectmgr.h" +#include "lltoolcomp.h" +#include "lltoolmgr.h" +#include "llviewercontrol.h" +#include "llviewerobject.h" +#include "llvieweruictrlfactory.h" + +LLFloaterInspect* LLFloaterInspect::sInstance = NULL; + +LLFloaterInspect::LLFloaterInspect(void) : + LLFloater("Inspect Object"), + mDirty(FALSE) +{ + sInstance = this; + gUICtrlFactory->buildFloater(this, "floater_inspect.xml"); +} + +LLFloaterInspect::~LLFloaterInspect(void) +{ + if(!gFloaterTools->getVisible()) + { + if(gToolMgr->getBaseTool() == gToolInspect) + { + select_tool(gToolNull); + } + // Switch back to basic toolset + gToolMgr->setCurrentToolset(gBasicToolset); + } + else + { + gFloaterTools->setFocus(TRUE); + } + sInstance = NULL; +} + +BOOL LLFloaterInspect::isVisible() +{ + return (!!sInstance); +} + +void LLFloaterInspect::show(void* ignored) +{ + if(sInstance) + { + sInstance->open(); + } + else + { + LLFloaterInspect* self = new LLFloaterInspect; + self->open(); + } + + sInstance->mObjectSelection = gSelectMgr->getSelection(); + select_tool(gToolInspect); + sInstance->refresh(); +} + +void LLFloaterInspect::onClickCreatorProfile(void* ctrl) +{ + if(sInstance->mObjectList->getAllSelected().size() == 0) return; + LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, creator_id; + obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); + while(obj) + { + if(obj_id == obj->getObject()->getID()) + { + creator_id = obj->mPermissions->getCreator(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(creator_id); + } +} + +void LLFloaterInspect::onClickOwnerProfile(void* ctrl) +{ + if(sInstance->mObjectList->getAllSelected().size() == 0) return; + LLSelectNode* obj = sInstance->mObjectSelection->getFirstNode(); + LLUUID obj_id, owner_id; + obj_id = sInstance->mObjectList->getFirstSelected()->getUUID(); + while(obj) + { + if(obj_id == obj->getObject()->getID()) + { + owner_id = obj->mPermissions->getOwner(); + break; + } + obj = sInstance->mObjectSelection->getNextNode(); + } + if(obj) + { + LLFloaterAvatarInfo::showFromDirectory(owner_id); + } +} + +BOOL LLFloaterInspect::postBuild() +{ + mObjectList = LLUICtrlFactory::getScrollListByName(this, "object_list"); + childSetAction("button owner",onClickOwnerProfile, this); + childSetAction("button creator",onClickCreatorProfile, this); + childSetCommitCallback("object_list", onSelectObject); + return TRUE; +} + +void LLFloaterInspect::onSelectObject(LLUICtrl* ctrl, void* user_data) +{ + if(LLFloaterInspect::getSelectedUUID() != LLUUID::null) + { + sInstance->childSetEnabled("button owner", true); + sInstance->childSetEnabled("button creator", true); + } +} + +LLUUID LLFloaterInspect::getSelectedUUID() +{ + if(sInstance) + { + if(sInstance->mObjectList->getAllSelected().size() > 0) return sInstance->mObjectList->getFirstSelected()->getUUID(); + } + return LLUUID::null; +} + +void LLFloaterInspect::refresh() +{ + LLUUID creator_id; + LLString creator_name; + S32 pos = mObjectList->getScrollPos(); + childSetEnabled("button owner", false); + childSetEnabled("button creator", false); + LLUUID selected_uuid; + S32 selected_index = mObjectList->getFirstSelectedIndex(); + if(selected_index > -1) selected_uuid = mObjectList->getFirstSelected()->getUUID(); + mObjectList->operateOnAll(LLScrollListCtrl::OP_DELETE); + //List all transient objects, then all linked objects + LLSelectNode* obj = mObjectSelection->getFirstNode(); + LLSD row; + while(obj) + { + char owner_first_name[MAX_STRING], owner_last_name[MAX_STRING]; + char creator_first_name[MAX_STRING], creator_last_name[MAX_STRING]; + char time[MAX_STRING]; + std::ostringstream owner_name, creator_name, date; + time_t timestamp = (time_t) (obj->mCreationDate/1000000); + LLString::copy(time, ctime(×tamp), MAX_STRING); + time[24] = '\0'; + date << obj->mCreationDate; + gCacheName->getName(obj->mPermissions->getOwner(), owner_first_name, owner_last_name); + owner_name << owner_first_name << " " << owner_last_name; + gCacheName->getName(obj->mPermissions->getCreator(), creator_first_name, creator_last_name); + creator_name << creator_first_name << " " << creator_last_name; + row["id"] = obj->getObject()->getID(); + row["columns"][0]["column"] = "object_name"; + row["columns"][0]["type"] = "text"; + // make sure we're either at the top of the link chain + // or top of the editable chain, for attachments + if(!(obj->getObject()->isRoot() || obj->getObject()->isRootEdit())) + { + row["columns"][0]["value"] = LLString(" ") + obj->mName; + } + else + { + row["columns"][0]["value"] = obj->mName; + } + row["columns"][1]["column"] = "owner_name"; + row["columns"][1]["type"] = "text"; + row["columns"][1]["value"] = owner_name.str().c_str(); + row["columns"][2]["column"] = "creator_name"; + row["columns"][2]["type"] = "text"; + row["columns"][2]["value"] = creator_name.str().c_str(); + row["columns"][3]["column"] = "creation_date"; + row["columns"][3]["type"] = "text"; + row["columns"][3]["value"] = time; + mObjectList->addElement(row, ADD_TOP); + obj = mObjectSelection->getNextNode(); + } + if(selected_index > -1 && mObjectList->getItemIndex(selected_uuid) == selected_index) + { + mObjectList->selectNthItem(selected_index); + } + else + { + mObjectList->selectNthItem(0); + } + onSelectObject(this, NULL); + mObjectList->setScrollPos(pos); +} + +void LLFloaterInspect::onFocusReceived() +{ + select_tool(gToolInspect); +} + +void LLFloaterInspect::dirty() +{ + if(sInstance) + { + sInstance->setDirty(); + } +} + +void LLFloaterInspect::draw() +{ + if (mDirty) + { + refresh(); + mDirty = FALSE; + } + + LLFloater::draw(); +} + diff --git a/linden/indra/newview/llfloaterinspect.h b/linden/indra/newview/llfloaterinspect.h index 2075204..51549ad 100644 --- a/linden/indra/newview/llfloaterinspect.h +++ b/linden/indra/newview/llfloaterinspect.h @@ -1,10 +1,10 @@ -/** -* @file llfloaterfriends.h -* @author Cube -* @date 2006-12-16 -* @brief Declaration of class for displaying object attributes -* -* Copyright (c) 2005-2007, Linden Research, Inc. +/** +* @file llfloaterfriends.h +* @author Cube +* @date 2006-12-16 +* @brief Declaration of class for displaying object attributes +* +* Copyright (c) 2005-2007, Linden Research, Inc. * * The source code in this file ("Source Code") is provided by Linden Lab * to you under the terms of the GNU General Public License, version 2.0 @@ -24,43 +24,46 @@ * * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY, - * COMPLETENESS OR PERFORMANCE. -*/ - -#ifndef LL_LLFLOATERINSPECT_H -#define LL_LLFLOATERINSPECT_H - -#include "llfloater.h" - -//class LLTool; -class LLScrollListCtrl; -class LLUICtrl; - -class LLFloaterInspect : public LLFloater -{ -public: - virtual ~LLFloaterInspect(void); - static void show(void* ignored = NULL); - virtual BOOL postBuild(); - static void dirty(); - static LLUUID getSelectedUUID(); - virtual void draw(); - virtual void refresh(); - static BOOL isVisible(); - virtual void onFocusReceived(); - static void onClickCreatorProfile(void* ctrl); - static void onClickOwnerProfile(void* ctrl); - static void onSelectObject(LLUICtrl* ctrl, void* user_data); - LLScrollListCtrl* mObjectList; -protected: - // protected members - LLFloaterInspect(); - void setDirty() { mDirty = TRUE; } - bool mDirty; - -private: - // static data - static LLFloaterInspect* sInstance; -}; - -#endif //LL_LLFLOATERINSPECT_H \ No newline at end of file + * COMPLETENESS OR PERFORMANCE. +*/ + +#ifndef LL_LLFLOATERINSPECT_H +#define LL_LLFLOATERINSPECT_H + +#include "llfloater.h" + +//class LLTool; +class LLObjectSelection; +class LLScrollListCtrl; +class LLUICtrl; + +class LLFloaterInspect : public LLFloater +{ +public: + virtual ~LLFloaterInspect(void); + static void show(void* ignored = NULL); + virtual BOOL postBuild(); + static void dirty(); + static LLUUID getSelectedUUID(); + virtual void draw(); + virtual void refresh(); + static BOOL isVisible(); + virtual void onFocusReceived(); + static void onClickCreatorProfile(void* ctrl); + static void onClickOwnerProfile(void* ctrl); + static void onSelectObject(LLUICtrl* ctrl, void* user_data); + LLScrollListCtrl* mObjectList; +protected: + // protected members + LLFloaterInspect(); + void setDirty() { mDirty = TRUE; } + bool mDirty; + +private: + // static data + static LLFloaterInspect* sInstance; + + LLHandle mObjectSelection; +}; + +#endif //LL_LLFLOATERINSPECT_H diff --git a/linden/indra/newview/llfloaterland.cpp b/linden/indra/newview/llfloaterland.cpp index f19baa9..6bb6aff 100644 --- a/linden/indra/newview/llfloaterland.cpp +++ b/linden/indra/newview/llfloaterland.cpp @@ -113,7 +113,7 @@ static const BOOL BUY_PERSONAL_LAND = FALSE; LLFloaterLand* LLFloaterLand::sInstance = NULL; LLParcelSelectionObserver* LLFloaterLand::sObserver = NULL; S32 LLFloaterLand::sLastTab = 0; -BOOL LLFloaterLand::sRequestReplyOnUpdate = TRUE; + LLViewHandle LLPanelLandGeneral::sBuyPassDialogHandle; // Local classes @@ -185,7 +185,7 @@ void LLFloaterLand::show() gParcelMgr->addObserver( sObserver ); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ // Done automatically when the selected parcel's properties arrive // (and hence we have the local id). @@ -193,13 +193,11 @@ void LLFloaterLand::show() // If we've already got the parcel data, fill the // floater with it. - LLParcel *parcel = gParcelMgr->getSelectedParcel(); - if (parcel) + sInstance->mParcel = gParcelMgr->getFloatingParcelSelection(); + if (sInstance->mParcel->getParcel()) { sInstance->refresh(); } - - sRequestReplyOnUpdate = TRUE; } //static @@ -233,19 +231,6 @@ void LLFloaterLand::refreshAll() } } - -// virtual -BOOL LLFloaterLand::canClose() -{ - // canClose is checked as the first step of attempting to close - // the window, before focus is released from controls. Since we're - // closing the window and deselecting the land, we - // don't want replies to the upstream messages that get sent - // (because the reply will cause the land to be selected again). - sRequestReplyOnUpdate = FALSE; - return TRUE; -} - // virtual void LLFloaterLand::onClose(bool app_quitting) { @@ -253,10 +238,6 @@ void LLFloaterLand::onClose(bool app_quitting) delete sObserver; sObserver = NULL; - // Must do this after removing observer, otherwise - // infinite loops notifying and closing. - gParcelMgr->deselectLand(); - // Might have been showing owned objects gSelectMgr->unhighlightAll(); @@ -321,7 +302,7 @@ void LLFloaterLand::refresh() void* LLFloaterLand::createPanelLandGeneral(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelGeneral = new LLPanelLandGeneral(); + self->mPanelGeneral = new LLPanelLandGeneral(self->mParcel); return self->mPanelGeneral; } @@ -331,7 +312,7 @@ void* LLFloaterLand::createPanelLandGeneral(void* data) void* LLFloaterLand::createPanelLandCovenant(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelCovenant = new LLPanelLandCovenant(); + self->mPanelCovenant = new LLPanelLandCovenant(self->mParcel); return self->mPanelCovenant; } @@ -340,7 +321,7 @@ void* LLFloaterLand::createPanelLandCovenant(void* data) void* LLFloaterLand::createPanelLandObjects(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelObjects = new LLPanelLandObjects(); + self->mPanelObjects = new LLPanelLandObjects(self->mParcel); return self->mPanelObjects; } @@ -348,7 +329,7 @@ void* LLFloaterLand::createPanelLandObjects(void* data) void* LLFloaterLand::createPanelLandOptions(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelOptions = new LLPanelLandOptions(); + self->mPanelOptions = new LLPanelLandOptions(self->mParcel); return self->mPanelOptions; } @@ -356,7 +337,7 @@ void* LLFloaterLand::createPanelLandOptions(void* data) void* LLFloaterLand::createPanelLandMedia(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelMedia = new LLPanelLandMedia(); + self->mPanelMedia = new LLPanelLandMedia(self->mParcel); return self->mPanelMedia; } @@ -364,7 +345,7 @@ void* LLFloaterLand::createPanelLandMedia(void* data) void* LLFloaterLand::createPanelLandAccess(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelAccess = new LLPanelLandAccess(); + self->mPanelAccess = new LLPanelLandAccess(self->mParcel); return self->mPanelAccess; } @@ -372,7 +353,7 @@ void* LLFloaterLand::createPanelLandAccess(void* data) void* LLFloaterLand::createPanelLandBan(void* data) { LLFloaterLand* self = (LLFloaterLand*)data; - self->mPanelBan = new LLPanelLandBan(); + self->mPanelBan = new LLPanelLandBan(self->mParcel); return self->mPanelBan; } @@ -382,9 +363,10 @@ void* LLFloaterLand::createPanelLandBan(void* data) //--------------------------------------------------------------------------- -LLPanelLandGeneral::LLPanelLandGeneral() +LLPanelLandGeneral::LLPanelLandGeneral(LLParcelSelectionHandle& parcel) : LLPanel("land_general_panel"), - mUncheckedSell(FALSE) + mUncheckedSell(FALSE), + mParcel(parcel) { } @@ -471,9 +453,8 @@ BOOL LLPanelLandGeneral::postBuild() mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND); - static BOOL deselect_when_done = FALSE; mBtnBuyPass = LLUICtrlFactory::getButtonByName(this, "Buy Pass..."); - mBtnBuyPass->setClickedCallback(onClickBuyPass, &deselect_when_done); + mBtnBuyPass->setClickedCallback(onClickBuyPass, this); mBtnReleaseLand = LLUICtrlFactory::getButtonByName(this, "Abandon Land..."); mBtnReleaseLand->setClickedCallback(onClickRelease, NULL); @@ -498,7 +479,7 @@ void LLPanelLandGeneral::refresh() { mBtnStartAuction->setVisible(gAgent.isGodlike()); - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); bool region_owner = false; LLViewerRegion* regionp = gParcelMgr->getSelectionRegion(); if(regionp && (regionp->getOwner() == gAgent.getID())) @@ -607,8 +588,8 @@ void LLPanelLandGeneral::refresh() } else if(parcel->getAuctionID()) { - char auction_str[MAX_STRING]; - sprintf(auction_str, "Auction ID: %u", parcel->getAuctionID()); + char auction_str[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(auction_str, sizeof(auction_str), "Auction ID: %u", parcel->getAuctionID()); /*Flawfinder: ignore*/ mTextSalePending->setText(auction_str); mTextSalePending->setEnabled(TRUE); } @@ -645,7 +626,7 @@ void LLPanelLandGeneral::refresh() // Display claim date time_t claim_date = parcel->getClaimDate(); - char time_buf[TIME_STR_LENGTH]; + char time_buf[TIME_STR_LENGTH]; /*Flawfinder: ignore*/ mTextClaimDate->setText(formatted_time(claim_date, time_buf)); mTextClaimDate->setEnabled(is_leased); @@ -735,7 +716,7 @@ void LLPanelLandGeneral::refresh() gParcelMgr->canAgentBuyParcel(parcel, true)); // show pricing information - char price[64]; + char price[64]; /*Flawfinder: ignore*/ const char* label = NULL; S32 area; S32 claim_price; @@ -748,13 +729,13 @@ void LLPanelLandGeneral::refresh() &dwell); // Area - sprintf(price, "%d sq. m.", area); + snprintf(price, sizeof(price), "%d sq. m.", area); /*Flawfinder: ignore*/ label = AREA; mTextPriceLabel->setText(label); mTextPrice->setText(price); - sprintf(price, "%.0f", dwell); + snprintf(price, sizeof(price), "%.0f", dwell); /*Flawfinder: ignore*/ mTextDwell->setText(price); if(region_owner) @@ -780,31 +761,31 @@ void LLPanelLandGeneral::refresh() // public void LLPanelLandGeneral::refreshNames() { - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); if (!parcel) { mTextOwner->setText(""); return; } - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ if (parcel->getIsGroupOwned()) { buffer[0] = '\0'; - strcat(buffer, "(Group Owned)"); + strcat(buffer, "(Group Owned)"); /*Flawfinder: ignore*/ } else { // Figure out the owner's name - char owner_first[MAX_STRING]; - char owner_last[MAX_STRING]; + char owner_first[MAX_STRING]; /*Flawfinder: ignore*/ + char owner_last[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getName(parcel->getOwnerID(), owner_first, owner_last); - sprintf(buffer, "%s %s", owner_first, owner_last); + snprintf(buffer, sizeof(buffer), "%s %s", owner_first, owner_last); /*Flawfinder: ignore*/ } if(LLParcel::OS_LEASE_PENDING == parcel->getOwnershipStatus()) { - strcat(buffer, " (Sale Pending)"); + strcat(buffer, " (Sale Pending)"); /*Flawfinder: ignore*/ } mTextOwner->setText(buffer); @@ -822,8 +803,8 @@ void LLPanelLandGeneral::refreshNames() if(auth_buyer_id.notNull()) { LLString name; - char firstname[MAX_STRING]; - char lastname[MAX_STRING]; + char firstname[MAX_STRING]; /*Flawfinder: ignore*/ + char lastname[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getName(auth_buyer_id, firstname, lastname); name.assign(firstname); name.append(" "); @@ -860,7 +841,8 @@ void LLPanelLandGeneral::onClickSetGroup(void* userdata) // static void LLPanelLandGeneral::onClickProfile(void* data) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; if (parcel->getIsGroupOwned()) @@ -885,7 +867,7 @@ void LLPanelLandGeneral::cbGroupID(LLUUID group_id, void* userdata) // public void LLPanelLandGeneral::setGroup(const LLUUID& group_id) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; // Set parcel properties and send message @@ -894,7 +876,7 @@ void LLPanelLandGeneral::setGroup(const LLUUID& group_id) //mTextGroup->setText(group_name); // Send update - gParcelMgr->sendParcelPropertiesUpdate(parcel, LLFloaterLand::sRequestReplyOnUpdate); + gParcelMgr->sendParcelPropertiesUpdate(parcel); // Update UI refresh(); @@ -907,16 +889,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data) gParcelMgr->startBuyLand(*for_group); } -BOOL LLPanelLandGeneral::enableDeedToGroup(void*) +BOOL LLPanelLandGeneral::enableDeedToGroup(void* data) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp->mParcel->getParcel(); return (parcel != NULL) && (parcel->getParcelFlag(PF_ALLOW_DEED_TO_GROUP)); } // static void LLPanelLandGeneral::onClickDeed(void*) { - //LLParcel* parcel = gParcelMgr->getSelectedParcel(); + //LLParcel* parcel = mParcel->getParcel(); //if (parcel) //{ gParcelMgr->startDeedLandToGroup(); @@ -937,39 +920,43 @@ void LLPanelLandGeneral::onClickReclaim(void*) } // static -BOOL LLPanelLandGeneral::enableBuyPass(void*) +BOOL LLPanelLandGeneral::enableBuyPass(void* data) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp != NULL ? panelp->mParcel->getParcel() : gParcelMgr->getParcelSelection()->getParcel(); return (parcel != NULL) && (parcel->getParcelFlag(PF_USE_PASS_LIST) && !gParcelMgr->isCollisionBanned()); } // static -void LLPanelLandGeneral::onClickBuyPass(void* deselect_when_done) +void LLPanelLandGeneral::onClickBuyPass(void* data) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp != NULL ? panelp->mParcel->getParcel() : gParcelMgr->getParcelSelection()->getParcel(); + if (!parcel) return; S32 pass_price = parcel->getPassPrice(); const char* parcel_name = parcel->getName(); F32 pass_hours = parcel->getPassHours(); - char cost[256], time[256]; - sprintf(cost, "%d", pass_price); - sprintf(time, "%.2f", pass_hours); + char cost[256], time[256]; /*Flawfinder: ignore*/ + snprintf(cost, sizeof(cost), "%d", pass_price); /*Flawfinder: ignore*/ + snprintf(time, sizeof(time), "%.2f", pass_hours); /*Flawfinder: ignore*/ LLStringBase::format_map_t args; args["[COST]"] = cost; args["[PARCEL_NAME]"] = parcel_name; args["[TIME]"] = time; - sBuyPassDialogHandle = gViewerWindow->alertXml("LandBuyPass", args, cbBuyPass, deselect_when_done)->getHandle(); + sBuyPassDialogHandle = gViewerWindow->alertXml("LandBuyPass", args, cbBuyPass)->getHandle(); } // static -void LLPanelLandGeneral::onClickStartAuction(void*) +void LLPanelLandGeneral::onClickStartAuction(void* data) { - LLParcel* parcelp = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcelp = panelp->mParcel->getParcel(); if(parcelp) { if(parcelp->getForSale()) @@ -986,18 +973,11 @@ void LLPanelLandGeneral::onClickStartAuction(void*) // static void LLPanelLandGeneral::cbBuyPass(S32 option, void* data) { - BOOL deselect_when_done = (BOOL)(intptr_t)data; - if (0 == option) { // User clicked OK gParcelMgr->buyPass(); } - - if (deselect_when_done) - { - gParcelMgr->deselectLand(); - } } //static @@ -1011,7 +991,7 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) { LLPanelLandGeneral *panelp = (LLPanelLandGeneral *)userdata; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) { return; @@ -1034,7 +1014,7 @@ void LLPanelLandGeneral::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setContributeWithDeed(contribute_with_deed); // Send update to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! panelp->refresh(); @@ -1049,20 +1029,21 @@ void LLPanelLandGeneral::onClickSellLand(void* data) // static void LLPanelLandGeneral::onClickStopSellLand(void* data) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data; + LLParcel* parcel = panelp->mParcel->getParcel(); parcel->setParcelFlag(PF_FOR_SALE, FALSE); parcel->setSalePrice(0); parcel->setAuthorizedBuyerID(LLUUID::null); - gParcelMgr->sendParcelPropertiesUpdate(parcel, LLFloaterLand::sRequestReplyOnUpdate); + gParcelMgr->sendParcelPropertiesUpdate(parcel); } //--------------------------------------------------------------------------- // LLPanelLandObjects //--------------------------------------------------------------------------- -LLPanelLandObjects::LLPanelLandObjects() -: LLPanel("land_objects_panel") +LLPanelLandObjects::LLPanelLandObjects(LLParcelSelectionHandle& parcel) +: LLPanel("land_objects_panel"), mParcel(parcel) { } @@ -1230,7 +1211,7 @@ void LLPanelLandObjects::onDoubleClickOwner(void *userdata) // public void LLPanelLandObjects::refresh() { - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); mBtnShowOwnerObjects->setEnabled(FALSE); mBtnShowGroupObjects->setEnabled(FALSE); @@ -1258,16 +1239,16 @@ void LLPanelLandObjects::refresh() } else { - char count[MAX_STRING]; - S32 sw_max; - S32 sw_total; - S32 max; - S32 total; - S32 owned; - S32 group; - S32 other; - S32 selected; - F32 parcel_object_bonus; + char count[MAX_STRING]; /*Flawfinder: ignore*/ + S32 sw_max = 0; + S32 sw_total = 0; + S32 max = 0; + S32 total = 0; + S32 owned = 0; + S32 group = 0; + S32 other = 0; + S32 selected = 0; + F32 parcel_object_bonus = 0.f; gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, @@ -1285,7 +1266,7 @@ void LLPanelLandObjects::refresh() if (parcel_object_bonus != 1.0f) { - sprintf(count, "Region Object Bonus Factor: %.2f", + snprintf(count, sizeof(count), "Region Object Bonus Factor: %.2f", /*Flawfinder: ignore*/ parcel_object_bonus); mParcelObjectBonus->setText(count); } @@ -1296,35 +1277,35 @@ void LLPanelLandObjects::refresh() if (sw_total > sw_max) { - sprintf(count, "%d out of %d (%d will be deleted)", + snprintf(count, sizeof(count), "%d out of %d (%d will be deleted)", /*Flawfinder: ignore*/ sw_total, sw_max, sw_total - sw_max); } else { - sprintf(count, "%d out of %d (%d available)", + snprintf(count, sizeof(count), "%d out of %d (%d available)", /*Flawfinder: ignore*/ sw_total, sw_max, sw_max - sw_total); } mSWTotalObjects->setText(count); - sprintf(count, "%d", max); + snprintf(count, sizeof(count), "%d", max); /*Flawfinder: ignore*/ mObjectContribution->setText(count); - sprintf(count, "%d", total); + snprintf(count, sizeof(count), "%d", total); /*Flawfinder: ignore*/ mTotalObjects->setText(count); - sprintf(count, "%d", owned); + snprintf(count, sizeof(count), "%d", owned); /*Flawfinder: ignore*/ mOwnerObjects->setText(count); - sprintf(count, "%d", group); + snprintf(count, sizeof(count), "%d", group); /*Flawfinder: ignore*/ mGroupObjects->setText(count); - sprintf(count, "%d", other); + snprintf(count, sizeof(count), "%d", other); /*Flawfinder: ignore*/ mOtherObjects->setText(count); - sprintf(count, "%d", selected); + snprintf(count, sizeof(count), "%d", selected); /*Flawfinder: ignore*/ mSelectedObjects->setText(count); - sprintf(count, "%d", mOtherTime); + snprintf(count, sizeof(count), "%d", mOtherTime); /*Flawfinder: ignore*/ mCleanOtherObjectsTime->setText(count); BOOL can_return_owned = LLViewerParcelMgr::isParcelModifiableByAgent(parcel, GP_LAND_RETURN_GROUP_OWNED); @@ -1425,7 +1406,7 @@ void send_return_objects_message(S32 parcel_local_id, S32 return_type, void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata) { LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata; - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = lop->mParcel->getParcel(); if (0 == option) { if (parcel) @@ -1438,8 +1419,8 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata) } else { - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getName(owner_id, first, last); args["[FIRST]"] = first; args["[LAST]"] = last; @@ -1450,7 +1431,7 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata) } gSelectMgr->unhighlightAll(); - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); lop->refresh(); } @@ -1458,12 +1439,12 @@ void LLPanelLandObjects::callbackReturnOwnerObjects(S32 option, void* userdata) void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata) { LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata; - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = lop->mParcel->getParcel(); if (0 == option) { if (parcel) { - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getGroupName(parcel->getGroupID(), group_name); LLString::format_map_t args; args["[GROUPNAME]"] = group_name; @@ -1472,7 +1453,7 @@ void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata) } } gSelectMgr->unhighlightAll(); - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); lop->refresh(); } @@ -1480,7 +1461,7 @@ void LLPanelLandObjects::callbackReturnGroupObjects(S32 option, void* userdata) void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata) { LLPanelLandObjects *lop = (LLPanelLandObjects *)userdata; - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = lop->mParcel->getParcel(); if (0 == option) { if (parcel) @@ -1490,7 +1471,7 @@ void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata) } } gSelectMgr->unhighlightAll(); - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); lop->refresh(); } @@ -1498,7 +1479,7 @@ void LLPanelLandObjects::callbackReturnOtherObjects(S32 option, void* userdata) void LLPanelLandObjects::callbackReturnOwnerList(S32 option, void* userdata) { LLPanelLandObjects *self = (LLPanelLandObjects *)userdata; - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = self->mParcel->getParcel(); if (0 == option) { if (parcel) @@ -1525,7 +1506,7 @@ void LLPanelLandObjects::callbackReturnOwnerList(S32 option, void* userdata) } } gSelectMgr->unhighlightAll(); - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); self->refresh(); } @@ -1543,7 +1524,7 @@ void LLPanelLandObjects::onClickReturnOwnerList(void* userdata) gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLParcel* parcelp = gParcelMgr->getSelectedParcel(); + LLParcel* parcelp = self->mParcel->getParcel(); if (!parcelp) return; // Make sure we have something selected. @@ -1577,7 +1558,7 @@ void LLPanelLandObjects::onClickRefresh(void* userdata) LLMessageSystem *msg = gMessageSystem; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) return; LLViewerRegion* region = gParcelMgr->getSelectionRegion(); @@ -1614,7 +1595,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo BOOL is_group_owned; S32 object_count; BOOL is_online; - char object_count_str[MAX_STRING]; + char object_count_str[MAX_STRING]; /*Flawfinder: ignore*/ //BOOL b_need_refresh = FALSE; // If we were waiting for the first reply, clear the "Searching..." text. @@ -1655,7 +1636,7 @@ void LLPanelLandObjects::processParcelObjectOwnersReply(LLMessageSystem *msg, vo // Placeholder for name. row->addColumn("", FONT, self->mColWidth[2]); - sprintf(object_count_str, "%d", object_count); + snprintf(object_count_str, sizeof(object_count_str), "%d", object_count); /*Flawfinder: ignore*/ row->addColumn(object_count_str, FONT, self->mColWidth[3]); if (is_group_owned) @@ -1730,7 +1711,7 @@ void LLPanelLandObjects::onCommitList(LLUICtrl* ctrl, void* data) self->mBtnReturnOwnerList->setEnabled(TRUE); // Highlight this user's objects - clickShowCore(RT_LIST, &(self->mSelectedOwners)); + clickShowCore(self, RT_LIST, &(self->mSelectedOwners)); } } @@ -1757,30 +1738,30 @@ void LLPanelLandObjects::onClickName(void* userdata) } // static -void LLPanelLandObjects::clickShowCore(S32 return_type, uuid_list_t* list) +void LLPanelLandObjects::clickShowCore(LLPanelLandObjects* self, S32 return_type, uuid_list_t* list) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) return; send_parcel_select_objects(parcel->getLocalID(), return_type, list); } // static -void LLPanelLandObjects::onClickShowOwnerObjects(void*) +void LLPanelLandObjects::onClickShowOwnerObjects(void* userdata) { - clickShowCore(RT_OWNER); + clickShowCore((LLPanelLandObjects*)userdata, RT_OWNER); } // static -void LLPanelLandObjects::onClickShowGroupObjects(void*) +void LLPanelLandObjects::onClickShowGroupObjects(void* userdata) { - clickShowCore(RT_GROUP); + clickShowCore((LLPanelLandObjects*)userdata, (RT_GROUP)); } // static -void LLPanelLandObjects::onClickShowOtherObjects(void*) +void LLPanelLandObjects::onClickShowOtherObjects(void* userdata) { - clickShowCore(RT_OTHER); + clickShowCore((LLPanelLandObjects*)userdata, RT_OTHER); } // static @@ -1794,7 +1775,8 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; + LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; send_parcel_select_objects(parcel->getLocalID(), RT_OWNER); @@ -1810,8 +1792,8 @@ void LLPanelLandObjects::onClickReturnOwnerObjects(void* userdata) } else { - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getName(owner_id, first, last); std::string name = first; name += " "; @@ -1832,12 +1814,13 @@ void LLPanelLandObjects::onClickReturnGroupObjects(void* userdata) gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; + LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; send_parcel_select_objects(parcel->getLocalID(), RT_GROUP); - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getGroupName(parcel->getGroupID(), group_name); LLStringBase::format_map_t args; @@ -1859,7 +1842,8 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) gParcelMgr->getPrimInfo(sw_max, sw_total, max, total, owned, group, other, selected, parcel_object_bonus, other_time); - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLPanelLandObjects* panelp = (LLPanelLandObjects*)userdata; + LLParcel* parcel = panelp->mParcel->getParcel(); if (!parcel) return; send_parcel_select_objects(parcel->getLocalID(), RT_OTHER); @@ -1869,7 +1853,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) if (parcel->getIsGroupOwned()) { - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getGroupName(parcel->getGroupID(), group_name); args["[NAME]"] = group_name; @@ -1885,8 +1869,8 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) } else { - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getName(owner_id, first, last); std::string name; name += first; @@ -1903,7 +1887,7 @@ void LLPanelLandObjects::onClickReturnOtherObjects(void* userdata) void LLPanelLandObjects::onLostFocus(LLLineEditor *caller, void* user_data) { LLPanelLandObjects *lop = (LLPanelLandObjects *)user_data; - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = lop->mParcel->getParcel(); if (parcel) { lop->mOtherTime = atoi(lop->mCleanOtherObjectsTime->getText().c_str()); @@ -1918,7 +1902,7 @@ void LLPanelLandObjects::onLostFocus(LLLineEditor *caller, void* user_data) // LLPanelLandOptions //--------------------------------------------------------------------------- -LLPanelLandOptions::LLPanelLandOptions() +LLPanelLandOptions::LLPanelLandOptions(LLParcelSelectionHandle& parcel) : LLPanel("land_options_panel"), mCheckEditObjects(NULL), mCheckEditGroupObjects(NULL), @@ -1940,7 +1924,8 @@ LLPanelLandOptions::LLPanelLandOptions() mAllowPublishCtrl(NULL), mMatureCtrl(NULL), mPushRestrictionCtrl(NULL), - mPublishHelpButton(NULL) + mPublishHelpButton(NULL), + mParcel(parcel) { } @@ -2073,7 +2058,7 @@ LLPanelLandOptions::~LLPanelLandOptions() // public void LLPanelLandOptions::refresh() { - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); if (!parcel) { @@ -2208,8 +2193,8 @@ void LLPanelLandOptions::refresh() } else { - char buffer[256]; - sprintf(buffer, "Landing Point: %d, %d, %d", + char buffer[256]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "Landing Point: %d, %d, %d", /*Flawfinder: ignore*/ llround(pos.mV[VX]), llround(pos.mV[VY]), llround(pos.mV[VZ])); @@ -2244,7 +2229,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) { LLPanelLandOptions *self = (LLPanelLandOptions *)userdata; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) { return; @@ -2298,7 +2283,7 @@ void LLPanelLandOptions::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setSnapshotID(snapshot_id); // Send current parcel data upstream to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! self->refresh(); @@ -2310,7 +2295,7 @@ void LLPanelLandOptions::onClickSet(void* userdata) { LLPanelLandOptions* self = (LLPanelLandOptions*)userdata; - LLParcel* selected_parcel = gParcelMgr->getSelectedParcel(); + LLParcel* selected_parcel = self->mParcel->getParcel(); if (!selected_parcel) return; LLParcel* agent_parcel = gParcelMgr->getAgentParcel(); @@ -2326,7 +2311,7 @@ void LLPanelLandOptions::onClickSet(void* userdata) selected_parcel->setUserLocation(pos_region); selected_parcel->setUserLookAt(gAgent.getFrameAgent().getAtAxis()); - gParcelMgr->sendParcelPropertiesUpdate(selected_parcel, LLFloaterLand::sRequestReplyOnUpdate); + gParcelMgr->sendParcelPropertiesUpdate(selected_parcel); self->refresh(); } @@ -2335,7 +2320,7 @@ void LLPanelLandOptions::onClickClear(void* userdata) { LLPanelLandOptions* self = (LLPanelLandOptions*)userdata; - LLParcel* selected_parcel = gParcelMgr->getSelectedParcel(); + LLParcel* selected_parcel = self->mParcel->getParcel(); if (!selected_parcel) return; // yes, this magic number of 0,0,0 means that it is clear @@ -2343,7 +2328,7 @@ void LLPanelLandOptions::onClickClear(void* userdata) selected_parcel->setUserLocation(zero_vec); selected_parcel->setUserLookAt(zero_vec); - gParcelMgr->sendParcelPropertiesUpdate(selected_parcel, LLFloaterLand::sRequestReplyOnUpdate); + gParcelMgr->sendParcelPropertiesUpdate(selected_parcel); self->refresh(); } @@ -2358,8 +2343,8 @@ void LLPanelLandOptions::onClickPublishHelp(void*) // LLPanelLandMedia //--------------------------------------------------------------------------- -LLPanelLandMedia::LLPanelLandMedia() -: LLPanel("land_media_panel") +LLPanelLandMedia::LLPanelLandMedia(LLParcelSelectionHandle& parcel) +: LLPanel("land_media_panel"), mParcel(parcel) { } @@ -2401,7 +2386,7 @@ LLPanelLandMedia::~LLPanelLandMedia() // public void LLPanelLandMedia::refresh() { - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); if (!parcel) { @@ -2486,7 +2471,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl *ctrl, void *userdata) { LLPanelLandMedia *self = (LLPanelLandMedia *)userdata; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) { return; @@ -2507,7 +2492,7 @@ void LLPanelLandMedia::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setMediaAutoScale ( media_auto_scale ); // Send current parcel data upstream to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! self->refresh(); @@ -2531,8 +2516,8 @@ void LLPanelLandMedia::onClickStartMedia ( void* data ) // LLPanelLandAccess //--------------------------------------------------------------------------- -LLPanelLandAccess::LLPanelLandAccess() -: LLPanel("land_access_panel") +LLPanelLandAccess::LLPanelLandAccess(LLParcelSelectionHandle& parcel) +: LLPanel("land_access_panel"), mParcel(parcel) { } @@ -2574,32 +2559,33 @@ BOOL LLPanelLandAccess::postBuild() LLPanelLandAccess::~LLPanelLandAccess() -{ } +{ +} void LLPanelLandAccess::refresh() { mListAccess->deleteAllItems(); - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); if (parcel) { - char label[256]; + char label[256]; /*Flawfinder: ignore*/ // Display options BOOL use_group = parcel->getParcelFlag(PF_USE_ACCESS_GROUP); mCheckGroup->set( use_group ); - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /*Flawfinder: ignore*/ gCacheName->getGroupName(parcel->getGroupID(), group_name); - sprintf(label, "Group: %s", group_name); + snprintf(label, sizeof(label), "Group: %s", group_name); /*Flawfinder: ignore*/ mCheckGroup->setLabel( label ); S32 count = parcel->mAccessList.size(); BOOL use_list = parcel->getParcelFlag(PF_USE_ACCESS_LIST); mCheckAccess->set( use_list ); - sprintf(label, "Avatars: (%d listed, %d max)", + snprintf(label, sizeof(label), "Avatars: (%d listed, %d max)", /*Flawfinder: ignore*/ count, PARCEL_MAX_ACCESS_LIST); mCheckAccess->setLabel( label ); @@ -2618,8 +2604,8 @@ void LLPanelLandAccess::refresh() suffix.assign(" ("); if (seconds >= 120) { - char buf[30]; - sprintf(buf, "%d minutes", (seconds/60)); + char buf[30]; /*Flawfinder: ignore*/ + snprintf(buf, sizeof(buf), "%d minutes", (seconds/60)); /*Flawfinder: ignore*/ suffix.append(buf); } else if (seconds >= 60) @@ -2628,8 +2614,8 @@ void LLPanelLandAccess::refresh() } else { - char buf[30]; - sprintf(buf, "%d seconds", seconds); + char buf[30]; /*Flawfinder: ignore*/ + snprintf(buf, sizeof(buf), "%d seconds", seconds); /*Flawfinder: ignore*/ suffix.append(buf); } suffix.append(" remaining)"); @@ -2686,15 +2672,15 @@ void LLPanelLandAccess::refresh() // public void LLPanelLandAccess::refreshNames() { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); - char group_name[DB_GROUP_NAME_BUF_SIZE]; + LLParcel* parcel = mParcel->getParcel(); + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ group_name[0] = '\0'; if(parcel) { gCacheName->getGroupName(parcel->getGroupID(), group_name); } - char label[MAX_STRING]; - snprintf(label, MAX_STRING, "Group: %s", group_name); + char label[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(label, sizeof(label), "Group: %s", group_name); /*Flawfinder: ignore*/ mCheckGroup->setLabel(label); } @@ -2717,7 +2703,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) { LLPanelLandAccess *self = (LLPanelLandAccess *)userdata; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) { return; @@ -2750,7 +2736,7 @@ void LLPanelLandAccess::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setPassHours( pass_hours ); // Send current parcel data upstream to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! self->refresh(); @@ -2774,7 +2760,7 @@ void LLPanelLandAccess::callbackAvatarID(const std::vector& names, void LLPanelLandAccess::addAvatar(LLUUID id) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; parcel->addToAccessList(id, 0); @@ -2794,7 +2780,7 @@ void LLPanelLandAccess::onClickRemove(void* data) LLScrollListItem* item = self->mListAccess->getFirstSelected(); if (!item) return; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) return; const LLUUID& agent_id = item->getUUID(); @@ -2811,8 +2797,8 @@ void LLPanelLandAccess::onClickRemove(void* data) //--------------------------------------------------------------------------- // LLPanelLandBan //--------------------------------------------------------------------------- -LLPanelLandBan::LLPanelLandBan() -: LLPanel("land_ban_panel") +LLPanelLandBan::LLPanelLandBan(LLParcelSelectionHandle& parcel) +: LLPanel("land_ban_panel"), mParcel(parcel) { } @@ -2856,11 +2842,11 @@ void LLPanelLandBan::refresh() { mList->deleteAllItems(); - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = mParcel->getParcel(); if (parcel) { - char label[256]; + char label[256]; /*Flawfinder: ignore*/ // Display options @@ -2869,7 +2855,7 @@ void LLPanelLandBan::refresh() BOOL use_ban = parcel->getParcelFlag(PF_USE_BAN_LIST); mCheck->set( use_ban ); - sprintf(label, "Ban these avatars: (%d listed, %d max)", + snprintf(label, sizeof(label), "Ban these avatars: (%d listed, %d max)", /*Flawfinder: ignore*/ count, PARCEL_MAX_ACCESS_LIST); mCheck->setLabel( label ); @@ -2887,8 +2873,8 @@ void LLPanelLandBan::refresh() suffix.assign(" ("); if (seconds >= 120) { - char buf[30]; - sprintf(buf, "%d minutes", (seconds/60)); + char buf[30]; /*Flawfinder: ignore*/ + snprintf(buf, sizeof(buf), "%d minutes", (seconds/60)); /*Flawfinder: ignore*/ suffix.append(buf); } else if (seconds >= 60) @@ -2897,8 +2883,8 @@ void LLPanelLandBan::refresh() } else { - char buf[30]; - sprintf(buf, "%d seconds", seconds); + char buf[30]; /*Flawfinder: ignore*/ + snprintf(buf, sizeof(buf), "%d seconds", seconds); /*Flawfinder: ignore*/ suffix.append(buf); } suffix.append(" remaining)"); @@ -2968,7 +2954,7 @@ void LLPanelLandBan::onCommitAny(LLUICtrl *ctrl, void *userdata) { LLPanelLandBan *self = (LLPanelLandBan*)userdata; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) { return; @@ -2987,7 +2973,7 @@ void LLPanelLandBan::onCommitAny(LLUICtrl *ctrl, void *userdata) parcel->setParcelFlag(PF_DENY_TRANSACTED, deny_access_transacted); // Send current parcel data upstream to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); // Might have changed properties, so let's redraw! self->refresh(); @@ -3011,7 +2997,7 @@ void LLPanelLandBan::callbackAvatarID(const std::vector& names, con void LLPanelLandBan::addAvatar(LLUUID id) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = mParcel->getParcel(); if (!parcel) return; parcel->addToBanList(id, 0); @@ -3031,7 +3017,7 @@ void LLPanelLandBan::onClickRemove(void* data) LLScrollListItem* item = self->mList->getFirstSelected(); if (!item) return; - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = self->mParcel->getParcel(); if (!parcel) return; const LLUUID& agent_id = item->getUUID(); @@ -3046,8 +3032,8 @@ void LLPanelLandBan::onClickRemove(void* data) //--------------------------------------------------------------------------- // LLPanelLandRenters //--------------------------------------------------------------------------- -LLPanelLandRenters::LLPanelLandRenters() -: LLPanel("landrenters", LLRect(0,500,500,0)) +LLPanelLandRenters::LLPanelLandRenters(LLParcelSelectionHandle& parcel) +: LLPanel("landrenters", LLRect(0,500,500,0)), mParcel(parcel) { const S32 BTN_WIDTH = 64; @@ -3122,8 +3108,8 @@ void LLPanelLandRenters::onClickRemove(void*) //--------------------------------------------------------------------------- // LLPanelLandCovenant //--------------------------------------------------------------------------- -LLPanelLandCovenant::LLPanelLandCovenant() -: LLPanel("land_covenant_panel") +LLPanelLandCovenant::LLPanelLandCovenant(LLParcelSelectionHandle& parcel) +: LLPanel("land_covenant_panel"), mParcel(parcel) { } diff --git a/linden/indra/newview/llfloaterland.h b/linden/indra/newview/llfloaterland.h index ba92c96..4301306 100644 --- a/linden/indra/newview/llfloaterland.h +++ b/linden/indra/newview/llfloaterland.h @@ -50,6 +50,7 @@ class LLParcelSelectionObserver; class LLTabContainer; class LLTextureCtrl; class LLViewerTextEditor; +class LLParcelSelection; class LLPanelLandGeneral; class LLPanelLandObjects; @@ -73,9 +74,6 @@ public: static LLPanelLandObjects* getCurrentPanelLandObjects(); static LLPanelLandCovenant* getCurrentPanelLandCovenant(); - // Returns TRUE, but does some early prep work for closing the window. - virtual BOOL canClose(); - // Destroys itself on close. virtual void onClose(bool app_quitting); @@ -112,6 +110,8 @@ protected: LLPanelLandCovenant* mPanelCovenant; LLPanelLandRenters* mPanelRenters; + LLHandle mParcel; + public: // When closing the dialog, we want to deselect the land. But when // we send an update to the simulator, it usually replies with the @@ -125,7 +125,7 @@ class LLPanelLandGeneral : public LLPanel { public: - LLPanelLandGeneral(); + LLPanelLandGeneral(LLHandle& parcelp); virtual ~LLPanelLandGeneral(); void refresh(); void refreshNames(); @@ -217,6 +217,8 @@ protected: LLButton* mBtnBuyPass; LLButton* mBtnStartAuction; + LLHandle& mParcel; + static LLViewHandle sBuyPassDialogHandle; }; @@ -224,7 +226,7 @@ class LLPanelLandObjects : public LLPanel { public: - LLPanelLandObjects(); + LLPanelLandObjects(LLHandle& parcelp); virtual ~LLPanelLandObjects(); void refresh(); virtual void draw(); @@ -234,7 +236,7 @@ public: static void callbackReturnOtherObjects(S32, void*); static void callbackReturnOwnerList(S32, void*); - static void clickShowCore(S32 return_type, uuid_list_t* list = 0); + static void clickShowCore(LLPanelLandObjects* panelp, S32 return_type, uuid_list_t* list = 0); static void onClickShowOwnerObjects(void*); static void onClickShowGroupObjects(void*); static void onClickShowOtherObjects(void*); @@ -314,6 +316,8 @@ protected: LLString mSelectedName; S32 mSelectedCount; BOOL mSelectedIsGroup; + + LLHandle& mParcel; }; @@ -321,7 +325,7 @@ class LLPanelLandOptions : public LLPanel { public: - LLPanelLandOptions(); + LLPanelLandOptions(LLHandle& parcelp); virtual ~LLPanelLandOptions(); void refresh(); @@ -359,6 +363,8 @@ protected: LLCheckBoxCtrl *mMatureCtrl; LLCheckBoxCtrl *mPushRestrictionCtrl; LLButton *mPublishHelpButton; + + LLHandle& mParcel; }; @@ -366,7 +372,7 @@ class LLPanelLandMedia : public LLPanel { public: - LLPanelLandMedia(); + LLPanelLandMedia(LLHandle& parcelp); virtual ~LLPanelLandMedia(); void refresh(); @@ -384,6 +390,8 @@ protected: LLCheckBoxCtrl* mMediaAutoScaleCheck; //LLButton* mMediaStopButton; //LLButton* mMediaStartButton; + + LLHandle& mParcel; }; @@ -392,7 +400,7 @@ class LLPanelLandAccess : public LLPanel { public: - LLPanelLandAccess(); + LLPanelLandAccess(LLHandle& parcelp); virtual ~LLPanelLandAccess(); void refresh(); void refreshNames(); @@ -426,6 +434,7 @@ protected: LLCheckBoxCtrl* mCheckTransacted; LLRadioGroup* mCheckStatusLevel; + LLHandle& mParcel; }; @@ -433,7 +442,7 @@ class LLPanelLandBan : public LLPanel { public: - LLPanelLandBan(); + LLPanelLandBan(LLHandle& parcelp); virtual ~LLPanelLandBan(); void refresh(); @@ -456,6 +465,8 @@ protected: LLCheckBoxCtrl* mCheckDenyAnonymous; LLCheckBoxCtrl* mCheckDenyIdentified; LLCheckBoxCtrl* mCheckDenyTransacted; + + LLHandle& mParcel; }; @@ -463,7 +474,7 @@ class LLPanelLandRenters : public LLPanel { public: - LLPanelLandRenters(); + LLPanelLandRenters(LLHandle& parcelp); virtual ~LLPanelLandRenters(); void refresh(); @@ -475,13 +486,15 @@ protected: LLNameListCtrl* mListRenters; LLButton* mBtnAddRenter; LLButton* mBtnRemoveRenter; + + LLHandle& mParcel; }; class LLPanelLandCovenant : public LLPanel { public: - LLPanelLandCovenant(); + LLPanelLandCovenant(LLHandle& parcelp); virtual ~LLPanelLandCovenant(); virtual BOOL postBuild(); void refresh(); @@ -489,6 +502,9 @@ public: static void updateEstateName(const std::string& name); static void updateLastModified(const std::string& text); static void updateEstateOwnerName(const std::string& name); + +protected: + LLHandle& mParcel; }; #endif diff --git a/linden/indra/newview/llfloaterlandholdings.cpp b/linden/indra/newview/llfloaterlandholdings.cpp index c9569d0..e34e84c 100644 --- a/linden/indra/newview/llfloaterlandholdings.cpp +++ b/linden/indra/newview/llfloaterlandholdings.cpp @@ -72,7 +72,7 @@ void LLFloaterLandHoldings::show(void*) ""); // TODO: request updated money balance? - floater->open(); + floater->open(); /* Flawfinder: ignore */ } @@ -177,14 +177,14 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**) } LLUUID owner_id; - char name[MAX_STRING]; - char desc[MAX_STRING]; + char name[MAX_STRING]; /* Flawfinder: ignore */ + char desc[MAX_STRING]; /* Flawfinder: ignore */ S32 actual_area; S32 billable_area; U8 flags; F32 global_x; F32 global_y; - char sim_name[MAX_STRING]; + char sim_name[MAX_STRING]; /* Flawfinder: ignore */ S32 i; S32 count = msg->getNumberOfBlocks("QueryData"); @@ -206,21 +206,21 @@ void LLFloaterLandHoldings::processPlacesReply(LLMessageSystem* msg, void**) S32 region_x = llround(global_x) % REGION_WIDTH_UNITS; S32 region_y = llround(global_y) % REGION_WIDTH_UNITS; - char location[MAX_STRING]; - sprintf(location, "%s (%d, %d)", sim_name, region_x, region_y); + char location[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(location, MAX_STRING, "%s (%d, %d)", sim_name, region_x, region_y); /* Flawfinder: ignore */ - char area[MAX_STRING]; + char area[MAX_STRING]; /* Flawfinder: ignore */ if(billable_area == actual_area) { - sprintf(area, "%d", billable_area); + snprintf(area, MAX_STRING, "%d", billable_area); /* Flawfinder: ignore */ } else { - sprintf(area, "%d / %d", billable_area, actual_area); + snprintf(area, MAX_STRING, "%d / %d", billable_area, actual_area); /* Flawfinder: ignore */ } - char hidden[MAX_STRING]; - sprintf(hidden, "%f %f", global_x, global_y); + char hidden[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(hidden, MAX_STRING, "%f %f", global_x, global_y); /* Flawfinder: ignore */ LLSD element; element["columns"][0]["column"] = "name"; @@ -311,14 +311,14 @@ void LLFloaterLandHoldings::refreshAggregates() S32 current_area = gStatusBar->getSquareMetersCommitted(); S32 available_area = gStatusBar->getSquareMetersLeft(); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ - sprintf(buffer, "%d sq. meters", allowed_area); + snprintf(buffer, MAX_STRING, "%d sq. meters", allowed_area); /* Flawfinder: ignore */ childSetValue("allowed_text", LLSD(buffer)); - sprintf(buffer, "%d sq. meters", current_area); + snprintf(buffer, MAX_STRING, "%d sq. meters", current_area); /* Flawfinder: ignore */ childSetValue("current_text", LLSD(buffer)); - sprintf(buffer, "%d sq. meters", available_area); + snprintf(buffer, MAX_STRING, "%d sq. meters", available_area); /* Flawfinder: ignore */ childSetValue("available_text", LLSD(buffer)); } diff --git a/linden/indra/newview/llfloatermap.cpp b/linden/indra/newview/llfloatermap.cpp index 29c4f08..2d549db 100644 --- a/linden/indra/newview/llfloatermap.cpp +++ b/linden/indra/newview/llfloatermap.cpp @@ -212,7 +212,7 @@ void LLFloaterMap::toggle(void*) } else { - gFloaterMap->open(); + gFloaterMap->open(); /* Flawfinder: ignore */ } } } diff --git a/linden/indra/newview/llfloatermute.cpp b/linden/indra/newview/llfloatermute.cpp index a78a616..f71b58f 100644 --- a/linden/indra/newview/llfloatermute.cpp +++ b/linden/indra/newview/llfloatermute.cpp @@ -106,7 +106,7 @@ LLFloaterMute::~LLFloaterMute() void LLFloaterMute::show() { // Make sure we make a noise. - open(); + open(); /* Flawfinder: ignore */ } //----------------------------------------------------------------------------- diff --git a/linden/indra/newview/llfloaternamedesc.cpp b/linden/indra/newview/llfloaternamedesc.cpp index 8d84f94..b39a2eb 100644 --- a/linden/indra/newview/llfloaternamedesc.cpp +++ b/linden/indra/newview/llfloaternamedesc.cpp @@ -83,7 +83,7 @@ BOOL LLFloaterNameDesc::postBuild() char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists if( !end_p ) { - end_p = asset_name_str + strlen( asset_name_str ); + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ } else if( !stricmp( end_p, ".wav") ) diff --git a/linden/indra/newview/llfloaternewim.cpp b/linden/indra/newview/llfloaternewim.cpp index 3199eef..4288209 100644 --- a/linden/indra/newview/llfloaternewim.cpp +++ b/linden/indra/newview/llfloaternewim.cpp @@ -117,9 +117,9 @@ void LLFloaterNewIM::addTarget(const LLUUID& uuid, const std::string& name, void LLFloaterNewIM::addAgent(const LLUUID& uuid, void* data, BOOL online) { LLScrollListItem* item = new LLScrollListItem(TRUE, data, uuid); - char first[DB_FIRST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ first[0] = '\0'; - char last[DB_LAST_NAME_BUF_SIZE]; + char last[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ last[0] = '\0'; gCacheName->getName(uuid, first, last); LLUIString fullname = sNameFormat; @@ -228,7 +228,6 @@ void LLFloaterNewIM::close(bool app_quitting) } else { - // this shouldn't be called, because we are always hosted LLFloater::close(app_quitting); } } diff --git a/linden/indra/newview/llfloateropenobject.cpp b/linden/indra/newview/llfloateropenobject.cpp index 1f0cd5d..22b4292 100644 --- a/linden/indra/newview/llfloateropenobject.cpp +++ b/linden/indra/newview/llfloateropenobject.cpp @@ -68,7 +68,6 @@ LLFloaterOpenObject::LLFloaterOpenObject() LLFloaterOpenObject::~LLFloaterOpenObject() { - gSelectMgr->deselectAll(); sInstance = NULL; } @@ -76,7 +75,7 @@ void LLFloaterOpenObject::refresh() { mPanelInventory->refresh(); - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = mObjectSelection->getFirstRootNode(); if (node) { std::string name = node->mName; @@ -103,7 +102,8 @@ void LLFloaterOpenObject::dirty() // static void LLFloaterOpenObject::show() { - if (gSelectMgr->getRootObjectCount() != 1) + LLObjectSelectionHandle object_selection = gSelectMgr->getSelection(); + if (object_selection->getRootObjectCount() != 1) { gViewerWindow->alertXml("UnableToViewContentsMoreThanOne"); return; @@ -116,21 +116,22 @@ void LLFloaterOpenObject::show() sInstance->center(); } - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ sInstance->setFocus(TRUE); + + sInstance->mObjectSelection = gSelectMgr->getEditSelection(); } -// static void LLFloaterOpenObject::moveToInventory(bool wear) { - if (gSelectMgr->getRootObjectCount() != 1) + if (mObjectSelection->getRootObjectCount() != 1) { gViewerWindow->alertXml("OnlyCopyContentsOfSingleItem"); return; } - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = mObjectSelection->getFirstRootNode(); if (!node) return; LLViewerObject* object = node->getObject(); if (!object) return; @@ -194,7 +195,7 @@ void LLFloaterOpenObject::callbackMoveInventory(S32 result, void* data) void LLFloaterOpenObject::onClickMoveToInventory(void* data) { LLFloaterOpenObject* self = (LLFloaterOpenObject*)data; - moveToInventory(false); + self->moveToInventory(false); self->close(); } @@ -202,7 +203,7 @@ void LLFloaterOpenObject::onClickMoveToInventory(void* data) void LLFloaterOpenObject::onClickMoveAndWear(void* data) { LLFloaterOpenObject* self = (LLFloaterOpenObject*)data; - moveToInventory(true); + self->moveToInventory(true); self->close(); } diff --git a/linden/indra/newview/llfloateropenobject.h b/linden/indra/newview/llfloateropenobject.h index aae3876..4772982 100644 --- a/linden/indra/newview/llfloateropenobject.h +++ b/linden/indra/newview/llfloateropenobject.h @@ -35,8 +35,7 @@ #include "llfloater.h" - - +class LLObjectSelection; class LLPanelInventory; class LLFloaterOpenObject @@ -59,9 +58,10 @@ protected: void refresh(); void draw(); + void moveToInventory(bool wear); + static void onClickMoveToInventory(void* data); static void onClickMoveAndWear(void* data); - static void moveToInventory(bool wear); static void callbackMoveInventory(S32 result, void* data); static void* createPanelInventory(void* data); @@ -69,6 +69,7 @@ protected: static LLFloaterOpenObject* sInstance; LLPanelInventory* mPanelInventory; + LLHandle mObjectSelection; BOOL mDirty; }; diff --git a/linden/indra/newview/llfloaterpermissionsmgr.cpp b/linden/indra/newview/llfloaterpermissionsmgr.cpp index 05945d9..1c13cf2 100644 --- a/linden/indra/newview/llfloaterpermissionsmgr.cpp +++ b/linden/indra/newview/llfloaterpermissionsmgr.cpp @@ -53,12 +53,12 @@ LLFloaterPermissionsMgr* LLFloaterPermissionsMgr::show() { sInstance = new LLFloaterPermissionsMgr(); - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ gFloaterView->adjustToFitScreen(sInstance, TRUE); } else { - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ } return sInstance; diff --git a/linden/indra/newview/llfloaterpostcard.cpp b/linden/indra/newview/llfloaterpostcard.cpp index d6c66e3..036ce38 100644 --- a/linden/indra/newview/llfloaterpostcard.cpp +++ b/linden/indra/newview/llfloaterpostcard.cpp @@ -58,6 +58,8 @@ #include "llvfs.h" #include "viewer.h" +#include "llassetuploadresponders.h" + ///---------------------------------------------------------------------------- /// Local function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- @@ -70,8 +72,8 @@ LLLinkedList LLFloaterPostcard::sInstances; LLFloaterPostcard::LLFloaterPostcard(LLImageJPEG* jpeg, LLImageGL *img, const LLVector2& img_scale, const LLVector3d& pos_taken_global) : LLFloater("Postcard Floater"), - mViewerImage(img), mJPEGImage(jpeg), + mViewerImage(img), mImageScale(img_scale), mPosTakenGlobal(pos_taken_global) { @@ -157,7 +159,7 @@ LLFloaterPostcard* LLFloaterPostcard::showFromSnapshot(LLImageJPEG *jpeg, LLImag gFloaterView->getNewFloaterPosition(&left, &top); instance->setOrigin(left, top - instance->getRect().getHeight()); - instance->open(); + instance->open(); /*Flawfinder: ignore*/ return instance; } @@ -225,6 +227,23 @@ void LLFloaterPostcard::onClickCancel(void* data) } } +class LLSendPostcardResponder : public LLAssetUploadResponder +{ +public: + LLSendPostcardResponder(const LLSD &post_data, + const LLUUID& vfile_id, + LLAssetType::EType asset_type): + LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + } + // *TODO define custom uploadFailed here so it's not such a generic message + void LLSendPostcardResponder::uploadComplete(const LLSD& content) + { + // we don't care about what the server returns from this post, just clean up the UI + LLUploadDialog::modalUploadFinished(); + } +}; + // static void LLFloaterPostcard::onClickSend(void* data) { @@ -249,12 +268,31 @@ void LLFloaterPostcard::onClickSend(void* data) if (self->mJPEGImage.notNull()) { - // upload the image self->mTransactionID.generate(); self->mAssetID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID()); LLVFile::writeFile(self->mJPEGImage->getData(), self->mJPEGImage->getDataSize(), gVFS, self->mAssetID, LLAssetType::AT_IMAGE_JPEG); - - gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)self, FALSE); + + // upload the image + std::string url = gAgent.getRegion()->getCapability("SendPostcard"); + if(!url.empty()) + { + llinfos << "Send Postcard via capability" << llendl; + LLSD body = LLSD::emptyMap(); + // the capability already encodes: agent ID, region ID + body["pos-global"] = self->mPosTakenGlobal.getValue(); + body["to"] = self->childGetValue("to_form").asString(); + body["from"] = self->childGetValue("from_form").asString(); + body["name"] = self->childGetValue("name_form").asString(); + body["subject"] = self->childGetValue("subject_form").asString(); + body["msg"] = self->childGetValue("msg_form").asString(); + body["allow-publish"] = self->childGetValue("allow_publish_check").asBoolean(); + body["mature-publish"] = self->childGetValue("mature_check").asBoolean(); + LLHTTPClient::post(url, body, new LLSendPostcardResponder(body, self->mAssetID, LLAssetType::AT_IMAGE_JPEG)); + } + else + { + gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_JPEG, &uploadCallback, (void *)self, FALSE); + } LLUploadDialog::modalUploadDialog("Uploading...\n\nPostcard"); diff --git a/linden/indra/newview/llfloaterpreference.cpp b/linden/indra/newview/llfloaterpreference.cpp index 5dbfc78..ad1990e 100644 --- a/linden/indra/newview/llfloaterpreference.cpp +++ b/linden/indra/newview/llfloaterpreference.cpp @@ -283,7 +283,7 @@ void LLFloaterPreference::show(void*) sInstance->center(); } - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ if(!gAgent.getID().isNull()) { diff --git a/linden/indra/newview/llfloaterproperties.cpp b/linden/indra/newview/llfloaterproperties.cpp index 8be2ce5..0beea67 100644 --- a/linden/indra/newview/llfloaterproperties.cpp +++ b/linden/indra/newview/llfloaterproperties.cpp @@ -126,7 +126,7 @@ LLFloaterProperties* LLFloaterProperties::show(const LLUUID& item_id, } instance->refresh(); - instance->open(); + instance->open(); /* Flawfinder: ignore */ } return instance; } @@ -233,7 +233,7 @@ void LLFloaterProperties::refresh() "RadioSaleType", "EditPrice" }; - for(int t=0;tgetName().empty()) { @@ -318,8 +318,8 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) ////////////////// // CREATOR NAME // ////////////////// - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_LAST_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char last_name[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ if(!gCacheName) return; if(!gAgent.getRegion()) return; @@ -351,7 +351,7 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) LLString name; if (perm.isGroupOwned()) { - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /* Flawfinder: ignore */ gCacheName->getGroupName(perm.getGroup(), group_name); name.assign(group_name); } @@ -432,29 +432,29 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) overwrite_group = flags & LLInventoryItem::II_FLAGS_OBJECT_PERM_OVERWRITE_GROUP; } - char perm_string[11]; + char perm_string[11]; /* Flawfinder: ignore */ - sprintf(perm_string, "B: "); + snprintf(perm_string, sizeof(perm_string), "B: "); /* Flawfinder: ignore */ mask_to_string(base_mask, perm_string+3); childSetText("BaseMaskDebug",perm_string); childSetVisible("BaseMaskDebug",TRUE); - sprintf(perm_string, "O: "); + snprintf(perm_string, sizeof(perm_string), "O: "); /* Flawfinder: ignore */ mask_to_string(owner_mask, perm_string+3); childSetText("OwnerMaskDebug",perm_string); childSetVisible("OwnerMaskDebug",TRUE); - sprintf(perm_string, "G%s: ", overwrite_group ? "*" : ""); + snprintf(perm_string, sizeof(perm_string), "G%s: ", overwrite_group ? "*" : ""); /* Flawfinder: ignore */ mask_to_string(group_mask, perm_string + (overwrite_group ? 4 : 3)); childSetText("GroupMaskDebug",perm_string); childSetVisible("GroupMaskDebug",TRUE); - sprintf(perm_string, "E%s: ", overwrite_everyone ? "*" : ""); + snprintf(perm_string, sizeof(perm_string), "E%s: ", overwrite_everyone ? "*" : ""); /* Flawfinder: ignore */ mask_to_string(everyone_mask, perm_string + (overwrite_everyone ? 4 : 3)); childSetText("EveryoneMaskDebug",perm_string); childSetVisible("EveryoneMaskDebug",TRUE); - sprintf(perm_string, "N%s: ", slam_perm ? "*" : ""); + snprintf(perm_string, sizeof(perm_string), "N%s: ", slam_perm ? "*" : ""); /* Flawfinder: ignore */ mask_to_string(next_owner_mask, perm_string + (slam_perm ? 4 : 3)); childSetText("NextMaskDebug",perm_string); childSetVisible("NextMaskDebug",TRUE); @@ -567,8 +567,8 @@ void LLFloaterProperties::refreshFromItem(LLInventoryItem* item) if (is_for_sale) { radioSaleType->setSelectedIndex((S32)sale_info.getSaleType() - 1); - char numerical_price[MAX_STRING]; - sprintf(numerical_price, "%d", sale_info.getSalePrice()); + char numerical_price[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(numerical_price, MAX_STRING, "%d", sale_info.getSalePrice()); /* Flawfinder: ignore */ childSetText("EditPrice",numerical_price); } else diff --git a/linden/indra/newview/llfloaterrate.cpp b/linden/indra/newview/llfloaterrate.cpp index 128d1e6..a057374 100644 --- a/linden/indra/newview/llfloaterrate.cpp +++ b/linden/indra/newview/llfloaterrate.cpp @@ -68,6 +68,8 @@ LLFloaterRate::LLFloaterRate(const std::string& name, const LLUUID &id) childSetAction("OK", onClickOK, this); childSetAction("Cancel", onClickCancel, this); + + mObjectSelection = gSelectMgr->getEditSelection(); } @@ -82,8 +84,8 @@ void LLFloaterRate::draw() LLString name; // Construct the name, if possible - char firstname[MAX_STRING]; - char lastname[MAX_STRING]; + char firstname[MAX_STRING]; /* Flawfinder: ignore */ + char lastname[MAX_STRING]; /* Flawfinder: ignore */ gCacheName->getName(mAvatarID, firstname, lastname); name.assign(firstname); name.append(" "); @@ -127,7 +129,7 @@ void LLFloaterRate::show(const LLUUID &avatar_id) if (iter != sInstanceMap.end()) { iter->second->setFocus(TRUE); - iter->second->open(); + iter->second->open(); /* Flawfinder: ignore */ } else if (avatar_id != LLUUID::null) { @@ -136,7 +138,7 @@ void LLFloaterRate::show(const LLUUID &avatar_id) f->center(); f->setFocus(TRUE); f->sendReputationIndividualRequest(avatar_id); - f->open(); + f->open(); /* Flawfinder: ignore */ } } @@ -166,10 +168,6 @@ void LLFloaterRate::show(ERateSelection which) { gViewerWindow->alertXml("SelectSingleRate"); } - - - // Clean up selection - gSelectMgr->deselectTransient(); } diff --git a/linden/indra/newview/llfloaterrate.h b/linden/indra/newview/llfloaterrate.h index 591fb96..1b24383 100644 --- a/linden/indra/newview/llfloaterrate.h +++ b/linden/indra/newview/llfloaterrate.h @@ -40,6 +40,7 @@ class LLRadioGroup; class LLButton; class LLMessageSystem; class LLLineEditor; +class LLObjectSelection; class LLFloaterRate : public LLFloater @@ -81,6 +82,7 @@ protected: F32 mLastAppearance; F32 mLastBuilding; BOOL mReputationRequested; + LLHandle mObjectSelection; }; #endif diff --git a/linden/indra/newview/llfloaterregioninfo.cpp b/linden/indra/newview/llfloaterregioninfo.cpp index 7fe6148..b758777 100644 --- a/linden/indra/newview/llfloaterregioninfo.cpp +++ b/linden/indra/newview/llfloaterregioninfo.cpp @@ -221,7 +221,7 @@ void LLFloaterRegionInfo::show(LLViewerRegion* region) "EstateOwnerMessage", &processEstateOwnerRequest); } - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore*/ sInstance->refreshFromRegion(region); // Must allow anyone to request the RegionInfo data @@ -291,7 +291,7 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) if(!tab) return; // extract message - char sim_name[MAX_STRING]; + char sim_name[MAX_STRING]; /* Flawfinder: ignore*/ U32 region_flags; U8 agent_limit; F32 object_bonus_factor; @@ -324,12 +324,20 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->childSetValue("restrict_pushobject", (region_flags & REGION_FLAGS_RESTRICT_PUSHOBJECT) ? TRUE : FALSE ); panel->childSetValue("allow_land_resell_check", (region_flags & REGION_FLAGS_BLOCK_LAND_RESELL) ? FALSE : TRUE ); panel->childSetValue("allow_parcel_changes_check", (region_flags & REGION_FLAGS_ALLOW_PARCEL_CHANGES) ? TRUE : FALSE ); - panel->childSetValue("agent_limit_spin", LLSD((F32)agent_limit) ); panel->childSetValue("object_bonus_spin", LLSD(object_bonus_factor) ); - panel->childSetValue("access_combo", LLSD(LLViewerRegion::accessToString(sim_access)) ); + + // detect teen grid for maturity + LLViewerRegion* region = gAgent.getRegion(); + + U32 parent_estate_id; + msg->getU32("RegionInfo", "ParentEstateID", parent_estate_id); + BOOL teen_grid = (parent_estate_id == 5); // *TODO add field to estate table and test that + panel->childSetEnabled("access_combo", gAgent.isGodlike() || (region && region->canManageEstate() && !teen_grid)); + + // DEBUG PANEL panel = LLUICtrlFactory::getPanelByName(tab, "Debug"); if(!panel) return; @@ -349,7 +357,6 @@ void LLFloaterRegionInfo::processRegionInfo(LLMessageSystem* msg) panel->childSetValue("terrain_lower_spin", LLSD(terrain_lower_limit)); panel->childSetValue("use_estate_sun_check", LLSD(use_estate_sun)); - LLViewerRegion* region = gAgent.getRegion(); BOOL allow_modify = gAgent.isGodlike() || (region && region->canManageEstate()); panel->childSetValue("fixed_sun_check", LLSD((BOOL)(region_flags & REGION_FLAGS_SUN_FIXED))); panel->childSetEnabled("fixed_sun_check", allow_modify && !use_estate_sun); @@ -525,7 +532,8 @@ bool LLPanelRegionGeneralInfo::refreshFromRegion(LLViewerRegion* region) setCtrlsEnabled(allow_modify); childDisable("apply_btn"); childSetEnabled("access_text", allow_modify); - childSetEnabled("access_combo", allow_modify); + // childSetEnabled("access_combo", allow_modify); + // now set in processRegionInfo for teen grid detection childSetEnabled("kick_btn", allow_modify); childSetEnabled("kick_all_btn", allow_modify); childSetEnabled("im_btn", allow_modify); @@ -591,7 +599,7 @@ void LLPanelRegionGeneralInfo::onKickCommit(const std::vector& name strings_t strings; // [0] = our agent id // [1] = target agent id - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ gAgent.getID().toString(buffer); strings.push_back(buffer); @@ -619,7 +627,7 @@ void LLPanelRegionGeneralInfo::onKickAllCommit(S32 option, void* userdata) if(!self) return; strings_t strings; // [0] = our agent id - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ gAgent.getID().toString(buffer); strings.push_back(buffer); @@ -654,7 +662,7 @@ void LLPanelRegionGeneralInfo::onMessageCommit(S32 option, const LLString& text, // [4] message strings.push_back("-1"); strings.push_back("-1"); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ gAgent.getID().toString(buffer); strings.push_back(buffer); std::string name; @@ -688,35 +696,35 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() llinfos << "LLPanelRegionGeneralInfo::sendUpdate()" << llendl; strings_t strings; //integers_t integers; - char buffer[MAX_STRING]; - sprintf(buffer, "%s", (childGetValue("block_terraform_check").asBoolean() ? "Y" : "N")); + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ + snprintf(buffer, MAX_STRING, "%s", (childGetValue("block_terraform_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); - sprintf(buffer, "%s", (childGetValue("block_fly_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("block_fly_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); - sprintf(buffer, "%s", (childGetValue("allow_damage_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("allow_damage_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); - sprintf(buffer, "%s", (childGetValue("allow_land_resell_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("allow_land_resell_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); F32 value = (F32)childGetValue("agent_limit_spin").asReal(); - sprintf(buffer, "%f", value); + snprintf(buffer, MAX_STRING, "%f", value); /* Flawfinder: ignore*/ strings.push_back(strings_t::value_type(buffer)); value = (F32)childGetValue("object_bonus_spin").asReal(); - sprintf(buffer, "%f", value); + snprintf(buffer, MAX_STRING, "%f", value); /* Flawfinder: ignore*/ strings.push_back(strings_t::value_type(buffer)); U8 access = LLViewerRegion::stringToAccess(childGetValue("access_combo").asString().c_str()); - sprintf(buffer, "%d", (S32)access); + snprintf(buffer, MAX_STRING, "%d", (S32)access); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); - sprintf(buffer, "%s", (childGetValue("restrict_pushobject").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("restrict_pushobject").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); - sprintf(buffer, "%s", (childGetValue("allow_parcel_changes_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("allow_parcel_changes_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); @@ -724,7 +732,7 @@ BOOL LLPanelRegionGeneralInfo::sendUpdate() LLViewerRegion* region = gAgent.getRegion(); if (region - && access != region->getSimAccess() ) + && access != region->getSimAccess() ) /* Flawfinder: ignore */ { gViewerWindow->alertXml("RegionMaturityChange"); } @@ -783,15 +791,15 @@ BOOL LLPanelRegionDebugInfo::sendUpdate() { llinfos << "LLPanelRegionDebugInfo::sendUpdate" << llendl; strings_t strings; - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ - sprintf(buffer, "%s", (childGetValue("disable_scripts_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("disable_scripts_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(buffer); - sprintf(buffer, "%s", (childGetValue("disable_collisions_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("disable_collisions_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(buffer); - sprintf(buffer, "%s", (childGetValue("disable_physics_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("disable_physics_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore */ strings.push_back(buffer); LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); @@ -946,10 +954,10 @@ bool LLPanelRegionTextureInfo::refreshFromRegion(LLViewerRegion* region) LLVLComposition* compp = region->getComposition(); LLTextureCtrl* texture_ctrl; - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - sprintf(buffer, "texture_detail_%d", i); + snprintf(buffer, MAX_STRING, "texture_detail_%d", i); /* Flawfinder: ignore */ texture_ctrl = LLViewerUICtrlFactory::getTexturePickerByName(this, buffer); if(texture_ctrl) { @@ -962,9 +970,9 @@ bool LLPanelRegionTextureInfo::refreshFromRegion(LLViewerRegion* region) for(S32 i = 0; i < CORNER_COUNT; ++i) { - sprintf(buffer, "height_start_spin_%d", i); + snprintf(buffer, MAX_STRING, "height_start_spin_%d", i); /* Flawfinder: ignore */ childSetValue(buffer, LLSD(compp->getStartHeight(i))); - sprintf(buffer, "height_range_spin_%d", i); + snprintf(buffer, MAX_STRING, "height_range_spin_%d", i); /* Flawfinder: ignore */ childSetValue(buffer, LLSD(compp->getHeightRange(i))); } @@ -976,18 +984,18 @@ bool LLPanelRegionTextureInfo::refreshFromRegion(LLViewerRegion* region) BOOL LLPanelRegionTextureInfo::postBuild() { LLPanelRegionInfo::postBuild(); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - sprintf(buffer, "texture_detail_%d", i); + snprintf(buffer, MAX_STRING, "texture_detail_%d", i); /* Flawfinder: ignore */ initCtrl(buffer); } for(S32 i = 0; i < CORNER_COUNT; ++i) { - sprintf(buffer, "height_start_spin_%d", i); + snprintf(buffer, MAX_STRING, "height_start_spin_%d", i); /* Flawfinder: ignore */ initCtrl(buffer); - sprintf(buffer, "height_range_spin_%d", i); + snprintf(buffer, MAX_STRING, "height_range_spin_%d", i); /* Flawfinder: ignore */ initCtrl(buffer); } @@ -1017,9 +1025,9 @@ BOOL LLPanelRegionTextureInfo::sendUpdate() } LLTextureCtrl* texture_ctrl; - char buffer[MAX_STRING]; - char buffer2[MAX_STRING]; - char id_str[UUID_STR_LENGTH]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char buffer2[MAX_STRING]; /* Flawfinder: ignore */ + char id_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ LLMessageSystem* msg = gMessageSystem; strings_t strings; @@ -1027,13 +1035,13 @@ BOOL LLPanelRegionTextureInfo::sendUpdate() for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - sprintf(buffer, "texture_detail_%d", i); + snprintf(buffer, MAX_STRING, "texture_detail_%d", i); /* Flawfinder: ignore */ texture_ctrl = LLViewerUICtrlFactory::getTexturePickerByName(this, buffer); if(texture_ctrl) { LLUUID tmp_id(texture_ctrl->getImageAssetID()); tmp_id.toString(id_str); - sprintf(buffer, "%d %s", i, id_str); + snprintf(buffer, MAX_STRING, "%d %s", i, id_str); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); } } @@ -1041,9 +1049,9 @@ BOOL LLPanelRegionTextureInfo::sendUpdate() strings.clear(); for(S32 i = 0; i < CORNER_COUNT; ++i) { - sprintf(buffer, "height_start_spin_%d", i); - sprintf(buffer2, "height_range_spin_%d", i); - sprintf(buffer, "%d %f %f", i, (F32)childGetValue(buffer).asReal(), (F32)childGetValue(buffer2).asReal()); + snprintf(buffer, MAX_STRING, "height_start_spin_%d", i); /* Flawfinder: ignore */ + snprintf(buffer2, MAX_STRING, "height_range_spin_%d", i); /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "%d %f %f", i, (F32)childGetValue(buffer).asReal(), (F32)childGetValue(buffer2).asReal()); /* Flawfinder: ignore */ strings.push_back(strings_t::value_type(buffer)); } sendEstateOwnerMessage(msg, "textureheights", invoice, strings); @@ -1056,8 +1064,8 @@ BOOL LLPanelRegionTextureInfo::validateTextureSizes() { for(S32 i = 0; i < TERRAIN_TEXTURE_COUNT; ++i) { - char buffer[MAX_STRING]; - sprintf(buffer, "texture_detail_%d", i); + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "texture_detail_%d", i); /* Flawfinder: ignore */ LLTextureCtrl* texture_ctrl = LLViewerUICtrlFactory::getTexturePickerByName(this, buffer); if (!texture_ctrl) continue; @@ -1158,21 +1166,21 @@ bool LLPanelRegionTerrainInfo::refreshFromRegion(LLViewerRegion* region) BOOL LLPanelRegionTerrainInfo::sendUpdate() { llinfos << "LLPanelRegionTerrainInfo::sendUpdate" << llendl; - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ strings_t strings; LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); - sprintf(buffer, "%f", (F32)childGetValue("water_height_spin").asReal()); + snprintf(buffer, MAX_STRING, "%f", (F32)childGetValue("water_height_spin").asReal()); /* Flawfinder: ignore */ strings.push_back(buffer); - sprintf(buffer, "%f", (F32)childGetValue("terrain_raise_spin").asReal()); + snprintf(buffer, MAX_STRING, "%f", (F32)childGetValue("terrain_raise_spin").asReal()); /* Flawfinder: ignore */ strings.push_back(buffer); - sprintf(buffer, "%f", (F32)childGetValue("terrain_lower_spin").asReal()); + snprintf(buffer, MAX_STRING, "%f", (F32)childGetValue("terrain_lower_spin").asReal()); /* Flawfinder: ignore */ strings.push_back(buffer); - sprintf(buffer, "%s", (childGetValue("use_estate_sun_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("use_estate_sun_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore*/ strings.push_back(buffer); - sprintf(buffer, "%s", (childGetValue("fixed_sun_check").asBoolean() ? "Y" : "N")); + snprintf(buffer, MAX_STRING, "%s", (childGetValue("fixed_sun_check").asBoolean() ? "Y" : "N")); /* Flawfinder: ignore*/ strings.push_back(buffer); - sprintf(buffer, "%f", (F32)childGetValue("sun_hour_slider").asReal() ); + snprintf(buffer, MAX_STRING, "%f", (F32)childGetValue("sun_hour_slider").asReal() ); /* Flawfinder: ignore*/ strings.push_back(buffer); // Grab estate information in case the user decided to set the @@ -1198,11 +1206,11 @@ BOOL LLPanelRegionTerrainInfo::sendUpdate() estate_sun_hour = panel->getSunHour(); } - sprintf(buffer, "%s", (estate_global_time ? "Y" : "N") ); + snprintf(buffer, MAX_STRING, "%s", (estate_global_time ? "Y" : "N") ); /* Flawfinder: ignore*/ strings.push_back(buffer); - sprintf(buffer, "%s", (estate_fixed_sun ? "Y" : "N") ); + snprintf(buffer, MAX_STRING, "%s", (estate_fixed_sun ? "Y" : "N") ); /* Flawfinder: ignore*/ strings.push_back(buffer); - sprintf(buffer, "%f", estate_sun_hour); + snprintf(buffer, MAX_STRING, "%f", estate_sun_hour); /* Flawfinder: ignore*/ strings.push_back(buffer); sendEstateOwnerMessage(gMessageSystem, "setregionterrain", invoice, strings); @@ -1531,7 +1539,7 @@ void LLPanelEstateInfo::kickUserConfirm(S32 option, void* userdata) LLUUID invoice(LLFloaterRegionInfo::getLastInvoice()); strings_t strings; - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ switch(option) { @@ -1814,12 +1822,12 @@ void LLPanelEstateInfo::sendEstateAccessDelta(U32 flags, const LLUUID& agent_or_ msg->addString("Method", "estateaccessdelta"); msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); - char buf[MAX_STRING]; + char buf[MAX_STRING]; /* Flawfinder: ignore*/ gAgent.getID().toString(buf); msg->nextBlock("ParamList"); msg->addString("Parameter", buf); - sprintf(buf, "%u", flags); + snprintf(buf, MAX_STRING, "%u", flags); /* Flawfinder: ignore*/ msg->nextBlock("ParamList"); msg->addString("Parameter", buf); @@ -2075,8 +2083,8 @@ void LLPanelEstateInfo::commitEstateInfo() msg->nextBlock("ParamList"); msg->addString("Parameter", getEstateName()); - char buf[MAX_STRING]; - sprintf(buf, "%u", computeEstateFlags()); + char buf[MAX_STRING]; /* Flawfinder: ignore*/ + snprintf(buf, MAX_STRING, "%u", computeEstateFlags()); /* Flawfinder: ignore*/ msg->nextBlock("ParamList"); msg->addString("Parameter", buf); @@ -2086,7 +2094,7 @@ void LLPanelEstateInfo::commitEstateInfo() sun_hour = 0.f; // 0 = global time } - sprintf(buf, "%d", (S32)(sun_hour*1024.0f)); + snprintf(buf, MAX_STRING, "%d", (S32)(sun_hour*1024.0f)); /* Flawfinder: ignore*/ msg->nextBlock("ParamList"); msg->addString("Parameter", buf); @@ -2560,8 +2568,13 @@ void LLPanelEstateCovenant::onLoadComplete(LLVFS *vfs, S32 file_length = file.getSize(); char* buffer = new char[file_length+1]; - file.read((U8*)buffer, file_length); + if (buffer == NULL) + { + llerrs << "Memory Allocation Failed" << llendl; + return; + } + file.read((U8*)buffer, file_length); /* Flawfinder: ignore */ // put a EOS at the end buffer[file_length] = 0; @@ -2633,7 +2646,7 @@ void LLPanelEstateCovenant::sendChangeCovenantID(const LLUUID &asset_id) msg->addUUID("Invoice", LLFloaterRegionInfo::getLastInvoice()); msg->nextBlock("ParamList"); - msg->addString("Parameter", getCovenantID().getString().c_str()); + msg->addString("Parameter", getCovenantID().asString()); gAgent.sendReliableMessage(); } } @@ -2879,7 +2892,7 @@ bool LLDispatchSetEstateAccess::operator()( for (S32 i = 0; i < num_allowed_agents && i < ESTATE_MAX_ACCESS_IDS; i++) { LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ allowed_agent_name_list->addNameItem(id); } panel->childSetEnabled("remove_allowed_avatar_btn", allowed_agent_name_list->getFirstSelected() ? TRUE : FALSE); @@ -2903,7 +2916,7 @@ bool LLDispatchSetEstateAccess::operator()( for (S32 i = 0; i < num_allowed_groups && i < ESTATE_MAX_GROUP_IDS; i++) { LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ allowed_group_name_list->addGroupNameItem(id); } panel->childSetEnabled("remove_allowed_group_btn", allowed_group_name_list->getFirstSelected() ? TRUE : FALSE); @@ -2935,7 +2948,7 @@ bool LLDispatchSetEstateAccess::operator()( for (S32 i = 0; i < num_banned_agents && i < ESTATE_MAX_ACCESS_IDS; i++) { LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ banned_agent_name_list->addNameItem(id); } panel->childSetEnabled("remove_banned_avatar_btn", banned_agent_name_list->getFirstSelected() ? TRUE : FALSE); @@ -2958,7 +2971,7 @@ bool LLDispatchSetEstateAccess::operator()( for (S32 i = 0; i < num_estate_managers && i < ESTATE_MAX_MANAGERS; i++) { LLUUID id; - memcpy(id.mData, strings[index++].data(), UUID_BYTES); + memcpy(id.mData, strings[index++].data(), UUID_BYTES); /* Flawfinder: ignore */ estate_manager_name_list->addNameItem(id); } panel->childSetEnabled("remove_estate_manager_btn", estate_manager_name_list->getFirstSelected() ? TRUE : FALSE); diff --git a/linden/indra/newview/llfloaterreporter.cpp b/linden/indra/newview/llfloaterreporter.cpp index 116b338..0337dd0 100644 --- a/linden/indra/newview/llfloaterreporter.cpp +++ b/linden/indra/newview/llfloaterreporter.cpp @@ -63,6 +63,7 @@ #include "lltooldraganddrop.h" #include "llfloatermap.h" #include "lluiconstants.h" +#include "lluploaddialog.h" #include "llcallingcard.h" #include "llviewerobjectlist.h" #include "llagent.h" @@ -80,6 +81,7 @@ #include "llvieweruictrlfactory.h" #include "viewer.h" +#include "llassetuploadresponders.h" const U32 INCLUDE_SCREENSHOT = 0x01 << 0; @@ -115,7 +117,8 @@ LLFloaterReporter::LLFloaterReporter( mDeselectOnClose( FALSE ), mPicking( FALSE), mPosition(), - mCopyrightWarningSeen( FALSE ) + mCopyrightWarningSeen( FALSE ), + mResourceDatap(new LLResourceData()) { if (report_type == BUG_REPORT) { @@ -166,9 +169,9 @@ LLFloaterReporter::LLFloaterReporter( gReporterInstances.addData(report_type, this); - // Upload a screenshot, but don't draw this floater. + // Take a screenshot, but don't draw this floater. setVisible(FALSE); - uploadScreenshot(); + takeScreenshot(); setVisible(TRUE); // Default text to be blank @@ -230,11 +233,7 @@ LLFloaterReporter::~LLFloaterReporter() std::for_each(mMCDList.begin(), mMCDList.end(), DeletePointer() ); mMCDList.clear(); - if (gSelectMgr) - { - gSelectMgr->deselectTransient(); - } - + delete mResourceDatap; gDialogVisible = FALSE; } @@ -368,7 +367,7 @@ void LLFloaterReporter::callbackAvatarID(const std::vector& names, if ( self->mReportType != BUG_REPORT ) { self->childSetText("abuser_name_edit", names[0] ); - + self->mAbuserID = ids[0]; self->refresh(); @@ -379,31 +378,59 @@ void LLFloaterReporter::callbackAvatarID(const std::vector& names, void LLFloaterReporter::onClickSend(void *userdata) { LLFloaterReporter *self = (LLFloaterReporter *)userdata; + + if (self->mPicking) + { + closePickTool(self); + } - // only do this for abuse reports - if ( self->mReportType != BUG_REPORT ) + if(self->validateReport()) { - if ( ! self->mCopyrightWarningSeen ) + // only show copyright alert for abuse reports + if ( self->mReportType != BUG_REPORT ) { - LLString details_lc = self->childGetText("details_edit"); - LLString::toLower( details_lc ); - LLString summary_lc = self->childGetText("summary_edit"); - LLString::toLower( summary_lc ); - if ( details_lc.find( "copyright" ) != std::string::npos || - summary_lc.find( "copyright" ) != std::string::npos ) + if ( ! self->mCopyrightWarningSeen ) { - gViewerWindow->alertXml("HelpReportAbuseContainsCopyright"); - self->mCopyrightWarningSeen = TRUE; - return; + LLString details_lc = self->childGetText("details_edit"); + LLString::toLower( details_lc ); + LLString summary_lc = self->childGetText("summary_edit"); + LLString::toLower( summary_lc ); + if ( details_lc.find( "copyright" ) != std::string::npos || + summary_lc.find( "copyright" ) != std::string::npos ) + { + gViewerWindow->alertXml("HelpReportAbuseContainsCopyright"); + self->mCopyrightWarningSeen = TRUE; + return; + }; }; }; - }; - if (self->mPicking) - { - closePickTool(self); + LLUploadDialog::modalUploadDialog("Uploading...\n\nReport"); + // *TODO don't upload image if checkbox isn't checked + std::string url = gAgent.getRegion()->getCapability("SendUserReport"); + std::string sshot_url = gAgent.getRegion()->getCapability("SendUserReportWithScreenshot"); + if(!url.empty() || !sshot_url.empty()) + { + self->sendReportViaCaps(url, sshot_url, self->gatherReport()); + self->close(); + } + else + { + if(self->childGetValue("screen_check")) + { + self->childDisable("send_btn"); + self->childDisable("cancel_btn"); + // the callback from uploading the image calls sendReportViaLegacy() + self->uploadImage(); + } + else + { + self->sendReportViaLegacy(self->gatherReport()); + LLUploadDialog::modalUploadFinished(); + self->close(); + } + } } - self->sendReport(); } @@ -459,7 +486,7 @@ void LLFloaterReporter::showFromMenu(EReportType report_type) { // ...bring that window to front LLFloaterReporter *f = gReporterInstances.getData(report_type); - f->open(); + f->open(); /* Flawfinder: ignore */ } else { @@ -515,7 +542,7 @@ void LLFloaterReporter::showFromObject(const LLUUID& object_id) // Need to deselect on close f->mDeselectOnClose = TRUE; - f->open(); + f->open(); /* Flawfinder: ignore */ } @@ -556,10 +583,9 @@ void LLFloaterReporter::setPickedObjectProperties(const char *object_name, const childSetText("owner_name", owner_name); } -void LLFloaterReporter::sendReport() + +bool LLFloaterReporter::validateReport() { - LLViewerRegion *regionp = gAgent.getRegion(); - if (!regionp) return; // Ensure user selected a category from the list LLSD category_sd = childGetValue("category_combo"); U8 category = (U8)category_sd.asInteger(); @@ -573,7 +599,7 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugSelectCategory"); } - return; + return false; } if ( mReportType != BUG_REPORT ) @@ -581,13 +607,13 @@ void LLFloaterReporter::sendReport() if ( childGetText("abuser_name_edit").empty() ) { gViewerWindow->alertXml("HelpReportAbuseAbuserNameEmpty"); - return; + return false; }; if ( childGetText("abuse_location_edit").empty() ) { gViewerWindow->alertXml("HelpReportAbuseAbuserLocationEmpty"); - return; + return false; }; }; @@ -601,7 +627,7 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugSummaryEmpty"); } - return; + return false; }; if ( childGetText("details_edit") == mDefaultSummary ) @@ -614,53 +640,19 @@ void LLFloaterReporter::sendReport() { gViewerWindow->alertXml("HelpReportBugDetailsEmpty"); } - return; + return false; }; + return true; +} + +LLSD LLFloaterReporter::gatherReport() +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return LLSD(); // *TODO handle this failure case more gracefully // reset flag in case the next report also contains this text mCopyrightWarningSeen = FALSE; - U32 check_flags = 0; - if (childGetValue("screen_check")) - { - check_flags |= INCLUDE_SCREENSHOT; - } - - LLMessageSystem *msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UserReport); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ReportData); - msg->addU8Fast(_PREHASH_ReportType, (U8) mReportType); - msg->addU8(_PREHASH_Category, category); - msg->addVector3Fast(_PREHASH_Position, mPosition); - msg->addU8Fast(_PREHASH_CheckFlags, (U8) check_flags); - - // only send a screenshot ID if we're asked too and the email is - // going to LL - Estate Owners cannot see the screenshot asset - LLSD screenshot_id = LLUUID::null; - if (childGetValue("screen_check")) - { - if ( mReportType != BUG_REPORT ) - { - if ( gEmailToEstateOwner == FALSE ) - { - screenshot_id = childGetValue("screenshot"); - } - } - else - { - screenshot_id = childGetValue("screenshot"); - }; - }; - msg->addUUIDFast(_PREHASH_ScreenshotID, screenshot_id); - msg->addUUIDFast(_PREHASH_ObjectID, mObjectID); - - msg->addUUID("AbuserID", mAbuserID ); - msg->addString("AbuseRegionName", ""); - msg->addUUID("AbuseRegionID", LLUUID::null); - std::ostringstream summary; if (!gInProductionGrid) { @@ -708,7 +700,6 @@ void LLFloaterReporter::sendReport() << " {" << childGetText("abuser_name_edit") << "} " // name of abuse entered in report (chosen using LLAvatarPicker) << " \"" << childGetValue("summary_edit").asString() << "\""; // summary as entered }; - msg->addStringFast(_PREHASH_Summary, summary.str().c_str()); std::ostringstream details; if (mReportType != BUG_REPORT) @@ -733,10 +724,10 @@ void LLFloaterReporter::sendReport() }; details << childGetValue("details_edit").asString(); - msg->addStringFast(_PREHASH_Details, details.str() ); - char version_string[MAX_STRING]; - sprintf(version_string, + char version_string[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(version_string, /* Flawfinder: ignore */ + MAX_STRING, "%d.%d.%d %s %s %s %s", LL_VERSION_MAJOR, LL_VERSION_MINOR, @@ -745,120 +736,204 @@ void LLFloaterReporter::sendReport() gSysCPU.getFamily().c_str(), gGLManager.mGLRenderer.c_str(), gGLManager.mDriverVersionVendorString.c_str()); - msg->addString("VersionString", version_string); - msg->sendReliable(regionp->getHost()); + // only send a screenshot ID if we're asked to and the email is + // going to LL - Estate Owners cannot see the screenshot asset + LLUUID screenshot_id = LLUUID::null; + if (childGetValue("screen_check")) + { + if ( mReportType != BUG_REPORT ) + { + if ( gEmailToEstateOwner == FALSE ) + { + screenshot_id = childGetValue("screenshot"); + } + } + else + { + screenshot_id = childGetValue("screenshot"); + }; + }; + + LLSD report = LLSD::emptyMap(); + report["report-type"] = (U8) mReportType; + report["category"] = childGetValue("category_combo"); + report["position"] = mPosition.getValue(); + report["check-flags"] = (U8)0; // this is not used + report["screenshot-id"] = screenshot_id; + report["object-id"] = mObjectID; + report["abuser-id"] = mAbuserID; + report["abuse-region-name"] = ""; + report["abuse-region-id"] = LLUUID::null; + report["summary"] = summary.str(); + report["version-string"] = version_string; + report["details"] = details.str(); + return report; +} - close(); +void LLFloaterReporter::sendReportViaLegacy(const LLSD & report) +{ + LLViewerRegion *regionp = gAgent.getRegion(); + if (!regionp) return; + LLMessageSystem *msg = gMessageSystem; + msg->newMessageFast(_PREHASH_UserReport); + msg->nextBlockFast(_PREHASH_AgentData); + msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + + msg->nextBlockFast(_PREHASH_ReportData); + msg->addU8Fast(_PREHASH_ReportType, report["report-type"].asInteger()); + msg->addU8(_PREHASH_Category, report["category"].asInteger()); + msg->addVector3Fast(_PREHASH_Position, LLVector3(report["position"])); + msg->addU8Fast(_PREHASH_CheckFlags, report["check-flags"].asInteger()); + msg->addUUIDFast(_PREHASH_ScreenshotID, report["screenshot-id"].asUUID()); + msg->addUUIDFast(_PREHASH_ObjectID, report["object-id"].asUUID()); + msg->addUUID("AbuserID", report["abuser-id"].asUUID()); + msg->addString("AbuseRegionName", report["abuse-region-name"].asString()); + msg->addUUID("AbuseRegionID", report["abuse-region-id"].asUUID()); + + msg->addStringFast(_PREHASH_Summary, report["summary"].asString().c_str()); + msg->addString("VersionString", report["version-string"]); + msg->addStringFast(_PREHASH_Details, report["details"] ); + + msg->sendReliable(regionp->getHost()); } +class LLUserReportScreenshotResponder : public LLAssetUploadResponder +{ +public: + LLUserReportScreenshotResponder(const LLSD & post_data, + const LLUUID & vfile_id, + LLAssetType::EType asset_type): + LLAssetUploadResponder(post_data, vfile_id, asset_type) + { + } + void uploadFailed(const LLSD& content) + { + // *TODO pop up a dialog so the user knows their report screenshot didn't make it + LLUploadDialog::modalUploadFinished(); + } + void uploadComplete(const LLSD& content) + { + // we don't care about what the server returns from this post, just clean up the UI + LLUploadDialog::modalUploadFinished(); + } +}; + +class LLUserReportResponder : public LLHTTPClient::Responder +{ +public: + LLUserReportResponder(): LLHTTPClient::Responder() {} + + void error(U32 status, const std::string& reason) + { + // *TODO do some user messaging here + LLUploadDialog::modalUploadFinished(); + } + void result(const LLSD& content) + { + // we don't care about what the server returns + LLUploadDialog::modalUploadFinished(); + } +}; + +void LLFloaterReporter::sendReportViaCaps(std::string url, std::string sshot_url, const LLSD& report) +{ + if(childGetValue("screen_check").asBoolean() && !sshot_url.empty()) + { + // try to upload screenshot + LLHTTPClient::post(sshot_url, report, new LLUserReportScreenshotResponder(report, + mResourceDatap->mAssetInfo.mUuid, + mResourceDatap->mAssetInfo.mType)); + } + else + { + // screenshot not wanted or we don't have screenshot cap + LLHTTPClient::post(url, report, new LLUserReportResponder()); + } +} -void LLFloaterReporter::uploadScreenshot() +void LLFloaterReporter::takeScreenshot() { const S32 IMAGE_WIDTH = 1024; const S32 IMAGE_HEIGHT = 768; - LLString filename("report_screenshot.bmp"); - if( !gViewerWindow->saveSnapshot( filename, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, FALSE ) ) + LLPointer raw = new LLImageRaw; + if( !gViewerWindow->rawSnapshot(raw, IMAGE_WIDTH, IMAGE_HEIGHT, TRUE, TRUE, FALSE)) { + llwarns << "Unable to take screenshot" << llendl; return; } + LLPointer upload_data = LLViewerImageList::convertToUploadFile(raw); - // Generate the temporary filename - std::string temp_filename = gDirUtilp->getTempFilename(); - - // try to create the upload file - if (!LLViewerImageList::createUploadFile(filename, - temp_filename, - IMG_CODEC_BMP )) + // create a resource data + mResourceDatap->mInventoryType = LLInventoryType::IT_NONE; + mResourceDatap->mAssetInfo.mTransactionID.generate(); + mResourceDatap->mAssetInfo.mUuid = mResourceDatap->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()); + if (BUG_REPORT == mReportType) { - llwarns << "Unable to upload report screenshot " << filename << ":\n\n" << LLImageBase::getLastError() << "\n" << llendl; - if(LLFile::remove(temp_filename.c_str()) == -1) - { - lldebugs << "unable to remove temp file" << llendl; - } - LLFilePicker::instance().reset(); + mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; + mResourceDatap->mPreferredLocation = LLAssetType::EType(-1); + } + else if (COMPLAINT_REPORT == mReportType) + { + mResourceDatap->mAssetInfo.mType = LLAssetType::AT_TEXTURE; + mResourceDatap->mPreferredLocation = LLAssetType::EType(-2); } else { - // create a resource data - LLResourceData* data = NULL; - data = new LLResourceData; - data->mInventoryType = LLInventoryType::IT_NONE; - data->mAssetInfo.mTransactionID.generate(); - data->mAssetInfo.mUuid = data->mAssetInfo.mTransactionID.makeAssetID(gAgent.getSecureSessionID()); - if (BUG_REPORT == mReportType) - { - //data->mAssetInfo.mType = LLAssetType::AT_BUG_REPORT_SCREENSHOT; - data->mAssetInfo.mType = LLAssetType::AT_TEXTURE; - data->mPreferredLocation = LLAssetType::EType(-1); - } - else if (COMPLAINT_REPORT == mReportType) - { - //data->mAssetInfo.mType = LLAssetType::AT_COMPLAINT_REPORT_SCREENSHOT; - data->mAssetInfo.mType = LLAssetType::AT_TEXTURE; - data->mPreferredLocation = LLAssetType::EType(-2); - } - else - { - llwarns << "Unknown LLFloaterReporter type" << llendl; - } - data->mAssetInfo.mCreatorID = gAgentID; - data->mAssetInfo.setName("screenshot_name"); - data->mAssetInfo.setDescription("screenshot_descr"); - - llinfos << "*** Uploading: " << llendl; - llinfos << "Type: " << LLAssetType::lookup(data->mAssetInfo.mType) << llendl; - llinfos << "File: " << filename << llendl; - llinfos << "Dest: " << temp_filename << llendl; - llinfos << "Name: " << data->mAssetInfo.getName() << llendl; - llinfos << "Desc: " << data->mAssetInfo.getDescription() << llendl; - - gAssetStorage->storeAssetData(temp_filename.c_str(), - data->mAssetInfo.mTransactionID, - data->mAssetInfo.mType, - LLFloaterReporter::uploadDoneCallback, - (void*)data, TRUE); + llwarns << "Unknown LLFloaterReporter type" << llendl; + } + mResourceDatap->mAssetInfo.mCreatorID = gAgentID; + mResourceDatap->mAssetInfo.setName("screenshot_name"); + mResourceDatap->mAssetInfo.setDescription("screenshot_descr"); + + // store in VFS + LLVFile::writeFile(upload_data->getData(), + upload_data->getDataSize(), + gVFS, + mResourceDatap->mAssetInfo.mUuid, + mResourceDatap->mAssetInfo.mType); + + // store in the image list so it doesn't try to fetch from the server + LLViewerImage* image_in_list = new LLViewerImage(mResourceDatap->mAssetInfo.mUuid, TRUE); + image_in_list->createGLTexture(0, raw); + gImageList.addImage(image_in_list); + + // the texture picker then uses that texture + LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(this, "screenshot"); + if (texture) + { + texture->setImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setDefaultImageAssetID(mResourceDatap->mAssetInfo.mUuid); + texture->setCaption("Screenshot"); } + +} + +void LLFloaterReporter::uploadImage() +{ + llinfos << "*** Uploading: " << llendl; + llinfos << "Type: " << LLAssetType::lookup(mResourceDatap->mAssetInfo.mType) << llendl; + llinfos << "UUID: " << mResourceDatap->mAssetInfo.mUuid << llendl; + llinfos << "Name: " << mResourceDatap->mAssetInfo.getName() << llendl; + llinfos << "Desc: " << mResourceDatap->mAssetInfo.getDescription() << llendl; + + gAssetStorage->storeAssetData(mResourceDatap->mAssetInfo.mTransactionID, + mResourceDatap->mAssetInfo.mType, + LLFloaterReporter::uploadDoneCallback, + (void*)mResourceDatap, TRUE); } // static void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, S32 result) // StoreAssetData callback (fixed) { - LLResourceData* data = (LLResourceData*)user_data; + LLUploadDialog::modalUploadFinished(); - if(result >= 0) - { - EReportType report_type = UNKNOWN_REPORT; - if (data->mPreferredLocation == -1) - { - report_type = BUG_REPORT; - } - else if (data->mPreferredLocation == -2) - { - report_type = COMPLAINT_REPORT; - } - else - { - llwarns << "Unknown report type : " << data->mPreferredLocation << llendl; - } + LLResourceData* data = (LLResourceData*)user_data; - LLFloaterReporter *self = getReporter(report_type); - if (self) - { - LLTexturePicker* texture = LLUICtrlFactory::getTexturePickerByName(self, "screenshot"); - if (texture) - { - texture->setImageAssetID(uuid); - texture->setDefaultImageAssetID(uuid); - texture->setCaption("Screenshot"); - } - self->mScreenID = uuid; - llinfos << "Got screen shot " << uuid << llendl; - } - } - else // if(result >= 0) + if(result < 0) { LLStringBase::format_map_t args; args["[REASON]"] = std::string(LLAssetStorage::getErrorString(result)); @@ -867,8 +942,31 @@ void LLFloaterReporter::uploadDoneCallback(const LLUUID &uuid, void *user_data, std::string err_msg("There was a problem uploading a report screenshot"); err_msg += " due to the following reason: " + args["[REASON]"]; llwarns << err_msg << llendl; + return; + } + + EReportType report_type = UNKNOWN_REPORT; + if (data->mPreferredLocation == -1) + { + report_type = BUG_REPORT; } - delete data; + else if (data->mPreferredLocation == -2) + { + report_type = COMPLAINT_REPORT; + } + else + { + llwarns << "Unknown report type : " << data->mPreferredLocation << llendl; + } + + LLFloaterReporter *self = getReporter(report_type); + if (self) + { + self->mScreenID = uuid; + llinfos << "Got screen shot " << uuid << llendl; + self->sendReportViaLegacy(self->gatherReport()); + } + self->close(); } diff --git a/linden/indra/newview/llfloaterreporter.h b/linden/indra/newview/llfloaterreporter.h index af01771..5e25d59 100644 --- a/linden/indra/newview/llfloaterreporter.h +++ b/linden/indra/newview/llfloaterreporter.h @@ -40,6 +40,7 @@ class LLViewerObject; class LLAgent; class LLToolObjPicker; class LLMeanCollisionData; +struct LLResourceData; // these flags are used to label info requests to the server const U32 BUG_REPORT_REQUEST = 0x01 << 0; @@ -70,7 +71,6 @@ enum EReportType CS_REQUEST_REPORT = 4 }; - class LLFloaterReporter : public LLFloater { @@ -106,11 +106,16 @@ public: static void processRegionInfo(LLMessageSystem* msg); void setPickedObjectProperties(const char *object_name, const char *owner_name); - void uploadScreenshot(); private: + void takeScreenshot(); + void sendReportViaCaps(std::string url); + void uploadImage(); + bool validateReport(); void setReporterID(); - void sendReport(); + LLSD gatherReport(); + void sendReportViaLegacy(const LLSD & report); + void sendReportViaCaps(std::string url, std::string sshot_url, const LLSD & report); void setPosBox(const LLVector3d &pos); void enableControls(BOOL own_avatar); void getObjectInfo(const LLUUID& object_id); @@ -127,6 +132,7 @@ private: BOOL mCopyrightWarningSeen; std::list mMCDList; LLString mDefaultSummary; + LLResourceData* mResourceDatap; }; #endif diff --git a/linden/indra/newview/llfloatersaveavatar.cpp b/linden/indra/newview/llfloatersaveavatar.cpp index 2f55288..3b8439e 100644 --- a/linden/indra/newview/llfloatersaveavatar.cpp +++ b/linden/indra/newview/llfloatersaveavatar.cpp @@ -68,7 +68,7 @@ void LLFloaterSaveAvatar::show() } else { - mSingleton->open(); + mSingleton->open(); /*Flawfinder: ignore*/ } } diff --git a/linden/indra/newview/llfloaterscriptdebug.cpp b/linden/indra/newview/llfloaterscriptdebug.cpp index 0781f7c..94047cb 100644 --- a/linden/indra/newview/llfloaterscriptdebug.cpp +++ b/linden/indra/newview/llfloaterscriptdebug.cpp @@ -66,7 +66,7 @@ void LLFloaterScriptDebug::show(const LLUUID& object_id) LLFloater* floaterp = addOutputWindow(object_id); if (sInstance) { - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ sInstance->showFloater(floaterp); } } @@ -225,7 +225,7 @@ LLFloaterScriptDebugOutput* LLFloaterScriptDebugOutput::show(const LLUUID& objec { floaterp = new LLFloaterScriptDebugOutput(object_id); sInstanceMap[object_id] = floaterp; - floaterp->open(); + floaterp->open(); /* Flawfinder: ignore*/ } else { diff --git a/linden/indra/newview/llfloatersellland.cpp b/linden/indra/newview/llfloatersellland.cpp index 5fac819..cc7df3b 100755 --- a/linden/indra/newview/llfloatersellland.cpp +++ b/linden/indra/newview/llfloatersellland.cpp @@ -55,15 +55,15 @@ private: virtual ~LLFloaterSellLandUI(); LLViewerRegion* mRegion; - LLParcel* mParcel; - bool mParcelIsForSale; - bool mSellToBuyer; - bool mChoseSellTo; - S32 mParcelPrice; - S32 mParcelActualArea; - LLUUID mParcelSnapshot; - LLUUID mAuthorizedBuyer; - bool mParcelSoldWithObjects; + LLParcelSelectionHandle mParcelSelection; + bool mParcelIsForSale; + bool mSellToBuyer; + bool mChoseSellTo; + S32 mParcelPrice; + S32 mParcelActualArea; + LLUUID mParcelSnapshot; + LLUUID mAuthorizedBuyer; + bool mParcelSoldWithObjects; void updateParcelInfo(); void refreshUI(); @@ -87,17 +87,24 @@ public: static LLFloaterSellLandUI* soleInstance(bool createIfNeeded); - bool setParcel(LLViewerRegion* region, LLParcel* parcel); + bool setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel); + +private: + class SelectionObserver : public LLParcelObserver + { + public: + virtual void changed(); + }; }; // static void LLFloaterSellLand::sellLand( - LLViewerRegion* region, LLParcel* parcel) + LLViewerRegion* region, LLParcelSelectionHandle parcel) { LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(true); if (ui->setParcel(region, parcel)) { - ui->open(); + ui->open(); /* Flawfinder: ignore */ } } @@ -115,12 +122,20 @@ LLFloaterSellLandUI* LLFloaterSellLandUI::soleInstance(bool createIfNeeded) sInstance->center(); } + + static SelectionObserver* parcelSelectionObserver = NULL; + if (!parcelSelectionObserver) + { + parcelSelectionObserver = new SelectionObserver; + gParcelMgr->addObserver(parcelSelectionObserver); + } + return sInstance; } LLFloaterSellLandUI::LLFloaterSellLandUI() : LLFloater("Sell Land"), - mRegion(0), mParcel(0) + mRegion(0) { } @@ -132,11 +147,27 @@ LLFloaterSellLandUI::~LLFloaterSellLandUI() } } +void LLFloaterSellLandUI::SelectionObserver::changed() +{ + LLFloaterSellLandUI* ui = LLFloaterSellLandUI::soleInstance(false); + if (ui) + { + if (gParcelMgr->selectionEmpty()) + { + ui->close(); + } + else { + ui->setParcel( + gParcelMgr->getSelectionRegion(), + gParcelMgr->getParcelSelection()); + } + } +} void LLFloaterSellLandUI::onClose(bool app_quitting) { LLFloater::onClose(app_quitting); - delete this; + destroy(); } BOOL LLFloaterSellLandUI::postBuild() @@ -152,17 +183,18 @@ BOOL LLFloaterSellLandUI::postBuild() return TRUE; } -bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel) +bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcelSelectionHandle parcel) { - if (!parcel) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS + if (!parcel->getParcel()) // || !can_agent_modify_parcel(parcel)) // can_agent_modify_parcel was deprecated by GROUPS { return false; } mRegion = region; - mParcel = parcel; + mParcelSelection = parcel; mChoseSellTo = false; + updateParcelInfo(); refreshUI(); @@ -171,14 +203,17 @@ bool LLFloaterSellLandUI::setParcel(LLViewerRegion* region, LLParcel* parcel) void LLFloaterSellLandUI::updateParcelInfo() { - mParcelActualArea = mParcel->getArea(); - mParcelIsForSale = mParcel->getForSale(); + LLParcel* parcelp = mParcelSelection->getParcel(); + if (!parcelp) return; + + mParcelActualArea = parcelp->getArea(); + mParcelIsForSale = parcelp->getForSale(); if (mParcelIsForSale) { mChoseSellTo = true; } - mParcelPrice = mParcelIsForSale ? mParcel->getSalePrice() : 0; - mParcelSoldWithObjects = mParcel->getSellWithObjects(); + mParcelPrice = mParcelIsForSale ? parcelp->getSalePrice() : 0; + mParcelSoldWithObjects = parcelp->getSellWithObjects(); if (mParcelIsForSale) { childSetValue("price", mParcelPrice); @@ -197,16 +232,16 @@ void LLFloaterSellLandUI::updateParcelInfo() childSetValue("sell_objects", "none"); } - mParcelSnapshot = mParcel->getSnapshotID(); + mParcelSnapshot = parcelp->getSnapshotID(); - mAuthorizedBuyer = mParcel->getAuthorizedBuyerID(); + mAuthorizedBuyer = parcelp->getAuthorizedBuyerID(); mSellToBuyer = mAuthorizedBuyer.notNull(); if(mSellToBuyer) { LLString name; - char firstname[MAX_STRING]; - char lastname[MAX_STRING]; + char firstname[MAX_STRING]; /* Flawfinder: ignore */ + char lastname[MAX_STRING]; /* Flawfinder: ignore */ gCacheName->getName(mAuthorizedBuyer, firstname, lastname); name.assign(firstname); name.append(" "); @@ -238,13 +273,16 @@ void LLFloaterSellLandUI::setBadge(const char* id, Badge badge) void LLFloaterSellLandUI::refreshUI() { + LLParcel* parcelp = mParcelSelection->getParcel(); + if (!parcelp) return; + LLTextureCtrl* snapshot = LLViewerUICtrlFactory::getTexturePickerByName(this, "info_image"); if (snapshot) { snapshot->setImageAssetID(mParcelSnapshot); } - childSetText("info_parcel", mParcel->getName()); + childSetText("info_parcel", parcelp->getName()); childSetTextArg("info_size", "[AREA]", llformat("%d", mParcelActualArea)); LLString price_str = childGetValue("price").asString(); @@ -377,7 +415,7 @@ void LLFloaterSellLandUI::doSelectAgent(void *userdata) void LLFloaterSellLandUI::callbackAvatarPick(const std::vector& names, const std::vector& ids, void* data) { LLFloaterSellLandUI* floaterp = (LLFloaterSellLandUI*)data; - LLParcel* parcel = floaterp->mParcel; + LLParcel* parcel = floaterp->mParcelSelection->getParcel(); if (names.empty() || ids.empty()) return; @@ -402,7 +440,10 @@ void LLFloaterSellLandUI::doCancel(void *userdata) void LLFloaterSellLandUI::doShowObjects(void *userdata) { LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata; - send_parcel_select_objects(self->mParcel->getLocalID(), RT_SELL); + LLParcel* parcel = self->mParcelSelection->getParcel(); + if (!parcel) return; + + send_parcel_select_objects(parcel->getLocalID(), RT_SELL); LLNotifyBox::showXml("TransferObjectsHighlighted", callbackHighlightTransferable, @@ -420,7 +461,7 @@ void LLFloaterSellLandUI::doSellLand(void *userdata) { LLFloaterSellLandUI* self = (LLFloaterSellLandUI*)userdata; - LLParcel* parcel = self->mParcel; + LLParcel* parcel = self->mParcelSelection->getParcel(); // Do a confirmation if (!parcel->getForSale()) @@ -472,7 +513,8 @@ void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata) return; } - LLParcel* parcel = self->mParcel; + LLParcel* parcel = self->mParcelSelection->getParcel(); + if (!parcel) return; // can_agent_modify_parcel deprecated by GROUPS // if (!can_agent_modify_parcel(parcel)) @@ -499,7 +541,7 @@ void LLFloaterSellLandUI::onConfirmSale(S32 option, void *userdata) } // Send update to server - gParcelMgr->sendParcelPropertiesUpdate( parcel, LLFloaterLand::sRequestReplyOnUpdate ); + gParcelMgr->sendParcelPropertiesUpdate( parcel ); self->close(); } diff --git a/linden/indra/newview/llfloatersellland.h b/linden/indra/newview/llfloatersellland.h index 183ffc4..4131011 100755 --- a/linden/indra/newview/llfloatersellland.h +++ b/linden/indra/newview/llfloatersellland.h @@ -26,15 +26,17 @@ #ifndef LL_LLFLOATERSELLLAND_H #define LL_LLFLOATERSELLLAND_H +#include "llmemory.h" class LLParcel; class LLViewerRegion; +class LLParcelSelection; class LLFloaterSellLand { public: static void sellLand(LLViewerRegion* region, - LLParcel* parcel); + LLHandle parcel); }; #endif // LL_LLFLOATERSELLLAND_H diff --git a/linden/indra/newview/llfloatersnapshot.cpp b/linden/indra/newview/llfloatersnapshot.cpp index 01f86af..cfa94a5 100644 --- a/linden/indra/newview/llfloatersnapshot.cpp +++ b/linden/indra/newview/llfloatersnapshot.cpp @@ -824,21 +824,22 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) //RN: freeze all avatars LLCharacter* avatarp; - for (avatarp = LLCharacter::sInstances.getFirstData(); avatarp; avatarp = LLCharacter::sInstances.getNextData()) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + avatarp = *iter; sInstance->impl.mAvatarPauseHandles.push_back(avatarp->requestPause()); } // freeze everything else gSavedSettings.setBOOL("FreezeTime", TRUE); - if (gCurrentToolset != gCameraToolset) + if (gToolMgr->getCurrentToolset() != gCameraToolset) { - sInstance->impl.mLastToolset = gCurrentToolset; - gCurrentToolset = gCameraToolset; + sInstance->impl.mLastToolset = gToolMgr->getCurrentToolset(); if (gToolMgr) { - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(gCameraToolset); } } } @@ -861,10 +862,9 @@ void LLFloaterSnapshot::Impl::updateLayout(LLFloaterSnapshot* floaterp) // restore last tool (e.g. pie menu, etc) if (sInstance->impl.mLastToolset) { - gCurrentToolset = sInstance->impl.mLastToolset; if (gToolMgr) { - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(sInstance->impl.mLastToolset); } } } @@ -1239,10 +1239,9 @@ LLFloaterSnapshot::~LLFloaterSnapshot() if (impl.mLastToolset) { - gCurrentToolset = impl.mLastToolset; - if (gToolMgr && gCurrentToolset) + if (gToolMgr) { - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->setCurrentToolset(impl.mLastToolset); } } @@ -1432,7 +1431,7 @@ void LLFloaterSnapshot::show(void*) sInstance->impl.updateLayout(sInstance); } - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ sInstance->focusFirstItem(FALSE); gSnapshotFloaterView->setEnabled(TRUE); gSnapshotFloaterView->adjustToFitScreen(sInstance, FALSE); @@ -1506,7 +1505,7 @@ BOOL LLSnapshotFloaterView::handleMouseDown(S32 x, S32 y, MASK mask) // give floater a change to handle mouse, else camera tool if (childrenHandleMouseDown(x, y, mask) == NULL) { - gToolMgr->getCurrentTool(mask)->handleMouseDown( x, y, mask ); + gToolMgr->getCurrentTool()->handleMouseDown( x, y, mask ); } return TRUE; } @@ -1521,7 +1520,7 @@ BOOL LLSnapshotFloaterView::handleMouseUp(S32 x, S32 y, MASK mask) // give floater a change to handle mouse, else camera tool if (childrenHandleMouseUp(x, y, mask) == NULL) { - gToolMgr->getCurrentTool(mask)->handleMouseUp( x, y, mask ); + gToolMgr->getCurrentTool()->handleMouseUp( x, y, mask ); } return TRUE; } @@ -1536,7 +1535,7 @@ BOOL LLSnapshotFloaterView::handleHover(S32 x, S32 y, MASK mask) // give floater a change to handle mouse, else camera tool if (childrenHandleHover(x, y, mask) == NULL) { - gToolMgr->getCurrentTool(mask)->handleHover( x, y, mask ); + gToolMgr->getCurrentTool()->handleHover( x, y, mask ); } return TRUE; } diff --git a/linden/indra/newview/llfloatertelehub.cpp b/linden/indra/newview/llfloatertelehub.cpp index 9fa614c..150e369 100644 --- a/linden/indra/newview/llfloatertelehub.cpp +++ b/linden/indra/newview/llfloatertelehub.cpp @@ -58,8 +58,8 @@ void LLFloaterTelehub::show() sInstance = new LLFloaterTelehub(); // Show tools floater by selecting translate (select) tool - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool( gToolTranslate ); + gToolMgr->setCurrentToolset(gBasicToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolTranslate ); // Find tools floater, glue to bottom if (gFloaterTools) @@ -101,6 +101,8 @@ LLFloaterTelehub::LLFloaterTelehub() // otherwise you can't walk with arrow keys while floater is up list->setAllowKeyboardMovement(FALSE); } + + mObjectSelection = gSelectMgr->getEditSelection(); } LLFloaterTelehub::~LLFloaterTelehub() @@ -123,10 +125,10 @@ void LLFloaterTelehub::draw() // Per-frame updates, because we don't have a selection manager observer. void LLFloaterTelehub::refresh() { - LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLViewerObject* object = mObjectSelection->getFirstRootObject(); if(!object) { - object = gSelectMgr->getFirstObject(); + object = mObjectSelection->getFirstObject(); } BOOL have_selection = (object != NULL); @@ -241,8 +243,8 @@ void LLFloaterTelehub::onClickRemoveSpawnPoint(void* data) msg->nextBlock("ParamList"); msg->addString("Parameter", "spawnpoint remove"); - char buffer[MAX_STRING]; - sprintf(buffer, "%d", spawn_index); + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "%d", spawn_index); /* Flawfinder: ignore */ msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); @@ -260,7 +262,7 @@ void LLFloaterTelehub::processTelehubInfo(LLMessageSystem* msg, void**) void LLFloaterTelehub::unpackTelehubInfo(LLMessageSystem* msg) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ msg->getUUID("TelehubBlock", "ObjectID", mTelehubObjectID); msg->getString("TelehubBlock", "ObjectName", MAX_STRING, buffer); diff --git a/linden/indra/newview/llfloatertelehub.h b/linden/indra/newview/llfloatertelehub.h index ccc75bc..3458998 100644 --- a/linden/indra/newview/llfloatertelehub.h +++ b/linden/indra/newview/llfloatertelehub.h @@ -32,6 +32,7 @@ #include "llfloater.h" class LLMessageSystem; +class LLObjectSelection; const S32 MAX_SPAWNPOINTS_PER_TELEHUB = 16; @@ -69,6 +70,8 @@ private: S32 mNumSpawn; LLVector3 mSpawnPointPos[MAX_SPAWNPOINTS_PER_TELEHUB]; + + LLHandle mObjectSelection; static LLFloaterTelehub* sInstance; }; diff --git a/linden/indra/newview/llfloatertest.cpp b/linden/indra/newview/llfloatertest.cpp index 9f0503b..29c897d 100644 --- a/linden/indra/newview/llfloatertest.cpp +++ b/linden/indra/newview/llfloatertest.cpp @@ -303,7 +303,7 @@ LLFloaterTestImpl::LLFloaterTestImpl() //----------------------------------------------------------------------- // Hook us up with the floater view //----------------------------------------------------------------------- - open(); + open(); /* Flawfinder: ignore */ center(); } diff --git a/linden/indra/newview/llfloatertools.cpp b/linden/indra/newview/llfloatertools.cpp index 05dd70b..f777581 100644 --- a/linden/indra/newview/llfloatertools.cpp +++ b/linden/indra/newview/llfloatertools.cpp @@ -264,7 +264,7 @@ BOOL LLFloaterTools::postBuild() &LLToolPlacerPanel::sTriangleTorus, &LLToolPlacerPanel::sTree, &LLToolPlacerPanel::sGrass}; - for(int t=0;tbuildFloater(this,"floater_tools.xml",&factory_map); + gUICtrlFactory->buildFloater(this,"floater_tools.xml",&factory_map,FALSE); mLargeHeight = getRect().getHeight(); mSmallHeight = mLargeHeight; @@ -478,7 +478,7 @@ void LLFloaterTools::resetToolState() void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) { - LLTool *tool = gToolMgr->getCurrentTool( mask ); + LLTool *tool = gToolMgr->getCurrentTool(); // HACK to allow seeing the buttons when you have the app in a window. // Keep the visibility the same as it @@ -579,7 +579,7 @@ void LLFloaterTools::updatePopup(LLCoordGL center, MASK mask) S32 index = mComboGridMode->getCurrentIndex(); mComboGridMode->removeall(); - switch (gSelectMgr->getSelectType()) + switch (mObjectSelection->getSelectType()) { case SELECT_TYPE_HUD: mComboGridMode->add("Screen"); @@ -726,6 +726,13 @@ BOOL LLFloaterTools::canClose() } // virtual +void LLFloaterTools::onOpen() +{ + mParcelSelection = gParcelMgr->getFloatingParcelSelection(); + mObjectSelection = gSelectMgr->getEditSelection(); +} + +// virtual void LLFloaterTools::onClose(bool app_quitting) { setMinimized(FALSE); @@ -744,10 +751,14 @@ void LLFloaterTools::onClose(bool app_quitting) resetToolState(); + mParcelSelection = NULL; + mObjectSelection = NULL; + // Switch back to basic toolset - gCurrentToolset = gBasicToolset; - gBasicToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gBasicToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); + // we were already in basic toolset, using build tools + // so manually reset tool to default (pie menu tool) + gToolMgr->getCurrentToolset()->selectFirstTool(); } void LLFloaterTools::showMore(BOOL show_more) @@ -955,6 +966,5 @@ void LLFloaterTools::setEditTool(void* tool_pointer) void LLFloaterTools::onFocusReceived() { - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool(gCurrentToolset->getSelectedTool()); -} \ No newline at end of file + gToolMgr->setCurrentToolset(gBasicToolset); +} diff --git a/linden/indra/newview/llfloatertools.h b/linden/indra/newview/llfloatertools.h index a6c4ceb..664aa62 100644 --- a/linden/indra/newview/llfloatertools.h +++ b/linden/indra/newview/llfloatertools.h @@ -44,6 +44,11 @@ class LLPanelFace; class LLPanelLandInfo; class LLComboBox; class LLVolumeSliderCtrl; +class LLParcelSelection; +class LLObjectSelection; + +typedef LLHandle LLParcelSelectionHandle; +typedef LLHandle LLObjectSelectionHandle; class LLFloaterTools : public LLFloater @@ -61,6 +66,7 @@ public: LLFloaterTools(); virtual ~LLFloaterTools(); + virtual void onOpen(); virtual void onClose(bool app_quitting); virtual BOOL canClose(); @@ -175,7 +181,10 @@ public: LLPanelLandInfo *mPanelLandInfo; LLTabContainer* mTabLand; - + + LLParcelSelectionHandle mParcelSelection; + LLObjectSelectionHandle mObjectSelection; + private: BOOL mDirty; S32 mSmallHeight; diff --git a/linden/indra/newview/llfloatertopobjects.cpp b/linden/indra/newview/llfloatertopobjects.cpp index 093b840..7c86e83 100644 --- a/linden/indra/newview/llfloatertopobjects.cpp +++ b/linden/indra/newview/llfloatertopobjects.cpp @@ -160,8 +160,8 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data) LLUUID task_id; F32 location_x, location_y, location_z; F32 score; - char name_buf[MAX_STRING]; - char owner_buf[MAX_STRING]; + char name_buf[MAX_STRING]; /* Flawfinder: ignore */ + char owner_buf[MAX_STRING]; /* Flawfinder: ignore */ msg->getU32Fast(_PREHASH_ReportData, _PREHASH_TaskLocalID, task_local_id, block); msg->getUUIDFast(_PREHASH_ReportData, _PREHASH_TaskID, task_id, block); @@ -250,7 +250,7 @@ void LLFloaterTopObjects::updateSelectionInfo() LLUUID object_id = list->getCurrentID(); if (object_id.isNull()) return; - LLString object_id_string = object_id.getString(); + std::string object_id_string = object_id.asString(); childSetValue("id_editor", LLSD(object_id_string)); childSetValue("object_name_editor", list->getFirstSelected()->getColumn(1)->getText()); diff --git a/linden/indra/newview/llfloatertos.cpp b/linden/indra/newview/llfloatertos.cpp index 35b4531..26346d5 100644 --- a/linden/indra/newview/llfloatertos.cpp +++ b/linden/indra/newview/llfloatertos.cpp @@ -125,9 +125,9 @@ BOOL LLFloaterTOS::postBuild() childSetAction("Cancel", onCancel, this); childSetCommitCallback("tos_agreement", updateAgree, this); - // this displays the critical message if ( mType != TOS_TOS ) { + // this displays the critical message LLTextEditor *Editor = LLUICtrlFactory::getTextEditorByName(this, "tos_text"); if (Editor) { @@ -137,25 +137,11 @@ BOOL LLFloaterTOS::postBuild() Editor->setWordWrap(TRUE); Editor->setFocus(TRUE); } - childSetValue("tos_text", LLSD(mMessage)); - }; - - // this displays the critical message - if ( mType != TOS_TOS ) - { - LLTextEditor *Editor = LLUICtrlFactory::getTextEditorByName(this, "tos_text"); - if (Editor) - { - Editor->setHandleEditKeysDirectly( TRUE ); - Editor->setEnabled( FALSE ); - Editor->setReadOnlyFgColor(LLColor4::white); - Editor->setWordWrap(TRUE); - Editor->setFocus(TRUE); - } - childSetValue("tos_text", LLSD(mMessage)); - }; + childSetValue("tos_text", LLSD(mMessage)); + return TRUE; + } - #if LL_LIBXUL_ENABLED +#if LL_LIBXUL_ENABLED // disable Agree to TOS radio button until the page has fully loaded LLRadioGroup* tos_agreement = LLUICtrlFactory::getRadioGroupByName(this, "tos_agreement"); if ( tos_agreement ) @@ -163,19 +149,26 @@ BOOL LLFloaterTOS::postBuild() tos_agreement->setEnabled( false ); }; + // hide the SL text widget if we're displaying TOS with using a browser widget. + LLTextEditor *editor = LLUICtrlFactory::getTextEditorByName(this, "tos_text"); + if ( editor ) + { + editor->setVisible( FALSE ); + }; + LLWebBrowserCtrl* web_browser = LLUICtrlFactory::getWebBrowserCtrlByName(this, "tos_html"); if ( web_browser ) { // start to observe it so we see navigate complete events if ( web_browser ) { - web_browser->addObserver( this ); + web_browser->addObserver( this ); }; gResponsePtr = LLIamHere::build( this ); LLHTTPClient::get( childGetValue( "real_url" ).asString(), gResponsePtr ); }; - #else +#else LLTextEditor *Editor = LLUICtrlFactory::getTextEditorByName(this, "tos_text"); if (Editor) { @@ -186,7 +179,8 @@ BOOL LLFloaterTOS::postBuild() Editor->setFocus(TRUE); } childSetValue("tos_text", LLSD(mMessage)); - #endif +#endif + return TRUE; } diff --git a/linden/indra/newview/llfloaterworldmap.cpp b/linden/indra/newview/llfloaterworldmap.cpp index af0e5c0..967e6d0 100644 --- a/linden/indra/newview/llfloaterworldmap.cpp +++ b/linden/indra/newview/llfloaterworldmap.cpp @@ -312,7 +312,7 @@ void LLFloaterWorldMap::show(void*, BOOL center_on_target) BOOL was_visible = gFloaterWorldMap->getVisible(); gFloaterWorldMap->mIsClosing = FALSE; - gFloaterWorldMap->open(); + gFloaterWorldMap->open(); /* Flawfinder: ignore */ LLWorldMapView* map_panel; map_panel = (LLWorldMapView*)gFloaterWorldMap->mTabs->getCurrentPanel(); @@ -458,6 +458,14 @@ void LLFloaterWorldMap::draw() return; } + // On orientation island, users don't have a home location yet, so don't + // let them teleport "home". It dumps them in an often-crowed welcome + // area (infohub) and they get confused. JC + LLViewerRegion* regionp = gAgent.getRegion(); + bool agent_on_prelude = (regionp && regionp->isPrelude()); + bool enable_go_home = gAgent.isGodlike() || !agent_on_prelude; + childSetEnabled("Go Home", enable_go_home); + updateLocation(); LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); diff --git a/linden/indra/newview/llfloaterworldmap.h b/linden/indra/newview/llfloaterworldmap.h index 67386c9..4b812b6 100644 --- a/linden/indra/newview/llfloaterworldmap.h +++ b/linden/indra/newview/llfloaterworldmap.h @@ -56,18 +56,18 @@ public: static void *createWorldMapView(void* data); BOOL postBuild(); - virtual void onClose(bool app_quitting); + /*virtual*/ void onClose(bool app_quitting); static void show(void*, BOOL center_on_target ); static void reloadIcons(void*); static void toggle(void*); static void hide(void*); - virtual void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE ); - virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); - virtual void setVisible(BOOL visible); - virtual void draw(); + /*virtual*/ void reshape( S32 width, S32 height, BOOL called_from_parent = TRUE ); + /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); + /*virtual*/ BOOL handleScrollWheel(S32 x, S32 y, S32 clicks); + /*virtual*/ void setVisible(BOOL visible); + /*virtual*/ void draw(); // methods for dealing with inventory. The observe() method is // called during program startup. inventoryUpdated() will be diff --git a/linden/indra/newview/llfolderview.cpp b/linden/indra/newview/llfolderview.cpp index 431f212..377e620 100644 --- a/linden/indra/newview/llfolderview.cpp +++ b/linden/indra/newview/llfolderview.cpp @@ -327,10 +327,10 @@ void LLFolderViewItem::arrangeFromRoot() // UI. If open is TRUE, then folders are opened up along the way to // the selection. void LLFolderViewItem::setSelectionFromRoot(LLFolderViewItem* selection, - BOOL open, + BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus) { - getRoot()->setSelection(selection, open, take_keyboard_focus); + getRoot()->setSelection(selection, open, take_keyboard_focus); /* Flawfinder: ignore */ } // helper function to change the selection from the root. @@ -534,7 +534,7 @@ void LLFolderViewItem::buildContextMenu(LLMenuGL& menu, U32 flags) } } -void LLFolderViewItem::open( void ) +void LLFolderViewItem::open( void ) /* Flawfinder: ignore */ { if( mListener ) { @@ -1365,7 +1365,7 @@ BOOL LLFolderViewFolder::hasFilteredDescendants() // Passes selection information on to children and record selection // information if necessary. -BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL open, +BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus) { BOOL rv = FALSE; @@ -1389,7 +1389,7 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL open, iter != mFolders.end();) { folders_t::iterator fit = iter++; - if((*fit)->setSelection(selection, open, take_keyboard_focus)) + if((*fit)->setSelection(selection, open, take_keyboard_focus)) /* Flawfinder: ignore */ { rv = TRUE; child_selected = TRUE; @@ -1400,14 +1400,14 @@ BOOL LLFolderViewFolder::setSelection(LLFolderViewItem* selection, BOOL open, iter != mItems.end();) { items_t::iterator iit = iter++; - if((*iit)->setSelection(selection, open, take_keyboard_focus)) + if((*iit)->setSelection(selection, open, take_keyboard_focus)) /* Flawfinder: ignore */ { rv = TRUE; child_selected = TRUE; mNumDescendantsSelected++; } } - if(open && child_selected) + if(open && child_selected) /* Flawfinder: ignore */ { setOpenArrangeRecursively(TRUE); } @@ -1964,16 +1964,16 @@ void LLFolderViewFolder::toggleOpen() } // Force a folder open or closed -void LLFolderViewFolder::setOpen(BOOL open) +void LLFolderViewFolder::setOpen(BOOL open) /* Flawfinder: ignore */ { - setOpenArrangeRecursively(open); + setOpenArrangeRecursively(open); /* Flawfinder: ignore */ } -void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recurse) +void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recurse) /* Flawfinder: ignore */ { BOOL was_open = mIsOpen; - mIsOpen = open; - if(!was_open && open) + mIsOpen = open; /* Flawfinder: ignore */ + if(!was_open && open) /* Flawfinder: ignore */ { if(mListener) { @@ -1986,12 +1986,12 @@ void LLFolderViewFolder::setOpenArrangeRecursively(BOOL open, ERecurseType recur iter != mFolders.end();) { folders_t::iterator fit = iter++; - (*fit)->setOpenArrangeRecursively(open, RECURSE_DOWN); + (*fit)->setOpenArrangeRecursively(open, RECURSE_DOWN); /* Flawfinder: ignore */ } } if (mParentFolder && (recurse == RECURSE_UP || recurse == RECURSE_UP_DOWN)) { - mParentFolder->setOpenArrangeRecursively(open, RECURSE_UP); + mParentFolder->setOpenArrangeRecursively(open, RECURSE_UP); /* Flawfinder: ignore */ } if (was_open != mIsOpen) @@ -2024,7 +2024,7 @@ BOOL LLFolderViewFolder::handleDragAndDropFromChild(MASK mask, return TRUE; } -void LLFolderViewFolder::open( void ) +void LLFolderViewFolder::open( void ) /* Flawfinder: ignore */ { toggleOpen(); } @@ -2713,10 +2713,10 @@ void LLFolderView::openFolder(const LLString& foldername) } } -void LLFolderView::setOpenArrangeRecursively(BOOL open, ERecurseType recurse) +void LLFolderView::setOpenArrangeRecursively(BOOL open, ERecurseType recurse) /* Flawfinder: ignore */ { // call base class to do proper recursion - LLFolderViewFolder::setOpenArrangeRecursively(open, recurse); + LLFolderViewFolder::setOpenArrangeRecursively(open, recurse); /* Flawfinder: ignore */ // make sure root folder is always open mIsOpen = TRUE; } @@ -2892,7 +2892,7 @@ LLFolderViewItem* LLFolderView::getCurSelectedItem( void ) // Record the selected item and pass it down the hierachy. -BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open, +BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus) { if( selection == this ) @@ -2914,8 +2914,8 @@ BOOL LLFolderView::setSelection(LLFolderViewItem* selection, BOOL open, addToSelectionList(selection); } - BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); - if(open) + BOOL rv = LLFolderViewFolder::setSelection(selection, open, take_keyboard_focus); /* Flawfinder: ignore */ + if(open) /* Flawfinder: ignore */ { selection->getParentFolder()->requestArrange(); } @@ -3331,7 +3331,7 @@ void LLFolderView::openSelectedItems( void ) { if (mSelectedItems.size() == 1) { - mSelectedItems.front()->open(); + mSelectedItems.front()->open(); /* Flawfinder: ignore */ } else { @@ -3345,11 +3345,11 @@ void LLFolderView::openSelectedItems( void ) selected_items_t::iterator item_it; for (item_it = mSelectedItems.begin(); item_it != mSelectedItems.end(); ++item_it) { - (*item_it)->open(); + (*item_it)->open(); /* Flawfinder: ignore */ } LLFloater::setFloaterHost(NULL); - multi_previewp->open(); + multi_previewp->open(); /* Flawfinder: ignore */ } } } @@ -3380,7 +3380,7 @@ void LLFolderView::propertiesSelectedItems( void ) } LLFloater::setFloaterHost(NULL); - multi_propertiesp->open(); + multi_propertiesp->open(); /* Flawfinder: ignore */ } } } @@ -3858,34 +3858,8 @@ BOOL LLFolderView::handleKeyHere( KEY key, MASK mask, BOOL called_from_parent ) search(getCurSelectedItem(), mSearchString.c_str(), FALSE); handled = TRUE; } - else if (mask & MASK_CONTROL && key == 'N') - { - LLFolderViewItem* selection = getCurSelectedItem(); - if (selection) - { - selection = selection->getNextOpenNode(); - } - search(selection, mSearchString.c_str(), FALSE); - mSearchTimer.reset(); - handled = TRUE; - } - else if (mask & MASK_CONTROL && key == 'P') - { - LLFolderViewItem* selection = getCurSelectedItem(); - if (selection) - { - selection = selection->getPreviousOpenNode(); - } - search(selection, mSearchString.c_str(), TRUE); - mSearchTimer.reset(); - handled = TRUE; - } } - if (handled) - { - gViewerWindow->requestFastFrame(this); - } return handled; } @@ -3921,11 +3895,6 @@ BOOL LLFolderView::handleUnicodeCharHere(llwchar uni_char, BOOL called_from_pare handled = TRUE; } - if (handled) - { - gViewerWindow->requestFastFrame(this); - } - return handled; } @@ -4078,7 +4047,7 @@ BOOL LLFolderView::handleRightMouseDown( S32 x, S32 y, MASK mask ) } menu->arrange(); - menu->updateParent(gMenuHolder); + menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); } else @@ -4499,14 +4468,15 @@ std::string::size_type LLInventoryFilter::getStringMatchOffset() const return mSubStringMatchOffset; } +// has user modified default filter params? BOOL LLInventoryFilter::isActive() { - return mFilterOps.mFilterTypes != 0xffffffff + return mFilterOps.mFilterTypes != mDefaultFilterOps.mFilterTypes || mFilterSubString.size() - || mFilterOps.mPermissions != PERM_NONE - || mFilterOps.mMinDate != 0 - || mFilterOps.mMaxDate != U32_MAX - || mFilterOps.mHoursAgo != 0; + || mFilterOps.mPermissions != mDefaultFilterOps.mPermissions + || mFilterOps.mMinDate != mDefaultFilterOps.mMinDate + || mFilterOps.mMaxDate != mDefaultFilterOps.mMaxDate + || mFilterOps.mHoursAgo != mDefaultFilterOps.mHoursAgo; } BOOL LLInventoryFilter::isModified() diff --git a/linden/indra/newview/llfolderview.h b/linden/indra/newview/llfolderview.h index a63ae26..ccadba9 100644 --- a/linden/indra/newview/llfolderview.h +++ b/linden/indra/newview/llfolderview.h @@ -317,7 +317,7 @@ protected: // the specified selected item appropriately for display and use // in the UI. If open is TRUE, then folders are opened up along // the way to the selection. - void setSelectionFromRoot(LLFolderViewItem* selection, BOOL open, + void setSelectionFromRoot(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus = TRUE); // helper function to change the selection from the root. @@ -366,7 +366,7 @@ public: // ignore. Returns TRUE if this object was affected. If open is // TRUE, then folders are opened up along the way to the // selection. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus); // This method is used to toggle the selection of an item. If @@ -433,7 +433,7 @@ public: void rename(const LLString& new_name); // open - virtual void open( void ); + virtual void open( void ); /* Flawfinder: ignore */ virtual void preview(void); // Show children (unfortunate that this is called "open") @@ -558,7 +558,7 @@ public: // Passes selection information on to children and record // selection information if necessary. Returns TRUE if this object // (or a child) was affected. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus); // This method is used to change the selection of an item. If @@ -612,7 +612,7 @@ public: virtual void toggleOpen(); // Force a folder open or closed - virtual void setOpen(BOOL open = TRUE); + virtual void setOpen(BOOL open = TRUE); /* Flawfinder: ignore */ // Called when a child is refreshed. virtual void requestArrange(); @@ -621,7 +621,7 @@ public: // method was written because the list iterators destroy the state // of other iterations, thus, we can't arrange while iterating // through the children (such as when setting which is selected. - virtual void setOpenArrangeRecursively(BOOL open, ERecurseType recurse = RECURSE_NO); + virtual void setOpenArrangeRecursively(BOOL open, ERecurseType recurse = RECURSE_NO); /* Flawfinder: ignore */ // Get the current state of the folder. virtual BOOL isOpen() { return mIsOpen; } @@ -637,7 +637,7 @@ public: void applyFunctorRecursively(LLFolderViewFunctor& functor); virtual void applyListenerFunctorRecursively(LLFolderViewListenerFunctor& functor); - virtual void open( void ); + virtual void open( void ); /* Flawfinder: ignore */ virtual BOOL addItem(LLFolderViewItem* item); virtual BOOL addFolder( LLFolderViewFolder* folder); @@ -705,7 +705,7 @@ public: void openFolder(const LLString& foldername); virtual void toggleOpen() {}; - virtual void setOpenArrangeRecursively(BOOL open, ERecurseType recurse); + virtual void setOpenArrangeRecursively(BOOL open, ERecurseType recurse); /* Flawfinder: ignore */ virtual BOOL addFolder( LLFolderViewFolder* folder); // Finds width and height of this object and it's children. Also @@ -722,7 +722,7 @@ public: virtual LLFolderViewItem* getCurSelectedItem( void ); // Record the selected item and pass it down the hierachy. - virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, + virtual BOOL setSelection(LLFolderViewItem* selection, BOOL open, /* Flawfinder: ignore */ BOOL take_keyboard_focus); // This method is used to toggle the selection of an item. Walks @@ -817,7 +817,6 @@ public: static void idle(void* user_data); - void setAutoSelectOverride(bool override) { mAutoSelectOverride = override; } BOOL needsAutoSelect() { return mNeedsAutoSelect && !mAutoSelectOverride; } BOOL getDebugFilters() { return mDebugFilters; } diff --git a/linden/indra/newview/llframestats.cpp b/linden/indra/newview/llframestats.cpp index cd49e7d..237f59b 100644 --- a/linden/indra/newview/llframestats.cpp +++ b/linden/indra/newview/llframestats.cpp @@ -168,7 +168,7 @@ void LLFrameStats::dump() S32 total_visible_objects = 0; time_t cur_time; - char time_str[24]; + char time_str[24]; /* Flawfinder: ignore */ //char *time_str; time(&cur_time); strftime(time_str, 24, "%Y.%m.%d %H:%M:%S", localtime(&cur_time)); @@ -177,13 +177,13 @@ void LLFrameStats::dump() static S32 dump_count = 0; - char file_with_num[256]; - sprintf(file_with_num, "fs%d.txt", dump_count); + char file_with_num[256]; /* Flawfinder: ignore */ + snprintf(file_with_num, sizeof(file_with_num), "fs%d.txt", dump_count); /* Flawfinder: ignore */ dump_count++; - char filename[LL_MAX_PATH]; - sprintf(filename, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_with_num).c_str()); - FILE *fp = LLFile::fopen(filename, "w"); + char filename[LL_MAX_PATH]; /* Flawfinder: ignore */ + snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, file_with_num).c_str()); /* Flawfinder: ignore */ + FILE *fp = LLFile::fopen(filename, "w"); /* Flawfinder: ignore */ if (!fp) { llinfos << "Couldn't open file for dumping frame stats!" << llendl; @@ -224,8 +224,8 @@ void LLFrameStats::dump() fclose(fp); // Now dump cumulative stats - sprintf(filename, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, mSummaryFilename.c_str()).c_str()); - fp = LLFile::fopen(filename, "a"); + snprintf(filename, LL_MAX_PATH, "%s", gDirUtilp->getExpandedFilename(LL_PATH_LOGS, mSummaryFilename.c_str()).c_str()); /* Flawfinder: ignore */ + fp = LLFile::fopen(filename, "a"); /* Flawfinder: ignore */ if (!fp) { llinfos << "Couldn't open file for dumping frame stats!" << llendl; diff --git a/linden/indra/newview/llframestatview.cpp b/linden/indra/newview/llframestatview.cpp index d17d51e..e0c1cc7 100644 --- a/linden/indra/newview/llframestatview.cpp +++ b/linden/indra/newview/llframestatview.cpp @@ -198,7 +198,7 @@ void LLFrameStatView::draw() // Draw ticks for the "Average bar" F32 tick_value; - char tick_label[256]; + char tick_label[256]; /* Flawfinder: ignore */ for (tick_value = 0; tick_value <= 100; tick_value += 10) { left = 10 + llfloor(tick_value*(total_width/100.f)); @@ -215,7 +215,7 @@ void LLFrameStatView::draw() right = left + 1; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.2f)); - sprintf(tick_label, "%.2f", tick_value); + snprintf(tick_label, sizeof(tick_label), "%.2f", tick_value); /* Flawfinder: ignore */ // draw labels for the tick marks LLFontGL::sMonospace->renderUTF8(tick_label, 0, left, bottom, LLColor4(1.f, 1.f, 1.f, 0.5f), @@ -265,7 +265,7 @@ void LLFrameStatView::draw() right = left + 1; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f)); - sprintf(tick_label, "%.2f", tick_value); + snprintf(tick_label, sizeof(tick_label), "%.2f", tick_value); /* Flawfinder: ignore */ // draw labels for the tick marks LLFontGL::sMonospace->renderUTF8(tick_label, 0, left, bottom, LLColor4(1.f, 1.f, 1.f, 0.5f), @@ -290,7 +290,7 @@ void LLFrameStatView::draw() right = left + 1; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f)); - sprintf(tick_label, "%.2f", tick_value); + snprintf(tick_label, sizeof(tick_label), "%.2f", tick_value); /* Flawfinder: ignore */ // draw labels for the tick marks LLFontGL::sMonospace->renderUTF8(tick_label, 0, left, bottom, LLColor4(1.f, 1.f, 1.f, 0.5f), diff --git a/linden/indra/newview/llframestatview.h b/linden/indra/newview/llframestatview.h index 35d63b1..465b238 100644 --- a/linden/indra/newview/llframestatview.h +++ b/linden/indra/newview/llframestatview.h @@ -64,7 +64,7 @@ public: private: LLStat *mStats[MAX_STATS]; LLColor4 mColors[MAX_STATS]; - const char *mLabels[MAX_STATS]; + const char *mLabels[MAX_STATS]; /* Flawfinder: ignore */ S32 mNumStats; }; diff --git a/linden/indra/newview/llgenepool.cpp b/linden/indra/newview/llgenepool.cpp index 33cb70d..2a2c864 100644 --- a/linden/indra/newview/llgenepool.cpp +++ b/linden/indra/newview/llgenepool.cpp @@ -56,10 +56,10 @@ LLGenePool::~LLGenePool() BOOL LLGenePool::load() { - char filename[MAX_PATH]; - - strcpy(filename,gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"genepool.xml").c_str()); + char filename[MAX_PATH]; /*Flawfinder: ignore*/ + strncpy(filename,gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"genepool.xml").c_str(), sizeof(filename) -1); /*Flawfinder: ignore*/ + filename[sizeof(filename) -1] = '\0'; if( mLoaded ) { return TRUE; diff --git a/linden/indra/newview/llgesturemgr.cpp b/linden/indra/newview/llgesturemgr.cpp index 8f906d9..76a2ca7 100644 --- a/linden/indra/newview/llgesturemgr.cpp +++ b/linden/indra/newview/llgesturemgr.cpp @@ -875,7 +875,13 @@ void LLGestureManager::onLoadComplete(LLVFS *vfs, S32 size = file.getSize(); char* buffer = new char[size+1]; - file.read((U8*)buffer, size); + if (buffer == NULL) + { + llerrs << "Memory Allocation Failed" << llendl; + return; + } + + file.read((U8*)buffer, size); /* Flawfinder: ignore */ // ensure there's a trailing NULL so strlen will work. buffer[size] = '\0'; diff --git a/linden/indra/newview/llgivemoney.cpp b/linden/indra/newview/llgivemoney.cpp index d3c7598..0baf1f3 100644 --- a/linden/indra/newview/llgivemoney.cpp +++ b/linden/indra/newview/llgivemoney.cpp @@ -91,6 +91,7 @@ LLFloaterPay::LLFloaterPay(const std::string& name, if (target_is_object) { gUICtrlFactory->buildFloater(this,"floater_pay_object.xml"); + mObjectSelection = gSelectMgr->getEditSelection(); } else { @@ -166,13 +167,16 @@ LLFloaterPay::LLFloaterPay(const std::string& name, childSetAction("cancel btn",&LLFloaterPay::onCancel,this); center(); - open(); + open(); /*Flawfinder: ignore*/ } // Destroys the object LLFloaterPay::~LLFloaterPay() { std::for_each(mCallbackData.begin(), mCallbackData.end(), DeletePointer()); + + // Clean up if we are still waiting for a name. + gCacheName->cancelCallback(mTargetUUID,onCacheOwnerName,this); } // static @@ -314,11 +318,16 @@ void LLFloaterPay::payViaObject(money_callback callback, const LLUUID& object_id LLViewerObject* object = gObjectList.findObject(object_id); if (!object) return; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); - if (!node) return; - LLFloaterPay *floater = new LLFloaterPay("Give Money", callback, object_id, TRUE); if (!floater) return; + + LLSelectNode* node = floater->mObjectSelection->getFirstRootNode(); + if (!node) + { + //FIXME: notify user object no longer exists + floater->close(); + return; + } LLHost target_region = object->getRegion()->getHost(); @@ -361,7 +370,7 @@ void LLFloaterPay::payDirectly(money_callback callback, void LLFloaterPay::finishPayUI(const LLUUID& target_id, BOOL is_group) { gCacheName->get(target_id, is_group, onCacheOwnerName, (void*)this); - + // Make sure the amount field has focus childSetFocus("amount", TRUE); @@ -402,10 +411,6 @@ void LLFloaterPay::onCancel(void* data) LLFloaterPay* self = reinterpret_cast(data); if(self) { - if (self->mTargetIsObject) - { - gSelectMgr->deselectAll(); - } self->close(); } } @@ -460,7 +465,7 @@ void LLFloaterPay::give(S32 amount) if (region) { // Find the name of the root object - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = mObjectSelection->getFirstRootNode(); LLString object_name; if (node) { @@ -469,7 +474,7 @@ void LLFloaterPay::give(S32 amount) S32 tx_type = TRANS_PAY_OBJECT; if(dest_object->isAvatar()) tx_type = TRANS_GIFT; mCallback(mTargetUUID, region, amount, FALSE, tx_type, object_name); - gSelectMgr->deselectAll(); + mObjectSelection = NULL; } } } diff --git a/linden/indra/newview/llgivemoney.h b/linden/indra/newview/llgivemoney.h index 0edb735..cff4fb7 100644 --- a/linden/indra/newview/llgivemoney.h +++ b/linden/indra/newview/llgivemoney.h @@ -40,6 +40,7 @@ class LLViewerRegion; class LLLineEditor; class LLTextBox; class LLButton; +class LLObjectSelection; struct LLGiveMoneyInfo; typedef void (*money_callback)(const LLUUID&, LLViewerRegion*,S32,BOOL,S32,const LLString&); @@ -85,10 +86,13 @@ protected: LLUUID mTargetUUID; BOOL mTargetIsObject; BOOL mTargetIsGroup; + BOOL mHaveName; LLButton* mQuickPayButton[MAX_PAY_BUTTONS]; LLGiveMoneyInfo* mQuickPayInfo[MAX_PAY_BUTTONS]; + LLHandle mObjectSelection; + static S32 sLastAmount; }; diff --git a/linden/indra/newview/llglsandbox.cpp b/linden/indra/newview/llglsandbox.cpp index cc4ec9d..decbdd9 100644 --- a/linden/indra/newview/llglsandbox.cpp +++ b/linden/indra/newview/llglsandbox.cpp @@ -181,15 +181,17 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance"); select_dist_squared = select_dist_squared * select_dist_squared; - x = llround((F32)x * LLUI::sGLScaleFactor.mV[VX]); - y = llround((F32)y * LLUI::sGLScaleFactor.mV[VY]); - BOOL deselect = (mask == MASK_CONTROL); S32 left = llmin(x, mDragStartX); S32 right = llmax(x, mDragStartX); S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); + left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]); + right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]); + top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]); + bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]); + F32 old_far_plane = gCamera->getFar(); F32 old_near_plane = gCamera->getNear(); @@ -245,9 +247,11 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) if (shrink_selection) { - for (LLViewerObject* vobjp = gSelectMgr->getFirstHighlightedObject(); + LLObjectSelectionHandle highlighted_objects = gSelectMgr->getHighlightedObjects(); + + for (LLViewerObject* vobjp = highlighted_objects->getFirstObject(); vobjp; - vobjp = gSelectMgr->getNextHighlightedObject()) + vobjp = highlighted_objects->getNextObject()) { LLDrawable* drawable = vobjp->mDrawable; if (!drawable || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment()) @@ -255,7 +259,7 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) continue; } - S32 result = gCamera->sphereInFrustum(drawable->getWorldPosition(), drawable->getRadius()); + S32 result = gCamera->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); switch (result) { case 0: @@ -278,11 +282,16 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) { std::vector potentials; - if (gPipeline.mObjectPartition) + + for (U32 i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++) { - gPipeline.mObjectPartition->cull(*gCamera, &potentials, TRUE); + LLSpatialPartition* part = gPipeline.getSpatialPartition(i); + if (part) + { + part->cull(*gCamera, &potentials, TRUE); + } } - + for (std::vector::iterator iter = potentials.begin(); iter != potentials.end(); iter++) { @@ -302,7 +311,7 @@ void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) continue; } - S32 result = gCamera->sphereInFrustum(drawable->getWorldPosition(), drawable->getRadius()); + S32 result = gCamera->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); if (result) { switch (result) @@ -956,119 +965,6 @@ void LLViewerParcelMgr::renderCollisionSegments(U8* segments, BOOL use_pass, LLV glEnd(); } - -const S32 CLIENT_RECT_VPAD = 4; -void LLPreviewTexture::draw() -{ - if( getVisible() ) - { - updateAspectRatio(); - - LLPreview::draw(); - - if (!mMinimized) - { - LLGLSUIDefault gls_ui; - LLGLSNoTexture gls_notex; - - const LLRect& border = mClientRect; - LLRect interior = mClientRect; - interior.stretch( -PREVIEW_BORDER_WIDTH ); - - // ...border - gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f)); - gl_rect_2d_checkerboard( interior ); - - if ( mImage.notNull() ) - { - LLGLSTexture gls_no_texture; - // Draw the texture - glColor3f( 1.f, 1.f, 1.f ); - gl_draw_scaled_image(interior.mLeft, - interior.mBottom, - interior.getWidth(), - interior.getHeight(), - mImage); - - // Pump the texture priority - F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); - mImage->addTextureStats( pixel_area ); - - // Don't bother decoding more than we can display, unless - // we're loading the full image. - if (!mLoadingFullImage) - { - S32 int_width = interior.getWidth(); - S32 int_height = interior.getHeight(); - mImage->setKnownDrawSize(int_width, int_height); - } - else - { - // Don't use this feature - mImage->setKnownDrawSize(0, 0); - } - - if( mLoadingFullImage ) - { - LLFontGL::sSansSerif->renderUTF8("Receiving:", 0, - interior.mLeft + 4, - interior.mBottom + 4, - LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, - LLFontGL::DROP_SHADOW); - - F32 data_progress = 0.0f; - F32 decode_progress = mImage->getDecodeProgress(&data_progress); - - // Draw the progress bar. - const S32 BAR_HEIGHT = 12; - const S32 BAR_LEFT_PAD = 80; - S32 left = interior.mLeft + 4 + BAR_LEFT_PAD; - S32 bar_width = mRect.getWidth() - left - RESIZE_HANDLE_WIDTH - 2; - S32 top = interior.mBottom + 4 + BAR_HEIGHT; - S32 right = left + bar_width; - S32 bottom = top - BAR_HEIGHT; - - LLColor4 background_color(0.f, 0.f, 0.f, 0.75f); - LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f); - LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f); - - gl_rect_2d(left, top, right, bottom, background_color); - - if (data_progress > 0.0f) - { - // Decoded bytes - right = left + llfloor(decode_progress * (F32)bar_width); - - if (left < right) - { - gl_rect_2d(left, top, right, bottom, decoded_color); - } - - // Downloaded bytes - left = right; - right = left + llfloor((data_progress - decode_progress) * (F32)bar_width); - - if (left < right) - { - gl_rect_2d(left, top, right, bottom, downloaded_color); - } - } - } - else - if( !mSavedFileTimer.hasExpired() ) - { - LLFontGL::sSansSerif->renderUTF8("File Saved", 0, - interior.mLeft + 4, - interior.mBottom + 4, - LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, - LLFontGL::DROP_SHADOW); - } - } - } - } -} - - void draw_line_cube(F32 width, const LLVector3& center) { width = 0.5f * width; diff --git a/linden/indra/newview/llgroupmgr.cpp b/linden/indra/newview/llgroupmgr.cpp index 35e1b95..d020236 100644 --- a/linden/indra/newview/llgroupmgr.cpp +++ b/linden/indra/newview/llgroupmgr.cpp @@ -820,8 +820,8 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data) if (group_datap->mMemberCount > 0) { S32 contribution = 0; - char online_status[DB_DATETIME_BUF_SIZE]; - char title[DB_GROUP_TITLE_BUF_SIZE]; + char online_status[DB_DATETIME_BUF_SIZE]; /* Flawfinder: ignore */ + char title[DB_GROUP_TITLE_BUF_SIZE]; /* Flawfinder: ignore */ U64 agent_powers = 0; BOOL is_owner = FALSE; @@ -862,7 +862,7 @@ void LLGroupMgr::processGroupMembersReply(LLMessageSystem* msg, void** data) } } - if (group_datap->mMembers.size() == group_datap->mMemberCount) + if (group_datap->mMembers.size() == (U32)group_datap->mMemberCount) { group_datap->mMemberDataComplete = TRUE; group_datap->mMemberRequestID.setNull(); @@ -892,13 +892,13 @@ void LLGroupMgr::processGroupPropertiesReply(LLMessageSystem* msg, void** data) } LLUUID group_id; - char name[DB_GROUP_NAME_BUF_SIZE]; - char charter[DB_GROUP_CHARTER_BUF_SIZE]; + char name[DB_GROUP_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char charter[DB_GROUP_CHARTER_BUF_SIZE]; /* Flawfinder: ignore */ BOOL show_in_list = FALSE; LLUUID founder_id; U64 powers_mask = GP_NO_POWERS; S32 money = 0; - char member_title[DB_GROUP_TITLE_BUF_SIZE]; + char member_title[DB_GROUP_TITLE_BUF_SIZE]; /* Flawfinder: ignore */ LLUUID insignia_id; LLUUID owner_role; U32 membership_fee = 0; @@ -974,9 +974,9 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data) msg->getS32(_PREHASH_GroupData, "RoleCount", group_data->mRoleCount ); - char name[DB_GROUP_NAME_BUF_SIZE]; - char title[DB_GROUP_TITLE_BUF_SIZE]; - char desc[DB_GROUP_CHARTER_BUF_SIZE]; + char name[DB_GROUP_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char title[DB_GROUP_TITLE_BUF_SIZE]; /* Flawfinder: ignore */ + char desc[DB_GROUP_CHARTER_BUF_SIZE]; /* Flawfinder: ignore */ U64 powers = 0; U32 member_count = 0; LLUUID role_id; @@ -998,7 +998,7 @@ void LLGroupMgr::processGroupRoleDataReply(LLMessageSystem* msg, void** data) group_data->mRoles[role_id] = rd; } - if (group_data->mRoles.size() == group_data->mRoleCount) + if (group_data->mRoles.size() == (U32)group_data->mRoleCount) { group_data->mRoleDataComplete = TRUE; group_data->mRoleDataRequestID.setNull(); @@ -1152,7 +1152,7 @@ void LLGroupMgr::processGroupTitlesReply(LLMessageSystem* msg, void** data) return; } - char title_buf[DB_GROUP_TITLE_BUF_SIZE]; + char title_buf[DB_GROUP_TITLE_BUF_SIZE]; /* Flawfinder: ignore */ LLGroupTitle title; @@ -1241,7 +1241,7 @@ void LLGroupMgr::processCreateGroupReply(LLMessageSystem* msg, void ** data) { LLUUID group_id; BOOL success; - char message[MAX_STRING]; + char message[MAX_STRING]; /* Flawfinder: ignore */ msg->getUUIDFast(_PREHASH_ReplyData, _PREHASH_GroupID, group_id ); diff --git a/linden/indra/newview/llgroupnotify.cpp b/linden/indra/newview/llgroupnotify.cpp index 5d839f2..d6e5785 100644 --- a/linden/indra/newview/llgroupnotify.cpp +++ b/linden/indra/newview/llgroupnotify.cpp @@ -80,7 +80,7 @@ LLGroupNotifyBox* LLGroupNotifyBox::show(const char* subject, LLGroupData group_data; if (!gAgent.getGroupData(group_id,group_data)) { - llwarns << "Group notice for unkown group : " << group_id.getString() << llendl; + llwarns << "Group notice for unkown group: " << group_id << llendl; return NULL; } @@ -129,7 +129,7 @@ LLGroupNotifyBox::LLGroupNotifyBox(const char* subject, time_t timestamp = (time_t)t; - char time_buf[30]; + char time_buf[30]; /*Flawfinder: ignore*/ g_formatted_time(timestamp, time_buf); setFollows(FOLLOWS_TOP|FOLLOWS_RIGHT); @@ -401,7 +401,8 @@ void LLGroupNotifyBox::close() inventory_offer_callback( 1 , mInventoryOffer); } gNotifyBoxView->removeChild(this); - delete this; + + die(); } diff --git a/linden/indra/newview/llhoverview.cpp b/linden/indra/newview/llhoverview.cpp index 9c403f4..30ee2b0 100644 --- a/linden/indra/newview/llhoverview.cpp +++ b/linden/indra/newview/llhoverview.cpp @@ -144,7 +144,7 @@ void LLHoverView::updateHover(LLTool* current_tool) else if (mStartHoverTimer.getElapsedTimeF32() > DELAY_BEFORE_SHOW_TIP) { gViewerWindow->hitObjectOrLandGlobalAsync(gViewerWindow->getCurrentMouseX(), - gViewerWindow->getCurrentMouseY(), 0, pickCallback, TRUE ); + gViewerWindow->getCurrentMouseY(), 0, pickCallback ); } } else @@ -214,9 +214,9 @@ void LLHoverView::resetLastHoverObject() void LLHoverView::updateText() { - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_LAST_NAME_BUF_SIZE]; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last_name[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLViewerObject* hit_object = getLastHoverObject(); @@ -274,12 +274,10 @@ void LLHoverView::updateText() // BOOL suppressObjectHoverDisplay = !gSavedSettings.getBOOL("ShowAllObjectHoverTip"); - - LLSelectNodeList &nodes = gSelectMgr->getHoverObjects(); - LLSelectNode *nodep = nodes.getFirstRootNode(); + LLSelectNode *nodep = gSelectMgr->getHoverNode();; if (nodep) { - char cstring[256]; + char cstring[256]; /*Flawfinder: ignore*/ LLString *temp_str = NULL; temp_str = new LLString(); @@ -426,7 +424,7 @@ void LLHoverView::updateText() { temp_str = new LLString(); temp_str->append("For Sale: "); - sprintf(cstring, "L$%d", nodep->mSaleInfo.getSalePrice()); + snprintf(cstring, sizeof(cstring), "L$%d", nodep->mSaleInfo.getSalePrice()); /*Flawfinder: ignore*/ temp_str->append(cstring); mText.addDataAtEnd(temp_str); suppressObjectHoverDisplay = FALSE; // Show tip @@ -616,8 +614,8 @@ void LLHoverView::updateText() */ if (hover_parcel && hover_parcel->getParcelFlag(PF_FOR_SALE)) { - char buffer[MAX_STRING]; - sprintf(buffer, "For Sale: L$%d", hover_parcel->getSalePrice() ); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "For Sale: L$%d", hover_parcel->getSalePrice() ); /*Flawfinder: ignore*/ line = new LLString(buffer); mText.addDataAtEnd(line); diff --git a/linden/indra/newview/llhoverview.h b/linden/indra/newview/llhoverview.h index 1fd1a2e..e7fdd6a 100644 --- a/linden/indra/newview/llhoverview.h +++ b/linden/indra/newview/llhoverview.h @@ -40,7 +40,6 @@ #include "lldarray.h" #include "llhudconnector.h" -class LLSelectNodeList; class LLTool; // diff --git a/linden/indra/newview/llhudeffecttrail.cpp b/linden/indra/newview/llhudeffecttrail.cpp index ac7f22f..cf76357 100644 --- a/linden/indra/newview/llhudeffecttrail.cpp +++ b/linden/indra/newview/llhudeffecttrail.cpp @@ -175,7 +175,7 @@ void LLHUDEffectSpiral::triggerLocal() mKillTime = mTimer.getElapsedTimeF32() + mDuration; BOOL show_beam = gSavedSettings.getBOOL("ShowSelectionBeam"); - + LLColor4 color; color.setVec(mColor); @@ -269,20 +269,12 @@ void LLHUDEffectSpiral::setTargetObject(LLViewerObject *objp) void LLHUDEffectSpiral::render() { - if (!mSourceObject.isNull() && mSourceObject->isDead()) - { - markDead(); - return; - } - - if(!mTargetObject.isNull() && mTargetObject->isDead()) - { - markDead(); - return; - } - F32 time = mTimer.getElapsedTimeF32(); - if (mKillTime < time) + + if (!mSourceObject.isNull() && mSourceObject->isDead() || + !mTargetObject.isNull() && mTargetObject->isDead() || + mKillTime < time || + !gSavedSettings.getBOOL("ShowSelectionBeam")) { markDead(); return; diff --git a/linden/indra/newview/llhudicon.cpp b/linden/indra/newview/llhudicon.cpp index 169a12b..d0d2ea5 100644 --- a/linden/indra/newview/llhudicon.cpp +++ b/linden/indra/newview/llhudicon.cpp @@ -34,6 +34,7 @@ #include "llviewerobject.h" #include "lldrawable.h" #include "llviewercamera.h" +#include "llviewerimage.h" #include "llviewerwindow.h" //----------------------------------------------------------------------------- diff --git a/linden/indra/newview/llhudobject.cpp b/linden/indra/newview/llhudobject.cpp index eece86f..4aef468 100644 --- a/linden/indra/newview/llhudobject.cpp +++ b/linden/indra/newview/llhudobject.cpp @@ -167,7 +167,7 @@ LLHUDObject *LLHUDObject::addHUDObject(const U8 type) ((LLHUDEffectSpiral *)hud_objectp)->setColor(LLColor4U(255, 255, 255, 255)); break; case LL_HUD_EFFECT_GLOW: - llerrs << "Glow not implemented!" << llendl; + // deprecated break; case LL_HUD_EFFECT_POINT: hud_objectp = new LLHUDEffectSpiral(type); diff --git a/linden/indra/newview/llimpanel.cpp b/linden/indra/newview/llimpanel.cpp index 317283c..088d601 100644 --- a/linden/indra/newview/llimpanel.cpp +++ b/linden/indra/newview/llimpanel.cpp @@ -263,7 +263,7 @@ BOOL LLFloaterIMPanel::addParticipants(const LLDynamicArray& ids) U8* pos = bucket; for(S32 i = 0; i < count; ++i) { - memcpy(pos, &(ids.get(i)), UUID_BYTES); + memcpy(pos, &(ids.get(i)), UUID_BYTES); /* Flawfinder: ignore */ pos += UUID_BYTES; } msg->addBinaryDataFast(_PREHASH_BinaryBucket, bucket, bucket_size); @@ -611,7 +611,7 @@ void LLFloaterIMPanel::onInputEditorKeystroke(LLLineEditor* caller, void* userda } } -void LLFloaterIMPanel::close(bool app_quitting) +void LLFloaterIMPanel::onClose(bool app_quitting) { setTyping(FALSE); @@ -685,8 +685,9 @@ void LLFloaterIMPanel::sendMsg() gAgent.buildFullname(history_echo); // Look for IRC-style emotes here. - char tmpstr[5]; - strcpy(tmpstr,utf8_text.substr(0,4).c_str()); + char tmpstr[5]; /* Flawfinder: ignore */ + strncpy(tmpstr,utf8_text.substr(0,4).c_str(), sizeof(tmpstr) -1); /* Flawfinder: ignore */ + tmpstr[sizeof(tmpstr) -1] = '\0'; if (!strncmp(tmpstr, "/me ", 4) || !strncmp(tmpstr, "/me'", 4)) { utf8_text.replace(0,3,""); diff --git a/linden/indra/newview/llimpanel.h b/linden/indra/newview/llimpanel.h index 08a35cd..877fd88 100644 --- a/linden/indra/newview/llimpanel.h +++ b/linden/indra/newview/llimpanel.h @@ -56,7 +56,7 @@ public: // Check typing timeout timer. /*virtual*/ void draw(); - /*virtual*/ void close(bool app_quitting = FALSE); + /*virtual*/ void onClose(bool app_quitting = FALSE); // add target ids to the session. // Return TRUE if successful, otherwise FALSE. diff --git a/linden/indra/newview/llimview.cpp b/linden/indra/newview/llimview.cpp index e2d33fd..a4fd729 100644 --- a/linden/indra/newview/llimview.cpp +++ b/linden/indra/newview/llimview.cpp @@ -558,7 +558,7 @@ void LLIMView::setFloaterOpen(BOOL set_open) //RN "visible" and "open" are considered synonomous for now if (set_open) { - mTalkFloater->open(); + mTalkFloater->open(); /*Flawfinder: ignore*/ } else { @@ -701,8 +701,8 @@ void LLIMView::noteOfflineUsers(LLFloaterIMPanel* floater, for(S32 i = 0; i < count; ++i) { info = at.getBuddyInfo(ids.get(i)); - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ if(info && !info->isOnline() && gCacheName->getName(ids.get(i), first, last)) { diff --git a/linden/indra/newview/llimview.h b/linden/indra/newview/llimview.h index 00b052f..9a0c462 100644 --- a/linden/indra/newview/llimview.h +++ b/linden/indra/newview/llimview.h @@ -97,7 +97,7 @@ public: // IM received that you haven't seen yet BOOL getIMReceived() const; - void setFloaterOpen(BOOL open); + void setFloaterOpen(BOOL open); /*Flawfinder: ignore*/ BOOL getFloaterOpen(); LLFloaterIM * getFloater() { return mTalkFloater; } diff --git a/linden/indra/newview/llinventoryactions.cpp b/linden/indra/newview/llinventoryactions.cpp index a10ccdf..756ba63 100644 --- a/linden/indra/newview/llinventoryactions.cpp +++ b/linden/indra/newview/llinventoryactions.cpp @@ -110,7 +110,7 @@ bool doToSelected(LLFolderView* folder, LLString action) LLMultiPreview* multi_previewp = NULL; LLMultiProperties* multi_propertiesp = NULL; - if ("open" == action && selected_items.size() > 1) + if (("task_open" == action || "open" == action) && selected_items.size() > 1) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); @@ -121,7 +121,7 @@ bool doToSelected(LLFolderView* folder, LLString action) LLFloater::setFloaterHost(multi_previewp); } - else if ("properties" == action && selected_items.size() > 1) + else if (("task_properties" == action || "properties" == action) && selected_items.size() > 1) { S32 left, top; gFloaterView->getNewFloaterPosition(&left, &top); @@ -145,13 +145,13 @@ bool doToSelected(LLFolderView* folder, LLString action) } LLFloater::setFloaterHost(NULL); - if ("open" == action && selected_items.size() > 1) + if (multi_previewp) { multi_previewp->open(); } - else if ("properties" == action && selected_items.size() > 1) + else if (multi_propertiesp) { - multi_propertiesp->open(); + multi_propertiesp->open(); /*Flawfinder: ignore*/ } return true; @@ -209,7 +209,7 @@ class LLNewWindow : public inventory_listener_t mPtr->getActivePanel()->getModel()); iv->getActivePanel()->setFilterTypes(mPtr->getActivePanel()->getFilterTypes()); iv->getActivePanel()->setFilterSubString(mPtr->getActivePanel()->getFilterSubString()); - iv->open(); + iv->open(); /*Flawfinder: ignore*/ // force onscreen gFloaterView->adjustToFitScreen(iv, FALSE); @@ -283,6 +283,29 @@ class LLEmptyTrash : public inventory_panel_listener_t } }; +class LLEmptyLostAndFound : public inventory_panel_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLInventoryModel* model = mPtr->getModel(); + if(!model) return false; + gViewerWindow->alertXml("ConfirmEmptyLostAndFound", callback_empty_lost_and_found, this); + return true; + } + + static void callback_empty_lost_and_found(S32 option, void* userdata) + { + LLEmptyLostAndFound* empty_lost_and_found = (LLEmptyLostAndFound*)userdata; + if (option == 0) // YES + { + LLInventoryModel* model = empty_lost_and_found->mPtr->getModel(); + LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + model->purgeDescendentsOf(lost_and_found_id); + model->notifyObservers(); + } + } +}; + class LLEmptyTrashFloater : public inventory_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -635,6 +658,7 @@ void init_inventory_panel_actions(LLInventoryPanel *panel) (new LLAttachObject())->registerListener(panel, "Inventory.AttachObject"); (new LLCloseAllFolders())->registerListener(panel, "Inventory.CloseAllFolders"); (new LLEmptyTrash())->registerListener(panel, "Inventory.EmptyTrash"); + (new LLEmptyLostAndFound())->registerListener(panel, "Inventory.EmptyLostAndFound"); (new LLDoCreate())->registerListener(panel, "Inventory.DoCreate"); (new LLBeginIMSession())->registerListener(panel, "Inventory.BeginIMSession"); } diff --git a/linden/indra/newview/llinventorybridge.cpp b/linden/indra/newview/llinventorybridge.cpp index a7628d7..baf6638 100644 --- a/linden/indra/newview/llinventorybridge.cpp +++ b/linden/indra/newview/llinventorybridge.cpp @@ -346,6 +346,14 @@ void hideContextEntries(LLMenuGL& menu, for (itor = list->begin(); itor != list->end(); ++itor) { LLString name = (*itor)->getName(); + + // descend into split menus: + if ((name == "More") && (WIDGET_TYPE_MENU_ITEM_BRANCH == (*itor)->getWidgetType())) + { + hideContextEntries(*((LLMenuItemBranchGL *)(*itor))->getBranch(), entries_to_show, disabled_entries); + } + + bool found = false; std::vector::const_iterator itor2; for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2) @@ -709,7 +717,7 @@ void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, LLInventoryItem* item = model->getItem(mUUID); if(!item) return; LLUUID asset_id = item->getAssetUUID(); - char buffer[UUID_STR_LENGTH]; + char buffer[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ asset_id.toString(buffer); gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer)); @@ -828,8 +836,8 @@ LLString LLItemBridge::getLabelSuffix() const const char* sxfer; if(xfer) sxfer = EMPTY; else sxfer = NO_XFER; - char buffer[MAX_STRING]; - snprintf( + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf( /*Flawfinder: ignore*/ buffer, MAX_STRING, "%s%s%s", @@ -1777,6 +1785,14 @@ void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags) LLInventoryModel* model = mInventoryPanel->getModel(); if(!model) return; LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); + LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLAssetType::AT_LOST_AND_FOUND); + + if (lost_and_found_id == mUUID) + { + // This is the lost+found folder. + mItems.push_back("Empty Lost And Found"); + } + if(trash_id == mUUID) { // This is the trash. @@ -2177,6 +2193,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, case LLAssetType::AT_CATEGORY: is_movable = ( LLAssetType::AT_NONE == ((LLInventoryCategory*)inv_item)->getPreferredType() ); break; + default: + break; } LLUUID trash_id = model->findCategoryUUIDForType(LLAssetType::AT_TRASH); @@ -2193,6 +2211,8 @@ BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item, case LLAssetType::AT_OBJECT: is_movable = !avatar->isWearingAttachment(inv_item->getUUID()); break; + default: + break; } } @@ -2762,6 +2782,8 @@ BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop, } break; } + default: + break; } } return rv; @@ -3190,7 +3212,7 @@ void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attach rez_action->mItemID = item->getUUID(); rez_action->mAttachPt = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment); - if (attachment && attachment->getObject(0)) + if (attachment && attachment->getObject()) { gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment_rez, (void*)rez_action); } @@ -3336,7 +3358,7 @@ BOOL LLObjectBridge::renameItem(const LLString& new_name) { gSelectMgr->deselectAll(); gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - gSelectMgr->setObjectName( new_name ); + gSelectMgr->selectionSetObjectName( new_name ); gSelectMgr->deselectAll(); } } @@ -3410,8 +3432,8 @@ struct LLFoundData LLAssetType::EType asset_type) : mItemID(item_id), mAssetID(asset_id), - mAssetType(asset_type), mName(name), + mAssetType(asset_type), mWearable( NULL ) {} LLUUID mItemID; diff --git a/linden/indra/newview/llinventorymodel.cpp b/linden/indra/newview/llinventorymodel.cpp index 7864aa8..e35f71b 100644 --- a/linden/indra/newview/llinventorymodel.cpp +++ b/linden/indra/newview/llinventorymodel.cpp @@ -47,6 +47,7 @@ #include "llmutelist.h" #include "llnotify.h" #include "llcallbacklist.h" +#include "llpreview.h" #include //#define DIFF_INVENTORY_FILES @@ -1150,11 +1151,11 @@ void LLInventoryModel::cache( items, INCLUDE_TRASH, can_cache); - char agent_id_str[UUID_STR_LENGTH]; - char inventory_filename[LL_MAX_PATH]; + char agent_id_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ + char inventory_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ agent_id.toString(agent_id_str); std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, agent_id_str)); - snprintf( + snprintf( /*Flawfinder: ignore*/ inventory_filename, LL_MAX_PATH, CACHE_FORMAT_STRING, @@ -1439,11 +1440,11 @@ bool LLInventoryModel::loadSkeleton( { cat_array_t categories; item_array_t items; - char owner_id_str[UUID_STR_LENGTH]; + char owner_id_str[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ owner_id.toString(owner_id_str); std::string path(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, owner_id_str)); - char inventory_filename[LL_MAX_PATH]; - snprintf( + char inventory_filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf( /*Flawfinder: ignore*/ inventory_filename, LL_MAX_PATH, CACHE_FORMAT_STRING, @@ -1451,7 +1452,7 @@ bool LLInventoryModel::loadSkeleton( const S32 NO_VERSION = LLViewerInventoryCategory::VERSION_UNKNOWN; std::string gzip_filename(inventory_filename); gzip_filename.append(".gz"); - FILE* fp = LLFile::fopen(gzip_filename.c_str(), "rb"); + FILE* fp = LLFile::fopen(gzip_filename.c_str(), "rb"); /*Flawfinder: ignore*/ bool remove_inventory_file = false; if(fp) { @@ -1959,19 +1960,24 @@ bool LLInventoryModel::loadFromFile( LLInventoryModel::cat_array_t& categories, LLInventoryModel::item_array_t& items) { + if(!filename) + { + llerrs << "Filename is Null!" << llendl; + return false; + } llinfos << "LLInventoryModel::loadFromFile(" << filename << ")" << llendl; - FILE* file = LLFile::fopen(filename, "rb"); + FILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if(!file) { llinfos << "unable to load inventory from: " << filename << llendl; return false; } // *NOTE: This buffer size is hard coded into scanf() below. - char buffer[MAX_STRING]; - char keyword[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + char keyword[MAX_STRING]; /*Flawfinder: ignore*/ while(!feof(file) && fgets(buffer, MAX_STRING, file)) { - sscanf(buffer, " %254s", keyword); + sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */ if(0 == strcmp("inv_category", keyword)) { LLPointer inv_cat = new LLViewerInventoryCategory(LLUUID::null); @@ -2027,8 +2033,13 @@ bool LLInventoryModel::saveToFile( const cat_array_t& categories, const item_array_t& items) { + if(!filename) + { + llerrs << "Filename is Null!" << llendl; + return false; + } llinfos << "LLInventoryModel::saveToFile(" << filename << ")" << llendl; - FILE* file = LLFile::fopen(filename, "wb"); + FILE* file = LLFile::fopen(filename, "wb"); /*Flawfinder: ignore*/ if(!file) { llwarns << "unable to save inventory to: " << filename << llendl; @@ -2304,6 +2315,8 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo item_array_t items; update_map_t update; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); + bool all_one_folder = true; + LLUUID folder_id; for(S32 i = 0; i < count; ++i) { LLPointer titem = new LLViewerInventoryItem; @@ -2330,6 +2343,14 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo { ++update[titem->getParentUUID()]; } + if (folder_id.isNull()) + { + folder_id = titem->getParentUUID(); + } + else + { + all_one_folder = false; + } } if(account) { @@ -2353,6 +2374,18 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); if(!gInventory.isObjectDescendentOf(lastitem->getUUID(), trash_id)) { + LLMultiPreview* multi_previewp = LLMultiPreview::getAutoOpenInstance(folder_id); + if (!multi_previewp && all_one_folder && count > 1) + { + S32 left, top; + gFloaterView->getNewFloaterPosition(&left, &top); + + multi_previewp = new LLMultiPreview(LLRect(left, top, left + 300, top - 100)); + LLMultiPreview::setAutoOpenInstance(multi_previewp, folder_id); + } + + LLFloater::setFloaterHost(multi_previewp); + bool show_keep_discard = lastitem->getPermissions().getCreator() != gAgent.getID(); switch(lastitem->getType()) { @@ -2383,6 +2416,13 @@ bool LLInventoryModel::messageUpdateCore(LLMessageSystem* msg, bool account, boo default: break; } + + LLFloater::setFloaterHost(NULL); + if (multi_previewp) + { + multi_previewp->open(); + } + LLInventoryView* view = LLInventoryView::getActiveInventory(); if(view) { @@ -2814,7 +2854,7 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**) LLUUID item_id; LLUUID folder_id; - char new_name[MAX_STRING]; + char new_name[MAX_STRING]; /*Flawfinder: ignore*/ bool anything_changed = false; S32 count = msg->getNumberOfBlocksFast(_PREHASH_InventoryData); for(S32 i = 0; i < count; ++i) @@ -2837,7 +2877,7 @@ void LLInventoryModel::processMoveInventoryItem(LLMessageSystem* msg, void**) gInventory.accountForUpdate(update); new_item->setParent(folder_id); - if(strlen(new_name) > 0) + if(strlen(new_name) > 0) /*Flawfinder: ignore*/ { new_item->rename(new_name); } diff --git a/linden/indra/newview/llinventoryview.cpp b/linden/indra/newview/llinventoryview.cpp index 9eb33ee..afeb3be 100644 --- a/linden/indra/newview/llinventoryview.cpp +++ b/linden/indra/newview/llinventoryview.cpp @@ -373,19 +373,15 @@ void LLInventoryViewFinder::selectNoTypes(void* user_data) ///---------------------------------------------------------------------------- /// LLInventoryView ///---------------------------------------------------------------------------- -class LLSaveFolderState : public LLFolderViewFunctor +void LLSaveFolderState::setApply(BOOL apply) { -public: - LLSaveFolderState() : mApply(FALSE) {} - virtual ~LLSaveFolderState() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item) {} - void setApply(BOOL apply) { mApply = apply; } - void clearOpenFolders() { mOpenFolders.clear(); } -protected: - std::set mOpenFolders; - BOOL mApply; -}; + mApply = apply; + // before generating new list of open folders, clear the old one + if(!apply) + { + clearOpenFolders(); + } +} void LLSaveFolderState::doFolder(LLFolderViewFolder* folder) { @@ -512,17 +508,6 @@ LLInventoryView::~LLInventoryView( void ) void LLInventoryView::draw() { - if (mActivePanel && mActivePanel->getNeedsAutoSelect()) - { - LLOpenFilteredFolders opener; - mActivePanel->getRootFolder()->applyFunctorRecursively(opener); - // select first filtered item - LLSelectFirstFilteredItem filter; - mActivePanel->getRootFolder()->applyFunctorRecursively(filter); - mActivePanel->getRootFolder()->scrollToShowSelection(); - mActivePanel->setNeedsAutoSelect(FALSE); - } - if (LLInventoryModel::isEverythingFetched()) { LLLocale locale(LLLocale::USER_LOCALE); @@ -590,15 +575,6 @@ void LLSelectFirstFilteredItem::doFolder(LLFolderViewFolder* folder) } } -class LLOpenFoldersWithSelection : public LLFolderViewFunctor -{ -public: - LLOpenFoldersWithSelection() {} - virtual ~LLOpenFoldersWithSelection() {} - virtual void doFolder(LLFolderViewFolder* folder); - virtual void doItem(LLFolderViewItem* item); -}; - void LLOpenFoldersWithSelection::doItem(LLFolderViewItem *item) { if (item->getParentFolder() && item->isSelected()) @@ -728,7 +704,7 @@ LLInventoryView* LLInventoryView::showAgentInventory(BOOL take_keyboard_focus) { // Make sure it's in front and it makes a noise iv->setTitle("Inventory"); - iv->open(); + iv->open(); /*Flawfinder: ignore*/ } //if (take_keyboard_focus) //{ @@ -813,7 +789,7 @@ void LLInventoryView::toggleFindOptions() LLRect(mRect.mLeft - INV_FINDER_WIDTH, mRect.mTop, mRect.mLeft, mRect.mTop - INV_FINDER_HEIGHT), this); mFinderHandle = finder->getHandle(); - finder->open(); + finder->open(); /*Flawfinder: ignore*/ addDependentFloater(mFinderHandle); // start background fetch of folders @@ -894,7 +870,6 @@ void LLInventoryView::onSearchEdit(const LLString& search_string, void* user_dat // save current folder open state if no filter currently applied if (!self->mActivePanel->getRootFolder()->isFilterActive()) { - self->mSavedFolderState->clearOpenFolders(); self->mSavedFolderState->setApply(FALSE); self->mActivePanel->getRootFolder()->applyFunctorRecursively(*self->mSavedFolderState); } @@ -1107,8 +1082,7 @@ LLInventoryPanel::LLInventoryPanel(const LLString& name, mScroller(NULL), mAllowMultiSelect(allow_multi_select), mSortOrderSetting(sort_order_setting), - mSearchFunction(search), - mNeedsAutoSelect(FALSE) + mSearchFunction(search) { } @@ -1258,8 +1232,10 @@ void LLInventoryPanel::modelChanged(U32 mask) { LLFastTimer t2(LLFastTimer::FTM_REFRESH); + bool handled = false; if(mask & LLInventoryObserver::LABEL) { + handled = true; // label change - empty out the display name for each object // in this change set. const std::set& changed_items = gInventory.getChangedIDs(); @@ -1282,11 +1258,11 @@ void LLInventoryPanel::modelChanged(U32 mask) } } } - else if((mask & (LLInventoryObserver::STRUCTURE + if((mask & (LLInventoryObserver::STRUCTURE | LLInventoryObserver::ADD | LLInventoryObserver::REMOVE)) != 0) { - + handled = true; // Record which folders are open by uuid. LLInventoryModel* model = getModel(); if (model) @@ -1347,7 +1323,8 @@ void LLInventoryPanel::modelChanged(U32 mask) } } } - else + + if (!handled) { // it's a small change that only requires a refresh. // *TODO: figure out a more efficient way to do the refresh diff --git a/linden/indra/newview/llinventoryview.h b/linden/indra/newview/llinventoryview.h index 38c44da..78fa362 100644 --- a/linden/indra/newview/llinventoryview.h +++ b/linden/indra/newview/llinventoryview.h @@ -126,11 +126,6 @@ public: void unSelectAll() { mFolders->setSelection(NULL, FALSE, FALSE); } - BOOL getNeedsAutoSelect() { return mNeedsAutoSelect; } - void setNeedsAutoSelect(BOOL val) { mNeedsAutoSelect = val; } - - void setAutoSelectOverride(bool override) { mFolders->setAutoSelectOverride(override); } - protected: // Given the id and the parent, build all of the folder views. void rebuildViewsFor(const LLUUID& id, U32 mask); @@ -155,7 +150,6 @@ protected: BOOL mAllowMultiSelect; const LLString mSortOrderSetting; LLFolderSearchFunction mSearchFunction; - BOOL mNeedsAutoSelect; }; class LLInventoryView; @@ -292,6 +286,29 @@ public: virtual void doItem(LLFolderViewItem* item); }; +class LLSaveFolderState : public LLFolderViewFunctor +{ +public: + LLSaveFolderState() : mApply(FALSE) {} + virtual ~LLSaveFolderState() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item) {} + void setApply(BOOL apply); + void clearOpenFolders() { mOpenFolders.clear(); } +protected: + std::set mOpenFolders; + BOOL mApply; +}; + +class LLOpenFoldersWithSelection : public LLFolderViewFunctor +{ +public: + LLOpenFoldersWithSelection() {} + virtual ~LLOpenFoldersWithSelection() {} + virtual void doFolder(LLFolderViewFolder* folder); + virtual void doItem(LLFolderViewItem* item); +}; + ///---------------------------------------------------------------------------- /// Function declarations, constants, enums, and typedefs ///---------------------------------------------------------------------------- diff --git a/linden/indra/newview/lljoystickbutton.h b/linden/indra/newview/lljoystickbutton.h index 8d1817a..69baa32 100644 --- a/linden/indra/newview/lljoystickbutton.h +++ b/linden/indra/newview/lljoystickbutton.h @@ -30,6 +30,7 @@ #include "llbutton.h" #include "llcoord.h" +#include "llviewerimage.h" typedef enum e_joystick_quadrant { diff --git a/linden/indra/newview/lllandmarklist.cpp b/linden/indra/newview/lllandmarklist.cpp index a1c658d..f17a73b 100644 --- a/linden/indra/newview/lllandmarklist.cpp +++ b/linden/indra/newview/lllandmarklist.cpp @@ -84,7 +84,7 @@ void LLLandmarkList::processGetAssetReply( S32 file_length = file.getSize(); char* buffer = new char[ file_length + 1 ]; - file.read( (U8*)buffer, file_length); + file.read( (U8*)buffer, file_length); /*Flawfinder: ignore*/ buffer[ file_length ] = 0; LLLandmark* landmark = LLLandmark::constructFromString(buffer); diff --git a/linden/indra/newview/lllogchat.cpp b/linden/indra/newview/lllogchat.cpp index f8b100e..6be5ee1 100644 --- a/linden/indra/newview/lllogchat.cpp +++ b/linden/indra/newview/lllogchat.cpp @@ -43,7 +43,13 @@ LLString LLLogChat::makeLogFileName(LLString filename) //static void LLLogChat::saveHistory(LLString filename, LLString line) { - FILE *fp = LLFile::fopen(LLLogChat::makeLogFileName(filename).c_str(), "a"); + if(!filename.size()) + { + llinfos << "Filename is Empty!" << llendl; + return; + } + + FILE* fp = LLFile::fopen(LLLogChat::makeLogFileName(filename).c_str(), "a"); /*Flawfinder: ignore*/ if (!fp) { llinfos << "Couldn't open chat history log!" << llendl; @@ -58,14 +64,19 @@ void LLLogChat::saveHistory(LLString filename, LLString line) void LLLogChat::loadHistory(LLString filename , void (*callback)(LLString,void*), void* userdata) { - FILE *fptr = LLFile::fopen(makeLogFileName(filename).c_str(), "r"); + if(!filename.size()) + { + llerrs << "Filename is Empty!" << llendl; + } + + FILE* fptr = LLFile::fopen(makeLogFileName(filename).c_str(), "r"); /*Flawfinder: ignore*/ if (!fptr) { return; //No previous conversation with this name. } else { - char buffer[LOG_RECALL_SIZE]; + char buffer[LOG_RECALL_SIZE]; /*Flawfinder: ignore*/ char *bptr; S32 len; bool firstline=TRUE; @@ -82,7 +93,7 @@ void LLLogChat::loadHistory(LLString filename , void (*callback)(LLString,void*) while ( fgets(buffer, LOG_RECALL_SIZE, fptr) && !feof(fptr) ) { - len = strlen(buffer) - 1; + len = strlen(buffer) - 1; /*Flawfinder: ignore*/ for ( bptr = (buffer + len); (*bptr == '\n' || *bptr == '\r') && bptr>buffer; bptr--) *bptr='\0'; if (!firstline) diff --git a/linden/indra/newview/llmanip.cpp b/linden/indra/newview/llmanip.cpp index 20d77e0..a1ff7c3 100644 --- a/linden/indra/newview/llmanip.cpp +++ b/linden/indra/newview/llmanip.cpp @@ -169,7 +169,7 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto { //update current snap subdivision level LLVector3 cam_to_reference; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_to_reference = LLVector3(1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f); } @@ -186,12 +186,27 @@ F32 LLManip::getSubdivisionLevel(const LLVector3 &reference_point, const LLVecto return subdivisions; } +void LLManip::handleSelect() +{ + mObjectSelection = gSelectMgr->getEditSelection(); +} + +void LLManip::handleDeselect() +{ + mObjectSelection = NULL; +} + +LLObjectSelectionHandle LLManip::getSelection() +{ + return mObjectSelection; +} + BOOL LLManip::handleHover(S32 x, S32 y, MASK mask) { // We only handle the event if mousedown started with us if( hasMouseCapture() ) { - if( gSelectMgr->isEmpty() ) + if( mObjectSelection->isEmpty() ) { // Somehow the object got deselected while we were dragging it. // Release the mouse @@ -236,7 +251,7 @@ BOOL LLManip::getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal) { - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { BOOL result = FALSE; F32 mouse_x = ((F32)x / gViewerWindow->getWindowWidth() - 0.5f) * gCamera->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom; @@ -271,12 +286,12 @@ BOOL LLManip::getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVect // Given the line defined by mouse cursor (a1 + a_param*(a2-a1)) and the line defined by b1 + b_param*(b2-b1), // returns a_param and b_param for the points where lines are closest to each other. // Returns false if the two lines are parallel. -BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) const +BOOL LLManip::nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) { LLVector3 a1; LLVector3 a2; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) * gCamera->getAspect() / gAgent.getAvatarObject()->mHUDCurZoom; F32 mouse_y = (((F32)y / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; @@ -324,11 +339,11 @@ LLVector3 LLManip::getSavedPivotPoint() const return gSelectMgr->getSavedBBoxOfSelection().getCenterAgent(); } -LLVector3 LLManip::getPivotPoint() const +LLVector3 LLManip::getPivotPoint() { - if (gSelectMgr->getFirstObject() && gSelectMgr->getObjectCount() == 1 && gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + if (mObjectSelection->getFirstObject() && mObjectSelection->getObjectCount() == 1 && mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { - return gSelectMgr->getFirstObject()->getPivotPositionAgent(); + return mObjectSelection->getFirstObject()->getPivotPositionAgent(); } return gSelectMgr->getBBoxOfSelection().getCenterAgent(); } @@ -341,10 +356,10 @@ void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z) LLVector3 grid_scale; gSelectMgr->getGrid(grid_origin, grid_rot, grid_scale); - LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLViewerObject* object = mObjectSelection->getFirstRootObject(); if (!object) { - object = gSelectMgr->getFirstObject(); + object = mObjectSelection->getFirstObject(); if (!object) { return; @@ -404,7 +419,7 @@ void LLManip::renderGuidelines(BOOL draw_x, BOOL draw_y, BOOL draw_z) void LLManip::renderXYZ(const LLVector3 &vec) { const S32 PAD = 10; - char feedback_string[128]; + char feedback_string[128]; /*Flawfinder: ignore*/ LLVector3 camera_pos = gCamera->getOrigin() + gCamera->getAtAxis(); S32 vertical_offset = gViewerWindow->getWindowHeight() / 2 - VERTICAL_OFFSET; S32 window_center_x = gViewerWindow->getWindowWidth() / 2; @@ -439,25 +454,25 @@ void LLManip::renderXYZ(const LLVector3 &vec) LLGLDepthTest gls_depth(GL_FALSE); LLGLEnable tex(GL_TEXTURE_2D); // render drop shadowed text - sprintf(feedback_string, "X: %.3f", vec.mV[VX]); + snprintf(feedback_string, sizeof(feedback_string), "X: %.3f", vec.mV[VX]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -102.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE); - sprintf(feedback_string, "Y: %.3f", vec.mV[VY]); + snprintf(feedback_string, sizeof(feedback_string), "Y: %.3f", vec.mV[VY]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -27.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE); - sprintf(feedback_string, "Z: %.3f", vec.mV[VZ]); + snprintf(feedback_string, sizeof(feedback_string), "Z: %.3f", vec.mV[VZ]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, 48.f + 1.f, (F32)vertical_offset - 1.f, LLColor4::black, FALSE); // render text on top - sprintf(feedback_string, "X: %.3f", vec.mV[VX]); + snprintf(feedback_string, sizeof(feedback_string), "X: %.3f", vec.mV[VX]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -102.f, (F32)vertical_offset, LLColor4(1.f, 0.5f, 0.5f, 1.f), FALSE); glColor3f(0.5f, 1.f, 0.5f); - sprintf(feedback_string, "Y: %.3f", vec.mV[VY]); + snprintf(feedback_string, sizeof(feedback_string), "Y: %.3f", vec.mV[VY]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, -27.f, (F32)vertical_offset, LLColor4(0.5f, 1.f, 0.5f, 1.f), FALSE); glColor3f(0.5f, 0.5f, 1.f); - sprintf(feedback_string, "Z: %.3f", vec.mV[VZ]); + snprintf(feedback_string, sizeof(feedback_string), "Z: %.3f", vec.mV[VZ]); /*Flawfinder: ignore*/ hud_render_text(utf8str_to_wstring(feedback_string), camera_pos, *gResMgr->getRes( LLFONT_SANSSERIF ), LLFontGL::NORMAL, 48.f, (F32)vertical_offset, LLColor4(0.5f, 0.5f, 1.f, 1.f), FALSE); } } @@ -466,7 +481,7 @@ void LLManip::renderTickText(const LLVector3& pos, const char* text, const LLCol { const LLFontGL* big_fontp = gResMgr->getRes( LLFONT_SANSSERIF ); - BOOL hud_selection = gSelectMgr->getSelectType() == SELECT_TYPE_HUD; + BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; glMatrixMode(GL_MODELVIEW); glPushMatrix(); LLVector3 render_pos = pos; @@ -484,9 +499,9 @@ void LLManip::renderTickText(const LLVector3& pos, const char* text, const LLCol LLGLEnable tex(GL_TEXTURE_2D); shadow_color.mV[VALPHA] = color.mV[VALPHA] * 0.5f; gViewerWindow->setupViewport(1, -1); - hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, shadow_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); gViewerWindow->setupViewport(); - hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(text, render_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(text), 3.f, color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); glPopMatrix(); } @@ -498,34 +513,34 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const char* suffi const LLFontGL* big_fontp = gResMgr->getRes( LLFONT_SANSSERIF ); const LLFontGL* small_fontp = gResMgr->getRes( LLFONT_SANSSERIF_SMALL ); - char val_string[128]; - char fraction_string[128]; + char val_string[128]; /*Flawfinder: ignore*/ + char fraction_string[128]; /*Flawfinder: ignore*/ F32 val_to_print = llround(value, 0.001f); S32 fractional_portion = llround(fmodf(llabs(val_to_print), 1.f) * 100.f); if (val_to_print < 0.f) { if (fractional_portion == 0) { - sprintf(val_string, "-%d%s", lltrunc(llabs(val_to_print)), suffix); + snprintf(val_string, sizeof(val_string), "-%d%s", lltrunc(llabs(val_to_print)), suffix); /*Flawfinder: ignore*/ } else { - sprintf(val_string, "-%d", lltrunc(llabs(val_to_print))); + snprintf(val_string, sizeof(val_string), "-%d", lltrunc(llabs(val_to_print))); /*Flawfinder: ignore*/ } } else { if (fractional_portion == 0) { - sprintf(val_string, "%d%s", lltrunc(llabs(val_to_print)), suffix); + snprintf(val_string, sizeof(val_string), "%d%s", lltrunc(llabs(val_to_print)), suffix); /*Flawfinder: ignore*/ } else { - sprintf(val_string, "%d", lltrunc(val_to_print)); + snprintf(val_string, sizeof(val_string), "%d", lltrunc(val_to_print)); /*Flawfinder: ignore*/ } } - BOOL hud_selection = gSelectMgr->getSelectType() == SELECT_TYPE_HUD; + BOOL hud_selection = mObjectSelection->getSelectType() == SELECT_TYPE_HUD; glMatrixMode(GL_MODELVIEW); glPushMatrix(); LLVector3 render_pos = pos; @@ -544,7 +559,7 @@ void LLManip::renderTickValue(const LLVector3& pos, F32 value, const char* suffi LLGLEnable tex(GL_TEXTURE_2D); if (fractional_portion != 0) { - sprintf(fraction_string, "%c%d%s", gResMgr->getDecimalPoint(), fractional_portion, suffix); + snprintf(fraction_string, sizeof(fraction_string), "%c%d%s", gResMgr->getDecimalPoint(), fractional_portion, suffix); /*Flawfinder: ignore*/ gViewerWindow->setupViewport(1, -1); hud_render_utf8text(val_string, render_pos, *big_fontp, LLFontGL::NORMAL, -1.f * big_fontp->getWidthF32(val_string), 3.f, shadow_color, hud_selection); diff --git a/linden/indra/newview/llmanip.h b/linden/indra/newview/llmanip.h index 7382bd4..7f83ae2 100644 --- a/linden/indra/newview/llmanip.h +++ b/linden/indra/newview/llmanip.h @@ -36,6 +36,7 @@ class LLTextBox; class LLViewerObject; class LLToolComposite; class LLVector3; +class LLObjectSelection; const S32 MIN_DIVISION_PIXEL_WIDTH = 9; @@ -121,14 +122,18 @@ public: void renderGuidelines(BOOL draw_x = TRUE, BOOL draw_y = TRUE, BOOL draw_z = TRUE); static void renderXYZ(const LLVector3 &vec); - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask) = 0; /*virtual*/ BOOL handleMouseUp(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleHover(S32 x, S32 y, MASK mask); virtual EManipPart getHighlightedPart() { return LL_NO_PART; } virtual void highlightManipulators(S32 x, S32 y) {}; + virtual void handleSelect(); + virtual void handleDeselect(); + + LLHandle getSelection(); + protected: LLVector3 getSavedPivotPoint() const; - LLVector3 getPivotPoint() const; + LLVector3 getPivotPoint(); void getManipNormal(LLViewerObject* object, EManipPart manip, LLVector3 &normal); BOOL getManipAxis(LLViewerObject* object, EManipPart manip, LLVector3 &axis); F32 getSubdivisionLevel(const LLVector3 &reference_point, const LLVector3 &translate_axis, F32 grid_scale, S32 min_pixel_spacing = MIN_DIVISION_PIXEL_WIDTH); @@ -137,11 +142,12 @@ protected: void updateGridSettings(); BOOL getMousePointOnPlaneGlobal(LLVector3d& point, S32 x, S32 y, LLVector3d origin, LLVector3 normal); BOOL getMousePointOnPlaneAgent(LLVector3& point, S32 x, S32 y, LLVector3 origin, LLVector3 normal); - BOOL nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ) const; + BOOL nearestPointOnLineFromMouse( S32 x, S32 y, const LLVector3& b1, const LLVector3& b2, F32 &a_param, F32 &b_param ); LLColor4 setupSnapGuideRenderPass(S32 pass); protected: LLFrameTimer mHelpTextTimer; BOOL mInSnapRegime; + LLHandle mObjectSelection; static F32 sHelpTextVisibleTime; static F32 sHelpTextFadeTime; diff --git a/linden/indra/newview/llmaniprotate.cpp b/linden/indra/newview/llmaniprotate.cpp index 93cbfe4..452e4d4 100644 --- a/linden/indra/newview/llmaniprotate.cpp +++ b/linden/indra/newview/llmaniprotate.cpp @@ -81,7 +81,6 @@ const F32 SELECTED_MANIPULATOR_SCALE = 1.05f; const F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f; extern void handle_reset_rotation(void*); // in LLViewerWindow -extern void handle_first_tool(void*); LLManipRotate::LLManipRotate( LLToolComposite* composite ) : LLManip( "Rotate", composite ), @@ -108,6 +107,7 @@ void LLManipRotate::handleSelect() // *FIX: put this in mouseDown? gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); gFloaterTools->setStatusText("Drag colored bands to rotate object"); + LLManip::handleSelect(); } void LLManipRotate::handleDeselect() @@ -116,6 +116,7 @@ void LLManipRotate::handleDeselect() mManipPart = LL_NO_PART; gFloaterTools->setStatusText(""); + LLManip::handleDeselect(); } void LLManipRotate::render() @@ -127,7 +128,7 @@ void LLManipRotate::render() LLGLEnable gls_alpha_test(GL_ALPHA_TEST); // You can rotate if you can move - LLViewerObject* first_object = gSelectMgr->getFirstMoveableObject(TRUE); + LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); if( !first_object ) { return; @@ -140,7 +141,7 @@ void LLManipRotate::render() glMatrixMode(GL_MODELVIEW); glPushMatrix(); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; glScalef(zoom, zoom, zoom); @@ -358,7 +359,7 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask) { BOOL handled = FALSE; - LLViewerObject* first_object = gSelectMgr->getFirstMoveableObject(TRUE); + LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(TRUE); if( first_object ) { LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); @@ -374,10 +375,10 @@ BOOL LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask) // Assumes that one of the parts of the manipulator was hit. BOOL LLManipRotate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_rotate = gSelectMgr->getObjectCount() != 0; - for (LLViewerObject* objectp = gSelectMgr->getFirstObject(); + BOOL can_rotate = mObjectSelection->getObjectCount() != 0; + for (LLViewerObject* objectp = mObjectSelection->getFirstObject(); objectp; - objectp = gSelectMgr->getNextObject()) + objectp = mObjectSelection->getNextObject()) { can_rotate = can_rotate && objectp->permMove() && (objectp->permModify() || gSavedSettings.getBOOL("SelectLinkedSet")); } @@ -463,11 +464,7 @@ BOOL LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask) mManipPart = LL_NO_PART; // Might have missed last update due to timing. - if (mSendUpdateOnMouseUp) - { - gSelectMgr->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION ); - mSendUpdateOnMouseUp = FALSE; - } + gSelectMgr->sendMultipleUpdate( UPD_ROTATION | UPD_POSITION ); gSelectMgr->enableSilhouette(TRUE); //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); @@ -482,7 +479,7 @@ BOOL LLManipRotate::handleHover(S32 x, S32 y, MASK mask) { if( hasMouseCapture() ) { - if( gSelectMgr->isEmpty() ) + if( mObjectSelection->isEmpty() ) { // Somehow the object got deselected while we were dragging it. setMouseCapture( FALSE ); @@ -523,12 +520,6 @@ extern U32 gFrameCount; // Freeform rotation void LLManipRotate::drag( S32 x, S32 y ) { - static LLTimer update_timer; - F32 elapsed_time = update_timer.getElapsedTimeF32(); - const F32 UPDATE_DELAY = 0.1f; // min time between transmitted updates - BOOL send_rotation_update = FALSE; - BOOL send_position_update = FALSE; - if( !updateVisiblity() ) { return; @@ -548,9 +539,8 @@ void LLManipRotate::drag( S32 x, S32 y ) LLViewerObject* object; LLSelectNode* selectNode; - BOOL using_linked_selection = gSavedSettings.getBOOL("SelectLinkedSet"); - for( selectNode = gSelectMgr->getFirstNode(); selectNode != NULL; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode != NULL; selectNode = mObjectSelection->getNextNode() ) { object = selectNode->getObject(); @@ -595,12 +585,6 @@ void LLManipRotate::drag( S32 x, S32 y ) rebuild(object); } - // don't send updates all the time for sub-objects - if (using_linked_selection && object->getRenderRotation() != new_rot) - { - send_rotation_update = TRUE; - } - // for individually selected roots, we need to counterrotate all the children if (object->isRootEdit() && selectNode->mIndividualSelection) { @@ -622,7 +606,7 @@ void LLManipRotate::drag( S32 x, S32 y ) } // update positions - for( selectNode = gSelectMgr->getFirstNode(); selectNode != NULL; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode != NULL; selectNode = mObjectSelection->getNextNode() ) { object = selectNode->getObject(); @@ -692,11 +676,6 @@ void LLManipRotate::drag( S32 x, S32 y ) } } - if (using_linked_selection && object->getPositionAgent() != new_position) - { - send_position_update = TRUE; - } - // for individually selected roots, we need to counter-translate all unselected children if (object->isRootEdit() && selectNode->mIndividualSelection) { @@ -727,27 +706,19 @@ void LLManipRotate::drag( S32 x, S32 y ) } } - if ((send_position_update || send_rotation_update) && (elapsed_time > UPDATE_DELAY)) + // store changes to override updates + for (LLSelectNode* selectNode = gSelectMgr->getSelection()->getFirstNode(); + selectNode != NULL; + selectNode = gSelectMgr->getSelection()->getNextNode()) { - U32 flag = UPD_NONE; - if (send_rotation_update) - { - flag |= UPD_ROTATION; - } - if (send_position_update) + LLViewerObject*cur = selectNode->getObject(); + if( cur->permModify() && cur->permMove() && !cur->isAvatar()) { - flag |= UPD_POSITION; + selectNode->mLastRotation = cur->getRotation(); + selectNode->mLastPositionLocal = cur->getPosition(); } + } - gSelectMgr->sendMultipleUpdate( flag ); - update_timer.reset(); - mSendUpdateOnMouseUp = FALSE; - } - else - { - mSendUpdateOnMouseUp = TRUE; - } - gSelectMgr->updateSelectionCenter(); // RN: just clear focus so camera doesn't follow spurious object updates @@ -785,7 +756,7 @@ void LLManipRotate::renderSnapGuides() LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); LLVector3 cam_at_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_at_axis.setVec(1.f, 0.f, 0.f); } @@ -799,7 +770,7 @@ void LLManipRotate::renderSnapGuides() LLVector3 test_axis = constraint_axis; BOOL constrain_to_ref_object = FALSE; - if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) { test_axis = test_axis * ~grid_rotation; } @@ -826,7 +797,7 @@ void LLManipRotate::renderSnapGuides() } LLVector3 projected_snap_axis = world_snap_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) { projected_snap_axis = projected_snap_axis * grid_rotation; } @@ -966,32 +937,32 @@ void LLManipRotate::renderSnapGuides() { if (i == 0) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white); } else if (i == 16) { if (constraint_axis.mV[VZ] > 0.f) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white); } else { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white); } } else if (i == 32) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white); } else { if (constraint_axis.mV[VZ] > 0.f) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white); } else { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white); } } } @@ -999,7 +970,7 @@ void LLManipRotate::renderSnapGuides() { if (i == 0) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Left" : "North", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Left" : "North", LLColor4::white); } else if (i == 16) { @@ -1014,7 +985,7 @@ void LLManipRotate::renderSnapGuides() } else if (i == 32) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Right" : "South", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Right" : "South", LLColor4::white); } else { @@ -1038,11 +1009,11 @@ void LLManipRotate::renderSnapGuides() { if (constraint_axis.mV[VY] > 0.f) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white); } else { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white); } } else if (i == 32) @@ -1053,11 +1024,11 @@ void LLManipRotate::renderSnapGuides() { if (constraint_axis.mV[VY] > 0.f) { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Back" : "West", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Back" : "West", LLColor4::white); } else { - renderTickText(text_point, gSelectMgr->selectionIsAttachment() ? "Forward" : "East", LLColor4::white); + renderTickText(text_point, mObjectSelection->isAttachment() ? "Forward" : "East", LLColor4::white); } } } @@ -1072,7 +1043,7 @@ void LLManipRotate::renderSnapGuides() getObjectAxisClosestToMouse(object_axis); // project onto constraint plane - LLSelectNode* first_node = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); object_axis = object_axis * first_node->getObject()->getRenderRotation(); object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis(); object_axis.normVec(); @@ -1156,7 +1127,7 @@ BOOL LLManipRotate::updateVisiblity() BOOL visible = FALSE; LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mCenterToCam = LLVector3(-1.f / gAgent.getAvatarObject()->mHUDCurZoom, 0.f, 0.f); mCenterToCamNorm = mCenterToCam; @@ -1265,7 +1236,7 @@ LLQuaternion LLManipRotate::dragUnconstrained( S32 x, S32 y ) F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) * in_sphere_angle; LLVector3 axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection; } @@ -1308,7 +1279,7 @@ LLVector3 LLManipRotate::getConstraintAxis() gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale); - LLSelectNode* first_node = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(TRUE); if (first_node) { // *FIX: get agent local attachment grid working @@ -1322,7 +1293,7 @@ LLVector3 LLManipRotate::getConstraintAxis() LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) { - LLSelectNode* first_object_node = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); LLVector3 constraint_axis = getConstraintAxis(); LLVector3 center = gAgent.getPosAgentFromGlobal( mRotationCenter ); @@ -1339,7 +1310,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) LLVector3 axis2; LLVector3 test_axis = constraint_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) { test_axis = test_axis * ~grid_rotation; } @@ -1363,7 +1334,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) axis1 = LLVector3::x_axis; } - if (gSelectMgr->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) { axis1 = axis1 * grid_rotation; } @@ -1385,7 +1356,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) // We're looking at the ring edge-on. LLVector3 snap_plane_center = (center + (constraint_axis * mRadiusMeters * 0.5f)); LLVector3 cam_to_snap_plane; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_to_snap_plane.setVec(1.f, 0.f, 0.f); } @@ -1435,7 +1406,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) { // try other plane snap_plane_center = (center - (constraint_axis * mRadiusMeters * 0.5f)); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_to_snap_plane.setVec(1.f, 0.f, 0.f); } @@ -1482,7 +1453,7 @@ LLQuaternion LLManipRotate::dragConstrained( S32 x, S32 y ) if (snap_plane > 0) { LLVector3 cam_at_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_at_axis.setVec(1.f, 0.f, 0.f); } @@ -1680,9 +1651,10 @@ LLVector3 LLManipRotate::intersectRayWithSphere( const LLVector3& ray_pt, const } // Utility function. Should probably be moved to another class. +//static void LLManipRotate::mouseToRay( S32 x, S32 y, LLVector3* ray_pt, LLVector3* ray_dir ) { - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (gSelectMgr->getSelection()->getSelectType() == SELECT_TYPE_HUD) { F32 mouse_x = (((F32)x / gViewerWindow->getWindowWidth()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; F32 mouse_y = ((((F32)y) / gViewerWindow->getWindowHeight()) - 0.5f) / gAgent.getAvatarObject()->mHUDCurZoom; @@ -1704,7 +1676,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y ) mHighlightedPart = LL_NO_PART; //LLBBox bbox = gSelectMgr->getBBoxOfSelection(); - LLViewerObject *first_object = gSelectMgr->getFirstMoveableObject(TRUE); + LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); if (!first_object) { @@ -1840,7 +1812,7 @@ void LLManipRotate::highlightManipulators( S32 x, S32 y ) S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis) { - LLSelectNode* first_object_node = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode* first_object_node = mObjectSelection->getFirstMoveableNode(TRUE); if (!first_object_node) { diff --git a/linden/indra/newview/llmanipscale.cpp b/linden/indra/newview/llmanipscale.cpp index f143c5a..d520fbe 100644 --- a/linden/indra/newview/llmanipscale.cpp +++ b/linden/indra/newview/llmanipscale.cpp @@ -159,6 +159,7 @@ void LLManipScale::handleSelect() updateSnapGuides(bbox); gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); gFloaterTools->setStatusText("Click and drag to stretch selected side"); + LLManip::handleSelect(); } void LLManipScale::handleDeselect() @@ -166,6 +167,7 @@ void LLManipScale::handleDeselect() mHighlightedPart = LL_NO_PART; mManipPart = LL_NO_PART; gFloaterTools->setStatusText(""); + LLManip::handleDeselect(); } BOOL sort_manip_by_z(LLManipScale::ManipulatorHandle *new_manip, LLManipScale::ManipulatorHandle *test_manip) @@ -215,7 +217,7 @@ void LLManipScale::render() { glMatrixMode(GL_MODELVIEW); glPushMatrix(); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; glScalef(zoom, zoom, zoom); @@ -231,7 +233,7 @@ void LLManipScale::render() F32 range; F32 range_from_agent; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mBoxHandleSize = BOX_HANDLE_BASE_SIZE * BOX_HANDLE_BASE_FACTOR / (F32) gCamera->getViewHeightInPixels(); mBoxHandleSize /= gAgent.getAvatarObject()->mHUDCurZoom; @@ -330,10 +332,10 @@ BOOL LLManipScale::handleMouseDown(S32 x, S32 y, MASK mask) // Assumes that one of the arrows on an object was hit. BOOL LLManipScale::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_scale = gSelectMgr->getObjectCount() != 0; - for (LLViewerObject* objectp = gSelectMgr->getFirstObject(); + BOOL can_scale = mObjectSelection->getObjectCount() != 0; + for (LLViewerObject* objectp = mObjectSelection->getFirstObject(); objectp; - objectp = gSelectMgr->getNextObject()) + objectp = mObjectSelection->getNextObject()) { can_scale = can_scale && objectp->permModify() && objectp->permMove() && !objectp->isSeat(); } @@ -377,15 +379,27 @@ BOOL LLManipScale::handleMouseUp(S32 x, S32 y, MASK mask) // first, perform normal processing in case this was a quick-click handleHover(x, y, mask); + if( (LL_FACE_MIN <= (S32)mManipPart) + && ((S32)mManipPart <= LL_FACE_MAX) ) + { + sendUpdates(TRUE,TRUE,FALSE); + } + else + if( (LL_CORNER_MIN <= (S32)mManipPart) + && ((S32)mManipPart <= LL_CORNER_MAX) ) + { + sendUpdates(TRUE,TRUE,TRUE); + } + + //send texture update + gSelectMgr->adjustTexturesByScale(TRUE, getStretchTextures()); + gSelectMgr->enableSilhouette(TRUE); mManipPart = LL_NO_PART; // Might have missed last update due to UPDATE_DELAY timing - if (mSendUpdateOnMouseUp) - { - gSelectMgr->sendMultipleUpdate( mLastUpdateFlags ); - } - + gSelectMgr->sendMultipleUpdate( mLastUpdateFlags ); + //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); return LLManip::handleMouseUp(x, y, mask); @@ -396,7 +410,7 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask) { if( hasMouseCapture() ) { - if( gSelectMgr->isEmpty() ) + if( mObjectSelection->isEmpty() ) { // Somehow the object got deselected while we were dragging it. setMouseCapture( FALSE ); @@ -415,7 +429,7 @@ BOOL LLManipScale::handleHover(S32 x, S32 y, MASK mask) } // Patch up textures, if possible. - gSelectMgr->adjustTexturesByScale(TRUE, getStretchTextures()); + gSelectMgr->adjustTexturesByScale(FALSE, getStretchTextures()); gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLSCALE); return TRUE; @@ -432,7 +446,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) if( isSelectionScalable() ) { LLMatrix4 transform; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { LLVector4 translation(bbox.getPositionAgent()); transform.initRotTrans(bbox.getRotation(), translation); @@ -473,7 +487,7 @@ void LLManipScale::highlightManipulators(S32 x, S32 y) mManipulatorVertices[numManips++] = LLVector4(max.mV[VX], max.mV[VY], max.mV[VZ], 1.f); // 1-D highlights are applicable iff one object is selected - if( gSelectMgr->getObjectCount() == 1 ) + if( mObjectSelection->getObjectCount() == 1 ) { // face centers mManipulatorVertices[numManips++] = LLVector4(ctr.mV[VX], ctr.mV[VY], max.mV[VZ], 1.f); @@ -539,7 +553,7 @@ void LLManipScale::renderFaces( const LLBBox& bbox ) { // Don't bother to render the drag handles for 1-D scaling if // more than one object is selected or if it is an attachment - if ( gSelectMgr->getObjectCount() > 1 ) + if ( mObjectSelection->getObjectCount() > 1 ) { return; } @@ -806,8 +820,21 @@ void LLManipScale::drag( S32 x, S32 y ) dragCorner( x, y ); } - //gAgent.setObjectTracking(FALSE); - gAgent.clearFocusObject(); + // store changes to override updates + for (LLSelectNode* selectNode = gSelectMgr->getSelection()->getFirstNode(); + selectNode != NULL; + selectNode = gSelectMgr->getSelection()->getNextNode()) + { + LLViewerObject*cur = selectNode->getObject(); + if( cur->permModify() && cur->permMove() && !cur->isAvatar()) + { + selectNode->mLastScale = cur->getScale(); + selectNode->mLastPositionLocal = cur->getPosition(); + } + } + + gSelectMgr->updateSelectionCenter(); + gAgent.clearFocusObject(); } // Scale around the @@ -818,10 +845,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) // Suppress scale if mouse hasn't moved. if (x == mLastMouseX && y == mLastMouseY) { - if (mSendUpdateOnMouseUp) - { - sendUpdates(TRUE,TRUE,TRUE); - } + // sendUpdates(TRUE,TRUE,TRUE); return; } @@ -945,7 +969,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) // find max and min scale factors that will make biggest object hit max absolute scale and smallest object hit min absolute scale LLSelectNode* selectNode; - for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() ) { LLViewerObject* cur = selectNode->getObject(); if( cur->permModify() && cur->permMove() && !cur->isAvatar() ) @@ -965,7 +989,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) LLVector3d drag_global = uniform ? mDragStartCenterGlobal : mDragFarHitGlobal; // do the root objects i.e. (TRUE == cur->isRootEdit()) - for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() ) { LLViewerObject* cur = selectNode->getObject(); if( cur->permModify() && cur->permMove() && !cur->isAvatar() && cur->isRootEdit() ) @@ -1009,7 +1033,7 @@ void LLManipScale::dragCorner( S32 x, S32 y ) } } // do the child objects i.e. (FALSE == cur->isRootEdit()) - for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() ) { LLViewerObject*cur = selectNode->getObject(); if( cur->permModify() && cur->permMove() && !cur->isAvatar() && !cur->isRootEdit() ) @@ -1020,11 +1044,8 @@ void LLManipScale::dragCorner( S32 x, S32 y ) if (!selectNode->mIndividualSelection) { cur->setPosition(selectNode->mSavedPositionLocal * scale_factor); - continue; } - LLVector3d new_pos_global = drag_global + (selectNode->mSavedPositionGlobal - drag_global) * scale_factor; - cur->setPositionAbsoluteGlobal( new_pos_global ); rebuild(cur); } } @@ -1032,8 +1053,6 @@ void LLManipScale::dragCorner( S32 x, S32 y ) mDragPointGlobal = drag_point_global; - - sendUpdates( TRUE, TRUE, TRUE ); } @@ -1042,10 +1061,7 @@ void LLManipScale::dragFace( S32 x, S32 y ) // Suppress scale if mouse hasn't moved. if (x == mLastMouseX && y == mLastMouseY) { - if (mSendUpdateOnMouseUp) - { - sendUpdates(TRUE,TRUE,FALSE); - } + // sendUpdates(TRUE,TRUE,FALSE); return; } @@ -1179,8 +1195,6 @@ void LLManipScale::dragFace( S32 x, S32 y ) send_scale_update = TRUE; mDragPointGlobal = drag_point_global; - - sendUpdates( send_position_update, send_scale_update ); } void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_update, BOOL corner ) @@ -1215,8 +1229,6 @@ void LLManipScale::sendUpdates( BOOL send_position_update, BOOL send_scale_updat { mSendUpdateOnMouseUp = TRUE; } - - gSelectMgr->updateSelectionCenter(); dialog_refresh_all(); } } @@ -1228,7 +1240,7 @@ void LLManipScale::stretchFace( const LLVector3& drag_start_agent, const LLVecto LLVector3 drag_start_center_agent = gAgent.getPosAgentFromGlobal(mDragStartCenterGlobal); LLSelectNode *selectNode; - for( selectNode = gSelectMgr->getFirstNode(); selectNode; selectNode = gSelectMgr->getNextNode() ) + for( selectNode = mObjectSelection->getFirstNode(); selectNode; selectNode = mObjectSelection->getNextNode() ) { LLViewerObject*cur = selectNode->getObject(); if( cur->permModify() && cur->permMove() && !cur->isAvatar() ) @@ -1349,7 +1361,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) mScaleDir = box_corner_agent - mScaleCenter; mScaleDir.normVec(); - if(gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if(mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mSnapRegimeOffset = SNAP_GUIDE_SCREEN_OFFSET / gAgent.getAvatarObject()->mHUDCurZoom; @@ -1361,7 +1373,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) } LLVector3 cam_at_axis; F32 snap_guide_length; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { cam_at_axis.setVec(1.f, 0.f, 0.f); snap_guide_length = SNAP_GUIDE_SCREEN_LENGTH / gAgent.getAvatarObject()->mHUDCurZoom; @@ -1408,7 +1420,7 @@ void LLManipScale::updateSnapGuides(const LLBBox& bbox) { LLVector3 local_scale_dir = partToUnitVector( mManipPart ); LLVector3 local_camera_dir; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { local_camera_dir = LLVector3(-1.f, 0.f, 0.f) * ~bbox.getRotation(); } @@ -1687,7 +1699,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) start_tick = -(llmin(ticks_from_scale_center_1, num_ticks_per_side1)); stop_tick = llmin(max_ticks1, num_ticks_per_side1); - F32 grid_resolution = gSelectMgr->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f); + F32 grid_resolution = mObjectSelection->getSelectType() == SELECT_TYPE_HUD ? 0.25f : llmax(gSavedSettings.getF32("GridResolution"), 0.001f); S32 label_sub_div_offset_1 = llround(fmod(dist_grid_axis - grid_offset1, mScaleSnapUnit1 * 32.f) / (mScaleSnapUnit1 / max_subdivisions)); S32 label_sub_div_offset_2 = llround(fmod(dist_grid_axis - grid_offset2, mScaleSnapUnit2 * 32.f) / (mScaleSnapUnit2 / max_subdivisions)); @@ -1793,7 +1805,7 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) // render help text - if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) { @@ -1815,10 +1827,10 @@ void LLManipScale::renderSnapGuides(const LLBBox& bbox) std::string help_text = "Move mouse cursor over ruler"; LLColor4 help_text_color = LLColor4::white; help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, grid_alpha, 0.f); - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); help_text = "to snap to grid"; help_text_pos -= gCamera->getUpAxis() * mSnapRegimeOffset * 0.4f; - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); } } } @@ -2022,14 +2034,16 @@ LLVector3 LLManipScale::nearestAxis( const LLVector3& v ) const return LLVector3( coords[greatest_index] ); } -BOOL LLManipScale::isSelectionScalable() const +//FIXME: make this const once we switch to iterator interface +//(making object traversal a const-able operation) +BOOL LLManipScale::isSelectionScalable() { // An selection is scalable if you are allowed to both edit and move // everything in it, and it does not have any sitting agents - BOOL scalable = gSelectMgr->getFirstObject() ? TRUE : FALSE; - for(LLViewerObject* cur = gSelectMgr->getFirstObject(); + BOOL scalable = mObjectSelection->getFirstObject() ? TRUE : FALSE; + for(LLViewerObject* cur = mObjectSelection->getFirstObject(); cur; - cur = gSelectMgr->getNextObject() ) + cur = mObjectSelection->getNextObject() ) { if( !(cur->permModify() && cur->permMove()) || cur->isSeat()) diff --git a/linden/indra/newview/llmanipscale.h b/linden/indra/newview/llmanipscale.h index 7ac3aef..2452e6b 100644 --- a/linden/indra/newview/llmanipscale.h +++ b/linden/indra/newview/llmanipscale.h @@ -113,7 +113,7 @@ private: F32 partToMinScale( S32 part, const LLBBox& bbox ) const; LLVector3 nearestAxis( const LLVector3& v ) const; - BOOL isSelectionScalable() const; + BOOL isSelectionScalable(); void stretchFace( const LLVector3& drag_start_agent, const LLVector3& drag_delta_agent); diff --git a/linden/indra/newview/llmaniptranslate.cpp b/linden/indra/newview/llmaniptranslate.cpp index fea6092..bb58a9c 100644 --- a/linden/indra/newview/llmaniptranslate.cpp +++ b/linden/indra/newview/llmaniptranslate.cpp @@ -59,6 +59,7 @@ #include "llworld.h" #include "viewer.h" #include "llui.h" +#include "pipeline.h" const S32 NUM_AXES = 3; const S32 MOUSE_DRAG_SLOP = 2; // pixels @@ -257,6 +258,7 @@ void LLManipTranslate::handleSelect() { gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); gFloaterTools->setStatusText("Drag to move, shift-drag to copy"); + LLManip::handleSelect(); } void LLManipTranslate::handleDeselect() @@ -264,6 +266,7 @@ void LLManipTranslate::handleDeselect() mHighlightedPart = LL_NO_PART; mManipPart = LL_NO_PART; gFloaterTools->setStatusText(""); + LLManip::handleDeselect(); } BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask) @@ -289,10 +292,10 @@ BOOL LLManipTranslate::handleMouseDown(S32 x, S32 y, MASK mask) // Assumes that one of the arrows on an object was hit. BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) { - BOOL can_move = gSelectMgr->getObjectCount() != 0; - for (LLViewerObject* objectp = gSelectMgr->getFirstObject(); + BOOL can_move = mObjectSelection->getObjectCount() != 0; + for (LLViewerObject* objectp = mObjectSelection->getFirstObject(); objectp; - objectp = gSelectMgr->getNextObject()) + objectp = mObjectSelection->getNextObject()) { can_move = can_move && objectp->permMove() && (objectp->permModify() || gSavedSettings.getBOOL("SelectLinkedSet")); } @@ -332,7 +335,7 @@ BOOL LLManipTranslate::handleMouseDownOnPart( S32 x, S32 y, MASK mask ) LLVector3 axis; - LLSelectNode *selectNode = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode *selectNode = mObjectSelection->getFirstMoveableNode(TRUE); if (!selectNode) { @@ -407,7 +410,7 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) BOOL rotated = FALSE; // ...build mode moves camera about focus point - if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { if (x < ROTATE_H_MARGIN) { @@ -421,6 +424,8 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) } } + LLViewerObject *object; + // Suppress processing if mouse hasn't actually moved. // This may cause problems if the camera moves outside of the // rotation above. @@ -467,11 +472,10 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) LLVector3 axis_f; LLVector3d axis_d; - LLViewerObject *object; // pick the first object to constrain to grid w/ common origin // this is so we don't screw up groups - LLSelectNode* selectNode = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode* selectNode = mObjectSelection->getFirstMoveableNode(TRUE); if (!selectNode) { // somehow we lost the object! @@ -643,12 +647,12 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) LLVector3d clamped_relative_move = axis_magnitude * axis_d; // scalar multiply LLVector3 clamped_relative_move_f = (F32)axis_magnitude * axis_f; // scalar multiply - for(selectNode = gSelectMgr->getFirstNode(); + for(selectNode = mObjectSelection->getFirstNode(); selectNode; - selectNode = gSelectMgr->getNextNode() ) + selectNode = mObjectSelection->getNextNode() ) { object = selectNode->getObject(); - + // Only apply motion to root objects and objects selected // as "individual". if (!object->isRootEdit() && !selectNode->mIndividualSelection) @@ -779,27 +783,12 @@ BOOL LLManipTranslate::handleHover(S32 x, S32 y, MASK mask) send_update = TRUE; } } + selectNode->mLastPositionLocal = object->getPosition(); } } - // Handle throttling to 10 updates per second. - F32 elapsed_time = mUpdateTimer.getElapsedTimeF32(); - const F32 UPDATE_DELAY = 0.1f; // min time between transmitted updates - if (send_update && (elapsed_time > UPDATE_DELAY)) - { - gSelectMgr->sendMultipleUpdate(UPD_POSITION); - mUpdateTimer.reset(); - mSendUpdateOnMouseUp = FALSE; - } - else - { - // ...suppressed update - mSendUpdateOnMouseUp = TRUE; - } - gSelectMgr->updateSelectionCenter(); gAgent.clearFocusObject(); - //gAgent.setObjectTracking(FALSE); dialog_refresh_all(); // ??? is this necessary? lldebugst(LLERR_USER_INPUT) << "hover handled by LLManipTranslate (active)" << llendl; @@ -811,7 +800,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) { mHighlightedPart = LL_NO_PART; - if (!gSelectMgr->getObjectCount()) + if (!mObjectSelection->getObjectCount()) { return; } @@ -832,7 +821,7 @@ void LLManipTranslate::highlightManipulators(S32 x, S32 y) LLMatrix4 transform; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { relative_camera_dir = LLVector3(1.f, 0.f, 0.f) * ~grid_rotation; LLVector4 translation(object_position); @@ -1056,17 +1045,8 @@ BOOL LLManipTranslate::handleMouseUp(S32 x, S32 y, MASK mask) gSelectMgr->enableSilhouette(TRUE); // Might have missed last update due to UPDATE_DELAY timing. - if (mSendUpdateOnMouseUp) - { - gSelectMgr->sendMultipleUpdate( UPD_POSITION ); - mSendUpdateOnMouseUp = FALSE; - } - -// if (mCopyMadeThisDrag) -// { -// gSelectMgr->clearGridObjects(); -// } - + gSelectMgr->sendMultipleUpdate( UPD_POSITION ); + mInSnapRegime = FALSE; gSelectMgr->saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); //gAgent.setObjectTracking(gSavedSettings.getBOOL("TrackFocusObject")); @@ -1079,7 +1059,7 @@ void LLManipTranslate::render() { glMatrixMode(GL_MODELVIEW); glPushMatrix(); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; glScalef(zoom, zoom, zoom); @@ -1117,7 +1097,7 @@ void LLManipTranslate::renderSnapGuides() return; } - LLSelectNode *first_node = gSelectMgr->getFirstMoveableNode(TRUE); + LLSelectNode *first_node = mObjectSelection->getFirstMoveableNode(TRUE); if (!first_node) { return; @@ -1139,10 +1119,36 @@ void LLManipTranslate::renderSnapGuides() //pick appropriate projection plane for snap rulers according to relative camera position if (mManipPart >= LL_X_ARROW && mManipPart <= LL_Z_ARROW) { + LLVector3 normal; + LLColor4 inner_color; + LLManip::EManipPart temp_manip = mManipPart; + switch (mManipPart) + { + case LL_X_ARROW: + normal.setVec(1,0,0); + inner_color.setVec(0,1,1,line_alpha); + mManipPart = LL_YZ_PLANE; + break; + case LL_Y_ARROW: + normal.setVec(0,1,0); + inner_color.setVec(1,0,1,line_alpha); + mManipPart = LL_XZ_PLANE; + break; + case LL_Z_ARROW: + normal.setVec(0,0,1); + inner_color.setVec(1,1,0,line_alpha); + mManipPart = LL_XY_PLANE; + break; + default: + break; + } + + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + mManipPart = temp_manip; getManipAxis(first_object, mManipPart, translate_axis); LLVector3 at_axis_abs; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { at_axis_abs = LLVector3::x_axis * ~grid_rotation; } @@ -1217,7 +1223,7 @@ void LLManipTranslate::renderSnapGuides() F32 guide_size_meters; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { guide_size_meters = 1.f / gAgent.getAvatarObject()->mHUDCurZoom; mSnapOffsetMeters = mArrowLengthMeters * 1.5f; @@ -1419,7 +1425,7 @@ void LLManipTranslate::renderSnapGuides() } } } - if (gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD) { // render helpful text if (mHelpTextTimer.getElapsedTimeF32() < sHelpTextVisibleTime + sHelpTextFadeTime && sNumTimesHelpTextShown < sMaxTimesShowHelpText) @@ -1443,10 +1449,10 @@ void LLManipTranslate::renderSnapGuides() std::string help_text = "Move mouse cursor over ruler to snap"; LLColor4 help_text_color = LLColor4::white; help_text_color.mV[VALPHA] = clamp_rescale(mHelpTextTimer.getElapsedTimeF32(), sHelpTextVisibleTime, sHelpTextVisibleTime + sHelpTextFadeTime, line_alpha, 0.f); - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); help_text = "to snap to grid"; help_text_pos -= gCamera->getUpAxis() * mSnapOffsetMeters * 0.2f; - hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + hud_render_utf8text(help_text, help_text_pos, *big_fontp, LLFontGL::NORMAL, -0.5f * big_fontp->getWidthF32(help_text), 3.f, help_text_color, mObjectSelection->getSelectType() == SELECT_TYPE_HUD); } } } @@ -1455,18 +1461,13 @@ void LLManipTranslate::renderSnapGuides() // render gridlines for planar snapping F32 u = 0, v = 0; - glPushMatrix(); - - F32 x,y,z,angle_radians; - grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); - glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); - glRotatef(angle_radians * RAD_TO_DEG, x, y, z); - + LLColor4 inner_color; + LLVector3 normal; LLVector3 grid_center = selection_center - grid_origin; - grid_center *= ~grid_rotation; - F32 usc = 1; F32 vsc = 1; + + grid_center *= ~grid_rotation; switch (mManipPart) { @@ -1475,23 +1476,38 @@ void LLManipTranslate::renderSnapGuides() v = grid_center.mV[VZ]; usc = grid_scale.mV[VY]; vsc = grid_scale.mV[VZ]; + inner_color.setVec(0,1,1,line_alpha); + normal.setVec(1,0,0); break; case LL_XZ_PLANE: u = grid_center.mV[VX]; v = grid_center.mV[VZ]; usc = grid_scale.mV[VX]; vsc = grid_scale.mV[VZ]; + inner_color.setVec(1,0,1,line_alpha); + normal.setVec(0,1,0); break; case LL_XY_PLANE: u = grid_center.mV[VX]; v = grid_center.mV[VY]; usc = grid_scale.mV[VX]; vsc = grid_scale.mV[VY]; + inner_color.setVec(1,1,0,line_alpha); + normal.setVec(0,0,1); break; default: break; } + highlightIntersection(normal, selection_center, grid_rotation, inner_color); + + glPushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + glRotatef(angle_radians * RAD_TO_DEG, x, y, z); + F32 sz = mGridSizeMeters; F32 tiles = sz; glMatrixMode(GL_TEXTURE); @@ -1608,20 +1624,118 @@ void LLManipTranslate::renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F } +void LLManipTranslate::highlightIntersection(LLVector3 normal, + LLVector3 selection_center, + LLQuaternion grid_rotation, + LLColor4 inner_color) +{ + if (!gSavedSettings.getBOOL("GridCrossSections")) + { + return; + } + + U32 types[] = { LLRenderPass::PASS_SIMPLE, LLRenderPass::PASS_ALPHA, LLRenderPass::PASS_FULLBRIGHT }; + + GLuint stencil_mask = 0xFFFFFFFF; + //stencil in volumes + { + glStencilMask(stencil_mask); + glClearStencil(1); + glClear(GL_STENCIL_BUFFER_BIT); + LLGLEnable cull_face(GL_CULL_FACE); + LLGLEnable stencil(GL_STENCIL_TEST); + LLGLDepthTest depth (GL_TRUE, GL_FALSE, GL_ALWAYS); + glStencilFunc(GL_ALWAYS, 0, stencil_mask); + glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); + LLGLDisable tex(GL_TEXTURE_2D); + glColor4f(1,1,1,1); + + //setup clip plane + normal = normal * grid_rotation; + if (normal * (gCamera->getOrigin()-selection_center) < 0) + { + normal = -normal; + } + F32 d = -(selection_center * normal); + F64 plane[] = { normal.mV[0], normal.mV[1], normal.mV[2], d }; + LLGLEnable clip(GL_CLIP_PLANE0); + glClipPlane(GL_CLIP_PLANE0, plane); + + BOOL particles = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + BOOL clouds = gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + //stencil in volumes + glStencilOp(GL_INCR, GL_INCR, GL_INCR); + glCullFace(GL_FRONT); + for (U32 i = 0; i < 3; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + glStencilOp(GL_DECR, GL_DECR, GL_DECR); + glCullFace(GL_BACK); + for (U32 i = 0; i < 3; i++) + { + gPipeline.renderObjects(types[i], LLVertexBuffer::MAP_VERTEX, FALSE); + } + + if (particles) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); + } + if (clouds) + { + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_CLOUDS); + } + + glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + + glPushMatrix(); + + F32 x,y,z,angle_radians; + grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z); + glTranslatef(selection_center.mV[VX], selection_center.mV[VY], selection_center.mV[VZ]); + glRotatef(angle_radians * RAD_TO_DEG, x, y, z); + + F32 sz = mGridSizeMeters; + F32 tiles = sz; + + //draw volume/plane intersections + { + LLGLDisable tex(GL_TEXTURE_2D); + LLGLDepthTest depth(GL_FALSE); + LLGLEnable stencil(GL_STENCIL_TEST); + glStencilOp(GL_KEEP, GL_KEEP, GL_KEEP); + glStencilFunc(GL_EQUAL, 0, stencil_mask); + renderGrid(0,0,tiles,inner_color.mV[0], inner_color.mV[1], inner_color.mV[2], 0.25f); + } + + glPopMatrix(); +} void LLManipTranslate::renderText() { - if (gSelectMgr->getRootObjectCount() && !gSelectMgr->selectionIsAttachment()) + if (mObjectSelection->getRootObjectCount() && !mObjectSelection->isAttachment()) { LLVector3 pos = getPivotPoint(); renderXYZ(pos); } else { - LLViewerObject* objectp = gSelectMgr->getFirstRootObject(); + LLViewerObject* objectp = mObjectSelection->getFirstRootObject(); if(!objectp) { - objectp = gSelectMgr->getFirstObject(); + objectp = mObjectSelection->getFirstObject(); } if (objectp) @@ -1640,7 +1754,7 @@ void LLManipTranslate::renderTranslationHandles() gSelectMgr->getGrid(grid_origin, grid_rotation, grid_scale); LLVector3 at_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { at_axis = LLVector3::x_axis * ~grid_rotation; } @@ -1676,13 +1790,13 @@ void LLManipTranslate::renderTranslationHandles() mPlaneManipPositions.mV[VZ] = -1.f; } - LLViewerObject *first_object = gSelectMgr->getFirstMoveableObject(TRUE); + LLViewerObject *first_object = mObjectSelection->getFirstMoveableObject(TRUE); if (!first_object) return; LLVector3 selection_center = getPivotPoint(); // Drag handles - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { mArrowLengthMeters = mAxisArrowLength / gViewerWindow->getWindowHeight(); mArrowLengthMeters /= gAgent.getAvatarObject()->mHUDCurZoom; @@ -1735,7 +1849,7 @@ void LLManipTranslate::renderTranslationHandles() LLVector3 relative_camera_dir; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { relative_camera_dir = LLVector3::x_axis * invRotation; } @@ -2007,7 +2121,7 @@ void LLManipTranslate::renderTranslationHandles() // draw arrows for deeper faces first, closer faces last LLVector3 camera_axis; - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD) { camera_axis = LLVector3::x_axis; } diff --git a/linden/indra/newview/llmaniptranslate.h b/linden/indra/newview/llmaniptranslate.h index b055478..4937d71 100644 --- a/linden/indra/newview/llmaniptranslate.h +++ b/linden/indra/newview/llmaniptranslate.h @@ -77,6 +77,10 @@ protected: void renderSnapGuides(); void renderGrid(F32 x, F32 y, F32 size, F32 r, F32 g, F32 b, F32 a); void renderGridVert(F32 x_trans, F32 y_trans, F32 r, F32 g, F32 b, F32 alpha); + void highlightIntersection(LLVector3 normal, + LLVector3 selection_center, + LLQuaternion grid_rotation, + LLColor4 inner_color); F32 getMinGridScale(); private: diff --git a/linden/indra/newview/llmapresponders.cpp b/linden/indra/newview/llmapresponders.cpp index 0bf8754..2863c0b 100644 --- a/linden/indra/newview/llmapresponders.cpp +++ b/linden/indra/newview/llmapresponders.cpp @@ -96,99 +96,102 @@ void LLMapLayerResponder::result(const LLSD& result) bool found_null_sim = false; adjust = FALSE; - const LLSD& map_blocks = result["MapBlocks"]; - for (iter = map_blocks.beginArray(); iter != map_blocks.endArray(); ++iter) + if (result.has("MapBlocks")) { - const LLSD& map_block = *iter; - - S32 x_regions = map_block["X"]; - S32 y_regions = map_block["Y"]; - std::string name = map_block["Name"]; - S32 access = map_block["Access"]; - S32 region_flags = map_block["RegionFlags"]; - S32 water_height = map_block["WaterHeight"]; - LLUUID image_id = map_block["MapImageID"]; - - U32 x_meters = x_regions * REGION_WIDTH_UNITS; - U32 y_meters = y_regions * REGION_WIDTH_UNITS; - - if (access == 255) + const LLSD& map_blocks = result["MapBlocks"]; + for (iter = map_blocks.beginArray(); iter != map_blocks.endArray(); ++iter) { - // This region doesn't exist - if (gWorldMap->mIsTrackingUnknownLocation && - gWorldMap->mUnknownLocation.mdV[0] >= x_meters && - gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 && - gWorldMap->mUnknownLocation.mdV[1] >= y_meters && - gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256) - { - // We were tracking this location, but it doesn't exist - gWorldMap->mInvalidLocation = TRUE; - } - - found_null_sim = true; - } - else - { - adjust = gWorldMap->extendAABB(x_meters, - y_meters, - x_meters+REGION_WIDTH_UNITS, - y_meters+REGION_WIDTH_UNITS) || adjust; - U64 handle = to_region_handle(x_meters, y_meters); - -// llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; - - LLSimInfo* siminfo = new LLSimInfo(); - LLWorldMap::sim_info_map_t::iterator iter = gWorldMap->mSimInfoMap.find(handle); - if (iter != gWorldMap->mSimInfoMap.end()) + const LLSD& map_block = *iter; + + S32 x_regions = map_block["X"]; + S32 y_regions = map_block["Y"]; + std::string name = map_block["Name"]; + S32 access = map_block["Access"]; + S32 region_flags = map_block["RegionFlags"]; + S32 water_height = map_block["WaterHeight"]; + LLUUID image_id = map_block["MapImageID"]; + + U32 x_meters = x_regions * REGION_WIDTH_UNITS; + U32 y_meters = y_regions * REGION_WIDTH_UNITS; + + if (access == 255) { - LLSimInfo* oldinfo = iter->second; - for (S32 image=0; imagemIsTrackingUnknownLocation && + gWorldMap->mUnknownLocation.mdV[0] >= x_meters && + gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 && + gWorldMap->mUnknownLocation.mdV[1] >= y_meters && + gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256) { - siminfo->mMapImageID[image] = oldinfo->mMapImageID[image]; + // We were tracking this location, but it doesn't exist + gWorldMap->mInvalidLocation = TRUE; } - delete oldinfo; - } - gWorldMap->mSimInfoMap[handle] = siminfo; - - siminfo->mHandle = handle; - siminfo->mName.assign( name ); - siminfo->mAccess = access; - siminfo->mRegionFlags = region_flags; - siminfo->mWaterHeight = (F32) water_height; - siminfo->mMapImageID[agent_flags] = image_id; - siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[gWorldMap->mCurrentMap], MIPMAP_TRUE, FALSE); - siminfo->mCurrentImage->bindTexture(0); - siminfo->mCurrentImage->setClamp(TRUE, TRUE); - - if (siminfo->mMapImageID[2].notNull()) - { - siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE); + + found_null_sim = true; } else { - siminfo->mOverlayImage = NULL; - } + adjust = gWorldMap->extendAABB(x_meters, + y_meters, + x_meters+REGION_WIDTH_UNITS, + y_meters+REGION_WIDTH_UNITS) || adjust; + U64 handle = to_region_handle(x_meters, y_meters); - if (gWorldMap->mIsTrackingUnknownLocation && - gWorldMap->mUnknownLocation.mdV[0] >= x_meters && - gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 && - gWorldMap->mUnknownLocation.mdV[1] >= y_meters && - gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256) - { - if (siminfo->mAccess == SIM_ACCESS_DOWN) + // llinfos << "Map sim " << name << " image layer " << agent_flags << " ID " << image_id.getString() << llendl; + + LLSimInfo* siminfo = new LLSimInfo(); + LLWorldMap::sim_info_map_t::iterator iter = gWorldMap->mSimInfoMap.find(handle); + if (iter != gWorldMap->mSimInfoMap.end()) { - // We were tracking this location, but it doesn't exist - gWorldMap->mInvalidLocation = true; + LLSimInfo* oldinfo = iter->second; + for (S32 image=0; imagemMapImageID[image] = oldinfo->mMapImageID[image]; + } + delete oldinfo; + } + gWorldMap->mSimInfoMap[handle] = siminfo; + + siminfo->mHandle = handle; + siminfo->mName.assign( name ); + siminfo->mAccess = access; /*Flawfinder: ignore*/ + siminfo->mRegionFlags = region_flags; + siminfo->mWaterHeight = (F32) water_height; + siminfo->mMapImageID[agent_flags] = image_id; + siminfo->mCurrentImage = gImageList.getImage(siminfo->mMapImageID[gWorldMap->mCurrentMap], MIPMAP_TRUE, FALSE); + siminfo->mCurrentImage->bindTexture(0); + siminfo->mCurrentImage->setClamp(TRUE, TRUE); + + if (siminfo->mMapImageID[2].notNull()) + { + siminfo->mOverlayImage = gImageList.getImage(siminfo->mMapImageID[2], MIPMAP_TRUE, FALSE); } else { - // We were tracking this location, and it does exist - bool is_tracking_dbl = gWorldMap->mIsTrackingDoubleClick == TRUE; - gFloaterWorldMap->trackLocation(gWorldMap->mUnknownLocation); - if (is_tracking_dbl) + siminfo->mOverlayImage = NULL; + } + + if (gWorldMap->mIsTrackingUnknownLocation && + gWorldMap->mUnknownLocation.mdV[0] >= x_meters && + gWorldMap->mUnknownLocation.mdV[0] < x_meters + 256 && + gWorldMap->mUnknownLocation.mdV[1] >= y_meters && + gWorldMap->mUnknownLocation.mdV[1] < y_meters + 256) + { + if (siminfo->mAccess == SIM_ACCESS_DOWN) + { + // We were tracking this location, but it doesn't exist + gWorldMap->mInvalidLocation = true; + } + else { - LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); - gAgent.teleportViaLocation( pos_global ); + // We were tracking this location, and it does exist + bool is_tracking_dbl = gWorldMap->mIsTrackingDoubleClick == TRUE; + gFloaterWorldMap->trackLocation(gWorldMap->mUnknownLocation); + if (is_tracking_dbl) + { + LLVector3d pos_global = LLTracker::getTrackedPositionGlobal(); + gAgent.teleportViaLocation( pos_global ); + } } } } diff --git a/linden/indra/newview/llmemoryview.cpp b/linden/indra/newview/llmemoryview.cpp index 3432c4d..c377560 100644 --- a/linden/indra/newview/llmemoryview.cpp +++ b/linden/indra/newview/llmemoryview.cpp @@ -35,6 +35,7 @@ #include "llgl.h" #include "llmath.h" #include "llfontgl.h" +#include "llmemtype.h" #include "viewer.h" #include "llui.h" @@ -114,6 +115,7 @@ static struct mtv_display_info mtv_display_table[] = { LLMemType::MTYPE_PIPELINE, "Pipeline", &LLColor4::green3 }, { LLMemType::MTYPE_PARTICLES, "Particles", &LLColor4::green4 }, { LLMemType::MTYPE_SPACE_PARTITION, "Space Partition", &LLColor4::blue2 }, + { LLMemType::MTYPE_VERTEX_DATA, "Vertex Buffer", &LLColor4::blue3 }, { LLMemType::MTYPE_AVATAR, "Avatar", &LLColor4::purple1 }, { LLMemType::MTYPE_REGIONS, "Regions", &LLColor4::blue1 }, { LLMemType::MTYPE_TEMP1, "Temp1", &LLColor4::red1 }, diff --git a/linden/indra/newview/llmorphview.cpp b/linden/indra/newview/llmorphview.cpp index 9c56ab3..f2ac87c 100644 --- a/linden/indra/newview/llmorphview.cpp +++ b/linden/indra/newview/llmorphview.cpp @@ -143,7 +143,7 @@ void LLMorphView::setVisible(BOOL visible) llassert( !gFloaterCustomize ); gFloaterCustomize = new LLFloaterCustomize(); gFloaterCustomize->fetchInventory(); - gFloaterCustomize->open(); + gFloaterCustomize->open(); /*Flawfinder: ignore*/ // Must do this _after_ gFloaterView is initialized. gFloaterCustomize->switchToDefaultSubpart(); diff --git a/linden/indra/newview/llmoveview.cpp b/linden/indra/newview/llmoveview.cpp index 878705f..755aec9 100644 --- a/linden/indra/newview/llmoveview.cpp +++ b/linden/indra/newview/llmoveview.cpp @@ -135,12 +135,12 @@ void LLFloaterMove::show(void*) { if (sInstance) { - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } else { LLFloaterMove* f = new LLFloaterMove(); - f->open(); + f->open(); /*Flawfinder: ignore*/ } gSavedSettings.setBOOL("ShowMovementControls", TRUE); diff --git a/linden/indra/newview/llmutelist.cpp b/linden/indra/newview/llmutelist.cpp index fc0046a..e02d6fc 100644 --- a/linden/indra/newview/llmutelist.cpp +++ b/linden/indra/newview/llmutelist.cpp @@ -356,7 +356,13 @@ std::vector LLMuteList::getMutes() const //----------------------------------------------------------------------------- BOOL LLMuteList::loadFromFile(const LLString& filename) { - FILE* fp = LLFile::fopen(filename.c_str(), "rb"); + if(!filename.size()) + { + llwarns << "Mute List Filename is Empty!" << llendl; + return FALSE; + } + + FILE* fp = LLFile::fopen(filename.c_str(), "rb"); /*Flawfinder: ignore*/ if (!fp) { llwarns << "Couldn't open mute list " << filename << llendl; @@ -365,16 +371,17 @@ BOOL LLMuteList::loadFromFile(const LLString& filename) // *NOTE: Changing the size of these buffers will require changes // in the scanf below. - char id_buffer[MAX_STRING]; - char name_buffer[MAX_STRING]; - char buffer[MAX_STRING]; + char id_buffer[MAX_STRING]; /*Flawfinder: ignore*/ + char name_buffer[MAX_STRING]; /*Flawfinder: ignore*/ + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ while (!feof(fp) && fgets(buffer, MAX_STRING, fp)) { id_buffer[0] = '\0'; name_buffer[0] = '\0'; S32 type = 0; - sscanf(buffer, " %d %254s %254[^|]", &type, id_buffer, name_buffer); + sscanf( /* Flawfinder: ignore */ + buffer, " %d %254s %254[^|]", &type, id_buffer, name_buffer); LLUUID id = LLUUID(id_buffer); LLMute mute(id, name_buffer, (LLMute::EType)type); if (mute.mID.isNull() @@ -398,14 +405,20 @@ BOOL LLMuteList::loadFromFile(const LLString& filename) //----------------------------------------------------------------------------- BOOL LLMuteList::saveToFile(const LLString& filename) { - FILE* fp = LLFile::fopen(filename.c_str(), "wb"); + if(!filename.size()) + { + llwarns << "Mute List Filename is Empty!" << llendl; + return FALSE; + } + + FILE* fp = LLFile::fopen(filename.c_str(), "wb"); /*Flawfinder: ignore*/ if (!fp) { llwarns << "Couldn't open mute list " << filename << llendl; return FALSE; } // legacy mutes have null uuid - char id_string[UUID_STR_LENGTH]; + char id_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ LLUUID::null.toString(id_string); for (string_set_t::iterator it = mLegacyMutes.begin(); it != mLegacyMutes.end(); @@ -446,10 +459,10 @@ BOOL LLMuteList::isMuted(const LLUUID& id, const LLString& name) const //----------------------------------------------------------------------------- void LLMuteList::requestFromServer(const LLUUID& agent_id) { - char agent_id_string[UUID_STR_LENGTH]; - char filename[LL_MAX_PATH]; + char agent_id_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ + char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ agent_id.toString(agent_id_string); - sprintf(filename, "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); + snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); /*Flawfinder: ignore*/ LLCRC crc; crc.update(filename); @@ -472,10 +485,10 @@ void LLMuteList::cache(const LLUUID& agent_id) // Write to disk even if empty. if(mIsLoaded) { - char agent_id_string[UUID_STR_LENGTH]; - char filename[LL_MAX_PATH]; + char agent_id_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ + char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ agent_id.toString(agent_id_string); - sprintf(filename, "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); + snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); /*Flawfinder: ignore*/ saveToFile(filename); } } @@ -495,7 +508,7 @@ void LLMuteList::processMuteListUpdate(LLMessageSystem* msg, void**) llwarns << "Got an mute list update for the wrong agent." << llendl; return; } - char filename[MAX_STRING]; + char filename[MAX_STRING]; /*Flawfinder: ignore*/ filename[0] = '\0'; msg->getStringFast(_PREHASH_MuteData, _PREHASH_Filename, MAX_STRING, filename); @@ -515,10 +528,10 @@ void LLMuteList::processUseCachedMuteList(LLMessageSystem* msg, void**) llinfos << "LLMuteList::processUseCachedMuteList()" << llendl; if (!gMuteListp) return; - char agent_id_string[UUID_STR_LENGTH]; + char agent_id_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ gAgent.getID().toString(agent_id_string); - char filename[LL_MAX_PATH]; - sprintf(filename, "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); + char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf(filename, sizeof(filename), "%s.cached_mute", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,agent_id_string).c_str()); /*Flawfinder: ignore*/ gMuteListp->loadFromFile(filename); } diff --git a/linden/indra/newview/llnamebox.cpp b/linden/indra/newview/llnamebox.cpp index bdaa224..8dacf34 100644 --- a/linden/indra/newview/llnamebox.cpp +++ b/linden/indra/newview/llnamebox.cpp @@ -66,9 +66,9 @@ void LLNameBox::setNameID(const LLUUID& name_id, BOOL is_group) { mNameID = name_id; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLString name; if (!is_group) diff --git a/linden/indra/newview/llnameeditor.cpp b/linden/indra/newview/llnameeditor.cpp index fb238e9..5cc5ddd 100644 --- a/linden/indra/newview/llnameeditor.cpp +++ b/linden/indra/newview/llnameeditor.cpp @@ -86,9 +86,9 @@ void LLNameEditor::setNameID(const LLUUID& name_id, BOOL is_group) { mNameID = name_id; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLString name; if (!is_group) diff --git a/linden/indra/newview/llnamelistctrl.cpp b/linden/indra/newview/llnamelistctrl.cpp index f02e86b..90bfb86 100644 --- a/linden/indra/newview/llnamelistctrl.cpp +++ b/linden/indra/newview/llnamelistctrl.cpp @@ -69,8 +69,8 @@ BOOL LLNameListCtrl::addNameItem(const LLUUID& agent_id, EAddPosition pos, { //llinfos << "LLNameListCtrl::addNameItem " << agent_id << llendl; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ BOOL result = gCacheName->getName(agent_id, first, last); @@ -138,7 +138,7 @@ void LLNameListCtrl::addGroupNameItem(const LLUUID& group_id, EAddPosition pos, BOOL enabled) { //llinfos << "LLNameListCtrl::addGroupNameItem " << group_id << llendl; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getGroupName(group_id, group_name); addStringUUIDItem(group_name, group_id, pos, enabled); } @@ -149,7 +149,7 @@ void LLNameListCtrl::addGroupNameItem(LLScrollListItem* item, EAddPosition pos) { //llinfos << "LLNameListCtrl::addGroupNameItem " << item->getUUID() << llendl; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getGroupName(item->getUUID(), group_name); LLScrollListCell* cell = (LLScrollListCell*)item->getColumn(mNameColumnIndex); @@ -162,8 +162,8 @@ BOOL LLNameListCtrl::addNameItem(LLScrollListItem* item, EAddPosition pos) { //llinfos << "LLNameListCtrl::addNameItem " << item->getUUID() << llendl; - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ BOOL result = gCacheName->getName(item->getUUID(), first, last); @@ -184,8 +184,8 @@ LLScrollListItem* LLNameListCtrl::addElement(const LLSD& value, EAddPosition pos { LLScrollListItem* item = LLScrollListCtrl::addElement(value, pos, userdata); - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getName(item->getUUID(), first, last); diff --git a/linden/indra/newview/llnetmap.cpp b/linden/indra/newview/llnetmap.cpp index 3db447a..dcbf960 100644 --- a/linden/indra/newview/llnetmap.cpp +++ b/linden/indra/newview/llnetmap.cpp @@ -609,7 +609,7 @@ BOOL LLNetMap::handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_s msg.assign( region->getName() ); #ifndef LL_RELEASE_FOR_DOWNLOAD - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ msg.append("\n"); region->getHost().getHostName(buffer, MAX_STRING); msg.append(buffer); @@ -791,7 +791,7 @@ BOOL LLNetMap::handleRightMouseDown(S32 x, S32 y, MASK mask) if (menu) { menu->buildDrawLabels(); - menu->updateParent(gMenuHolder); + menu->updateParent(LLMenuGL::sMenuContainer); LLMenuGL::showPopup(this, menu, x, y); } return TRUE; diff --git a/linden/indra/newview/llnotify.cpp b/linden/indra/newview/llnotify.cpp index c7d3a95..3512e57 100644 --- a/linden/indra/newview/llnotify.cpp +++ b/linden/indra/newview/llnotify.cpp @@ -281,10 +281,6 @@ LLNotifyBox::LLNotifyBox(const LLString& xml_desc, const LLString::format_map_t& // virtual LLNotifyBox::~LLNotifyBox() { - if (!mIsTip) - { - sNotifyBoxCount--; - } S32 count = mBtnCallbackData.count(); for (S32 i = 0; i < count; i++) { @@ -395,9 +391,13 @@ void LLNotifyBox::drawBackground() const void LLNotifyBox::close() { BOOL isTipTmp = mIsTip; - // delete this so that the sNotifyBoxCount is updated properly, so that the - // new frontman properly has a next button or not - delete this; + + if (!mIsTip) + { + sNotifyBoxCount--; + } + + die(); if(!isTipTmp) { LLNotifyBox * front = gNotifyBoxView->getFirstNontipBox(); @@ -714,7 +714,7 @@ LLNotifyBox * LLNotifyBoxView::getFirstNontipBox() const iter++) { LLNotifyBox * box = static_cast(*iter); - if(!box->isTip()) + if(!box->isTip() && !box->isDead()) { return box; } diff --git a/linden/indra/newview/llpanelavatar.cpp b/linden/indra/newview/llpanelavatar.cpp index c7019e0..70b18be 100644 --- a/linden/indra/newview/llpanelavatar.cpp +++ b/linden/indra/newview/llpanelavatar.cpp @@ -64,6 +64,7 @@ #include "lluiconstants.h" #include "llvoavatar.h" #include "llviewermenu.h" // *FIX: for is_agent_friend() +#include "llviewermessage.h" // send_generic_message #include "llviewerobjectlist.h" #include "llviewerregion.h" #include "llviewborder.h" @@ -253,35 +254,60 @@ BOOL LLDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop, //----------------------------------------------------------------------------- -// LLPanelAvatarSecondLife() +// LLPanelAvatarTab() //----------------------------------------------------------------------------- -LLPanelAvatarSecondLife::LLPanelAvatarSecondLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar ) +LLPanelAvatarTab::LLPanelAvatarTab(const std::string& name, const LLRect &rect, + LLPanelAvatar* panel_avatar) : LLPanel(name, rect), mPanelAvatar(panel_avatar), - mPartnerID() -{ -} + mDataRequested(false) +{ } -LLPanelAvatarSecondLife::~LLPanelAvatarSecondLife() +// virtual +void LLPanelAvatarTab::draw() { + if (getVisible()) + { + refresh(); + + LLPanel::draw(); + } } -void LLPanelAvatarSecondLife::draw() +void LLPanelAvatarTab::sendAvatarProfileRequestIfNeeded(const char* type) { - if (getVisible()) + if (!mDataRequested) { - updatePartnerName(); + std::vector strings; + strings.push_back( mPanelAvatar->getAvatarID().asString() ); + strings.push_back( type ); + send_generic_message("avatarprofilerequest", strings); + mDataRequested = true; } +} + +//----------------------------------------------------------------------------- +// LLPanelAvatarSecondLife() +//----------------------------------------------------------------------------- +LLPanelAvatarSecondLife::LLPanelAvatarSecondLife(const std::string& name, + const LLRect &rect, + LLPanelAvatar* panel_avatar ) +: LLPanelAvatarTab(name, rect, panel_avatar), + mPartnerID() +{ +} - LLPanel::draw(); +void LLPanelAvatarSecondLife::refresh() +{ + updatePartnerName(); } void LLPanelAvatarSecondLife::updatePartnerName() { if (mPartnerID.notNull()) { - char first[128]; - char last[128]; + char first[128]; /*Flawfinder: ignore*/ + char last[128]; /*Flawfinder: ignore*/ BOOL found = gCacheName->getName(mPartnerID, first, last); if (found) { @@ -378,17 +404,27 @@ void LLPanelAvatarSecondLife::onClickPublishHelp(void *) gViewerWindow->alertXml("ClickPublishHelpAvatar"); } -//----------------------------------------------------------------------------- -// LLPanelAvatarFirstLife() -//----------------------------------------------------------------------------- -LLPanelAvatarFirstLife::LLPanelAvatarFirstLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar ) -: LLPanel(name, rect), - mPanelAvatar(panel_avatar) +// static +void LLPanelAvatarSecondLife::onClickPartnerHelp(void *) +{ + gViewerWindow->alertXml("ClickPartnerHelpAvatar", onClickPartnerHelpLoadURL, (void*) NULL); +} + +// static +void LLPanelAvatarSecondLife::onClickPartnerHelpLoadURL(S32 option, void* userdata) { + if (option == 0) + LLWeb::loadURL("http://secondlife.com/partner"); } -LLPanelAvatarFirstLife::~LLPanelAvatarFirstLife() +//----------------------------------------------------------------------------- +// LLPanelAvatarFirstLife() +//----------------------------------------------------------------------------- +LLPanelAvatarFirstLife::LLPanelAvatarFirstLife(const std::string& name, + const LLRect &rect, + LLPanelAvatar* panel_avatar ) +: LLPanelAvatarTab(name, rect, panel_avatar) { } @@ -407,9 +443,10 @@ BOOL LLPanelAvatarSecondLife::postBuild(void) { childSetEnabled("born", FALSE); childSetEnabled("partner_edit", FALSE); + childSetAction("partner_help",onClickPartnerHelp,this); childSetAction("?",onClickPublishHelp,this); - BOOL own_avatar = (mPanelAvatar->getAvatarID() == gAgent.getID() ); + BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() ); enableControls(own_avatar); childSetVisible("About:",LLPanelAvatar::sAllowFirstLife); @@ -426,26 +463,30 @@ BOOL LLPanelAvatarSecondLife::postBuild(void) childSetVisible("online_unknown",FALSE); childSetVisible("online_no",FALSE); - childSetAction("Show on Map", LLPanelAvatar::onClickTrack, mPanelAvatar); - childSetAction("Instant Message...", LLPanelAvatar::onClickIM, mPanelAvatar); - childSetAction("Rate...", LLPanelAvatar::onClickRate, mPanelAvatar); - childSetAction("Pay...", LLPanelAvatar::onClickPay, mPanelAvatar); - childSetAction("Mute", LLPanelAvatar::onClickMute, mPanelAvatar ); + childSetAction("Show on Map", LLPanelAvatar::onClickTrack, getPanelAvatar()); + childSetAction("Instant Message...", LLPanelAvatar::onClickIM, getPanelAvatar()); + childSetAction("Rate...", LLPanelAvatar::onClickRate, getPanelAvatar()); + childSetAction("Pay...", LLPanelAvatar::onClickPay, getPanelAvatar()); + childSetAction("Mute", LLPanelAvatar::onClickMute, getPanelAvatar() ); - childSetAction("Offer Teleport...", LLPanelAvatar::onClickOfferTeleport, mPanelAvatar); + childSetAction("Offer Teleport...", LLPanelAvatar::onClickOfferTeleport, + getPanelAvatar() ); childSetDoubleClickCallback("groups", onDoubleClickGroup, this ); return TRUE; } + BOOL LLPanelAvatarFirstLife::postBuild(void) { - BOOL own_avatar = (mPanelAvatar->getAvatarID() == gAgent.getID() ); + BOOL own_avatar = (getPanelAvatar()->getAvatarID() == gAgent.getID() ); enableControls(own_avatar); return TRUE; } + BOOL LLPanelAvatarNotes::postBuild(void) -{ childSetCommitCallback("notes edit",onCommitNotes,this); +{ + childSetCommitCallback("notes edit",onCommitNotes,this); LLTextEditor* te = LLUICtrlFactory::getTextEditorByName(this,"notes edit"); if(te) te->setCommitOnFocusLost(TRUE); @@ -482,6 +523,7 @@ BOOL LLPanelAvatarClassified::postBuild(void) childSetAction("Delete...",onClickDelete,NULL); return TRUE; } + BOOL LLPanelAvatarPicks::postBuild(void) { childSetAction("New...",onClickNew,NULL); @@ -489,25 +531,25 @@ BOOL LLPanelAvatarPicks::postBuild(void) return TRUE; } -BOOL LLPanelAvatarAdvanced::postBuild() +BOOL LLPanelAvatarAdvanced::postBuild() { - for( S32 i = 0; i < kArraySize(mWantToCheck); i++ ) - mWantToCheck[i] = NULL; - for( S32 i = 0; i < kArraySize(mSkillsCheck); i++ ) - mSkillsCheck[i] = NULL; + for(size_t ii = 0; ii < kArraySize(mWantToCheck); ++ii) + mWantToCheck[ii] = NULL; + for(size_t ii = 0; ii < kArraySize(mSkillsCheck); ++ii) + mSkillsCheck[ii] = NULL; mWantToCount = (8>kArraySize(mWantToCheck))?kArraySize(mWantToCheck):8; - for(int t=0;t < mWantToCount ;t++) + for(S32 tt=0; tt < mWantToCount; ++tt) { - LLString ctlname = llformat("chk%d",t); - mWantToCheck[t] = LLUICtrlFactory::getCheckBoxByName(this,ctlname); + LLString ctlname = llformat("chk%d", tt); + mWantToCheck[tt] = LLUICtrlFactory::getCheckBoxByName(this,ctlname); } mSkillsCount = (6>kArraySize(mSkillsCheck))?kArraySize(mSkillsCheck):6; - for(int t=0;tsetEnabled(self); @@ -774,25 +816,27 @@ void LLPanelAvatarAdvanced::getWantSkills(U32* want_to_mask, std::string& want_t // LLPanelAvatarNotes() //----------------------------------------------------------------------------- LLPanelAvatarNotes::LLPanelAvatarNotes(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar) -: LLPanel(name, rect), - mPanelAvatar(panel_avatar) +: LLPanelAvatarTab(name, rect, panel_avatar) { } -LLPanelAvatarNotes::~LLPanelAvatarNotes() +void LLPanelAvatarNotes::refresh() { + sendAvatarProfileRequestIfNeeded("notes"); } - -void LLPanelAvatarNotes::enableControls(BOOL self) -{ } +void LLPanelAvatarNotes::clearControls() +{ + childSetText("notes edit", "Loading..."); + childSetEnabled("notes edit", false); +} // static void LLPanelAvatarNotes::onCommitNotes(LLUICtrl*, void* userdata) { LLPanelAvatarNotes* self = (LLPanelAvatarNotes*)userdata; - self->mPanelAvatar->sendAvatarNotesUpdate(); + self->getPanelAvatar()->sendAvatarNotesUpdate(); } @@ -801,33 +845,14 @@ void LLPanelAvatarNotes::onCommitNotes(LLUICtrl*, void* userdata) //----------------------------------------------------------------------------- LLPanelAvatarClassified::LLPanelAvatarClassified(const LLString& name, const LLRect& rect, LLPanelAvatar* panel_avatar) -: LLPanel(name, rect), - mPanelAvatar(panel_avatar) +: LLPanelAvatarTab(name, rect, panel_avatar) { } -LLPanelAvatarClassified::~LLPanelAvatarClassified() -{ - // children deleted by view destructor -} - - -void LLPanelAvatarClassified::draw() -{ - if (getVisible()) - { - refresh(); - - LLPanel::draw(); - } -} - - void LLPanelAvatarClassified::refresh() { - BOOL self = (gAgent.getID() == mPanelAvatar->getAvatarID()); - + BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName(this,"classified tab"); @@ -839,15 +864,12 @@ void LLPanelAvatarClassified::refresh() childSetEnabled("New...",self && allow_new); childSetEnabled("Delete...",self && allow_delete); - childSetVisible("help_text",self && show_help); childSetVisible("classified tab",!show_help); -} - -void LLPanelAvatarClassified::enableControls(BOOL self) -{ + sendAvatarProfileRequestIfNeeded("classifieds"); } + BOOL LLPanelAvatarClassified::titleIsValid() { LLTabContainerCommon* tabs = LLViewerUICtrlFactory::getTabContainerByName(this, "classified tab"); @@ -884,6 +906,10 @@ void LLPanelAvatarClassified::deleteClassifiedPanels() { tabs->deleteAllTabs(); } + + childSetVisible("New...", false); + childSetVisible("Delete...", false); + childSetVisible("loading_text", true); } @@ -892,7 +918,7 @@ void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg, S32 block = 0; S32 block_count = 0; LLUUID classified_id; - char classified_name[DB_PICK_NAME_SIZE]; + char classified_name[DB_PICK_NAME_SIZE]; /*Flawfinder: ignore*/ LLPanelClassified* panel_classified = NULL; LLTabContainerCommon* tabs = LLViewerUICtrlFactory::getTabContainerByName(this,"classified tab"); @@ -927,6 +953,10 @@ void LLPanelAvatarClassified::processAvatarClassifiedReply(LLMessageSystem* msg, { tabs->selectFirstTab(); } + + childSetVisible("New...", true); + childSetVisible("Delete...", true); + childSetVisible("loading_text", false); } @@ -1018,34 +1048,17 @@ void LLPanelAvatarClassified::callbackDelete(S32 option, void* data) //----------------------------------------------------------------------------- // LLPanelAvatarPicks() //----------------------------------------------------------------------------- -LLPanelAvatarPicks::LLPanelAvatarPicks(const std::string& name, const LLRect& rect, +LLPanelAvatarPicks::LLPanelAvatarPicks(const std::string& name, + const LLRect& rect, LLPanelAvatar* panel_avatar) -: LLPanel(name, rect), - mPanelAvatar(panel_avatar) +: LLPanelAvatarTab(name, rect, panel_avatar) { } -LLPanelAvatarPicks::~LLPanelAvatarPicks() -{ - // children deleted by view destructor -} - - -void LLPanelAvatarPicks::draw() -{ - if (getVisible()) - { - refresh(); - - LLPanel::draw(); - } -} - - void LLPanelAvatarPicks::refresh() { - BOOL self = (gAgent.getID() == mPanelAvatar->getAvatarID()); + BOOL self = (gAgent.getID() == getPanelAvatar()->getAvatarID()); LLTabContainerCommon* tabs = LLViewerUICtrlFactory::getTabContainerByName(this,"picks tab"); S32 tab_count = tabs ? tabs->getTabCount() : 0; @@ -1054,12 +1067,8 @@ void LLPanelAvatarPicks::refresh() childSetEnabled("New...",self && allow_new); childSetEnabled("Delete...",self && allow_delete); -} - -// You are only allowed 10 picks. -void LLPanelAvatarPicks::enableControls(BOOL self) -{ + sendAvatarProfileRequestIfNeeded("picks"); } @@ -1070,15 +1079,18 @@ void LLPanelAvatarPicks::deletePickPanels() { tabs->deleteAllTabs(); } -} + childSetVisible("New...", false); + childSetVisible("Delete...", false); + childSetVisible("loading_text", true); +} void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**) { S32 block = 0; S32 block_count = 0; LLUUID pick_id; - char pick_name[DB_PICK_NAME_SIZE]; + char pick_name[DB_PICK_NAME_SIZE]; /*Flawfinder: ignore*/ LLPanelPick* panel_pick = NULL; LLTabContainerCommon* tabs = LLUICtrlFactory::getTabContainerByName(this,"picks tab"); @@ -1114,6 +1126,10 @@ void LLPanelAvatarPicks::processAvatarPicksReply(LLMessageSystem* msg, void**) { tabs->selectFirstTab(); } + + childSetVisible("New...", true); + childSetVisible("Delete...", true); + childSetVisible("loading_text", false); } @@ -1313,6 +1329,31 @@ void LLPanelAvatar::setOnlineStatus(EOnlineStatus online_status) } mPanelSecondLife->childSetVisible("online_yes", (online_status == ONLINE_STATUS_YES)); + + // Since setOnlineStatus gets called after setAvatarID + // need to make sure that "Offer Teleport" doesn't get set + // to TRUE again for yourself + if (mAvatarID != gAgent.getID()) + { + childSetVisible("Offer Teleport...",TRUE); + } + + BOOL in_prelude = gAgent.inPrelude(); + if(gAgent.isGodlike()) + { + childSetEnabled("Offer Teleport...", TRUE); + childSetToolTip("Offer Teleport...", childGetValue("TeleportGod").asString()); + } + else if (in_prelude) + { + childSetEnabled("Offer Teleport...",FALSE); + childSetToolTip("Offer Teleport...",childGetValue("TeleportPrelude").asString()); + } + else + { + childSetEnabled("Offer Teleport...", (online_status == ONLINE_STATUS_YES)); + childSetToolTip("Offer Teleport...", childGetValue("TeleportNormal").asString()); + } } void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, @@ -1338,12 +1379,8 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, mPanelSecondLife->enableControls(own_avatar && mAllowEdit); mPanelWeb->enableControls(own_avatar && mAllowEdit); mPanelAdvanced->enableControls(own_avatar && mAllowEdit); - mPanelPicks->enableControls(own_avatar && mAllowEdit); - mPanelClassified->enableControls(own_avatar && mAllowEdit); // Teens don't have this. if (mPanelFirstLife) mPanelFirstLife->enableControls(own_avatar && mAllowEdit); - mPanelNotes->enableControls(own_avatar && mAllowEdit); - LLView *target_view = getChildByName("drop_target_rect", TRUE); if(target_view) @@ -1357,16 +1394,16 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, mDropTarget->setAgentID(mAvatarID); } - LLNameEditor* NameEdit = LLViewerUICtrlFactory::getNameEditorByName(this, "name"); - if(NameEdit) + LLNameEditor* name_edit = LLViewerUICtrlFactory::getNameEditorByName(this, "name"); + if(name_edit) { if (name.empty()) { - NameEdit->setNameID(avatar_id, FALSE); + name_edit->setNameID(avatar_id, FALSE); } else { - NameEdit->setText(name); + name_edit->setText(name); } } // if (avatar_changed) @@ -1374,9 +1411,19 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, // While we're waiting for data off the network, clear out the // old data. mPanelSecondLife->clearControls(); + mPanelPicks->deletePickPanels(); + mPanelPicks->setDataRequested(false); + mPanelClassified->deleteClassifiedPanels(); + mPanelClassified->setDataRequested(false); + mPanelNotes->clearControls(); + mPanelNotes->setDataRequested(false); + + // Request just the first two pages of data. The picks, + // classifieds, and notes will be requested when that panel + // is made visible. JC sendAvatarPropertiesRequest(); if (own_avatar) @@ -1423,25 +1470,6 @@ void LLPanelAvatar::setAvatarID(const LLUUID &avatar_id, const LLString &name, childSetVisible("Mute",TRUE); childSetEnabled("Mute",FALSE); - childSetVisible("Offer Teleport...",TRUE); - BOOL in_prelude = gAgent.inPrelude(); - if(gAgent.isGodlike()) - { - childSetEnabled("Offer Teleport...", TRUE); - childSetToolTip("Offer Teleport...", childGetValue("TeleportGod").asString()); - } - else if (in_prelude) - { - childSetEnabled("Offer Teleport...",FALSE); - childSetToolTip("Offer Teleport...",childGetValue("TeleportPrelude").asString()); - } - else - { - // Even if user might be offline, allow a teleport offer. - BOOL maybe_online = (online_status != ONLINE_STATUS_NO); - childSetEnabled("Offer Teleport...", maybe_online); - childSetToolTip("Offer Teleport...", childGetValue("TeleportNormal").asString()); - } childSetVisible("drop target",TRUE); childSetEnabled("drop target",FALSE); @@ -1670,12 +1698,17 @@ void LLPanelAvatar::onClickCancel(void *userdata) if (self) { - self->sendAvatarPropertiesRequest(); LLFloaterAvatarInfo *infop; if ((infop = LLFloaterAvatarInfo::getInstance(self->mAvatarID))) { infop->close(); } + else + { + // We're in the Search directory and are cancelling an edit + // to our own profile, so reset. + self->sendAvatarPropertiesRequest(); + } } } @@ -1721,16 +1754,16 @@ void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**) LLUUID image_id; LLUUID fl_image_id; LLUUID partner_id; - char about_text[DB_USER_ABOUT_BUF_SIZE]; - char fl_about_text[DB_USER_FL_ABOUT_BUF_SIZE]; - char born_on[DB_BORN_BUF_SIZE]; + char about_text[DB_USER_ABOUT_BUF_SIZE]; /*Flawfinder: ignore*/ + char fl_about_text[DB_USER_FL_ABOUT_BUF_SIZE]; /*Flawfinder: ignore*/ + char born_on[DB_BORN_BUF_SIZE]; /*Flawfinder: ignore*/ S32 charter_member_size = 0; BOOL allow_publish = FALSE; //BOOL mature = FALSE; BOOL identified = FALSE; BOOL transacted = FALSE; BOOL online = FALSE; - char profile_url[DB_USER_PROFILE_URL_BUF_SIZE]; + char profile_url[DB_USER_PROFILE_URL_BUF_SIZE]; /*Flawfinder: ignore*/ U32 flags = 0x0; @@ -1786,7 +1819,7 @@ void LLPanelAvatar::processAvatarPropertiesReply(LLMessageSystem *msg, void**) } else if(1 < charter_member_size) { - char caption[MAX_STRING]; + char caption[MAX_STRING]; /*Flawfinder: ignore*/ msg->getString("PropertiesData", "CharterMember", MAX_STRING, caption); caption_text = caption; } @@ -1868,10 +1901,10 @@ void LLPanelAvatar::processAvatarInterestsReply(LLMessageSystem *msg, void**) LLUUID avatar_id; // target of this panel U32 want_to_mask; - char want_to_text[DB_USER_WANT_TO_BUF_SIZE]; + char want_to_text[DB_USER_WANT_TO_BUF_SIZE]; /*Flawfinder: ignore*/ U32 skills_mask; - char skills_text[DB_USER_SKILLS_BUF_SIZE]; - char languages_text[DB_USER_SKILLS_BUF_SIZE]; + char skills_text[DB_USER_SKILLS_BUF_SIZE]; /*Flawfinder: ignore*/ + char languages_text[DB_USER_SKILLS_BUF_SIZE]; /*Flawfinder: ignore*/ //llinfos << "properties packet size " << msg->getReceiveSize() << llendl; @@ -1903,9 +1936,9 @@ void LLPanelAvatar::processAvatarGroupsReply(LLMessageSystem *msg, void**) LLUUID agent_id; // your id LLUUID avatar_id; // target of this panel U64 group_powers; - char group_title[DB_GROUP_TITLE_BUF_SIZE]; + char group_title[DB_GROUP_TITLE_BUF_SIZE]; /*Flawfinder: ignore*/ LLUUID group_id; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ LLUUID group_insignia_id; const LLFontGL* FONT = LLFontGL::sSansSerifSmall; @@ -2117,10 +2150,10 @@ void LLPanelAvatar::processAvatarStatisticsReply(LLMessageSystem *msg, void**) S32 items = msg->getNumberOfBlocksFast(_PREHASH_StatisticsData); for (S32 i = 0; i < items; i++) { - char name[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ S32 positive; S32 negative; - char value_string[MAX_STRING]; + char value_string[MAX_STRING]; /*Flawfinder: ignore*/ msg->getStringFast( _PREHASH_StatisticsData, _PREHASH_Name, MAX_STRING, name, i); @@ -2134,7 +2167,7 @@ void LLPanelAvatar::processAvatarStatisticsReply(LLMessageSystem *msg, void**) item = new LLScrollListItem(); item->addColumn( name, font, TEXT_WIDTH ); - sprintf( value_string, "+%d", positive); + snprintf( value_string, sizeof(value_string), "+%d", positive); /*Flawfinder: ignore*/ item->addColumn( value_string, font, 50 ); item->addColumn("", font); // extra column to force striped appearance @@ -2163,9 +2196,10 @@ void LLPanelAvatar::processAvatarNotesReply(LLMessageSystem *msg, void**) continue; } - char text[DB_USER_NOTE_SIZE]; + char text[DB_USER_NOTE_SIZE]; /*Flawfinder: ignore*/ msg->getString("Data", "Notes", DB_USER_NOTE_SIZE, text); self->childSetValue("notes edit", text); + self->childSetEnabled("notes edit", true); } } diff --git a/linden/indra/newview/llpanelavatar.h b/linden/indra/newview/llpanelavatar.h index 81cfe02..3e8bffd 100644 --- a/linden/indra/newview/llpanelavatar.h +++ b/linden/indra/newview/llpanelavatar.h @@ -59,35 +59,61 @@ enum EOnlineStatus ONLINE_STATUS_YES = 1 }; -class LLPanelAvatarFirstLife -: public LLPanel +// Base class for all sub-tabs inside the avatar profile. Many of these +// panels need to keep track of the parent panel (to get the avatar id) +// and only request data from the database when they are first drawn. JC +class LLPanelAvatarTab : public LLPanel { public: - LLPanelAvatarFirstLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar); - /*virtual*/ ~LLPanelAvatarFirstLife(); - /*virtual*/ BOOL postBuild(void); + LLPanelAvatarTab(const std::string& name, const LLRect &rect, + LLPanelAvatar* panel_avatar); - void enableControls(BOOL own_avatar); + // Calls refresh() once per frame when panel is visible + /*virtual*/ void draw(); -protected: + LLPanelAvatar* getPanelAvatar() const { return mPanelAvatar; } + + void setDataRequested(bool requested) { mDataRequested = requested; } + bool isDataRequested() const { return mDataRequested; } + + // If the data for this tab has not yet been requested, + // send the request. Used by tabs that are filled in only + // when they are first displayed. + // type is one of "notes", "classifieds", "picks" + void sendAvatarProfileRequestIfNeeded(const char* type); + +private: LLPanelAvatar* mPanelAvatar; + bool mDataRequested; +}; + + +class LLPanelAvatarFirstLife : public LLPanelAvatarTab +{ +public: + LLPanelAvatarFirstLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar); + + /*virtual*/ BOOL postBuild(void); + + void enableControls(BOOL own_avatar); }; class LLPanelAvatarSecondLife -: public LLPanel +: public LLPanelAvatarTab { public: LLPanelAvatarSecondLife(const std::string& name, const LLRect &rect, LLPanelAvatar* panel_avatar ); - /*virtual*/ ~LLPanelAvatarSecondLife(); - /*virtual*/ BOOL postBuild(void); - /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(void); + /*virtual*/ void refresh(); static void onClickImage( void *userdata); static void onClickFriends( void *userdata); static void onDoubleClickGroup(void* userdata); static void onClickPublishHelp(void *userdata); + static void onClickPartnerHelp(void *userdata); + static void onClickPartnerHelpLoadURL(S32 option, void* userdata); // Clear out the controls anticipating new network data. void clearControls(); @@ -97,15 +123,14 @@ public: void setPartnerID(LLUUID id) { mPartnerID = id; } -protected: - LLPanelAvatar* mPanelAvatar; - +private: LLUUID mPartnerID; }; + // WARNING! The order of the inheritance here matters!! Do not change. - KLW class LLPanelAvatarWeb : - public LLPanel + public LLPanelAvatarTab #if LL_LIBXUL_ENABLED , public LLWebBrowserCtrlObserver #endif @@ -132,17 +157,17 @@ public: virtual void onLocationChange( const EventType& eventIn ); #endif -protected: - LLPanelAvatar* mPanelAvatar; +private: std::string mURL; LLWebBrowserCtrl* mWebBrowser; }; -class LLPanelAvatarAdvanced : public LLPanel + +class LLPanelAvatarAdvanced : public LLPanelAvatarTab { public: LLPanelAvatarAdvanced(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar); - /*virtual*/ ~LLPanelAvatarAdvanced(); + /*virtual*/ BOOL postBuild(void); void enableControls(BOOL own_avatar); @@ -153,8 +178,7 @@ public: U32* skills_mask, std::string& skills_text, std::string& languages_text); -protected: - LLPanelAvatar* mPanelAvatar; +private: S32 mWantToCount; S32 mSkillsCount; LLCheckBoxCtrl *mWantToCheck[8]; @@ -164,35 +188,31 @@ protected: }; -class LLPanelAvatarNotes : public LLPanel +class LLPanelAvatarNotes : public LLPanelAvatarTab { public: LLPanelAvatarNotes(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar); - /*virtual*/ ~LLPanelAvatarNotes(); + /*virtual*/ BOOL postBuild(void); - void enableControls(BOOL own_avatar); + /*virtual*/ void refresh(); - static void onCommitNotes(LLUICtrl* field, void* userdata); + void clearControls(); -protected: - LLPanelAvatar* mPanelAvatar; + static void onCommitNotes(LLUICtrl* field, void* userdata); }; -class LLPanelAvatarClassified : public LLPanel +class LLPanelAvatarClassified : public LLPanelAvatarTab { public: LLPanelAvatarClassified(const LLString& name, const LLRect& rect, LLPanelAvatar* panel_avatar); - /*virtual*/ ~LLPanelAvatarClassified(); - /*virtual*/ BOOL postBuild(void); - /*virtual*/ void draw(); + /*virtual*/ BOOL postBuild(void); - void refresh(); + /*virtual*/ void refresh(); void apply(); - void enableControls(BOOL own_avatar); BOOL titleIsValid(); @@ -209,23 +229,17 @@ private: static void callbackDelete(S32 option, void* data); static void callbackNew(S32 option, void* data); - -private: - LLPanelAvatar* mPanelAvatar; }; -class LLPanelAvatarPicks : public LLPanel + +class LLPanelAvatarPicks : public LLPanelAvatarTab { public: LLPanelAvatarPicks(const std::string& name, const LLRect& rect, LLPanelAvatar* panel_avatar); - /*virtual*/ ~LLPanelAvatarPicks(); /*virtual*/ BOOL postBuild(void); - /*virtual*/ void draw(); - - void refresh(); - void enableControls(BOOL own_avatar); + /*virtual*/ void refresh(); // Delete all the pick sub-panels from the tab container void deletePickPanels(); @@ -240,9 +254,6 @@ private: static void onClickDelete(void* data); static void callbackDelete(S32 option, void* data); - -private: - LLPanelAvatar* mPanelAvatar; }; diff --git a/linden/indra/newview/llpanelclassified.cpp b/linden/indra/newview/llpanelclassified.cpp index d6ca984..11120e0 100644 --- a/linden/indra/newview/llpanelclassified.cpp +++ b/linden/indra/newview/llpanelclassified.cpp @@ -102,16 +102,17 @@ LLPanelClassified::LLPanelClassified(BOOL in_finder) mDataRequested(FALSE), mEnableCommit(FALSE), mPaidFor(FALSE), - mParcelID(), mPosGlobal(), mSnapshotCtrl(NULL), mNameEditor(NULL), - mLocationEditor(NULL), mDescEditor(NULL), + mLocationEditor(NULL), + mCategoryCombo(NULL), + mUpdateBtn(NULL), mTeleportBtn(NULL), mMapBtn(NULL), - //mLandmarkBtn(NULL), - //mEnabledCheck(NULL), + mProfileBtn(NULL), + mInfoText(NULL), mMatureCheck(NULL), mAutoRenewCheck(NULL), mSetBtn(NULL), @@ -441,10 +442,10 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void ** LLUUID parcel_id; msg->getUUIDFast(_PREHASH_Data, _PREHASH_ParcelID, parcel_id); - char name[DB_PARCEL_NAME_SIZE]; + char name[DB_PARCEL_NAME_SIZE]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_Data, _PREHASH_Name, DB_PARCEL_NAME_SIZE, name); - char desc[DB_PICK_DESC_SIZE]; + char desc[DB_PICK_DESC_SIZE]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_Data, _PREHASH_Desc, DB_PICK_DESC_SIZE, desc); LLUUID snapshot_id; @@ -452,7 +453,7 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void ** // "Location text" is actually the original // name that owner gave the parcel, and the location. - char buffer[256]; + char buffer[256]; /*Flawfinder: ignore*/ LLString location_text; msg->getStringFast(_PREHASH_Data, _PREHASH_ParcelName, 256, buffer); @@ -466,7 +467,7 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void ** location_text.assign(""); } - char sim_name[256]; + char sim_name[256]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_Data, _PREHASH_SimName, 256, sim_name); LLVector3d pos_global; @@ -476,7 +477,7 @@ void LLPanelClassified::processClassifiedInfoReply(LLMessageSystem *msg, void ** S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; S32 region_z = llround((F32)pos_global.mdV[VZ]); - sprintf(buffer, "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z); + snprintf(buffer, sizeof(buffer), "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z); /*Flawfinder: ignore*/ location_text.append(buffer); U8 flags; @@ -762,7 +763,7 @@ void LLPanelClassified::onClickSet(void* data) self->mPosGlobal = gAgent.getPositionGlobal(); LLString location_text; - location_text.assign("(will update after save)"); + location_text.assign("(will update after publish)"); location_text.append(", "); S32 region_x = llround((F32)self->mPosGlobal.mdV[VX]) % REGION_WIDTH_UNITS; @@ -804,7 +805,7 @@ void LLPanelClassified::sendClassifiedClickMessage(const char* type) // You're allowed to click on your own ads to reassure yourself // that the system is working. std::vector strings; - strings.push_back(mClassifiedID.getString()); + strings.push_back(mClassifiedID.asString()); strings.push_back(type); LLUUID no_invoice; send_generic_message("classifiedclick", strings, no_invoice); diff --git a/linden/indra/newview/llpanelcontents.cpp b/linden/indra/newview/llpanelcontents.cpp index 6fa34cf..47f2d35 100644 --- a/linden/indra/newview/llpanelcontents.cpp +++ b/linden/indra/newview/llpanelcontents.cpp @@ -115,8 +115,8 @@ void LLPanelContents::getState(LLViewerObject *objectp ) // unambiguous destination for the object. if( editable && all_volume && - ((gSelectMgr->getRootObjectCount() == 1) - || (gSelectMgr->getObjectCount() == 1))) + ((gSelectMgr->getSelection()->getRootObjectCount() == 1) + || (gSelectMgr->getSelection()->getObjectCount() == 1))) { //mBtnNewScript->setEnabled(TRUE); childSetEnabled("button new script",TRUE); @@ -131,10 +131,10 @@ void LLPanelContents::getState(LLViewerObject *objectp ) void LLPanelContents::refresh() { - LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject(); if(!object) { - object = gSelectMgr->getFirstObject(); + object = gSelectMgr->getSelection()->getFirstObject(); } getState(object); @@ -153,10 +153,10 @@ void LLPanelContents::refresh() // static void LLPanelContents::onClickNewScript(void *userdata) { - LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject(); if(!object) { - object = gSelectMgr->getFirstObject(); + object = gSelectMgr->getSelection()->getFirstObject(); } if(object) { @@ -203,7 +203,7 @@ void LLPanelContents::onClickNewScript(void *userdata) "Script: New Script", object->mID, LLUUID::null); - editor->open(); + editor->open(); /*Flawfinder: ignore*/ // keep onscreen gFloaterView->adjustToFitScreen(editor, FALSE); diff --git a/linden/indra/newview/llpaneldirbrowser.cpp b/linden/indra/newview/llpaneldirbrowser.cpp index f701bf4..7f15a85 100644 --- a/linden/indra/newview/llpaneldirbrowser.cpp +++ b/linden/indra/newview/llpaneldirbrowser.cpp @@ -400,8 +400,8 @@ void LLPanelDirBrowser::showEvent(const U32 event_id) void LLPanelDirBrowser::processDirPeopleReply(LLMessageSystem *msg, void**) { LLUUID query_id; - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_LAST_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char last_name[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ LLUUID agent_id; msg->getUUIDFast(_PREHASH_QueryData,_PREHASH_QueryID, query_id); @@ -471,9 +471,7 @@ void LLPanelDirBrowser::processDirPeopleReply(LLMessageSystem *msg, void**) content["name"] = fullname; list->addElement(row); - - LLString id_str = agent_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[agent_id.asString()] = content; } list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending); @@ -490,7 +488,7 @@ void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**) LLUUID agent_id; LLUUID query_id; LLUUID parcel_id; - char name[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ BOOL is_for_sale; BOOL is_auction; BOOL is_newbie; @@ -552,9 +550,7 @@ void LLPanelDirBrowser::processDirPlacesReply(LLMessageSystem* msg, void**) row["columns"][3]["font"] = "SANSSERIFSMALL"; list->addElement(row); - - LLString id_str = parcel_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[parcel_id.asString()] = content; } list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending); @@ -572,7 +568,7 @@ void LLPanelDirBrowser::processDirPopularReply(LLMessageSystem *msg, void**) LLUUID agent_id; LLUUID query_id; LLUUID parcel_id; - char name[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ F32 dwell; msg->getUUID("AgentData", "AgentID", agent_id); @@ -634,9 +630,7 @@ void LLPanelDirBrowser::processDirPopularReply(LLMessageSystem *msg, void**) row["columns"][2]["font"] = "SANSSERIFSMALL"; list->addElement(row); - - LLString id_str = parcel_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[parcel_id.asString()] = content; } list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending); @@ -653,8 +647,8 @@ void LLPanelDirBrowser::processDirEventsReply(LLMessageSystem* msg, void**) LLUUID agent_id; LLUUID query_id; LLUUID owner_id; - char name[MAX_STRING]; - char date[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ + char date[MAX_STRING]; /*Flawfinder: ignore*/ BOOL show_mature = gSavedSettings.getBOOL("ShowMatureEvents"); msg->getUUID("AgentData", "AgentID", agent_id); @@ -771,7 +765,7 @@ void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**) LLUUID query_id; LLUUID group_id; - char group_name[DB_GROUP_NAME_BUF_SIZE]; + char group_name[DB_GROUP_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ S32 members; BOOL open_enrollment; S32 membership_fee; @@ -836,8 +830,7 @@ void LLPanelDirBrowser::processDirGroupsReply(LLMessageSystem* msg, void**) row["columns"][2]["font"] = "SANSSERIFSMALL"; list->addElement(row); - LLString id_str = group_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[group_id.asString()] = content; } list->sortByColumn(self->mCurrentSortColumn, self->mCurrentSortAscending); self->updateResultCount(); @@ -890,7 +883,7 @@ void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**) for (i = 0; i < num_new_rows; i++) { LLUUID classified_id; - char name[DB_PARCEL_NAME_SIZE]; + char name[DB_PARCEL_NAME_SIZE]; /*Flawfinder: ignore*/ U32 creation_date = 0; // unix timestamp U32 expiration_date = 0; // future use S32 price_for_listing = 0; @@ -907,9 +900,7 @@ void LLPanelDirBrowser::processDirClassifiedReply(LLMessageSystem* msg, void**) LLSD content; content["type"] = CLASSIFIED_CODE; content["name"] = name; - - LLString id_str = classified_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[classified_id.asString()] = content; } } // The server does the initial sort, by price paid per listing and date. JC @@ -925,7 +916,7 @@ void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**) LLUUID agent_id; LLUUID query_id; LLUUID parcel_id; - char name[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ BOOL auction; BOOL for_sale; S32 sale_price; @@ -1033,8 +1024,7 @@ void LLPanelDirBrowser::processDirLandReply(LLMessageSystem *msg, void**) } list->addElement(row); - LLString id_str = parcel_id.getString(); - self->mResultsContents[id_str] = content; + self->mResultsContents[parcel_id.asString()] = content; } // All auction results are shown on the first page diff --git a/linden/indra/newview/llpaneldirevents.cpp b/linden/indra/newview/llpaneldirevents.cpp index 703ee5e..f3cd2ce 100644 --- a/linden/indra/newview/llpaneldirevents.cpp +++ b/linden/indra/newview/llpaneldirevents.cpp @@ -50,8 +50,8 @@ BOOL gDisplayEventHack = FALSE; LLPanelDirEvents::LLPanelDirEvents(const std::string& name, LLFloaterDirectory* floater) : LLPanelDirBrowser(name, floater), - mDay(0), - mDoneQuery(FALSE) + mDoneQuery(FALSE), + mDay(0) { // more results per page for this mResultsPerPage = 200; diff --git a/linden/indra/newview/llpaneldisplay.cpp b/linden/indra/newview/llpaneldisplay.cpp index ea3d7e7..a8611b1 100644 --- a/linden/indra/newview/llpaneldisplay.cpp +++ b/linden/indra/newview/llpaneldisplay.cpp @@ -247,11 +247,11 @@ void LLPanelDisplay::onApplyResolution(LLUICtrl* src, void* user_data) void LLPanelDisplay::applyResolution() { - char aspect_ratio_text[ASPECT_RATIO_STR_LEN]; + char aspect_ratio_text[ASPECT_RATIO_STR_LEN]; /*Flawfinder: ignore*/ if (mCtrlAspectRatio->getCurrentIndex() == -1) { - strcpy(aspect_ratio_text, mCtrlAspectRatio->getSimple().c_str()); - + strncpy(aspect_ratio_text, mCtrlAspectRatio->getSimple().c_str(), sizeof(aspect_ratio_text) -1); /*Flawfinder: ignore*/ + aspect_ratio_text[sizeof(aspect_ratio_text) -1] = '\0'; char *element = strtok(aspect_ratio_text, ":/\\"); if (!element) { @@ -385,7 +385,7 @@ void LLPanelDisplay::onCommitAutoDetectAspect(LLUICtrl *ctrl, void *data) if (auto_detect) { - char aspect[100]; + char aspect[100]; /*Flawfinder: ignore*/ S32 numerator = 0; S32 denominator = 0; // clear any aspect ratio override @@ -394,11 +394,11 @@ void LLPanelDisplay::onCommitAutoDetectAspect(LLUICtrl *ctrl, void *data) if (numerator != 0) { - sprintf(aspect, "%d:%d", numerator, denominator); + snprintf(aspect, sizeof(aspect), "%d:%d", numerator, denominator); /*Flawfinder: ignore*/ } else { - sprintf(aspect, "%.3f", gViewerWindow->mWindow->getNativeAspectRatio()); + snprintf(aspect, sizeof(aspect), "%.3f", gViewerWindow->mWindow->getNativeAspectRatio()); /*Flawfinder: ignore*/ } panel->mCtrlAspectRatio->setLabel(aspect); @@ -449,7 +449,7 @@ BOOL LLPanelDisplay2::postBuild() requires("ani", WIDGET_TYPE_CHECKBOX); requires("gamma", WIDGET_TYPE_SPINNER); - requires("agp", WIDGET_TYPE_CHECKBOX); + requires("vbo", WIDGET_TYPE_CHECKBOX); requires("video card memory radio", WIDGET_TYPE_RADIO_GROUP); requires("fog", WIDGET_TYPE_SPINNER); requires("particles", WIDGET_TYPE_SPINNER); @@ -460,35 +460,9 @@ BOOL LLPanelDisplay2::postBuild() return FALSE; } - //============================================================================ - //Visual Enancements - - // Anisotropic filtering checkbox - mCtrlAnisotropic = LLUICtrlFactory::getCheckBoxByName(this, "ani"); - - //============================================================================ - // Gamma - mCtrlGamma = LLUICtrlFactory::getSpinnerByName(this, "gamma"); - - // Nighttime brigtness detail slider - mCtrlNighttimeBrightness = LLUICtrlFactory::getSpinnerByName(this, "nighttime_brightness"); - - //============================================================================ - // Use AGP - mCtrlUseAGP = LLUICtrlFactory::getCheckBoxByName(this, "agp"); - // Graphics Card Memory mRadioVideoCardMem = LLUICtrlFactory::getRadioGroupByName(this, "video card memory radio"); - // Fog ratio spin ctrl - mCtrlFogRatio = LLUICtrlFactory::getSpinnerByName(this, "fog"); - - // Particle count spin ctrl - mCtrlParticles = LLUICtrlFactory::getSpinnerByName(this, "particles"); - - // Avatar composite limit spin ctrl - mCtrlCompositeLimit = LLUICtrlFactory::getSpinnerByName(this, "comp limit"); - refresh(); return TRUE; @@ -504,7 +478,7 @@ void LLPanelDisplay2::refresh() { LLPanel::refresh(); - mUseAGP = gSavedSettings.getBOOL("RenderUseAGP"); + mUseVBO = gSavedSettings.getBOOL("RenderVBOEnable"); mUseAniso = gSavedSettings.getBOOL("RenderAnisotropic"); mGamma = gSavedSettings.getF32("RenderGamma"); mBrightness = gSavedSettings.getF32("RenderNightBrightness"); @@ -525,9 +499,10 @@ void LLPanelDisplay2::refreshEnabledState() mRadioVideoCardMem->getRadioButton(i)->setEnabled(FALSE); } - if (!gGLManager.mHasAnyAGP || !gFeatureManagerp->isFeatureAvailable("RenderAGP")) + if (!gFeatureManagerp->isFeatureAvailable("RenderVBO") || + !gGLManager.mHasVertexBufferObject) { - mCtrlUseAGP->setEnabled(FALSE); + childSetEnabled("vbo", FALSE); } } @@ -535,7 +510,7 @@ void LLPanelDisplay2::apply() { // Anisotropic rendering BOOL old_anisotropic = LLImageGL::sGlobalUseAnisotropic; - LLImageGL::sGlobalUseAnisotropic = mCtrlAnisotropic->get(); + LLImageGL::sGlobalUseAnisotropic = childGetValue("ani"); if (old_anisotropic != LLImageGL::sGlobalUseAnisotropic) { BOOL logged_in = (gStartupState >= STATE_STARTED); @@ -549,7 +524,7 @@ void LLPanelDisplay2::apply() void LLPanelDisplay2::cancel() { - gSavedSettings.setBOOL("RenderUseAGP", mUseAGP); + gSavedSettings.setBOOL("RenderVBOEnable", mUseVBO); gSavedSettings.setBOOL("RenderAnisotropic", mUseAniso); gSavedSettings.setF32("RenderGamma", mGamma); gSavedSettings.setF32("RenderNightBrightness", mBrightness); diff --git a/linden/indra/newview/llpaneldisplay.h b/linden/indra/newview/llpaneldisplay.h index ed711c5..305b290 100644 --- a/linden/indra/newview/llpaneldisplay.h +++ b/linden/indra/newview/llpaneldisplay.h @@ -90,17 +90,9 @@ public: void refreshEnabledState(); protected: - LLCheckBoxCtrl *mCtrlAnisotropic; // Anisitropic filtering - LLSpinCtrl *mCtrlGamma; - LLSpinCtrl *mCtrlNighttimeBrightness; // user adjusted nighttime brightness ([0.0, 2.0] 1.0 = normal) - LLCheckBoxCtrl *mCtrlUseAGP; // Use AGP if available - LLSpinCtrl *mCtrlFogRatio; // Fig distance / draw distance ratio - LLSpinCtrl *mCtrlParticles; // Max number of particles - LLSpinCtrl *mCtrlCompositeLimit; // Max num non-self avatars that can be composited - LLRadioGroup* mRadioVideoCardMem; - BOOL mUseAGP; + BOOL mUseVBO; BOOL mUseAniso; F32 mGamma; F32 mBrightness; diff --git a/linden/indra/newview/llpanelevent.cpp b/linden/indra/newview/llpanelevent.cpp index 498d4fc..9478ea2 100644 --- a/linden/indra/newview/llpanelevent.cpp +++ b/linden/indra/newview/llpanelevent.cpp @@ -166,7 +166,7 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) { continue; } - char buffer[256]; + char buffer[256]; /*Flawfinder: ignore*/ self->mEventInfo.unpack(msg); self->mTBName->setText(self->mEventInfo.mName); @@ -174,7 +174,7 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) self->mTBDate->setText(self->mEventInfo.mTimeStr); self->mTBDesc->setText(self->mEventInfo.mDesc); - sprintf(buffer, "%d:%.2d", self->mEventInfo.mDuration / 60, self->mEventInfo.mDuration % 60); + snprintf(buffer, sizeof(buffer), "%d:%.2d", self->mEventInfo.mDuration / 60, self->mEventInfo.mDuration % 60); /*Flawfinder: ignore*/ self->mTBDuration->setText(buffer); @@ -184,7 +184,7 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) } else { - sprintf(buffer, "%d", self->mEventInfo.mCover); + snprintf(buffer, sizeof(buffer), "%d", self->mEventInfo.mCover); /*Flawfinder: ignore*/ self->mTBCover->setText(buffer); } @@ -195,7 +195,7 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) S32 region_y = llround(global_y) % REGION_WIDTH_UNITS; S32 region_z = llround((F32)self->mEventInfo.mPosGlobal.mdV[VZ]); - sprintf(buffer, "%s (%d, %d, %d)", self->mEventInfo.mSimName.c_str(), region_x, region_y, region_z); + snprintf(buffer, sizeof(buffer), "%s (%d, %d, %d)", self->mEventInfo.mSimName.c_str(), region_x, region_y, region_z); /*Flawfinder: ignore*/ self->mTBLocation->setText(buffer); if (self->mEventInfo.mEventFlags & EVENT_FLAG_MATURE) @@ -232,8 +232,8 @@ void LLPanelEvent::processEventInfoReply(LLMessageSystem *msg, void **) void LLPanelEvent::draw() { - char firstname[DB_FIRST_NAME_BUF_SIZE]; - char lastname[DB_LAST_NAME_BUF_SIZE]; + char firstname[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char lastname[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ gCacheName->getName(mEventInfo.mRunByID, firstname, lastname); LLString name; diff --git a/linden/indra/newview/llpanelface.cpp b/linden/indra/newview/llpanelface.cpp index 56deb91..c69d765 100644 --- a/linden/indra/newview/llpanelface.cpp +++ b/linden/indra/newview/llpanelface.cpp @@ -257,7 +257,8 @@ void LLPanelFace::sendTextureInfo() { S32 te; LLViewerObject* object; - for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) ) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) ) { BOOL valid; F32 value; @@ -336,7 +337,7 @@ void LLPanelFace::sendTextureInfo() } } - for ( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() ) + for ( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() ) { object->sendTEUpdate(); } @@ -344,7 +345,7 @@ void LLPanelFace::sendTextureInfo() void LLPanelFace::getState() { - LLViewerObject* objectp = gSelectMgr->getFirstObject(); + LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstObject(); if( objectp && objectp->getPCode() == LL_PCODE_VOLUME) @@ -619,7 +620,7 @@ BOOL LLPanelFace::allFacesSameValue( F32 (get_face_value(LLViewerObject*, S32)), // Get the value from the primary selected TE F32 first_value = *value; BOOL got_first = FALSE; - gSelectMgr->getPrimaryTE(&object, &te); + gSelectMgr->getSelection()->getPrimaryTE(&object, &te); if (object) { first_value = get_face_value(object, te); @@ -628,7 +629,8 @@ BOOL LLPanelFace::allFacesSameValue( F32 (get_face_value(LLViewerObject*, S32)), // Now iterate through all TEs to test for sameness BOOL identical = TRUE; - for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) ) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) ) { if (!got_first) { @@ -779,13 +781,13 @@ void LLPanelFace::onCommitFullbright(LLUICtrl* ctrl, void* userdata) BOOL LLPanelFace::onDragTexture(LLUICtrl*, LLInventoryItem* item, void*) { BOOL accept = TRUE; - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); + LLViewerObject* obj = gSelectMgr->getSelection()->getFirstRootObject(); while(accept && obj) { if(!LLToolDragAndDrop::isInventoryDropAcceptable(obj, item)) accept = FALSE; else - obj = gSelectMgr->getNextRootObject(); + obj = gSelectMgr->getSelection()->getNextRootObject(); } return accept; } @@ -842,7 +844,8 @@ void LLPanelFace::onClickAutoFix(void* userdata) LLViewerObject* object; // for all selected objects - for ( gSelectMgr->getFirstTE(&object, &te); object; gSelectMgr->getNextTE(&object, &te) ) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for ( selection->getFirstTE(&object, &te); object; selection->getNextTE(&object, &te) ) { // only do this if it's a media texture if ( object->getTE ( te )->getID() == LLMediaEngine::getInstance()->getImageUUID () ) @@ -867,7 +870,7 @@ void LLPanelFace::onClickAutoFix(void* userdata) }; // not clear why this is in a separate loop but i followed the patter from further up this file just in case. - for ( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() ) + for ( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() ) { object->sendTEUpdate(); }; diff --git a/linden/indra/newview/llpanelgroup.cpp b/linden/indra/newview/llpanelgroup.cpp index 8a44da5..ce7c67a 100644 --- a/linden/indra/newview/llpanelgroup.cpp +++ b/linden/indra/newview/llpanelgroup.cpp @@ -151,8 +151,8 @@ LLPanelGroup::LLPanelGroup(const std::string& filename, mCurrentTab( NULL ), mRequestedTab( NULL ), mTabContainer( NULL ), - mForceClose( FALSE ), mIgnoreTransition( FALSE ), + mForceClose( FALSE ), mInitialTab(initial_tab_selected), mAllowEdit( TRUE ), mShowingNotifyDialog( FALSE ) diff --git a/linden/indra/newview/llpanelgroupgeneral.cpp b/linden/indra/newview/llpanelgroupgeneral.cpp index 871bc4b..e99f341 100644 --- a/linden/indra/newview/llpanelgroupgeneral.cpp +++ b/linden/indra/newview/llpanelgroupgeneral.cpp @@ -452,7 +452,7 @@ bool LLPanelGroupGeneral::apply(LLString& mesg) if (!gdatap) { mesg = "No group data found for group "; - mesg.append(mGroupID.getString()); + mesg.append(mGroupID.asString()); return false; } @@ -638,7 +638,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) } if ( mBtnJoinGroup ) { - char fee_buff[20]; + char fee_buff[20]; /*Flawfinder: ignore*/ bool visible; visible = !is_member && gdatap->mOpenEnrollment; @@ -646,7 +646,7 @@ void LLPanelGroupGeneral::update(LLGroupChange gc) if ( visible ) { - sprintf(fee_buff, "Join (L$%d)", gdatap->mMembershipFee); + snprintf(fee_buff, sizeof(fee_buff), "Join (L$%d)", gdatap->mMembershipFee); /*Flawfinder: ignore*/ mBtnJoinGroup->setLabelSelected(std::string(fee_buff)); mBtnJoinGroup->setLabelUnselected(std::string(fee_buff)); } diff --git a/linden/indra/newview/llpanelgrouplandmoney.cpp b/linden/indra/newview/llpanelgrouplandmoney.cpp index e7dcb9f..21f4d4b 100644 --- a/linden/indra/newview/llpanelgrouplandmoney.cpp +++ b/linden/indra/newview/llpanelgrouplandmoney.cpp @@ -226,9 +226,9 @@ int LLPanelGroupLandMoney::impl::getStoredContribution() // Fills in the text field with the contribution, contrib void LLPanelGroupLandMoney::impl::setYourContributionTextField(int contrib) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore*/ buffer[0] = '\0'; - sprintf(buffer, "%d", contrib); + snprintf(buffer, sizeof(buffer), "%d", contrib); /* Flawfinder: ignore*/ if ( mYourContributionEditorp ) { @@ -239,10 +239,10 @@ void LLPanelGroupLandMoney::impl::setYourContributionTextField(int contrib) void LLPanelGroupLandMoney::impl::setYourMaxContributionTextBox(int max) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ buffer[0] = '\0'; - sprintf(buffer, "(%d max)", max); + snprintf(buffer, sizeof(buffer), "(%d max)", max); /*Flawfinder: ignore*/ if ( mYourContributionMaxTextp ) { mYourContributionMaxTextp->setText(buffer); @@ -307,15 +307,15 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) ++first_block; S32 total_contribution; msg->getS32("QueryData", "ActualArea", total_contribution, 0); - char buffer[MAX_STRING]; - sprintf(buffer, "%d sq. meters", total_contribution); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "%d sq. meters", total_contribution); /*Flawfinder: ignore*/ mTotalContributedLandp->setText(buffer); S32 committed; msg->getS32("QueryData", "BillableArea", committed, 0); - sprintf(buffer, "%d sq. meters", committed); + snprintf(buffer, sizeof(buffer), "%d sq. meters", committed); /*Flawfinder: ignore*/ mTotalLandInUsep->setText(buffer); S32 available = total_contribution - committed; - sprintf(buffer, "%d sq. meters", available); + snprintf(buffer, sizeof(buffer), "%d sq. meters", available); /*Flawfinder: ignore*/ mLandAvailablep->setText(buffer); buffer[0] = '\0'; if ( mGroupOverLimitTextp && mGroupOverLimitIconp ) @@ -336,14 +336,14 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) mMapButtonp->setEnabled(TRUE); } - char name[MAX_STRING]; - char desc[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ + char desc[MAX_STRING]; /*Flawfinder: ignore*/ S32 actual_area; S32 billable_area; U8 flags; F32 global_x; F32 global_y; - char sim_name[MAX_STRING]; + char sim_name[MAX_STRING]; /*Flawfinder: ignore*/ for(S32 i = first_block; i < count; ++i) { msg->getUUID("QueryData", "OwnerID", owner_id, i); @@ -358,19 +358,19 @@ void LLPanelGroupLandMoney::impl::processGroupLand(LLMessageSystem* msg) S32 region_x = llround(global_x) % REGION_WIDTH_UNITS; S32 region_y = llround(global_y) % REGION_WIDTH_UNITS; - char location[MAX_STRING]; - sprintf(location, "%s (%d, %d)", sim_name, region_x, region_y); - char area[MAX_STRING]; + char location[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(location, MAX_STRING, "%s (%d, %d)", sim_name, region_x, region_y); /*Flawfinder: ignore*/ + char area[MAX_STRING]; /*Flawfinder: ignore*/ if(billable_area == actual_area) { - sprintf(area, "%d", billable_area); + snprintf(area, MAX_STRING, "%d", billable_area); /*Flawfinder: ignore*/ } else { - sprintf(area, "%d / %d", billable_area, actual_area); + snprintf(area, MAX_STRING, "%d / %d", billable_area, actual_area); /*Flawfinder: ignore*/ } - char hidden[MAX_STRING]; - sprintf(hidden, "%f %f", global_x, global_y); + char hidden[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(hidden, MAX_STRING, "%f %f", global_x, global_y); /*Flawfinder: ignore*/ LLSD row; @@ -977,10 +977,10 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg, return; } - char line[MAX_STRING]; + char line[MAX_STRING]; /*Flawfinder: ignore*/ LLString text; - char start_date[MAX_STRING]; + char start_date[MAX_STRING]; /*Flawfinder: ignore*/ S32 interval_days; S32 current_interval; @@ -996,7 +996,7 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg, return; } - sprintf(line, "%s\n\n", start_date); + snprintf(line, MAX_STRING, "%s\n\n", start_date); /*Flawfinder: ignore*/ text.append(line); S32 total_amount = 0; @@ -1004,14 +1004,14 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg, for(S32 i = 0; i < transactions; i++) { S32 amount = 0; - char desc[MAX_STRING]; + char desc[MAX_STRING]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_HistoryData, _PREHASH_Description, MAX_STRING, desc, i ); msg->getS32Fast(_PREHASH_HistoryData, _PREHASH_Amount, amount, i); if (amount != 0) { - sprintf(line, "%-24s %6d\n", desc, amount ); + snprintf(line, MAX_STRING, "%-24s %6d\n", desc, amount ); /*Flawfinder: ignore*/ text.append(line); } else @@ -1024,7 +1024,7 @@ void LLGroupMoneyDetailsTabEventHandler::processReply(LLMessageSystem* msg, text.append(1, '\n'); - sprintf(line, "%-24s %6d\n", "Total", total_amount ); + snprintf(line, MAX_STRING, "%-24s %6d\n", "Total", total_amount ); /*Flawfinder: ignore*/ text.append(line); if ( mImplementationp->mTextEditorp ) @@ -1116,10 +1116,10 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg, return; } - char line[MAX_STRING]; + char line[MAX_STRING]; /*Flawfinder: ignore*/ std::string text = mImplementationp->mTextEditorp->getText(); - char start_date[MAX_STRING]; + char start_date[MAX_STRING]; /*Flawfinder: ignore*/ S32 interval_days; S32 current_interval; @@ -1141,7 +1141,7 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg, { text.clear(); - sprintf(line, "%s\n\n", start_date); + snprintf(line, MAX_STRING, "%s\n\n", start_date); /*Flawfinder: ignore*/ text.append(line); } @@ -1155,11 +1155,11 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg, for(S32 i = 0; i < transactions; i++) { const S32 SHORT_STRING = 64; - char time[SHORT_STRING]; + char time[SHORT_STRING]; /*Flawfinder: ignore*/ S32 type = 0; S32 amount = 0; - char user[SHORT_STRING]; - char item[SHORT_STRING]; + char user[SHORT_STRING]; /*Flawfinder: ignore*/ + char item[SHORT_STRING]; /*Flawfinder: ignore*/ msg->getStringFast(_PREHASH_HistoryData, _PREHASH_Time, SHORT_STRING, time, i); msg->getStringFast(_PREHASH_HistoryData, _PREHASH_User, SHORT_STRING, user, i ); @@ -1196,7 +1196,7 @@ void LLGroupMoneySalesTabEventHandler::processReply(LLMessageSystem* msg, break; } - sprintf(line, "%s %6d - %s %s %s\n", time, amount, user, verb, item); + snprintf(line, sizeof(line), "%s %6d - %s %s %s\n", time, amount, user, verb, item); /*Flawfinder: ignore*/ text.append(line); } } @@ -1292,12 +1292,12 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg, return; } - char line[MAX_STRING]; + char line[MAX_STRING]; /*Flawfinder: ignore*/ LLString text; - char start_date[MAX_STRING]; - char last_stipend_date[MAX_STRING]; - char next_stipend_date[MAX_STRING]; + char start_date[MAX_STRING]; /*Flawfinder: ignore*/ + char last_stipend_date[MAX_STRING]; /*Flawfinder: ignore*/ + char next_stipend_date[MAX_STRING]; /*Flawfinder: ignore*/ S32 interval_days; S32 current_interval; S32 balance; @@ -1349,26 +1349,26 @@ void LLGroupMoneyPlanningTabEventHandler::processReply(LLMessageSystem* msg, return; } - sprintf(line, "Summary for this week, beginning on %s\n", start_date); + snprintf(line, MAX_STRING, "Summary for this week, beginning on %s\n", start_date); /*Flawfinder: ignore*/ text.append(line); if (current_interval == 0) { - sprintf(line, "The next stipend day is %s\n\n", next_stipend_date); + snprintf(line, MAX_STRING, "The next stipend day is %s\n\n", next_stipend_date); /*Flawfinder: ignore*/ text.append(line); - sprintf(line, "%-24sL$%6d\n", "Balance", balance ); + snprintf(line, MAX_STRING, "%-24sL$%6d\n", "Balance", balance ); /*Flawfinder: ignore*/ text.append(line); text.append(1, '\n'); } - sprintf(line, " Group Individual Share\n"); + snprintf(line, MAX_STRING, " Group Individual Share\n"); /*Flawfinder: ignore*/ text.append(line); - sprintf(line, "%-24s %6d %6d \n", "Credits", total_credits, (S32)floor((F32)total_credits/(F32)non_exempt_members)); + snprintf(line, MAX_STRING, "%-24s %6d %6d \n", "Credits", total_credits, (S32)floor((F32)total_credits/(F32)non_exempt_members)); /*Flawfinder: ignore*/ text.append(line); - sprintf(line, "%-24s %6d %6d \n", "Debits", total_debits, (S32)floor((F32)total_debits/(F32)non_exempt_members)); + snprintf(line, MAX_STRING, "%-24s %6d %6d \n", "Debits", total_debits, (S32)floor((F32)total_debits/(F32)non_exempt_members)); /*Flawfinder: ignore*/ text.append(line); - sprintf(line, "%-24s %6d %6d \n", "Total", total_credits + total_debits, (S32)floor((F32)(total_credits + total_debits)/(F32)non_exempt_members)); + snprintf(line, MAX_STRING, "%-24s %6d %6d \n", "Total", total_credits + total_debits, (S32)floor((F32)(total_credits + total_debits)/(F32)non_exempt_members)); /*Flawfinder: ignore*/ text.append(line); if ( mImplementationp->mTextEditorp ) diff --git a/linden/indra/newview/llpanelgroupnotices.cpp b/linden/indra/newview/llpanelgroupnotices.cpp index b8b2f2c..2a7cdf5 100644 --- a/linden/indra/newview/llpanelgroupnotices.cpp +++ b/linden/indra/newview/llpanelgroupnotices.cpp @@ -50,6 +50,8 @@ #include "llviewerwindow.h" #include "llviewermessage.h" +const S32 NOTICE_DATE_STRING_SIZE = 30; + ///////////////////////// // LLPanelGroupNotices // ///////////////////////// @@ -181,8 +183,7 @@ char* build_notice_date(const time_t& the_time, char* buffer) tm* lt = localtime(&t); //for some reason, the month is off by 1. See other uses of //"local" time in the code... - sprintf(buffer,"%i/%i/%i", lt->tm_mon + 1, lt->tm_mday, lt->tm_year + 1900); - + snprintf(buffer, NOTICE_DATE_STRING_SIZE, "%i/%i/%i", lt->tm_mon + 1, lt->tm_mday, lt->tm_year + 1900); /*Flawfinder: ignore*/ return buffer; } @@ -447,8 +448,8 @@ void LLPanelGroupNotices::processGroupNoticesListReply(LLMessageSystem* msg, voi void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) { LLUUID id; - char subj[MAX_STRING]; - char name[MAX_STRING]; + char subj[MAX_STRING]; /*Flawfinder: ignore*/ + char name[MAX_STRING]; /*Flawfinder: ignore*/ U32 timestamp; BOOL has_attachment; U8 asset_type; @@ -492,12 +493,12 @@ void LLPanelGroupNotices::processNotices(LLMessageSystem* msg) row["columns"][2]["column"] = "from"; row["columns"][2]["value"] = name; - char buffer[30]; + char buffer[NOTICE_DATE_STRING_SIZE]; /*Flawfinder: ignore*/ build_notice_date(t, buffer); row["columns"][3]["column"] = "date"; row["columns"][3]["value"] = buffer; - snprintf(buffer, 30, "%u", timestamp); + snprintf(buffer, 30, "%u", timestamp); /*Flawfinder: ignore*/ row["columns"][4]["column"] = "sort"; row["columns"][4]["value"] = buffer; @@ -522,7 +523,7 @@ void LLPanelGroupNotices::onSelectNotice(LLUICtrl* ctrl, void* data) msg->addUUID("GroupNoticeID",item->getUUID()); gAgent.sendReliableMessage(); - lldebugs << "Item " << item->getUUID().getString().c_str() << " selected." << llendl; + lldebugs << "Item " << item->getUUID() << " selected." << llendl; } void LLPanelGroupNotices::showNotice(const char* subject, diff --git a/linden/indra/newview/llpanelgrouproles.cpp b/linden/indra/newview/llpanelgrouproles.cpp index 82f38e2..59ac556 100644 --- a/linden/indra/newview/llpanelgrouproles.cpp +++ b/linden/indra/newview/llpanelgrouproles.cpp @@ -185,6 +185,9 @@ BOOL LLPanelGroupRoles::postBuild() BOOL LLPanelGroupRoles::isVisibleByAgent(LLAgent* agentp) { + if (agentp->isGodlike()) + return TRUE; + /* This power was removed to make group roles simpler return agentp->hasPowerInGroup(mGroupID, GP_ROLE_CREATE | @@ -1117,7 +1120,10 @@ void LLPanelGroupMembersSubTab::handleMemberSelect() check->setCommitCallback(onRoleCheck); check->setCallbackUserData(this); check->set( count > 0 ); - check->setTentative(0 != count && selected_members.size() != count); + check->setTentative( + (0 != count) + && (selected_members.size() != + (std::vector::size_type)count)); //NOTE: as of right now a user can break the group //by removing himself from a role if he is the @@ -1696,8 +1702,8 @@ void LLPanelGroupMembersSubTab::updateMembers() LLGroupMgrGroupData::member_iter end = gdatap->mMembers.end(); - char first[DB_FIRST_NAME_BUF_SIZE]; - char last[DB_LAST_NAME_BUF_SIZE]; + char first[DB_FIRST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ + char last[DB_LAST_NAME_BUF_SIZE]; /*Flawfinder: ignore*/ S32 i = 0; for( ; mMemberProgress != end && isortByColumn("name", TRUE); - if ( (gdatap->mRoles.size() < MAX_ROLES) + if ( (gdatap->mRoles.size() < (U32)MAX_ROLES) && gAgent.hasPowerInGroup(mGroupID, GP_ROLE_CREATE) ) { mCreateRoleButton->setEnabled(TRUE); diff --git a/linden/indra/newview/llpanelgroupvoting.cpp b/linden/indra/newview/llpanelgroupvoting.cpp index 1be6bf0..ebe99b1 100644 --- a/linden/indra/newview/llpanelgroupvoting.cpp +++ b/linden/indra/newview/llpanelgroupvoting.cpp @@ -330,8 +330,8 @@ void LLPanelGroupVoting::impl::setEnableVoteProposal() if (already_voted == "Yes") { - char message[MAX_STRING]; - sprintf(message, "You have voted: %s ", vote_cast.c_str()); + char message[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(message, MAX_STRING, "You have voted: %s ", vote_cast.c_str()); /*Flawfinder: ignore*/ mInstructions->setText(message); mBtnYes->setEnabled(FALSE); @@ -641,8 +641,8 @@ void LLPanelGroupVoting::impl::updateQuorumText() if ( mQuorumText ) { //update the quorum count - char quorum_text[MAX_STRING]; - sprintf(quorum_text, + char quorum_text[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(quorum_text, MAX_STRING, /*Flawfinder: ignore*/ " out of %d members must vote", mNumGroupMembers); mQuorumText->setText(quorum_text); @@ -737,15 +737,15 @@ void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSyst U32 num_expected; const S32 MAX_STRING_NUM_LEN = 20; - char item_num_string[DB_TERSE_DATETIME_BUF_SIZE]; - char proposal_text[DB_VOTE_TEXT_BUF_SIZE]; - char vote_cast[DB_VOTE_RESULT_BUF_SIZE]; - char start_datetime[DB_DATETIME_BUF_SIZE]; - char end_datetime[DB_DATETIME_BUF_SIZE]; - char vote_type[DB_VOTE_TYPE_BUF_SIZE]; - char majority_text[MAX_STRING_NUM_LEN]; - char quorum_text[MAX_STRING_NUM_LEN]; - char vote_initiator_string[UUID_STR_LENGTH]; + char item_num_string[DB_TERSE_DATETIME_BUF_SIZE]; /*Flawfinder: ignore*/ + char proposal_text[DB_VOTE_TEXT_BUF_SIZE]; /*Flawfinder: ignore*/ + char vote_cast[DB_VOTE_RESULT_BUF_SIZE]; /*Flawfinder: ignore*/ + char start_datetime[DB_DATETIME_BUF_SIZE]; /*Flawfinder: ignore*/ + char end_datetime[DB_DATETIME_BUF_SIZE]; /*Flawfinder: ignore*/ + char vote_type[DB_VOTE_TYPE_BUF_SIZE]; /*Flawfinder: ignore*/ + char majority_text[MAX_STRING_NUM_LEN]; /*Flawfinder: ignore*/ + char quorum_text[MAX_STRING_NUM_LEN]; /*Flawfinder: ignore*/ + char vote_initiator_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ LLUUID vote_id; LLUUID vote_initiator; @@ -778,8 +778,8 @@ void LLPanelGroupVoting::impl::processGroupActiveProposalItemReply(LLMessageSyst msg->getS32Fast(_PREHASH_ProposalData, _PREHASH_Quorum, quorum, i ); vote_initiator.toString(vote_initiator_string); - sprintf(majority_text, "%f", majority); - sprintf(quorum_text, "%i", quorum); + snprintf(majority_text, MAX_STRING_NUM_LEN, "%f", majority); /*Flawfinder: ignore*/ + snprintf(quorum_text, MAX_STRING_NUM_LEN, "%i", quorum); /*Flawfinder: ignore*/ LLScrollListItem *row = new LLScrollListItem( TRUE, NULL, vote_id ); if (!row) return; @@ -879,12 +879,12 @@ void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem } const S32 ITEM_NUM_MAX_BUF_LEN = 15; - char item_num_string[ITEM_NUM_MAX_BUF_LEN]; - char proposal_text[DB_VOTE_TEXT_BUF_SIZE]; - char vote_result[MAX_STRING]; - char start_datetime[DB_DATETIME_BUF_SIZE]; - char end_datetime[DB_DATETIME_BUF_SIZE]; - char vote_type[DB_VOTE_TYPE_BUF_SIZE]; + char item_num_string[ITEM_NUM_MAX_BUF_LEN]; /*Flawfinder: ignore*/ + char proposal_text[DB_VOTE_TEXT_BUF_SIZE]; /*Flawfinder: ignore*/ + char vote_result[MAX_STRING]; /*Flawfinder: ignore*/ + char start_datetime[DB_DATETIME_BUF_SIZE]; /*Flawfinder: ignore*/ + char end_datetime[DB_DATETIME_BUF_SIZE]; /*Flawfinder: ignore*/ + char vote_type[DB_VOTE_TYPE_BUF_SIZE]; /*Flawfinder: ignore*/ LLString vote_text; LLUUID vote_id; @@ -927,15 +927,15 @@ void LLPanelGroupVoting::impl::processGroupVoteHistoryItemReply(LLMessageSystem } vote_text.append(" Votes->\n"); - char vote_result[DB_VOTE_RESULT_BUF_SIZE]; - char result_msg[MAX_STRING]; + char vote_result[DB_VOTE_RESULT_BUF_SIZE]; /*Flawfinder: ignore*/ + char result_msg[MAX_STRING]; /*Flawfinder: ignore*/ S32 num_votes; for (S32 i = 0; i < vote_items; ++i) { msg->getStringFast(_PREHASH_VoteItem, _PREHASH_VoteCast, DB_VOTE_RESULT_BUF_SIZE, vote_result, i); msg->getS32Fast(_PREHASH_VoteItem, _PREHASH_NumVotes, num_votes, i); - sprintf(result_msg, + snprintf(result_msg, MAX_STRING, /*Flawfinder: ignore*/ " %s: %d\n", vote_result, num_votes); diff --git a/linden/indra/newview/llpanelinventory.cpp b/linden/indra/newview/llpanelinventory.cpp index bd32ad2..d9638fd 100644 --- a/linden/indra/newview/llpanelinventory.cpp +++ b/linden/indra/newview/llpanelinventory.cpp @@ -182,7 +182,7 @@ void LLTaskInvFVBridge::showProperties() "Object Inventory Item Properties", mUUID, mPanel->getTaskUUID()); - floater->open(); + floater->open(); /*Flawfinder: ignore*/ } } @@ -943,7 +943,7 @@ void LLTaskSoundBridge::openSoundPreview(void* data) self->getName(), self->mUUID, self->mPanel->getTaskUUID()); - floaterp->open(); + floaterp->open(); /*Flawfinder: ignore*/ } } @@ -1182,7 +1182,7 @@ void LLTaskLSLBridge::openItem() mUUID); LLMultiFloater* previous_host = LLFloater::getFloaterHost(); LLFloater::setFloaterHost(NULL); - editor->open(); + editor->open(); /*Flawfinder: ignore*/ LLFloater::setFloaterHost(previous_host); // keep onscreen @@ -1824,16 +1824,16 @@ void LLPanelInventory::refresh() { //llinfos << "LLPanelInventory::refresh()" << llendl; BOOL has_inventory = FALSE; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if(!node) { - node = gSelectMgr->getFirstNode(); + node = gSelectMgr->getSelection()->getFirstNode(); } if(node) { LLViewerObject* object = node->getObject(); - if(object && ((gSelectMgr->getRootObjectCount() == 1) - || (gSelectMgr->getObjectCount() == 1))) + if(object && ((gSelectMgr->getSelection()->getRootObjectCount() == 1) + || (gSelectMgr->getSelection()->getObjectCount() == 1))) { // determine if we need to make a request. Start with a // default based on if we have inventory at all. diff --git a/linden/indra/newview/llpanelland.cpp b/linden/indra/newview/llpanelland.cpp index 38eac5d..1b3e146 100644 --- a/linden/indra/newview/llpanelland.cpp +++ b/linden/indra/newview/llpanelland.cpp @@ -109,7 +109,7 @@ void LLPanelLandInfo::refreshAll() // public void LLPanelLandInfo::refresh() { - LLParcel *parcel = gParcelMgr->getSelectedParcel(); + LLParcel *parcel = gParcelMgr->getParcelSelection()->getParcel(); LLViewerRegion *regionp = gParcelMgr->getSelectionRegion(); if (!parcel || !regionp) @@ -177,7 +177,7 @@ void LLPanelLandInfo::refresh() // and it must not be a whole parcel. if (gParcelMgr->getSelectedArea() > PARCEL_UNIT_AREA //&& gParcelMgr->getSelfCount() > 1 - && !gParcelMgr->getWholeParcelSelected()) + && !gParcelMgr->getParcelSelection()->getWholeParcelSelected()) { childSetEnabled("button join land",TRUE); } @@ -200,7 +200,7 @@ void LLPanelLandInfo::refresh() &rent_price, &for_sale, &dwell); - if(is_public || (is_for_sale && gParcelMgr->getWholeParcelSelected())) + if(is_public || (is_for_sale && gParcelMgr->getParcelSelection()->getWholeParcelSelected())) { childSetTextArg("label_area_price","[PRICE]", llformat("%d",claim_price)); childSetTextArg("label_area_price","[AREA]", llformat("%d",area)); @@ -246,7 +246,7 @@ void LLPanelLandInfo::onClickJoin(void*) void LLPanelLandInfo::onClickAbout(void*) { // Promote the rectangle selection to a parcel selection - if (!gParcelMgr->getWholeParcelSelected()) + if (!gParcelMgr->getParcelSelection()->getWholeParcelSelected()) { gParcelMgr->selectParcelInRectangle(); } diff --git a/linden/indra/newview/llpanellogin.cpp b/linden/indra/newview/llpanellogin.cpp index 3d3aee9..6a0bdb4 100644 --- a/linden/indra/newview/llpanellogin.cpp +++ b/linden/indra/newview/llpanellogin.cpp @@ -518,14 +518,15 @@ void LLPanelLogin::setFields(const std::string& firstname, const std::string& la // nice row of asterixes. const char* filler = "123456789!123456"; sInstance->childSetText("password_edit", filler); - strcpy(sInstance->mIncomingPassword, filler); - strcpy(sInstance->mMungedPassword, password.c_str()); + strcpy(sInstance->mIncomingPassword, filler); /*Flawfinder: ignore*/ + strcpy(sInstance->mMungedPassword, password.c_str()); /*Flawfinder: ignore*/ } else { // this is a normal text password sInstance->childSetText("password_edit", password); - strcpy(sInstance->mIncomingPassword, password.c_str()); + strncpy(sInstance->mIncomingPassword, password.c_str(), sizeof(sInstance->mIncomingPassword) -1); /*Flawfinder: ignore*/ + sInstance->mIncomingPassword[sizeof(sInstance->mIncomingPassword) -1] = '\0'; LLMD5 pass((unsigned char *)password.c_str()); pass.hex_digest(sInstance->mMungedPassword); } diff --git a/linden/indra/newview/llpanellogin.h b/linden/indra/newview/llpanellogin.h index 6e11f6f..6bd825a 100644 --- a/linden/indra/newview/llpanellogin.h +++ b/linden/indra/newview/llpanellogin.h @@ -91,8 +91,8 @@ private: void (*mCallback)(S32 option, void *userdata); void* mCallbackData; - char mIncomingPassword[DB_USER_PASSWORD_BUF_SIZE]; - char mMungedPassword[MD5HEX_STR_SIZE]; + char mIncomingPassword[DB_USER_PASSWORD_BUF_SIZE]; /*Flawfinder: ignore*/ + char mMungedPassword[MD5HEX_STR_SIZE]; /*Flawfinder: ignore*/ static LLPanelLogin* sInstance; static BOOL sCapslockDidNotification; diff --git a/linden/indra/newview/llpanelmoney.cpp b/linden/indra/newview/llpanelmoney.cpp deleted file mode 100644 index 1dcd544..0000000 --- a/linden/indra/newview/llpanelmoney.cpp +++ /dev/null @@ -1,483 +0,0 @@ -/** - * @file llpanelmoney.cpp - * @author James Cook - * @brief Panels for Account History floater - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llpanelmoney.h" - -#include "llfontgl.h" -#include "message.h" -#include "lltransactiontypes.h" - -#include "llpanel.h" -#include "llbutton.h" -#include "llviewercontrol.h" -#include "llstatusbar.h" -#include "lluiconstants.h" -#include "llvieweruictrlfactory.h" -#include "viewer.h" - -// XUI:translate -const char LOADING_STRING[] = "Computing..."; - -S32 LLPanelAccount::sCurrentInterval = 0; - -//--------------------------------------------------------------------------- -// LLPanelAccount - the base class for all account panels -//--------------------------------------------------------------------------- - -// Construct with a dummy rectangle because tab containers will -// resize their panels. Thus, merely need to make sure the follow -// flags are correctly set. -LLPanelAccount::LLPanelAccount(const LLUUID& request_id, S32 interval_days, S32 max_interval, const std::string& filename) -: LLPanel("account_panel"), - mRequestID( request_id ), - mDataRequested( FALSE ), - mIntervalDays( interval_days ), - mMaxInterval( max_interval ) -{ - sCurrentInterval = 0; - - gUICtrlFactory->buildPanel(this, filename); - - childSetText("editor", LOADING_STRING); - - childSetAction("earlier_btn", onClickEarlier, this); - childSetAction("later_btn", onClickLater, this); -} - - -// public virtual -void LLPanelAccount::draw() -{ - if (!mDataRequested || (mDisplayedInterval != sCurrentInterval) ) - { - sendRequest(); - refreshPanel(); - mDisplayedInterval = sCurrentInterval; - mDataRequested = TRUE; - } - - LLPanel::draw(); -} - -void LLPanelAccount::refreshPanel() -{ - // Used by some panels that have buttons and some that don't (so no warnings) - if (hasChild("earlier_btn")) - { - childSetEnabled("earlier_btn", sCurrentInterval < mMaxInterval); - } - if (hasChild("later_btn")) - { - childSetEnabled("later_btn", sCurrentInterval > 0); - } -} - -// static -void LLPanelAccount::onClickEarlier(void *userdata) -{ - LLPanelAccount* self = (LLPanelAccount*)userdata; - if (!self) return; - - if (self->sCurrentInterval < self->mMaxInterval) - { - self->childSetText("editor", LOADING_STRING); - self->sCurrentInterval++; - self->refreshPanel(); - self->setDataRequested(FALSE); - } -} - -// static -void LLPanelAccount::onClickLater(void *userdata) -{ - LLPanelAccount* self = (LLPanelAccount*)userdata; - if (!self) return; - - if (self->sCurrentInterval > 0) - { - self->childSetText("editor", LOADING_STRING); - self->sCurrentInterval--; - self->refreshPanel(); - self->setDataRequested(FALSE); - } -} - - -//--------------------------------------------------------------------------- -// LLPanelAccountPlanning - the first, default view of money -//--------------------------------------------------------------------------- -LLPanelAccountPlanning::LLPanelAccountPlanning(const LLUUID& request_id) -: LLPanelAccount(request_id, SUMMARY_INTERVAL, SUMMARY_MAX, "panel_account_planning.xml") -{ - childSetText("editor", LOADING_STRING); -} - -// virtual -void LLPanelAccountPlanning::sendRequest() -{ - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_MoneySummaryRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_get_id() ); - msg->addUUIDFast(_PREHASH_SessionID, agent_get_session_id() ); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_RequestID, mRequestID ); - msg->addS32Fast(_PREHASH_IntervalDays, mIntervalDays ); - msg->addS32Fast(_PREHASH_CurrentInterval, 0 ); - - agent_send_reliable_message(); - - childSetText("editor", LOADING_STRING); -} - -// virtual -void LLPanelAccountPlanning::processReply(LLMessageSystem* msg, void** data) -{ - char line[MAX_STRING]; - LLString text; - - char start_date[MAX_STRING]; - char last_stipend_date[MAX_STRING]; - char next_stipend_date[MAX_STRING]; - S32 interval_days; - S32 current_interval; - S32 balance; - S32 total_credits; - S32 total_debits; - S32 cur_object_tax; - S32 cur_light_tax; - S32 cur_land_tax; - S32 cur_group_tax; - S32 cur_parcel_dir_fee; - S32 cur_total_tax; - S32 proj_object_tax; - S32 proj_light_tax; - S32 proj_land_tax; - S32 proj_group_tax; - S32 proj_parcel_dir_fee; - S32 proj_total_tax; - S32 stipend; - - msg->getS32("MoneyData", "IntervalDays", interval_days ); - msg->getS32("MoneyData", "CurrentInterval", current_interval ); - msg->getS32("MoneyData", "Balance", balance ); - msg->getS32("MoneyData", "TotalCredits", total_credits ); - msg->getS32("MoneyData", "TotalDebits", total_debits ); - msg->getS32("MoneyData", "ObjectTaxCurrent", cur_object_tax ); - msg->getS32("MoneyData", "LightTaxCurrent", cur_light_tax ); - msg->getS32("MoneyData", "LandTaxCurrent", cur_land_tax ); - msg->getS32("MoneyData", "GroupTaxCurrent", cur_group_tax ); - msg->getS32("MoneyData", "ParcelDirFeeCurrent", cur_parcel_dir_fee ); - msg->getS32("MoneyData", "ObjectTaxEstimate", proj_object_tax ); - msg->getS32("MoneyData", "LightTaxEstimate", proj_light_tax ); - msg->getS32("MoneyData", "LandTaxEstimate", proj_land_tax ); - msg->getS32("MoneyData", "GroupTaxEstimate", proj_group_tax ); - msg->getS32("MoneyData", "ParcelDirFeeEstimate", proj_parcel_dir_fee ); - msg->getS32("MoneyData", "StipendEstimate", stipend ); - - msg->getString("MoneyData", "StartDate", MAX_STRING, start_date); - msg->getString("MoneyData", "LastTaxDate", MAX_STRING, last_stipend_date); - msg->getString("MoneyData", "TaxDate", MAX_STRING, next_stipend_date); - - cur_total_tax = cur_object_tax + cur_light_tax + cur_land_tax + cur_group_tax + cur_parcel_dir_fee; - proj_total_tax = proj_object_tax + proj_light_tax + proj_land_tax + proj_group_tax + proj_parcel_dir_fee; - - if (interval_days != mIntervalDays || current_interval != sCurrentInterval) - { - llinfos << "Out of date summary packet " << interval_days << " " - << current_interval << llendl; - return; - } - - // *NOTE: actually use the balance from the status bar, so the two - // match. This should not be necessary because the simulator no - // longer buffers transaction. If status bar balance is zero, - // assume this is because we haven't received the first balance - // yet, and trust the database. - if (0 != gStatusBar->getBalance()) - { - balance = gStatusBar->getBalance(); - } - - sprintf(line, "Summary for this week, beginning on %s\n", start_date); - text.append(line); - - if (current_interval == 0) - { - text.append(1, '\n'); - - sprintf(line, "Your next stipend day is %s\n\n", next_stipend_date); - text.append(line); - sprintf(line, "%-24sL$%6d\n", "Balance", balance ); - text.append(line); - - text.append(1, '\n'); - } - - sprintf(line, "%-24s %6d\n", "Credits", total_credits); - text.append(line); - - sprintf(line, "%-24s %6d\n", "Debits", total_debits); - text.append(line); - - sprintf(line, "%-24s %6d\n", "Total Change", total_credits + total_debits); - text.append(line); - - if (current_interval == 0) - { - text.append(1, '\n'); - - text.append(1, '\n'); - - sprintf(line, "%-24s %6d\n", "Estimated Stipend", stipend ); - text.append(line); - - // Generate projected "wealth tax" based on current balance, projected stipend/bonus - } - else - { - text.append(1, '\n'); - text.append(1, '\n'); - - sprintf(line, "%-24s %6d\n", "Parcel Directory Fee", cur_parcel_dir_fee); - text.append(line); - } - - childSetText("editor", text); -} - - -//--------------------------------------------------------------------------- -// LLPanelAccountDetails -//--------------------------------------------------------------------------- -LLPanelAccountDetails::LLPanelAccountDetails(const LLUUID& request_id) -: LLPanelAccount(request_id, - DETAILS_INTERVAL, - DETAILS_MAX, - "panel_account_details.xml") -{ - childSetText("editor", LOADING_STRING); -} - -// virtual -void LLPanelAccountDetails::sendRequest() -{ - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_MoneyDetailsRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_get_id() ); - msg->addUUIDFast(_PREHASH_SessionID, agent_get_session_id() ); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_RequestID, mRequestID ); - msg->addS32Fast(_PREHASH_IntervalDays, mIntervalDays ); - msg->addS32Fast(_PREHASH_CurrentInterval, sCurrentInterval ); - - agent_send_reliable_message(); -} - -// virtual -void LLPanelAccountDetails::processReply(LLMessageSystem* msg, void** data) -{ - char line[MAX_STRING]; - LLString text; - - char start_date[MAX_STRING]; - S32 interval_days; - S32 current_interval; - - msg->getS32Fast(_PREHASH_MoneyData, _PREHASH_IntervalDays, interval_days ); - msg->getS32Fast(_PREHASH_MoneyData, _PREHASH_CurrentInterval, current_interval ); - msg->getStringFast(_PREHASH_MoneyData, _PREHASH_StartDate, MAX_STRING, start_date); - - if (interval_days != mIntervalDays || current_interval != sCurrentInterval) - { - llinfos << "Out of date details packet " << interval_days << " " - << current_interval << llendl; - return; - } - - sprintf(line, "%s\n\n", start_date); - text.append(line); - - S32 total_amount = 0; - S32 transactions = msg->getNumberOfBlocksFast(_PREHASH_HistoryData); - for(S32 i = 0; i < transactions; i++) - { - S32 amount = 0; - char desc[MAX_STRING]; - - msg->getStringFast(_PREHASH_HistoryData, _PREHASH_Description, MAX_STRING, desc, i ); - msg->getS32Fast(_PREHASH_HistoryData, _PREHASH_Amount, amount, i); - - if (amount != 0) - { - sprintf(line, "%-24s %6d\n", desc, amount ); - text.append(line); - } - else - { - // skip it - } - - total_amount += amount; - } - - text.append(1, '\n'); - - sprintf(line, "%-24s %6d\n", "Total", total_amount ); - text.append(line); - - childSetText("editor", text); -} - -//--------------------------------------------------------------------------- -// LLPanelAccountTransactions -//--------------------------------------------------------------------------- -LLPanelAccountTransactions::LLPanelAccountTransactions(const LLUUID& request_id) -: LLPanelAccount(request_id, - TRANSACTIONS_INTERVAL, - TRANSACTIONS_MAX, - "panel_account_transactions.xml") -{ - childSetText("editor", LOADING_STRING); -} - -// virtual -void LLPanelAccountTransactions::sendRequest() -{ - LLMessageSystem* msg = gMessageSystem; - - msg->newMessageFast(_PREHASH_MoneyTransactionsRequest); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, agent_get_id() ); - msg->addUUIDFast(_PREHASH_SessionID, agent_get_session_id() ); - msg->nextBlockFast(_PREHASH_MoneyData); - msg->addUUIDFast(_PREHASH_RequestID, mRequestID ); - msg->addS32Fast(_PREHASH_IntervalDays, mIntervalDays ); - msg->addS32Fast(_PREHASH_CurrentInterval, sCurrentInterval ); - - agent_send_reliable_message(); - - childSetText("editor", LOADING_STRING); -} - -// virtual -void LLPanelAccountTransactions::processReply(LLMessageSystem* msg, void** data) -{ - char line[MAX_STRING]; - LLSD value = childGetValue("editor"); - std::string text = value.asString(); - - char start_date[MAX_STRING]; - S32 interval_days; - S32 current_interval; - - msg->getS32Fast(_PREHASH_MoneyData, _PREHASH_IntervalDays, interval_days ); - msg->getS32Fast(_PREHASH_MoneyData, _PREHASH_CurrentInterval, current_interval ); - msg->getStringFast(_PREHASH_MoneyData, _PREHASH_StartDate, MAX_STRING, start_date); - - if (interval_days != mIntervalDays || current_interval != sCurrentInterval) - { - llinfos << "Out of date details packet " << interval_days << " " - << current_interval << llendl; - return; - } - - // If this is the first packet, clear the text, don't append. - // Start with the date. - if (text == LOADING_STRING) - { - text.clear(); - - sprintf(line, "%s\n\n", start_date); - text.append(line); - } - - S32 transactions = msg->getNumberOfBlocksFast(_PREHASH_HistoryData); - if (transactions == 0) - { - text.append("(none)"); - } - else - { - for(S32 i = 0; i < transactions; i++) - { - const S32 SHORT_STRING = 64; - char time[SHORT_STRING]; - S32 type = 0; - S32 amount = 0; - char user[SHORT_STRING]; - char item[SHORT_STRING]; - - msg->getStringFast(_PREHASH_HistoryData, _PREHASH_Time, SHORT_STRING, time, i); - msg->getStringFast(_PREHASH_HistoryData, _PREHASH_User, SHORT_STRING, user, i ); - msg->getS32Fast(_PREHASH_HistoryData, _PREHASH_Type, type, i); - msg->getStringFast(_PREHASH_HistoryData, _PREHASH_Item, SHORT_STRING, item, i ); - msg->getS32Fast(_PREHASH_HistoryData, _PREHASH_Amount, amount, i); - - if (amount != 0) - { - char* verb; - - switch(type) - { - case TRANS_OBJECT_SALE: - verb = "bought"; - break; - case TRANS_GIFT: - verb = "paid you"; - break; - case TRANS_PAY_OBJECT: - verb = "paid into"; - break; - case TRANS_LAND_PASS_SALE: - verb = "bought pass to"; - break; - case TRANS_EVENT_FEE: - verb = "paid fee for event"; - break; - case TRANS_EVENT_PRIZE: - verb = "paid prize for event"; - break; - default: - verb = ""; - break; - } - - sprintf(line, "%s %6d - %s %s %s\n", time, amount, user, verb, item); - text.append(line); - } - } - } - - childSetText("editor", text); -} diff --git a/linden/indra/newview/llpanelmoney.h b/linden/indra/newview/llpanelmoney.h deleted file mode 100644 index 9600a33..0000000 --- a/linden/indra/newview/llpanelmoney.h +++ /dev/null @@ -1,106 +0,0 @@ -/** - * @file llpanelmoney.h - * @author James Cook - * @brief Panels for Account History floater - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLPANELMONEY_H -#define LL_LLPANELMONEY_H - -#include "llpanel.h" -#include "lluuid.h" - -class LLMessageSystem; -class LLTextEditor; -class LLButton; - -// Base class for all the panels. -class LLPanelAccount -: public LLPanel -{ -public: - LLPanelAccount(const LLUUID& request_id, S32 interval_days, S32 max_interval, const std::string& filename); - - void setDataRequested(BOOL b) { mDataRequested = b; } - - virtual void draw(); - - virtual void sendRequest() = 0; - virtual void processReply(LLMessageSystem* msg, void** data) = 0; - - void refreshPanel(); - - static void onClickEarlier(void* userdata); - static void onClickLater(void* userdata); - -protected: - LLUUID mRequestID; - - BOOL mDataRequested; - - // Time between start and end day, inclusive. 7 = one week - S32 mIntervalDays; - - // How many intervals back are we looking? - static S32 sCurrentInterval; - S32 mDisplayedInterval; - - S32 mMaxInterval; -}; - - -class LLPanelAccountPlanning -: public LLPanelAccount -{ -public: - LLPanelAccountPlanning(const LLUUID& request_id); - - virtual void sendRequest(); - virtual void processReply(LLMessageSystem* msg, void** data); -}; - - -class LLPanelAccountDetails -: public LLPanelAccount -{ -public: - LLPanelAccountDetails(const LLUUID& request_id); - - virtual void sendRequest(); - virtual void processReply(LLMessageSystem* msg, void** data); -}; - - -class LLPanelAccountTransactions -: public LLPanelAccount -{ -public: - LLPanelAccountTransactions(const LLUUID& request_id); - - virtual void sendRequest(); - virtual void processReply(LLMessageSystem* msg, void** data); -}; - -#endif diff --git a/linden/indra/newview/llpanelnetwork.cpp b/linden/indra/newview/llpanelnetwork.cpp index c55dacb..ef538ba 100644 --- a/linden/indra/newview/llpanelnetwork.cpp +++ b/linden/indra/newview/llpanelnetwork.cpp @@ -37,19 +37,25 @@ // project includes #include "llbutton.h" +#include "lldirpicker.h" #include "llui.h" #include "lluictrlfactory.h" #include "llresmgr.h" #include "llsliderctrl.h" +#include "llspinctrl.h" +#include "llcheckboxctrl.h" #include "lltextbox.h" #include "llviewerregion.h" #include "llviewerthrottle.h" #include "llworld.h" #include "llviewercontrol.h" #include "llvieweruictrlfactory.h" -#include "llmozlib.h" #include "llviewerwindow.h" +#if LL_LIBXUL_ENABLED +#include "llmozlib.h" +#endif // LL_LIBXUL_ENABLED + LLPanelNetwork::LLPanelNetwork() { @@ -58,22 +64,17 @@ LLPanelNetwork::LLPanelNetwork() BOOL LLPanelNetwork::postBuild() { - requires("disk cache", WIDGET_TYPE_RADIO_GROUP); - requires("max_bandwidth", WIDGET_TYPE_SLIDER); - requires("clear_cache", WIDGET_TYPE_BUTTON); - - if (!checkRequirements()) - { - return FALSE; - } + LLString cache_location = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ""); + childSetText("cache_location", cache_location); + + childSetAction("clear_cache", onClickClearCache, this); + childSetAction("set_cache", onClickSetCache, this); + childSetAction("reset_cache", onClickResetCache, this); + + childSetEnabled("connection_port", + gSavedSettings.getBOOL("ConnectionPortEnabled")); + childSetCommitCallback("connection_port_enabled", onCommitPort, this); - // retrieve controls - mDiskCacheRadio = LLUICtrlFactory::getRadioGroupByName(this, "disk cache"); - mCtrlBandwidth = LLUICtrlFactory::getSliderByName(this, "max_bandwidth"); - - mClearCacheBtn = LLUICtrlFactory::getButtonByName(this, "clear_cache"); - mClearCacheBtn->setClickedCallback(onClickClearCache); - mClearCacheBtn->setCallbackUserData(this); refresh(); @@ -94,14 +95,18 @@ void LLPanelNetwork::refresh() { LLPanel::refresh(); - mCacheSetting = gSavedSettings.getU32("VFSSize"); + mCacheSetting = gSavedSettings.getU32("CacheSize"); mBandwidthBPS = gSavedSettings.getF32("ThrottleBandwidthKBPS")*1024; + mConnectionPortEnabled = gSavedSettings.getBOOL("ConnectionPortEnabled"); + mConnectionPort = gSavedSettings.getU32("ConnectionPort"); } void LLPanelNetwork::cancel() { - gSavedSettings.setU32("VFSSize", mCacheSetting); + gSavedSettings.setU32("CacheSize", mCacheSetting); gSavedSettings.setF32("ThrottleBandwidthKBPS", mBandwidthBPS/1024); + gSavedSettings.setBOOL("ConnectionPortEnabled", mConnectionPortEnabled); + gSavedSettings.setU32("ConnectionPort", mConnectionPort); } // static @@ -116,3 +121,55 @@ void LLPanelNetwork::onClickClearCache(void*) gSavedSettings.setBOOL("PurgeCacheOnNextStartup", TRUE); gViewerWindow->alertXml("CacheWillClear"); } + +// static +void LLPanelNetwork::onClickSetCache(void* user_data) +{ + LLPanelNetwork* self = (LLPanelNetwork*)user_data; + + LLString cur_name(gSavedSettings.getString("CacheLocation")); + LLString proposed_name(cur_name); + + LLDirPicker& picker = LLDirPicker::instance(); + if (! picker.getDir(&proposed_name ) ) + { + return; //Canceled! + } + + LLString dir_name = picker.getDirName(); + if (!dir_name.empty() && dir_name != cur_name) + { + self->childSetText("cache_location", dir_name); + gViewerWindow->alertXml("CacheWillBeMoved"); + gSavedSettings.setString("NewCacheLocation", dir_name); + } + else + { + LLString cache_location = gDirUtilp->getCacheDir(); + self->childSetText("cache_location", cache_location); + } +} + +// static +void LLPanelNetwork::onClickResetCache(void* user_data) +{ + LLPanelNetwork* self = (LLPanelNetwork*)user_data; + if (!gSavedSettings.getString("CacheLocation").empty()) + { + gSavedSettings.setString("NewCacheLocation", ""); + gViewerWindow->alertXml("CacheWillBeMoved"); + } + LLString cache_location = gDirUtilp->getCacheDir(true); + self->childSetText("cache_location", cache_location); +} + +// static +void LLPanelNetwork::onCommitPort(LLUICtrl* ctrl, void* data) +{ + LLPanelNetwork* self = (LLPanelNetwork*)data; + LLCheckBoxCtrl* check = (LLCheckBoxCtrl*)ctrl; + + if (!self || !check) return; + self->childSetEnabled("connection_port", check->get()); + gViewerWindow->alertXml("ChangeConnectionPort"); +} diff --git a/linden/indra/newview/llpanelnetwork.h b/linden/indra/newview/llpanelnetwork.h index eb54042..051293a 100644 --- a/linden/indra/newview/llpanelnetwork.h +++ b/linden/indra/newview/llpanelnetwork.h @@ -51,14 +51,15 @@ public: private: static void onClickClearCache(void*); + static void onClickSetCache(void*); + static void onClickResetCache(void*); + static void onCommitPort(LLUICtrl* ctrl, void*); private: - LLSliderCtrl *mCtrlBandwidth; - LLRadioGroup* mDiskCacheRadio; - LLButton* mClearCacheBtn; - U32 mCacheSetting; F32 mBandwidthBPS; + BOOL mConnectionPortEnabled; + U32 mConnectionPort; }; #endif diff --git a/linden/indra/newview/llpanelobject.cpp b/linden/indra/newview/llpanelobject.cpp index 54e24e2..590eb63 100644 --- a/linden/indra/newview/llpanelobject.cpp +++ b/linden/indra/newview/llpanelobject.cpp @@ -275,11 +275,11 @@ LLPanelObject::~LLPanelObject() void LLPanelObject::getState( ) { - LLViewerObject* objectp = gSelectMgr->getFirstRootObject(); + LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstRootObject(); LLViewerObject* root_objectp = objectp; if(!objectp) { - objectp = gSelectMgr->getFirstObject(); + objectp = gSelectMgr->getSelection()->getFirstObject(); // *FIX: shouldn't we just keep the child? if (objectp) { @@ -391,9 +391,9 @@ void LLPanelObject::getState( ) owners_identical = gSelectMgr->selectGetOwner(owner_id, owner_name); // BUG? Check for all objects being editable? - S32 roots_selected = gSelectMgr->getRootObjectCount(); + S32 roots_selected = gSelectMgr->getSelection()->getRootObjectCount(); BOOL editable = root_objectp->permModify(); - S32 selected_count = gSelectMgr->getObjectCount(); + S32 selected_count = gSelectMgr->getSelection()->getObjectCount(); BOOL single_volume = (gSelectMgr->selectionAllPCode( LL_PCODE_VOLUME )) && (selected_count == 1); @@ -1525,7 +1525,7 @@ void LLPanelObject::draw() const LLColor4 blue( 0.f, 0.5f, 1.0f, 1); // Tune the colors of the labels - LLTool* tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + LLTool* tool = gToolMgr->getCurrentTool(); if (tool == gToolTranslate) { @@ -1645,7 +1645,7 @@ void LLPanelObject::onCommitLock(LLUICtrl *ctrl, void *data) BOOL new_state = self->mCheckLock->get(); - gSelectMgr->setObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY); + gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY); } // static diff --git a/linden/indra/newview/llpanelpermissions.cpp b/linden/indra/newview/llpanelpermissions.cpp index 84509a9..8512342 100644 --- a/linden/indra/newview/llpanelpermissions.cpp +++ b/linden/indra/newview/llpanelpermissions.cpp @@ -147,16 +147,16 @@ void LLPanelPermissions::refresh() BtnDeedToGroup->setLabelUnselected(deedText); } BOOL root_selected = TRUE; - LLSelectNode* nodep = gSelectMgr->getFirstRootNode(); - S32 object_count = gSelectMgr->getRootObjectCount(); + LLSelectNode* nodep = gSelectMgr->getSelection()->getFirstRootNode(); + S32 object_count = gSelectMgr->getSelection()->getRootObjectCount(); if(!nodep || 0 == object_count) { - nodep = gSelectMgr->getFirstNode(); - object_count = gSelectMgr->getObjectCount(); + nodep = gSelectMgr->getSelection()->getFirstNode(); + object_count = gSelectMgr->getSelection()->getObjectCount(); root_selected = FALSE; } - //BOOL attachment_selected = gSelectMgr->selectionIsAttachment(); + //BOOL attachment_selected = gSelectMgr->getSelection()->isAttachment(); //attachment_selected = false; LLViewerObject* objectp = NULL; if(nodep) objectp = nodep->getObject(); @@ -249,7 +249,7 @@ void LLPanelPermissions::refresh() BOOL is_one_object = (object_count == 1); // BUG: fails if a root and non-root are both single-selected. - BOOL is_perm_modify = (gSelectMgr->getFirstRootNode() + BOOL is_perm_modify = (gSelectMgr->getSelection()->getFirstRootNode() && gSelectMgr->selectGetRootsModify()) || gSelectMgr->selectGetModify(); const LLView* keyboard_focus_view = gFocusMgr.getKeyboardFocus(); @@ -373,8 +373,8 @@ void LLPanelPermissions::refresh() // Pre-compute object info string - S32 prim_count = gSelectMgr->getObjectCount(); - S32 obj_count = gSelectMgr->getRootObjectCount(); + S32 prim_count = gSelectMgr->getSelection()->getObjectCount(); + S32 obj_count = gSelectMgr->getSelection()->getRootObjectCount(); LLString object_info_string; if (1 == obj_count) @@ -383,8 +383,8 @@ void LLPanelPermissions::refresh() } else { - char buffer[MAX_STRING]; - sprintf(buffer, "%d Objects, ", obj_count); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, MAX_STRING, "%d Objects, ", obj_count); /*Flawfinder: ignore*/ object_info_string.assign(buffer); } if (1 == prim_count) @@ -393,8 +393,8 @@ void LLPanelPermissions::refresh() } else { - char buffer[MAX_STRING]; - sprintf(buffer, "%d Primitives", prim_count); + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + snprintf(buffer, MAX_STRING, "%d Primitives", prim_count); /*Flawfinder: ignore*/ object_info_string.append(buffer); } childSetText("prim info",object_info_string); @@ -496,36 +496,36 @@ void LLPanelPermissions::refresh() if( gSavedSettings.getBOOL("DebugPermissions") ) { - char perm_string[10]; + char perm_string[10]; /*Flawfinder: ignore*/ if (valid_base_perms) { - strcpy(perm_string, "B: "); + strcpy(perm_string, "B: "); /*Flawfinder: ignore*/ mask_to_string(base_mask_on, perm_string+3); childSetText("B:",perm_string); childSetVisible("B:",true); - strcpy(perm_string, "O: "); + strcpy(perm_string, "O: "); /*Flawfinder: ignore*/ mask_to_string(owner_mask_on, perm_string+3); childSetText("O:",perm_string); childSetVisible("O:",true); - strcpy(perm_string, "G: "); + strcpy(perm_string, "G: "); /*Flawfinder: ignore*/ mask_to_string(group_mask_on, perm_string+3); childSetText("G:",perm_string); childSetVisible("G:",true); - strcpy(perm_string, "E: "); + strcpy(perm_string, "E: "); /*Flawfinder: ignore*/ mask_to_string(everyone_mask_on, perm_string+3); childSetText("E:",perm_string); childSetVisible("E:",true); - strcpy(perm_string, "N: "); + strcpy(perm_string, "N: "); /*Flawfinder: ignore*/ mask_to_string(next_owner_mask_on, perm_string+3); childSetText("N:",perm_string); childSetVisible("N:",true); } - strcpy(perm_string, "F: "); + strcpy(perm_string, "F: "); /*Flawfinder: ignore*/ U32 flag_mask = 0x0; if (objectp->permMove()) flag_mask |= PERM_MOVE; @@ -729,6 +729,11 @@ void LLPanelPermissions::refresh() { RadioSaleType->setSelectedIndex((S32)sale_type - 1); } + else + { + // default option is sell copy, determined to be safest + RadioSaleType->setSelectedIndex((S32)LLSaleInfo::FS_COPY - 1); + } if (is_for_sale) { @@ -847,7 +852,7 @@ void LLPanelPermissions::onClickDeedToGroup(void* data) // static void LLPanelPermissions::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 perm) { - LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLViewerObject* object = gSelectMgr->getSelection()->getFirstRootObject(); if(!object) return; // Checkbox will have toggled itself @@ -855,7 +860,7 @@ void LLPanelPermissions::onCommitPerm(LLUICtrl *ctrl, void *data, U8 field, U32 LLCheckBoxCtrl *check = (LLCheckBoxCtrl *)ctrl; BOOL new_state = check->get(); - gSelectMgr->setObjectPermissions(field, new_state, perm); + gSelectMgr->selectionSetObjectPermissions(field, new_state, perm); } // static @@ -906,8 +911,8 @@ void LLPanelPermissions::onCommitName(LLUICtrl*, void* data) LLLineEditor* tb = gUICtrlFactory->getLineEditorByName(self,"Object Name"); if(tb) { - gSelectMgr->setObjectName(tb->getText()); -// gSelectMgr->setObjectName(self->mLabelObjectName->getText()); + gSelectMgr->selectionSetObjectName(tb->getText()); +// gSelectMgr->selectionSetObjectName(self->mLabelObjectName->getText()); } } @@ -920,7 +925,7 @@ void LLPanelPermissions::onCommitDesc(LLUICtrl*, void* data) LLLineEditor* le = gUICtrlFactory->getLineEditorByName(self,"Object Description"); if(le) { - gSelectMgr->setObjectDescription(le->getText()); + gSelectMgr->selectionSetObjectDescription(le->getText()); } } @@ -982,7 +987,7 @@ void LLPanelPermissions::setAllSaleInfo() } LLSaleInfo sale_info(sale_type, price); - gSelectMgr->setObjectSaleInfo(sale_info); + gSelectMgr->selectionSetObjectSaleInfo(sale_info); // If turned off for-sale, make sure click-action buy is turned // off as well @@ -1036,7 +1041,7 @@ void LLPanelPermissions::onCommitClickAction(LLUICtrl* ctrl, void*) { // Verify object has script with money() handler LLSelectionPayable payable; - bool can_pay = gSelectMgr->applyToObjects(&payable); + bool can_pay = gSelectMgr->getSelection()->applyToObjects(&payable); if (!can_pay) { // Warn, but do it anyway. diff --git a/linden/indra/newview/llpanelpick.cpp b/linden/indra/newview/llpanelpick.cpp index 4c9d5c3..ddd7934 100644 --- a/linden/indra/newview/llpanelpick.cpp +++ b/linden/indra/newview/llpanelpick.cpp @@ -289,10 +289,10 @@ void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) LLUUID parcel_id; msg->getUUID("Data", "ParcelID", parcel_id); - char name[DB_PARCEL_NAME_SIZE]; + char name[DB_PARCEL_NAME_SIZE]; /*Flawfinder: ignore*/ msg->getString("Data", "Name", DB_PARCEL_NAME_SIZE, name); - char desc[DB_PICK_DESC_SIZE]; + char desc[DB_PICK_DESC_SIZE]; /*Flawfinder: ignore*/ msg->getString("Data", "Desc", DB_PICK_DESC_SIZE, desc); LLUUID snapshot_id; @@ -300,7 +300,7 @@ void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) // "Location text" is actually the owner name, the original // name that owner gave the parcel, and the location. - char buffer[256]; + char buffer[256]; /*Flawfinder: ignore*/ LLString location_text; msg->getString("Data", "User", 256, buffer); @@ -314,7 +314,7 @@ void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) location_text.append(", "); } - char sim_name[256]; + char sim_name[256]; /*Flawfinder: ignore*/ msg->getString("Data", "SimName", 256, sim_name); LLVector3d pos_global; @@ -324,7 +324,7 @@ void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) S32 region_y = llround((F32)pos_global.mdV[VY]) % REGION_WIDTH_UNITS; S32 region_z = llround((F32)pos_global.mdV[VZ]); - sprintf(buffer, "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z); + snprintf(buffer, sizeof(buffer), "%s (%d, %d, %d)", sim_name, region_x, region_y, region_z); /*Flawfinder: ignore*/ location_text.append(buffer); S32 sort_order; @@ -359,7 +359,7 @@ void LLPanelPick::processPickInfoReply(LLMessageSystem *msg, void **) self->mLocationEditor->setText(location_text); self->mEnabledCheck->set(enabled); - sprintf(buffer, "%d", sort_order); + snprintf(buffer, sizeof(buffer), "%d", sort_order); /*Flawfinder: ignore*/ self->mSortOrderEditor->setText(buffer); } } @@ -506,8 +506,11 @@ void LLPanelPick::onCommitAny(LLUICtrl* ctrl, void* data) } else {*/ - LLTabContainerVertical* tab = (LLTabContainerVertical*)self->getParent(); - tab->setCurrentTabName(self->mNameEditor->getText()); + LLTabContainerVertical* tab = (LLTabContainerVertical*)self->getParent(); + if (tab) + { + if(tab) tab->setCurrentTabName(self->mNameEditor->getText()); + } //} } } diff --git a/linden/indra/newview/llpanelplace.cpp b/linden/indra/newview/llpanelplace.cpp index 4f316c9..f373e99 100644 --- a/linden/indra/newview/llpanelplace.cpp +++ b/linden/indra/newview/llpanelplace.cpp @@ -139,20 +139,20 @@ void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **) LLUUID agent_id; LLUUID parcel_id; LLUUID owner_id; - char name[MAX_STRING]; - char desc[MAX_STRING]; + char name[MAX_STRING]; /*Flawfinder: ignore*/ + char desc[MAX_STRING]; /*Flawfinder: ignore*/ S32 actual_area; S32 billable_area; U8 flags; F32 global_x; F32 global_y; F32 global_z; - char sim_name[MAX_STRING]; + char sim_name[MAX_STRING]; /*Flawfinder: ignore*/ LLUUID snapshot_id; F32 dwell; S32 sale_price; S32 auction_id; - char buffer[256]; + char buffer[256]; /*Flawfinder: ignore*/ msg->getUUID("AgentData", "AgentID", agent_id ); msg->getUUID("Data", "ParcelID", parcel_id); @@ -193,16 +193,16 @@ void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **) self->mDescEditor->setText(desc); LLString info; - sprintf(buffer, "Traffic: %.0f, Area: %d sq. m.", dwell, actual_area); + snprintf(buffer, sizeof(buffer), "Traffic: %.0f, Area: %d sq. m.", dwell, actual_area); /*Flawfinder: ignore*/ info.append(buffer); if (flags & DFQ_FOR_SALE) { - sprintf(buffer, ", For Sale for L$%d", sale_price); + snprintf(buffer, sizeof(buffer), ", For Sale for L$%d", sale_price); /*Flawfinder: ignore*/ info.append(buffer); } if (auction_id != 0) { - sprintf(buffer, ", Auction ID %010d", auction_id); + snprintf(buffer, sizeof(buffer), ", Auction ID %010d", auction_id); /*Flawfinder: ignore*/ info.append(buffer); } self->mInfoEditor->setText(info); @@ -218,7 +218,7 @@ void LLPanelPlace::processParcelInfoReply(LLMessageSystem *msg, void **) rating = LLViewerRegion::accessToString(SIM_ACCESS_MATURE); } - sprintf(buffer, "%s %d, %d, %d (%s)", + snprintf(buffer, sizeof(buffer), "%s %d, %d, %d (%s)", /*Flawfinder: ignore*/ sim_name, region_x, region_y, region_z, rating); self->mLocationEditor->setText(buffer); @@ -280,8 +280,8 @@ void LLPanelPlace::callbackAuctionWebPage(S32 option, void* data) if (0 == option) { - char url[256]; - sprintf(url, "%s%010d", AUCTION_URL, self->mAuctionID); + char url[256]; /*Flawfinder: ignore*/ + snprintf(url, sizeof(url), "%s%010d", AUCTION_URL, self->mAuctionID); /*Flawfinder: ignore*/ llinfos << "Loading auction page " << url << llendl; diff --git a/linden/indra/newview/llpanelvolume.cpp b/linden/indra/newview/llpanelvolume.cpp index afda5bd..3a8650d 100644 --- a/linden/indra/newview/llpanelvolume.cpp +++ b/linden/indra/newview/llpanelvolume.cpp @@ -136,11 +136,11 @@ LLPanelVolume::~LLPanelVolume() void LLPanelVolume::getState( ) { - LLViewerObject* objectp = gSelectMgr->getFirstRootObject(); + LLViewerObject* objectp = gSelectMgr->getSelection()->getFirstRootObject(); LLViewerObject* root_objectp = objectp; if(!objectp) { - objectp = gSelectMgr->getFirstObject(); + objectp = gSelectMgr->getSelection()->getFirstObject(); // *FIX: shouldn't we just keep the child? if (objectp) { @@ -185,7 +185,7 @@ void LLPanelVolume::getState( ) // BUG? Check for all objects being editable? BOOL editable = root_objectp->permModify(); BOOL single_volume = gSelectMgr->selectionAllPCode( LL_PCODE_VOLUME ) - && gSelectMgr->getObjectCount() == 1; + && gSelectMgr->getSelection()->getObjectCount() == 1; // Select Single Message if (single_volume) diff --git a/linden/indra/newview/llpolymesh.cpp b/linden/indra/newview/llpolymesh.cpp index d58ec74..4f339ac 100644 --- a/linden/indra/newview/llpolymesh.cpp +++ b/linden/indra/newview/llpolymesh.cpp @@ -261,7 +261,12 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //------------------------------------------------------------------------- // Open the file //------------------------------------------------------------------------- - FILE *fp = LLFile::fopen(fileName, "rb"); + if(!fileName) + { + llerrs << "Filename is Empty!" << llendl; + return FALSE; + } + FILE* fp = LLFile::fopen(fileName, "rb"); /*Flawfinder: ignore*/ if (!fp) { llerrs << "can't open: " << fileName << llendl; @@ -271,14 +276,14 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //------------------------------------------------------------------------- // Read a chunk //------------------------------------------------------------------------- - char header[128]; + char header[128]; /*Flawfinder: ignore*/ fread(header, sizeof(char), 128, fp); //------------------------------------------------------------------------- // Check for proper binary header //------------------------------------------------------------------------- BOOL status = FALSE; - if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) + if ( strncmp(header, HEADER_BINARY, strlen(HEADER_BINARY)) == 0 ) /*Flawfinder: ignore*/ { lldebugs << "Loading " << fileName << llendl; @@ -541,7 +546,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //---------------------------------------------------------------- for (i=0; i < numSkinJoints; i++) { - char jointName[64]; + char jointName[64]; /*Flawfinder: ignore*/ numRead = fread(jointName, sizeof(jointName), 1, fp); if (numRead != 1) { @@ -555,7 +560,7 @@ BOOL LLPolyMeshSharedData::loadMesh( const char *fileName ) //------------------------------------------------------------------------- // look for morph section //------------------------------------------------------------------------- - char morphName[64]; + char morphName[64]; /*Flawfinder: ignore*/ while(fread(&morphName, sizeof(char), 64, fp) == 64) { if (!strcmp(morphName, "End Morphs")) @@ -739,8 +744,8 @@ LLPolyMesh *LLPolyMesh::getMesh(const LLString &name, LLPolyMesh* reference_mesh //------------------------------------------------------------------------- // if not found, create a new one, add it to the list //------------------------------------------------------------------------- - char full_path[LL_MAX_PATH]; - sprintf(full_path, "%s", (gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name.c_str())).c_str()); + char full_path[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf(full_path, LL_MAX_PATH, "%s", (gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,name.c_str())).c_str()); /*Flawfinder: ignore*/ LLPolyMeshSharedData *mesh_data = new LLPolyMeshSharedData(); if (reference_mesh) @@ -799,7 +804,7 @@ void LLPolyMesh::dumpDiagInfo() U32 total_faces = 0; U32 total_kb = 0; - char buf[1024]; + char buf[1024]; /*Flawfinder: ignore*/ llinfos << "-----------------------------------------------------" << llendl; llinfos << " Global PolyMesh Table (DEBUG only)" << llendl; @@ -818,7 +823,7 @@ void LLPolyMesh::dumpDiagInfo() S32 num_faces = mesh.mNumFaces; U32 num_kb = mesh.getNumKB(); - sprintf(buf, "%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name_p->c_str()); + snprintf(buf, sizeof(buf), "%8d %8d %8d %s", num_verts, num_faces, num_kb, mesh_name_p->c_str()); /*Flawfinder: ignore*/ llinfos << buf << llendl; total_verts += num_verts; @@ -827,7 +832,7 @@ void LLPolyMesh::dumpDiagInfo() } llinfos << "-----------------------------------------------------" << llendl; - sprintf(buf, "%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); + snprintf(buf, sizeof(buf), "%8d %8d %8d TOTAL", total_verts, total_faces, total_kb ); /*Flawfinder: ignore*/ llinfos << buf << llendl; llinfos << "-----------------------------------------------------" << llendl; } @@ -906,12 +911,12 @@ void LLPolyMesh::initializeForMorph() if (!mSharedData) return; - memcpy(mCoords, mSharedData->mBaseCoords, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); - memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); + memcpy(mCoords, mSharedData->mBaseCoords, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + memcpy(mNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + memcpy(mScaledNormals, mSharedData->mBaseNormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + memcpy(mBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + memcpy(mScaledBinormals, mSharedData->mBaseBinormals, sizeof(LLVector3) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ + memcpy(mTexCoords, mSharedData->mTexCoords, sizeof(LLVector2) * mSharedData->mNumVertices); /*Flawfinder: ignore*/ memset(mClothingWeights, 0, sizeof(LLVector4) * mSharedData->mNumVertices); } @@ -1070,10 +1075,10 @@ BOOL LLPolySkeletalDistortion::setInfo(LLPolySkeletalDistortionInfo *info) mJointScales[joint] = bone_info->mScaleDeformation; // apply to children that need to inherit it - for ( LLViewerJoint *child_joint = (LLViewerJoint *)joint->mChildren.getFirstData(); - child_joint != NULL; - child_joint = (LLViewerJoint *)joint->mChildren.getNextData() ) + for (LLJoint::child_list_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) { + LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); if (child_joint->inheritScale()) { LLVector3 childDeformation = LLVector3(child_joint->getScale()); diff --git a/linden/indra/newview/llpolymesh.h b/linden/indra/newview/llpolymesh.h index 851a9bc..0d448ac 100644 --- a/linden/indra/newview/llpolymesh.h +++ b/linden/indra/newview/llpolymesh.h @@ -324,6 +324,7 @@ public: U32 mFaceVertexOffset; U32 mFaceVertexCount; + U32 mFaceIndexOffset; U32 mFaceIndexCount; U32 mCurVertexCount; private: diff --git a/linden/indra/newview/llpolymorph.cpp b/linden/indra/newview/llpolymorph.cpp index ae9b37a..3937da2 100644 --- a/linden/indra/newview/llpolymorph.cpp +++ b/linden/indra/newview/llpolymorph.cpp @@ -49,8 +49,8 @@ LLPolyMorphData::LLPolyMorphData(char *morph_name) { llassert (morph_name); - mName = new char[strlen(morph_name) + 1]; - strcpy(mName, morph_name); + mName = new char[strlen(morph_name) + 1]; /*Flawfinder: ignore*/ + strcpy(mName, morph_name); /*Flawfinder: ignore*/ mNumIndices = 0; mCurrentIndex = 0; diff --git a/linden/indra/newview/llpreview.cpp b/linden/indra/newview/llpreview.cpp index c5dc414..534513f 100644 --- a/linden/indra/newview/llpreview.cpp +++ b/linden/indra/newview/llpreview.cpp @@ -52,6 +52,7 @@ // Globals and statics LLPreview::preview_multimap_t LLPreview::sPreviewsBySource; LLPreview::preview_map_t LLPreview::sInstances; +std::map LLMultiPreview::sAutoOpenPreviewHandles; // Functions LLPreview::LLPreview(const std::string& name) : @@ -219,11 +220,11 @@ void LLPreview::onCommit() { gSelectMgr->deselectAll(); gSelectMgr->addAsIndividual( obj, SELECT_ALL_TES, FALSE ); - gSelectMgr->setObjectDescription( childGetText("desc") ); + gSelectMgr->selectionSetObjectDescription( childGetText("desc") ); if( has_sale_info ) { - gSelectMgr->setObjectSaleInfo( sale_info ); + gSelectMgr->selectionSetObjectSaleInfo( sale_info ); } gSelectMgr->deselectAll(); @@ -272,7 +273,7 @@ LLPreview* LLPreview::show( const LLUUID& item_uuid, BOOL take_focus ) // needs to be rehosted LLFloater::getFloaterHost()->addFloater(instance, TRUE); } - instance->open(); + instance->open(); /*Flawfinder: ignore*/ if (take_focus) { instance->setFocus(TRUE); @@ -382,14 +383,14 @@ BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask) return LLFloater::handleHover(x,y,mask); } -void LLPreview::open() +void LLPreview::open() /*Flawfinder: ignore*/ { LLMultiFloater* hostp = getHost(); if (!sHostp && !hostp && getAssetStatus() == PREVIEW_ASSET_UNLOADED) { loadAsset(); } - LLFloater::open(); + LLFloater::open(); /*Flawfinder: ignore*/ } // virtual @@ -491,11 +492,12 @@ LLPreview* LLPreview::getFirstPreviewForSource(const LLUUID& source_id) LLMultiPreview::LLMultiPreview(const LLRect& rect) : LLMultiFloater("Preview", rect) { + setCanResize(TRUE); } -void LLMultiPreview::open() +void LLMultiPreview::open() /*Flawfinder: ignore*/ { - LLMultiFloater::open(); + LLMultiFloater::open(); /*Flawfinder: ignore*/ LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel(); if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED) { @@ -511,3 +513,23 @@ void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click) opened_preview->loadAsset(); } } + +//static +LLMultiPreview* LLMultiPreview::getAutoOpenInstance(const LLUUID& id) +{ + handle_map_t::iterator found_it = sAutoOpenPreviewHandles.find(id); + if (found_it != sAutoOpenPreviewHandles.end()) + { + return (LLMultiPreview*)gFloaterView->getFloaterByHandle(found_it->second); + } + return NULL; +} + +//static +void LLMultiPreview::setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id) +{ + if (previewp) + { + sAutoOpenPreviewHandles[id] = previewp->getHandle(); + } +} diff --git a/linden/indra/newview/llpreview.h b/linden/indra/newview/llpreview.h index 418c797..7882b4c 100644 --- a/linden/indra/newview/llpreview.h +++ b/linden/indra/newview/llpreview.h @@ -34,7 +34,7 @@ #include "lluuid.h" #include "llviewerinventory.h" #include "lltabcontainer.h" -#include "lllineeditor.h" +#include class LLLineEditor; class LLRadioGroup; @@ -45,8 +45,15 @@ class LLMultiPreview : public LLMultiFloater public: LLMultiPreview(const LLRect& rect); - /*virtual*/void open(); + /*virtual*/void open(); /*Flawfinder: ignore*/ /*virtual*/void tabOpen(LLFloater* opened_floater, bool from_click); + + static LLMultiPreview* getAutoOpenInstance(const LLUUID& id); + static void setAutoOpenInstance(LLMultiPreview* previewp, const LLUUID& id); + +protected: + typedef std::map handle_map_t; + static std::map sAutoOpenPreviewHandles; }; class LLPreview : public LLFloater @@ -79,7 +86,7 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); - virtual void open(); + virtual void open(); /*Flawfinder: ignore*/ virtual bool saveItem(LLPointer* itemptr); void setAuxItem( const LLInventoryItem* item ) diff --git a/linden/indra/newview/llpreviewgesture.cpp b/linden/indra/newview/llpreviewgesture.cpp index 1ff782a..fdbeb6c 100644 --- a/linden/indra/newview/llpreviewgesture.cpp +++ b/linden/indra/newview/llpreviewgesture.cpp @@ -41,6 +41,7 @@ // newview #include "llagent.h" // todo: remove +#include "llassetuploadresponders.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -57,6 +58,7 @@ #include "llviewerinventory.h" #include "llviewerobject.h" #include "llviewerobjectlist.h" +#include "llviewerregion.h" #include "llviewerstats.h" #include "llviewerwindow.h" // busycount #include "viewer.h" // gVFS @@ -112,7 +114,7 @@ LLPreviewGesture* LLPreviewGesture::show(const std::string& title, const LLUUID& LLPreviewGesture* previewp = (LLPreviewGesture*)LLPreview::find(item_id); if (previewp) { - previewp->open(); + previewp->open(); /*Flawfinder: ignore*/ if (take_focus) { previewp->setFocus(TRUE); @@ -790,8 +792,8 @@ void LLPreviewGesture::refresh() mWaitTimeCheck->setVisible(TRUE); mWaitTimeCheck->set(wait_step->mFlags & WAIT_FLAG_TIME); mWaitTimeEditor->setVisible(TRUE); - char buffer[16]; - sprintf(buffer, "%.1f", (double)wait_step->mWaitSeconds); + char buffer[16]; /*Flawfinder: ignore*/ + snprintf(buffer, sizeof(buffer), "%.1f", (double)wait_step->mWaitSeconds); /*Flawfinder: ignore*/ mWaitTimeEditor->setText(buffer); break; } @@ -895,7 +897,7 @@ void LLPreviewGesture::onLoadComplete(LLVFS *vfs, S32 size = file.getSize(); char* buffer = new char[size+1]; - file.read((U8*)buffer, size); + file.read((U8*)buffer, size); /*Flawfinder: ignore*/ buffer[size] = '\0'; LLMultiGesture* gesture = new LLMultiGesture(); @@ -1120,13 +1122,31 @@ void LLPreviewGesture::saveIfNeeded() LLInventoryItem* item = getItem(); if (item) { - LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); - LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid); - - const BOOL temp_file = FALSE; - - gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, temp_file); - + std::string agent_url = gAgent.getRegion()->getCapability("UpdateGestureAgentInventory"); + std::string task_url = gAgent.getRegion()->getCapability("UpdateGestureTaskInventory"); + if (mObjectUUID.isNull() && !agent_url.empty()) + { + // Saving into agent inventory + LLSD body; + body["item_id"] = mItemUUID; + LLHTTPClient::post(agent_url, body, + new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE)); + } + else if (!mObjectUUID.isNull() && !task_url.empty()) + { + // Saving into task inventory + LLSD body; + body["task_id"] = mObjectUUID; + body["item_id"] = mItemUUID; + LLHTTPClient::post(task_url, body, + new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_GESTURE)); + } + else if (gAssetStorage) + { + LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); + LLSaveInfo* info = new LLSaveInfo(mItemUUID, mObjectUUID, descEditor->getText(), tid); + gAssetStorage->storeAssetData(tid, LLAssetType::AT_GESTURE, onSaveComplete, info, FALSE); + } } // If this gesture is active, then we need to update the in-memory diff --git a/linden/indra/newview/llpreviewnotecard.cpp b/linden/indra/newview/llpreviewnotecard.cpp index da8b9fc..fe5ade2 100644 --- a/linden/indra/newview/llpreviewnotecard.cpp +++ b/linden/indra/newview/llpreviewnotecard.cpp @@ -32,6 +32,7 @@ #include "llinventory.h" #include "llagent.h" +#include "llassetuploadresponders.h" #include "llviewerwindow.h" #include "llbutton.h" #include "llinventorymodel.h" @@ -110,8 +111,12 @@ LLPreviewNotecard::LLPreviewNotecard(const std::string& name, } } - reshape(curRect.getWidth(), curRect.getHeight(), TRUE); - setRect(curRect); + // only assert shape if not hosted in a multifloater + if (!getHost()) + { + reshape(curRect.getWidth(), curRect.getHeight(), TRUE); + setRect(curRect); + } childSetVisible("lock", FALSE); @@ -142,6 +147,7 @@ BOOL LLPreviewNotecard::postBuild() if (ed) { ed->setNotecardInfo(mNotecardItemID, mObjectID); + ed->makePristine(); } return TRUE; } @@ -234,6 +240,22 @@ const LLInventoryItem* LLPreviewNotecard::getDragItem() return NULL; } +bool LLPreviewNotecard::hasEmbeddedInventory() +{ + LLViewerTextEditor* editor = NULL; + editor = LLViewerUICtrlFactory::getViewerTextEditorByName( + this, + "Notecard Editor"); + if (!editor) return false; + return editor->hasEmbeddedInventory(); +} + +void LLPreviewNotecard::refreshFromInventory() +{ + lldebugs << "LLPreviewNotecard::refreshFromInventory()" << llendl; + loadAsset(); +} + void LLPreviewNotecard::loadAsset() { // request the asset. @@ -337,7 +359,7 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, S32 file_length = file.getSize(); char* buffer = new char[file_length+1]; - file.read((U8*)buffer, file_length); + file.read((U8*)buffer, file_length); /*Flawfinder: ignore*/ // put a EOS at the end buffer[file_length] = 0; @@ -363,7 +385,7 @@ void LLPreviewNotecard::onLoadComplete(LLVFS *vfs, LLInventoryItem* item = preview->getItem(); BOOL modifiable = item && gAgent.allowOperation(PERM_MODIFY, item->getPermissions(), GP_OBJECT_MANIPULATE); - previewEditor->setEnabled(modifiable); + preview->setEnabled(modifiable); delete[] buffer; preview->mAssetStatus = PREVIEW_ASSET_LOADED; } @@ -468,14 +490,43 @@ bool LLPreviewNotecard::saveIfNeeded(LLInventoryItem* copyitem) LLInventoryItem* item = getItem(); // save it out to database if (item) - { - - LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, - tid, copyitem); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD, - &onSaveComplete, - (void*)info, - FALSE); + { + std::string agent_url = gAgent.getRegion()->getCapability("UpdateNotecardAgentInventory"); + std::string task_url = gAgent.getRegion()->getCapability("UpdateNotecardTaskInventory"); + if (mObjectUUID.isNull() && !agent_url.empty()) + { + // Saving into agent inventory + mAssetStatus = PREVIEW_ASSET_LOADING; + setEnabled(FALSE); + LLSD body; + body["item_id"] = mItemUUID; + llinfos << "Saving notecard " << mItemUUID + << " into agent inventory via " << agent_url << llendl; + LLHTTPClient::post(agent_url, body, + new LLUpdateAgentInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD)); + } + else if (!mObjectUUID.isNull() && !task_url.empty()) + { + // Saving into task inventory + mAssetStatus = PREVIEW_ASSET_LOADING; + setEnabled(FALSE); + LLSD body; + body["task_id"] = mObjectUUID; + body["item_id"] = mItemUUID; + llinfos << "Saving notecard " << mItemUUID << " into task " + << mObjectUUID << " via " << task_url << llendl; + LLHTTPClient::post(task_url, body, + new LLUpdateTaskInventoryResponder(body, asset_id, LLAssetType::AT_NOTECARD)); + } + else if (gAssetStorage) + { + LLSaveNotecardInfo* info = new LLSaveNotecardInfo(this, mItemUUID, mObjectUUID, + tid, copyitem); + gAssetStorage->storeAssetData(tid, LLAssetType::AT_NOTECARD, + &onSaveComplete, + (void*)info, + FALSE); + } } } return true; @@ -551,10 +602,10 @@ void LLPreviewNotecard::onSaveComplete(const LLUUID& asset_uuid, void* user_data gViewerWindow->alertXml("SaveNotecardFailReason",args); } - char uuid_string[UUID_STR_LENGTH]; + char uuid_string[UUID_STR_LENGTH]; /*Flawfinder: ignore*/ asset_uuid.toString(uuid_string); - char filename[LL_MAX_PATH]; - sprintf(filename, "%s.tmp", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); + char filename[LL_MAX_PATH]; /*Flawfinder: ignore*/ + snprintf(filename, LL_MAX_PATH, "%s.tmp", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); /*Flawfinder: ignore*/ LLFile::remove(filename); delete info; } diff --git a/linden/indra/newview/llpreviewnotecard.h b/linden/indra/newview/llpreviewnotecard.h index da3fc3f..9b72ec8 100644 --- a/linden/indra/newview/llpreviewnotecard.h +++ b/linden/indra/newview/llpreviewnotecard.h @@ -69,6 +69,14 @@ public: const LLInventoryItem* getDragItem(); + // return true if there is any embedded inventory. + bool hasEmbeddedInventory(); + + // After saving a notecard, the tcp based upload system will + // change the asset, therefore, we need to re-fetch it from the + // asset system. :( + void refreshFromInventory(); + protected: virtual void loadAsset(); diff --git a/linden/indra/newview/llpreviewscript.cpp b/linden/indra/newview/llpreviewscript.cpp index c13da9b..75371b2 100644 --- a/linden/indra/newview/llpreviewscript.cpp +++ b/linden/indra/newview/llpreviewscript.cpp @@ -30,6 +30,7 @@ #include "llpreviewscript.h" #include "llassetstorage.h" +#include "llassetuploadresponders.h" #include "llbutton.h" #include "llcheckboxctrl.h" #include "llcombobox.h" @@ -155,7 +156,7 @@ public: LLScriptEdCore* getEditorCore() { return mEditorCore; } static LLFloaterScriptSearch* getInstance() { return sInstance; } - void open(); + void open(); /*Flawfinder: ignore*/ private: @@ -187,6 +188,18 @@ LLFloaterScriptSearch::LLFloaterScriptSearch(std::string title, LLRect rect, LLS sInstance = this; childSetFocus("search_text", TRUE); + + // find floater in which script panel is embedded + LLView* viewp = (LLView*)editor_core; + while(viewp) + { + if (viewp->getWidgetType() == WIDGET_TYPE_FLOATER) + { + ((LLFloater*)viewp)->addDependentFloater(this); + break; + } + viewp = viewp->getParent(); + } } //static @@ -208,7 +221,7 @@ void LLFloaterScriptSearch::show(LLScriptEdCore* editor_core) new LLFloaterScriptSearch("Script Search",LLRect(left,top,left + SCRIPT_SEARCH_WIDTH,top - SCRIPT_SEARCH_HEIGHT),editor_core); } - sInstance->open(); + sInstance->open(); /*Flawfinder: ignore*/ } LLFloaterScriptSearch::~LLFloaterScriptSearch() @@ -255,9 +268,9 @@ void LLFloaterScriptSearch::handleBtnReplaceAll() mEditorCore->mEditor->replaceTextAll(childGetText("search_text"), childGetText("replace_text"), caseChk->get()); } -void LLFloaterScriptSearch::open() +void LLFloaterScriptSearch::open() /*Flawfinder: ignore*/ { - LLFloater::open(); + LLFloater::open(); /*Flawfinder: ignore*/ childSetFocus("search_text", TRUE); } /// --------------------------------------------------------------------------- @@ -428,8 +441,8 @@ void LLScriptEdCore::draw() S32 line = 0; S32 column = 0; mEditor->getCurrentLineAndColumn( &line, &column, FALSE ); // don't include wordwrap - char cursor_pos[STD_STRING_BUF_SIZE]; - sprintf( cursor_pos, "Line %d, Column %d", line, column ); + char cursor_pos[STD_STRING_BUF_SIZE]; /*Flawfinder: ignore*/ + snprintf( cursor_pos, STD_STRING_BUF_SIZE, "Line %d, Column %d", line, column ); /*Flawfinder: ignore*/ childSetText("line_col", cursor_pos); } else @@ -851,6 +864,33 @@ LLPreviewLSL::LLPreviewLSL(const std::string& name, const LLRect& rect, } } +// virtual +void LLPreviewLSL::callbackLSLCompileSucceeded() +{ + llinfos << "LSL Bytecode saved" << llendl; + mScriptEd->mErrorList->addSimpleItem("Compile successful!"); + mScriptEd->mErrorList->addSimpleItem("Save complete."); + closeIfNeeded(); +} + +// virtual +void LLPreviewLSL::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + llinfos << "Compile failed!" << llendl; + + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + LLScrollListItem* item = NULL; + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + item = new LLScrollListItem(); + item->addColumn(line->asString(), err_font); + mScriptEd->mErrorList->addItem(item); + } + mScriptEd->selectFirstError(); + closeIfNeeded(); +} void LLPreviewLSL::loadAsset() { @@ -912,10 +952,21 @@ BOOL LLPreviewLSL::canClose() return mScriptEd->canClose(); } +void LLPreviewLSL::closeIfNeeded() +{ + // Find our window and close it if requested. + getWindow()->decBusyCount(); + mPendingUploads--; + if (mPendingUploads <= 0 && mCloseAfterSave) + { + close(); + } +} + //override the llpreview open which attempts to load asset, load after xml ui made -void LLPreviewLSL::open() +void LLPreviewLSL::open() /*Flawfinder: ignore*/ { - LLFloater::open(); + LLFloater::open(); /*Flawfinder: ignore*/ } // static @@ -933,152 +984,152 @@ void LLPreviewLSL::onSave(void* userdata, BOOL close_after_save) self->saveIfNeeded(); } - // Save needs to compile the text in the buffer. If the compile // succeeds, then save both assets out to the database. If the compile // fails, go ahead and save the text anyway so that the user doesn't // get too fucked. void LLPreviewLSL::saveIfNeeded() { - // llinfos << "LLPreviewLSL::save()" << llendl; - if(!mScriptEd->mEditor->isPristine()) + // llinfos << "LLPreviewLSL::saveIfNeeded()" << llendl; + if(mScriptEd->mEditor->isPristine()) { - mPendingUploads = 0; - mScriptEd->mErrorList->deleteAllItems(); - mScriptEd->mEditor->makePristine(); - - // We need to update the asset information - LLTransactionID tid; - LLAssetID uuid; - tid.generate(); - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - char uuid_string[UUID_STR_LENGTH]; - uuid.toString(uuid_string); - char filename[LL_MAX_PATH]; - sprintf(filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - FILE* fp = LLFile::fopen(filename, "wb"); - if(!fp) - { - llwarns << "Unable to write to " << filename << llendl; - LLScrollListItem* item = new LLScrollListItem(); - item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall); - mScriptEd->mErrorList->addItem(item); - return; - } + return; + } - LLString utf8text = mScriptEd->mEditor->getText(); - //fprintf(fp, "%s|%s\n", LLAssetType::lookup(LLAssetType::AT_LSL_TEXT), - //uuid_string); - //fprintf(fp,"{\n%s}\n", text.c_str()); - fputs(utf8text.c_str(), fp); - fclose(fp); - fp = NULL; + mPendingUploads = 0; + mScriptEd->mErrorList->deleteAllItems(); + mScriptEd->mEditor->makePristine(); - // also write it out to the vfs for upload - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND); - S32 size = utf8text.length() + 1; + // save off asset into file + LLTransactionID tid; + tid.generate(); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string filename = llformat("%s.lsl", filepath.c_str()); - file.setMaxSize(size); - file.write((U8*)utf8text.c_str(), size); + FILE* fp = LLFile::fopen(filename.c_str(), "wb"); + if(!fp) + { + llwarns << "Unable to write to " << filename << llendl; + LLScrollListItem* item = new LLScrollListItem(); + item->addColumn("Error writing to local file. Is your hard drive full?", LLFontGL::sSansSerifSmall); + mScriptEd->mErrorList->addItem(item); + return; + } - LLInventoryItem *inv_item = getItem(); + LLString utf8text = mScriptEd->mEditor->getText(); + fputs(utf8text.c_str(), fp); + fclose(fp); + fp = NULL; - // save it out to database - if(gAssetStorage && inv_item) + LLInventoryItem *inv_item = getItem(); + // save it out to asset server + std::string url = gAgent.getRegion()->getCapability("UpdateScriptAgentInventory"); + if(inv_item) + { + getWindow()->incBusyCount(); + mPendingUploads++; + if (!url.empty()) { - getWindow()->incBusyCount(); - mPendingUploads++; - LLScriptSaveInfo* info = NULL; + uploadAssetViaCaps(url, filename, mItemUUID); + } + else if (gAssetStorage) + { + uploadAssetLegacy(filename, mItemUUID, tid); + } + } +} - LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); +void LLPreviewLSL::uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& item_id) +{ + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["item_id"] = item_id; + LLHTTPClient::post(url, body, new LLUpdateAgentInventoryResponder(body, filename)); +} - info = new LLScriptSaveInfo(mItemUUID, - descEditor->getText(), - tid); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &LLPreviewLSL::onSaveComplete, info); - } +void LLPreviewLSL::uploadAssetLegacy(const std::string& filename, + const LLUUID& item_id, + const LLTransactionID& tid) +{ + LLLineEditor* descEditor = LLUICtrlFactory::getLineEditorByName(this, "desc"); + LLScriptSaveInfo* info = new LLScriptSaveInfo(item_id, + descEditor->getText(), + tid); + gAssetStorage->storeAssetData(filename.c_str(), tid, + LLAssetType::AT_LSL_TEXT, + &LLPreviewLSL::onSaveComplete, + info); - char dst_filename[LL_MAX_PATH]; - sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - char err_filename[LL_MAX_PATH]; - sprintf(err_filename, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - LLScrollListItem* item = NULL; - const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); - if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike())) - { - llinfos << "Compile failed!" << llendl; - //char command[256]; - //sprintf(command, "type %s\n", err_filename); - //system(command); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + std::string err_filename = llformat("%s.out", filepath.c_str()); - // load the error file into the error scrolllist - if(NULL != (fp = LLFile::fopen(err_filename, "r"))) + LLScrollListItem* item = NULL; + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + if(!lscript_compile(filename.c_str(), + dst_filename.c_str(), + err_filename.c_str(), + gAgent.isGodlike())) + { + llinfos << "Compile failed!" << llendl; + //char command[256]; + //sprintf(command, "type %s\n", err_filename); + //system(command); + + // load the error file into the error scrolllist + FILE* fp = LLFile::fopen(err_filename.c_str(), "r"); + if(fp) + { + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ + LLString line; + while(!feof(fp)) { - char buffer[MAX_STRING]; - LLString line; - while(!feof(fp)) + fgets(buffer, MAX_STRING, fp); + if(feof(fp)) { - - fgets(buffer, MAX_STRING, fp); - if(feof(fp)) - { - break; - } - else if(!buffer) - { - continue; - } - else - { - line.assign(buffer); - LLString::stripNonprintable(line); - item = new LLScrollListItem(); - item->addColumn(line, err_font); - mScriptEd->mErrorList->addItem(item); - } + break; } - fclose(fp); - mScriptEd->selectFirstError(); - } - } - else - { - llinfos << "Compile worked!" << llendl; - if(gAssetStorage) - { - // move the compiled file into the vfs for transport - FILE* fp = LLFile::fopen(dst_filename, "rb"); - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND); - - fseek(fp, 0, SEEK_END); - S32 size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = fread(copy_buf, 1, buf_size, fp))) + else if(!buffer) { - file.write(copy_buf, size); + continue; + } + else + { + line.assign(buffer); + LLString::stripNonprintable(line); + item = new LLScrollListItem(); + item->addColumn(line, err_font); + mScriptEd->mErrorList->addItem(item); } - fclose(fp); - fp = NULL; - getWindow()->incBusyCount(); - mPendingUploads++; - LLUUID* this_uuid = new LLUUID(mItemUUID); - gAssetStorage->storeAssetData(tid, - LLAssetType::AT_LSL_BYTECODE, - &LLPreviewLSL::onSaveBytecodeComplete, - (void**)this_uuid); } + fclose(fp); + mScriptEd->selectFirstError(); + } + } + else + { + llinfos << "Compile worked!" << llendl; + if(gAssetStorage) + { + getWindow()->incBusyCount(); + mPendingUploads++; + LLUUID* this_uuid = new LLUUID(mItemUUID); + gAssetStorage->storeAssetData(dst_filename.c_str(), + tid, + LLAssetType::AT_LSL_BYTECODE, + &LLPreviewLSL::onSaveBytecodeComplete, + (void**)this_uuid); } - - // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); } + + // get rid of any temp files left lying around + LLFile::remove(filename.c_str()); + LLFile::remove(err_filename.c_str()); + LLFile::remove(dst_filename.c_str()); } @@ -1184,7 +1235,7 @@ void LLPreviewLSL::onLoadComplete( LLVFS *vfs, const LLUUID& asset_uuid, LLAsset S32 file_length = file.getSize(); char* buffer = new char[file_length+1]; - file.read((U8*)buffer, file_length); + file.read((U8*)buffer, file_length); /*Flawfinder: ignore*/ // put a EOS at the end buffer[file_length] = 0; @@ -1287,7 +1338,7 @@ LLLiveLSLEditor::LLLiveLSLEditor(const std::string& name, const std::string& title, const LLUUID& object_id, const LLUUID& item_id) : - LLFloater(name, rect, title, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT), + LLPreview(name, rect, title, item_id, object_id, TRUE, SCRIPT_MIN_WIDTH, SCRIPT_MIN_HEIGHT), mObjectID(object_id), mItemID(item_id), mScriptEd(NULL), @@ -1346,6 +1397,40 @@ LLLiveLSLEditor::~LLLiveLSLEditor() LLLiveLSLEditor::sInstances.removeData(mItemID ^ mObjectID); } +// this is called via LLPreview::loadAsset() virtual method +void LLLiveLSLEditor::loadAsset() +{ + loadAsset(FALSE); +} + +// virtual +void LLLiveLSLEditor::callbackLSLCompileSucceeded(const LLUUID& task_id, + const LLUUID& item_id, + bool is_script_running) +{ + lldebugs << "LSL Bytecode saved" << llendl; + mScriptEd->mErrorList->addSimpleItem("Compile successful!"); + mScriptEd->mErrorList->addSimpleItem("Save complete."); + closeIfNeeded(); +} + +// virtual +void LLLiveLSLEditor::callbackLSLCompileFailed(const LLSD& compile_errors) +{ + lldebugs << "Compile failed!" << llendl; + const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); + LLScrollListItem* item = NULL; + for(LLSD::array_const_iterator line = compile_errors.beginArray(); + line < compile_errors.endArray(); + line++) + { + item = new LLScrollListItem(); + item->addColumn(line->asString(), err_font); + mScriptEd->mErrorList->addItem(item); + } + mScriptEd->selectFirstError(); + closeIfNeeded(); +} void LLLiveLSLEditor::loadAsset(BOOL is_new) { @@ -1377,6 +1462,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) mScriptEd->mEditor->setText("You are not allowed to view this script."); mScriptEd->mEditor->makePristine(); mScriptEd->mEditor->setEnabled(FALSE); + mAssetStatus = PREVIEW_ASSET_LOADED; } else if(mItem.notNull()) { @@ -1400,11 +1486,13 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) msg->addUUIDFast(_PREHASH_ItemID, mItemID); msg->sendReliable(object->getRegion()->getHost()); mAskedForRunningInfo = TRUE; + mAssetStatus = PREVIEW_ASSET_LOADING; } else { mScriptEd->mEditor->setText(""); mScriptEd->mEditor->makePristine(); + mAssetStatus = PREVIEW_ASSET_LOADED; } if(item @@ -1448,6 +1536,7 @@ void LLLiveLSLEditor::loadAsset(BOOL is_new) LLSaleInfo::DEFAULT, LLInventoryItem::II_FLAGS_NONE, time_corrected()); + mAssetStatus = PREVIEW_ASSET_LOADED; } } @@ -1463,10 +1552,11 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, if( LLLiveLSLEditor::sInstances.checkData(*xored_id) ) { + instance = LLLiveLSLEditor::sInstances[*xored_id]; if( LL_ERR_NOERR == status ) { - instance = LLLiveLSLEditor::sInstances[*xored_id]; instance->loadScriptText(vfs, asset_id, type); + instance->mAssetStatus = PREVIEW_ASSET_LOADED; } else { @@ -1488,6 +1578,7 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, { LLNotifyBox::showXml("UnableToLoadScript"); } + instance->mAssetStatus = PREVIEW_ASSET_ERROR; } } @@ -1496,7 +1587,11 @@ void LLLiveLSLEditor::onLoadComplete(LLVFS *vfs, const LLUUID& asset_id, void LLLiveLSLEditor::loadScriptText(const char* filename) { - FILE* file = LLFile::fopen(filename, "rb"); + if(!filename) + { + llerrs << "Filename is Empty!" << llendl; + } + FILE* file = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if(file) { // read in the whole file @@ -1522,7 +1617,7 @@ void LLLiveLSLEditor::loadScriptText(LLVFS *vfs, const LLUUID &uuid, LLAssetType LLVFile file(vfs, uuid, type); S32 file_length = file.getSize(); char *buffer = new char[file_length + 1]; - file.read((U8*)buffer, file_length); + file.read((U8*)buffer, file_length); /*Flawfinder: ignore*/ if (file.getLastBytesRead() != file_length || file_length <= 0) @@ -1680,18 +1775,16 @@ void LLLiveLSLEditor::saveIfNeeded() // set up the save on the local machine. mScriptEd->mEditor->makePristine(); LLTransactionID tid; - LLAssetID uuid; tid.generate(); - uuid = tid.makeAssetID(gAgent.getSecureSessionID()); - mItem->setAssetUUID(uuid); + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string filename = llformat("%s.lsl", filepath.c_str()); + + mItem->setAssetUUID(asset_id); mItem->setTransactionID(tid); // write out the data, and store it in the asset database - char uuid_string[UUID_STR_LENGTH]; - uuid.toString(uuid_string); - char filename[LL_MAX_PATH]; - sprintf(filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - FILE* fp = LLFile::fopen(filename, "wb"); + FILE* fp = LLFile::fopen(filename.c_str(), "wb"); if(!fp) { llwarns << "Unable to write to " << filename << llendl; @@ -1703,65 +1796,71 @@ void LLLiveLSLEditor::saveIfNeeded() LLString utf8text = mScriptEd->mEditor->getText(); fputs(utf8text.c_str(), fp); fclose(fp); - - LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running"); + fp = NULL; - // save it out to database - if(gAssetStorage) + // save it out to asset server + std::string url = gAgent.getRegion()->getCapability("UpdateScriptTaskInventory"); + getWindow()->incBusyCount(); + mPendingUploads++; + BOOL is_running = LLUICtrlFactory::getCheckBoxByName(this, "running")->get(); + if (!url.empty()) { - // write it out to the vfs for upload - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_TEXT, LLVFile::APPEND); - S32 size = utf8text.length() + 1; - - file.setMaxSize(size); - file.write((U8*)utf8text.c_str(), size); - - getWindow()->incBusyCount(); - mPendingUploads++; - LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID, - mItem, - runningCheckbox->get()); - gAssetStorage->storeAssetData(tid, LLAssetType::AT_LSL_TEXT, &onSaveTextComplete, (void*)data, FALSE); + uploadAssetViaCaps(url, filename, mObjectID, + mItemID, is_running); } - -#if LL_WINDOWS - // This major hack was inserted because sometimes compilation - // would fail because it couldn't open this file... I decided - // to make a loop until open was successful. This seems to be - // a problem specific to ntfs. - fp = NULL; - const U32 MAX_TRIES = 20; - U32 tries = MAX_TRIES; - while((!fp) && --tries) + else if (gAssetStorage) { - ms_sleep(17); - fp = LLFile::fopen(filename, "r"); - if(!fp) - { - llwarns << "Trying to open the source file " << filename - << " again" << llendl; - } - else - { - fclose(fp); - } + uploadAssetLegacy(filename, object, tid, is_running); } - fp = NULL; -#endif +} + +void LLLiveLSLEditor::uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + BOOL is_running) +{ + llinfos << "Update Task Inventory via capability" << llendl; + LLSD body; + body["task_id"] = task_id; + body["item_id"] = item_id; + body["is_script_running"] = is_running; + LLHTTPClient::post(url, body, + new LLUpdateTaskInventoryResponder(body, filename)); +} + +void LLLiveLSLEditor::uploadAssetLegacy(const std::string& filename, + LLViewerObject* object, + const LLTransactionID& tid, + BOOL is_running) +{ + LLLiveLSLSaveData* data = new LLLiveLSLSaveData(mObjectID, + mItem, + is_running); + gAssetStorage->storeAssetData(filename.c_str(), tid, + LLAssetType::AT_LSL_TEXT, + &onSaveTextComplete, + (void*)data, + FALSE); + + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_id.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + std::string err_filename = llformat("%s.out", filepath.c_str()); - char dst_filename[LL_MAX_PATH]; - sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - char err_filename[LL_MAX_PATH]; - sprintf(err_filename, "%s.out", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); LLScrollListItem* item = NULL; const LLFontGL* err_font = gResMgr->getRes(LLFONT_OCRA); - if(!lscript_compile(filename, dst_filename, err_filename, gAgent.isGodlike())) + FILE *fp; + if(!lscript_compile(filename.c_str(), + dst_filename.c_str(), + err_filename.c_str(), + gAgent.isGodlike())) { // load the error file into the error scrolllist llinfos << "Compile failed!" << llendl; - if(NULL != (fp = LLFile::fopen(err_filename, "r"))) + if(NULL != (fp = LLFile::fopen(err_filename.c_str(), "r"))) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /*Flawfinder: ignore*/ LLString line; while(!feof(fp)) { @@ -1801,33 +1900,14 @@ void LLLiveLSLEditor::saveIfNeeded() { llinfos << "LLLiveLSLEditor::saveAsset " << mItem->getAssetUUID() << llendl; - - // move the compiled file into the vfs for transport - FILE* fp = LLFile::fopen(dst_filename, "rb"); - LLVFile file(gVFS, uuid, LLAssetType::AT_LSL_BYTECODE, LLVFile::APPEND); - - fseek(fp, 0, SEEK_END); - S32 size = ftell(fp); - fseek(fp, 0, SEEK_SET); - - file.setMaxSize(size); - - const S32 buf_size = 65536; - U8 copy_buf[buf_size]; - while ((size = fread(copy_buf, 1, buf_size, fp))) - { - file.write(copy_buf, size); - } - fclose(fp); - fp = NULL; - getWindow()->incBusyCount(); mPendingUploads++; LLLiveLSLSaveData* data = NULL; data = new LLLiveLSLSaveData(mObjectID, mItem, - runningCheckbox->get()); - gAssetStorage->storeAssetData(tid, + is_running); + gAssetStorage->storeAssetData(dst_filename.c_str(), + tid, LLAssetType::AT_LSL_BYTECODE, &LLLiveLSLEditor::onSaveBytecodeComplete, (void*)data); @@ -1836,11 +1916,12 @@ void LLLiveLSLEditor::saveIfNeeded() } // get rid of any temp files left lying around - LLFile::remove(filename); - LLFile::remove(err_filename); - LLFile::remove(dst_filename); + LLFile::remove(filename.c_str()); + LLFile::remove(err_filename.c_str()); + LLFile::remove(dst_filename.c_str()); // If we successfully saved it, then we should be able to check/uncheck the running box! + LLCheckBoxCtrl* runningCheckbox = LLUICtrlFactory::getCheckBoxByName(this, "running"); runningCheckbox->setLabel(ENABLED_RUNNING_CHECKBOX_LABEL); runningCheckbox->setEnabled(TRUE); } @@ -1916,13 +1997,10 @@ void LLLiveLSLEditor::onSaveBytecodeComplete(const LLUUID& asset_uuid, void* use args["[REASON]"] = std::string(LLAssetStorage::getErrorString(status)); gViewerWindow->alertXml("CompileQueueSaveBytecode", args); } - char uuid_string[UUID_STR_LENGTH]; - data->mItem->getAssetUUID().toString(uuid_string); - char dst_filename[LL_MAX_PATH]; - sprintf(dst_filename, "%s.lso", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - LLFile::remove(dst_filename); - sprintf(dst_filename, "%s.lsl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,uuid_string).c_str()); - LLFile::remove(dst_filename); + + std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_CACHE,asset_uuid.asString()); + std::string dst_filename = llformat("%s.lso", filepath.c_str()); + LLFile::remove(dst_filename.c_str()); delete data; } @@ -1931,6 +2009,16 @@ BOOL LLLiveLSLEditor::canClose() return (mScriptEd->canClose()); } +void LLLiveLSLEditor::closeIfNeeded() +{ + getWindow()->decBusyCount(); + mPendingUploads--; + if (mPendingUploads <= 0 && mCloseAfterSave) + { + close(); + } +} + // static void LLLiveLSLEditor::onLoad(void* userdata) { @@ -1955,7 +2043,7 @@ LLLiveLSLEditor* LLLiveLSLEditor::show(const LLUUID& script_id, const LLUUID& ob { // Move the existing view to the front instance = LLLiveLSLEditor::sInstances[xored_id]; - instance->open(); + instance->open(); /*Flawfinder: ignore*/ } return instance; } @@ -1974,6 +2062,13 @@ void LLLiveLSLEditor::hide(const LLUUID& script_id, const LLUUID& object_id) delete instance; } } +// static +LLLiveLSLEditor* LLLiveLSLEditor::find(const LLUUID& script_id, const LLUUID& object_id) +{ + LLUUID xored_id = script_id ^ object_id; + return sInstances.getIfThere(xored_id); +} + // static void LLLiveLSLEditor::processScriptRunningReply(LLMessageSystem* msg, void**) diff --git a/linden/indra/newview/llpreviewscript.h b/linden/indra/newview/llpreviewscript.h index fd17388..cdc4df8 100644 --- a/linden/indra/newview/llpreviewscript.h +++ b/linden/indra/newview/llpreviewscript.h @@ -135,15 +135,24 @@ class LLPreviewLSL : public LLPreview public: LLPreviewLSL(const std::string& name, const LLRect& rect, const std::string& title, const LLUUID& item_uuid ); + virtual void callbackLSLCompileSucceeded(); + virtual void callbackLSLCompileFailed(const LLSD& compile_errors); - /*virtual*/ void open(); + /*virtual*/ void open(); /*Flawfinder: ignore*/ protected: virtual BOOL canClose(); + void closeIfNeeded(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); virtual void loadAsset(); void saveIfNeeded(); + void uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& item_id); + void uploadAssetLegacy(const std::string& filename, + const LLUUID& item_id, + const LLTransactionID& tid); static void onLoad(void* userdata); static void onSave(void* userdata, BOOL close_after_save); @@ -166,7 +175,7 @@ protected: // Used to view and edit an LSL that is attached to an object. -class LLLiveLSLEditor : public LLFloater +class LLLiveLSLEditor : public LLPreview { public: LLLiveLSLEditor(const std::string& name, const LLRect& rect, @@ -177,16 +186,33 @@ public: static LLLiveLSLEditor* show(const LLUUID& item_id, const LLUUID& object_id); static void hide(const LLUUID& item_id, const LLUUID& object_id); + static LLLiveLSLEditor* find(const LLUUID& item_id, const LLUUID& object_id); static void processScriptRunningReply(LLMessageSystem* msg, void**); - + + virtual void callbackLSLCompileSucceeded(const LLUUID& task_id, + const LLUUID& item_id, + bool is_script_running); + virtual void callbackLSLCompileFailed(const LLSD& compile_errors); + protected: virtual BOOL canClose(); + void closeIfNeeded(); virtual void draw(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE); - void loadAsset(BOOL is_new = FALSE); + virtual void loadAsset(); + void loadAsset(BOOL is_new); void saveIfNeeded(); + void uploadAssetViaCaps(const std::string& url, + const std::string& filename, + const LLUUID& task_id, + const LLUUID& item_id, + BOOL is_running); + void uploadAssetLegacy(const std::string& filename, + LLViewerObject* object, + const LLTransactionID& tid, + BOOL is_running); static void onLoad(void* userdata); static void onSave(void* userdata, BOOL close_after_save); diff --git a/linden/indra/newview/llpreviewsound.cpp b/linden/indra/newview/llpreviewsound.cpp index 76d41b0..10130db 100644 --- a/linden/indra/newview/llpreviewsound.cpp +++ b/linden/indra/newview/llpreviewsound.cpp @@ -35,6 +35,7 @@ #include "audioengine.h" #include "llviewermessage.h" // send_guid_sound_trigger #include "llagent.h" // gAgent +#include "lllineeditor.h" #include "llvieweruictrlfactory.h" extern LLAudioEngine* gAudiop; diff --git a/linden/indra/newview/llpreviewtexture.cpp b/linden/indra/newview/llpreviewtexture.cpp index 7948db4..99d0959 100644 --- a/linden/indra/newview/llpreviewtexture.cpp +++ b/linden/indra/newview/llpreviewtexture.cpp @@ -29,19 +29,21 @@ #include "llpreviewtexture.h" -#include "llviewerimage.h" -#include "llviewerimagelist.h" -#include "llresmgr.h" #include "llagent.h" #include "llbutton.h" -#include "llui.h" +#include "llfilepicker.h" +#include "llimagetga.h" #include "llinventoryview.h" #include "llinventory.h" -#include "llviewerwindow.h" +#include "llresmgr.h" #include "lltextbox.h" -#include "llimagetga.h" -#include "llfilepicker.h" +#include "lltextureview.h" +#include "llui.h" +#include "llviewerimage.h" +#include "llviewerimagelist.h" #include "llvieweruictrlfactory.h" +#include "llviewerwindow.h" +#include "lllineeditor.h" const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300; const S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120; @@ -185,6 +187,105 @@ void LLPreviewTexture::init() } } +void LLPreviewTexture::draw() +{ + if( getVisible() ) + { + updateAspectRatio(); + + LLPreview::draw(); + + if (!mMinimized) + { + LLGLSUIDefault gls_ui; + LLGLSNoTexture gls_notex; + + const LLRect& border = mClientRect; + LLRect interior = mClientRect; + interior.stretch( -PREVIEW_BORDER_WIDTH ); + + // ...border + gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f)); + gl_rect_2d_checkerboard( interior ); + + if ( mImage.notNull() ) + { + LLGLSTexture gls_no_texture; + // Draw the texture + glColor3f( 1.f, 1.f, 1.f ); + gl_draw_scaled_image(interior.mLeft, + interior.mBottom, + interior.getWidth(), + interior.getHeight(), + mImage); + + // Pump the texture priority + F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() ); + mImage->addTextureStats( pixel_area ); + + // Don't bother decoding more than we can display, unless + // we're loading the full image. + if (!mLoadingFullImage) + { + S32 int_width = interior.getWidth(); + S32 int_height = interior.getHeight(); + mImage->setKnownDrawSize(int_width, int_height); + } + else + { + // Don't use this feature + mImage->setKnownDrawSize(0, 0); + } + + if( mLoadingFullImage ) + { + LLFontGL::sSansSerif->renderUTF8("Receiving:", 0, + interior.mLeft + 4, + interior.mBottom + 4, + LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, + LLFontGL::DROP_SHADOW); + + F32 data_progress = mImage->mDownloadProgress; + + // Draw the progress bar. + const S32 BAR_HEIGHT = 12; + const S32 BAR_LEFT_PAD = 80; + S32 left = interior.mLeft + 4 + BAR_LEFT_PAD; + S32 bar_width = mRect.getWidth() - left - RESIZE_HANDLE_WIDTH - 2; + S32 top = interior.mBottom + 4 + BAR_HEIGHT; + S32 right = left + bar_width; + S32 bottom = top - BAR_HEIGHT; + + LLColor4 background_color(0.f, 0.f, 0.f, 0.75f); + LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f); + LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f); + + gl_rect_2d(left, top, right, bottom, background_color); + + if (data_progress > 0.0f) + { + // Downloaded bytes + right = left + llfloor(data_progress * (F32)bar_width); + if (right > left) + { + gl_rect_2d(left, top, right, bottom, downloaded_color); + } + } + } + else + if( !mSavedFileTimer.hasExpired() ) + { + LLFontGL::sSansSerif->renderUTF8("File Saved", 0, + interior.mLeft + 4, + interior.mBottom + 4, + LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM, + LLFontGL::DROP_SHADOW); + } + } + } + } +} + // virtual BOOL LLPreviewTexture::canSaveAs() @@ -330,43 +431,46 @@ void LLPreviewTexture::updateAspectRatio() button_height = BTN_HEIGHT + PREVIEW_PAD; } - LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); - window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); - window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; - LLMultiFloater* hostp = getHost(); - if (hostp) + if (client_height != mLastHeight || client_width != mLastWidth) { - // try to keep aspect ratio when hosted, as hosting view can resize without user input - mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); - } - else - { - mClientRect.setLeftTopAndSize(LLPANEL_BORDER_WIDTH + PREVIEW_PAD + 6, - mRect.getHeight() - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD), - mRect.getWidth() - horiz_pad, - mRect.getHeight() - (view_height - client_height) - 8); - } - - if (mImage->mFullHeight > mLastHeight && mImage->mFullWidth > mLastWidth) - { - mLastWidth = image_width; - mLastHeight = image_height; + mLastWidth = client_width; + mLastHeight = client_height; S32 old_top = mRect.mTop; S32 old_left = mRect.mLeft; - if (hostp) + if (getHost()) { - hostp->growToFit(this, view_width, view_height); + getHost()->growToFit(this, view_width, view_height); } else { reshape( view_width, view_height ); S32 new_bottom = old_top - mRect.getHeight(); setOrigin( old_left, new_bottom ); + // Try to keep whole view onscreen, don't allow partial offscreen. + gFloaterView->adjustToFitScreen(this, FALSE); } + } + + // clamp texture size to fit within actual size of floater after attempting resize + client_width = llmin(client_width, mRect.getWidth() - horiz_pad); + client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height); - // Try to keep whole view onscreen, don't allow partial offscreen. - gFloaterView->adjustToFitScreen(this, FALSE); + LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0); + window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD); + window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD; + + if (getHost()) + { + // try to keep aspect ratio when hosted, as hosting view can resize without user input + mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height); + } + else + { + mClientRect.setLeftTopAndSize(LLPANEL_BORDER_WIDTH + PREVIEW_PAD + 6, + mRect.getHeight() - (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD), + mRect.getWidth() - horiz_pad, + client_height); } } diff --git a/linden/indra/newview/llprogressview.cpp b/linden/indra/newview/llprogressview.cpp index 9e7f1a5..dd75c3f 100644 --- a/linden/indra/newview/llprogressview.cpp +++ b/linden/indra/newview/llprogressview.cpp @@ -39,8 +39,9 @@ #include "llglheaders.h" #include "llagent.h" -#include "llfocusmgr.h" #include "llbutton.h" +#include "llfocusmgr.h" +#include "llstartup.h" #include "llviewercontrol.h" #include "llviewerimagelist.h" #include "llviewerwindow.h" @@ -48,9 +49,8 @@ LLProgressView* LLProgressView::sInstance = NULL; -LLPointer gStartImageGL = NULL; -S32 gStartImageWidth = 1; -S32 gStartImageHeight = 1; +S32 gStartImageWidth = 1; +S32 gStartImageHeight = 1; const F32 FADE_IN_TIME = 1.f; const LLString ANIMATION_FILENAME = "Login Sequence "; diff --git a/linden/indra/newview/llselectmgr.cpp b/linden/indra/newview/llselectmgr.cpp index 9b13441..4e0cb17 100644 --- a/linden/indra/newview/llselectmgr.cpp +++ b/linden/indra/newview/llselectmgr.cpp @@ -122,6 +122,10 @@ LLColor4 LLSelectMgr::sHighlightParentColor; LLColor4 LLSelectMgr::sHighlightChildColor; LLColor4 LLSelectMgr::sContextSilhouetteColor; +static LLObjectSelection* get_null_object_selection(); +template<> + const LLHandle::NullFunc + LLHandle::sNullFunc = get_null_object_selection; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ // struct LLDeRezInfo @@ -146,6 +150,13 @@ struct LLDeRezInfo // Functions // +LLObjectSelection* get_null_object_selection() +{ + static LLObjectSelectionHandle null_ptr(new LLObjectSelection()); + return (LLObjectSelection*)null_ptr; +} + + //----------------------------------------------------------------------------- // LLSelectMgr() //----------------------------------------------------------------------------- @@ -177,7 +188,9 @@ LLSelectMgr::LLSelectMgr() gSavedSettings.setS32("GridMode", (S32)GRID_MODE_WORLD); mGridValid = FALSE; - mSelectType = SELECT_TYPE_WORLD; + mSelectedObjects = new LLObjectSelection(); + mHoverObjects = new LLObjectSelection(); + mHighlightedObjects = new LLObjectSelection(); } @@ -186,78 +199,72 @@ LLSelectMgr::LLSelectMgr() //----------------------------------------------------------------------------- LLSelectMgr::~LLSelectMgr() { - mHoverObjects.deleteAllNodes(); - mSelectedObjects.deleteAllNodes(); - mHighlightedObjects.deleteAllNodes(); + mHoverObjects->deleteAllNodes(); + mSelectedObjects->deleteAllNodes(); + mHighlightedObjects->deleteAllNodes(); mRectSelectedObjects.clear(); mGridObjects.deleteAllNodes(); - mUndoQueue.clear(); - mRedoQueue.clear(); -} - -bool LLSelectMgr::applyToObjects(LLSelectedObjectFunctor* func) -{ - bool result = true; - LLViewerObject* object; - for (object = getFirstObject(); object != NULL; object = getNextObject()) - { - result = result && func->apply(object); - } - return result; -} - -bool LLSelectMgr::applyToRootObjects(LLSelectedObjectFunctor* func) -{ - bool result = true; - LLViewerObject* object; - for (object = getFirstRootObject(); - object != NULL; - object = getNextRootObject()) - { - result = result && func->apply(object); - } - return result; } -bool LLSelectMgr::applyToNodes(LLSelectedNodeFunctor *func) +void LLSelectMgr::updateEffects() { - bool result = true; - LLSelectNode* node; - for (node = getFirstNode(); node != NULL; node = getNextNode()) + if (mEffectsTimer.getElapsedTimeF32() > 1.f) { - result = result && func->apply(node); + mSelectedObjects->updateEffects(); + mEffectsTimer.reset(); } - return result; } -void LLSelectMgr::updateEffects() +void LLSelectMgr::overrideObjectUpdates() { - if (mEffectsTimer.getElapsedTimeF32() > 1.f) + //override any position updates from simulator on objects being edited + LLSelectNode* selectNode; + for (selectNode = gSelectMgr->getSelection()->getFirstNode(); + selectNode != NULL; + selectNode = gSelectMgr->getSelection()->getNextNode()) { - mSelectedObjects.updateEffects(); - mEffectsTimer.reset(); + LLViewerObject* object = selectNode->getObject(); + + if (object->permMove()) + { + if (!selectNode->mLastPositionLocal.isExactlyZero()) + { + object->setPosition(selectNode->mLastPositionLocal); + } + if (selectNode->mLastRotation != LLQuaternion()) + { + object->setRotation(selectNode->mLastRotation); + } + if (!selectNode->mLastScale.isExactlyZero()) + { + object->setScale(selectNode->mLastScale); + } + } } } //----------------------------------------------------------------------------- // Select just the object, not any other group members. //----------------------------------------------------------------------------- -void LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) +LLObjectSelectionHandle LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) { llassert( object ); + //remember primary object + mSelectedObjects->mPrimaryObject = object; + // Don't add an object that is already in the list if (object->isSelected() ) { // make sure point at position is updated updatePointAt(); gEditMenuHandler = this; - return; + return NULL; } if (!canSelectObject(object)) { //make_ui_sound("UISndInvalidOp"); - return; + return NULL; } // llinfos << "Adding object to selected object list" << llendl; @@ -291,19 +298,24 @@ void LLSelectMgr::selectObjectOnly(LLViewerObject* object, S32 face) // have selection manager handle edit menu immediately after // user selects an object - if (getObjectCount()) + if (mSelectedObjects->getObjectCount()) { gEditMenuHandler = this; } + + return mSelectedObjects; } //----------------------------------------------------------------------------- // Select the object, parents and children. //----------------------------------------------------------------------------- -void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) +LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) { llassert( obj ); + //remember primary object + mSelectedObjects->mPrimaryObject = obj; + // This may be incorrect if things weren't family selected before... - djs 07/08/02 // Don't add an object that is already in the list if (obj->isSelected() ) @@ -311,13 +323,13 @@ void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) // make sure pointat position is updated updatePointAt(); gEditMenuHandler = this; - return; + return NULL; } if (!canSelectObject(obj)) { //make_ui_sound("UISndInvalidOp"); - return; + return NULL; } // Since we're selecting a family, start at the root, but @@ -366,16 +378,18 @@ void LLSelectMgr::selectObjectAndFamily(LLViewerObject* obj, BOOL add_to_end) // have selection manager handle edit menu immediately after // user selects an object - if (getObjectCount()) + if (mSelectedObjects->getObjectCount()) { gEditMenuHandler = this; } + + return mSelectedObjects; } //----------------------------------------------------------------------------- // Select the object, parents and children. //----------------------------------------------------------------------------- -void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray& object_list, +LLObjectSelectionHandle LLSelectMgr::selectObjectAndFamily(const LLDynamicArray& object_list, BOOL send_to_sim) { // Collect all of the objects, children included @@ -383,7 +397,10 @@ void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray& o LLViewerObject *object; S32 i; - if (object_list.count() < 1) return; + //clear primary object (no primary object) + mSelectedObjects->mPrimaryObject = NULL; + + if (object_list.count() < 1) return NULL; // NOTE -- we add the objects in REVERSE ORDER // to preserve the order in the mSelectedObjects list @@ -429,25 +446,25 @@ void LLSelectMgr::selectObjectAndFamily(const LLDynamicArray& o // have selection manager handle edit menu immediately after // user selects an object - if (getObjectCount()) + if (mSelectedObjects->getObjectCount()) { gEditMenuHandler = this; } + + return mSelectedObjects; } // Use for when the simulator kills an object. This version also // handles informing the current tool of the object's deletion. // // Caller needs to call dialog_refresh_all if necessary. -BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id) +BOOL LLSelectMgr::removeObjectFromSelections(const LLUUID &id) { - - BOOL object_found = FALSE; LLTool *tool = NULL; if (!gNoRender) { - tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + tool = gToolMgr->getCurrentTool(); // It's possible that the tool is editing an object that is not selected LLViewerObject* tool_editing_object = tool->getEditingObject(); @@ -462,13 +479,13 @@ BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id) if( !object_found ) { LLViewerObject* prevobjp = NULL; - for( LLViewerObject* tobjp = getFirstObject(); tobjp != NULL; tobjp = getNextObject() ) + for( LLViewerObject* tobjp = mSelectedObjects->getFirstObject(); tobjp != NULL; tobjp = mSelectedObjects->getNextObject() ) { if (tobjp == prevobjp) { // Somehow we got stuck in an infinite loop... (DaveP) // this logic is kind of twisted, not sure how this is happening, so... - llwarns << "Detected infinite loop #1 in LLSelectMgr::selectionRemoveObject:|" << llendl; + llwarns << "Detected infinite loop #1 in LLSelectMgr::removeObjectFromSelections:|" << llendl; //MikeS. adding warning and comment... //These infinite loops happen because the LLSelectMgr iteration routines are non-reentrant. //deselectObjectAndFamily uses getFirstObject and getNextObject to mess with the array, @@ -492,7 +509,7 @@ BOOL LLSelectMgr::selectionRemoveObject(const LLUUID &id) if(object_found == TRUE){ //MikeS. adding warning... This happens when removing a linked attachment while sitting on an object.. //I think the selection manager needs to be rewritten. BAD. - llwarns << "Detected infinite loop #2 in LLSelectMgr::selectionRemoveObject:|" << llendl; + llwarns << "Detected infinite loop #2 in LLSelectMgr::removeObjectFromSelections:|" << llendl; break; } object_found = TRUE; @@ -613,11 +630,11 @@ void LLSelectMgr::addAsFamily(LLDynamicArray& objects, BOOL add nodep = new LLSelectNode(objectp, TRUE); if (add_to_end) { - mSelectedObjects.addNodeAtEnd(nodep); + mSelectedObjects->addNodeAtEnd(nodep); } else { - mSelectedObjects.addNode(nodep); + mSelectedObjects->addNode(nodep); } objectp->setSelected(TRUE); @@ -634,7 +651,7 @@ void LLSelectMgr::addAsFamily(LLDynamicArray& objects, BOOL add { // we want this object to be selected for real // so clear transient flag - LLSelectNode* select_node = findSelectNode(objectp); + LLSelectNode* select_node = mSelectedObjects->findNode(objectp); if (select_node) { select_node->setTransient(FALSE); @@ -650,21 +667,21 @@ void LLSelectMgr::addAsFamily(LLDynamicArray& objects, BOOL add void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoable) { // check to see if object is already in list - LLSelectNode *nodep = findSelectNode(objectp); + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); // if not in list, add it if (!nodep) { nodep = new LLSelectNode(objectp, TRUE); - mSelectedObjects.addNode(nodep); + mSelectedObjects->addNode(nodep); } else { // make this a full-fledged selection nodep->setTransient(FALSE); // Move it to the front of the list - mSelectedObjects.removeNode(nodep); - mSelectedObjects.addNode(nodep); + mSelectedObjects->removeNode(nodep); + mSelectedObjects->addNode(nodep); } // Make sure the object is tagged as selected @@ -698,26 +715,26 @@ void LLSelectMgr::addAsIndividual(LLViewerObject *objectp, S32 face, BOOL undoab } -void LLSelectMgr::setHoverObject(LLViewerObject *objectp) +LLObjectSelectionHandle LLSelectMgr::setHoverObject(LLViewerObject *objectp) { // Always blitz hover list when setting - mHoverObjects.deleteAllNodes(); + mHoverObjects->deleteAllNodes(); if (!objectp) { - return; + return NULL; } // Can't select yourself if (objectp->mID == gAgentID) { - return; + return NULL; } // Can't select land if (objectp->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) { - return; + return NULL; } // Collect all of the objects @@ -733,15 +750,16 @@ void LLSelectMgr::setHoverObject(LLViewerObject *objectp) { cur_objectp = objects[i]; nodep = new LLSelectNode(cur_objectp, FALSE); - mHoverObjects.addNodeAtEnd(nodep); + mHoverObjects->addNodeAtEnd(nodep); } requestObjectPropertiesFamily(objectp); + return mHoverObjects; } LLSelectNode *LLSelectMgr::getHoverNode() { - return getHoverObjects().getFirstRootNode(); + return getHoverObjects()->getFirstRootNode(); } void LLSelectMgr::highlightObjectOnly(LLViewerObject* objectp) @@ -842,20 +860,23 @@ void LLSelectMgr::unhighlightObjectAndFamily(LLViewerObject* objectp) void LLSelectMgr::unhighlightAll() { mRectSelectedObjects.clear(); - mHighlightedObjects.deleteAllNodes(); + mHighlightedObjects->deleteAllNodes(); } -void LLSelectMgr::selectHighlightedObjects() +LLObjectSelectionHandle LLSelectMgr::selectHighlightedObjects() { - if (!mHighlightedObjects.getNumNodes()) + if (!mHighlightedObjects->getNumNodes()) { - return; + return NULL; } + //clear primary object + mSelectedObjects->mPrimaryObject = NULL; + LLSelectNode *nodep; - for (nodep = mHighlightedObjects.getFirstNode(); + for (nodep = mHighlightedObjects->getFirstNode(); nodep; - nodep = mHighlightedObjects.getNextNode()) + nodep = mHighlightedObjects->getNextNode()) { LLViewerObject* objectp = nodep->getObject(); @@ -871,12 +892,12 @@ void LLSelectMgr::selectHighlightedObjects() } LLSelectNode* new_nodep = new LLSelectNode(*nodep); - mSelectedObjects.addNode(new_nodep); + mSelectedObjects->addNode(new_nodep); // flag this object as selected objectp->setSelected(TRUE); - mSelectType = getSelectTypeForObject(objectp); + mSelectedObjects->mSelectType = getSelectTypeForObject(objectp); // request properties on root objects if (objectp->isRootEdit()) @@ -892,10 +913,12 @@ void LLSelectMgr::selectHighlightedObjects() saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK); updatePointAt(); - if (getObjectCount()) + if (mSelectedObjects->getObjectCount()) { gEditMenuHandler = this; } + + return mSelectedObjects; } void LLSelectMgr::deselectHighlightedObjects() @@ -957,7 +980,7 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & grid_object = NULL; } - if (mGridMode == GRID_MODE_LOCAL && gSelectMgr->getObjectCount()) + if (mGridMode == GRID_MODE_LOCAL && mSelectedObjects->getObjectCount()) { LLBBox bbox = mSavedSelectionBBox; mGridOrigin = mSavedSelectionBBox.getCenterAgent(); @@ -1011,18 +1034,18 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & } else // GRID_MODE_WORLD or just plain default { - LLViewerObject* first_object = gSelectMgr->getFirstRootObject(); + LLViewerObject* first_object = mSelectedObjects->getFirstRootObject(); if (!first_object) { - first_object = gSelectMgr->getFirstObject(); + first_object = mSelectedObjects->getFirstObject(); } mGridOrigin.clearVec(); mGridRotation.loadIdentity(); - mSelectType = getSelectTypeForObject( first_object ); + mSelectedObjects->mSelectType = getSelectTypeForObject( first_object ); - switch (mSelectType) + switch (mSelectedObjects->mSelectType) { case SELECT_TYPE_ATTACHMENT: if (first_object) @@ -1051,59 +1074,6 @@ void LLSelectMgr::getGrid(LLVector3& origin, LLQuaternion &rotation, LLVector3 & mGridValid = TRUE; } - - -LLSelectNode* LLSelectMgr::findSelectNode(LLViewerObject *object) -{ - return mSelectedObjects.findNode(object); -} - -//----------------------------------------------------------------------------- -// contains() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::contains(LLViewerObject* object) -{ - return mSelectedObjects.findNode(object) != NULL; -} - - -//----------------------------------------------------------------------------- -// contains() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::contains(LLViewerObject* object, S32 te) -{ - LLSelectNode *nodep; - if (te == SELECT_ALL_TES) - { - // ...all faces - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() ) - { - if (nodep->getObject() == object) - { - BOOL all_selected = TRUE; - for (S32 i = 0; i < SELECT_MAX_TES; i++) - { - all_selected = all_selected && nodep->isTESelected(i); - } - return all_selected; - } - } - return FALSE; - } - else - { - // ...one face - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() ) - { - if (nodep->getObject() == object && nodep->isTESelected(te)) - { - return TRUE; - } - } - return FALSE; - } -} - //----------------------------------------------------------------------------- // remove() - an array of objects //----------------------------------------------------------------------------- @@ -1116,14 +1086,14 @@ void LLSelectMgr::remove(LLDynamicArray& objects) for(S32 i = 0; i < count; i++) { objectp = objects.get(i); - for(nodep = mSelectedObjects.getFirstNode(); + for(nodep = mSelectedObjects->getFirstNode(); nodep != NULL; - nodep = mSelectedObjects.getNextNode()) + nodep = mSelectedObjects->getNextNode()) { if(nodep->getObject() == objectp) { objectp->setSelected(FALSE); - mSelectedObjects.removeNode(nodep); + mSelectedObjects->removeNode(nodep); break; } } @@ -1140,7 +1110,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) { // check if object already in list // *FIX: can we just check isSelected()? - LLSelectNode *nodep = findSelectNode(objectp); + LLSelectNode *nodep = mSelectedObjects->findNode(objectp); if (!nodep) { @@ -1152,12 +1122,12 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) if (objectp->getNumTEs() <= 0) { // object doesn't have faces, so blow it away - mSelectedObjects.removeNode(nodep); + mSelectedObjects->removeNode(nodep); objectp->setSelected( FALSE ); } else if (te == SELECT_ALL_TES) { - mSelectedObjects.removeNode(nodep); + mSelectedObjects->removeNode(nodep); objectp->setSelected( FALSE ); } else if (0 <= te && te < SELECT_MAX_TES) @@ -1183,7 +1153,7 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) // ...all faces now turned off, so remove if (!found) { - mSelectedObjects.removeNode(nodep); + mSelectedObjects->removeNode(nodep); objectp->setSelected( FALSE ); // BUG: Doesn't update simulator that object is gone. @@ -1206,12 +1176,12 @@ void LLSelectMgr::remove(LLViewerObject *objectp, S32 te, BOOL undoable) void LLSelectMgr::removeAll() { LLViewerObject *objectp; - for (objectp = mSelectedObjects.getFirstObject(); objectp; objectp = mSelectedObjects.getNextObject() ) + for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject() ) { objectp->setSelected( FALSE ); } - mSelectedObjects.deleteAllNodes(); + mSelectedObjects->deleteAllNodes(); updateSelectionCenter(); dialog_refresh_all(); @@ -1228,9 +1198,9 @@ void LLSelectMgr::promoteSelectionToRoot() LLSelectNode* nodep; LLViewerObject *objectp; - for (nodep = mSelectedObjects.getFirstNode(); + for (nodep = mSelectedObjects->getFirstNode(); nodep; - nodep = mSelectedObjects.getNextNode() ) + nodep = mSelectedObjects->getNextNode() ) { if (nodep->mIndividualSelection) { @@ -1266,9 +1236,9 @@ void LLSelectMgr::demoteSelectionToIndividuals() { LLDynamicArray objects; - for (LLViewerObject* root_objectp = mSelectedObjects.getFirstRootObject(); + for (LLViewerObject* root_objectp = mSelectedObjects->getFirstRootObject(); root_objectp; - root_objectp = mSelectedObjects.getNextRootObject()) + root_objectp = mSelectedObjects->getNextRootObject()) { root_objectp->addThisAndNonJointChildren(objects); } @@ -1284,71 +1254,20 @@ void LLSelectMgr::demoteSelectionToIndividuals() } //----------------------------------------------------------------------------- -// getObjectCount() -//----------------------------------------------------------------------------- -S32 LLSelectMgr::getObjectCount() -{ - return mSelectedObjects.getNumNodes(); -} - - -//----------------------------------------------------------------------------- -// getTECount() -//----------------------------------------------------------------------------- -S32 LLSelectMgr::getTECount() -{ - S32 count = 0; - - LLSelectNode* nodep; - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() ) - { - if (nodep->getObject()) - { - S32 num_tes = nodep->getObject()->getNumTEs(); - for (S32 te = 0; te < num_tes; te++) - { - if (nodep->isTESelected(te)) - { - count++; - } - } - } - } - - return count; -} - -//----------------------------------------------------------------------------- -// getRootObjectCount() -//----------------------------------------------------------------------------- -S32 LLSelectMgr::getRootObjectCount() -{ - LLSelectNode *nodep; - - S32 count = 0; - for(nodep = mSelectedObjects.getFirstRootNode(); nodep; nodep = mSelectedObjects.getNextRootNode()) - { - ++count; - } - return count; -} - - -//----------------------------------------------------------------------------- // dump() //----------------------------------------------------------------------------- void LLSelectMgr::dump() { - llinfos << "Selection Manager: " << mSelectedObjects.getNumNodes() << " items" << llendl; + llinfos << "Selection Manager: " << mSelectedObjects->getNumNodes() << " items" << llendl; llinfos << "TE mode " << mTEMode << llendl; S32 i = 0; LLViewerObject *objectp; - for (objectp = mSelectedObjects.getFirstObject(); + for (objectp = mSelectedObjects->getFirstObject(); objectp; - objectp = mSelectedObjects.getNextObject()) + objectp = mSelectedObjects->getNextObject()) { llinfos << "Object " << i << " type " << LLPrimitive::pCodeToString(objectp->getPCode()) << llendl; llinfos << " hasLSL " << objectp->flagScripted() << llendl; @@ -1366,14 +1285,14 @@ void LLSelectMgr::dump() // Face iterator S32 te; - for (mSelectedObjects.getFirstTE(&objectp, &te); + for (mSelectedObjects->getFirstTE(&objectp, &te); objectp; - mSelectedObjects.getNextTE(&objectp, &te)) + mSelectedObjects->getNextTE(&objectp, &te)) { llinfos << "Object " << objectp << " te " << te << llendl; } - llinfos << mHighlightedObjects.getNumNodes() << " objects currently highlighted." << llendl; + llinfos << mHighlightedObjects->getNumNodes() << " objects currently highlighted." << llendl; llinfos << "Center global " << mSelectionCenterGlobal << llendl; } @@ -1402,7 +1321,7 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) if(item && !item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID()) - && (mSelectedObjects.getNumNodes() > 1) ) + && (mSelectedObjects->getNumNodes() > 1) ) { llwarns << "Attempted to apply no-copy texture to multiple objects" << llendl; @@ -1412,43 +1331,43 @@ void LLSelectMgr::selectionSetImage(const LLUUID& imageid) LLViewerObject* objectp; S32 te; - // Apply the texture to each side - for (mSelectedObjects.getFirstTE(&objectp, &te); objectp; mSelectedObjects.getNextTE(&objectp, &te)) + for (mSelectedObjects->getFirstTE(&objectp, &te); objectp; mSelectedObjects->getNextTE(&objectp, &te)) { - if (item) { - LLToolDragAndDrop::dropTextureOneFace(objectp,te,item,LLToolDragAndDrop::SOURCE_AGENT,LLUUID::null); - - // HACK! HACK! ARG! - // *TODO: Replace mSelectedObjects with a REAL container class! - LLViewerObject* tmp_object; - S32 tmp_te; - mSelectedObjects.getCurrentTE(&tmp_object,&tmp_te); - if ((tmp_object != objectp) || (tmp_te != te) ) + if (te == -1) // all faces { - //AAARG someone has moved our list around! - mSelectedObjects.getFirstTE(&tmp_object, &tmp_te); - while ((tmp_object != objectp) || (tmp_te != te)) - { - mSelectedObjects.getNextTE(&tmp_object, &tmp_te); - } + LLToolDragAndDrop::dropTextureAllFaces(objectp, + item, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); + } + else // one face + { + LLToolDragAndDrop::dropTextureOneFace(objectp, + te, + item, + LLToolDragAndDrop::SOURCE_AGENT, + LLUUID::null); } } - else + + else // not an inventory item { // Texture picker defaults aren't inventory items // * Don't need to worry about permissions for them // * Can just apply the texture and be done with it. objectp->setTEImage(te, gImageList.getImage(imageid)); + objectp->sendTEUpdate(); } } + // 1 particle effect per object - if (mSelectType != SELECT_TYPE_HUD) + if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD) { - for (objectp = mSelectedObjects.getFirstObject(); objectp; objectp = mSelectedObjects.getNextObject()) + for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject()) { LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); effectp->setSourceObject(gAgent.getAvatarObject()); @@ -1466,7 +1385,7 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1475,7 +1394,7 @@ void LLSelectMgr::selectionSetColor(const LLColor4 &color) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1492,7 +1411,7 @@ void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) LLViewerObject* object; LLColor4 new_color = color; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1503,7 +1422,7 @@ void LLSelectMgr::selectionSetColorOnly(const LLColor4 &color) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1519,7 +1438,7 @@ void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1530,7 +1449,7 @@ void LLSelectMgr::selectionSetAlphaOnly(const F32 alpha) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1544,11 +1463,11 @@ void LLSelectMgr::selectionRevertColors() LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { - LLSelectNode* nodep = mSelectedObjects.findNode(object); + LLSelectNode* nodep = mSelectedObjects->findNode(object); if (nodep && te < (S32)nodep->mSavedColors.size()) { LLColor4 color = nodep->mSavedColors[te]; @@ -1558,7 +1477,7 @@ void LLSelectMgr::selectionRevertColors() } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1573,11 +1492,11 @@ BOOL LLSelectMgr::selectionRevertTextures() S32 te; BOOL revert_successful = TRUE; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { - LLSelectNode* nodep = mSelectedObjects.findNode(object); + LLSelectNode* nodep = mSelectedObjects->findNode(object); if (nodep && te < (S32)nodep->mSavedTextures.size()) { LLUUID id = nodep->mSavedTextures[te]; @@ -1596,7 +1515,7 @@ BOOL LLSelectMgr::selectionRevertTextures() } // propagate texture changes to server - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1611,7 +1530,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1620,7 +1539,7 @@ void LLSelectMgr::selectionSetBumpmap(U8 bumpmap) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1633,7 +1552,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1642,7 +1561,7 @@ void LLSelectMgr::selectionSetTexGen(U8 texgen) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1656,7 +1575,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1665,7 +1584,7 @@ void LLSelectMgr::selectionSetShiny(U8 shiny) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1678,7 +1597,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1687,7 +1606,7 @@ void LLSelectMgr::selectionSetFullbright(U8 fullbright) } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1718,7 +1637,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& media_flags = LLTextureEntry::MF_WEB_PAGE; } - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te) ) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te) ) { if (object->permModify()) { @@ -1727,7 +1646,7 @@ void LLSelectMgr::selectionSetMediaTypeAndURL(U8 media_type, const std::string& } } - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -1749,7 +1668,7 @@ LLPermissions* LLSelectMgr::findObjectPermissions(const LLViewerObject* object) { LLSelectNode* nodep; - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode() ) + for (nodep = mSelectedObjects->getFirstNode(); nodep; nodep = mSelectedObjects->getNextNode() ) { if((nodep->getObject() == object) && nodep->mValid) { @@ -1768,7 +1687,7 @@ BOOL LLSelectMgr::selectionGetTexUUID(LLUUID& id) { LLViewerObject* first_objectp; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_objectp, &first_te); + mSelectedObjects->getPrimaryTE(&first_objectp, &first_te); // nothing selected if (!first_objectp) @@ -1786,7 +1705,7 @@ BOOL LLSelectMgr::selectionGetTexUUID(LLUUID& id) BOOL identical = TRUE; LLViewerObject *objectp; S32 te; - for (mSelectedObjects.getFirstTE(&objectp, &te); objectp; mSelectedObjects.getNextTE(&objectp, &te) ) + for (mSelectedObjects->getFirstTE(&objectp, &te); objectp; mSelectedObjects->getNextTE(&objectp, &te) ) { if (objectp->getTEImage(te) != first_imagep) { @@ -1806,7 +1725,7 @@ BOOL LLSelectMgr::selectionGetColor(LLColor4 &color) { LLViewerObject* first_object; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_object, &first_te); + mSelectedObjects->getPrimaryTE(&first_object, &first_te); // nothing selected if (!first_object) @@ -1827,7 +1746,7 @@ BOOL LLSelectMgr::selectionGetColor(LLColor4 &color) BOOL identical = TRUE; LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->getTE(te) || (object->getTE(te)->getColor() != first_color)) { @@ -1848,7 +1767,7 @@ BOOL LLSelectMgr::selectionGetBumpmap(U8 *bumpmap) { LLViewerObject* first_object; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_object, &first_te); + mSelectedObjects->getPrimaryTE(&first_object, &first_te); // nothing selected if (!first_object) @@ -1869,7 +1788,7 @@ BOOL LLSelectMgr::selectionGetBumpmap(U8 *bumpmap) BOOL identical = TRUE; LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->getTE(te) || (object->getTE(te)->getBumpmap() != first_value)) { @@ -1889,7 +1808,7 @@ BOOL LLSelectMgr::selectionGetShiny(U8 *shiny) { LLViewerObject* first_object; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_object, &first_te); + mSelectedObjects->getPrimaryTE(&first_object, &first_te); // nothing selected if (!first_object) @@ -1910,7 +1829,7 @@ BOOL LLSelectMgr::selectionGetShiny(U8 *shiny) BOOL identical = TRUE; LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->getTE(te) || (object->getTE(te)->getShiny() != first_value)) { @@ -1930,7 +1849,7 @@ BOOL LLSelectMgr::selectionGetFullbright(U8 *fullbright) { LLViewerObject* first_object; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_object, &first_te); + mSelectedObjects->getPrimaryTE(&first_object, &first_te); // nothing selected if (!first_object) @@ -1951,7 +1870,7 @@ BOOL LLSelectMgr::selectionGetFullbright(U8 *fullbright) BOOL identical = TRUE; LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->getTE(te) || (object->getTE(te)->getFullbright() != first_value)) { @@ -1969,7 +1888,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type) { LLViewerObject* first_object; S32 first_te; - mSelectedObjects.getPrimaryTE(&first_object, &first_te); + mSelectedObjects->getPrimaryTE(&first_object, &first_te); // nothing selected if (!first_object) @@ -1990,7 +1909,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type) bool identical = true; LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->getTE(te) || (object->getTE(te)->getMediaFlags() != first_value)) { @@ -2011,7 +1930,7 @@ bool LLSelectMgr::selectionGetMediaType(U8 *media_type) void LLSelectMgr::selectionSetMaterial(U8 material) { LLViewerObject* object; - for (object = mSelectedObjects.getFirstObject(); object != NULL; object = mSelectedObjects.getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object != NULL; object = mSelectedObjects->getNextObject() ) { if (object->permModify()) { @@ -2027,7 +1946,7 @@ void LLSelectMgr::selectionSetMaterial(U8 material) BOOL LLSelectMgr::selectionAllPCode(LLPCode code) { LLViewerObject *object; - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if (object->getPCode() != code) { @@ -2042,13 +1961,13 @@ BOOL LLSelectMgr::selectionAllPCode(LLPCode code) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectionGetMaterial(U8 *out_material) { - LLViewerObject *object = mSelectedObjects.getFirstObject(); + LLViewerObject *object = mSelectedObjects->getFirstObject(); if (!object) return FALSE; U8 material = object->getMaterial(); BOOL identical = TRUE; - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( material != object->getMaterial()) { @@ -2063,13 +1982,13 @@ BOOL LLSelectMgr::selectionGetMaterial(U8 *out_material) BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) { - LLViewerObject *object = mSelectedObjects.getFirstObject(); + LLViewerObject *object = mSelectedObjects->getFirstObject(); if (!object) return FALSE; U8 action = object->getClickAction(); BOOL identical = TRUE; - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( action != object->getClickAction()) { @@ -2085,7 +2004,7 @@ BOOL LLSelectMgr::selectionGetClickAction(U8 *out_action) void LLSelectMgr::selectionSetClickAction(U8 action) { LLViewerObject* object = NULL; - for ( object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for ( object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { object->setClickAction(action); } @@ -2118,7 +2037,7 @@ void LLSelectMgr::sendGodlikeRequest(const LLString& request, const LLString& pa } godlike_request_t data(request, param); - if(!getRootObjectCount()) + if(!mSelectedObjects->getRootObjectCount()) { LLMessageSystem* msg = gMessageSystem; msg->newMessage(message_type.c_str()); @@ -2158,8 +2077,8 @@ void LLSelectMgr::packGodlikeHead(void* user_data) // static void LLSelectMgr::packObjectIDAsParam(LLSelectNode* node, void *) { - char buf [MAX_STRING]; - sprintf(buf, "%u", node->getObject()->getLocalID()); + char buf [MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buf, MAX_STRING, "%u", node->getObject()->getLocalID()); /* Flawfinder: ignore */ gMessageSystem->nextBlock("ParamList"); gMessageSystem->addString("Parameter", buf); } @@ -2172,7 +2091,7 @@ void LLSelectMgr::selectionResetRotation() LLQuaternion identity(0.f, 0.f, 0.f, 1.f); LLViewerObject* object; - for (object = mSelectedObjects.getFirstRootObject(); object; object = mSelectedObjects.getNextRootObject() ) + for (object = mSelectedObjects->getFirstRootObject(); object; object = mSelectedObjects->getNextRootObject() ) { object->setRotation(identity); if (object->mDrawable.notNull()) @@ -2188,7 +2107,7 @@ void LLSelectMgr::selectionRotateAroundZ(F32 degrees) LLQuaternion rot( degrees * DEG_TO_RAD, LLVector3(0,0,1) ); LLViewerObject* object; - for (object = mSelectedObjects.getFirstRootObject(); object; object = mSelectedObjects.getNextRootObject() ) + for (object = mSelectedObjects->getFirstRootObject(); object; object = mSelectedObjects->getNextRootObject() ) { object->setRotation( object->getRotationEdit() * rot ); if (object->mDrawable.notNull()) @@ -2207,7 +2126,7 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) { LLViewerObject* object; S32 te; - for (mSelectedObjects.getFirstTE(&object, &te); object; mSelectedObjects.getNextTE(&object, &te)) + for (mSelectedObjects->getFirstTE(&object, &te); object; mSelectedObjects->getNextTE(&object, &te)) { if (!object->permModify()) { @@ -2232,7 +2151,7 @@ void LLSelectMgr::selectionTexScaleAutofit(F32 repeats_per_meter) object->setTEScale(te, new_s, new_t); } - for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject()) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject()) { if (object->permModify()) { @@ -2299,7 +2218,7 @@ void LLSelectMgr::adjustTexturesByScale(BOOL send_to_sim, BOOL stretch) BOOL send = FALSE; - for (selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode()) + for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode()) { object = selectNode->getObject(); if (!object->permModify()) @@ -2357,7 +2276,7 @@ void LLSelectMgr::selectionResetTexInfo(S32 selected_face) S32 start_face, end_face; LLViewerObject* object; - for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject()) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject()) { if (!object->permModify()) { @@ -2392,318 +2311,71 @@ void LLSelectMgr::selectionResetTexInfo(S32 selected_face) } //----------------------------------------------------------------------------- -// getFirstEditableObject() +// selectGetAllRootsValid() +// Returns true if the viewer has information on all selected objects //----------------------------------------------------------------------------- -LLViewerObject* LLSelectMgr::getFirstEditableObject(BOOL get_root) +BOOL LLSelectMgr::selectGetAllRootsValid() { - LLViewerObject* object = NULL; - for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject()) + for( LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { - if( cur->permModify() ) + + if( !node->mValid ) { - object = cur; - break; + return FALSE; } - } - if (get_root && object) - { - LLViewerObject *parent; - while ((parent = (LLViewerObject*)object->getParent())) + if( !node->getObject() ) { - if (parent->isSelected()) - { - object = parent; - } - else - { - break; - } + return FALSE; } } - - return object; + return TRUE; } + //----------------------------------------------------------------------------- -// getFirstMoveableObject() +// selectGetAllValid() +// Returns true if the viewer has information on all selected objects //----------------------------------------------------------------------------- -LLViewerObject* LLSelectMgr::getFirstMoveableObject(BOOL get_root) +BOOL LLSelectMgr::selectGetAllValid() { - LLViewerObject* object = NULL; - for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject()) + for( LLSelectNode* node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() ) { - if( cur->permMove() ) + + if( !node->mValid ) { - object = cur; - break; + return FALSE; } - } - if (get_root && object && !object->isJointChild()) - { - LLViewerObject *parent; - while ((parent = (LLViewerObject*)object->getParent())) + if( !node->getObject() ) { - if (parent->isSelected()) - { - object = parent; - } - else - { - break; - } + return FALSE; } } - - return object; + return TRUE; } + //----------------------------------------------------------------------------- -// getFirstEditableNode() +// selectGetModify() - return true if current agent can modify all +// selected objects. //----------------------------------------------------------------------------- -LLSelectNode* LLSelectMgr::getFirstEditableNode(BOOL get_root) +BOOL LLSelectMgr::selectGetModify() { - LLSelectNode* selectNode = NULL; - - if (get_root) + for( LLSelectNode* node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() ) { - for(selectNode = mSelectedObjects.getFirstRootNode(); selectNode; selectNode = mSelectedObjects.getNextRootNode()) + if( !node->mValid ) { - if( selectNode->getObject()->permModify() ) - { - return selectNode; - break; - } + return FALSE; } - } - for(selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode()) - { - if( selectNode->getObject()->permModify() ) + LLViewerObject* object = node->getObject(); + if( !object || !object->permModify() ) { - return selectNode; - break; + return FALSE; } } - - return NULL; -} - -//----------------------------------------------------------------------------- -// getFirstMoveableNode() -//----------------------------------------------------------------------------- -LLSelectNode* LLSelectMgr::getFirstMoveableNode(BOOL get_root) -{ - LLSelectNode* selectNode = NULL; - - if (get_root) - { - for(selectNode = mSelectedObjects.getFirstRootNode(); selectNode; selectNode = mSelectedObjects.getNextRootNode()) - { - if( selectNode->getObject()->permMove() ) - { - return selectNode; - break; - } - } - } - for(selectNode = mSelectedObjects.getFirstNode(); selectNode; selectNode = mSelectedObjects.getNextNode()) - { - if( selectNode->getObject()->permMove() ) - { - return selectNode; - break; - } - } - - return NULL; -} - -//----------------------------------------------------------------------------- -// getFirstDeleteableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLSelectMgr::getFirstDeleteableObject(BOOL get_root) -{ - //RN: don't currently support deletion of child objects, as that requires separating them first - // then derezzing to trash - get_root = TRUE; - - LLViewerObject* object = NULL; - if (get_root) - { - for(LLViewerObject* current = getFirstRootObject(); - current != NULL; - current = getNextRootObject()) - { - // you can delete an object if permissions allow it, you are - // the owner, you are an officer in the group that owns the - // object, or you are not the owner but it is on land you own - // or land owned by your group. (whew!) - if( (current->permModify()) - || (current->permYouOwner()) - || (!current->permAnyOwner()) // public - || (current->isOverAgentOwnedLand()) - || (current->isOverGroupOwnedLand()) - ) - { - - if( !current->isAttachment() ) - { - object = current; - break; - } - } - } - } - else - { - for(LLViewerObject* current = getFirstObject(); - current != NULL; - current = getNextObject()) - { - // you can delete an object if permissions allow it, you are - // the owner, you are an officer in the group that owns the - // object, or you are not the owner but it is on land you own - // or land owned by your group. (whew!) - if( (current->permModify()) - || (current->permYouOwner()) - || (!current->permAnyOwner()) // public - || (current->isOverAgentOwnedLand()) - || (current->isOverGroupOwnedLand()) - ) - { - if( !current->isAttachment() ) - { - object = current; - break; - } - } - } - } - - return object; -} - -//----------------------------------------------------------------------------- -// getFirstCopyableObject() -//----------------------------------------------------------------------------- -LLViewerObject* LLSelectMgr::getFirstCopyableObject(BOOL get_root) -{ - LLViewerObject* object = NULL; - for(LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject()) - { - if( cur->permCopy() && !cur->isAttachment()) - { - object = cur; - break; - } - } - - if (get_root && object) - { - LLViewerObject *parent; - while ((parent = (LLViewerObject*)object->getParent())) - { - if (parent->isSelected()) - { - object = parent; - } - else - { - break; - } - } - } - - return object; -} - -//----------------------------------------------------------------------------- -// areMultpleEditableObjectsSelected() -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::areMultpleEditableObjectsSelected() -{ - S32 count = 0; - for( LLViewerObject* cur = mSelectedObjects.getFirstObject(); cur; cur = mSelectedObjects.getNextObject() ) - { - if( cur->permModify() ) - { - count++; - if( count > 1 ) - { - return TRUE; - } - } - } - return FALSE; -} - -//----------------------------------------------------------------------------- -// selectGetAllRootsValid() -// Returns true if the viewer has information on all selected objects -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetAllRootsValid() -{ - for( LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode() ) - { - - if( !node->mValid ) - { - return FALSE; - } - - if( !node->getObject() ) - { - return FALSE; - } - } - return TRUE; -} - - -//----------------------------------------------------------------------------- -// selectGetAllValid() -// Returns true if the viewer has information on all selected objects -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetAllValid() -{ - for( LLSelectNode* node = getFirstNode(); node; node = getNextNode() ) - { - - if( !node->mValid ) - { - return FALSE; - } - - if( !node->getObject() ) - { - return FALSE; - } - } - return TRUE; -} - - -//----------------------------------------------------------------------------- -// selectGetModify() - return true if current agent can modify all -// selected objects. -//----------------------------------------------------------------------------- -BOOL LLSelectMgr::selectGetModify() -{ - for( LLSelectNode* node = getFirstNode(); node; node = getNextNode() ) - { - if( !node->mValid ) - { - return FALSE; - } - LLViewerObject* object = node->getObject(); - if( !object || !object->permModify() ) - { - return FALSE; - } - } - - return TRUE; + + return TRUE; } //----------------------------------------------------------------------------- @@ -2712,7 +2384,7 @@ BOOL LLSelectMgr::selectGetModify() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsModify() { - for( LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode() ) + for( LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if( !node->mValid ) { @@ -2735,7 +2407,7 @@ BOOL LLSelectMgr::selectGetRootsModify() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsTransfer() { - for(LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode()) + for(LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode()) { if(!node->mValid) { @@ -2756,7 +2428,7 @@ BOOL LLSelectMgr::selectGetRootsTransfer() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetRootsCopy() { - for(LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode()) + for(LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode()) { if(!node->mValid) { @@ -2777,8 +2449,8 @@ BOOL LLSelectMgr::selectGetRootsCopy() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name) { - LLSelectNode* node = getFirstRootNode(); - if(!node) node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); + if(!node) node = mSelectedObjects->getFirstNode(); if(!node) return FALSE; if(!node->mValid) return FALSE; LLViewerObject* obj = node->getObject(); @@ -2788,7 +2460,7 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name) id = node->mPermissions->getCreator(); BOOL identical = TRUE; - for ( node = getNextRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -2805,8 +2477,8 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name) if (identical) { - char firstname[DB_FIRST_NAME_BUF_SIZE]; - char lastname[DB_LAST_NAME_BUF_SIZE]; + char firstname[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char lastname[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ gCacheName->getName(id, firstname, lastname); name.assign( firstname ); name.append( " " ); @@ -2827,8 +2499,8 @@ BOOL LLSelectMgr::selectGetCreator(LLUUID& id, LLString& name) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name) { - LLSelectNode* node = getFirstRootNode(); - if(!node) node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); + if(!node) node = mSelectedObjects->getFirstNode(); if(!node) return FALSE; if(!node->mValid) return FALSE; LLViewerObject* obj = node->getObject(); @@ -2840,7 +2512,7 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name) node->mPermissions->getOwnership(id, group_owner); BOOL identical = TRUE; - for ( node = getNextRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -2868,8 +2540,8 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name) } else if(!public_owner) { - char firstname[DB_FIRST_NAME_BUF_SIZE]; - char lastname[DB_LAST_NAME_BUF_SIZE]; + char firstname[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char lastname[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ gCacheName->getName(id, firstname, lastname); name.assign( firstname ); name.append( " " ); @@ -2895,8 +2567,8 @@ BOOL LLSelectMgr::selectGetOwner(LLUUID& id, LLString& name) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name) { - LLSelectNode* node = getFirstRootNode(); - if(!node) node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); + if(!node) node = mSelectedObjects->getFirstNode(); if(!node) return FALSE; if(!node->mValid) return FALSE; LLViewerObject* obj = node->getObject(); @@ -2906,7 +2578,7 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name) id = node->mPermissions->getLastOwner(); BOOL identical = TRUE; - for ( node = getNextRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -2927,8 +2599,8 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name) { if(!public_owner) { - char firstname[DB_FIRST_NAME_BUF_SIZE]; - char lastname[DB_LAST_NAME_BUF_SIZE]; + char firstname[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char lastname[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ gCacheName->getName(id, firstname, lastname); name.assign( firstname ); name.append( " " ); @@ -2954,8 +2626,8 @@ BOOL LLSelectMgr::selectGetLastOwner(LLUUID& id, LLString& name) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetGroup(LLUUID& id) { - LLSelectNode* node = getFirstRootNode(); - if(!node) node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); + if(!node) node = mSelectedObjects->getFirstNode(); if(!node) return FALSE; if(!node->mValid) return FALSE; LLViewerObject* obj = node->getObject(); @@ -2965,7 +2637,7 @@ BOOL LLSelectMgr::selectGetGroup(LLUUID& id) id = node->mPermissions->getGroup(); BOOL identical = TRUE; - for ( node = getNextRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -2990,8 +2662,8 @@ BOOL LLSelectMgr::selectGetGroup(LLUUID& id) //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectIsGroupOwned() { - LLSelectNode* node = getFirstRootNode(); - if(!node) node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); + if(!node) node = mSelectedObjects->getFirstNode(); if(!node) return FALSE; if(!node->mValid) return FALSE; LLViewerObject* obj = node->getObject(); @@ -3002,7 +2674,7 @@ BOOL LLSelectMgr::selectIsGroupOwned() if(is_group_owned) { - for ( node = getNextRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getNextRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -3031,7 +2703,7 @@ BOOL LLSelectMgr::selectIsGroupOwned() //----------------------------------------------------------------------------- BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) { - LLSelectNode* node = getFirstRootNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); if (!node) return FALSE; if (!node->mValid) return FALSE; @@ -3040,7 +2712,7 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) U32 mask_or = 0x00000000; BOOL all_valid = TRUE; - for ( node = getFirstRootNode(); node; node = getNextRootNode() ) + for ( node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (!node->mValid) { @@ -3094,17 +2766,17 @@ BOOL LLSelectMgr::selectGetPerm(U8 which_perm, U32* mask_on, U32* mask_off) BOOL LLSelectMgr::selectGetOwnershipCost(S32* out_cost) { - return mSelectedObjects.getOwnershipCost(*out_cost); + return mSelectedObjects->getOwnershipCost(*out_cost); } BOOL LLSelectMgr::selectGetPermissions(LLPermissions& perm) { - LLSelectNode* node = getFirstRootNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); if (!node) return FALSE; if (!node->mValid) return FALSE; BOOL valid = TRUE; perm = *(node->mPermissions); - for(node = getNextRootNode(); node != NULL; node = getNextRootNode()) + for(node = mSelectedObjects->getNextRootNode(); node != NULL; node = mSelectedObjects->getNextRootNode()) { if(!node->mValid) { @@ -3124,9 +2796,9 @@ void LLSelectMgr::selectDelete() BOOL locked_but_deleteable_object = FALSE; BOOL no_copy_but_deleteable_object = FALSE; BOOL all_owned_by_you = TRUE; - for(LLViewerObject* obj = getFirstObject(); + for(LLViewerObject* obj = mSelectedObjects->getFirstObject(); obj != NULL; - obj = getNextObject()) + obj = mSelectedObjects->getNextObject()) { if( obj->isAttachment() ) { @@ -3156,6 +2828,8 @@ void LLSelectMgr::selectDelete() return; } + LLObjectSelectionHandle* selection_handlep = new LLObjectSelectionHandle(getSelection()); + if(locked_but_deleteable_object || no_copy_but_deleteable_object || !all_owned_by_you) @@ -3172,49 +2846,49 @@ void LLSelectMgr::selectDelete() //Locked only gViewerWindow->alertXml( "ConfirmObjectDeleteLock", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) { //No Copy only gViewerWindow->alertXml( "ConfirmObjectDeleteNoCopy", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else if(!locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) { //not owned only gViewerWindow->alertXml( "ConfirmObjectDeleteNoOwn", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else if(locked_but_deleteable_object && no_copy_but_deleteable_object && all_owned_by_you) { //locked and no copy gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoCopy", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else if(locked_but_deleteable_object && !no_copy_but_deleteable_object && !all_owned_by_you) { //locked and not owned gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoOwn", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else if(!locked_but_deleteable_object && no_copy_but_deleteable_object && !all_owned_by_you) { //no copy and not owned gViewerWindow->alertXml( "ConfirmObjectDeleteNoCopyNoOwn", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } else { //locked, no copy and not owned gViewerWindow->alertXml( "ConfirmObjectDeleteLockNoCopyNoOwn", &LLSelectMgr::confirmDelete, - this); + selection_handlep); } @@ -3222,15 +2896,22 @@ void LLSelectMgr::selectDelete() } else { - confirmDelete(0, (void*)this); + confirmDelete(0, (void*)selection_handlep); } } // static void LLSelectMgr::confirmDelete(S32 option, void* data) { - LLSelectMgr* self = (LLSelectMgr*)data; - if(!self) return; + LLObjectSelectionHandle handle = *(LLObjectSelectionHandle*)data; + delete (LLObjectSelectionHandle*)data; + + if (!handle->getObjectCount()) + { + llwarns << "Nothing to delete!" << llendl; + return; + } + switch(option) { case 0: @@ -3239,19 +2920,19 @@ void LLSelectMgr::confirmDelete(S32 option, void* data) LLUUID trash_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); // attempt to derez into the trash. LLDeRezInfo* info = new LLDeRezInfo(DRD_TRASH, trash_id); - self->sendListToRegions("DeRezObject", + gSelectMgr->sendListToRegions("DeRezObject", packDeRezHeader, packObjectLocalID, (void*)info, SEND_ONLY_ROOTS); // VEFFECT: Delete Object - one effect for all deletes - if (self->mSelectType != SELECT_TYPE_HUD) + if (gSelectMgr->mSelectedObjects->mSelectType != SELECT_TYPE_HUD) { LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_POINT, TRUE); - effectp->setPositionGlobal( self->getSelectionCenterGlobal() ); + effectp->setPositionGlobal( gSelectMgr->getSelectionCenterGlobal() ); effectp->setColor(LLColor4U(gAgent.getEffectColor())); F32 duration = 0.5f; - duration += self->getObjectCount() / 64.f; + duration += gSelectMgr->mSelectedObjects->getObjectCount() / 64.f; effectp->setDuration(duration); } @@ -3259,7 +2940,7 @@ void LLSelectMgr::confirmDelete(S32 option, void* data) // Keep track of how many objects have been deleted. F64 obj_delete_count = gViewerStats->getStat(LLViewerStats::ST_OBJECT_DELETE_COUNT); - obj_delete_count += self->getObjectCount(); + obj_delete_count += gSelectMgr->mSelectedObjects->getObjectCount(); gViewerStats->setStat(LLViewerStats::ST_OBJECT_DELETE_COUNT, obj_delete_count ); } break; @@ -3289,7 +2970,7 @@ BOOL LLSelectMgr::selectIsForSale(S32& price) price = 0; LLSelectNode *node; - for (node = getFirstRootNode(); node; node = getNextRootNode() ) + for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode() ) { if (node->mSaleInfo.isForSale()) { @@ -3306,12 +2987,12 @@ BOOL LLSelectMgr::selectIsForSale(S32& price) // accumulated sale info. BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& sale_info) { - LLSelectNode* node = getFirstRootNode(); + LLSelectNode* node = mSelectedObjects->getFirstRootNode(); if (!node) return FALSE; if (!node->mValid) return FALSE; BOOL valid = TRUE; sale_info = node->mSaleInfo; - for(node = getNextRootNode(); node != NULL; node = getNextRootNode()) + for(node = mSelectedObjects->getNextRootNode(); node != NULL; node = mSelectedObjects->getNextRootNode()) { if(!node->mValid) { @@ -3325,12 +3006,12 @@ BOOL LLSelectMgr::selectGetSaleInfo(LLSaleInfo& sale_info) BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& ag_perm) { - LLSelectNode* node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstNode(); if (!node) return FALSE; if (!node->mValid) return FALSE; BOOL valid = TRUE; ag_perm = node->mAggregatePerm; - for(node = getNextNode(); node != NULL; node = getNextNode()) + for(node = mSelectedObjects->getNextNode(); node != NULL; node = mSelectedObjects->getNextNode()) { if(!node->mValid) { @@ -3344,12 +3025,12 @@ BOOL LLSelectMgr::selectGetAggregatePermissions(LLAggregatePermissions& ag_perm) BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm) { - LLSelectNode* node = getFirstNode(); + LLSelectNode* node = mSelectedObjects->getFirstNode(); if (!node) return FALSE; if (!node->mValid) return FALSE; BOOL valid = TRUE; ag_perm = node->getObject()->permYouOwner() ? node->mAggregateTexturePermOwner : node->mAggregateTexturePerm; - for(node = getNextNode(); node != NULL; node = getNextNode()) + for(node = mSelectedObjects->getNextNode(); node != NULL; node = mSelectedObjects->getNextNode()) { if(!node->mValid) { @@ -3362,12 +3043,6 @@ BOOL LLSelectMgr::selectGetAggregateTexturePermissions(LLAggregatePermissions& a } -// returns TRUE is any node is currenly worn as an attachment -BOOL LLSelectMgr::selectionIsAttachment() -{ - return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); -} - //-------------------------------------------------------------------- // Duplicate objects //-------------------------------------------------------------------- @@ -3383,7 +3058,7 @@ struct LLDuplicateData void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) { - if (selectionIsAttachment()) + if (mSelectedObjects->isAttachment()) { //RN: do not duplicate attachments make_ui_sound("UISndInvalidOp"); @@ -3403,7 +3078,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) } else { - for (LLSelectNode* node = getFirstRootNode(); node; node = getNextRootNode()) + for (LLSelectNode* node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode()) { node->mDuplicated = TRUE; node->mDuplicatePos = node->getObject()->getPositionGlobal(); @@ -3414,7 +3089,7 @@ void LLSelectMgr::selectDuplicate(const LLVector3& offset, BOOL select_copy) void LLSelectMgr::repeatDuplicate() { - if (selectionIsAttachment()) + if (mSelectedObjects->isAttachment()) { //RN: do not duplicate attachments make_ui_sound("UISndInvalidOp"); @@ -3424,7 +3099,7 @@ void LLSelectMgr::repeatDuplicate() LLSelectNode* node; LLDynamicArray non_duplicated_objects; - for (node = getFirstRootNode(); node; node = getNextRootNode()) + for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode()) { if (!node->mDuplicated) { @@ -3447,7 +3122,7 @@ void LLSelectMgr::repeatDuplicate() sendListToRegions("ObjectDuplicate", packDuplicateHeader, packDuplicate, &data, SEND_ONLY_ROOTS); // move current selection based on delta from duplication position and update duplication position - for (node = getFirstRootNode(); node; node = getNextRootNode()) + for (node = mSelectedObjects->getFirstRootNode(); node; node = mSelectedObjects->getNextRootNode()) { if (node->mDuplicated) { @@ -3502,7 +3177,7 @@ void LLSelectMgr::selectDuplicateOnRay(const LLVector3 &ray_start_region, BOOL copy_rotates, BOOL select_copy) { - if (selectionIsAttachment()) + if (mSelectedObjects->isAttachment()) { // do not duplicate attachments make_ui_sound("UISndInvalidOp"); @@ -3714,7 +3389,7 @@ struct LLPermData }; // TODO: Make this able to fail elegantly. -void LLSelectMgr::setObjectPermissions(U8 field, +void LLSelectMgr::selectionSetObjectPermissions(U8 field, BOOL set, U32 mask, BOOL override) @@ -3751,7 +3426,7 @@ void LLSelectMgr::sendSelect() void LLSelectMgr::deselectAll() { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -3772,42 +3447,29 @@ void LLSelectMgr::deselectAll() updateSelectionCenter(); } -void LLSelectMgr::deselectTransient() +void LLSelectMgr::deselectUnused() { - std::set objects_to_deselect; - LLSelectNode *nodep; - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode()) - { - if (nodep->isTransient()) - { - objects_to_deselect.insert(nodep->getObject()); - } - } - - std::set::iterator iter; - for (iter = objects_to_deselect.begin(); - iter != objects_to_deselect.end(); - ++iter) + // no more outstanding references to this selection + if (mSelectedObjects->getNumRefs() == 1) { - deselectObjectOnly(*iter); + deselectAll(); } - - gHUDManager->clearJoints(); - updateSelectionCenter(); } void LLSelectMgr::convertTransient() { - LLSelectNode *nodep; - for (nodep = mSelectedObjects.getFirstNode(); nodep; nodep = mSelectedObjects.getNextNode()) + // use STL-style iteration to avoid recursive iteration problems + LLObjectSelection::iterator node_it; + for (node_it = mSelectedObjects->begin(); node_it != mSelectedObjects->end(); ++node_it) { + LLSelectNode *nodep = *node_it; nodep->setTransient(FALSE); } } void LLSelectMgr::deselectAllIfTooFar() { - if (isEmpty() || mSelectType == SELECT_TYPE_HUD) + if (mSelectedObjects->isEmpty() || mSelectedObjects->mSelectType == SELECT_TYPE_HUD) { return; } @@ -3844,10 +3506,10 @@ void LLSelectMgr::deselectAllIfTooFar() } -void LLSelectMgr::setObjectName(const LLString& name) +void LLSelectMgr::selectionSetObjectName(const LLString& name) { // we only work correctly if 1 object is selected. - if(getRootObjectCount() == 1) + if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectName", packAgentAndSessionID, @@ -3855,7 +3517,7 @@ void LLSelectMgr::setObjectName(const LLString& name) (void*)name.c_str(), SEND_ONLY_ROOTS); } - else if(getObjectCount() == 1) + else if(mSelectedObjects->getObjectCount() == 1) { sendListToRegions("ObjectName", packAgentAndSessionID, @@ -3865,10 +3527,10 @@ void LLSelectMgr::setObjectName(const LLString& name) } } -void LLSelectMgr::setObjectDescription(const LLString& desc) +void LLSelectMgr::selectionSetObjectDescription(const LLString& desc) { // we only work correctly if 1 object is selected. - if(getRootObjectCount() == 1) + if(mSelectedObjects->getRootObjectCount() == 1) { sendListToRegions("ObjectDescription", packAgentAndSessionID, @@ -3876,7 +3538,7 @@ void LLSelectMgr::setObjectDescription(const LLString& desc) (void*)desc.c_str(), SEND_ONLY_ROOTS); } - else if(getObjectCount() == 1) + else if(mSelectedObjects->getObjectCount() == 1) { sendListToRegions("ObjectDescription", packAgentAndSessionID, @@ -3886,11 +3548,11 @@ void LLSelectMgr::setObjectDescription(const LLString& desc) } } -void LLSelectMgr::setObjectCategory(const LLCategory& category) +void LLSelectMgr::selectionSetObjectCategory(const LLCategory& category) { // for now, we only want to be able to set one root category at // a time. - if(getRootObjectCount() != 1) return; + if(mSelectedObjects->getRootObjectCount() != 1) return; sendListToRegions("ObjectCategory", packAgentAndSessionID, packObjectCategory, @@ -3898,10 +3560,10 @@ void LLSelectMgr::setObjectCategory(const LLCategory& category) SEND_ONLY_ROOTS); } -void LLSelectMgr::setObjectSaleInfo(const LLSaleInfo& sale_info) +void LLSelectMgr::selectionSetObjectSaleInfo(const LLSaleInfo& sale_info) { // Only one sale info at a time for now - if(getRootObjectCount() != 1) return; + if(mSelectedObjects->getRootObjectCount() != 1) return; sendListToRegions("ObjectSaleInfo", packAgentAndSessionID, packObjectSaleInfo, @@ -3915,16 +3577,17 @@ void LLSelectMgr::setObjectSaleInfo(const LLSaleInfo& sale_info) void LLSelectMgr::sendAttach(U8 attachment_point) { - LLViewerObject* attach_object = mSelectedObjects.getFirstRootObject(); + LLViewerObject* attach_object = mSelectedObjects->getFirstRootObject(); - if (!attach_object || !gAgent.getAvatarObject() || mSelectType != SELECT_TYPE_WORLD) + if (!attach_object || !gAgent.getAvatarObject() || mSelectedObjects->mSelectType != SELECT_TYPE_WORLD) { return; } BOOL build_mode = gToolMgr->inEdit(); // Special case: Attach to default location for this object. - if (0 == attachment_point) + if (0 == attachment_point || + gAgent.getAvatarObject()->mAttachmentPoints.getIfThere(attachment_point)) { sendListToRegions( "ObjectAttach", @@ -3937,53 +3600,11 @@ void LLSelectMgr::sendAttach(U8 attachment_point) deselectAll(); } } - else - { - LLViewerJointAttachment* attachment = gAgent.getAvatarObject()->mAttachmentPoints.getIfThere(attachment_point); - if (attachment) - { - LLQuaternion object_world_rot = attach_object->getRenderRotation(); - LLQuaternion attachment_pt__world_rot = attachment->getWorldRotation(); - LLQuaternion local_rot = object_world_rot * ~attachment_pt__world_rot; - - F32 x,y,z; - local_rot.getEulerAngles(&x, &y, &z); - // snap to nearest 90 degree rotation - // make sure all euler angles are positive - if (x < F_PI_BY_TWO) x += F_TWO_PI; - if (y < F_PI_BY_TWO) y += F_TWO_PI; - if (z < F_PI_BY_TWO) z += F_TWO_PI; - - // add 45 degrees so that rounding down becomes rounding off - x += F_PI_BY_TWO / 2.f; - y += F_PI_BY_TWO / 2.f; - z += F_PI_BY_TWO / 2.f; - // round down to nearest multiple of 90 degrees - x -= fmodf(x, F_PI_BY_TWO); - y -= fmodf(y, F_PI_BY_TWO); - z -= fmodf(z, F_PI_BY_TWO); - - // pass the requested rotation on to the simulator - local_rot.setQuat(x, y, z); - attach_object->setRotation(local_rot); - - sendListToRegions( - "ObjectAttach", - packAgentIDAndSessionAndAttachment, - packObjectIDAndRotation, - &attachment_point, - SEND_ONLY_ROOTS ); - if (!build_mode) - { - deselectAll(); - } - } - } } void LLSelectMgr::sendDetach() { - if (!mSelectedObjects.getNumNodes() || mSelectType == SELECT_TYPE_WORLD) + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) { return; } @@ -3999,7 +3620,7 @@ void LLSelectMgr::sendDetach() void LLSelectMgr::sendDropAttachment() { - if (!mSelectedObjects.getNumNodes() || mSelectType == SELECT_TYPE_WORLD) + if (!mSelectedObjects->getNumNodes() || mSelectedObjects->mSelectType == SELECT_TYPE_WORLD) { return; } @@ -4018,7 +3639,7 @@ void LLSelectMgr::sendDropAttachment() void LLSelectMgr::sendLink() { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -4033,7 +3654,7 @@ void LLSelectMgr::sendLink() void LLSelectMgr::sendDelink() { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -4055,7 +3676,7 @@ void LLSelectMgr::sendDelink() void LLSelectMgr::sendHinge(U8 type) { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -4071,7 +3692,7 @@ void LLSelectMgr::sendHinge(U8 type) void LLSelectMgr::sendDehinge() { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -4086,7 +3707,7 @@ void LLSelectMgr::sendDehinge() void LLSelectMgr::sendSelect() { - if (!mSelectedObjects.getNumNodes()) + if (!mSelectedObjects->getNumNodes()) { return; } @@ -4116,7 +3737,7 @@ void LLSelectMgr::selectionDump() { LLViewerObject *object; - for (object = getFirstObject(); object; object = getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { object->dump(); } @@ -4125,7 +3746,7 @@ void LLSelectMgr::selectionDump() void LLSelectMgr::saveSelectedObjectColors() { LLSelectNode* selectNode; - for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() ) + for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() ) { selectNode->saveColors(); } @@ -4136,7 +3757,7 @@ void LLSelectMgr::saveSelectedObjectTextures() LLSelectNode* selectNode; // invalidate current selection so we update saved textures - for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() ) + for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() ) { selectNode->mValid = FALSE; } @@ -4152,13 +3773,13 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) { LLSelectNode* selectNode; - if (isEmpty()) + if (mSelectedObjects->isEmpty()) { // nothing selected, so nothing to save return; } - for (selectNode = getFirstNode(); selectNode; selectNode = getNextNode() ) + for (selectNode = mSelectedObjects->getFirstNode(); selectNode; selectNode = mSelectedObjects->getNextNode() ) { LLViewerObject* object; object = selectNode->getObject(); @@ -4168,7 +3789,10 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) if (object->isRootEdit()) { LLXform* parent_xform = object->mDrawable->getXform()->getParent(); - selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); + if (parent_xform) + { + selectNode->mSavedPositionGlobal = gAgent.getPosGlobalFromAgent((object->getPosition() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition()); + } } else { @@ -4189,42 +3813,6 @@ void LLSelectMgr::saveSelectedObjectTransform(EActionType action_type) selectNode->mSavedScale = object->getScale(); selectNode->saveTextureScaleRatios(); - if (object->isAttachment() && - action_type != SELECT_ACTION_TYPE_PICK) - { - LLSelectAction* selectAction = new LLSelectAction(); - selectAction->mActionType = action_type; - selectAction->mPosition = object->getPosition(); - selectAction->mRotation = object->getRotation(); - selectAction->mScale = object->getScale(); - selectAction->mObjectID = object->getID(); - selectAction->mIndividualSelection = selectNode->mIndividualSelection; - - mUndoQueue.push_back(selectAction); - - while ((mUndoQueue.size() > (U32)MAX_ACTION_QUEUE_SIZE)) - { - LLSelectAction* action = mUndoQueue.front(); - mUndoQueue.pop_front(); - delete action; - } - - // remove this object from the redo queue - std::deque::iterator it; - for (it = mRedoQueue.begin(); it != mRedoQueue.end();) - { - if ((*it)->mObjectID == object->getID()) - { - LLSelectAction* actionp = *it; - it = mRedoQueue.erase(it); - delete actionp; - } - else - { - ++it; - } - } - } } mSavedSelectionBBox = getBBoxOfSelection(); } @@ -4233,7 +3821,7 @@ void LLSelectMgr::selectionUpdatePhysics(BOOL physics) { LLViewerObject *object; - for (object = getFirstObject(); object; object = getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( !object->permModify() // preemptive permissions check || !(object->isRoot() // don't send for child objects @@ -4249,7 +3837,7 @@ void LLSelectMgr::selectionUpdateTemporary(BOOL is_temporary) { LLViewerObject *object; - for (object = getFirstObject(); object; object = getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( !object->permModify() // preemptive permissions check || !(object->isRoot() // don't send for child objects @@ -4265,7 +3853,7 @@ void LLSelectMgr::selectionUpdatePhantom(BOOL is_phantom) { LLViewerObject *object; - for (object = getFirstObject(); object; object = getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( !object->permModify() // preemptive permissions check || !(object->isRoot() // don't send for child objects @@ -4281,7 +3869,7 @@ void LLSelectMgr::selectionUpdateCastShadows(BOOL cast_shadows) { LLViewerObject *object; - for (object = getFirstObject(); object; object = getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { if ( !object->permModify() // preemptive permissions check || object->isJointChild()) @@ -4505,70 +4093,81 @@ void LLSelectMgr::sendListToRegions(const LLString& message_name, S32 packets_sent = 0; S32 objects_in_this_packet = 0; + + //clear update override data (allow next update through) + for (node = mSelectedObjects->getFirstNode(); + node; + node = mSelectedObjects->getNextNode()) + { + node->mLastPositionLocal.setVec(0,0,0); + node->mLastRotation = LLQuaternion(); + node->mLastScale.setVec(0,0,0); + } + std::queue nodes_to_send; switch(send_type) { case SEND_ONLY_ROOTS: - node = mSelectedObjects.getFirstRootNode(); + node = mSelectedObjects->getFirstRootNode(); while(node) { nodes_to_send.push(node); - node = mSelectedObjects.getNextRootNode(); + node = mSelectedObjects->getNextRootNode(); } break; case SEND_INDIVIDUALS: - node = mSelectedObjects.getFirstNode(); + node = mSelectedObjects->getFirstNode(); while(node) { nodes_to_send.push(node); - node = mSelectedObjects.getNextNode(); + node = mSelectedObjects->getNextNode(); } break; case SEND_ROOTS_FIRST: // first roots... - node = mSelectedObjects.getFirstNode(); + node = mSelectedObjects->getFirstNode(); while(node) { if (node->getObject()->isRootEdit()) { nodes_to_send.push(node); } - node = mSelectedObjects.getNextNode(); + node = mSelectedObjects->getNextNode(); } // then children... - node = mSelectedObjects.getFirstNode(); + node = mSelectedObjects->getFirstNode(); while(node) { if (!node->getObject()->isRootEdit()) { nodes_to_send.push(node); } - node = mSelectedObjects.getNextNode(); + node = mSelectedObjects->getNextNode(); } break; case SEND_CHILDREN_FIRST: // first children... - node = mSelectedObjects.getFirstNode(); + node = mSelectedObjects->getFirstNode(); while(node) { if (!node->getObject()->isRootEdit()) { nodes_to_send.push(node); } - node = mSelectedObjects.getNextNode(); + node = mSelectedObjects->getNextNode(); } // ...then roots - node = mSelectedObjects.getFirstNode(); + node = mSelectedObjects->getFirstNode(); while(node) { if (node->getObject()->isRootEdit()) { nodes_to_send.push(node); } - node = mSelectedObjects.getNextNode(); + node = mSelectedObjects->getNextNode(); } break; @@ -4720,14 +4319,14 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id, i); - char name[DB_INV_ITEM_NAME_BUF_SIZE]; + char name[DB_INV_ITEM_NAME_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name, i); - char desc[DB_INV_ITEM_DESC_BUF_SIZE]; + char desc[DB_INV_ITEM_DESC_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc, i); - char touch_name[DB_INV_ITEM_NAME_BUF_SIZE]; + char touch_name[DB_INV_ITEM_NAME_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_TouchName, DB_INV_ITEM_NAME_BUF_SIZE, touch_name, i); - char sit_name[DB_INV_ITEM_DESC_BUF_SIZE]; + char sit_name[DB_INV_ITEM_DESC_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_SitName, DB_INV_ITEM_DESC_BUF_SIZE, sit_name, i); //unpack TE IDs @@ -4741,7 +4340,7 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data for (S32 buf_offset = 0; buf_offset < size; buf_offset += UUID_BYTES) { LLUUID id; - memcpy(id.mData, packed_buffer + buf_offset, UUID_BYTES); + memcpy(id.mData, packed_buffer + buf_offset, UUID_BYTES); /* Flawfinder: ignore */ texture_ids.push_back(id); } } @@ -4750,9 +4349,9 @@ void LLSelectMgr::processObjectProperties(LLMessageSystem* msg, void** user_data // Iterate through nodes at end, since it can be on both the regular AND hover list BOOL found = FALSE; LLSelectNode* node; - for (node = gSelectMgr->mSelectedObjects.getFirstNode(); + for (node = gSelectMgr->mSelectedObjects->getFirstNode(); node; - node = gSelectMgr->mSelectedObjects.getNextNode()) + node = gSelectMgr->mSelectedObjects->getNextNode()) { if (node->getObject()->mID == id) { @@ -4874,10 +4473,10 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use msg->getUUIDFast(_PREHASH_ObjectData, _PREHASH_LastOwnerID, last_owner_id ); // unpack name & desc - char name[DB_INV_ITEM_NAME_BUF_SIZE]; + char name[DB_INV_ITEM_NAME_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Name, DB_INV_ITEM_NAME_BUF_SIZE, name); - char desc[DB_INV_ITEM_DESC_BUF_SIZE]; + char desc[DB_INV_ITEM_DESC_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_ObjectData, _PREHASH_Description, DB_INV_ITEM_DESC_BUF_SIZE, desc); // the reporter widget askes the server for info about picked objects @@ -4887,8 +4486,8 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use LLFloaterReporter *reporterp = LLFloaterReporter::getReporter(report_type); if (reporterp) { - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_LAST_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char last_name[DB_LAST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ gCacheName->getName(owner_id, first_name, last_name); LLString fullname(first_name); fullname.append(" "); @@ -4900,9 +4499,9 @@ void LLSelectMgr::processObjectPropertiesFamily(LLMessageSystem* msg, void** use // Now look through all of the hovered nodes BOOL found = FALSE; LLSelectNode* node; - for (node = gSelectMgr->mHoverObjects.getFirstNode(); + for (node = gSelectMgr->mHoverObjects->getFirstNode(); node; - node = gSelectMgr->mHoverObjects.getNextNode()) + node = gSelectMgr->mHoverObjects->getNextNode()) { if (node->getObject()->mID == id) { @@ -4985,7 +4584,7 @@ void LLSelectMgr::updateSilhouettes() if((cameraPos - mLastCameraPos).magVecSquared() > SILHOUETTE_UPDATE_THRESHOLD_SQUARED * currentCameraZoom * currentCameraZoom) { - for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() ) + for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() ) { if (node->getObject()) { @@ -4998,7 +4597,7 @@ void LLSelectMgr::updateSilhouettes() LLDynamicArray changed_objects; - if (mSelectedObjects.getNumNodes()) + if (mSelectedObjects->getNumNodes()) { //gGLSPipelineSelection.set(); @@ -5007,7 +4606,7 @@ void LLSelectMgr::updateSilhouettes() for (S32 pass = 0; pass < 2; pass++) { - for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() ) + for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() ) { LLViewerObject* objectp = node->getObject(); @@ -5023,7 +4622,7 @@ void LLSelectMgr::updateSilhouettes() || objectp->isChanged(LLXform::SILHOUETTE) || (objectp->getParent() && objectp->getParent()->isChanged(LLXform::SILHOUETTE))) { - if (num_sils_genned++ < MAX_SILS_PER_FRAME && objectp->mDrawable->isVisible()) + if (num_sils_genned++ < MAX_SILS_PER_FRAME)// && objectp->mDrawable->isVisible()) { generateSilhouette(node, gCamera->getOrigin()); changed_objects.put(objectp); @@ -5077,7 +4676,7 @@ void LLSelectMgr::updateSilhouettes() // remove highlight nodes not in roots list LLDynamicArray remove_these_nodes; LLDynamicArray remove_these_roots; - for (LLSelectNode* nodep = mHighlightedObjects.getFirstNode(); nodep; nodep = mHighlightedObjects.getNextNode()) + for (LLSelectNode* nodep = mHighlightedObjects->getFirstNode(); nodep; nodep = mHighlightedObjects->getNextNode()) { LLViewerObject* objectp = nodep->getObject(); if (objectp->isRoot() || !select_linked_set) @@ -5106,7 +4705,7 @@ void LLSelectMgr::updateSilhouettes() S32 i; for (i = 0; i < remove_these_nodes.count(); i++) { - mHighlightedObjects.removeNode(remove_these_nodes[i]); + mHighlightedObjects->removeNode(remove_these_nodes[i]); } // remove all root objects already being highlighted @@ -5128,7 +4727,7 @@ void LLSelectMgr::updateSilhouettes() continue; } - mHighlightedObjects.addNode(rect_select_node); + mHighlightedObjects->addNode(rect_select_node); if (!select_linked_set) { @@ -5147,7 +4746,7 @@ void LLSelectMgr::updateSilhouettes() rect_select_node = new LLSelectNode(objectp->mChildList[i], TRUE); rect_select_node->selectAllTEs(TRUE); - mHighlightedObjects.addNode(rect_select_node); + mHighlightedObjects->addNode(rect_select_node); } } } @@ -5158,7 +4757,7 @@ void LLSelectMgr::updateSilhouettes() //BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); for (S32 pass = 0; pass < 2; pass++) { - for (node = mHighlightedObjects.getFirstNode(); node; node = mHighlightedObjects.getNextNode() ) + for (node = mHighlightedObjects->getFirstNode(); node; node = mHighlightedObjects->getNextNode() ) { LLViewerObject* objectp = node->getObject(); @@ -5207,7 +4806,7 @@ void LLSelectMgr::updateSilhouettes() } else { - mHighlightedObjects.deleteAllNodes(); + mHighlightedObjects->deleteAllNodes(); } for (S32 i = 0; i < changed_objects.count(); i++) @@ -5254,13 +4853,12 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (depth *0.5f), 0.f, 0.f); glScalef(cur_zoom, cur_zoom, cur_zoom); } - if (mSelectedObjects.getNumNodes()) + if (mSelectedObjects->getNumNodes()) { - glPushAttrib(GL_FOG_BIT); LLUUID inspect_item_id = LLFloaterInspect::getSelectedUUID(); for (S32 pass = 0; pass < 2; pass++) { - for (node = mSelectedObjects.getFirstNode(); node; node = mSelectedObjects.getNextNode() ) + for (node = mSelectedObjects->getFirstNode(); node; node = mSelectedObjects->getNextNode() ) { LLViewerObject* objectp = node->getObject(); if (objectp->isHUDAttachment() != for_hud) @@ -5288,16 +4886,15 @@ void LLSelectMgr::renderSilhouettes(BOOL for_hud) } } } - glPopAttrib(); } - if (mHighlightedObjects.getNumNodes()) + if (mHighlightedObjects->getNumNodes()) { // render silhouettes for highlighted objects BOOL subtracting_from_selection = (gKeyboard->currentMask(TRUE) == MASK_CONTROL); for (S32 pass = 0; pass < 2; pass++) { - for (node = mHighlightedObjects.getFirstNode(); node; node = mHighlightedObjects.getNextNode() ) + for (node = mHighlightedObjects->getFirstNode(); node; node = mHighlightedObjects->getNextNode() ) { LLViewerObject* objectp = node->getObject(); if (objectp->isHUDAttachment() != for_hud) @@ -5706,13 +5303,8 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) } BOOL is_hud_object = objectp->isHUDAttachment(); - - if (!drawable->isVisible() && !is_hud_object) - { - return; - } - - if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) + + if (mSilhouetteVertices.size() == 0 || mSilhouetteNormals.size() != mSilhouetteVertices.size()) { return; } @@ -5742,7 +5334,7 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) else { LLVector3 view_vector = gCamera->getOrigin() - objectp->getRenderPosition(); - silhouette_thickness = drawable->mDistanceWRTCamera * LLSelectMgr::sHighlightThickness * (gCamera->getView() / gCamera->getDefaultFOV()); + silhouette_thickness = view_vector.magVec() * LLSelectMgr::sHighlightThickness * (gCamera->getView() / gCamera->getDefaultFOV()); } F32 animationTime = (F32)LLFrameTimer::getElapsedSeconds(); @@ -5768,7 +5360,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) S32 i = 0; for (S32 seg_num = 0; seg_num < (S32)mSilhouetteSegments.size(); seg_num++) { -// S32 first_i = i; for(; i < mSilhouetteSegments[seg_num]; i++) { u_coord += u_divisor * LLSelectMgr::sHighlightUScale; @@ -5777,11 +5368,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) glTexCoord2f( u_coord, v_coord ); glVertex3fv( mSilhouetteVertices[i].mV ); } - - /*u_coord += u_divisor * LLSelectMgr::sHighlightUScale; - glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f); - glTexCoord2f( u_coord, v_coord ); - glVertex3fv( mSilhouetteVertices[first_i].mV );*/ } } glEnd(); @@ -5789,7 +5375,6 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color) } glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - //glAlphaFunc(GL_GREATER, LLSelectMgr::sHighlightAlphaTest); glBegin(GL_TRIANGLES); { S32 i = 0; @@ -5908,7 +5493,11 @@ void LLSelectMgr::updateSelectionCenter() const F32 MOVE_SELECTION_THRESHOLD = 1.f; // Movement threshold in meters for updating selection // center (tractor beam) - LLViewerObject* object = mSelectedObjects.getFirstObject(); + //override any object updates received + //for selected objects + gSelectMgr->overrideObjectUpdates(); + + LLViewerObject* object = mSelectedObjects->getFirstObject(); if (!object) { // nothing selected, probably grabbing @@ -5925,9 +5514,9 @@ void LLSelectMgr::updateSelectionCenter() } else { - mSelectType = getSelectTypeForObject(object); + mSelectedObjects->mSelectType = getSelectTypeForObject(object); - if (mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) + if (mSelectedObjects->mSelectType == SELECT_TYPE_ATTACHMENT && gAgent.getAvatarObject()) { mPauseRequest = gAgent.getAvatarObject()->requestPause(); } @@ -5936,7 +5525,7 @@ void LLSelectMgr::updateSelectionCenter() mPauseRequest = NULL; } - if (mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject()) + if (mSelectedObjects->mSelectType != SELECT_TYPE_HUD && gAgent.getAvatarObject()) { // reset hud ZOOM gAgent.getAvatarObject()->mHUDTargetZoom = 1.f; @@ -5952,11 +5541,11 @@ void LLSelectMgr::updateSelectionCenter() gHUDManager->clearJoints(); LLDynamicArray < LLViewerObject *> jointed_objects; - for (object = mSelectedObjects.getFirstObject(); object; object = mSelectedObjects.getNextObject() ) + for (object = mSelectedObjects->getFirstObject(); object; object = mSelectedObjects->getNextObject() ) { LLViewerObject *myAvatar = gAgent.getAvatarObject(); LLViewerObject *root = object->getRootEdit(); - if (mSelectType == SELECT_TYPE_WORLD && // not an attachment + if (mSelectedObjects->mSelectType == SELECT_TYPE_WORLD && // not an attachment !root->isChild(myAvatar) && // not the object you're sitting on !object->isAvatar()) // not another avatar { @@ -5981,9 +5570,9 @@ void LLSelectMgr::updateSelectionCenter() } } - if ( !(gAgentID == LLUUID::null) ) + if ( !(gAgentID == LLUUID::null) && gToolMgr) { - LLTool *tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + LLTool *tool = gToolMgr->getCurrentTool(); if (mShowSelection) { LLVector3d select_center_global; @@ -6010,7 +5599,7 @@ void LLSelectMgr::updateSelectionCenter() } // give up edit menu if no objects selected - if (gEditMenuHandler == this && getObjectCount() == 0) + if (gEditMenuHandler == this && mSelectedObjects->getObjectCount() == 0) { gEditMenuHandler = NULL; } @@ -6020,7 +5609,7 @@ void LLSelectMgr::updatePointAt() { if (mShowSelection) { - if (getObjectCount()) + if (mSelectedObjects->getObjectCount()) { LLVector3 select_offset; LLViewerObject *click_object = gObjectList.findObject(gLastHitObjectID); @@ -6036,8 +5625,8 @@ void LLSelectMgr::updatePointAt() else { // didn't click on an object this time, revert to pointing at center of first object - gAgent.setPointAt(POINTAT_TARGET_SELECT, getFirstObject()); - gAgent.setLookAt(LOOKAT_TARGET_SELECT, getFirstObject()); + gAgent.setPointAt(POINTAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); + gAgent.setLookAt(LOOKAT_TARGET_SELECT, mSelectedObjects->getFirstObject()); } } else @@ -6067,7 +5656,7 @@ LLBBox LLSelectMgr::getBBoxOfSelection() const //----------------------------------------------------------------------------- BOOL LLSelectMgr::canUndo() { - return getFirstEditableObject() != NULL; + return mSelectedObjects->getFirstEditableObject() != NULL; } //----------------------------------------------------------------------------- @@ -6085,7 +5674,7 @@ void LLSelectMgr::undo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canRedo() { - return getFirstEditableObject() != NULL; + return mSelectedObjects->getFirstEditableObject() != NULL; } //----------------------------------------------------------------------------- @@ -6103,7 +5692,7 @@ void LLSelectMgr::redo() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDoDelete() { - return getFirstDeleteableObject() != NULL; + return mSelectedObjects->getFirstDeleteableObject() != NULL; } //----------------------------------------------------------------------------- @@ -6119,7 +5708,7 @@ void LLSelectMgr::doDelete() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDeselect() { - return !isEmpty(); + return !mSelectedObjects->isEmpty(); } //----------------------------------------------------------------------------- @@ -6134,7 +5723,7 @@ void LLSelectMgr::deselect() //----------------------------------------------------------------------------- BOOL LLSelectMgr::canDuplicate() { - return getFirstCopyableObject() != NULL; + return mSelectedObjects->getFirstCopyableObject() != NULL; } //----------------------------------------------------------------------------- // duplicate() @@ -6144,125 +5733,6 @@ void LLSelectMgr::duplicate() LLVector3 offset(0.5f, 0.5f, 0.f); selectDuplicate(offset, TRUE); } -//----------------------------------------------------------------------------- -// undoRedo() -//----------------------------------------------------------------------------- -U32 LLSelectMgr::undoRedo(std::deque &queue_src, std::deque &queue_dst, const LLUUID &object_id) -{ - if (queue_src.size() == 0) - { - return 0; - } - - U32 update_type = 0; - std::deque temp_queue; - LLSelectAction* src_actionp = queue_src.back(); - - while (src_actionp->mObjectID != object_id) - { - temp_queue.push_back(src_actionp); - queue_src.pop_back(); - if (!queue_src.size()) - { - // put everything back - LLSelectAction* actionp; - while (temp_queue.size()) - { - actionp = temp_queue.back(); - temp_queue.pop_back(); - queue_src.push_back(actionp); - } - return 0; - } - src_actionp = queue_src.back(); - } - - if(src_actionp) - { - LLSelectAction* dst_actionp = new LLSelectAction(); - dst_actionp->mActionType = src_actionp->mActionType; - dst_actionp->mObjectID = src_actionp->mObjectID; - dst_actionp->mIndividualSelection = src_actionp->mIndividualSelection; - - LLViewerObject* object = gObjectList.findObject(src_actionp->mObjectID); - if (object && object->mDrawable.notNull()) - { - LLVector3 old_position_local = object->getPosition(); - - switch(src_actionp->mActionType) - { - case SELECT_ACTION_TYPE_MOVE: - dst_actionp->mPosition = object->mDrawable->getPosition(); - object->setPosition(src_actionp->mPosition, TRUE); - if (object->isRootEdit() && src_actionp->mIndividualSelection) - { - // counter-translate children - LLVector3 parent_offset = (src_actionp->mPosition - old_position_local) * ~object->getRotation(); - - // counter-translate child objects if we are moving the root as an individual - for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++) - { - LLViewerObject* childp = object->mChildList[child_num]; - childp->setPosition(childp->getPosition() - parent_offset); - } - } - update_type |= UPD_POSITION; - break; - case SELECT_ACTION_TYPE_ROTATE: - dst_actionp->mPosition = object->mDrawable->getPosition(); - dst_actionp->mRotation = object->mDrawable->getRotation(); - object->setRotation(src_actionp->mRotation, TRUE); - object->setPosition(src_actionp->mPosition, TRUE); - if (object->isRootEdit() && src_actionp->mIndividualSelection) - { - // counter-translate and rotate children - LLVector3 parent_offset = (src_actionp->mPosition - old_position_local) * ~object->getRotation(); - - for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++) - { - LLViewerObject* childp = object->mChildList[child_num]; - LLQuaternion delta_rot_inv = dst_actionp->mRotation * ~src_actionp->mRotation; - childp->setPosition((childp->getPosition() * delta_rot_inv) - parent_offset); - childp->setRotation(childp->getRotation() * delta_rot_inv ); - } - } - update_type |= UPD_ROTATION | UPD_POSITION; - break; - case SELECT_ACTION_TYPE_SCALE: - dst_actionp->mPosition = object->mDrawable->getPosition(); - dst_actionp->mScale = object->getScale(); - object->setScale(src_actionp->mScale, TRUE); - object->setPosition(src_actionp->mPosition, TRUE); - update_type |= UPD_SCALE | UPD_POSITION; - break; - default: - // do nothing - break; - } - } - queue_src.pop_back(); - delete src_actionp; - queue_dst.push_back(dst_actionp); - while (queue_dst.size() > (U32)MAX_ACTION_QUEUE_SIZE) - { - LLSelectAction* action = queue_dst.front(); - queue_dst.pop_front(); - delete action; - } - - } - - // put everything back - LLSelectAction* actionp; - while (temp_queue.size()) - { - actionp = temp_queue.back(); - temp_queue.pop_back(); - queue_src.push_back(actionp); - } - - return update_type; -} ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object) { @@ -6287,7 +5757,7 @@ ESelectType LLSelectMgr::getSelectTypeForObject(LLViewerObject* object) void LLSelectMgr::validateSelection() { LLViewerObject* objectp; - for (objectp = getFirstObject(); objectp; objectp = getNextObject()) + for (objectp = mSelectedObjects->getFirstObject(); objectp; objectp = mSelectedObjects->getNextObject()) { if (!canSelectObject(objectp)) { @@ -6323,64 +5793,71 @@ BOOL LLSelectMgr::canSelectObject(LLViewerObject* object) if (object->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) return FALSE; ESelectType selection_type = getSelectTypeForObject(object); - if (getObjectCount() > 0 && mSelectType != selection_type) return FALSE; + if (mSelectedObjects->getObjectCount() > 0 && mSelectedObjects->mSelectType != selection_type) return FALSE; return TRUE; } -LLSelectNodeList::LLSelectNodeList() : std::list() +LLObjectSelection::LLObjectSelection() : + std::list(), + LLRefCount(), + mCurrentNode(end()), + mCurrentTE(-1), + mSelectType(SELECT_TYPE_WORLD) { - mCurrentTE = -1; - mCurrentNode = end(); } -LLSelectNodeList::~LLSelectNodeList() +LLObjectSelection::~LLObjectSelection() { std::for_each(begin(), end(), DeletePointer()); } -void LLSelectNodeList::updateEffects() +void LLObjectSelection::updateEffects() { } -S32 LLSelectNodeList::getNumNodes() +S32 LLObjectSelection::getNumNodes() { return size(); } -void LLSelectNodeList::addNode(LLSelectNode *nodep) +void LLObjectSelection::addNode(LLSelectNode *nodep) { push_front(nodep); mSelectNodeMap[nodep->getObject()] = nodep; } -void LLSelectNodeList::addNodeAtEnd(LLSelectNode *nodep) +void LLObjectSelection::addNodeAtEnd(LLSelectNode *nodep) { push_back(nodep); mSelectNodeMap[nodep->getObject()] = nodep; } -void LLSelectNodeList::removeNode(LLSelectNode *nodep) +void LLObjectSelection::removeNode(LLSelectNode *nodep) { - std::list::iterator iter; - for (iter = begin(); iter != end(); ++iter) + std::list::iterator iter = begin(); + while(iter != end()) { if ((*iter) == nodep) { mSelectNodeMap.erase(nodep->getObject()); - erase(iter++); + iter = erase(iter); + } + else + { + ++iter; } } } -void LLSelectNodeList::deleteAllNodes() +void LLObjectSelection::deleteAllNodes() { std::for_each(begin(), end(), DeletePointer()); clear(); mSelectNodeMap.clear(); } -LLSelectNode* LLSelectNodeList::findNode(LLViewerObject* objectp) +LLSelectNode* LLObjectSelection::findNode(LLViewerObject* objectp) { std::map::iterator found_it = mSelectNodeMap.find(objectp); if (found_it != mSelectNodeMap.end()) @@ -6393,7 +5870,7 @@ LLSelectNode* LLSelectNodeList::findNode(LLViewerObject* objectp) //----------------------------------------------------------------------------- // getFirstNode() //----------------------------------------------------------------------------- -LLSelectNode *LLSelectNodeList::getFirstNode() +LLSelectNode *LLObjectSelection::getFirstNode() { mCurrentNode = begin();//getFirstData(); @@ -6414,7 +5891,7 @@ LLSelectNode *LLSelectNodeList::getFirstNode() //----------------------------------------------------------------------------- // getCurrentNode() //----------------------------------------------------------------------------- -LLSelectNode *LLSelectNodeList::getCurrentNode() +LLSelectNode *LLObjectSelection::getCurrentNode() { while (mCurrentNode != end() && !(*mCurrentNode)->getObject()) { @@ -6432,7 +5909,7 @@ LLSelectNode *LLSelectNodeList::getCurrentNode() //----------------------------------------------------------------------------- // getNextNode() //----------------------------------------------------------------------------- -LLSelectNode *LLSelectNodeList::getNextNode() +LLSelectNode *LLObjectSelection::getNextNode() { ++mCurrentNode; @@ -6454,7 +5931,7 @@ LLSelectNode *LLSelectNodeList::getNextNode() //----------------------------------------------------------------------------- // getFirstObject() //----------------------------------------------------------------------------- -LLViewerObject* LLSelectNodeList::getFirstObject() +LLViewerObject* LLObjectSelection::getFirstObject() { mCurrentNode = begin(); @@ -6476,7 +5953,7 @@ LLViewerObject* LLSelectNodeList::getFirstObject() //----------------------------------------------------------------------------- // getNextObject() //----------------------------------------------------------------------------- -LLViewerObject* LLSelectNodeList::getNextObject() +LLViewerObject* LLObjectSelection::getNextObject() { ++mCurrentNode;// = getNextData(); @@ -6499,7 +5976,7 @@ LLViewerObject* LLSelectNodeList::getNextObject() //----------------------------------------------------------------------------- // getPrimaryTE() //----------------------------------------------------------------------------- -void LLSelectNodeList::getPrimaryTE(LLViewerObject* *object, S32 *te) +void LLObjectSelection::getPrimaryTE(LLViewerObject* *object, S32 *te) { // initialize object and te *te = 0; @@ -6554,7 +6031,7 @@ void LLSelectNodeList::getPrimaryTE(LLViewerObject* *object, S32 *te) //----------------------------------------------------------------------------- // getFirstTE() //----------------------------------------------------------------------------- -void LLSelectNodeList::getFirstTE(LLViewerObject* *object, S32 *te) +void LLObjectSelection::getFirstTE(LLViewerObject* *object, S32 *te) { // start with first face mCurrentTE = 0; @@ -6608,7 +6085,7 @@ void LLSelectNodeList::getFirstTE(LLViewerObject* *object, S32 *te) //----------------------------------------------------------------------------- // getNextFace() //----------------------------------------------------------------------------- -void LLSelectNodeList::getNextTE(LLViewerObject* *object, S32 *te) +void LLObjectSelection::getNextTE(LLViewerObject* *object, S32 *te) { // try next face mCurrentTE++; @@ -6651,7 +6128,7 @@ void LLSelectNodeList::getNextTE(LLViewerObject* *object, S32 *te) return; } -void LLSelectNodeList::getCurrentTE(LLViewerObject* *object, S32 *te) +void LLObjectSelection::getCurrentTE(LLViewerObject* *object, S32 *te) { if (mCurrentNode != end()) { @@ -6667,7 +6144,7 @@ void LLSelectNodeList::getCurrentTE(LLViewerObject* *object, S32 *te) //----------------------------------------------------------------------------- // getFirstRootNode() //----------------------------------------------------------------------------- -LLSelectNode *LLSelectNodeList::getFirstRootNode() +LLSelectNode *LLObjectSelection::getFirstRootNode() { LLSelectNode *cur_node = getFirstNode(); @@ -6686,7 +6163,7 @@ LLSelectNode *LLSelectNodeList::getFirstRootNode() //----------------------------------------------------------------------------- // getNextRootNode() //----------------------------------------------------------------------------- -LLSelectNode *LLSelectNodeList::getNextRootNode() +LLSelectNode *LLObjectSelection::getNextRootNode() { LLSelectNode *cur_node = getNextNode(); @@ -6704,7 +6181,7 @@ LLSelectNode *LLSelectNodeList::getNextRootNode() //----------------------------------------------------------------------------- // getFirstRootObject() //----------------------------------------------------------------------------- -LLViewerObject *LLSelectNodeList::getFirstRootObject() +LLViewerObject *LLObjectSelection::getFirstRootObject() { LLSelectNode *node = getFirstRootNode(); @@ -6722,7 +6199,7 @@ LLViewerObject *LLSelectNodeList::getFirstRootObject() //----------------------------------------------------------------------------- // getNextRootObject() //----------------------------------------------------------------------------- -LLViewerObject *LLSelectNodeList::getNextRootObject() +LLViewerObject *LLObjectSelection::getNextRootObject() { LLSelectNode *node = getNextRootNode(); @@ -6739,7 +6216,7 @@ LLViewerObject *LLSelectNodeList::getNextRootObject() //----------------------------------------------------------------------------- // isEmpty() //----------------------------------------------------------------------------- -BOOL LLSelectNodeList::isEmpty() +BOOL LLObjectSelection::isEmpty() { return (size() == 0); } @@ -6747,7 +6224,7 @@ BOOL LLSelectNodeList::isEmpty() //----------------------------------------------------------------------------- // getOwnershipCost() //----------------------------------------------------------------------------- -BOOL LLSelectNodeList::getOwnershipCost(S32 &cost) +BOOL LLObjectSelection::getOwnershipCost(S32 &cost) { S32 count = 0; for( LLSelectNode* nodep = getFirstNode(); nodep; nodep = getNextNode() ) @@ -6759,3 +6236,341 @@ BOOL LLSelectNodeList::getOwnershipCost(S32 &cost) return (count > 0); } + + + +//----------------------------------------------------------------------------- +// getObjectCount() +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getObjectCount() +{ + return getNumNodes(); +} + + +//----------------------------------------------------------------------------- +// getTECount() +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getTECount() +{ + S32 count = 0; + + LLSelectNode* nodep; + for (nodep = getFirstNode(); nodep; nodep = getNextNode() ) + { + if (nodep->getObject()) + { + S32 num_tes = nodep->getObject()->getNumTEs(); + for (S32 te = 0; te < num_tes; te++) + { + if (nodep->isTESelected(te)) + { + count++; + } + } + } + } + + return count; +} + +//----------------------------------------------------------------------------- +// getRootObjectCount() +//----------------------------------------------------------------------------- +S32 LLObjectSelection::getRootObjectCount() +{ + LLSelectNode *nodep; + + S32 count = 0; + for(nodep = getFirstRootNode(); nodep; nodep = getNextRootNode()) + { + ++count; + } + return count; +} + +bool LLObjectSelection::applyToObjects(LLSelectedObjectFunctor* func) +{ + bool result = true; + LLViewerObject* object; + for (object = getFirstObject(); object != NULL; object = getNextObject()) + { + result = result && func->apply(object); + } + return result; +} + +bool LLObjectSelection::applyToRootObjects(LLSelectedObjectFunctor* func) +{ + bool result = true; + LLViewerObject* object; + for (object = getFirstRootObject(); + object != NULL; + object = getNextRootObject()) + { + result = result && func->apply(object); + } + return result; +} + +bool LLObjectSelection::applyToNodes(LLSelectedNodeFunctor *func) +{ + bool result = true; + LLSelectNode* node; + for (node = getFirstNode(); node != NULL; node = getNextNode()) + { + result = result && func->apply(node); + } + return result; +} + +//----------------------------------------------------------------------------- +// contains() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::contains(LLViewerObject* object) +{ + return findNode(object) != NULL; +} + + +//----------------------------------------------------------------------------- +// contains() +//----------------------------------------------------------------------------- +BOOL LLObjectSelection::contains(LLViewerObject* object, S32 te) +{ + LLSelectNode *nodep; + if (te == SELECT_ALL_TES) + { + // ...all faces + for (nodep = getFirstNode(); nodep; nodep = getNextNode() ) + { + if (nodep->getObject() == object) + { + BOOL all_selected = TRUE; + for (S32 i = 0; i < SELECT_MAX_TES; i++) + { + all_selected = all_selected && nodep->isTESelected(i); + } + return all_selected; + } + } + return FALSE; + } + else + { + // ...one face + for (nodep = getFirstNode(); nodep; nodep = getNextNode() ) + { + if (nodep->getObject() == object && nodep->isTESelected(te)) + { + return TRUE; + } + } + return FALSE; + } +} + +// returns TRUE is any node is currenly worn as an attachment +BOOL LLObjectSelection::isAttachment() +{ + return (mSelectType == SELECT_TYPE_ATTACHMENT || mSelectType == SELECT_TYPE_HUD); +} + +//----------------------------------------------------------------------------- +// getFirstMoveableNode() +//----------------------------------------------------------------------------- +LLSelectNode* LLObjectSelection::getFirstMoveableNode(BOOL get_root) +{ + LLSelectNode* selectNode = NULL; + + if (get_root) + { + for(selectNode = getFirstRootNode(); selectNode; selectNode = getNextRootNode()) + { + if( selectNode->getObject()->permMove() ) + { + return selectNode; + break; + } + } + } + for(selectNode = getFirstNode(); selectNode; selectNode = getNextNode()) + { + if( selectNode->getObject()->permMove() ) + { + return selectNode; + break; + } + } + + return NULL; +} + +//----------------------------------------------------------------------------- +// getFirstCopyableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstCopyableObject(BOOL get_root) +{ + LLViewerObject* object = NULL; + for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject()) + { + if( cur->permCopy() && !cur->isAttachment()) + { + object = cur; + break; + } + } + + if (get_root && object) + { + LLViewerObject *parent; + while ((parent = (LLViewerObject*)object->getParent())) + { + if (parent->isSelected()) + { + object = parent; + } + else + { + break; + } + } + } + + return object; +} + + +//----------------------------------------------------------------------------- +// getFirstDeleteableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstDeleteableObject(BOOL get_root) +{ + //RN: don't currently support deletion of child objects, as that requires separating them first + // then derezzing to trash + get_root = TRUE; + + LLViewerObject* object = NULL; + if (get_root) + { + for(LLViewerObject* current = getFirstRootObject(); + current != NULL; + current = getNextRootObject()) + { + // you can delete an object if permissions allow it, you are + // the owner, you are an officer in the group that owns the + // object, or you are not the owner but it is on land you own + // or land owned by your group. (whew!) + if( (current->permModify()) + || (current->permYouOwner()) + || (!current->permAnyOwner()) // public + || (current->isOverAgentOwnedLand()) + || (current->isOverGroupOwnedLand()) + ) + { + + if( !current->isAttachment() ) + { + object = current; + break; + } + } + } + } + else + { + for(LLViewerObject* current = getFirstObject(); + current != NULL; + current = getNextObject()) + { + // you can delete an object if permissions allow it, you are + // the owner, you are an officer in the group that owns the + // object, or you are not the owner but it is on land you own + // or land owned by your group. (whew!) + if( (current->permModify()) + || (current->permYouOwner()) + || (!current->permAnyOwner()) // public + || (current->isOverAgentOwnedLand()) + || (current->isOverGroupOwnedLand()) + ) + { + if( !current->isAttachment() ) + { + object = current; + break; + } + } + } + } + + return object; +} + + +//----------------------------------------------------------------------------- +// getFirstEditableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstEditableObject(BOOL get_root) +{ + LLViewerObject* object = NULL; + for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject()) + { + if( cur->permModify() ) + { + object = cur; + break; + } + } + + if (get_root && object) + { + LLViewerObject *parent; + while ((parent = (LLViewerObject*)object->getParent())) + { + if (parent->isSelected()) + { + object = parent; + } + else + { + break; + } + } + } + + return object; +} + +//----------------------------------------------------------------------------- +// getFirstMoveableObject() +//----------------------------------------------------------------------------- +LLViewerObject* LLObjectSelection::getFirstMoveableObject(BOOL get_root) +{ + LLViewerObject* object = NULL; + for(LLViewerObject* cur = getFirstObject(); cur; cur = getNextObject()) + { + if( cur->permMove() ) + { + object = cur; + break; + } + } + + if (get_root && object && !object->isJointChild()) + { + LLViewerObject *parent; + while ((parent = (LLViewerObject*)object->getParent())) + { + if (parent->isSelected()) + { + object = parent; + } + else + { + break; + } + } + } + + return object; +} diff --git a/linden/indra/newview/llselectmgr.h b/linden/indra/newview/llselectmgr.h index fe54360..4b9a550 100644 --- a/linden/indra/newview/llselectmgr.h +++ b/linden/indra/newview/llselectmgr.h @@ -110,11 +110,12 @@ typedef enum e_selection_type SELECT_TYPE_HUD }ESelectType; -class LLSelectNodeList : public std::list +class LLObjectSelection : public std::list, public LLRefCount { + friend class LLSelectMgr; public: - LLSelectNodeList(); - virtual ~LLSelectNodeList(); + LLObjectSelection(); + virtual ~LLObjectSelection(); void updateEffects(); @@ -129,6 +130,8 @@ public: LLSelectNode *getFirstRootNode(); LLSelectNode *getNextRootNode(); + LLSelectNode* getFirstMoveableNode(BOOL get_root = FALSE); + // iterate through objects LLViewerObject* getFirstObject(); LLViewerObject* getNextObject(); @@ -137,6 +140,12 @@ public: LLViewerObject *getFirstRootObject(); LLViewerObject *getNextRootObject(); + LLViewerObject* getFirstEditableObject(BOOL get_root = FALSE); + LLViewerObject* getFirstCopyableObject(BOOL get_root = FALSE); + LLViewerObject* getFirstDeleteableObject(BOOL get_root = FALSE); + LLViewerObject* getFirstMoveableObject(BOOL get_root = FALSE); + LLViewerObject* getPrimaryObject() { return mPrimaryObject; } + // iterate through texture entries void getPrimaryTE(LLViewerObject* *object, S32 *te); void getFirstTE(LLViewerObject* *object, S32 *te); @@ -149,24 +158,37 @@ public: void deleteAllNodes(); // Delete all nodes S32 getNumNodes(); LLSelectNode* findNode(LLViewerObject* objectp); + + // count members + S32 getObjectCount(); + S32 getTECount(); + S32 getRootObjectCount(); + + BOOL contains(LLViewerObject* object); + BOOL contains(LLViewerObject* object, S32 te); + + // returns TRUE is any node is currenly worn as an attachment + BOOL isAttachment(); + + // Apply functors to various subsets of the selected objects + // Returns the AND of all apply() calls. + bool applyToRootObjects(LLSelectedObjectFunctor* func); + bool applyToObjects(LLSelectedObjectFunctor* func); + bool applyToNodes(LLSelectedNodeFunctor* func); + + ESelectType getSelectType() { return mSelectType; } + private: - const LLSelectNodeList &operator=(const LLSelectNodeList &); + const LLObjectSelection &operator=(const LLObjectSelection &); - std::list::iterator mCurrentNode; - S32 mCurrentTE; - std::map mSelectNodeMap; + LLPointer mPrimaryObject; + std::list::iterator mCurrentNode; + S32 mCurrentTE; + std::map mSelectNodeMap; + ESelectType mSelectType; }; -struct LLSelectAction -{ -public: - EActionType mActionType; - LLVector3 mPosition; - LLVector3 mScale; - LLQuaternion mRotation; - LLUUID mObjectID; - BOOL mIndividualSelection; -}; +typedef LLHandle LLObjectSelectionHandle; class LLSelectMgr : public LLEditMenuHandler { @@ -187,6 +209,7 @@ public: static LLColor4 sHighlightChildColor; static LLColor4 sHighlightInspectColor; static LLColor4 sContextSilhouetteColor; + public: LLSelectMgr(); ~LLSelectMgr(); @@ -207,115 +230,91 @@ public: virtual void duplicate(); virtual BOOL canDuplicate(); - // Apply functors to various subsets of the selected objects - // Returns the AND of all apply() calls. - bool applyToRootObjects(LLSelectedObjectFunctor* func); - bool applyToObjects(LLSelectedObjectFunctor* func); - bool applyToNodes(LLSelectedNodeFunctor* func); - void updateEffects(); // Update HUD effects + void overrideObjectUpdates(); void setForceSelection(BOOL force) { mForceSelection = force; } + //////////////////////////////////////////////////////////////// + // Selection methods + //////////////////////////////////////////////////////////////// + + //////////////////////////////////////////////////////////////// + // Add + //////////////////////////////////////////////////////////////// + // For when you want just a child object. - void selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); + LLObjectSelectionHandle selectObjectOnly(LLViewerObject* object, S32 face = SELECT_ALL_TES); // This method is meant to select an object, and then select all // of the ancestors and descendents. This should be the normal behavior. - void selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE); + LLObjectSelectionHandle selectObjectAndFamily(LLViewerObject* object, BOOL add_to_end = FALSE); // Same as above, but takes a list of objects. Used by rectangle select. - void selectObjectAndFamily(const LLDynamicArray& object_list, BOOL send_to_sim = TRUE); + LLObjectSelectionHandle selectObjectAndFamily(const LLDynamicArray& object_list, BOOL send_to_sim = TRUE); - void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE); + // converts all objects currently highlighted to a selection, and returns it + LLObjectSelectionHandle selectHighlightedObjects(); - void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE); + LLObjectSelectionHandle setHoverObject(LLViewerObject *objectp); - void deselectTransient(); // deselect "temporarily" selected objects (via pie menu) - void convertTransient(); // converts temporarily selected objects to full-fledged selections + void highlightObjectOnly(LLViewerObject *objectp); + void highlightObjectAndFamily(LLViewerObject *objectp); + void highlightObjectAndFamily(const LLDynamicArray& list); + + //////////////////////////////////////////////////////////////// + // Remove + //////////////////////////////////////////////////////////////// + + void deselectObjectOnly(LLViewerObject* object, BOOL send_to_sim = TRUE); + void deselectObjectAndFamily(LLViewerObject* object, BOOL send_to_sim = TRUE); // Send deselect messages to simulator, then clear the list void deselectAll(); + // deselect only if nothing else currently referencing the selection + void deselectUnused(); + // Deselect if the selection center is too far away from the agent. void deselectAllIfTooFar(); - BOOL selectionRemoveObject(const LLUUID &id); - - BOOL contains(LLViewerObject* object); - BOOL contains(LLViewerObject* object, S32 te); - - ESelectType getSelectType() { return mSelectType; } - - // count members - S32 getObjectCount(); - S32 getTECount(); - S32 getRootObjectCount(); - - BOOL isEmpty() { return !mSelectedObjects.getNumNodes(); } - - BOOL shouldShowSelection() { return mShowSelection; } - - LLSelectNodeList &getHoverObjects() { return mHoverObjects; } - LLSelectNodeList &getSelectedObjects() { return mSelectedObjects; } - - // iterate through objects - LLViewerObject* getFirstObject() { return mSelectedObjects.getFirstObject(); } - LLViewerObject* getNextObject() { return mSelectedObjects.getNextObject(); } - - // iterate through root objects - LLViewerObject *getFirstRootObject() { return mSelectedObjects.getFirstRootObject(); } - LLViewerObject *getNextRootObject() { return mSelectedObjects.getNextRootObject(); } - - LLViewerObject* getFirstHighlightedObject() { return mHighlightedObjects.getFirstObject(); } - LLViewerObject* getNextHighlightedObject() { return mHighlightedObjects.getNextObject(); } - - // iterate through tes - void getPrimaryTE(LLViewerObject* *object, S32 *te) { mSelectedObjects.getPrimaryTE(object, te); } - void getFirstTE(LLViewerObject* *object, S32 *te) { mSelectedObjects.getFirstTE(object, te); } - void getNextTE(LLViewerObject* *object, S32 *te) { mSelectedObjects.getNextTE(object, te); }; - - void setHoverObject(LLViewerObject *objectp); - - void addGridObject(LLViewerObject* objectp); - void clearGridObjects(); - void setGridMode(EGridMode mode); - EGridMode getGridMode() { return mGridMode; } - void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale); + // Removes all highlighted objects from current selection + void deselectHighlightedObjects(); - void highlightObjectOnly(LLViewerObject *objectp); - void highlightObjectAndFamily(LLViewerObject *objectp); - void highlightObjectAndFamily(const LLDynamicArray& list); void unhighlightObjectOnly(LLViewerObject *objectp); void unhighlightObjectAndFamily(LLViewerObject *objectp); void unhighlightAll(); - void selectHighlightedObjects(); - void deselectHighlightedObjects(); - LLSelectNode *findSelectNode(LLViewerObject *objectp); - LLSelectNode *getFirstRootNode() { return mSelectedObjects.getFirstRootNode(); } - LLSelectNode *getNextRootNode() { return mSelectedObjects.getNextRootNode(); } - LLSelectNode* getFirstNode() { return mSelectedObjects.getFirstNode(); } - LLSelectNode* getNextNode() { return mSelectedObjects.getNextNode(); } + BOOL removeObjectFromSelections(const LLUUID &id); + + //////////////////////////////////////////////////////////////// + // Selection accessors + //////////////////////////////////////////////////////////////// + LLObjectSelectionHandle getHoverObjects() { return mHoverObjects; } + LLObjectSelectionHandle getSelection() { return mSelectedObjects; } + // right now this just renders the selection with root/child colors instead of a single color + LLObjectSelectionHandle getEditSelection() { convertTransient(); return mSelectedObjects; } + LLObjectSelectionHandle getHighlightedObjects() { return mHighlightedObjects; } LLSelectNode *getHoverNode(); + //////////////////////////////////////////////////////////////// + // Grid manipulation + //////////////////////////////////////////////////////////////// + void addGridObject(LLViewerObject* objectp); + void clearGridObjects(); + void setGridMode(EGridMode mode); + EGridMode getGridMode() { return mGridMode; } + void getGrid(LLVector3& origin, LLQuaternion& rotation, LLVector3 &scale); + BOOL getTEMode() { return mTEMode; } void setTEMode(BOOL b) { mTEMode = b; } - LLViewerObject* getFirstCopyableObject(BOOL get_root = FALSE); - LLViewerObject* getFirstEditableObject(BOOL get_root = FALSE); - LLViewerObject* getFirstMoveableObject(BOOL get_root = FALSE); - LLViewerObject* getFirstDeleteableObject(BOOL get_root = FALSE); - - LLSelectNode* getFirstEditableNode(BOOL get_root = FALSE); - LLSelectNode* getFirstMoveableNode(BOOL get_root = FALSE); + BOOL shouldShowSelection() { return mShowSelection; } LLBBox getBBoxOfSelection() const; LLBBox getSavedBBoxOfSelection() const { return mSavedSelectionBBox; } - BOOL areMultpleEditableObjectsSelected(); - void dump(); void cleanup(); @@ -323,17 +322,18 @@ public: void renderSilhouettes(BOOL for_hud); void enableSilhouette(BOOL enable) { mRenderSilhouettes = enable; } - // Utility functions to operate on the list - - void saveSelectedObjectTransform(EActionType action_type); - void saveSelectedObjectColors(); - void saveSelectedObjectTextures(); - - void selectionUpdatePhysics(BOOL use_physics); - void selectionUpdateTemporary(BOOL is_temporary); - void selectionUpdatePhantom(BOOL is_ghost); - void selectionUpdateCastShadows(BOOL cast_shadows); - void selectionDump(); + //////////////////////////////////////////////////////////////// + // Utility functions that operate on the current selection + //////////////////////////////////////////////////////////////// + void saveSelectedObjectTransform(EActionType action_type); + void saveSelectedObjectColors(); + void saveSelectedObjectTextures(); + + void selectionUpdatePhysics(BOOL use_physics); + void selectionUpdateTemporary(BOOL is_temporary); + void selectionUpdatePhantom(BOOL is_ghost); + void selectionUpdateCastShadows(BOOL cast_shadows); + void selectionDump(); BOOL selectionAllPCode(LLPCode code); // all objects have this PCode BOOL selectionGetMaterial(U8 *material); // all objects have same material @@ -362,11 +362,11 @@ public: void selectionSetMediaTypeAndURL( U8 media_type, const std::string& media_url ); void selectionSetClickAction(U8 action); - void setObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); - void setObjectName(const LLString& name); - void setObjectDescription(const LLString& desc); - void setObjectCategory(const LLCategory& category); - void setObjectSaleInfo(const LLSaleInfo& sale_info); + void selectionSetObjectPermissions(U8 perm_field, BOOL set, U32 perm_mask, BOOL override = FALSE); + void selectionSetObjectName(const LLString& name); + void selectionSetObjectDescription(const LLString& desc); + void selectionSetObjectCategory(const LLCategory& category); + void selectionSetObjectSaleInfo(const LLSaleInfo& sale_info); void selectionTexScaleAutofit(F32 repeats_per_meter); void selectionResetTexInfo(S32 te); // sets S,T to 1 @@ -433,23 +433,20 @@ public: // with the aggregate permissions for texture inventory items of the selection. BOOL selectGetAggregateTexturePermissions(LLAggregatePermissions& ag_perm); - // returns TRUE is any node is currenly worn as an attachment - BOOL selectionIsAttachment(); - LLPermissions* findObjectPermissions(const LLViewerObject* object); void selectDelete(); // Delete on simulator - void selectForceDelete(); // just delete, no into trash + void selectForceDelete(); // just delete, no into trash void selectDuplicate(const LLVector3& offset, BOOL select_copy); // Duplicate on simulator void repeatDuplicate(); - void selectDuplicateOnRay(const LLVector3 &ray_start_region, - const LLVector3 &ray_end_region, - BOOL bypass_raycast, - BOOL ray_end_is_intersection, - const LLUUID &ray_target_id, - BOOL copy_centers, - BOOL copy_rotates, - BOOL select_copy); + void selectDuplicateOnRay(const LLVector3 &ray_start_region, + const LLVector3 &ray_end_region, + BOOL bypass_raycast, + BOOL ray_end_is_intersection, + const LLUUID &ray_target_id, + BOOL copy_centers, + BOOL copy_rotates, + BOOL select_copy); void sendMultipleUpdate(U32 type); // Position, rotation, scale all in one void sendOwner(const LLUUID& owner_id, const LLUUID& group_id, BOOL override = FALSE); @@ -490,7 +487,7 @@ public: void demoteSelectionToIndividuals(); private: - + void convertTransient(); // converts temporarily selected objects to full-fledged selections ESelectType getSelectTypeForObject(LLViewerObject* object); void addAsFamily(LLDynamicArray& objects, BOOL add_to_end = FALSE); void generateSilhouette(LLSelectNode *nodep, const LLVector3& view_point); @@ -501,7 +498,6 @@ private: void (*pack_body)(LLSelectNode* node, void *user_data), void *user_data, ESendType send_type); - U32 undoRedo(std::deque &queue_src, std::deque &queue_dst, const LLUUID &object_id); static void packAgentID( void *); static void packAgentAndSessionID(void* user_data); @@ -536,22 +532,19 @@ private: static void confirmDelete(S32 option, void* data); private: - LLPointer mSilhouetteImagep; - - LLSelectNodeList mSelectedObjects; - - LLSelectNodeList mHoverObjects; - + LLPointer mSilhouetteImagep; + LLObjectSelectionHandle mSelectedObjects; + LLObjectSelectionHandle mHoverObjects; + LLObjectSelectionHandle mHighlightedObjects; std::set > mRectSelectedObjects; - LLSelectNodeList mGridObjects; + LLObjectSelection mGridObjects; LLQuaternion mGridRotation; LLVector3 mGridOrigin; LLVector3 mGridScale; EGridMode mGridMode; BOOL mGridValid; - LLSelectNodeList mHighlightedObjects; BOOL mTEMode; // render te LLVector3d mSelectionCenterGlobal; @@ -563,15 +556,10 @@ private: BOOL mRenderSilhouettes; // do we render the silhouette LLBBox mSavedSelectionBBox; - ESelectType mSelectType; - LLFrameTimer mEffectsTimer; BOOL mForceSelection; - std::deque mUndoQueue; - std::deque mRedoQueue; - - LLAnimPauseRequest mPauseRequest; + LLAnimPauseRequest mPauseRequest; }; @@ -614,9 +602,12 @@ public: LLCategory mCategory; S16 mInventorySerial; LLVector3 mSavedPositionLocal; // for interactively modifying object position + LLVector3 mLastPositionLocal; LLVector3d mSavedPositionGlobal; // for interactively modifying object position LLVector3 mSavedScale; // for interactively modifying object scale + LLVector3 mLastScale; LLQuaternion mSavedRotation; // for interactively modifying object rotation + LLQuaternion mLastRotation; BOOL mDuplicated; LLVector3d mDuplicatePos; LLQuaternion mDuplicateRot; diff --git a/linden/indra/newview/llsky.cpp b/linden/indra/newview/llsky.cpp index f4e305c..2888d95 100644 --- a/linden/indra/newview/llsky.cpp +++ b/linden/indra/newview/llsky.cpp @@ -366,7 +366,7 @@ void LLSky::updateCull() if (mVOStarsp.notNull() && mVOStarsp->mDrawable.notNull()) { - gPipeline.markVisible(mVOStarsp->mDrawable); + gPipeline.markVisible(mVOStarsp->mDrawable, *gCamera); } else { @@ -391,10 +391,10 @@ void LLSky::updateSky() } if (mVOStarsp) { - if (mVOStarsp->mDrawable) - { - gPipeline.markRebuild(mVOStarsp->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } + //if (mVOStarsp->mDrawable) + //{ + // gPipeline.markRebuild(mVOStarsp->mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + //} } } diff --git a/linden/indra/newview/llspatialpartition.cpp b/linden/indra/newview/llspatialpartition.cpp index fd9eec0..24ac1ca 100644 --- a/linden/indra/newview/llspatialpartition.cpp +++ b/linden/indra/newview/llspatialpartition.cpp @@ -29,25 +29,21 @@ #include "llspatialpartition.h" -#include "llglheaders.h" - +#include "llviewerwindow.h" #include "llviewerobjectlist.h" #include "llvovolume.h" #include "llviewercamera.h" #include "llface.h" #include "viewer.h" - +#include "llagent.h" +#include "llviewerregion.h" #include "llcamera.h" #include "pipeline.h" -static BOOL sIgnoreOcclusion = TRUE; static GLuint sBoxList = 0; -const S32 SG_LOD_SWITCH_STAGGER = 4; -const F32 SG_MAX_OBJ_RAD = 1.f; -const F32 SG_OCCLUSION_FUDGE = 1.1f; -const S32 SG_MOVE_PERIOD = 32; -const S32 SG_LOD_PERIOD = 16; +const F32 SG_OCCLUSION_FUDGE = 1.01f; +//const S32 SG_LOD_PERIOD = 16; #define SG_DISCARD_TOLERANCE 0.25f @@ -57,11 +53,12 @@ const S32 SG_LOD_PERIOD = 16; #define assert_octree_valid(x) #endif +static U32 sZombieGroups = 0; + static F32 sLastMaxTexPriority = 1.f; static F32 sCurMaxTexPriority = 1.f; //static counter for frame to switch LOD on -S32 LLSpatialGroup::sLODSeed = 0; void sg_assert(BOOL expr) { @@ -144,30 +141,22 @@ S32 LLSphereAABB(const LLVector3& center, const LLVector3& size, const LLVector3 LLSpatialGroup::~LLSpatialGroup() { - LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - if (!safeToDelete()) + if (isState(DEAD)) { -#ifdef LL_RELEASE_FOR_DOWNLOAD - llwarns << "Spatial Group deleted while being tracked " << ((void*) mState) << llendl; -#else - llerrs << "Spatial Group deleted while being tracked " << ((void*) mState) << llendl; -#endif + sZombieGroups--; } -#if LL_OCTREE_PARANOIA_CHECK - for (U32 i = 0; i < mSpatialPartition->mOccludedList.size(); i++) - { - if (mSpatialPartition->mOccludedList[i] == this) - { - llerrs << "Spatial Group deleted while being tracked STATE ERROR " << ((void*) mState) << llendl; - } - } -#endif + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + clearDrawMap(); } -BOOL LLSpatialGroup::safeToDelete() +void LLSpatialGroup::clearDrawMap() { - return gQuit || !isState(IN_QUEUE | ACTIVE_OCCLUSION | RESHADOW_QUEUE); + for (LLSpatialGroup::draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) + { + std::for_each(i->second.begin(), i->second.end(), DeletePointer()); + } + mDrawMap.clear(); } class LLRelightPainter : public LLSpatialGroup::OctreeTraveler @@ -212,13 +201,13 @@ public: BOOL LLSpatialGroup::isVisible() { - if (sIgnoreOcclusion) + if (LLPipeline::sUseOcclusion) { - return !isState(CULLED); + return !isState(CULLED | OCCLUDED); } else { - return !isState(CULLED | OCCLUDED); + return !isState(CULLED); } } @@ -254,6 +243,90 @@ void LLSpatialGroup::validate() #endif } +void validate_draw_info(LLDrawInfo& params) +{ +#if LL_DEBUG +/* if (params.mVertexBuffer.isNull()) + { + llerrs << "Draw batch has no vertex buffer." << llendl; + } + + //bad range + if (params.mStart >= params.mEnd) + { + llerrs << "Draw batch has invalid range." << llendl; + } + + if (params.mEnd >= params.mVertexBuffer->getNumVerts()) + { + llerrs << "Draw batch has buffer overrun error." << llendl; + } + + if (params.mOffset + params.mCount > params.mVertexBuffer->getNumIndices()) + { + llerrs << "Draw batch has index buffer ovverrun error." << llendl; + } + + //bad indices + U32* indicesp = (U32*) params.mVertexBuffer->getIndicesPointer(); + if (indicesp) + { + for (U32 i = params.mOffset; i < params.mOffset+params.mCount; i++) + { + if (indicesp[i] < params.mStart) + { + llerrs << "Draw batch has vertex buffer index out of range error (index too low)." << llendl; + } + + if (indicesp[i] > params.mEnd) + { + llerrs << "Draw batch has vertex buffer index out of range error (index too high)." << llendl; + } + } + }*/ +#endif +} + +void LLSpatialGroup::validateDrawMap() +{ +/* for (draw_map_t::iterator i = mDrawMap.begin(); i != mDrawMap.end(); ++i) + { + std::vector& draw_vec = i->second; + for (std::vector::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo& params = **j; + + validate_draw_info(params); + } + }*/ +} + +void LLSpatialGroup::makeStatic() +{ +#if !LL_DARWIN + if (isState(GEOM_DIRTY | ALPHA_DIRTY)) + { + return; + } + + if (mSpatialPartition->mRenderByGroup && mBufferUsage != GL_STATIC_DRAW_ARB) + { + mBufferUsage = GL_STATIC_DRAW_ARB; + if (mVertexBuffer.notNull()) + { + mVertexBuffer->makeStatic(); + } + + for (buffer_map_t::iterator i = mBufferMap.begin(); i != mBufferMap.end(); ++i) + { + i->second->makeStatic(); + } + + mBuilt = 1.f; + } +#endif +} + BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -261,10 +334,16 @@ BOOL LLSpatialGroup::updateInGroup(LLDrawable *drawablep, BOOL immediate) drawablep->updateSpatialExtents(); validate_drawable(drawablep); - if (mOctreeNode->isInside(drawablep) && mOctreeNode->contains(drawablep)) + OctreeNode* parent = mOctreeNode->getOctParent(); + + if (mOctreeNode->isInside(drawablep->getPositionGroup()) && + (mOctreeNode->contains(drawablep) || + (drawablep->getBinRadius() > mOctreeNode->getSize().mdV[0] && + parent && parent->getElementCount() >= LL_OCTREE_MAX_CAPACITY))) { unbound(); setState(OBJECT_DIRTY); + setState(GEOM_DIRTY); validate_drawable(drawablep); return TRUE; } @@ -284,11 +363,82 @@ BOOL LLSpatialGroup::addObject(LLDrawable *drawablep, BOOL add_all, BOOL from_oc { drawablep->setSpatialGroup(this, 0); validate_drawable(drawablep); + setState(OBJECT_DIRTY | GEOM_DIRTY); + mLastAddTime = gFrameTimeSeconds; + if (drawablep->isSpatialBridge()) + { + mBridgeList.push_back((LLSpatialBridge*) drawablep); + } + setState(IMAGE_DIRTY); } return TRUE; } +void LLSpatialGroup::rebuildGeom() +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + if (!isDead()) + { + mSpatialPartition->rebuildGeom(this); + } +} + +void LLSpatialPartition::rebuildGeom(LLSpatialGroup* group) +{ + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + group->mLastUpdateViewAngle = group->mViewAngle; + } + + if (group->isDead() || !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + return; + } + + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); + + group->clearDrawMap(); + + //get geometry count + group->mIndexCount = 0; + group->mVertexCount = 0; + + addGeometryCount(group, group->mVertexCount, group->mIndexCount); + + if (group->mVertexCount > 0 && group->mIndexCount > 0) + { //create vertex buffer containing volume geometry for this node + group->mBuilt = 1.f; + if (group->mVertexBuffer.isNull() || (group->mBufferUsage != group->mVertexBuffer->getUsage() && LLVertexBuffer::sEnableVBOs)) + { + //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB); + group->mVertexBuffer = createVertexBuffer(mVertexDataMask, group->mBufferUsage); + group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true); + stop_glerror(); + } + else + { + //LLFastTimer ftm(LLFastTimer::FTM_REBUILD_NONE_VB); + group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount); + stop_glerror(); + } + + { + LLFastTimer ftm((LLFastTimer::EFastTimerType) ((U32) LLFastTimer::FTM_REBUILD_VOLUME_VB + mPartitionType)); + getGeometry(group); + } + } + else + { + group->mVertexBuffer = NULL; + group->mBufferMap.clear(); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY); +} + BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxOut) { const OctreeState* node = mOctreeNode->getOctState(); @@ -304,7 +454,7 @@ BOOL LLSpatialGroup::boundObjects(BOOL empty, LLVector3& minOut, LLVector3& maxO LLVector3& newMin = mObjectExtents[0]; LLVector3& newMax = mObjectExtents[1]; - + if (isState(OBJECT_DIRTY)) { //calculate new bounding box clearState(OBJECT_DIRTY); @@ -390,11 +540,28 @@ void LLSpatialGroup::unbound() } } +LLSpatialGroup* LLSpatialGroup::getParent() +{ + if (isDead()) + { + return NULL; + } + + OctreeNode* parent = mOctreeNode->getOctParent(); + + if (parent) + { + return (LLSpatialGroup*) parent->getListener(0); + } + + return NULL; +} + BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); unbound(); - if (!from_octree) + if (mOctreeNode && !from_octree) { if (!mOctreeNode->remove(drawablep)) { @@ -404,6 +571,18 @@ BOOL LLSpatialGroup::removeObject(LLDrawable *drawablep, BOOL from_octree) else { drawablep->setSpatialGroup(NULL, -1); + setState(GEOM_DIRTY); + if (drawablep->isSpatialBridge()) + { + for (bridge_list_t::iterator i = mBridgeList.begin(); i != mBridgeList.end(); ++i) + { + if (*i == drawablep) + { + mBridgeList.erase(i); + break; + } + } + } } return TRUE; } @@ -420,6 +599,8 @@ void LLSpatialGroup::shift(const LLVector3 &offset) mObjectBounds[0] += offset; mObjectExtents[0] += offset; mObjectExtents[1] += offset; + + setState(GEOM_DIRTY | MATRIX_DIRTY | OCCLUSION_DIRTY); } class LLSpatialSetState : public LLSpatialGroup::OctreeTraveler @@ -533,30 +714,160 @@ void LLSpatialGroup::clearState(U32 state, S32 mode) // Octree Listener Implementation //====================================== -LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) -: mState(0), mOctreeNode(node), mSpatialPartition(part) +LLSpatialGroup::LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part) : + mState(0), + mBuilt(0.f), + mOctreeNode(node), + mSpatialPartition(part), + mVertexBuffer(NULL), + mBufferUsage(GL_STATIC_DRAW_ARB), + mDistance(0.f), + mDepth(0.f), + mLastUpdateDistance(-1.f), + mLastUpdateTime(gFrameTimeSeconds), + mLastAddTime(gFrameTimeSeconds), + mLastRenderTime(gFrameTimeSeconds), + mViewAngle(0.f), + mLastUpdateViewAngle(-1.f) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + sg_assert(mOctreeNode->getListenerCount() == 0); mOctreeNode->addListener(this); - setState(DIRTY); + setState(SG_INITIAL_STATE_MASK); mBounds[0] = LLVector3(node->getCenter()); mBounds[1] = LLVector3(node->getSize()); - sLODSeed = (sLODSeed+1)%SG_LOD_PERIOD; - mLODHash = sLODSeed; + part->mLODSeed = (part->mLODSeed+1)%part->mLODPeriod; + mLODHash = part->mLODSeed; + + mRadius = 1; + mPixelArea = 1024.f; +} + +void LLSpatialGroup::updateDistance(LLCamera &camera) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + if (isState(LLSpatialGroup::OBJECT_DIRTY)) + { + llerrs << "Spatial group dirty on distance update." << llendl; + } +#endif + if (!getData().empty()) + { + mRadius = mSpatialPartition->mRenderByGroup ? mObjectBounds[1].magVec() : + (F32) mOctreeNode->getSize().magVec(); + mDistance = mSpatialPartition->calcDistance(this, camera); + mPixelArea = mSpatialPartition->calcPixelArea(this, camera); + } +} + +F32 LLSpatialPartition::calcDistance(LLSpatialGroup* group, LLCamera& camera) +{ + LLVector3 eye = group->mObjectBounds[0] - camera.getOrigin(); + + F32 dist = 0.f; + + if (group->mDrawMap.find(LLRenderPass::PASS_ALPHA) != group->mDrawMap.end()) + { + LLVector3 v = eye; + dist = eye.normVec(); + + if (!group->isState(LLSpatialGroup::ALPHA_DIRTY)) + { + LLVector3 view_angle = LLVector3(eye * LLVector3(1,0,0), + eye * LLVector3(0,1,0), + eye * LLVector3(0,0,1)); + + if ((view_angle-group->mLastUpdateViewAngle).magVec() > 0.64f) + { + group->mViewAngle = view_angle; + group->mLastUpdateViewAngle = view_angle; + //for occasional alpha sorting within the group + //NOTE: If there is a trivial way to detect that alpha sorting here would not change the render order, + //not setting this node to dirty would be a very good thing + group->setState(LLSpatialGroup::ALPHA_DIRTY); + } + } + + //calculate depth of node for alpha sorting + + LLVector3 at = camera.getAtAxis(); + + //front of bounding box + for (U32 i = 0; i < 3; i++) + { + v.mV[i] -= group->mObjectBounds[1].mV[i]*0.25f * at.mV[i]; + } + + group->mDepth = v * at; + + F32 water_height = gAgent.getRegion()->getWaterHeight(); + //figure out if this node is above or below water + if (group->mObjectBounds[0].mV[2] < water_height) + { + group->setState(LLSpatialGroup::BELOW_WATER); + } + else + { + group->clearState(LLSpatialGroup::BELOW_WATER); + } + } + else + { + dist = eye.magVec(); + } + + if (dist < 16.f) + { + dist /= 16.f; + dist *= dist; + dist *= 16.f; + } + + return dist; +} + +F32 LLSpatialPartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) +{ + return LLPipeline::calcPixelArea(group->mObjectBounds[0], group->mObjectBounds[1], camera); } BOOL LLSpatialGroup::changeLOD() { - return LLDrawable::getCurrentFrame()%SG_LOD_PERIOD == mLODHash; + if (isState(ALPHA_DIRTY)) + { ///an alpha sort is going to happen, update distance and LOD + return TRUE; + } + + if (mSpatialPartition->mSlopRatio > 0.f) + { + F32 ratio = (mDistance - mLastUpdateDistance)/(llmax(mLastUpdateDistance, mRadius)); + + if (fabsf(ratio) >= mSpatialPartition->mSlopRatio) + { + return TRUE; + } + + if (mDistance > mRadius) + { + return FALSE; + } + } + + if (LLDrawable::getCurrentFrame()%mSpatialPartition->mLODPeriod == mLODHash) + { + return TRUE; + } + + return FALSE; } -void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawable) +void LLSpatialGroup::handleInsertion(const TreeNode* node, LLDrawable* drawablep) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - addObject(drawable, FALSE, TRUE); + addObject(drawablep, FALSE, TRUE); unbound(); setState(OBJECT_DIRTY); } @@ -571,29 +882,13 @@ void LLSpatialGroup::handleRemoval(const TreeNode* node, LLDrawable* drawable) void LLSpatialGroup::handleDestruction(const TreeNode* node) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - - if (mOctreeNode) - { - OctreeState* state = mOctreeNode->getOctState(); - for (OctreeState::element_iter i = state->getData().begin(); i != state->getData().end(); ++i) - { - LLDrawable* drawable = *i; - if (!drawable->isDead()) - { - drawable->setSpatialGroup(NULL, -1); - } - } - } - - if (safeToDelete()) - { - delete this; - } - else - { - setState(DEAD); - mOctreeNode = NULL; - } + setState(DEAD); + clearDrawMap(); + mOcclusionVerts = NULL; + mVertexBuffer = NULL; + mBufferMap.clear(); + sZombieGroups++; + mOctreeNode = NULL; } void LLSpatialGroup::handleStateChange(const TreeNode* node) @@ -611,7 +906,8 @@ void LLSpatialGroup::handleChildAddition(const OctreeNode* parent, OctreeNode* c LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); if (child->getListenerCount() == 0) { - (new LLSpatialGroup(child, mSpatialPartition))->setState(mState & SG_STATE_INHERIT_MASK); + LLSpatialGroup* group = new LLSpatialGroup(child, mSpatialPartition); + group->setState(mState & SG_STATE_INHERIT_MASK); } else { @@ -626,6 +922,31 @@ void LLSpatialGroup::handleChildRemoval(const OctreeNode* parent, const OctreeNo unbound(); } +void LLSpatialGroup::destroyGL() +{ + setState(LLSpatialGroup::GEOM_DIRTY | + LLSpatialGroup::OCCLUSION_DIRTY | + LLSpatialGroup::IMAGE_DIRTY); + mLastUpdateTime = gFrameTimeSeconds; + mVertexBuffer = NULL; + mBufferMap.clear(); + + mOcclusionVerts = NULL; + mReflectionMap = NULL; + clearDrawMap(); + + for (LLSpatialGroup::element_iter i = getData().begin(); i != getData().end(); ++i) + { + LLDrawable* drawable = *i; + for (S32 j = 0; j < drawable->getNumFaces(); j++) + { + LLFace* facep = drawable->getFace(j); + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + } + } +} + BOOL LLSpatialGroup::rebound() { if (!isState(DIRTY)) @@ -635,7 +956,7 @@ BOOL LLSpatialGroup::rebound() LLVector3 oldBounds[2]; - if (isState(QUERY_OUT)) + if (mSpatialPartition->isVolatile() && isState(QUERY_OUT)) { //a query has been issued, if our bounding box changes significantly //we need to discard the issued query oldBounds[0] = mBounds[0]; @@ -700,7 +1021,7 @@ BOOL LLSpatialGroup::rebound() mBounds[1] = (newMax - newMin)*0.5f; } - if (isState(QUERY_OUT)) + if (mSpatialPartition->isVolatile() && isState(QUERY_OUT)) { for (U32 i = 0; i < 3 && !isState(DISCARD_QUERY); i++) { @@ -713,6 +1034,8 @@ BOOL LLSpatialGroup::rebound() } } + setState(OCCLUSION_DIRTY); + clearState(DIRTY); return TRUE; @@ -720,9 +1043,21 @@ BOOL LLSpatialGroup::rebound() //============================================== -LLSpatialPartition::LLSpatialPartition() +LLSpatialPartition::LLSpatialPartition(U32 data_mask, BOOL is_volatile, U32 buffer_usage) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + mDrawableType = 0; + mPartitionType = LLPipeline::PARTITION_NONE; + mVolatile = is_volatile; + mLODSeed = 0; + mLODPeriod = 1; + mVertexDataMask = data_mask; + mBufferUsage = buffer_usage; + mDepthMask = FALSE; + mSlopRatio = 0.25f; + mRenderByGroup = TRUE; + mImageEnabled = FALSE; + mOctree = new LLSpatialGroup::OctreeNode(LLVector3d(0,0,0), LLVector3d(1,1,1), new LLSpatialGroup::OctreeRoot(), NULL); @@ -733,19 +1068,25 @@ LLSpatialPartition::LLSpatialPartition() LLSpatialPartition::~LLSpatialPartition() { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + for (U32 i = 0; i < mOcclusionQueries.size(); i++) + { + glDeleteQueriesARB(1, (GLuint*)(&(mOcclusionQueries[i]))); + } + delete mOctree; mOctree = NULL; } -LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep) +LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep, BOOL was_visible) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million if (drawablep->getPositionGroup().magVecSquared() > MAX_MAG) { -#ifndef LL_RELEASE_FOR_DOWNLOAD +#if 0 //ndef LL_RELEASE_FOR_DOWNLOAD llwarns << "LLSpatialPartition::put Object out of range!" << llendl; llinfos << drawablep->getPositionGroup() << llendl; @@ -770,7 +1111,13 @@ LLSpatialGroup *LLSpatialPartition::put(LLDrawable *drawablep) LLSpatialGroup::OctreeNode* node = mOctree->getNodeAt(drawablep); - return (LLSpatialGroup*) node->getListener(0); + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + if (was_visible && group->isState(LLSpatialGroup::QUERY_OUT)) + { + group->setState(LLSpatialGroup::DISCARD_QUERY); + } + + return group; } BOOL LLSpatialPartition::remove(LLDrawable *drawablep, LLSpatialGroup *curp) @@ -793,14 +1140,16 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); - + + BOOL was_visible = curp ? curp->isVisible() : FALSE; + if (curp && curp->mSpatialPartition != this) { //keep drawable from being garbage collected LLPointer ptr = drawablep; if (curp->mSpatialPartition->remove(drawablep, curp)) { - put(drawablep); + put(drawablep, was_visible); return; } else @@ -823,7 +1172,7 @@ void LLSpatialPartition::move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL OCT_ERRS << "Move couldn't find existing spatial group!" << llendl; } - put(drawablep); + put(drawablep, was_visible); } class LLSpatialShift : public LLSpatialGroup::OctreeTraveler @@ -848,13 +1197,9 @@ void LLSpatialPartition::shift(const LLVector3 &offset) BOOL LLSpatialPartition::checkOcclusion(LLSpatialGroup* group, LLCamera* camera) { - if (sIgnoreOcclusion) - { - return FALSE; - } - - if (!group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) && - !earlyFail(camera, group)) + if (LLPipeline::sUseOcclusion && + !group->isState(LLSpatialGroup::ACTIVE_OCCLUSION | LLSpatialGroup::OCCLUDED) && + (!camera || !earlyFail(camera, group))) { group->setState(LLSpatialGroup::ACTIVE_OCCLUSION); mQueryQueue.push(group); @@ -872,8 +1217,8 @@ public: virtual bool earlyFail(const LLSpatialGroup* group) { - if (mRes && //never occlusion cull the root node - !sIgnoreOcclusion && //never occlusion cull selection + if (group->mOctreeNode->getParent() && //never occlusion cull the root node + LLPipeline::sUseOcclusion && //never occlusion cull selection group->isState(LLSpatialGroup::OCCLUDED)) { return true; @@ -950,22 +1295,19 @@ public: group->mSpatialPartition->checkOcclusion(group, mCamera); } } + + if (LLPipeline::sDynamicReflections && + group->mOctreeNode->getSize().mdV[0] == 16.0 && + group->mDistance < 64.f && + group->mLastAddTime < gFrameTimeSeconds - 2.f) + { + group->mSpatialPartition->markReimage(group); + } } - virtual void processDrawable(LLDrawable* drawable) + virtual void processGroup(LLSpatialGroup* group) { - if (!drawable->isDead()) - { - const LLVector3* extents = drawable->getSpatialExtents(); - - F32 objRad = drawable->getRadius(); - objRad *= objRad; - F32 distSqr = ((extents[0]+extents[1])*0.5f - mCamera->getOrigin()).magVecSquared(); - if (objRad/distSqr > SG_MIN_DIST_RATIO) - { - gPipeline.markNotCulled(drawable, *mCamera); - } - } + gPipeline.markNotCulled(group, *mCamera); } virtual void visit(const LLSpatialGroup::OctreeState* branch) @@ -976,10 +1318,7 @@ public: if (checkObjects(branch, group)) { - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) - { - processDrawable(*i); - } + processGroup(group); } } @@ -998,33 +1337,31 @@ public: virtual void lateFail(LLSpatialGroup* group) { } virtual void preprocess(LLSpatialGroup* group) { } - virtual void processDrawable(LLDrawable* drawable) + virtual void processGroup(LLSpatialGroup* group) { - if (!drawable->isDead()) + LLSpatialGroup::OctreeState* branch = group->mOctreeNode->getOctState(); + + for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { - if (drawable->isSpatialBridge()) - { - drawable->setVisible(*mCamera, mResults, TRUE); - } - else + LLDrawable* drawable = *i; + + if (!drawable->isDead()) { - mResults->push_back(drawable); - } - } - } - - std::vector* mResults; -}; - + if (drawable->isSpatialBridge()) + { + drawable->setVisible(*mCamera, mResults, TRUE); + } + else + { + mResults->push_back(drawable); + } + } + } + } + + std::vector* mResults; +}; -void drawBox(const LLVector3& c, const LLVector3& r) -{ - glPushMatrix(); - glTranslatef(c.mV[0], c.mV[1], c.mV[2]); - glScalef(r.mV[0], r.mV[1], r.mV[2]); - glCallList(sBoxList); - glPopMatrix(); -} void genBoxList() { @@ -1077,6 +1414,83 @@ void genBoxList() glEndList(); } +void drawBox(const LLVector3& c, const LLVector3& r) +{ + genBoxList(); + + glPushMatrix(); + glTranslatef(c.mV[0], c.mV[1], c.mV[2]); + glScalef(r.mV[0], r.mV[1], r.mV[2]); + glCallList(sBoxList); + glPopMatrix(); +} + +void drawBoxOutline(const LLVector3& pos, const LLVector3& size) +{ + LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); + LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); + LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); + LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); + + glBegin(GL_LINE_LOOP); //top + glVertex3fv((pos+v1).mV); + glVertex3fv((pos+v2).mV); + glVertex3fv((pos+v3).mV); + glVertex3fv((pos+v4).mV); + glEnd(); + + glBegin(GL_LINE_LOOP); //bottom + glVertex3fv((pos-v1).mV); + glVertex3fv((pos-v2).mV); + glVertex3fv((pos-v3).mV); + glVertex3fv((pos-v4).mV); + glEnd(); + + + glBegin(GL_LINES); + + //right + glVertex3fv((pos+v1).mV); + glVertex3fv((pos-v3).mV); + + glVertex3fv((pos+v4).mV); + glVertex3fv((pos-v2).mV); + + //left + glVertex3fv((pos+v2).mV); + glVertex3fv((pos-v4).mV); + + glVertex3fv((pos+v3).mV); + glVertex3fv((pos-v1).mV); + + glEnd(); +} + +class LLOctreeDirty : public LLOctreeTraveler +{ +public: + virtual void visit(const LLOctreeState* state) + { + LLSpatialGroup* group = (LLSpatialGroup*) state->getListener(0); + group->destroyGL(); + + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) + { + LLDrawable* drawable = *i; + if (drawable->getVObj() && !group->mSpatialPartition->mRenderByGroup) + { + gPipeline.markRebuild(drawable, LLDrawable::REBUILD_ALL, TRUE); + } + } + + for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) + { + LLSpatialBridge* bridge = *i; + traverse(bridge->mOctree); + } + } +}; + void LLSpatialPartition::restoreGL() { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1099,6 +1513,14 @@ void LLSpatialPartition::restoreGL() genBoxList(); } +void LLSpatialPartition::resetVertexBuffers() +{ + LLOctreeDirty dirty; + dirty.traverse(mOctree); + + mOcclusionIndices = NULL; +} + S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* results, BOOL for_select) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1115,11 +1537,11 @@ S32 LLSpatialPartition::cull(LLCamera &camera, std::vector* result } else { + LLFastTimer ftm(LLFastTimer::FTM_FRUSTUM_CULL); LLOctreeCull culler(&camera); culler.traverse(mOctree); } - sIgnoreOcclusion = !(gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery); return 0; } @@ -1174,9 +1596,10 @@ public: BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) { LLVector3 c = group->mBounds[0]; - LLVector3 r = group->mBounds[1] * (SG_OCCLUSION_FUDGE*2.f) + LLVector3(0.01f,0.01f,0.01f); + LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.2f,0.2f,0.2f); - if (group->isState(LLSpatialGroup::CULLED) || !camera->AABBInFrustum(c, r)) + //if (group->isState(LLSpatialGroup::CULLED)) // || + if (!camera->AABBInFrustum(c, r)) { return TRUE; } @@ -1197,6 +1620,100 @@ BOOL earlyFail(LLCamera* camera, LLSpatialGroup* group) return TRUE; } +void LLSpatialPartition::markReimage(LLSpatialGroup* group) +{ + if (mImageEnabled && group->isState(LLSpatialGroup::IMAGE_DIRTY)) + { + if (!group->isState(LLSpatialGroup::IN_IMAGE_QUEUE)) + { + group->setState(LLSpatialGroup::IN_IMAGE_QUEUE); + mImageQueue.push(group); + } + } +} + +void LLSpatialPartition::processImagery(LLCamera* camera) +{ + if (!mImageEnabled) + { + return; + } + + U32 process_count = 1; + + while (process_count > 0 && !mImageQueue.empty()) + { + LLPointer group = mImageQueue.front(); + mImageQueue.pop(); + + group->clearState(LLSpatialGroup::IN_IMAGE_QUEUE); + + if (group->isDead()) + { + continue; + } + + if (LLPipeline::sDynamicReflections) + { + process_count--; + LLVector3 origin = group->mBounds[0]; + + LLCamera cube_cam; + cube_cam.setOrigin(origin); + cube_cam.setFar(64.f); + + LLPointer cube_map = group->mReflectionMap; + group->mReflectionMap = NULL; + if (cube_map.isNull()) + { + cube_map = new LLCubeMap(); + cube_map->initGL(); + } + + if (gPipeline.mCubeBuffer == NULL) + { + gPipeline.mCubeBuffer = new LLCubeMap(); + gPipeline.mCubeBuffer->initGL(); + } + + gPipeline.generateReflectionMap(gPipeline.mCubeBuffer, cube_cam, 128); + gPipeline.blurReflectionMap(gPipeline.mCubeBuffer, cube_map, 64); + group->mReflectionMap = cube_map; + group->setState(LLSpatialGroup::GEOM_DIRTY); + } + + group->clearState(LLSpatialGroup::IMAGE_DIRTY); + } +} + +void validate_occlusion_list(std::vector >& occluded_list) +{ +#if !LL_RELEASE_FOR_DOWNLOAD + for (U32 i = 0; i < occluded_list.size(); i++) + { + LLSpatialGroup* group = occluded_list[i]; + for (U32 j = i+1; j < occluded_list.size(); j++) + { + if (occluded_list[i] == occluded_list[j]) + { + llerrs << "Duplicate node in occlusion list." << llendl; + } + } + + LLSpatialGroup::OctreeNode* parent = group->mOctreeNode->getOctParent(); + while (parent) + { + LLSpatialGroup* parent_group = (LLSpatialGroup*) parent->getListener(0); + if (parent_group->isState(LLSpatialGroup::OCCLUDED)) + { + llerrs << "Child node of occluded node in occlusion list (redundant query)." << llendl; + } + parent = parent->getOctParent(); + } + } +#endif +} + void LLSpatialPartition::processOcclusion(LLCamera* camera) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); @@ -1217,12 +1734,12 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) const U32 MAX_PUSHED = mOcclusionQueue.size(); U32 count = 0; U32 pcount = 0; - + while (pcount < MAX_PUSHED && count < MAX_PULLED && !mOcclusionQueue.empty()) { - LLFastTimer t(LLFastTimer::FTM_OCCLUSION); + LLFastTimer t(LLFastTimer::FTM_OCCLUSION); - LLSpatialGroup* group = mOcclusionQueue.front(); + LLPointer group = mOcclusionQueue.front(); if (!group->isState(LLSpatialGroup::IN_QUEUE)) { OCT_ERRS << "Spatial Group State Error. Group in queue not tagged as such." << llendl; @@ -1233,10 +1750,6 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) if (group->isDead()) { - if (group->safeToDelete()) - { - delete group; - } continue; } @@ -1250,22 +1763,14 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) { LLSpatialGroup* child = (LLSpatialGroup*) group->mOctreeNode->getChild(i)->getListener(0); - if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED) - && !child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION)) + //if (!child->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED) + if (!child->isState(LLSpatialGroup::IN_QUEUE | LLSpatialGroup::ACTIVE_OCCLUSION)) { child->setState(LLSpatialGroup::IN_QUEUE); mOcclusionQueue.push(child); } } - - /*if (group->isState(LLSpatialGroup::QUERY_PENDING)) - { //already on the pending group, put it back - group->setState(LLSpatialGroup::IN_QUEUE); - mOcclusionQueue.push(group); - pcount++; - continue; - }*/ - + if (earlyFail(camera, group)) { sg_assert(!group->isState(LLSpatialGroup::OCCLUDED)); @@ -1284,7 +1789,6 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) sg_assert(mOccludedList[i] != group); } #endif - //group->setState(LLSpatialGroup::QUERY_PENDING); group->setState(LLSpatialGroup::ACTIVE_OCCLUSION); mQueryQueue.push(group); count++; @@ -1296,7 +1800,7 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) { LLFastTimer t(LLFastTimer::FTM_OCCLUSION_READBACK); - if (mOccludedList[i]->isDead() || !mOccludedList[i]->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) + if (mOccludedList[i]->isDead() || mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) { continue; } @@ -1347,8 +1851,7 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) LLSpatialGroup* parent = (LLSpatialGroup*) oct_parent->getListener(0); if (checkOcclusion(parent, camera)) - { //force a guess on the parent and siblings - + { //force a guess on the parent and siblings for (U32 i = 0; i < parent->mOctreeNode->getChildCount(); i++) { LLSpatialGroup* child = (LLSpatialGroup*) parent->mOctreeNode->getChild(i)->getListener(0); @@ -1356,13 +1859,17 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) } } } + + //take children off the active list + mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH); + mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); } mOccludedList[i]->setState(LLSpatialGroup::OCCLUDED, LLSpatialGroup::STATE_MODE_DIFF); } else { //take children off the active list - mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_DIFF); + mOccludedList[i]->setState(LLSpatialGroup::DEACTIVATE_OCCLUSION, LLSpatialGroup::STATE_MODE_BRANCH); //keep this node on the active list mOccludedList[i]->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); @@ -1383,15 +1890,13 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) mOccludedList[i]->isState(LLSpatialGroup::DEACTIVATE_OCCLUSION)) //parent is occluded { LLSpatialGroup* groupp = mOccludedList[i]; - mOccludedList.erase(mOccludedList.begin()+i); - groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION); - groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); - groupp->clearState(LLSpatialGroup::OCCLUDING); - - if (groupp->isDead() && groupp->safeToDelete()) + if (!groupp->isDead()) { - delete groupp; + groupp->clearState(LLSpatialGroup::ACTIVE_OCCLUSION); + groupp->clearState(LLSpatialGroup::DEACTIVATE_OCCLUSION); + groupp->clearState(LLSpatialGroup::OCCLUDING); } + mOccludedList.erase(mOccludedList.begin()+i); } else { @@ -1399,11 +1904,13 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) } } + validate_occlusion_list(mOccludedList); + //pump some non-culled items onto the occlusion list //count = MAX_PULLED; while (!mQueryQueue.empty()) { - LLSpatialGroup* group = mQueryQueue.front(); + LLPointer group = mQueryQueue.front(); mQueryQueue.pop(); //group->clearState(LLSpatialGroup::QUERY_PENDING); mOccludedList.push_back(group); @@ -1418,12 +1925,161 @@ void LLSpatialPartition::processOcclusion(LLCamera* camera) } } +class LLOcclusionIndexBuffer : public LLVertexBuffer +{ +public: + LLOcclusionIndexBuffer(U32 size) + : LLVertexBuffer(0, GL_STREAM_DRAW_ARB) + { + allocateBuffer(0, size, TRUE); + + LLStrider idx; + + getIndexStrider(idx); + + //12 triangles' indices + idx[0] = 1; idx[1] = 0; idx[2] = 2; //front + idx[3] = 3; idx[4] = 2; idx[5] = 0; + + idx[6] = 4; idx[7] = 5; idx[8] = 1; //top + idx[9] = 0; idx[10] = 1; idx[11] = 5; + + idx[12] = 5; idx[13] = 4; idx[14] = 6; //back + idx[15] = 7; idx[16] = 6; idx[17] = 4; + + idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom + idx[21] = 2; idx[22] = 3; idx[23] = 7; + + idx[24] = 0; idx[25] = 5; idx[26] = 3; //left + idx[27] = 6; idx[28] = 3; idx[29] = 5; + + idx[30] = 4; idx[31] = 1; idx[32] = 7; //right + idx[33] = 2; idx[34] = 7; idx[35] = 1; + } + + //virtual BOOL useVBOs() const { return FALSE; } + + void setBuffer(U32 data_mask) + { + if (useVBOs()) + { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, mGLIndices); + sIBOActive = TRUE; + unmapBuffer(); + } + else if (sIBOActive) + { + glBindBufferARB(GL_ELEMENT_ARRAY_BUFFER_ARB, 0); + sIBOActive = FALSE; + } + + sGLRenderIndices = mGLIndices; + } +}; + +class LLOcclusionVertexBuffer : public LLVertexBuffer +{ +public: + LLOcclusionVertexBuffer(S32 usage) + : LLVertexBuffer(MAP_VERTEX, usage) + { + allocateBuffer(8, 0, TRUE); + } + + //virtual BOOL useVBOs() const { return FALSE; } + + void setBuffer(U32 data_mask) + { + if (useVBOs()) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, mGLBuffer); + sVBOActive = TRUE; + unmapBuffer(); + } + else if (sVBOActive) + { + glBindBufferARB(GL_ARRAY_BUFFER_ARB, 0); + sVBOActive = FALSE; + } + + if (data_mask) + { + glVertexPointer(3,GL_FLOAT, 0, useVBOs() ? 0 : mMappedData); + } + + sGLRenderBuffer = mGLBuffer; + } +}; + +void LLSpatialPartition::buildOcclusion() +{ + if (mOccludedList.empty()) + { + return; + } + + BOOL reset_all = FALSE; + if (mOcclusionIndices.isNull()) + { + mOcclusionIndices = new LLOcclusionIndexBuffer(36); + reset_all = TRUE; + } + + //fill occlusion vertex buffers + for (U32 i = 0; i < mOccludedList.size(); i++) + { + LLSpatialGroup* group = mOccludedList[i]; + + if (group->isState(LLSpatialGroup::OCCLUSION_DIRTY) || reset_all) + { + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB); + + if (group->mOcclusionVerts.isNull()) + { + group->mOcclusionVerts = new LLOcclusionVertexBuffer(GL_STREAM_DRAW_ARB); + } + + group->clearState(LLSpatialGroup::OCCLUSION_DIRTY); + + LLStrider vert; + + group->mOcclusionVerts->getVertexStrider(vert); + + LLVector3 r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.1f,0.1f,0.1f); + + for (U32 k = 0; k < 3; k++) + { + r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]); + } + + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,1)); // 1 - right top front + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front + + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back + *vert++ = group->mBounds[0] + r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back + } + } + +/* for (U32 i = 0; i < mOccludedList.size(); i++) + { + LLSpatialGroup* group = mOccludedList[i]; + if (!group->mOcclusionVerts.isNull() && group->mOcclusionVerts->isLocked()) + { + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_OCCLUSION_VB); + group->mOcclusionVerts->setBuffer(0); + } + }*/ +} + void LLSpatialPartition::doOcclusion(LLCamera* camera) { LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - sIgnoreOcclusion = gUseWireframe; - LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); + LLFastTimer t(LLFastTimer::FTM_RENDER_OCCLUSION); #if LL_OCTREE_PARANOIA_CHECK LLSpatialGroup* check = (LLSpatialGroup*) mOctree->getListener(0); @@ -1432,9 +2088,16 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera) stop_glerror(); + U32 num_verts = mOccludedList.size() * 8; + + if (num_verts == 0) + { + return; + } + //actually perform the occlusion queries LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - glDisable(GL_TEXTURE_2D); + LLGLDisable(GL_TEXTURE_2D); gPipeline.disableLights(); LLGLEnable cull_face(GL_CULL_FACE); LLGLDisable blend(GL_BLEND); @@ -1443,25 +2106,16 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera) glColorMask(GL_FALSE, GL_FALSE, GL_FALSE, GL_FALSE); glColor4f(1,1,1,1); - //sort occlusion queries front to back - /*for (U32 i = 0; i < mOccludedList.size(); i++) - { - LLSpatialGroup* group = mOccludedList[i]; - - LLVector3 v = group->mOctreeNode->getCenter()-camera->getOrigin(); - group->mDistance = v*v; - } - - std::sort(mOccludedList.begin(), mOccludedList.end(), dist_greater()); + mOcclusionIndices->setBuffer(0); - glClearStencil(0); - glClear(GL_STENCIL_BUFFER_BIT); - LLGLEnable stencil(GL_STENCIL_TEST); - glStencilFunc(GL_GREATER, 1, 0xFFFFFFFF); - glStencilOp(GL_KEEP, GL_SET, GL_KEEP);*/ - - genBoxList(); + U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer(); + glDisableClientState(GL_NORMAL_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); +#if !LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkClientArrays(LLVertexBuffer::MAP_VERTEX); +#endif for (U32 i = 0; i < mOccludedList.size(); i++) { #if LL_OCTREE_PARANOIA_CHECK @@ -1482,32 +2136,10 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera) } else { //early rejection criteria passed, send some geometry to the query - LLVector3 c; - LLVector3 r; - - sg_assert(!group->isState(LLSpatialGroup::DIRTY)); - - c = group->mBounds[0]; - r = group->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.01f,0.01f,0.01f); - for (U32 k = 0; k < 3; k++) - { - r.mV[k] = llmin(group->mBounds[1].mV[k]+0.25f, r.mV[k]); - } - -#if LL_OCTREE_PARANOIA_CHECK - LLVector3 e = camera->getOrigin(); - LLVector3 min = c - r; - LLVector3 max = c + r; - BOOL outside = FALSE; - for (U32 j = 0; j < 3; j++) - { - outside = outside || (e.mV[j] < min.mV[j] || e.mV[j] > max.mV[j]); - } - sg_assert(outside); -#endif - + group->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); glBeginQueryARB(GL_SAMPLES_PASSED_ARB, mOcclusionQueries[i]); - drawBox(c,r); + glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, + GL_UNSIGNED_INT, indicesp); glEndQueryARB(GL_SAMPLES_PASSED_ARB); group->setState(LLSpatialGroup::QUERY_OUT); @@ -1516,10 +2148,11 @@ void LLSpatialPartition::doOcclusion(LLCamera* camera) } stop_glerror(); + gPipeline.mTrianglesDrawn += mOccludedList.size()*12; + glFlush(); glColorMask(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glEnable(GL_TEXTURE_2D); } class LLOctreeGet : public LLSpatialGroup::OctreeTraveler @@ -1618,6 +2251,8 @@ S32 LLSpatialPartition::getDrawables(const LLVector3& pos, F32 rad, S32 LLSpatialPartition::getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results) { + LLSpatialGroup* group = (LLSpatialGroup*) mOctree->getListener(0); + group->rebound(); return getDrawables(pos, rad, results, FALSE); } @@ -1626,182 +2261,363 @@ S32 LLSpatialPartition::getLights(const LLVector3& pos, F32 rad, LLDrawable::dra return getDrawables(pos, rad, results, TRUE); } -class LLOctreeRenderNonOccluded : public LLOctreeTraveler +void pushVerts(LLDrawInfo* params, U32 mask) { -public: - LLOctreeRenderNonOccluded() {} - - virtual void traverse(const LLSpatialGroup::OctreeNode* node) + params->mVertexBuffer->setBuffer(mask); + U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, + GL_UNSIGNED_INT, indicesp+params->mOffset); +} + +void pushVerts(LLSpatialGroup* group, U32 mask) +{ + LLDrawInfo* params = NULL; + + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) { - const LLSpatialGroup::OctreeState* state = node->getOctState(); - LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); - - if (!group->isState(LLSpatialGroup::OCCLUDED | LLSpatialGroup::CULLED)) + for (std::vector::iterator j = i->second.begin(); j != i->second.end(); ++j) { - state->accept(this); + params = *j; + pushVerts(params, mask); + } + } +} - for (U32 i = 0; i < state->getChildCount(); i++) - { - traverse(state->getChild(i)); +void pushVertsColorCoded(LLSpatialGroup* group, U32 mask) +{ + LLDrawInfo* params = NULL; + + LLColor4 colors[] = { + LLColor4::green, + LLColor4::green1, + LLColor4::green2, + LLColor4::green3, + LLColor4::green4, + LLColor4::green5, + LLColor4::green6 + }; + + static const U32 col_count = sizeof(colors)/sizeof(LLColor4); + + U32 col = 0; + + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (std::vector::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + params = *j; + glColor4f(colors[col].mV[0], colors[col].mV[1], colors[col].mV[2], 0.5f); + params->mVertexBuffer->setBuffer(mask); + U32* indicesp = (U32*) params->mVertexBuffer->getIndicesPointer(); + glDrawRangeElements(params->mParticle ? GL_POINTS : GL_TRIANGLES, params->mStart, params->mEnd, params->mCount, + GL_UNSIGNED_INT, indicesp+params->mOffset); + col = (col+1)%col_count; + } + } +} + +void renderOctree(LLSpatialGroup* group) +{ + //render solid object bounding box, color + //coded by buffer usage and activity + LLGLDepthTest depth(GL_TRUE, GL_FALSE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + LLVector4 col; + if (group->mBuilt > 0.f) + { + group->mBuilt -= 2.f * gFrameIntervalSeconds; + if (group->mBufferUsage == GL_STATIC_DRAW_ARB) + { + col.setVec(1.0f, 0, 0, group->mBuilt*0.5f); + } + else + { + col.setVec(0.1f,0.1f,1,0.1f); + //col.setVec(1.0f, 1.0f, 0, sinf(group->mBuilt*3.14159f)*0.5f); + } + + if (group->mBufferUsage != GL_STATIC_DRAW_ARB) + { + if (group->mBufferUsage == GL_DYNAMIC_DRAW_ARB) + { + glColor4f(1,0,0,group->mBuilt); } - - /*if (state->getElementCount() == 0) + else { - return; - }*/ + glColor4f(1,1,0,group->mBuilt); + } - //draw tight fit bounding box for spatial group - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) + LLGLDepthTest gl_depth(FALSE, FALSE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { - if (node->getElementCount() == 0) + LLDrawable* drawable = *i; + for (S32 j = 0; j < drawable->getNumFaces(); j++) { - return; - } - - if (node->hasLeafState()) - { - glColor4f(1,1,1,1); - } - else - { - glColor4f(0,1,1,1); + LLFace* face = drawable->getFace(j); + if (gFrameTimeSeconds - face->mLastUpdateTime < 0.5f && face->mVertexBuffer.notNull()) + { + face->mVertexBuffer->setBuffer(LLVertexBuffer::MAP_VERTEX); + //drawBox((face->mExtents[0] + face->mExtents[1])*0.5f, + // (face->mExtents[1]-face->mExtents[0])*0.5f); + glDrawElements(GL_TRIANGLES, face->getIndicesCount(), GL_UNSIGNED_INT, + ((U32*) face->mVertexBuffer->getIndicesPointer())+face->getIndicesStart()); + } } + } + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); + } + } + else + { + if (group->mBufferUsage == GL_STATIC_DRAW_ARB && !group->getData().empty() + && group->mSpatialPartition->mRenderByGroup) + { + col.setVec(0.8f, 0.4f, 0.1f, 0.1f); + } + else + { + col.setVec(0.1f, 0.1f, 1.f, 0.1f); + } + } + glColor4fv(col.mV); + drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); + glDepthMask(GL_TRUE); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - LLVector3 pos; - LLVector3 size; - - pos = group->mObjectBounds[0]; - size = group->mObjectBounds[1]; - - LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); - LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); - LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); - LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); - - glBegin(GL_LINE_LOOP); //top - glVertex3fv((pos+v1).mV); - glVertex3fv((pos+v2).mV); - glVertex3fv((pos+v3).mV); - glVertex3fv((pos+v4).mV); - glEnd(); - - glBegin(GL_LINE_LOOP); //bottom - glVertex3fv((pos-v1).mV); - glVertex3fv((pos-v2).mV); - glVertex3fv((pos-v3).mV); - glVertex3fv((pos-v4).mV); - glEnd(); - - - glBegin(GL_LINES); - - //right - glVertex3fv((pos+v1).mV); - glVertex3fv((pos-v3).mV); - - glVertex3fv((pos+v4).mV); - glVertex3fv((pos-v2).mV); - - //left - glVertex3fv((pos+v2).mV); - glVertex3fv((pos-v4).mV); - - glVertex3fv((pos+v3).mV); - glVertex3fv((pos-v1).mV); + //draw opaque outline + glColor4f(col.mV[0], col.mV[1], col.mV[2], 1.f); + drawBoxOutline(group->mObjectBounds[0], group->mObjectBounds[1]); - glEnd(); + if (group->mOctreeNode->hasLeafState()) + { + glColor4f(1,1,1,1); + } + else + { + glColor4f(0,1,1,1); + } + + drawBoxOutline(group->mBounds[0],group->mBounds[1]); + +// LLSpatialGroup::OctreeNode* node = group->mOctreeNode; +// glColor4f(0,1,0,1); +// drawBoxOutline(LLVector3(node->getCenter()), LLVector3(node->getSize())); +} - LLVector3 nc = LLVector3(node->getCenter()); - LLVector3 ns = LLVector3(node->getSize()); +void renderVisibility(LLSpatialGroup* group) +{ + LLGLEnable blend(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + LLGLEnable cull(GL_CULL_FACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + { + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + glColor4f(0, 0.5f, 0, 0.5f); + pushVerts(group, LLVertexBuffer::MAP_VERTEX); + } - LLVector3 nv1 = ns.scaledVec(LLVector3( 1, 1,1)); - LLVector3 nv2 = ns.scaledVec(LLVector3(-1, 1,1)); - LLVector3 nv3 = ns.scaledVec(LLVector3(-1,-1,1)); - LLVector3 nv4 = ns.scaledVec(LLVector3( 1,-1,1)); + { + LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); + pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); - + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); - /*if (node->getElementCount() > 0) - { - //spokes - glColor4f(1,1,0,1); - glVertex3fv(pos.mV); - glColor4f(1,1,0,0); - glVertex3fv(nc.mV); - - glColor4f(1,1,0,1); glVertex3fv((pos+v1).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos-v1).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos+v2).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos-v2).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos+v3).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos-v3).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos+v4).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - glColor4f(1,1,0,1); glVertex3fv((pos-v4).mV); glColor4f(1,1,0,0); glVertex3fv(pos.mV); - }*/ + pushVertsColorCoded(group, LLVertexBuffer::MAP_VERTEX); + } +} - +void renderBoundingBox(LLDrawable* drawable) +{ + if (drawable->isSpatialBridge()) + { + glColor4f(1,0.5f,0,1); + } + else if (drawable->getVOVolume()) + { + if (drawable->isRoot()) + { + glColor4f(1,1,0,1); + } + else + { + glColor4f(0,1,0,1); + } + } + else if (drawable->getVObj()) + { + switch (drawable->getVObj()->getPCode()) + { + case LLViewerObject::LL_VO_SURFACE_PATCH: + glColor4f(0,1,1,1); + break; + case LLViewerObject::LL_VO_CLOUDS: + glColor4f(0.5f,0.5f,0.5f,1.0f); + break; + case LLViewerObject::LL_VO_PART_GROUP: + glColor4f(0,0,1,1); + break; + case LLViewerObject::LL_VO_WATER: + glColor4f(0,0.5f,1,1); + break; + case LL_PCODE_LEGACY_TREE: + glColor4f(0,0.5f,0,1); + default: + glColor4f(1,0,1,1); + break; + } + } + else + { + glColor4f(1,0,0,1); + } - /*glColor4f(0,1,0,1); - glBegin(GL_LINE_LOOP); //top - glVertex3fv((nc+nv1).mV); - glVertex3fv((nc+nv2).mV); - glVertex3fv((nc+nv3).mV); - glVertex3fv((nc+nv4).mV); - glEnd(); + const LLVector3* ext; + LLVector3 pos, size; - glBegin(GL_LINE_LOOP); //bottom - glVertex3fv((nc-nv1).mV); - glVertex3fv((nc-nv2).mV); - glVertex3fv((nc-nv3).mV); - glVertex3fv((nc-nv4).mV); - glEnd(); + //render face bounding boxes + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + ext = facep->mExtents; - glBegin(GL_LINES); + if (ext[0].isExactlyZero() && ext[1].isExactlyZero()) + { + continue; + } + pos = (ext[0] + ext[1]) * 0.5f; + size = (ext[1] - ext[0]) * 0.5f; + drawBoxOutline(pos,size); + } - //right - glVertex3fv((nc+nv1).mV); - glVertex3fv((nc-nv3).mV); - - glVertex3fv((nc+nv4).mV); - glVertex3fv((nc-nv2).mV); + //render drawable bounding box + ext = drawable->getSpatialExtents(); - //left - glVertex3fv((nc+nv2).mV); - glVertex3fv((nc-nv4).mV); + pos = (ext[0] + ext[1]) * 0.5f; + size = (ext[1] - ext[0]) * 0.5f; + + drawBoxOutline(pos,size); +} - glVertex3fv((nc+nv3).mV); - glVertex3fv((nc-nv1).mV); - glEnd();*/ +void renderTexturePriority(LLDrawable* drawable) +{ + for (int face=0; facegetNumFaces(); ++face) + { + LLFace *facep = drawable->getFace(face); + + LLVector4 cold(0,0,0.25f); + LLVector4 hot(1,0.25f,0.25f); + + LLVector4 boost_cold(0,0,0,0); + LLVector4 boost_hot(0,1,0,1); + + LLGLDisable blend(GL_BLEND); + + //LLViewerImage* imagep = facep->getTexture(); + //if (imagep) + { + + //F32 vsize = LLVOVolume::getTextureVirtualSize(facep); + //F32 vsize = imagep->mMaxVirtualSize; + F32 vsize = facep->getPixelArea(); - glLineWidth(1); - - glDepthMask(GL_FALSE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4f(0.1f,0.1f,1,0.1f); - drawBox(group->mObjectBounds[0], group->mObjectBounds[1]*1.01f+LLVector3(0.001f, 0.001f, 0.001f)); - glDepthMask(GL_TRUE); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + if (vsize > sCurMaxTexPriority) + { + sCurMaxTexPriority = vsize; } + + F32 t = vsize/sLastMaxTexPriority; + + LLVector4 col = lerp(cold, hot, t); + glColor4fv(col.mV); } - /*else + //else + //{ + // glColor4f(1,0,1,1); + //} + + + + LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f; + LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f); + drawBox(center, size); + + /*S32 boost = imagep->getBoostLevel(); + if (boost) + { + F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1); + LLVector4 col = lerp(boost_cold, boost_hot, t); + LLGLEnable blend_on(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE); + glColor4fv(col.mV); + drawBox(center, size); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + }*/ + } +} + +void renderPoints(LLDrawable* drawablep) +{ + LLGLDepthTest depth(GL_FALSE, GL_FALSE); + glBegin(GL_POINTS); + glColor3f(1,1,1); + LLVector3 center(drawablep->getPositionGroup()); + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + glVertex3fv(drawablep->getFace(i)->mCenterLocal.mV); + } + glEnd(); +} + +void renderTextureAnim(LLDrawInfo* params) +{ + if (!params->mTextureMatrix) + { + return; + } + + LLGLEnable blend(GL_BLEND); + glColor4f(1,1,0,0.5f); + pushVerts(params, LLVertexBuffer::MAP_VERTEX); +} + +class LLOctreeRenderNonOccluded : public LLOctreeTraveler +{ +public: + LLOctreeRenderNonOccluded() {} + + virtual void traverse(const LLSpatialGroup::OctreeNode* node) + { + const LLSpatialGroup::OctreeState* state = node->getOctState(); + LLSpatialGroup* group = (LLSpatialGroup*) node->getListener(0); + + + if ((!gPipeline.sUseOcclusion || !group->isState(LLSpatialGroup::OCCLUDED)) && + !group->isState(LLSpatialGroup::CULLED)) { - //occlusion paranoia check - const LLSpatialGroup::OctreeNode* parent = node; - while (parent != NULL) + state->accept(this); + + for (U32 i = 0; i < state->getChildCount(); i++) { - LLSpatialGroup* grp = (LLSpatialGroup*) parent->getListener(0); - if (grp->isState(LLSpatialGroup::ACTIVE_OCCLUSION)) - { - return; - } - parent = (const LLSpatialGroup::OctreeNode*) parent->getParent(); + traverse(state->getChild(i)); + } + + //draw tight fit bounding boxes for spatial group + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) + { + renderOctree(group); } - glColor4f(1,0,1,1); - drawBox(group->mBounds[0], group->mBounds[1]); - }*/ + //render visibility wireframe + if (group->mSpatialPartition->mRenderByGroup && + gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && + !group->isState(LLSpatialGroup::GEOM_DIRTY)) + { + renderVisibility(group); + } + } } virtual void visit(const LLSpatialGroup::OctreeState* branch) @@ -1816,276 +2632,37 @@ public: LLVector3 nodeCenter = group->mBounds[0]; LLVector3 octCenter = LLVector3(group->mOctreeNode->getCenter()); - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCTREE)) - { - glBegin(GL_LINES); - glColor4f(1,0.5f,0,1); - glVertex3fv(nodeCenter.mV); - glColor4f(0,1,1,0); - glVertex3fv(octCenter.mV); - glEnd(); - } - for (LLSpatialGroup::OctreeState::const_element_iter i = branch->getData().begin(); i != branch->getData().end(); ++i) { LLDrawable* drawable = *i; - - if (drawable->isSpatialBridge()) - { - LLSpatialBridge* bridge = (LLSpatialBridge*) drawable; - glPushMatrix(); - glMultMatrixf((F32*)bridge->mDrawable->getWorldMatrix().mMatrix); - traverse(bridge->mOctree); - glPopMatrix(); - } - - if (!drawable->isVisible()) - { - continue; - } - + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_BBOXES)) { - if (drawable->isSpatialBridge()) - { - glColor4f(1,0.5f,0,1); - } - else if (drawable->getVOVolume()) - { - if (drawable->isRoot()) - { - glColor4f(1,1,0,1); - } - else - { - glColor4f(0,1,0,1); - } - } - else if (drawable->getVObj()) - { - switch (drawable->getVObj()->getPCode()) - { - case LLViewerObject::LL_VO_SURFACE_PATCH: - glColor4f(0,1,1,1); - break; - case LLViewerObject::LL_VO_CLOUDS: - glColor4f(0.5f,0.5f,0.5f,1.0f); - break; - case LLViewerObject::LL_VO_PART_GROUP: - glColor4f(0,0,1,1); - break; - case LLViewerObject::LL_VO_WATER: - glColor4f(0,0.5f,1,1); - break; - case LL_PCODE_LEGACY_TREE: - glColor4f(0,0.5f,0,1); - default: - glColor4f(1,0,1,1); - break; - } - } - else - { - glColor4f(1,0,0,1); - } - - - const LLVector3* ext = drawable->getSpatialExtents(); - - LLVector3 pos = (ext[0] + ext[1]) * 0.5f; - LLVector3 size = (ext[1] - ext[0]) * 0.5f; - - LLVector3 v1 = size.scaledVec(LLVector3( 1, 1,1)); - LLVector3 v2 = size.scaledVec(LLVector3(-1, 1,1)); - LLVector3 v3 = size.scaledVec(LLVector3(-1,-1,1)); - LLVector3 v4 = size.scaledVec(LLVector3( 1,-1,1)); - - glBegin(GL_LINE_LOOP); //top - glVertex3fv((pos+v1).mV); - glVertex3fv((pos+v2).mV); - glVertex3fv((pos+v3).mV); - glVertex3fv((pos+v4).mV); - glEnd(); - - glBegin(GL_LINE_LOOP); //bottom - glVertex3fv((pos-v1).mV); - glVertex3fv((pos-v2).mV); - glVertex3fv((pos-v3).mV); - glVertex3fv((pos-v4).mV); - glEnd(); - - - glBegin(GL_LINES); - - //right - glVertex3fv((pos+v1).mV); - glVertex3fv((pos-v3).mV); - - glVertex3fv((pos+v4).mV); - glVertex3fv((pos-v2).mV); - - //left - glVertex3fv((pos+v2).mV); - glVertex3fv((pos-v4).mV); - - glVertex3fv((pos+v3).mV); - glVertex3fv((pos-v1).mV); - - glEnd(); - - //render space partition trace - glBegin(GL_LINE_STRIP); - glColor4f(1,0,0,1); - glVertex3fv(pos.mV); - glColor4f(0,1,0,1); - glVertex3dv(drawable->getPositionGroup().mdV); - glColor4f(0,0,1,1); - glVertex3fv(nodeCenter.mV); - glColor4f(1,1,0,1); - glVertex3fv(octCenter.mV); - glEnd(); + renderBoundingBox(drawable); } - if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_CHAINS | LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + if (drawable->getVOVolume() && gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { - glLineWidth(3); - - for (int face=0; facegetNumFaces(); ++face) - { - LLFace *facep = drawable->getFace(face); - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_CHAINS)) - { - LLGLDepthTest depth(GL_FALSE); - if (facep->mNextFace) - { - glBegin(GL_LINE_STRIP); - - if (facep->isState(LLFace::GLOBAL)) - { - glColor4f(0,1,0,1); - } - else - { - glColor4f(1,0.5f,0.25f,1); - } - - if (drawable->isActive()) - { - glVertex3fv(facep->mCenterLocal.mV); - glVertex3fv(facep->mNextFace->mCenterLocal.mV); - } - else - { - glVertex3fv(facep->mCenterAgent.mV); - glVertex3fv(facep->mNextFace->mCenterAgent.mV); - } - - glEnd(); - } - else - { - glPointSize(5); - glBegin(GL_POINTS); - - if (!facep->isState(LLFace::GLOBAL)) - { - glColor4f(1,0.75f,0,1); - glVertex3fv(facep->mCenterLocal.mV); - } - else - { - glColor4f(0,0.75f,1,1); - glVertex3fv(facep->mCenterAgent.mV); - } - - glEnd(); - glPointSize(1); - } - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) - { - LLVector4 cold(0,0,0.25f); - LLVector4 hot(1,0.25f,0.25f); - - LLVector4 boost_cold(0,0,0,0); - LLVector4 boost_hot(0,1,0,1); - - LLGLDisable blend(GL_BLEND); - - LLViewerImage* imagep = facep->getTexture(); - if (imagep) - { - - //F32 vsize = LLVOVolume::getTextureVirtualSize(facep); - F32 vsize = imagep->mMaxVirtualSize; - - if (vsize > sCurMaxTexPriority) - { - sCurMaxTexPriority = vsize; - } - - F32 t = vsize/sLastMaxTexPriority; - - LLVector4 col = lerp(cold, hot, t); - glColor4fv(col.mV); - } - else - { - glColor4f(1,0,1,1); - } - - LLVector3 center = (facep->mExtents[1]+facep->mExtents[0])*0.5f; - LLVector3 size = (facep->mExtents[1]-facep->mExtents[0])*0.5f + LLVector3(0.01f, 0.01f, 0.01f); - drawBox(center, size); - - S32 boost = imagep->getBoostLevel(); - if (boost) - { - F32 t = (F32) boost / (F32) (LLViewerImage::BOOST_MAX_LEVEL-1); - LLVector4 col = lerp(boost_cold, boost_hot, t); - LLGLEnable blend_on(GL_BLEND); - glBlendFunc(GL_SRC_ALPHA, GL_ONE); - glColor4fv(col.mV); - drawBox(center, size); - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); - } - - } - } + renderTexturePriority(drawable); } - + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_POINTS)) { - glPointSize(4); - glColor4f(1,1,1,1); - glBegin(GL_POINTS); - S32 num_faces = drawable->getNumFaces(); - for (S32 i = 0; i < num_faces; i++) + renderPoints(drawable); + } + } + + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + std::vector& draw_vec = i->second; + for (std::vector::iterator j = draw_vec.begin(); j != draw_vec.end(); ++j) + { + LLDrawInfo* draw_info = *j; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) { - LLStrider vertices; - drawable->getFace(i)->getVertices(vertices); - - LLFace* face = drawable->getFace(i); - - for (S32 v = 0; v < (S32)drawable->getFace(i)->getGeomCount(); v++) - { - if (!face->getDrawable()->isActive()) - { - //glVertex3fv(vertices[v].mV); - } - else - { - glVertex3fv((vertices[v]*face->getRenderMatrix()).mV); - } - } + renderTextureAnim(draw_info); } - glEnd(); - glPointSize(1); } - - glLineWidth(1); } } }; @@ -2096,8 +2673,8 @@ void LLSpatialPartition::renderDebug() LLPipeline::RENDER_DEBUG_OCCLUSION | LLPipeline::RENDER_DEBUG_BBOXES | LLPipeline::RENDER_DEBUG_POINTS | - LLPipeline::RENDER_DEBUG_FACE_CHAINS | - LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY | + LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)) { return; } @@ -2105,7 +2682,7 @@ void LLSpatialPartition::renderDebug() if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) { //sLastMaxTexPriority = lerp(sLastMaxTexPriority, sCurMaxTexPriority, gFrameIntervalSeconds); - sLastMaxTexPriority = sCurMaxTexPriority; + sLastMaxTexPriority = (F32) gCamera->getScreenPixelArea(); sCurMaxTexPriority = 0.f; } @@ -2119,78 +2696,50 @@ void LLSpatialPartition::renderDebug() LLOctreeRenderNonOccluded render_debug; render_debug.traverse(mOctree); - - LLGLDisable cull_face(GL_CULL_FACE); - { - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - //draw frustum - glColor4f(0,0,1,0.5f); - glBegin(GL_QUADS); - //glVertex3fv(gCamera->mAgentFrustum[0].mV); - //glVertex3fv(gCamera->mAgentFrustum[1].mV); - //glVertex3fv(gCamera->mAgentFrustum[2].mV); - //glVertex3fv(gCamera->mAgentFrustum[3].mV); + LLGLDisable cull_face(GL_CULL_FACE); - //glVertex3fv(gCamera->mAgentFrustum[4].mV); - //glVertex3fv(gCamera->mAgentFrustum[5].mV); - //glVertex3fv(gCamera->mAgentFrustum[6].mV); - //glVertex3fv(gCamera->mAgentFrustum[7].mV); - - glVertex3fv(gCamera->mAgentFrustum[0].mV); - glVertex3fv(gCamera->mAgentFrustum[1].mV); - glVertex3fv(gCamera->mAgentFrustum[5].mV); - glVertex3fv(gCamera->mAgentFrustum[4].mV); - - glVertex3fv(gCamera->mAgentFrustum[1].mV); - glVertex3fv(gCamera->mAgentFrustum[2].mV); - glVertex3fv(gCamera->mAgentFrustum[6].mV); - glVertex3fv(gCamera->mAgentFrustum[5].mV); - - glVertex3fv(gCamera->mAgentFrustum[2].mV); - glVertex3fv(gCamera->mAgentFrustum[3].mV); - glVertex3fv(gCamera->mAgentFrustum[7].mV); - glVertex3fv(gCamera->mAgentFrustum[6].mV); - - glVertex3fv(gCamera->mAgentFrustum[3].mV); - glVertex3fv(gCamera->mAgentFrustum[0].mV); - glVertex3fv(gCamera->mAgentFrustum[4].mV); - glVertex3fv(gCamera->mAgentFrustum[7].mV); - - glEnd(); - } - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION)) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_OCCLUSION) && !mOccludedList.empty() && + mOcclusionIndices.notNull()) { LLGLDisable fog(GL_FOG); LLGLDepthTest gls_depth(GL_FALSE); glBlendFunc(GL_SRC_ALPHA, GL_ONE); + mOcclusionIndices->setBuffer(0); + U32* indicesp = (U32*) mOcclusionIndices->getIndicesPointer(); - for (std::vector::iterator i = mOccludedList.begin(); i != mOccludedList.end(); ++i) + LLGLEnable blend(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + LLGLEnable cull(GL_CULL_FACE); + glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + + for (U32 i = 0; i < mOccludedList.size(); i++) { //draw occluded nodes - LLSpatialGroup* node = *i; - if (node->isDead()) + LLSpatialGroup* node = mOccludedList[i]; + if (node->isDead() || + !node->isState(LLSpatialGroup::OCCLUDED) || + node->mOcclusionVerts.isNull()) { continue; } - if (!node->isState(LLSpatialGroup::OCCLUDED)) + + node->mOcclusionVerts->setBuffer(LLVertexBuffer::MAP_VERTEX); { - continue; + LLGLDepthTest depth_under(GL_TRUE, GL_FALSE, GL_GREATER); + glColor4f(0.5, 0.5f, 0, 0.25f); + glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, + GL_UNSIGNED_INT, indicesp); } - else + { - glColor4f(0.25f,0.125f,0.1f,0.125f); + LLGLDepthTest depth_over(GL_TRUE, GL_FALSE, GL_LEQUAL); + glColor4f(0.0,1.0f,1.0f,1.0f); + glDrawRangeElements(GL_TRIANGLES, 0, 7, 36, + GL_UNSIGNED_INT, indicesp); } - LLVector3 c; - LLVector3 r; - - c = node->mBounds[0]; - r = node->mBounds[1]*SG_OCCLUSION_FUDGE + LLVector3(0.01f,0.01f,0.01f);; - - drawBox(c,r); } - glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); + + glPolygonMode(GL_FRONT_AND_BACK, GL_FILL); } } @@ -2272,3 +2821,27 @@ LLDrawable* LLSpatialPartition::pickDrawable(const LLVector3& start, const LLVec collision.setVec(pick.mEnd); return ret; } + +LLDrawInfo::LLDrawInfo(U32 start, U32 end, U32 count, U32 offset, + LLViewerImage* texture, LLVertexBuffer* buffer, + BOOL fullbright, U8 bump, BOOL particle, F32 part_size) +: + mVertexBuffer(buffer), + mTexture(texture), + mTextureMatrix(NULL), + mStart(start), + mEnd(end), + mCount(count), + mOffset(offset), + mFullbright(fullbright), + mBump(bump), + mParticle(particle), + mPartSize(part_size), + mVSize(0.f) +{ +} + +LLVertexBuffer* LLGeometryManager::createVertexBuffer(U32 type_mask, U32 usage) +{ + return new LLVertexBuffer(type_mask, usage); +} diff --git a/linden/indra/newview/llspatialpartition.h b/linden/indra/newview/llspatialpartition.h index 737029a..5804a57 100644 --- a/linden/indra/newview/llspatialpartition.h +++ b/linden/indra/newview/llspatialpartition.h @@ -33,26 +33,77 @@ #include "llmemory.h" #include "lldrawable.h" #include "lloctree.h" +#include "llvertexbuffer.h" #include "llgltypes.h" +#include "llcubemap.h" #include -class LLCullInfo +#define SG_STATE_INHERIT_MASK (CULLED | OCCLUDED) +#define SG_INITIAL_STATE_MASK (OCCLUSION_DIRTY | DIRTY | GEOM_DIRTY) + +class LLSpatialPartition; +class LLSpatialBridge; + +class LLDrawInfo { public: - LLVector3 mPos; - F32 mRadius; - LLPointer mDrawablep; -}; + LLDrawInfo(U32 start, U32 end, U32 count, U32 offset, + LLViewerImage* image, LLVertexBuffer* buffer, + BOOL fullbright = FALSE, U8 bump = 0, BOOL particle = FALSE, F32 part_size = 0); + + LLPointer mVertexBuffer; + LLPointer mTexture; + LLPointer mReflectionMap; + LLColor4U mGlowColor; + const LLMatrix4* mTextureMatrix; + U32 mStart; + U32 mEnd; + U32 mCount; + U32 mOffset; + BOOL mFullbright; + U8 mBump; + BOOL mParticle; + F32 mPartSize; + F32 mVSize; + + struct CompareTexture + { + bool operator()(const LLDrawInfo& lhs, const LLDrawInfo& rhs) + { + return lhs.mTexture > rhs.mTexture; + } + }; -#define SG_STATE_INHERIT_MASK (CULLED | OCCLUDED) -class LLSpatialPartition; + struct CompareTexturePtr + { + bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs) + { + + return lhs == NULL || rhs == NULL || lhs->mTexture > rhs->mTexture; + } + }; + + struct CompareBump + { + bool operator()(const LLDrawInfo* const& lhs, const LLDrawInfo* const& rhs) + { + return lhs == NULL || rhs == NULL || lhs->mBump > rhs->mBump; + } + }; +}; class LLSpatialGroup : public LLOctreeListener { friend class LLSpatialPartition; public: + typedef std::vector > sg_vector_t; + typedef std::set > sg_set_t; + typedef std::vector > bridge_list_t; + typedef std::map > draw_map_t; + typedef std::map, LLPointer > buffer_map_t; + typedef LLOctreeListener BaseType; typedef LLOctreeListener OctreeListener; typedef LLTreeNode TreeNode; @@ -60,6 +111,24 @@ public: typedef LLOctreeRoot OctreeRoot; typedef LLOctreeState OctreeState; typedef LLOctreeTraveler OctreeTraveler; + typedef LLOctreeState::element_iter element_iter; + typedef LLOctreeState::element_list element_list; + + struct CompareDistanceGreater + { + bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) + { + return lhs->mDistance > rhs->mDistance; + } + }; + + struct CompareDepthGreater + { + bool operator()(const LLSpatialGroup* const& lhs, const LLSpatialGroup* const& rhs) + { + return lhs->mDepth > rhs->mDepth; + } + }; typedef enum { @@ -75,10 +144,17 @@ public: RESHADOW_QUEUE = 0x00000200, DIRTY = 0x00000400, OBJECT_DIRTY = 0x00000800, - DISCARD_QUERY = 0x00001000, - QUERY_OUT = 0x00002000, - OCCLUDING = 0x00004000, - SKIP_FRUSTUM_CHECK = 0x00008000, + GEOM_DIRTY = 0x00001000, + MATRIX_DIRTY = 0x00002000, + ALPHA_DIRTY = 0x00004000, + DISCARD_QUERY = 0x00008000, + QUERY_OUT = 0x00010000, + OCCLUDING = 0x00020000, + SKIP_FRUSTUM_CHECK = 0x00040000, + OCCLUSION_DIRTY = 0x00080000, + BELOW_WATER = 0x00100000, + IN_IMAGE_QUEUE = 0x00200000, + IMAGE_DIRTY = 0x00400000, } eSpatialState; typedef enum @@ -89,20 +165,21 @@ public: } eSetStateMode; LLSpatialGroup(OctreeNode* node, LLSpatialPartition* part); - BOOL safeToDelete(); virtual ~LLSpatialGroup(); - S32 getCount() const { return mObjects.size(); } BOOL isDead() { return isState(DEAD); } BOOL isState(U32 state) const { return mState & state ? TRUE : FALSE; } U32 getState() { return mState; } void setState(U32 state) { mState |= state; } void clearState(U32 state) { mState &= ~state; } + void clearDrawMap(); void validate(); - + void validateDrawMap(); + void setState(U32 state, S32 mode); + LLSpatialGroup* getParent(); void clearState(U32 state, S32 mode); BOOL addObject(LLDrawable *drawablep, BOOL add_all = FALSE, BOOL from_octree = FALSE); @@ -113,8 +190,16 @@ public: BOOL boundObjects(BOOL empty, LLVector3& newMin, LLVector3& newMax); void unbound(); BOOL rebound(); + void destroyGL(); + + void updateDistance(LLCamera& camera); BOOL changeLOD(); - + void rebuildGeom(); + void makeStatic(); + + void dirtyGeom() { setState(GEOM_DIRTY); } + element_list& getData() { return mOctreeNode->getOctState()->getData(); } + //LISTENER FUNCTIONS virtual void handleInsertion(const TreeNode* node, LLDrawable* face); virtual void handleRemoval(const TreeNode* node, LLDrawable* face); @@ -124,12 +209,15 @@ public: virtual void handleChildRemoval(const OctreeNode* parent, const OctreeNode* child); protected: - std::vector mObjects; U32 mState; S32 mLODHash; static S32 sLODSeed; public: + bridge_list_t mBridgeList; + buffer_map_t mBufferMap; //used by volume buffers to store unique buffers per texture + + F32 mBuilt; OctreeNode* mOctreeNode; LLSpatialPartition* mSpatialPartition; LLVector3 mBounds[2]; @@ -137,69 +225,130 @@ public: LLVector3 mObjectExtents[2]; LLVector3 mObjectBounds[2]; + LLPointer mVertexBuffer; + LLPointer mOcclusionVerts; + LLPointer mReflectionMap; + + U32 mBufferUsage; + draw_map_t mDrawMap; + + U32 mVertexCount; + U32 mIndexCount; + F32 mDistance; + F32 mDepth; + F32 mLastUpdateDistance; + F32 mLastUpdateTime; + F32 mLastAddTime; + F32 mLastRenderTime; + + LLVector3 mViewAngle; + LLVector3 mLastUpdateViewAngle; + + F32 mPixelArea; + F32 mRadius; }; -class LLSpatialPartition +class LLGeometryManager { public: - LLSpatialPartition(); + std::vector mFaceList; + virtual ~LLGeometryManager() { } + virtual void rebuildGeom(LLSpatialGroup* group) = 0; + virtual void getGeometry(LLSpatialGroup* group) = 0; + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count); + virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); +}; + +class LLSpatialPartition: public LLGeometryManager +{ +public: + LLSpatialPartition(U32 data_mask, BOOL is_volatile = FALSE, U32 mBufferUsage = GL_STATIC_DRAW_ARB); virtual ~LLSpatialPartition(); - LLSpatialGroup *put(LLDrawable *drawablep); + LLSpatialGroup *put(LLDrawable *drawablep, BOOL was_visible = FALSE); BOOL remove(LLDrawable *drawablep, LLSpatialGroup *curp); LLDrawable* pickDrawable(const LLVector3& start, const LLVector3& end, LLVector3& collision); // If the drawable moves, move it here. virtual void move(LLDrawable *drawablep, LLSpatialGroup *curp, BOOL immediate = FALSE); - void shift(const LLVector3 &offset); + virtual void shift(const LLVector3 &offset); + + virtual F32 calcDistance(LLSpatialGroup* group, LLCamera& camera); + virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); + + virtual void rebuildGeom(LLSpatialGroup* group); S32 cull(LLCamera &camera, std::vector* results = NULL, BOOL for_select = FALSE); // Cull on arbitrary frustum BOOL checkOcclusion(LLSpatialGroup* group, LLCamera* camera); + void markReimage(LLSpatialGroup* group); + void processImagery(LLCamera* camera); void processOcclusion(LLCamera* camera); + void buildOcclusion(); void doOcclusion(LLCamera* camera); BOOL isVisible(const LLVector3& v); - + BOOL isVolatile() const { return mVolatile; } + + virtual LLSpatialBridge* asBridge() { return NULL; } + virtual BOOL isBridge() { return asBridge() != NULL; } + S32 getObjects(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results ); S32 getLights(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results ); void renderDebug(); void restoreGL(); + void resetVertexBuffers(); protected: S32 getDrawables(const LLVector3& pos, F32 rad, LLDrawable::drawable_set_t &results, BOOL get_lights ); - LLSpatialGroup *mLastAddedGroupp; - - typedef std::set spatial_group_set_t; + typedef std::set > spatial_group_set_t; spatial_group_set_t mSpatialGroups; //things that might be occluded - std::queue mOcclusionQueue; + typedef std::queue > spatial_group_queue_t; + spatial_group_queue_t mOcclusionQueue; + + //things that need an image update + spatial_group_queue_t mImageQueue; //things awaiting query - std::queue mQueryQueue; + spatial_group_queue_t mQueryQueue; std::vector mOcclusionQueries; public: LLSpatialGroup::OctreeNode* mOctree; - //things that are occluded - std::vector mOccludedList; - - std::queue mReshadowQueue; + U32 mBufferUsage; + BOOL mRenderByGroup; + BOOL mImageEnabled; + U32 mLODSeed; + U32 mLODPeriod; + U32 mVertexDataMask; + F32 mSlopRatio; //percentage distance must change before drawables receive LOD update (default is 0.25); + BOOL mVolatile; //if TRUE, occlusion queries will be discarded when nodes change size + BOOL mDepthMask; //if TRUE, objects in this partition will be written to depth during alpha rendering + U32 mDrawableType; + U32 mPartitionType; + + //index buffer for occlusion verts + LLPointer mOcclusionIndices; + //things that are occluded + std::vector > mOccludedList; }; // class for creating bridges between spatial partitions class LLSpatialBridge : public LLDrawable, public LLSpatialPartition { public: - LLSpatialBridge(LLDrawable* root); + typedef std::vector > bridge_vector_t; + + LLSpatialBridge(LLDrawable* root, U32 data_mask); virtual ~LLSpatialBridge(); - virtual BOOL isSpatialBridge() const { return TRUE; } + virtual BOOL isSpatialBridge() const { return TRUE; } virtual void updateSpatialExtents(); virtual void updateBinRadius(); @@ -212,11 +361,123 @@ public: virtual void shiftPos(const LLVector3& vec); virtual void cleanupReferences(); virtual LLSpatialPartition* asPartition() { return this; } - LLCamera transformCamera(LLCamera& camera); + virtual LLSpatialBridge* asBridge() { return this; } + + virtual LLCamera transformCamera(LLCamera& camera); LLDrawable* mDrawable; }; +//spatial partition for water (implemented in LLVOWater.cpp) +class LLWaterPartition : public LLSpatialPartition +{ +public: + LLWaterPartition(); + virtual void getGeometry(LLSpatialGroup* group) { } + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } +}; + +//spatial partition for terrain (impelmented in LLVOSurfacePatch.cpp) +class LLTerrainPartition : public LLSpatialPartition +{ +public: + LLTerrainPartition(); + virtual void getGeometry(LLSpatialGroup* group); + virtual LLVertexBuffer* createVertexBuffer(U32 type_mask, U32 usage); +}; + +//spatial partition for trees +class LLTreePartition : public LLSpatialPartition +{ +public: + LLTreePartition(); + virtual void getGeometry(LLSpatialGroup* group) { } + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } + +}; + +//spatial partition for particles (implemented in LLVOPartGroup.cpp) +class LLParticlePartition : public LLSpatialPartition +{ +public: + LLParticlePartition(); + virtual void getGeometry(LLSpatialGroup* group); + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count); + virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); +protected: + U32 mRenderPass; +}; + +//spatial partition for grass (implemented in LLVOGrass.cpp) +class LLGrassPartition : public LLParticlePartition +{ +public: + LLGrassPartition(); +}; + +//spatial partition for clouds (implemented in LLVOClouds.cpp) +class LLCloudPartition : public LLParticlePartition +{ +public: + LLCloudPartition(); +}; + +//class for wrangling geometry out of volumes (implemented in LLVOVolume.cpp) +class LLVolumeGeometryManager: public LLGeometryManager +{ +public: + virtual ~LLVolumeGeometryManager() { } + virtual void rebuildGeom(LLSpatialGroup* group); + virtual void getGeometry(LLSpatialGroup* group); + void registerFace(LLSpatialGroup* group, LLFace* facep, U32 type); +}; + +//spatial partition that uses volume geometry manager (implemented in LLVOVolume.cpp) +class LLVolumePartition : public LLSpatialPartition, public LLVolumeGeometryManager +{ +public: + LLVolumePartition(); + virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } + virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } +}; + +//spatial bridge that uses volume geometry manager (implemented in LLVOVolume.cpp) +class LLVolumeBridge : public LLSpatialBridge, public LLVolumeGeometryManager +{ +public: + LLVolumeBridge(LLDrawable* drawable); + virtual void rebuildGeom(LLSpatialGroup* group) { LLVolumeGeometryManager::rebuildGeom(group); } + virtual void getGeometry(LLSpatialGroup* group) { LLVolumeGeometryManager::getGeometry(group); } + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { LLVolumeGeometryManager::addGeometryCount(group, vertex_count, index_count); } +}; + +class LLHUDBridge : public LLVolumeBridge +{ +public: + LLHUDBridge(LLDrawable* drawablep); + virtual void shiftPos(const LLVector3& vec); + virtual F32 calcPixelArea(LLSpatialGroup* group, LLCamera& camera); +}; + +//spatial partition that holds nothing but spatial bridges +class LLBridgePartition : public LLSpatialPartition +{ +public: + LLBridgePartition(); + virtual void getGeometry(LLSpatialGroup* group) { } + virtual void addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32& index_count) { } +}; + +class LLHUDPartition : public LLBridgePartition +{ +public: + LLHUDPartition(); + virtual void shift(const LLVector3 &offset); +}; + +void validate_draw_info(LLDrawInfo& params); + extern const F32 SG_BOX_SIDE; extern const F32 SG_BOX_OFFSET; extern const F32 SG_BOX_RAD; diff --git a/linden/indra/newview/llsphere.cpp b/linden/indra/newview/llsphere.cpp index 44eaeff..5c49e6e 100644 --- a/linden/indra/newview/llsphere.cpp +++ b/linden/indra/newview/llsphere.cpp @@ -32,7 +32,7 @@ #include "llviewerprecompiledheaders.h" #include "llsphere.h" #include "llerror.h" - +#include "llvertexbuffer.h" #include "llglheaders.h" GLUquadricObj *gQuadObj2 = NULL; @@ -167,11 +167,13 @@ void LLSphere::render(F32 pixel_area) { level_of_detail = 3; } + LLVertexBuffer::unbind(); glCallList(mDList[level_of_detail]); } void LLSphere::render() { + LLVertexBuffer::unbind(); glCallList(mDList[0]); } diff --git a/linden/indra/newview/llsprite.cpp b/linden/indra/newview/llsprite.cpp index 601810c..fb56f4d 100644 --- a/linden/indra/newview/llsprite.cpp +++ b/linden/indra/newview/llsprite.cpp @@ -94,14 +94,7 @@ void LLSprite::updateFace(LLFace &face) // First, figure out how many vertices/indices we need. U32 num_vertices, num_indices; U32 vertex_count = 0; - - - LLStrider verticesp; - LLStrider normalsp; - LLStrider tex_coordsp; - U32 *indicesp; - S32 index_offset; - + // Get the total number of vertices and indices if (mFollow) { @@ -114,14 +107,7 @@ void LLSprite::updateFace(LLFace &face) num_indices = 12; } - // Setup face - face.setPrimType(LLTriangles); face.setSize(num_vertices, num_indices); - index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp); - if (-1 == index_offset) - { - return; - } if (mFollow) { @@ -206,7 +192,30 @@ void LLSprite::updateFace(LLFace &face) } face.setFaceColor(mColor); - + + LLStrider verticesp; + LLStrider normalsp; + LLStrider tex_coordsp; + LLStrider indicesp; + S32 index_offset; + + // Setup face + if (face.mVertexBuffer.isNull()) + { + face.mVertexBuffer = new LLVertexBuffer(LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD, + GL_STREAM_DRAW_ARB); + face.mVertexBuffer->allocateBuffer(4, 12, TRUE); + face.setGeomIndex(0); + face.setIndicesIndex(0); + } + + index_offset = face.getGeometry(verticesp,normalsp,tex_coordsp, indicesp); + if (-1 == index_offset) + { + return; + } + *tex_coordsp = LLVector2(0.f, 0.f); *verticesp = mC; tex_coordsp++; @@ -251,6 +260,7 @@ void LLSprite::updateFace(LLFace &face) *indicesp++ = 3 + index_offset; } + //face.mVertexBuffer->setBuffer(0); face.mCenterAgent = mPosition; } diff --git a/linden/indra/newview/llstartup.cpp b/linden/indra/newview/llstartup.cpp index 916db16..cfdf899 100644 --- a/linden/indra/newview/llstartup.cpp +++ b/linden/indra/newview/llstartup.cpp @@ -44,9 +44,9 @@ #include "audiosettings.h" #include "llcachename.h" #include "llviewercontrol.h" -#include "llcrypto.h" #include "lldir.h" #include "lleconomy.h" +#include "llerrorcontrol.h" #include "llfiltersd2xmlrpc.h" #include "llfocusmgr.h" #include "imageids.h" @@ -64,6 +64,7 @@ #include "llversion.h" #include "llvfs.h" #include "llwindow.h" // for shell_open +#include "llxorcipher.h" // saved password, MAC address #include "message.h" #include "v3math.h" @@ -81,7 +82,6 @@ #include "lleventnotifier.h" #include "llface.h" #include "llfeaturemanager.h" -#include "llfloateraccounthistory.h" #include "llfloaterchat.h" #include "llfloatergesture.h" #include "llfloaterland.h" @@ -118,6 +118,8 @@ #include "llsky.h" #include "llstatview.h" #include "llsurface.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" #include "lltoolmgr.h" #include "llui.h" #include "llurlwhitelist.h" @@ -145,10 +147,13 @@ #include "viewer.h" #include "llmediaengine.h" #include "llfasttimerview.h" -#include "llmozlib.h" #include "llweb.h" #include "llfloaterhtml.h" +#if LL_LIBXUL_ENABLED +#include "llmozlib.h" +#endif // LL_LIBXUL_ENABLED + #if LL_WINDOWS #include "llwindebug.h" #include "lldxhardware.h" @@ -183,7 +188,6 @@ const char* SCREEN_LAST_FILENAME = "screen_last.bmp"; // // Imported globals // -extern LLPointer gStartImageGL; extern S32 gStartImageWidth; extern S32 gStartImageHeight; extern std::string gSerialNumber; @@ -192,6 +196,8 @@ extern std::string gSerialNumber; // local globals // +LLPointer gStartImageGL; + static LLHost gAgentSimHost; static BOOL gSkipOptionalUpdate = FALSE; @@ -250,7 +256,13 @@ public: } }; - +void update_texture_fetch() +{ + gTextureCache->update(1); // unpauses the texture cache thread + gImageDecodeThread->update(1); // unpauses the image thread + gTextureFetch->update(1); // unpauses the texture fetch thread + gImageList.updateImages(0.10f); +} // Returns FALSE to skip other idle processing. Should only return // TRUE when all initialization done. @@ -301,8 +313,6 @@ BOOL idle_startup() static BOOL samename = FALSE; - static BOOL did_precache = FALSE; - BOOL do_normal_idle = FALSE; // HACK: These are things from the main loop that usually aren't done @@ -391,14 +401,22 @@ BOOL idle_startup() std::string message_template_path = gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS,"message_template.msg"); FILE* found_template = NULL; - found_template = LLFile::fopen(message_template_path.c_str(), "r"); + found_template = LLFile::fopen(message_template_path.c_str(), "r"); /* Flawfinder: ignore */ if (found_template) { fclose(found_template); + U32 port = gAgent.mViewerPort; + + if ((NET_USE_OS_ASSIGNED_PORT == port) && // if nothing specified on command line (-port) + (gSavedSettings.getBOOL("ConnectionPortEnabled"))) + { + port = gSavedSettings.getU32("ConnectionPort"); + } + if(!start_messaging_system( message_template_path, - gAgent.mViewerPort, + port, LL_VERSION_MAJOR, LL_VERSION_MINOR, LL_VERSION_PATCH, @@ -432,7 +450,6 @@ BOOL idle_startup() invalid_message_callback, NULL); - gErrorStream.setUTCTimestamp(gLogUTC); if (gSavedSettings.getBOOL("LogMessages") || gLogMessages) { llinfos << "Message logging activated!" << llendl; @@ -476,12 +493,13 @@ BOOL idle_startup() #if LL_LIBXUL_ENABLED set_startup_status(0.48f, "Initializing embedded web browser...", gAgent.mMOTD.c_str()); display_startup(); + llinfos << "Initializing embedded web browser..." << llendl; #if LL_DARWIN // For Mac OS, we store both the shared libraries and the runtime files (chrome/, plugins/, etc) in // Second Life.app/Contents/MacOS/. This matches the way Firefox is distributed on the Mac. std::string profileBaseDir(gDirUtilp->getExecutableDir()); - #else + #elif LL_WINDOWS std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); profileBaseDir += gDirUtilp->getDirDelimiter(); #ifdef LL_DEBUG @@ -489,8 +507,28 @@ BOOL idle_startup() #else profileBaseDir += "mozilla"; #endif + #elif LL_LINUX + std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); + profileBaseDir += gDirUtilp->getDirDelimiter(); + profileBaseDir += "mozilla-runtime-linux-i686"; + #else + std::string profileBaseDir( gDirUtilp->getExpandedFilename( LL_PATH_APP_SETTINGS, "" ) ); + profileBaseDir += gDirUtilp->getDirDelimiter(); + profileBaseDir += "mozilla"; #endif - LLMozLib::getInstance()->init( profileBaseDir, gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) ); + +#if LL_LINUX + // Yuck, Mozilla init plays with the locale - push/pop + // the locale to protect it, as exotic/non-C locales + // causes our code lots of general critical weirdness + // and crashness. (SL-35450) + char *saved_locale = setlocale(LC_ALL, NULL); +#endif // LL_LINUX + LLMozLib::getInstance()->init( profileBaseDir, gDirUtilp->getExpandedFilename( LL_PATH_MOZILLA_PROFILE, "" ) ); +#if LL_LINUX + if (saved_locale) + setlocale(LC_ALL, saved_locale); +#endif // LL_LINUX std::ostringstream codec; codec << "[Second Life " << LL_VERSION_MAJOR << "." << LL_VERSION_MINOR << "." << LL_VERSION_PATCH << "." << LL_VERSION_BUILD << "]"; @@ -556,7 +594,7 @@ BOOL idle_startup() lastname = gCmdLineLastName; LLMD5 pass((unsigned char*)gCmdLinePassword.c_str()); - char md5pass[33]; + char md5pass[33]; /* Flawfinder: ignore */ pass.hex_digest(md5pass); password = md5pass; @@ -728,7 +766,7 @@ BOOL idle_startup() if (gUserServerChoice == USERSERVER_OTHER) { gUserServer.setHostByName( server_label.c_str() ); - snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str()); + snprintf(gUserServerName, MAX_STRING, "%s", server_label.c_str()); /* Flawfinder: ignore */ } } @@ -814,11 +852,12 @@ BOOL idle_startup() case USERSERVER_SHAKTI: case USERSERVER_DURGA: case USERSERVER_SOMA: + case USERSERVER_VAAK: case USERSERVER_GANGA: case USERSERVER_UMA: { const char* host_name = gUserServerDomainName[gUserServerChoice].mName; - sprintf(gUserServerName,"%s", host_name); + snprintf(gUserServerName, MAX_STRING, "%s", host_name); /* Flawfinder: ignore */ llinfos << "Resolving " << gUserServerDomainName[gUserServerChoice].mLabel << " userserver domain name " << host_name << llendl; @@ -892,7 +931,7 @@ BOOL idle_startup() } write_debug("Userserver: "); - char tmp_str[256]; + char tmp_str[256]; /* Flawfinder: ignore */ gUserServer.getIPString(tmp_str, 256); write_debug(tmp_str); write_debug("\n"); @@ -1128,7 +1167,7 @@ BOOL idle_startup() start << "home"; } - char hashed_mac_string[MD5HEX_STR_SIZE]; + char hashed_mac_string[MD5HEX_STR_SIZE]; /* Flawfinder: ignore */ LLMD5 hashed_mac; hashed_mac.update( gMACAddress, MAC_ADDRESS_BYTES ); hashed_mac.finalize(); @@ -1442,7 +1481,7 @@ BOOL idle_startup() const char* look_at_str = gUserAuthp->getResponse("look_at"); if (look_at_str) { - LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str)); + LLMemoryStream mstr((U8*)look_at_str, strlen(look_at_str)); /* Flawfinder: ignore */ LLSD sd = LLSDNotationParser::parse(mstr); agent_start_look_at = ll_vector3_from_sd(sd); } @@ -1464,7 +1503,7 @@ BOOL idle_startup() const char* home_location = gUserAuthp->getResponse("home"); if(home_location) { - LLMemoryStream mstr((U8*)home_location, strlen(home_location)); + LLMemoryStream mstr((U8*)home_location, strlen(home_location)); /* Flawfinder: ignore */ LLSD sd = LLSDNotationParser::parse(mstr); S32 region_x = sd["region_handle"][0].asInteger(); S32 region_y = sd["region_handle"][1].asInteger(); @@ -1582,6 +1621,8 @@ BOOL idle_startup() args["[ERROR_MESSAGE]"] = emsg.str(); gViewerWindow->alertXml("ErrorMessage", args, login_alert_done); gStartupState = STATE_LOGIN_SHOW; + gAutoLogin = FALSE; + show_connect_box = TRUE; } } else @@ -1597,6 +1638,8 @@ BOOL idle_startup() args["[ERROR_MESSAGE]"] = emsg.str(); gViewerWindow->alertXml("ErrorMessage", args, login_alert_done); gStartupState = STATE_LOGIN_SHOW; + gAutoLogin = FALSE; + show_connect_box = TRUE; } return do_normal_idle; } @@ -1629,6 +1672,9 @@ BOOL idle_startup() // // Initialize classes w/graphics stuff. // + gImageList.doPrefetchImages(); + update_texture_fetch(); + LLSurface::initClasses(); LLFace::initClass(); @@ -1690,7 +1736,7 @@ BOOL idle_startup() // Move the progress view in front of the UI gViewerWindow->moveProgressViewToFront(); - gErrorStream.setFixedBuffer(gDebugView->mDebugConsolep); + LLError::logToFixedBuffer(gDebugView->mDebugConsolep); // set initial visibility of debug console gDebugView->mDebugConsolep->setVisible(gSavedSettings.getBOOL("ShowDebugConsole")); gDebugView->mStatViewp->setVisible(gSavedSettings.getBOOL("ShowDebugStats")); @@ -1791,7 +1837,7 @@ BOOL idle_startup() llinfos << "Decoding images..." << llendl; // For all images pre-loaded into viewer cache, decode them. // Need to do this AFTER we init the sky - gImageList.decodeAllImages(); + gImageList.decodeAllImages(2.f); gStartupState++; // JC - Do this as late as possible to increase likelihood Purify @@ -2298,11 +2344,11 @@ BOOL idle_startup() // JC - 7/20/2002 gViewerWindow->sendShapeToSim(); + // Ignore stipend information for now. Money history is on the web site. // if needed, show the money history window - if (stipend_since_login && !gNoRender) - { - LLFloaterAccountHistory::show(NULL); - } + //if (stipend_since_login && !gNoRender) + //{ + //} if (!gAgent.isFirstLogin()) { @@ -2360,18 +2406,6 @@ BOOL idle_startup() if (STATE_PRECACHE == gStartupState) { do_normal_idle = TRUE; - if (!did_precache) - { - did_precache = TRUE; - // Don't preload map information! The amount of data for all the - // map items (icons for classifieds, avatar locations, etc.) is - // huge, and not throttled. This overflows the downstream - // pipe during startup, when lots of information is being sent. - // The problem manifests itself as invisible avatars on login. JC - //gWorldMap->setCurrentLayer(0); // pre-load layer 0 of the world map - - gImageList.doPreloadImages(); // pre-load some images from static VFS - } F32 timeout_frac = timeout.getElapsedTimeF32()/PRECACHING_DELAY; // wait precache-delay and for agent's avatar or a lot longer. @@ -2382,6 +2416,7 @@ BOOL idle_startup() } else { + update_texture_fetch(); set_startup_status(0.50f + 0.50f * timeout_frac, "Precaching...", gAgent.mMOTD.c_str()); } @@ -2410,6 +2445,7 @@ BOOL idle_startup() } else { + update_texture_fetch(); set_startup_status(0.f + 0.25f * wearables_time / MAX_WEARABLES_TIME, "Downloading clothing...", gAgent.mMOTD.c_str()); @@ -2512,34 +2548,6 @@ BOOL idle_startup() // local function definition // -void unsupported_graphics_callback(S32 option, void* userdata) -{ - if (0 == option) - { - llinfos << "User cancelled after driver check" << llendl; - std::string help_path; - help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, - "unsupported_card.html"); - app_force_quit( help_path.c_str() ); - } - - LLPanelLogin::giveFocus(); -} - -void check_driver_callback(S32 option, void* userdata) -{ - if (0 == option) - { - llinfos << "User cancelled after driver check" << llendl; - std::string help_path; - help_path = gDirUtilp->getExpandedFilename(LL_PATH_HELP, - "graphics_driver_update.html"); - app_force_quit( help_path.c_str() ); - } - - LLPanelLogin::giveFocus(); -} - void login_show() { LLPanelLogin::show( gViewerWindow->getVirtualWindowRect(), @@ -2547,7 +2555,7 @@ void login_show() login_callback, NULL ); // Make sure all the UI textures are present and decoded. - gImageList.decodeAllImages(); + gImageList.decodeAllImages(2.f); if( USERSERVER_OTHER == gUserServerChoice ) { @@ -2569,6 +2577,7 @@ void login_show() LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_GANGA].mLabel, USERSERVER_GANGA ); LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_UMA].mLabel, USERSERVER_UMA ); LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_SOMA].mLabel, USERSERVER_SOMA ); + LLPanelLogin::addServer( gUserServerDomainName[USERSERVER_VAAK].mLabel, USERSERVER_VAAK ); } // Callback for when login screen is closed. Option 0 = connect, option 1 = quit. @@ -2628,7 +2637,7 @@ LLString load_password_from_disk() std::string filepath = gDirUtilp->getExpandedFilename(LL_PATH_USER_SETTINGS, "password.dat"); - FILE* fp = LLFile::fopen(filepath.c_str(), "rb"); + FILE* fp = LLFile::fopen(filepath.c_str(), "rb"); /* Flawfinder: ignore */ if (!fp) { return hashed_password; @@ -2675,7 +2684,7 @@ void save_password_to_disk(const char* hashed_password) } else { - FILE* fp = LLFile::fopen(filepath.c_str(), "wb"); + FILE* fp = LLFile::fopen(filepath.c_str(), "wb"); /* Flawfinder: ignore */ if (!fp) { return; @@ -2889,7 +2898,7 @@ void update_dialog_callback(S32 option, void *userdata) } #if LL_WINDOWS - char ip[MAX_STRING]; + char ip[MAX_STRING]; /* Flawfinder: ignore */ update_exe_path = gDirUtilp->getTempFilename(); if (update_exe_path.empty()) @@ -2934,7 +2943,7 @@ void update_dialog_callback(S32 option, void *userdata) // Figure out the program name. const char* data_dir = gDirUtilp->getAppRODataDir().c_str(); // Roll back from the end, stopping at the first '\' - const char* program_name = data_dir + strlen(data_dir); + const char* program_name = data_dir + strlen(data_dir); /* Flawfinder: ignore */ while ( (data_dir != --program_name) && *(program_name) != '\\'); @@ -2981,7 +2990,7 @@ void update_dialog_callback(S32 option, void *userdata) remove_marker_file(); // In case updater fails // Run the auto-updater. - system(update_exe_path.c_str()); + system(update_exe_path.c_str()); /* Flawfinder: ignore */ #elif LL_LINUX OSMessageBox("Automatic updating is not yet implemented for Linux.\n" @@ -3019,8 +3028,8 @@ void use_circuit_callback(void**, S32 result) void register_viewer_callbacks(LLMessageSystem* msg) { msg->setHandlerFuncFast(_PREHASH_LayerData, process_layer_data ); - msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImage::receiveImage ); - msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImage::receiveImagePacket ); + msg->setHandlerFuncFast(_PREHASH_ImageData, LLViewerImageList::receiveImageHeader ); + msg->setHandlerFuncFast(_PREHASH_ImagePacket, LLViewerImageList::receiveImagePacket ); msg->setHandlerFuncFast(_PREHASH_ObjectUpdate, process_object_update ); msg->setHandlerFunc("ObjectUpdateCompressed", process_compressed_object_update ); msg->setHandlerFunc("ObjectUpdateCached", process_cached_object_update ); @@ -3136,14 +3145,6 @@ void register_viewer_callbacks(LLMessageSystem* msg) msg->setHandlerFuncFast(_PREHASH_GrantGodlikePowers, process_grant_godlike_powers); - msg->setHandlerFuncFast(_PREHASH_MoneySummaryReply, - LLFloaterAccountHistory::processMoneySummaryReply); - msg->setHandlerFuncFast(_PREHASH_MoneyDetailsReply, - LLFloaterAccountHistory::processMoneyDetailsReply); - msg->setHandlerFuncFast(_PREHASH_MoneyTransactionsReply, - LLFloaterAccountHistory::processMoneyTransactionsReply); - - // ASDF msg->setHandlerFuncFast(_PREHASH_GroupAccountSummaryReply, LLGroupMoneyPlanningTabEventHandler::processGroupAccountSummaryReply); msg->setHandlerFuncFast(_PREHASH_GroupAccountDetailsReply, @@ -3869,7 +3870,7 @@ void dialog_choose_gender_first_start() // location_id = 1 => home position void init_start_screen(S32 location_id) { - if (gStartImageGL) + if (gStartImageGL.notNull()) { gStartImageGL = NULL; llinfos << "re-initializing start screen" << llendl; diff --git a/linden/indra/newview/llstartup.h b/linden/indra/newview/llstartup.h index c2c822e..26f5bc6 100644 --- a/linden/indra/newview/llstartup.h +++ b/linden/indra/newview/llstartup.h @@ -28,10 +28,13 @@ #ifndef LL_LLSTARTUP_H #define LL_LLSTARTUP_H +#include "llimagegl.h" + // functions BOOL idle_startup(); void cleanup_app(); LLString load_password_from_disk(); +void release_start_screen(); // constants, variables, & enumerations extern const char* SCREEN_HOME_FILENAME; @@ -78,6 +81,7 @@ enum EStartupState{ // exorted symbol extern S32 gStartupState; extern bool gQuickTimeInitialized; +extern LLPointer gStartImageGL; class LLStartUp { diff --git a/linden/indra/newview/llstatbar.cpp b/linden/indra/newview/llstatbar.cpp index b23840a..4b7067c 100644 --- a/linden/indra/newview/llstatbar.cpp +++ b/linden/indra/newview/llstatbar.cpp @@ -143,17 +143,17 @@ void LLStatBar::draw() LLFontGL::sMonospace->renderUTF8(mLabel, 0, 0, mRect.getHeight(), LLColor4(1.f, 1.f, 1.f, 1.f), LLFontGL::LEFT, LLFontGL::TOP); - char value_format[64]; - char value_str[256]; + char value_format[64]; /* Flawfinder: ignore */ + char value_str[256]; /* Flawfinder: ignore */ if (!mUnitLabel.empty()) { - sprintf(value_format, "%%.%df%%s", mPrecision); - sprintf(value_str, value_format, mValue, mUnitLabel.c_str()); + snprintf(value_format, sizeof(value_format), "%%.%df%%s", mPrecision); /* Flawfinder: ignore */ + snprintf(value_str, sizeof(value_str), value_format, mValue, mUnitLabel.c_str()); /* Flawfinder: ignore */ } else { - sprintf(value_format, "%%.%df", mPrecision); - sprintf(value_str, value_format, mValue); + snprintf(value_format, sizeof(value_format), "%%.%df", mPrecision); /* Flawfinder: ignore */ + snprintf(value_str, sizeof(value_str), value_format, mValue); /* Flawfinder: ignore */ } // Draw the value. @@ -161,10 +161,10 @@ void LLStatBar::draw() LLColor4(1.f, 1.f, 1.f, 0.5f), LLFontGL::RIGHT, LLFontGL::TOP); - sprintf(value_format, "%%.%df", mPrecision); + snprintf(value_format, sizeof(value_format), "%%.%df", mPrecision); /* Flawfinder: ignore */ if (mDisplayBar) { - char tick_label[256]; + char tick_label[256]; /* Flawfinder: ignore */ // Draw the tick marks. F32 tick_value; @@ -188,7 +188,7 @@ void LLStatBar::draw() right = left + tick_width; gl_rect_2d(left, top, right, bottom, LLColor4(1.f, 1.f, 1.f, 0.25f)); - sprintf(tick_label, value_format, tick_value); + snprintf(tick_label, sizeof(tick_label), value_format, tick_value); /* Flawfinder: ignore */ // draw labels for the tick marks LLFontGL::sMonospace->renderUTF8(tick_label, 0, left - 1, bar_top - bar_height - tick_height, LLColor4(1.f, 1.f, 1.f, 0.5f), diff --git a/linden/indra/newview/llstatgraph.cpp b/linden/indra/newview/llstatgraph.cpp index b2dec08..e85dc8d 100644 --- a/linden/indra/newview/llstatgraph.cpp +++ b/linden/indra/newview/llstatgraph.cpp @@ -91,10 +91,10 @@ void LLStatGraph::draw() if (mUpdateTimer.getElapsedTimeF32() > 0.5f) { - char format_str[256]; - char tmp_str[256]; - sprintf(format_str, "%%s%%.%df%%s", mPrecision); - sprintf(tmp_str, format_str, mLabel.c_str(), mValue, mUnits.c_str()); + char format_str[256]; /* Flawfinder: ignore */ + char tmp_str[256]; /* Flawfinder: ignore */ + snprintf(format_str, sizeof(format_str), "%%s%%.%df%%s", mPrecision); /* Flawfinder: ignore */ + sprintf(tmp_str, format_str, mLabel.c_str(), mValue, mUnits.c_str()); /* Flawfinder: ignore */ setToolTip(tmp_str); mUpdateTimer.reset(); diff --git a/linden/indra/newview/llstatusbar.cpp b/linden/indra/newview/llstatusbar.cpp index a358f1e..22c0a2a 100644 --- a/linden/indra/newview/llstatusbar.cpp +++ b/linden/indra/newview/llstatusbar.cpp @@ -209,7 +209,13 @@ void LLStatusBar::draw() { refresh(); - LLView::draw(); + if (mBgVisible) + { + gl_drop_shadow(0, mRect.getHeight(), mRect.getWidth(), 0, + LLUI::sColorsGroup->getColor("ColorDropShadow"), + LLUI::sConfigGroup->getS32("DropShadowFloater") ); + } + LLPanel::draw(); } @@ -262,6 +268,12 @@ void LLStatusBar::refresh() const S32 MENU_RIGHT = gMenuBarView->getRightmostMenuEdge(); S32 x = MENU_RIGHT + MENU_PARCEL_SPACING; S32 y = 0; + + // reshape menu bar to its content's width + if (MENU_RIGHT != gMenuBarView->getRect().getWidth()) + { + gMenuBarView->reshape(MENU_RIGHT, gMenuBarView->getRect().getHeight()); + } LLViewerRegion *region = gAgent.getRegion(); LLParcel *parcel = gParcelMgr->getAgentParcel(); @@ -448,6 +460,7 @@ void LLStatusBar::setVisibleForMouselook(bool visible) mSGBandwidth->setVisible(visible); mSGPacketLoss->setVisible(visible); mBtnBuyCurrency->setVisible(visible); + setBackgroundVisible(visible); } void LLStatusBar::debitBalance(S32 debit) @@ -484,8 +497,8 @@ void LLStatusBar::setBalance(S32 balance) void LLStatusBar::setHealth(S32 health) { - char buffer[MAX_STRING]; - sprintf(buffer, "%d%%", health); + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "%d%%", health); /* Flawfinder: ignore */ //llinfos << "Setting health to: " << buffer << llendl; mTextHealth->setText(buffer); diff --git a/linden/indra/newview/llstatview.cpp b/linden/indra/newview/llstatview.cpp index e288879..64ad5aa 100644 --- a/linden/indra/newview/llstatview.cpp +++ b/linden/indra/newview/llstatview.cpp @@ -50,7 +50,7 @@ LLStatView::LLStatView(const LLString& name, const LLString& label, const LLStri { open = gSavedSettings.getBOOL(mSetting); } - setDisplayChildren(open); + setDisplayChildren(open); /* Flawfinder: ignore */ } LLStatView::~LLStatView() @@ -59,7 +59,7 @@ LLStatView::~LLStatView() if (mSetting.length() > 0) { BOOL open = getDisplayChildren(); - gSavedSettings.setBOOL(mSetting, open); + gSavedSettings.setBOOL(mSetting, open); /* Flawfinder: ignore */ } } diff --git a/linden/indra/newview/llsurface.cpp b/linden/indra/newview/llsurface.cpp index c1b22c9..191c079 100644 --- a/linden/indra/newview/llsurface.cpp +++ b/linden/indra/newview/llsurface.cpp @@ -50,7 +50,7 @@ #include "noise.h" #include "llviewercamera.h" #include "llglheaders.h" -#include "lldrawpool.h" +#include "lldrawpoolterrain.h" #include "lldrawable.h" extern LLPipeline gPipeline; @@ -120,7 +120,7 @@ LLSurface::~LLSurface() mNumberOfPatches = 0; destroyPatchData(); - LLDrawPool *poolp = gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); + LLDrawPoolTerrain *poolp = (LLDrawPoolTerrain*) gPipeline.findPool(LLDrawPool::POOL_TERRAIN, mSTexturep); if (!poolp) { llwarns << "No pool for terrain on destruction!" << llendl; @@ -331,7 +331,6 @@ void LLSurface::setOriginGlobal(const LLVector3d &origin_global) LLVector3d water_origin_global(x, y, z); mWaterObjp->setPositionGlobal(water_origin_global); - gPipeline.markMoved(mWaterObjp->mDrawable); } } @@ -621,45 +620,45 @@ void LLSurface::updatePatchVisibilities(LLAgent &agent) } } - - -BOOL LLSurface::idleUpdate() +BOOL LLSurface::idleUpdate(F32 max_update_time) { if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_TERRAIN)) { - return TRUE; + return FALSE; } // Perform idle time update of non-critical stuff. // In this case, texture and normal updates. LLTimer update_timer; - LLSurfacePatch *patchp = NULL; + BOOL did_update = FALSE; // If the Z height data has changed, we need to rebuild our // property line vertex arrays. - if (mDirtyPatchList.count() > 0) + if (mDirtyPatchList.size() > 0) { getRegion()->dirtyHeights(); } - S32 i = 0; - while (i < mDirtyPatchList.count()) + // Always call updateNormals() / updateVerticalStats() + // every frame to avoid artifacts + for(std::set::iterator iter = mDirtyPatchList.begin(); + iter != mDirtyPatchList.end(); ) { - patchp = mDirtyPatchList[i]; + std::set::iterator curiter = iter++; + LLSurfacePatch *patchp = *curiter; patchp->updateNormals(); patchp->updateVerticalStats(); - - if ((update_timer.getElapsedTimeF32() < 0.05f) && patchp->updateTexture()) - { - patchp->clearDirty(); - mDirtyPatchList.remove(i); - } - else + if (max_update_time == 0.f || update_timer.getElapsedTimeF32() < max_update_time) { - i++; + if (patchp->updateTexture()) + { + did_update = TRUE; + patchp->clearDirty(); + mDirtyPatchList.erase(curiter); + } } } - return TRUE; + return did_update; } // TODO -- move this to LLViewerRegion class @@ -1229,10 +1228,7 @@ void LLSurface::dirtyAllPatches() void LLSurface::dirtySurfacePatch(LLSurfacePatch *patchp) { // Put surface patch on dirty surface patch list - if (-1 == mDirtyPatchList.find(patchp)) - { - mDirtyPatchList.put(patchp); - } + mDirtyPatchList.insert(patchp); } diff --git a/linden/indra/newview/llsurface.h b/linden/indra/newview/llsurface.h index 12c1afc..73fe6e6 100644 --- a/linden/indra/newview/llsurface.h +++ b/linden/indra/newview/llsurface.h @@ -41,7 +41,6 @@ #include "llvowater.h" #include "llpatchvertexarray.h" -#include "lldarray.h" #include "llviewerimage.h" class LLTimer; @@ -115,7 +114,7 @@ public: LLSurfacePatch *resolvePatchGlobal(const LLVector3d &position_global) const; // Update methods (called during idle, normally) - BOOL idleUpdate(); + BOOL idleUpdate(F32 max_update_time); void renderSurfaceBounds(); @@ -200,7 +199,7 @@ protected: // Array of grid normals, mGridsPerEdge * mGridsPerEdge LLVector3 *mNorm; - LLDynamicArray mDirtyPatchList; + std::set mDirtyPatchList; // The textures should never be directly initialized - use the setter methods! diff --git a/linden/indra/newview/llsurfacepatch.cpp b/linden/indra/newview/llsurfacepatch.cpp index d19d930..66d100f 100644 --- a/linden/indra/newview/llsurfacepatch.cpp +++ b/linden/indra/newview/llsurfacepatch.cpp @@ -813,7 +813,7 @@ void LLSurfacePatch::connectNeighbor(LLSurfacePatch *neighbor_patchp, const U32 void LLSurfacePatch::updateVisibility() { - if (mVObjp == (LLVOSurfacePatch*)NULL) + if (mVObjp.isNull()) { return; } diff --git a/linden/indra/newview/lltexlayer.cpp b/linden/indra/newview/lltexlayer.cpp index 63d167d..d8a97cf 100644 --- a/linden/indra/newview/lltexlayer.cpp +++ b/linden/indra/newview/lltexlayer.cpp @@ -55,8 +55,6 @@ // SJB: We really always want to use the GL cache; // let GL page textures in and out of video RAM instead of trying to do so by hand. -// const U32 USE_AVATAR_GL_CACHE_THRESHOLD = 1024 * 1024 * 35; // 35 MB -BOOL gUseAvatarGLCache = TRUE; //FALSE; LLGradientPaletteList gGradientPaletteList; @@ -237,8 +235,6 @@ BOOL LLTexLayerSetBuffer::render() { U8* baked_bump_data = NULL; -// gUseAvatarGLCache = ( gImageList.getMaxResidentTexMem() > USE_AVATAR_GL_CACHE_THRESHOLD ); - // do we need to upload, and do we have sufficient data to create an uploadable composite? // When do we upload the texture if gAgent.mNumPendingQueries is non-zero? BOOL upload_now = (gAgent.mNumPendingQueries == 0 && mNeedsUpload && mTexLayerSet->isLocalTextureDataFinal()); @@ -773,7 +769,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) glColorMask( GL_FALSE, GL_FALSE, GL_FALSE, GL_TRUE ); glBlendFunc( GL_ONE, GL_ZERO ); - if( gUseAvatarGLCache ) { LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticAlphaFileName, TRUE ); if( image_gl ) @@ -787,29 +782,6 @@ BOOL LLTexLayerSet::render( S32 x, S32 y, S32 width, S32 height ) success = FALSE; } } - else - { - LLImageRaw* image_raw = gTexStaticImageList.getImageRaw( getInfo()->mStaticAlphaFileName ); - if( image_raw ) - { - GLenum format = GL_ALPHA; - if( mAvatar->bindScratchTexture(format) ) - { - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, image_raw->getWidth(), image_raw->getHeight(), format, GL_UNSIGNED_BYTE, image_raw->getData() ); - stop_glerror(); - - gl_rect_2d_simple_tex( width, height ); - } - else - { - success = FALSE; - } - } - else - { - success = FALSE; - } - } LLImageGL::unbindTexture(0, GL_TEXTURE_2D); glColorMask( GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE ); @@ -1286,23 +1258,6 @@ BOOL LLTexLayer::parseData( LLXmlTreeNode* node ) //----------------------------------------------------------------------------- -BOOL LLTexLayer::loadStaticImageRaw() -{ - if( mStaticImageRaw.isNull() && !mStaticImageInvalid) - { - mStaticImageRaw = gTexStaticImageList.getImageRaw( getInfo()->mStaticImageFileName ); - // We now have something in one of our caches - LLTexLayerSet::sHasCaches |= mStaticImageRaw.notNull() ? TRUE : FALSE; - if( mStaticImageRaw.isNull() ) - { - llwarns << "Unable to load static file: " << getInfo()->mStaticImageFileName << llendl; - mStaticImageInvalid = TRUE; // don't try again. - return FALSE; - } - } - return TRUE; -} - void LLTexLayer::deleteCaches() { for( alpha_list_t::iterator iter = mParamAlphaList.begin(); @@ -1375,7 +1330,6 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) if( (getInfo()->mLocalTexture != -1) && !getInfo()->mUseLocalTextureAlphaOnly ) { - if( gUseAvatarGLCache ) { LLImageGL* image_gl = NULL; if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) @@ -1401,29 +1355,10 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) success = FALSE; } } - else - { - LLPointer image_raw = new LLImageRaw; - if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) ) - { - success &= renderImageRaw( image_raw->getData(), - image_raw->getWidth(), - image_raw->getHeight(), - image_raw->getComponents(), - width, - height, - FALSE ); - } - else - { - success = FALSE; - } - } } if( !getInfo()->mStaticImageFileName.empty() ) { - if( gUseAvatarGLCache ) { LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); if( image_gl ) @@ -1437,26 +1372,6 @@ BOOL LLTexLayer::render( S32 x, S32 y, S32 width, S32 height ) success = FALSE; } } - else - { - // Don't load the image file until we actually need it the first time. Like now. - if (!loadStaticImageRaw()) - { - success = FALSE; - } - if( mStaticImageRaw.notNull() ) - { - success &= renderImageRaw( - mStaticImageRaw->getData(), - mStaticImageRaw->getWidth(), - mStaticImageRaw->getHeight(), - mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask ); - } - else - { - success = FALSE; - } - } } if( ((-1 == getInfo()->mLocalTexture) || @@ -1610,7 +1525,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 // Accumulate the alpha component of the texture if( getInfo()->mLocalTexture != -1 ) { - if( gUseAvatarGLCache ) { LLImageGL* image_gl = NULL; if( mTexLayerSet->getAvatar()->getLocalTextureGL( getInfo()->mLocalTexture, &image_gl ) ) @@ -1635,30 +1549,10 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 success = FALSE; } } - else - { - LLPointer image_raw = new LLImageRaw; - if( mTexLayerSet->getAvatar()->getLocalTextureRaw( getInfo()->mLocalTexture, image_raw ) ) - { - if(image_raw->getComponents() == 4) - { - success &= renderImageRaw( - image_raw->getData(), - image_raw->getWidth(), - image_raw->getHeight(), - image_raw->getComponents(), width, height, FALSE ); - } - } - else - { - success = FALSE; - } - } } if( !getInfo()->mStaticImageFileName.empty() ) { - if( gUseAvatarGLCache ) { LLImageGL* image_gl = gTexStaticImageList.getImageGL( getInfo()->mStaticImageFileName, getInfo()->mStaticImageIsMask ); if( image_gl ) @@ -1677,31 +1571,6 @@ BOOL LLTexLayer::renderAlphaMasks( S32 x, S32 y, S32 width, S32 height, LLColor4 success = FALSE; } } - else - { - // Don't load the image file until we actually need it the first time. Like now. - if (!loadStaticImageRaw()) - { - success = FALSE; - } - - if( mStaticImageRaw.notNull() ) - { - if( (mStaticImageRaw->getComponents() == 4) || - ( (mStaticImageRaw->getComponents() == 1) && getInfo()->mStaticImageIsMask ) ) - { - success &= renderImageRaw( - mStaticImageRaw->getData(), - mStaticImageRaw->getWidth(), - mStaticImageRaw->getHeight(), - mStaticImageRaw->getComponents(), width, height, getInfo()->mStaticImageIsMask ); - } - } - else - { - success = FALSE; - } - } } // Draw a rectangle with the layer color to multiply the alpha by that color's alpha. @@ -2106,8 +1975,7 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) if( !mCachedProcessedImageGL || (mCachedProcessedImageGL->getWidth() != image_tga_width) || (mCachedProcessedImageGL->getHeight() != image_tga_height) || - (weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) || - (!gUseAvatarGLCache) ) + (weight_changed && !(gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE))) ) { // llinfos << "Building Cached Alpha: " << mName << ": (" << mStaticImageRaw->getWidth() << ", " << mStaticImageRaw->getHeight() << ") " << effective_weight << llendl; mCachedEffectiveWeight = effective_weight; @@ -2149,7 +2017,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) if( mCachedProcessedImageGL ) { - if( gUseAvatarGLCache ) // 64 MB { if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) { @@ -2187,94 +2054,6 @@ BOOL LLTexLayerParamAlpha::render( S32 x, S32 y, S32 width, S32 height ) } stop_glerror(); } - else - { - if( (mCachedProcessedImageGL->getWidth() != VOAVATAR_SCRATCH_TEX_WIDTH) || - (mCachedProcessedImageGL->getHeight() != VOAVATAR_SCRATCH_TEX_HEIGHT) ) - { - if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) - { - mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); - - LLGLSNoAlphaTest gls_no_alpha_test; - - mCachedProcessedImageGL->bind(); - mCachedProcessedImageGL->setClamp(TRUE, TRUE); - - gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight ); - gl_rect_2d_simple_tex( width, height ); - LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - mCachedProcessedImageGL->destroyGLTexture(); - } - else - { - // Create the GL texture, bind it and draw a rect, and then immediately destroy it. - mCachedProcessedImageGL->createGLTexture(0, mStaticImageRaw); - - LLGLSNoAlphaTest gls_no_alpha_test; - - mCachedProcessedImageGL->bind(); - mCachedProcessedImageGL->setClamp(TRUE, TRUE); - - gl_rect_2d_simple_tex( width, height ); - - LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - - mCachedProcessedImageGL->destroyGLTexture(); - } - stop_glerror(); - } - else - { - if (gGLManager.mHasPalettedTextures && gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_PALETTE)) - { - // Write into a pre-existing GL Image, and then bind and render that. - // Faster than creating a new GL Image and then destroying it. - if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_COLOR_INDEX ) ) - { - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, - mCachedProcessedImageGL->getWidth(), - mCachedProcessedImageGL->getHeight(), - GL_COLOR_INDEX, GL_UNSIGNED_BYTE, - mStaticImageRaw->getData() ); - stop_glerror(); - - LLGLSNoAlphaTest gls_no_alpha_test; - gGradientPaletteList.setHardwarePalette( getInfo()->mDomain, effective_weight ); - gl_rect_2d_simple_tex( width, height ); - - LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - } - else - { - success = FALSE; - } - } - else - { - // Write into a pre-existing GL Image, and then bind and render that. - // Faster than creating a new GL Image and then destroying it. - if( mTexLayer->getTexLayerSet()->getAvatar()->bindScratchTexture( GL_ALPHA ) ) - { - glTexSubImage2D( GL_TEXTURE_2D, 0, 0, 0, - mCachedProcessedImageGL->getWidth(), - mCachedProcessedImageGL->getHeight(), - GL_ALPHA, GL_UNSIGNED_BYTE, - mStaticImageRaw->getData() ); - stop_glerror(); - - LLGLSNoAlphaTest gls_no_alpha_test; - gl_rect_2d_simple_tex( width, height ); - - LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - } - else - { - success = FALSE; - } - } - } - } } // Don't keep the cache for other people's avatars @@ -2625,7 +2404,6 @@ LLStringTable LLTexStaticImageList::sImageNames(16384); LLTexStaticImageList::LLTexStaticImageList() : - mRawBytes( 0 ), mGLBytes( 0 ), mTGABytes( 0 ) {} @@ -2638,36 +2416,31 @@ LLTexStaticImageList::~LLTexStaticImageList() void LLTexStaticImageList::dumpByteCount() { llinfos << "Avatar Static Textures " << - " Raw:" << (mRawBytes / 1024) << "KB GL:" << (mGLBytes / 1024) << "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; } void LLTexStaticImageList::deleteCachedImages() { - if( mRawBytes || mGLBytes || mTGABytes ) + if( mGLBytes || mTGABytes ) { llinfos << "Clearing Static Textures " << - " Raw:" << (mRawBytes / 1024) << "KB GL:" << (mGLBytes / 1024) << "KB TGA:" << (mTGABytes / 1024) << "KB" << llendl; //mStaticImageLists uses LLPointers, clear() will cause deletion - mStaticImageListRaw.clear(); mStaticImageListTGA.clear(); mStaticImageListGL.clear(); - mRawBytes = 0; mGLBytes = 0; mTGABytes = 0; } } -// Note: in general, for a given image image we'll call either getImageTga(), getImageRaw() or getImageGL(). +// Note: in general, for a given image image we'll call either getImageTga() or getImageGL(). // We call getImageTga() if the image is used as an alpha gradient. -// Otherwise, we call getImageRaw() if we have 32 MB or less of video RAM or less and getImageGL() if we have -// more video RAM than that. +// Otherwise, we call getImageGL() // Returns an LLImageTGA that contains the encoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. @@ -2699,34 +2472,6 @@ LLImageTGA* LLTexStaticImageList::getImageTGA(const LLString& file_name) -// Returns an LLImageRaw that contains the decoded data from a tga file named file_name. -// Caches the result to speed identical subsequent requests. -LLImageRaw* LLTexStaticImageList::getImageRaw(const LLString& file_name) -{ - LLPointer image_raw; - const char *namekey = sImageNames.addString(file_name); - image_raw_map_t::iterator iter = mStaticImageListRaw.find(namekey); - if( iter != mStaticImageListRaw.end() ) - { - image_raw = iter->second; - } - else - { - image_raw = new LLImageRaw(); - if( loadImageRaw( file_name, image_raw ) ) - { - mStaticImageListRaw[ namekey ] = image_raw; - mRawBytes += image_raw->getDataSize(); - } - else - { - image_raw = NULL; - } - } - - return image_raw; -} - // Returns a GL Image (without a backing ImageRaw) that contains the decoded data from a tga file named file_name. // Caches the result to speed identical subsequent requests. LLImageGL* LLTexStaticImageList::getImageGL(const LLString& file_name, BOOL is_mask ) diff --git a/linden/indra/newview/lltexlayer.h b/linden/indra/newview/lltexlayer.h index 3db6f96..5d12da5 100644 --- a/linden/indra/newview/lltexlayer.h +++ b/linden/indra/newview/lltexlayer.h @@ -341,9 +341,6 @@ public: BOOL hasAlphaParams() { return (!mParamAlphaList.empty());} protected: - BOOL loadStaticImageRaw(); - -protected: LLTexLayerSet* mTexLayerSet; LLPointer mStaticImageRaw; @@ -517,15 +514,12 @@ private: private: static LLStringTable sImageNames; - typedef std::map< const char *, LLPointer > image_raw_map_t; typedef std::map< const char *, LLPointer > image_gl_map_t; typedef std::map< const char *, LLPointer > image_tga_map_t; - image_raw_map_t mStaticImageListRaw; image_gl_map_t mStaticImageListGL; image_tga_map_t mStaticImageListTGA; public: - S32 mRawBytes; S32 mGLBytes; S32 mTGABytes; }; diff --git a/linden/indra/newview/lltexturebar.cpp b/linden/indra/newview/lltexturebar.cpp deleted file mode 100644 index d3be39e..0000000 --- a/linden/indra/newview/lltexturebar.cpp +++ /dev/null @@ -1,412 +0,0 @@ -/** - * @file lltexturebar.cpp - * @brief LLTextureBar class implementation - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "lltexturebar.h" -#include "llviewerimage.h" -#include "lltexturetable.h" -#include "llfontgl.h" -#include "llui.h" -#include "llassetstorage.h" -#include "llglheaders.h" -#include "llviewerimagelist.h" - -#include "lltexlayer.h" - -// colors used for highlighting textures -const F32 select_colors[][4] = { {1.0f, 1.0f, 1.0f, 0.7f}, // default = white - {1.0f, 1.0f, 0.3f, 1.0f}, // selected = yellow - {0.3f, 1.0f, 1.0f, 1.0f}, // flagged = cyan - {1.0f, 0.3f, 1.0f, 1.0f}, // boosted = magenta - {0.5f, 0.5f, 1.0f, 1.0f}, // blue - {0.5f, 1.0f, 0.5f, 1.0f}, // green - {1.0f, 0.5f, 0.5f, 1.0f}, // updated this frame = red - {1.0f, 0.8f, 0.8f, 1.0f}, // nodiscard = pale red - {0.8f, 1.0f, 0.8f, 1.0f}, // fullres = pale green - {0.8f, 0.8f, 0.8f, 0.7f} // 0 priority = grey -}; - -LLTextureBar::LLTextureBar(const std::string& name, const LLRect& r) - : LLView(name, r, FALSE) -{ - mHilite = 0; -} - -static LLString title_string1("Tex UUID Area DDis(Req) DecodePri(Req) [decode] pkts/max"); -static LLString title_string2("W x H (Dis) Mem"); - -static S32 pip_base = 480; -static S32 pip_width = 6; - -EWidgetType LLTextureBar::getWidgetType() const -{ - return WIDGET_TYPE_TEXTURE_BAR; -} - -LLString LLTextureBar::getWidgetTag() const -{ - return LL_TEXTURE_BAR_TAG; -} - - -void LLTextureBar::draw() -{ - if (!mImagep) - { - return; - } - - S32 color; - if (mHilite) - { - color = llclamp(mHilite,0,4); - } - else if (mImagep->getBoostLevel()) - { - color = 3; - } - else if (mImagep->mDontDiscard) - { - color = 7; - } - else if (!mImagep->getUseMipMaps()) - { - color = 8; - } - else if (mImagep->getDecodePriority() == 0.0f) - { - color = 9; - } - else - { - color = 0; - } - - // We need to draw: - // The texture UUID or name - // The progress bar for the texture, highlighted if it's being download - // Various numerical stats. - char tex_str[256]; - S32 left, right; - S32 top = 0; - S32 bottom = top + 6; - - // Get the name or UUID of the image. - gTextureTable.getName(mImagep->mID); - - // Name, pixel_area, requested pixel area, decode priority - char uuid_str[255]; - mImagep->mID.toString(uuid_str); - uuid_str[8] = 0; - sprintf(tex_str, "%s %7.0f %d(%d) %8.2f(%8.2f)", - uuid_str, - mImagep->mMaxVirtualSize, - mImagep->mDesiredDiscardLevel, - mImagep->mRequestedDiscardLevel, - mImagep->getDecodePriority(), - mImagep->mRequestedDownloadPriority); - - - LLGLSUIDefault gls_ui; - LLFontGL::sMonospace->renderUTF8(tex_str, 0, 0, mRect.getHeight(), - select_colors[color], - LLFontGL::LEFT, LLFontGL::TOP); - - LLGLSNoTexture gls_no_texture; - F32 last_event; - LLColor4 clr; - - // Draw the packet pip - last_event = mImagep->mLastPacketTimer.getElapsedTimeF32(); - if (last_event < 1.f) - { - clr = LLColor4::white; clr.setAlpha(1.f - last_event); - glColor4fv(clr.mV); - gl_rect_2d(pip_base, top, pip_base + pip_width, bottom); - } - else - { - last_event = mImagep->mRequestTime.getElapsedTimeF32() * 1.f/5.f; - if (last_event < 1.f) - { - clr = LLColor4::green; clr.setAlpha(1.f - last_event); - glColor4fv(clr.mV); - gl_rect_2d(pip_base, top, pip_base + pip_width, bottom); - } - } - - // Draw the decode pip - if (mImagep->getDiscardLevel() < 0) - last_event = 1.f; - else - last_event = mImagep->mLastDecodeTime.getElapsedTimeF32(); - if (last_event < 1.f) - { - clr = LLColor4::yellow; clr.setAlpha(1.f - last_event); - glColor4fv(clr.mV); - gl_rect_2d(pip_base + pip_width*2, top, pip_base + pip_width*3, bottom); - } - - // we don't want to show bind/resident pips for textures using the default texture - if (mImagep->getHasGLTexture()) - { - BOOL miss = FALSE; - // Draw the bound pip - last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime; - if (last_event < 1.f) - { - clr = LLColor4::magenta1; clr.setAlpha(1.f - last_event); - glColor4fv(clr.mV); - gl_rect_2d(pip_base + pip_width*4, top, pip_base + pip_width*5, bottom); - - miss = mImagep->getMissed(); - } - - // Draw the miss pip - if (miss) - { - clr = LLColor4::red; - glColor4fv(clr.mV); - gl_rect_2d(pip_base + pip_width*6, top, pip_base + pip_width*7, bottom); - } - } - - // Draw the progress bar. - S32 bar_width = 100; - S32 bar_left = 280; - left = bar_left; - right = left + bar_width; - - glColor4f(0.f, 0.f, 0.f, 0.75f); - gl_rect_2d(left, top, right, bottom); - - F32 data_progress = 0.0f; - F32 decode_progress = mImagep->getDecodeProgress(&data_progress); - - if (data_progress > 0.0f) - { - // Decoded bytes - right = left + llfloor(decode_progress * (F32)bar_width); - - if (left < right) - { - if (mImagep->getDiscardLevel() >= 0) - { - glColor4f(0.f, 0.f, 1.f, 0.75f); - } - else - { - glColor4f(0.5f, 0.0f, 0.5f, 0.75f); - } - gl_rect_2d(left, top, right, bottom); - } - - // Downloaded bytes - left = right; - right = left + llfloor((data_progress - decode_progress) * (F32)bar_width); - - if (left < right) - { - glColor4f(1.f, 0.f, 0.f, 0.75f); - gl_rect_2d(left, top, right, bottom); - } - } - - { - LLGLSUIDefault gls_ui; - // draw the packet data - { - LLString num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets); - LLFontGL::sMonospace->renderUTF8(num_str, 0, bar_left + 100, mRect.getHeight(), select_colors[color], - LLFontGL::LEFT, LLFontGL::TOP); - } - - // draw the image size at the end - { - LLString num_str = llformat("%4d x %4d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(), - mImagep->getDiscardLevel(), mImagep->mTextureMemory); - LLFontGL::sMonospace->renderUTF8(num_str, 0, pip_base + pip_width*8, mRect.getHeight(), select_colors[color], - LLFontGL::LEFT, LLFontGL::TOP); - } - } - -} - -BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask) -{ - return FALSE; -} - -LLRect LLTextureBar::getRequiredRect() -{ - LLRect rect; - - rect.mTop = 8; - - return rect; -} - -//============================================================================== - -LLGLTexMemBar::LLGLTexMemBar(const std::string& name) - : LLView(name, FALSE) -{ - S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f); - setRect(LLRect(0,0,100,line_height * 4)); - updateRect(); -} - -EWidgetType LLGLTexMemBar::getWidgetType() const -{ - return WIDGET_TYPE_TEX_MEM_BAR; -} - -LLString LLGLTexMemBar::getWidgetTag() const -{ - return LL_GL_TEX_MEM_BAR_TAG; -} - - -extern F32 texmem_lower_bound_scale; - -void LLGLTexMemBar::draw() -{ - S32 bound_mem = LLViewerImage::sBoundTextureMemory; - S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMem; - S32 total_mem = LLViewerImage::sTotalTextureMemory; - S32 max_total_mem = LLViewerImage::sMaxTotalTextureMem; - F32 discard_bias = LLViewerImage::sDesiredDiscardBias; - S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f); - - //---------------------------------------------------------------------------- - LLGLSUIDefault gls_ui; - F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; - - std::string text; - text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f", - total_mem/(1024*1024), - max_total_mem/(1024*1024), - bound_mem/(1024*1024), - max_bound_mem/(1024*1024), - discard_bias); - - LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*3, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - - //---------------------------------------------------------------------------- - S32 bar_left = 350; - S32 bar_width = 200; - S32 top = line_height*3 - 2; - S32 bottom = top - 6; - S32 left = bar_left; - S32 right = left + bar_width; - - F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f); - - LLGLSNoTexture gls_no_texture; - - glColor4f(0.5f, 0.5f, 0.5f, 0.75f); - gl_rect_2d(left, top, right, bottom); - - - left = bar_left; - right = left + llfloor(bound_mem * bar_scale); - if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) - { - glColor4f(0.f, 1.f, 0.f, 0.75f); - } - else if (bound_mem < max_bound_mem) - { - glColor4f(1.f, 1.f, 0.f, 0.75f); - } - else - { - glColor4f(1.f, 0.f, 0.f, 0.75f); - } - gl_rect_2d(left, top, right, bottom); - - bar_scale = (F32)bar_width / (max_total_mem * 1.5f); - - top = bottom - 2; - bottom = top - 6; - left = bar_left; - right = left + llfloor(total_mem * bar_scale); - if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) - { - glColor4f(0.f, 1.f, 0.f, 0.75f); - } - else if (total_mem < max_total_mem) - { - glColor4f(1.f, 1.f, 0.f, 0.75f); - } - else - { - glColor4f(1.f, 0.f, 0.f, 0.75f); - } - gl_rect_2d(left, top, right, bottom); - - //---------------------------------------------------------------------------- - text = llformat("TexStaticImageList Raw: %d GL: %d TGA: %d", - gTexStaticImageList.mRawBytes, gTexStaticImageList.mGLBytes, gTexStaticImageList.mTGABytes); - - LLGLEnable tex(GL_TEXTURE_2D); - LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*2, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - - - //---------------------------------------------------------------------------- - - S32 x = 0; - LLFontGL::sMonospace->renderUTF8(title_string1, 0, x, line_height, - text_color, LLFontGL::LEFT, LLFontGL::TOP); - S32 dx = 24; - x = pip_base - dx; - LLFontGL::sMonospace->renderUTF8("pkt", 0, x, line_height, LLColor4::white, LLFontGL::LEFT, LLFontGL::TOP); - x += dx; - LLFontGL::sMonospace->renderUTF8("dec", 0, x, line_height, LLColor4::yellow, LLFontGL::LEFT, LLFontGL::TOP); - x += dx; - LLFontGL::sMonospace->renderUTF8("bnd", 0, x, line_height, LLColor4::magenta1, LLFontGL::LEFT, LLFontGL::TOP); - x += dx; - LLFontGL::sMonospace->renderUTF8("mis", 0, x, line_height, LLColor4::red, LLFontGL::LEFT, LLFontGL::TOP); - x += dx; - LLFontGL::sMonospace->renderUTF8(title_string2, 0, x, line_height, - text_color, LLFontGL::LEFT, LLFontGL::TOP); -} - -BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask) -{ - return FALSE; -} - -LLRect LLGLTexMemBar::getRequiredRect() -{ - LLRect rect; - rect.mTop = 8; - return rect; -} - diff --git a/linden/indra/newview/lltexturebar.h b/linden/indra/newview/lltexturebar.h deleted file mode 100644 index ea704a2..0000000 --- a/linden/indra/newview/lltexturebar.h +++ /dev/null @@ -1,75 +0,0 @@ -/** - * @file lltexturebar.h - * @brief LLTextureBar class definition - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLTEXTUREBAR_H -#define LL_LLTEXTUREBAR_H - -#include "llview.h" -#include "lltimer.h" -#include "llviewerimage.h" - -class LLAssetInfo; -class LLTimer; - - -class LLTextureBar : public LLView -{ -public: - LLPointer mImagep; - S32 mHilite; - -public: - LLTextureBar(const std::string& name, const LLRect& r); - - virtual EWidgetType getWidgetType() const; - virtual LLString getWidgetTag() const; - - virtual void draw(); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - - virtual LLRect getRequiredRect(); // Return the height of this object, given the set options. -}; - -class LLGLTexMemBar : public LLView -{ -public: - LLGLTexMemBar(const std::string& name); - - virtual EWidgetType getWidgetType() const; - virtual LLString getWidgetTag() const; - - virtual void draw(); - - virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); - - virtual LLRect getRequiredRect(); // Return the height of this object, given the set options. - -protected: -}; - -#endif // LL_TEXTURE_BAR_ diff --git a/linden/indra/newview/lltexturecache.cpp b/linden/indra/newview/lltexturecache.cpp new file mode 100644 index 0000000..084211a --- /dev/null +++ b/linden/indra/newview/lltexturecache.cpp @@ -0,0 +1,1409 @@ +/** + * @file texturecache.cpp + * @brief Object which handles local texture caching + * + * Copyright (c) 2000-2007, Linden Research, Inc. + * + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed 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. + */ + +#include "llviewerprecompiledheaders.h" + +#include "lltexturecache.h" + +#include "llapr.h" +#include "lldir.h" +#include "llimage.h" +#include "lllfsthread.h" +#include "llviewercontrol.h" + +#define USE_LFS_READ 0 +#define USE_LFS_WRITE 0 + +// Note: first 4 bytes store file size, rest is j2c data +const S32 TEXTURE_CACHE_ENTRY_SIZE = FIRST_PACKET_SIZE; //1024; + +class LLTextureCacheWorker : public LLWorkerClass +{ + friend class LLTextureCache; + +private: + enum e_state + { + INIT = 0, + LOCAL = 1, + CACHE = 2, + HEADER = 3, + BODY = 4 + }; + + class ReadResponder : public LLLFSThread::Responder + { + public: + ReadResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {} + ~ReadResponder() {} + void completed(S32 bytes) + { + mCache->lockWorkers(); + LLTextureCacheWorker* reader = mCache->getReader(mHandle); + if (reader) reader->ioComplete(bytes); + mCache->unlockWorkers(); + } + LLTextureCache* mCache; + LLTextureCacheWorker::handle_t mHandle; + }; + + class WriteResponder : public LLLFSThread::Responder + { + public: + WriteResponder(LLTextureCache* cache, handle_t handle) : mCache(cache), mHandle(handle) {} + ~WriteResponder() {} + void completed(S32 bytes) + { + mCache->lockWorkers(); + LLTextureCacheWorker* writer = mCache->getWriter(mHandle); + if (writer) writer->ioComplete(bytes); + mCache->unlockWorkers(); + } + LLTextureCache* mCache; + LLTextureCacheWorker::handle_t mHandle; + }; + +public: + LLTextureCacheWorker(LLTextureCache* cache, U32 priority, const LLUUID& id, + U8* data, S32 datasize, S32 offset, + S32 imagesize, // for writes + LLTextureCache::Responder* responder) + : LLWorkerClass(cache, "LLTextureCacheWorker"), + mCache(cache), + mPriority(priority), + mID(id), + mState(INIT), + mReadData(NULL), + mWriteData(data), + mDataSize(datasize), + mOffset(offset), + mImageSize(imagesize), + mImageFormat(IMG_CODEC_J2C), + mImageLocal(FALSE), + mResponder(responder), + mFileHandle(LLLFSThread::nullHandle()), + mBytesToRead(0), + mBytesRead(0) + { + mPriority &= LLWorkerThread::PRIORITY_LOWBITS; + } + ~LLTextureCacheWorker() + { + llassert_always(!haveWork()); + delete[] mReadData; + } + + bool doRead(); + bool doWrite(); + virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() + + handle_t read() { addWork(0, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } + handle_t write() { addWork(1, LLWorkerThread::PRIORITY_HIGH | mPriority); return mRequestHandle; } + bool complete() { return checkWork(); } + void ioComplete(S32 bytes) + { + mBytesRead = bytes; + setPriority(LLWorkerThread::PRIORITY_HIGH | mPriority); + } + +private: + virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) + virtual void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) + virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) + +private: + LLTextureCache* mCache; + U32 mPriority; + LLUUID mID; + e_state mState; + + U8* mReadData; + U8* mWriteData; + S32 mDataSize; + S32 mOffset; + S32 mImageSize; + S32 mImageFormat; + BOOL mImageLocal; + LLPointer mResponder; + LLLFSThread::handle_t mFileHandle; + S32 mBytesToRead; + LLAtomicS32 mBytesRead; +}; + +//virtual +void LLTextureCacheWorker::startWork(S32 param) +{ +} + +bool LLTextureCacheWorker::doRead() +{ + S32 local_size = 0; + std::string local_filename; + + if (mState == INIT) + { + std::string filename = mCache->getLocalFileName(mID); + local_filename = filename + ".j2c"; + local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + if (local_size == 0) + { + local_filename = filename + ".tga"; + local_size = ll_apr_file_size(local_filename, mCache->getFileAPRPool()); + if (local_size > 0) + { + mImageFormat = IMG_CODEC_TGA; + mDataSize = local_size; // Only a complete .tga file is valid + } + } + if (local_size > 0) + { + mState = LOCAL; + } + else + { + mState = CACHE; + } + } + + if (mState == LOCAL) + { +#if USE_LFS_READ + if (mFileHandle == LLLFSThread::nullHandle()) + { + mImageLocal = TRUE; + mImageSize = local_size; + if (!mDataSize || mDataSize + mOffset > local_size) + { + mDataSize = local_size - mOffset; + } + if (mDataSize <= 0) + { + // no more data to read + mDataSize = 0; + return true; + } + mReadData = new U8[mDataSize]; + mBytesRead = -1; + mBytesToRead = mDataSize; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + mFileHandle = LLLFSThread::sLocal->read(local_filename, mReadData, mOffset, mDataSize, + new ReadResponder(mCache, mRequestHandle)); + return false; + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "Error reading file from local cache: " << local_filename + << " Bytes: " << mDataSize << " Offset: " << mOffset + << " / " << mDataSize << llendl; + mDataSize = 0; // failed + delete[] mReadData; + mReadData = NULL; + } + return true; + } + else + { + return false; + } + } +#else + if (!mDataSize || mDataSize > local_size) + { + mDataSize = local_size; + } + mReadData = new U8[mDataSize]; + S32 bytes_read = ll_apr_file_read_ex(local_filename, mCache->getFileAPRPool(), + mReadData, mOffset, mDataSize); + if (bytes_read != mDataSize) + { + llwarns << "Error reading file from local cache: " << local_filename + << " Bytes: " << mDataSize << " Offset: " << mOffset + << " / " << mDataSize << llendl; + mDataSize = 0; + delete[] mReadData; + mReadData = NULL; + } + else + { + mImageSize = local_size; + mImageLocal = TRUE; + } + return true; +#endif + } + + S32 idx = -1; + + if (mState == CACHE) + { + llassert_always(mImageSize == 0); + idx = mCache->getHeaderCacheEntry(mID, false, &mImageSize); + if (idx >= 0 && mImageSize > mOffset) + { + llassert_always(mImageSize > 0); + if (!mDataSize || mDataSize > mImageSize) + { + mDataSize = mImageSize; + } + mState = mOffset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; + } + else + { + mDataSize = 0; // no data + return true; + } + } + + if (mState == HEADER) + { +#if USE_LFS_READ + if (mFileHandle == LLLFSThread::nullHandle()) + { + llassert_always(idx >= 0); + llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; + S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + llassert_always(mReadData == NULL); + mReadData = new U8[size]; + mBytesRead = -1; + mBytesToRead = size; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + mFileHandle = LLLFSThread::sLocal->read(mCache->mHeaderDataFileName, + mReadData, offset, mBytesToRead, + new ReadResponder(mCache, mRequestHandle)); + return false; + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from header: " << mBytesRead + << " != " << mBytesToRead << llendl; + mDataSize = -1; // failed + return true; + } + if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) + { + return true; // done + } + else + { + mFileHandle = LLLFSThread::nullHandle(); + mState = BODY; + } + } + else + { + return false; + } + } +#else + llassert_always(idx >= 0); + llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; + S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + mReadData = new U8[size]; + S32 bytes_read = ll_apr_file_read_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), + mReadData, offset, size); + if (bytes_read != size) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from header: " << bytes_read + << " / " << size << llendl; + mDataSize = -1; // failed + return true; + } + if (mDataSize <= TEXTURE_CACHE_ENTRY_SIZE) + { + return true; // done + } + else + { + mState = BODY; + } +#endif + } + + if (mState == BODY) + { +#if USE_LFS_READ + if (mFileHandle == LLLFSThread::nullHandle()) + { + std::string filename = mCache->getTextureFileName(mID); + S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + if (filesize > mOffset) + { + S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; + mDataSize = llmin(datasize, mDataSize); + S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + data_offset = llmax(data_offset, 0); + S32 file_size = mDataSize - data_offset; + S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; + file_offset = llmax(file_offset, 0); + + llassert_always(mDataSize > 0); + U8* data = new U8[mDataSize]; + if (data_offset > 0) + { + llassert_always(mReadData); + llassert_always(data_offset <= mDataSize); + memcpy(data, mReadData, data_offset); + delete[] mReadData; + mReadData = NULL; + } + llassert_always(mReadData == NULL); + mReadData = data; + + mBytesRead = -1; + mBytesToRead = file_size; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + llassert_always(data_offset + mBytesToRead <= mDataSize); + mFileHandle = LLLFSThread::sLocal->read(filename, + mReadData + data_offset, file_offset, mBytesToRead, + new ReadResponder(mCache, mRequestHandle)); + return false; + } + else + { + mDataSize = TEXTURE_CACHE_ENTRY_SIZE; + return true; // done + } + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from body: " << mBytesRead + << " != " << mBytesToRead << llendl; + mDataSize = -1; // failed + } + return true; + } + else + { + return false; + } + } +#else + std::string filename = mCache->getTextureFileName(mID); + S32 filesize = ll_apr_file_size(filename, mCache->getFileAPRPool()); + S32 bytes_read = 0; + if (filesize > mOffset) + { + S32 datasize = TEXTURE_CACHE_ENTRY_SIZE + filesize; + mDataSize = llmin(datasize, mDataSize); + S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + data_offset = llmax(data_offset, 0); + S32 file_size = mDataSize - data_offset; + S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; + file_offset = llmax(file_offset, 0); + + U8* data = new U8[mDataSize]; + if (data_offset > 0) + { + llassert_always(mReadData); + memcpy(data, mReadData, data_offset); + delete[] mReadData; + } + mReadData = data; + bytes_read = ll_apr_file_read_ex(filename, mCache->getFileAPRPool(), + mReadData + data_offset, + file_offset, file_size); + if (bytes_read != file_size) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes read from body: " << bytes_read + << " / " << file_size << llendl; + mDataSize = -1; // failed + return true; + } + } + else + { + mDataSize = TEXTURE_CACHE_ENTRY_SIZE; + } + + return true; +#endif + } + + return false; +} + +bool LLTextureCacheWorker::doWrite() +{ + S32 idx = -1; + + if (mState == INIT) + { + llassert_always(mOffset == 0); // Currently don't support offsets + mState = CACHE; + } + + // No LOCAL state for write() + + if (mState == CACHE) + { + S32 cur_imagesize = 0; + S32 offset = mOffset; + idx = mCache->getHeaderCacheEntry(mID, false, &cur_imagesize); + if (idx >= 0 && cur_imagesize > 0) + { + offset = TEXTURE_CACHE_ENTRY_SIZE; // don't re-write header + } + idx = mCache->getHeaderCacheEntry(mID, true, &mImageSize); // touch entry + if (idx >= 0) + { + llassert_always(cur_imagesize <= 0 || mImageSize == cur_imagesize); + mState = offset < TEXTURE_CACHE_ENTRY_SIZE ? HEADER : BODY; + } + else + { + mDataSize = -1; // failed + return true; + } + } + + if (mState == HEADER) + { +#if USE_LFS_WRITE + if (mFileHandle == LLLFSThread::nullHandle()) + { + llassert_always(idx >= 0); + llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; + S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + mBytesRead = -1; + mBytesToRead = size; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + mFileHandle = LLLFSThread::sLocal->write(mCache->mHeaderDataFileName, + mWriteData, offset, mBytesToRead, + new WriteResponder(mCache, mRequestHandle)); + return false; + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes written to header: " << mBytesRead + << " != " << mBytesToRead << llendl; + mDataSize = -1; // failed + return true; + } + if (mDataSize <= mBytesToRead) + { + return true; // done + } + else + { + mFileHandle = LLLFSThread::nullHandle(); + mState = BODY; + } + } + else + { + return false; + } + } +#else + llassert_always(idx >= 0); + llassert_always(mOffset < TEXTURE_CACHE_ENTRY_SIZE); + S32 offset = idx * TEXTURE_CACHE_ENTRY_SIZE + mOffset; + S32 size = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + S32 bytes_written = ll_apr_file_write_ex(mCache->mHeaderDataFileName, mCache->getFileAPRPool(), + mWriteData, offset, size); + + if (bytes_written <= 0) + { + llwarns << "LLTextureCacheWorker: missing entry: " << mID << llendl; + mDataSize = -1; // failed + return true; + } + + if (mDataSize <= size) + { + return true; // done + } + else + { + mState = BODY; + } +#endif + } + + if (mState == BODY) + { +#if USE_LFS_WRITE + if (mFileHandle == LLLFSThread::nullHandle()) + { + S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + data_offset = llmax(data_offset, 0); + S32 file_size = mDataSize - data_offset; + S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; + file_offset = llmax(file_offset, 0); + if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) + { + std::string filename = mCache->getTextureFileName(mID); + mBytesRead = -1; + mBytesToRead = file_size; + setPriority(LLWorkerThread::PRIORITY_LOW | mPriority); + mFileHandle = LLLFSThread::sLocal->write(filename, + mWriteData + data_offset, file_offset, mBytesToRead, + new WriteResponder(mCache, mRequestHandle)); + return false; + } + else + { + mDataSize = 0; // no data written + return true; // done + } + } + else + { + if (mBytesRead >= 0) + { + if (mBytesRead != mBytesToRead) + { + llwarns << "LLTextureCacheWorker: " << mID + << " incorrect number of bytes written to body: " << mBytesRead + << " != " << mBytesToRead << llendl; + mDataSize = -1; // failed + } + return true; + } + else + { + return false; + } + } +#else + S32 data_offset = TEXTURE_CACHE_ENTRY_SIZE - mOffset; + data_offset = llmax(data_offset, 0); + S32 file_size = mDataSize - data_offset; + S32 file_offset = mOffset - TEXTURE_CACHE_ENTRY_SIZE; + file_offset = llmax(file_offset, 0); + S32 bytes_written = 0; + if (file_size > 0 && mCache->appendToTextureEntryList(mID, file_size)) + { + std::string filename = mCache->getTextureFileName(mID); + bytes_written = ll_apr_file_write_ex(filename, mCache->getFileAPRPool(), + mWriteData + data_offset, + file_offset, file_size); + if (bytes_written <= 0) + { + mDataSize = -1; // failed + } + } + else + { + mDataSize = 0; // no data written + } + + return true; +#endif + } + + return false; +} + +//virtual +bool LLTextureCacheWorker::doWork(S32 param) +{ + bool res = false; + if (param == 0) // read + { + res = doRead(); + } + else if (param == 1) // write + { + res = doWrite(); + } + else + { + llassert_always(0); + } + return res; +} + +//virtual (WORKER THREAD) +void LLTextureCacheWorker::finishWork(S32 param, bool completed) +{ + if (mResponder.notNull()) + { + bool success = (completed && mDataSize > 0); + if (param == 0) + { + // read + if (success) + { + mResponder->setData(mReadData, mDataSize, mImageSize, mImageFormat, mImageLocal); + mReadData = NULL; // responder owns data + mDataSize = 0; + } + else + { + delete[] mReadData; + mReadData = NULL; + + } + } + else + { + // write + mWriteData = NULL; // we never owned data + mDataSize = 0; + } + mCache->addCompleted(mResponder, success); + } +} + +//virtual (MAIN THREAD) +void LLTextureCacheWorker::endWork(S32 param, bool aborted) +{ + if (aborted) + { + // Let the destructor handle any cleanup + return; + } + switch(param) + { + default: + case 0: // read + case 1: // write + { + if (mDataSize < 0) + { + // failed + mCache->removeFromCache(mID); + } + break; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +LLTextureCache::LLTextureCache(bool threaded) + : LLWorkerThread("TextureCache", threaded), + mWorkersMutex(getAPRPool()), + mHeaderMutex(getAPRPool()), + mListMutex(getAPRPool()), + mFileAPRPool(NULL), + mReadOnly(FALSE), + mTexturesSizeTotal(0), + mDoPurge(FALSE) +{ + apr_pool_create(&mFileAPRPool, NULL); +} + +LLTextureCache::~LLTextureCache() +{ + apr_pool_destroy(mFileAPRPool); +} + +////////////////////////////////////////////////////////////////////////////// + +//virtual +S32 LLTextureCache::update(U32 max_time_ms) +{ + S32 res; + res = LLWorkerThread::update(max_time_ms); + + mListMutex.lock(); + handle_list_t priorty_list = mPrioritizeWriteList; // copy list + mPrioritizeWriteList.clear(); + responder_list_t completed_list = mCompletedList; // copy list + mCompletedList.clear(); + mListMutex.unlock(); + + lockWorkers(); + + for (handle_list_t::iterator iter1 = priorty_list.begin(); + iter1 != priorty_list.end(); ++iter1) + { + handle_t handle = *iter1; + handle_map_t::iterator iter2 = mWriters.find(handle); + if(iter2 != mWriters.end()) + { + LLTextureCacheWorker* worker = iter2->second; + worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mPriority); + } + } + + for (responder_list_t::iterator iter1 = completed_list.begin(); + iter1 != completed_list.end(); ++iter1) + { + Responder *responder = iter1->first; + bool success = iter1->second; + responder->completed(success); + } + + unlockWorkers(); + + return res; +} + +////////////////////////////////////////////////////////////////////////////// + +std::string LLTextureCache::getLocalFileName(const LLUUID& id) +{ + // Does not include extension + std::string idstr = id.asString(); + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_SKINS, "textures", idstr); + return filename; +} + +std::string LLTextureCache::getTextureFileName(const LLUUID& id) +{ + std::string idstr = id.asString(); + std::string delem = gDirUtilp->getDirDelimiter(); + std::string filename = mTexturesDirName + delem + idstr[0] + delem + idstr; + return filename; +} + +bool LLTextureCache::appendToTextureEntryList(const LLUUID& id, S32 bodysize) +{ + bool res = false; + bool purge = false; + // Append UUID to end of texture entries + { + LLMutexLock lock(&mHeaderMutex); + size_map_t::iterator iter = mTexturesSizeMap.find(id); + if (iter == mTexturesSizeMap.end() || iter->second < bodysize) + { + llassert_always(bodysize > 0); + Entry* entry = new Entry(id, bodysize, time(NULL)); + ll_apr_file_write_ex(mTexturesDirEntriesFileName, getFileAPRPool(), + (U8*)entry, -1, 1*sizeof(Entry)); + delete entry; + if (iter != mTexturesSizeMap.end()) + { + mTexturesSizeTotal -= iter->second; + } + mTexturesSizeTotal += bodysize; + mTexturesSizeMap[id] = bodysize; + if (mTexturesSizeTotal > sCacheMaxTexturesSize) + { + purge = true; + } + res = true; + } + } + if (purge) + { + mDoPurge = TRUE; + } + return res; +} + +////////////////////////////////////////////////////////////////////////////// + +//static +const S32 MAX_REASONABLE_FILE_SIZE = 512*1024*1024; // 512 MB +F32 LLTextureCache::sHeaderCacheVersion = 1.0f; +U32 LLTextureCache::sCacheMaxEntries = MAX_REASONABLE_FILE_SIZE / TEXTURE_CACHE_ENTRY_SIZE; +S64 LLTextureCache::sCacheMaxTexturesSize = 0; // no limit +const char* entries_filename = "texture.entries"; +const char* cache_filename = "texture.cache"; +const char* textures_dirname = "textures"; + +void LLTextureCache::setDirNames(ELLPath location) +{ + std::string delem = gDirUtilp->getDirDelimiter(); + mHeaderEntriesFileName = gDirUtilp->getExpandedFilename(location, entries_filename); + mHeaderDataFileName = gDirUtilp->getExpandedFilename(location, cache_filename); + mTexturesDirName = gDirUtilp->getExpandedFilename(location, textures_dirname); + mTexturesDirEntriesFileName = mTexturesDirName + delem + entries_filename; +} + +void LLTextureCache::purgeCache(ELLPath location) +{ + if (!mReadOnly) + { + setDirNames(location); + + ll_apr_file_remove(mHeaderEntriesFileName, NULL); + ll_apr_file_remove(mHeaderDataFileName, NULL); + } + purgeAllTextures(true); +} + +S64 LLTextureCache::initCache(ELLPath location, S64 max_size, BOOL read_only) +{ + mReadOnly = read_only; + + S64 header_size = (max_size * 2) / 10; + S64 max_entries = header_size / TEXTURE_CACHE_ENTRY_SIZE; + sCacheMaxEntries = (S32)(llmin((S64)sCacheMaxEntries, max_entries)); + header_size = sCacheMaxEntries * TEXTURE_CACHE_ENTRY_SIZE; + max_size -= header_size; + if (sCacheMaxTexturesSize > 0) + sCacheMaxTexturesSize = llmin(sCacheMaxTexturesSize, max_size); + else + sCacheMaxTexturesSize = max_size; + max_size -= sCacheMaxTexturesSize; + + llinfos << "TEXTURE CACHE: Headers: " << sCacheMaxEntries + << " Textures size: " << sCacheMaxTexturesSize/(1024*1024) << " MB" << llendl; + + setDirNames(location); + + if (!mReadOnly) + { + LLFile::mkdir(mTexturesDirName.c_str()); + const char* subdirs = "0123456789abcdef"; + for (S32 i=0; i<16; i++) + { + std::string dirname = mTexturesDirName + gDirUtilp->getDirDelimiter() + subdirs[i]; + LLFile::mkdir(dirname.c_str()); + } + } + readHeaderCache(); + purgeTextures(true); // calc mTexturesSize and make some room in the texture cache if we need it + + return max_size; // unused cache space +} + +struct lru_data +{ + lru_data(U32 t, S32 i, const LLUUID& id) { time=t; index=i; uuid=id; } + U32 time; + S32 index; + LLUUID uuid; + struct Compare + { + // lhs < rhs + typedef const lru_data* lru_data_ptr; + bool operator()(const lru_data_ptr& a, const lru_data_ptr& b) const + { + if (!(a->time < b->time)) + return true; + else if (!(b->time < a->time)) + return false; + else + return a->index < b->index; + } + }; +}; + +// Called from either the main thread or the worker thread +void LLTextureCache::readHeaderCache(apr_pool_t* poolp) +{ + LLMutexLock lock(&mHeaderMutex); + mHeaderEntriesInfo.mVersion = 0.f; + mHeaderEntriesInfo.mEntries = 0; + if (ll_apr_file_exists(mHeaderEntriesFileName, poolp)) + { + ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + } + if (mHeaderEntriesInfo.mVersion != sHeaderCacheVersion) + { + if (!mReadOnly) + { + // Info with 0 entries + mHeaderEntriesInfo.mVersion = sHeaderCacheVersion; + ll_apr_file_write_ex(mHeaderEntriesFileName, poolp, + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + } + } + else + { + S32 num_entries = mHeaderEntriesInfo.mEntries; + if (num_entries) + { + Entry* entries = new Entry[num_entries]; + ll_apr_file_read_ex(mHeaderEntriesFileName, poolp, + (U8*)entries, sizeof(EntriesInfo), num_entries*sizeof(Entry)); + typedef std::set lru_set_t; + lru_set_t lru; + for (S32 i=0; i= 0) // -1 indicates erased entry, skip + { + const LLUUID& id = entries[i].mID; + lru.insert(new lru_data(entries[i].mTime, i, id)); + mHeaderIDMap[id] = i; + } + } + mLRU.clear(); + S32 lru_entries = sCacheMaxEntries / 10; + for (lru_set_t::iterator iter = lru.begin(); iter != lru.end(); ++iter) + { + lru_data* data = *iter; + mLRU[data->index] = data->uuid; + if (--lru_entries <= 0) + break; + } + for_each(lru.begin(), lru.end(), DeletePointer()); + delete[] entries; + } + } +} + +////////////////////////////////////////////////////////////////////////////// + +void LLTextureCache::purgeAllTextures(bool purge_directories) +{ + if (!mReadOnly) + { + const char* subdirs = "0123456789abcdef"; + std::string delem = gDirUtilp->getDirDelimiter(); + std::string mask = delem + "*"; + for (S32 i=0; i<16; i++) + { + std::string dirname = mTexturesDirName + delem + subdirs[i]; + gDirUtilp->deleteFilesInDir(dirname.c_str(),mask); + if (purge_directories) + { + LLFile::rmdir(dirname.c_str()); + } + } + ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); + if (purge_directories) + { + LLFile::rmdir(mTexturesDirName.c_str()); + } + } + mTexturesSizeMap.clear(); +} + +void LLTextureCache::purgeTextures(bool validate) +{ + if (mReadOnly) + { + return; + } + + LLMutexLock lock(&mHeaderMutex); + + S32 filesize = ll_apr_file_size(mTexturesDirEntriesFileName, NULL); + S32 num_entries = filesize / sizeof(Entry); + if (num_entries * (S32)sizeof(Entry) != filesize) + { + llwarns << "Bad cache file: " << mTexturesDirEntriesFileName << " Purging." << llendl; + purgeAllTextures(false); + return; + } + if (num_entries == 0) + { + return; // nothing to do + } + + Entry* entries = new Entry[num_entries]; + S32 bytes_read = ll_apr_file_read_ex(mTexturesDirEntriesFileName, NULL, + (U8*)entries, 0, num_entries*sizeof(Entry)); + if (bytes_read != filesize) + { + llwarns << "Bad cache file (2): " << mTexturesDirEntriesFileName << " Purging." << llendl; + purgeAllTextures(false); + return; + } + + llinfos << "TEXTURE CACHE: Reading Entries..." << llendl; + + std::map entry_idx_map; + S64 total_size = 0; + for (S32 idx=0; idx::iterator iter = entry_idx_map.find(id); + if (iter != entry_idx_map.end()) + { + // Newer entry replacing older entry + S32 pidx = iter->second; + total_size -= entries[pidx].mSize; + entries[pidx].mSize = 0; // flag: skip older entry + } + entry_idx_map[id] = idx; + total_size += entries[idx].mSize; + } + + U32 validate_idx = 0; + if (validate) + { + validate_idx = gSavedSettings.getU32("CacheValidateCounter"); + U32 next_idx = (++validate_idx) % 256; + gSavedSettings.setU32("CacheValidateCounter", next_idx); + llinfos << "TEXTURE CACHE: Validating: " << validate_idx << llendl; + } + + S64 min_cache_size = (sCacheMaxTexturesSize * 9) / 10; + S32 purge_count = 0; + S32 next_idx = 0; + for (S32 idx=0; idx= min_cache_size) + { + purge_entry = true; + } + else if (validate) + { + // make sure file exists and is the correct size + S32 uuididx = entries[idx].mID.mData[0]; + if (uuididx == validate_idx) + { +// llinfos << "Validating: " << filename << "Size: " << entries[idx].mSize << llendl; + S32 bodysize = ll_apr_file_size(filename, NULL); + if (bodysize != entries[idx].mSize) + { + llwarns << "TEXTURE CACHE BODY HAS BAD SIZE: " << bodysize << " != " << entries[idx].mSize + << filename << llendl; + purge_entry = true; + } + } + } + if (purge_entry) + { + purge_count++; +// llinfos << "PURGING: " << filename << llendl; + ll_apr_file_remove(filename, NULL); + total_size -= entries[idx].mSize; + entries[idx].mSize = 0; + } + else + { + if (next_idx != idx) + { + entries[next_idx] = entries[idx]; + } + ++next_idx; + } + } + num_entries = next_idx; + + llinfos << "TEXTURE CACHE: Writing Entries: " << num_entries << llendl; + + ll_apr_file_remove(mTexturesDirEntriesFileName, NULL); + ll_apr_file_write_ex(mTexturesDirEntriesFileName, NULL, + (U8*)&entries[0], 0, num_entries*sizeof(Entry)); + + mTexturesSizeTotal = 0; + mTexturesSizeMap.clear(); + for (S32 idx=0; idxsecond; + } + return res; +} + +LLTextureCacheWorker* LLTextureCache::getWriter(handle_t handle) +{ + LLTextureCacheWorker* res = NULL; + handle_map_t::iterator iter = mWriters.find(handle); + if (iter != mWriters.end()) + { + res = iter->second; + } + return res; +} + +////////////////////////////////////////////////////////////////////////////// + +// Called from work thread +S32 LLTextureCache::getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize) +{ + bool retry = false; + S32 idx = -1; + + { + LLMutexLock lock(&mHeaderMutex); + id_map_t::iterator iter = mHeaderIDMap.find(id); + if (iter != mHeaderIDMap.end()) + { + idx = iter->second; + } + else if (touch && !mReadOnly) + { + if (mHeaderEntriesInfo.mEntries < sCacheMaxEntries) + { + // Add an entry + idx = mHeaderEntriesInfo.mEntries++; + mHeaderIDMap[id] = idx; + // Update Info + ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), + (U8*)&mHeaderEntriesInfo, 0, sizeof(EntriesInfo)); + } + else if (!mLRU.empty()) + { + idx = mLRU.begin()->first; // will be erased below + const LLUUID& oldid = mLRU.begin()->second; + mHeaderIDMap.erase(oldid); + mTexturesSizeMap.erase(oldid); + mHeaderIDMap[id] = idx; + } + else + { + idx = -1; + retry = true; + } + } + if (idx >= 0) + { + if (touch && !mReadOnly) + { + // Update the lru entry + mLRU.erase(idx); + llassert_always(imagesize && *imagesize > 0); + Entry* entry = new Entry(id, *imagesize, time(NULL)); + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + ll_apr_file_write_ex(mHeaderEntriesFileName, getFileAPRPool(), + (U8*)entry, offset, sizeof(Entry)); + delete entry; + } + else if (imagesize) + { + // Get the image size + Entry entry; + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + ll_apr_file_read_ex(mHeaderEntriesFileName, getFileAPRPool(), + (U8*)&entry, offset, sizeof(Entry)); + *imagesize = entry.mSize; + } + } + } + if (retry) + { + readHeaderCache(getFileAPRPool()); // updates the lru + llassert_always(!mLRU.empty() || mHeaderEntriesInfo.mEntries < sCacheMaxEntries); + idx = getHeaderCacheEntry(id, touch, imagesize); // assert above ensures no inf. recursion + } + return idx; +} + +////////////////////////////////////////////////////////////////////////////// + +// Calls from texture pipeline thread (i.e. LLTextureFetch) + +LLTextureCache::handle_t LLTextureCache::readFromCache(const LLUUID& id, U32 priority, + S32 offset, S32 size, ReadResponder* responder) +{ + // Note: checking to see if an entry exists can cause a stall, + // so let the thread handle it + LLMutexLock lock(&mWorkersMutex); + LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, + NULL, size, offset, 0, + responder); + handle_t handle = worker->read(); + mReaders[handle] = worker; + return handle; +} + +bool LLTextureCache::readComplete(handle_t handle, bool abort) +{ + lockWorkers(); + handle_map_t::iterator iter = mReaders.find(handle); + llassert_always(iter != mReaders.end()); + LLTextureCacheWorker* worker = iter->second; + bool res = worker->complete(); + if (res || abort) + { + mReaders.erase(handle); + unlockWorkers(); + worker->scheduleDelete(); + return true; + } + else + { + unlockWorkers(); + return false; + } +} + +LLTextureCache::handle_t LLTextureCache::writeToCache(const LLUUID& id, U32 priority, + U8* data, S32 datasize, S32 imagesize, + WriteResponder* responder) +{ + if (mReadOnly) + { + return LLWorkerThread::nullHandle(); + } + if (mDoPurge) + { + // NOTE: This may cause an occasional hiccup, + // but it really needs to be done on the control thread + // (i.e. here) + purgeTextures(false); + mDoPurge = FALSE; + } + if (datasize >= TEXTURE_CACHE_ENTRY_SIZE) + { + LLMutexLock lock(&mWorkersMutex); + llassert_always(imagesize > 0); + LLTextureCacheWorker* worker = new LLTextureCacheWorker(this, priority, id, + data, datasize, 0, + imagesize, responder); + handle_t handle = worker->write(); + mWriters[handle] = worker; + return handle; + } + return LLWorkerThread::nullHandle(); +} + +bool LLTextureCache::writeComplete(handle_t handle, bool abort) +{ + lockWorkers(); + handle_map_t::iterator iter = mWriters.find(handle); + llassert_always(iter != mWriters.end()); + LLTextureCacheWorker* worker = iter->second; + if (worker->complete() || abort) + { + mWriters.erase(handle); + unlockWorkers(); + worker->scheduleDelete(); + return true; + } + else + { + unlockWorkers(); + return false; + } +} + +void LLTextureCache::prioritizeWrite(handle_t handle) +{ + // Don't prioritize yet, we might be working on this now + // which could create a deadlock + LLMutexLock lock(&mListMutex); + mPrioritizeWriteList.push_back(handle); +} + +void LLTextureCache::addCompleted(Responder* responder, bool success) +{ + LLMutexLock lock(&mListMutex); + mCompletedList.push_back(std::make_pair(responder,success)); +} + +////////////////////////////////////////////////////////////////////////////// + +// Called from MAIN thread (endWork()) + +bool LLTextureCache::removeHeaderCacheEntry(const LLUUID& id) +{ + if (mReadOnly) + { + return false; + } + LLMutexLock lock(&mHeaderMutex); + id_map_t::iterator iter = mHeaderIDMap.find(id); + if (iter != mHeaderIDMap.end()) + { + S32 idx = iter->second; + if (idx >= 0) + { + Entry* entry = new Entry(id, -1, time(NULL)); + S32 offset = sizeof(EntriesInfo) + idx * sizeof(Entry); + ll_apr_file_write_ex(mHeaderEntriesFileName, NULL, + (U8*)entry, offset, sizeof(Entry)); + delete entry; + mLRU[idx] = id; + mHeaderIDMap.erase(id); + mTexturesSizeMap.erase(id); + return true; + } + } + return false; +} + +void LLTextureCache::removeFromCache(const LLUUID& id) +{ + llwarns << "Removing texture from cache: " << id << llendl; + if (!mReadOnly) + { + removeHeaderCacheEntry(id); + ll_apr_file_remove(getTextureFileName(id), NULL); + } +} + +////////////////////////////////////////////////////////////////////////////// + +LLTextureCache::ReadResponder::ReadResponder() + : mImageSize(0), + mImageLocal(FALSE) +{ +} + +void LLTextureCache::ReadResponder::setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) +{ + if (mFormattedImage.notNull()) + { + llassert_always(mFormattedImage->getCodec() == imageformat); + mFormattedImage->appendData(data, datasize); + } + else + { + mFormattedImage = LLImageFormatted::createFromType(imageformat); + mFormattedImage->setData(data,datasize); + } + mImageSize = imagesize; + mImageLocal = imagelocal; +} + +////////////////////////////////////////////////////////////////////////////// diff --git a/linden/indra/newview/lltexturecache.h b/linden/indra/newview/lltexturecache.h new file mode 100644 index 0000000..ec20066 --- /dev/null +++ b/linden/indra/newview/lltexturecache.h @@ -0,0 +1,175 @@ +/** + * @file lltexturecache.h + * @brief Object for managing texture cachees. + * + * Copyright (c) 2000-2007, Linden Research, Inc. + * + * The source code in this file ("Source Code") is provided by Linden Lab + * to you under the terms of the GNU General Public License, version 2.0 + * ("GPL"), unless you have obtained a separate licensing agreement + * ("Other License"), formally executed 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. + */ + +#ifndef LL_LLTEXTURECACHE_ +#define LL_LLTEXTURECACHE_H + +#include "lldir.h" +#include "llstl.h" +#include "llstring.h" +#include "lluuid.h" + +#include "llworkerthread.h" + +class LLTextureCacheWorker; + +class LLTextureCache : public LLWorkerThread +{ + friend class LLTextureCacheWorker; + +public: + + class Responder : public LLResponder + { + public: + virtual void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) = 0; + }; + + class ReadResponder : public Responder + { + public: + ReadResponder(); + void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal); + void setImage(LLImageFormatted* image) { mFormattedImage = image; } + protected: + LLPointer mFormattedImage; + S32 mImageSize; + BOOL mImageLocal; + }; + + class WriteResponder : public Responder + { + void setData(U8* data, S32 datasize, S32 imagesize, S32 imageformat, BOOL imagelocal) + { + // not used + } + }; + + LLTextureCache(bool threaded); + ~LLTextureCache(); + + /*virtual*/ S32 update(U32 max_time_ms); + + void purgeCache(ELLPath location); + S64 initCache(ELLPath location, S64 maxsize, BOOL read_only); + + handle_t readFromCache(const LLUUID& id, U32 priority, S32 offset, S32 size, + ReadResponder* responder); + bool readComplete(handle_t handle, bool abort); + handle_t writeToCache(const LLUUID& id, U32 priority, U8* data, S32 datasize, S32 imagesize, + WriteResponder* responder); + bool writeComplete(handle_t handle, bool abort = false); + void prioritizeWrite(handle_t handle); + + void removeFromCache(const LLUUID& id); + + // For LLTextureCacheWorker::Responder + LLTextureCacheWorker* getReader(handle_t handle); + LLTextureCacheWorker* getWriter(handle_t handle); + void lockWorkers() { mWorkersMutex.lock(); } + void unlockWorkers() { mWorkersMutex.unlock(); } + + // debug + S32 getNumReads() { return mReaders.size(); } + S32 getNumWrites() { return mWriters.size(); } + +protected: + // Accessed by LLTextureCacheWorker + apr_pool_t* getFileAPRPool() { return mFileAPRPool; } + bool appendToTextureEntryList(const LLUUID& id, S32 size); + std::string getLocalFileName(const LLUUID& id); + std::string getTextureFileName(const LLUUID& id); + void addCompleted(Responder* responder, bool success); + +private: + void setDirNames(ELLPath location); + void readHeaderCache(apr_pool_t* poolp = NULL); + void purgeAllTextures(bool purge_directories); + void purgeTextures(bool validate); + S32 getHeaderCacheEntry(const LLUUID& id, bool touch, S32* imagesize = NULL); + bool removeHeaderCacheEntry(const LLUUID& id); + void lockHeaders() { mHeaderMutex.lock(); } + void unlockHeaders() { mHeaderMutex.unlock(); } + +private: + // Internal + LLMutex mWorkersMutex; + LLMutex mHeaderMutex; + LLMutex mListMutex; + apr_pool_t* mFileAPRPool; + + typedef std::map handle_map_t; + handle_map_t mReaders; + handle_map_t mWriters; + + typedef std::vector handle_list_t; + handle_list_t mPrioritizeWriteList; + + typedef std::vector, bool> > responder_list_t; + responder_list_t mCompletedList; + + BOOL mReadOnly; + + // Entries + struct EntriesInfo + { + F32 mVersion; + U32 mEntries; + }; + struct Entry + { + Entry() {} + Entry(const LLUUID& id, S32 size, U32 time) : mID(id), mSize(size), mTime(time) {} + LLUUID mID; // 128 bits + S32 mSize; // total size of image if known (NOT size cached) + U32 mTime; // seconds since 1/1/1970 + }; + + // HEADERS (Include first mip) + std::string mHeaderEntriesFileName; + std::string mHeaderDataFileName; + EntriesInfo mHeaderEntriesInfo; + typedef std::map index_map_t; + index_map_t mLRU; // index, id; stored as a map for fast removal + typedef std::map id_map_t; + id_map_t mHeaderIDMap; + + // BODIES (TEXTURES minus headers) + std::string mTexturesDirName; + std::string mTexturesDirEntriesFileName; + typedef std::map size_map_t; + size_map_t mTexturesSizeMap; + S64 mTexturesSizeTotal; + LLAtomic32 mDoPurge; + + // Statics + static F32 sHeaderCacheVersion; + static U32 sCacheMaxEntries; + static S64 sCacheMaxTexturesSize; +}; + +#endif // LL_LLTEXTURECACHE_H diff --git a/linden/indra/newview/lltexturectrl.cpp b/linden/indra/newview/lltexturectrl.cpp index 9edd0ad..666b5d2 100644 --- a/linden/indra/newview/lltexturectrl.cpp +++ b/linden/indra/newview/lltexturectrl.cpp @@ -114,6 +114,7 @@ public: EAcceptance *accept, LLString& tooltip_msg); virtual void draw(); + virtual BOOL handleKeyHere(KEY key, MASK mask, BOOL called_from_parent); // LLFloater overrides virtual void onClose(bool app_quitting); @@ -175,6 +176,7 @@ protected: BOOL mCanApplyImmediately; BOOL mNoCopyTextureSelected; F32 mContextConeOpacity; + LLSaveFolderState mSavedFolderState; }; LLFloaterTexturePicker::LLFloaterTexturePicker( @@ -229,12 +231,16 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( filter_types |= 0x1 << LLInventoryType::IT_TEXTURE; filter_types |= 0x1 << LLInventoryType::IT_SNAPSHOT; - mInventoryPanel->setAutoSelectOverride(true); mInventoryPanel->setFilterTypes(filter_types); - mInventoryPanel->setFilterPermMask(getFilterPermMask()); + //mInventoryPanel->setFilterPermMask(getFilterPermMask()); //Commented out due to no-copy texture loss. + mInventoryPanel->setFilterPermMask(immediate_filter_perm_mask); mInventoryPanel->setSelectCallback(onSelectionChange, this); mInventoryPanel->setShowFolderState(LLInventoryFilter::SHOW_NON_EMPTY_FOLDERS); mInventoryPanel->setAllowMultiSelect(FALSE); + + // store this filter as the default one + mInventoryPanel->getRootFolder()->getFilter()->markDefault(); + // Commented out to stop opening all folders with textures // mInventoryPanel->openDefaultFolderForType(LLAssetType::AT_TEXTURE); @@ -262,6 +268,8 @@ LLFloaterTexturePicker::LLFloaterTexturePicker( updateFilterPermMask(); setCanMinimize(FALSE); + + mSavedFolderState.setApply(FALSE); } LLFloaterTexturePicker::~LLFloaterTexturePicker() @@ -315,7 +323,7 @@ void LLFloaterTexturePicker::setCanApplyImmediately(BOOL b) void LLFloaterTexturePicker::stopUsingPipette() { - if (gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette) + if (gToolMgr && gToolMgr->getCurrentTool() == gToolPipette) { gToolMgr->clearTransientTool(); } @@ -338,7 +346,8 @@ void LLFloaterTexturePicker::updateImageStats() } if (gAgent.isGodlike()) { - LLString tstring = "Pick: " + mTexturep->getID().getString(); + LLString tstring = "Pick: "; + tstring.append(mTexturep->getID().asString()); setTitle(tstring); } } @@ -368,7 +377,8 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( if (mod) item_perm_mask |= PERM_MODIFY; if (xfer) item_perm_mask |= PERM_TRANSFER; - PermissionMask filter_perm_mask = getFilterPermMask(); + //PermissionMask filter_perm_mask = getFilterPermMask(); Commented out due to no-copy texture loss. + PermissionMask filter_perm_mask = mImmediateFilterPermMask; if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) { if (drop) @@ -395,6 +405,41 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop( return handled; } +BOOL LLFloaterTexturePicker::handleKeyHere(KEY key, MASK mask, BOOL called_from_parent) +{ + LLFolderView* root_folder = mInventoryPanel->getRootFolder(); + + if (!called_from_parent && root_folder && + mSearchEdit && mSearchEdit->hasFocus() && + (key == KEY_RETURN || key == KEY_DOWN) && mask == MASK_NONE) + { + if (!root_folder->getCurSelectedItem()) + { + LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); + if (itemp) + { + root_folder->setSelection(itemp, FALSE, FALSE); + } + } + root_folder->scrollToShowSelection(); + + // move focus to inventory proper + root_folder->setFocus(TRUE); + + // treat this as a user selection of the first filtered result + commitIfImmediateSet(); + + return TRUE; + } + + if (root_folder->hasFocus() && key == KEY_UP) + { + mSearchEdit->focusFirstItem(TRUE); + } + + return LLFloater::handleKeyHere(key, mask, called_from_parent); +} + // virtual void LLFloaterTexturePicker::onClose(bool app_quitting) { @@ -469,7 +514,7 @@ void LLFloaterTexturePicker::draw() childSetEnabled("show_folders_check", mActive && mCanApplyImmediately && !mNoCopyTextureSelected); childSetEnabled("Select", mActive); childSetEnabled("Pipette", gToolMgr != NULL && mActive); - childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolPipette); + childSetValue("Pipette", gToolMgr && gToolMgr->getCurrentTool() == gToolPipette); //RN: reset search bar to reflect actual search query (all caps, for example) mSearchEdit->setText(mInventoryPanel->getFilterSubString()); @@ -747,60 +792,43 @@ void LLFloaterTexturePicker::onApplyImmediateCheck(LLUICtrl* ctrl, void *user_da void LLFloaterTexturePicker::updateFilterPermMask() { - mInventoryPanel->setFilterPermMask( getFilterPermMask() ); + //mInventoryPanel->setFilterPermMask( getFilterPermMask() ); Commented out due to no-copy texture loss. } void LLFloaterTexturePicker::onSearchEdit(const LLString& search_string, void* user_data ) { LLFloaterTexturePicker* picker = (LLFloaterTexturePicker*)user_data; - std::string filter_text = search_string; - - if (filter_text.empty()&& picker->mInventoryPanel->getFilterSubString().empty()) - { - // current filter and new filter empty, do nothing - return; - } - std::string upper_case_search_string = filter_text; + std::string upper_case_search_string = search_string; LLString::toUpper(upper_case_search_string); - picker->mInventoryPanel->setFilterSubString(upper_case_search_string); - - LLFolderView* root_folder = picker->mInventoryPanel->getRootFolder(); - - //if (search_string.size()) - //{ - // LLSelectFirstFilteredItem filter; - // root_folder->applyFunctorRecursively(filter); - // //...and scroll to show it - // root_folder->scrollToShowSelection(); - //} - - KEY key = gKeyboard->currentKey(); - - if ((key == KEY_RETURN || key == KEY_DOWN) && gKeyboard->currentMask(FALSE) == MASK_NONE) + if (upper_case_search_string.empty()) { - if (search_string.size()) + if (picker->mInventoryPanel->getFilterSubString().empty()) { - LLSelectFirstFilteredItem filter; - root_folder->applyFunctorRecursively(filter); - //...and scroll to show it - root_folder->scrollToShowSelection(); + // current filter and new filter empty, do nothing + return; } - if (!root_folder->getCurSelectedItem()) + picker->mSavedFolderState.setApply(TRUE); + picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState); + // add folder with current item to list of previously opened folders + LLOpenFoldersWithSelection opener; + picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(opener); + picker->mInventoryPanel->getRootFolder()->scrollToShowSelection(); + + } + else if (picker->mInventoryPanel->getFilterSubString().empty()) + { + // first letter in search term, save existing folder open state + if (!picker->mInventoryPanel->getRootFolder()->isFilterActive()) { - LLFolderViewItem* itemp = root_folder->getItemByID(gAgent.getInventoryRootID()); - if (itemp) - { - root_folder->setSelection(itemp, FALSE, FALSE); - } + picker->mSavedFolderState.setApply(FALSE); + picker->mInventoryPanel->getRootFolder()->applyFunctorRecursively(picker->mSavedFolderState); } - - // move focus to inventory proper - root_folder->setFocus(TRUE); - root_folder->scrollToShowSelection(); } + + picker->mInventoryPanel->setFilterSubString(upper_case_search_string); } //static @@ -1039,7 +1067,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus) // Show the dialog if( floaterp ) { - floaterp->open( ); + floaterp->open( ); /* Flawfinder: ignore */ } else { @@ -1060,7 +1088,7 @@ void LLTextureCtrl::showPicker(BOOL take_focus) mFloaterHandle = floaterp->getHandle(); gFloaterView->getParentFloater(this)->addDependentFloater(floaterp); - floaterp->open(); + floaterp->open(); /* Flawfinder: ignore */ } if (take_focus) @@ -1270,8 +1298,9 @@ BOOL LLTextureCtrl::allowDrop(LLInventoryItem* item) if (mod) item_perm_mask |= PERM_MODIFY; if (xfer) item_perm_mask |= PERM_TRANSFER; - PermissionMask filter_perm_mask = mCanApplyImmediately ? - mImmediateFilterPermMask : mNonImmediateFilterPermMask; +// PermissionMask filter_perm_mask = mCanApplyImmediately ? commented out due to no-copy texture loss. +// mImmediateFilterPermMask : mNonImmediateFilterPermMask; + PermissionMask filter_perm_mask = mImmediateFilterPermMask; if ( (item_perm_mask & filter_perm_mask) == filter_perm_mask ) { if(mDragCallback) diff --git a/linden/indra/newview/lltexturefetch.cpp b/linden/indra/newview/lltexturefetch.cpp index 9344bbf..54b3f28 100644 --- a/linden/indra/newview/lltexturefetch.cpp +++ b/linden/indra/newview/lltexturefetch.cpp @@ -1,6 +1,6 @@ /** - * @file llviewerimage.cpp - * @brief Object which handles a received image (and associated texture(s)) + * @file lltexturecache.cpp + * @brief Object which fetches textures from the cache and/or network * * Copyright (c) 2000-2007, Linden Research, Inc. * @@ -31,96 +31,290 @@ #include "lltexturefetch.h" -#include "llworkerthread.h" +#include "llcurl.h" +#include "llhttpclient.h" #include "llimage.h" -#include "llvfs.h" +#include "llimageworker.h" +#include "llworkerthread.h" +#include "llagent.h" +#include "lltexturecache.h" +#include "llviewerimagelist.h" #include "llviewerimage.h" +#include "llviewerregion.h" #include "viewer.h" ////////////////////////////////////////////////////////////////////////////// +//static class LLTextureFetchWorker : public LLWorkerClass { - friend class LLTextureFetchImpl; - -public: - // From LLWorkerClass - static void initClass(bool threaded, bool runalways); - static void updateClass(); - static void cleanupClass(); - - // New methods - static LLTextureFetchWorker* getWorker(const LLUUID& id, const LLHost& host, - F32 mPriority, S32 discard, - BOOL needs_aux = FALSE); - static LLTextureFetchWorker* getActiveWorker(const LLUUID& id); + friend class LLTextureFetch; private: - static void sendRequestListToSimulators(); + class URLResponder : public LLHTTPClient::Responder + { + public: + URLResponder(LLTextureFetch* fetcher, const LLUUID& id) + : mFetcher(fetcher), mID(id) + { + } + ~URLResponder() + { + } + virtual void error(U32 status, const std::string& reason) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + llinfos << "LLTextureFetchWorker::URLResponder::error " << status << ": " << reason << llendl; + worker->callbackURLReceived(LLSD(), false); + } + mFetcher->unlockQueue(); + } + virtual void result(const LLSD& content) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + worker->callbackURLReceived(content, true); + } + mFetcher->unlockQueue(); + } + private: + LLTextureFetch* mFetcher; + LLUUID mID; + }; + + class HTTPGetResponder : public LLCurl::Responder + { + public: + HTTPGetResponder(LLTextureFetch* fetcher, const LLUUID& id) + : mFetcher(fetcher), mID(id) + { + } + ~HTTPGetResponder() + { + } + virtual void completed(U32 status, const std::stringstream& content) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + const std::string& cstr = content.str(); + if (200 <= status && status < 300) + { + if (203 == status) // partial information (i.e. last block) + { + worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), true); + } + else + { + worker->callbackHttpGet((U8*)cstr.c_str(), cstr.length(), false); + } + } + else + { + llinfos << "LLTextureFetchWorker::HTTPGetResponder::error " << status << ": " << cstr << llendl; + worker->callbackHttpGet(NULL, -1, true); + } + } + mFetcher->unlockQueue(); + } + private: + LLTextureFetch* mFetcher; + LLUUID mID; + }; + + class CacheReadResponder : public LLTextureCache::ReadResponder + { + public: + CacheReadResponder(LLTextureFetch* fetcher, const LLUUID& id, LLImageFormatted* image) + : mFetcher(fetcher), mID(id) + { + setImage(image); + } + virtual void completed(bool success) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + worker->callbackCacheRead(success, mFormattedImage, mImageSize, mImageLocal); + } + mFetcher->unlockQueue(); + } + private: + LLTextureFetch* mFetcher; + LLUUID mID; + }; + + class CacheWriteResponder : public LLTextureCache::WriteResponder + { + public: + CacheWriteResponder(LLTextureFetch* fetcher, const LLUUID& id) + : mFetcher(fetcher), mID(id) + { + } + virtual void completed(bool success) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + worker->callbackCacheWrite(success); + } + mFetcher->unlockQueue(); + } + private: + LLTextureFetch* mFetcher; + LLUUID mID; + }; + + class DecodeResponder : public LLResponder + { + public: + DecodeResponder(LLTextureFetch* fetcher, const LLUUID& id, LLTextureFetchWorker* worker) + : mFetcher(fetcher), mID(id), mWorker(worker) + { + } + virtual void completed(bool success) + { + mFetcher->lockQueue(); + LLTextureFetchWorker* worker = mFetcher->getWorker(mID); + if (worker) + { + worker->callbackDecoded(success); + } + mFetcher->unlockQueue(); + } + private: + LLTextureFetch* mFetcher; + LLUUID mID; + LLTextureFetchWorker* mWorker; // debug only (may get deleted from under us, use mFetcher/mID) + }; + + struct Compare + { + // lhs < rhs + bool operator()(const LLTextureFetchWorker* lhs, const LLTextureFetchWorker* rhs) const + { + // greater priority is "less" + const F32 lpriority = lhs->mImagePriority; + const F32 rpriority = rhs->mImagePriority; + if (lpriority > rpriority) // higher priority + return true; + else if (lpriority < rpriority) + return false; + else + return lhs < rhs; + } + }; public: - virtual bool doWork(S32 param); // Called from LLWorkerThread::processRequest() + /*virtual*/ bool doWork(S32 param); // Called from LLWorkerThread::processRequest() + /*virtual*/ void finishWork(S32 param, bool completed); // called from finishRequest() (WORK THREAD) + /*virtual*/ bool deleteOK(); // called from update() (WORK THREAD) ~LLTextureFetchWorker(); void relese() { --mActiveCount; } - protected: - LLTextureFetchWorker(const LLUUID& id, const LLHost& host, F32 mPriority, S32 discard); + LLTextureFetchWorker(LLTextureFetch* fetcher, const LLUUID& id, const LLHost& host, + F32 priority, S32 discard, S32 size); private: - virtual void startWork(S32 param); // called from addWork() (MAIN THREAD) - virtual void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) + /*virtual*/ void startWork(S32 param); // called from addWork() (MAIN THREAD) + /*virtual*/ void endWork(S32 param, bool aborted); // called from doWork() (MAIN THREAD) + void resetFormattedData(); + void setImagePriority(F32 priority); - void setDesiredDiscard(S32 discard); - void insertPacket(S32 index, U8* data, S32 size); + void setDesiredDiscard(S32 discard, S32 size); + bool insertPacket(S32 index, U8* data, S32 size); void clearPackets(); U32 calcWorkPriority(); - bool startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type); - bool loadFromVFS(); + void removeFromCache(); bool processSimulatorPackets(); - void startDecode(); bool decodeImage(); - + bool writeToCacheComplete(); + void lockWorkData() { mWorkMutex.lock(); } void unlockWorkData() { mWorkMutex.unlock(); } - - static void lockQueue() { sDataMutex->lock(); } - static void unlockQueue() { sDataMutex->unlock(); } + + void callbackURLReceived(const LLSD& data, bool success); + void callbackHttpGet(U8* data, S32 data_size, bool last_block); + void callbackCacheRead(bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal); + void callbackCacheWrite(bool success); + void callbackDecoded(bool success); private: - enum e_state + enum e_state // mState { - INIT = 1, - LOAD_FROM_CACHE, + // NOTE: Affects LLTextureBar::draw in lltextureview.cpp (debug hack) + INVALID = 0, + INIT, + LOAD_FROM_TEXTURE_CACHE, + CACHE_POST, + LOAD_FROM_NETWORK, LOAD_FROM_SIMULATOR, - WRITE_TO_VFS, + LOAD_FROM_HTTP_GET_URL, + LOAD_FROM_HTTP_GET_DATA, DECODE_IMAGE, DECODE_IMAGE_UPDATE, + WRITE_TO_CACHE, + WAIT_ON_WRITE, DONE }; + enum e_request_state // mSentRequest + { + UNSENT = 0, + QUEUED = 1, + SENT_SIM = 2, + SENT_URL = 3, + SENT_HTTP = 4 + }; + static const char* sStateDescs[]; e_state mState; + LLTextureFetch* mFetcher; + LLImageWorker* mImageWorker; LLPointer mFormattedImage; LLPointer mRawImage; LLPointer mAuxImage; LLUUID mID; LLHost mHost; - F32 mPriority; + U8 mType; + F32 mImagePriority; + U32 mWorkPriority; + F32 mRequestedPriority; S32 mDesiredDiscard; + S32 mSimRequestedDiscard; S32 mRequestedDiscard; + S32 mLoadedDiscard; S32 mDecodedDiscard; LLFrameTimer mRequestedTimer; - LLFrameTimer mIdleTimer; - LLVFSThread::handle_t mFileHandle; + LLFrameTimer mFetchTimer; + LLTextureCache::handle_t mCacheReadHandle; + LLTextureCache::handle_t mCacheWriteHandle; U8* mBuffer; S32 mBufferSize; S32 mRequestedSize; + S32 mDesiredSize; + S32 mFileSize; + S32 mCachedSize; BOOL mLoaded; - BOOL mRequested; + e_request_state mSentRequest; BOOL mDecoded; + BOOL mWritten; BOOL mNeedsAux; + BOOL mHaveAllData; + BOOL mInLocalCache; + S32 mRetryAttempt; + std::string mURL; S32 mActiveCount; // Work Data @@ -129,635 +323,1532 @@ private: { PacketData(U8* data, S32 size) { mData = data; mSize = size; } ~PacketData() { clearData(); } - void clearData() { delete mData; mData = NULL; } + void clearData() { delete[] mData; mData = NULL; } U8* mData; U32 mSize; }; std::vector mPackets; + S32 mFirstPacket; S32 mLastPacket; - S32 mTotalPackets; - S32 mTotalBytes; - - // Class variables (statics) - - static LLWorkerThread* sWorkerThread; - static LLMutex* sDataMutex; - - // Map of all requests by UUID - typedef std::map map_t; - static map_t sRequests; - - // Set of requests that require network data - typedef std::set queue_t ; - static queue_t sNetworkQueue; - - static LLFrameTimer sNetworkTimer; + U16 mTotalPackets; + U8 mImageCodec; }; -//statics -LLTextureFetchWorker::map_t LLTextureFetchWorker::sRequests; -LLTextureFetchWorker::queue_t LLTextureFetchWorker::sNetworkQueue; -LLFrameTimer LLTextureFetchWorker::sNetworkTimer; -LLWorkerThread* LLTextureFetchWorker::sWorkerThread = NULL; -LLMutex* LLTextureFetchWorker::sDataMutex = NULL; - -// called from MAIN THREAD -//static -void LLTextureFetchWorker::initClass(bool threaded, bool runalways) -{ - sWorkerThread = new LLWorkerThread(threaded, runalways); - sDataMutex = new LLMutex(sWorkerThread->getAPRPool()); -} - -// called from MAIN THREAD //static -void LLTextureFetchWorker::updateClass() -{ - const F32 REQUEST_TIME = 1.f; - const F32 MIN_IDLE_TIME = 1.f * 60.f; // 1 minute - const F32 MAX_IDLE_TIME = 5.f * 60.f; // 5 minutes - const S32 MIN_IDLE_COUNT = 16; // always keep last 16 idle requests - const F32 MAX_IDLE_COUNT = 1024; // max number of idle requests - - // Periodically, gather the list of textures that need data from the network - // And send the requests out to the simulators - if (sNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME) - { - sNetworkTimer.reset(); - sendRequestListToSimulators(); - } - // Remove any old requests (releasing their raw data) - typedef std::pair idle_pair; - typedef std::set > idle_set; - idle_set remove_set; - for (map_t::iterator iter = sRequests.begin(); iter != sRequests.end(); ++iter) - { - LLTextureFetchWorker* worker = iter->second; - if (worker->mActiveCount > 0) - continue; - if (worker->haveWork()) - continue; - F32 idletime = worker->mIdleTimer.getElapsedTimeF32(); - if (idletime < MIN_IDLE_TIME) - continue; - remove_set.insert(std::make_pair(idletime, worker)); - } - S32 num_left = remove_set.size(); - for (idle_set::iterator iter = remove_set.begin(); iter != remove_set.end(); ++iter) - { - if (num_left <= MIN_IDLE_COUNT) - break; - if (iter->first < MAX_IDLE_TIME && - num_left < MAX_IDLE_COUNT) - break; - num_left--; - } -} +const char* LLTextureFetchWorker::sStateDescs[] = { + "INVALID", + "INIT", + "LOAD_FROM_TEXTURE_CACHE", + "CACHE_POST", + "LOAD_FROM_NETWORK", + "LOAD_FROM_SIMULATOR", + "LOAD_FROM_HTTP_URL", + "LOAD_FROM_HTTP_DATA", + "DECODE_IMAGE", + "DECODE_IMAGE_UPDATE", + "WRITE_TO_CACHE", + "WAIT_ON_WRITE", + "DONE", +}; // called from MAIN THREAD -//static -void LLTextureFetchWorker::sendRequestListToSimulators() -{ - const F32 LAZY_FLUSH_TIMEOUT = 60.f; - const S32 IMAGES_PER_REQUEST = 50; - // Send requests - typedef std::map< LLHost, std::vector > work_request_map_t; - work_request_map_t requests; - for (queue_t::iterator iter = sNetworkQueue.begin(); iter != sNetworkQueue.end(); ++iter) - { - LLTextureFetchWorker* req = *iter; - if (req->haveWork()) - { - continue; // busy - } - if ((req->mRequestedDiscard == req->mDesiredDiscard) && - (req->mRequestedTimer.getElapsedTimeF32() < LAZY_FLUSH_TIMEOUT)) - { - continue; - } - req->mRequestedDiscard = req->mDesiredDiscard; - req->mRequestedTimer.reset(); - requests[req->mHost].push_back(req); - } - for (work_request_map_t::iterator iter1 = requests.begin(); - iter1 != requests.end(); ++iter1) - { - LLHost host = iter1->first; - // invalid host = load from static VFS - if (host != LLHost::invalid) - { - S32 request_count = 0; - for (std::vector::iterator iter2 = iter1->second.begin(); - iter2 != iter1->second.end(); ++iter2) - { - LLTextureFetchWorker* req = *iter2; - if (0 == request_count) - { - gMessageSystem->newMessageFast(_PREHASH_RequestImage); - } - S32 packet = req->mLastPacket + 1; - gMessageSystem->nextBlockFast(_PREHASH_RequestImage); - gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID); - gMessageSystem->addS32Fast(_PREHASH_DiscardLevel, req->mDesiredDiscard); - gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mPriority); - gMessageSystem->addU32Fast(_PREHASH_Packet, packet); - - request_count++; - if (request_count >= IMAGES_PER_REQUEST) - { - gMessageSystem->sendSemiReliable(host, NULL, NULL); - request_count = 0; - } - } - if (request_count >= IMAGES_PER_REQUEST) - { - gMessageSystem->sendSemiReliable(host, NULL, NULL); - } - } - } -} - -//static -LLTextureFetchWorker* LLTextureFetchWorker::getWorker(const LLUUID& id, - const LLHost& host, - F32 priority, - S32 discard, - BOOL needs_aux) -{ - LLTextureFetchWorker* res; - lockQueue(); - map_t::iterator iter = sRequests.find(id); - if (iter != sRequests.end()) - { - res = iter->second; - if (res->mHost != host) - { - llerrs << "LLTextureFetchWorker::getWorker called with multiple hosts" << llendl; - } - res->setImagePriority(priority); - res->setDesiredDiscard(discard); - - } - else - { - res = new LLTextureFetchWorker(id, host, priority, discard); - } - unlockQueue(); - res->mActiveCount++; - res->mNeedsAux = needs_aux; - return res; -} - -LLTextureFetchWorker* LLTextureFetchWorker::getActiveWorker(const LLUUID& id) -{ - LLTextureFetchWorker* res = NULL; - lockQueue(); - map_t::iterator iter = sRequests.find(id); - if (iter != sRequests.end()) - { - res = iter->second; - } - unlockQueue(); - return res; -} -LLTextureFetchWorker::LLTextureFetchWorker(const LLUUID& id, // Image UUID +LLTextureFetchWorker::LLTextureFetchWorker(LLTextureFetch* fetcher, + const LLUUID& id, // Image UUID const LLHost& host, // Simulator host F32 priority, // Priority - S32 discard) // Desired discard level - : LLWorkerClass(sWorkerThread, "TextureFetch"), + S32 discard, // Desired discard + S32 size) // Desired size + : LLWorkerClass(fetcher, "TextureFetch"), mState(INIT), + mFetcher(fetcher), + mImageWorker(NULL), mID(id), mHost(host), - mPriority(priority), - mDesiredDiscard(discard), + mImagePriority(priority), + mWorkPriority(0), + mRequestedPriority(0.f), + mDesiredDiscard(-1), + mSimRequestedDiscard(-1), mRequestedDiscard(-1), + mLoadedDiscard(-1), mDecodedDiscard(-1), - mFileHandle(LLVFSThread::nullHandle()), + mCacheReadHandle(LLTextureCache::nullHandle()), + mCacheWriteHandle(LLTextureCache::nullHandle()), mBuffer(NULL), mBufferSize(0), mRequestedSize(0), + mDesiredSize(FIRST_PACKET_SIZE), + mFileSize(0), + mCachedSize(0), mLoaded(FALSE), - mRequested(FALSE), + mSentRequest(UNSENT), mDecoded(FALSE), + mWritten(FALSE), + mNeedsAux(FALSE), + mHaveAllData(FALSE), + mInLocalCache(FALSE), + mRetryAttempt(0), mActiveCount(0), - mWorkMutex(sWorkerThread->getAPRPool()), + mWorkMutex(fetcher->getWorkerAPRPool()), + mFirstPacket(0), mLastPacket(-1), mTotalPackets(0), - mTotalBytes(0) + mImageCodec(IMG_CODEC_INVALID) { - lockQueue(); - sRequests[mID] = this; - unlockQueue(); - addWork(0, calcWorkPriority()); + calcWorkPriority(); + mType = host.isOk() ? LLImageBase::TYPE_AVATAR_BAKE : LLImageBase::TYPE_NORMAL; +// llinfos << "Create: " << mID << " mHost:" << host << " Discard=" << discard << llendl; + if (!mFetcher->mDebugPause) + { + U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; + addWork(0, work_priority ); + } + setDesiredDiscard(discard, size); } LLTextureFetchWorker::~LLTextureFetchWorker() { - lockQueue(); - mFormattedImage = NULL; - map_t::iterator iter = sRequests.find(mID); - if (iter != sRequests.end() && iter->second == this) +// llinfos << "Destroy: " << mID +// << " Decoded=" << mDecodedDiscard +// << " Requested=" << mRequestedDiscard +// << " Desired=" << mDesiredDiscard << llendl; + llassert_always(!haveWork()); + lockWorkData(); + if (mCacheReadHandle != LLTextureCache::nullHandle()) + { + mFetcher->mTextureCache->readComplete(mCacheReadHandle, true); + } + if (mCacheWriteHandle != LLTextureCache::nullHandle()) + { + mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true); + } + if (mImageWorker) { - sRequests.erase(iter); + mImageWorker->scheduleDelete(); } - sNetworkQueue.erase(this); - unlockQueue(); + mFormattedImage = NULL; clearPackets(); + unlockWorkData(); } void LLTextureFetchWorker::clearPackets() { - lockWorkData(); for_each(mPackets.begin(), mPackets.end(), DeletePointer()); mPackets.clear(); - unlockWorkData(); + mTotalPackets = 0; + mLastPacket = -1; + mFirstPacket = 0; } U32 LLTextureFetchWorker::calcWorkPriority() { +// llassert_always(mImagePriority >= 0 && mImagePriority <= LLViewerImage::maxDecodePriority()); F32 priority_scale = (F32)LLWorkerThread::PRIORITY_LOWBITS / LLViewerImage::maxDecodePriority(); - U32 priority = (U32)(mPriority * priority_scale); - return LLWorkerThread::PRIORITY_NORMAL | priority; + mWorkPriority = (U32)(mImagePriority * priority_scale); + return mWorkPriority; } -void LLTextureFetchWorker::setDesiredDiscard(S32 discard) +// mWorkMutex is locked +void LLTextureFetchWorker::setDesiredDiscard(S32 discard, S32 size) { + bool prioritize = false; if (mDesiredDiscard != discard) { - mDesiredDiscard = discard; if (!haveWork()) { - addWork(0, calcWorkPriority()); + calcWorkPriority(); + if (!mFetcher->mDebugPause) + { + U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; + addWork(0, work_priority); + } + } + else if (mDesiredDiscard < discard) + { + prioritize = true; } + mDesiredDiscard = discard; + mDesiredSize = size; } -} - -void LLTextureFetchWorker::setImagePriority(F32 priority) -{ - if (priority != mPriority) + else if (size > mDesiredSize) + { + mDesiredSize = size; + prioritize = true; + } + if ((prioritize && mState == INIT) || mState == DONE) { - mPriority = priority; - setPriority(calcWorkPriority()); + mState = INIT; + U32 work_priority = mWorkPriority | LLWorkerThread::PRIORITY_HIGH; + setPriority(work_priority); } } -void LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) +void LLTextureFetchWorker::setImagePriority(F32 priority) { - PacketData* packet = new PacketData(data, size); - - lockWorkData(); - if (index >= (S32)mPackets.size()) - { - mPackets.resize(index+1, (PacketData*)NULL); // initializes v to NULL pointers - } - if (mPackets[index] != NULL) - { - llwarns << "LLTextureFetchWorker::insertPacket called for duplicate packet: " << index << llendl; - } - mPackets[index] = packet; - while (mLastPacket+1 < (S32)mPackets.size() && mPackets[mLastPacket+1] != NULL) +// llassert_always(priority >= 0 && priority <= LLViewerImage::maxDecodePriority()); + F32 delta = fabs(priority - mImagePriority); + if (delta > (mImagePriority * .05f) || mState == DONE) { - ++mLastPacket; + mImagePriority = priority; + calcWorkPriority(); + U32 work_priority = mWorkPriority | (getPriority() & LLWorkerThread::PRIORITY_HIGHBITS); + setPriority(work_priority); } - unlockWorkData(); } -// Called from LLWorkerThread::processRequest() -bool LLTextureFetchWorker::doWork(S32 param) +void LLTextureFetchWorker::resetFormattedData() { - switch(mState) - { - case INIT: - { - // fall through - } - case LOAD_FROM_CACHE: - { - // Load any existing data from the cache - if (mFileHandle == LLVFSThread::nullHandle()) - { - bool res = startVFSLoad(gVFS, LLAssetType::AT_TEXTURE); - if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE_TGA); - if (!res) res = startVFSLoad(gStaticVFS, LLAssetType::AT_TEXTURE); - if (!res) - { - // Didn't load from VFS - mFormattedImage = new LLImageJ2C; - mState = LOAD_FROM_SIMULATOR; - } - } - if (mFileHandle != LLVFSThread::nullHandle()) - { - if (!loadFromVFS()) - { - return false; // not done - } - if (!mLoaded) - { - llwarns << "Load from VFS failed on: " << mID << llendl; - return true; - } - bool res = mFormattedImage->setData(mBuffer, mBufferSize); - if (!res) - { - llwarns << "loadLocalImage() - setData() failed" << llendl; - mFormattedImage->deleteData(); - return true; - } - // Successfully loaded - if (mFormattedImage->getDiscardLevel() <= mRequestedDiscard) - { - // we have enough data, decode it - mState = DECODE_IMAGE; - mRequestedSize = mBufferSize; - } - else - { - // need more data - mState = LOAD_FROM_SIMULATOR; - mRequestedSize = mFormattedImage->calcDataSize(mRequestedDiscard); - } - } - return false; - } - case LOAD_FROM_SIMULATOR: - { - if (!mRequested) - { - lockQueue(); - sNetworkQueue.insert(this); - unlockQueue(); - mRequested = TRUE; - } - if (processSimulatorPackets()) - { - mState = WRITE_TO_VFS; - } - return false; - } - case WRITE_TO_VFS: - { - mState = DECODE_IMAGE; - // fall through - } - case DECODE_IMAGE: - { - startDecode(); - mState = DECODE_IMAGE_UPDATE; - // fall through - } - case DECODE_IMAGE_UPDATE: - { - if (decodeImage()) - { - mState = DONE; - } - return false; - } - case DONE: - { - // Do any cleanup here - // Destroy the formatted image, we don't need it any more (raw image is still valid) - mFormattedImage = NULL; - mIdleTimer.reset(); - return true; - } - default: - { - llerrs << "LLTextureFetchWorker::doWork() has illegal state" << llendl; - return true; - } + delete[] mBuffer; + mBuffer = NULL; + mBufferSize = 0; + if (mFormattedImage.notNull()) + { + mFormattedImage->deleteData(); } + mHaveAllData = FALSE; } // Called from MAIN thread void LLTextureFetchWorker::startWork(S32 param) { + llassert(mImageWorker == NULL); + llassert(mFormattedImage.isNull()); } -void LLTextureFetchWorker::endWork(S32 param, bool aborted) -{ -} - -////////////////////////////////////////////////////////////////////////////// +#include "llviewerimagelist.h" // debug -bool LLTextureFetchWorker::startVFSLoad(LLVFS* vfs, LLAssetType::EType asset_type) +// Called from LLWorkerThread::processRequest() +bool LLTextureFetchWorker::doWork(S32 param) { - // Start load from VFS if it's there - if (vfs->getExists(mID, asset_type)) + LLMutexLock lock(&mWorkMutex); + + if (mFetcher->mDebugPause) { - mBufferSize = vfs->getSize(mID, asset_type); - mBuffer = new U8[mBufferSize]; - mFileHandle = LLVFSThread::sLocal->read(vfs, mID, asset_type, mBuffer, 0, mBufferSize); - if (mFileHandle == LLVFSThread::nullHandle()) - { - llwarns << "loadLocalImage() - vfs read failed in static VFS: " << mID << llendl; - delete mBuffer; - mBuffer = NULL; - return false; - } - if (asset_type == LLAssetType::AT_TEXTURE_TGA) - { - mFormattedImage = new LLImageTGA; - } - else if (asset_type == LLAssetType::AT_TEXTURE) - { - mFormattedImage = new LLImageJ2C; - } - else - { - llerrs << "LLTextureFetchWorker::startVFSLoad called with bad asset type: " << asset_type << llendl; - } - return true; + return false; // debug: don't do any work } - return false; -} - -bool LLTextureFetchWorker::loadFromVFS() -{ - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - - llassert(mLoaded == FALSE); - - // Check loading status - LLVFSThread::status_t status = LLVFSThread::sLocal->getRequestStatus(mFileHandle); - if (status == LLVFSThread::STATUS_QUEUED || status == LLVFSThread::STATUS_INPROGRESS) + if (mID == mFetcher->mDebugID) { - return false; + mFetcher->mDebugCount++; // for setting breakpoints } - else if (status == LLVFSThread::STATUS_COMPLETE) + + if (mState != DONE) { - mLoaded = TRUE; - return true; + mFetchTimer.reset(); } - else + + if (mState == INIT) { - llwarns << "loadLocalImage() - vfs read failed" << llendl; - LLVFSThread::Request* req = (LLVFSThread::Request*)LLVFSThread::sLocal->getRequest(mFileHandle); - if (req && mFormattedImage.notNull()) - { - LLVFS* vfs = req->getVFS(); - LLAssetType::EType asset_type = mFormattedImage->getCodec() == IMG_CODEC_TGA ? LLAssetType::AT_TEXTURE_TGA : LLAssetType::AT_TEXTURE; - vfs->removeFile(mID, asset_type); - } - return true; + mRequestedDiscard = -1; + mLoadedDiscard = -1; + mDecodedDiscard = -1; + mRequestedSize = 0; + mFileSize = 0; + mCachedSize = 0; + mLoaded = FALSE; + mSentRequest = UNSENT; + mDecoded = FALSE; + mWritten = FALSE; + delete[] mBuffer; + mBuffer = NULL; + mBufferSize = 0; + mHaveAllData = FALSE; + clearPackets(); // TODO: Shouldn't be necessary + mCacheReadHandle = LLTextureCache::nullHandle(); + mCacheWriteHandle = LLTextureCache::nullHandle(); + mURL.clear(); + mState = LOAD_FROM_TEXTURE_CACHE; + // fall through } -} - - -////////////////////////////////////////////////////////////////////////////// -bool LLTextureFetchWorker::processSimulatorPackets() -{ - bool res = false; - lockWorkData(); - if (mLastPacket >= 0) + if (mState == LOAD_FROM_TEXTURE_CACHE) { - S32 data_size = 0; - for (S32 i = 0; i<=mLastPacket; i++) + if (mCacheReadHandle == LLTextureCache::nullHandle()) { - data_size += mPackets[i]->mSize; + U32 cache_priority = mWorkPriority; + S32 offset = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; + S32 size = mDesiredSize - offset; + if (size <= 0) + { + mState = CACHE_POST; + return false; + } + mFileSize = 0; + mLoaded = FALSE; + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it + CacheReadResponder* responder = new CacheReadResponder(mFetcher, mID, mFormattedImage); + mCacheReadHandle = mFetcher->mTextureCache->readFromCache(mID, cache_priority, + offset, size, responder); } - if (data_size >= mRequestedSize || mLastPacket == mTotalPackets) + + if (mLoaded) { - /// We have enough (or all) data, copy it into mBuffer - if (mBufferSize < data_size) + // Make sure request is complete. *TODO: make this auto-complete + if (mFetcher->mTextureCache->readComplete(mCacheReadHandle, false)) { - delete mBuffer; - mBuffer = new U8[data_size]; - mBufferSize = data_size; + mCacheReadHandle = LLTextureCache::nullHandle(); + mState = CACHE_POST; + // fall through } - S32 offset = 0; - for (S32 i = 0; i<=mLastPacket; i++) + else { - memcpy(mBuffer + offset, mPackets[i]->mData, mPackets[i]->mSize); - offset += mPackets[i]->mSize; + return false; } - res = true; + } + else + { + return false; } } - unlockWorkData(); - return res; + + if (mState == CACHE_POST) + { + mCachedSize = mFormattedImage.notNull() ? mFormattedImage->getDataSize() : 0; + // Successfully loaded + if ((mCachedSize >= mDesiredSize) || mHaveAllData) + { + // we have enough data, decode it + llassert_always(mFormattedImage->getDataSize() > 0); + mState = DECODE_IMAGE; + // fall through + } + else + { + // need more data + mState = LOAD_FROM_NETWORK; + // fall through + } + } + + if (mState == LOAD_FROM_NETWORK) + { + if (mSentRequest == UNSENT) + { + if (mFormattedImage.isNull()) + { + mFormattedImage = new LLImageJ2C; + } + // Add this to the network queue and sit here. + // LLTextureFetch::update() will send off a request which will change our state + S32 data_size = mFormattedImage->getDataSize(); + if (data_size > 0) + { + // Only used for simulator requests + mFirstPacket = (data_size - FIRST_PACKET_SIZE) / MAX_IMG_PACKET_SIZE + 1; + if (FIRST_PACKET_SIZE + (mFirstPacket-1) * MAX_IMG_PACKET_SIZE != data_size) + { + llwarns << "Bad CACHED TEXTURE size: " << data_size << " removing." << llendl; + removeFromCache(); + resetFormattedData(); + clearPackets(); + } + else + { + mLastPacket = mFirstPacket-1; + mTotalPackets = (mFileSize - FIRST_PACKET_SIZE + MAX_IMG_PACKET_SIZE-1) / MAX_IMG_PACKET_SIZE + 1; + } + } + mRequestedSize = mDesiredSize; + mRequestedDiscard = mDesiredDiscard; + mSentRequest = QUEUED; + mFetcher->lockQueue(); + mFetcher->addToNetworkQueue(this); + mFetcher->unlockQueue(); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + } + return false; + } + + if (mState == LOAD_FROM_SIMULATOR) + { + if (processSimulatorPackets()) + { + mFetcher->lockQueue(); + mFetcher->removeFromNetworkQueue(this); + mFetcher->unlockQueue(); + if (!mFormattedImage->getDataSize()) + { + // processSimulatorPackets() failed + llwarns << "processSimulatorPackets() failed to load buffer" << llendl; + return true; // failed + } + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mState = DECODE_IMAGE; + } + else + { + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + } + return false; + } + +#if 0 + if (mState == LOAD_FROM_HTTP_GET_URL) + { + if (!mSentRequest) + { + mSentRequest = TRUE; + mLoaded = FALSE; + std::string url; + LLViewerRegion* region = gAgent.getRegion(); + if (region) + { + url = region->getCapability("RequestTextureDownload"); + } + if (!url.empty()) + { + LLSD sd; + sd = mID.asString(); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + LLHTTPClient::post(url, sd, new URLResponder(mFetcher, mID)); + return false; + } + else + { + llwarns << mID << ": HTTP get url failed, requesting from simulator" << llendl; + mSentRequest = FALSE; + mState = LOAD_FROM_SIMULATOR; + return false; + } + } + else + { + if (mLoaded) + { + if (!mURL.empty()) + { + mState = LOAD_FROM_HTTP_GET_DATA; + mSentRequest = FALSE; // reset + mLoaded = FALSE; // reset + } + else + { + llwarns << mID << ": HTTP get url is empty, requesting from simulator" << llendl; + mSentRequest = FALSE; + mState = LOAD_FROM_SIMULATOR; + return false; + } + } + } + // fall through + } + + if (mState == LOAD_FROM_HTTP_GET_DATA) + { + if (!mSentRequest) + { + mSentRequest = TRUE; + S32 cur_size = mFormattedImage->getDataSize(); // amount of data we already have + mRequestedSize = mDesiredSize; + mRequestedDiscard = mDesiredDiscard; +#if 1 // *TODO: LLCurl::getByteRange is broken (ignores range) + cur_size = 0; + mFormattedImage->deleteData(); +#endif + mRequestedSize -= cur_size; + // F32 priority = mImagePriority / (F32)LLViewerImage::maxDecodePriority(); // 0-1 + S32 offset = cur_size; + mBufferSize = cur_size; // This will get modified by callbackHttpGet() + std::string url; + if (mURL.empty()) + { + //url = "http://asset.agni/0000002f-38ae-0e17-8e72-712e58964e9c.texture"; + std::stringstream urlstr; + urlstr << "http://asset.agni/" << mID.asString() << ".texture"; + url = urlstr.str(); + } + else + { + url = mURL; + } + mLoaded = FALSE; +// llinfos << "HTTP GET: " << mID << " Offset: " << offset << " Bytes: " << mRequestedSize << llendl; + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + LLCurl::getByteRange(url, offset, mRequestedSize, + new HTTPGetResponder(mFetcher, mID)); // *TODO: use mWorkPriority + return false; // not done + } + + if (mLoaded) + { + S32 cur_size = mFormattedImage->getDataSize(); + if (mRequestedSize < 0) + { + llwarns << "http get failed for: " << mID << llendl; + if (cur_size == 0) + { + resetFormattedData(); + return true; // failed + } + else + { + mState = DECODE_IMAGE; + return false; // use what we have + } + } + llassert_always(mBufferSize == cur_size + mRequestedSize); + if (mHaveAllData) + { + mFileSize = mBufferSize; + } + U8* buffer = new U8[mBufferSize]; + if (cur_size > 0) + { + memcpy(buffer, mFormattedImage->getData(), cur_size); + } + memcpy(buffer + cur_size, mBuffer, mRequestedSize); // append + // NOTE: setData releases current data and owns new data (buffer) + mFormattedImage->setData(buffer, mBufferSize); + // delete temp data + delete[] mBuffer; // Note: not 'buffer' (assigned in setData()) + mBuffer = NULL; + mBufferSize = 0; + mLoadedDiscard = mRequestedDiscard; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mState = DECODE_IMAGE; + return false; + } + + // NOTE: Priority gets updated when the http get completes (in callbackHTTPGet()) + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return false; + } +#endif + + if (mState == DECODE_IMAGE) + { + llassert_always(mFormattedImage->getDataSize() > 0); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it + mRawImage = NULL; + mAuxImage = NULL; + llassert_always(mImageWorker == NULL); + llassert_always(mFormattedImage.notNull()); + S32 discard = mHaveAllData ? 0 : mLoadedDiscard; + U32 image_priority = LLWorkerThread::PRIORITY_NORMAL | mWorkPriority; + mDecoded = FALSE; + mState = DECODE_IMAGE_UPDATE; + mImageWorker = new LLImageWorker(mFormattedImage, image_priority, discard, new DecodeResponder(mFetcher, mID, this)); + // fall though (need to call requestDecodedData() to start work) + } + + if (mState == DECODE_IMAGE_UPDATE) + { + if (decodeImage()) + { + if (mDecodedDiscard < 0) + { + if (mCachedSize > 0 && !mInLocalCache && mRetryAttempt == 0) + { + // Cache file should be deleted, try again + llwarns << mID << ": Decode of cached file failed (removed), retrying" << llendl; + mFormattedImage = NULL; + ++mRetryAttempt; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mState = INIT; + return false; + } + else + { + llwarns << "UNABLE TO LOAD TEXTURE: " << mID << " RETRIES: " << mRetryAttempt << llendl; + mState = DONE; // failed + } + } + else + { + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + mState = WRITE_TO_CACHE; + } + // fall through + } + else + { + return false; + } + } + + if (mState == WRITE_TO_CACHE) + { + if (mInLocalCache || !mFileSize || mSentRequest == UNSENT) + { + // If we're in a local cache or we didn't actually receive any new data, skip + mState = DONE; + return false; + } + S32 datasize = mFormattedImage->getDataSize(); + llassert_always(datasize); + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); // Set priority first since Responder may change it + U32 cache_priority = mWorkPriority; + mWritten = FALSE; + mState = WAIT_ON_WRITE; + CacheWriteResponder* responder = new CacheWriteResponder(mFetcher, mID); + mCacheWriteHandle = mFetcher->mTextureCache->writeToCache(mID, cache_priority, + mFormattedImage->getData(), datasize, + mFileSize, responder); + // fall through + } + + if (mState == WAIT_ON_WRITE) + { + if (writeToCacheComplete()) + { + mState = DONE; + // fall through + } + else + { + if (mDesiredDiscard < mDecodedDiscard) + { + // We're waiting for this write to complete before we can receive more data + // (we can't touch mFormattedImage until the write completes) + // Prioritize the write + mFetcher->mTextureCache->prioritizeWrite(mCacheWriteHandle); + } + return false; + } + } + + if (mState == DONE) + { + if (mDecodedDiscard >= 0 && mDesiredDiscard < mDecodedDiscard) + { + // More data was requested, return to INIT + mState = INIT; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); + return false; + } + else + { + setPriority(LLWorkerThread::PRIORITY_LOW | mWorkPriority); + return true; + } + } + + return false; +} + +// Called from MAIN thread +void LLTextureFetchWorker::endWork(S32 param, bool aborted) +{ + if (mImageWorker) + { + mImageWorker->scheduleDelete(); + mImageWorker = NULL; + } + mFormattedImage = NULL; +} + +////////////////////////////////////////////////////////////////////////////// + +// virtual +void LLTextureFetchWorker::finishWork(S32 param, bool completed) +{ + // The following are required in case the work was aborted + if (mCacheReadHandle != LLTextureCache::nullHandle()) + { + mFetcher->mTextureCache->readComplete(mCacheReadHandle, true); + mCacheReadHandle = LLTextureCache::nullHandle(); + } + if (mCacheWriteHandle != LLTextureCache::nullHandle()) + { + mFetcher->mTextureCache->writeComplete(mCacheWriteHandle, true); + mCacheWriteHandle = LLTextureCache::nullHandle(); + } +} + +// virtual +bool LLTextureFetchWorker::deleteOK() +{ + bool delete_ok = true; + // Allow any pending reads or writes to complete + if (mCacheReadHandle != LLTextureCache::nullHandle()) + { + if (mFetcher->mTextureCache->readComplete(mCacheReadHandle, true)) + { + mCacheReadHandle = LLTextureCache::nullHandle(); + } + else + { + delete_ok = false; + } + } + if (mCacheWriteHandle != LLTextureCache::nullHandle()) + { + if (mFetcher->mTextureCache->writeComplete(mCacheWriteHandle)) + { + mCacheWriteHandle = LLTextureCache::nullHandle(); + } + else + { + delete_ok = false; + } + } + + if ((haveWork() && + // not ok to delete from these states + ((mState >= LOAD_FROM_HTTP_GET_URL && mState <= LOAD_FROM_HTTP_GET_DATA) || + (mState >= WRITE_TO_CACHE && mState <= WAIT_ON_WRITE)))) + { + delete_ok = false; + } + + return delete_ok; +} + + +void LLTextureFetchWorker::removeFromCache() +{ + if (!mInLocalCache) + { + mFetcher->mTextureCache->removeFromCache(mID); + } +} + + +////////////////////////////////////////////////////////////////////////////// + +bool LLTextureFetchWorker::processSimulatorPackets() +{ + if (mLastPacket >= mFirstPacket) + { + S32 buffer_size = mFormattedImage->getDataSize(); + for (S32 i = mFirstPacket; i<=mLastPacket; i++) + { + buffer_size += mPackets[i]->mSize; + } + bool have_all_data = mLastPacket >= mTotalPackets-1; + llassert_always(mRequestedSize > 0); + if (buffer_size >= mRequestedSize || have_all_data) + { + /// We have enough (or all) data + if (have_all_data) + { + mHaveAllData = TRUE; + } + S32 cur_size = mFormattedImage->getDataSize(); + if (buffer_size > cur_size) + { + /// We have new data + U8* buffer = new U8[buffer_size]; + S32 offset = 0; + if (cur_size > 0 && mFirstPacket > 0) + { + memcpy(buffer, mFormattedImage->getData(), cur_size); + offset = cur_size; + } + for (S32 i=mFirstPacket; i<=mLastPacket; i++) + { + memcpy(buffer + offset, mPackets[i]->mData, mPackets[i]->mSize); + offset += mPackets[i]->mSize; + } + // NOTE: setData releases current data + mFormattedImage->setData(buffer, buffer_size); + } + mLoadedDiscard = mRequestedDiscard; + return true; + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////////// + +void LLTextureFetchWorker::callbackURLReceived(const LLSD& data, bool success) +{ +#if 0 + LLMutexLock lock(&mWorkMutex); + if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_URL) + { + llwarns << "callbackURLReceived for unrequested fetch worker, req=" + << mSentRequest << " state= " << mState << llendl; + return; + } + if (success) + { + mURL = data.asString(); + } + mLoaded = TRUE; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +#endif +} + +////////////////////////////////////////////////////////////////////////////// + +void LLTextureFetchWorker::callbackHttpGet(U8* data, S32 data_size, bool last_block) +{ +#if 0 + LLMutexLock lock(&mWorkMutex); + if (!mSentRequest || mState != LOAD_FROM_HTTP_GET_DATA) + { + llwarns << "callbackHttpGet for unrequested fetch worker, req=" + << mSentRequest << " state= " << mState << llendl; + return; + } +// llinfos << "HTTP RECEIVED: " << mID.asString() << " Bytes: " << data_size << llendl; + if (mLoaded) + { + llwarns << "Duplicate callback for " << mID.asString() << llendl; + return; // ignore duplicate callback + } + if (data_size >= 0) + { + if (data_size > 0) + { + mBuffer = new U8[data_size]; + // *TODO: set the formatted image data here + memcpy(mBuffer, data, data_size); + mBufferSize += data_size; + if (data_size < mRequestedSize || last_block == true) + { + mHaveAllData = TRUE; + } + else if (data_size > mRequestedSize) + { + // *TODO: This will happen until we fix LLCurl::getByteRange() + llinfos << "HUH?" << llendl; + mHaveAllData = TRUE; + mFormattedImage->deleteData(); + mBufferSize = data_size; + } + } + else + { + // We requested data but received none (and no error), + // so presumably we have all of it + mHaveAllData = TRUE; + } + mRequestedSize = data_size; + } + else + { + mRequestedSize = -1; // error + } + mLoaded = TRUE; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +#endif +} + +////////////////////////////////////////////////////////////////////////////// + +void LLTextureFetchWorker::callbackCacheRead(bool success, LLImageFormatted* image, + S32 imagesize, BOOL islocal) +{ + LLMutexLock lock(&mWorkMutex); + if (mState != LOAD_FROM_TEXTURE_CACHE) + { + llwarns << "Read callback for " << mID << " with state = " << mState << llendl; + return; + } + if (success) + { + llassert_always(imagesize > 0); + mFileSize = imagesize; + mFormattedImage = image; + mImageCodec = image->getCodec(); + mInLocalCache = islocal; + if (mFileSize != 0 && mFormattedImage->getDataSize() >= mFileSize) + { + mHaveAllData = TRUE; + } + } + mLoaded = TRUE; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +} + +void LLTextureFetchWorker::callbackCacheWrite(bool success) +{ + LLMutexLock lock(&mWorkMutex); + if (mState != WAIT_ON_WRITE) + { + llwarns << "Write callback for " << mID << " with state = " << mState << llendl; + return; + } + mWritten = TRUE; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +} + +////////////////////////////////////////////////////////////////////////////// + +void LLTextureFetchWorker::callbackDecoded(bool success) +{ + if (mState != DECODE_IMAGE_UPDATE) + { + llwarns << "Decode callback for " << mID << " with state = " << mState << llendl; + return; + } +// llinfos << mID << " : DECODE COMPLETE " << llendl; + setPriority(LLWorkerThread::PRIORITY_HIGH | mWorkPriority); +} + +////////////////////////////////////////////////////////////////////////////// + +bool LLTextureFetchWorker::decodeImage() +{ + llassert_always(mImageWorker); + bool res = true; + if (mRawImage.isNull()) + { + res = false; + if (mImageWorker->requestDecodedData(mRawImage, -1)) + { + res = true; +// llinfos << mID << " : BASE DECODE FINISHED" << llendl; + } + } + if (res && + (mRawImage.notNull() && mRawImage->getDataSize() > 0) && + (mNeedsAux && mAuxImage.isNull())) + { + res = false; + if (mImageWorker->requestDecodedAuxData(mAuxImage, 4, -1)) + { + res = true; +// llinfos << mID << " : AUX DECODE FINISHED" << llendl; + } + } + if (res) + { + if ((mRawImage.notNull() && mRawImage->getDataSize() > 0) && + (!mNeedsAux || (mAuxImage.notNull() && mAuxImage->getDataSize() > 0))) + { + mDecodedDiscard = mFormattedImage->getDiscardLevel(); +// llinfos << mID << " : DECODE FINISHED. DISCARD: " << mDecodedDiscard << llendl; + } + else + { + llwarns << "DECODE FAILED: " << mID << " Discard: " << (S32)mFormattedImage->getDiscardLevel() << llendl; + removeFromCache(); + } + mImageWorker->scheduleDelete(); + mImageWorker = NULL; + } + return res; +} + +////////////////////////////////////////////////////////////////////////////// + +bool LLTextureFetchWorker::writeToCacheComplete() +{ + // Complete write to cache + if (mCacheWriteHandle != LLTextureCache::nullHandle()) + { + if (!mWritten) + { + return false; + } + if (mFetcher->mTextureCache->writeComplete(mCacheWriteHandle)) + { + mCacheWriteHandle = LLTextureCache::nullHandle(); + } + else + { + return false; + } + } + return true; +} + + +////////////////////////////////////////////////////////////////////////////// +////////////////////////////////////////////////////////////////////////////// +// public + +LLTextureFetch::LLTextureFetch(LLTextureCache* cache, bool threaded) + : LLWorkerThread("TextureFetch", threaded), + mDebugCount(0), + mDebugPause(FALSE), + mQueueMutex(getAPRPool()), + mTextureCache(cache) +{ +} + +LLTextureFetch::~LLTextureFetch() +{ + // ~LLQueuedThread() called here +} + +bool LLTextureFetch::createRequest(const LLUUID& id, const LLHost& host, F32 priority, + S32 w, S32 h, S32 c, S32 discard, bool needs_aux) +{ + if (mDebugPause) + { + return false; + } + + LLTextureFetchWorker* worker = NULL; + LLMutexLock lock(&mQueueMutex); + map_t::iterator iter = mRequestMap.find(id); + if (iter != mRequestMap.end()) + { + worker = iter->second; + if (worker->mHost != host) + { + llwarns << "LLTextureFetch::createRequest " << id << " called with multiple hosts: " + << host << " != " << worker->mHost << llendl; + removeRequest(worker, true); + worker = NULL; + return false; + } + } + // If the requester knows the dimentions of the image, + // this will calculate how much data we need without having to parse the header + S32 desired_size; + if (w*h*c > 0) + { + desired_size = LLImageJ2C::calcDataSizeJ2C(w, h, c, discard); + } + else + { + desired_size = FIRST_PACKET_SIZE; + discard = MAX_DISCARD_LEVEL; + } + if (worker) + { + if (worker->wasAborted()) + { + return false; // need to wait for previous aborted request to complete + } + worker->lockWorkData(); + worker->setImagePriority(priority); + worker->setDesiredDiscard(discard, desired_size); + worker->unlockWorkData(); + if (!worker->haveWork()) + { + worker->mState = LLTextureFetchWorker::INIT; + worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + } + } + else + { + worker = new LLTextureFetchWorker(this, id, host, priority, discard, desired_size); + mRequestMap[id] = worker; + } + worker->mActiveCount++; + worker->mNeedsAux = needs_aux; +// llinfos << "REQUESTED: " << id << " Discard: " << discard << llendl; + return true; +} + +void LLTextureFetch::deleteRequest(const LLUUID& id, bool cancel) +{ + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + if (worker) + { + removeRequest(worker, cancel); + } +} + +// protected + +// call lockQueue() first! +void LLTextureFetch::addToNetworkQueue(LLTextureFetchWorker* worker) +{ + if (mRequestMap.find(worker->mID) != mRequestMap.end()) + { + // only add to the queue if in the request map + // i.e. a delete has not been requested + mNetworkQueue.insert(worker->mID); + } + for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); + iter1 != mCancelQueue.end(); ++iter1) + { + iter1->second.erase(worker->mID); + } +} + +// call lockQueue() first! +void LLTextureFetch::removeFromNetworkQueue(LLTextureFetchWorker* worker) +{ + mNetworkQueue.erase(worker->mID); +} + +// call lockQueue() first! +void LLTextureFetch::removeRequest(LLTextureFetchWorker* worker, bool cancel) +{ + mRequestMap.erase(worker->mID); + size_t erased = mNetworkQueue.erase(worker->mID); + if (cancel && erased > 0) + { + mCancelQueue[worker->mHost].insert(worker->mID); + } + worker->scheduleDelete(); +} + +// call lockQueue() first! +LLTextureFetchWorker* LLTextureFetch::getWorker(const LLUUID& id) +{ + LLTextureFetchWorker* res = NULL; + map_t::iterator iter = mRequestMap.find(id); + if (iter != mRequestMap.end()) + { + res = iter->second; + } + return res; +} + + +bool LLTextureFetch::getRequestFinished(const LLUUID& id, S32& discard_level, + LLPointer& raw, LLPointer& aux) +{ + bool res = false; + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + if (worker) + { + if (worker->wasAborted()) + { + res = true; + } + else if (!worker->haveWork()) + { + // Should only happen if we set mDebugPause... + if (!mDebugPause) + { +// llwarns << "Adding work for inactive worker: " << id << llendl; + worker->addWork(0, LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + } + } + else if (worker->checkWork()) + { + discard_level = worker->mDecodedDiscard; + raw = worker->mRawImage; worker->mRawImage = NULL; + aux = worker->mAuxImage; worker->mAuxImage = NULL; + res = true; + } + else + { + worker->lockWorkData(); + if ((worker->mDecodedDiscard >= 0) && + (worker->mDecodedDiscard < discard_level || discard_level < 0) && + (worker->mState >= LLTextureFetchWorker::WAIT_ON_WRITE)) + { + // Not finished, but data is ready + discard_level = worker->mDecodedDiscard; + if (worker->mRawImage) raw = worker->mRawImage; + if (worker->mAuxImage) aux = worker->mAuxImage; + } + worker->unlockWorkData(); + } + } + else + { + res = true; + } + return res; +} + +bool LLTextureFetch::updateRequestPriority(const LLUUID& id, F32 priority) +{ + bool res = false; + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + if (worker) + { + worker->lockWorkData(); + worker->setImagePriority(priority); + worker->unlockWorkData(); + res = true; + } + return res; } ////////////////////////////////////////////////////////////////////////////// -void LLTextureFetchWorker::startDecode() +//virtual +S32 LLTextureFetch::update(U32 max_time_ms) { - mRawImage = NULL; - mAuxImage = NULL; + S32 res; + res = LLWorkerThread::update(max_time_ms); + + const F32 REQUEST_TIME = 1.f; + + // Periodically, gather the list of textures that need data from the network + // And send the requests out to the simulators + if (mNetworkTimer.getElapsedTimeF32() >= REQUEST_TIME) + { + mNetworkTimer.reset(); + sendRequestListToSimulators(); + } + + return res; } -bool LLTextureFetchWorker::decodeImage() +////////////////////////////////////////////////////////////////////////////// + +void LLTextureFetch::sendRequestListToSimulators() { - const F32 MAX_DECODE_TIME = .001f; // 1 ms - if (mRawImage->getDataSize() == 0) + const S32 IMAGES_PER_REQUEST = 50; + const F32 LAZY_FLUSH_TIMEOUT = 15.f; // 10.0f // temp + const F32 MIN_REQUEST_TIME = 1.0f; + const F32 MIN_DELTA_PRIORITY = 1000.f; + + LLMutexLock lock(&mQueueMutex); + + // Send requests + typedef std::set request_list_t; + typedef std::map< LLHost, request_list_t > work_request_map_t; + work_request_map_t requests; + for (queue_t::iterator iter = mNetworkQueue.begin(); iter != mNetworkQueue.end(); ) { - if (!mFormattedImage->requestDecodedData(mRawImage, -1, MAX_DECODE_TIME)) + queue_t::iterator curiter = iter++; + LLTextureFetchWorker* req = getWorker(*curiter); + if (!req) { - return false; + mNetworkQueue.erase(curiter); + continue; // paranoia + } + if (req->mID == mDebugID) + { + mDebugCount++; // for setting breakpoints + } + if (req->mTotalPackets > 0 && req->mLastPacket >= req->mTotalPackets-1) + { + // We have all the packets... make sure this is high priority +// req->setPriority(LLWorkerThread::PRIORITY_HIGH | req->mWorkPriority); + continue; + } + F32 elapsed = req->mRequestedTimer.getElapsedTimeF32(); + F32 delta_priority = llabs(req->mRequestedPriority - req->mImagePriority); + if ((req->mSimRequestedDiscard != req->mDesiredDiscard) || + (delta_priority > MIN_DELTA_PRIORITY && elapsed >= MIN_REQUEST_TIME) || + (elapsed >= LAZY_FLUSH_TIMEOUT)) + { + requests[req->mHost].insert(req); } - mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image } - if (mNeedsAux && mAuxImage->getDataSize() == 0) + + std::string http_url; +#if 0 + if (gSavedSettings.getBOOL("ImagePipelineUseHTTP")) { - if (!mFormattedImage->requestDecodedAuxData(mAuxImage, 4, -1, MAX_DECODE_TIME )) + LLViewerRegion* region = gAgent.getRegion(); + if (region) { - return false; + http_url = region->getCapability("RequestTextureDownload"); } - mFormattedImage->releaseDecodedData(); // so that we have the only ref to the raw image } - mDecodedDiscard = mFormattedImage->getDiscardLevel(); - return true; +#endif + + for (work_request_map_t::iterator iter1 = requests.begin(); + iter1 != requests.end(); ++iter1) + { + bool use_http = http_url.empty() ? false : true; + LLHost host = iter1->first; + // invalid host = use agent host + if (host == LLHost::invalid) + { + host = gAgent.getRegionHost(); + } + else + { + use_http = false; + } + + if (use_http) + { + } + else + { + S32 request_count = 0; + for (request_list_t::iterator iter2 = iter1->second.begin(); + iter2 != iter1->second.end(); ++iter2) + { + LLTextureFetchWorker* req = *iter2; + req->mSentRequest = LLTextureFetchWorker::SENT_SIM; + if (0 == request_count) + { + gMessageSystem->newMessageFast(_PREHASH_RequestImage); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + } + S32 packet = req->mLastPacket + 1; + gMessageSystem->nextBlockFast(_PREHASH_RequestImage); + gMessageSystem->addUUIDFast(_PREHASH_Image, req->mID); + gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)req->mSimRequestedDiscard); + gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, req->mImagePriority); + gMessageSystem->addU32Fast(_PREHASH_Packet, packet); + gMessageSystem->addU8Fast(_PREHASH_Type, req->mType); +// llinfos << "IMAGE REQUEST: " << req->mID << " Discard: " << req->mDesiredDiscard +// << " Packet: " << packet << " Priority: " << req->mImagePriority << llendl; + + req->lockWorkData(); + req->mSimRequestedDiscard = req->mDesiredDiscard; + req->mRequestedPriority = req->mImagePriority; + req->mRequestedTimer.reset(); + req->unlockWorkData(); + request_count++; + if (request_count >= IMAGES_PER_REQUEST) + { +// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; + gMessageSystem->sendSemiReliable(host, NULL, NULL); + request_count = 0; + } + } + if (request_count > 0 && request_count < IMAGES_PER_REQUEST) + { +// llinfos << "REQUESTING " << request_count << " IMAGES FROM HOST: " << host.getIPString() << llendl; + gMessageSystem->sendSemiReliable(host, NULL, NULL); + request_count = 0; + } + } + } + + // Send cancelations + if (!mCancelQueue.empty()) + { + for (cancel_queue_t::iterator iter1 = mCancelQueue.begin(); + iter1 != mCancelQueue.end(); ++iter1) + { + LLHost host = iter1->first; + if (host == LLHost::invalid) + { + host = gAgent.getRegionHost(); + } + S32 request_count = 0; + for (queue_t::iterator iter2 = iter1->second.begin(); + iter2 != iter1->second.end(); ++iter2) + { + if (0 == request_count) + { + gMessageSystem->newMessageFast(_PREHASH_RequestImage); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + } + gMessageSystem->nextBlockFast(_PREHASH_RequestImage); + gMessageSystem->addUUIDFast(_PREHASH_Image, *iter2); + gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, -1); + gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, 0); + gMessageSystem->addU32Fast(_PREHASH_Packet, 0); + gMessageSystem->addU8Fast(_PREHASH_Type, 0); +// llinfos << "CANCELING IMAGE REQUEST: " << (*iter2) << llendl; + + request_count++; + if (request_count >= IMAGES_PER_REQUEST) + { + gMessageSystem->sendSemiReliable(host, NULL, NULL); + request_count = 0; + } + } + if (request_count > 0 && request_count < IMAGES_PER_REQUEST) + { + gMessageSystem->sendSemiReliable(host, NULL, NULL); + } + } + mCancelQueue.clear(); + } } ////////////////////////////////////////////////////////////////////////////// -#if 0 -// static -void LLTextureFetchWorker::receiveImageHeader(LLMessageSystem *msg, void **user_data) +bool LLTextureFetchWorker::insertPacket(S32 index, U8* data, S32 size) { - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + mRequestedTimer.reset(); + if (index >= mTotalPackets) + { +// llwarns << "Received Image Packet " << index << " > max: " << mTotalPackets << " for image: " << mID << llendl; + return false; + } + if (index > 0 && index < mTotalPackets-1 && size != MAX_IMG_PACKET_SIZE) + { +// llwarns << "Received bad sized packet: " << index << ", " << size << " != " << MAX_IMG_PACKET_SIZE << " for image: " << mID << llendl; + return false; + } - // Receive image header, copy into image object and decompresses - // if this is a one-packet image. + if (index >= (S32)mPackets.size()) + { + mPackets.resize(index+1, (PacketData*)NULL); // initializes v to NULL pointers + } + else if (mPackets[index] != NULL) + { +// llwarns << "Received duplicate packet: " << index << " for image: " << mID << llendl; + return false; + } + + mPackets[index] = new PacketData(data, size); + while (mLastPacket+1 < (S32)mPackets.size() && mPackets[mLastPacket+1] != NULL) + { + ++mLastPacket; + } + return true; +} - gImageList.sTextureBits += msg->getReceiveBytes(); - gImageList.sTexturePackets++; +bool LLTextureFetch::receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, + U16 data_size, U8* data) +{ + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + bool res = true; - LLUUID id; - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); -// LLString ip_string(u32_to_ip_string(msg->getSenderIP())); + ++mPacketCount; - LLTextureFetchWorker* worker = getActiveWorker(id); if (!worker) { - llwarns << "receiveImageHeader for non active worker: " << id << llendl; - return; +// llwarns << "Received header for non active worker: " << id << llendl; + res = false; } - worker->mRequestedTimer.reset(); - - // check to see if we've gotten this packet before - if (worker->mLastPacket != -1) + else if (worker->mState != LLTextureFetchWorker::LOAD_FROM_NETWORK || + worker->mSentRequest != LLTextureFetchWorker::SENT_SIM) { - llwarns << "Img: " << id << ":" << " Duplicate Image Header" << llendl; - return; +// llwarns << "receiveImageHeader for worker: " << id +// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] +// << " sent: " << worker->mSentRequest << llendl; + res = false; } - - // Copy header data into image object - worker->lockWorkData(); - msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, image->mDataCodec); - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, image->mTotalPackets); - msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, image->mTotalBytes); - if (0 == image->mTotalPackets) + else if (worker->mLastPacket != -1) { - llwarns << "Img: " << id << ":" << " Number of packets is 0" << llendl; + // check to see if we've gotten this packet before +// llwarns << "Received duplicate header for: " << id << llendl; + res = false; } - worker->unlockWorkData(); - - U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - if (data_size) + else if (!data_size) + { + llwarns << "Img: " << id << ":" << " Empty Image Header" << llendl; + res = false; + } + if (!res) { - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - worker->insertPacket(0, data, data_size) + ++mBadPacketCount; + mCancelQueue[host].insert(id); + return false; } + + worker->lockWorkData(); + + // Copy header data into image object + worker->mImageCodec = codec; + worker->mTotalPackets = packets; + worker->mFileSize = (S32)totalbytes; + llassert_always(totalbytes > 0); + llassert_always(data_size == FIRST_PACKET_SIZE || data_size == worker->mFileSize); + res = worker->insertPacket(0, data, data_size); + worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; + worker->unlockWorkData(); + return res; } -/////////////////////////////////////////////////////////////////////////////// -// static -void LLTextureFetchWorker::receiveImagePacket(LLMessageSystem *msg, void **user_data) +bool LLTextureFetch::receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data) { - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + bool res = true; + + ++mPacketCount; + + if (!worker) + { +// llwarns << "Received packet " << packet_num << " for non active worker: " << id << llendl; + res = false; + } + else if (worker->mLastPacket == -1) + { +// llwarns << "Received packet " << packet_num << " before header for: " << id << llendl; + res = false; + } + else if (!data_size) + { + llwarns << "Img: " << id << ":" << " Empty Image Header" << llendl; + res = false; + } + if (!res) + { + ++mBadPacketCount; + mCancelQueue[host].insert(id); + return false; + } + + worker->lockWorkData(); + + res = worker->insertPacket(packet_num, data, data_size); + + if ((worker->mState == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) || + (worker->mState == LLTextureFetchWorker::LOAD_FROM_NETWORK)) + { + worker->setPriority(LLWorkerThread::PRIORITY_HIGH | worker->mWorkPriority); + worker->mState = LLTextureFetchWorker::LOAD_FROM_SIMULATOR; + } + else + { +// llwarns << "receiveImagePacket " << packet_num << "/" << worker->mLastPacket << " for worker: " << id +// << " in state: " << LLTextureFetchWorker::sStateDescs[worker->mState] << llendl; + removeFromNetworkQueue(worker); // failsafe + mCancelQueue[host].insert(id); + } - gImageList.sTextureBits += msg->getReceiveBytes(); - gImageList.sTexturePackets++; + worker->unlockWorkData(); - LLUUID id; - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); -// LLString ip_string(u32_to_ip_string(msg->getSenderIP())); + return res; +} - U16 packet_num; - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num); +////////////////////////////////////////////////////////////////////////////// - LLTextureFetchWorker* worker = getActiveWorker(id); - if (!worker) +S32 LLTextureFetch::getFetchState(const LLUUID& id, F32& data_progress_p, F32& requested_priority_p, + U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p) +{ + S32 state = LLTextureFetchWorker::INVALID; + F32 data_progress = 0.0f; + F32 requested_priority = 0.0f; + F32 fetch_dtime = 999999.f; + F32 request_dtime = 999999.f; + U32 fetch_priority = 0; + + LLMutexLock lock(&mQueueMutex); + LLTextureFetchWorker* worker = getWorker(id); + if (worker && worker->haveWork()) { - llwarns << "receiveImageHeader for non active worker: " << id << llendl; - return; + worker->lockWorkData(); + state = worker->mState; + fetch_dtime = worker->mFetchTimer.getElapsedTimeF32(); + request_dtime = worker->mRequestedTimer.getElapsedTimeF32(); + if (worker->mFileSize > 0) + { + if (state == LLTextureFetchWorker::LOAD_FROM_SIMULATOR) + { + S32 data_size = FIRST_PACKET_SIZE + (worker->mLastPacket-1) * MAX_IMG_PACKET_SIZE; + data_size = llmax(data_size, 0); + data_progress = (F32)data_size / (F32)worker->mFileSize; + } + else if (worker->mFormattedImage.notNull()) + { + data_progress = (F32)worker->mFormattedImage->getDataSize() / (F32)worker->mFileSize; + } + } + if (state >= LLTextureFetchWorker::LOAD_FROM_NETWORK && state <= LLTextureFetchWorker::LOAD_FROM_HTTP_GET_DATA) + { + requested_priority = worker->mRequestedPriority; + } + else + { + requested_priority = worker->mImagePriority; + } + fetch_priority = worker->getPriority(); + worker->unlockWorkData(); } - worker->mRequestedTimer.reset(); + data_progress_p = data_progress; + requested_priority_p = requested_priority; + fetch_priority_p = fetch_priority; + fetch_dtime_p = fetch_dtime; + request_dtime_p = request_dtime; + return state; +} - U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - if (data_size) +void LLTextureFetch::dump() +{ + llinfos << "LLTextureFetch REQUESTS:" << llendl; + for (request_queue_t::iterator iter = mRequestQueue.begin(); + iter != mRequestQueue.end(); ++iter) { - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - worker->insertPacket(0, data, data_size) + LLQueuedThread::QueuedRequest* qreq = *iter; + LLWorkerThread::WorkRequest* wreq = (LLWorkerThread::WorkRequest*)qreq; + LLTextureFetchWorker* worker = (LLTextureFetchWorker*)wreq->getWorkerClass(); + llinfos << " ID: " << worker->mID + << " PRI: " << llformat("0x%08x",wreq->getPriority()) + << " STATE: " << worker->sStateDescs[worker->mState] + << llendl; } } -#endif - ////////////////////////////////////////////////////////////////////////////// + +////////////////////////////////////////////////////////////////////////////// diff --git a/linden/indra/newview/lltexturefetch.h b/linden/indra/newview/lltexturefetch.h index 29cac99..a53deae 100644 --- a/linden/indra/newview/lltexturefetch.h +++ b/linden/indra/newview/lltexturefetch.h @@ -28,20 +28,79 @@ #ifndef LL_LLTEXTUREFETCH_H #define LL_LLTEXTUREFETCH_H +#include "lldir.h" +#include "llimage.h" +#include "lluuid.h" #include "llworkerthread.h" class LLViewerImage; +class LLTextureFetchWorker; +class LLTextureCache; +class LLHost; // Interface class -class LLTextureFetch +class LLTextureFetch : public LLWorkerThread { + friend class LLTextureFetchWorker; + public: - static void initClass(); - static void updateClass(); - static void cleanupClass(); + LLTextureFetch(LLTextureCache* cache, bool threaded); + ~LLTextureFetch(); - static LLWorkerClass::handle_t addRequest(LLImageFormatted* image, S32 discard); - static bool getRequestFinished(LLWorkerClass::handle_t handle); + /*virtual*/ S32 update(U32 max_time_ms); + + bool createRequest(const LLUUID& id, const LLHost& host, F32 priority, + S32 w, S32 h, S32 c, S32 discard, bool needs_aux); + void deleteRequest(const LLUUID& id, bool cancel); + bool getRequestFinished(const LLUUID& id, S32& discard_level, + LLPointer& raw, LLPointer& aux); + bool updateRequestPriority(const LLUUID& id, F32 priority); + + bool receiveImageHeader(const LLHost& host, const LLUUID& id, U8 codec, U16 packets, U32 totalbytes, U16 data_size, U8* data); + bool receiveImagePacket(const LLHost& host, const LLUUID& id, U16 packet_num, U16 data_size, U8* data); + + // Debug + S32 getFetchState(const LLUUID& id, F32& decode_progress_p, F32& requested_priority_p, + U32& fetch_priority_p, F32& fetch_dtime_p, F32& request_dtime_p); + void dump(); + S32 getNumRequests() { return mRequestMap.size(); } + + // Public for access by callbacks + void lockQueue() { mQueueMutex.lock(); } + void unlockQueue() { mQueueMutex.unlock(); } + LLTextureFetchWorker* getWorker(const LLUUID& id); + +protected: + void addToNetworkQueue(LLTextureFetchWorker* worker); + void removeFromNetworkQueue(LLTextureFetchWorker* worker); + void removeRequest(LLTextureFetchWorker* worker, bool cancel); + +private: + void sendRequestListToSimulators(); + +public: + LLUUID mDebugID; + S32 mDebugCount; + BOOL mDebugPause; + S32 mPacketCount; + S32 mBadPacketCount; + +private: + LLMutex mQueueMutex; + + LLTextureCache* mTextureCache; + + // Map of all requests by UUID + typedef std::map map_t; + map_t mRequestMap; + + // Set of requests that require network data + typedef std::set queue_t; + queue_t mNetworkQueue; + typedef std::map > cancel_queue_t; + cancel_queue_t mCancelQueue; + + LLFrameTimer mNetworkTimer; }; -#endif LL_LLTEXTUREFETCH_H +#endif // LL_LLTEXTUREFETCH_H diff --git a/linden/indra/newview/lltextureview.cpp b/linden/indra/newview/lltextureview.cpp index 75abb39..d28ee74 100644 --- a/linden/indra/newview/lltextureview.cpp +++ b/linden/indra/newview/lltextureview.cpp @@ -33,48 +33,509 @@ #include "llrect.h" #include "llerror.h" - -#include "viewer.h" +#include "lllfsthread.h" #include "llui.h" +#include "llimageworker.h" -#include "llviewerimagelist.h" +#include "llhoverview.h" #include "llselectmgr.h" +#include "lltexlayer.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" +#include "lltexturetable.h" #include "llviewerobject.h" #include "llviewerimage.h" -#include "llhoverview.h" +#include "llviewerimagelist.h" +#include "viewer.h" + +extern F32 texmem_lower_bound_scale; LLTextureView *gTextureView = NULL; //static std::set LLTextureView::sDebugImages; +//////////////////////////////////////////////////////////////////////////// + +static LLString title_string1a("Tex UUID Area DDis(Req) DecodePri(Fetch) [download] pk/max"); +static LLString title_string1b("Tex UUID Area DDis(Req) Fetch(DecodePri) [download] pk/max"); +static LLString title_string2("State"); +static LLString title_string3("Pkt Bnd"); +static LLString title_string4(" W x H (Dis) Mem"); + +static S32 title_x1 = 0; +static S32 title_x2 = 440; +static S32 title_x3 = title_x2 + 40; +static S32 title_x4 = title_x3 + 50; +static S32 texture_bar_height = 8; + +//////////////////////////////////////////////////////////////////////////// + +class LLTextureBar : public LLView +{ +public: + LLPointer mImagep; + S32 mHilite; + +public: + LLTextureBar(const std::string& name, const LLRect& r, LLTextureView* texview) + : LLView(name, r, FALSE), + mHilite(0), + mTextureView(texview) + { + } + + virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEXTURE_BAR; } + virtual LLString getWidgetTag() const { return LL_TEXTURE_BAR_TAG; } + + virtual void draw(); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual LLRect getRequiredRect(); // Return the height of this object, given the set options. + // Used for sorting -struct SortTextureBars + struct sort + { + bool operator()(const LLView* i1, const LLView* i2) + { + LLTextureBar* bar1p = (LLTextureBar*)i1; + LLTextureBar* bar2p = (LLTextureBar*)i2; + LLViewerImage *i1p = bar1p->mImagep; + LLViewerImage *i2p = bar2p->mImagep; + F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority + F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority + if (pri1 > pri2) + return true; + else if (pri2 > pri1) + return false; + else + return i1p->getID() < i2p->getID(); + } + }; + + struct sort_fetch + { + bool operator()(const LLView* i1, const LLView* i2) + { + LLTextureBar* bar1p = (LLTextureBar*)i1; + LLTextureBar* bar2p = (LLTextureBar*)i2; + LLViewerImage *i1p = bar1p->mImagep; + LLViewerImage *i2p = bar2p->mImagep; + U32 pri1 = i1p->mFetchPriority; + U32 pri2 = i2p->mFetchPriority; + if (pri1 > pri2) + return true; + else if (pri2 > pri1) + return false; + else + return i1p->getID() < i2p->getID(); + } + }; +private: + LLTextureView* mTextureView; +}; + +void LLTextureBar::draw() { - bool operator()(const LLView* i1, const LLView* i2) - { - LLTextureBar* bar1p = (LLTextureBar*)i1; - LLTextureBar* bar2p = (LLTextureBar*)i2; - LLViewerImage *i1p = bar1p->mImagep; - LLViewerImage *i2p = bar2p->mImagep; - F32 pri1 = i1p->getDecodePriority(); // i1p->mRequestedDownloadPriority - F32 pri2 = i2p->getDecodePriority(); // i2p->mRequestedDownloadPriority - if (pri1 > pri2) - return true; - else if (pri2 > pri1) - return false; + if (!mImagep) + { + return; + } + + LLColor4 color; + if (mImagep->getID() == gTextureFetch->mDebugID) + { + color = LLColor4::cyan2; + } + else if (mHilite) + { + S32 idx = llclamp(mHilite,1,3); + if (idx==1) color = LLColor4::orange; + else if (idx==2) color = LLColor4::yellow; + else color = LLColor4::pink2; + } + else if (mImagep->mDontDiscard) + { + color = LLColor4::green4; + } + else if (mImagep->getBoostLevel()) + { + color = LLColor4::magenta; + } + else if (mImagep->getDecodePriority() == 0.0f) + { + color = LLColor4::grey; color[VALPHA] = .7f; + } + else + { + color = LLColor4::white; color[VALPHA] = .7f; + } + + // We need to draw: + // The texture UUID or name + // The progress bar for the texture, highlighted if it's being download + // Various numerical stats. + char tex_str[256]; + S32 left, right; + S32 top = 0; + S32 bottom = top + 6; + LLColor4 clr; + + LLGLSUIDefault gls_ui; + + // Get the name or UUID of the image. + gTextureTable.getName(mImagep->mID); + + // Name, pixel_area, requested pixel area, decode priority + char uuid_str[255]; + mImagep->mID.toString(uuid_str); + uuid_str[8] = 0; + if (mTextureView->mOrderFetch) + { + sprintf(tex_str, "%s %7.0f %d(%d) 0x%08x(%8.0f)", + uuid_str, + mImagep->mMaxVirtualSize, + mImagep->mDesiredDiscardLevel, + mImagep->mRequestedDiscardLevel, + mImagep->mFetchPriority, + mImagep->getDecodePriority()); + } + else + { + sprintf(tex_str, "%s %7.0f %d(%d) %8.0f(0x%08x)", + uuid_str, + mImagep->mMaxVirtualSize, + mImagep->mDesiredDiscardLevel, + mImagep->mRequestedDiscardLevel, + mImagep->getDecodePriority(), + mImagep->mFetchPriority); + } + + LLFontGL::sMonospace->renderUTF8(tex_str, 0, title_x1, mRect.getHeight(), + color, LLFontGL::LEFT, LLFontGL::TOP); + + // State + // Hack: mirrored from lltexturefetch.cpp + struct { const char* desc; LLColor4 color; } fetch_state_desc[] = { + { "---", LLColor4::red }, // INVALID + { "INI", LLColor4::white }, // INIT + { "DSK", LLColor4::cyan }, // LOAD_FROM_TEXTURE_CACHE + { "DSK", LLColor4::blue }, // CACHE_POST + { "NET", LLColor4::green }, // LOAD_FROM_NETWORK + { "SIM", LLColor4::green }, // LOAD_FROM_SIMULATOR + { "URL", LLColor4::green2 },// LOAD_FROM_HTTP_GET_URL + { "HTP", LLColor4::green }, // LOAD_FROM_HTTP_GET_DATA + { "DEC", LLColor4::yellow },// DECODE_IMAGE + { "DEC", LLColor4::yellow },// DECODE_IMAGE_UPDATE + { "WRT", LLColor4::purple },// WRITE_TO_CACHE + { "WRT", LLColor4::orange },// WAIT_ON_WRITE + { "END", LLColor4::red }, // DONE +#define LAST_STATE 12 + { "CRE", LLColor4::magenta }, // LAST_STATE+1 + { "FUL", LLColor4::green }, // LAST_STATE+2 + { "BAD", LLColor4::red }, // LAST_STATE+3 + { "MIS", LLColor4::red }, // LAST_STATE+4 + { "---", LLColor4::white }, // LAST_STATE+5 + }; + const S32 fetch_state_desc_size = (S32)(sizeof(fetch_state_desc)/sizeof(fetch_state_desc[0])); + S32 state = + mImagep->mNeedsCreateTexture ? LAST_STATE+1 : + mImagep->mFullyLoaded ? LAST_STATE+2 : + mImagep->mMinDiscardLevel > 0 ? LAST_STATE+3 : + mImagep->mIsMissingAsset ? LAST_STATE+4 : + !mImagep->mIsFetching ? LAST_STATE+5 : + mImagep->mFetchState; + state = llclamp(state,0,fetch_state_desc_size-1); + + LLFontGL::sMonospace->renderUTF8(fetch_state_desc[state].desc, 0, title_x2, mRect.getHeight(), + fetch_state_desc[state].color, + LLFontGL::LEFT, LLFontGL::TOP); + LLGLSNoTexture gls_no_texture; + + // Draw the progress bar. + S32 bar_width = 100; + S32 bar_left = 280; + left = bar_left; + right = left + bar_width; + + glColor4f(0.f, 0.f, 0.f, 0.75f); + gl_rect_2d(left, top, right, bottom); + + F32 data_progress = mImagep->mDownloadProgress; + + if (data_progress > 0.0f) + { + // Downloaded bytes + right = left + llfloor(data_progress * (F32)bar_width); + if (right > left) + { + glColor4f(0.f, 0.f, 1.f, 0.75f); + gl_rect_2d(left, top, right, bottom); + } + } + + S32 pip_width = 6; + S32 pip_space = 14; + S32 pip_x = title_x3 + pip_space/2; + + // Draw the packet pip + F32 last_event = mImagep->mLastPacketTimer.getElapsedTimeF32(); + if (last_event < 1.f) + { + clr = LLColor4::white; + } + else + { + last_event = mImagep->mRequestDeltaTime; + if (last_event < 1.f) + { + clr = LLColor4::green; + } else - return i1p->getID() < i2p->getID(); + { + last_event = mImagep->mFetchDeltaTime; + if (last_event < 1.f) + { + clr = LLColor4::yellow; + } + } + } + if (last_event < 1.f) + { + clr.setAlpha(1.f - last_event); + glColor4fv(clr.mV); + gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); } + pip_x += pip_width + pip_space; + + // we don't want to show bind/resident pips for textures using the default texture + if (mImagep->getHasGLTexture()) + { + // Draw the bound pip + last_event = mImagep->sLastFrameTime - mImagep->mLastBindTime; + if (last_event < 1.f) + { + clr = mImagep->getMissed() ? LLColor4::red : LLColor4::magenta1; + clr.setAlpha(1.f - last_event); + glColor4fv(clr.mV); + gl_rect_2d(pip_x, top, pip_x + pip_width, bottom); + } + } + pip_x += pip_width + pip_space; + + + { + LLGLSUIDefault gls_ui; + // draw the packet data +// { +// LLString num_str = llformat("%3d/%3d", mImagep->mLastPacket+1, mImagep->mPackets); +// LLFontGL::sMonospace->renderUTF8(num_str, 0, bar_left + 100, mRect.getHeight(), color, +// LLFontGL::LEFT, LLFontGL::TOP); +// } + + // draw the image size at the end + { + LLString num_str = llformat("%3dx%3d (%d) %7d", mImagep->getWidth(), mImagep->getHeight(), + mImagep->getDiscardLevel(), mImagep->mTextureMemory); + LLFontGL::sMonospace->renderUTF8(num_str, 0, title_x4, mRect.getHeight(), color, + LLFontGL::LEFT, LLFontGL::TOP); + } + } + +} + +BOOL LLTextureBar::handleMouseDown(S32 x, S32 y, MASK mask) +{ + if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == MASK_ALT) + { + gTextureFetch->mDebugID = mImagep->getID(); + return TRUE; + } + return LLView::handleMouseDown(x,y,mask); +} + +LLRect LLTextureBar::getRequiredRect() +{ + LLRect rect; + + rect.mTop = texture_bar_height; + + return rect; +} + +//////////////////////////////////////////////////////////////////////////// + +class LLGLTexMemBar : public LLView +{ +public: + LLGLTexMemBar(const std::string& name, LLTextureView* texview) + : LLView(name, FALSE), + mTextureView(texview) + { + S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f); + setRect(LLRect(0,0,100,line_height * 4)); + updateRect(); + } + + virtual EWidgetType getWidgetType() const { return WIDGET_TYPE_TEX_MEM_BAR; }; + virtual LLString getWidgetTag() const { return LL_GL_TEX_MEM_BAR_TAG; }; + + virtual void draw(); + virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); + virtual LLRect getRequiredRect(); // Return the height of this object, given the set options. + +private: + LLTextureView* mTextureView; }; +void LLGLTexMemBar::draw() +{ + S32 bound_mem = LLViewerImage::sBoundTextureMemory; + S32 max_bound_mem = LLViewerImage::sMaxBoundTextureMem; + S32 total_mem = LLViewerImage::sTotalTextureMemory; + S32 max_total_mem = LLViewerImage::sMaxTotalTextureMem; + F32 discard_bias = LLViewerImage::sDesiredDiscardBias; + S32 line_height = (S32)(LLFontGL::sMonospace->getLineHeight() + .5f); + + //---------------------------------------------------------------------------- + LLGLSUIDefault gls_ui; + F32 text_color[] = {1.f, 1.f, 1.f, 0.75f}; + + std::string text; + text = llformat("GL Tot: %d/%d MB Bound: %d/%d MB Discard Bias: %.2f", + total_mem/(1024*1024), + max_total_mem/(1024*1024), + bound_mem/(1024*1024), + max_bound_mem/(1024*1024), + discard_bias); + + LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*3, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + //---------------------------------------------------------------------------- + S32 bar_left = 380; + S32 bar_width = 200; + S32 top = line_height*3 - 2; + S32 bottom = top - 6; + S32 left = bar_left; + S32 right = left + bar_width; + + F32 bar_scale = (F32)bar_width / (max_bound_mem * 1.5f); + + LLGLSNoTexture gls_no_texture; + + glColor4f(0.5f, 0.5f, 0.5f, 0.75f); + gl_rect_2d(left, top, right, bottom); + + + left = bar_left; + right = left + llfloor(bound_mem * bar_scale); + if (bound_mem < llfloor(max_bound_mem * texmem_lower_bound_scale)) + { + glColor4f(0.f, 1.f, 0.f, 0.75f); + } + else if (bound_mem < max_bound_mem) + { + glColor4f(1.f, 1.f, 0.f, 0.75f); + } + else + { + glColor4f(1.f, 0.f, 0.f, 0.75f); + } + gl_rect_2d(left, top, right, bottom); + + bar_scale = (F32)bar_width / (max_total_mem * 1.5f); + + top = bottom - 2; + bottom = top - 6; + left = bar_left; + right = left + llfloor(total_mem * bar_scale); + if (total_mem < llfloor(max_total_mem * texmem_lower_bound_scale)) + { + glColor4f(0.f, 1.f, 0.f, 0.75f); + } + else if (total_mem < max_total_mem) + { + glColor4f(1.f, 1.f, 0.f, 0.75f); + } + else + { + glColor4f(1.f, 0.f, 0.f, 0.75f); + } + gl_rect_2d(left, top, right, bottom); + + //---------------------------------------------------------------------------- + + LLGLEnable tex(GL_TEXTURE_2D); + + text = llformat("Textures: Count: %d Fetch: %d(%d) Pkts:%d(%d) Cache R/W: %d/%d LFS:%d IW:%d(%d) RAW:%d", + gImageList.getNumImages(), + gTextureFetch->getNumRequests(), gTextureFetch->getNumDeletes(), + gTextureFetch->mPacketCount, gTextureFetch->mBadPacketCount, + gTextureCache->getNumReads(), gTextureCache->getNumWrites(), + LLLFSThread::sLocal->getPending(), + LLImageWorker::sCount, LLImageWorker::getWorkerThread()->getNumDeletes(), + LLImageRaw::sRawImageCount); + + LLFontGL::sMonospace->renderUTF8(text, 0, 0, line_height*2, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + S32 dx1 = 0; + if (gTextureFetch->mDebugPause) + { + LLFontGL::sMonospace->renderUTF8("!", 0, title_x1, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + dx1 += 8; + } + if (mTextureView->mFreezeView) + { + LLFontGL::sMonospace->renderUTF8("*", 0, title_x1, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + dx1 += 8; + } + if (mTextureView->mOrderFetch) + { + LLFontGL::sMonospace->renderUTF8(title_string1b, 0, title_x1+dx1, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + else + { + LLFontGL::sMonospace->renderUTF8(title_string1a, 0, title_x1+dx1, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + } + + LLFontGL::sMonospace->renderUTF8(title_string2, 0, title_x2, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + LLFontGL::sMonospace->renderUTF8(title_string3, 0, title_x3, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); + + LLFontGL::sMonospace->renderUTF8(title_string4, 0, title_x4, line_height, + text_color, LLFontGL::LEFT, LLFontGL::TOP); +} + +BOOL LLGLTexMemBar::handleMouseDown(S32 x, S32 y, MASK mask) +{ + return FALSE; +} + +LLRect LLGLTexMemBar::getRequiredRect() +{ + LLRect rect; + rect.mTop = 8; + return rect; +} + +//////////////////////////////////////////////////////////////////////////// + LLTextureView::LLTextureView(const std::string& name, const LLRect& rect) -: LLContainerView(name, rect) + : LLContainerView(name, rect), + mFreezeView(FALSE), + mOrderFetch(FALSE), + mPrintList(FALSE), + mNumTextureBars(0) { setVisible(FALSE); - mFreezeView = FALSE; - mNumTextureBars = 0; setDisplayChildren(TRUE); mGLTexMemBar = 0; } @@ -122,46 +583,79 @@ void LLTextureView::draw() typedef std::multiset display_list_t; display_list_t display_image_list; - for (LLViewerImageList::image_list_t::iterator iter = gImageList.mImageList.begin(); + if (mPrintList) + { + llinfos << "ID\tMEM\tBOOST\tPRI\tWIDTH\tHEIGHT\tDISCARD" << llendl; + } + + for (LLViewerImageList::image_priority_list_t::iterator iter = gImageList.mImageList.begin(); iter != gImageList.mImageList.end(); ) { LLPointer imagep = *iter++; -#if 1 + + S32 cur_discard = imagep->getDiscardLevel(); + S32 desired_discard = imagep->mDesiredDiscardLevel; + + if (mPrintList) + { + llinfos << imagep->getID() + << "\t" << imagep->mTextureMemory + << "\t" << imagep->getBoostLevel() + << "\t" << imagep->getDecodePriority() + << "\t" << imagep->getWidth() + << "\t" << imagep->getHeight() + << "\t" << cur_discard + << llendl; + } + +#if 0 if (imagep->getDontDiscard()) { continue; } -#endif + if (imagep->isMissingAsset()) { continue; } - -#define HIGH_PRIORITY 100000000.f - F32 pri = imagep->getDecodePriority(); +#endif - if (sDebugImages.find(imagep) != sDebugImages.end()) +#define HIGH_PRIORITY 100000000.f + F32 pri; + if (mOrderFetch) + { + pri = ((F32)imagep->mFetchPriority)/256.f; + } + else { - pri += 3*HIGH_PRIORITY; + pri = imagep->getDecodePriority(); } + if (sDebugImages.find(imagep) != sDebugImages.end()) + { + pri += 4*HIGH_PRIORITY; + } + + if (!mOrderFetch) + { #if 1 if (pri < HIGH_PRIORITY && gSelectMgr) { S32 te; LLViewerObject *objectp; - for (gSelectMgr->getFirstTE(&objectp, &te); objectp; gSelectMgr->getNextTE(&objectp, &te)) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (selection->getFirstTE(&objectp, &te); objectp; selection->getNextTE(&objectp, &te)) { if (imagep == objectp->getTEImage(te)) { - pri += 2*HIGH_PRIORITY; + pri += 3*HIGH_PRIORITY; break; } } } #endif #if 1 - if (pri < HIGH_PRIORITY) + if (pri < HIGH_PRIORITY && (cur_discard< 0 || desired_discard < cur_discard)) { LLViewerObject *objectp = gHoverView->getLastHoverObject(); if (objectp) @@ -178,31 +672,29 @@ void LLTextureView::draw() } } #endif -#if 0 - if (pri < HIGH_PRIORITY) - { - if (imagep->mBoostPriority) - { - pri += 4*HIGH_PRIORITY; - } - } -#endif #if 1 if (pri > 0.f && pri < HIGH_PRIORITY) { if (imagep->mLastPacketTimer.getElapsedTimeF32() < 1.f || - imagep->mLastDecodeTime.getElapsedTimeF32() < 1.f) + imagep->mFetchDeltaTime < 0.25f) { pri += 1*HIGH_PRIORITY; } } #endif -// if (pri > 0.0f) + } + + if (pri > 0.0f) { display_image_list.insert(std::make_pair(pri, imagep)); } } - + + if (mPrintList) + { + mPrintList = FALSE; + } + static S32 max_count = 50; S32 count = 0; for (display_list_t::iterator iter = display_image_list.begin(); @@ -224,9 +716,12 @@ void LLTextureView::draw() } } - sortChildren(SortTextureBars()); - - mGLTexMemBar = new LLGLTexMemBar("gl texmem bar"); + if (mOrderFetch) + sortChildren(LLTextureBar::sort_fetch()); + else + sortChildren(LLTextureBar::sort()); + + mGLTexMemBar = new LLGLTexMemBar("gl texmem bar", this); addChild(mGLTexMemBar); reshape(mRect.getWidth(), mRect.getHeight(), TRUE); @@ -256,54 +751,46 @@ void LLTextureView::draw() BOOL LLTextureView::addBar(LLViewerImage *imagep, S32 hilite) { - if (!imagep) - { - return FALSE; - } - + llassert(imagep); + LLTextureBar *barp; LLRect r; mNumTextureBars++; - for (std::vector::iterator iter = mTextureBars.begin(); - iter != mTextureBars.end(); iter++) - { - LLTextureBar* barp = *iter; - if (barp->mImagep == imagep) - { - barp->mHilite = hilite; - return FALSE; - } - } - - barp = new LLTextureBar("texture bar", r); + barp = new LLTextureBar("texture bar", r, this); barp->mImagep = imagep; barp->mHilite = hilite; addChild(barp); mTextureBars.push_back(barp); - // Rearrange all child bars. - reshape(mRect.getWidth(), mRect.getHeight()); return TRUE; } BOOL LLTextureView::handleMouseDown(S32 x, S32 y, MASK mask) { - if (mask & MASK_SHIFT) + if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_ALT|MASK_SHIFT)) { - mFreezeView = !mFreezeView; + mPrintList = TRUE; return TRUE; } - else if (mask & MASK_CONTROL) + if ((mask & (MASK_CONTROL|MASK_SHIFT|MASK_ALT)) == (MASK_CONTROL|MASK_SHIFT)) { - return FALSE; + gTextureFetch->mDebugPause = !gTextureFetch->mDebugPause; + return TRUE; } - else + if (mask & MASK_SHIFT) { - return FALSE; + mFreezeView = !mFreezeView; + return TRUE; } + if (mask & MASK_CONTROL) + { + mOrderFetch = !mOrderFetch; + return TRUE; + } + return LLView::handleMouseDown(x,y,mask); } BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask) @@ -313,11 +800,6 @@ BOOL LLTextureView::handleMouseUp(S32 x, S32 y, MASK mask) BOOL LLTextureView::handleKey(KEY key, MASK mask, BOOL called_from_parent) { - if (key == ' ') - { - mFreezeView = !mFreezeView; - return TRUE; - } return FALSE; } diff --git a/linden/indra/newview/lltextureview.h b/linden/indra/newview/lltextureview.h index bfeb8f9..70ca39a 100644 --- a/linden/indra/newview/lltextureview.h +++ b/linden/indra/newview/lltextureview.h @@ -28,14 +28,17 @@ #ifndef LL_LLTEXTUREVIEW_H #define LL_LLTEXTUREVIEW_H -#include "lltexturebar.h" #include "llcontainerview.h" #include "linked_lists.h" class LLViewerImage; +class LLTextureBar; +class LLGLTexMemBar; class LLTextureView : public LLContainerView { + friend class LLTextureBar; + friend class LLGLTexMemBar; public: LLTextureView(const std::string& name, const LLRect& rect); ~LLTextureView(); @@ -55,16 +58,18 @@ public: private: BOOL addBar(LLViewerImage *image, BOOL hilight = FALSE); void removeAllBars(); - + private: + BOOL mFreezeView; + BOOL mOrderFetch; + BOOL mPrintList; + LLTextBox *mInfoTextp; std::vector mTextureBars; U32 mNumTextureBars; LLGLTexMemBar* mGLTexMemBar; - - BOOL mFreezeView; public: static std::set sDebugImages; diff --git a/linden/indra/newview/lltool.cpp b/linden/indra/newview/lltool.cpp index d004a2d..9489a2b 100644 --- a/linden/indra/newview/lltool.cpp +++ b/linden/indra/newview/lltool.cpp @@ -35,6 +35,7 @@ #include "llviewerwindow.h" #include "lltoolcomp.h" +#include "lltoolfocus.h" #include "llfocusmgr.h" #include "llagent.h" #include "llviewborder.h" @@ -154,6 +155,14 @@ BOOL LLTool::handleKey(KEY key, MASK mask) return FALSE; } +LLTool* LLTool::getOverrideTool(MASK mask) +{ + if (mask & MASK_ALT) + { + return gToolCamera; + } + return NULL; +} // static void LLTool::onMouseCaptureLost( LLMouseHandler* old_captor ) diff --git a/linden/indra/newview/lltool.h b/linden/indra/newview/lltool.h index 3116c72..866755a 100644 --- a/linden/indra/newview/lltool.h +++ b/linden/indra/newview/lltool.h @@ -77,6 +77,8 @@ public: virtual void handleSelect() { } // do stuff when your tool is selected virtual void handleDeselect() { } // clean up when your tool is deselected + virtual LLTool* getOverrideTool(MASK mask); + // isAlwaysRendered() - return true if this is a tool that should // always be rendered regardless of selection. virtual BOOL isAlwaysRendered() { return FALSE; } diff --git a/linden/indra/newview/lltoolbrush.cpp b/linden/indra/newview/lltoolbrush.cpp index 1822c63..210a1e7 100644 --- a/linden/indra/newview/lltoolbrush.cpp +++ b/linden/indra/newview/lltoolbrush.cpp @@ -182,7 +182,7 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() return; } - if (gToolMgr->getCurrentTool(gKeyboard->currentMask(TRUE)) == gToolParcel) + if (gToolMgr->getCurrentTool() == gToolParcel) { // selecting land, don't do anything return; @@ -301,8 +301,8 @@ void LLToolBrushLand::modifyLandInSelectionGlobal() msg->addF32Fast(_PREHASH_Seconds, seconds); msg->addF32Fast(_PREHASH_Height, mStartingZ); - BOOL parcel_selected = gParcelMgr->getWholeParcelSelected(); - LLParcel* selected_parcel = gParcelMgr->getSelectedParcel(); + BOOL parcel_selected = gParcelMgr->getParcelSelection()->getWholeParcelSelected(); + LLParcel* selected_parcel = gParcelMgr->getParcelSelection()->getParcel(); if (parcel_selected && selected_parcel) { @@ -535,7 +535,7 @@ void LLToolBrushLand::onIdle( void* brush_tool ) { LLToolBrushLand* self = reinterpret_cast(brush_tool); - if( gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ) == self ) + if( gToolMgr->getCurrentTool() == self ) { self->brush(); } diff --git a/linden/indra/newview/lltoolcomp.cpp b/linden/indra/newview/lltoolcomp.cpp index 0ef710d..8898dcb 100644 --- a/linden/indra/newview/lltoolcomp.cpp +++ b/linden/indra/newview/lltoolcomp.cpp @@ -167,7 +167,7 @@ void LLToolCompInspect::pickCallback(S32 x, S32 y, MASK mask) if( hit_obj ) { - if (gSelectMgr->getObjectCount()) + if (gSelectMgr->getSelection()->getObjectCount()) { gEditMenuHandler = gSelectMgr; } @@ -223,7 +223,7 @@ BOOL LLToolCompTranslate::handleHover(S32 x, S32 y, MASK mask) BOOL LLToolCompTranslate::handleMouseDown(S32 x, S32 y, MASK mask) { mMouseDown = TRUE; - gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback); + gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, pickCallback, TRUE); return TRUE; } @@ -241,7 +241,7 @@ void LLToolCompTranslate::pickCallback(S32 x, S32 y, MASK mask) if( hit_obj || gToolTranslate->mManip->getHighlightedPart() != LLManip::LL_NO_PART ) { - if (gSelectMgr->getObjectCount()) + if (gToolTranslate->mManip->getSelection()->getObjectCount()) { gEditMenuHandler = gSelectMgr; } @@ -272,9 +272,22 @@ BOOL LLToolCompTranslate::handleMouseUp(S32 x, S32 y, MASK mask) return LLToolComposite::handleMouseUp(x, y, mask); } +LLTool* LLToolCompTranslate::getOverrideTool(MASK mask) +{ + if (mask == MASK_CONTROL) + { + return gToolRotate; + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return gToolStretch; + } + return LLToolComposite::getOverrideTool(mask); +} + BOOL LLToolCompTranslate::handleDoubleClick(S32 x, S32 y, MASK mask) { - if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) + if (mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) { // You should already have an object selected from the mousedown. // If so, show its properties @@ -350,7 +363,7 @@ void LLToolCompScale::pickCallback(S32 x, S32 y, MASK mask) if( hit_obj || gToolStretch->mManip->getHighlightedPart() != LLManip::LL_NO_PART) { - if (gSelectMgr->getObjectCount()) + if (gToolStretch->mManip->getSelection()->getObjectCount()) { gEditMenuHandler = gSelectMgr; } @@ -378,9 +391,20 @@ BOOL LLToolCompScale::handleMouseUp(S32 x, S32 y, MASK mask) return LLToolComposite::handleMouseUp(x, y, mask); } +LLTool* LLToolCompScale::getOverrideTool(MASK mask) +{ + if (mask == MASK_CONTROL) + { + return gToolRotate; + } + + return LLToolComposite::getOverrideTool(mask); +} + + BOOL LLToolCompScale::handleDoubleClick(S32 x, S32 y, MASK mask) { - if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) + if (!mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) { // You should already have an object selected from the mousedown. // If so, show its properties @@ -480,6 +504,11 @@ BOOL LLToolCompCreate::handleMouseUp(S32 x, S32 y, MASK mask) mObjectPlacedOnMouseDown = FALSE; mMouseDown = FALSE; + if (!handled) + { + handled = LLToolComposite::handleMouseUp(x, y, mask); + } + return handled; } @@ -534,7 +563,7 @@ void LLToolCompRotate::pickCallback(S32 x, S32 y, MASK mask) if( hit_obj || gToolRotate->mManip->getHighlightedPart() != LLManip::LL_NO_PART) { - if (gSelectMgr->getObjectCount()) + if (gToolRotate->mManip->getSelection()->getObjectCount()) { gEditMenuHandler = gSelectMgr; } @@ -562,10 +591,18 @@ BOOL LLToolCompRotate::handleMouseUp(S32 x, S32 y, MASK mask) return LLToolComposite::handleMouseUp(x, y, mask); } +LLTool* LLToolCompRotate::getOverrideTool(MASK mask) +{ + if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return gToolStretch; + } + return LLToolComposite::getOverrideTool(mask); +} BOOL LLToolCompRotate::handleDoubleClick(S32 x, S32 y, MASK mask) { - if (!gSelectMgr->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) + if (!mManip->getSelection()->isEmpty() && mManip->getHighlightedPart() == LLManip::LL_NO_PART) { // You should already have an object selected from the mousedown. // If so, show its properties @@ -668,7 +705,7 @@ BOOL LLToolCompGun::handleMouseDown(S32 x, S32 y, MASK mask) // On mousedown, start grabbing gGrabTransientTool = this; - gCurrentToolset->selectTool( (LLTool*) mGrab ); + gToolMgr->getCurrentToolset()->selectTool( (LLTool*) mGrab ); return gToolGrab->handleMouseDown(x, y, mask); } @@ -685,7 +722,7 @@ BOOL LLToolCompGun::handleDoubleClick(S32 x, S32 y, MASK mask) // On mousedown, start grabbing gGrabTransientTool = this; - gCurrentToolset->selectTool( (LLTool*) mGrab ); + gToolMgr->getCurrentToolset()->selectTool( (LLTool*) mGrab ); return gToolGrab->handleDoubleClick(x, y, mask); } diff --git a/linden/indra/newview/lltoolcomp.h b/linden/indra/newview/lltoolcomp.h index 143b5b1..d75cd11 100644 --- a/linden/indra/newview/lltoolcomp.h +++ b/linden/indra/newview/lltoolcomp.h @@ -129,6 +129,8 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); // Returns to the default tool virtual void render(); + virtual LLTool* getOverrideTool(MASK mask); + static void pickCallback(S32 x, S32 y, MASK mask); }; @@ -148,8 +150,9 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); // Returns to the default tool virtual void render(); + virtual LLTool* getOverrideTool(MASK mask); + static void pickCallback(S32 x, S32 y, MASK mask); - }; @@ -169,6 +172,8 @@ public: virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual void render(); + virtual LLTool* getOverrideTool(MASK mask); + static void pickCallback(S32 x, S32 y, MASK mask); protected: diff --git a/linden/indra/newview/lltooldraganddrop.cpp b/linden/indra/newview/lltooldraganddrop.cpp index 398263f..ffa124f 100644 --- a/linden/indra/newview/lltooldraganddrop.cpp +++ b/linden/indra/newview/lltooldraganddrop.cpp @@ -601,6 +601,7 @@ LLToolDragAndDrop::LLToolDragAndDrop() LLTool("draganddrop", NULL), mDragStartX(0), mDragStartY(0), + mSource(SOURCE_AGENT), mCursor(UI_CURSOR_NO), mLastAccept(ACCEPT_NO), mDrop(FALSE), @@ -1203,6 +1204,8 @@ BOOL LLToolDragAndDrop::handleDropTextureProtections(LLViewerObject* hit_obj, return TRUE; } + if (!item) return FALSE; + LLPointer new_item = new LLViewerInventoryItem(item); if(!item->getPermissions().allowOperationBy(PERM_COPY, gAgent.getID())) { @@ -1258,6 +1261,11 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, LLToolDragAndDrop::ESource source, const LLUUID& src_id) { + if (!item) + { + llwarns << "LLToolDragAndDrop::dropTextureAllFaces no texture item." << llendl; + return; + } LLUUID asset_id = item->getAssetUUID(); BOOL success = handleDropTextureProtections(hit_obj, item, source, src_id); if(!success) @@ -1273,11 +1281,9 @@ void LLToolDragAndDrop::dropTextureAllFaces(LLViewerObject* hit_obj, // update viewer side image in anticipation of update from simulator hit_obj->setTEImage(face, image); dialog_refresh_all(); - - // send the update to the simulator - hit_obj->sendTEUpdate(); } - + // send the update to the simulator + hit_obj->sendTEUpdate(); } /* @@ -1480,6 +1486,9 @@ void LLToolDragAndDrop::dropObject(LLViewerObject* raycast_target, // since it's coming from the library or trash, we want to not // 'take' it back to the same place. item->setParent(LLUUID::null); + // *TODO this code isn't working - the parent (FolderID) is still + // set when the object is "taken". so code on the "take" side is + // checking for trash and library as well (llviewermenu.cpp) } if (mSource == SOURCE_NOTECARD) { @@ -1662,7 +1671,7 @@ void LLToolDragAndDrop::commitGiveInventoryItem(const LLUUID& to_agent, const S32 BUCKET_SIZE = sizeof(U8) + UUID_BYTES; U8 bucket[BUCKET_SIZE]; bucket[0] = (U8)item->getType(); - memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); + memcpy(&bucket[1], &(item->getUUID().mData), UUID_BYTES); /* Flawfinder: ignore */ pack_instant_message( gMessageSystem, gAgent.getID(), @@ -1842,26 +1851,26 @@ void LLToolDragAndDrop::commitGiveInventoryCategory(const LLUUID& to_agent, U8* bucket = new U8[bucket_size]; U8* pos = bucket; U8 type = (U8)cat->getType(); - memcpy(pos, &type, sizeof(U8)); + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ pos += sizeof(U8); - memcpy(pos, &(cat->getUUID()), UUID_BYTES); + memcpy(pos, &(cat->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ pos += UUID_BYTES; S32 i; count = cats.count(); for(i = 0; i < count; ++i) { - memcpy(pos, &type, sizeof(U8)); + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ pos += sizeof(U8); - memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); + memcpy(pos, &(cats.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ pos += UUID_BYTES; } count = items.count(); for(i = 0; i < count; ++i) { type = (U8)items.get(i)->getType(); - memcpy(pos, &type, sizeof(U8)); + memcpy(pos, &type, sizeof(U8)); /* Flawfinder: ignore */ pos += sizeof(U8); - memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); + memcpy(pos, &(items.get(i)->getUUID()), UUID_BYTES); /* Flawfinder: ignore */ pos += UUID_BYTES; } pack_instant_message( @@ -2320,6 +2329,12 @@ EAcceptance LLToolDragAndDrop::dad3dTextureObject( { return ACCEPT_NO_LOCKED; } + //If texture !copyable don't texture or you'll never get it back. + if(!item->getPermissions().allowCopyBy(gAgent.getID())) + { + return ACCEPT_NO; + } + if(drop && (ACCEPT_YES_SINGLE <= rv)) { if((mask & MASK_SHIFT)) diff --git a/linden/indra/newview/lltoolface.cpp b/linden/indra/newview/lltoolface.cpp index 504a787..b855e0f 100644 --- a/linden/indra/newview/lltoolface.cpp +++ b/linden/indra/newview/lltoolface.cpp @@ -61,7 +61,7 @@ LLToolFace::~LLToolFace() BOOL LLToolFace::handleDoubleClick(S32 x, S32 y, MASK mask) { - if (!gSelectMgr->isEmpty()) + if (!gSelectMgr->getSelection()->isEmpty()) { // You should already have an object selected from the mousedown. // If so, show its properties @@ -109,7 +109,7 @@ void LLToolFace::pickCallback(S32 x, S32 y, MASK mask) // object wasn't selected so add the object and face gSelectMgr->selectObjectOnly(hit_obj, hit_face); } - else if (!gSelectMgr->contains(hit_obj, hit_face) ) + else if (!gSelectMgr->getSelection()->contains(hit_obj, hit_face) ) { // object is selected, but not this face, so add it. gSelectMgr->addAsIndividual(hit_obj, hit_face); diff --git a/linden/indra/newview/lltoolfocus.cpp b/linden/indra/newview/lltoolfocus.cpp index e57f5fb..479d55c 100644 --- a/linden/indra/newview/lltoolfocus.cpp +++ b/linden/indra/newview/lltoolfocus.cpp @@ -62,9 +62,6 @@ BOOL gCameraBtnPan = FALSE; const S32 SLOP_RANGE = 4; const F32 FOCUS_OFFSET_FACTOR = 1.f; -extern void handle_first_tool(void*); - - // // Camera - shared functionality // @@ -91,13 +88,19 @@ LLToolCamera::~LLToolCamera() // virtual void LLToolCamera::handleSelect() { - gFloaterTools->setStatusText("Click and drag to change view"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("Click and drag to change view"); + } } // virtual void LLToolCamera::handleDeselect() { - gFloaterTools->setStatusText(""); + if (gFloaterTools) + { + gFloaterTools->setStatusText(""); + } // gAgent.setLookingAtAvatar(FALSE); } @@ -155,7 +158,8 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask) // check for hud attachments if (hit_obj && hit_obj->isHUDAttachment()) { - if (!gSelectMgr->getObjectCount() || gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (!selection->getObjectCount() || selection->getSelectType() != SELECT_TYPE_HUD) { gToolCamera->mValidClickPoint = FALSE; return; @@ -194,7 +198,7 @@ void LLToolCamera::pickCallback(S32 x, S32 y, MASK mask) } //RN: check to see if this is mouse-driving as opposed to ALT-zoom or Focus tool else if (mask & MASK_ALT || - (gToolMgr->getCurrentTool(mask)->getName() == "Camera")) + (gToolMgr->getCurrentTool()->getName() == "Camera")) { LLViewerObject* hit_obj = gViewerWindow->lastObjectHit(); if (hit_obj) diff --git a/linden/indra/newview/lltoolfocus.h b/linden/indra/newview/lltoolfocus.h index 9b15463..26a7085 100644 --- a/linden/indra/newview/lltoolfocus.h +++ b/linden/indra/newview/lltoolfocus.h @@ -46,6 +46,8 @@ public: virtual void handleSelect(); virtual void handleDeselect(); + virtual LLTool* getOverrideTool(MASK mask) { return NULL; } + static void pickCallback(S32 x, S32 y, MASK mask); BOOL mouseSteerMode() { return mMouseSteering; } diff --git a/linden/indra/newview/lltoolgrab.cpp b/linden/indra/newview/lltoolgrab.cpp index 90dbd48..e186e4a 100644 --- a/linden/indra/newview/lltoolgrab.cpp +++ b/linden/indra/newview/lltoolgrab.cpp @@ -145,7 +145,7 @@ void LLToolGrab::pickCallback(S32 x, S32 y, MASK mask) BOOL extend_select = (mask & MASK_SHIFT); - if (!extend_select && !gSelectMgr->isEmpty()) + if (!extend_select && !gSelectMgr->getSelection()->isEmpty()) { gSelectMgr->deselectAll(); gToolGrab->mDeselectedThisClick = TRUE; diff --git a/linden/indra/newview/lltoolgrab.h b/linden/indra/newview/lltoolgrab.h index db8242c..ad05295 100644 --- a/linden/indra/newview/lltoolgrab.h +++ b/linden/indra/newview/lltoolgrab.h @@ -53,7 +53,7 @@ public: virtual void handleSelect(); virtual void handleDeselect(); - + virtual LLViewerObject* getEditingObject(); virtual LLVector3d getEditingPointGlobal(); virtual BOOL isEditing(); diff --git a/linden/indra/newview/lltoolgun.cpp b/linden/indra/newview/lltoolgun.cpp index e4ec56a..dfe97ae 100644 --- a/linden/indra/newview/lltoolgun.cpp +++ b/linden/indra/newview/lltoolgun.cpp @@ -67,7 +67,7 @@ void LLToolGun::handleDeselect() BOOL LLToolGun::handleMouseDown(S32 x, S32 y, MASK mask) { gGrabTransientTool = this; - gCurrentToolset->selectTool( gToolGrab ); + gToolMgr->getCurrentToolset()->selectTool( gToolGrab ); return gToolGrab->handleMouseDown(x, y, mask); } diff --git a/linden/indra/newview/lltoolgun.h b/linden/indra/newview/lltoolgun.h index 38854a3..6884cb6 100644 --- a/linden/indra/newview/lltoolgun.h +++ b/linden/indra/newview/lltoolgun.h @@ -45,6 +45,7 @@ public: virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleHover(S32 x, S32 y, MASK mask); + virtual LLTool* getOverrideTool(MASK mask) { return NULL; } virtual BOOL clipMouseWhenDown() { return FALSE; } private: diff --git a/linden/indra/newview/lltoolindividual.cpp b/linden/indra/newview/lltoolindividual.cpp index e17a2a1..96bd89e 100644 --- a/linden/indra/newview/lltoolindividual.cpp +++ b/linden/indra/newview/lltoolindividual.cpp @@ -85,7 +85,7 @@ void LLToolIndividual::pickCallback(S32 x, S32 y, MASK mask) BOOL LLToolIndividual::handleDoubleClick(S32 x, S32 y, MASK mask) { - if(!gSelectMgr->isEmpty()) + if(!gSelectMgr->getSelection()->isEmpty()) { // You should already have an object selected from the mousedown. // If so, show its inventory. @@ -104,10 +104,10 @@ BOOL LLToolIndividual::handleDoubleClick(S32 x, S32 y, MASK mask) void LLToolIndividual::handleSelect() { - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); + LLViewerObject* obj = gSelectMgr->getSelection()->getFirstRootObject(); if(!obj) { - obj = gSelectMgr->getFirstObject(); + obj = gSelectMgr->getSelection()->getFirstObject(); } gSelectMgr->deselectAll(); if(obj) diff --git a/linden/indra/newview/lltoolmgr.cpp b/linden/indra/newview/lltoolmgr.cpp index 68a3e77..b6e14a2 100644 --- a/linden/indra/newview/lltoolmgr.cpp +++ b/linden/indra/newview/lltoolmgr.cpp @@ -53,7 +53,6 @@ LLToolMgr* gToolMgr = NULL; // Used when app not active to avoid processing hover. LLTool* gToolNull = NULL; -LLToolset* gCurrentToolset = NULL; LLToolset* gBasicToolset = NULL; LLToolset* gCameraToolset = NULL; //LLToolset* gLandToolset = NULL; @@ -65,10 +64,12 @@ LLToolset* gFaceEditToolset = NULL; LLToolMgr::LLToolMgr() : - mCurrentTool(NULL), + mBaseTool(NULL), mSavedTool(NULL), mTransientTool( NULL ), - mOverrideTool( NULL ) + mOverrideTool( NULL ), + mSelectedTool( NULL ), + mCurrentToolset( NULL ) { gToolNull = new LLTool(NULL); // Does nothing setCurrentTool(gToolNull); @@ -78,8 +79,6 @@ LLToolMgr::LLToolMgr() // gLandToolset = new LLToolset(); gMouselookToolset = new LLToolset(); gFaceEditToolset = new LLToolset(); - - gCurrentToolset = gBasicToolset; } void LLToolMgr::initTools() @@ -197,8 +196,8 @@ void LLToolMgr::initTools() gToolObjPicker = new LLToolObjPicker(); // On startup, use "select" tool + setCurrentToolset(gBasicToolset); gBasicToolset->selectTool( gToolPie ); - useSelectedTool( gBasicToolset ); } LLToolMgr::~LLToolMgr() @@ -267,138 +266,103 @@ LLToolMgr::~LLToolMgr() gToolNull = NULL; } - -void LLToolMgr::useSelectedTool( LLToolset* vp ) -{ - setCurrentTool( vp->getSelectedTool() ); -} - BOOL LLToolMgr::usingTransientTool() { return mTransientTool ? TRUE : FALSE; } -void LLToolMgr::setCurrentTool( LLTool* tool ) +void LLToolMgr::setCurrentToolset(LLToolset* current) { - if (tool == mCurrentTool) + if (!current) return; + + // switching toolsets? + if (current != mCurrentToolset) { - // didn't change tool, so don't mess with - // handleSelect or handleDeselect - return; + // deselect current tool + if (mSelectedTool) + { + mSelectedTool->handleDeselect(); + } + mCurrentToolset = current; + // select first tool of new toolset only if toolset changed + mCurrentToolset->selectFirstTool(); } + // update current tool based on new toolset + setCurrentTool( mCurrentToolset->getSelectedTool() ); +} + +LLToolset* LLToolMgr::getCurrentToolset() +{ + return mCurrentToolset; +} +void LLToolMgr::setCurrentTool( LLTool* tool ) +{ if (mTransientTool) { - mTransientTool->handleDeselect(); mTransientTool = NULL; } - else if( mCurrentTool ) - { - mCurrentTool->handleDeselect(); - } - mCurrentTool = tool; - if (mCurrentTool) - { - mCurrentTool->handleSelect(); - } + mBaseTool = tool; + updateToolStatus(); } -LLTool* LLToolMgr::getCurrentTool(MASK override_mask) +LLTool* LLToolMgr::getCurrentTool() { - // In mid-drag, always keep the current tool - if (gToolTranslate->hasMouseCapture() - || gToolRotate->hasMouseCapture() - || gToolStretch->hasMouseCapture()) - { - // might have gotten here by overriding another tool - if (mOverrideTool) - { - return mOverrideTool; - } - else - { - return mCurrentTool; - } - } + MASK override_mask = gKeyboard->currentMask(TRUE); + LLTool* cur_tool = NULL; + // always use transient tools if available if (mTransientTool) { mOverrideTool = NULL; - return mTransientTool; + cur_tool = mTransientTool; } - - if (mCurrentTool == gToolGun) + // tools currently grabbing mouse input will stay active + else if (mSelectedTool && mSelectedTool->hasMouseCapture()) { - mOverrideTool = NULL; - return mCurrentTool; + cur_tool = mSelectedTool; } - - // ALT always gets you the camera tool - if (override_mask & MASK_ALT) + else { - mOverrideTool = gToolCamera; - return mOverrideTool; - } + mOverrideTool = mBaseTool ? mBaseTool->getOverrideTool(override_mask) : NULL; - if (mCurrentTool == gToolCamera) - { - // ...can't switch out of camera - mOverrideTool = NULL; - return mCurrentTool; - } - else if (mCurrentTool == gToolGrab) - { - // ...can't switch out of grab - mOverrideTool = NULL; - return mCurrentTool; + // use override tool if available otherwise drop back to base tool + cur_tool = mOverrideTool ? mOverrideTool : mBaseTool; } - else if (mCurrentTool == gToolInspect) - { - // ...can't switch out of grab - mOverrideTool = NULL; - return mCurrentTool; - } - else + + //update tool selection status + if (mSelectedTool != cur_tool) { - // ...can switch between editing tools - if (override_mask == MASK_CONTROL) - { - // Control lifts when in the pie tool, otherwise switches to rotate - if (mCurrentTool == gToolPie) - { - mOverrideTool = gToolGrab; - } - else - { - mOverrideTool = gToolRotate; - } - return mOverrideTool; - } - else if (override_mask == (MASK_CONTROL | MASK_SHIFT)) + if (mSelectedTool) { - // Shift-Control spins when in the pie tool, otherwise switches to scale - if (mCurrentTool == gToolPie) - { - mOverrideTool = gToolGrab; - } - else - { - mOverrideTool = gToolStretch; - } - return mOverrideTool; + mSelectedTool->handleDeselect(); } - else + if (cur_tool) { - mOverrideTool = NULL; - return mCurrentTool; + cur_tool->handleSelect(); } + mSelectedTool = cur_tool; } + + return mSelectedTool; +} + +LLTool* LLToolMgr::getBaseTool() +{ + return mBaseTool; +} + +void LLToolMgr::updateToolStatus() +{ + // call getcurrenttool() to calculate active tool and call handleSelect() and handleDeselect() immediately + // when active tool changes + getCurrentTool(); } BOOL LLToolMgr::inEdit() { - return mCurrentTool != gToolPie && mCurrentTool != gToolNull; + return mBaseTool != gToolPie && mBaseTool != gToolNull; } void LLToolMgr::setTransientTool(LLTool* tool) @@ -411,34 +375,26 @@ void LLToolMgr::setTransientTool(LLTool* tool) { if (mTransientTool) { - mTransientTool->handleDeselect(); mTransientTool = NULL; } - else if (mCurrentTool) - { - mCurrentTool->handleDeselect(); - } mTransientTool = tool; - mTransientTool->handleSelect(); } + + updateToolStatus(); } void LLToolMgr::clearTransientTool() { if (mTransientTool) { - mTransientTool->handleDeselect(); mTransientTool = NULL; - if (mCurrentTool) - { - mCurrentTool->handleSelect(); - } - else + if (!mBaseTool) { - llwarns << "mCurrentTool is NULL" << llendl; + llwarns << "mBaseTool is NULL" << llendl; } } + updateToolStatus(); } @@ -447,26 +403,19 @@ void LLToolMgr::clearTransientTool() // release this locking. void LLToolMgr::onAppFocusLost() { - if (mCurrentTool - && mCurrentTool == gToolGun) - { - mCurrentTool->handleDeselect(); - } - mSavedTool = mCurrentTool; - mCurrentTool = gToolNull; + mSavedTool = mBaseTool; + mBaseTool = gToolNull; + updateToolStatus(); } void LLToolMgr::onAppFocusGained() { if (mSavedTool) { - if (mSavedTool == gToolGun) - { - mCurrentTool->handleSelect(); - } - mCurrentTool = mSavedTool; + mBaseTool = mSavedTool; mSavedTool = NULL; } + updateToolStatus(); } ///////////////////////////////////////////////////// @@ -510,7 +459,10 @@ BOOL LLToolset::isToolSelected( S32 index ) void LLToolset::selectFirstTool() { mSelectedTool = mToolList.getFirstData(); - gToolMgr->setCurrentTool( mSelectedTool ); + if (gToolMgr) + { + gToolMgr->setCurrentTool( mSelectedTool ); + } } @@ -559,5 +511,5 @@ void LLToolset::selectPrevTool() void select_tool( void *tool_pointer ) { LLTool *tool = (LLTool *)tool_pointer; - gCurrentToolset->selectTool( tool ); + gToolMgr->getCurrentToolset()->selectTool( tool ); } diff --git a/linden/indra/newview/lltoolmgr.h b/linden/indra/newview/lltoolmgr.h index 6f0f50b..5cf005a 100644 --- a/linden/indra/newview/lltoolmgr.h +++ b/linden/indra/newview/lltoolmgr.h @@ -51,27 +51,33 @@ public: // Must be called after gSavedSettings set up. void initTools(); - LLTool* getCurrentTool(MASK override_mask); + LLTool* getCurrentTool(); // returns active tool, taking into account keyboard state + LLTool* getBaseTool(); // returns active tool when overrides are deactivated BOOL inEdit(); - void useSelectedTool( LLToolset* vp ); void setTransientTool(LLTool* tool); void clearTransientTool(); BOOL usingTransientTool(); + void setCurrentToolset(LLToolset* current); + LLToolset* getCurrentToolset(); + void onAppFocusGained(); void onAppFocusLost(); protected: friend class LLToolset; // to allow access to setCurrentTool(); void setCurrentTool(LLTool* tool); + void updateToolStatus(); protected: - LLTool* mCurrentTool; + LLTool* mBaseTool; LLTool* mSavedTool; // The current tool at the time application focus was lost. LLTool* mTransientTool; LLTool* mOverrideTool; // Tool triggered by keyboard override + LLTool* mSelectedTool; // last known active tool + LLToolset* mCurrentToolset; }; // Sets of tools for various modes @@ -106,7 +112,6 @@ void select_tool(void *tool); // Globals (created and destroyed by LLViewerWindow) extern LLToolMgr* gToolMgr; -extern LLToolset* gCurrentToolset; extern LLToolset* gBasicToolset; extern LLToolset *gCameraToolset; //extern LLToolset *gLandToolset; diff --git a/linden/indra/newview/lltoolmorph.cpp b/linden/indra/newview/lltoolmorph.cpp index ca3d0e7..a779554 100644 --- a/linden/indra/newview/lltoolmorph.cpp +++ b/linden/indra/newview/lltoolmorph.cpp @@ -234,10 +234,7 @@ BOOL LLVisualParamHint::render() { LLDrawPoolAvatar *avatarPoolp = (LLDrawPoolAvatar *)avatarp->mDrawable->getFace(0)->getPool(); LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); - gPipeline.unbindAGP(); - avatarPoolp->syncAGP(); - gPipeline.bindAGP(); - avatarPoolp->renderAvatars(avatarp, TRUE); // renders only one avatar (no shaders) + avatarPoolp->renderAvatars(avatarp); // renders only one avatar } avatarp->setVisualParamWeight(mVisualParam, mLastParamWeight); diff --git a/linden/indra/newview/lltoolpie.cpp b/linden/indra/newview/lltoolpie.cpp index e4be8ce..3eaa275 100644 --- a/linden/indra/newview/lltoolpie.cpp +++ b/linden/indra/newview/lltoolpie.cpp @@ -62,6 +62,7 @@ LLToolPie *gToolPie = NULL; LLViewerObject* LLToolPie::sClickActionObject = NULL; +LLHandle LLToolPie::sLeftClickSelection = NULL; extern void handle_buy(void*); @@ -79,8 +80,7 @@ LLToolPie::LLToolPie() BOOL LLToolPie::handleMouseDown(S32 x, S32 y, MASK mask) { - // if buttons swapped, don't pick transparent so users can't "pay" - // transparent objects + //left mouse down always picks transparent gViewerWindow->hitObjectOrLandGlobalAsync(x, y, mask, leftMouseCallback, TRUE, TRUE); mGrabMouseButtonDown = TRUE; @@ -188,19 +188,19 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) || parent && parent->flagTakesMoney()) { sClickActionObject = parent; - LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); return TRUE; } break; case CLICK_ACTION_BUY: sClickActionObject = parent; - LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); return TRUE; case CLICK_ACTION_OPEN: if (parent && parent->allowOpen()) { sClickActionObject = parent; - LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); + sLeftClickSelection = LLToolSelect::handleObjectSelection(parent, MASK_NONE, FALSE, TRUE); } return TRUE; } @@ -213,7 +213,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) !always_show) { gGrabTransientTool = this; - gCurrentToolset->selectTool( gToolGrab ); + gToolMgr->getCurrentToolset()->selectTool( gToolGrab ); return gToolGrab->handleObjectHit( object, x, y, mask); } @@ -272,8 +272,8 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) // Spawn pie menu if (mHitLand) { - gParcelMgr->selectParcelAt( gLastHitPosGlobal ); - + LLParcelSelectionHandle selection = gParcelMgr->selectParcelAt( gLastHitPosGlobal ); + gMenuHolder->setParcelSelection(selection); gPieLand->show(x, y, mPieMouseButtonDown); // VEFFECT: ShowPie @@ -288,6 +288,8 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) } else if (object) { + gMenuHolder->setObjectSelection(gSelectMgr->getSelection()); + if (object->isAvatar() || (object->isAttachment() && !object->isHUDAttachment() && !object->permYouOwner())) { @@ -321,7 +323,7 @@ BOOL LLToolPie::pickAndShowMenu(S32 x, S32 y, MASK mask, BOOL always_show) { // BUG: What about chatting child objects? LLString name; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (node) { name = node->mName; @@ -413,10 +415,11 @@ void LLToolPie::selectionPropertiesReceived() return; } - if (sClickActionObject - && !sClickActionObject->isDead()) + if (!sLeftClickSelection->isEmpty()) { - LLViewerObject* root = gSelectMgr->getFirstRootObject(); + LLViewerObject* root = sLeftClickSelection->getFirstRootObject(); + // since we don't currently have a way to lock a selection, it could have changed + // after we initially clicked on the object if (root == sClickActionObject) { U8 action = root->getClickAction(); @@ -436,6 +439,7 @@ void LLToolPie::selectionPropertiesReceived() } } } + sLeftClickSelection = NULL; sClickActionObject = NULL; } @@ -622,6 +626,19 @@ void LLToolPie::handleDeselect() gSelectMgr->validateSelection(); } +LLTool* LLToolPie::getOverrideTool(MASK mask) +{ + if (mask == MASK_CONTROL) + { + return gToolGrab; + } + else if (mask == (MASK_CONTROL | MASK_SHIFT)) + { + return gToolGrab; + } + + return LLTool::getOverrideTool(mask); +} void LLToolPie::stopEditing() { diff --git a/linden/indra/newview/lltoolpie.h b/linden/indra/newview/lltoolpie.h index 3a8f85b..dd54b5c 100644 --- a/linden/indra/newview/lltoolpie.h +++ b/linden/indra/newview/lltoolpie.h @@ -32,6 +32,7 @@ #include "lluuid.h" class LLViewerObject; +class LLObjectSelection; class LLToolPie : public LLTool @@ -52,6 +53,7 @@ public: virtual void onMouseCaptureLost(); virtual void handleDeselect(); + virtual LLTool* getOverrideTool(MASK mask); static void leftMouseCallback(S32 x, S32 y, MASK mask); static void rightMouseCallback(S32 x, S32 y, MASK mask); @@ -71,6 +73,7 @@ protected: LLUUID mHitObjectID; BOOL mMouseOutsideSlop; // for this drag, has mouse moved outside slop region static LLViewerObject* sClickActionObject; + static LLHandle sLeftClickSelection; }; extern LLToolPie *gToolPie; diff --git a/linden/indra/newview/lltoolplacer.cpp b/linden/indra/newview/lltoolplacer.cpp index 594be6c..e246546 100644 --- a/linden/indra/newview/lltoolplacer.cpp +++ b/linden/indra/newview/lltoolplacer.cpp @@ -129,7 +129,7 @@ BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask) // ...and go back to the default tool if (added && !gSavedSettings.getBOOL("CreateToolKeepSelected")) { - gCurrentToolset->selectTool( gToolTranslate ); + gToolMgr->getCurrentToolset()->selectTool( gToolTranslate ); } return added; @@ -171,7 +171,6 @@ LLPCode LLToolPlacerPanel::sSphere = LL_PCODE_SPHERE; LLPCode LLToolPlacerPanel::sSphereHemi = LL_PCODE_SPHERE_HEMI; LLPCode LLToolPlacerPanel::sTree = LL_PCODE_LEGACY_TREE; LLPCode LLToolPlacerPanel::sGrass = LL_PCODE_LEGACY_GRASS; -LLPCode LLToolPlacerPanel::sTreeNew = LL_PCODE_TREE_NEW; S32 LLToolPlacerPanel::sButtonsAdded = 0; LLButton* LLToolPlacerPanel::sButtons[ TOOL_PLACER_NUM_BUTTONS ]; diff --git a/linden/indra/newview/lltoolplacer.h b/linden/indra/newview/lltoolplacer.h index e4f9c7a..ab90ca1 100644 --- a/linden/indra/newview/lltoolplacer.h +++ b/linden/indra/newview/lltoolplacer.h @@ -85,7 +85,6 @@ public: static LLPCode sSphereHemi; static LLPCode sTree; static LLPCode sGrass; - static LLPCode sTreeNew; private: void addButton( const LLString& up_state, const LLString& down_state, LLPCode* pcode ); diff --git a/linden/indra/newview/lltoolselect.cpp b/linden/indra/newview/lltoolselect.cpp index a557136..924916c 100644 --- a/linden/indra/newview/lltoolselect.cpp +++ b/linden/indra/newview/lltoolselect.cpp @@ -93,7 +93,7 @@ BOOL LLToolSelect::handleDoubleClick(S32 x, S32 y, MASK mask) } // static -void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select) +LLHandle LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select) { BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); @@ -193,9 +193,10 @@ void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL if (!already_selected) { LLViewerObject* root_object = (LLViewerObject*)object->getRootEdit(); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); // this is just a temporary selection - LLSelectNode* select_node = gSelectMgr->findSelectNode(root_object); + LLSelectNode* select_node = selection->findNode(root_object); if (select_node) { select_node->setTransient(TRUE); @@ -203,7 +204,7 @@ void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL for (S32 i = 0; i < (S32)root_object->mChildList.size(); i++) { - select_node = gSelectMgr->findSelectNode(root_object->mChildList[i]); + select_node = selection->findNode(root_object->mChildList[i]); if (select_node) { select_node->setTransient(TRUE); @@ -221,6 +222,8 @@ void LLToolSelect::handleObjectSelection(LLViewerObject *object, MASK mask, BOOL gSavedSettings.setBOOL("SelectMovableOnly", select_movable); gSelectMgr->setForceSelection(FALSE); } + + return gSelectMgr->getSelection(); } BOOL LLToolSelect::handleMouseUp(S32 x, S32 y, MASK mask) diff --git a/linden/indra/newview/lltoolselect.h b/linden/indra/newview/lltoolselect.h index 5d2cc9d..065e08f 100644 --- a/linden/indra/newview/lltoolselect.h +++ b/linden/indra/newview/lltoolselect.h @@ -32,6 +32,8 @@ #include "v3math.h" #include "lluuid.h" +class LLObjectSelection; + class LLToolSelect : public LLTool { public: @@ -43,7 +45,7 @@ public: virtual void stopEditing(); - static void handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select); + static LLHandle handleObjectSelection(LLViewerObject *object, MASK mask, BOOL ignore_group, BOOL temp_select); virtual void onMouseCaptureLost(); virtual void handleDeselect(); diff --git a/linden/indra/newview/lltoolselectland.cpp b/linden/indra/newview/lltoolselectland.cpp index c0c0818..eaad28c 100644 --- a/linden/indra/newview/lltoolselectland.cpp +++ b/linden/indra/newview/lltoolselectland.cpp @@ -65,6 +65,10 @@ LLToolSelectLand::LLToolSelectLand( ) mLastShowParcelOwners(FALSE) { } +LLToolSelectLand::~LLToolSelectLand() +{ +} + BOOL LLToolSelectLand::handleMouseDown(S32 x, S32 y, MASK mask) { @@ -133,7 +137,7 @@ BOOL LLToolSelectLand::handleMouseUp(S32 x, S32 y, MASK mask) roundXY(mEastNorthTop); // Don't auto-select entire parcel. - gParcelMgr->selectLand( mWestSouthBottom, mEastNorthTop, FALSE ); + mSelection = gParcelMgr->selectLand( mWestSouthBottom, mEastNorthTop, FALSE ); } mMouseOutsideSlop = FALSE; @@ -220,6 +224,7 @@ void LLToolSelectLand::handleSelect() void LLToolSelectLand::handleDeselect() { gFloaterTools->setStatusText(""); + mSelection = NULL; //gParcelMgr->deselectLand(); gSavedSettings.setBOOL("ShowParcelOwners", mLastShowParcelOwners); } diff --git a/linden/indra/newview/lltoolselectland.h b/linden/indra/newview/lltoolselectland.h index 9bc1880..06ce1ee 100644 --- a/linden/indra/newview/lltoolselectland.h +++ b/linden/indra/newview/lltoolselectland.h @@ -31,11 +31,14 @@ #include "lltool.h" #include "v3dmath.h" +class LLParcelSelection; + class LLToolSelectLand : public LLTool { public: LLToolSelectLand( ); + virtual ~LLToolSelectLand(); /*virtual*/ BOOL handleMouseDown(S32 x, S32 y, MASK mask); /*virtual*/ BOOL handleDoubleClick(S32 x, S32 y, MASK mask); @@ -68,6 +71,7 @@ protected: LLVector3d mEastNorthTop; // global coords, from drag BOOL mLastShowParcelOwners; // store last Show Parcel Owners setting + LLHandle mSelection; // hold on to a parcel selection }; extern LLToolSelectLand *gToolParcel; diff --git a/linden/indra/newview/lltoolview.cpp b/linden/indra/newview/lltoolview.cpp index 5b80339..fa8d65b 100644 --- a/linden/indra/newview/lltoolview.cpp +++ b/linden/indra/newview/lltoolview.cpp @@ -148,7 +148,7 @@ void LLToolView::draw() { // turn off highlighting for all containers // and hide all option panels except for the selected one. - LLTool* selected = gCurrentToolset->getSelectedTool(); + LLTool* selected = gToolMgr->getCurrentToolset()->getSelectedTool(); for( LLToolContainer* contain = mContainList.getFirstData(); contain != NULL; contain = mContainList.getNextData() @@ -188,7 +188,6 @@ void LLToolView::onClickToolButton(void* userdata) LLToolContainer* clicked = (LLToolContainer*) userdata; // Switch to this one - gCurrentToolset->selectTool( clicked->mTool ); - gToolMgr->useSelectedTool( gCurrentToolset ); + gToolMgr->getCurrentToolset()->selectTool( clicked->mTool ); } diff --git a/linden/indra/newview/lltracker.cpp b/linden/indra/newview/lltracker.cpp index 58ba9b8..80d35dd 100644 --- a/linden/indra/newview/lltracker.cpp +++ b/linden/indra/newview/lltracker.cpp @@ -264,7 +264,7 @@ void LLTracker::render3D() else { const LLRelationship* buddy = av_tracker.getBuddyInfo(avatar_id); - if(buddy && !buddy->isOnline()) + if(buddy && !buddy->isOnline() && !gAgent.isGodlike()) { stop_tracking = TRUE; } @@ -556,8 +556,8 @@ void LLTracker::renderBeacon(LLVector3d pos_global, //gCylinder.render(1000); glPopMatrix(); - char text[1024]; - sprintf(text, "%.0f m", to_vec.magVec()); + char text[1024]; /* Flawfinder: ignore */ + snprintf(text, sizeof(text), "%.0f m", to_vec.magVec()); /* Flawfinder: ignore */ LLWString wstr; wstr += utf8str_to_wstring(label); diff --git a/linden/indra/newview/lluploaddialog.cpp b/linden/indra/newview/lluploaddialog.cpp index a67aa7d..620133e 100644 --- a/linden/indra/newview/lluploaddialog.cpp +++ b/linden/indra/newview/lluploaddialog.cpp @@ -102,8 +102,13 @@ void LLUploadDialog::setMessage( const std::string& msg) char* temp_msg = new char[size]; //strcpy(temp_msg,"Uploading...\n\n"); - strcpy( temp_msg, msg.c_str()); + if (temp_msg == NULL) + { + llerrs << "Memory Allocation Failed" << llendl; + return; + } + strcpy( temp_msg, msg.c_str()); /* Flawfinder: ignore */ char* token = strtok( temp_msg, "\n" ); while( token ) { diff --git a/linden/indra/newview/llurl.cpp b/linden/indra/newview/llurl.cpp index d3ad8e2..0374ec9 100644 --- a/linden/indra/newview/llurl.cpp +++ b/linden/indra/newview/llurl.cpp @@ -66,9 +66,10 @@ void LLURL::init(const char * url) mExtension[0] = '\0'; mTag[0] = '\0'; - char url_copy[MAX_STRING]; + char url_copy[MAX_STRING]; /* Flawfinder: ignore */ - strcpy (url_copy,url); + strncpy (url_copy,url, MAX_STRING -1); /* Flawfinder: ignore */ + url_copy[MAX_STRING -1] = '\0'; char *parse; char *leftover_url = url_copy; @@ -77,7 +78,8 @@ void LLURL::init(const char * url) // copy and lop off tag if ((parse = strchr(url_copy,'#'))) { - strcpy(mTag,parse+1); + strncpy(mTag,parse+1, LL_MAX_PATH -1); /* Flawfinder: ignore */ + mTag[LL_MAX_PATH -1] = '\0'; *parse = '\0'; } @@ -85,7 +87,8 @@ void LLURL::init(const char * url) if ((parse = strchr(url_copy,':'))) { *parse = '\0'; - strcpy(mURI,leftover_url); + strncpy(mURI,leftover_url, LL_MAX_PATH -1); /* Flawfinder: ignore */ + mURI[LL_MAX_PATH -1] = '\0'; leftover_url = parse + 1; } @@ -95,14 +98,15 @@ void LLURL::init(const char * url) leftover_url += 2; // skip the "//" span = strcspn(leftover_url, "/"); - strncat(mAuthority,leftover_url,span); + strncat(mAuthority,leftover_url,span); /* Flawfinder: ignore */ leftover_url += span; } if ((parse = strrchr(leftover_url,'.'))) { // copy and lop off extension - strcpy(mExtension,parse+1); + strncpy(mExtension,parse+1, LL_MAX_PATH -1); /* Flawfinder: ignore */ + mExtension[LL_MAX_PATH -1] = '\0'; *parse = '\0'; } @@ -116,11 +120,13 @@ void LLURL::init(const char * url) } // copy and lop off filename - strcpy(mFilename,parse); + strncpy(mFilename,parse, LL_MAX_PATH -1);/* Flawfinder: ignore */ + mFilename[LL_MAX_PATH -1] = '\0'; *parse = '\0'; // what's left should be the path - strcpy(mPath,leftover_url); + strncpy(mPath,leftover_url, LL_MAX_PATH -1); /* Flawfinder: ignore */ + mPath[LL_MAX_PATH -1] = '\0'; // llinfos << url << " decomposed into: " << llendl; // llinfos << " URI : <" << mURI << ">" << llendl; @@ -169,42 +175,43 @@ bool LLURL::operator!=(const LLURL& rhs) const const char * LLURL::getFQURL() const { - char fqurl[LL_MAX_PATH]; + char fqurl[LL_MAX_PATH]; /* Flawfinder: ignore */ fqurl[0] = '\0'; if (mURI[0]) { - strcat(fqurl,mURI); - strcat(fqurl,":"); + strncat(fqurl,mURI, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ + strcat(fqurl,":"); /* Flawfinder: ignore */ if (mAuthority[0]) { - strcat(fqurl,"//"); + strcat(fqurl,"//"); /* Flawfinder: ignore */ } } if (mAuthority[0]) { - strcat(fqurl,mAuthority); + strncat(fqurl,mAuthority, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ } - strcat(fqurl,mPath); + strncat(fqurl,mPath, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ - strcat(fqurl,mFilename); + strncat(fqurl,mFilename, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ if (mExtension[0]) { - strcat(fqurl,"."); - strcat(fqurl,mExtension); + strcat(fqurl,"."); /* Flawfinder: ignore */ + strncat(fqurl,mExtension, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ } if (mTag[0]) { - strcat(fqurl,"#"); - strcat(fqurl,mTag); + strcat(fqurl,"#"); /* Flawfinder: ignore */ + strncat(fqurl,mTag, LL_MAX_PATH - strlen(fqurl) -1); /* Flawfinder: ignore */ } - strcpy(LLURL::sReturnString,fqurl); + strncpy(LLURL::sReturnString,fqurl, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLURL::sReturnString[LL_MAX_PATH -1] = '\0'; return(LLURL::sReturnString); } @@ -212,16 +219,18 @@ const char * LLURL::getFQURL() const const char* LLURL::updateRelativePath(const LLURL &url) { - char new_path[LL_MAX_PATH]; - char tmp_path[LL_MAX_PATH]; + char new_path[LL_MAX_PATH]; /* Flawfinder: ignore */ + char tmp_path[LL_MAX_PATH]; /* Flawfinder: ignore */ char *parse; if (mPath[0] != '/') { //start with existing path - strcpy (new_path,url.mPath); - strcpy (tmp_path,mPath); + strncpy (new_path,url.mPath, LL_MAX_PATH -1); /* Flawfinder: ignore */ + new_path[LL_MAX_PATH -1] = '\0'; + strncpy (tmp_path,mPath, LL_MAX_PATH -1); /* Flawfinder: ignore */ + tmp_path[LL_MAX_PATH -1] = '\0'; parse = strtok(tmp_path,"/"); while (parse) @@ -246,28 +255,30 @@ const char* LLURL::updateRelativePath(const LLURL &url) } else { - strcat(new_path,"../"); + strcat(new_path,"../"); /* Flawfinder: ignore */ } } else { - strcat(new_path,parse); - strcat(new_path,"/"); + strncat(new_path,parse, LL_MAX_PATH - strlen(new_path) -1 ); /* Flawfinder: ignore */ + strcat(new_path,"/"); /* Flawfinder: ignore */ } parse = strtok(NULL,"/"); } - strcpy(mPath,new_path); + strncpy(mPath,new_path, LL_MAX_PATH -1); /* Flawfinder: ignore */ + mPath[LL_MAX_PATH -1] = '\0'; } return mPath; } const char * LLURL::getFullPath() { - strcpy(LLURL::sReturnString,mPath); - strcat(LLURL::sReturnString,mFilename); - strcat(LLURL::sReturnString,"."); - strcat(LLURL::sReturnString,mExtension); + strncpy(LLURL::sReturnString,mPath, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLURL::sReturnString[LL_MAX_PATH -1] = '\0'; + strncat(LLURL::sReturnString,mFilename, LL_MAX_PATH - strlen(LLURL::sReturnString) -1); /* Flawfinder: ignore */ + strcat(LLURL::sReturnString,"."); /* Flawfinder: ignore */ + strncat(LLURL::sReturnString,mExtension, LL_MAX_PATH - strlen(LLURL::sReturnString) -1); /* Flawfinder: ignore */ return(sReturnString); } diff --git a/linden/indra/newview/llurl.h b/linden/indra/newview/llurl.h index 58e8cf0..f60f06b 100644 --- a/linden/indra/newview/llurl.h +++ b/linden/indra/newview/llurl.h @@ -81,14 +81,14 @@ public: public: - char mURI[LL_MAX_PATH]; - char mAuthority[LL_MAX_PATH]; - char mPath[LL_MAX_PATH]; - char mFilename[LL_MAX_PATH]; - char mExtension[LL_MAX_PATH]; - char mTag[LL_MAX_PATH]; + char mURI[LL_MAX_PATH]; /* Flawfinder: ignore */ + char mAuthority[LL_MAX_PATH]; /* Flawfinder: ignore */ + char mPath[LL_MAX_PATH]; /* Flawfinder: ignore */ + char mFilename[LL_MAX_PATH]; /* Flawfinder: ignore */ + char mExtension[LL_MAX_PATH]; /* Flawfinder: ignore */ + char mTag[LL_MAX_PATH]; /* Flawfinder: ignore */ - static char sReturnString[LL_MAX_PATH]; + static char sReturnString[LL_MAX_PATH]; /* Flawfinder: ignore */ }; #endif // LL_LLURL_H diff --git a/linden/indra/newview/llurlwhitelist.cpp b/linden/indra/newview/llurlwhitelist.cpp index 8992146..3a8c952 100644 --- a/linden/indra/newview/llurlwhitelist.cpp +++ b/linden/indra/newview/llurlwhitelist.cpp @@ -40,7 +40,7 @@ LLUrlWhiteList::LLUrlWhiteList () : mLoaded ( false ), mFilename ( "url_whitelist.ini" ), mUrlList ( 0 ), - mUrlListIter ( 0 ) + mCurIndex ( 0 ) { } @@ -121,10 +121,10 @@ bool LLUrlWhiteList::save () if ( file.is_open () ) { // for each entry we have - for ( LLStringListIter iter = mUrlList.begin (); iter != mUrlList.end (); ++iter ) + for ( string_list_t::iterator iter = mUrlList.begin (); iter != mUrlList.end (); ++iter ) { file << ( *iter ) << std::endl; - }; + } file.close (); @@ -140,8 +140,7 @@ bool LLUrlWhiteList::clear () { mUrlList.clear (); - // invalidate iterator since we changed the contents - mUrlListIter = mUrlList.end (); + mCurIndex = 0; return true; } @@ -175,7 +174,7 @@ bool LLUrlWhiteList::addItem ( const LLString& itemIn, bool saveAfterAdd ) { LLString item = url_cleanup(itemIn); - mUrlList.insert ( mUrlList.end (), item ); + mUrlList.push_back ( item ); // use this when all you want to do is call addItem ( ... ) where necessary if ( saveAfterAdd ) @@ -191,11 +190,8 @@ bool LLUrlWhiteList::getFirst ( LLString& valueOut ) if ( mUrlList.size () == 0 ) return false; - mUrlListIter = mUrlList.begin (); - - valueOut = * ( mUrlListIter ); - - ++mUrlListIter; + mCurIndex = 0; + valueOut = mUrlList[mCurIndex++]; return true; } @@ -204,12 +200,10 @@ bool LLUrlWhiteList::getFirst ( LLString& valueOut ) // bool LLUrlWhiteList::getNext ( LLString& valueOut ) { - if ( mUrlListIter == mUrlList.end () ) + if ( mCurIndex >= mUrlList.size () ) return false; - valueOut = * ( mUrlListIter ); - - ++mUrlListIter; + valueOut = mUrlList[mCurIndex++]; return true; } diff --git a/linden/indra/newview/llurlwhitelist.h b/linden/indra/newview/llurlwhitelist.h index 18ccf71..6f4289b 100644 --- a/linden/indra/newview/llurlwhitelist.h +++ b/linden/indra/newview/llurlwhitelist.h @@ -55,13 +55,12 @@ class LLUrlWhiteList LLUrlWhiteList (); static LLUrlWhiteList* sInstance; - typedef std::list < LLString > LLStringList; - typedef std::list < LLString >::iterator LLStringListIter; + typedef std::vector < LLString > string_list_t ; bool mLoaded; const LLString mFilename; - LLStringList mUrlList; - LLStringListIter mUrlListIter; + string_list_t mUrlList; + U32 mCurIndex; }; #endif // LL_LLURLWHITELIST_H diff --git a/linden/indra/newview/lluserauth.cpp b/linden/indra/newview/lluserauth.cpp index f980aa0..4b554a9 100644 --- a/linden/indra/newview/lluserauth.cpp +++ b/linden/indra/newview/lluserauth.cpp @@ -117,14 +117,14 @@ void LLUserAuth::authenticate( XMLRPC_VectorAppendString(params, "last", lastname, 0); XMLRPC_VectorAppendString(params, "passwd", dpasswd.c_str(), 0); XMLRPC_VectorAppendString(params, "start", start, 0); - char buffer[MAX_STRING]; - sprintf(buffer, "%d", LL_VERSION_MAJOR); + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, MAX_STRING, "%d", LL_VERSION_MAJOR); /* Flawfinder: ignore */ XMLRPC_VectorAppendString(params, "major", buffer, 0); - sprintf(buffer, "%d", LL_VERSION_MINOR); + snprintf(buffer, MAX_STRING, "%d", LL_VERSION_MINOR); /* Flawfinder: ignore */ XMLRPC_VectorAppendString(params, "minor", buffer, 0); - sprintf(buffer, "%d", LL_VERSION_PATCH); + snprintf(buffer, MAX_STRING, "%d", LL_VERSION_PATCH); /* Flawfinder: ignore */ XMLRPC_VectorAppendString(params, "patch", buffer, 0); - sprintf(buffer, "%d", LL_VIEWER_BUILD); + snprintf(buffer, MAX_STRING, "%d", LL_VIEWER_BUILD); /* Flawfinder: ignore */ XMLRPC_VectorAppendString(params, "build", buffer, 0); XMLRPC_VectorAppendString(params, "platform", PLATFORM_STRING, 0); XMLRPC_VectorAppendString(params, "mac", hashed_mac.c_str(), 0); @@ -230,7 +230,7 @@ static void parseOptionInto( { std::string key; std::string val; - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ XMLRPC_VALUE_TYPE_EASY type; XMLRPC_VALUE row = XMLRPC_VectorRewind(option); while(row) @@ -248,7 +248,7 @@ static void parseOptionInto( } else if(xmlrpc_type_int == type) { - sprintf(buffer, "%d", XMLRPC_GetValueInt(opt)); + snprintf(buffer, MAX_STRING, "%d", XMLRPC_GetValueInt(opt)); /* Flawfinder: ignore */ val.assign(buffer); } //llinfos "option val: " << val << llendl; @@ -296,8 +296,8 @@ LLUserAuth::UserAuthcode LLUserAuth::parseResponse() } else if(xmlrpc_type_int == type) { - char buf[MAX_STRING]; - snprintf(buf, MAX_STRING, "%d", XMLRPC_GetValueInt(current)); + char buf[MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buf, MAX_STRING, "%d", XMLRPC_GetValueInt(current)); /* Flawfinder: ignore */ val.assign(buf); lldebugs << "val: " << val << llendl; mResponses.insert(response_t::value_type(key, val)); diff --git a/linden/indra/newview/llvelocitybar.cpp b/linden/indra/newview/llvelocitybar.cpp index d285733..403ff4f 100644 --- a/linden/indra/newview/llvelocitybar.cpp +++ b/linden/indra/newview/llvelocitybar.cpp @@ -121,8 +121,8 @@ void LLVelocityBar::draw() top = BAR_TOP + 15; left = 0; - char str[80]; - sprintf(str, "Velocity %.3fm/s", velocity); + char str[80]; /* Flawfinder: ignore */ + snprintf(str, sizeof(str), "Velocity %.3fm/s", velocity); /* Flawfinder: ignore */ LLFontGL::sMonospace->renderUTF8(str, 0, left, top, color, LLFontGL::LEFT, LLFontGL::TOP); top = TICK_BOTTOM; diff --git a/linden/indra/newview/llviewerassetstorage.cpp b/linden/indra/newview/llviewerassetstorage.cpp index 72af419..fd92d75 100644 --- a/linden/indra/newview/llviewerassetstorage.cpp +++ b/linden/indra/newview/llviewerassetstorage.cpp @@ -101,7 +101,7 @@ void LLViewerAssetStorage::storeAssetData( // Read the data from the VFS if it'll fit in this packet. if (asset_size + 100 < MTUBYTES) { - BOOL res = vfile.read(buffer, asset_size); + BOOL res = vfile.read(buffer, asset_size); /* Flawfinder: ignore */ S32 bytes_read = res ? vfile.getLastBytesRead() : 0; if( bytes_read == asset_size ) @@ -162,6 +162,11 @@ void LLViewerAssetStorage::storeAssetData( bool temp_file, bool is_priority) { + if(!filename) + { + llerrs << "No filename specified" << llendl; + } + LLAssetID asset_id = tid.makeAssetID(gAgent.getSecureSessionID()); llinfos << "LLViewerAssetStorage::storeAssetData (legacy)" << asset_id << ":" << LLAssetType::lookup(asset_type) << llendl; @@ -172,7 +177,7 @@ void LLViewerAssetStorage::storeAssetData( legacy->mUpCallback = callback; legacy->mUserData = user_data; - FILE *fp = LLFile::fopen(filename, "rb"); + FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ if (fp) { LLVFile file(mVFS, asset_id, asset_type, LLVFile::WRITE); diff --git a/linden/indra/newview/llviewercamera.cpp b/linden/indra/newview/llviewercamera.cpp index 62fa0ef..598046a 100644 --- a/linden/indra/newview/llviewercamera.cpp +++ b/linden/indra/newview/llviewercamera.cpp @@ -138,7 +138,8 @@ void LLViewerCamera::calcProjection(const F32 far_distance) const LLMatrix4 gProjectionMat; -void LLViewerCamera::updateFrustumPlanes() +//static +void LLViewerCamera::updateFrustumPlanes(LLCamera& camera, BOOL ortho) { GLint viewport[4]; GLdouble model[16]; @@ -159,23 +160,26 @@ void LLViewerCamera::updateFrustumPlanes() frust[2].setVec((F32)objX,(F32)objY,(F32)objZ); gluUnProject(viewport[0],viewport[1]+viewport[3],0,model,proj,viewport,&objX,&objY,&objZ); frust[3].setVec((F32)objX,(F32)objY,(F32)objZ); - /*gluUnProject(viewport[0],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[4].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1],1,model,proj,viewport,&objX,&objY,&objZ); - frust[5].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0]+viewport[2],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[6].setVec((F32)objX,(F32)objY,(F32)objZ); - gluUnProject(viewport[0],viewport[1]+viewport[3],1,model,proj,viewport,&objX,&objY,&objZ); - frust[7].setVec((F32)objX,(F32)objY,(F32)objZ);*/ - for (U32 i = 0; i < 4; i++) + if (ortho) { - LLVector3 vec = frust[i] - getOrigin(); - vec.normVec(); - frust[i+4] = getOrigin() + vec*getFar()*2.0; + LLVector3 far_shift = LLVector3(camera.getFar()*2.0f,0,0); + for (U32 i = 0; i < 4; i++) + { + frust[i+4] = frust[i] + far_shift; + } + } + else + { + for (U32 i = 0; i < 4; i++) + { + LLVector3 vec = frust[i] - camera.getOrigin(); + vec.normVec(); + frust[i+4] = camera.getOrigin() + vec*camera.getFar()*2.0f; + } } - calcAgentFrustumPlanes(frust); + camera.calcAgentFrustumPlanes(frust); } void LLViewerCamera::setPerspective(BOOL for_selection, @@ -274,7 +278,7 @@ void LLViewerCamera::setPerspective(BOOL for_selection, glGetIntegerv(GL_VIEWPORT, (GLint*)gGLViewport); } - updateFrustumPlanes(); + updateFrustumPlanes(*this); if (gSavedSettings.getBOOL("CameraOffset")) { @@ -602,22 +606,34 @@ BOOL LLViewerCamera::areVertsVisible(LLViewerObject* volumep, BOOL all_verts) return FALSE; } - num_faces = drawablep->getNumFaces(); + LLVolume* volume = volumep->getVolume(); + if (!volume) + { + return FALSE; + } + + LLVOVolume* vo_volume = (LLVOVolume*) volumep; + + vo_volume->updateRelativeXform(); + LLMatrix4 mat = vo_volume->getRelativeXform(); + + LLMatrix4 render_mat(vo_volume->getRenderRotation(), LLVector4(vo_volume->getRenderPosition())); + + num_faces = volume->getNumFaces(); for (i = 0; i < num_faces; i++) { - LLStrider vertices; - LLFace* face = drawablep->getFace(i); - face->getVertices(vertices); - - for (S32 v = 0; v < (S32)drawablep->getFace(i)->getGeomCount(); v++) + const LLVolumeFace& face = volume->getVolumeFace(i); + + for (U32 v = 0; v < face.mVertices.size(); v++) { - LLVector3 vec = vertices[v]; - if (!face->isState(LLFace::GLOBAL)) + LLVector4 vec = LLVector4(face.mVertices[v].mPosition) * mat; + + if (drawablep->isActive()) { - vec = vec*face->getRenderMatrix(); + vec = vec * render_mat; } - - BOOL in_frustum = pointInFrustum(vec) > 0; + + BOOL in_frustum = pointInFrustum(LLVector3(vec)) > 0; if ( !in_frustum && all_verts || in_frustum && !all_verts) diff --git a/linden/indra/newview/llviewercamera.h b/linden/indra/newview/llviewercamera.h index 8ea2738..a7e600b 100644 --- a/linden/indra/newview/llviewercamera.h +++ b/linden/indra/newview/llviewercamera.h @@ -55,7 +55,7 @@ public: const LLVector3 &up_direction, const LLVector3 &point_of_interest); - void updateFrustumPlanes(); + static void updateFrustumPlanes(LLCamera& camera, BOOL ortho = FALSE); void setPerspective(BOOL for_selection, S32 x, S32 y_from_bot, S32 width, S32 height, BOOL limit_select_distance, F32 z_near = 0, F32 z_far = 0); const LLMatrix4 &getProjection() const; diff --git a/linden/indra/newview/llviewercontrol.cpp b/linden/indra/newview/llviewercontrol.cpp index 86e58d1..e1aa3ae 100644 --- a/linden/indra/newview/llviewercontrol.cpp +++ b/linden/indra/newview/llviewercontrol.cpp @@ -105,7 +105,7 @@ BOOL LLFloaterSettingsDebug::postBuild() childSetUserData("boolean_combo", this); childSetCommitCallback("color_swatch", onCommitSettings); childSetUserData("color_swatch", this); - + childSetAction("default_btn", onClickDefault, this); mComment = (LLTextEditor*)getChildByName("comment_text"); return TRUE; } @@ -129,7 +129,7 @@ void LLFloaterSettingsDebug::show(void*) gUICtrlFactory->buildFloater(sInstance, "floater_settings_debug.xml"); } - sInstance->open(); + sInstance->open(); /* Flawfinder: ignore */ } //static @@ -217,6 +217,20 @@ void LLFloaterSettingsDebug::onCommitSettings(LLUICtrl* ctrl, void* user_data) } } +// static +void LLFloaterSettingsDebug::onClickDefault(void* user_data) +{ + LLFloaterSettingsDebug* floaterp = (LLFloaterSettingsDebug*)user_data; + LLComboBox* settings_combo = (LLComboBox*)floaterp->getChildByName("settings_combo"); + LLControlBase* controlp = (LLControlBase*)settings_combo->getCurrentUserdata(); + + if (controlp) + { + controlp->resetToDefault(); + floaterp->updateControl(controlp); + } +} + // we've switched controls, or doing per-frame update, so update spinners, etc. void LLFloaterSettingsDebug::updateControl(LLControlBase* controlp) { @@ -440,6 +454,8 @@ void LLFloaterSettingsDebug::updateControl(LLControlBase* controlp) if (!spinner4->hasFocus()) { spinner4->setPrecision(3); + spinner4->setMinValue(0.0); + spinner4->setMaxValue(1.f); spinner4->setValue(clr.mV[VALPHA]); } break; diff --git a/linden/indra/newview/llviewercontrol.h b/linden/indra/newview/llviewercontrol.h index 4be4313..d9a2682 100644 --- a/linden/indra/newview/llviewercontrol.h +++ b/linden/indra/newview/llviewercontrol.h @@ -46,6 +46,7 @@ public: static void show(void*); static void onSettingSelect(LLUICtrl* ctrl, void* user_data); static void onCommitSettings(LLUICtrl* ctrl, void* user_data); + static void onClickDefault(void* user_data); protected: static LLFloaterSettingsDebug* sInstance; @@ -54,6 +55,7 @@ protected: //setting variables are declared in this function void declare_settings(); +void settings_version_fixup(); // saved at end of session extern LLControlGroup gSavedSettings; diff --git a/linden/indra/newview/llviewerdisplay.cpp b/linden/indra/newview/llviewerdisplay.cpp index f09e34c..071b699 100644 --- a/linden/indra/newview/llviewerdisplay.cpp +++ b/linden/indra/newview/llviewerdisplay.cpp @@ -63,6 +63,9 @@ #include "llfloatertools.h" #include "llviewerimagelist.h" #include "llfocusmgr.h" +#include "llcubemap.h" +#include "llviewerregion.h" +#include "lldrawpoolwater.h" extern U32 gFrameCount; extern LLPointer gStartImageGL; @@ -103,8 +106,12 @@ void display_startup() return; } - LLDynamicTexture::updateAllInstances(); - + // Required for HTML update in login screen + static S32 frame_count = 0; + if (frame_count++ > 1) // make sure we have rendered a frame first + { + LLDynamicTexture::updateAllInstances(); + } glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); LLGLSDefault gls_default; LLGLSUIDefault gls_ui; @@ -174,11 +181,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) // Clean up memory the pools may have allocated if (rebuild) { - if (!gViewerWindow->renderingFastFrame()) - { - gFrameStats.start(LLFrameStats::REBUILD); - gPipeline.rebuildPools(); - } + gFrameStats.start(LLFrameStats::REBUILD); + gPipeline.rebuildPools(); } return; } @@ -378,14 +382,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) } } - if (rebuild) - { - if (gViewerWindow->renderingFastFrame()) - { - gFrameStats.start(LLFrameStats::STATE_SORT); - gFrameStats.start(LLFrameStats::REBUILD); - } - } ///////////////////////////// // @@ -394,6 +390,7 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) // gCamera->setZoomParameters(zoom_factor, subfield); + gCamera->setNear(MIN_NEAR_PLANE); ////////////////////////// // @@ -409,6 +406,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) else if (!gViewerWindow->isPickPending()) { glClear( GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT ); + //DEBUG TEMPORARY + glClear(GL_COLOR_BUFFER_BIT); } gViewerWindow->setupViewport(); @@ -429,7 +428,13 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) glClearColor(0.5f, 0.5f, 0.5f, 0.f); glClear(GL_COLOR_BUFFER_BIT); glPolygonMode(GL_FRONT_AND_BACK, GL_LINE); + LLPipeline::sUseOcclusion = FALSE; } + else + { + LLPipeline::sUseOcclusion = gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery; + } + stop_glerror(); /////////////////////////////////////// @@ -442,7 +447,8 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) glLightModelfv (GL_LIGHT_MODEL_AMBIENT,one); stop_glerror(); - //LLGLState::verify(); + //Increment drawable frame counter + LLDrawable::incrementVisible(); ///////////////////////////////////// // @@ -452,6 +458,11 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) // if (!gDisconnected) { + if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { //don't draw hud objects in this frame + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + } + LLFastTimer t(LLFastTimer::FTM_WORLD_UPDATE); stop_glerror(); display_update_camera(); @@ -467,34 +478,41 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) gPipeline.updateGeom(max_geom_update_time); stop_glerror(); + LLSpatialPartition* part = gPipeline.getSpatialPartition(LLPipeline::PARTITION_VOLUME); + part->processImagery(gCamera); + + display_update_camera(); + gFrameStats.start(LLFrameStats::UPDATE_CULL); - gPipeline.updateCull(); + gPipeline.updateCull(*gCamera); stop_glerror(); - if (rebuild && !gViewerWindow->renderingFastFrame()) + /////////////////////////////////// + // + // StateSort + // + // Responsible for taking visible objects, and adding them to the appropriate draw orders. + // In the case of alpha objects, z-sorts them first. + // Also creates special lists for outlines and selected face rendering. + // { LLFastTimer t(LLFastTimer::FTM_REBUILD); - - /////////////////////////////////// - // - // StateSort - // - // Responsible for taking visible objects, and adding them to the appropriate draw orders. - // In the case of alpha objects, z-sorts them first. - // Also creates special lists for outlines and selected face rendering. - // - gFrameStats.start(LLFrameStats::STATE_SORT); - gPipeline.stateSort(); - stop_glerror(); - ////////////////////////////////////// - // - // rebuildPools - // - // - gFrameStats.start(LLFrameStats::REBUILD); - gPipeline.rebuildPools(); + gFrameStats.start(LLFrameStats::STATE_SORT); + gPipeline.stateSort(*gCamera); stop_glerror(); + + if (rebuild) + { + ////////////////////////////////////// + // + // rebuildPools + // + // + gFrameStats.start(LLFrameStats::REBUILD); + gPipeline.rebuildPools(); + stop_glerror(); + } } } @@ -535,19 +553,74 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) // glPopMatrix(); //} - if (gViewerWindow->renderingFastFrame()) - { - gFrameStats.start(LLFrameStats::RENDER_SYNC); - gFrameStats.start(LLFrameStats::RENDER_GEOM); - } - else if (!(gLogoutRequestSent && gHaveSavedSnapshot) + if (!(gLogoutRequestSent && gHaveSavedSnapshot) && !gRestoreGL && !gDisconnected) { - gPipeline.renderGeom(); + gPipeline.renderGeom(*gCamera); stop_glerror(); } + //render hud attachments + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + if (LLPipeline::sShowHUDAttachments && !gDisconnected && setup_hud_matrices(FALSE)) + { + LLCamera hud_cam = *gCamera; + glClear(GL_DEPTH_BUFFER_BIT); + LLVector3 origin = hud_cam.getOrigin(); + hud_cam.setOrigin(-1.f,0,0); + hud_cam.setAxes(LLVector3(1,0,0), LLVector3(0,1,0), LLVector3(0,0,1)); + LLViewerCamera::updateFrustumPlanes(hud_cam, TRUE); + //only render hud objects + U32 mask = gPipeline.getRenderTypeMask(); + gPipeline.setRenderTypeMask(0); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_HUD); + + BOOL has_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); + if (has_ui) + { + gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + BOOL use_occlusion = gSavedSettings.getBOOL("UseOcclusion"); + gSavedSettings.setBOOL("UseOcclusion", FALSE); + + //cull, sort, and render hud objects + gPipeline.updateCull(hud_cam); + + gPipeline.toggleRenderType(LLDrawPool::POOL_ALPHA_POST_WATER); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_BUMP); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_SIMPLE); + gPipeline.toggleRenderType(LLPipeline::RENDER_TYPE_VOLUME); + + { + LLFastTimer ftm(LLFastTimer::FTM_REBUILD); + gPipeline.stateSort(hud_cam); + } + + if (LLVertexBuffer::sEnableVBOs) + { + LLImageGL::sBoundTextureMemory += LLVertexBuffer::sAllocatedBytes; + } + + gPipeline.renderGeom(hud_cam); + + //restore type mask + gPipeline.setRenderTypeMask(mask); + if (has_ui) + { + gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + gSavedSettings.setBOOL("UseOcclusion", use_occlusion); + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + gFrameStats.start(LLFrameStats::RENDER_UI); if (gHandleKeysAsync) @@ -570,6 +643,64 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield) } +BOOL setup_hud_matrices(BOOL for_select) +{ + LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); + if (my_avatarp && my_avatarp->hasHUDAttachment()) + { + if (!for_select) + { + // clamp target zoom level to reasonable values + my_avatarp->mHUDTargetZoom = llclamp(my_avatarp->mHUDTargetZoom, 0.1f, 1.f); + // smoothly interpolate current zoom level + my_avatarp->mHUDCurZoom = lerp(my_avatarp->mHUDCurZoom, my_avatarp->mHUDTargetZoom, LLCriticalDamp::getInterpolant(0.03f)); + } + + F32 zoom_level = my_avatarp->mHUDCurZoom; + // clear z buffer and set up transform for hud + if (!for_select) + { + glClear(GL_DEPTH_BUFFER_BIT); + } + LLBBox hud_bbox = my_avatarp->getHUDBBox(); + + // set up transform to encompass bounding box of HUD + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + F32 hud_depth = llmax(1.f, hud_bbox.getExtentLocal().mV[VX] * 1.1f); + if (for_select) + { + //RN: reset viewport to window extents so ortho screen is calculated with proper reference frame + gViewerWindow->setupViewport(); + } + glOrtho(-0.5f * gCamera->getAspect(), 0.5f * gCamera->getAspect(), -0.5f, 0.5f, 0.f, hud_depth); + + // apply camera zoom transform (for high res screenshots) + F32 zoom_factor = gCamera->getZoomFactor(); + S16 sub_region = gCamera->getZoomSubRegion(); + if (zoom_factor > 1.f) + { + float offset = zoom_factor - 1.f; + int pos_y = sub_region / llceil(zoom_factor); + int pos_x = sub_region - (pos_y*llceil(zoom_factor)); + glTranslatef(gCamera->getAspect() * 0.5f * (offset - (F32)pos_x * 2.f), 0.5f * (offset - (F32)pos_y * 2.f), 0.f); + glScalef(zoom_factor, zoom_factor, 1.f); + } + + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + glLoadMatrixf(OGL_TO_CFR_ROTATION); // Load Cory's favorite reference frame + glTranslatef(-hud_bbox.getCenterLocal().mV[VX] + (hud_depth * 0.5f), 0.f, 0.f); + glScalef(zoom_level, zoom_level, zoom_level); + + return TRUE; + } + else + { + return FALSE; + } +} + void render_ui_and_swap() { @@ -581,11 +712,11 @@ void render_ui_and_swap() { LLGLSUIDefault gls_ui; gPipeline.disableLights(); - + LLVertexBuffer::startRender(); if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { LLFastTimer t(LLFastTimer::FTM_RENDER_UI); - if (!gViewerWindow->renderingFastFrame() && !gDisconnected) + if (!gDisconnected) { render_ui_3d(); #ifndef LL_RELEASE_FOR_DOWNLOAD @@ -598,6 +729,8 @@ void render_ui_and_swap() LLGLState::checkStates(); #endif } + LLVertexBuffer::stopRender(); + glFlush(); // now do the swap buffer if (gDisplaySwapBuffers) @@ -605,9 +738,13 @@ void render_ui_and_swap() LLFastTimer t(LLFastTimer::FTM_SWAP); gViewerWindow->mWindow->swapBuffers(); } - } - gViewerWindow->finishFirstFastFrame(); + { + LLFastTimer ftm(LLFastTimer::FTM_CLIENT_COPY); + LLVertexBuffer::clientCopy(0.016); + } + + } } void render_ui_3d() @@ -622,8 +759,6 @@ void render_ui_3d() // // Render selections - - glDisableClientState(GL_VERTEX_ARRAY); glDisableClientState(GL_COLOR_ARRAY); glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); @@ -680,7 +815,6 @@ void render_ui_2d() LLFontGL::sCurOrigin.mY -= llround((F32)gViewerWindow->getWindowHeight() * (F32)pos_y / zoom_factor); } - stop_glerror(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); @@ -781,11 +915,12 @@ void render_disconnected_background() { llinfos << "Loading last bitmap..." << llendl; - char temp_str[MAX_PATH]; - strcpy(temp_str, gDirUtilp->getLindenUserDir().c_str()); - strcat(temp_str, gDirUtilp->getDirDelimiter().c_str()); + char temp_str[MAX_PATH]; /* Flawfinder: ignore */ + strncpy(temp_str, gDirUtilp->getLindenUserDir().c_str(), MAX_PATH -1); /* Flawfinder: ignore */ + temp_str[MAX_PATH -1] = '\0'; + strncat(temp_str, gDirUtilp->getDirDelimiter().c_str(), MAX_PATH - strlen(temp_str) -1); /* Flawfinder: ignore */ - strcat(temp_str, SCREEN_LAST_FILENAME); + strcat(temp_str, SCREEN_LAST_FILENAME); /* Flawfinder: ignore */ LLPointer image_bmp = new LLImageBMP; if( !image_bmp->load(temp_str) ) diff --git a/linden/indra/newview/llviewergesture.cpp b/linden/indra/newview/llviewergesture.cpp index d4201c0..fd98070 100644 --- a/linden/indra/newview/llviewergesture.cpp +++ b/linden/indra/newview/llviewergesture.cpp @@ -156,18 +156,18 @@ void LLViewerGestureList::saveToServer() //U64 xfer_id = gXferManager->registerXfer(buffer, end - buffer); // write to a file because mem<->mem xfer isn't implemented LLUUID random_uuid; - char filename[LL_MAX_PATH]; + char filename[LL_MAX_PATH]; /* Flawfinder: ignore */ random_uuid.generate(); random_uuid.toString(filename); - strcat(filename,".tmp"); + strcat(filename,".tmp"); /* Flawfinder: ignore */ - char filename_and_path[LL_MAX_PATH]; - sprintf(filename_and_path, "%s%s%s", + char filename_and_path[LL_MAX_PATH]; /* Flawfinder: ignore */ + snprintf(filename_and_path, LL_MAX_PATH, "%s%s%s", /* Flawfinder: ignore */ gDirUtilp->getTempDir().c_str(), gDirUtilp->getDirDelimiter().c_str(), filename); - FILE *fp = LLFile::fopen(filename_and_path, "wb"); + FILE* fp = LLFile::fopen(filename_and_path, "wb"); /* Flawfinder: ignore */ if (fp) { @@ -270,7 +270,7 @@ void LLViewerGestureList::xferCallback(void *data, S32 size, void** /*user_data* // static void LLViewerGestureList::processGestureUpdate(LLMessageSystem *msg, void** /*user_data*/) { - char remote_filename[MAX_STRING]; + char remote_filename[MAX_STRING]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_AgentBlock, _PREHASH_Filename, MAX_STRING, remote_filename); diff --git a/linden/indra/newview/llviewerimage.cpp b/linden/indra/newview/llviewerimage.cpp index 7500ada..5a745ae 100644 --- a/linden/indra/newview/llviewerimage.cpp +++ b/linden/indra/newview/llviewerimage.cpp @@ -34,11 +34,13 @@ #include "llmath.h" #include "llerror.h" #include "llgl.h" +#include "llglheaders.h" #include "llhost.h" #include "llimage.h" #include "llimagebmp.h" #include "llimagej2c.h" #include "llimagetga.h" +#include "llmemtype.h" #include "llstl.h" #include "lltexturetable.h" #include "llvfile.h" @@ -47,41 +49,12 @@ #include "lltimer.h" // viewer includes +#include "lldrawpool.h" +#include "lltexturefetch.h" #include "llviewerimagelist.h" #include "llviewercontrol.h" -#include "viewer.h" -#include "llglheaders.h" #include "pipeline.h" -#include "lldrawpool.h" - -const S32 IMAGE_HEADER_SIZE = 27; -const S32 PACKET_HEADER_SIZE = 4; - -/////////////////////////////////////////////////////////////////////////////// - -class LLViewerImagePacket -{ -public: - LLViewerImagePacket(U8 *data, U16 data_size, U16 packet_num, BOOL wrote_to_disk) - { - mData = data; - mDataSize = data_size; - mPacketNum = packet_num; - mWroteToDisk = wrote_to_disk; - } - - ~LLViewerImagePacket() - { - delete[] mData; - } - -public: - U8 *mData; - U16 mDataSize; - U16 mPacketNum; - BOOL mWroteToDisk; -}; - +#include "viewer.h" /////////////////////////////////////////////////////////////////////////////// @@ -95,6 +68,8 @@ LLPointer LLViewerImage::sNullImagep = NULL; S32 LLViewerImage::sImageCount = 0; LLTimer LLViewerImage::sEvaluationTimer; F32 LLViewerImage::sDesiredDiscardBias = 0.f; +static F32 sDesiredDiscardBiasMin = -2.0f; // -max number of levels to improve image quality by +static F32 sDesiredDiscardBiasMax = 1.5f; // max number of levels to reduce image quality by F32 LLViewerImage::sDesiredDiscardScale = 1.1f; S32 LLViewerImage::sBoundTextureMemory = 0; S32 LLViewerImage::sTotalTextureMemory = 0; @@ -109,6 +84,43 @@ void LLViewerImage::initClass() LLPointer raw = new LLImageRaw(1,1,3); raw->clear(0x77, 0x77, 0x77, 0xFF); sNullImagep->createGLTexture(0, raw); + +#if 1 + LLViewerImage* imagep = new LLViewerImage(IMG_DEFAULT, TRUE); + sDefaultImagep = imagep; + const S32 dim = 128; + LLPointer image_raw = new LLImageRaw(dim,dim,3); + U8* data = image_raw->getData(); + for (S32 i = 0; i=(dim-border) || j>=(dim-border)) + { + *data++ = 0xff; + *data++ = 0xff; + *data++ = 0xff; + } + else +#endif + { + *data++ = 0x7f; + *data++ = 0x7f; + *data++ = 0x7f; + } + } + } + imagep->createGLTexture(0, image_raw); + image_raw = NULL; + gImageList.addImage(imagep); + imagep->dontDiscard(); +#else + sDefaultImagep = gImageList.getImage(IMG_DEFAULT, TRUE, TRUE); +#endif + sSmokeImagep = gImageList.getImage(IMG_SMOKE, TRUE, TRUE); + } // static @@ -171,6 +183,7 @@ void LLViewerImage::updateClass(const F32 velocity, const F32 angular_velocity) sEvaluationTimer.reset(); } } + sDesiredDiscardBias = llclamp(sDesiredDiscardBias, sDesiredDiscardBiasMin, sDesiredDiscardBiasMax); } //---------------------------------------------------------------------------- @@ -209,35 +222,20 @@ LLViewerImage::LLViewerImage(const LLImageRaw* raw, BOOL usemipmaps) void LLViewerImage::init(bool firstinit) { - mDataCodec = 0; mFullWidth = 0; mFullHeight = 0; - mFormattedImagep = NULL; mNeedsAux = FALSE; - mRequested = FALSE; - mNeedsDecode = FALSE; mTexelsPerImage = 64.f*64.f; mMaxVirtualSize = 0.f; + mDiscardVirtualSize = 0.f; mMaxCosAngle = -1.f; mRequestedDiscardLevel = -1; mRequestedDownloadPriority = 0.f; - mPackets = 0; - mGotFirstPacket = FALSE; - mPacketsReceived = 0; mFullyLoaded = FALSE; mDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; mMinDesiredDiscardLevel = MAX_DISCARD_LEVEL + 1; - mStreamFile = NULL; - mCachedData = NULL; - mCachedSize = 0; - mFormattedFlushed = FALSE; - mTotalBytes = 0; - - resetPacketData(); + mCalculatedDiscardLevel = -1.f; - mLastPacketProcessed = -1; - mLastBytesProcessed = 0; - mLastPacket = -1; mDecodingAux = FALSE; mKnownDrawWidth = 0; @@ -247,7 +245,6 @@ void LLViewerImage::init(bool firstinit) { mDecodePriority = 0.f; mInImageList = 0; - mInStaticVFS = FALSE; } mIsMediaTexture = FALSE; @@ -261,9 +258,18 @@ void LLViewerImage::init(bool firstinit) mIsRawImageValid = FALSE; mRawDiscardLevel = INVALID_DISCARD_LEVEL; - mRawImage = NULL; + mMinDiscardLevel = 0; mTargetHost = LLHost::invalid; + + mHasFetcher = FALSE; + mIsFetching = FALSE; + mFetchState = 0; + mFetchPriority = 0; + mDownloadProgress = 0.f; + mFetchDeltaTime = 999999.f; + mDecodeFrame = 0; + mVisibleFrame = 0; } // virtual @@ -283,6 +289,10 @@ void LLViewerImage::dump() LLViewerImage::~LLViewerImage() { + if (mHasFetcher) + { + gTextureFetch->deleteRequest(getID(), true); + } // Explicitly call LLViewerImage::cleanup since we're in a destructor and cleanup is virtual LLViewerImage::cleanup(); sImageCount--; @@ -304,27 +314,9 @@ void LLViewerImage::cleanup() } mLoadedCallbackList.clear(); - // Clean up any remaining packet data. - std::for_each(mReceivedPacketMap.begin(), mReceivedPacketMap.end(), DeletePairedPointer()); - mReceivedPacketMap.clear(); - - // Clean up the streaming file - if (mStreamFile && !mStreamFile->isReadComplete()) - { -// llwarns << "Destroying LLViewerImage stream file while still reading data!" << llendl; - } - delete mStreamFile; - mStreamFile = NULL; - // Clean up image data - setFormattedImage(NULL); - mRawImage = NULL; - mIsRawImageValid = FALSE; - mAuxRawImage = NULL; + destroyRawImage(); - delete[] mCachedData; - mCachedData = NULL; - // LLImageGL::cleanup will get called more than once when this is used in the destructor. LLImageGL::cleanup(); } @@ -335,128 +327,25 @@ void LLViewerImage::reinit(BOOL usemipmaps /* = TRUE */) LLImageGL::init(usemipmaps); init(false); setSize(0,0,0); - if (mInStaticVFS) - { - mFormattedFlushed = TRUE; - } } /////////////////////////////////////////////////////////////////////////////// -void LLViewerImage::setFormattedImage(LLImageFormatted* imagep) -{ - mFormattedImagep = NULL; // deletes image - mFormattedImagep = imagep; - if (mFormattedImagep.notNull()) - { - mFormattedImagep->mMemType = LLMemType::MTYPE_APPFMTIMAGE; - mFormattedFlushed = FALSE; - } - else - { - setNeedsDecode(FALSE); - } -} - -BOOL LLViewerImage::loadLocalImage(const LLUUID &image_id) -{ - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - - // first look for this image in the static VFS - LLAssetType::EType asset_type = LLAssetType::AT_NONE; - // Try TGA first - if (gStaticVFS->getExists(image_id, LLAssetType::AT_TEXTURE_TGA)) - { - asset_type = LLAssetType::AT_TEXTURE_TGA; - //RN: force disable discards for TGA files because they can't decode at different quality levels - dontDiscard(); - mDataCodec = IMG_CODEC_TGA; - } - else if (gStaticVFS->getExists(image_id, LLAssetType::AT_TEXTURE)) - { - // then try for a J2C version - asset_type = LLAssetType::AT_TEXTURE; - mDataCodec = IMG_CODEC_J2C; - LLImageJ2C* imagej2c = new LLImageJ2C(); - setFormattedImage(imagej2c); - } - - if (asset_type != LLAssetType::AT_NONE) - { - S32 size = gStaticVFS->getSize(image_id, asset_type); - U8* buffer = new U8[size]; - BOOL success = LLVFSThread::sLocal->readImmediate(gStaticVFS, image_id, asset_type, buffer, 0, size); - - if (!success) - { - llwarns << "loadLocalImage() - vfs read failed" << llendl; - return FALSE; - } - - mInStaticVFS = TRUE; - mFullyLoaded = TRUE; - setNeedsDecode(TRUE); // Loading a local image - mID = image_id; - setDecodeData(buffer, size); - mTotalBytes = size; - mLastBytesProcessed = size; - return TRUE; - } - - return FALSE; -} - -BOOL LLViewerImage::startVFSLoad() -{ - // We're no longer considered "flushed" no matter what happens after here. - mFormattedFlushed = FALSE; - if (!mStreamFile && mFormattedImagep.isNull()) - { - // Start load from VFS if it's there - if (gVFS->getExists(mID, LLAssetType::AT_TEXTURE)) - { -// llinfos << "Reading image from disk " << getID() << llendl; - - //llinfos << mID << ": starting VFS load" << llendl; - mStreamFile = new LLVFile(gVFS, mID, LLAssetType::AT_TEXTURE, LLVFile::READ_WRITE); - mCachedSize = 0; - gImageList.mLoadingStreamList.push_back(this); - } - else - { - return loadLocalImage(mID); - } - } - return TRUE; -} - -void LLViewerImage::startImageDecode() -{ - // We need to load and/or decode the image - if (mFormattedImagep.isNull()) - { - startVFSLoad(); // Start the VFS loading - } - else - { - setNeedsDecode(TRUE); // Force a new decode of this texture - } -} - - +// ONLY called from LLViewerImageList BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) { - if (mFormattedImagep.notNull() && mFormattedImagep->isDecoding()) + if (!mNeedsCreateTexture) { - llerrs << "Trying to create texture on an image that is currently being decoded: " << mID << llendl; + destroyRawImage(); + return FALSE; } mNeedsCreateTexture = FALSE; if (mRawImage.isNull()) { llerrs << "LLViewerImage trying to create texture with no Raw Image" << llendl; } -// llinfos << llformat("IMAGE Creating (%d,%d) [%d x %d] Bytes: %d ", -// mRawDiscardLevel, mFormattedImagep ? mFormattedImagep->getDiscardLevel() : -1, +// llinfos << llformat("IMAGE Creating (%d) [%d x %d] Bytes: %d ", +// mRawDiscardLevel, // mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize()) // << mID.getString() << llendl; BOOL res = TRUE; @@ -471,7 +360,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) // A non power-of-two image was uploaded (through a non standard client) // We treat these images as missing assets which causes them to // be renderd as 'missing image' and to stop requesting data - setIsMissingAsset(TRUE); + setIsMissingAsset(); destroyRawImage(); return FALSE; } @@ -481,6 +370,7 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) // Iterate through the list of image loading callbacks to see // what sort of data they need. // + // *TODO: Fix image callback code BOOL imageraw_callbacks = FALSE; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) @@ -500,292 +390,6 @@ BOOL LLViewerImage::createTexture(S32 usename/*= 0*/) return res; } -BOOL LLViewerImage::destroyTexture() -{ - LLImageGL::destroyGLTexture(); - return TRUE; -} - -void LLViewerImage::resetPacketData() -{ - //llinfos << "resetting packet data for " << getID() << llendl; - mPackets = 0; - mLastPacket = -1; - mPacketsReceived = 0; - mGotFirstPacket = FALSE; - mRequested = FALSE; - - std::for_each(mReceivedPacketMap.begin(), mReceivedPacketMap.end(), DeletePairedPointer()); - mReceivedPacketMap.clear(); - mLastPacketProcessed = -1; -} - -//////////////////////////////////////////////////////////////////////////////// -// This sets up a new formatted image at the requested size, and sets the decode flag -void LLViewerImage::setDecodeData(U8 * data, U32 size) -{ - if (size == mTotalBytes) - { - mFullyLoaded = TRUE; - } - if (mDataCodec == IMG_CODEC_J2C) - { - //Codec 2 = compressed with JPEG2000 (Wavelet) - // Create formatted image first, then use it to generate the - // raw image. - if (mFormattedImagep.isNull()) - { - LLPointer j2cp = new LLImageJ2C(); - setFormattedImage(j2cp); - } - BOOL res = mFormattedImagep->setData(data, size); - if (mFullyLoaded) - { - mFormattedImagep->setDiscardLevel(0); // Force full res if all data is loaded - } - if ((mFormattedImagep->getWidth() > MAX_IMAGE_SIZE_DEFAULT || - mFormattedImagep->getHeight() > MAX_IMAGE_SIZE_DEFAULT) && - (mFormattedImagep->getDiscardLevel() == 0)) - { - mFormattedImagep->setDiscardLevel(1); // Force x2048 images to x1024 - } - - if( res ) - { - if (mFormattedImagep->getComponents() > 4) - { - mNeedsAux = TRUE; - } - else - { - mNeedsAux = FALSE; - } - mFullWidth = mFormattedImagep->getWidth(); - mFullHeight = mFormattedImagep->getHeight(); - if ((mFullWidth == 0) || (mFullHeight == 0)) - { - llwarns << "Zero size width/height!" << llendl; - } - setNeedsDecode(TRUE); // Setting new formatted data - } - else - { - llwarns << "Unable to setData() for image " << mID << " Aborting." << llendl; - abortDecode(); - } - } - else if (mDataCodec == IMG_CODEC_TGA) - { - //Codec 4 = compressed with TGA - // Create formatted image first, then use it to generate the - // raw image. - if (mFormattedImagep.isNull()) - { - LLPointer tgap = new LLImageTGA(); - setFormattedImage(tgap); - } - BOOL res = mFormattedImagep->setData(data, size); - - if( res ) - { - mFullWidth = mFormattedImagep->getWidth(); - mFullHeight = mFormattedImagep->getHeight(); - if ((mFullWidth == 0) || (mFullHeight == 0)) - { - llwarns << "Zero size width/height!" << llendl; - } - setNeedsDecode(TRUE); // Setting new formatted data - } - else - { - llwarns << "Unable to setData() for image " << mID << " Aborting." << llendl; - abortDecode(); - } - } - else - { - llerrs << "Image " << mID << ": Unknown codec " << (int)mDataCodec << llendl; - setNeedsDecode(FALSE); // Unknown codec - } -} - -void LLViewerImage::decodeImage(const F32 decode_time) -{ - if (!needsDecode()) - { - return; - } - - if (mFormattedImagep.isNull()) - { - llerrs << "Decoding image without formatted data!" << llendl; - return; - } - - // - // Only do a decode if we don't already have an image for this resolution. - // - if (getTexName() != 0 && getDiscardLevel() <= mFormattedImagep->getDiscardLevel() - && !mNeedsAux) - { - // We already have an image this size or larger - setNeedsDecode(FALSE); - return; - } - - // Partial Decode of J2C images: - // If this is the first time we are decoding an image, - // make sure we limit the amount of data we decode in order not to stall other decodes - if (!mFormattedImagep->isDecoding() && mFormattedImagep->getCodec() == IMG_CODEC_J2C) - { - LLImageJ2C* j2cp = (LLImageJ2C*)((LLImageFormatted*)mFormattedImagep); - const S32 INITIAL_DECODE_SIZE = 2048; - if (!mDontDiscard && - getUseMipMaps() && - !mNeedsAux && - getDiscardLevel() < 0 && - mFormattedImagep->getDataSize() > INITIAL_DECODE_SIZE * 2) - { - j2cp->setMaxBytes(INITIAL_DECODE_SIZE); - } - else - { - j2cp->setMaxBytes(0); // In case we set it on a previous decode - } - } - - // - // Decode Image - // - mLastDecodeTime.reset(); - - if (mFormattedImagep->getCodec() == 0) - { - llerrs << "LLViewerImage::decodeImage: mFormattedImagep->getCodec() == 0" << llendl; - } - - // - // Decode first 4 channels - // - // Skip over this if we're already in the process of decoding the aux channel, - // that means that we've alredy decoded the base channels of this texture. - if (!mDecodingAux) - { - if (!mFormattedImagep->isDecoding()) - { - mNeedsCreateTexture = FALSE; // Raw is no longer valid - destroyRawImage(); - createRawImage(mFormattedImagep->getDiscardLevel()); - //llinfos << "starting decode at " << (S32)mFormattedImagep->getDiscardLevel() << " for " << getID() << llendl; - } - else - { - llassert(mRawImage.notNull()); - } - if (!mFormattedImagep->decode(mRawImage, decode_time, 0, 4)) - { - if (!mFormattedImagep->isDecoding()) - { - // bogus data, delete and try again - llwarns << "Failed to decode " << mID << ":" << gTextureTable.getName(mID) << llendl; - abortDecode(); - destroyRawImage(); - return; - } - } -// llinfos << llformat("IMAGE Decode (%d) ", mFormattedImagep->getDiscardLevel()) << mID << llendl; - - // Get the discard level of the decoded raw image, - // which may not match the formatted image discard level if a partial decode was done - mRawDiscardLevel = mFormattedImagep->getRawDiscardLevel(); - - if (mFormattedImagep->isDecoding()) - { - return; // Not done decoding. - } - } - - // - // If we've finished with the main channels and need to decode the aux, do it now. - // Aux buffers contain extra data (e.g. cloth maps) - // - if (mNeedsAux) - { - mDecodingAux = TRUE; - - // Create the target raw image for the aux channels - if (mAuxRawImage.isNull()) - { - S32 discard = mFormattedImagep->getDiscardLevel(); - mAuxRawImage = new LLImageRaw(getWidth(discard), getHeight(discard), 1); - mAuxRawImage->mMemType = LLMemType::MTYPE_APPAUXRAWIMAGE; - } - - if (!mFormattedImagep->decode(mAuxRawImage, decode_time, 4, 4)) - { - if (!mFormattedImagep->isDecoding()) - { - llwarns << "Failed to decode high components " << mID << ":" << gTextureTable.getName(mID) << llendl; - abortDecode(); - destroyRawImage(); - return; // decode failed; re-request - } - } - - if (mFormattedImagep->isDecoding()) - { - return; // Not done decoding. - } - - mDecodingAux = FALSE; - } - - if (mRawImage.notNull() && getComponents() != mRawImage->getComponents()) - { - // - // We've changed the number of components (presumably this is after - // decoding the first packet of an image), so we need to move any - // objects using this pool to a different pool. - // - mComponents = mRawImage->getComponents(); - gPipeline.dirtyPoolObjectTextures(this); - } - - // - // We've decoded this image, and no longer need to. - // - setNeedsDecode(FALSE); // Done decoding image - mIsRawImageValid = TRUE; - - // - // We have a raw image, and now we need to push the data - // from the raw image into the GL image - // - llassert(mRawImage.notNull()); - mNeedsCreateTexture = TRUE; - - // Everything's OK... -#if LL_DEBUG - lldebugst(LLERR_IMAGE) << "Img: "; - std::string tex_name = gTextureTable.getName(mID); - if (!tex_name.empty()) - { - llcont << tex_name; - } - else - { - llcont << mID; - } - llcont << " Discard level " << (S32)getDiscardLevel(); - llcont << llendl; -#endif -} - -bool LLViewerImage::isDecoding() -{ - return (mFormattedImagep.notNull() && mFormattedImagep->isDecoding()); -} - //============================================================================ void LLViewerImage::addTextureStats(F32 pixel_area, @@ -868,15 +472,23 @@ void LLViewerImage::processTextureStats() } else { - // Guess the required scale factor of the image using pixels per texel.. - // Right now, use a safe 1:1 for the tradeoff - we can adjust this later. - // Actually, it might be nice to generate a float, so we can prioritize which - // ones we can discard quality levels from. - discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); + if ((mCalculatedDiscardLevel >= 0.f) && + (llabs(mMaxVirtualSize - mDiscardVirtualSize) < mMaxVirtualSize*.20f)) + { + // < 20% change in virtual size = no change in desired discard + discard_level = mCalculatedDiscardLevel; + } + else + { + // Calculate the required scale factor of the image using pixels per texel + discard_level = (F32)(log(mTexelsPerImage/mMaxVirtualSize) / log_4); + mDiscardVirtualSize = mMaxVirtualSize; + mCalculatedDiscardLevel = discard_level; + } } if (mBoostLevel < LLViewerImage::BOOST_HIGH) { - static const F32 discard_bias = 0.5f; // Must be < 1 or highest discard will never load! + static const F32 discard_bias = -.5f; // Must be < 1 or highest discard will never load! discard_level += discard_bias; discard_level += sDesiredDiscardBias; discard_level *= sDesiredDiscardScale; // scale @@ -901,145 +513,142 @@ void LLViewerImage::processTextureStats() // proper action if we don't. // - // - // Only need to do an actual decode if we don't have the right GL level, - // or we don't have raw data and need raw data. - // BOOL increase_discard = FALSE; - if (getDiscardLevel() < 0 || mDesiredDiscardLevel < getDiscardLevel()) + S32 current_discard = getDiscardLevel(); + if ((sDesiredDiscardBias > 0.0f) && + (current_discard >= 0 && mDesiredDiscardLevel >= current_discard)) { - // We need to do a decode of that discard level to get more data. - if (mFormattedImagep.notNull() && !needsDecode()) + if ( sBoundTextureMemory > sMaxBoundTextureMem*texmem_middle_bound_scale) { - if (mFormattedImagep->getDiscardLevel() <= mDesiredDiscardLevel) + // Limit the amount of GL memory bound each frame + if (mDesiredDiscardLevel > current_discard) { - setNeedsDecode(TRUE); // processTextureStats - Changing discard level of texture + increase_discard = TRUE; } - // else let the llviewerimagelist logic do its thing - } - else if (mFormattedFlushed) - { - //llinfos << "Attempting vfs reload (a) of " << mID << llendl; - startVFSLoad(); } - } - else if (sDesiredDiscardBias > 0.0f && sBoundTextureMemory > sMaxBoundTextureMem*texmem_middle_bound_scale) - { - // Limit the amount of GL memory bound each frame - if (mDesiredDiscardLevel > getDiscardLevel()) + if ( sTotalTextureMemory > sMaxTotalTextureMem*texmem_middle_bound_scale) { - increase_discard = TRUE; + // Only allow GL to have 2x the video card memory + if (!getBoundRecently()) + { + increase_discard = TRUE; + } } - } - else if (sDesiredDiscardBias > 0.0f && sTotalTextureMemory > sTotalTextureMemory*texmem_middle_bound_scale) - { - // Only allow GL to have 2x the video card memory - if (!getBoundRecently()) + if (increase_discard) { - increase_discard = TRUE; + // llinfos << "DISCARDED: " << mID << " Discard: " << current_discard << llendl; + sBoundTextureMemory -= mTextureMemory; + sTotalTextureMemory -= mTextureMemory; + // Increase the discard level (reduce the texture res) + S32 new_discard = current_discard+1; + setDiscardLevel(new_discard); + sBoundTextureMemory += mTextureMemory; + sTotalTextureMemory += mTextureMemory; } } - if (increase_discard) - { - sBoundTextureMemory -= mTextureMemory; - sTotalTextureMemory -= mTextureMemory; - // Increase the discard level (reduce the texture res) - S32 new_discard = getDiscardLevel()+1; - setDiscardLevel(new_discard); - sBoundTextureMemory += mTextureMemory; - sTotalTextureMemory += mTextureMemory; - } - } - - // - // Flush the formatted data for this image if it hasn't been used in a while. - // -#if 1 - const F32 FLUSH_TIME = 30.f; - if (mFormattedImagep.notNull()) - { - if ((mLastDecodeTime.getElapsedTimeF32() > FLUSH_TIME) - && !mStreamFile - && (this->mLastPacketTimer.getElapsedTimeF32() > FLUSH_TIME) - && !mNeedsDecode - && !mFormattedImagep->isDecoding() - && (mDesiredDiscardLevel == getDiscardLevel())) - { - //llinfos << mID << ": flushing formatted image, last processed packet " << mLastPacketProcessed << llendl; - // Treat this very similarly to like we haven't gotten any data - // Flush all received packets that haven't been processed, they will be readded on reload. - resetPacketData(); - - setFormattedImage(NULL); - mFullyLoaded = FALSE; - - // This flag says that we may have VFS data if we want to reload this texture - // (or get network traffic for this texture) - mFormattedFlushed = TRUE; - } } -#endif } //============================================================================ F32 LLViewerImage::calcDecodePriority() { - F32 priority; - S32 gldiscard = getDiscardLevel(); - S32 ddiscard = gldiscard - mDesiredDiscardLevel; - - if (mIsMissingAsset) +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (mID == gTextureFetch->mDebugID) { - priority = 0.0f; + gTextureFetch->mDebugCount++; // for setting breakpoints } - else if (mDesiredDiscardLevel > mMaxDiscardLevel) +#endif + + if (mNeedsCreateTexture) { - // Don't decode anything we don't need - priority = 0.0f; + return mDecodePriority; // no change while waiting to create } - else if (gldiscard < 0 && mDesiredDiscardLevel >= 0) - { - // We don't have any data yet, we need something immideately - priority = 200000.f; - } - else if (getDiscardLevel() < 0 && mDesiredDiscardLevel < MAX_DISCARD_LEVEL+1) + + F32 priority; + S32 cur_discard = getDiscardLevel(); + F32 pixel_priority = fsqrtf(mMaxVirtualSize) * (1.f + mMaxCosAngle); + const S32 MIN_NOT_VISIBLE_FRAMES = 30; // NOTE: this function is not called every frame + mDecodeFrame++; + if (pixel_priority > 0.f) { - // We have data, but haven't decoded any of it yet, but it on top - priority = 300000.f; + mVisibleFrame = mDecodeFrame; } - else if (gldiscard <= mDesiredDiscardLevel) + + if (mIsMissingAsset) { priority = 0.0f; } + else if (mDesiredDiscardLevel > mMaxDiscardLevel) + { + // Don't decode anything we don't need + priority = -1.0f; + } + else if (pixel_priority <= 0.f && (cur_discard < 0 || mDesiredDiscardLevel < cur_discard)) + { + // Not on screen but we might want some data + if (mBoostLevel > BOOST_HIGH) + { + // Always want high boosted images + priority = 1.f; + } + else if (mVisibleFrame == 0 || (mDecodeFrame - mVisibleFrame > MIN_NOT_VISIBLE_FRAMES)) + { + // Don't decode anything that isn't visible unless it's important + priority = -2.0f; + } + else + { + // Leave the priority as-is + return mDecodePriority; + } + } + else if (cur_discard < 0) + { + // We don't have any data yet, so we don't know the size of the image, treat as 1024x1024 +// priority = 900000.f; + static const F64 log_2 = log(2.0); + F32 desired = (F32)(log(1024.0/pixel_priority) / log_2); + S32 ddiscard = MAX_DISCARD_LEVEL - (S32)desired + 1; + ddiscard = llclamp(ddiscard, 1, 9); + priority = ddiscard*100000.f; + } + else if (cur_discard <= mMinDiscardLevel) + { + // larger mips are corrupted + priority = -3.0f; + } + else if (cur_discard <= mDesiredDiscardLevel) + { + priority = -4.0f; + } else { - // priority range = 0 - 10000 (10 ^ 4) + // priority range = 100000-400000 + S32 ddiscard = cur_discard - mDesiredDiscardLevel; if (getDontDiscard()) { ddiscard+=2; } - else if (!getBoundRecently()) + else if (!getBoundRecently() && mBoostLevel == 0) { ddiscard-=2; } - else - { - ddiscard-=1; - } ddiscard = llclamp(ddiscard, 0, 4); - - priority = powf(10.f,(F32)ddiscard); + priority = ddiscard*100000.f; } if (priority > 0.0f) { - F32 pixel_priority = llmin(mMaxVirtualSize * (1.5f + mMaxCosAngle) * (100.f / (1024.f*1024.f)), 100.f); pixel_priority = llclamp(pixel_priority, 0.0f, priority-1.f); priority += pixel_priority; - if ( mBoostLevel > 0) + if ( mBoostLevel > BOOST_HIGH) { priority += 1000000.f + 1000.f * mBoostLevel; } + else if ( mBoostLevel > 0) + { + priority += 0.f + 1000.f * mBoostLevel; + } } return priority; } @@ -1048,7 +657,7 @@ F32 LLViewerImage::calcDecodePriority() //static F32 LLViewerImage::maxDecodePriority() { - return 1400000.f; + return 2000000.f; } void LLViewerImage::setDecodePriority(F32 priority) @@ -1062,10 +671,6 @@ void LLViewerImage::setDecodePriority(F32 priority) { mDecodePriority = priority; } - if (mStreamFile) - { - mStreamFile->setReadPriority(priority); - } } void LLViewerImage::setBoostLevel(S32 level) @@ -1079,187 +684,219 @@ void LLViewerImage::setBoostLevel(S32 level) //============================================================================ -void LLViewerImage::abortDecode() +bool LLViewerImage::updateFetch() { - // Don't try to recover, just don't set a formatted image. - // Recovery makes the code MUCH more complex - //llinfos << "Reset on abort decode" << llendl; - resetPacketData(); + mFetchState = 0; + mFetchPriority = 0; + mFetchDeltaTime = 999999.f; + mRequestDeltaTime = 999999.f; - setFormattedImage(NULL); - mFullyLoaded = FALSE; - // Make sure mNeedsAux is false, otherwise it'll try to decode the 5th channel - mNeedsAux = FALSE; - mFullWidth = 0; - mFullHeight = 0; - setNeedsDecode(FALSE); // Aborting setDecodeData - mDecodingAux = FALSE; - if (mStreamFile) +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (mID == gTextureFetch->mDebugID) { - llwarns << "Removing bad texture: " << mID << llendl; - hoseStreamFile(); + gTextureFetch->mDebugCount++; // for setting breakpoints } - else +#endif + + if (mIsMediaTexture) { - llwarns << "Removing bad texture: " << mID << llendl; - LLVFile vf(gVFS, mID, LLAssetType::AT_TEXTURE, LLVFile::READ_WRITE); - vf.remove(); + llassert_always(!mHasFetcher); + return false; // skip } - mRequestedDiscardLevel = -1; // make sure we re-request the data -} - -void LLViewerImage::hoseStreamFile() -{ - mStreamFile->remove(); - - delete mStreamFile; - mStreamFile = NULL; - - delete[] mCachedData; - mCachedData = NULL; - mCachedSize = 0; -} - - -// Sets mStreamFile to NULL when finishes loading. -BOOL LLViewerImage::loadStreamFile() -{ - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - // load as much data as possible from the stream cache file - // TODO: unify stream cache with load local - - // are we waiting on a file read? - if (mStreamFile) + if (mNeedsCreateTexture) + { + // We may be fetching still (e.g. waiting on write) + // but don't check until we've processed the raw data we have + return false; + } + if (mFullyLoaded) + { + llassert_always(!mHasFetcher); + return false; + } + if (mIsMissingAsset) { - if (mCachedSize == 0) + llassert_always(!mHasFetcher); + return false; // skip + } + if (!mLoadedCallbackList.empty() && mRawImage.notNull()) + { + return false; // process any raw image data in callbacks before replacing + } + + S32 current_discard = getDiscardLevel(); + S32 desired_discard = getDesiredDiscardLevel(); + F32 decode_priority = getDecodePriority(); + + if (mIsFetching) + { + // Sets mRawDiscardLevel, mRawImage, mAuxRawImage + S32 fetch_discard = current_discard; + bool finished = gTextureFetch->getRequestFinished(getID(), fetch_discard, mRawImage, mAuxRawImage); + if (finished) { - if (mStreamFile->isLocked(VFSLOCK_APPEND)) - { - // avoid stalling if we are still writing to the file - return FALSE; - } - mCachedSize = mStreamFile->getSize(); - if (mCachedSize >= 27) + mIsFetching = FALSE; + } + else + { + mFetchState = gTextureFetch->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + } + + // We may have data ready regardless of whether or not we are finished (e.g. waiting on write) + if (mRawImage.notNull()) + { + mRawDiscardLevel = fetch_discard; + if ((mRawImage->getDataSize() > 0 && mRawDiscardLevel >= 0) && + (current_discard < 0 || mRawDiscardLevel < current_discard)) { - mCachedData = new U8[mCachedSize]; - mStreamFile->read(mCachedData, mCachedSize, TRUE, 100 + mDecodePriority); + if (getComponents() != mRawImage->getComponents()) + { + // We've changed the number of components, so we need to move any + // objects using this pool to a different pool. + mComponents = mRawImage->getComponents(); + gImageList.dirtyImage(this); + } + mIsRawImageValid = TRUE; + gImageList.mCreateTextureList.insert(this); + mNeedsCreateTexture = TRUE; + mFullWidth = mRawImage->getWidth() << mRawDiscardLevel; + mFullHeight = mRawImage->getHeight() << mRawDiscardLevel; } else { - llwarns << "Cached image " << mID << " has length " << mCachedSize << " not loading" << llendl; - - mStreamFile->remove(); - - delete mStreamFile; - mStreamFile = NULL; - mCachedSize = 0; - return FALSE; + // Data is ready but we don't need it + // (received it already while fetcher was writing to disk) + destroyRawImage(); + return false; // done } } - // is it finished? - if (mStreamFile->isReadComplete()) + if (!mIsFetching) { - //llinfos << mID << ": loading from stream file " << llendl; - U16 packet; - U32 file_version; - LLUUID file_id; - - U8 *tmp = mCachedData; - memcpy(&file_version, tmp, 4); - tmp += 4; - memcpy(file_id.mData, tmp, 16); - tmp += 16; - - if (file_version != sCurrentFileVersion || - file_id != mID) + if (mRawDiscardLevel < 0) { - // this file is from an old version, failed to open, or is invalid - hoseStreamFile(); - - return TRUE; // done - } - - mGotFirstPacket = TRUE; - - memcpy(&mDataCodec, tmp, 1); - tmp += 1; - memcpy(&mPackets, tmp, 2); - tmp += 2; - - memcpy(&mTotalBytes, tmp, 4); - tmp += 4; - - while (tmp - mCachedData < mCachedSize) - { - memcpy(&packet, tmp, 2); - tmp += 2; - - if (packet >= mPackets) - { - llwarns << "Cached image " << mID << " has bogus packet " << packet << " of " << mPackets << llendl; - - hoseStreamFile(); - return TRUE; // done - } - - U16 data_size; - memcpy((U8*)&(data_size), tmp, 2); - tmp += 2; - - if (tmp + data_size > mCachedData + mCachedSize) + // We finished but received no data + if (current_discard < 0) { - llwarns << "Cached image " << mID << " has bad length " << mCachedSize << ", should be " << (S32)(tmp + data_size - mCachedData) << llendl; - - hoseStreamFile(); - return TRUE; // done - } - - if (mReceivedPacketMap.find(packet) == mReceivedPacketMap.end()) - { - U8 *buf = new U8[data_size]; - memcpy(buf, tmp, data_size); - mReceivedPacketMap[packet] = new LLViewerImagePacket(buf, data_size, packet, TRUE); + llwarns << mID << ": Marking image as missing" << llendl; + setIsMissingAsset(); + desired_discard = -1; } else { - // Technically this assertion is correct, but there may be bogus VFS files out there which invalidate this - // condition. - //llassert(!mReceivedPacketMap[packet]->mWroteToDisk); - mReceivedPacketMap[packet]->mWroteToDisk = TRUE; + llwarns << mID << ": Setting min discard to " << current_discard << llendl; + mMinDiscardLevel = current_discard; + desired_discard = current_discard; } - - tmp += data_size; - - mPacketsReceived++; + destroyRawImage(); } + else if (mRawImage.isNull()) + { + // We have data, but our fetch failed to return raw data + // *TODO: FIgure out why this is happening and fix it + destroyRawImage(); + } + } + else if (mDecodePriority >= 0.f) + { + gTextureFetch->updateRequestPriority(mID, mDecodePriority); + } + } - delete mStreamFile; - mStreamFile = NULL; - - delete[] mCachedData; - mCachedData = NULL; - mCachedSize = 0; - - // Make sure we process all of the packet data associated with this texture. - mLastPacketProcessed = -1; - mLastPacket = -1; - mLastPacketTimer.reset(); - - // Process the packets and write to disk any that have not been written - checkPacketData(); - - return TRUE; // done + bool make_request = true; + + if (decode_priority <= 0) + { + make_request = false; + } + else if (mNeedsCreateTexture || mIsMissingAsset) + { + make_request = false; + } + else if (current_discard >= 0 && current_discard <= mMinDiscardLevel) + { + make_request = false; + } + else + { + if (mIsFetching) + { + if (mRequestedDiscardLevel <= desired_discard) + { + make_request = false; + } } else { - return FALSE; // still loading + if (current_discard >= 0 && current_discard <= desired_discard) + { + make_request = false; + } } } - else + + if (make_request) { - return TRUE; // not loading + S32 w=0, h=0, c=0; + if (current_discard >= 0) + { + w = getWidth(0); + h = getHeight(0); + c = getComponents(); + } + if (!mDontDiscard) + { + if (mBoostLevel == 0) + { + desired_discard = llmax(desired_discard, current_discard-1); + } + else + { + desired_discard = llmax(desired_discard, current_discard-2); + } + } + if (gTextureFetch->createRequest(getID(),getTargetHost(), decode_priority, + w, h, c, desired_discard, + needsAux())) + { + mHasFetcher = TRUE; + mIsFetching = TRUE; + mRequestedDiscardLevel = desired_discard; + mFetchState = gTextureFetch->getFetchState(mID, mDownloadProgress, mRequestedDownloadPriority, + mFetchPriority, mFetchDeltaTime, mRequestDeltaTime); + } + // if createRequest() failed, we're finishing up a request for this UUID, + // wait for it to complete + } + else if (mHasFetcher && !mIsFetching) + { + // Only delete requests that haven't receeived any network data for a while + const F32 FETCH_IDLE_TIME = 5.f; + if (mLastPacketTimer.getElapsedTimeF32() > FETCH_IDLE_TIME) + { +// llinfos << "Deleting request: " << getID() << " Discard: " << current_discard << " <= min:" << mMinDiscardLevel << " or priority == 0: " << decode_priority << llendl; + gTextureFetch->deleteRequest(getID(), true); + mHasFetcher = FALSE; + } } + + llassert_always(mRawImage.notNull() || (!mNeedsCreateTexture && !mIsRawImageValid)); + + return mIsFetching ? true : false; +} + +void LLViewerImage::setIsMissingAsset() +{ + if (mHasFetcher) + { + gTextureFetch->deleteRequest(getID(), true); + mHasFetcher = FALSE; + mIsFetching = FALSE; + mFetchState = 0; + mFetchPriority = 0; + } + mIsMissingAsset = TRUE; } //============================================================================ @@ -1278,13 +915,14 @@ void LLViewerImage::setLoadedCallback( loaded_callback_func loaded_callback, S32 mLoadedCallbackList.push_back(entryp); } -void LLViewerImage::doLoadedCallbacks() +bool LLViewerImage::doLoadedCallbacks() { - // Need to make sure we don't do these during the process of a decode or something? - if ((mFormattedImagep.notNull() && mFormattedImagep->isDecoding()) || mNeedsCreateTexture) + if (mNeedsCreateTexture) { - return; + return false; } + + bool res = false; if (isMissingAsset()) { @@ -1311,12 +949,6 @@ void LLViewerImage::doLoadedCallbacks() gl_discard = MAX_DISCARD_LEVEL + 1; } - // assert: We should either have a valid raw image, be decoding one, or not have one at all - llassert(mIsRawImageValid || needsDecode() || mRawImage.isNull()); - // assert: We should either not have a raw image, or it's discard level should be <= gl_discard - llassert(!mIsRawImageValid || mRawDiscardLevel <= gl_discard); - - // // Determine the quality levels of textures that we can provide to callbacks // and whether we need to do decompression/readback to get it @@ -1335,18 +967,9 @@ void LLViewerImage::doLoadedCallbacks() } else { - if (mFormattedImagep.notNull()) - { - // If we don't have a raw image or a GL image, we need to decode from a formatted image - best_aux_discard = llmin(best_aux_discard, - mFormattedImagep->calcDiscardLevelBytes(mFormattedImagep->getDataSize())); - } - else - { - // We have no data at all, we need to get the formatted image. - // Do this by forcing the best aux discard to be 0. - best_aux_discard = 0; - } + // We have no data at all, we need to get it + // Do this by forcing the best aux discard to be 0. + best_aux_discard = 0; } @@ -1357,7 +980,6 @@ void LLViewerImage::doLoadedCallbacks() bool run_gl_callbacks = false; bool run_raw_callbacks = false; bool need_readback = false; - bool need_decompress = false; for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) @@ -1375,12 +997,6 @@ void LLViewerImage::doLoadedCallbacks() // We have useful data, run the callbacks run_raw_callbacks = true; } - else if (entryp->mLastUsedDiscard > best_aux_discard) - { - // We need to decompress data, but don't need - // to run the callbacks - need_decompress = true; - } } else { @@ -1420,10 +1036,8 @@ void LLViewerImage::doLoadedCallbacks() createRawImage(gl_discard, TRUE); readBackRaw(gl_discard, mRawImage); mIsRawImageValid = TRUE; - } - if (need_decompress) - { - startImageDecode(); + llassert_always(mRawImage.notNull()); + llassert_always(!mNeedsAux || mAuxRawImage.notNull()); } // @@ -1434,10 +1048,6 @@ void LLViewerImage::doLoadedCallbacks() // Do callbacks which require raw image data. //llinfos << "doLoadedCallbacks raw for " << getID() << llendl; - LLImageRaw* raw_image = mRawImage; - LLImageRaw* raw_image_aux = mAuxRawImage; - llassert(!mNeedsAux || mAuxRawImage.notNull()); - // Call each party interested in the raw data. for(callback_list_t::iterator iter = mLoadedCallbackList.begin(); iter != mLoadedCallbackList.end(); ) @@ -1450,28 +1060,26 @@ void LLViewerImage::doLoadedCallbacks() // to satisfy the interested party, then this is the last time that // we're going to call them. + llassert_always(mRawImage.notNull()); + llassert_always(!mNeedsAux || mAuxRawImage.notNull()); BOOL final = mRawDiscardLevel <= entryp->mDesiredDiscard ? TRUE : FALSE; //llinfos << "Running callback for " << getID() << llendl; - //llinfos << raw_image->getWidth() << "x" << raw_image->getHeight() << llendl; + //llinfos << mRawImage->getWidth() << "x" << mRawImage->getHeight() << llendl; if (final) { //llinfos << "Final!" << llendl; } entryp->mLastUsedDiscard = mRawDiscardLevel; - entryp->mCallback(TRUE, this, raw_image, raw_image_aux, mRawDiscardLevel, final, entryp->mUserData); + entryp->mCallback(TRUE, this, mRawImage, mAuxRawImage, mRawDiscardLevel, final, entryp->mUserData); if (final) { iter = mLoadedCallbackList.erase(curiter); delete entryp; } + res = true; } } - - // - // If you want to keep a copy of the raw image, you better copy it off yourself - // - destroyRawImage(); } // @@ -1497,6 +1105,7 @@ void LLViewerImage::doLoadedCallbacks() iter = mLoadedCallbackList.erase(curiter); delete entryp; } + res = true; } } } @@ -1508,450 +1117,14 @@ void LLViewerImage::doLoadedCallbacks() { gImageList.mCallbackList.erase(this); } -} - -//============================================================================ -// static -void LLViewerImage::receiveImage(LLMessageSystem *msg, void **user_data) -{ - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + // Done with any raw image data at this point (will be re-created if we still have callbacks) + destroyRawImage(); - // Receive image header, copy into image object and decompresses - // if this is a one-packet image. - - LLUUID id; - - char ip_string[256]; - u32_to_ip_string(msg->getSenderIP(),ip_string); - - if (msg->getReceiveCompressedSize()) - { - gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8; - } - else - { - gImageList.sTextureBits += msg->getReceiveSize() * 8; - } - gImageList.sTexturePackets++; - - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); - - char id_string[UUID_STR_LENGTH]; - id.toString(id_string); - - LLViewerImage *image = gImageList.getImage(id); // Look up the correct image - - image->mLastPacketTimer.reset(); - - if (image->mFullyLoaded) - { -// llinfos << id << ":" << " Packet 0 for already loaded image!" << llendl; - return; - } - - // check to see if we've gotten this packet before - if (image->mGotFirstPacket) - { - //llinfos << id << ":" << " Duplicate Packet 0" << llendl; - return; - } - if (!image->mRequested) - { -// llinfos << id << ":" << " Packet 0 for unrequested image!" << llendl; - return; - } - - image->mGotFirstPacket = TRUE; - - // Copy header data into image object - msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, image->mDataCodec); - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, image->mPackets); - msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, image->mTotalBytes); - - if (0 == image->mPackets) - { - llwarns << "Img: " << (gTextureTable.getName(id).empty() ? id_string : gTextureTable.getName(id)) << ":" << " Number of packets is 0" << llendl; - return; - } - - lldebugst(LLERR_IMAGE) << "Img: " << (gTextureTable.getName(id).empty() ? id_string : gTextureTable.getName(id)) << ":" << " Packet 0:" << image->mPackets - 1 << llendl; - - U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - - // Got a packet, reset the counter. - image->mRequestTime.reset(); - image->mPacketsReceived++; - - if (data_size) - { - if (gVFS->getExists(image->mID, LLAssetType::AT_TEXTURE)) - { - // We have data in the VFS, but it's not loaded. - // We should start the VFS load on the assumption that we're going to use this data shortly. - image->startVFSLoad(); - // We can throw out this data, because we have at least ONE packet on the disk - //llinfos << "Throwing out first packet for " << image->mID << " which we already have a VFS file for!" << llendl; - return; - } - - // this buffer gets saved off in the packet list - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - - // output this image data to cache file - // only do this if we don't have old data - LLVFile file(gVFS, image->mID, LLAssetType::AT_TEXTURE, LLVFile::APPEND); - if (! file.getSize()) - { - BOOL write_to_vfs = FALSE; - if (image->mPackets == 0) - { - // Uh oh, we don't have packet data size - // This must be something from a local cache - llwarns << "Creating VFS file even though we don't know the number of packets!" << llendl; - } - else - { - write_to_vfs = file.setMaxSize(image->mTotalBytes + IMAGE_HEADER_SIZE + image->mPackets * PACKET_HEADER_SIZE); - } - - // to avoid another dynamic allocation, just assume we won't be gettimg image packets > 1 MTU - if (data_size > MTUBYTES) - { - llerrs << "image data chunk too large: " << data_size << " bytes" << llendl; - } - - if (write_to_vfs) - { - const S32 WRITE_BUF_SIZE = IMAGE_HEADER_SIZE + PACKET_HEADER_SIZE + MTUBYTES; - U8 buffer[WRITE_BUF_SIZE]; - U8 *tmp = buffer; - - // write current version byte to file, so we can change the format and detect old files later - memcpy(tmp, &LLViewerImage::sCurrentFileVersion, 4); - tmp += 4; - memcpy(tmp, id.mData, 16); - tmp += 16; - memcpy(tmp, (U8*)&(image->mDataCodec), 1); - tmp += 1; - memcpy(tmp, (U8*)&(image->mPackets), 2); - tmp += 2; - memcpy(tmp, (U8*)&(image->mTotalBytes), 4); - tmp += 4; - U16 zero = 0; - memcpy(tmp, (U8*)&zero, 2); - tmp += 2; - memcpy(tmp, (U8*)&(data_size), 2); - tmp += 2; - - // now copy in the image data - // it's a shame we can't use the original data buffer - // but this needs to be a single, atomic write - memcpy(tmp, data, data_size); - -// llinfos << "Writing packet 0 to disk for " << image->getID() << llendl; - file.write(buffer, IMAGE_HEADER_SIZE + PACKET_HEADER_SIZE + data_size); - } - // do this AFTER writing to the VFS since LLViewerImagePacket may delete 'data' - llassert( image->mReceivedPacketMap.find(0) == image->mReceivedPacketMap.end() ); - image->mReceivedPacketMap[0] = new LLViewerImagePacket(data, data_size, 0, TRUE); - } - - image->checkPacketData(); - } -} - - -/////////////////////////////////////////////////////////////////////////////// -// TODO: lastbytes vs. texturebits? -// TODO: is mRequested already used? - -// static -void LLViewerImage::receiveImagePacket(LLMessageSystem *msg, void **user_data) -{ - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); - - // Receives image packet, copy into image object, - // checks if all packets received, decompresses if so. - - LLUUID id; - U16 packet_num; - char id_string[UUID_STR_LENGTH]; - - char ip_string[256]; - u32_to_ip_string(msg->getSenderIP(),ip_string); - - if (msg->getReceiveCompressedSize()) - { - gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8; - } - else - { - gImageList.sTextureBits += msg->getReceiveSize() * 8; - } - gImageList.sTexturePackets++; - - //llprintline("Start decode, image header..."); - msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); - msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num); - - id.toString(id_string); - - LLViewerImage *image = gImageList.hasImage(id); // Look up the correct image - if (!image ||!(image->mRequested)) - { - // Getting a packet for an unrequested image. - lldebugst(LLERR_IMAGE) << "Img: " << (gTextureTable.getName(id).empty() ? id_string : gTextureTable.getName(id)) << " Packet "; - llcont << packet_num << " for unrequested from " << ip_string << llendl; - - // don't cancel the request - this might just be an out of order packet - return; - } - - image->mLastPacketTimer.reset(); - - if (image->mReceivedPacketMap.find(packet_num) != image->mReceivedPacketMap.end()) - { - return; - } - - // check to see if we already got this packet - BOOL duplicate = FALSE; - if (packet_num <= image->mLastPacketProcessed) - { - duplicate = TRUE; - } - else if (image->mReceivedPacketMap.find(packet_num) != image->mReceivedPacketMap.end()) - { - duplicate = TRUE; - } - - if (duplicate) - { - //llinfos << image->mID << ": duplicate packet " << packet_num << " last " << image->mLastPacketProcessed << llendl; - return; - } - - // Got a packet, reset the counter. - image->mRequestTime.reset(); - image->mPacketsReceived++; - - std::string tex_name = gTextureTable.getName(id); - if (image->mPackets == 0) - { - lldebugst(LLERR_IMAGE) << "Img: " << (tex_name.empty() ? id_string : tex_name) << " Packet " << packet_num << " out of order " << llendl; - } - else - { - lldebugst(LLERR_IMAGE) << "Img: " << (tex_name.empty() ? id_string : tex_name) << " Packet " << packet_num << ":" << image->mPackets - 1 << llendl; - } - - - U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); - if (data_size) - { - - U8 *data = new U8[data_size]; - msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); - - // as above assume we won't be gettimg image packets > 1 MTU - if (data_size > MTUBYTES) - { - llerrs << "image data chunk too large: " << data_size << " bytes" << llendl; - } - - // We don't want to write it to disk yet, just put it on the queue. - image->mReceivedPacketMap[packet_num] = new LLViewerImagePacket(data, data_size, packet_num, FALSE); - // Process this packet. - image->checkPacketData(); - } -} - - -BOOL LLViewerImage::checkPacketData() -{ - LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); - - S32 cur_size = 0; - S32 next_size = 0; - S32 next_discard = llmax(getDiscardLevel()-1,0); - - // 1. Check if we already have formatted data to decode - if (mFormattedImagep.notNull()) - { - if ((mFormattedImagep->isDecoding()) || mStreamFile) - { - return TRUE; // we're busy decoding, don't request more data yet - } - - cur_size = mFormattedImagep->getDataSize(); - next_size = mFormattedImagep->calcDataSize(next_discard); - next_size = llmin(next_size, (S32)mTotalBytes); - - if (cur_size >= next_size) - { - setDecodeData(mFormattedImagep->getData(), cur_size); - return TRUE; - } - } - - if (mFullyLoaded) - { - // Somehow we think we have new packet data but are flagged as fully loaded - resetPacketData(); - return TRUE; - } - - // 2. Check if we already have new packets - if (!mPackets || !mGotFirstPacket) - { - return FALSE; - } - if (mReceivedPacketMap.empty() || mReceivedPacketMap.find(mLastPacketProcessed + 1) == mReceivedPacketMap.end()) - { - return FALSE; - } - - // 3. Decide if we have enough new data to decode - S32 new_size = cur_size; - U16 next_packet_num = mLastPacketProcessed; - for (vip_map_t::iterator iter = mReceivedPacketMap.begin(); - iter != mReceivedPacketMap.end() && iter->second->mPacketNum == ++next_packet_num; - iter++) - { - new_size += iter->second->mDataSize; - mLastPacket = iter->second->mPacketNum; - } - mLastBytesProcessed = new_size; - - if (new_size < next_size) - { - return FALSE; - } - - if (!gVFS->getExists(mID, LLAssetType::AT_TEXTURE)) - { - // We must have removed the file, probably because it was corrupted. Abort! - //llinfos << "Reset on no VFS file!" << llendl; - abortDecode(); - return FALSE; - } - - if (mLastPacketProcessed == -1 && cur_size != 0) - { - llerrs << "LLViewerImage: duplicate first packet!" << llendl; - } - - // 4. Append new data to existing data and decode - - // 4a. Write the packets to disk - LLVFile file(gVFS, mID, LLAssetType::AT_TEXTURE, LLVFile::APPEND); - vip_map_t::iterator first_iter = mReceivedPacketMap.begin(); - S32 first_idx = 0; - while (first_iter != mReceivedPacketMap.end()) - { - S32 packet_data_size = 0; - vip_map_t::iterator end_iter = first_iter; - S32 end_idx = first_idx; - while(end_iter != mReceivedPacketMap.end()) - { - LLViewerImagePacket *vip = end_iter->second; - if (!vip->mWroteToDisk) - { - packet_data_size += (PACKET_HEADER_SIZE + vip->mDataSize); - } - else - { - break; - } - ++end_iter; - ++end_idx; - } - if (packet_data_size > 0) - { - U8* packet_data_buffer = new U8[packet_data_size]; - U8* packet_data = packet_data_buffer; - for (vip_map_t::iterator iter = first_iter; iter != end_iter; ++iter) - { - LLViewerImagePacket *vip = iter->second; - - memcpy(packet_data, &vip->mPacketNum, 2); - memcpy(packet_data + 2, &(vip->mDataSize), 2); - memcpy(packet_data + PACKET_HEADER_SIZE, vip->mData, vip->mDataSize); - packet_data += (PACKET_HEADER_SIZE + vip->mDataSize); - - vip->mWroteToDisk = TRUE; - } - if (packet_data - packet_data_buffer != packet_data_size) llerrs << "wtf?" << llendl; - - // llinfos << mID << " Writing packets " << first_idx << "-" << end_idx << " to file." << llendl; - file.write(packet_data_buffer, packet_data_size); - - delete[] packet_data_buffer; - } - if (end_iter == first_iter) - { - ++end_iter; - ++end_idx; - } - first_iter = end_iter; - first_idx = end_idx; - } - - // 4b. Append the data - U8* data = new U8[new_size]; - if (cur_size > 0) - { - memcpy(data, mFormattedImagep->getData(), cur_size); - } - LLViewerImagePacket *pkt = mReceivedPacketMap.begin()->second; - while (pkt && pkt->mPacketNum == mLastPacketProcessed + 1) - { - memcpy((U8*)(data + cur_size), pkt->mData, pkt->mDataSize); - cur_size += pkt->mDataSize; - mLastPacketProcessed = pkt->mPacketNum; - delete mReceivedPacketMap.begin()->second; - mReceivedPacketMap.erase(mReceivedPacketMap.begin()); - pkt = NULL; - if (!mReceivedPacketMap.empty()) - { - pkt = mReceivedPacketMap.begin()->second; - } - } - - llassert(cur_size == new_size); - lldebugst(LLERR_IMAGE) << "IMAGE RECEIVED: " << mID.getString() << " Bytes: " << cur_size << "/" << mTotalBytes << llendl; - - // 4c. Set the data to be decoded, and the number of bytes to use. - setDecodeData(data, new_size); - - // 5. Recalculate the image priority - gImageList.removeImageFromList(this); - F32 decode_priority = calcDecodePriority(); - setDecodePriority(decode_priority); - gImageList.addImageToList(this); - - return TRUE; + return res; } -F32 LLViewerImage::getDecodeProgress(F32 *data_progress_p) -{ - F32 decode_progress = 0.0f; - F32 data_progress = 0.0f; - - if (mLastPacket >= 0) - { - S32 max_bytes = mTotalBytes; - S32 data_bytes = mLastBytesProcessed; - S32 decode_bytes = mFormattedImagep.notNull() ? mFormattedImagep->getDataSize() : data_bytes; - data_progress = (F32)data_bytes / (F32)max_bytes; - decode_progress = (F32)decode_bytes / (F32)max_bytes; - } - if (data_progress_p) *data_progress_p = data_progress; - return decode_progress; -} +//============================================================================ // Call with 0,0 to turn this feature off. void LLViewerImage::setKnownDrawSize(S32 width, S32 height) @@ -1976,13 +1149,8 @@ BOOL LLViewerImage::bind(S32 stage) const BOOL res = bindTextureInternal(stage); if (res) { - if (mIsMissingAsset) - { - // If we can bind, clearly we have an asset. - // If mIsMissingAsset was true and we get here, it's likely - // that the asset server was messed up and then it recovered. - mIsMissingAsset = FALSE; - } + //llassert_always(mIsMissingAsset == FALSE); + } else { @@ -2013,7 +1181,6 @@ BOOL LLViewerImage::bind(S32 stage) const LLImageRaw* LLViewerImage::createRawImage(S8 discard_level, BOOL allocate) { llassert(discard_level >= 0); - llassert(mFormattedImagep.isNull() || !mFormattedImagep->isDecoding()); if (mRawImage.notNull()) { llerrs << "createRawImage() called with existing mRawImage" << llendl; diff --git a/linden/indra/newview/llviewerimage.h b/linden/indra/newview/llviewerimage.h index e2f44e5..54865ff 100644 --- a/linden/indra/newview/llviewerimage.h +++ b/linden/indra/newview/llviewerimage.h @@ -41,7 +41,6 @@ class LLViewerImage; typedef void (*loaded_callback_func)( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* src_aux, S32 discard_level, BOOL final, void* userdata ); class LLVFile; -class LLViewerImagePacket; class LLMessageSystem; class LLLoadedCallbackEntry @@ -70,7 +69,8 @@ class LLTextureBar; class LLViewerImage : public LLImageGL { -// friend class LLViewerImageList; + LOG_CLASS(LLViewerImage); + friend class LLTextureBar; // debug info only friend class LLTextureView; // debug info only @@ -78,8 +78,6 @@ public: static void initClass(); static void cleanupClass(); static void updateClass(const F32 velocity, const F32 angular_velocity); - static void receiveImage(LLMessageSystem *msg, void **user_data); - static void receiveImagePacket(LLMessageSystem *msg, void **user_data); static BOOL bindTexture(LLImageGL* image, const U32 stage = 0) { if (image) @@ -188,24 +186,6 @@ public: const LLUUID& getID() { return mID; } - void setFormattedImage(LLImageFormatted* imagep); - - // Load an image from the static VFS - BOOL loadLocalImage(const LLUUID& uuid); - - // Start loading of data from VFS, if any - BOOL startVFSLoad(); - void startImageDecode(); - - // Methods for loading and decoding data - void setDecodeData(U8 *data, U32 size); - void decodeImage(const F32 decode_time = 0.0); - bool isDecoding(); - - // Poll the VFS to see if the read is complete. Returns TRUE if - // the read is complete (and sets mStreamFile to NULL). - BOOL loadStreamFile(); - // New methods for determining image quality/priority // texel_area_ratio is ("scaled" texel area)/(original texel area), approximately. void addTextureStats(F32 pixel_area, @@ -216,9 +196,6 @@ public: // Process image stats to determine priority/quality requirements. void processTextureStats(); - // Checks image data and decodes if ready. Returns true if packets were decoded or are pending - BOOL checkPacketData(); - // Set callbacks to get called when the image gets updated with higher // resolution versions. void setLoadedCallback(loaded_callback_func cb, @@ -226,13 +203,11 @@ public: BOOL keep_imageraw, void* userdata); + // ONLY call from LLViewerImageList BOOL createTexture(S32 usename = 0); - BOOL destroyTexture(); BOOL needsAux() const { return mNeedsAux; } void setNeedsAux(const BOOL needs_aux) { mNeedsAux = needs_aux; } - BOOL needsDecode() const { return mNeedsDecode; } - void setNeedsDecode(const BOOL needs_decode) { mNeedsDecode = needs_decode; } // setDesiredDiscardLevel is only used by LLViewerImageList void setDesiredDiscardLevel(S32 discard) { mDesiredDiscardLevel = discard; } @@ -247,20 +222,20 @@ public: enum { BOOST_NONE = 0, - BOOST_TERRAIN = 1, - BOOST_AVATAR_BAKED = 2, - BOOST_AVATAR = 3, - BOOST_CLOUDS = 4, + BOOST_AVATAR_BAKED = 1, + BOOST_AVATAR = 2, + BOOST_CLOUDS = 3, BOOST_HIGH = 10, - BOOST_SELECTED = 11, - BOOST_HUD = 12, - BOOST_AVATAR_BAKED_SELF = 13, - BOOST_UI = 14, - BOOST_PREVIEW = 15, - BOOST_MAP = 16, - BOOST_MAP_LAYER = 17, - BOOST_AVATAR_SELF = 18, // needed for baking avatar + BOOST_TERRAIN = 11, // has to be high priority for minimap / low detail + BOOST_SELECTED = 12, + BOOST_HUD = 13, + BOOST_AVATAR_BAKED_SELF = 14, + BOOST_UI = 15, + BOOST_PREVIEW = 16, + BOOST_MAP = 17, + BOOST_MAP_LAYER = 18, + BOOST_AVATAR_SELF = 19, // needed for baking avatar BOOST_MAX_LEVEL }; void setBoostLevel(S32 level); @@ -275,111 +250,88 @@ public: // the priority list, and cause horrible things to happen. void setDecodePriority(F32 priority = -1.0f); + bool updateFetch(); + // Override the computation of discard levels if we know the exact output // size of the image. Used for UI textures to not decode, even if we have // more data. void setKnownDrawSize(S32 width, S32 height); - void setIsMissingAsset(BOOL b) { mIsMissingAsset = b; } + void setIsMissingAsset(); BOOL isMissingAsset() { return mIsMissingAsset; } - BOOL getNeedsCreateTexture() const { return mNeedsCreateTexture; } - bool hasCallbacks() { return mLoadedCallbackList.empty() ? false : true; } - void doLoadedCallbacks(); - S32 getLastPacket() { return mLastPacket; } - F32 getDecodeProgress(F32 *data_progress_p = 0); + bool doLoadedCallbacks(); - void abortDecode(); - void destroyRawImage(); // Delete the raw image for this discard level - private: /*virtual*/ void cleanup(); // Cleanup the LLViewerImage (so we can reinitialize it) void init(bool firstinit); - void hoseStreamFile(); - void resetPacketData(); // Used to be in LLImageGL LLImageRaw* createRawImage(S8 discard_level = 0, BOOL allocate = FALSE); + void destroyRawImage(); public: S32 mFullWidth; S32 mFullHeight; - LLVFile *mStreamFile; // Data used for calculating required image priority/quality level/decimation mutable F32 mMaxVirtualSize; // The largest virtual size of the image, in pixels - how much data to we need? mutable F32 mMaxCosAngle; // The largest cos of the angle between camera X vector and the object F32 mTexelsPerImage; // Texels per image. + F32 mDiscardVirtualSize; // Virtual size used to calculate desired discard S8 mInImageList; // TRUE if image is in list (in which case don't reset priority!) S8 mIsMediaTexture; // TRUE if image is being replaced by media (in which case don't update) - S8 mInStaticVFS; // Source data in local VFS - S8 mFormattedFlushed; - S8 mRequested; // An image request is currently in process. - S8 mFullyLoaded; - // Various info regarding image requests - LLFrameTimer mRequestTime; S32 mRequestedDiscardLevel; F32 mRequestedDownloadPriority; + S32 mFetchState; + U32 mFetchPriority; + F32 mDownloadProgress; + F32 mFetchDeltaTime; + F32 mRequestDeltaTime; + S32 mDecodeFrame; + S32 mVisibleFrame; // decode frame where image was last visible // Timers - LLFrameTimer mLastDecodeTime; // Time since last decode. LLFrameTimer mLastPacketTimer; // Time since last packet. LLFrameTimer mLastReferencedTimer; - + private: LLUUID mID; - LLPointer mFormattedImagep; S8 mDesiredDiscardLevel; // The discard level we'd LIKE to have - if we have it and there's space S8 mMinDesiredDiscardLevel; // The minimum discard level we'd like to have - S8 mGotFirstPacket; - S8 mNeedsCreateTexture; - - S8 mNeedsDecode; // We have a compressed image that we want to decode, now. + S8 mNeedsCreateTexture; S8 mNeedsAux; // We need to decode the auxiliary channels - S8 mDecodingAux; // Are we decoding high components - mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - - // Codec of incoming packet data - U8 mDataCodec; S8 mIsRawImageValid; + S8 mHasFetcher; // We've made a fecth request + S8 mIsFetching; // Fetch request is active + S8 mFullyLoaded; + mutable S8 mIsMissingAsset; // True if we know that there is no image asset with this image id in the database. - typedef std::map vip_map_t; - vip_map_t mReceivedPacketMap; - S32 mLastPacketProcessed; - U32 mLastBytesProcessed; // Total bytes including the last packet rec'd - - // Data download/decode info - U32 mPacketsReceived; - U32 mTotalBytes; - S32 mLastPacket; // Last packet received without a gap. - U16 mPackets; - - // VFS info - U8 *mCachedData; - S32 mCachedSize; - // Override the computation of discard levels if we know the exact output size of the image. // Used for UI textures to not decode, even if we have more data. - S32 mKnownDrawWidth; - S32 mKnownDrawHeight; + S32 mKnownDrawWidth; + S32 mKnownDrawHeight; - F32 mDecodePriority; // The priority for decoding this image. - S32 mBoostLevel; // enum describing priority level + F32 mDecodePriority; // The priority for decoding this image. + S32 mBoostLevel; // enum describing priority level typedef std::list callback_list_t; callback_list_t mLoadedCallbackList; LLPointer mRawImage; - S32 mRawDiscardLevel; + S32 mRawDiscardLevel; + S32 mMinDiscardLevel; + F32 mCalculatedDiscardLevel; // Last calculated discard level + // Used ONLY for cloth meshes right now. Make SURE you know what you're // doing if you use it for anything else! - djs LLPointer mAuxRawImage; diff --git a/linden/indra/newview/llviewerimagelist.cpp b/linden/indra/newview/llviewerimagelist.cpp index 20ca3bf..456afdb 100644 --- a/linden/indra/newview/llviewerimagelist.cpp +++ b/linden/indra/newview/llviewerimagelist.cpp @@ -39,57 +39,30 @@ #include "llimagejpeg.h" #include "llmediaengine.h" +#include "llsdserialize.h" +#include "llsys.h" #include "llvfs.h" #include "llvfile.h" #include "llvfsthread.h" #include "message.h" #include "llagent.h" -#include "llviewercontrol.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" #include "lltexturetable.h" // For looking up names from uuid's. +#include "llviewercontrol.h" #include "llviewerimage.h" #include "llviewerregion.h" +#include "pipeline.h" #include "viewer.h" -#include "llsys.h" -#include "llpaneldisplay.h" // for LL_MAX_VRAM_INDEX -void (*LLViewerImageList::sUUIDCallback)(void **, const LLUUID&) = NULL; +//////////////////////////////////////////////////////////////////////////// -const U32 SIXTEEN_MEG = 0x1000000; -const F32 MAX_IMAGE_PRIORITY = 100000000.f; +void (*LLViewerImageList::sUUIDCallback)(void **, const LLUUID&) = NULL; U32 LLViewerImageList::sTextureBits = 0; U32 LLViewerImageList::sTexturePackets = 0; -struct CodecExtMap -{ - CodecExtMap( const char* ext, U8 codec ) : mExt( ext ), mCodec( codec ) {} - const char* mExt; - U8 mCodec; -}; - -// Note: Keep codec extensions in order of likelihood the image -// will be found. -const S32 CODEC_EXT_MAP_COUNT = 2; -const CodecExtMap CODEC_EXT_MAP[CODEC_EXT_MAP_COUNT] = -{ - CodecExtMap( "_07", IMG_CODEC_J2C ), - CodecExtMap( ".tga", IMG_CODEC_TGA ) -}; - -const U32 MIN_AVAIL_MEM_FOR_DECODE = 1048576; - -// HACK: We have to try to allocate a constant fraction of this -// memory for AGP. This isn't worthwhile on 128 meg cards. -// So for 128 meg cards, only alloc 64 megs. -const S32 VIDEO_CARD_MEM_SIZES[6] = { 0x1000000, // 16MB - 0x2000000, // 32MB - 0x4000000, // 64MB+ - 0x8000000, // 128MB - 0x10000000, // 256MB - 0x20000000, // 512MB - }; - const S32 IMAGES_PER_REQUEST = 42; const S32 IMAGES_MIN_UPDATES = 4; // Always update the highest N images each frame const S32 IMAGES_MAX_PACKET_UPDATES = 1; // Only send N packets of IMAGES_PER_REQUEST in a frame @@ -105,22 +78,6 @@ LLStat LLViewerImageList::sGLBoundMemStat(32, TRUE); LLStat LLViewerImageList::sRawMemStat(32, TRUE); LLStat LLViewerImageList::sFormattedMemStat(32, TRUE); -//static -S32 LLViewerImageList::calcMaxTextureRAM() -{ - // Decide the maximum amount of RAM we should allow the user to allocate to texture cache - LLMemoryInfo memory_info; - U32 available_memory = memory_info.getPhysicalMemory(); - - clamp_rescale((F32)available_memory, - (F32)(SIXTEEN_MEG * 16), - (F32)U32_MAX, - (F32)(SIXTEEN_MEG * 4), - (F32)(U32_MAX >> 1)); - return available_memory; -} - - /////////////////////////////////////////////////////////////////////////////// LLViewerImageList::LLViewerImageList() @@ -145,57 +102,22 @@ void LLViewerImageList::init() return; } - // This stuff is global! Bad behavior if more than one image list. - - // Set the fallback GL texture to smoke... - LLViewerImage::sSmokeImagep = getImage(IMG_SMOKE, TRUE, TRUE); - // Set the fallback GL texture to gray with a white border... -#if 0 - LLViewerImage* imagep = new LLViewerImage(IMG_DEFAULT, TRUE); - LLViewerImage::sDefaultImagep = imagep; - const S32 dim = 128; - const S32 border = 2; - LLPointer image_raw = new LLImageRaw(dim,dim,3); - U8* data = image_raw->getData(); - for (S32 i = 0; i=(dim-border) || j>=(dim-border)) - { - *data++ = 0xff; - *data++ = 0xff; - *data++ = 0xff; - } - else - { - *data++ = 0x7f; - *data++ = 0x7f; - *data++ = 0x7f; - } - } - } - imagep->createGLTexture(0, image_raw); - image_raw = NULL; - addImage(imagep); - imagep->dontDiscard(); -#else - LLViewerImage::sDefaultImagep = getImage(IMG_DEFAULT, TRUE, TRUE); -#endif - - mUpdateStats = TRUE; // Update how much texture RAM we're allowed to use. updateMaxResidentTexMem(); mMovieImageHasMips = FALSE; + + doPreloadImages(); + + decodeAllImages(5.f); // decode preloaded images } void LLViewerImageList::doPreloadImages() { llinfos << "Preloading images..." << llendl; - + // Set the "missing asset" image LLViewerImage::sMissingAssetImagep = preloadImage("missing_asset.tga" , LLUUID::null, TRUE); @@ -335,6 +257,7 @@ void LLViewerImageList::doPreloadImages() preloadImage("spin_up_in_blue.tga", LLUUID::null, FALSE); preloadImage("spin_up_out_blue.tga", LLUUID::null, FALSE); preloadImage("square_btn_32x128.tga", LLUUID::null, FALSE); + preloadImage("square_btn_selected_32x128.tga", LLUUID::null, FALSE); preloadImage("startup_logo.tga", LLUUID::null, FALSE); preloadImage("status_build.tga", LLUUID::null, FALSE); preloadImage("status_buy_currency.tga", LLUUID::null, FALSE); @@ -346,6 +269,8 @@ void LLViewerImageList::doPreloadImages() preloadImage("status_scripts.tga", LLUUID::null, FALSE); preloadImage("tab_bottom_blue.tga", LLUUID::null, FALSE); preloadImage("tab_bottom_selected_blue.tga", LLUUID::null, FALSE); + preloadImage("tab_left.tga", LLUUID::null, FALSE); + preloadImage("tab_left_selected.tga", LLUUID::null, FALSE); preloadImage("tab_top_blue.tga", LLUUID::null, FALSE); preloadImage("tab_top_selected_blue.tga", LLUUID::null, FALSE); preloadImage("tool_dozer.tga", LLUUID::null, FALSE); @@ -355,6 +280,45 @@ void LLViewerImageList::doPreloadImages() preloadImage("white.tga", LLUUID::null, TRUE); } +static std::string get_texture_list_name() +{ + BOOL login_last = gSavedSettings.getBOOL("LoginLastLocation"); + return std::string("texture_list_") + (login_last?"last":"home") + ".xml"; +} + +void LLViewerImageList::doPrefetchImages() +{ + if (gPurgeCache) + { + // cache was purged, no point + return; + } + + // Pre-fetch textures from last logout + LLSD imagelist; + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); + llifstream file; + file.open(filename.c_str()); + if (file.is_open()) + { + LLSDSerialize::fromXML(imagelist, file); + } + for (LLSD::array_iterator iter = imagelist.beginArray(); + iter != imagelist.endArray(); ++iter) + { + LLSD imagesd = *iter; + LLUUID uuid = imagesd["uuid"]; + S32 pixel_area = imagesd["area"]; + LLViewerImage* image = getImage(uuid, MIPMAP_TRUE, FALSE); + if (image) + { + image->addTextureStats((F32)pixel_area); + } + } + + +} + /////////////////////////////////////////////////////////////////////////////// LLViewerImageList::~LLViewerImageList() @@ -364,43 +328,70 @@ LLViewerImageList::~LLViewerImageList() void LLViewerImageList::shutdown() { - // Clean up potential callback data - // mIRCallbackData is now stl and will clean itself up + // Write out list of currently loaded textures for precaching on startup + typedef std::set > image_area_list_t; + image_area_list_t image_area_list; + for (image_priority_list_t::iterator iter = mImageList.begin(); + iter != mImageList.end(); ++iter) + { + LLViewerImage* image = *iter; + if (!image->getUseDiscard() || + image->needsAux() || + image->getTargetHost() != LLHost::invalid) + { + continue; // avoid UI, baked, and other special images + } + S32 desired = image->getDesiredDiscardLevel(); + if (desired >= 0 && desired < MAX_DISCARD_LEVEL) + { + S32 pixel_area = image->getWidth(desired) * image->getHeight(desired); + image_area_list.insert(std::make_pair(pixel_area, image)); + } + } + + LLSD imagelist; + const S32 max_count = 1000; + S32 count = 0; + for (image_area_list_t::reverse_iterator riter = image_area_list.rbegin(); + riter != image_area_list.rend(); ++riter) + { + LLViewerImage* image = riter->second; + imagelist[count]["area"] = riter->first; + imagelist[count]["uuid"] = image->getID(); + if (++count >= max_count) + break; + } + if (count > 0 && !gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, "").empty()) + { + std::string filename = gDirUtilp->getExpandedFilename(LL_PATH_PER_SL_ACCOUNT, get_texture_list_name()); + llofstream file; + file.open(filename.c_str()); + LLSDSerialize::toPrettyXML(imagelist, file); + } + // // Clean up "loaded" callbacks. // mCallbackList.clear(); - + mIRCallbackData.clear(); + // Clean up preloaded images mPreloadedImages.clear(); - // - // If we're working on decoding an image, finish it off so we can clean it up. - // - LLViewerImage *imagep = mCurrentDecodeImagep; - if (imagep) - { - imagep->abortDecode(); - imagep->destroyRawImage(); - mCurrentDecodeImagep = NULL; - } - // Flush all of the references mLoadingStreamList.clear(); + mCreateTextureList.clear(); mUUIDMap.clear(); - // This stuff is global! - LLViewerImage::sDefaultImagep = NULL; - mImageList.clear(); } void LLViewerImageList::dump() { llinfos << "LLViewerImageList::dump()" << llendl; - for (image_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) + for (image_priority_list_t::iterator it = mImageList.begin(); it != mImageList.end(); ++it) { LLViewerImage* image = *it; @@ -456,20 +447,20 @@ LLViewerImage* LLViewerImageList::preloadImage(const LLString& filename, const L /////////////////////////////////////////////////////////////////////////////// -LLViewerImage * LLViewerImageList::getImage(const LLString& filename, - const LLUUID &image_set_id, - BOOL usemipmaps, - BOOL level_immediate) +LLViewerImage* LLViewerImageList::getImage(const LLString& filename, + const LLUUID &image_set_id, + BOOL usemipmaps, + BOOL level_immediate) { return getImageFromFile(filename, image_set_id, usemipmaps, level_immediate, 0, 0); } -LLViewerImage * LLViewerImageList::getImageFromFile(const LLString& filename, - const LLUUID &image_set_id, - BOOL usemipmaps, - BOOL level_immediate, - LLGLint internal_format, - LLGLenum primary_format) +LLViewerImage* LLViewerImageList::getImageFromFile(const LLString& filename, + const LLUUID &image_set_id, + BOOL usemipmaps, + BOOL level_immediate, + LLGLint internal_format, + LLGLenum primary_format) { if (gNoRender) { @@ -485,7 +476,7 @@ LLViewerImage * LLViewerImageList::getImageFromFile(const LLString& filename, LLUUID image_id = LLUUID( gViewerArt.getString(filename.c_str()) ); if (image_id.isNull()) { - llwarns << "Unable to find inage " << filename << " in gViewerArt" << llendl; + llwarns << "Unable to find image " << filename << " in gViewerArt" << llendl; if (image_set_id.notNull()) { // We *know* that missing_asset.tga exists, @@ -512,58 +503,9 @@ LLViewerImage * LLViewerImageList::getImageFromFile(const LLString& filename, image_id = image_set_id; } - // First see if we already have this image loaded. - LLPointer imagep = hasImage(image_id); - - if (imagep.isNull()) - { - // No image loaded. Try to read the filename given. - bool success = false; - if (!filename.empty()) - { - // This is strictly for local .tga files not in the static VFS - LLString image_file = gDirUtilp->getExpandedFilename(LL_PATH_TOP_SKIN, filename); - imagep = new LLViewerImage(image_id, usemipmaps); - LLPointer image_raw = new LLImageRaw(image_file); - if ( image_raw->getDataSize() > 0 ) - { - imagep->createGLTexture(0, image_raw); - image_raw = NULL; - - if (usemipmaps == FALSE) - { - // num mipmaped textures are almost always clamped, so clamp by default - imagep->bind(); - imagep->setClamp(TRUE, TRUE); - } - - if (internal_format && primary_format) - { - imagep->setExplicitFormat(internal_format, primary_format); - } - - addImage(imagep); - - if (level_immediate) - { - imagep->dontDiscard(); - } - - success = true; - } - else - { - imagep = NULL; - } - } - - if (!success) - { - // We couldn't load from a file. Try the VFS. - imagep = getImageFromUUID(image_id, usemipmaps, level_immediate, - internal_format, primary_format, LLHost()); - } - } + // Load the image + LLViewerImage* imagep = getImageFromUUID(image_id, usemipmaps, level_immediate, + internal_format, primary_format, LLHost()); return imagep; } @@ -609,40 +551,7 @@ LLViewerImage* LLViewerImageList::getImageFromUUID(const LLUUID &image_id, if (level_immediate) { imagep->dontDiscard(); - } - - // if rendering enabled, actually try to load this image - if (!gNoRender) - { - // First check the local image cache to see if it's there. - if (imagep->loadLocalImage(image_id)) - { -// llinfos << "Loading Local Image: " << image_id -// << llformat(" MIP:%d IMM:%d",usemipmaps,level_immediate) -// << llendl; - if( level_immediate ) - { - if (imagep->needsDecode()) - { - imagep->decodeImage(0.f); // getImage (local image) - } - - if (imagep->getNeedsCreateTexture()) - { - imagep->createTexture(); - } - } - } - else - { - // if we don't have this locally, we'll want to start on the highest discard - if (!imagep->getDontDiscard()) - { - imagep->setDesiredDiscardLevel(imagep->getMaxDiscardLevel()); - } - - imagep->startVFSLoad(); - } + imagep->setBoostLevel(LLViewerImage::BOOST_UI); } } @@ -695,13 +604,6 @@ void LLViewerImageList::addImage(LLViewerImage *new_image) } sNumImages++; -#if 0 - // Add this image to the viewer image list. - if (new_image->getDecodePriority() == 0.0f) - { - new_image->setDecodePriority(MAX_IMAGE_PRIORITY); // Initially put in front of list - } -#endif addImageToList(new_image); mUUIDMap[image_id] = new_image; } @@ -721,35 +623,6 @@ void LLViewerImageList::deleteImage(LLViewerImage *image) } } - - - -/////////////////////////////////////////////////////////////////////////////// - -void image_request_callback(void **data, S32 number) -{ - gImageList.handleIRCallback(data, number); -} - -void LLViewerImageList::handleIRCallback(void **data, const S32 number) -{ - callback_data_t* requested_images = (callback_data_t*)data; - if (number == LL_ERR_TCP_TIMEOUT) - { - for (callback_data_t::iterator iter = requested_images->begin(); - iter != requested_images->end();) - { - LLViewerImage* image = *iter++; - image->mRequested = FALSE; - image->mRequestedDiscardLevel = -1; // Indicates we need to re-request this - } - } - - // Delete and remove from our list of callback data - delete requested_images; - llverify(mIRCallbackData.erase(requested_images) == 1); -} - /////////////////////////////////////////////////////////////////////////////// void LLViewerImageList::updateMovieImage(const LLUUID& uuid, BOOL active) @@ -785,7 +658,16 @@ void LLViewerImageList::updateMovieImage(const LLUUID& uuid, BOOL active) } } -void LLViewerImageList::updateImages(const F32 decode_time_max) +//////////////////////////////////////////////////////////////////////////// + +void LLViewerImageList::dirtyImage(LLViewerImage *image) +{ + mDirtyTextureList.insert(image); +} + +//////////////////////////////////////////////////////////////////////////// + +void LLViewerImageList::updateImages(F32 max_time) { sNumImagesStat.addValue(sNumImages); sNumRawImagesStat.addValue(LLImageRaw::sRawImageCount); @@ -795,28 +677,40 @@ void LLViewerImageList::updateImages(const F32 decode_time_max) sFormattedMemStat.addValue(LLImageFormatted::sGlobalFormattedMemory/(1024.f*1024.f)); updateImagesDecodePriorities(); - updateImagesSendRequests(); - - if (gGLManager.mIsDisabled) + max_time -= updateImagesFetchTextures(max_time); + max_time = llmax(max_time, 0.001f); + max_time -= updateImagesCreateTextures(max_time); + max_time = llmax(max_time, 0.001f); + + if (!mDirtyTextureList.empty()) { - // We don't want to run this part of the texture system while we don't have - // a GL context - we COULD probably do some of it, but that's tricky - djs 10/29/03 - return; + LLFastTimer t(LLFastTimer::FTM_IMAGE_MARK_DIRTY); + gPipeline.dirtyPoolObjectTextures(mDirtyTextureList); + mDirtyTextureList.clear(); } - updateImagesDecodeTextures(decode_time_max); + for (image_list_t::iterator iter = mCallbackList.begin(); + iter != mCallbackList.end(); ) + { + LLViewerImage* image = *iter++; + // Do stuff to handle callbacks, update priorities, etc. + bool res = image->doLoadedCallbacks(); + if (res) + { + break; // only actually do one callback per frame + } + } + updateImagesMediaStreams(); - updateImagesPollVFS(); updateImagesUpdateStats(); } - void LLViewerImageList::updateImagesDecodePriorities() { // Update the decode priority for N images each frame { const size_t max_update_count = 256; - S32 update_counter = llmin(max_update_count, mUUIDMap.size()); + S32 update_counter = llmin(max_update_count, mUUIDMap.size()/10); uuid_map_t::iterator iter = mUUIDMap.upper_bound(mLastUpdateUUID); while(update_counter > 0) { @@ -826,6 +720,33 @@ void LLViewerImageList::updateImagesDecodePriorities() } mLastUpdateUUID = iter->first; LLPointer imagep = iter->second; + ++iter; // safe to incrament now + + // + // Flush formatted images using a lazy flush + // + const F32 LAZY_FLUSH_TIMEOUT = 30.f; + S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference + if (imagep->hasCallbacks()) + { + min_refs++; // Add an extra reference if we're on the loaded callback list + } + S32 num_refs = imagep->getNumRefs(); + if (num_refs == min_refs) + { + if (imagep->mLastReferencedTimer.getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) + { + // Remove the unused image from the image list + deleteImage(imagep); + imagep = NULL; // should destroy the image + continue; + } + } + else + { + imagep->mLastReferencedTimer.reset(); + } + imagep->processTextureStats(); F32 old_priority = imagep->getDecodePriority(); F32 decode_priority = imagep->calcDecodePriority(); @@ -836,12 +757,12 @@ void LLViewerImageList::updateImagesDecodePriorities() imagep->setDecodePriority(decode_priority); addImageToList(imagep); } - iter++; update_counter--; } } } +/* static U8 get_image_type(LLViewerImage* imagep, LLHost target_host) { // Having a target host implies this is a baked image. I don't @@ -866,478 +787,90 @@ static U8 get_image_type(LLViewerImage* imagep, LLHost target_host) } return type_from_host; } +*/ -void LLViewerImageList::updateImagesSendRequests() +F32 LLViewerImageList::updateImagesCreateTextures(F32 max_time) { - // Send requests for images based on priority. - { - S32 request_count = 0; - S32 request_packets_sent = 0; - S32 update_count = 0; + if (gNoRender || gGLManager.mIsDisabled) return 0.0f; - callback_data_t *requested_images = NULL; - - // Baked texture images may live on a separate host. JC - std::vector< LLPointer > images_on_other_hosts; - LLHost agent_host = gAgent.getRegionHost(); - - for (image_list_t::iterator iter = mImageList.begin(); - iter != mImageList.end(); ) - { - image_list_t::iterator curiter = iter++; - LLPointer imagep = *curiter; - - if (imagep->mIsMediaTexture) - { - continue; // skip - } - - F32 decode_priority = imagep->getDecodePriority(); - - update_count++; - if (mUpdateStats == FALSE && - update_count >= IMAGES_MIN_UPDATES && - decode_priority < MAX_IMAGE_PRIORITY) - { - break; - } - - // - // Flush formatted images using a lazy flush - // - const F32 LAZY_FLUSH_TIMEOUT = 30.f; - S32 min_refs = 3; // 1 for mImageList, 1 for mUUIDMap, 1 for local reference - if (imagep->hasCallbacks()) - { - min_refs++; // Add an extra reference if we're on the loaded callback list - } - S32 num_refs = imagep->getNumRefs(); - if (num_refs == min_refs) - { - if (!(imagep->isDecoding())) - { - if (imagep->mLastReferencedTimer.getElapsedTimeF32() > LAZY_FLUSH_TIMEOUT) - { - if (imagep->mStreamFile && !imagep->mStreamFile->isReadComplete()) - { - llwarns << "Stream file is still reading data, delaying flush!" << llendl; - } - else - { - // Remove the unused image from the image list - deleteImage(imagep); - imagep = NULL; // should destroy the image - continue; - } - } - } - } - else - { - imagep->mLastReferencedTimer.reset(); - } - - if (decode_priority <= 0) - { - continue; - } - if (imagep->isMissingAsset()) - { - continue; - } - if (imagep->checkPacketData()) - { - // New packets have been processed, re-evaluate next time - continue; - } - if (request_packets_sent >= IMAGES_MAX_PACKET_UPDATES) - { - continue; - } - if (!gAgent.getRegion()) - { - //llinfos << "Skipping request for " << imagep->getID() << " while waiting for a region" << llendl; - continue; - } - - F32 old_priority = imagep->mRequestedDownloadPriority; - S32 current_discard = imagep->getDiscardLevel(); - S32 desired_discard = imagep->getDesiredDiscardLevel(); - - if (current_discard >= 0 && current_discard <= desired_discard) - { - continue; - } - - if (imagep->mRequestTime.getElapsedTimeF32() <= RESEND_IMAGE_REQUEST_TIME) - { - // Ignore < 20% difference, or no change in requested discard level - if ((decode_priority > old_priority * .8f && decode_priority < old_priority * 1.25f) && - (desired_discard == imagep->mRequestedDiscardLevel)) - { - continue; - } - } - - // Send the request - { - // Baked avatar textures may live on other hosts. JC - LLHost target_host = imagep->getTargetHost(); - - // This file is in the static VFS, we don't ever need to request it from the network. - if (imagep->mInStaticVFS && imagep->mFormattedFlushed) - { - // Unneeded? JC 8/2006 - imagep->mRequestedDiscardLevel = desired_discard; - imagep->mRequestedDownloadPriority = decode_priority; - - // It's in the static VFS but not loaded, just load it from disk instead of sending a request. - imagep->startVFSLoad(); - } - else if (target_host.isOk() && target_host != agent_host) - { - // This is a special texture to request off a sim other than - // the one the agent is on. We'll deal with it later. - images_on_other_hosts.push_back(imagep); - } - else - { - imagep->mRequestedDiscardLevel = desired_discard; - imagep->mRequestedDownloadPriority = decode_priority; - - if (0 == request_count) - { - // Create a message if this is the first image request. - gMessageSystem->newMessageFast(_PREHASH_RequestImage); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast( - _PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast( - _PREHASH_SessionID, gAgent.getSessionID()); - requested_images = new callback_data_t; - // verify that requested_images is placed uniquely in the list - llverify((mIRCallbackData.insert(requested_images)).second); - } - - requested_images->push_back(imagep); - request_count++; - - gMessageSystem->nextBlockFast(_PREHASH_RequestImage); - S32 packet = imagep->getLastPacket() + 1; - gMessageSystem->addUUIDFast(_PREHASH_Image, imagep->getID()); - gMessageSystem->addS8Fast(_PREHASH_DiscardLevel, (S8)desired_discard); - gMessageSystem->addF32Fast(_PREHASH_DownloadPriority, decode_priority); - gMessageSystem->addU32Fast(_PREHASH_Packet, packet); - U8 type = get_image_type(imagep, target_host); - gMessageSystem->addU8Fast(_PREHASH_Type, type); - - lldebugst(LLERR_IMAGE) - << "IMAGE REQUEST: " << imagep->getID().getString() - << " discard: " << desired_discard - << " old_pri: " << old_priority - << " dld_pri: " << decode_priority - << " dec_pri: " << imagep->getDecodePriority() - << llendl; - - } - - imagep->mRequested = TRUE; - imagep->mRequestTime.reset(); - - if (request_count >= IMAGES_PER_REQUEST) - { - // IMAGES_PER_REQUEST packets combined, send packet. - gMessageSystem->sendSemiReliable(gAgent.getRegion()->getHost(), image_request_callback, (void **)requested_images); + // + // Create GL textures for all textures that need them (images which have been + // decoded, but haven't been pushed into GL). + // + LLFastTimer t(LLFastTimer::FTM_IMAGE_CREATE); - requested_images = NULL; - request_count = 0; - ++request_packets_sent; - } - } - } - - if (request_count != 0) - { - // fill in the unused requested_images w/ NULL - gMessageSystem->sendSemiReliable(gAgent.getRegion()->getHost(), image_request_callback, (void **)requested_images); - requested_images = NULL; - ++request_packets_sent; - } - - // We might have picked up some images on other hosts. - if (!images_on_other_hosts.empty()) + LLTimer create_timer; + image_list_t::iterator enditer = mCreateTextureList.begin(); + for (image_list_t::iterator iter = mCreateTextureList.begin(); + iter != mCreateTextureList.end();) + { + image_list_t::iterator curiter = iter++; + enditer = iter; + LLViewerImage *imagep = *curiter; + imagep->createTexture(); + if (create_timer.getElapsedTimeF32() > max_time) { - // llinfos << "TAT: images_on_other_hosts " << images_on_other_hosts.size() << llendl; - - std::sort(images_on_other_hosts.begin(), images_on_other_hosts.end(), LLViewerImage::CompareByHostAndPriority()); - - LLMessageSystem* msg = gMessageSystem; - LLHost current_host = images_on_other_hosts[0]->getTargetHost(); - request_count = 0; - - for (std::vector >::iterator it = images_on_other_hosts.begin(); - it != images_on_other_hosts.end(); - ++it) - { - LLPointer imagep = *it; - - F32 decode_priority = imagep->getDecodePriority(); - S32 desired_discard = imagep->getDesiredDiscardLevel(); - - imagep->mRequestedDiscardLevel = desired_discard; - imagep->mRequestedDownloadPriority = decode_priority; - - if ((current_host != imagep->getTargetHost() || request_count >= IMAGES_PER_REQUEST) && request_count) - { - // llinfos << "TAT: Sending " << request_count << " image requests for host: " << current_host << llendl; - - // Need to flush to current host. - gMessageSystem->sendSemiReliable(current_host, image_request_callback, (void **)requested_images); - - requested_images = NULL; - current_host = imagep->getTargetHost(); - request_count = 0; - } - - if (request_count == 0) - { - // Start a packet and build a new callback list for dropped - // packet handler. - msg->newMessageFast(_PREHASH_RequestImage); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - requested_images = new callback_data_t; - mIRCallbackData.insert(requested_images); - current_host = imagep->getTargetHost(); - } - - requested_images->push_back(imagep); - request_count++; - - msg->nextBlockFast(_PREHASH_RequestImage); - S32 packet = imagep->getLastPacket() + 1; - msg->addUUIDFast(_PREHASH_Image, imagep->getID()); - msg->addS8Fast(_PREHASH_DiscardLevel, (S8)desired_discard); - msg->addF32Fast(_PREHASH_DownloadPriority, decode_priority); - msg->addU32Fast(_PREHASH_Packet, packet); - U8 type = get_image_type(imagep, current_host); - gMessageSystem->addU8Fast(_PREHASH_Type, type); - - if (!gMessageSystem->checkCircuitAlive(current_host)) - { - llinfos << "TAT: Image request for dead circuit " << current_host << ", " << imagep->getID() << llendl; - imagep->setTargetHost(agent_host); - } - - if (!gMessageSystem->checkCircuitAlive(current_host)) - { - llinfos << "TAT: Image request for dead circuit " << current_host << ", " << imagep->getID() << llendl; - imagep->setTargetHost(agent_host); - } - - imagep->mRequested = TRUE; - imagep->mRequestTime.reset(); - } - - if (request_count != 0) - { - // fill in the unused requested_images w/ NULL - msg->sendSemiReliable(current_host, image_request_callback, (void **)requested_images); - requested_images = NULL; - } + break; } } + mCreateTextureList.erase(mCreateTextureList.begin(), enditer); + return create_timer.getElapsedTimeF32(); } - - -void LLViewerImageList::updateImagesDecodeTextures(F32 decode_time_max) +F32 LLViewerImageList::updateImagesFetchTextures(F32 max_time) { - if (gNoRender) return; - - LLTimer image_op_timer; - - BOOL done_one = FALSE; - image_op_timer.reset(); - - S32 create_count = 0; - - // added by IW to help track down a bug - stop_glerror(); - - // - // Create GL textures for all textures that need them (images which have been - // decoded, but haven't been pushed into GL). - // - { - LLFastTimer t(LLFastTimer::FTM_IMAGE_CREATE); - - for (image_list_t::iterator iter = mImageList.begin(); - iter != mImageList.end(); ) - { - LLPointer imagep = *iter++; - if (imagep->getNeedsCreateTexture()) - { - create_count++; - imagep->createTexture(); - if (decode_time_max != 0.f) - { - if (image_op_timer.getElapsedTimeF32() > decode_time_max) - { - lldebugst(LLERR_IMAGE) << "Broke out of create texture!" << llendl; - break; - } - } - } - } - } - - // - // Work on decoding any image that's partially decoded, first - // - // Everything after here is time-sliced - // - - if (mCurrentDecodeImagep.notNull() - && mCurrentDecodeImagep->needsDecode() - && mCurrentDecodeImagep->isDecoding()) - { - //llinfos << "Continue decoding " << mCurrentDecodeImagep->getID() << llendl; - LLFastTimer t(LLFastTimer::FTM_IMAGE_DECODE); - if (decode_time_max != 0.f) - { - if (done_one && image_op_timer.getElapsedTimeF32() >= decode_time_max) - { - lldebugst(LLERR_IMAGE) << "Broke out of partial decode!" << llendl; - } - else - { - F32 decode_time = decode_time_max - image_op_timer.getElapsedTimeF32(); - decode_time = llmax(decode_time, .0001f); // min .1 ms - mCurrentDecodeImagep->decodeImage(decode_time); // Partial decode - done_one = TRUE; - } - } - else - { - mCurrentDecodeImagep->decodeImage(0.0f); // Partial decode - done_one = TRUE; - } - } - - // - // Reprioritize any image that we just finished decoding - // - if (mCurrentDecodeImagep.notNull() - && (!mCurrentDecodeImagep->needsDecode() - || !mCurrentDecodeImagep->isDecoding())) + LLTimer image_op_timer; + + // Update the decode priority for N images each frame + // Make a list with 32 high priority entries + 256 cycled entries + const size_t max_priority_count = 32; + const size_t max_update_count = 256; + + // 32 high priority entries + std::set entries; + size_t update_counter = llmin(max_priority_count, mImageList.size()); + image_priority_list_t::iterator iter1 = mImageList.begin(); + while(update_counter > 0) + { + entries.insert(*iter1); + ++iter1; + update_counter--; + } + + // 256 cycled entries + update_counter = llmin(max_update_count, mUUIDMap.size()); + uuid_map_t::iterator iter2 = mUUIDMap.upper_bound(mLastFetchUUID); + while(update_counter > 0) + { + if (iter2 == mUUIDMap.end()) { - // Reprioritize this image - if (mCurrentDecodeImagep->mInImageList) - { - removeImageFromList(mCurrentDecodeImagep); - mCurrentDecodeImagep->setDecodePriority(); - addImageToList(mCurrentDecodeImagep); - } - mCurrentDecodeImagep = NULL; + iter2 = mUUIDMap.begin(); } + mLastFetchUUID = iter2->first; + entries.insert(iter2->second); + ++iter2; + update_counter--; + } - // - // At this point, we're going to check out the status of anything that's - // on our callback list. Instead of calling the callback lists from a - // billion different places, we're ONLY going to handle them here. - // - // Do this here so if the callbacks take a lot of time, it counts - // against our decode timer totals - - // For right now, just be really lame and just iterate through all images. - // This WILL be optimized soon. - - if (mUpdateStats) - { - // This is somewhat intensive, and it doesn't need to happen - // immediately, so only do it when we update stats. - for (image_callback_list_t::iterator iter = mCallbackList.begin(); - iter != mCallbackList.end(); ) - { - LLViewerImage* image = *iter++; - // Do stuff to handle callbacks, update priorities, etc. - image->doLoadedCallbacks(); - } - } + S32 min_count = max_priority_count + max_update_count/4; + for (std::set::iterator iter3 = entries.begin(); + iter3 != entries.end(); ) + { + LLPointer imagep = *iter3++; - // - // Decode as many images as we can at this point. - // If we're in the middle of finishing up one still, - // don't decode any more textures - // - if (mCurrentDecodeImagep.isNull() || mCurrentDecodeImagep->getBoostLevel()) + imagep->updateFetch(); + if (min_count <= 0 && image_op_timer.getElapsedTimeF32() > max_time) { - LLFastTimer t(LLFastTimer::FTM_IMAGE_DECODE); - do - { - BOOL did_decode = FALSE; - BOOL have_map_image = FALSE; - for (image_list_t::iterator iter = mImageList.begin(); - iter != mImageList.end(); ) - { - image_list_t::iterator curiter = iter++; - LLPointer imagep = *curiter; - if (imagep->needsDecode()) - { - if (decode_time_max != 0.f) - { - if (!imagep->getBoostLevel() && done_one && - image_op_timer.getElapsedTimeF32() >= decode_time_max) - { - break; - } - F32 decode_time = decode_time_max - image_op_timer.getElapsedTimeF32(); - decode_time = llmax(decode_time, .0001f); // min .1 ms - imagep->decodeImage(decode_time); - } - else - { - imagep->decodeImage(0.0f); - } - - if (imagep->needsDecode()) - { - mCurrentDecodeImagep = imagep; - } - else - { - // Reprioritize this image - removeImageFromList(imagep); - imagep->setDecodePriority(); - addImageToList(imagep); - - mCurrentDecodeImagep = NULL; - } - done_one = TRUE; - did_decode = TRUE; - } - if (imagep->getBoostLevel() >= LLViewerImage::BOOST_MAP) - { - have_map_image = TRUE; - } - else if (have_map_image) - { - break; // skip other images if we are decoding map images - } - } - if (!did_decode) - { - break; - } - } while (image_op_timer.getElapsedTimeF32() < decode_time_max); + break; } + min_count--; + } + return image_op_timer.getElapsedTimeF32(); } void LLViewerImageList::updateImagesMediaStreams() { - if (gNoRender) return; + if (gNoRender || gGLManager.mIsDisabled) return; // update media stream if required LLMediaEngine* media_engine = LLMediaEngine::getInstance(); @@ -1358,8 +891,6 @@ void LLViewerImageList::updateImagesMediaStreams() (renderer->getTextureDepth() != viewerImage->getComponents()) || (viewerImage->getHasGLTexture() == FALSE)) { - llassert(!viewerImage->getUseMipMaps()); - // destroy existing GL image viewerImage->destroyGLTexture(); @@ -1380,14 +911,15 @@ void LLViewerImageList::updateImagesMediaStreams() renderer->getTextureFormatPrimary(), renderer->getTextureFormatType(), renderer->getTextureFormatSwapBytes()); + // This should be redundant, but just in case: + viewerImage->setUseMipMaps(FALSE); LLImageRaw* rawImage = media_engine->getImageRaw(); - if ( rawImage ) { - ((LLImageGL*)viewerImage)->setSubImage(rawImage, 0, 0, - renderer->getMediaWidth(), - renderer->getMediaHeight()); + viewerImage->setSubImage(rawImage, 0, 0, + renderer->getMediaWidth(), + renderer->getMediaHeight()); } } else @@ -1404,89 +936,76 @@ void LLViewerImageList::updateImagesMediaStreams() } } -void LLViewerImageList::updateImagesPollVFS() -{ - // Sigh, VFS stuff has to be polled. The VFS really needs some sort - // of mechanism to avoid this issue. - for (image_loading_list_t::iterator iter = mLoadingStreamList.begin(); - iter != mLoadingStreamList.end();) - { - image_loading_list_t::iterator curiter = iter++; - LLViewerImage *imagep = *curiter; - imagep->loadStreamFile(); - if (!imagep->mStreamFile) - { - iter = mLoadingStreamList.erase(curiter); - } - } -} - void LLViewerImageList::updateImagesUpdateStats() { if (mUpdateStats) { - for (image_list_t::iterator iter = mImageList.begin(); + for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerImage* imagep = *iter++; imagep->resetTextureStats(mForceResetTextureStats); } -#if 0 - S32 needs_decode_count = 0; - for (image_list_t::iterator iter = mImageList.begin(); - iter != mImageList.end(); ) - { - LLViewerImage* imagep = *iter++; - // count priority images in need of decode (10000 ~= 100x100 pixels) - if (imagep->getDecodePriority() > 10000.f && (imagep->needsDecode() || imagep->getNeedsCreateTexture())) - { - needs_decode_count++; - } - } - - // If we have a lot of priority decodes pending, take some time to decode them - const S32 force_decode_count = 20; - const F32 force_decode_time = 2.f; // seconds - const F32 force_decode_delay = 30.f; // seconds - if (needs_decode_count > force_decode_count && mForceDecodeTimer.hasExpired()) - { - decodeAllImages(force_decode_time); // spend some time decoding images - mForceDecodeTimer.setTimerExpirySec(force_decode_delay); // wait 10 seconds - } -#endif mUpdateStats = FALSE; mForceResetTextureStats = FALSE; } } -void LLViewerImageList::decodeAllImages(F32 max_decode_time) +void LLViewerImageList::decodeAllImages(F32 max_time) { LLTimer timer; if(!gNoRender) { - for (image_list_t::iterator iter = mImageList.begin(); + // Update texture stats and priorities + std::vector > image_list; + for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerImage* imagep = *iter++; - if (imagep->needsDecode()) - { - imagep->decodeImage(0.f); // LLViewerImageList::decodeAllImages - } - if (max_decode_time > 0.0f && timer.getElapsedTimeF32() > max_decode_time) + image_list.push_back(imagep); + imagep->mInImageList = FALSE; + } + mImageList.clear(); + for (std::vector >::iterator iter = image_list.begin(); + iter != image_list.end(); ++iter) + { + LLViewerImage* imagep = *iter; + imagep->processTextureStats(); + F32 decode_priority = imagep->calcDecodePriority(); + imagep->setDecodePriority(decode_priority); + mImageList.insert(imagep); + imagep->mInImageList = TRUE; + } + image_list.clear(); + + // Update fetch (decode) + for (image_priority_list_t::iterator iter = mImageList.begin(); + iter != mImageList.end(); ) + { + LLViewerImage* imagep = *iter++; + imagep->updateFetch(); + } + // Run threads + while (1) + { + gTextureCache->update(1); // unpauses the texture cache thread + gImageDecodeThread->update(1); // unpauses the image thread + S32 fetch_pending = gTextureFetch->update(1); // unpauses the texture fetch thread + if (fetch_pending == 0 || timer.getElapsedTimeF32() > max_time) { break; } } - - for (image_list_t::iterator iter = mImageList.begin(); + // Update fetch again + for (image_priority_list_t::iterator iter = mImageList.begin(); iter != mImageList.end(); ) { LLViewerImage* imagep = *iter++; - if (imagep->getNeedsCreateTexture()) - { - imagep->createTexture(); - } + imagep->updateFetch(); } + max_time -= timer.getElapsedTimeF32(); + max_time = llmax(max_time, .01f); + updateImagesCreateTextures(max_time); } if (timer.getElapsedTimeF32() > .5f) // seconds { @@ -1560,12 +1079,8 @@ BOOL LLViewerImageList::createUploadFile(const LLString& filename, return FALSE; } - raw_image->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT); - - LLPointer compressedImage = new LLImageJ2C; + LLPointer compressedImage = convertToUploadFile(raw_image); - compressedImage->setRate(0.f); - compressedImage->encode(raw_image); if( !compressedImage->save(out_filename) ) { llinfos << "Couldn't create output file " << out_filename << llendl; @@ -1583,6 +1098,17 @@ BOOL LLViewerImageList::createUploadFile(const LLString& filename, return TRUE; } +// note: modifies the argument raw_image!!!! +LLPointer LLViewerImageList::convertToUploadFile(LLPointer raw_image) +{ + raw_image->biasedScaleToPowerOfTwo(LLViewerImage::MAX_IMAGE_SIZE_DEFAULT); + LLPointer compressedImage = new LLImageJ2C(); + compressedImage->setRate(0.f); + compressedImage->encode(raw_image); + + return compressedImage; +} + //static S32 LLViewerImageList::getMaxVideoRamSetting(S32 max) { @@ -1606,7 +1132,7 @@ S32 LLViewerImageList::getMaxVideoRamSetting(S32 max) llwarns << "VRAM amount not detected, defaulting to " << max_vram/(double)(1<<20) << " MB" << llendl; } U32 system_ram = gSysMemory.getPhysicalMemory(); - llinfos << "*** DETECTED " << system_ram/(double)(1<<20) << " MB of system memory." << llendl; // TomY TESTING DNCI + //llinfos << "*** DETECTED " << system_ram/(double)(1<<20) << " MB of system memory." << llendl; // TomY TESTING DNCI if (max == -2) { max_vram = llmin(max_vram, (U32)(system_ram/2)); // max recommended setting @@ -1629,6 +1155,16 @@ S32 LLViewerImageList::getMaxVideoRamSetting(S32 max) return idx; } +const S32 VIDEO_CARD_MEM_SIZES[6] = { 0x1000000, // 16MB + 0x2000000, // 32MB + 0x4000000, // 64MB + 0x8000000, // 128MB + 0x10000000, // 256MB + 0x20000000, // 512MB + }; + +const S32 VIDEO_CARD_FRAMEBUFFER_MEM = 0xC00000; // 12MB + void LLViewerImageList::updateMaxResidentTexMem(S32 max, U32 fudge) { // Initialize the image pipeline VRAM settings @@ -1651,15 +1187,127 @@ void LLViewerImageList::updateMaxResidentTexMem(S32 max, U32 fudge) } mVideoMemorySetting = cur_setting; // TODO: set available resident texture mem based on use by other subsystems - // currently 12MB assumed... + // currently max(12MB, VRAM/4) assumed... + + S32 vram_amt = VIDEO_CARD_MEM_SIZES[cur_setting]; + S32 fb_mem = llmax(VIDEO_CARD_FRAMEBUFFER_MEM, vram_amt/4); + mMaxResidentTexMem = vram_amt - fb_mem - fudge; - mMaxResidentTexMem = VIDEO_CARD_MEM_SIZES[cur_setting] - 0xC00000 - fudge; // - 12MB - mMaxResidentTexMem -= mMaxResidentTexMem/8; +// llinfos << "Graphics Card memory set to " << (VIDEO_CARD_MEM_SIZES[cur_setting]>>20) +// << " MB" << llendl; +} + +/////////////////////////////////////////////////////////////////////////////// + +// static +void LLViewerImageList::receiveImageHeader(LLMessageSystem *msg, void **user_data) +{ + LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + + // Receive image header, copy into image object and decompresses + // if this is a one-packet image. + + LLUUID id; + + char ip_string[256]; + u32_to_ip_string(msg->getSenderIP(),ip_string); + + if (msg->getReceiveCompressedSize()) + { + gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8; + } + else + { + gImageList.sTextureBits += msg->getReceiveSize() * 8; + } + gImageList.sTexturePackets++; + + U8 codec; + U16 packets; + U32 totalbytes; + msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); + msg->getU8Fast(_PREHASH_ImageID, _PREHASH_Codec, codec); + msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packets, packets); + msg->getU32Fast(_PREHASH_ImageID, _PREHASH_Size, totalbytes); + + U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); + if (!data_size) + { + return; + } - llinfos << "Graphics Card memory set to " << (VIDEO_CARD_MEM_SIZES[cur_setting]>>20) - << " MB" << llendl; + // this buffer gets saved off in the packet list + U8 *data = new U8[data_size]; + msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); + + LLViewerImage *image = gImageList.getImage(id); + if (!image) + { + return; + } + image->mLastPacketTimer.reset(); + bool res = gTextureFetch->receiveImageHeader(msg->getSender(), id, codec, packets, totalbytes, data_size, data); + if (!res) + { + delete[] data; + } } +// static +void LLViewerImageList::receiveImagePacket(LLMessageSystem *msg, void **user_data) +{ + LLMemType mt1(LLMemType::MTYPE_APPFMTIMAGE); + LLFastTimer t(LLFastTimer::FTM_PROCESS_IMAGES); + + // Receives image packet, copy into image object, + // checks if all packets received, decompresses if so. + + LLUUID id; + U16 packet_num; + + char ip_string[256]; + u32_to_ip_string(msg->getSenderIP(),ip_string); + + if (msg->getReceiveCompressedSize()) + { + gImageList.sTextureBits += msg->getReceiveCompressedSize() * 8; + } + else + { + gImageList.sTextureBits += msg->getReceiveSize() * 8; + } + gImageList.sTexturePackets++; + + //llprintline("Start decode, image header..."); + msg->getUUIDFast(_PREHASH_ImageID, _PREHASH_ID, id); + msg->getU16Fast(_PREHASH_ImageID, _PREHASH_Packet, packet_num); + U16 data_size = msg->getSizeFast(_PREHASH_ImageData, _PREHASH_Data); + + if (!data_size) + { + return; + } + if (data_size > MTUBYTES) + { + llerrs << "image data chunk too large: " << data_size << " bytes" << llendl; + } + U8 *data = new U8[data_size]; + msg->getBinaryDataFast(_PREHASH_ImageData, _PREHASH_Data, data, data_size); + + LLViewerImage *image = gImageList.getImage(id); + if (!image) + { + return; + } + image->mLastPacketTimer.reset(); + bool res = gTextureFetch->receiveImagePacket(msg->getSender(), id, packet_num, data_size, data); + if (!res) + { + delete[] data; + } +} + + // We've been that the asset server does not contain the requested image id. // static void LLViewerImageList::processImageNotInDatabase(LLMessageSystem *msg,void **user_data) @@ -1671,6 +1319,26 @@ void LLViewerImageList::processImageNotInDatabase(LLMessageSystem *msg,void **us LLViewerImage* image = gImageList.hasImage( image_id ); if( image ) { - image->setIsMissingAsset( TRUE ); + image->setIsMissingAsset(); } } + +/////////////////////////////////////////////////////////////////////////////// + +//static +const U32 SIXTEEN_MEG = 0x1000000; +S32 LLViewerImageList::calcMaxTextureRAM() +{ + // Decide the maximum amount of RAM we should allow the user to allocate to texture cache + LLMemoryInfo memory_info; + U32 available_memory = memory_info.getPhysicalMemory(); + + clamp_rescale((F32)available_memory, + (F32)(SIXTEEN_MEG * 16), + (F32)U32_MAX, + (F32)(SIXTEEN_MEG * 4), + (F32)(U32_MAX >> 1)); + return available_memory; +} + +/////////////////////////////////////////////////////////////////////////////// diff --git a/linden/indra/newview/llviewerimagelist.h b/linden/indra/newview/llviewerimagelist.h index 68cfcaf..3f3e521 100644 --- a/linden/indra/newview/llviewerimagelist.h +++ b/linden/indra/newview/llviewerimagelist.h @@ -58,12 +58,17 @@ typedef void (*LLImageCallback)(BOOL success, class LLViewerImageList : public LLImageProviderInterface { + LOG_CLASS(LLViewerImageList); + friend class LLTextureView; public: static BOOL createUploadFile(const LLString& filename, const LLString& out_filename, const U8 codec); + static LLPointer convertToUploadFile(LLPointer raw_image); static void processImageNotInDatabase( LLMessageSystem *msg, void **user_data ); static S32 calcMaxTextureRAM(); + static void receiveImageHeader(LLMessageSystem *msg, void **user_data); + static void receiveImagePacket(LLMessageSystem *msg, void **user_data); public: LLViewerImageList(); @@ -117,12 +122,13 @@ public: void removeImageFromList(LLViewerImage *image); void updateMovieImage(const LLUUID& image_id, BOOL active); + void dirtyImage(LLViewerImage *image); // Using image stats, determine what images are necessary, and perform image updates. - void updateImages(F32 decode_time); + void updateImages(F32 max_time); // Decode and create textures for all images currently in list. - void decodeAllImages(F32 max_decode_time = 0.f); + void decodeAllImages(F32 max_decode_time); void handleIRCallback(void **data, const S32 number); @@ -136,40 +142,35 @@ public: void updateMaxResidentTexMem(S32 max = -1, U32 fudge = 0); void doPreloadImages(); + void doPrefetchImages(); private: LLViewerImage* preloadImage(const LLString& filename, const LLUUID &image_set_id, BOOL use_mips); void updateImagesDecodePriorities(); - void updateImagesSendRequests(); - void updateImagesDecodeTextures(F32 decode_max_time); + F32 updateImagesCreateTextures(F32 max_time); + F32 updateImagesFetchTextures(F32 max_time); void updateImagesMediaStreams(); - void updateImagesPollVFS(); void updateImagesUpdateStats(); public: - typedef std::set, LLViewerImage::Compare> image_list_t; - typedef std::set, LLViewerImage::CompareForRemoval> image_removal_list_t; - typedef std::set, LLViewerImage::CompareForWorstVisibility> image_visibility_list_t; - - // List of pending texture loads, waiting for the VFS. - // The asynchronous read has been initiated for all images in the list. - typedef std::list > image_loading_list_t; - image_loading_list_t mLoadingStreamList; - - // Images with "loaded" callbacks - typedef std::set > image_callback_list_t; - image_callback_list_t mCallbackList; + typedef std::set > image_list_t; + image_list_t mLoadingStreamList; + image_list_t mCreateTextureList; + image_list_t mCallbackList; + // Note: just raw pointers because they are never referenced, just compared against + std::set mDirtyTextureList; + BOOL mForceResetTextureStats; private: typedef std::map< LLUUID, LLPointer > uuid_map_t; uuid_map_t mUUIDMap; LLUUID mLastUpdateUUID; + LLUUID mLastFetchUUID; - image_list_t mImageList; - - LLPointer mCurrentDecodeImagep; + typedef std::set, LLViewerImage::Compare> image_priority_list_t; + image_priority_list_t mImageList; typedef std::vector > callback_data_t; typedef std::set< callback_data_t* > callback_data_list_t; diff --git a/linden/indra/newview/llviewerinventory.cpp b/linden/indra/newview/llviewerinventory.cpp index 487a9f8..7c12f56 100644 --- a/linden/indra/newview/llviewerinventory.cpp +++ b/linden/indra/newview/llviewerinventory.cpp @@ -268,7 +268,7 @@ bool LLViewerInventoryItem::importFileLocal(FILE* fp) bool LLViewerInventoryItem::exportFileLocal(FILE* fp) const { - char uuid_str[UUID_STR_LENGTH]; + char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ fprintf(fp, "\tinv_item\t0\n\t{\n"); mUUID.toString(uuid_str); fprintf(fp, "\t\titem_id\t%s\n", uuid_str); @@ -450,16 +450,17 @@ bool LLViewerInventoryCategory::fetchDescendents() bool LLViewerInventoryCategory::importFileLocal(FILE* fp) { // *NOTE: This buffer size is hard coded into scanf() below. - char buffer[MAX_STRING]; - char keyword[MAX_STRING]; - char valuestr[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ + char keyword[MAX_STRING]; /* Flawfinder: ignore */ + char valuestr[MAX_STRING]; /* Flawfinder: ignore */ keyword[0] = '\0'; valuestr[0] = '\0'; while(!feof(fp)) { fgets(buffer, MAX_STRING, fp); - sscanf(buffer, " %254s %254s", keyword, valuestr); + sscanf( /* Flawfinder: ignore */ + buffer, " %254s %254s", keyword, valuestr); if(!keyword) { continue; @@ -492,7 +493,8 @@ bool LLViewerInventoryCategory::importFileLocal(FILE* fp) { //strcpy(valuestr, buffer + strlen(keyword) + 3); // *NOTE: Not ANSI C, but widely supported. - sscanf(buffer, " %254s %254[^|]", keyword, valuestr); + sscanf( /* Flawfinder: ignore */ + buffer, " %254s %254[^|]", keyword, valuestr); mName.assign(valuestr); LLString::replaceNonstandardASCII(mName, ' '); LLString::replaceChar(mName, '|', ' '); @@ -516,7 +518,7 @@ bool LLViewerInventoryCategory::importFileLocal(FILE* fp) bool LLViewerInventoryCategory::exportFileLocal(FILE* fp) const { - char uuid_str[UUID_STR_LENGTH]; + char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ fprintf(fp, "\tinv_category\t0\n\t{\n"); mUUID.toString(uuid_str); fprintf(fp, "\t\tcat_id\t%s\n", uuid_str); @@ -672,7 +674,7 @@ void copy_inventory_item( msg->addUUIDFast(_PREHASH_OldAgentID, current_owner); msg->addUUIDFast(_PREHASH_OldItemID, item_id); msg->addUUIDFast(_PREHASH_NewFolderID, parent_id); - msg->addString("NewName", new_name); + msg->addStringFast(_PREHASH_NewName, new_name); gAgent.sendReliableMessage(); } @@ -689,11 +691,11 @@ void move_inventory_item( msg->nextBlockFast(_PREHASH_AgentData); msg->addUUIDFast(_PREHASH_AgentID, agent_id); msg->addUUIDFast(_PREHASH_SessionID, session_id); - msg->addBOOLFast(_PREHASH_Stamp, false); + msg->addBOOLFast(_PREHASH_Stamp, FALSE); msg->nextBlockFast(_PREHASH_InventoryData); msg->addUUIDFast(_PREHASH_ItemID, item_id); msg->addUUIDFast(_PREHASH_FolderID, parent_id); - msg->addString("NewName", new_name); + msg->addStringFast(_PREHASH_NewName, new_name); gAgent.sendReliableMessage(); } diff --git a/linden/indra/newview/llviewerjoint.cpp b/linden/indra/newview/llviewerjoint.cpp index f8fed01..a1294be 100644 --- a/linden/indra/newview/llviewerjoint.cpp +++ b/linden/indra/newview/llviewerjoint.cpp @@ -101,10 +101,10 @@ void LLViewerJoint::setValid( BOOL valid, BOOL recursive ) //---------------------------------------------------------------- if (recursive) { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); joint->setValid(valid, TRUE); } } @@ -217,10 +217,10 @@ void LLViewerJoint::renderSkeleton(BOOL recursive) //---------------------------------------------------------------- if (recursive) { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); joint->renderSkeleton(); } } @@ -235,7 +235,7 @@ void LLViewerJoint::renderSkeleton(BOOL recursive) //-------------------------------------------------------------------- // render() //-------------------------------------------------------------------- -U32 LLViewerJoint::render( F32 pixelArea ) +U32 LLViewerJoint::render( F32 pixelArea, BOOL first_pass ) { U32 triangle_count = 0; @@ -245,73 +245,68 @@ U32 LLViewerJoint::render( F32 pixelArea ) if ( mValid ) { + //---------------------------------------------------------------- // if object is transparent, defer it, otherwise // give the joint subclass a chance to draw itself //---------------------------------------------------------------- if ( gRenderForSelect ) { - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, first_pass ); } else if ( isTransparent() ) { - LLGLEnable blend(GL_BLEND); // Hair and Skirt if ((pixelArea > MIN_PIXEL_AREA_3PASS_HAIR)) { // render all three passes - LLGLEnable alpha_test(GL_ALPHA_TEST); LLGLDisable cull(GL_CULL_FACE); // first pass renders without writing to the z buffer { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, first_pass); } // second pass writes to z buffer only glColorMask(FALSE, FALSE, FALSE, FALSE); { - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, FALSE ); } // third past respects z buffer and writes color glColorMask(TRUE, TRUE, TRUE, TRUE); { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, FALSE ); } } else { - LLGLEnable alpha_test(GL_ALPHA_TEST); // Render Inside (no Z buffer write) glCullFace(GL_FRONT); { LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, first_pass ); } // Render Outside (write to the Z buffer) glCullFace(GL_BACK); { - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, FALSE ); } } } else { // set up render state - LLGLDisable blend(GL_BLEND); - LLGLSPipelineAvatar gls_pipeline_avatar; - triangle_count += drawShape( pixelArea ); + triangle_count += drawShape( pixelArea, first_pass ); } } //---------------------------------------------------------------- // render children //---------------------------------------------------------------- - LLViewerJoint *joint; - for ( joint = (LLViewerJoint *)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint *)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); F32 jointLOD = joint->getLOD(); if (pixelArea >= jointLOD || sDisableLOD) { @@ -324,7 +319,6 @@ U32 LLViewerJoint::render( F32 pixelArea ) } } - glColorMask(TRUE, TRUE, TRUE, TRUE); return triangle_count; } @@ -396,7 +390,7 @@ BOOL LLViewerJoint::isTransparent() //-------------------------------------------------------------------- // drawShape() //-------------------------------------------------------------------- -U32 LLViewerJoint::drawShape( F32 pixelArea ) +U32 LLViewerJoint::drawShape( F32 pixelArea, BOOL first_pass ) { return 0; } @@ -409,65 +403,75 @@ void LLViewerJoint::setSkeletonComponents( U32 comp, BOOL recursive ) mComponents = comp; if (recursive) { - for ( LLViewerJoint *joint = (LLViewerJoint *)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint *)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); joint->setSkeletonComponents(comp, recursive); } } } -void LLViewerJoint::updateFaceSizes(U32 &num_vertices, F32 pixel_area) +void LLViewerJoint::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { - F32 jointLOD = joint->getLOD(); - if (pixel_area >= jointLOD || sDisableLOD) + LLViewerJoint* joint = (LLViewerJoint*)(*iter); + //F32 jointLOD = joint->getLOD(); + //if (pixel_area >= jointLOD || sDisableLOD) { - joint->updateFaceSizes(num_vertices, pixel_area); + joint->updateFaceSizes(num_vertices, num_indices, pixel_area); - if (jointLOD != DEFAULT_LOD) - { - break; - } + // if (jointLOD != DEFAULT_LOD) + // { + // break; + // } } } } void LLViewerJoint::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { - F32 jointLOD = joint->getLOD(); - if (pixel_area >= jointLOD || sDisableLOD) + LLViewerJoint* joint = (LLViewerJoint*)(*iter); + //F32 jointLOD = joint->getLOD(); + //if (pixel_area >= jointLOD || sDisableLOD) { joint->updateFaceData(face, pixel_area, damp_wind); - if (jointLOD != DEFAULT_LOD) - { - break; - } + // if (jointLOD != DEFAULT_LOD) + // { + // break; + // } } } } +void LLViewerJoint::updateGeometry() +{ + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); + joint->updateGeometry(); + } +} + BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate) { BOOL lod_changed = FALSE; BOOL found_lod = FALSE; - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); F32 jointLOD = joint->getLOD(); - + if (found_lod || jointLOD == DEFAULT_LOD) { // we've already found a joint to enable, so enable the rest as alternatives @@ -491,12 +495,12 @@ BOOL LLViewerJoint::updateLOD(F32 pixel_area, BOOL activate) void LLViewerJoint::dump() { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) - { - joint->dump(); - } + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); + joint->dump(); + } } void LLViewerJoint::setVisible(BOOL visible, BOOL recursive) @@ -505,12 +509,12 @@ void LLViewerJoint::setVisible(BOOL visible, BOOL recursive) if (recursive) { - for ( LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) - { - joint->setVisible(visible, recursive); - } + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) + { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); + joint->setVisible(visible, recursive); + } } } @@ -530,10 +534,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp) LLQuaternion bone_rot; S32 num_children = 0; - for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); if (joint->mJointNum != -1) { num_children++; @@ -560,10 +564,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp) apr_file_printf(fp, " 0 0 0 1\n"); apr_file_printf(fp, " %d\n", mParent ? mParent->mJointNum + 1 : -1); - for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); if (joint->mJointNum != -1) { apr_file_printf(fp, " %d\n", joint->mJointNum + 1); @@ -572,10 +576,10 @@ void LLViewerJoint::writeCAL3D(apr_file_t* fp) apr_file_printf(fp, " \n"); // recurse - for (LLViewerJoint *joint = (LLViewerJoint*)mChildren.getFirstData(); - joint != NULL; - joint = (LLViewerJoint*)mChildren.getNextData() ) + for (child_list_t::iterator iter = mChildren.begin(); + iter != mChildren.end(); ++iter) { + LLViewerJoint* joint = (LLViewerJoint*)(*iter); if (joint->mJointNum != -1) { joint->writeCAL3D(fp); diff --git a/linden/indra/newview/llviewerjoint.h b/linden/indra/newview/llviewerjoint.h index 44ad8e7..148f3a6 100644 --- a/linden/indra/newview/llviewerjoint.h +++ b/linden/indra/newview/llviewerjoint.h @@ -62,7 +62,7 @@ public: // Traverses the entire joint hierarchy, setting up // transforms and calling the drawShape(). // Derived classes may add text/graphic output. - virtual U32 render( F32 pixelArea ); // Returns triangle count + virtual U32 render( F32 pixelArea, BOOL first_pass = TRUE ); // Returns triangle count // Draws a bone graphic to the parent joint. // Derived classes may add text/graphic output. @@ -78,7 +78,7 @@ public: // Draws the shape attached to a joint. // Called by render(). - virtual U32 drawShape( F32 pixelArea ); + virtual U32 drawShape( F32 pixelArea, BOOL first_pass = TRUE ); virtual void drawNormals() {} enum Components @@ -97,9 +97,9 @@ public: // Sets the level of detail for this node as a minimum // pixel area threshold. If the current pixel area for this // object is less than the specified threshold, the node is - // not traversed. In additin, if a value is specified (not + // not traversed. In addition, if a value is specified (not // default of 0.0), and the pixel area is larger than the - // specified miniumn, the node is rendered, but no other siblings + // specified minimum, the node is rendered, but no other siblings // of this node under the same parent will be. F32 getLOD() { return mMinPixelArea; } void setLOD( F32 pixelArea ) { mMinPixelArea = pixelArea; } @@ -120,9 +120,10 @@ public: void setPickName(PickName name) { mPickName = name; } PickName getPickName() { return mPickName; } - virtual void updateFaceSizes(U32 &num_vertices, F32 pixel_area); + virtual void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); virtual void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); virtual BOOL updateLOD(F32 pixel_area, BOOL activate); + virtual void updateGeometry(); virtual void dump(); void setVisible( BOOL visible, BOOL recursive ); @@ -154,3 +155,4 @@ public: #endif // LL_LLVIEWERJOINT_H + diff --git a/linden/indra/newview/llviewerjointattachment.cpp b/linden/indra/newview/llviewerjointattachment.cpp index 89db44d..2a54a47 100644 --- a/linden/indra/newview/llviewerjointattachment.cpp +++ b/linden/indra/newview/llviewerjointattachment.cpp @@ -79,7 +79,7 @@ BOOL LLViewerJointAttachment::isTransparent() //----------------------------------------------------------------------------- // drawShape() //----------------------------------------------------------------------------- -U32 LLViewerJointAttachment::drawShape( F32 pixelArea ) +U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass ) { if (LLVOAvatar::sShowAttachmentPoints) { @@ -296,47 +296,20 @@ void LLViewerJointAttachment::removeObject(LLViewerObject *object) //----------------------------------------------------------------------------- void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible) { - if (!mAttachedObject || mAttachedObject->mDrawable.isNull()) + if (!mAttachedObject || mAttachedObject->mDrawable.isNull() || + !(mAttachedObject->mDrawable->getSpatialBridge())) return; if (visible) { // Hack to make attachments not visible by disabling their type mask! // This will break if you can ever attach non-volumes! - djs 02/14/03 - mAttachedObject->mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - for (LLViewerObject::child_list_t::iterator iter = mAttachedObject->mChildList.begin(); - iter != mAttachedObject->mChildList.end(); ++iter) - { - LLViewerObject* childp = *iter; - if (childp && childp->mDrawable.notNull()) - { - childp->mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - } - } + mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = + mAttachedObject->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME; } else { - //RN: sometimes we call this on objects that are already invisible, so check for that case - if (!mAttachedObject->mDrawable->isRenderType(LLPipeline::RENDER_TYPE_VOLUME) && - !mAttachedObject->mDrawable->isRenderType(0)) - { - llerrs << "Tried to attach non-volume to a joint, visibility hack dangerous!" << llendl; - } - mAttachedObject->mDrawable->setRenderType(0); - for (LLViewerObject::child_list_t::iterator iter = mAttachedObject->mChildList.begin(); - iter != mAttachedObject->mChildList.end(); ++iter) - { - LLViewerObject* childp = *iter; - if (childp && childp->mDrawable.notNull()) - { - if (!childp->mDrawable->isRenderType(LLPipeline::RENDER_TYPE_VOLUME) && - !mAttachedObject->mDrawable->isRenderType(0)) - { - llerrs << "Tried to attach non-volume to a joint, visibility hack dangerous!" << llendl; - } - childp->mDrawable->setRenderType(0); - } - } + mAttachedObject->mDrawable->getSpatialBridge()->mDrawableType = 0; } } diff --git a/linden/indra/newview/llviewerjointattachment.h b/linden/indra/newview/llviewerjointattachment.h index 3d5f914..be671fb 100644 --- a/linden/indra/newview/llviewerjointattachment.h +++ b/linden/indra/newview/llviewerjointattachment.h @@ -56,7 +56,7 @@ public: // Draws the shape attached to a joint. // Called by render(). - /*virtual*/ U32 drawShape( F32 pixelArea ); + /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass ); /*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate); @@ -79,7 +79,7 @@ public: S32 getGroup() { return mGroup; } S32 getPieSlice() { return mPieSlice; } BOOL getAttachmentDirty() { return mAttachmentDirty && mAttachedObject; } - LLViewerObject *getObject(S32 i) { return mAttachedObject; } + LLViewerObject *getObject() { return mAttachedObject; } S32 getNumObjects() { return (mAttachedObject ? 1 : 0); } const LLUUID& getItemID() { return mItemID; } diff --git a/linden/indra/newview/llviewerjointmesh.cpp b/linden/indra/newview/llviewerjointmesh.cpp index 96cdb88..3070cb4 100644 --- a/linden/indra/newview/llviewerjointmesh.cpp +++ b/linden/indra/newview/llviewerjointmesh.cpp @@ -38,7 +38,6 @@ #include "llfasttimer.h" #include "llagent.h" -#include "llagparray.h" #include "llbox.h" #include "lldrawable.h" #include "lldrawpoolavatar.h" @@ -62,6 +61,10 @@ extern PFNGLVERTEXBLENDARBPROC glVertexBlendARB; #endif extern BOOL gRenderForSelect; +static LLPointer sRenderBuffer = NULL; +static const U32 sRenderMask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_NORMAL | + LLVertexBuffer::MAP_TEXCOORD; LLMatrix4 gBlendMat; //----------------------------------------------------------------------------- @@ -394,11 +397,11 @@ void LLViewerJointMesh::setupJoint(LLViewerJoint* current_joint) } // depth-first traversal - for (LLJoint *child_joint = current_joint->mChildren.getFirstData(); - child_joint; - child_joint = current_joint->mChildren.getNextData()) + for (LLJoint::child_list_t::iterator iter = current_joint->mChildren.begin(); + iter != current_joint->mChildren.end(); ++iter) { - setupJoint((LLViewerJoint*)child_joint); + LLViewerJoint* child_joint = (LLViewerJoint*)(*iter); + setupJoint(child_joint); } } @@ -431,7 +434,7 @@ void LLViewerJointMesh::uploadJointMatrices() if (hardware_skinning) { - joint_mat *= gCamera->getModelview(); + joint_mat *= LLDrawPoolAvatar::getModelView(); } gJointMat[joint_num] = joint_mat; gJointRot[joint_num] = joint_mat.getMat3(); @@ -532,620 +535,39 @@ int compare_int(const void *a, const void *b) else return 0; } -#if LL_WINDOWS || (LL_DARWIN && __i386__) // SSE optimizations in avatar code - -#if LL_DARWIN -#include - - // On Windows, this class is defined in fvec.h. I've only reproduced the parts of it we use here for now. - #pragma pack(push,16) /* Must ensure class & union 16-B aligned */ - class F32vec4 - { - protected: - __m128 vec; - public: - - /* Constructors: __m128, 4 floats, 1 float */ - F32vec4() {} - - /* initialize 4 SP FP with __m128 data type */ - F32vec4(__m128 m) { vec = m;} - - /* Explicitly initialize each of 4 SP FPs with same float */ - explicit F32vec4(float f) { vec = _mm_set_ps1(f); } - }; - #pragma pack(pop) /* 16-B aligned */ - - -#endif - -void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output, - LLStrider& vertices, LLStrider& texcoords, LLStrider& normals, LLStrider& weights) +void llDrawRangeElements(GLenum mode, GLuint start, GLuint end, GLsizei count, GLenum type, const GLvoid *indices) { - F32 last_weight = F32_MAX; - LLMatrix4 *blend_mat = &gBlendMat; - - for (S32 index = vert_offset; index < vert_offset + vert_count; index++) + if (end-start+1 > (U32) gGLManager.mGLMaxVertexRange || + count > gGLManager.mGLMaxIndexRange) { - F32 w = weights [index]; // register copy of weight - F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever - F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned - - if (w == last_weight) - { - // load input and output vertices, and last blended matrix - __asm { - mov esi, vin - mov edi, vout - - mov edx, blend_mat - movaps xmm4, [edx] - movaps xmm5, [edx+0x10] - movaps xmm6, [edx+0x20] - movaps xmm7, [edx+0x30] - } - } - else - { - last_weight = w; - S32 joint = llfloor(w); - w -= joint; - - LLMatrix4 *m0 = &(gJointMat[joint+1]); - LLMatrix4 *m1 = &(gJointMat[joint+0]); - - // some initial code to load Matrix 0 into SSE registers - __asm { - mov esi, vin - mov edi, vout - - //matrix2 - mov edx, m0 - movaps xmm4, [edx] - movaps xmm5, [edx+0x10] - movaps xmm6, [edx+0x20] - movaps xmm7, [edx+0x30] - }; - - // if w == 1.0f, we don't need to blend. - // but since we do the trick of blending the matrices, here, if w != 1.0, - // we load Matrix 1 into the other 4 SSE registers and blend both matrices - // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w) - - if (w != 1.0f) - { - F32vec4 weight(w); - - __asm { // do blending of matrices instead of verts and normals -- faster - mov edx, m1 - movaps xmm0, [edx] - movaps xmm1, [edx+0x10] - movaps xmm2, [edx+0x20] - movaps xmm3, [edx+0x30] - - subps xmm4, xmm0 // do blend for each matrix column - subps xmm5, xmm1 // diff, then multiply weight and re-add - subps xmm6, xmm2 - subps xmm7, xmm3 - - mulps xmm4, weight - mulps xmm5, weight - mulps xmm6, weight - mulps xmm7, weight - - addps xmm4, xmm0 - addps xmm5, xmm1 - addps xmm6, xmm2 - addps xmm7, xmm3 - }; - } - - __asm { - // save off blended matrix - mov edx, blend_mat; - movaps [edx], xmm4; - movaps [edx+0x10], xmm5; - movaps [edx+0x20], xmm6; - movaps [edx+0x30], xmm7; - } - } - - // now, we have either a blended matrix in xmm4-7 or the original Matrix 0 - // we then multiply each vertex and normal by this one matrix. - - // For SSE2, we would try to keep the original two matrices in other registers - // and avoid reloading them. However, they should ramain in L1 cache in the - // current case. - - // One possible optimization would be to sort the vertices by weight instead - // of just index (we still want to uniqify). If we note when two or more vertices - // share the same weight, we can avoid doing the middle SSE code above and just - // re-use the blended matrix for those vertices - - - // now, we do the actual vertex blending - __asm { - // load Vertex into xmm0. - movaps xmm0, [esi] // change aps to ups when input is no longer 16-baligned - movaps xmm1, xmm0 // copy vector into xmm0 through xmm2 (x,y,z) - movaps xmm2, xmm0 - shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // clone vertex (x) across vector - shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1); // clone vertex (y) across vector - shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2); // same for Z - mulps xmm0, xmm4 // do the actual matrix multipication for r0 - mulps xmm1, xmm5 // for r1 - mulps xmm2, xmm6 // for r2 - addps xmm0, xmm1 // accumulate - addps xmm0, xmm2 // accumulate - addps xmm0, xmm7 // add in the row 4 which holds the x,y,z translation. assumes w=1 (vertex-w, not weight) - - movaps [edi], xmm0 // store aligned in output array - - // load Normal into xmm0. - movaps xmm0, [esi + 0x10] // change aps to ups when input no longer 16-byte aligned - movaps xmm1, xmm0 // - movaps xmm2, xmm0 - shufps xmm0, xmm0, _MM_SHUFFLE(0,0,0,0); // since UV sits between vertex and normal, normal starts at element 1, not 0 - shufps xmm1, xmm1, _MM_SHUFFLE(1,1,1,1); - shufps xmm2, xmm2, _MM_SHUFFLE(2,2,2,2); - mulps xmm0, xmm4 // multiply by matrix - mulps xmm1, xmm5 // multiply - mulps xmm2, xmm6 // multiply - addps xmm0, xmm1 // accumulate - addps xmm0, xmm2 // accumulate. note: do not add translation component to normals, save time too - movaps [edi + 0x10], xmm0 // store aligned - } - - *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot. - } -} - -#elif LL_LINUX - -void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output, - LLStrider& vertices, LLStrider& texcoords, LLStrider& normals, LLStrider& weights) -{ - assert(0); -} - -#elif LL_DARWIN -// AltiVec versions of the same... - -static inline vector float loadAlign(int offset, vector float *addr) -{ - vector float in0 = vec_ld(offset, addr); - vector float in1 = vec_ld(offset + 16, addr); - vector unsigned char perm = vec_lvsl(0, (unsigned char*)addr); - - return(vec_perm(in0, in1, perm)); -} - -static inline void storeAlign(vector float v, int offset, vector float *addr) -{ - vector float in0 = vec_ld(offset, addr); - vector float in1 = vec_ld(offset + 16, addr); - vector unsigned char perm = vec_lvsr(0, (unsigned char *)addr); - vector float temp = vec_perm(v, v, perm); - vector unsigned char mask = (vector unsigned char)vec_cmpgt(perm, vec_splat_u8(15)); - - in0 = vec_sel(in0, temp, (vector unsigned int)mask); - in1 = vec_sel(temp, in1, (vector unsigned int)mask); - - vec_st(in0, offset, addr); - vec_st(in1, offset + 16, addr); -} - -void blend_SSE_32_32_batch(const int vert_offset, const int vert_count, float* output, - LLStrider& vertices, LLStrider& texcoords, LLStrider& normals, LLStrider& weights) -{ - F32 last_weight = F32_MAX; -// LLMatrix4 &blend_mat = gBlendMat; - - vector float matrix0_0, matrix0_1, matrix0_2, matrix0_3; - vector unsigned char out0perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F ); -// vector unsigned char out1perm = (vector unsigned char) ( 0x00,0x01,0x02,0x03, 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B ); - vector unsigned char out1perm = (vector unsigned char) ( 0x10,0x11,0x12,0x13, 0x14,0x15,0x16,0x17, 0x18,0x19,0x1A,0x1B, 0x0C,0x0D,0x0E,0x0F ); - - vector float zero = (vector float)vec_splat_u32(0); - - for (U32 index = vert_offset; index < vert_offset + vert_count; index++) - { - F32 w = weights [index]; // register copy of weight - F32 *vin = &vertices[index].mV[0]; // pointer to input vertex data, assumed to be V3+T2+N3+whatever - F32 *vout = output + index * (AVATAR_VERTEX_BYTES/sizeof(F32)); // pointer to the output vertex data, assumed to be 16 byte aligned - - // MBW -- XXX -- If this isn't the case, this code gets more complicated. - if(0x0000000F & (U32)vin) - { - llerrs << "blend_SSE_batch: input not 16-byte aligned!" << llendl; - } - if(0x0000000F & (U32)vout) - { - llerrs << "blend_SSE_batch: output not 16-byte aligned!" << llendl; - } -// if(0x0000000F & (U32)&(blend_mat.mMatrix)) -// { -// llerrs << "blend_SSE_batch: blend_mat not 16-byte aligned!" << llendl; -// } - - if (w == last_weight) - { - // load last blended matrix - // Still loaded from last time through the loop. -// matrix0_0 = vec_ld(0x00, (vector float*)&(blend_mat.mMatrix)); -// matrix0_1 = vec_ld(0x10, (vector float*)&(blend_mat.mMatrix)); -// matrix0_2 = vec_ld(0x20, (vector float*)&(blend_mat.mMatrix)); -// matrix0_3 = vec_ld(0x30, (vector float*)&(blend_mat.mMatrix)); - } - else - { - last_weight = w; - S32 joint = llfloor(w); - w -= joint; - - LLMatrix4 &m0 = gJointMat[joint+1]; - LLMatrix4 &m1 = gJointMat[joint+0]; - - // load Matrix 0 into vector registers - matrix0_0 = vec_ld(0x00, (vector float*)&(m0.mMatrix)); - matrix0_1 = vec_ld(0x10, (vector float*)&(m0.mMatrix)); - matrix0_2 = vec_ld(0x20, (vector float*)&(m0.mMatrix)); - matrix0_3 = vec_ld(0x30, (vector float*)&(m0.mMatrix)); - - // if w == 1.0f, we don't need to blend. - // but since we do the trick of blending the matrices, here, if w != 1.0, - // we load Matrix 1 into the other 4 SSE registers and blend both matrices - // based on the weight (which we load ingo a 16-byte aligned vector: w,w,w,w) - - if (w != 1.0f) - { - vector float matrix1_0, matrix1_1, matrix1_2, matrix1_3; - - // This loads the weight somewhere in the vector register - vector float weight = vec_lde(0, &(w)); - // and this splats it to all elements. - weight = vec_splat(vec_perm(weight, weight, vec_lvsl(0, &(w))), 0); - - // do blending of matrices instead of verts and normals -- faster - matrix1_0 = vec_ld(0x00, (vector float*)&(m1.mMatrix)); - matrix1_1 = vec_ld(0x10, (vector float*)&(m1.mMatrix)); - matrix1_2 = vec_ld(0x20, (vector float*)&(m1.mMatrix)); - matrix1_3 = vec_ld(0x30, (vector float*)&(m1.mMatrix)); - - // m0[col] = ((m0[col] - m1[col]) * weight) + m1[col]; - matrix0_0 = vec_madd(vec_sub(matrix0_0, matrix1_0), weight, matrix1_0); - matrix0_1 = vec_madd(vec_sub(matrix0_1, matrix1_1), weight, matrix1_1); - matrix0_2 = vec_madd(vec_sub(matrix0_2, matrix1_2), weight, matrix1_2); - matrix0_3 = vec_madd(vec_sub(matrix0_3, matrix1_3), weight, matrix1_3); - } - - // save off blended matrix -// vec_st(matrix0_0, 0x00, (vector float*)&(blend_mat.mMatrix)); -// vec_st(matrix0_1, 0x10, (vector float*)&(blend_mat.mMatrix)); -// vec_st(matrix0_2, 0x20, (vector float*)&(blend_mat.mMatrix)); -// vec_st(matrix0_3, 0x30, (vector float*)&(blend_mat.mMatrix)); - } - - // now, we have either a blended matrix in matrix0_0-3 or the original Matrix 0 - // we then multiply each vertex and normal by this one matrix. - - // For SSE2, we would try to keep the original two matrices in other registers - // and avoid reloading them. However, they should ramain in L1 cache in the - // current case. - - // One possible optimization would be to sort the vertices by weight instead - // of just index (we still want to uniqify). If we note when two or more vertices - // share the same weight, we can avoid doing the middle SSE code above and just - // re-use the blended matrix for those vertices - - - // now, we do the actual vertex blending - - vector float in0 = vec_ld(AVATAR_OFFSET_POS, (vector float*)vin); - vector float in1 = vec_ld(AVATAR_OFFSET_NORMAL, (vector float*)vin); - - // Matrix multiply vertex - vector float out0 = vec_madd - ( - vec_splat(in0, 0), - matrix0_0, - vec_madd - ( - vec_splat(in0, 1), - matrix0_1, - vec_madd - ( - vec_splat(in0, 2), - matrix0_2, - matrix0_3 - ) - ) - ); - - // Matrix multiply normal - vector float out1 = vec_madd - ( - vec_splat(in1, 0), - matrix0_0, - vec_madd - ( - vec_splat(in1, 1), - matrix0_1, - vec_madd - ( - vec_splat(in1, 2), - matrix0_2, - // no translation for normals - (vector float)vec_splat_u32(0) - ) - ) - ); - - // indexed store - vec_stl(vec_perm(in0, out0, out0perm), AVATAR_OFFSET_POS, (vector float*)vout); // Pos - vec_stl(vec_perm(in1, out1, out1perm), AVATAR_OFFSET_NORMAL, (vector float*)vout); // Norm - *(LLVector2*)(vout + (AVATAR_OFFSET_TEX0/sizeof(F32))) = texcoords[index]; // write texcoord into appropriate spot. - } -} - -#endif - - -void llDrawElementsBatchBlend(const U32 vert_offset, const U32 vert_count, LLFace *face, const S32 index_count, const U32 *indices) -{ - U8* gAGPVertices = gPipeline.bufferGetScratchMemory(); - - if (gAGPVertices) - { - LLStrider vertices; - LLStrider normals; - LLStrider tcoords0; - LLStrider weights; - - LLStrider o_vertices; - LLStrider o_normals; - LLStrider o_texcoords0; - - - LLStrider binormals; - LLStrider o_texcoords1; - // get the source vertices from the draw pool. We index these ourselves, as there was - // no guarantee the indices for a single jointmesh were contigious - - LLDrawPool *pool = face->getPool(); - pool->getVertexStrider (vertices, 0); - pool->getTexCoordStrider (tcoords0, 0, 0); - pool->getNormalStrider (normals, 0); - pool->getBinormalStrider (binormals, 0); - pool->getVertexWeightStrider(weights, 0); - - // load the addresses of the output striders - o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES); - o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES); - o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES); - o_texcoords1= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX1); o_texcoords1.setStride(AVATAR_VERTEX_BYTES); - -#if !LL_LINUX // !!! *TODO: do the linux implementation - if (gGLManager.mSoftwareBlendSSE) - { - // do SSE blend without binormals or extra texcoords - blend_SSE_32_32_batch(vert_offset, vert_count, (float*)gAGPVertices, - vertices, tcoords0, normals, weights); - } - else // fully backwards compatible software blending, no SSE -#endif - { - LLVector4 tpos0, tnorm0, tpos1, tnorm1, tbinorm0, tbinorm1; - F32 last_weight = F32_MAX; - LLMatrix3 gBlendRotMat; - - { - for (U32 index=vert_offset; index < vert_offset + vert_count; index++) - { - // blend by first matrix - F32 w = weights [index]; - - if (w != last_weight) - { - last_weight = w; - - S32 joint = llfloor(w); - w -= joint; - - LLMatrix4 &m0 = gJointMat[joint+1]; - LLMatrix4 &m1 = gJointMat[joint+0]; - LLMatrix3 &n0 = gJointRot[joint+1]; - LLMatrix3 &n1 = gJointRot[joint+0]; - - if (w == 1.0f) - { - gBlendMat = m0; - gBlendRotMat = n0; - } - else - { - gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w); - gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w); - gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w); - - gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w); - gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w); - gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w); - - gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w); - gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w); - gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w); - - gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w); - gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w); - gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w); - - gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w); - gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w); - gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w); - - gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w); - gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w); - gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w); - - gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w); - gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w); - gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w); - } - } - - // write result - o_vertices [index] = vertices[index] * gBlendMat; - o_normals [index] = normals [index] * gBlendRotMat; - o_texcoords0[index] = tcoords0[index]; - - /* - // Verification code. Leave this here. It's useful for keeping the SSE and non-SSE versions in sync. - LLVector3 temp; - temp = tpos0; - if( (o_vertices[index] - temp).magVecSquared() > 0.001f ) - { - llerrs << "V SSE: " << o_vertices[index] << " v. " << temp << llendl; - } - - temp = tnorm0; - if( (o_normals[index] - temp).magVecSquared() > 0.001f ) - { - llerrs << "N SSE: " << o_normals[index] << " v. " << temp << llendl; - } - - if( (o_texcoords0[index] - tcoords0[index]).magVecSquared() > 0.001f ) - { - llerrs << "T0 SSE: " << o_texcoords0[index] << " v. " << tcoords0[index] << llendl; - } - */ - } - } - } - -#if LL_DARWIN - // *HACK* *CHOKE* *PUKE* - // No way does this belong here. - glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * vert_count, gAGPVertices + (AVATAR_VERTEX_BYTES * vert_offset)); -#endif - glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices); // draw it! + glDrawElements(mode,count,type,indices); } else { - glDrawElements(GL_TRIANGLES, index_count, GL_UNSIGNED_INT, indices); + glDrawRangeElements(mode,start,end,count,type,indices); } } - - -//-------------------------------------------------------------------- -// DrawElements - -// works just like glDrawElements, except it assumes GL_TRIANGLES and GL_UNSIGNED_INT indices - -// why? because the destination buffer may not be the AGP buffer and the eyes do not use blending -// separate the eyes into their own drawpools and this code goes away. - -//-------------------------------------------------------------------- - -void llDrawElements(const S32 count, const U32 *indices, LLFace *face) -{ - U8* gAGPVertices = gPipeline.bufferGetScratchMemory(); - - if (gAGPVertices) - { -#if LL_DARWIN - U32 minIndex = indices[0]; - U32 maxIndex = indices[0]; -#endif - { - LLStrider vertices; - LLStrider normals; - LLStrider tcoords; - LLStrider weights; - - LLStrider o_vertices; - LLStrider o_normals; - LLStrider o_texcoords0; - - LLDrawPool *pool = face->getPool(); - pool->getVertexStrider (vertices,0); - pool->getNormalStrider (normals, 0); - pool->getTexCoordStrider (tcoords, 0); - - o_vertices = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_POS); o_vertices.setStride( AVATAR_VERTEX_BYTES); - o_normals = (LLVector3*)(gAGPVertices + AVATAR_OFFSET_NORMAL); o_normals.setStride( AVATAR_VERTEX_BYTES); - o_texcoords0= (LLVector2*)(gAGPVertices + AVATAR_OFFSET_TEX0); o_texcoords0.setStride(AVATAR_VERTEX_BYTES); - - for (S32 i=0; i < count; i++) - { - U32 index = indices[i]; - - o_vertices [index] = vertices[index]; - o_normals [index] = normals [index]; - o_texcoords0[index] = tcoords [index]; - -#if LL_DARWIN - maxIndex = llmax(index, maxIndex); - minIndex = llmin(index, minIndex); -#endif - } - } - -#if LL_DARWIN - // *HACK* *CHOKE* *PUKE* - // No way does this belong here. - glFlushVertexArrayRangeAPPLE(AVATAR_VERTEX_BYTES * (maxIndex + 1 - minIndex), gAGPVertices + (AVATAR_VERTEX_BYTES * minIndex)); -#endif - - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices); - } - else - { - glDrawElements(GL_TRIANGLES, count, GL_UNSIGNED_INT, indices); - } -} - - //-------------------------------------------------------------------- // LLViewerJointMesh::drawShape() //-------------------------------------------------------------------- -U32 LLViewerJointMesh::drawShape( F32 pixelArea ) +U32 LLViewerJointMesh::drawShape( F32 pixelArea, BOOL first_pass) { - if (!mValid || !mVisible) return 0; - - U32 triangle_count = 0; - - //---------------------------------------------------------------- - // if no mesh bail out now - //---------------------------------------------------------------- - if ( !mMesh || !mFace) + if (!mValid || !mMesh || !mFace || !mVisible || + mFace->mVertexBuffer.isNull() || + mMesh->getNumFaces() == 0) { return 0; } - //---------------------------------------------------------------- - // if we have no faces, bail out now - //---------------------------------------------------------------- - if ( mMesh->getNumFaces() == 0 ) - { - return 0; - } + U32 triangle_count = 0; stop_glerror(); //---------------------------------------------------------------- // setup current color //---------------------------------------------------------------- - if (gRenderForSelect) - { - S32 name = mFace->getDrawable() ? mFace->getDrawable()->getVObj()->mGLName : 0; - LLColor4U color((U8)(name >> 16), (U8)(name >> 8), (U8)name, 0xff); - LLColor4 color_float(color); - - glColor4f(color_float.mV[0], color_float.mV[1], color_float.mV[2], 1.f); - } - else + if (!gRenderForSelect) { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { @@ -1169,7 +591,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) stop_glerror(); -// LLGLSSpecular specular(mSpecular, gRenderForSelect ? 0.0f : mShiny); LLGLSSpecular specular(LLColor4(1.f,1.f,1.f,1.f), gRenderForSelect ? 0.0f : mShiny && !(mFace->getPool()->getVertexShaderLevel() > 0)); LLGLEnable texture_2d((gRenderForSelect && isTransparent()) ? GL_TEXTURE_2D : 0); @@ -1179,11 +600,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) //---------------------------------------------------------------- llassert( !(mTexture.notNull() && mLayerSet) ); // mutually exclusive - //GLuint test_image_name = 0; - - // - LLGLState force_alpha_test(GL_ALPHA_TEST, isTransparent()); - if (mTestImageName) { LLImageGL::bindExternalTexture( mTestImageName, 0, GL_TEXTURE_2D ); @@ -1236,11 +652,12 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) gImageList.getImage(IMG_DEFAULT_AVATAR)->bind(); } + LLGLDisable tex(gRenderForSelect && !isTransparent() ? GL_TEXTURE_2D : 0); + if (gRenderForSelect) { if (isTransparent()) { - //gGLSObjectSelectDepthAlpha.set(); glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); @@ -1251,19 +668,14 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); // GL_TEXTURE_ENV_COLOR is set in renderPass1 glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); } - else - { - //gGLSObjectSelectDepth.set(); - } } else { //---------------------------------------------------------------- // by default, backface culling is enabled //---------------------------------------------------------------- - if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER) + /*if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_INNER) { - //LLGLSPipelineAvatar gls_pipeline_avatar; LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D ); glClientActiveTextureARB(GL_TEXTURE0_ARB); @@ -1303,7 +715,6 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) } else if (sRenderPass == AVATAR_RENDER_PASS_CLOTHING_OUTER) { - //gGLSPipelineAvatarAlphaPass1.set(); glAlphaFunc(GL_GREATER, 0.1f); LLImageGL::bindExternalTexture( sClothingMaskImageName, 1, GL_TEXTURE_2D ); @@ -1334,81 +745,48 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - } - else if ( isTransparent()) - { - //gGLSNoCullFaces.set(); - } - else - { - //gGLSCullFaces.set(); - } + }*/ } - if (mMesh->hasWeights()) - { - uploadJointMatrices(); + mFace->mVertexBuffer->setBuffer(sRenderMask); + U32 start = mMesh->mFaceVertexOffset; + U32 end = start + mMesh->mFaceVertexCount - 1; + U32 count = mMesh->mFaceIndexCount; + U32* indicesp = ((U32*) mFace->mVertexBuffer->getIndicesPointer()) + mMesh->mFaceIndexOffset; + if (mMesh->hasWeights()) + { if ((mFace->getPool()->getVertexShaderLevel() > 0)) { - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices()); - - glPopMatrix(); + if (first_pass) + { + uploadJointMatrices(); + } + llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); } else { - if (mFace->getGeomIndex() < 0) - { - llerrs << "Invalid geometry index in LLViewerJointMesh::drawShape() " << mFace->getGeomIndex() << llendl; - } - - if ((S32)(mMesh->mFaceVertexOffset + mMesh->mFaceVertexCount) > mFace->getGeomCount()) - { - ((LLVOAvatar*)mFace->getDrawable()->getVObj())->mRoot.dump(); - llerrs << "Rendering outside of vertex bounds with mesh " << mName << " at pixel area " << pixelArea << llendl; - } - llDrawElementsBatchBlend(mMesh->mFaceVertexOffset, mMesh->mFaceVertexCount, - mFace, mMesh->mFaceIndexCount, mMesh->getIndices()); + llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); } - } else { glPushMatrix(); LLMatrix4 jointToWorld = getWorldMatrix(); - jointToWorld *= gCamera->getModelview(); - glLoadMatrixf((GLfloat*)jointToWorld.mMatrix); - - if ((mFace->getPool()->getVertexShaderLevel() > 0)) - { - glDrawElements(GL_TRIANGLES, mMesh->mFaceIndexCount, GL_UNSIGNED_INT, mMesh->getIndices()); - } - else // this else clause handles non-weighted vertices. llDrawElements just copies and draws - { - llDrawElements(mMesh->mFaceIndexCount, mMesh->getIndices(), mFace); - } - + glMultMatrixf((GLfloat*)jointToWorld.mMatrix); + llDrawRangeElements(GL_TRIANGLES, start, end, count, GL_UNSIGNED_INT, indicesp); glPopMatrix(); } triangle_count += mMesh->mFaceIndexCount; - - if (gRenderForSelect) - { - glColor4fv(mColor.mV); - } - + if (mTestImageName) { glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); } - if (sRenderPass != AVATAR_RENDER_PASS_SINGLE) + /*if (sRenderPass != AVATAR_RENDER_PASS_SINGLE) { LLImageGL::unbindTexture(1, GL_TEXTURE_2D); glActiveTextureARB(GL_TEXTURE1_ARB); @@ -1421,7 +799,7 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_MODULATE); glAlphaFunc(GL_GREATER, 0.01f); - } + }*/ if (mTexture.notNull()) { if (!mTexture->getClampS()) { @@ -1438,19 +816,20 @@ U32 LLViewerJointMesh::drawShape( F32 pixelArea ) //----------------------------------------------------------------------------- // updateFaceSizes() //----------------------------------------------------------------------------- -void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, F32 pixel_area) +void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area) { // Do a pre-alloc pass to determine sizes of data. if (mMesh && mValid) { mMesh->mFaceVertexOffset = num_vertices; mMesh->mFaceVertexCount = mMesh->getNumVertices(); + mMesh->mFaceIndexOffset = num_indices; + mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices; + mMesh->getReferenceMesh()->mCurVertexCount = mMesh->mFaceVertexCount; - num_vertices += mMesh->getNumVertices(); - mMesh->mFaceIndexCount = mMesh->getSharedData()->mNumTriangleIndices; - - mMesh->getSharedData()->genIndices(mMesh->mFaceVertexOffset); + num_vertices += mMesh->getNumVertices(); + num_indices += mMesh->mFaceIndexCount; } } @@ -1460,9 +839,7 @@ void LLViewerJointMesh::updateFaceSizes(U32 &num_vertices, F32 pixel_area) void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind) { U32 i; - - if (!mValid) return; - + mFace = face; LLStrider verticesp; @@ -1471,13 +848,15 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w LLStrider tex_coordsp; LLStrider vertex_weightsp; LLStrider clothing_weightsp; + LLStrider indicesp; // Copy data into the faces from the polymesh data. - if (mMesh) + if (mMesh && mValid) { if (mMesh->getNumVertices()) { S32 index = face->getGeometryAvatar(verticesp, normalsp, binormalsp, tex_coordsp, vertex_weightsp, clothing_weightsp); + face->mVertexBuffer->getIndexStrider(indicesp); if (-1 == index) { @@ -1493,11 +872,20 @@ void LLViewerJointMesh::updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_w vertex_weightsp[mMesh->mFaceVertexOffset + i] = *(mMesh->getWeights() + i); if (damp_wind) { - clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(0,0,0,0); + clothing_weightsp[mMesh->mFaceVertexOffset + i] = LLVector4(0,0,0,0); } else { - clothing_weightsp[mMesh->mFaceVertexOffset + i].setVec(*(mMesh->getClothingWeights() + i)); + clothing_weightsp[mMesh->mFaceVertexOffset + i] = (*(mMesh->getClothingWeights() + i)); + } + } + + for (S32 i = 0; i < mMesh->getNumFaces(); i++) + { + for (U32 j = 0; j < 3; j++) + { + U32 k = i*3+j+mMesh->mFaceIndexOffset; + indicesp[k] = mMesh->getFaces()[i][j] + mMesh->mFaceVertexOffset; } } } @@ -1514,6 +902,92 @@ BOOL LLViewerJointMesh::updateLOD(F32 pixel_area, BOOL activate) return (valid != activate); } +void LLViewerJointMesh::updateGeometry() +{ + if (mValid && mMesh && mFace && + mMesh->hasWeights() && + mFace->mVertexBuffer.notNull() && + gPipeline.getVertexShaderLevel(LLPipeline::SHADER_AVATAR) == 0) + { + uploadJointMatrices(); + LLStrider o_vertices; + LLStrider o_normals; + + //get vertex and normal striders + LLVertexBuffer *buffer = mFace->mVertexBuffer; + buffer->getVertexStrider(o_vertices, 0); + buffer->getNormalStrider(o_normals, 0); + + { + LLVector4 tpos0, tnorm0, tpos1, tnorm1, tbinorm0, tbinorm1; + F32 last_weight = F32_MAX; + LLMatrix3 gBlendRotMat; + + + for (U32 index= 0; index < mMesh->getNumVertices(); index++) + { + // blend by first matrix + F32 w = mMesh->getWeights()[index]; + + if (w != last_weight) + { + last_weight = w; + + S32 joint = llfloor(w); + w -= joint; + + LLMatrix4 &m0 = gJointMat[joint+1]; + LLMatrix4 &m1 = gJointMat[joint+0]; + LLMatrix3 &n0 = gJointRot[joint+1]; + LLMatrix3 &n1 = gJointRot[joint+0]; + + if (w == 1.0f) + { + gBlendMat = m0; + gBlendRotMat = n0; + } + else + { + gBlendMat.mMatrix[VX][VX] = lerp(m1.mMatrix[VX][VX], m0.mMatrix[VX][VX], w); + gBlendMat.mMatrix[VX][VY] = lerp(m1.mMatrix[VX][VY], m0.mMatrix[VX][VY], w); + gBlendMat.mMatrix[VX][VZ] = lerp(m1.mMatrix[VX][VZ], m0.mMatrix[VX][VZ], w); + + gBlendMat.mMatrix[VY][VX] = lerp(m1.mMatrix[VY][VX], m0.mMatrix[VY][VX], w); + gBlendMat.mMatrix[VY][VY] = lerp(m1.mMatrix[VY][VY], m0.mMatrix[VY][VY], w); + gBlendMat.mMatrix[VY][VZ] = lerp(m1.mMatrix[VY][VZ], m0.mMatrix[VY][VZ], w); + + gBlendMat.mMatrix[VZ][VX] = lerp(m1.mMatrix[VZ][VX], m0.mMatrix[VZ][VX], w); + gBlendMat.mMatrix[VZ][VY] = lerp(m1.mMatrix[VZ][VY], m0.mMatrix[VZ][VY], w); + gBlendMat.mMatrix[VZ][VZ] = lerp(m1.mMatrix[VZ][VZ], m0.mMatrix[VZ][VZ], w); + + gBlendMat.mMatrix[VW][VX] = lerp(m1.mMatrix[VW][VX], m0.mMatrix[VW][VX], w); + gBlendMat.mMatrix[VW][VY] = lerp(m1.mMatrix[VW][VY], m0.mMatrix[VW][VY], w); + gBlendMat.mMatrix[VW][VZ] = lerp(m1.mMatrix[VW][VZ], m0.mMatrix[VW][VZ], w); + + gBlendRotMat.mMatrix[VX][VX] = lerp(n1.mMatrix[VX][VX], n0.mMatrix[VX][VX], w); + gBlendRotMat.mMatrix[VX][VY] = lerp(n1.mMatrix[VX][VY], n0.mMatrix[VX][VY], w); + gBlendRotMat.mMatrix[VX][VZ] = lerp(n1.mMatrix[VX][VZ], n0.mMatrix[VX][VZ], w); + + gBlendRotMat.mMatrix[VY][VX] = lerp(n1.mMatrix[VY][VX], n0.mMatrix[VY][VX], w); + gBlendRotMat.mMatrix[VY][VY] = lerp(n1.mMatrix[VY][VY], n0.mMatrix[VY][VY], w); + gBlendRotMat.mMatrix[VY][VZ] = lerp(n1.mMatrix[VY][VZ], n0.mMatrix[VY][VZ], w); + + gBlendRotMat.mMatrix[VZ][VX] = lerp(n1.mMatrix[VZ][VX], n0.mMatrix[VZ][VX], w); + gBlendRotMat.mMatrix[VZ][VY] = lerp(n1.mMatrix[VZ][VY], n0.mMatrix[VZ][VY], w); + gBlendRotMat.mMatrix[VZ][VZ] = lerp(n1.mMatrix[VZ][VZ], n0.mMatrix[VZ][VZ], w); + } + } + + // write result + U32 bidx = index + mMesh->mFaceVertexOffset; + + o_vertices[bidx] = mMesh->getCoords()[index] * gBlendMat; + o_normals[bidx] = mMesh->getNormals()[index] * gBlendRotMat; + } + } + } +} + void LLViewerJointMesh::dump() { if (mValid) diff --git a/linden/indra/newview/llviewerjointmesh.h b/linden/indra/newview/llviewerjointmesh.h index 30b2f29..591b21c 100644 --- a/linden/indra/newview/llviewerjointmesh.h +++ b/linden/indra/newview/llviewerjointmesh.h @@ -133,11 +133,12 @@ public: // overloaded from base class /*virtual*/ void drawBone(); /*virtual*/ BOOL isTransparent(); - /*virtual*/ U32 drawShape( F32 pixelArea ); + /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass ); - /*virtual*/ void updateFaceSizes(U32 &num_vertices, F32 pixel_area); + /*virtual*/ void updateFaceSizes(U32 &num_vertices, U32& num_indices, F32 pixel_area); /*virtual*/ void updateFaceData(LLFace *face, F32 pixel_area, BOOL damp_wind = FALSE); /*virtual*/ BOOL updateLOD(F32 pixel_area, BOOL activate); + /*virtual*/ void updateGeometry(); /*virtual*/ void dump(); void setIsTransparent(BOOL is_transparent) { mIsTransparent = is_transparent; } diff --git a/linden/indra/newview/llviewerjointshape.cpp b/linden/indra/newview/llviewerjointshape.cpp index d40d8c3..c22cfbe 100644 --- a/linden/indra/newview/llviewerjointshape.cpp +++ b/linden/indra/newview/llviewerjointshape.cpp @@ -155,7 +155,7 @@ BOOL LLViewerJointShape::isTransparent() //-------------------------------------------------------------------- // drawShape() //-------------------------------------------------------------------- -U32 LLViewerJointShape::drawShape( F32 pixelArea ) +U32 LLViewerJointShape::drawShape( F32 pixelArea, BOOL first_pass ) { U32 triangle_count = 0; diff --git a/linden/indra/newview/llviewerjointshape.h b/linden/indra/newview/llviewerjointshape.h index 029c588..28d2c09 100644 --- a/linden/indra/newview/llviewerjointshape.h +++ b/linden/indra/newview/llviewerjointshape.h @@ -86,7 +86,7 @@ public: virtual void drawBone(); virtual BOOL isTransparent(); /*virutal*/ BOOL isAnimatable() { return FALSE; } - /*virtual*/ U32 drawShape( F32 pixelArea ); + /*virtual*/ U32 drawShape( F32 pixelArea, BOOL first_pass ); }; #endif // LL_LLVIEWERJOINTSHAPE_H diff --git a/linden/indra/newview/llviewerkeyboard.cpp b/linden/indra/newview/llviewerkeyboard.cpp index c5ada54..30fa19a 100644 --- a/linden/indra/newview/llviewerkeyboard.cpp +++ b/linden/indra/newview/llviewerkeyboard.cpp @@ -703,12 +703,12 @@ S32 LLViewerKeyboard::loadBindings(const char *filename) { FILE *fp; const S32 BUFFER_SIZE = 2048; - char buffer[BUFFER_SIZE]; + char buffer[BUFFER_SIZE]; /* Flawfinder: ignore */ // *NOTE: This buffer size is hard coded into scanf() below. - char mode_string[MAX_STRING]; - char key_string[MAX_STRING]; - char mask_string[MAX_STRING]; - char function_string[MAX_STRING]; + char mode_string[MAX_STRING]; /* Flawfinder: ignore */ + char key_string[MAX_STRING]; /* Flawfinder: ignore */ + char mask_string[MAX_STRING]; /* Flawfinder: ignore */ + char function_string[MAX_STRING]; /* Flawfinder: ignore */ S32 mode = MODE_THIRD_PERSON; KEY key = 0; MASK mask = 0; @@ -716,10 +716,15 @@ S32 LLViewerKeyboard::loadBindings(const char *filename) S32 binding_count = 0; S32 line_count = 0; - fp = LLFile::fopen(filename, "r"); + fp = LLFile::fopen(filename, "r"); /* Flawfinder: ignore */ if (!fp) { + if(!filename) + { + llerrs << " No filename specified" << llendl; + return 0; + } return 0; } @@ -734,7 +739,13 @@ S32 LLViewerKeyboard::loadBindings(const char *filename) if (buffer[0] == '#' || buffer[0] == '\n') continue; // grab the binding strings - tokens_read = sscanf(buffer, "%254s %254s %254s %254s", mode_string, key_string, mask_string, function_string); + tokens_read = sscanf( /* Flawfinder: ignore */ + buffer, + "%254s %254s %254s %254s", + mode_string, + key_string, + mask_string, + function_string); if (tokens_read == EOF) { diff --git a/linden/indra/newview/llviewermenu.cpp b/linden/indra/newview/llviewermenu.cpp index ab400de..217fb80 100644 --- a/linden/indra/newview/llviewermenu.cpp +++ b/linden/indra/newview/llviewermenu.cpp @@ -63,6 +63,7 @@ // newview includes #include "llagent.h" + #include "llagentpilot.h" #include "llbox.h" #include "llcallingcard.h" @@ -75,7 +76,6 @@ #include "lldir.h" #include "lldrawable.h" #include "lldrawpoolalpha.h" -#include "lldrawpoolhud.h" #include "lldrawpooltree.h" #include "llface.h" #include "llfirstuse.h" @@ -107,7 +107,6 @@ #include "llfloaterland.h" #include "llfloaterlandholdings.h" #include "llfloatermap.h" -#include "llfloateraccounthistory.h" #include "llfloaterimagepreview.h" #include "llfloatermute.h" #include "llfloaternamedesc.h" @@ -282,7 +281,6 @@ typedef LLMemberListener view_listener_t; // // Local prototypes // -BOOL enable_attach(void*); void handle_leave_group(void *); // File Menu @@ -294,6 +292,7 @@ BOOL enable_save_as(void *); // Edit menu void handle_dump_group_info(void *); +void handle_dump_capabilities_info(void *); void handle_dump_focus(void*); void handle_region_dump_settings(void*); @@ -354,9 +353,6 @@ BOOL check_toggle_hacked_godmode(void*); void toggle_glow(void *); BOOL check_glow(void *); -void toggle_vbo(void *); -BOOL check_vbo(void *); - void toggle_vertex_shaders(void *); BOOL check_vertex_shaders(void *); @@ -438,9 +434,6 @@ BOOL get_visibility(void*); void request_friendship(const LLUUID& agent_id); // Tools menu -void handle_first_tool(void*); -void handle_next_tool(void*); -void handle_previous_tool(void*); void handle_force_unlock(void*); void handle_selected_texture_info(void*); void handle_dump_image_list(void*); @@ -448,8 +441,6 @@ void handle_dump_image_list(void*); void handle_fullscreen_debug(void*); void handle_crash(void*); void handle_dump_followcam(void*); -void handle_viewer_enable_circuit_log(void*); -void handle_viewer_disable_circuit_log(void*); void handle_viewer_enable_message_log(void*); void handle_viewer_disable_message_log(void*); void handle_send_postcard(void*); @@ -565,52 +556,14 @@ void init_menus() // Main menu bar // gMenuHolder = new LLViewerMenuHolderGL(); - gMenuHolder->setRect(LLRect(0, top - MENU_BAR_HEIGHT, width, STATUS_BAR_HEIGHT)); + gMenuHolder->setRect(LLRect(0, top, width, 0)); gMenuHolder->setFollowsAll(); - LLMenuGL::sDefaultMenuContainer = gMenuHolder; + LLMenuGL::sMenuContainer = gMenuHolder; // Initialize actions initialize_menu_actions(); - gMenuBarView = (LLMenuBarGL*)gUICtrlFactory->buildMenu("menu_viewer.xml", gMenuHolder); - gMenuBarView->setRect(LLRect(0, top, width, top - MENU_BAR_HEIGHT)); - gViewerWindow->getRootView()->addChild(gMenuBarView); - - // menu holder appears on top of menu bar so you can see the menu title - // flash when an item is triggered (the flash occurs in the holder) - gViewerWindow->getRootView()->addChild(gMenuHolder); - - gMenuHolder->childSetLabelArg("Upload Image", "[COST]", "10"); - gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", "10"); - gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", "10"); - gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", "10"); - - gAFKMenu = (LLMenuItemCallGL*)gMenuBarView->getChildByName("Set Away", TRUE); - gBusyMenu = (LLMenuItemCallGL*)gMenuBarView->getChildByName("Set Busy", TRUE); - gAttachSubMenu = gMenuBarView->getChildMenuByName("Attach Object", TRUE); - gDetachSubMenu = gMenuBarView->getChildMenuByName("Detach Object", TRUE); - - if (gAgent.mAccess < SIM_ACCESS_MATURE) - { - gMenuBarView->getChildByName("Menu Underpants", TRUE)->setVisible(FALSE); - gMenuBarView->getChildByName("Menu Undershirt", TRUE)->setVisible(FALSE); - } - - // TomY TODO convert these two - LLMenuGL*menu; - menu = new LLMenuGL(CLIENT_MENU_NAME); - init_client_menu(menu); - gMenuBarView->appendMenu( menu ); - menu->updateParent(gMenuHolder); - - menu = new LLMenuGL(SERVER_MENU_NAME); - init_server_menu(menu); - gMenuBarView->appendMenu( menu ); - menu->updateParent(gMenuHolder); - - gMenuBarView->createJumpKeys(); - /// /// Popup menu /// @@ -653,6 +606,16 @@ void init_menus() /// LLColor4 color; + LLColor4 pie_color = gColors.getColor("PieMenuBgColor"); + gPieSelf->setBackgroundColor( pie_color ); + gPieAvatar->setBackgroundColor( pie_color ); + gPieObject->setBackgroundColor( pie_color ); + gPieAttachment->setBackgroundColor( pie_color ); + gPieLand->setBackgroundColor( pie_color ); + + color = gColors.getColor( "MenuPopupBgColor" ); + gPopupMenuView->setBackgroundColor( color ); + // If we are not in production, use a different color to make it apparent. if (gInProductionGrid) { @@ -662,18 +625,45 @@ void init_menus() { color = gColors.getColor( "MenuNonProductionBgColor" ); } - + gMenuBarView = (LLMenuBarGL*)gUICtrlFactory->buildMenu("menu_viewer.xml", gMenuHolder); + gMenuBarView->setRect(LLRect(0, top, 0, top - MENU_BAR_HEIGHT)); gMenuBarView->setBackgroundColor( color ); - LLColor4 pie_color = gColors.getColor("PieMenuBgColor"); - gPieSelf->setBackgroundColor( pie_color ); - gPieAvatar->setBackgroundColor( pie_color ); - gPieObject->setBackgroundColor( pie_color ); - gPieAttachment->setBackgroundColor( pie_color ); - gPieLand->setBackgroundColor( pie_color ); + gMenuHolder->addChild(gMenuBarView); + + // menu holder appears on top of menu bar so you can see the menu title + // flash when an item is triggered (the flash occurs in the holder) + gViewerWindow->getRootView()->addChild(gMenuHolder); - color = gColors.getColor( "MenuPopupBgColor" ); - gPopupMenuView->setBackgroundColor( color ); + gMenuHolder->childSetLabelArg("Upload Image", "[COST]", "10"); + gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", "10"); + gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", "10"); + gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", "10"); + + gAFKMenu = (LLMenuItemCallGL*)gMenuBarView->getChildByName("Set Away", TRUE); + gBusyMenu = (LLMenuItemCallGL*)gMenuBarView->getChildByName("Set Busy", TRUE); + gAttachSubMenu = gMenuBarView->getChildMenuByName("Attach Object", TRUE); + gDetachSubMenu = gMenuBarView->getChildMenuByName("Detach Object", TRUE); + + if (gAgent.mAccess < SIM_ACCESS_MATURE) + { + gMenuBarView->getChildByName("Menu Underpants", TRUE)->setVisible(FALSE); + gMenuBarView->getChildByName("Menu Undershirt", TRUE)->setVisible(FALSE); + } + + // TomY TODO convert these two + LLMenuGL*menu; + menu = new LLMenuGL(CLIENT_MENU_NAME); + init_client_menu(menu); + gMenuBarView->appendMenu( menu ); + menu->updateParent(LLMenuGL::sMenuContainer); + + menu = new LLMenuGL(SERVER_MENU_NAME); + init_server_menu(menu); + gMenuBarView->appendMenu( menu ); + menu->updateParent(LLMenuGL::sMenuContainer); + + gMenuBarView->createJumpKeys(); // Let land based option enable when parcel changes gMenuParcelObserver = new LLMenuParcelObserver(); @@ -746,6 +736,8 @@ void init_client_menu(LLMenuGL* menu) &handle_region_dump_settings, NULL)); sub->append(new LLMenuItemCallGL("Group Info to Debug Console", &handle_dump_group_info, NULL, NULL)); + sub->append(new LLMenuItemCallGL("Capabilities Info to Debug Console", + &handle_dump_capabilities_info, NULL, NULL)); sub->createJumpKeys(); } @@ -783,6 +775,12 @@ void init_client_menu(LLMenuGL* menu) menu->append(new LLMenuItemToggleGL("Quiet Snapshots to Disk", &gQuietSnapshot)); + menu->append(new LLMenuItemCheckGL( "Compress Snapshots to Disk", + &menu_toggle_control, + NULL, + &menu_check_control, + (void*)"CompressSnapshotsToDisk")); + menu->append(new LLMenuItemCheckGL("Show Mouselook Crosshairs", &menu_toggle_control, NULL, @@ -836,10 +834,6 @@ void init_client_menu(LLMenuGL* menu) LLMenuGL* sub = NULL; sub = new LLMenuGL("Network"); - sub->append(new LLMenuItemCallGL("Enable Circuit Log", - &handle_viewer_enable_circuit_log, NULL)); - sub->append(new LLMenuItemCallGL("Disable Circuit Log", - &handle_viewer_disable_circuit_log, NULL)); sub->append(new LLMenuItemCallGL("Enable Message Log", &handle_viewer_enable_message_log, NULL)); sub->append(new LLMenuItemCallGL("Disable Message Log", @@ -909,6 +903,11 @@ void init_client_menu(LLMenuGL* menu) menu->append(new LLMenuItemToggleGL("Disable Camera Constraints", &LLViewerCamera::sDisableCameraConstraints)); + menu->append(new LLMenuItemCheckGL("Mouse Smoothing", + &menu_toggle_control, + NULL, + &menu_check_control, + (void*) "MouseSmooth")); menu->appendSeparator(); menu->append(new LLMenuItemCheckGL( "Console Window", @@ -1004,6 +1003,7 @@ void init_debug_ui_menu(LLMenuGL* menu) menu->append(new LLMenuItemToggleGL("Debug SelectMgr", &gDebugSelectMgr)); menu->append(new LLMenuItemToggleGL("Debug Clicks", &gDebugClicks)); menu->append(new LLMenuItemToggleGL("Debug Views", &LLView::sDebugRects)); + menu->append(new LLMenuItemCheckGL("Show Name Tooltips", toggle_show_xui_names, NULL, check_show_xui_names, NULL)); menu->append(new LLMenuItemToggleGL("Debug Mouse Events", &LLView::sDebugMouseHandling)); menu->append(new LLMenuItemToggleGL("Debug Keys", &LLView::sDebugKeys)); menu->append(new LLMenuItemToggleGL("Debug WindowProc", &gDebugWindowProc)); @@ -1036,56 +1036,56 @@ void init_debug_rendering_menu(LLMenuGL* menu) menu->appendMenu(sub_menu); sub_menu->append(new LLMenuItemCheckGL("Simple", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_SIMPLE, '1', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Alpha", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_ALPHA, '2', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Tree", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_TREE, '3', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Character", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_AVATAR, '4', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("SurfacePatch", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_TERRAIN, '5', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Sky", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_SKY, '6', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Water", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_WATER, '7', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Ground", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_GROUND, '8', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Volume", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_VOLUME, '9', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Grass", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_GRASS, '0', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Clouds", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_CLOUDS, '-', MASK_CONTROL|MASK_ALT| MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Particles", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_PARTICLES, '=', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->append(new LLMenuItemCheckGL("Bump", - &LLPipeline::toggleRenderType, NULL, - &LLPipeline::toggleRenderTypeControl, + &LLPipeline::toggleRenderTypeControl, NULL, + &LLPipeline::hasRenderTypeControl, (void*)LLPipeline::RENDER_TYPE_BUMP, '\\', MASK_CONTROL|MASK_ALT|MASK_SHIFT)); sub_menu->createJumpKeys(); sub_menu = new LLMenuGL("Features"); @@ -1106,6 +1106,10 @@ void init_debug_rendering_menu(LLMenuGL* menu) &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_DYNAMIC_TEXTURES, '4', MASK_ALT|MASK_CONTROL)); + sub_menu->append(new LLMenuItemCheckGL( "Foot Shadows", + &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeatureControl, + (void*)LLPipeline::RENDER_DEBUG_FEATURE_FOOT_SHADOWS, '5', MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL("Fog", &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, @@ -1119,13 +1123,9 @@ void init_debug_rendering_menu(LLMenuGL* menu) &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FR_INFO, '8', MASK_ALT|MASK_CONTROL)); sub_menu->append(new LLMenuItemCheckGL( "Flexible Objects", - &LLPipeline::toggleRenderDebugFeature, NULL, + &LLPipeline::toggleRenderDebugFeature, NULL, &LLPipeline::toggleRenderDebugFeatureControl, (void*)LLPipeline::RENDER_DEBUG_FEATURE_FLEXIBLE, '9', MASK_ALT|MASK_CONTROL)); - sub_menu->append(new LLMenuItemCheckGL( "Chain Faces", - &LLPipeline::toggleRenderDebugFeature, NULL, - &LLPipeline::toggleRenderDebugFeatureControl, - (void*)LLPipeline::RENDER_DEBUG_FEATURE_CHAIN_FACES, '0', MASK_ALT|MASK_CONTROL)); sub_menu->createJumpKeys(); ///////////////////////////// @@ -1138,9 +1138,6 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("Verify", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_VERIFY)); - sub_menu->append(new LLMenuItemCheckGL("AGP Map", &LLPipeline::toggleRenderDebug, NULL, - &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_AGP_MEM)); sub_menu->append(new LLMenuItemCheckGL("BBoxes", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_BBOXES)); @@ -1153,12 +1150,24 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("Occlusion", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_OCCLUSION)); - sub_menu->append(new LLMenuItemCheckGL("Face Chains", &LLPipeline::toggleRenderDebug, NULL, + sub_menu->append(new LLMenuItemCheckGL("Animated Textures", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_FACE_CHAINS)); + (void*)LLPipeline::RENDER_DEBUG_TEXTURE_ANIM)); sub_menu->append(new LLMenuItemCheckGL("Texture Priority", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)); + (void*)LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)); + sub_menu->append(new LLMenuItemCheckGL("Texture Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_TEXTURE_AREA)); + sub_menu->append(new LLMenuItemCheckGL("Face Area (sqrt(A))",&LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_FACE_AREA)); + sub_menu->append(new LLMenuItemCheckGL("Pick Render", &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_PICKING)); + sub_menu->append(new LLMenuItemCheckGL("Particles", &LLPipeline::toggleRenderDebug, NULL, + &LLPipeline::toggleRenderDebugControl, + (void*)LLPipeline::RENDER_DEBUG_PARTICLES)); sub_menu->append(new LLMenuItemCheckGL("Composition", &LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_COMPOSITION)); @@ -1168,16 +1177,7 @@ void init_debug_rendering_menu(LLMenuGL* menu) sub_menu->append(new LLMenuItemCheckGL("LightTrace",&LLPipeline::toggleRenderDebug, NULL, &LLPipeline::toggleRenderDebugControl, (void*)LLPipeline::RENDER_DEBUG_LIGHT_TRACE)); - sub_menu->append(new LLMenuItemCheckGL("Pools", &LLPipeline::toggleRenderDebug, NULL, - &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_POOLS)); - sub_menu->append(new LLMenuItemCheckGL("Queues", &LLPipeline::toggleRenderDebug, NULL, - &LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_QUEUES)); - sub_menu->append(new LLMenuItemCheckGL("Map", &LLPipeline::toggleRenderDebug, NULL, - LLPipeline::toggleRenderDebugControl, - (void*)LLPipeline::RENDER_DEBUG_MAP)); - + sub_menu->append(new LLMenuItemCheckGL("Show Depth Buffer", &menu_toggle_control, NULL, @@ -1202,8 +1202,6 @@ void init_debug_rendering_menu(LLMenuGL* menu) menu->appendSeparator(); menu->append(new LLMenuItemCheckGL("Axes", menu_toggle_control, NULL, menu_check_control, (void*)"ShowAxes")); - menu->append(new LLMenuItemCheckGL("Use VBO", toggle_vbo, NULL, check_vbo, NULL)); - menu->append(new LLMenuItemCheckGL("Light Glows", toggle_glow, NULL, check_glow, NULL)); // menu->append(new LLMenuItemCheckGL("Cull Small Objects", toggle_cull_small, NULL, menu_check_control, (void*)"RenderCullBySize")); menu->appendSeparator(); @@ -1228,6 +1226,19 @@ void init_debug_rendering_menu(LLMenuGL* menu) item = new LLMenuItemCheckGL("Disable Textures", menu_toggle_variable, NULL, menu_check_variable, (void*)&LLViewerImage::sDontLoadVolumeTextures); menu->append(item); +#ifndef LL_RELEASE_FOR_DOWNLOAD + item = new LLMenuItemCheckGL("HTTP Get Textures", menu_toggle_control, NULL, menu_check_control, (void*)"ImagePipelineUseHTTP"); + menu->append(item); +#endif + + item = new LLMenuItemCheckGL("Run Multiple Threads", menu_toggle_control, NULL, menu_check_control, (void*)"RunMultipleThreads"); + menu->append(item); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + item = new LLMenuItemCheckGL("Dynamic Reflections", menu_toggle_control, NULL, menu_check_control, (void*)"RenderDynamicReflections"); + menu->append(item); +#endif + item = new LLMenuItemCheckGL("Cheesy Beacon", menu_toggle_control, NULL, menu_check_control, (void*)"CheesyBeacon"); menu->append(item); @@ -1284,10 +1295,6 @@ void init_debug_avatar_menu(LLMenuGL* menu) //menu->append(new LLMenuItemToggleGL("Show Attachment Points", &LLVOAvatar::sShowAttachmentPoints)); menu->append(new LLMenuItemToggleGL("Show Collision Plane", &LLVOAvatar::sShowFootPlane)); menu->append(new LLMenuItemToggleGL("Show Collision Skeleton", &LLVOAvatar::sShowCollisionVolumes)); - menu->append(new LLMenuItemToggleGL("Software Blending SSE", &gGLManager.mSoftwareBlendSSE)); -#if 0 // Removed since this feature doesn't actually work as of 1.9.1 --TomY - menu->append(new LLMenuItemToggleGL("Character Load Test", &LLVOAvatar::sAvatarLoadTest)); -#endif menu->append(new LLMenuItemToggleGL( "Display Agent Target", &LLAgent::sDebugDisplayTarget)); menu->append(new LLMenuItemToggleGL( "Debug Rotation", &gDebugAvatarRotation)); menu->append(new LLMenuItemCallGL("Dump Attachments", handle_dump_attachments)); @@ -1325,11 +1332,6 @@ void init_server_menu(LLMenuGL* menu) &handle_normal_llinfo_log, &enable_god_customer_service)); sub_menu->appendSeparator(); - sub_menu->append(new LLMenuItemCallGL("Enable Circuit Log", - &handle_sim_enable_circuit_log, &enable_god_customer_service)); - sub_menu->append(new LLMenuItemCallGL("Disable Circuit Log", - &handle_sim_disable_circuit_log, &enable_god_customer_service)); - sub_menu->appendSeparator(); sub_menu->append(new LLMenuItemCallGL("Enable Message Log", &handle_sim_enable_message_log, &enable_god_customer_service)); sub_menu->append(new LLMenuItemCallGL("Disable Message Log", @@ -1352,7 +1354,8 @@ void init_server_menu(LLMenuGL* menu) menu->appendMenu(sub); sub->append(new LLMenuItemCallGL( "Take Copy", - &force_take_copy, &enable_god_customer_service, NULL)); + &force_take_copy, &enable_god_customer_service, NULL, + 'O', MASK_SHIFT | MASK_ALT | MASK_CONTROL)); #ifdef _CORY_TESTING sub->append(new LLMenuItemCallGL( "Export Copy", &force_export_copy, NULL, NULL)); @@ -1456,7 +1459,7 @@ class LLObjectRateOwner : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { // Don't allow rating of group owned objects. - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (!node) return true; if (node->mPermissions->isGroupOwned()) { @@ -1542,36 +1545,6 @@ class LLObjectEnableReportAbuse : public view_listener_t } }; - -BOOL enable_attach(void*) -{ - // All root objects must be owned by agent. - BOOL rv = FALSE; - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); - if(obj) - { - rv = TRUE; - for(obj = gSelectMgr->getFirstRootObject() ; obj != NULL; obj = gSelectMgr->getNextRootObject()) - { - for (U32 child_num = 0; child_num < obj->mChildList.size(); child_num++ ) - { - LLViewerObject *child = obj->mChildList[child_num]; - if (child->isAvatar()) - { - return FALSE; - } - } - if(!obj->permMove()) - { - rv = FALSE; - break; - } - } - } - return rv; -} - - class LLObjectTouch : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -1601,7 +1574,6 @@ class LLObjectTouch : public view_listener_t msg->addU32Fast(_PREHASH_LocalID, object->mLocalID); msg->sendMessage(object->getRegion()->getHost()); - gSelectMgr->deselectTransient(); return true; } }; @@ -1617,7 +1589,7 @@ class LLObjectEnableTouch : public view_listener_t gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); // Update label based on the node touch name if available. - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { gMenuHolder->childSetText("Object Touch", node->mTouchName); @@ -1633,7 +1605,7 @@ class LLObjectEnableTouch : public view_listener_t void label_touch(LLString& label, void*) { - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mTouchName.empty()) { label.assign(node->mTouchName); @@ -1649,8 +1621,6 @@ bool handle_object_open() LLViewerObject* obj = gObjectList.findObject(gLastHitObjectID); if(!obj) return true; - // transient selection must be made permanent - gSelectMgr->convertTransient(); LLFloaterOpenObject::show(); return true; } @@ -1711,8 +1681,8 @@ bool toggle_build_mode() gAgent.cameraOrbitOver( 30.f * DEG_TO_RAD ); } - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool( gToolCreate ); + gToolMgr->setCurrentToolset(gBasicToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolCreate ); // Could be first use LLFirstUse::useBuild(); @@ -1748,8 +1718,8 @@ class LLObjectBuild : public view_listener_t gViewerWindow->moveCursorToCenter(); } - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool( gToolCreate ); + gToolMgr->setCurrentToolset(gBasicToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolCreate ); // Could be first use LLFirstUse::useBuild(); @@ -1762,12 +1732,12 @@ class LLObjectEdit : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { gParcelMgr->deselectLand(); - // convert transient selections to permanent - gSelectMgr->convertTransient(); if (gAgent.getFocusOnAvatar() && !gToolMgr->inEdit()) { - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + + if (selection->getSelectType() == SELECT_TYPE_HUD || !gSavedSettings.getBOOL("EditCameraMovement")) { // always freeze camera in space, even if camera doesn't move // so, for example, follow cam scripts can't affect you when in build mode @@ -1785,9 +1755,9 @@ class LLObjectEdit : public view_listener_t } } - gFloaterTools->open(); + gFloaterTools->open(); /* Flawfinder: ignore */ - gCurrentToolset = gBasicToolset; + gToolMgr->setCurrentToolset(gBasicToolset); gFloaterTools->setEditTool( gToolTranslate ); // Could be first use @@ -1800,7 +1770,6 @@ class LLObjectInspect : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - gSelectMgr->convertTransient(); LLFloaterInspect::show(); return true; } @@ -1833,8 +1802,8 @@ class LLLandBuild : public view_listener_t } - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool( gToolCreate ); + gToolMgr->setCurrentToolset(gBasicToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolCreate ); // Could be first use LLFirstUse::useBuild(); @@ -1922,7 +1891,7 @@ class LLSelfEnableRemoveAllAttachments : public view_listener_t attachmentp; attachmentp = avatarp->mAttachmentPoints.getNextData()) { - if (attachmentp->getObject(0)) + if (attachmentp->getObject()) { new_value = true; break; @@ -2003,7 +1972,7 @@ class LLObjectMute : public view_listener_t // it's an object id = object->getID(); - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (node) { name = node->mName; @@ -2023,7 +1992,6 @@ class LLObjectMute : public view_listener_t gFloaterMute->show(); } - gSelectMgr->deselectAll(); return true; } }; @@ -2041,9 +2009,6 @@ bool handle_go_to() strings.push_back(val); send_generic_message("autopilot", strings); - // Don't select anything - gSelectMgr->deselectTransient(); - gParcelMgr->deselectLand(); if (gAgent.getAvatarObject() && !gSavedSettings.getBOOL("AutoPilotLocksCamera")) @@ -2153,7 +2118,7 @@ class LLAvatarDebug : public view_listener_t } llinfos << "Dumping temporary asset data to simulator logs for avatar " << avatar->getID() << llendl; std::vector strings; - strings.push_back( avatar->getID().getString() ); + strings.push_back(avatar->getID().asString()); LLUUID invoice; send_generic_message("dumptempassetdata", strings, invoice); LLFloaterAvatarTextures::show( avatar->getID() ); @@ -2336,18 +2301,18 @@ void handle_leave_group(void *) void append_aggregate(LLString& string, const LLAggregatePermissions& ag_perm, PermissionBit bit, const char* txt) { LLAggregatePermissions::EValue val = ag_perm.getValue(bit); - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ buffer[0] = '\0'; switch(val) { case LLAggregatePermissions::AP_NONE: - sprintf(buffer, "* %s None\n", txt); + snprintf(buffer, MAX_STRING, "* %s None\n", txt); /* Flawfinder: ignore */ break; case LLAggregatePermissions::AP_SOME: - sprintf(buffer, "* %s Some\n", txt); + snprintf(buffer, MAX_STRING, "* %s Some\n", txt); /* Flawfinder: ignore */ break; case LLAggregatePermissions::AP_ALL: - sprintf(buffer, "* %s All\n", txt); + snprintf(buffer, MAX_STRING, "* %s All\n", txt); /* Flawfinder: ignore */ break; case LLAggregatePermissions::AP_EMPTY: default: @@ -2388,9 +2353,9 @@ BOOL enable_buy(void*) { // In order to buy, there must only be 1 purchaseable object in // the selection manger. - if(gSelectMgr->getRootObjectCount() != 1) return FALSE; + if(gSelectMgr->getSelection()->getRootObjectCount() != 1) return FALSE; LLViewerObject* obj = NULL; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if(node) { obj = node->getObject(); @@ -2451,14 +2416,12 @@ void handle_buy_object(LLSaleInfo sale_info) return; } - gSelectMgr->convertTransient(); LLFloaterBuy::show(sale_info); } void handle_buy_contents(LLSaleInfo sale_info) { - gSelectMgr->convertTransient(); LLFloaterBuyContents::show(sale_info); } @@ -2513,6 +2476,14 @@ void handle_dump_group_info(void *) //llinfos << "insig " << gAgent.mGroupInsigniaID << llendl; } +void handle_dump_capabilities_info(void *) +{ + LLViewerRegion* regionp = gAgent.getRegion(); + if (regionp) + { + regionp->logActiveCapabilities(); + } +} void handle_dump_focus(void *) { @@ -2590,10 +2561,12 @@ void set_god_level(U8 god_level) if (gInProductionGrid) { gMenuBarView->setBackgroundColor( gColors.getColor( "MenuBarGodBgColor" ) ); + gStatusBar->setBackgroundColor( gColors.getColor( "MenuBarGodBgColor" ) ); } else { gMenuBarView->setBackgroundColor( gColors.getColor( "MenuNonProductionGodBgColor" ) ); + gStatusBar->setBackgroundColor( gColors.getColor( "MenuNonProductionGodBgColor" ) ); } LLNotifyBox::showXml("EnteringGodMode", args); } @@ -2603,10 +2576,12 @@ void set_god_level(U8 god_level) if (gInProductionGrid) { gMenuBarView->setBackgroundColor( gColors.getColor( "MenuBarBgColor" ) ); + gStatusBar->setBackgroundColor( gColors.getColor( "MenuBarBgColor" ) ); } else { gMenuBarView->setBackgroundColor( gColors.getColor( "MenuNonProductionBgColor" ) ); + gStatusBar->setBackgroundColor( gColors.getColor( "MenuNonProductionBgColor" ) ); } LLNotifyBox::showXml("LeavingGodMode", args); } @@ -2801,7 +2776,6 @@ bool handle_sit_or_stand() if (sitting_on_selection()) { gAgent.setControlFlags(AGENT_CONTROL_STAND_UP); - gSelectMgr->deselectTransient(); return true; } @@ -2822,8 +2796,6 @@ bool handle_sit_or_stand() gMessageSystem->addVector3Fast(_PREHASH_Offset, offset_single); object->getRegion()->sendReliableMessage(); - - gSelectMgr->deselectTransient(); } return true; } @@ -2838,11 +2810,14 @@ class LLObjectSitOrStand : public view_listener_t void near_sit_down_point(BOOL success, void *) { - gAgent.setFlying(FALSE); - gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); + if (success) + { + gAgent.setFlying(FALSE); + gAgent.setControlFlags(AGENT_CONTROL_SIT_ON_GROUND); - // Might be first sit - LLFirstUse::useSit(); + // Might be first sit + LLFirstUse::useSit(); + } } class LLLandSit : public view_listener_t @@ -3182,13 +3157,12 @@ void reset_view_final( BOOL proceed, void* ) gAgent.changeCameraToDefault(); gAgent.resetView(!gFloaterTools->getVisible()); + gFloaterTools->close(); gViewerWindow->showCursor(); // Switch back to basic toolset - gCurrentToolset = gBasicToolset; - gBasicToolset->selectFirstTool(); - gToolMgr->useSelectedTool( gBasicToolset ); + gToolMgr->setCurrentToolset(gBasicToolset); } class LLViewLookAtLastChatter : public view_listener_t @@ -3261,7 +3235,7 @@ class LLEditEnableDuplicate : public view_listener_t void disabled_duplicate(void*) { - if (gSelectMgr->getFirstObject()) + if (gSelectMgr->getSelection()->getFirstObject()) { LLNotifyBox::showXml("CopyFailed"); } @@ -3291,7 +3265,7 @@ void handle_deed_object_to_group(void*) BOOL enable_deed_object_to_group(void*) { - if(gSelectMgr->isEmpty()) return FALSE; + if(gSelectMgr->getSelection()->isEmpty()) return FALSE; LLPermissions perm; LLUUID group_id; @@ -3350,8 +3324,8 @@ void handle_object_owner_permissive(void*) if(gAgent.isGodlike()) { // do the objects. - gSelectMgr->setObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE); - gSelectMgr->setObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE); + gSelectMgr->selectionSetObjectPermissions(PERM_BASE, TRUE, PERM_ALL, TRUE); + gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, TRUE, PERM_ALL, TRUE); } } @@ -3367,7 +3341,7 @@ void handle_object_owner_self(void*) // Shortcut to set owner permissions to not editable. void handle_object_lock(void*) { - gSelectMgr->setObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY); + gSelectMgr->selectionSetObjectPermissions(PERM_OWNER, FALSE, PERM_MODIFY); } void handle_object_asset_ids(void*) @@ -3412,17 +3386,17 @@ void handle_claim_public_land(void*) msg->nextBlock("MethodData"); msg->addString("Method", "claimpublicland"); msg->addUUID("Invoice", LLUUID::null); - char buffer[32]; - sprintf(buffer, "%f", west_south.mV[VX]); + char buffer[32]; /* Flawfinder: ignore */ + snprintf(buffer, sizeof(buffer), "%f", west_south.mV[VX]); /* Flawfinder: ignore */ msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); - sprintf(buffer, "%f", west_south.mV[VY]); + snprintf(buffer, sizeof(buffer), "%f", west_south.mV[VY]); /* Flawfinder: ignore */ msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); - sprintf(buffer, "%f", east_north.mV[VX]); + snprintf(buffer, sizeof(buffer), "%f", east_north.mV[VX]); /* Flawfinder: ignore */ msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); - sprintf(buffer, "%f", east_north.mV[VY]); + snprintf(buffer, sizeof(buffer), "%f", east_north.mV[VY]); /* Flawfinder: ignore */ msg->nextBlock("ParamList"); msg->addString("Parameter", buffer); gAgent.sendReliableMessage(); @@ -3519,8 +3493,9 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) } //gInventoryView->setPanelOpen(TRUE); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); LLViewerObject* object = NULL; - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = selection->getFirstRootNode(); if(!node) return; object = node->getObject(); if(!object) return; @@ -3531,7 +3506,7 @@ void derez_objects(EDeRezDestination dest, const LLUUID& dest_id) // everything that we'll actually be derezzing. LLDynamicArray derez_objects; BOOL can_derez_current; - for( ; node != NULL; node = gSelectMgr->getNextRootNode()) + for( ; node != NULL; node = selection->getNextRootNode()) { object = node->getObject(); if(!object || !node->mValid) continue; @@ -3665,42 +3640,47 @@ class LLToolsTakeCopy : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (gSelectMgr->isEmpty()) return true; + if (gSelectMgr->getSelection()->isEmpty()) return true; const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); derez_objects(DRD_ACQUIRE_TO_AGENT_INVENTORY, category_id); - // Only deselect if we're not building - if (!gToolMgr->inEdit()) - { - gSelectMgr->deselectTransient(); - } return true; } }; -void callback_return_to_owner(S32 option, void* data) -{ - if (0 == option) - { - // Ignore category ID for this derez destination. - derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null); - } -} - // You can return an object to its owner if it is on your land. class LLObjectReturn : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (gSelectMgr->isEmpty()) return true; + if (gSelectMgr->getSelection()->isEmpty()) return true; + + mObjectSelection = gSelectMgr->getEditSelection(); gViewerWindow->alertXml("ReturnToOwner", - callback_return_to_owner, - NULL); + onReturnToOwner, + (void*)this); return true; } + + static void onReturnToOwner(S32 option, void* data) + { + LLObjectReturn* object_return = (LLObjectReturn*)data; + + if (0 == option) + { + // Ignore category ID for this derez destination. + derez_objects(DRD_RETURN_TO_OWNER, LLUUID::null); + } + + // drop reference to current selection + object_return->mObjectSelection = NULL; + } + +protected: + LLObjectSelectionHandle mObjectSelection; }; @@ -3730,10 +3710,11 @@ class LLObjectEnableReturn : public view_listener_t } else { + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); LLViewerObject* obj = NULL; - for(obj = gSelectMgr->getFirstRootObject(); + for(obj = selection->getFirstRootObject(); obj; - obj = gSelectMgr->getNextRootObject()) + obj = selection->getNextRootObject()) { if (obj->isOverAgentOwnedLand() || obj->isOverGroupOwnedLand() @@ -3754,22 +3735,16 @@ class LLObjectEnableReturn : public view_listener_t void force_take_copy(void*) { - if (gSelectMgr->isEmpty()) return; + if (gSelectMgr->getSelection()->isEmpty()) return; const LLUUID& category_id = gInventory.findCategoryUUIDForType(LLAssetType::AT_OBJECT); derez_objects(DRD_FORCE_TO_GOD_INVENTORY, category_id); - - // Only deselect if we're not building - if (!gToolMgr->inEdit()) - { - gSelectMgr->deselectTransient(); - } } #ifdef _CORY_TESTING void force_export_copy(void*) { LLViewerObject* object = NULL; - LLSelectNode* node = gSelectMgr->getFirstNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstNode(); if(!node) return; object = node->getObject(); if(!object) return; @@ -3790,7 +3765,7 @@ void force_export_copy(void*) S32 object_index = 0; - for( ; node != NULL; node = gSelectMgr->getNextNode()) + for( ; node != NULL; node = gSelectMgr->getSelection()->getNextNode()) { object = node->getObject(); if(!object || !node->mValid) @@ -3831,8 +3806,9 @@ void force_export_copy(void*) } // Copy the directory + file name - char filepath[LL_MAX_PATH]; - strcpy(filepath, picker.getFirstFile()); + char filepath[LL_MAX_PATH]; /* Flawfinder: ignore */ + strncpy(filepath, picker.getFirstFile(), LL_MAX_PATH -1); /* Flawfinder: ignore */ + filepath[LL_MAX_PATH -1] = '\0'; apr_file_t* fp = ll_apr_file_open(filepath, LL_APR_W); @@ -3876,7 +3852,7 @@ void force_export_copy(void*) LLColor4 color = te->getColor(); apr_file_printf(fp, "\tgetID(); texid.toString(texture); F32 sx, sy, ox, oy; @@ -3942,8 +3918,9 @@ void force_import_geometry(void*) return; } - char directory[LL_MAX_PATH]; - strcpy(directory, picker.getFirstFile()); + char directory[LL_MAX_PATH]; /* Flawfinder: ignore */ + strncpy(directory, picker.getFirstFile(), LL_MAX_PATH -1); /* Flawfinder: ignore */ + directory[LL_MAX_PATH -1] = '\0'; llinfos << "Loading LSG file " << directory << llendl; LLXmlTree *xmlparser = new LLXmlTree(); @@ -3966,8 +3943,8 @@ void force_import_geometry(void*) { // get object data // *NOTE: This buffer size is hard coded into scanf() below. - char name[255]; // Shape - char description[255]; // Description + char name[255]; /* Flawfinder: ignore */ // Shape + char description[255]; /* Flawfinder: ignore */ // Description U32 material; // Material F32 sx, sy, sz; // Scale LLVector3 scale; @@ -3998,9 +3975,11 @@ void force_import_geometry(void*) child->getAttributeString("PCode", &attribute); pcode = atoi(attribute.c_str()); child->getAttributeString("Shape", &attribute); - sscanf(attribute.c_str(), "%254s", name); + sscanf( /* Flawfinder: ignore */ + attribute.c_str(), "%254s", name); child->getAttributeString("Description", &attribute); - sscanf(attribute.c_str(), "%254s", description); + sscanf( /* Flawfinder: ignore */ + attribute.c_str(), "%254s", description); child->getAttributeString("Material", &attribute); material = atoi(attribute.c_str()); child->getAttributeString("Scale", &attribute); @@ -4115,16 +4094,16 @@ void handle_take() { // we want to use the folder this was derezzed from if it's // available. Otherwise, derez to the normal place. - if(gSelectMgr->isEmpty()) return; + if(gSelectMgr->getSelection()->isEmpty()) return; LLSelectNode* node = NULL; LLViewerObject* object = NULL; BOOL you_own_everything = TRUE; BOOL locked_but_takeable_object = FALSE; LLUUID category_id; - for(node = gSelectMgr->getFirstRootNode(); + for(node = gSelectMgr->getSelection()->getFirstRootNode(); node != NULL; - node = gSelectMgr->getNextRootNode()) + node = gSelectMgr->getSelection()->getNextRootNode()) { object = node->getObject(); if(object) @@ -4160,7 +4139,7 @@ void handle_take() if(category_id.notNull()) { // there is an unambiguous destination. See if this agent has - // such a location and it is not in the trash. + // such a location and it is not in the trash or library if(!gInventory.getCategory(category_id)) { // nope, set to NULL. @@ -4168,12 +4147,20 @@ void handle_take() } if(category_id.notNull()) { + // check trash LLUUID trash; trash = gInventory.findCategoryUUIDForType(LLAssetType::AT_TRASH); if(category_id == trash || gInventory.isObjectDescendentOf(category_id, trash)) { category_id.setNull(); } + + // check library + if(gInventory.isObjectDescendentOf(category_id, gInventoryLibraryRoot)) + { + category_id.setNull(); + } + } } if(category_id.isNull()) @@ -4185,10 +4172,8 @@ void handle_take() !you_own_everything) { - if(locked_but_takeable_object && you_own_everything) { - gViewerWindow->alertXml("ConfirmObjectTakeLock", confirm_take, (void*)cat_id); @@ -4196,7 +4181,6 @@ void handle_take() } else if(!locked_but_takeable_object && !you_own_everything) { - gViewerWindow->alertXml("ConfirmObjectTakeNoOwn", confirm_take, (void*)cat_id); @@ -4239,9 +4223,9 @@ BOOL enable_take() } LLViewerObject* object = NULL; - for(LLSelectNode* node = gSelectMgr->getFirstRootNode(); + for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); node != NULL; - node = gSelectMgr->getNextRootNode()) + node = gSelectMgr->getSelection()->getNextRootNode()) { object = node->getObject(); if(!object || !node->mValid) continue; @@ -4275,7 +4259,7 @@ class LLToolsBuyOrTake : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - if (gSelectMgr->isEmpty()) + if (gSelectMgr->getSelection()->isEmpty()) { return true; } @@ -4355,9 +4339,9 @@ class LLToolsEnableBuyOrTake : public view_listener_t BOOL is_selection_buy_not_take() { LLViewerObject* obj = NULL; - for(LLSelectNode* node = gSelectMgr->getFirstRootNode(); + for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); node != NULL; - node = gSelectMgr->getNextRootNode()) + node = gSelectMgr->getSelection()->getNextRootNode()) { obj = node->getObject(); if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) @@ -4374,9 +4358,9 @@ S32 selection_price() { LLViewerObject* obj = NULL; S32 total_price = 0; - for(LLSelectNode* node = gSelectMgr->getFirstRootNode(); + for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); node != NULL; - node = gSelectMgr->getNextRootNode()) + node = gSelectMgr->getSelection()->getNextRootNode()) { obj = node->getObject(); if(obj && !(obj->permYouOwner()) && (node->mSaleInfo.isForSale())) @@ -4425,7 +4409,7 @@ void handle_buy_currency(void*) void handle_buy(void*) { - if (gSelectMgr->isEmpty()) return; + if (gSelectMgr->getSelection()->isEmpty()) return; LLSaleInfo sale_info; BOOL valid = gSelectMgr->selectGetSaleInfo(sale_info); @@ -4452,7 +4436,7 @@ class LLObjectBuy : public view_listener_t BOOL sitting_on_selection() { - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (!node) { return FALSE; @@ -4497,7 +4481,7 @@ class LLToolsSaveToObjectInventory : public view_listener_t { if(gSelectMgr) { - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if(node && (node->mValid) && (!node->mFromTaskID.isNull())) { // *TODO: check to see if the fromtaskid object exists. @@ -4516,9 +4500,10 @@ class LLToolsSnapObjectXY : public view_listener_t F64 snap_size = (F64)gSavedSettings.getF32("GridResolution"); LLViewerObject* obj; - for (obj = gSelectMgr->getFirstRootObject(); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (obj = selection->getFirstRootObject(); obj != NULL; - obj = gSelectMgr->getNextRootObject()) + obj = selection->getNextRootObject()) { if (obj->permModify()) { @@ -4574,11 +4559,12 @@ class LLToolsEnableLink : public view_listener_t // in component mode, can't link if (gSavedSettings.getBOOL("SelectLinkedSet")) { - if(gSelectMgr->selectGetAllRootsValid() && gSelectMgr->getRootObjectCount() >= 2) + if(gSelectMgr->selectGetAllRootsValid() && gSelectMgr->getSelection()->getRootObjectCount() >= 2) { - for(LLViewerObject* object = gSelectMgr->getFirstRootObject(); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for(LLViewerObject* object = selection->getFirstRootObject(); object != NULL; - object = gSelectMgr->getNextRootObject()) + object = selection->getNextRootObject()) { if(object->permModify()) { @@ -4603,7 +4589,7 @@ class LLToolsLink : public view_listener_t return true; } - S32 object_count = gSelectMgr->getObjectCount(); + S32 object_count = gSelectMgr->getSelection()->getObjectCount(); if (object_count > MAX_CHILDREN_PER_TASK + 1) { LLStringBase::format_map_t args; @@ -4614,7 +4600,7 @@ class LLToolsLink : public view_listener_t return true; } - if(gSelectMgr->getRootObjectCount() < 2) + if(gSelectMgr->getSelection()->getRootObjectCount() < 2) { gViewerWindow->alertXml("CannotLinkIncompleteSet"); return true; @@ -4644,8 +4630,8 @@ class LLToolsEnableUnlink : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { bool new_value = gSelectMgr->selectGetAllRootsValid() && - gSelectMgr->getFirstEditableObject() && - !gSelectMgr->getFirstEditableObject()->isAttachment(); + gSelectMgr->getSelection()->getFirstEditableObject() && + !gSelectMgr->getSelection()->getFirstEditableObject()->isAttachment(); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -4707,7 +4693,7 @@ void handle_dehinge(void*) BOOL enable_dehinge(void*) { - LLViewerObject* obj = gSelectMgr->getFirstEditableObject(); + LLViewerObject* obj = gSelectMgr->getSelection()->getFirstEditableObject(); return obj && !obj->isAttachment(); } @@ -5003,7 +4989,7 @@ void toggle_map( void* user_data ) } else { - gFloaterMap->open(); + gFloaterMap->open(); /* Flawfinder: ignore */ } } @@ -5082,8 +5068,8 @@ const char* upload_pick(void* data) { const char* cur_token = token_iter->c_str(); - if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || - 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) + if (0 == strnicmp(cur_token, ext, strlen(cur_token)) || /* Flawfinder: ignore */ + 0 == strnicmp(cur_token, "*.*", strlen(cur_token))) /* Flawfinder: ignore */ { //valid extension //or the acceptable extension is any @@ -5110,7 +5096,7 @@ const char* upload_pick(void* data) if (type == LLFilePicker::FFLOAD_WAV) { // pre-qualify wavs to make sure the format is acceptable - char error_msg[MAX_STRING]; + char error_msg[MAX_STRING]; /* Flawfinder: ignore */ if (check_for_invalid_wav_formats(filename,error_msg)) { llinfos << error_msg << ": " << filename << llendl; @@ -5213,7 +5199,7 @@ class LLFileUploadBulk : public view_listener_t char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists if( !end_p ) { - end_p = asset_name_str + strlen( asset_name_str ); + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ } S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); @@ -5241,15 +5227,23 @@ void upload_error(const char* error_message, const char* label, const std::strin LLFilePicker::instance().reset(); } +class LLFileEnableCloseWindow : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + bool new_value = gFloaterView->getFocusedFloater() != NULL || gSnapshotFloaterView->getFocusedFloater() != NULL; + // horrendously opaque, this code + gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); + return true; + } +}; + class LLFileCloseWindow : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLFloater *top = gFloaterView->getFrontmost(); - if (top && top->hasFocus()) - { - LLFloater::closeByMenu( top ); - } + LLFloater::closeFocusedFloater(); + return true; } }; @@ -5394,7 +5388,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, LLString ext = src_filename.substr(src_filename.find_last_of('.')); LLAssetType::EType asset_type = LLAssetType::AT_NONE; - char error_message[MAX_STRING]; + char error_message[MAX_STRING]; /* Flawfinder: ignore */ error_message[0] = '\0'; LLString temp_str; @@ -5408,7 +5402,8 @@ void upload_new_resource(const LLString& src_filename, std::string name, LLString short_name = filename.substr(offset); // No extension - sprintf(error_message, + snprintf(error_message, /* Flawfinder: ignore */ + MAX_STRING, "No file extension for the file: '%s'\nPlease make sure the file has a correct file extension", short_name.c_str()); args["[FILE]"] = short_name; @@ -5422,7 +5417,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, filename, IMG_CODEC_BMP )) { - sprintf(error_message, "Problem with file %s:\n\n%s\n", + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ src_filename.c_str(), LLImageBase::getLastError().c_str()); args["[FILE]"] = src_filename; args["[ERROR]"] = LLImageBase::getLastError(); @@ -5437,7 +5432,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, filename, IMG_CODEC_TGA )) { - sprintf(error_message, "Problem with file %s:\n\n%s\n", + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ src_filename.c_str(), LLImageBase::getLastError().c_str()); args["[FILE]"] = src_filename; args["[ERROR]"] = LLImageBase::getLastError(); @@ -5452,7 +5447,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, filename, IMG_CODEC_JPEG )) { - sprintf(error_message, "Problem with file %s:\n\n%s\n", + snprintf(error_message, MAX_STRING, "Problem with file %s:\n\n%s\n", /* Flawfinder: ignore */ src_filename.c_str(), LLImageBase::getLastError().c_str()); args["[FILE]"] = src_filename; args["[ERROR]"] = LLImageBase::getLastError(); @@ -5480,13 +5475,13 @@ void upload_new_resource(const LLString& src_filename, std::string name, switch(encode_result) { case LLVORBISENC_DEST_OPEN_ERR: - sprintf(error_message, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); + snprintf(error_message, MAX_STRING, "Couldn't open temporary compressed sound file for writing: %s\n", filename.c_str()); /* Flawfinder: ignore */ args["[FILE]"] = filename; upload_error(error_message, "CannotOpenTemporarySoundFile", filename, args); break; default: - sprintf(error_message, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); + snprintf(error_message, MAX_STRING, "Unknown vorbis encode failure on: %s\n", src_filename.c_str()); /* Flawfinder: ignore */ args["[FILE]"] = src_filename; upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args); break; @@ -5498,26 +5493,29 @@ void upload_new_resource(const LLString& src_filename, std::string name, { // This is a generic .lin resource file asset_type = LLAssetType::AT_OBJECT; - FILE *in = LLFile::fopen(src_filename.c_str(), "rb"); + FILE* in = LLFile::fopen(src_filename.c_str(), "rb"); /* Flawfinder: ignore */ if (in) { // read in the file header - char buf[16384]; - S32 read; + char buf[16384]; /* Flawfinder: ignore */ + S32 read; /* Flawfinder: ignore */ S32 version; if (fscanf(in, "LindenResource\nversion %d\n", &version)) { if (2 == version) { // *NOTE: This buffer size is hard coded into scanf() below. - char label[MAX_STRING]; - char value[MAX_STRING]; + char label[MAX_STRING]; /* Flawfinder: ignore */ + char value[MAX_STRING]; /* Flawfinder: ignore */ S32 tokens_read; while (fgets(buf, 1024, in)) { label[0] = '\0'; value[0] = '\0'; - tokens_read = sscanf(buf, "%254s %254s\n", label, value); + tokens_read = sscanf( /* Flawfinder: ignore */ + buf, + "%254s %254s\n", + label, value); llinfos << "got: " << label << " = " << value << llendl; @@ -5525,7 +5523,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, if (EOF == tokens_read) { fclose(in); - sprintf(error_message, "corrupt resource file: %s", src_filename.c_str()); + snprintf(error_message, MAX_STRING, "corrupt resource file: %s", src_filename.c_str()); /* Flawfinder: ignore */ args["[FILE]"] = src_filename; upload_error(error_message, "CorruptResourceFile", filename, args); return; @@ -5553,7 +5551,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, else { fclose(in); - sprintf(error_message, "unknown linden resource file version in file: %s", src_filename.c_str()); + snprintf(error_message, MAX_STRING, "unknown linden resource file version in file: %s", src_filename.c_str()); /* Flawfinder: ignore */ args["[FILE]"] = src_filename; upload_error(error_message, "UnknownResourceFileVersion", filename, args); return; @@ -5572,24 +5570,24 @@ void upload_new_resource(const LLString& src_filename, std::string name, // read in and throw out most of the header except for the type fread(buf, header_size, 1, in); - memcpy(&type_num, buf + 16, sizeof(S16)); + memcpy(&type_num, buf + 16, sizeof(S16)); /* Flawfinder: ignore */ asset_type = (LLAssetType::EType)type_num; } // copy the file's data segment into another file for uploading - FILE *out = LLFile::fopen(filename.c_str(), "wb"); + FILE* out = LLFile::fopen(filename.c_str(), "wb"); /* Flawfinder: ignore */ if (out) { - while((read = fread(buf, 1, 16384, in))) + while((read = fread(buf, 1, 16384, in))) /* Flawfinder: ignore */ { - fwrite(buf, 1, read, out); + fwrite(buf, 1, read, out); /* Flawfinder: ignore */ } fclose(out); } else { fclose(in); - sprintf(error_message, "Unable to create output file: %s", filename.c_str()); + snprintf(error_message, MAX_STRING, "Unable to create output file: %s", filename.c_str()); /* Flawfinder: ignore */ args["[FILE]"] = filename; upload_error(error_message, "UnableToCreateOutputFile", filename, args); return; @@ -5604,14 +5602,14 @@ void upload_new_resource(const LLString& src_filename, std::string name, } else if (LLString::compareInsensitive(ext.c_str(),".bvh") == 0) { - sprintf(error_message, "We do not currently support bulk upload of animation files\n"); + snprintf(error_message, MAX_STRING, "We do not currently support bulk upload of animation files\n"); /* Flawfinder: ignore */ upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args); return; } else { // Unknown extension - sprintf(error_message, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); + snprintf(error_message, MAX_STRING, "Unknown file extension %s\nExpected .wav, .tga, .bmp, .jpg, .jpeg, or .bvh", ext.c_str()); /* Flawfinder: ignore */ error = TRUE;; } @@ -5640,7 +5638,7 @@ void upload_new_resource(const LLString& src_filename, std::string name, } else { - sprintf(error_message, "Unable to access output file: %s", filename.c_str()); + snprintf(error_message, MAX_STRING, "Unable to access output file: %s", filename.c_str()); /* Flawfinder: ignore */ error = TRUE; } } @@ -5724,7 +5722,7 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty llinfos << "Desc: " << desc << llendl; lldebugs << "Folder: " << gInventory.findCategoryUUIDForType(destination_folder_type) << llendl; lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl; - std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory"); if (!url.empty()) { llinfos << "New Agent Inventory via capability" << llendl; @@ -5738,7 +5736,7 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty std::ostringstream llsdxml; LLSDSerialize::toXML(body, llsdxml); lldebugs << "posting body to capability: " << llsdxml.str() << llendl; - LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(uuid, body)); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type)); } else { @@ -5884,7 +5882,7 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result) // St char* end_p = strrchr(asset_name_str, '.'); // strip extension if exists if( !end_p ) { - end_p = asset_name_str + strlen( asset_name_str ); + end_p = asset_name_str + strlen( asset_name_str ); /* Flawfinder: ignore */ } S32 len = llmin( (S32) (DB_INV_ITEM_NAME_STR_LEN), (S32) (end_p - asset_name_str) ); @@ -5903,12 +5901,13 @@ LLUploadDialog *gExportDialog = NULL; void handle_export_selected( void * ) { - if (gSelectMgr->isEmpty()) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (selection->isEmpty()) { return; } llinfos << "Exporting selected objects:" << llendl; - LLViewerObject *object = gSelectMgr->getFirstRootObject(); + LLViewerObject *object = selection->getFirstRootObject(); gExporterRequestID.generate(); gExportDirectory = ""; @@ -5920,7 +5919,7 @@ void handle_export_selected( void * ) msg->addUUIDFast(_PREHASH_RequestID, gExporterRequestID); msg->addS16Fast(_PREHASH_VolumeDetail, 4); - for (; object != NULL; object = gSelectMgr->getNextRootObject()) + for (; object != NULL; object = selection->getNextRootObject()) { msg->nextBlockFast(_PREHASH_ObjectData); msg->addUUIDFast(_PREHASH_ObjectID, object->getID()); @@ -5934,7 +5933,7 @@ void handle_export_selected( void * ) BOOL menu_check_build_tool( void* user_data ) { S32 index = (intptr_t) user_data; - return gCurrentToolset->isToolSelected( index ); + return gToolMgr->getCurrentToolset()->isToolSelected( index ); } void handle_reload_settings(void*) @@ -6083,7 +6082,7 @@ class LLToolsLookAtSelection : public view_listener_t { const F32 PADDING_FACTOR = 2.f; BOOL zoom = (userdata.asString() == "zoom"); - if (!gSelectMgr->isEmpty()) + if (!gSelectMgr->getSelection()->isEmpty()) { gAgent.setFocusOnAvatar(FALSE, ANIMATE); @@ -6096,26 +6095,17 @@ class LLToolsLookAtSelection : public view_listener_t if (zoom) { - gAgent.setCameraPosAndFocusGlobal(gSelectMgr->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getFirstObject()->mID ); + gAgent.setCameraPosAndFocusGlobal(gSelectMgr->getSelectionCenterGlobal() + LLVector3d(obj_to_cam * distance), gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getSelection()->getFirstObject()->mID ); } else { - gAgent.setFocusGlobal( gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getFirstObject()->mID ); + gAgent.setFocusGlobal( gSelectMgr->getSelectionCenterGlobal(), gSelectMgr->getSelection()->getFirstObject()->mID ); } } return true; } }; -/* -void handle_reset_rotation(void*) -{ - gSelectMgr->selectionResetRotation(); - - dialog_refresh_all(); -} -*/ - class LLAvatarAddFriend : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) @@ -6125,7 +6115,6 @@ class LLAvatarAddFriend : public view_listener_t { request_friendship(avatar->getID()); } - gSelectMgr->deselectTransient(); return true; } }; @@ -6137,54 +6126,47 @@ void complete_give_money(S32 option, void* user_data) gAgent.clearBusy(); } - LLUUID* object_id = (LLUUID*)user_data; + LLObjectSelectionHandle handle(*(LLObjectSelectionHandle*)user_data); + delete (LLObjectSelectionHandle*)user_data; - LLViewerObject* object = gObjectList.findObject(*object_id); - if (object) + LLViewerObject* objectp = handle->getPrimaryObject(); + + // Show avatar's name if paying attachment + if (objectp && objectp->isAttachment()) { - if (object->isAvatar()) + while (objectp && !objectp->isAvatar()) + { + objectp = (LLViewerObject*)objectp->getParent(); + } + } + + if (objectp) + { + if (objectp->isAvatar()) { const BOOL is_group = FALSE; LLFloaterPay::payDirectly(&give_money, - *object_id, + objectp->getID(), is_group); } else { - LLFloaterPay::payViaObject(&give_money, *object_id); + LLFloaterPay::payViaObject(&give_money, objectp->getID()); } } - - delete object_id; } bool handle_give_money_dialog() { - LLViewerObject *objectp = gViewerWindow->lastObjectHit(); - LLUUID* object_id = new LLUUID(); - - // Show avatar's name if paying attachment - if (objectp && objectp->isAttachment()) - { - while (objectp && !objectp->isAvatar()) - { - objectp = (LLViewerObject*)objectp->getParent(); - } - } - - if (objectp) - { - *object_id = objectp->getID(); - } - + LLObjectSelectionHandle* handlep = new LLObjectSelectionHandle(gSelectMgr->getSelection()); if (gAgent.getBusy()) { // warn users of being in busy mode during a transaction - gViewerWindow->alertXml("BusyModePay", complete_give_money, object_id); + gViewerWindow->alertXml("BusyModePay", complete_give_money, handlep); } else { - complete_give_money(1, object_id); + complete_give_money(1, handlep); } return true; } @@ -6252,7 +6234,7 @@ class LLObjectEnableSitOrStand : public view_listener_t } else { - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if (node && node->mValid && !node->mSitName.empty()) { label.assign(node->mSitName); @@ -6288,25 +6270,6 @@ void dump_inventory(void*) gInventory.dumpInventory(); } - -void handle_first_tool(void*) -{ - gCurrentToolset->selectFirstTool(); -} - - -void handle_next_tool(void*) -{ - gCurrentToolset->selectNextTool(); -} - - -void handle_previous_tool(void*) -{ - gCurrentToolset->selectPrevTool(); -} - - // forcibly unlock an object void handle_force_unlock(void*) { @@ -6315,7 +6278,7 @@ void handle_force_unlock(void*) // Second, lie to the viewer and mark it editable and unowned LLViewerObject* object; - for (object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() ) + for (object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() ) { object->mFlags |= FLAGS_OBJECT_MOVE; object->mFlags |= FLAGS_OBJECT_MODIFY; @@ -6377,24 +6340,6 @@ void handle_dump_followcam(void*) LLFollowCamMgr::dump(); } -void handle_viewer_enable_circuit_log(void*) -{ - llinfos << "Showing circuit information every " << gMessageSystem->mCircuitPrintFreq << " seconds" << llendl; - gErrorStream.setLevel( LLErrorStream::DEBUG ); - gErrorStream.setDebugFlag( LLERR_CIRCUIT_INFO ); - // and dump stuff out immediately - gMessageSystem->dumpCircuitInfo(); -} - -void handle_viewer_disable_circuit_log(void*) -{ - llinfos << "Hiding circuit information" << llendl; -#if !LL_DEBUG - gErrorStream.setLevel( LLErrorStream::INFO ); -#endif - gErrorStream.clearDebugFlag( LLERR_CIRCUIT_INFO ); -} - void handle_viewer_enable_message_log(void*) { gMessageSystem->startLogging(); @@ -6470,10 +6415,6 @@ class LLShowFloater : public view_listener_t { gDebugView->mStatViewp->setVisible(!gDebugView->mStatViewp->getVisible()); } - else if (floater_name == "account history") - { - LLFloaterAccountHistory::show(NULL); - } else if (floater_name == "my land") { LLFloaterLandHoldings::show(NULL); @@ -6624,7 +6565,15 @@ class LLPromptShowURL : public view_listener_t LLString alert = param.substr(0, offset); LLString url = param.substr(offset+1); char *url_copy = new char[url.size()+1]; - strcpy(url_copy, url.c_str()); + if (url_copy != NULL) + { + strcpy(url_copy, url.c_str()); /* Flawfinder: ignore */ + } + else + { + llerrs << "Memory Allocation Failed" << llendl; + return false; + } gViewerWindow->alertXml(alert, callback_show_url, url_copy); } else @@ -6656,7 +6605,15 @@ class LLPromptShowFile : public view_listener_t LLString alert = param.substr(0, offset); LLString file = param.substr(offset+1); char *file_copy = new char[file.size()+1]; - strcpy(file_copy, file.c_str()); + if (file_copy != NULL) + { + strcpy(file_copy, file.c_str()); /* Flawfinder: ignore */ + } + else + { + llerrs << "Memory Allocation Failed" << llendl; + return false; + } gViewerWindow->alertXml(alert, callback_show_file, file_copy); } else @@ -6737,8 +6694,8 @@ void handle_focus(void *) gViewerWindow->moveCursorToCenter(); // Switch to camera toolset -// gCurrentToolset = gCameraToolset; - gCurrentToolset->selectTool( gToolCamera ); +// gToolMgr->setCurrentToolset(gCameraToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolCamera ); } class LLLandEdit : public view_listener_t @@ -6764,10 +6721,10 @@ class LLLandEdit : public view_listener_t gParcelMgr->selectParcelAt( gLastHitPosGlobal ); gFloaterTools->showMore(TRUE); - gFloaterView->bringToFront( gFloaterTools ); + gFloaterView->bringToFront( gFloaterTools ); // Switch to land edit toolset - gCurrentToolset->selectTool( gToolParcel ); + gToolMgr->getCurrentToolset()->selectTool( gToolParcel ); return true; } }; @@ -6779,7 +6736,7 @@ class LLWorldEnableBuyLand : public view_listener_t bool new_value = gParcelMgr->canAgentBuyParcel( gParcelMgr->selectionEmpty() ? gParcelMgr->getAgentParcel() - : gParcelMgr->getSelectedParcel(), + : gParcelMgr->getParcelSelection()->getParcel(), false); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; @@ -6789,7 +6746,7 @@ class LLWorldEnableBuyLand : public view_listener_t BOOL enable_buy_land(void*) { return gParcelMgr->canAgentBuyParcel( - gParcelMgr->getSelectedParcel(), false); + gParcelMgr->getParcelSelection()->getParcel(), false); } @@ -6810,66 +6767,63 @@ void handle_move(void*) gViewerWindow->moveCursorToCenter(); - gCurrentToolset = gBasicToolset; - gCurrentToolset->selectTool( gToolGrab ); -} - - -void near_attach_object(BOOL success, void *user_data) -{ - LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; - - U8 attachment_id; - if (attachment) - { - attachment_id = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment); - } - else - { - // interpret 0 as "default location" - attachment_id = 0; - } - - gSelectMgr->sendAttach(attachment_id); + gToolMgr->setCurrentToolset(gBasicToolset); + gToolMgr->getCurrentToolset()->selectTool( gToolGrab ); } class LLObjectAttachToAvatar : public view_listener_t { +public: + static void setObjectSelection(LLObjectSelectionHandle selection) { sObjectSelection = selection; } + +private: bool handleEvent(LLPointer event, const LLSD& userdata) { - LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject(); + setObjectSelection(gSelectMgr->getSelection()); + LLViewerObject* selectedObject = sObjectSelection->getFirstRootObject(); if (selectedObject) { - confirm_replace_attachment(0, NULL); + S32 index = userdata.asInteger(); + LLViewerJointAttachment* attachment_point = index > 0 ? + gAgent.getAvatarObject()->mAttachmentPoints[index] : + NULL; + confirm_replace_attachment(0, attachment_point); } return true; } + +protected: + static LLObjectSelectionHandle sObjectSelection; }; -// move this somewhere global -void handle_attach_to_avatar(void* user_data) -{ - LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject(); - if (selectedObject) - { - LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; +LLObjectSelectionHandle LLObjectAttachToAvatar::sObjectSelection; - if (attachment && attachment->getObject(0)) - { - gViewerWindow->alertXml("ReplaceAttachment", confirm_replace_attachment, user_data); - } - else - { - confirm_replace_attachment(0, user_data); - } - } +void near_attach_object(BOOL success, void *user_data) +{ + if (success) + { + LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; + + U8 attachment_id; + if (attachment) + { + attachment_id = gAgent.getAvatarObject()->mAttachmentPoints.reverseLookup(attachment); + } + else + { + // interpret 0 as "default location" + attachment_id = 0; + } + gSelectMgr->sendAttach(attachment_id); + } + LLObjectAttachToAvatar::setObjectSelection(NULL); } + void confirm_replace_attachment(S32 option, void* user_data) { if (option == 0/*YES*/) { - gSelectMgr->convertTransient(); - LLViewerObject* selectedObject = gSelectMgr->getFirstRootObject(); + LLViewerObject* selectedObject = gSelectMgr->getSelection()->getFirstRootObject(); if (selectedObject) { const F32 MIN_STOP_DISTANCE = 1.f; // meters @@ -6936,12 +6890,7 @@ class LLAttachmentDrop : public view_listener_t // objects. Thus we need to clear the list, make sure it only // contains the object the user clicked, send the message, // then clear the list. - // We use deselectAll to update the simulator's notion of what's - // selected, and removeAll just to change things locally. - //gSelectMgr->deselectAll(); - //gSelectMgr->selectObjectAndFamily(object); gSelectMgr->sendDropAttachment(); - gSelectMgr->deselectTransient(); return true; } }; @@ -6951,7 +6900,7 @@ void handle_detach_from_avatar(void* user_data) { LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; - LLViewerObject* attached_object = attachment->getObject(0); + LLViewerObject* attached_object = attachment->getObject(); if (attached_object) { @@ -6972,7 +6921,7 @@ void attach_label(LLString& label, void* user_data) if (attachmentp) { label = attachmentp->getName(); - if (attachmentp->getObject(0)) + if (attachmentp->getObject()) { LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID()); if (itemp) @@ -6989,7 +6938,7 @@ void detach_label(LLString& label, void* user_data) if (attachmentp) { label = attachmentp->getName(); - if (attachmentp->getObject(0)) + if (attachmentp->getObject()) { LLViewerInventoryItem* itemp = gInventory.getItem(attachmentp->getItemID()); if (itemp) @@ -7044,10 +6993,9 @@ class LLAttachmentDetach : public view_listener_t // We use deselectAll to update the simulator's notion of what's // selected, and removeAll just to change things locally. //RN: I thought it was more useful to detach everything that was selected - if (gSelectMgr->selectionIsAttachment()) + if (gSelectMgr->getSelection()->isAttachment()) { gSelectMgr->sendDetach(); - gSelectMgr->deselectAll(); } return true; } @@ -7164,8 +7112,10 @@ class LLAttachmentEnableDetach : public view_listener_t BOOL object_selected_and_point_valid(void *user_data) { //LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; + if (gSelectMgr == NULL) return FALSE; - for (LLViewerObject *object = gSelectMgr->getFirstRootObject(); object; object = gSelectMgr->getNextRootObject()) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (LLViewerObject *object = selection->getFirstRootObject(); object; object = selection->getNextRootObject()) { for (U32 child_num = 0; child_num < object->mChildList.size(); child_num++ ) { @@ -7176,12 +7126,11 @@ BOOL object_selected_and_point_valid(void *user_data) } } - return ((gSelectMgr != NULL) && - (gSelectMgr->getRootObjectCount() == 1) && - (gSelectMgr->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && - gSelectMgr->getFirstRootObject()->permYouOwner() && - !((LLViewerObject*)gSelectMgr->getFirstRootObject()->getRoot())->isAvatar() && - (gSelectMgr->getFirstRootObject()->getNVPair("AssetContainer") == NULL)); + return (selection->getRootObjectCount() == 1) && + (selection->getFirstRootObject()->getPCode() == LL_PCODE_VOLUME) && + selection->getFirstRootObject()->permYouOwner() && + !((LLViewerObject*)selection->getFirstRootObject()->getRoot())->isAvatar() && + (selection->getFirstRootObject()->getNVPair("AssetContainer") == NULL); } // Also for seeing if object can be attached. See above. @@ -7189,22 +7138,7 @@ class LLObjectEnableWear : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = false; - if (gSelectMgr) - { - LLViewerObject* first_root = gSelectMgr->getFirstRootObject(); - if (first_root) - { - new_value = gSelectMgr->getRootObjectCount() == 1 - && first_root->getPCode() == LL_PCODE_VOLUME - && first_root->permYouOwner() - && !((LLViewerObject*)gSelectMgr->getFirstRootObject()->getRoot())->isAvatar() - && (first_root->getNVPair("AssetContainer") == NULL); - } - } - - gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); - return true; + return object_selected_and_point_valid(NULL); } }; @@ -7213,7 +7147,7 @@ BOOL object_attached(void *user_data) { LLViewerJointAttachment *attachment = (LLViewerJointAttachment *)user_data; - return attachment->getObject(0) != NULL; + return attachment->getObject() != NULL; } class LLAvatarSendIM : public view_listener_t @@ -7281,9 +7215,9 @@ class LLToolsSelectedScriptAction : public view_listener_t BOOL scripted = FALSE; BOOL modifiable = FALSE; - for(LLViewerObject* obj = gSelectMgr->getFirstObject(); + for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject(); obj; - obj = gSelectMgr->getNextObject()) + obj = gSelectMgr->getSelection()->getNextObject()) { scripted = obj->flagScripted(); modifiable = obj->permModify(); @@ -7316,9 +7250,9 @@ void handle_reset_selection(void*) BOOL scripted = FALSE; BOOL modifiable = FALSE; - for(LLViewerObject* obj = gSelectMgr->getFirstObject(); + for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject(); obj; - obj = gSelectMgr->getNextObject()) + obj = gSelectMgr->getSelection()->getNextObject()) { scripted = obj->flagScripted(); modifiable = obj->permModify(); @@ -7349,9 +7283,9 @@ void handle_set_run_selection(void*) BOOL scripted = FALSE; BOOL modifiable = FALSE; - for(LLViewerObject* obj = gSelectMgr->getFirstObject(); + for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject(); obj; - obj = gSelectMgr->getNextObject()) + obj = gSelectMgr->getSelection()->getNextObject()) { scripted = obj->flagScripted(); modifiable = obj->permModify(); @@ -7382,9 +7316,9 @@ void handle_set_not_run_selection(void*) BOOL scripted = FALSE; BOOL modifiable = FALSE; - for(LLViewerObject* obj = gSelectMgr->getFirstObject(); + for(LLViewerObject* obj = gSelectMgr->getSelection()->getFirstObject(); obj; - obj = gSelectMgr->getNextObject()) + obj = gSelectMgr->getSelection()->getNextObject()) { scripted = obj->flagScripted(); modifiable = obj->permModify(); @@ -7411,7 +7345,7 @@ void handle_set_not_run_selection(void*) void handle_selected_texture_info(void*) { LLSelectNode* node = NULL; - for (node = gSelectMgr->getFirstNode(); node != NULL; node = gSelectMgr->getNextNode()) + for (node = gSelectMgr->getSelection()->getFirstNode(); node != NULL; node = gSelectMgr->getSelection()->getNextNode()) { if (!node->mValid) continue; @@ -7446,7 +7380,7 @@ void handle_selected_texture_info(void*) std::string image_id_string; if (gAgent.isGodlike()) { - image_id_string = image_id.getString() + " "; + image_id_string = image_id.asString() + " "; } msg = llformat("%s%dx%d %s on face ", image_id_string.c_str(), @@ -7510,16 +7444,16 @@ void handle_dump_attachments(void*) attachment = avatar->mAttachmentPoints.getNextData() ) { S32 key = avatar->mAttachmentPoints.getCurrentKeyWithoutIncrement(); - BOOL visible = (attachment->getObject(0) != NULL && - attachment->getObject(0)->mDrawable.notNull() && - !attachment->getObject(0)->mDrawable->isRenderType(0)); + BOOL visible = (attachment->getObject() != NULL && + attachment->getObject()->mDrawable.notNull() && + !attachment->getObject()->mDrawable->isRenderType(0)); LLVector3 pos; - if (visible) pos = attachment->getObject(0)->mDrawable->getPosition(); + if (visible) pos = attachment->getObject()->mDrawable->getPosition(); llinfos << "ATTACHMENT " << key << ": item_id=" << attachment->getItemID() - << (attachment->getObject(0) ? " present " : " absent ") + << (attachment->getObject() ? " present " : " absent ") << (visible ? "visible " : "invisible ") << " at " << pos - << " and " << (visible ? attachment->getObject(0)->getPosition() : LLVector3::zero) + << " and " << (visible ? attachment->getObject()->getPosition() : LLVector3::zero) << llendl; } } @@ -7598,7 +7532,7 @@ class LLSomethingSelected : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = !(gSelectMgr->isEmpty()); + bool new_value = !(gSelectMgr->getSelection()->isEmpty()); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -7608,7 +7542,8 @@ class LLSomethingSelectedNoHUD : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = !(gSelectMgr->isEmpty()) && !(gSelectMgr->getSelectType() == SELECT_TYPE_HUD); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + bool new_value = !(selection->isEmpty()) && !(selection->getSelectType() == SELECT_TYPE_HUD); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -7616,14 +7551,14 @@ class LLSomethingSelectedNoHUD : public view_listener_t BOOL enable_more_than_one_selected(void* ) { - return (gSelectMgr->getObjectCount() > 1); + return (gSelectMgr->getSelection()->getObjectCount() > 1); } class LLEditableSelected : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = (gSelectMgr->getFirstEditableObject() != NULL); + bool new_value = (gSelectMgr->getSelection()->getFirstEditableObject() != NULL); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -7642,10 +7577,11 @@ class LLToolsEnableTakeCopy : public view_listener_t if (gInProductionGrid || !gAgent.isGodlike()) # endif { - LLViewerObject* obj = gSelectMgr->getFirstRootObject(); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + LLViewerObject* obj = selection->getFirstRootObject(); if(obj) { - for( ; obj; obj = gSelectMgr->getNextRootObject()) + for( ; obj; obj = selection->getNextRootObject()) { if(!(obj->permCopy()) || obj->isAttachment()) { @@ -7665,11 +7601,15 @@ class LLToolsEnableTakeCopy : public view_listener_t BOOL enable_selection_you_own_all(void*) { LLViewerObject *obj; - for (obj = gSelectMgr->getFirstRootObject(); obj; obj = gSelectMgr->getNextRootObject()) + if (gSelectMgr) { - if (!obj->permYouOwner()) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (obj = selection->getFirstRootObject(); obj; obj = selection->getNextRootObject()) { - return FALSE; + if (!obj->permYouOwner()) + { + return FALSE; + } } } @@ -7678,15 +7618,18 @@ BOOL enable_selection_you_own_all(void*) BOOL enable_selection_you_own_one(void*) { - LLViewerObject *obj; - for (obj = gSelectMgr->getFirstRootObject(); obj; obj = gSelectMgr->getNextRootObject()) + if (gSelectMgr) { - if (obj->permYouOwner()) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + LLViewerObject *obj; + for (obj = selection->getFirstRootObject(); obj; obj = selection->getNextRootObject()) { - return TRUE; + if (obj->permYouOwner()) + { + return TRUE; + } } } - return FALSE; } @@ -7720,9 +7663,9 @@ BOOL enable_save_into_inventory(void*) { // find the last root LLSelectNode* last_node = NULL; - for(LLSelectNode* node = gSelectMgr->getFirstRootNode(); + for(LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); node != NULL; - node = gSelectMgr->getNextRootNode()) + node = gSelectMgr->getSelection()->getNextRootNode()) { last_node = node; } @@ -7766,7 +7709,7 @@ BOOL enable_save_into_task_inventory(void*) { if(gSelectMgr) { - LLSelectNode* node = gSelectMgr->getFirstRootNode(); + LLSelectNode* node = gSelectMgr->getSelection()->getFirstRootNode(); if(node && (node->mValid) && (!node->mFromTaskID.isNull())) { // *TODO: check to see if the fromtaskid object exists. @@ -7807,7 +7750,7 @@ class LLFileEnableUpload : public view_listener_t BOOL enable_export_selected(void *) { - if (gSelectMgr->isEmpty()) + if (gSelectMgr->getSelection()->isEmpty()) { return FALSE; } @@ -7838,7 +7781,7 @@ class LLToolsEnableToolNotPie : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = ( gToolMgr->getCurrentTool(MASK_NONE) != gToolPie ); + bool new_value = ( gToolMgr->getBaseTool() != gToolPie ); gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -7866,6 +7809,18 @@ class LLWorldEnableSetHomeLocation : public view_listener_t } }; +class LLWorldEnableTeleportHome : public view_listener_t +{ + bool handleEvent(LLPointer event, const LLSD& userdata) + { + LLViewerRegion* regionp = gAgent.getRegion(); + bool agent_on_prelude = (regionp && regionp->isPrelude()); + bool enable_teleport_home = gAgent.isGodlike() || !agent_on_prelude; + gMenuHolder->findControl(userdata["control"].asString())->setValue(enable_teleport_home); + return true; + } +}; + BOOL enable_region_owner(void*) { if(gAgent.getRegion() && gAgent.getRegion()->getOwner() == gAgent.getID()) @@ -7893,26 +7848,6 @@ BOOL enable_god_basic(void*) return gAgent.getGodLevel() > GOD_NOT; } -void toggle_vbo(void *) -{ - gPipeline.mUseVBO = !gPipeline.mUseVBO; - - if (!gPipeline.usingAGP()) - { - return; - } - - gPipeline.setUseAGP(FALSE); - gPipeline.setUseAGP(TRUE); - - gSavedSettings.setBOOL("RenderUseVBO", gPipeline.mUseVBO); -} - -BOOL check_vbo(void *) -{ - return gPipeline.mUseVBO; -} - #if 0 // 1.9.2 void toggle_vertex_shaders(void *) { @@ -7926,19 +7861,6 @@ BOOL check_vertex_shaders(void *) } #endif -void toggle_glow(void *) -{ - gRenderLightGlows = !gRenderLightGlows; - - gSavedSettings.setBOOL("RenderLightGlows", gRenderLightGlows); -} - -BOOL check_glow(void *) -{ - return gRenderLightGlows; -} - - void toggle_show_xui_names(void *) { BOOL showXUINames = gSavedSettings.getBOOL("ShowXUINames"); @@ -8213,10 +8135,10 @@ LLVOAvatar* find_avatar_from_object( const LLUUID& object_id ) void handle_disconnect_viewer(void *) { - char message[2048]; + char message[2048]; /* Flawfinder: ignore */ message[0] = '\0'; - sprintf(message, "Testing viewer disconnect"); + snprintf(message, sizeof(message), "Testing viewer disconnect"); /* Flawfinder: ignore */ do_disconnect(message); } @@ -8227,10 +8149,10 @@ class LLToolsUseSelectionForGrid : public view_listener_t bool handleEvent(LLPointer event, const LLSD& userdata) { gSelectMgr->clearGridObjects(); - - for (LLViewerObject* objectp = gSelectMgr->getFirstRootObject(); + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (LLViewerObject* objectp = selection->getFirstRootObject(); objectp; - objectp = gSelectMgr->getNextRootObject()) + objectp = selection->getNextRootObject()) { gSelectMgr->addGridObject(objectp); } @@ -8255,23 +8177,40 @@ void handle_test_load_url(void*) // LLViewerMenuHolderGL // +LLViewerMenuHolderGL::LLViewerMenuHolderGL() : LLMenuHolderGL() +{ +} + BOOL LLViewerMenuHolderGL::hideMenus() { BOOL handled = LLMenuHolderGL::hideMenus(); - if (handled) - { - gSelectMgr->deselectTransient(); - if (!gFloaterTools->getVisible() && !LLFloaterLand::floaterVisible()) - { - gParcelMgr->deselectLand(); - } - } + + // drop pie menu selection + mParcelSelection = NULL; + mObjectSelection = NULL; + gMenuBarView->clearHoverItem(); gMenuBarView->resetMenuTrigger(); return handled; } +void LLViewerMenuHolderGL::setParcelSelection(LLHandle selection) +{ + mParcelSelection = selection; +} + +void LLViewerMenuHolderGL::setObjectSelection(LLHandle selection) +{ + mObjectSelection = selection; +} + + +const LLRect LLViewerMenuHolderGL::getMenuRect() const +{ + return LLRect(0, mRect.getHeight() - MENU_BAR_HEIGHT, mRect.getWidth(), STATUS_BAR_HEIGHT); +} + void handle_save_to_xml(void*) { LLFloater* frontmost = gFloaterView->getFrontmost(); @@ -8431,7 +8370,7 @@ class LLViewToggleRenderType : public view_listener_t LLString type = userdata.asString(); if (type == "particles") { - LLPipeline::toggleRenderType((void *)(S32)LLPipeline::RENDER_TYPE_PARTICLES); + LLPipeline::toggleRenderType(LLPipeline::RENDER_TYPE_PARTICLES); } return true; } @@ -8452,12 +8391,11 @@ class LLViewCheckRenderType : public view_listener_t } }; -// TomY TODO: Get rid of these? class LLViewShowHUDAttachments : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - LLDrawPoolHUD::sShowHUDAttachments = !LLDrawPoolHUD::sShowHUDAttachments; + LLPipeline::sShowHUDAttachments = !LLPipeline::sShowHUDAttachments; return true; } }; @@ -8466,7 +8404,7 @@ class LLViewCheckHUDAttachments : public view_listener_t { bool handleEvent(LLPointer event, const LLSD& userdata) { - bool new_value = LLDrawPoolHUD::sShowHUDAttachments; + bool new_value = LLPipeline::sShowHUDAttachments; gMenuHolder->findControl(userdata["control"].asString())->setValue(new_value); return true; } @@ -8594,23 +8532,23 @@ class LLToolsSelectTool : public view_listener_t LLString tool_name = userdata.asString(); if (tool_name == "focus") { - gCurrentToolset->selectToolByIndex(1); + gToolMgr->getCurrentToolset()->selectToolByIndex(1); } else if (tool_name == "move") { - gCurrentToolset->selectToolByIndex(2); + gToolMgr->getCurrentToolset()->selectToolByIndex(2); } else if (tool_name == "edit") { - gCurrentToolset->selectToolByIndex(3); + gToolMgr->getCurrentToolset()->selectToolByIndex(3); } else if (tool_name == "create") { - gCurrentToolset->selectToolByIndex(4); + gToolMgr->getCurrentToolset()->selectToolByIndex(4); } else if (tool_name == "land") { - gCurrentToolset->selectToolByIndex(5); + gToolMgr->getCurrentToolset()->selectToolByIndex(5); } return true; } @@ -8624,6 +8562,7 @@ void initialize_menu_actions() (new LLFileUploadAnim())->registerListener(gMenuHolder, "File.UploadAnim"); (new LLFileUploadBulk())->registerListener(gMenuHolder, "File.UploadBulk"); (new LLFileCloseWindow())->registerListener(gMenuHolder, "File.CloseWindow"); + (new LLFileEnableCloseWindow())->registerListener(gMenuHolder, "File.EnableCloseWindow"); (new LLFileSaveTexture())->registerListener(gMenuHolder, "File.SaveTexture"); (new LLFileTakeSnapshot())->registerListener(gMenuHolder, "File.TakeSnapshot"); (new LLFileTakeSnapshotToDisk())->registerListener(gMenuHolder, "File.TakeSnapshotToDisk"); @@ -8698,6 +8637,7 @@ void initialize_menu_actions() (new LLWorldEnableCreateLandmark())->registerListener(gMenuHolder, "World.EnableCreateLandmark"); (new LLWorldEnableSetHomeLocation())->registerListener(gMenuHolder, "World.EnableSetHomeLocation"); + (new LLWorldEnableTeleportHome())->registerListener(gMenuHolder, "World.EnableTeleportHome"); (new LLWorldEnableBuyLand())->registerListener(gMenuHolder, "World.EnableBuyLand"); (new LLWorldCheckAlwaysRun())->registerListener(gMenuHolder, "World.CheckAlwaysRun"); diff --git a/linden/indra/newview/llviewermenu.h b/linden/indra/newview/llviewermenu.h index 9847e41..0c42426 100644 --- a/linden/indra/newview/llviewermenu.h +++ b/linden/indra/newview/llviewermenu.h @@ -37,6 +37,8 @@ class LLUICtrl; class LLView; +class LLParcelSelection; +class LLObjectSelection; struct LLResourceData { @@ -85,7 +87,6 @@ BOOL is_agent_mappable(const LLUUID& agent_id); void menu_toggle_control( void* user_data ); void check_toggle_control( LLUICtrl *, void* user_data ); -void handle_attach_to_avatar(void* user_data); void confirm_replace_attachment(S32 option, void* user_data); void handle_detach_from_avatar(void* user_data); void attach_label(LLString& label, void* user_data); @@ -145,10 +146,18 @@ class LLPermissions; class LLViewerMenuHolderGL : public LLMenuHolderGL { public: - LLViewerMenuHolderGL() : LLMenuHolderGL() {}; + LLViewerMenuHolderGL(); virtual BOOL hideMenus(); - //virtual BOOL handleKey(KEY key, MASK mask, BOOL called_from_parent); + + void setParcelSelection(LLHandle selection); + void setObjectSelection(LLHandle selection); + + virtual const LLRect getMenuRect() const; + +protected: + LLHandle mParcelSelection; + LLHandle mObjectSelection; }; extern const LLString SAVE_INTO_INVENTORY; diff --git a/linden/indra/newview/llviewermessage.cpp b/linden/indra/newview/llviewermessage.cpp index 1b91f9d..41d24fd 100644 --- a/linden/indra/newview/llviewermessage.cpp +++ b/linden/indra/newview/llviewermessage.cpp @@ -314,7 +314,7 @@ void export_complete() gExporterRequestID.setNull(); gExportDirectory = ""; - FILE *fXML = LLFile::fopen(gExportedFile.c_str(), "rb"); + FILE* fXML = LLFile::fopen(gExportedFile.c_str(), "rb"); /* Flawfinder: ignore */ fseek(fXML, 0, SEEK_END); U32 length = ftell(fXML); fseek(fXML, 0, SEEK_SET); @@ -330,8 +330,8 @@ void export_complete() if (pos_check && pos_uuid) { - char image_uuid_str[UUID_STR_SIZE]; - memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); + char image_uuid_str[UUID_STR_SIZE]; /* Flawfinder: ignore */ + memcpy(image_uuid_str, pos_uuid+2, UUID_STR_SIZE-1); /* Flawfinder: ignore */ image_uuid_str[UUID_STR_SIZE-1] = 0; LLUUID image_uuid(image_uuid_str); @@ -342,12 +342,15 @@ void export_complete() if (itor != gImageChecksums.end()) { llinfos << "Replacing with checksum: " << itor->second << llendl; - memcpy(&pos_check[10], itor->second.c_str(), 32); + if (itor->second.c_str() != NULL) + { + memcpy(&pos_check[10], itor->second.c_str(), 32); /* Flawfinder: ignore */ + } } } } - FILE *fXMLOut = LLFile::fopen(gExportedFile.c_str(), "wb"); + FILE* fXMLOut = LLFile::fopen(gExportedFile.c_str(), "wb"); /* Flawfinder: ignore */ fwrite(buffer, 1, length, fXMLOut); fclose(fXMLOut); @@ -400,7 +403,7 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) } else { - FILE *fIn = LLFile::fopen(filename.c_str(), "rb"); + FILE* fIn = LLFile::fopen(filename.c_str(), "rb"); /* Flawfinder: ignore */ if (fIn) { LLPointer ImageUtility = new LLImageJ2C; @@ -425,22 +428,22 @@ void exported_j2c_complete(const LLTSCode status, void *user_data) S32 data_size = TargaUtility->getDataSize(); char *file_path = new char[filename.size()+1]; - strcpy(file_path, filename.c_str()); + strcpy(file_path, filename.c_str()); /* Flawfinder: ignore */ char *end = strrchr(file_path, gDirUtilp->getDirDelimiter()[0]); end[0] = 0; LLString output_file = llformat("%s/image-%03d.tga", file_path, image_num);//filename; delete file_path; //S32 name_len = output_file.length(); //strcpy(&output_file[name_len-3], "tga"); - FILE *fOut = LLFile::fopen(output_file.c_str(), "wb"); - char md5_hash_string[33]; - strcpy(md5_hash_string, "00000000000000000000000000000000"); + FILE* fOut = LLFile::fopen(output_file.c_str(), "wb"); /* Flawfinder: ignore */ + char md5_hash_string[33]; /* Flawfinder: ignore */ + strcpy(md5_hash_string, "00000000000000000000000000000000"); /* Flawfinder: ignore */ if (fOut) { fwrite(data, 1, data_size, fOut); fseek(fOut, 0, SEEK_SET); fclose(fOut); - fOut = LLFile::fopen(output_file.c_str(), "rb"); + fOut = LLFile::fopen(output_file.c_str(), "rb"); /* Flawfinder: ignore */ LLMD5 my_md5_hash(fOut); my_md5_hash.hex_digest(md5_hash_string); } @@ -801,7 +804,7 @@ void inventory_offer_callback(S32 option, void* user_data) { if (info->mFromGroup) { - char group_name[MAX_STRING]; + char group_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getGroupName(info->mFromID, group_name)) { from_string = LLString("An object named ") + info->mFromName + " owned by the group '" + group_name + "'"; @@ -813,8 +816,8 @@ void inventory_offer_callback(S32 option, void* user_data) } else { - char first_name[MAX_STRING]; - char last_name[MAX_STRING]; + char first_name[MAX_STRING]; /* Flawfinder: ignore */ + char last_name[MAX_STRING]; /* Flawfinder: ignore */ if (gCacheName->getName(info->mFromID, first_name, last_name)) { from_string = LLString("An object named ") + info->mFromName + " owned by " + first_name + " " + last_name; @@ -938,9 +941,9 @@ void inventory_offer_callback(S32 option, void* user_data) } } - if (!info->mFromGroup) + if (!info->mFromGroup && !info->mFromObject) { - busy_message(msg,info->mFromID); + busy_message(msg,info->mFromID); } break; } @@ -1000,8 +1003,8 @@ void inventory_offer_handler(LLOfferInfo* info, BOOL from_task) // Name cache callbacks don't store userdata, so can't save // off the LLOfferInfo. Argh. JC BOOL name_found = FALSE; - char first_name[MAX_STRING]; - char last_name[MAX_STRING]; + char first_name[MAX_STRING]; /* Flawfinder: ignore */ + char last_name[MAX_STRING]; /* Flawfinder: ignore */ if (info->mFromGroup) { if (gCacheName->getGroupName(info->mFromID, first_name)) @@ -1133,12 +1136,12 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) U8 d = 0; LLUUID session_id; U32 t; - char name[DB_FULL_NAME_BUF_SIZE]; - char message[DB_IM_MSG_BUF_SIZE]; + char name[DB_FULL_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char message[DB_IM_MSG_BUF_SIZE]; /* Flawfinder: ignore */ U32 parent_estate_id = 0; LLUUID region_id; LLVector3 position; - char buffer[DB_IM_MSG_BUF_SIZE * 2]; + char buffer[DB_IM_MSG_BUF_SIZE * 2]; /* Flawfinder: ignore */ U8 binary_bucket[MTUBYTES]; S32 binary_bucket_size; LLChat chat; @@ -1171,19 +1174,19 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) chat.mFromID = from_id; chat.mFromName = name; - LLViewerObject *source = gObjectList.findObject(session_id); + LLViewerObject *source = gObjectList.findObject(session_id); //Session ID is probably the wrong thing. if (source) { is_owned_by_me = source->permYouOwner(); } - char separator_string[3]=": "; + char separator_string[3]=": "; /* Flawfinder: ignore */ int message_offset=0; //Handle IRC styled /me messages. if (!strncmp(message, "/me ", 4) || !strncmp(message, "/me'", 4)) { - strcpy(separator_string,""); + strcpy(separator_string,""); /* Flawfinder: ignore */ message_offset=3; } @@ -1237,7 +1240,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // now store incoming IM in chat history - sprintf(buffer, "%s%s%s", name, separator_string, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "%s%s%s", name, separator_string, (message+message_offset)); /* Flawfinder: ignore */ if(from_id == gAgentID) { @@ -1258,14 +1261,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) position); // pretend this is chat generated by self, so it does not show up on screen - sprintf(buffer, "IM: %s%s%s", name, separator_string, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "IM: %s%s%s", name, separator_string, (message+message_offset)); /* Flawfinder: ignore */ chat.mText = buffer; LLFloaterChat::addChat( chat, TRUE, TRUE ); } else if (from_id.isNull()) { // Messages from "Second Life" don't go to IM history - sprintf(buffer, "%s: %s", name, message); + snprintf(buffer, sizeof(buffer), "%s: %s", name, message); /* Flawfinder: ignore */ chat.mText = buffer; LLFloaterChat::addChat(chat, FALSE, FALSE); } @@ -1279,7 +1282,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Treat like a system message and put in chat history. // Claim to be from a local agent so it doesn't go into // console. - sprintf(buffer, "%s%s%s", name, separator_string, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "%s%s%s", name, separator_string, (message+message_offset)); /* Flawfinder: ignore */ chat.mText = buffer; BOOL local_agent = TRUE; LLFloaterChat::addChat(chat, FALSE, local_agent); @@ -1287,15 +1290,15 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) else { // standard message, not from system - char saved[MAX_STRING]; + char saved[MAX_STRING]; /* Flawfinder: ignore */ saved[0] = '\0'; if(offline == IM_OFFLINE) { - char time_buf[TIME_STR_LENGTH]; - sprintf(saved, "(Saved %s) ", + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(saved, MAX_STRING, "(Saved %s) ", /* Flawfinder: ignore */ formatted_time(timestamp, time_buf)); } - sprintf(buffer, "%s%s%s%s", name, separator_string, saved,(message+message_offset)); + snprintf(buffer, sizeof(buffer), "%s%s%s%s", name, separator_string, saved,(message+message_offset)); /* Flawfinder: ignore */ if(from_id == gAgentID) { from_id = LLUUID::null; @@ -1314,7 +1317,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) parent_estate_id, region_id, position); - sprintf(buffer, "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ chat.mText = buffer; BOOL local_agent = FALSE; @@ -1373,7 +1376,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) // Make sure the binary bucket is big enough to hold the header // and a null terminated item name. - if ( (binary_bucket_size < (sizeof(notice_bucket_header_t) + sizeof(U8))) + if ( (binary_bucket_size < (S32)((sizeof(notice_bucket_header_t) + sizeof(U8)))) || (binary_bucket[binary_bucket_size - 1] != '\0') ) { llwarns << "Malformed group notice binary bucket" << llendl; @@ -1527,8 +1530,8 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) info->mFromName = name; info->mDesc = message; info->mHost = msg->getSender(); - //if (!is_linden && ((is_busy && !is_owned_by_me) || is_muted)) - if (((is_busy && !is_owned_by_me) || is_muted)) + //if (((is_busy && !is_owned_by_me) || is_muted)) + if ( is_muted ) { // Same as closing window inventory_offer_callback(-1, info); @@ -1578,16 +1581,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } // standard message, not from system - char saved[MAX_STRING]; + char saved[MAX_STRING]; /* Flawfinder: ignore */ saved[0] = '\0'; if(offline == IM_OFFLINE) { - char time_buf[TIME_STR_LENGTH]; - sprintf(saved, + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(saved, /* Flawfinder: ignore */ + MAX_STRING, "(Saved %s) ", formatted_time(timestamp, time_buf)); } - sprintf(buffer, "%s%s%s%s", name, separator_string, saved, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "%s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ BOOL is_this_agent = FALSE; if(from_id == gAgentID) { @@ -1605,7 +1609,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) region_id, position); - sprintf(buffer, "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "IM: %s%s%s%s", name, separator_string, saved, (message+message_offset)); /* Flawfinder: ignore */ chat.mText = buffer; LLFloaterChat::addChat(chat, TRUE, is_this_agent); } @@ -1616,7 +1620,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) { return; } - sprintf(buffer, "%s%s%s", name, separator_string, (message+message_offset)); + snprintf(buffer, sizeof(buffer), "%s%s%s", name, separator_string, (message+message_offset)); /* Flawfinder: ignore */ // Note: lie to LLFloaterChat::addChat(), pretending that this is NOT an IM, because // IMs from objcts don't open IM sessions. chat.mText = buffer; @@ -1636,7 +1640,17 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) } break; case IM_BUSY_AUTO_RESPONSE: - gIMView->addMessage(session_id, from_id, name, message); + // fix for JIRA issue VWR-20 submitted 13-JAN-2007 - Paul Churchill + if (is_muted) + { + lldebugs << "Ignoring busy response from " << from_id << llendl; + return; + } + else + { + // original code resumes + gIMView->addMessage(session_id, from_id, name, message); + } break; case IM_LURE_USER: @@ -1688,7 +1702,14 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) case IM_GOTO_URL: { char* url = new char[binary_bucket_size]; - strcpy(url, (char*)binary_bucket); + if (url == NULL) + { + llerrs << "Memory Allocation failed" << llendl; + return; + } + + strncpy(url, (char*)binary_bucket, binary_bucket_size-1); /* Flawfinder: ignore */ + url[binary_bucket_size-1] = '\0'; args["[MESSAGE]"] = message; args["[URL]"] = url; LLNotifyBox::showXml("GotoURL", args, @@ -1730,7 +1751,7 @@ void process_improved_im(LLMessageSystem *msg, void **user_data) LLAvatarTracker::formFriendship(from_id); std::vector strings; - strings.push_back( from_id.getString() ); + strings.push_back(from_id.asString()); send_generic_message("requestonlinenotification", strings); args["[NAME]"] = name; @@ -1931,8 +1952,8 @@ void process_decline_callingcard(LLMessageSystem* msg, void**) void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) { LLChat chat; - char mesg[DB_CHAT_MSG_BUF_SIZE]; - char from_name[DB_FULL_NAME_BUF_SIZE]; + char mesg[DB_CHAT_MSG_BUF_SIZE]; /* Flawfinder: ignore */ + char from_name[DB_FULL_NAME_BUF_SIZE]; /* Flawfinder: ignore */ U8 source_temp; U8 type_temp; U8 audible_temp; @@ -1976,6 +1997,7 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) is_linden = gMuteListp->isLinden(from_name); } + BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); chatter = gObjectList.findObject(from_id); if (chatter) { @@ -1995,7 +2017,8 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) } // only pay attention to other people chatting - if ((is_linden || (!is_muted && !is_busy)) + if (is_audible + && (is_linden || (!is_muted && !is_busy)) && chatter != gAgent.getAvatarObject()) { gAgent.heardChat(chat); @@ -2008,7 +2031,6 @@ void process_chat_from_simulator(LLMessageSystem *msg, void **user_data) is_owned_by_me = chatter->permYouOwner(); } - BOOL is_audible = (CHAT_AUDIBLE_FULLY == chat.mAudible); if (is_audible) { BOOL visible_in_chat_bubble = FALSE; @@ -2283,7 +2305,7 @@ void process_teleport_progress(LLMessageSystem* msg, void**) { gViewerWindow->setProgressCancelButtonVisible(TRUE, "Cancel"); } - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ msg->getString("Info", "Message", MAX_STRING, buffer); lldebugs << "teleport progress: " << buffer << llendl; gAgent.setTeleportMessage(buffer); @@ -2373,7 +2395,7 @@ void process_teleport_finish(LLMessageSystem* msg, void**) msg->getU32Fast(_PREHASH_Info, _PREHASH_TeleportFlags, teleport_flags); - char seedCap[STD_STRING_BUF_SIZE]; + char seedCap[STD_STRING_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_Info, _PREHASH_SeedCapability, STD_STRING_BUF_SIZE, seedCap); @@ -2657,7 +2679,7 @@ void process_crossed_region(LLMessageSystem* msg, void**) U64 region_handle; msg->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); - char seedCap[STD_STRING_BUF_SIZE]; + char seedCap[STD_STRING_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_RegionData, _PREHASH_SeedCapability, STD_STRING_BUF_SIZE, seedCap); send_complete_agent_movement(sim_host); @@ -2891,7 +2913,8 @@ void send_agent_update(BOOL force_send, BOOL send_reliable) extern U32 gObjectBits; void process_object_update(LLMessageSystem *mesgsys, void **user_data) -{ +{ + LLMemType mt(LLMemType::MTYPE_OBJECT); // Update the data counters if (mesgsys->getReceiveCompressedSize()) { @@ -2909,6 +2932,7 @@ void process_object_update(LLMessageSystem *mesgsys, void **user_data) void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data) { + LLMemType mt(LLMemType::MTYPE_OBJECT); // Update the data counters if (mesgsys->getReceiveCompressedSize()) { @@ -2926,6 +2950,7 @@ void process_compressed_object_update(LLMessageSystem *mesgsys, void **user_data void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) { + LLMemType mt(LLMemType::MTYPE_OBJECT); // Update the data counters if (mesgsys->getReceiveCompressedSize()) { @@ -2944,6 +2969,7 @@ void process_cached_object_update(LLMessageSystem *mesgsys, void **user_data) void process_terse_object_update_improved(LLMessageSystem *mesgsys, void **user_data) { + LLMemType mt(LLMemType::MTYPE_OBJECT); if (mesgsys->getReceiveCompressedSize()) { gObjectBits += mesgsys->getReceiveCompressedSize() * 8; @@ -2988,7 +3014,7 @@ void process_kill_object(LLMessageSystem *mesgsys, void **user_data) //llinfos << "Kill message for local " << local_id << llendl; } - gSelectMgr->selectionRemoveObject(id); + gSelectMgr->removeObjectFromSelections(id); // ...don't kill the avatar if (!(id == gAgentID)) @@ -3470,12 +3496,15 @@ void process_camera_constraint(LLMessageSystem *mesgsys, void **user_data) void near_sit_object(BOOL success, void *data) { - // Send message to sit on object - gMessageSystem->newMessageFast(_PREHASH_AgentSit); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gAgent.sendReliableMessage(); + if (success) + { + // Send message to sit on object + gMessageSystem->newMessageFast(_PREHASH_AgentSit); + gMessageSystem->nextBlockFast(_PREHASH_AgentData); + gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); + gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); + gAgent.sendReliableMessage(); + } } void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) @@ -3516,9 +3545,6 @@ void process_avatar_sit_response(LLMessageSystem *mesgsys, void **user_data) { gAgent.startAutoPilotGlobal(gAgent.getPosGlobalFromAgent(sit_spot), "Sit", &sitRotation, near_sit_object, NULL, 0.5f); } - - // deselect transient selections (pie menu) when sitting - gSelectMgr->deselectTransient(); } else { @@ -3658,7 +3684,7 @@ void process_set_follow_cam_properties(LLMessageSystem *mesgsys, void **user_dat // Culled from newsim lltask.cpp void process_name_value(LLMessageSystem *mesgsys, void **user_data) { - char temp_str[NAME_VALUE_BUF_SIZE]; + char temp_str[NAME_VALUE_BUF_SIZE]; /* Flawfinder: ignore */ LLUUID id; S32 i, num_blocks; @@ -3684,7 +3710,7 @@ void process_name_value(LLMessageSystem *mesgsys, void **user_data) void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data) { - char temp_str[NAME_VALUE_BUF_SIZE]; + char temp_str[NAME_VALUE_BUF_SIZE]; /* Flawfinder: ignore */ LLUUID id; S32 i, num_blocks; @@ -3710,7 +3736,7 @@ void process_remove_name_value(LLMessageSystem *mesgsys, void **user_data) void process_kick_user(LLMessageSystem *msg, void** /*user_data*/) { - char message[2048]; + char message[2048]; /* Flawfinder: ignore */ message[0] = '\0'; msg->getStringFast(_PREHASH_UserInfo, _PREHASH_Reason, 2048, message); @@ -3778,7 +3804,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) S32 balance = 0; S32 credit = 0; S32 committed = 0; - char desc[STD_STRING_BUF_SIZE] = ""; + char desc[STD_STRING_BUF_SIZE] = ""; /* Flawfinder: ignore */ msg->getS32("MoneyData", "MoneyBalance", balance); msg->getS32("MoneyData", "SquareMetersCredit", credit); @@ -3839,7 +3865,7 @@ void process_money_balance_reply( LLMessageSystem* msg, void** ) void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, MAX_STRING, buffer); BOOL modal = FALSE; msgsystem->getBOOL("AlertData", "Modal", modal); @@ -3848,7 +3874,7 @@ void process_agent_alert_message(LLMessageSystem* msgsystem, void** user_data) void process_alert_message(LLMessageSystem *msgsystem, void **user_data) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ msgsystem->getStringFast(_PREHASH_AlertData, _PREHASH_Message, MAX_STRING, buffer); BOOL modal = FALSE; process_alert_core(buffer, modal); @@ -3868,10 +3894,11 @@ void process_alert_core(const char* buffer, BOOL modal) else if( !strcmp( buffer, "Home position set." ) ) { // save the home location image to disk - char temp_str[LL_MAX_PATH]; - strcpy(temp_str, gDirUtilp->getLindenUserDir().c_str()); - strcat(temp_str, "/"); - strcat(temp_str,SCREEN_HOME_FILENAME); + char temp_str[LL_MAX_PATH]; /* Flawfinder: ignore */ + strncpy(temp_str, gDirUtilp->getLindenUserDir().c_str(), LL_MAX_PATH -1); /* Flawfinder: ignore */ + temp_str[LL_MAX_PATH -1] = '\0'; + strcat(temp_str, "/"); /* Flawfinder: ignore */ + strcat(temp_str,SCREEN_HOME_FILENAME); /* Flawfinder: ignore */ gViewerWindow->saveSnapshot(temp_str, gViewerWindow->getWindowWidth(), gViewerWindow->getWindowHeight(), FALSE, FALSE); } @@ -3949,8 +3976,10 @@ void mean_name_callback(const LLUUID &id, const char *first, const char *last, B { if (mcd->mPerp == id) { - strcpy(mcd->mFirstName, first); - strcpy(mcd->mLastName, last); + strncpy(mcd->mFirstName, first, DB_FIRST_NAME_BUF_SIZE -1); /* Flawfinder: ignore */ + mcd->mFirstName[DB_FIRST_NAME_BUF_SIZE -1] = '\0'; + strncpy(mcd->mLastName, last, DB_LAST_NAME_BUF_SIZE -1); /* Flawfinder: ignore */ + mcd->mLastName[DB_LAST_NAME_BUF_SIZE -1] = '\0'; } } } @@ -4101,8 +4130,8 @@ void process_script_question(LLMessageSystem *msg, void **user_data) LLUUID taskid; LLUUID itemid; S32 questions; - char object_name[255]; - char owner_name[DB_FULL_NAME_BUF_SIZE]; + char object_name[255]; /* Flawfinder: ignore */ + char owner_name[DB_FULL_NAME_BUF_SIZE]; /* Flawfinder: ignore */ msg->getUUIDFast(_PREHASH_Data, _PREHASH_TaskID, taskid ); msg->getUUIDFast(_PREHASH_Data, _PREHASH_ItemID, itemid ); @@ -4262,7 +4291,7 @@ char* formatted_time(const time_t& the_time, char* buffer) void process_teleport_failed(LLMessageSystem *msg, void**) { - char reason[STD_STRING_BUF_SIZE]; + char reason[STD_STRING_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_Info, _PREHASH_Reason, STD_STRING_BUF_SIZE, reason); LLStringBase::format_map_t args; @@ -4536,10 +4565,10 @@ void process_user_info_reply(LLMessageSystem* msg, void**) BOOL im_via_email; msg->getBOOLFast(_PREHASH_UserData, _PREHASH_IMViaEMail, im_via_email); - char email[DB_USER_EMAIL_ADDR_BUF_SIZE]; + char email[DB_USER_EMAIL_ADDR_BUF_SIZE]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_UserData, _PREHASH_EMail, DB_USER_EMAIL_ADDR_BUF_SIZE, email); - char dir_visibility[MAX_STRING]; + char dir_visibility[MAX_STRING]; /* Flawfinder: ignore */ msg->getString( "UserData", "DirectoryVisibility", MAX_STRING, dir_visibility); @@ -4596,11 +4625,11 @@ void process_script_dialog(LLMessageSystem* msg, void**) ScriptDialogInfo* info = new ScriptDialogInfo; const S32 messageLength = SCRIPT_DIALOG_MAX_MESSAGE_SIZE + sizeof(SCRIPT_DIALOG_HEADER); - char message[messageLength]; // Account for size of "Script Dialog:\n" + char message[messageLength]; /* Flawfinder: ignore */ // Account for size of "Script Dialog:\n" - char first_name[DB_FIRST_NAME_BUF_SIZE]; - char last_name[DB_GROUP_NAME_BUF_SIZE]; - char title[DB_INV_ITEM_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char last_name[DB_GROUP_NAME_BUF_SIZE]; /* Flawfinder: ignore */ + char title[DB_INV_ITEM_NAME_BUF_SIZE]; /* Flawfinder: ignore */ info->mSender = msg->getSender(); msg->getUUID("Data", "ObjectID", info->mObjectID); @@ -4622,7 +4651,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) for (i = 0; i < button_count; i++) { - char tdesc[SCRIPT_DIALOG_BUTTON_STR_SIZE+1]; + char tdesc[SCRIPT_DIALOG_BUTTON_STR_SIZE+1]; /* Flawfinder: ignore */ msg->getString("Buttons", "ButtonLabel", SCRIPT_DIALOG_BUTTON_STR_SIZE + 1, tdesc, i); info->mButtons.push_back(LLString(tdesc)); } @@ -4630,7 +4659,7 @@ void process_script_dialog(LLMessageSystem* msg, void**) LLStringBase::format_map_t args; args["[TITLE]"] = title; args["[MESSAGE]"] = message; - if (strlen(first_name) > 0) + if (strlen(first_name) > 0) /* Flawfinder: ignore */ { args["[FIRST]"] = first_name; args["[LAST]"] = last_name; @@ -4656,9 +4685,9 @@ struct LoadUrlInfo LLUUID mObjectID; LLUUID mOwnerID; BOOL mOwnerIsGroup; - char mObjectName[256]; - char mMessage[256]; - char mUrl[256]; + char mObjectName[256]; /* Flawfinder: ignore */ + char mMessage[256]; /* Flawfinder: ignore */ + char mUrl[256]; /* Flawfinder: ignore */ }; std::vector gLoadUrlList; @@ -4770,8 +4799,8 @@ void process_initiate_download(LLMessageSystem* msg, void**) return; } - char sim_filename[MAX_PATH]; - char viewer_filename[MAX_PATH]; + char sim_filename[MAX_PATH]; /* Flawfinder: ignore */ + char viewer_filename[MAX_PATH]; /* Flawfinder: ignore */ msg->getString("FileData", "SimFilename", MAX_PATH, sim_filename); msg->getString("FileData", "ViewerFilename", MAX_PATH, viewer_filename); @@ -4787,8 +4816,8 @@ void process_initiate_download(LLMessageSystem* msg, void**) void process_script_teleport_request(LLMessageSystem* msg, void**) { - char object_name[256]; - char sim_name[256]; + char object_name[256]; /* Flawfinder: ignore */ + char sim_name[256]; /* Flawfinder: ignore */ LLVector3 pos; LLVector3 look_at; @@ -4804,7 +4833,7 @@ void process_script_teleport_request(LLMessageSystem* msg, void**) void process_covenant_reply(LLMessageSystem* msg, void**) { LLUUID covenant_id, estate_owner_id; - char estate_name[MAX_STRING]; + char estate_name[MAX_STRING]; /* Flawfinder: ignore */ U32 covenant_timestamp; msg->getUUID("Data", "CovenantID", covenant_id); msg->getU32("Data", "CovenantTimestamp", covenant_timestamp); @@ -4816,10 +4845,10 @@ void process_covenant_reply(LLMessageSystem* msg, void**) LLFloaterBuyLand::updateEstateName(estate_name); // standard message, not from system - char last_modified[MAX_STRING]; + char last_modified[MAX_STRING]; /* Flawfinder: ignore */ last_modified[0] = '\0'; - char time_buf[TIME_STR_LENGTH]; - sprintf(last_modified, "Last Modified %s", + char time_buf[TIME_STR_LENGTH]; /* Flawfinder: ignore */ + snprintf(last_modified, MAX_STRING, "Last Modified %s", /* Flawfinder: ignore */ formatted_time((time_t)covenant_timestamp, time_buf)); LLPanelEstateCovenant::updateLastModified(last_modified); @@ -4898,7 +4927,13 @@ void onCovenantLoadComplete(LLVFS *vfs, S32 file_length = file.getSize(); char* buffer = new char[file_length+1]; - file.read((U8*)buffer, file_length); + if (buffer == NULL) + { + llerrs << "Memory Allocation failed" << llendl; + return; + } + + file.read((U8*)buffer, file_length); /* Flawfinder: ignore */ // put a EOS at the end buffer[file_length] = 0; @@ -5009,7 +5044,7 @@ void process_feature_disabled_message(LLMessageSystem* msg, void**) // Handle Blacklisted feature simulator response... LLUUID agentID; LLUUID transactionID; - char messageText[MAX_STRING]; + char messageText[MAX_STRING]; /* Flawfinder: ignore */ msg->getStringFast(_PREHASH_FailureInfo,_PREHASH_ErrorMessage,MAX_STRING,&messageText[0],0); msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_AgentID,agentID); msg->getUUIDFast(_PREHASH_FailureInfo,_PREHASH_TransactionID,transactionID); diff --git a/linden/indra/newview/llviewernetwork.cpp b/linden/indra/newview/llviewernetwork.cpp index 84c5833..d870871 100644 --- a/linden/indra/newview/llviewernetwork.cpp +++ b/linden/indra/newview/llviewernetwork.cpp @@ -65,6 +65,10 @@ LLUserServerData gUserServerDomainName[USERSERVER_COUNT] = "userserver.ganga.lindenlab.com", "https://login.ganga.lindenlab.com/cgi-bin/login.cgi", "http://ganga-secondlife.webdev.lindenlab.com/helpers/" }, + { "Vaak", + "userserver.vaak.lindenlab.com", + "https://login.vaak.lindenlab.com/cgi-bin/login.cgi", + "http://vaak-secondlife.webdev.lindenlab.com/helpers/" }, { "Uma", "userserver.uma.lindenlab.com", "https://login.uma.lindenlab.com/cgi-bin/login.cgi", @@ -82,7 +86,7 @@ LLUserServerData gUserServerDomainName[USERSERVER_COUNT] = // Use this to figure out which domain name and login URI to use. EUserServerDomain gUserServerChoice = USERSERVER_NONE; -char gUserServerName[MAX_STRING]; +char gUserServerName[MAX_STRING]; /* Flawfinder: ignore */ LLHost gUserServer; @@ -90,4 +94,4 @@ F32 gPacketDropPercentage = 0.f; F32 gInBandwidth = 0.f; F32 gOutBandwidth = 0.f; -unsigned char gMACAddress[MAC_ADDRESS_BYTES]; +unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */ diff --git a/linden/indra/newview/llviewernetwork.h b/linden/indra/newview/llviewernetwork.h index ae5292c..4c90c5b 100644 --- a/linden/indra/newview/llviewernetwork.h +++ b/linden/indra/newview/llviewernetwork.h @@ -42,6 +42,7 @@ enum EUserServerDomain USERSERVER_SHAKTI, USERSERVER_SOMA, USERSERVER_GANGA, + USERSERVER_VAAK, USERSERVER_UMA, USERSERVER_LOCAL, USERSERVER_OTHER, // IP address set via -user or other command line option @@ -64,9 +65,9 @@ extern F32 gInBandwidth; extern F32 gOutBandwidth; extern EUserServerDomain gUserServerChoice; extern LLUserServerData gUserServerDomainName[]; -extern char gUserServerName[MAX_STRING]; +extern char gUserServerName[MAX_STRING]; /* Flawfinder: ignore */ const S32 MAC_ADDRESS_BYTES = 6; -extern unsigned char gMACAddress[MAC_ADDRESS_BYTES]; +extern unsigned char gMACAddress[MAC_ADDRESS_BYTES]; /* Flawfinder: ignore */ #endif diff --git a/linden/indra/newview/llviewerobject.cpp b/linden/indra/newview/llviewerobject.cpp index 40930e6..a1a971f 100644 --- a/linden/indra/newview/llviewerobject.cpp +++ b/linden/indra/newview/llviewerobject.cpp @@ -80,14 +80,12 @@ #include "llvoground.h" #include "llvolume.h" #include "llvolumemessage.h" -#include "llvopart.h" #include "llvopartgroup.h" #include "llvosky.h" #include "llvostars.h" #include "llvosurfacepatch.h" #include "llvotextbubble.h" #include "llvotree.h" -#include "llvotreenew.h" #include "llvovolume.h" #include "llvowater.h" #include "llworld.h" @@ -125,14 +123,15 @@ LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pco case LL_PCODE_LEGACY_GRASS: res = new LLVOGrass(id, pcode, regionp); break; case LL_PCODE_LEGACY_PART_SYS: - res = new LLVOPart(id, pcode, regionp); break; +// llwarns << "Creating old part sys!" << llendl; +// res = new LLVOPart(id, pcode, regionp); break; + res = NULL; break; case LL_PCODE_LEGACY_TREE: res = new LLVOTree(id, pcode, regionp); break; case LL_PCODE_TREE_NEW: - llwarns << "Creating new tree!" << llendl; -// res = new LLVOTree(id, pcode, regionp); break; -// res = new LLVOTreeNew(id, pcode, regionp); break; - res = NULL; break; +// llwarns << "Creating new tree!" << llendl; +// res = new LLVOTree(id, pcode, regionp); break; + res = NULL; break; case LL_PCODE_LEGACY_TEXT_BUBBLE: res = new LLVOTextBubble(id, pcode, regionp); break; case LL_VO_CLOUDS: @@ -173,10 +172,11 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mText(), mLastInterpUpdateSecs(0.f), mLastMessageUpdateSecs(0.f), + mLatestRecvPacketID(0), mData(NULL), mAudioSourcep(NULL), mAppAngle(0.f), - mPixelArea(0.f), + mPixelArea(1024.f), mInventory(NULL), mInventorySerialNum(0), mRegionp( regionp ), @@ -188,7 +188,6 @@ LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRe mOnActiveList(FALSE), mOnMap(FALSE), mStatic(FALSE), - mFaceIndexOffset(0), mNumFaces(0), mLastUpdateFrame(0), mTimeDilation(1.f), @@ -368,10 +367,12 @@ void LLViewerObject::dump() const llinfos << "Velocity: " << getVelocity() << llendl; if (mDrawable.notNull() && mDrawable->getNumFaces()) { - LLDrawPool *poolp = mDrawable->getFace(0)->getPool(); - llinfos << "Pool: " << poolp << llendl; - llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl; - llinfos << "Pool vertex count: " << poolp->getVertexCount() << llendl; + LLFacePool *poolp = mDrawable->getFace(0)->getPool(); + if (poolp) + { + llinfos << "Pool: " << poolp << llendl; + llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl; + } } //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl; //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl; @@ -423,7 +424,6 @@ void LLViewerObject::initVOClasses() } llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl; LLVOGrass::initClass(); - LLVOPart::initClass(); LLVOWater::initClass(); LLVOSky::initClass(); LLVOVolume::initClass(); @@ -615,11 +615,24 @@ BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) return FALSE; } + LLDrawable* old_parent = mDrawable->mParent; + mDrawable->mParent = parentp; BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - gPipeline.markMoved(mDrawable, FALSE); + if (old_parent || (parentp && parentp->isActive())) + { + gPipeline.markMoved(mDrawable, FALSE); + } + else + { + mDrawable->updateXform(TRUE); + if (!mDrawable->getSpatialGroup()) + { + mDrawable->movePartition(); + } + } return ret; } @@ -674,7 +687,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, LLVector3 new_acc; LLVector3 new_angv; LLQuaternion new_rot; - LLVector3 new_scale; + LLVector3 new_scale = getScale(); U32 parent_id = 0; U8 material = 0; @@ -900,13 +913,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // ...new objects that should come in selected need to be added to the selected list mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - // Set the change flags for scale - if (new_scale != getScale()) - { - setChanged(SCALED | SILHOUETTE); - setScale(new_scale); // Must follow setting permYouOwner() - } - // Set all name value pairs S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue); if (nv_size > 0) @@ -952,7 +958,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText->setOnHUDAttachment(isHUDAttachment()); } - char temp_string[256]; // not MAX_STRING, must hold 255 chars + \0 + char temp_string[256]; /* Flawfinder: ignore */ // not MAX_STRING, must hold 255 chars + \0 mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, 256, temp_string, block_num ); LLColor4U coloru; @@ -975,7 +981,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, mText = NULL; } - char media_url[MAX_STRING+1]; + char media_url[MAX_STRING+1]; /* Flawfinder: ignore */ mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, MAX_STRING+1, media_url, block_num); //if (media_url[0]) //{ @@ -1419,8 +1425,14 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Unpack particle system data // if (value & 0x8) + { unpackParticleSource(*dp, owner_id); - + } + else + { + deleteParticleSource(); + } + // Mark all extra parameters not used std::map::iterator iter; for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) @@ -1484,14 +1496,6 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // ...new objects that should come in selected need to be added to the selected list mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - - // Set the change flags for scale - if (new_scale != getScale()) - { - setChanged(SCALED | SILHOUETTE); - setScale(new_scale); // Must follow setting permYouOwner() - } - } break; @@ -1763,6 +1767,23 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // // + U32 packet_id = mesgsys->getCurrentRecvPacketID(); + if (packet_id < mLatestRecvPacketID && + mLatestRecvPacketID - packet_id < 65536) + { + //skip application of this message, it's old + return retval; + } + + mLatestRecvPacketID = packet_id; + + // Set the change flags for scale + if (new_scale != getScale()) + { + setChanged(SCALED | SILHOUETTE); + setScale(new_scale); // Must follow setting permYouOwner() + } + // first, let's see if the new position is actually a change //static S32 counter = 0; @@ -1790,14 +1811,10 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, if (new_rot != mLastRot) { - // if (getAngularVelocity().isExactlyZero() || - // new_angv != getAngularVelocity()) - { - mLastRot = new_rot; - setChanged(ROTATED | SILHOUETTE); - setRotation(new_rot); - resetRot(); - } + mLastRot = new_rot; + setChanged(ROTATED | SILHOUETTE); + setRotation(new_rot); + resetRot(); } @@ -2048,7 +2065,7 @@ BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size) { return FALSE; } - memcpy(mData, datap, data_size); + memcpy(mData, datap, data_size); /* Flawfinder: ignore */ } return TRUE; } @@ -2300,7 +2317,7 @@ void LLViewerObject::requestInventory() struct LLFilenameAndTask { LLUUID mTaskID; - char mFilename[MAX_STRING]; // Just the filename, not the path + char mFilename[MAX_STRING]; /* Flawfinder: ignore */ // Just the filename, not the path #ifdef _DEBUG static S32 sCount; LLFilenameAndTask() @@ -2331,41 +2348,45 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) LLUUID task_id; msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id); LLViewerObject* object = gObjectList.findObject(task_id); - if(object) + if(!object) + { + llwarns << "LLViewerObject::processTaskInv object " + << task_id << " does not exist." << llendl; + return; + } + + msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); + LLFilenameAndTask* ft = new LLFilenameAndTask; + ft->mTaskID = task_id; + msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, MAX_STRING, ft->mFilename); + if(!ft->mFilename[0]) { - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); - LLFilenameAndTask* ft = new LLFilenameAndTask; - ft->mTaskID = task_id; - msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, MAX_STRING, ft->mFilename); - if(!ft->mFilename[0]) + lldebugs << "Task has no inventory" << llendl; + // mock up some inventory to make a drop target. + if(object->mInventory) { - lldebugs << "Task has no inventory" << llendl; - // mock up some inventory to make a drop target. - if(object->mInventory) - { - object->mInventory->clear(); // will deref and delete it - } - else - { - object->mInventory = new InventoryObjectList(); - } - LLPointer obj; - obj = new LLInventoryObject(object->mID, LLUUID::null, - LLAssetType::AT_CATEGORY, - "Contents"); - object->mInventory->push_front(obj); - object->doInventoryCallback(); - delete ft; - return; + object->mInventory->clear(); // will deref and delete it } - gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename).c_str(), - ft->mFilename, LL_PATH_CACHE, - object->mRegionp->getHost(), - TRUE, - &LLViewerObject::processTaskInvFile, - (void**)ft, - LLXferManager::HIGH_PRIORITY); + else + { + object->mInventory = new InventoryObjectList(); + } + LLPointer obj; + obj = new LLInventoryObject(object->mID, LLUUID::null, + LLAssetType::AT_CATEGORY, + "Contents"); + object->mInventory->push_front(obj); + object->doInventoryCallback(); + delete ft; + return; } + gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename).c_str(), + ft->mFilename, LL_PATH_CACHE, + object->mRegionp->getHost(), + TRUE, + &LLViewerObject::processTaskInvFile, + (void**)ft, + LLXferManager::HIGH_PRIORITY); } void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code) @@ -2395,9 +2416,9 @@ void LLViewerObject::loadTaskInvFile(const char* filename) llifstream ifs(filename_and_local_path.c_str()); if(ifs.good()) { - char buffer[MAX_STRING]; + char buffer[MAX_STRING]; /* Flawfinder: ignore */ // *NOTE: This buffer size is hard coded into scanf() below. - char keyword[MAX_STRING]; + char keyword[MAX_STRING]; /* Flawfinder: ignore */ if(mInventory) { mInventory->clear(); // will deref and delete it @@ -2409,7 +2430,7 @@ void LLViewerObject::loadTaskInvFile(const char* filename) while(ifs.good()) { ifs.getline(buffer, MAX_STRING); - sscanf(buffer, " %254s", keyword); + sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */ if(0 == strcmp("inv_item", keyword)) { LLPointer inv = new LLViewerInventoryItem; @@ -2590,6 +2611,18 @@ LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& ass return rv; } +void LLViewerObject::updateViewerInventoryAsset( + const LLViewerInventoryItem* item, + const LLUUID& new_asset) +{ + LLPointer task_item = + new LLViewerInventoryItem(item); + task_item->setAssetUUID(new_asset); + + // do the internal logic + doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false); +} + void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) { if (getVolume()) @@ -2644,6 +2677,11 @@ BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) return TRUE; } +void LLViewerObject::updateFaceSize(S32 idx) +{ + +} + LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline) { return NULL; @@ -2684,13 +2722,23 @@ void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) void LLViewerObject::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) { LLVector3 center = getRenderPosition(); - F32 sz = llmin(mDrawable->getRadius(), 256.f); - LLVector3 size = LLVector3(sz,sz,sz); + LLVector3 size = getScale(); newMin.setVec(center-size); newMax.setVec(center+size); mDrawable->setPositionGroup((newMin + newMax) * 0.5f); } +F32 LLViewerObject::getBinRadius() +{ + if (mDrawable.notNull()) + { + const LLVector3* ext = mDrawable->getSpatialExtents(); + return (ext[1]-ext[0]).magVec(); + } + + return getScale().magVec(); +} + F32 LLViewerObject::getMaxScale() const { return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]); @@ -3593,11 +3641,6 @@ S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen) { retval = LLPrimitive::setTETexGen(te, texgen); setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - } } return retval; } @@ -3614,11 +3657,6 @@ S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny) { retval = LLPrimitive::setTEShiny(te, shiny); setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - } } return retval; } @@ -3763,7 +3801,7 @@ LLViewerImage *LLViewerObject::getTEImage(const U8 face) const } } - llerrs << "Requested invalid face!" << llendl; + llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; return NULL; } @@ -3857,6 +3895,11 @@ void LLViewerObject::setCanSelect(BOOL canSelect) void LLViewerObject::setDebugText(const std::string &utf8text) { + if (utf8text.empty() && !mText) + { + return; + } + if (!mText) { mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); @@ -4045,6 +4088,15 @@ void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_ } } +void LLViewerObject::deleteParticleSource() +{ + if (mPartSourcep.notNull()) + { + mPartSourcep->setDead(); + mPartSourcep = NULL; + } +} + // virtual void LLViewerObject::updateDrawable(BOOL force_damped) { @@ -4577,6 +4629,7 @@ void LLViewerObject::markForUpdate(BOOL priority) void LLViewerObject::setRegion(LLViewerRegion *regionp) { llassert(regionp); + mLatestRecvPacketID = 0; mRegionp = regionp; setChanged(MOVED | SILHOUETTE); updateDrawable(FALSE); @@ -4665,3 +4718,30 @@ void LLViewerObject::resetRot() { mRotTime = 0.0f; } + +U32 LLViewerObject::getPartitionType() const +{ + return LLPipeline::PARTITION_NONE; +} + +BOOL LLAlphaObject::isParticle() +{ + return FALSE; +} + +F32 LLAlphaObject::getPartSize(S32 idx) +{ + return 0.f; +} + +// virtual +void LLStaticViewerObject::updateDrawable(BOOL force_damped) +{ + // Force an immediate rebuild on any update + if (mDrawable.notNull()) + { + mDrawable->updateXform(TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + clearChanged(SHIFTED); +} diff --git a/linden/indra/newview/llviewerobject.h b/linden/indra/newview/llviewerobject.h index a439a01..7176d24 100644 --- a/linden/indra/newview/llviewerobject.h +++ b/linden/indra/newview/llviewerobject.h @@ -37,6 +37,7 @@ #include "llhudicon.h" #include "llinventory.h" #include "llmemory.h" +#include "llmemtype.h" #include "llprimitive.h" #include "lluuid.h" #include "llvoinventorylistener.h" @@ -44,6 +45,7 @@ #include "llquaternion.h" #include "v3dmath.h" #include "v3math.h" +#include "llvertexbuffer.h" class LLAgent; // TODO: Get rid of this. class LLAudioSource; @@ -187,6 +189,7 @@ public: virtual LLDrawable* createDrawable(LLPipeline *pipeline); virtual BOOL updateGeometry(LLDrawable *drawable); + virtual void updateFaceSize(S32 idx); virtual BOOL updateLOD(); virtual BOOL setDrawableParent(LLDrawable* parentp); virtual BOOL updateLighting(BOOL do_lighting) { return TRUE; }; @@ -203,7 +206,7 @@ public: LLViewerRegion* getRegion() const { return mRegionp; } BOOL isSelected() const { return mUserSelected; } - void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;} + virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;} const LLUUID &getID() const { return mID; } U32 getLocalID() const { return mLocalID; } @@ -293,8 +296,6 @@ public: /*virtual*/ BOOL setMaterial(const U8 material); virtual void setTEImage(const U8 te, LLViewerImage *imagep); // Not derived from LLPrimitive LLViewerImage *getTEImage(const U8 te) const; - - S32 getFaceIndexOffset() { return mFaceIndexOffset; } void fitFaceTexture(const U8 face); void sendTEUpdate() const; // Sends packed representation of all texture entry information @@ -307,6 +308,8 @@ public: U8 getState() { return mState; } F32 getAppAngle() const { return mAppAngle; } + F32 getPixelArea() const { return mPixelArea; } + void setPixelArea(F32 area) { mPixelArea = area; } F32 getMaxScale() const; F32 getMidScale() const; F32 getMinScale() const; @@ -339,6 +342,7 @@ public: void markForUpdate(BOOL priority); void updateVolume(const LLVolumeParams& volume_params); virtual void updateSpatialExtents(LLVector3& min, LLVector3& max); + virtual F32 getBinRadius(); LLBBox getBoundingBoxAgent() const; @@ -378,6 +382,11 @@ public: LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); S16 getInventorySerial() const { return mInventorySerialNum; } + // These functions does viewer-side only object inventory modifications + void updateViewerInventoryAsset( + const LLViewerInventoryItem* item, + const LLUUID& new_asset); + // This function will make sure that we refresh the inventory. void dirtyInventory(); BOOL isInventoryDirty() { return mInventoryDirty; } @@ -436,6 +445,7 @@ public: void printNameValuePairs() const; virtual S32 getLOD() const { return 3; } + virtual U32 getPartitionType() const; virtual LLNetworkData* getParameterEntry(U16 param_type) const; virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); @@ -536,6 +546,7 @@ protected: void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); + void deleteParticleSource(); private: void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string @@ -547,7 +558,7 @@ protected: F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation F64 mLastMessageUpdateSecs; // Last update from a message from the simulator - + TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator // extra data sent from the sim...currently only used for tree species info U8* mData; @@ -578,7 +589,6 @@ protected: BOOL mOnActiveList; BOOL mOnMap; // On the map. BOOL mStatic; // Object doesn't move. - S32 mFaceIndexOffset; // offset into drawable's faces, zero except in special cases S32 mNumFaces; S32 mLastUpdateFrame; // frames in which an object had last moved for smart coalescing of drawables @@ -611,7 +621,6 @@ private: static S32 sNumObjects; }; - /////////////////// // // Inlines @@ -642,4 +651,34 @@ public: U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc. }; +// subclass of viewer object that can be added to particle partitions +class LLAlphaObject : public LLViewerObject +{ +public: + LLAlphaObject(const LLUUID &id, const LLPCode type, LLViewerRegion *regionp) + : LLViewerObject(id,type,regionp) + { mDepth = 0.f; } + + virtual BOOL isParticle(); + virtual F32 getPartSize(S32 idx); + virtual void getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp) = 0; + + F32 mDepth; +}; + +class LLStaticViewerObject : public LLViewerObject +{ +public: + LLStaticViewerObject(const LLUUID& id, const LLPCode type, LLViewerRegion* regionp) + : LLViewerObject(id,type,regionp) + { } + + virtual void updateDrawable(BOOL force_damped); +}; + #endif diff --git a/linden/indra/newview/llviewerobjectlist.cpp b/linden/indra/newview/llviewerobjectlist.cpp index 49f2aae..8c15906 100644 --- a/linden/indra/newview/llviewerobjectlist.cpp +++ b/linden/indra/newview/llviewerobjectlist.cpp @@ -230,7 +230,7 @@ void LLViewerObjectList::processUpdateCore(LLViewerObject* objectp, && update_type != OUT_TERSE_IMPROVED && objectp->mCreateSelected) { - if ( gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ) != gToolPie ) + if ( gToolMgr->getCurrentTool() != gToolPie ) { //llinfos << "DEBUG selecting " << objectp->mID << " " // << objectp->mLocalID << llendl; @@ -584,7 +584,8 @@ void LLViewerObjectList::updateApparentAngles(LLAgent &agent) } // Selected - for (objectp = gSelectMgr->getFirstRootObject(); objectp; objectp = gSelectMgr->getNextRootObject()) + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + for (objectp = selection->getFirstRootObject(); objectp; objectp = selection->getNextRootObject()) { objectp->boostTexturePriority(); } @@ -749,6 +750,15 @@ void LLViewerObjectList::update(LLAgent &agent, LLWorld &world) mNumVisCulledStat.addValue(mNumVisCulled); } +void LLViewerObjectList::clearDebugText() +{ + for (S32 i = 0; i < mObjects.count(); i++) + { + mObjects[i]->setDebugText(""); + } +} + + void LLViewerObjectList::cleanupReferences(LLViewerObject *objectp) { LLMemType mt(LLMemType::MTYPE_OBJECT); @@ -1070,7 +1080,15 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce mSelectPickList.clear(); std::vector pick_drawables; - gPipeline.mObjectPartition->cull(camera, &pick_drawables, TRUE); + + for (i = 0; i < LLPipeline::NUM_PARTITIONS-1; i++) + { + LLSpatialPartition* part = gPipeline.getSpatialPartition(i); + if (part) + { + part->cull(camera, &pick_drawables, TRUE); + } + } for (std::vector::iterator iter = pick_drawables.begin(); iter != pick_drawables.end(); iter++) @@ -1092,10 +1110,10 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce LLHUDText::addPickable(mSelectPickList); - for (objectp = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - objectp; - objectp = (LLVOAvatar*)LLCharacter::sInstances.getNextData()) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + objectp = (LLVOAvatar*) *iter; if (!objectp->isDead()) { if (objectp->mDrawable.notNull() && objectp->mDrawable->isVisible()) @@ -1116,7 +1134,7 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce { if (attachmentp->getIsHUDAttachment()) { - LLViewerObject* objectp = attachmentp->getObject(0); + LLViewerObject* objectp = attachmentp->getObject(); if (objectp) { mSelectPickList.insert(objectp); @@ -1132,32 +1150,36 @@ U32 LLViewerObjectList::renderObjectsForSelect(LLCamera &camera, BOOL pick_parce } } } - + S32 num_pickables = (S32)mSelectPickList.size() + LLHUDIcon::getNumInstances(); - S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables; - - std::set::iterator pick_it; - i = 0; - for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();) + if (num_pickables != 0) { - LLViewerObject* objp = (*pick_it); - if (!objp || objp->isDead() || !objp->mbCanSelect) + S32 step = (0x000fffff - GL_NAME_INDEX_OFFSET) / num_pickables; + + std::set::iterator pick_it; + i = 0; + for (pick_it = mSelectPickList.begin(); pick_it != mSelectPickList.end();) { - mSelectPickList.erase(pick_it++); - continue; + LLViewerObject* objp = (*pick_it); + if (!objp || objp->isDead() || !objp->mbCanSelect) + { + mSelectPickList.erase(pick_it++); + continue; + } + + objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET; + i++; + ++pick_it; } - objp->mGLName = (i * step) + GL_NAME_INDEX_OFFSET; - i++; - ++pick_it; + LLHUDIcon::generatePickIDs(i * step, step); + + // At this point, we should only have live drawables/viewer objects + gPipeline.renderForSelect(mSelectPickList); } - - LLHUDIcon::generatePickIDs(i * step, step); } - // At this point, we should only have live drawables/viewer objects - gPipeline.renderForSelect(); // // Render pass for selected objects // @@ -1214,7 +1236,7 @@ LLViewerObject *LLViewerObjectList::createObjectViewer(const LLPCode pcode, LLVi LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); if (!objectp) { - llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << llendl; +// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << llendl; return NULL; } @@ -1248,7 +1270,7 @@ LLViewerObject *LLViewerObjectList::createObject(const LLPCode pcode, LLViewerRe LLViewerObject *objectp = LLViewerObject::createObject(fullid, pcode, regionp); if (!objectp) { - llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl; +// llwarns << "Couldn't create object of type " << LLPrimitive::pCodeToString(pcode) << " id:" << fullid << llendl; return NULL; } @@ -1440,7 +1462,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) if (orphans_found && objectp->isSelected()) { - LLSelectNode* nodep = gSelectMgr->findSelectNode(objectp); + LLSelectNode* nodep = gSelectMgr->getSelection()->findNode(objectp); if (nodep && !nodep->mIndividualSelection) { // rebuild selection with orphans @@ -1450,6 +1472,7 @@ void LLViewerObjectList::findOrphans(LLViewerObject* objectp, U32 ip, U32 port) } } +//////////////////////////////////////////////////////////////////////////// LLViewerObjectList::OrphanInfo::OrphanInfo() { diff --git a/linden/indra/newview/llviewerobjectlist.h b/linden/indra/newview/llviewerobjectlist.h index 3122d9d..f92c989 100644 --- a/linden/indra/newview/llviewerobjectlist.h +++ b/linden/indra/newview/llviewerobjectlist.h @@ -115,6 +115,7 @@ public: void addToMap(LLViewerObject *objectp); void removeFromMap(LLViewerObject *objectp); + void clearDebugText(); //////////////////////////////////////////// // diff --git a/linden/indra/newview/llviewerparcelmgr.cpp b/linden/indra/newview/llviewerparcelmgr.cpp index af910e8..a21d2f7 100644 --- a/linden/indra/newview/llviewerparcelmgr.cpp +++ b/linden/indra/newview/llviewerparcelmgr.cpp @@ -65,6 +65,7 @@ const F32 PARCEL_COLLISION_DRAW_SECS = 1.f; + // Globals LLViewerParcelMgr *gParcelMgr = NULL; @@ -72,6 +73,12 @@ U8* LLViewerParcelMgr::sPackedOverlay = NULL; LLUUID gCurrentMovieID = LLUUID::null; +static LLParcelSelection* get_null_parcel_selection(); +template<> + const LLHandle::NullFunc + LLHandle::sNullFunc = get_null_parcel_selection; + + // Local functions void optionally_start_music(const LLString& music_url); void callback_start_music(S32 option, void* data); @@ -102,8 +109,6 @@ struct LLGodForceOwnerData // LLViewerParcelMgr::LLViewerParcelMgr() : mSelected(FALSE), - mSelectedMultipleOwners(FALSE), - mWholeParcelSelected(FALSE), mWestSouth(), mEastNorth(), mSelectedDwell(0.f), @@ -113,11 +118,12 @@ LLViewerParcelMgr::LLViewerParcelMgr() mRenderCollision(FALSE), mRenderSelection(TRUE), mCollisionBanned(0), - mCollisionTimer(), - mMediaParcelId(0), - mMediaRegionId(0) + mCollisionTimer() { - mParcel = new LLParcel(); + mCurrentParcel = new LLParcel(); + mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel); + mFloatingParcelSelection = new LLParcelSelection(mCurrentParcel); + mAgentParcel = new LLParcel(); mHoverParcel = new LLParcel(); mCollisionParcel = new LLParcel(); @@ -149,8 +155,14 @@ LLViewerParcelMgr::LLViewerParcelMgr() LLViewerParcelMgr::~LLViewerParcelMgr() { - delete mParcel; - mParcel = NULL; + mCurrentParcelSelection->setParcel(NULL); + mCurrentParcelSelection = NULL; + + mFloatingParcelSelection->setParcel(NULL); + mFloatingParcelSelection = NULL; + + delete mCurrentParcel; + mCurrentParcel = NULL; delete mAgentParcel; mAgentParcel = NULL; @@ -175,32 +187,17 @@ LLViewerParcelMgr::~LLViewerParcelMgr() mAgentParcelOverlay = NULL; } - -void LLViewerParcelMgr::destroyGL() -{ - mBlockedImage = NULL; - mPassImage = NULL; -} - - -void LLViewerParcelMgr::restoreGL() -{ - mBlockedImage = gImageList.getImage(mBlockedImageID, TRUE, TRUE); - mPassImage = gImageList.getImage(mPassImageID, TRUE, TRUE); -} - - void LLViewerParcelMgr::dump() { llinfos << "Parcel Manager Dump" << llendl; llinfos << "mSelected " << S32(mSelected) << llendl; llinfos << "Selected parcel: " << llendl; llinfos << mWestSouth << " to " << mEastNorth << llendl; - mParcel->dump(); - llinfos << "banning " << mParcel->mBanList.size() << llendl; + mCurrentParcel->dump(); + llinfos << "banning " << mCurrentParcel->mBanList.size() << llendl; - access_map_const_iterator cit = mParcel->mBanList.begin(); - access_map_const_iterator end = mParcel->mBanList.end(); + access_map_const_iterator cit = mCurrentParcel->mBanList.begin(); + access_map_const_iterator end = mCurrentParcel->mBanList.end(); for ( ; cit != end; ++cit) { llinfos << "ban id " << (*cit).first << llendl; @@ -233,27 +230,27 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out, if (mSelected) { - if (mSelectedMultipleOwners) + if (mCurrentParcelSelection->mSelectedMultipleOwners) { - area = getClaimableArea(); + area = mCurrentParcelSelection->getClaimableArea(); } else { area = getSelectedArea(); } - if (mParcel->getForSale()) + if (mCurrentParcel->getForSale()) { - price = mParcel->getSalePrice(); + price = mCurrentParcel->getSalePrice(); for_sale = TRUE; } else { - price = area * mParcel->getClaimPricePerMeter(); + price = area * mCurrentParcel->getClaimPricePerMeter(); for_sale = FALSE; } - rent = mParcel->getTotalRent(); + rent = mCurrentParcel->getTotalRent(); dwell = mSelectedDwell; } @@ -267,51 +264,27 @@ void LLViewerParcelMgr::getDisplayInfo(S32* area_out, S32* claim_out, void LLViewerParcelMgr::getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean) { - if (mSelected && mParcel) + if (mSelected && mCurrentParcel) { - sw_max = mParcel->getSimWideMaxPrimCapacity(); - sw_total = mParcel->getSimWidePrimCount(); - max = llround(mParcel->getMaxPrimCapacity()*mParcel->getParcelPrimBonus()); - total = mParcel->getPrimCount(); - owner = mParcel->getOwnerPrimCount(); - group = mParcel->getGroupPrimCount(); - other = mParcel->getOtherPrimCount(); - selected = mParcel->getSelectedPrimCount(); - parcel_object_bonus = mParcel->getParcelPrimBonus(); - other_clean = mParcel->getCleanOtherTime(); + sw_max = mCurrentParcel->getSimWideMaxPrimCapacity(); + sw_total = mCurrentParcel->getSimWidePrimCount(); + max = llround(mCurrentParcel->getMaxPrimCapacity()*mCurrentParcel->getParcelPrimBonus()); + total = mCurrentParcel->getPrimCount(); + owner = mCurrentParcel->getOwnerPrimCount(); + group = mCurrentParcel->getGroupPrimCount(); + other = mCurrentParcel->getOtherPrimCount(); + selected = mCurrentParcel->getSelectedPrimCount(); + parcel_object_bonus = mCurrentParcel->getParcelPrimBonus(); + other_clean = mCurrentParcel->getCleanOtherTime(); } } -BOOL LLViewerParcelMgr::getMultipleOwners() const -{ - return mSelectedMultipleOwners; -} - - -BOOL LLViewerParcelMgr::getWholeParcelSelected() const -{ - return mWholeParcelSelected; -} - - -S32 LLViewerParcelMgr::getClaimableArea() const -{ - const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS ); - return mSelectedPublicCount * UNIT_AREA; -} - -bool LLViewerParcelMgr::hasOthersSelected() const -{ - return mSelectedOtherCount != 0; -} - - S32 LLViewerParcelMgr::getSelectedArea() const { S32 rv = 0; - if(mSelected && mParcel && mWholeParcelSelected) + if(mSelected && mCurrentParcel && mCurrentParcelSelection->mWholeParcelSelected) { - rv = mParcel->getArea(); + rv = mCurrentParcel->getArea(); } else if(mSelected) { @@ -447,7 +420,7 @@ void LLViewerParcelMgr::writeAgentParcelFromBitmap(U8* bitmap) // Given a point, find the PARCEL_GRID_STEP x PARCEL_GRID_STEP block // containing it and select that. -void LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global) +LLParcelSelectionHandle LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global) { LLVector3d southwest = pos_global; LLVector3d northeast = pos_global; @@ -461,14 +434,14 @@ void LLViewerParcelMgr::selectParcelAt(const LLVector3d& pos_global) northeast.mdV[VY] = llround( northeast.mdV[VY], (F64)PARCEL_GRID_STEP_METERS ); // Snap to parcel - selectLand( southwest, northeast, TRUE ); + return selectLand( southwest, northeast, TRUE ); } // Tries to select the parcel inside the rectangle -void LLViewerParcelMgr::selectParcelInRectangle() +LLParcelSelectionHandle LLViewerParcelMgr::selectParcelInRectangle() { - selectLand(mWestSouth, mEastNorth, TRUE); + return selectLand(mWestSouth, mEastNorth, TRUE); } @@ -498,28 +471,32 @@ void LLViewerParcelMgr::selectCollisionParcel() mRequestResult = PARCEL_RESULT_NO_DATA; // Hack: Copy some data over temporarily - mParcel->setName( mCollisionParcel->getName() ); - mParcel->setDesc( mCollisionParcel->getDesc() ); - mParcel->setPassPrice(mCollisionParcel->getPassPrice()); - mParcel->setPassHours(mCollisionParcel->getPassHours()); + mCurrentParcel->setName( mCollisionParcel->getName() ); + mCurrentParcel->setDesc( mCollisionParcel->getDesc() ); + mCurrentParcel->setPassPrice(mCollisionParcel->getPassPrice()); + mCurrentParcel->setPassHours(mCollisionParcel->getPassHours()); // clear the list of segments to prevent flashing resetSegments(mHighlightSegments); + mFloatingParcelSelection->setParcel(mCurrentParcel); + mCurrentParcelSelection->setParcel(NULL); + mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel); + mSelected = TRUE; - mWholeParcelSelected = TRUE; + mCurrentParcelSelection->mWholeParcelSelected = TRUE; notifyObservers(); return; } // snap_selection = auto-select the hit parcel, if there is exactly one -void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2, +LLParcelSelectionHandle LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d &corner2, BOOL snap_selection) { if (!gWorldp) { - return; + return NULL; } sanitize_corners( corner1, corner2, mWestSouth, mEastNorth ); @@ -530,7 +507,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d & { mSelected = FALSE; notifyObservers(); - return; + return NULL; } // ...y isn't more than one meter away @@ -539,7 +516,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d & { mSelected = FALSE; notifyObservers(); - return; + return NULL; } // Can't select across region boundary @@ -556,7 +533,7 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d & { // just in case they somehow selected no land. mSelected = FALSE; - return; + return NULL; } if (region != region_other) @@ -564,50 +541,13 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d & LLNotifyBox::showXml("CantSelectLandFromMultipleRegions"); mSelected = FALSE; notifyObservers(); - return; + return NULL; } // Build region global copies of corners LLVector3 wsb_region = region->getPosRegionFromGlobal( mWestSouth ); LLVector3 ent_region = region->getPosRegionFromGlobal( mEastNorth ); - /* - // Check land to make sure all is either public, owned, or self - LLViewerParcelOverlay* overlay = region->getParcelOverlay(); - if (!overlay) - { - llerrs << "No overlay in LLViewerParcelMgr::selectLand" << llendl; - return; - } - - U8 start_ownership = overlay->ownership( wsb_region ); - BOOL identical = TRUE; - S32 x_steps = S32( getSelectionWidth() / PARCEL_GRID_STEP_METERS ); - S32 y_steps = S32( getSelectionHeight() / PARCEL_GRID_STEP_METERS ); - - for (S32 x = 0; x < x_steps && identical; x++ ) - { - for (S32 y = 0; y < y_steps && identical; y++ ) - { - // strange recomputation each time to avoid error accumulation - LLVector3 check = wsb_region; - check.mV[VX] += x * PARCEL_GRID_STEP_METERS; - check.mV[VY] += y * PARCEL_GRID_STEP_METERS; - - identical = (start_ownership == overlay->ownership(check)); - } - } - - if (!identical) - { - add_chat("Can't select mix of your own, other people's and public land.", FALSE, "", FALSE, CHAT_SOURCE_SYSTEM); - add_chat("Try selecting a smaller piece of land.", FALSE, "", FALSE, CHAT_SOURCE_SYSTEM); - mSelected = FALSE; - notifyObservers(); - return; - } - */ - // Send request message LLMessageSystem *msg = gMessageSystem; msg->newMessageFast(_PREHASH_ParcelPropertiesRequest); @@ -628,12 +568,24 @@ void LLViewerParcelMgr::selectLand(const LLVector3d &corner1, const LLVector3d & // clear the list of segments to prevent flashing resetSegments(mHighlightSegments); + mFloatingParcelSelection->setParcel(mCurrentParcel); + mCurrentParcelSelection->setParcel(NULL); + mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel); + mSelected = TRUE; - mWholeParcelSelected = snap_selection; + mCurrentParcelSelection->mWholeParcelSelected = snap_selection; notifyObservers(); - return; + return mCurrentParcelSelection; } +void LLViewerParcelMgr::deselectUnused() +{ + // no more outstanding references to this selection, other than our own + if (mCurrentParcelSelection->getNumRefs() == 1 && mFloatingParcelSelection->getNumRefs() == 1) + { + deselectLand(); + } +} void LLViewerParcelMgr::deselectLand() { @@ -642,14 +594,20 @@ void LLViewerParcelMgr::deselectLand() mSelected = FALSE; // Invalidate the selected parcel - mParcel->setLocalID(-1); - mParcel->mAccessList.clear(); - mParcel->mBanList.clear(); - //mParcel->mRenterList.reset(); + mCurrentParcel->setLocalID(-1); + mCurrentParcel->mAccessList.clear(); + mCurrentParcel->mBanList.clear(); + //mCurrentParcel->mRenterList.reset(); mSelectedDwell = 0.f; notifyObservers(); + + // invalidate parcel selection so that existing users of this selection can clean up + mCurrentParcelSelection->setParcel(NULL); + mFloatingParcelSelection->setParcel(NULL); + // create new parcel selection + mCurrentParcelSelection = new LLParcelSelection(mCurrentParcel); } } @@ -694,18 +652,15 @@ BOOL LLViewerParcelMgr::selectionEmpty() const } -LLParcel *LLViewerParcelMgr::getSelectedParcel() const +LLParcelSelectionHandle LLViewerParcelMgr::getParcelSelection() const { - if (mSelected) - { - return mParcel; - } - else - { - return NULL; - } + return mCurrentParcelSelection; } +LLParcelSelectionHandle LLViewerParcelMgr::getFloatingParcelSelection() const +{ + return mFloatingParcelSelection; +} LLParcel *LLViewerParcelMgr::getAgentParcel() const { @@ -717,9 +672,10 @@ BOOL LLViewerParcelMgr::agentCanBuild() const { if (mAgentParcel) { - return gAgent.isGodlike() - || (mAgentParcel->getOwnerID() == gAgent.getID()) - || (mAgentParcel->getAllowModify()); + return (gAgent.isGodlike() + || (mAgentParcel->allowModifyBy( + gAgent.getID(), + gAgent.getGroupID()))); } else { @@ -923,11 +879,11 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags) if (flags & AL_BAN) { - mParcel->mBanList.clear(); + mCurrentParcel->mBanList.clear(); } if (flags & AL_ACCESS) { - mParcel->mAccessList.clear(); + mCurrentParcel->mAccessList.clear(); } // Only the headers differ @@ -938,7 +894,7 @@ void LLViewerParcelMgr::sendParcelAccessListRequest(U32 flags) msg->nextBlockFast(_PREHASH_Data); msg->addS32Fast(_PREHASH_SequenceID, 0); msg->addU32Fast(_PREHASH_Flags, flags); - msg->addS32("LocalID", mParcel->getLocalID() ); + msg->addS32("LocalID", mCurrentParcel->getLocalID() ); msg->sendReliable( region->getHost() ); } @@ -961,7 +917,7 @@ void LLViewerParcelMgr::sendParcelDwellRequest() msg->addUUID("AgentID", gAgent.getID() ); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("Data"); - msg->addS32("LocalID", mParcel->getLocalID()); + msg->addS32("LocalID", mCurrentParcel->getLocalID()); msg->addUUID("ParcelID", LLUUID::null); // filled in on simulator msg->sendReliable( region->getHost() ); } @@ -1000,8 +956,8 @@ void LLViewerParcelMgr::sendParcelGodForceOwner(const LLUUID& owner_id) llinfos << "Region " << region->getOriginGlobal() << llendl; - LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mParcel->getLocalID(), region->getHost()); - if(mParcel->getAuctionID()) + LLGodForceOwnerData* data = new LLGodForceOwnerData(owner_id, mCurrentParcel->getLocalID(), region->getHost()); + if(mCurrentParcel->getAuctionID()) { gViewerWindow->alertXml("ForceOwnerAuctionWarning", callback_god_force_owner, @@ -1051,7 +1007,7 @@ void LLViewerParcelMgr::sendParcelGodForceToContent() msg->addUUID("AgentID", gAgent.getID()); msg->addUUID("SessionID", gAgent.getSessionID()); msg->nextBlock("ParcelData"); - msg->addS32("LocalID", mParcel->getLocalID()); + msg->addS32("LocalID", mCurrentParcel->getLocalID()); msg->sendReliable(region->getHost()); } @@ -1079,7 +1035,7 @@ void LLViewerParcelMgr::sendParcelRelease() msg->addUUID("AgentID", gAgent.getID() ); msg->addUUID("SessionID", gAgent.getSessionID() ); msg->nextBlock("Data"); - msg->addS32("LocalID", mParcel->getLocalID() ); + msg->addS32("LocalID", mCurrentParcel->getLocalID() ); //msg->addU32("Flags", flags); msg->sendReliable( region->getHost() ); @@ -1117,7 +1073,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy( BOOL is_claim, BOOL remove_contribution) { - if (!mSelected || !mParcel) + if (!mSelected || !mCurrentParcel) { gViewerWindow->alertXml("CannotBuyLandNothingSelected"); return NULL; @@ -1162,7 +1118,7 @@ LLViewerParcelMgr::ParcelBuyInfo* LLViewerParcelMgr::setupParcelBuy( if (!is_claim) { - info->mParcelID = mParcel->getLocalID(); + info->mParcelID = mCurrentParcel->getLocalID(); } else { @@ -1215,7 +1171,7 @@ void LLViewerParcelMgr::deleteParcelBuy(ParcelBuyInfo*& info) void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) { - if (!mSelected || !mParcel) + if (!mSelected || !mCurrentParcel) { gViewerWindow->alertXml("CannotDeedLandNothingSelected"); return; @@ -1239,7 +1195,7 @@ void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) msg->addUUID("SessionID", gAgent.getSessionID() ); msg->nextBlock("Data"); msg->addUUID("GroupID", group_id ); - msg->addS32("LocalID", mParcel->getLocalID() ); + msg->addS32("LocalID", mCurrentParcel->getLocalID() ); //msg->addU32("JoinNeighbors", join); msg->sendReliable( region->getHost() ); } @@ -1253,7 +1209,7 @@ void LLViewerParcelMgr::sendParcelDeed(const LLUUID& group_id) void LLViewerParcelMgr::makeLandmarkAtSelection() { // Don't create for parcels you don't own - if (gAgent.getID() != mParcel->getOwnerID()) + if (gAgent.getID() != mCurrentParcel->getOwnerID()) { return; } @@ -1289,7 +1245,7 @@ const char* LLViewerParcelMgr::getAgentParcelName() const } -void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_reply_to_update) +void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel) { if (!parcel) return; @@ -1306,7 +1262,8 @@ void LLViewerParcelMgr::sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_r msg->addS32Fast(_PREHASH_LocalID, parcel->getLocalID() ); U32 flags = 0x0; - if (want_reply_to_update) flags |= 0x01; + // request new properties update from simulator + flags |= 0x01; msg->addU32("Flags", flags); parcel->packMessage(msg); @@ -1450,7 +1407,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use { // ...selected parcels report this sequence id gParcelMgr->mRequestResult = PARCEL_RESULT_SUCCESS; - parcel = gParcelMgr->mParcel; + parcel = gParcelMgr->mCurrentParcel; } else if (sequence_id == HOVERED_PARCEL_SEQ_ID) { @@ -1559,11 +1516,11 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use if (sequence_id == SELECTED_PARCEL_SEQ_ID) { // Update selected counts - gParcelMgr->mSelectedSelfCount = self_count; - gParcelMgr->mSelectedOtherCount = other_count; - gParcelMgr->mSelectedPublicCount = public_count; + gParcelMgr->mCurrentParcelSelection->mSelectedSelfCount = self_count; + gParcelMgr->mCurrentParcelSelection->mSelectedOtherCount = other_count; + gParcelMgr->mCurrentParcelSelection->mSelectedPublicCount = public_count; - gParcelMgr->mSelectedMultipleOwners = + gParcelMgr->mCurrentParcelSelection->mSelectedMultipleOwners = (request_result == PARCEL_RESULT_MULTIPLE); // Select the whole parcel @@ -1583,7 +1540,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use west_south.mV[VY], east_north.mV[VX], east_north.mV[VY] ); - gParcelMgr->mWholeParcelSelected = FALSE; + gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = FALSE; } else if (0 == local_id) { @@ -1597,7 +1554,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use aabb_min.mV[VY], aabb_max.mV[VX], aabb_max.mV[VY] ); - gParcelMgr->mWholeParcelSelected = TRUE; + gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE; } else { @@ -1614,10 +1571,10 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use gParcelMgr->resetSegments(gParcelMgr->mHighlightSegments); gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mHighlightSegments ); - delete bitmap; + delete[] bitmap; bitmap = NULL; - gParcelMgr->mWholeParcelSelected = TRUE; + gParcelMgr->mCurrentParcelSelection->mWholeParcelSelected = TRUE; } // Request access list information for this land @@ -1666,7 +1623,7 @@ void LLViewerParcelMgr::processParcelProperties(LLMessageSystem *msg, void **use gParcelMgr->resetSegments(gParcelMgr->mCollisionSegments); gParcelMgr->writeSegmentsFromBitmap( bitmap, gParcelMgr->mCollisionSegments ); - delete bitmap; + delete[] bitmap; bitmap = NULL; } @@ -1815,10 +1772,10 @@ void optionally_start_music(const LLString& music_url) { if (gSavedSettings.getWarning("FirstStreamingMusic")) { - void* data = (void*)strdup(music_url.c_str()); + std::string* newstring = new std::string(music_url); gViewerWindow->alertXml("ParcelCanPlayMusic", callback_start_music, - (void*)data); + (void*)newstring); } else if (gSavedSettings.getBOOL("AudioStreamingMusic")) @@ -1841,7 +1798,7 @@ void optionally_start_music(const LLString& music_url) void callback_start_music(S32 option, void* data) { - const char* music_url = (const char*)data; + std::string* music_url = (std::string*)data; if (0 == option) { @@ -1849,7 +1806,7 @@ void callback_start_music(S32 option, void* data) llinfos << "Starting first parcel music " << music_url << llendl; if (gAudiop) { - gAudiop->startInternetStream(music_url); + gAudiop->startInternetStream(music_url->c_str()); LLMediaRemoteCtrl* ctrl = gOverlayBar->getMusicRemoteControl(); ctrl->setTransportState( LLMediaRemoteCtrl::Play, FALSE ); } @@ -1861,7 +1818,7 @@ void callback_start_music(S32 option, void* data) gSavedSettings.setWarning("FirstStreamingMusic", FALSE); - delete [] music_url; + delete music_url; music_url = NULL; } @@ -1962,7 +1919,7 @@ void LLViewerParcelMgr::processParcelAccessListReply(LLMessageSystem *msg, void msg->getU32Fast( _PREHASH_Data, _PREHASH_Flags, message_flags); msg->getS32Fast( _PREHASH_Data, _PREHASH_LocalID, parcel_id); - LLParcel* parcel = gParcelMgr->mParcel; + LLParcel* parcel = gParcelMgr->mCurrentParcel; if (!parcel) return; if (parcel_id != parcel->getLocalID()) @@ -2004,7 +1961,7 @@ void LLViewerParcelMgr::processParcelDwellReply(LLMessageSystem* msg, void**) F32 dwell; msg->getF32("Data", "Dwell", dwell); - if (local_id == gParcelMgr->mParcel->getLocalID()) + if (local_id == gParcelMgr->mCurrentParcel->getLocalID()) { gParcelMgr->mSelectedDwell = dwell; gParcelMgr->notifyObservers(); @@ -2028,7 +1985,7 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) LLMessageSystem* msg = gMessageSystem; - LLParcel* parcel = mParcel; + LLParcel* parcel = mCurrentParcel; if (!parcel) return; if (which & AL_ACCESS) @@ -2148,18 +2105,18 @@ void LLViewerParcelMgr::sendParcelAccessListUpdate(U32 which) void LLViewerParcelMgr::deedLandToGroup() { - char group_name[MAX_STRING]; - gCacheName->getGroupName(mParcel->getGroupID(), group_name); + char group_name[MAX_STRING]; /* Flawfinder: ignore */ + gCacheName->getGroupName(mCurrentParcel->getGroupID(), group_name); LLString::format_map_t args; - args["[AREA]"] = llformat("%d", mParcel->getArea()); + args["[AREA]"] = llformat("%d", mCurrentParcel->getArea()); args["[GROUP_NAME]"] = group_name; - if(mParcel->getContributeWithDeed()) + if(mCurrentParcel->getContributeWithDeed()) { - char first_name[DB_FIRST_NAME_BUF_SIZE]; + char first_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ first_name[0] = '\0'; - char last_name[DB_FIRST_NAME_BUF_SIZE]; + char last_name[DB_FIRST_NAME_BUF_SIZE]; /* Flawfinder: ignore */ last_name[0] = '\0'; - gCacheName->getName(mParcel->getOwnerID(), first_name, last_name); + gCacheName->getName(mCurrentParcel->getOwnerID(), first_name, last_name); args["[FIRST_NAME]"] = first_name; args["[LAST_NAME]"] = last_name; gViewerWindow->alertXml("DeedLandToGroupWithContribution",args, deedAlertCB, NULL); @@ -2175,7 +2132,7 @@ void LLViewerParcelMgr::deedAlertCB(S32 option, void*) { if (option == 0) { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel(); LLUUID group_id; if(parcel) { @@ -2206,7 +2163,7 @@ void LLViewerParcelMgr::startReleaseLand() return; } - if (!isParcelOwnedByAgent(mParcel, GP_LAND_RELEASE) + if (!isParcelOwnedByAgent(mCurrentParcel, GP_LAND_RELEASE) && !(gAgent.canManageEstate())) { gViewerWindow->alertXml("CannotReleaseLandDontOwn"); @@ -2231,7 +2188,7 @@ void LLViewerParcelMgr::startReleaseLand() } */ - if (!mWholeParcelSelected) + if (!mCurrentParcelSelection->mWholeParcelSelected) { gViewerWindow->alertXml("CannotReleaseLandPartialSelection"); return; @@ -2239,7 +2196,7 @@ void LLViewerParcelMgr::startReleaseLand() // Compute claim price LLStringBase::format_map_t args; - args["[AREA]"] = llformat("%d",mParcel->getArea()); + args["[AREA]"] = llformat("%d",mCurrentParcel->getArea()); gViewerWindow->alertXml("ReleaseLandWarning", args, releaseAlertCB, this); } @@ -2251,7 +2208,7 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const return false; } - if (mSelected && parcel == mParcel) + if (mSelected && parcel == mCurrentParcel) { if (mRequestResult == PARCEL_RESULT_NO_DATA) { @@ -2291,12 +2248,12 @@ bool LLViewerParcelMgr::canAgentBuyParcel(LLParcel* parcel, bool forGroup) const void LLViewerParcelMgr::startBuyLand(BOOL is_for_group) { - LLFloaterBuyLand::buyLand(getSelectionRegion(), mParcel, is_for_group == TRUE); + LLFloaterBuyLand::buyLand(getSelectionRegion(), mCurrentParcelSelection, is_for_group == TRUE); } void LLViewerParcelMgr::startSellLand() { - LLFloaterSellLand::sellLand(getSelectionRegion(), mParcel); + LLFloaterSellLand::sellLand(getSelectionRegion(), mCurrentParcelSelection); } void LLViewerParcelMgr::startDivideLand() @@ -2307,7 +2264,7 @@ void LLViewerParcelMgr::startDivideLand() return; } - if (mWholeParcelSelected) + if (mCurrentParcelSelection->mWholeParcelSelected) { gViewerWindow->alertXml("CannotDivideLandPartialSelection"); return; @@ -2359,13 +2316,13 @@ void LLViewerParcelMgr::startJoinLand() return; } - if (mWholeParcelSelected) + if (mCurrentParcelSelection->mWholeParcelSelected) { gViewerWindow->alertXml("CannotJoinLandEntireParcelSelected"); return; } - if (!mSelectedMultipleOwners) + if (!mCurrentParcelSelection->mSelectedMultipleOwners) { gViewerWindow->alertXml("CannotJoinLandSelection"); return; @@ -2411,7 +2368,7 @@ void LLViewerParcelMgr::callbackJoinLand(S32 option, void* data) void LLViewerParcelMgr::startDeedLandToGroup() { - if (!mSelected || !mParcel) + if (!mSelected || !mCurrentParcel) { gViewerWindow->alertXml("CannotDeedLandNothingSelected"); return; @@ -2441,7 +2398,7 @@ void LLViewerParcelMgr::startDeedLandToGroup() if(!gAgent.isGodlike()) { if((region->getRegionFlags() & REGION_FLAGS_BLOCK_LAND_RESELL) - && (mParcel->getOwnerID() != region->getOwner())) + && (mCurrentParcel->getOwnerID() != region->getOwner())) { LLStringBase::format_map_t args; args["[REGION]"] = region->getName(); @@ -2455,7 +2412,7 @@ void LLViewerParcelMgr::startDeedLandToGroup() } void LLViewerParcelMgr::reclaimParcel() { - LLParcel* parcel = gParcelMgr->getSelectedParcel(); + LLParcel* parcel = gParcelMgr->getParcelSelection()->getParcel(); LLViewerRegion* regionp = gParcelMgr->getSelectionRegion(); if(parcel && parcel->getOwnerID().notNull() && (parcel->getOwnerID() != gAgent.getID()) @@ -2484,7 +2441,7 @@ void LLViewerParcelMgr::releaseAlertCB(S32 option, void *) void LLViewerParcelMgr::buyPass() { - LLParcel* parcel = getSelectedParcel(); + LLParcel* parcel = getParcelSelection()->getParcel(); if (!parcel) return; LLViewerRegion* region = getSelectionRegion(); @@ -2578,3 +2535,58 @@ void sanitize_corners(const LLVector3d &corner1, east_north_top.mdV[VZ] = llmax( corner1.mdV[VZ], corner2.mdV[VZ] ); } +// +// LLParcelSelection +// +LLParcelSelection::LLParcelSelection() : + mParcel(NULL), + mSelectedMultipleOwners(FALSE), + mWholeParcelSelected(FALSE), + mSelectedSelfCount(0), + mSelectedOtherCount(0), + mSelectedPublicCount(0) +{ +} + +LLParcelSelection::LLParcelSelection(LLParcel* parcel) : + mParcel(parcel), + mSelectedMultipleOwners(FALSE), + mWholeParcelSelected(FALSE), + mSelectedSelfCount(0), + mSelectedOtherCount(0), + mSelectedPublicCount(0) +{ +} + +LLParcelSelection::~LLParcelSelection() +{ +} + +BOOL LLParcelSelection::getMultipleOwners() const +{ + return mSelectedMultipleOwners; +} + + +BOOL LLParcelSelection::getWholeParcelSelected() const +{ + return mWholeParcelSelected; +} + + +S32 LLParcelSelection::getClaimableArea() const +{ + const S32 UNIT_AREA = S32( PARCEL_GRID_STEP_METERS * PARCEL_GRID_STEP_METERS ); + return mSelectedPublicCount * UNIT_AREA; +} + +bool LLParcelSelection::hasOthersSelected() const +{ + return mSelectedOtherCount != 0; +} + +LLParcelSelection* get_null_parcel_selection() +{ + static LLParcelSelectionHandle null_ptr = new LLParcelSelection(); + return null_ptr; +} diff --git a/linden/indra/newview/llviewerparcelmgr.h b/linden/indra/newview/llviewerparcelmgr.h index 781ba15..c970611 100644 --- a/linden/indra/newview/llviewerparcelmgr.h +++ b/linden/indra/newview/llviewerparcelmgr.h @@ -68,15 +68,56 @@ public: virtual void changed() = 0; }; +class LLParcelSelection : public LLRefCount +{ + friend class LLViewerParcelMgr; + +public: + LLParcelSelection(LLParcel* parcel); + LLParcelSelection(); + + ~LLParcelSelection(); + + // this can return NULL at any time, as parcel selection + // might have been invalidated. + LLParcel* getParcel() { return mParcel; } + + // Return the number of grid units that are owned by you within + // the selection (computed by server). + S32 getSelfCount() const { return mSelectedSelfCount; } + + // Returns area that will actually be claimed in meters squared. + S32 getClaimableArea() const; + bool hasOthersSelected() const; + + // Does the selection have multiple land owners in it? + BOOL getMultipleOwners() const; + + // Is the entire parcel selected, or just a part? + BOOL getWholeParcelSelected() const; + +protected: + void setParcel(LLParcel* parcel) { mParcel = parcel; } + +protected: + + LLParcel* mParcel; + BOOL mSelectedMultipleOwners; + BOOL mWholeParcelSelected; + S32 mSelectedSelfCount; + S32 mSelectedOtherCount; + S32 mSelectedPublicCount; +}; + +typedef LLHandle LLParcelSelectionHandle; + class LLViewerParcelMgr { + public: LLViewerParcelMgr(); ~LLViewerParcelMgr(); - void destroyGL(); - void restoreGL(); - BOOL selectionEmpty() const; F32 getSelectionWidth() const { return F32(mEastNorth.mdV[VX] - mWestSouth.mdV[VX]); } F32 getSelectionHeight() const { return F32(mEastNorth.mdV[VY] - mWestSouth.mdV[VY]); } @@ -87,16 +128,6 @@ public: void getPrimInfo(S32 &sw_max, S32 &sw_total, S32 &max, S32 &total, S32 &owner, S32 &group, S32 &other, S32& selected, F32 &parcel_object_bonus, S32 &other_clean); - // Does the selection have multiple land owners in it? - BOOL getMultipleOwners() const; - - // Is the entire parcel selected, or just a part? - BOOL getWholeParcelSelected() const; - - // Returns area that will actually be claimed in meters squared. - S32 getClaimableArea() const; - bool hasOthersSelected() const; - // Returns selected area S32 getSelectedArea() const; @@ -115,18 +146,19 @@ public: void selectCollisionParcel(); // Select the parcel at a specific point - void selectParcelAt(const LLVector3d& pos_global); + LLHandle selectParcelAt(const LLVector3d& pos_global); // Take the current rectangle select, and select the parcel contained // within it. - void selectParcelInRectangle(); + LLParcelSelectionHandle selectParcelInRectangle(); // Select a piece of land - void selectLand(const LLVector3d &corner1, const LLVector3d &corner2, + LLParcelSelectionHandle selectLand(const LLVector3d &corner1, const LLVector3d &corner2, BOOL snap_to_parcel); // Clear the selection, and stop drawing the highlight. void deselectLand(); + void deselectUnused(); void addObserver(LLParcelObserver* observer); void removeObserver(LLParcelObserver* observer); @@ -141,15 +173,23 @@ public: BOOL canHearSound(const LLVector3d &pos_global) const; - LLParcel *getSelectedParcel() const; + // Returns a reference counted pointer to current parcel selection. + // Selection does not change to reflect new selections made by user + // Use this when implementing a task UI that refers to a specific + // selection. + LLParcelSelectionHandle getParcelSelection() const; + + // Returns a reference counted pointer to current parcel selection. + // Pointer tracks whatever the user has currently selected. + // Use this when implementing an inspector UI. + // http://en.wikipedia.org/wiki/Inspector_window + LLParcelSelectionHandle getFloatingParcelSelection() const; + + //LLParcel *getParcelSelection() const; LLParcel *getAgentParcel() const; BOOL inAgentParcel(const LLVector3d &pos_global) const; - // Return the number of grid units that are owned by you within - // the selection (computed by server). - S32 getSelfCount() const { return mSelectedSelfCount; } - // Returns a pointer only when it has valid data. LLParcel* getHoverParcel() const; @@ -191,7 +231,7 @@ public: // containing the southwest corner of the selection. // If want_reply_to_update, simulator will send back a ParcelProperties // message. - void sendParcelPropertiesUpdate(LLParcel* parcel, BOOL want_reply_to_update); + void sendParcelPropertiesUpdate(LLParcel* parcel); // Takes an Access List flag, like AL_ACCESS or AL_BAN void sendParcelAccessListUpdate(U32 which); @@ -284,26 +324,23 @@ protected: //void finishClaim(BOOL user_to_user_sale, U32 join); private: - BOOL mSelected; - BOOL mSelectedMultipleOwners; - BOOL mWholeParcelSelected; - S32 mSelectedSelfCount; - S32 mSelectedOtherCount; - S32 mSelectedPublicCount; + BOOL mSelected; - LLParcel *mParcel; // selected parcel info - S32 mRequestResult; // result of last parcel request - LLVector3d mWestSouth; - LLVector3d mEastNorth; - F32 mSelectedDwell; + LLParcel* mCurrentParcel; // selected parcel info + LLParcelSelectionHandle mCurrentParcelSelection; + LLParcelSelectionHandle mFloatingParcelSelection; + S32 mRequestResult; // result of last parcel request + LLVector3d mWestSouth; + LLVector3d mEastNorth; + F32 mSelectedDwell; - LLParcel *mAgentParcel; // info for parcel agent is in - S32 mAgentParcelSequenceID; // incrementing counter to suppress out of order updates + LLParcel *mAgentParcel; // info for parcel agent is in + S32 mAgentParcelSequenceID; // incrementing counter to suppress out of order updates - LLParcel* mHoverParcel; - S32 mHoverRequestResult; - LLVector3d mHoverWestSouth; - LLVector3d mHoverEastNorth; + LLParcel* mHoverParcel; + S32 mHoverRequestResult; + LLVector3d mHoverWestSouth; + LLVector3d mHoverEastNorth; LLDynamicArray mObservers; @@ -312,30 +349,30 @@ private: // we can represent edges of the grid. // WEST_MASK = draw west edge // SOUTH_MASK = draw south edge - S32 mParcelsPerEdge; - U8* mHighlightSegments; - U8* mAgentParcelOverlay; + S32 mParcelsPerEdge; + U8* mHighlightSegments; + U8* mAgentParcelOverlay; // Raw data buffer for unpacking parcel overlay chunks // Size = parcels_per_edge * parcels_per_edge / parcel_overlay_chunks - static U8* sPackedOverlay; + static U8* sPackedOverlay; // Watch for pending collisions with a parcel you can't access. // If it's coming, draw the parcel's boundaries. - LLParcel* mCollisionParcel; - U8* mCollisionSegments; - BOOL mRenderCollision; - BOOL mRenderSelection; - S32 mCollisionBanned; - LLFrameTimer mCollisionTimer; - LLUUID mBlockedImageID; - LLUUID mPassImageID; - LLPointer mBlockedImage; - LLPointer mPassImage; + LLParcel* mCollisionParcel; + U8* mCollisionSegments; + BOOL mRenderCollision; + BOOL mRenderSelection; + S32 mCollisionBanned; + LLFrameTimer mCollisionTimer; + LLUUID mBlockedImageID; + LLUUID mPassImageID; + LLPointer mBlockedImage; + LLPointer mPassImage; // Media - S32 mMediaParcelId; - U64 mMediaRegionId; + S32 mMediaParcelId; + U64 mMediaRegionId; }; extern LLViewerParcelMgr *gParcelMgr; diff --git a/linden/indra/newview/llviewerparceloverlay.cpp b/linden/indra/newview/llviewerparceloverlay.cpp index 91159f0..36a4449 100644 --- a/linden/indra/newview/llviewerparceloverlay.cpp +++ b/linden/indra/newview/llviewerparceloverlay.cpp @@ -293,7 +293,7 @@ void LLViewerParcelOverlay::uncompressLandOverlay(S32 chunk, U8 *packed_overlay) S32 size = mParcelGridsPerEdge * mParcelGridsPerEdge; S32 chunk_size = size / PARCEL_OVERLAY_CHUNKS; - memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size); + memcpy(mOwnership + chunk*chunk_size, packed_overlay, chunk_size); /*Flawfinder: ignore*/ // Force property lines and overlay texture to update setDirty(); @@ -780,27 +780,6 @@ S32 LLViewerParcelOverlay::renderPropertyLines () const S32 GRID_STEP = S32( PARCEL_GRID_STEP_METERS ); const S32 vertex_per_edge = 3 + 2 * (GRID_STEP-1) + 3; - /* JC - Don't do this. Unbinding AGP stalls the draw process, - dropping frame rate. Not unbinding AGP causes random crashes - on nVidia cards due to binding non-AGP arrays. - - gPipeline.unbindAGP(); - glEnableClientState(GL_VERTEX_ARRAY); - glEnableClientState(GL_COLOR_ARRAY); - glVertexPointer(3, GL_FLOAT, 0, mVertexArray ); - glColorPointer( 4, GL_UNSIGNED_BYTE, 0, mColorArray ); - - S32 i; - for (i = 0; i < mVertexCount; i += vertex_per_edge) - { - // Each edge is several vertices - glDrawArrays(GL_LINE_STRIP, i, vertex_per_edge); - } - - glDisableClientState(GL_COLOR_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); - */ - // Stomp the camera into two dimensions LLVector3 camera_region = mRegion->getPosRegionFromGlobal( gAgent.getCameraPositionGlobal() ); diff --git a/linden/indra/newview/llviewerpartsim.cpp b/linden/indra/newview/llviewerpartsim.cpp index be2c90f..2658e67 100644 --- a/linden/indra/newview/llviewerpartsim.cpp +++ b/linden/indra/newview/llviewerpartsim.cpp @@ -32,6 +32,7 @@ #include "llviewercontrol.h" #include "llagent.h" +#include "llviewercamera.h" #include "llviewerobjectlist.h" #include "llviewerpartsource.h" #include "llviewerregion.h" @@ -41,7 +42,7 @@ const S32 MAX_PART_COUNT = 4096; -const F32 PART_SIM_BOX_SIDE = 32.f; +const F32 PART_SIM_BOX_SIDE = 16.f; const F32 PART_SIM_BOX_OFFSET = 0.5f*PART_SIM_BOX_SIDE; const F32 PART_SIM_BOX_RAD = 0.5f*F_SQRT3*PART_SIM_BOX_SIDE; @@ -52,18 +53,28 @@ S32 LLViewerPartSim::sParticleCount = 0; U32 LLViewerPart::sNextPartID = 1; +F32 calc_desired_size(LLVector3 pos, LLVector2 scale) +{ + F32 desired_size = (pos-gCamera->getOrigin()).magVec(); + desired_size /= 4; + return llclamp(desired_size, scale.magVec()*0.5f, PART_SIM_BOX_SIDE*2); +} + LLViewerPart::LLViewerPart() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mPartSourcep = NULL; } LLViewerPart::~LLViewerPart() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mPartSourcep = NULL; } LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mPartID = part.mPartID; mFlags = part.mFlags; mMaxAge = part.mMaxAge; @@ -93,6 +104,7 @@ LLViewerPart &LLViewerPart::operator=(const LLViewerPart &part) void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVPCallback cb) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mPartID = LLViewerPart::sNextPartID; LLViewerPart::sNextPartID++; mFlags = 0x00f; @@ -115,8 +127,13 @@ void LLViewerPart::init(LLViewerPartSource *sourcep, LLViewerImage *imagep, LLVP LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 box_side) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mVOPartGroupp = NULL; + mUniformParticles = TRUE; + mRegionp = gWorldPointer->getRegionFromPosAgent(center_agent); + llassert_always(center_agent.isFinite()); + if (!mRegionp) { //llwarns << "No region at position, using agent region!" << llendl; @@ -125,28 +142,39 @@ LLViewerPartGroup::LLViewerPartGroup(const LLVector3 ¢er_agent, const F32 bo mCenterAgent = center_agent; mBoxRadius = F_SQRT3*box_side*0.5f; - LLVector3 rad_vec(box_side*0.5f, box_side*0.5f, box_side*0.5f); - rad_vec += LLVector3(0.001f, 0.001f, 0.001f); - mMinObjPos = mCenterAgent - rad_vec; - mMaxObjPos = mCenterAgent + rad_vec; + mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion()); + mVOPartGroupp->setViewerPartGroup(this); + mVOPartGroupp->setPositionAgent(getCenterAgent()); + F32 scale = box_side * 0.5f; + mVOPartGroupp->setScale(LLVector3(scale,scale,scale)); + gPipeline.addObject(mVOPartGroupp); + + LLSpatialGroup* group = mVOPartGroupp->mDrawable->getSpatialGroup(); + + LLVector3 center(group->mOctreeNode->getCenter()); + LLVector3 size(group->mOctreeNode->getSize()); + size += LLVector3(0.01f, 0.01f, 0.01f); + mMinObjPos = center - size; + mMaxObjPos = center + size; + + static U32 id_seed = 0; + mID = ++id_seed; } LLViewerPartGroup::~LLViewerPartGroup() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); cleanup(); - S32 count = mParticles.count(); - S32 i; - - for (i = 0; i < count; i++) - { - mParticles[i].mPartSourcep = NULL; - } - mParticles.reset(); + + S32 count = (S32) mParticles.size(); + mParticles.clear(); + LLViewerPartSim::decPartCount(count); } void LLViewerPartGroup::cleanup() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (mVOPartGroupp) { if (!mVOPartGroupp->isDead()) @@ -157,8 +185,9 @@ void LLViewerPartGroup::cleanup() } } -BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos) +BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos, const F32 desired_size) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if ((pos.mV[VX] < mMinObjPos.mV[VX]) || (pos.mV[VY] < mMinObjPos.mV[VY]) || (pos.mV[VZ] < mMinObjPos.mV[VZ])) @@ -173,29 +202,33 @@ BOOL LLViewerPartGroup::posInGroup(const LLVector3 &pos) return FALSE; } + if (desired_size > 0 && + (desired_size < mBoxRadius*0.5f || + desired_size > mBoxRadius*2.f)) + { + return FALSE; + } + return TRUE; } -BOOL LLViewerPartGroup::addPart(LLViewerPart &part) +BOOL LLViewerPartGroup::addPart(LLViewerPart* part, F32 desired_size) { - if (!posInGroup(part.mPosAgent) || - (mVOPartGroupp.notNull() && (part.mImagep != mVOPartGroupp->getTEImage(0)))) + LLMemType mt(LLMemType::MTYPE_PARTICLES); + BOOL uniform_part = part->mScale.mV[0] == part->mScale.mV[1] && + !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK); + + if (!posInGroup(part->mPosAgent, desired_size) || + (mUniformParticles && !uniform_part) || + (!mUniformParticles && uniform_part)) { return FALSE; } - if (!mVOPartGroupp) - { - mVOPartGroupp = (LLVOPartGroup *)gObjectList.createObjectViewer(LLViewerObject::LL_VO_PART_GROUP, getRegion()); - mVOPartGroupp->setViewerPartGroup(this); - mVOPartGroupp->setPositionAgent(getCenterAgent()); - mVOPartGroupp->setScale(LLVector3(PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE, PART_SIM_BOX_SIDE)); - mVOPartGroupp->setTEImage(0, part.mImagep); - gPipeline.addObject(mVOPartGroupp); - } + gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); - mParticles.put(part); + mParticles.push_back(part); LLViewerPartSim::incPartCount(1); return TRUE; } @@ -203,33 +236,29 @@ BOOL LLViewerPartGroup::addPart(LLViewerPart &part) void LLViewerPartGroup::removePart(const S32 part_num) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); // Remove the entry for the particle we just deleted. - LLPointer ps = mParticles[mParticles.count() - 1].mPartSourcep; - - mParticles[mParticles.count() - 1].mPartSourcep = NULL; - mParticles.remove(part_num); - if (part_num < mParticles.count()) + mParticles.erase(mParticles.begin() + part_num); + if (mVOPartGroupp.notNull()) { - mParticles[part_num].mPartSourcep = ps; + gPipeline.markRebuild(mVOPartGroupp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); } - LLViewerPartSim::decPartCount(1); } - void LLViewerPartGroup::updateParticles(const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); S32 i, count; - - + LLVector3 gravity(0.f, 0.f, -9.8f); LLViewerRegion *regionp = getRegion(); - count = mParticles.count(); + count = (S32) mParticles.size(); for (i = 0; i < count; i++) { LLVector3 a(0.f, 0.f, 0.f); - LLViewerPart &part = mParticles[i]; + LLViewerPart& part = *((LLViewerPart*) mParticles[i]); // Update current time const F32 cur_time = part.mLastUpdateTime + dt; @@ -271,8 +300,6 @@ void LLViewerPartGroup::updateParticles(const F32 dt) part.mVelocity *= (1.f - step); part.mVelocity += step*delta_pos; - //part.mPosAgent *= 1.f - to_target_frac; - //part.mPosAgent += to_target_frac*part.mPartSourcep->mTargetPosAgent; } @@ -341,18 +368,22 @@ void LLViewerPartGroup::updateParticles(const F32 dt) i--; count--; } - else if (!posInGroup(part.mPosAgent)) + else { - // Transfer particles between groups - gWorldPointer->mPartSim.put(part); - removePart(i); - i--; - count--; + F32 desired_size = calc_desired_size(part.mPosAgent, part.mScale); + if (!posInGroup(part.mPosAgent, desired_size)) + { + // Transfer particles between groups + gWorldPointer->mPartSim.put(&part); + removePart(i); + i--; + count--; + } } } // Kill the viewer object if this particle group is empty - if (!mParticles.count()) + if (mParticles.empty()) { gObjectList.killObject(mVOPartGroupp); mVOPartGroupp = NULL; @@ -362,15 +393,16 @@ void LLViewerPartGroup::updateParticles(const F32 dt) void LLViewerPartGroup::shift(const LLVector3 &offset) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mCenterAgent += offset; mMinObjPos += offset; mMaxObjPos += offset; - S32 count = mParticles.count(); + S32 count = (S32) mParticles.size(); S32 i; for (i = 0; i < count; i++) { - mParticles[i].mPosAgent += offset; + mParticles[i]->mPosAgent += offset; } } @@ -384,34 +416,34 @@ void LLViewerPartGroup::shift(const LLVector3 &offset) LLViewerPartSim::LLViewerPartSim() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); sMaxParticleCount = gSavedSettings.getS32("RenderMaxPartCount"); + static U32 id_seed = 0; + mID = ++id_seed; } LLViewerPartSim::~LLViewerPartSim() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); S32 i; S32 count; // Kill all of the groups (and particles) - count = mViewerPartGroups.count(); + count = (S32) mViewerPartGroups.size(); for (i = 0; i < count; i++) { delete mViewerPartGroups[i]; } - mViewerPartGroups.reset(); + mViewerPartGroups.clear(); // Kill all of the sources - count = mViewerPartSources.count(); - for (i = 0; i < count; i++) - { - mViewerPartSources[i] = NULL; - } - mViewerPartSources.reset(); + mViewerPartSources.clear(); } BOOL LLViewerPartSim::shouldAddPart() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (sParticleCount > 0.75f*sMaxParticleCount) { @@ -432,33 +464,35 @@ BOOL LLViewerPartSim::shouldAddPart() return TRUE; } -void LLViewerPartSim::addPart(LLViewerPart &part) +void LLViewerPartSim::addPart(LLViewerPart* part) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (sParticleCount < MAX_PART_COUNT) { put(part); } } -LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part) + +LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart* part) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); const F32 MAX_MAG = 1000000.f*1000000.f; // 1 million - if (part.mPosAgent.magVecSquared() > MAX_MAG) + if (part->mPosAgent.magVecSquared() > MAX_MAG || !part->mPosAgent.isFinite()) { -#ifndef LL_RELEASE_FOR_DOWNLOAD +#if !LL_RELEASE_FOR_DOWNLOAD llwarns << "LLViewerPartSim::put Part out of range!" << llendl; - llwarns << part.mPosAgent << llendl; + llwarns << part->mPosAgent << llendl; #endif return NULL; } + + F32 desired_size = calc_desired_size(part->mPosAgent, part->mScale); - S32 i; - S32 count; - - count = mViewerPartGroups.count(); - for (i = 0; i < count; i++) + S32 count = (S32) mViewerPartGroups.size(); + for (S32 i = 0; i < count; i++) { - if (mViewerPartGroups[i]->addPart(part)) + if (mViewerPartGroups[i]->addPart(part, desired_size)) { // We found a spatial group that we fit into, add us and exit return mViewerPartGroups[i]; @@ -467,43 +501,27 @@ LLViewerPartGroup *LLViewerPartSim::put(LLViewerPart &part) // Hmm, we didn't fit in any of the existing spatial groups // Create a new one... - LLViewerPartGroup *groupp = createViewerPartGroup(part.mPosAgent); + llassert_always(part->mPosAgent.isFinite()); + LLViewerPartGroup *groupp = createViewerPartGroup(part->mPosAgent, desired_size); + groupp->mUniformParticles = (part->mScale.mV[0] == part->mScale.mV[1] && + !(part->mFlags & LLPartData::LL_PART_FOLLOW_VELOCITY_MASK)); if (!groupp->addPart(part)) { llwarns << "LLViewerPartSim::put - Particle didn't go into its box!" << llendl; llinfos << groupp->getCenterAgent() << llendl; - llinfos << part.mPosAgent << llendl; + llinfos << part->mPosAgent << llendl; return NULL; } return groupp; } -LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent) +LLViewerPartGroup *LLViewerPartSim::createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size) { - F32 x_origin = ((S32)(pos_agent.mV[VX]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE; - if (x_origin > pos_agent.mV[VX]) - { - x_origin -= PART_SIM_BOX_SIDE; - } - - F32 y_origin = ((S32)(pos_agent.mV[VY]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE; - if (y_origin > pos_agent.mV[VY]) - { - y_origin -= PART_SIM_BOX_SIDE; - } - - F32 z_origin = ((S32)(pos_agent.mV[VZ]/PART_SIM_BOX_SIDE))*PART_SIM_BOX_SIDE; - if (z_origin > pos_agent.mV[VZ]) - { - z_origin -= PART_SIM_BOX_SIDE; - } - - LLVector3 group_center(x_origin + PART_SIM_BOX_OFFSET, - y_origin + PART_SIM_BOX_OFFSET, - z_origin + PART_SIM_BOX_OFFSET); - - LLViewerPartGroup *groupp = new LLViewerPartGroup(group_center, PART_SIM_BOX_SIDE); - mViewerPartGroups.put(groupp); + LLMemType mt(LLMemType::MTYPE_PARTICLES); + //find a box that has a center position divisible by PART_SIM_BOX_SIDE that encompasses + //pos_agent + LLViewerPartGroup *groupp = new LLViewerPartGroup(pos_agent, desired_size); + mViewerPartGroups.push_back(groupp); return groupp; } @@ -513,7 +531,7 @@ void LLViewerPartSim::shift(const LLVector3 &offset) S32 i; S32 count; - count = mViewerPartSources.count(); + count = (S32) mViewerPartSources.size(); for (i = 0; i < count; i++) { mViewerPartSources[i]->mPosAgent += offset; @@ -521,13 +539,20 @@ void LLViewerPartSim::shift(const LLVector3 &offset) mViewerPartSources[i]->mLastUpdatePosAgent += offset; } - count = mViewerPartGroups.count(); + count = (S32) mViewerPartGroups.size(); for (i = 0; i < count; i++) { mViewerPartGroups[i]->shift(offset); } } +S32 dist_rate_func(F32 distance) +{ + //S32 dist = (S32) sqrtf(distance); + //dist /= 2; + //return llmax(dist,1); + return 1; +} void LLViewerPartSim::updateSimulation() { @@ -542,13 +567,15 @@ void LLViewerPartSim::updateSimulation() return; } + LLFastTimer ftm(LLFastTimer::FTM_SIMULATE_PARTICLES); + // Start at a random particle system so the same // particle system doesn't always get first pick at the // particles. Theoretically we'd want to do this in distance // order or something, but sorting particle sources will be a big // pain. S32 i; - S32 count = mViewerPartSources.count(); + S32 count = (S32) mViewerPartSources.size(); S32 start = (S32)ll_frand((F32)count); S32 dir = 1; if (ll_frand() > 0.5f) @@ -570,12 +597,24 @@ void LLViewerPartSim::updateSimulation() if (!mViewerPartSources[i]->isDead()) { - mViewerPartSources[i]->update(dt); + LLViewerObject* source_object = mViewerPartSources[i]->mSourceObjectp; + if (source_object && source_object->mDrawable.notNull()) + { + S32 dist = dist_rate_func(source_object->mDrawable->mDistanceWRTCamera); + if ((LLDrawable::getCurrentFrame()+mViewerPartSources[i]->mID)%dist == 0) + { + mViewerPartSources[i]->update(dt*dist); + } + } + else + { + mViewerPartSources[i]->update(dt); + } } if (mViewerPartSources[i]->isDead()) { - mViewerPartSources.remove(i); + mViewerPartSources.erase(mViewerPartSources.begin() + i); count--; } else @@ -586,16 +625,36 @@ void LLViewerPartSim::updateSimulation() } - count = mViewerPartGroups.count(); + count = (S32) mViewerPartGroups.size(); for (i = 0; i < count; i++) { - mViewerPartGroups[i]->updateParticles(dt); - if (!mViewerPartGroups[i]->getCount()) + LLViewerObject* vobj = mViewerPartGroups[i]->mVOPartGroupp; + + S32 dist = vobj && !vobj->mDrawable->isState(LLDrawable::IN_REBUILD_Q1) ? + dist_rate_func(vobj->mDrawable->mDistanceWRTCamera) : 1; + if (vobj) { - delete mViewerPartGroups[i]; - mViewerPartGroups.remove(i); - i--; - count--; + LLSpatialGroup* group = vobj->mDrawable->getSpatialGroup(); + if (group && !group->isVisible()) // && !group->isState(LLSpatialGroup::OBJECT_DIRTY)) + { + dist *= 8; + } + } + + if ((LLDrawable::getCurrentFrame()+mViewerPartGroups[i]->mID)%dist == 0) + { + if (vobj) + { + gPipeline.markRebuild(vobj->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + mViewerPartGroups[i]->updateParticles(dt*dist); + if (!mViewerPartGroups[i]->getCount()) + { + delete mViewerPartGroups[i]; + mViewerPartGroups.erase(mViewerPartGroups.begin() + i); + i--; + count--; + } } } //llinfos << "Particles: " << sParticleCount << llendl; @@ -604,42 +663,40 @@ void LLViewerPartSim::updateSimulation() void LLViewerPartSim::addPartSource(LLViewerPartSource *sourcep) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (!sourcep) { llwarns << "Null part source!" << llendl; return; } - mViewerPartSources.put(sourcep); + mViewerPartSources.push_back(sourcep); } void LLViewerPartSim::cleanupRegion(LLViewerRegion *regionp) { - S32 i, count; - count = mViewerPartGroups.count(); - for (i = 0; i < count; i++) + LLMemType mt(LLMemType::MTYPE_PARTICLES); + for (group_list_t::iterator i = mViewerPartGroups.begin(); i != mViewerPartGroups.end(); ) { - if (mViewerPartGroups[i]->getRegion() == regionp) + group_list_t::iterator iter = i++; + + if ((*iter)->getRegion() == regionp) { - delete mViewerPartGroups[i]; - mViewerPartGroups.remove(i); - i--; - count--; + i = mViewerPartGroups.erase(iter); } } } void LLViewerPartSim::cleanMutedParticles(const LLUUID& task_id) { - S32 i; - S32 count = mViewerPartSources.count(); - for (i = 0; i < count; ++i) + LLMemType mt(LLMemType::MTYPE_PARTICLES); + for (source_list_t::iterator i = mViewerPartSources.begin(); i != mViewerPartSources.end(); ) { - if (mViewerPartSources[i]->getOwnerUUID() == task_id) + source_list_t::iterator iter = i++; + + if ((*iter)->getOwnerUUID() == task_id) { - mViewerPartSources.remove(i); - i--; - count--; + i = mViewerPartSources.erase(iter); } } } diff --git a/linden/indra/newview/llviewerpartsim.h b/linden/indra/newview/llviewerpartsim.h index 7983838..c1ef43b 100644 --- a/linden/indra/newview/llviewerpartsim.h +++ b/linden/indra/newview/llviewerpartsim.h @@ -50,7 +50,7 @@ typedef void (*LLVPCallback)(LLViewerPart &part, const F32 dt); // -class LLViewerPart : public LLPartData +class LLViewerPart : public LLPartData, public LLRefCount { public: LLViewerPart(); @@ -90,19 +90,26 @@ public: void cleanup(); - BOOL addPart(LLViewerPart &part); + BOOL addPart(LLViewerPart* part, const F32 desired_size = -1.f); void updateParticles(const F32 dt); - BOOL posInGroup(const LLVector3 &pos); + BOOL posInGroup(const LLVector3 &pos, const F32 desired_size = -1.f); void shift(const LLVector3 &offset); - LLDynamicArray mParticles; + typedef std::vector > part_list_t; + part_list_t mParticles; const LLVector3 &getCenterAgent() const { return mCenterAgent; } - S32 getCount() const { return mParticles.count(); } + S32 getCount() const { return (S32) mParticles.size(); } LLViewerRegion *getRegion() const { return mRegionp; } + + LLPointer mVOPartGroupp; + + BOOL mUniformParticles; + U32 mID; + protected: void removePart(const S32 part_num); @@ -112,11 +119,9 @@ protected: LLVector3 mMinObjPos; LLVector3 mMaxObjPos; - LLPointer mVOPartGroupp; LLViewerRegion *mRegionp; }; - class LLViewerPartSim { public: @@ -132,7 +137,7 @@ public: void cleanupRegion(LLViewerRegion *regionp); BOOL shouldAddPart(); // Just decides whether this particle should be added or not (for particle count capping) - void addPart(LLViewerPart &part); + void addPart(LLViewerPart* part); void cleanMutedParticles(const LLUUID& task_id); friend class LLViewerPartGroup; @@ -144,15 +149,18 @@ public: static void incPartCount(const S32 count) { sParticleCount += count; } static void decPartCount(const S32 count) { sParticleCount -= count; } + U32 mID; + protected: - LLViewerPartGroup *createViewerPartGroup(const LLVector3 &pos_agent); - LLViewerPartGroup *put(LLViewerPart &part); + LLViewerPartGroup *createViewerPartGroup(const LLVector3 &pos_agent, const F32 desired_size); + LLViewerPartGroup *put(LLViewerPart* part); protected: - LLDynamicArray mViewerPartGroups; - LLDynamicArrayPtr > mViewerPartSources; + typedef std::vector group_list_t; + typedef std::vector > source_list_t; + group_list_t mViewerPartGroups; + source_list_t mViewerPartSources; LLFrameTimer mSimulationTimer; - static S32 sMaxParticleCount; static S32 sParticleCount; }; diff --git a/linden/indra/newview/llviewerpartsource.cpp b/linden/indra/newview/llviewerpartsource.cpp index 39869e2..33e6df4 100644 --- a/linden/indra/newview/llviewerpartsource.cpp +++ b/linden/indra/newview/llviewerpartsource.cpp @@ -37,6 +37,7 @@ #include "llviewerobjectlist.h" #include "llvoavatar.h" #include "llworld.h" +#include "pipeline.h" LLViewerPartSource::LLViewerPartSource(const U32 type) : mType(type), @@ -45,6 +46,8 @@ LLViewerPartSource::LLViewerPartSource(const U32 type) : mLastUpdateTime = 0.f; mLastPartTime = 0.f; mIsDead = FALSE; + static U32 id_seed = 0; + mID = ++id_seed; } void LLViewerPartSource::setDead() @@ -67,6 +70,7 @@ void LLViewerPartSource::update(const F32 dt) LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) : LLViewerPartSource(LL_PART_SOURCE_SCRIPT) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); llassert(source_objp); mSourceObjectp = source_objp; mPosAgent = mSourceObjectp->getPositionAgent(); @@ -80,18 +84,18 @@ LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) void LLViewerPartSourceScript::setDead() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mIsDead = TRUE; mSourceObjectp = NULL; mTargetObjectp = NULL; } - - void LLViewerPartSourceScript::update(const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); F32 old_update_time = mLastUpdateTime; mLastUpdateTime += dt; - + F32 dt_update = mLastUpdateTime - mLastPartTime; // Update this for objects which have the follow flag set... @@ -142,6 +146,17 @@ void LLViewerPartSourceScript::update(const F32 dt) return; } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES)) + { + if (mSourceObjectp.notNull()) + { + std::ostringstream ostr; + ostr << mPartSysData; + mSourceObjectp->setDebugText(ostr.str()); + } + } + BOOL first_run = FALSE; if (old_update_time <= 0.f) { @@ -153,21 +168,7 @@ void LLViewerPartSourceScript::update(const F32 dt) while ((dt_update > mPartSysData.mBurstRate) || first_run) { first_run = FALSE; - LLViewerPart part; - - part.init(this, mImagep, NULL); - part.mFlags = mPartSysData.mPartData.mFlags; - part.mMaxAge = mPartSysData.mPartData.mMaxAge; - part.mStartColor = mPartSysData.mPartData.mStartColor; - part.mEndColor = mPartSysData.mPartData.mEndColor; - part.mColor = part.mStartColor; - - part.mStartScale = mPartSysData.mPartData.mStartScale; - part.mEndScale = mPartSysData.mPartData.mEndScale; - part.mScale = part.mStartScale; - - part.mAccel = mPartSysData.mPartAccel; - + // Update the rotation of the particle source by the angular velocity // First check to see if there is still an angular velocity. F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec(); @@ -200,14 +201,29 @@ void LLViewerPartSourceScript::update(const F32 dt) continue; } + LLPointer part = new LLViewerPart(); + + part->init(this, mImagep, NULL); + part->mFlags = mPartSysData.mPartData.mFlags; + part->mMaxAge = mPartSysData.mPartData.mMaxAge; + part->mStartColor = mPartSysData.mPartData.mStartColor; + part->mEndColor = mPartSysData.mPartData.mEndColor; + part->mColor = part->mStartColor; + + part->mStartScale = mPartSysData.mPartData.mStartScale; + part->mEndScale = mPartSysData.mPartData.mEndScale; + part->mScale = part->mStartScale; + + part->mAccel = mPartSysData.mPartAccel; + if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP) { - part.mPosAgent = mPosAgent; - part.mVelocity.setVec(0.f, 0.f, 0.f); + part->mPosAgent = mPosAgent; + part->mVelocity.setVec(0.f, 0.f, 0.f); } else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE) { - part.mPosAgent = mPosAgent; + part->mPosAgent = mPosAgent; LLVector3 part_dir_vector; F32 mvs; @@ -221,19 +237,18 @@ void LLViewerPartSourceScript::update(const F32 dt) while ((mvs > 1.f) || (mvs < 0.01f)); part_dir_vector.normVec(); - part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; - part.mVelocity = part_dir_vector; + part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; + part->mVelocity = part_dir_vector; F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); - part.mVelocity *= speed; + part->mVelocity *= speed; } else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE) - { - part.mPosAgent = mPosAgent; + { + part->mPosAgent = mPosAgent; // original implemenetation for part_dir_vector was just: LLVector3 part_dir_vector(0.0, 0.0, 1.0); - // params from the script... // outer = outer cone angle // inner = inner cone angle @@ -243,13 +258,11 @@ void LLViewerPartSourceScript::update(const F32 dt) // generate a random angle within the given space... F32 angle = innerAngle + ll_frand(outerAngle - innerAngle); - // split which side it will go on randomly... if (ll_frand() < 0.5) { angle = -angle; } - // Both patterns rotate around the x-axis first: part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0); @@ -258,31 +271,32 @@ void LLViewerPartSourceScript::update(const F32 dt) { part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0); } - + // Only apply this rotation if using the deprecated angles. if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE)) { // Deprecated... part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0); } - + if (mSourceObjectp) { part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation(); } + part_dir_vector = part_dir_vector * mRotation; + + part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; - part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; - - part.mVelocity = part_dir_vector; + part->mVelocity = part_dir_vector; F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); - part.mVelocity *= speed; + part->mVelocity *= speed; } else { - part.mPosAgent = mPosAgent; - part.mVelocity.setVec(0.f, 0.f, 0.f); + part->mPosAgent = mPosAgent; + part->mVelocity.setVec(0.f, 0.f, 0.f); //llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl; } @@ -297,6 +311,7 @@ void LLViewerPartSourceScript::update(const F32 dt) // static LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, const S32 block_num) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (!pssp) { if (LLPartSysData::isNullPS(block_num)) @@ -338,6 +353,7 @@ LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *so LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, LLDataPacker &dp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (!pssp) { LLViewerPartSourceScript *new_pssp = new LLViewerPartSourceScript(source_objp); @@ -369,11 +385,13 @@ LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *so void LLViewerPartSourceScript::setImage(LLViewerImage *imagep) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mImagep = imagep; } void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mTargetObjectp = objp; } @@ -389,6 +407,7 @@ LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) : void LLViewerPartSourceSpiral::setDead() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mIsDead = TRUE; mSourceObjectp = NULL; } @@ -396,6 +415,7 @@ void LLViewerPartSourceSpiral::setDead() void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); F32 frac = part.mLastUpdateTime/part.mMaxAge; LLVector3 center_pos; @@ -420,6 +440,7 @@ void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt) void LLViewerPartSourceSpiral::update(const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (!mImagep) { LLUUID id; @@ -448,18 +469,18 @@ void LLViewerPartSourceSpiral::update(const F32 dt) { mPosAgent = mSourceObjectp->getRenderPosition(); } - LLViewerPart part; - part.init(this, mImagep, updatePart); - part.mStartColor = mColor; - part.mEndColor = mColor; - part.mEndColor.mV[3] = 0.f; - part.mPosAgent = mPosAgent; - part.mMaxAge = 1.f; - part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; - part.mLastUpdateTime = 0.f; - part.mScale.mV[0] = 0.25f; - part.mScale.mV[1] = 0.25f; - part.mParameter = ll_frand(F_TWO_PI); + LLPointer part = new LLViewerPart(); + part->init(this, mImagep, updatePart); + part->mStartColor = mColor; + part->mEndColor = mColor; + part->mEndColor.mV[3] = 0.f; + part->mPosAgent = mPosAgent; + part->mMaxAge = 1.f; + part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; + part->mLastUpdateTime = 0.f; + part->mScale.mV[0] = 0.25f; + part->mScale.mV[1] = 0.25f; + part->mParameter = ll_frand(F_TWO_PI); gWorldPointer->mPartSim.addPart(part); } @@ -467,6 +488,7 @@ void LLViewerPartSourceSpiral::update(const F32 dt) void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mSourceObjectp = objp; } @@ -490,6 +512,7 @@ LLViewerPartSourceBeam::~LLViewerPartSourceBeam() void LLViewerPartSourceBeam::setDead() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mIsDead = TRUE; mSourceObjectp = NULL; mTargetObjectp = NULL; @@ -503,6 +526,7 @@ void LLViewerPartSourceBeam::setColor(const LLColor4 &color) void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); F32 frac = part.mLastUpdateTime/part.mMaxAge; LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep; @@ -547,7 +571,7 @@ void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt) void LLViewerPartSourceBeam::update(const F32 dt) { - + LLMemType mt(LLMemType::MTYPE_PARTICLES); const F32 RATE = 0.025f; mLastUpdateTime += dt; @@ -595,25 +619,25 @@ void LLViewerPartSourceBeam::update(const F32 dt) mImagep = gImageList.getImage(id); } - LLViewerPart part; - part.init(this, mImagep, NULL); + LLPointer part = new LLViewerPart(); + part->init(this, mImagep, NULL); - part.mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | + part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | LLPartData::LL_PART_INTERP_SCALE_MASK | LLPartData::LL_PART_TARGET_POS_MASK | LLPartData::LL_PART_FOLLOW_VELOCITY_MASK; - part.mMaxAge = 0.5f; - part.mStartColor = mColor; - part.mEndColor = part.mStartColor; - part.mEndColor.mV[3] = 0.4f; - part.mColor = part.mStartColor; + part->mMaxAge = 0.5f; + part->mStartColor = mColor; + part->mEndColor = part->mStartColor; + part->mEndColor.mV[3] = 0.4f; + part->mColor = part->mStartColor; - part.mStartScale = LLVector2(0.1f, 0.1f); - part.mEndScale = LLVector2(0.1f, 0.1f); - part.mScale = part.mStartScale; + part->mStartScale = LLVector2(0.1f, 0.1f); + part->mEndScale = LLVector2(0.1f, 0.1f); + part->mScale = part->mStartScale; - part.mPosAgent = mPosAgent; - part.mVelocity = mTargetPosAgent - mPosAgent; + part->mPosAgent = mPosAgent; + part->mVelocity = mTargetPosAgent - mPosAgent; gWorldPointer->mPartSim.addPart(part); } @@ -621,11 +645,13 @@ void LLViewerPartSourceBeam::update(const F32 dt) void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mSourceObjectp = objp; } void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mTargetObjectp = objp; } @@ -640,6 +666,7 @@ LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) : void LLViewerPartSourceChat::setDead() { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mIsDead = TRUE; mSourceObjectp = NULL; } @@ -647,6 +674,7 @@ void LLViewerPartSourceChat::setDead() void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); F32 frac = part.mLastUpdateTime/part.mMaxAge; LLVector3 center_pos; @@ -671,6 +699,7 @@ void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt) void LLViewerPartSourceChat::update(const F32 dt) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); if (!mImagep) { LLUUID id; @@ -709,18 +738,18 @@ void LLViewerPartSourceChat::update(const F32 dt) { mPosAgent = mSourceObjectp->getRenderPosition(); } - LLViewerPart part; - part.init(this, mImagep, updatePart); - part.mStartColor = mColor; - part.mEndColor = mColor; - part.mEndColor.mV[3] = 0.f; - part.mPosAgent = mPosAgent; - part.mMaxAge = 1.f; - part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; - part.mLastUpdateTime = 0.f; - part.mScale.mV[0] = 0.25f; - part.mScale.mV[1] = 0.25f; - part.mParameter = ll_frand(F_TWO_PI); + LLPointer part = new LLViewerPart(); + part->init(this, mImagep, updatePart); + part->mStartColor = mColor; + part->mEndColor = mColor; + part->mEndColor.mV[3] = 0.f; + part->mPosAgent = mPosAgent; + part->mMaxAge = 1.f; + part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; + part->mLastUpdateTime = 0.f; + part->mScale.mV[0] = 0.25f; + part->mScale.mV[1] = 0.25f; + part->mParameter = ll_frand(F_TWO_PI); gWorldPointer->mPartSim.addPart(part); } @@ -728,6 +757,7 @@ void LLViewerPartSourceChat::update(const F32 dt) void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp) { + LLMemType mt(LLMemType::MTYPE_PARTICLES); mSourceObjectp = objp; } diff --git a/linden/indra/newview/llviewerpartsource.h b/linden/indra/newview/llviewerpartsource.h index 66de36b..15f7ba2 100644 --- a/linden/indra/newview/llviewerpartsource.h +++ b/linden/indra/newview/llviewerpartsource.h @@ -70,13 +70,16 @@ public: LLVector3 mPosAgent; // Location of the particle source LLVector3 mTargetPosAgent; // Location of the target position LLVector3 mLastUpdatePosAgent; + LLPointer mSourceObjectp; + U32 mID; + protected: U32 mType; BOOL mIsDead; F32 mLastUpdateTime; F32 mLastPartTime; LLUUID mOwnerUUID; - + // Particle information U32 mPartFlags; // Flags for the particle }; @@ -115,7 +118,6 @@ public: protected: LLQuaternion mRotation; // Current rotation for particle source LLPointer mImagep; // Cached image pointer of the mPartSysData UUID - LLPointer mSourceObjectp; // Source object that this particle system is attached to LLPointer mTargetObjectp; // Target object for the particle source }; @@ -141,7 +143,6 @@ public: LLColor4 mColor; protected: LLPointer mImagep; - LLPointer mSourceObjectp; LLVector3d mLKGSourcePosGlobal; }; @@ -169,7 +170,6 @@ public: static void updatePart(LLViewerPart &part, const F32 dt); LLPointer mImagep; - LLPointer mSourceObjectp; LLPointer mTargetObjectp; LLVector3d mLKGTargetPosGlobal; LLColor4 mColor; @@ -199,7 +199,6 @@ public: LLColor4 mColor; protected: LLPointer mImagep; - LLPointer mSourceObjectp; LLVector3d mLKGSourcePosGlobal; }; diff --git a/linden/indra/newview/llviewerprecompiledheaders.h b/linden/indra/newview/llviewerprecompiledheaders.h index 5478129..8ba45fc 100644 --- a/linden/indra/newview/llviewerprecompiledheaders.h +++ b/linden/indra/newview/llviewerprecompiledheaders.h @@ -82,8 +82,6 @@ #include "lldqueueptr.h" #include "llendianswizzle.h" #include "llerror.h" -#include "llerrorbuffer.h" -#include "llerrorstream.h" #include "llfasttimer.h" #include "llfixedbuffer.h" #include "llframetimer.h" @@ -165,7 +163,6 @@ #include "llcachename.h" #include "llcallbacklisth.h" #include "llcircuit.h" -#include "llcrypto.h" #include "lldatapacker.h" #include "lldbstrings.h" #include "lldispatcher.h" diff --git a/linden/indra/newview/llviewerregion.cpp b/linden/indra/newview/llviewerregion.cpp index 9c741b4..88d8a40 100644 --- a/linden/indra/newview/llviewerregion.cpp +++ b/linden/indra/newview/llviewerregion.cpp @@ -178,14 +178,14 @@ void LLViewerRegion::loadCache() LLVOCacheEntry *entry; - char filename[256]; - sprintf(filename, "%s%sobjects_%d_%d.slc", + char filename[256]; /* Flawfinder: ignore */ + snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc", /* Flawfinder: ignore */ gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(), gDirUtilp->getDirDelimiter().c_str(), U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS ); - FILE *fp = LLFile::fopen(filename, "rb"); + FILE* fp = LLFile::fopen(filename, "rb"); /* Flawfinder: ignore */ if (!fp) { // might not have a file, which is normal @@ -259,14 +259,14 @@ void LLViewerRegion::saveCache() return; } - char filename[256]; - sprintf(filename, "%s%sobjects_%d_%d.slc", + char filename[256]; /* Flawfinder: ignore */ + snprintf(filename, sizeof(filename), "%s%sobjects_%d_%d.slc", /* Flawfinder: ignore */ gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(), gDirUtilp->getDirDelimiter().c_str(), U32(mHandle>>32)/REGION_WIDTH_UNITS, U32(mHandle)/REGION_WIDTH_UNITS ); - FILE *fp = LLFile::fopen(filename, "wb"); + FILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ if (!fp) { llwarns << "Unable to write cache file " << filename << llendl; @@ -500,9 +500,9 @@ char* SIM_ACCESS_STR[] = { "Free Trial", "Unknown" }; // static -const char* LLViewerRegion::accessToString(U8 access) +const char* LLViewerRegion::accessToString(U8 access) /* Flawfinder: ignore */ { - switch(access) + switch(access) /* Flawfinder: ignore */ { case SIM_ACCESS_TRIAL: return SIM_ACCESS_STR[0]; @@ -538,13 +538,13 @@ U8 LLViewerRegion::stringToAccess(const char* access_str) { access = SIM_ACCESS_MATURE; } - return access; + return access; /* Flawfinder: ignore */ } // static -const char* LLViewerRegion::accessToShortString(U8 access) +const char* LLViewerRegion::accessToShortString(U8 access) /* Flawfinder: ignore */ { - switch(access) + switch(access) /* Flawfinder: ignore */ { case SIM_ACCESS_PG: return "PG"; @@ -594,23 +594,25 @@ void LLViewerRegion::dirtyHeights() } } -BOOL LLViewerRegion::idleUpdate(LLTimer &timer, const F32 max_time) +BOOL LLViewerRegion::idleUpdate(F32 max_update_time) { - BOOL done = mLandp->idleUpdate(); - + // did_update returns TRUE if we did at least one significant update + BOOL did_update = mLandp->idleUpdate(max_update_time); + if (mParcelOverlay) { + // Hopefully not a significant time sink... mParcelOverlay->idleUpdate(); } - return done; + return did_update; } // As above, but forcibly do the update. void LLViewerRegion::forceUpdate() { - mLandp->idleUpdate(); + mLandp->idleUpdate(0.f); if (mParcelOverlay) { @@ -845,7 +847,7 @@ LLVector3 LLViewerRegion::getPosAgentFromRegion(const LLVector3 &pos_region) con LLVector3 LLViewerRegion::getPosRegionFromAgent(const LLVector3 &pos_agent) const { - return getPosRegionFromGlobal(gAgent.getPosGlobalFromAgent(pos_agent)); + return pos_agent - getOriginAgent(); } F32 LLViewerRegion::getLandHeightRegion(const LLVector3& region_pos) @@ -916,7 +918,7 @@ void LLViewerRegion::updateCoarseLocations(LLMessageSystem* msg) LLString LLViewerRegion::getInfoString() { - char tmp_buf[256]; + char tmp_buf[256]; /* Flawfinder: ignore */ LLString info; info = "Region: "; @@ -928,7 +930,7 @@ LLString LLViewerRegion::getInfoString() U32 x, y; from_region_handle(getHandle(), &x, &y); - sprintf(tmp_buf, "%d:%d", x, y); + snprintf(tmp_buf, sizeof(tmp_buf), "%d:%d", x, y); /* Flawfinder: ignore */ info += "Handle:"; info += tmp_buf; info += "\n"; @@ -1140,7 +1142,7 @@ void LLViewerRegion::unpackRegionHandshake() const S32 SIM_NAME_BUF = 256; U32 region_flags; U8 sim_access; - char sim_name[SIM_NAME_BUF]; + char sim_name[SIM_NAME_BUF]; /* Flawfinder: ignore */ LLUUID sim_owner; BOOL is_estate_manager; F32 water_height; @@ -1277,8 +1279,20 @@ void LLViewerRegion::setSeedCapability(const std::string& url) LLSD capabilityNames = LLSD::emptyArray(); capabilityNames.append("MapLayer"); capabilityNames.append("MapLayerGod"); - capabilityNames.append("NewAgentInventory"); + capabilityNames.append("NewFileAgentInventory"); capabilityNames.append("EventQueueGet"); + capabilityNames.append("UpdateGestureAgentInventory"); + capabilityNames.append("UpdateNotecardAgentInventory"); + capabilityNames.append("UpdateScriptAgentInventory"); + capabilityNames.append("UpdateGestureTaskInventory"); + capabilityNames.append("UpdateNotecardTaskInventory"); + capabilityNames.append("UpdateScriptTaskInventory"); + capabilityNames.append("SendPostcard"); + capabilityNames.append("ViewerStartAuction"); + capabilityNames.append("ParcelGodReserveForNewbie"); + capabilityNames.append("SendUserReport"); + capabilityNames.append("SendUserReportWithScreenshot"); + capabilityNames.append("RequestTextureDownload"); LLHTTPClient::post(url, capabilityNames, BaseCapabilitiesComplete::build(this)); } @@ -1320,3 +1334,16 @@ std::string LLViewerRegion::getCapability(const std::string& name) const return iter->second; } +void LLViewerRegion::logActiveCapabilities() const +{ + CapabilityMap::const_iterator iter; + for (iter = mCapabilities.begin(); iter != mCapabilities.end(); iter++) + { + if (!iter->second.empty()) + { + // llinfos << "Active capability is " << iter->first << llendl; + llinfos << iter->first << " URL is " << iter->second << llendl; + } + } +} + diff --git a/linden/indra/newview/llviewerregion.h b/linden/indra/newview/llviewerregion.h index 76b9aaf..69a8f19 100644 --- a/linden/indra/newview/llviewerregion.h +++ b/linden/indra/newview/llviewerregion.h @@ -162,7 +162,7 @@ public: static U8 stringToAccess(const char* access_str); // Returns "M", "PG", etc. - static const char* accessToShortString(U8 access); + static const char* accessToShortString(U8 access); /* Flawfinder: ignore */ // helper function which just makes sure all interested parties // can process the message. @@ -172,7 +172,7 @@ public: F32 getWidth() const { return mWidth; } - BOOL idleUpdate(LLTimer &timer, const F32 max_time); + BOOL idleUpdate(F32 max_update_time); // Like idleUpdate, but forces everything to complete regardless of // how long it takes. @@ -188,6 +188,7 @@ public: void setSeedCapability(const std::string& url); void setCapability(const std::string& name, const std::string& url); std::string getCapability(const std::string& name) const; + void logActiveCapabilities() const; const LLHost &getHost() const { return mHost; } const U64 &getHandle() const { return mHandle; } diff --git a/linden/indra/newview/llviewerreputation.cpp b/linden/indra/newview/llviewerreputation.cpp index 8cccb6b..3ee4ab3 100644 --- a/linden/indra/newview/llviewerreputation.cpp +++ b/linden/indra/newview/llviewerreputation.cpp @@ -90,7 +90,7 @@ void send_reputation_agent_assign(const LLUUID& rator_id, message.append(" rated you: "); } - if (text && strlen(text) > 0) + if (text && strlen(text) > 0) /* Flawfinder: ignore */ { message.append(text); } diff --git a/linden/indra/newview/llviewerstats.cpp b/linden/indra/newview/llviewerstats.cpp index e04918e..f09b297 100644 --- a/linden/indra/newview/llviewerstats.cpp +++ b/linden/indra/newview/llviewerstats.cpp @@ -122,13 +122,13 @@ const StatAttributes STAT_INFO[LLViewerStats::ST_COUNT] = // ST_SIM_FPS_20_SECONDS StatAttributes("Seconds with sim FPS below 20", TRUE, TRUE), // ST_PHYS_FPS_20_SECONDS - StatAttributes("Seconds with physics FPS below 20", TRUE, TRUE), + StatAttributes("Seconds with physics FPS below 20", FALSE, TRUE), // ST_LOSS_05_SECONDS StatAttributes("Seconds with packet loss > 5%", TRUE, TRUE), // ST_FPS_DROP_50_RATIO - StatAttributes("Ratio of frames 2x longer than previous", TRUE, FALSE), - // ST_MEDIA_OBJECT_LIST_LENGTH - StatAttributes("Number of objects that want to display web pages", TRUE, FALSE), + StatAttributes("Ratio of frames 2x longer than previous", FALSE, FALSE), + // ST_ENABLE_VBO + StatAttributes("Vertex Buffers Enabled", TRUE, FALSE), // ST_DELTA_BANDWIDTH StatAttributes("Increase/Decrease in bandwidth based on packet loss", TRUE, FALSE), // ST_MAX_BANDWIDTH diff --git a/linden/indra/newview/llviewerstats.h b/linden/indra/newview/llviewerstats.h index a3eb4c1..22f6e57 100644 --- a/linden/indra/newview/llviewerstats.h +++ b/linden/indra/newview/llviewerstats.h @@ -133,7 +133,7 @@ public: ST_PHYS_FPS_20_SECONDS = 32, ST_LOSS_05_SECONDS = 33, ST_FPS_DROP_50_RATIO = 34, - ST_MEDIA_OBJECT_LIST_LENGTH = 35, + ST_ENABLE_VBO = 35, ST_DELTA_BANDWIDTH = 36, ST_MAX_BANDWIDTH = 37, ST_LIGHTING_DETAIL = 38, diff --git a/linden/indra/newview/llviewertexteditor.cpp b/linden/indra/newview/llviewertexteditor.cpp index 00e25af..f84c875 100644 --- a/linden/indra/newview/llviewertexteditor.cpp +++ b/linden/indra/newview/llviewertexteditor.cpp @@ -72,6 +72,9 @@ public: LLEmbeddedItems(const LLViewerTextEditor* editor); ~LLEmbeddedItems(); void clear(); + + // return true if there are no embedded items. + bool empty(); void bindEmbeddedChars(const LLFontGL* font); void unbindEmbeddedChars(const LLFontGL* font); @@ -134,6 +137,13 @@ void LLEmbeddedItems::clear() removeEmbeddedItem(*nextiter); } mEmbeddedUsedChars.clear(); + mEmbeddedIndexedChars.clear(); +} + +bool LLEmbeddedItems::empty() +{ + removeUnusedChars(); + return mEmbeddedUsedChars.empty(); } // Inserts a new unique entry @@ -1386,10 +1396,11 @@ S32 LLViewerTextEditor::insertEmbeddedItem( S32 pos, LLInventoryItem* item ) bool LLViewerTextEditor::importStream(std::istream& str) { - LLNotecard nc(MAX_NOTECARD_SIZE); + LLNotecard nc(LLNotecard::MAX_SIZE); bool success = nc.importStream(str); if (success) { + mEmbeddedItemList->clear(); const std::vector >& items = nc.getItems(); mEmbeddedItemList->addItems(items); // Actually set the text @@ -1415,6 +1426,11 @@ void LLViewerTextEditor::copyInventory(LLInventoryItem* item) item); } +bool LLViewerTextEditor::hasEmbeddedInventory() +{ + return (!(mEmbeddedItemList->empty())); +} + //////////////////////////////////////////////////////////////////////////// BOOL LLViewerTextEditor::importBuffer( const LLString& buffer ) @@ -1425,7 +1441,7 @@ BOOL LLViewerTextEditor::importBuffer( const LLString& buffer ) BOOL LLViewerTextEditor::exportBuffer( LLString& buffer ) { - LLNotecard nc(MAX_NOTECARD_SIZE); + LLNotecard nc(LLNotecard::MAX_SIZE); std::vector > embedded_items; mEmbeddedItemList->getEmbeddedItemList(embedded_items); diff --git a/linden/indra/newview/llviewertexteditor.h b/linden/indra/newview/llviewertexteditor.h index b8452e3..da980d1 100644 --- a/linden/indra/newview/llviewertexteditor.h +++ b/linden/indra/newview/llviewertexteditor.h @@ -86,7 +86,14 @@ public: // If this starts a line, you need to prepend a newline. void copyInventory(LLInventoryItem* item); - + + // returns true if there is embedded inventory. + // *HACK: This is only useful because the notecard verifier may + // change the asset if there is embedded inventory. This mechanism + // should be changed to get a different asset id from the verifier + // rather than checking if a re-load is necessary. Phoenix 2007-02-27 + bool hasEmbeddedInventory(); + protected: // Embedded object operations virtual llwchar pasteEmbeddedItem(llwchar ext_char); diff --git a/linden/indra/newview/llviewertextureanim.cpp b/linden/indra/newview/llviewertextureanim.cpp index 0766b83..bd4d0ef 100644 --- a/linden/indra/newview/llviewertextureanim.cpp +++ b/linden/indra/newview/llviewertextureanim.cpp @@ -36,6 +36,9 @@ LLViewerTextureAnim::LLViewerTextureAnim() : LLTextureAnim() { mLastFrame = -1.f; // Force an update initially mLastTime = 0.f; + mOffS = mOffT = 0; + mScaleS = mScaleT = 1; + mRot = 0; } LLViewerTextureAnim::~LLViewerTextureAnim() @@ -167,13 +170,13 @@ S32 LLViewerTextureAnim::animateTextures(F32 &off_s, F32 &off_t, if (mMode & ROTATE) { result |= ROTATE; - rot = frame_counter; + mRot = rot = frame_counter; } else if (mMode & SCALE) { result |= SCALE; - scale_s = frame_counter; - scale_t = frame_counter; + mScaleS = scale_s = frame_counter; + mScaleT = scale_t = frame_counter; } else { @@ -187,22 +190,22 @@ S32 LLViewerTextureAnim::animateTextures(F32 &off_s, F32 &off_t, &&(mSizeY)) { result |= SCALE; - scale_s = 1.f/mSizeX; - scale_t = 1.f/mSizeY; + mScaleS = scale_s = 1.f/mSizeX; + mScaleT = scale_t = 1.f/mSizeY; x_frame = fmod(frame_counter, mSizeX); y_frame = (S32)(frame_counter / mSizeX); x_pos = x_frame * scale_s; y_pos = y_frame * scale_t; - off_s = (-0.5f + 0.5f*scale_s)+ x_pos; - off_t = (0.5f - 0.5f*scale_t) - y_pos; + mOffS = off_s = (-0.5f + 0.5f*scale_s)+ x_pos; + mOffT = off_t = (0.5f - 0.5f*scale_t) - y_pos; } else { - scale_s = 1.f; - scale_t = 1.f; + mScaleS = scale_s = 1.f; + mScaleT = scale_t = 1.f; x_pos = frame_counter * scale_s; - off_s = (-0.5f + 0.5f*scale_s)+ x_pos; - off_t = 0.f; + mOffS = off_s = (-0.5f + 0.5f*scale_s)+ x_pos; + mOffT = off_t = 0.f; } } } diff --git a/linden/indra/newview/llviewertextureanim.h b/linden/indra/newview/llviewertextureanim.h index 2f95cae..c5b4e84 100644 --- a/linden/indra/newview/llviewertextureanim.h +++ b/linden/indra/newview/llviewertextureanim.h @@ -44,6 +44,13 @@ public: { TRANSLATE = 0x01 // Result code JUST for animateTextures }; + + F32 mOffS; + F32 mOffT; + F32 mScaleS; + F32 mScaleT; + F32 mRot; + protected: LLFrameTimer mTimer; F64 mLastTime; diff --git a/linden/indra/newview/llviewerthrottle.h b/linden/indra/newview/llviewerthrottle.h index 1ccef63..c9157bd 100644 --- a/linden/indra/newview/llviewerthrottle.h +++ b/linden/indra/newview/llviewerthrottle.h @@ -73,7 +73,7 @@ public: LLViewerThrottleGroup getThrottleGroup(const F32 bandwidth_kbps); - static const char *sNames[TC_EOF]; + static const char* sNames[TC_EOF]; /* Flawfinder: ignore */ protected: F32 mMaxBandwidth; F32 mCurrentBandwidth; diff --git a/linden/indra/newview/llviewerwindow.cpp b/linden/indra/newview/llviewerwindow.cpp index dc2db19..a4d38f8 100644 --- a/linden/indra/newview/llviewerwindow.cpp +++ b/linden/indra/newview/llviewerwindow.cpp @@ -133,6 +133,8 @@ #include "llimview.h" #include "lltexlayer.h" #include "lltextbox.h" +#include "lltexturecache.h" +#include "lltexturefetch.h" #include "lltextureview.h" #include "lltool.h" #include "lltoolbar.h" @@ -397,7 +399,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask if (gToolMgr) { // Don't let the user move the mouse out of the window until mouse up. - if( gToolMgr->getCurrentTool(mask)->clipMouseWhenDown() ) + if( gToolMgr->getCurrentTool()->clipMouseWhenDown() ) { mWindow->setMouseClipping(TRUE); } @@ -448,7 +450,7 @@ BOOL LLViewerWindow::handleMouseDown(LLWindow *window, LLCoordGL pos, MASK mask if (gToolMgr) { - if(gToolMgr->getCurrentTool(mask)->handleMouseDown( x, y, mask ) ) + if(gToolMgr->getCurrentTool()->handleMouseDown( x, y, mask ) ) { // This is necessary to force clicks in the world to cause edit // boxes that might have keyboard focus to relinquish it, and hence @@ -526,7 +528,7 @@ BOOL LLViewerWindow::handleDoubleClick(LLWindow *window, LLCoordGL pos, MASK ma if (gToolMgr) { - if(gToolMgr->getCurrentTool(mask)->handleDoubleClick( x, y, mask ) ) + if(gToolMgr->getCurrentTool()->handleDoubleClick( x, y, mask ) ) { return TRUE; } @@ -569,7 +571,7 @@ BOOL LLViewerWindow::handleMouseUp(LLWindow *window, LLCoordGL pos, MASK mask) LLTool *tool = NULL; if (gToolMgr) { - tool = gToolMgr->getCurrentTool(mask); + tool = gToolMgr->getCurrentTool(); if( tool->clipMouseWhenDown() ) { @@ -668,7 +670,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK if (gToolMgr) { // Don't let the user move the mouse out of the window until mouse up. - if( gToolMgr->getCurrentTool(mask)->clipMouseWhenDown() ) + if( gToolMgr->getCurrentTool()->clipMouseWhenDown() ) { mWindow->setMouseClipping(TRUE); } @@ -711,7 +713,7 @@ BOOL LLViewerWindow::handleRightMouseDown(LLWindow *window, LLCoordGL pos, MASK if (gToolMgr) { - if(gToolMgr->getCurrentTool(mask)->handleRightMouseDown( x, y, mask ) ) + if(gToolMgr->getCurrentTool()->handleRightMouseDown( x, y, mask ) ) { // This is necessary to force clicks in the world to cause edit // boxes that might have keyboard focus to relinquish it, and hence @@ -769,7 +771,7 @@ BOOL LLViewerWindow::handleRightMouseUp(LLWindow *window, LLCoordGL pos, MASK m LLTool *tool = NULL; if (gToolMgr) { - tool = gToolMgr->getCurrentTool(mask); + tool = gToolMgr->getCurrentTool(); if( tool->clipMouseWhenDown() ) { @@ -1080,19 +1082,19 @@ BOOL LLViewerWindow::handlePaint(LLWindow *window, S32 x, S32 y, S32 width, S gAgent.getName(name_str); S32 len; - char temp_str[255]; - sprintf(temp_str, "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", + char temp_str[255]; /* Flawfinder: ignore */ + snprintf(temp_str, sizeof(temp_str), "%s FPS %3.1f Phy FPS %2.1f Time Dil %1.3f", /* Flawfinder: ignore */ name_str.c_str(), gViewerStats->mFPSStat.getMeanPerSec(), gViewerStats->mSimPhysicsFPS.getPrev(0), gViewerStats->mSimTimeDilation.getPrev(0)); - len = strlen(temp_str); + len = strlen(temp_str); /* Flawfinder: ignore */ TextOutA(hdc, 0, 0, temp_str, len); LLVector3d pos_global = gAgent.getPositionGlobal(); - sprintf(temp_str, "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); - len = strlen(temp_str); + snprintf(temp_str, sizeof(temp_str), "Avatar pos %6.1lf %6.1lf %6.1lf", pos_global.mdV[0], pos_global.mdV[1], pos_global.mdV[2]); /* Flawfinder: ignore */ + len = strlen(temp_str); /* Flawfinder: ignore */ TextOutA(hdc, 0, 25, temp_str, len); TextOutA(hdc, 0, 50, "Set \"DisableRendering FALSE\" in settings.ini file to reenable", 61); @@ -1169,15 +1171,13 @@ LLViewerWindow::LLViewerWindow( mSuppressToolbox( FALSE ), mHideCursorPermanent( FALSE ), mPickPending(FALSE), - mIgnoreActivate( FALSE ), - mRenderFullFrame(FALSE) + mIgnoreActivate( FALSE ) { // Default to application directory. - strcpy(LLViewerWindow::sSnapshotBaseName, "Snapshot"); - strcpy(LLViewerWindow::sMovieBaseName, "SLmovie"); + strcpy(LLViewerWindow::sSnapshotBaseName, "Snapshot"); /* Flawfinder: ignore */ + strcpy(LLViewerWindow::sMovieBaseName, "SLmovie"); /* Flawfinder: ignore */ LLViewerWindow::sSnapshotDir[0] = '\0'; - mFastFrameTimer.stop(); // create window mWindow = LLWindowManager::createWindow( @@ -1224,6 +1224,13 @@ LLViewerWindow::LLViewerWindow( LLFontManager::initClass(); + if (!gFeatureManagerp->isFeatureAvailable("RenderVBO") || + !gGLManager.mHasVertexBufferObject) + { + gSavedSettings.setBOOL("RenderVBOEnable", FALSE); + } + LLVertexBuffer::initClass(gSavedSettings.getBOOL("RenderVBOEnable")); + // // We want to set this stuff up BEFORE we initialize the pipeline, so we can turn off // stuff like AGP if we think that it'll crash the viewer. @@ -1252,7 +1259,6 @@ LLViewerWindow::LLViewerWindow( gPipeline.init(); stop_glerror(); initGLDefaults(); - LLViewerImage::initClass(); } // @@ -1265,11 +1271,11 @@ LLViewerWindow::LLViewerWindow( // Init the image list. Must happen after GL is initialized and before the images that // LLViewerWindow needs are requested. gImageList.init(); + LLViewerImage::initClass(); gBumpImageList.init(); // Create container for all sub-views mRootView = new LLRootView("root", mVirtualWindowRect, FALSE); - mRootView->setRenderInFastFrame(FALSE); if (!gNoRender) { @@ -1632,8 +1638,14 @@ void LLViewerWindow::initWorldUI() gStatusBar->reshape(root_rect.getWidth(), gStatusBar->getRect().getHeight(), TRUE); gStatusBar->translate(0, root_rect.getHeight() - gStatusBar->getRect().getHeight()); + // sync bg color with menu bar + gStatusBar->setBackgroundColor( gMenuBarView->getBackgroundColor() ); + gViewerWindow->getRootView()->addChild(gStatusBar); + + // menu holder appears on top to get first pass at all mouse events + gViewerWindow->getRootView()->sendChildToFront(gMenuHolder); } @@ -1693,11 +1705,23 @@ LLViewerWindow::~LLViewerWindow() LLWorldMapView::cleanupTextures(); + llinfos << "Cleaning up pipeline" << llendl; + gPipeline.cleanup(); + stop_glerror(); + LLViewerImage::cleanupClass(); delete[] mPickBuffer; mPickBuffer = NULL; + if (gSelectMgr) + { + llinfos << "Cleaning up select manager" << llendl; + gSelectMgr->cleanup(); + } + + LLVertexBuffer::cleanupClass(); + llinfos << "Stopping GL during shutdown" << llendl; if (!gNoRender) { @@ -1705,15 +1729,7 @@ LLViewerWindow::~LLViewerWindow() stop_glerror(); } - if (gSelectMgr) - { - llinfos << "Cleaning up select manager" << llendl; - gSelectMgr->cleanup(); - } - llinfos << "Cleaning up pipeline" << llendl; - gPipeline.cleanup(); - stop_glerror(); llinfos << "Destroying Window" << llendl; destroyWindow(); } @@ -1876,7 +1892,7 @@ void LLViewerWindow::draw() if (gSavedSettings.getBOOL("DisplayTimecode")) { // draw timecode block - char text[256]; + char text[256]; /* Flawfinder: ignore */ glLoadIdentity(); @@ -1925,7 +1941,7 @@ void LLViewerWindow::draw() if (gToolMgr) { // Draw tool specific overlay on world - gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) )->draw(); + gToolMgr->getCurrentTool()->draw(); } if( gAgent.cameraMouselook() ) @@ -2113,7 +2129,7 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) if (gToolMgr) { - if( gToolMgr->getCurrentTool(mask)->handleKey(key, mask) ) + if( gToolMgr->getCurrentTool()->handleKey(key, mask) ) { return TRUE; } @@ -2175,7 +2191,9 @@ BOOL LLViewerWindow::handleKey(KEY key, MASK mask) } // don't pass keys on to world when something in ui has focus - return gFocusMgr.childHasKeyboardFocus(mRootView) || (gMenuBarView && gMenuBarView->getHighlightedItem()); + return gFocusMgr.childHasKeyboardFocus(mRootView) + || LLMenuGL::getKeyboardMode() + || (gMenuBarView && gMenuBarView->getHighlightedItem() && gMenuBarView->getHighlightedItem()->isActive()); } @@ -2279,44 +2297,15 @@ void LLViewerWindow::handleScrollWheel(S32 clicks) void LLViewerWindow::moveCursorToCenter() { -#if 1 // old version - -#if 0 // Dave's changes - this reportedly is making the drift worse on some systems? - S32 x = llround((F32) mVirtualWindowRect.getWidth() / 2); - S32 y = llround((F32) mVirtualWindowRect.getHeight() / 2); -#else S32 x = mVirtualWindowRect.getWidth() / 2; S32 y = mVirtualWindowRect.getHeight() / 2; -#endif //on a forced move, all deltas get zeroed out to prevent jumping mCurrentMousePoint.set(x,y); mLastMousePoint.set(x,y); mCurrentMouseDelta.set(0,0); - LLUI::setCursorPositionScreen(x, y); - -#else // Richard's version - fails on intel macs - - S32 x = llround((F32) mWindowRect.getWidth() / 2); - S32 y = llround((F32) mWindowRect.getHeight() / 2); - - LLCoordWindow window_point; - mWindow->convertCoords(LLCoordGL(x, y), &window_point); - mWindow->setCursorPosition(window_point); - - // read back cursor position - mWindow->getCursorPosition(&window_point); - LLCoordGL new_mouse_pos; - mWindow->convertCoords(window_point, &new_mouse_pos); - new_mouse_pos.mX = llround((F32)new_mouse_pos.mX / mDisplayScale.mV[VX]); - new_mouse_pos.mY = llround((F32)new_mouse_pos.mY / mDisplayScale.mV[VY]); - - //on a forced move, all deltas get zeroed out to prevent jumping - mCurrentMousePoint = new_mouse_pos; - mLastMousePoint = new_mouse_pos; - mCurrentMouseDelta.set(0,0); -#endif + LLUI::setCursorPositionScreen(x, y); } ////////////////////////////////////////////////////////////////////// @@ -2345,10 +2334,29 @@ BOOL LLViewerWindow::handlePerFrameHover() mMouseInWindow = TRUE; } - S32 dx = mCurrentMousePoint.mX - mLastMousePoint.mX; - S32 dy = mCurrentMousePoint.mY - mLastMousePoint.mY; - mCurrentMouseDelta.set(dx,dy); - LLVector2 mouse_vel((F32)dx, (F32)dy); + S32 dx = lltrunc((F32) (mCurrentMousePoint.mX - mLastMousePoint.mX) * LLUI::sGLScaleFactor.mV[VX]); + S32 dy = lltrunc((F32) (mCurrentMousePoint.mY - mLastMousePoint.mY) * LLUI::sGLScaleFactor.mV[VY]); + + LLVector2 mouse_vel; + + if (gSavedSettings.getBOOL("MouseSmooth")) + { + static F32 fdx = 0.f; + static F32 fdy = 0.f; + + F32 amount = 16.f; + fdx = fdx + ((F32) dx - fdx) * llmin(gFrameIntervalSeconds*amount,1.f); + fdy = fdy + ((F32) dy - fdy) * llmin(gFrameIntervalSeconds*amount,1.f); + + mCurrentMouseDelta.set(llround(fdx), llround(fdy)); + mouse_vel.setVec(fdx,fdy); + } + else + { + mCurrentMouseDelta.set(dx, dy); + mouse_vel.setVec((F32) dx, (F32) dy); + } + mMouseVelocityStat.addValue(mouse_vel.magVec()); if (gNoRender) @@ -2473,7 +2481,7 @@ BOOL LLViewerWindow::handlePerFrameHover() LLTool *tool = NULL; if (gToolMgr && gHoverView) { - tool = gToolMgr->getCurrentTool(mask); + tool = gToolMgr->getCurrentTool(); if(!handled && tool) { @@ -2493,8 +2501,8 @@ BOOL LLViewerWindow::handlePerFrameHover() // Suppress the toolbox view if our source tool was the pie tool, // and we've overridden to something else. mSuppressToolbox = - (gToolMgr->getCurrentTool(MASK_NONE) == gToolPie) && - (gToolMgr->getCurrentTool(mask) != gToolPie); + (gToolMgr->getBaseTool() == gToolPie) && + (gToolMgr->getCurrentTool() != gToolPie); } @@ -2555,15 +2563,15 @@ BOOL LLViewerWindow::handlePerFrameHover() (tool != gToolPie // not default tool && tool != gToolGun // not coming out of mouselook && !mSuppressToolbox // not override in third person - && gCurrentToolset != gFaceEditToolset // not special mode - && gCurrentToolset != gMouselookToolset + && gToolMgr->getCurrentToolset() != gFaceEditToolset // not special mode + && gToolMgr->getCurrentToolset() != gMouselookToolset && (!captor || captor->isView())) // not dragging ) { // Force floater tools to be visible (unless minimized) if (!gFloaterTools->getVisible()) { - gFloaterTools->open(); + gFloaterTools->open(); /* Flawfinder: ignore */ } // Update the location of the blue box tool popup LLCoordGL select_center_screen; @@ -2669,7 +2677,7 @@ BOOL LLViewerWindow::handlePerFrameHover() mLastMousePoint = mCurrentMousePoint; // last ditch force of edit menu to selection manager - if (gEditMenuHandler == NULL && gSelectMgr && gSelectMgr->getObjectCount()) + if (gEditMenuHandler == NULL && gSelectMgr && gSelectMgr->getSelection()->getObjectCount()) { gEditMenuHandler = gSelectMgr; } @@ -2705,15 +2713,15 @@ BOOL LLViewerWindow::handlePerFrameHover() gChatBar->startChat(NULL); } - // sync land selection with edit and about land dialogs - if (gParcelMgr - && !gMenuHolder->hasVisibleMenu() - && !LLFloaterLand::floaterVisible() - && !LLFloaterBuyLand::isOpen() - && !LLPanelLandGeneral::buyPassDialogVisible() - && (!gFloaterTools || !gFloaterTools->getVisible())) + // cleanup unused selections when no modal dialogs are open + if (gParcelMgr && LLModalDialog::activeCount() == 0) + { + gParcelMgr->deselectUnused(); + } + + if (gSelectMgr && LLModalDialog::activeCount() == 0) { - gParcelMgr->deselectLand(); + gSelectMgr->deselectUnused(); } return handled; @@ -2761,6 +2769,7 @@ void LLViewerWindow::saveLastMouse(const LLCoordGL &point) void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, BOOL for_hud ) { LLViewerObject* object; + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); if (!for_hud && !for_gl_pick) { @@ -2776,15 +2785,15 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, gParcelMgr->renderParcelCollision(); } } - else if (( for_hud && gSelectMgr->getSelectType() == SELECT_TYPE_HUD) || - (!for_hud && gSelectMgr->getSelectType() != SELECT_TYPE_HUD)) + else if (( for_hud && selection->getSelectType() == SELECT_TYPE_HUD) || + (!for_hud && selection->getSelectType() != SELECT_TYPE_HUD)) { gSelectMgr->renderSilhouettes(for_hud); stop_glerror(); // setup HUD render - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getObjectCount()) + if (selection->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getSelection()->getObjectCount()) { LLBBox hud_bbox = gAgent.getAvatarObject()->getHUDBBox(); @@ -2810,12 +2819,12 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, LLGLDepthTest gls_depth(GL_TRUE, GL_TRUE); glMatrixMode(GL_MODELVIEW); glPushMatrix(); - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD) + if (selection->getSelectType() == SELECT_TYPE_HUD) { F32 zoom = gAgent.getAvatarObject()->mHUDCurZoom; glScalef(zoom, zoom, zoom); } - for( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() ) + for( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() ) { LLDrawable* drawable = object->mDrawable; if (drawable && drawable->isLight()) @@ -2850,7 +2859,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, // not be recalculated at this time. If they are, then group rotations will break. // Draw arrows at average center of all selected objects - LLTool* tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + LLTool* tool = gToolMgr->getCurrentTool(); if (tool) { if(tool->isAlwaysRendered()) @@ -2859,13 +2868,13 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, } else { - if( !gSelectMgr->isEmpty() ) + if( !gSelectMgr->getSelection()->isEmpty() ) { BOOL moveable_object_selected = FALSE; BOOL all_selected_objects_move = TRUE; BOOL all_selected_objects_modify = TRUE; BOOL selecting_linked_set = gSavedSettings.getBOOL("SelectLinkedSet"); - for( object = gSelectMgr->getFirstObject(); object; object = gSelectMgr->getNextObject() ) + for( object = gSelectMgr->getSelection()->getFirstObject(); object; object = gSelectMgr->getSelection()->getNextObject() ) { BOOL this_object_movable = FALSE; if (object->permMove() && (object->permModify() || selecting_linked_set)) @@ -2900,7 +2909,7 @@ void LLViewerWindow::renderSelections( BOOL for_gl_pick, BOOL pick_parcel_walls, } } } - if (gSelectMgr->getSelectType() == SELECT_TYPE_HUD && gSelectMgr->getObjectCount()) + if (selection->getSelectType() == SELECT_TYPE_HUD && selection->getObjectCount()) { glMatrixMode(GL_PROJECTION); glPopMatrix(); @@ -2963,8 +2972,6 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask S32 scaled_x = llround((F32)x * mDisplayScale.mV[VX]); S32 scaled_y = llround((F32)y_from_bot * mDisplayScale.mV[VY]); - F32 delta_time = gAlphaFadeTimer.getElapsedTimeAndResetF32(); - BOOL in_build_mode = gFloaterTools && gFloaterTools->getVisible(); if (in_build_mode || LLDrawPoolAlpha::sShowDebugAlpha) { @@ -2974,17 +2981,6 @@ void LLViewerWindow::hitObjectOrLandGlobalAsync(S32 x, S32 y_from_bot, MASK mask } gPickTransparent = pick_transparent; - if (gPickTransparent) - { - gPickAlphaTargetThreshold = 0.f; - gPickAlphaThreshold = llmax(gPickAlphaTargetThreshold, gPickAlphaThreshold - (delta_time * 0.7f)); - } - else - { - gPickAlphaTargetThreshold = 1.f; - gPickAlphaThreshold = llmin(gPickAlphaTargetThreshold, gPickAlphaThreshold + (delta_time * 0.7f)); - } - gUseGLPick = FALSE; mPickCallback = callback; @@ -3151,8 +3147,6 @@ void LLViewerWindow::performPick() return; } - finishFastFrame(); - mPickPending = FALSE; U32 te_offset = NO_FACE; @@ -3407,8 +3401,8 @@ void LLViewerWindow::analyzeHit( const S32 UV_PICK_WIDTH = 41; const S32 UV_PICK_HALF_WIDTH = (UV_PICK_WIDTH - 1) / 2; U8 uv_pick_buffer[UV_PICK_WIDTH * UV_PICK_WIDTH * 4]; - S32 pick_face = ((LLVOVolume*)objectp)->getAllTEsSame() ? 0 : face; - LLFace* facep = objectp->mDrawable->getFace(objectp->getFaceIndexOffset() + pick_face); + S32 pick_face = face; + LLFace* facep = objectp->mDrawable->getFace(pick_face); gCamera->setPerspective(FOR_SELECTION, scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH, FALSE); glViewport(scaled_x - UV_PICK_HALF_WIDTH, scaled_y - UV_PICK_HALF_WIDTH, UV_PICK_WIDTH, UV_PICK_WIDTH); gPipeline.renderFaceForUVSelect(facep); @@ -3438,45 +3432,6 @@ void LLViewerWindow::analyzeHit( //llinfos << "DEBUG Hit Nothing " << llendl; } - -void LLViewerWindow::requestFastFrame(LLView *view) -{ - if (!mPickPending && - mWindow->getSwapMethod() != LLWindow::SWAP_METHOD_UNDEFINED && - gStartupState >= STATE_STARTED && - gSavedSettings.getBOOL("RenderFastUI") && - !gbCapturing) - { - if (!mFastFrameTimer.getStarted()) - { - // we're double buffered, so when first requesting a fast ui update - // we need to render the scene again so that the front and back buffers - // are synced - mRenderFullFrame = TRUE; - } - // calculation new expiration time and reset timer - F32 expiration; - if (mFastFrameTimer.hasExpired()) - { - expiration = FAST_FRAME_INCREMENT; - } - else - { - expiration = llmin(MAX_FAST_FRAME_TIME, mFastFrameTimer.getTimeToExpireF32() + FAST_FRAME_INCREMENT); - } - - mFastFrameTimer.start(); - mFastFrameTimer.setTimerExpirySec(expiration); - - LLView::sFastFrameView = view->getRootMostFastFrameView(); - if (!LLView::sFastFrameView) - { - LLView::sFastFrameView = view; - } - } -} - - // Returns unit vector relative to camera // indicating direction of point on screen x,y LLVector3 LLViewerWindow::mouseDirectionGlobal(const S32 x, const S32 y) const @@ -3673,37 +3628,54 @@ BOOL LLViewerWindow::mousePointOnLandGlobal(const S32 x, const S32 y, LLVector3d } // Saves an image to the harddrive as "SnapshotX" where X >= 1. -BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw) +BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw, const LLString& extension_in) { if (! raw) { return FALSE; } + + LLString extension(extension_in); + if (extension.empty()) + { + extension = (gSavedSettings.getBOOL("CompressSnapshotsToDisk")) ? ".j2c" : ".bmp"; + } + + LLFilePicker::ESaveFilter pick_type; + if (extension == ".j2c") + pick_type = LLFilePicker::FFSAVE_J2C; + else if (extension == ".bmp") + pick_type = LLFilePicker::FFSAVE_BMP; + else if (extension == ".tga") + pick_type = LLFilePicker::FFSAVE_TGA; + else + pick_type = LLFilePicker::FFSAVE_ALL; // ??? // Get a directory if this is the first time. - if (strlen(sSnapshotDir) == 0) + if (strlen(sSnapshotDir) == 0) /* Flawfinder: ignore */ { LLString proposed_name( sSnapshotBaseName ); - proposed_name.append( ".bmp" ); + proposed_name.append( extension ); // pick a directory in which to save LLFilePicker& picker = LLFilePicker::instance(); - if (!picker.getSaveFile(LLFilePicker::FFSAVE_BMP, proposed_name.c_str())) + if (!picker.getSaveFile(pick_type, proposed_name.c_str())) { // Clicked cancel return FALSE; } // Copy the directory + file name - char directory[LL_MAX_PATH]; - strcpy(directory, picker.getFirstFile()); + char directory[LL_MAX_PATH]; /* Flawfinder: ignore */ + strncpy(directory, picker.getFirstFile(), LL_MAX_PATH -1); /* Flawfinder: ignore */ + directory[LL_MAX_PATH -1] = '\0'; // Smash the file extension - S32 length = strlen(directory); + S32 length = strlen(directory); /* Flawfinder: ignore */ S32 index = length; - // Back up over ".bmp" - index -= 4; + // Back up over extension + index -= extension.length(); if (index >= 0 && directory[index] == '.') { directory[index] = '\0'; @@ -3724,12 +3696,14 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw) { if (index + 1 <= length) { - strcpy(LLViewerWindow::sSnapshotBaseName, directory + index + 1); + strncpy(LLViewerWindow::sSnapshotBaseName, directory + index + 1, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLViewerWindow::sSnapshotBaseName[LL_MAX_PATH -1] = '\0'; } index++; directory[index] = '\0'; - strcpy(LLViewerWindow::sSnapshotDir, directory); + strncpy(LLViewerWindow::sSnapshotDir, directory, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLViewerWindow::sSnapshotDir[LL_MAX_PATH -1] = '\0'; } } @@ -3740,10 +3714,9 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw) do { - char extension[100]; - sprintf( extension, "_%.3d.bmp", i ); filepath = sSnapshotDir; filepath += sSnapshotBaseName; + filepath += llformat("_%.3d",i); filepath += extension; struct stat stat_info; @@ -3752,12 +3725,12 @@ BOOL LLViewerWindow::saveImageNumbered(LLImageRaw *raw) } while( -1 != err ); // search until the file is not found (i.e., stat() gives an error). - LLPointer bmp_image = new LLImageBMP; + LLPointer formatted_image = LLImageFormatted::createFromExtension(extension); LLImageBase::setSizeOverride(TRUE); - BOOL success = bmp_image->encode(raw); + BOOL success = formatted_image->encode(raw); if( success ) { - success = bmp_image->save(filepath); + success = formatted_image->save(filepath); } else { @@ -3773,7 +3746,7 @@ void LLViewerWindow::saveMovieNumbered(void*) if (!gbCapturing) { // Get a directory if this is the first time. - if (strlen(sSnapshotDir) == 0) + if (strlen(sSnapshotDir) == 0) /* Flawfinder: ignore */ { LLString proposed_name( sMovieBaseName ); #if LL_DARWIN @@ -3791,11 +3764,12 @@ void LLViewerWindow::saveMovieNumbered(void*) } // Copy the directory + file name - char directory[LL_MAX_PATH]; - strcpy(directory, picker.getFirstFile()); + char directory[LL_MAX_PATH]; /* Flawfinder: ignore */ + strncpy(directory, picker.getFirstFile(), LL_MAX_PATH -1); /* Flawfinder: ignore */ + directory[LL_MAX_PATH -1] = '\0'; // Smash the file extension - S32 length = strlen(directory); + S32 length = strlen(directory); /* Flawfinder: ignore */ S32 index = length; // Back up over ".bmp" @@ -3820,12 +3794,14 @@ void LLViewerWindow::saveMovieNumbered(void*) { if (index + 1 <= length) { - strcpy(LLViewerWindow::sMovieBaseName, directory + index + 1); + strncpy(LLViewerWindow::sMovieBaseName, directory + index + 1, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLViewerWindow::sMovieBaseName[LL_MAX_PATH -1] = '\0'; } index++; directory[index] = '\0'; - strcpy(LLViewerWindow::sSnapshotDir, directory); + strncpy(LLViewerWindow::sSnapshotDir, directory, LL_MAX_PATH -1); /* Flawfinder: ignore */ + LLViewerWindow::sSnapshotDir[LL_MAX_PATH -1] = '\0'; } } @@ -3836,11 +3812,11 @@ void LLViewerWindow::saveMovieNumbered(void*) do { - char extension[100]; + char extension[100]; /* Flawfinder: ignore */ #if LL_DARWIN - sprintf( extension, "_%.3d.mov", i ); + snprintf( extension, sizeof(extension), "_%.3d.mov", i ); /* Flawfinder: ignore */ #else - sprintf( extension, "_%.3d.avi", i ); + snprintf( extension, sizeof(extension), "_%.3d.avi", i ); /* Flawfinder: ignore */ #endif filepath.assign( sSnapshotDir ); filepath.append( sMovieBaseName ); @@ -3944,9 +3920,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei return FALSE; } - // IW 3/5/04 We don'a wan' nunna yer fest frumes har! - finishFastFrame(); - // PRE SNAPSHOT glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); @@ -3960,10 +3933,11 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); } - BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD); + + BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments; if (hide_hud) { - LLPipeline::toggleRenderType((void*)LLPipeline::RENDER_TYPE_HUD); + LLPipeline::sShowHUDAttachments = FALSE; } // Copy screen to a buffer @@ -4027,7 +4001,6 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei setupViewport(); BOOL first_time_through = (subimage_x + subimage_y == 0); gPickTransparent = FALSE; - gPickAlphaThreshold = 0.1f; gObjectList.renderObjectsForSelect(*gCamera, FALSE, !first_time_through); } else @@ -4101,7 +4074,7 @@ BOOL LLViewerWindow::rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_hei if (hide_hud) { - LLPipeline::toggleRenderType((void*)LLPipeline::RENDER_TYPE_HUD); + LLPipeline::sShowHUDAttachments = TRUE; } if (high_res) @@ -4363,6 +4336,12 @@ void LLViewerWindow::stopGL(BOOL save_state) if (!gGLManager.mIsDisabled) { llinfos << "Shutting down GL..." << llendl; + + // Pause texture decode threads (will get unpaused during main loop) + gTextureCache->pause(); + gImageDecodeThread->pause(); + gTextureFetch->pause(); + gSky.destroyGL(); stop_glerror(); @@ -4381,8 +4360,6 @@ void LLViewerWindow::stopGL(BOOL save_state) LLDynamicTexture::destroyGL(); stop_glerror(); - if(gParcelMgr) gParcelMgr->destroyGL(); - gPipeline.destroyGL(); gCone.cleanupGL(); @@ -4415,10 +4392,8 @@ void LLViewerWindow::restoreGL(const LLString& progress_message) LLManipTranslate::restoreGL(); gImageList.restoreGL(); gBumpImageList.restoreGL(); - gPipeline.setUseAGP(gSavedSettings.getBOOL("RenderUseAGP")); LLDynamicTexture::restoreGL(); LLVOAvatar::restoreGL(); - if (gParcelMgr) gParcelMgr->restoreGL(); if (gFloaterCustomize && gFloaterCustomize->getVisible()) { diff --git a/linden/indra/newview/llviewerwindow.h b/linden/indra/newview/llviewerwindow.h index 8c6d812..debe509 100644 --- a/linden/indra/newview/llviewerwindow.h +++ b/linden/indra/newview/llviewerwindow.h @@ -208,7 +208,7 @@ public: BOOL saveSnapshot(const LLString& filename, S32 image_width, S32 image_height, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR); BOOL rawSnapshot(LLImageRaw *raw, S32 image_width, S32 image_height, BOOL keep_window_aspect = TRUE, BOOL show_ui = TRUE, BOOL do_rebuild = FALSE, ESnapshotType type = SNAPSHOT_TYPE_COLOR ); - BOOL saveImageNumbered(LLImageRaw *raw); + BOOL saveImageNumbered(LLImageRaw *raw, const LLString& extension = ""); void playSnapshotAnimAndSound(); @@ -224,12 +224,6 @@ public: LLViewerObject* getObjectUnderCursor(const F32 depth = 16.0f); - void requestFastFrame(LLView* view); - BOOL renderingFastFrame() { return mFastFrameTimer.getStarted() && !firstFastFrame(); } - void finishFastFrame() { mFastFrameTimer.stop(); mRenderFullFrame = FALSE; } - BOOL firstFastFrame() { return mRenderFullFrame; } - void finishFirstFastFrame() { mRenderFullFrame = FALSE; } - // Returns a pointer to the last object hit LLViewerObject *lastObjectHit(); LLViewerObject *lastNonFloraObjectHit(); @@ -339,14 +333,12 @@ protected: LLString mOverlayTitle; // Used for special titles such as "Second Life - Special E3 2003 Beta" - static char sSnapshotBaseName[LL_MAX_PATH]; - static char sSnapshotDir[LL_MAX_PATH]; + static char sSnapshotBaseName[LL_MAX_PATH]; /* Flawfinder: ignore */ + static char sSnapshotDir[LL_MAX_PATH]; /* Flawfinder: ignore */ - static char sMovieBaseName[LL_MAX_PATH]; + static char sMovieBaseName[LL_MAX_PATH]; /* Flawfinder: ignore */ BOOL mIgnoreActivate; - LLFrameTimer mFastFrameTimer; - BOOL mRenderFullFrame; U8* mPickBuffer; }; diff --git a/linden/indra/newview/llvoavatar.cpp b/linden/indra/newview/llvoavatar.cpp index ece24e0..7113177 100644 --- a/linden/indra/newview/llvoavatar.cpp +++ b/linden/indra/newview/llvoavatar.cpp @@ -47,7 +47,6 @@ #include "timing.h" #include "llagent.h" // Get state values from here -#include "llagparray.h" #include "llviewercontrol.h" #include "llcriticaldamp.h" #include "lldir.h" @@ -210,7 +209,7 @@ const F32 UNDERWATER_FREQUENCY_DAMP = 0.33f; const F32 APPEARANCE_MORPH_TIME = 0.65f; const F32 CAMERA_SHAKE_ACCEL_THRESHOLD_SQUARED = 5.f * 5.f; const F32 TIME_BEFORE_MESH_CLEANUP = 5.f; // seconds -const S32 AVATAR_AGP_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing AGP memory +const S32 AVATAR_RELEASE_THRESHOLD = 10; // number of avatar instances before releasing memory const F32 FOOT_GROUND_COLLISION_TOLERANCE = 0.25f; const F32 AVATAR_LOD_TWEAK_RANGE = 0.7f; const S32 MAX_LOD_CHANGES_PER_FRAME = 2; @@ -768,9 +767,9 @@ LLVOAvatar::LLVOAvatar( mLastSkirtBakedID( IMG_DEFAULT_AVATAR ), mIsDummy(FALSE), mSpecialRenderMode(0), + mTurning(FALSE), mPelvisToFoot(0.f), mLastSkeletonSerialNum( 0 ), - mTurning(FALSE), mHeadOffset(), mIsSitting(FALSE), mTimeVisible(), @@ -789,7 +788,6 @@ LLVOAvatar::LLVOAvatar( mEyesLayerSet( NULL ), mSkirtLayerSet( NULL ), mRenderPriority(1.0f), - mNumAGPVertices(0), mNameString(), mTitle(), mNameAway(FALSE), @@ -848,7 +846,7 @@ LLVOAvatar::LLVOAvatar( mSpeed = 0.f; setAnimationData("Speed", &mSpeed); - strcpy(mAvatarDefinition, AVATAR_DEFAULT_CHAR); + strcpy(mAvatarDefinition, AVATAR_DEFAULT_CHAR); /* Flawfinder: ignore */ if (id == gAgentID) { @@ -1007,7 +1005,7 @@ LLVOAvatar::LLVOAvatar( //------------------------------------------------------------------------- // register motions //------------------------------------------------------------------------- - if (LLCharacter::sInstances.getLength() == 1) + if (LLCharacter::sInstances.size() == 1) { LLKeyframeMotion::setVFS(gStaticVFS); addMotion( ANIM_AGENT_BUSY, LLNullMotion::create ); @@ -1151,7 +1149,8 @@ void LLVOAvatar::markDead() BOOL LLVOAvatar::isFullyBaked() { if (mIsDummy) return TRUE; - + if (getNumTEs() == 0) return FALSE; + BOOL head_baked = ( getTEImage( TEX_HEAD_BAKED )->getID() != IMG_DEFAULT_AVATAR ); BOOL upper_baked = ( getTEImage( TEX_UPPER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); BOOL lower_baked = ( getTEImage( TEX_LOWER_BAKED )->getID() != IMG_DEFAULT_AVATAR ); @@ -1180,10 +1179,10 @@ void LLVOAvatar::deleteLayerSetCaches() // static BOOL LLVOAvatar::areAllNearbyInstancesBaked() { - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; if( inst->isDead() ) { continue; @@ -1213,10 +1212,10 @@ void LLVOAvatar::dumpBakedStatus() { LLVector3d camera_pos_global = gAgent.getCameraPositionGlobal(); - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; llinfos << "Avatar "; LLNameValue* firstname = inst->getNVPair("FirstName"); @@ -1405,11 +1404,10 @@ void LLVOAvatar::initVertexPrograms() //static void LLVOAvatar::restoreGL() { - LLVOAvatar* inst; - for( inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->setCompositeUpdatesEnabled( TRUE ); inst->invalidateComposite( inst->mHeadLayerSet, FALSE ); inst->invalidateComposite( inst->mLowerBodyLayerSet, FALSE ); @@ -1433,10 +1431,10 @@ void LLVOAvatar::deleteCachedImages() if (LLTexLayerSet::sHasCaches) { lldebugs << "Deleting layer set caches" << llendl; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; inst->deleteLayerSetCaches(); } LLTexLayerSet::sHasCaches = FALSE; @@ -1472,9 +1470,9 @@ void LLVOAvatar::initClass() { LLVOAvatar::sMaxOtherAvatarsToComposite = gSavedSettings.getS32("AvatarCompositeLimit"); - char xmlFile[MAX_PATH]; + char xmlFile[MAX_PATH]; /* Flawfinder: ignore */ - sprintf(xmlFile, "%s_lad.xml", gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR).c_str()); + snprintf(xmlFile, MAX_PATH, "%s_lad.xml", gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,AVATAR_DEFAULT_CHAR).c_str()); /* Flawfinder: ignore */ BOOL success = sXMLTree.parseFile( xmlFile, FALSE ); if (!success) { @@ -1537,30 +1535,30 @@ void LLVOAvatar::initClass() sSkeletonInfo = new LLVOAvatarSkeletonInfo; if (!sSkeletonInfo->parseXml(sSkeletonXMLTree.getRoot())) { - llerrs << "Error parsing skeleton XML file" << llendl; + llerrs << "Error parsing skeleton XML file: " << skeleton_path << llendl; } // parse avatar_lad.xml llassert(!sAvatarInfo); sAvatarInfo = new LLVOAvatarInfo; if (!sAvatarInfo->parseXmlSkeletonNode(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlMeshNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlColorNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlLayerNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } if (!sAvatarInfo->parseXmlDriverNodes(root)) { - llerrs << "Error parsing skeleton node in avatar XML file" << llendl; + llerrs << "Error parsing skeleton node in avatar XML file: " << skeleton_path << llendl; } } @@ -1576,6 +1574,19 @@ void LLVOAvatar::cleanupClass() } +void LLVOAvatar::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax) +{ + LLVector3 center = getRenderPosition(); + LLVector3 size = getScale(); + //maximum amount an animation can move avatar from drawable position + LLVector3 animation_buffer(5, 5, 5); + + newMin.setVec((center-size)-animation_buffer); + newMax.setVec(center+size+animation_buffer); + mDrawable->setPositionGroup((newMin + newMax) * 0.5f); +} + + //----------------------------------------------------------------------------- // parseSkeletonFile() //----------------------------------------------------------------------------- @@ -1728,10 +1739,16 @@ BOOL LLVOAvatar::buildSkeleton(LLVOAvatarSkeletonInfo *info) } // add special-purpose "screen" joint - mScreenp = new LLViewerJoint("mScreen", NULL); - // for now, put screen at origin, as it is only used during special - // HUD rendering mode - mScreenp->setWorldPosition(LLVector3::zero); + if (mIsSelf) + { + mScreenp = new LLViewerJoint("mScreen", NULL); + // for now, put screen at origin, as it is only used during special + // HUD rendering mode + F32 aspect = gCamera->getAspect(); + LLVector3 scale(1.f, aspect, 1.f); + mScreenp->setScale(scale); + mScreenp->setWorldPosition(LLVector3::zero); + } return TRUE; } @@ -1812,7 +1829,7 @@ void LLVOAvatar::buildCharacter() return; } - gPrintMessagesThisFrame = TRUE; +// gPrintMessagesThisFrame = TRUE; lldebugs << "Avatar load took " << timer.getElapsedTimeF32() << " seconds." << llendl; if ( ! status ) @@ -1944,9 +1961,10 @@ void LLVOAvatar::buildCharacter() { LLMenuItemCallGL* item; item = new LLMenuItemCallGL(attachment->getName(), - &handle_attach_to_avatar, - object_selected_and_point_valid, - attachment); + NULL, + object_selected_and_point_valid); + item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment)); + gAttachPieMenu->append(item); attachment_found = TRUE; @@ -1998,9 +2016,9 @@ void LLVOAvatar::buildCharacter() { LLMenuItemCallGL* item; item = new LLMenuItemCallGL(attachment->getName(), - &handle_attach_to_avatar, - object_selected_and_point_valid, - attachment); + NULL, + object_selected_and_point_valid); + item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment)); gAttachScreenPieMenu->append(item); gDetachScreenPieMenu->append(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); @@ -2017,8 +2035,11 @@ void LLVOAvatar::buildCharacter() { continue; } - gAttachSubMenu->append(new LLMenuItemCallGL(attachment->getName(), - &handle_attach_to_avatar, object_selected_and_point_valid, &attach_label, attachment)); + LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), + NULL, &object_selected_and_point_valid, &attach_label, attachment); + item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment)); + gAttachSubMenu->append(item); + gDetachSubMenu->append(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, &detach_label, attachment)); @@ -2068,8 +2089,10 @@ void LLVOAvatar::buildCharacter() LLViewerJointAttachment* attachment = attach_it->second; - gAttachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), - &handle_attach_to_avatar, object_selected_and_point_valid, attachment)); + LLMenuItemCallGL* item = new LLMenuItemCallGL(attachment->getName(), + NULL, object_selected_and_point_valid); + gAttachBodyPartPieMenus[group]->append(item); + item->addListener(gMenuHolder->getListenerByName("Object.AttachToAvatar"), "on_click", mAttachmentPoints.reverseLookup(attachment)); gDetachBodyPartPieMenus[group]->append(new LLMenuItemCallGL(attachment->getName(), &handle_detach_from_avatar, object_attached, attachment)); @@ -2089,7 +2112,7 @@ void LLVOAvatar::releaseMeshData() { LLMemType mt(LLMemType::MTYPE_AVATAR); - if (sInstances.getLength() < AVATAR_AGP_RELEASE_THRESHOLD || mIsDummy) + if (sInstances.size() < AVATAR_RELEASE_THRESHOLD || mIsDummy) { return; } @@ -2106,18 +2129,11 @@ void LLVOAvatar::releaseMeshData() mEyeBallRightLOD.setValid(FALSE, TRUE); mSkirtLOD.setValid(FALSE, TRUE); - //cleanup AGP data + //cleanup data if (mDrawable.notNull()) { LLFace* facep = mDrawable->getFace(0); facep->setSize(0, 0); - mNumAGPVertices = 0; - - // You need to reset the vertex data in order to guarantee - // that the data is deallocated, AND you start at the 0 index - // when you restore the face. We're assuming ONLY ONE FACE per - // avatar pool, this logic is broken if that isn't the case! - facep->getPool()->resetVertexData(0); } for (LLViewerJointAttachment *attachmentPoint = mAttachmentPoints.getFirstData(); @@ -2161,7 +2177,7 @@ void LLVOAvatar::restoreMeshData() } // force mesh update as LOD might not have changed to trigger this - updateMeshData(); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); } //----------------------------------------------------------------------------- @@ -2174,29 +2190,28 @@ void LLVOAvatar::updateMeshData() LLFace* facep = mDrawable->getFace(0); U32 num_vertices = 0; + U32 num_indices = 0; // this order is determined by number of LODS // if a mesh earlier in this list changed LODs while a later mesh doesn't, // the later mesh's index offset will be inaccurate - mEyeBallLeftLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mEyeBallRightLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mEyeLashLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mHeadLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mLowerBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mSkirtLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mUpperBodyLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - mHairLOD.updateFaceSizes(num_vertices, mAdjustedPixelArea); - - if (num_vertices != mNumAGPVertices) - { - // resize immediately -// llinfos << "Resizing avatar AGP buffer!" << llendl; - facep->getPool()->resetVertexData(num_vertices); - facep->setSize(0,0); - facep->setSize(num_vertices, 0); - mNumAGPVertices = num_vertices; - } - + mEyeBallLeftLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mEyeBallRightLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mEyeLashLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mHeadLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mLowerBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mSkirtLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mUpperBodyLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + mHairLOD.updateFaceSizes(num_vertices, num_indices, mAdjustedPixelArea); + + // resize immediately + facep->setSize(num_vertices, num_indices); + + facep->mVertexBuffer = new LLVertexBufferAvatar(); + facep->mVertexBuffer->allocateBuffer(num_vertices, num_indices, TRUE); + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + // This is a hack! Avatars have their own pool, so we are detecting // the case of more than one avatar in the pool (thus > 0 instead of >= 0) if (facep->getGeomIndex() > 0) @@ -2379,13 +2394,8 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) setPixelAreaAndAngle(gAgent); // Update the LOD of the joints - static const F32 UPDATE_TIME = .5f; - if (mUpdateLODTimer.hasExpired()) - { - mUpdateLODTimer.setTimerExpirySec(UPDATE_TIME * (.75f + ll_frand(0.5f))); - updateJointLODs(); - } - + //static const F32 UPDATE_TIME = .5f; + // force asynchronous drawable update if(mDrawable.notNull() && !gNoRender) { @@ -2445,6 +2455,17 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) updateCharacter(agent); + + + if (LLVOAvatar::sJointDebug) + { + llinfos << getNVPair("FirstName")->getString() << getNVPair("LastName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; + } + + LLJoint::sNumUpdates = 0; + LLJoint::sNumTouches = 0; + + if (gNoRender) { return TRUE; @@ -2453,7 +2474,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) // *NOTE: this is necessary for the floating name text above your head. if (mDrawable.notNull()) { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_SHADOW, TRUE); } // update attachments positions @@ -2463,11 +2484,15 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); - if (attached_object && !attached_object->isDead() && attachment->getValid()) + LLViewerObject *attached_object = attachment->getObject(); + + BOOL visibleAttachment = isVisible() || !(attached_object && attached_object->mDrawable->getSpatialBridge() + && (attached_object->mDrawable->getSpatialBridge()->getRadius() < 2.0)); + + if (visibleAttachment && attached_object && !attached_object->isDead() && attachment->getValid()) { // if selecting any attachments, update all of them as non-damped - if (gSelectMgr->getObjectCount() && gSelectMgr->selectionIsAttachment()) + if (gSelectMgr->getSelection()->getObjectCount() && gSelectMgr->getSelection()->isAttachment()) { gPipeline.updateMoveNormalAsync(attached_object->mDrawable); } @@ -2618,9 +2643,9 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) const F32 FADE_DURATION = gSavedSettings.getF32("RenderNameFadeDuration"); // seconds BOOL visible_chat = gSavedSettings.getBOOL("UseChatBubbles") && (mChats.size() || mTyping); BOOL render_name = visible_chat || - (mVisible && - (sRenderName == RENDER_NAME_ALWAYS) || - (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME)); + (isVisible() && + ((sRenderName == RENDER_NAME_ALWAYS) || + (sRenderName == RENDER_NAME_FADE && time_visible < NAME_SHOW_TIME))); // If it's your own avatar, don't draw in mouselook, and don't // draw if we're specifically hiding our own name. if (mIsSelf) @@ -2737,53 +2762,55 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) (is_away != mNameAway || is_busy != mNameBusy || is_muted != mNameMute) || is_appearance != mNameAppearance) { - char line[MAX_STRING]; + char line[MAX_STRING]; /* Flawfinder: ignore */ if (title && title->getString() && title->getString()[0] != '\0') { - strcpy(line, title->getString() ); - strcat(line, "\n"); - strcat(line, firstname->getString() ); + strncpy(line, title->getString(), MAX_STRING -1 ); /* Flawfinder: ignore */ + line[MAX_STRING -1] = '\0'; + strcat(line, "\n"); /* Flawfinder: ignore */ + strncat(line, firstname->getString(), MAX_STRING - strlen(line) -1 ); /* Flawfinder: ignore */ } else { - strcpy(line, firstname->getString() ); + strncpy(line, firstname->getString(), MAX_STRING -1 ); /* Flawfinder: ignore */ + line[MAX_STRING -1] = '\0'; } - strcat(line, " "); - strcat(line, lastname->getString()); + strcat(line, " "); /* Flawfinder: ignore */ + strncat(line, lastname->getString(), MAX_STRING - strlen(line) -1); /* Flawfinder: ignore */ BOOL need_comma = FALSE; if (is_away || is_muted || is_busy) { - strcat(line, " ("); + strcat(line, " ("); /* Flawfinder: ignore */ if (is_away) { - strcat(line, "Away"); + strcat(line, "Away"); /* Flawfinder: ignore */ need_comma = TRUE; } if (is_busy) { if (need_comma) { - strcat(line, ", "); + strcat(line, ", "); /* Flawfinder: ignore */ } - strcat(line, "Busy"); + strcat(line, "Busy"); /* Flawfinder: ignore */ need_comma = TRUE; } if (is_muted) { if (need_comma) { - strcat(line, ", "); + strcat(line, ", "); /* Flawfinder: ignore */ } - strcat(line, "Muted"); + strcat(line, "Muted"); /* Flawfinder: ignore */ need_comma = TRUE; } - strcat(line,")"); + strcat(line,")"); /* Flawfinder: ignore */ } if (is_appearance) { - strcat(line, "\n(Editing Appearance)"); + strcat(line, "\n(Editing Appearance)"); /* Flawfinder: ignore */ } mNameAway = is_away; mNameBusy = is_busy; @@ -2805,7 +2832,7 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) mNameText->setLabel(mNameString); } - char line[MAX_STRING]; + char line[MAX_STRING]; /* Flawfinder: ignore */ line[0] = '\0'; std::deque::iterator chat_iter = mChats.begin(); mNameText->clearString(); @@ -2922,22 +2949,24 @@ BOOL LLVOAvatar::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) if (!mBeam.isNull()) { + LLObjectSelectionHandle selection = gSelectMgr->getSelection(); + if (gAgent.mPointAt.notNull()) { // get point from pointat effect mBeam->setPositionGlobal(gAgent.mPointAt->getPointAtPosGlobal()); mBeam->triggerLocal(); } - else if (gSelectMgr->getFirstRootObject() && - gSelectMgr->getSelectType() != SELECT_TYPE_HUD) + else if (selection->getFirstRootObject() && + selection->getSelectType() != SELECT_TYPE_HUD) { - LLViewerObject* objectp = gSelectMgr->getFirstRootObject(); + LLViewerObject* objectp = selection->getFirstRootObject(); mBeam->setTargetObject(objectp); } else { mBeam->setTargetObject(NULL); - LLTool *tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + LLTool *tool = gToolMgr->getCurrentTool(); if (tool->isEditing()) { if (tool->getEditingObject()) @@ -2993,6 +3022,16 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); + // update screen joint size + if (mScreenp) + { + F32 aspect = gCamera->getAspect(); + LLVector3 scale(1.f, aspect, 1.f); + mScreenp->setScale(scale); + mScreenp->updateWorldMatrixChildren(); + resetHUDAttachments(); + } + // clear debug text mDebugText.clear(); @@ -3005,28 +3044,30 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) { if (motionp->getMinPixelArea() < getPixelArea()) { - char output[256]; + char output[MAX_STRING]; /* Flawfinder: ignore */ if (motionp->getName().empty()) { - sprintf(output, "%s - %d", motionp->getID().getString().c_str(), (U32)motionp->getPriority()); + snprintf( /* Flawfinder: ignore */ + output, + MAX_STRING, + "%s - %d", + motionp->getID().asString().c_str(), + (U32)motionp->getPriority()); } else { - sprintf(output, "%s - %d", motionp->getName().c_str(), (U32)motionp->getPriority()); + snprintf( /* Flawfinder: ignore */ + output, + MAX_STRING, + "%s - %d", + motionp->getName().c_str(), + (U32)motionp->getPriority()); } addDebugText(output); } } } - if (LLVOAvatar::sJointDebug) - { - llinfos << getNVPair("FirstName")->getString() << ": joint touches: " << LLJoint::sNumTouches << " updates: " << LLJoint::sNumUpdates << llendl; - - LLJoint::sNumUpdates = 0; - LLJoint::sNumTouches = 0; - } -// llinfos << mPixelArea << llendl; if (gNoRender) { // Hack if we're running drones... @@ -3045,10 +3086,15 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) return; } + if (!mIsSelf && !isVisible()) + { + return; + } + // change animation time quanta based on avatar render load if (!mIsSelf) { - F32 time_quantum = clamp_rescale((F32)sInstances.getLength(), 10.f, 35.f, 0.f, 0.25f); + F32 time_quantum = clamp_rescale((F32)sInstances.size(), 10.f, 35.f, 0.f, 0.25f); F32 pixel_area_scale = clamp_rescale(mPixelArea, 100, 5000, 1.f, 0.f); F32 time_step = time_quantum * pixel_area_scale; if (time_step != 0.f) @@ -3077,10 +3123,6 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) mTimeVisible.reset(); } - // update screen joint size - mScreenp->setScale(LLVector3(1.f, gCamera->getAspect(), 1.f)); - mScreenp->updateWorldMatrixChildren(); - //-------------------------------------------------------------------- // create local variables in world coords for region position values //-------------------------------------------------------------------- @@ -3091,6 +3133,8 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) xyVel.mV[VZ] = 0.0f; speed = xyVel.magVec(); + BOOL throttle = TRUE; + if (!(mIsSitting && getParent())) { //-------------------------------------------------------------------- @@ -3101,6 +3145,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) if (mTimeLast == 0.0f) { mTimeLast = animation_time; + throttle = FALSE; // put the pelvis at slaved position/mRotation mRoot.setWorldPosition( getPositionAgent() ); // first frame @@ -3144,7 +3189,16 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) // correct for the fact that the pelvis is not necessarily the center // of the agent's physical representation root_pos.mdV[VZ] -= (0.5f * mBodySize.mV[VZ]) - mPelvisToFoot; - mRoot.setWorldPosition(gAgent.getPosAgentFromGlobal(root_pos) ); // regular update + + + LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); + + if (newPosition != mRoot.getXform()->getWorldPosition()) + { + mRoot.touch(); + mRoot.setWorldPosition(newPosition ); // regular update + } + //-------------------------------------------------------------------- // Propagate viewer object rotation to root of avatar @@ -3314,9 +3368,10 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) //} //end Ventrella - F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); - + F32 u = llclamp((deltaTime / pelvis_lag_time), 0.0f, 1.0f); + mRoot.setWorldRotation( slerp(u, mRoot.getWorldRotation(), wQv) ); + } } else if (mDrawable.notNull()) @@ -3328,8 +3383,17 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) //-------------------------------------------------------------------- // the rest should only be done when close enough to see it //-------------------------------------------------------------------- + + + if (mPixelArea > 12.0f) + throttle = FALSE; + if (mPixelArea < 400.0f) + { + throttle = (LLDrawable::getCurrentFrame()+mID.mData[0])%2 != 0; + } + if ( !(mIsSitting && getParent()) && - ((mPixelArea < 12.0f) || + (throttle || (!isVisible() && (mPixelArea < MIN_PIXEL_AREA_FOR_COMPOSITE))) ) { mRoot.setWorldRotation( getRotation() ); @@ -3433,7 +3497,7 @@ void LLVOAvatar::updateCharacter(LLAgent &agent) } } } - + mRoot.updateWorldMatrixChildren(); if (!mDebugText.size() && mText.notNull()) @@ -3490,10 +3554,8 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) else if (!force_invisible) { // calculate avatar distance wrt head - LLVector3 pos = mDrawable->getPositionAgent(); - pos -= gCamera->getOrigin(); - mDrawable->mDistanceWRTCamera = pos.magVec(); - + mDrawable->updateDistance(*gCamera); + if (!mDrawable->getSpatialGroup() || mDrawable->getSpatialGroup()->isVisible()) { visible = TRUE; @@ -3565,9 +3627,9 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getObject(0)) + if (attachment->getObject()) { - if(attachment->getObject(0)->mDrawable->isVisible()) + if(attachment->getObject()->mDrawable->isVisible()) { llinfos << attachment->getName() << " visible" << llendl; } @@ -3591,7 +3653,6 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) { restoreMeshData(); } - gPipeline.markVisible(mDrawable); } else { @@ -3618,11 +3679,12 @@ void LLVOAvatar::updateVisibility(BOOL force_invisible) void LLVOAvatar::updateAllAvatarVisiblity() { LLVOAvatar::sNumVisibleAvatars = 0; - LLVOAvatar *avatarp; - + F32 render_priority = (F32)LLVOAvatar::sMaxVisible; - for (avatarp = (LLVOAvatar*)sInstances.getFirstData(); avatarp; avatarp = (LLVOAvatar*)sInstances.getNextData()) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* avatarp = (LLVOAvatar*) *iter; if (avatarp->isDead()) { continue; @@ -3661,7 +3723,7 @@ BOOL LLVOAvatar::needsRenderBeam() { return FALSE; } - LLTool *tool = gToolMgr->getCurrentTool( gKeyboard->currentMask(TRUE) ); + LLTool *tool = gToolMgr->getCurrentTool(); BOOL is_touching_or_grabbing = (tool == gToolGrab && gToolGrab->isEditing()); if (gToolGrab->getEditingObject() && @@ -3760,26 +3822,22 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) if (pass == AVATAR_RENDER_PASS_SINGLE) { + BOOL first_pass = TRUE; if (!mIsSelf || gAgent.needsRenderHead()) { num_indices += mHeadLOD.render(mAdjustedPixelArea); + first_pass = FALSE; } - num_indices += mUpperBodyLOD.render(mAdjustedPixelArea); - num_indices += mLowerBodyLOD.render(mAdjustedPixelArea); - if( isWearingWearableType( WT_SKIRT ) ) - { - glAlphaFunc(GL_GREATER,0.25f); - num_indices += mSkirtLOD.render(mAdjustedPixelArea); - glAlphaFunc(GL_GREATER,0.01f); - } + num_indices += mUpperBodyLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mLowerBodyLOD.render(mAdjustedPixelArea, FALSE); - if (!mIsSelf || gAgent.needsRenderHead()) { - num_indices += mEyeLashLOD.render(mAdjustedPixelArea); - num_indices += mHairLOD.render(mAdjustedPixelArea); + LLGLEnable blend(GL_BLEND); + LLGLEnable test(GL_ALPHA_TEST); + num_indices += renderTransparent(); } } - else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER) + /*else if (pass == AVATAR_RENDER_PASS_CLOTHING_INNER) { if (!mIsSelf || gAgent.needsRenderHead()) { @@ -3812,7 +3870,7 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) LLViewerJointMesh::sClothingMaskImageName = mLowerMaskTexName; num_indices += mLowerBodyLOD.render(mAdjustedPixelArea); LLViewerJointMesh::sClothingMaskImageName = 0; - } + }*/ LLViewerJointMesh::sRenderPass = AVATAR_RENDER_PASS_SINGLE; @@ -3823,6 +3881,27 @@ U32 LLVOAvatar::renderSkinned(EAvatarRenderPass pass) return num_indices; } +U32 LLVOAvatar::renderTransparent() +{ + U32 num_indices = 0; + BOOL first_pass = FALSE; + if( isWearingWearableType( WT_SKIRT ) ) + { + glAlphaFunc(GL_GREATER,0.25f); + num_indices += mSkirtLOD.render(mAdjustedPixelArea, FALSE); + first_pass = FALSE; + glAlphaFunc(GL_GREATER,0.01f); + } + + if (!mIsSelf || gAgent.needsRenderHead()) + { + num_indices += mEyeLashLOD.render(mAdjustedPixelArea, first_pass); + num_indices += mHairLOD.render(mAdjustedPixelArea, FALSE); + } + + return num_indices; +} + //----------------------------------------------------------------------------- // renderRigid() //----------------------------------------------------------------------------- @@ -3851,6 +3930,39 @@ U32 LLVOAvatar::renderRigid() return num_indices; } +U32 LLVOAvatar::renderFootShadows() +{ + U32 num_indices = 0; + + if (!mIsBuilt) + { + return 0; + } + + if (mIsSelf && (!gAgent.needsRenderAvatar() || !gAgent.needsRenderHead())) + { + return 0; + } + + if (!mIsBuilt) + { + return 0; + } + + U32 foot_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD; + + //render foot shadows + LLGLEnable blend(GL_BLEND); + mShadowImagep->bind(); + glColor4fv(mShadow0Facep->getRenderColor().mV); + mShadow0Facep->renderIndexed(foot_mask); + glColor4fv(mShadow1Facep->getRenderColor().mV); + mShadow1Facep->renderIndexed(foot_mask); + + return num_indices; +} + //----------------------------------------------------------------------------- // renderCollisionVolumes() //----------------------------------------------------------------------------- @@ -3867,6 +3979,7 @@ void LLVOAvatar::renderCollisionVolumes() //------------------------------------------------------------------------ void LLVOAvatar::updateTextures(LLAgent &agent) { +// LLFastTimer ftm(LLFastTimer::FTM_TEMP5); BOOL render_avatar = TRUE; if (mIsDummy || gNoRender) @@ -3941,6 +4054,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } */ + mMaxPixelArea = 0.f; + mMinPixelArea = 99999999.f; for (U32 i = 0; i < getNumTEs(); i++) { LLViewerImage *imagep = getTEImage(i); @@ -3965,9 +4080,10 @@ void LLVOAvatar::updateTextures(LLAgent &agent) && imagep->getID() != IMG_DEFAULT_AVATAR && !imagep->getTargetHost().isOk()) { - llwarns << "LLVOAvatar::updateTextures No host for texture " << imagep->getID() - << " for avatar " << (mIsSelf ? "" : getID().getString()) - << " on host " << getRegion()->getHost() << llendl; + llwarns << "LLVOAvatar::updateTextures No host for texture " + << imagep->getID() << " for avatar " + << (mIsSelf ? "" : getID().asString().c_str()) + << " on host " << getRegion()->getHost() << llendl; } switch( i ) @@ -4037,40 +4153,35 @@ void LLVOAvatar::updateTextures(LLAgent &agent) case TEX_HEAD_BAKED: if (head_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_UPPER_BAKED: if (upper_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_LOWER_BAKED: if (lower_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_EYES_BAKED: if (eyes_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; case TEX_SKIRT_BAKED: if (skirt_baked) { - imagep->setBoostLevel(boost_level); - imagep->addTextureStats(mPixelArea, texel_area_ratio); + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); } break; @@ -4078,15 +4189,8 @@ void LLVOAvatar::updateTextures(LLAgent &agent) // Hair is neither a local texture used for baking, nor the output // of the baking process. It's just a texture that happens to be // used to draw avatars. Hence BOOST_AVATAR. JC - if (mIsSelf) - { - imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR_SELF); - } - else - { - imagep->setBoostLevel(LLViewerImage::BOOST_AVATAR); - } - imagep->addTextureStats(mPixelArea, texel_area_ratio); + boost_level = mIsSelf ? LLViewerImage::BOOST_AVATAR_SELF : LLViewerImage::BOOST_AVATAR; + addBakedTextureStats( imagep, mPixelArea, texel_area_ratio, boost_level ); break; default: @@ -4096,6 +4200,11 @@ void LLVOAvatar::updateTextures(LLAgent &agent) } } + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%4.0f:%4.0f", fsqrtf(mMinPixelArea),fsqrtf(mMaxPixelArea))); + } + if( render_avatar ) { mShadowImagep->addTextureStats(mPixelArea, 1.f); @@ -4125,6 +4234,15 @@ void LLVOAvatar::addLocalTextureStats( LLVOAvatar::ELocTexIndex idx, LLViewerIma } } + +void LLVOAvatar::addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level) +{ + mMaxPixelArea = llmax(pixel_area, mMaxPixelArea); + mMinPixelArea = llmin(pixel_area, mMinPixelArea); + imagep->addTextureStats(pixel_area, texel_area_ratio); + imagep->setBoostLevel(boost_level); +} + //----------------------------------------------------------------------------- // resolveHeight() //----------------------------------------------------------------------------- @@ -4409,14 +4527,7 @@ BOOL LLVOAvatar::stopMotion(const LLUUID& id, BOOL stop_immediate) { if (mIsSelf) { - if (id == ANIM_AGENT_STAND) - { - LLAgent::stopFidget(); - } - else if (id == ANIM_AGENT_AWAY) - { - gAgent.clearAFK(); - } + gAgent.onAnimStop(id); } if (id == ANIM_AGENT_WALK) @@ -4609,7 +4720,7 @@ F32 LLVOAvatar::getTimeDilation() //----------------------------------------------------------------------------- // LLVOAvatar::getPixelArea() //----------------------------------------------------------------------------- -F32 LLVOAvatar::getPixelArea() +F32 LLVOAvatar::getPixelArea() const { if (mIsDummy) { @@ -4971,6 +5082,11 @@ BOOL LLVOAvatar::loadSkeletonNode () iter != sAvatarInfo->mAttachmentInfoList.end(); iter++) { LLVOAvatarInfo::LLVOAvatarAttachmentInfo *info = *iter; + if (!isSelf() && info->mJointName == "mScreen") + { //don't process screen joint for other avatars + continue; + } + LLViewerJointAttachment* attachment = new LLViewerJointAttachment(); attachment->setName(info->mName); @@ -5321,15 +5437,6 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) { LLMemType mt(LLMemType::MTYPE_AVATAR); - LLVector3 viewer_pos_agent = agent.getCameraPositionAgent(); - LLVector3 pos_agent; - - pos_agent = getRenderPosition(); - - F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; - F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; - F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; - F32 max_scale = getMaxScale(); F32 mid_scale = getMidScale(); F32 min_scale = llmin( getScale().mV[VX], llmin( getScale().mV[VY], getScale().mV[VZ] ) ); @@ -5338,7 +5445,7 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) // to try to get a min distance from face, subtract min_scale/2 from the range. // This means we'll load too much detail sometimes, but that's better than not enough // I don't think there's a better way to do this without calculating distance per-poly - F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; + F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec() - min_scale/2; if (range < 0.001f) // range == zero { @@ -5373,17 +5480,11 @@ void LLVOAvatar::setPixelAreaAndAngle(LLAgent &agent) //----------------------------------------------------------------------------- // updateJointLODs() //----------------------------------------------------------------------------- -void LLVOAvatar::updateJointLODs() +BOOL LLVOAvatar::updateJointLODs() { - if (!mMeshValid) - { - return; - } - F32 lod_factor = (sLODFactor * AVATAR_LOD_TWEAK_RANGE + (1.f - AVATAR_LOD_TWEAK_RANGE)); F32 avatar_num_min_factor = clamp_rescale(sLODFactor, 0.f, 1.f, 0.25f, 0.6f); F32 avatar_num_factor = clamp_rescale((F32)sNumVisibleAvatars, 8, 25, 1.f, avatar_num_min_factor); - { if (mIsSelf) { @@ -5406,16 +5507,17 @@ void LLVOAvatar::updateJointLODs() mAdjustedPixelArea = (F32)mPixelArea * lod_factor * lod_factor * avatar_num_factor * avatar_num_factor; } - // now select meshes to render based on adjusted pixel area, and perform AGP data push as necessary + // now select meshes to render based on adjusted pixel area BOOL res = mRoot.updateLOD(mAdjustedPixelArea, TRUE); if (res) { sNumLODChangesThisFrame++; - updateMeshData(); + dirtyMesh(); + return TRUE; } } - return; + return FALSE; } //----------------------------------------------------------------------------- @@ -5426,24 +5528,22 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); - LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_AVATAR); + LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR); // Only a single face (one per avatar) mDrawable->setState(LLDrawable::ACTIVE); mDrawable->addFace(poolp, NULL); + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR); - poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - LLFace *facep; // Add faces for the foot shadows - facep = mDrawable->addFace(poolp, mShadowImagep); + facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); mShadow0Facep = facep; - facep = mDrawable->addFace(poolp, mShadowImagep); + facep = mDrawable->addFace((LLFacePool*) NULL, mShadowImagep); mShadow1Facep = facep; - gPipeline.markMaterialed(mDrawable); dirtyMesh(); return mDrawable; } @@ -5454,6 +5554,7 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) //----------------------------------------------------------------------------- BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_AVATAR); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; @@ -5469,30 +5570,9 @@ BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) llerrs << "LLVOAvatar::updateGeometry() called with NULL drawable" << llendl; } - // Update the shadow, tractor, and text label geometry. - - updateShadowFaces(); - - if (!drawable->isVisible()) - { - return TRUE; - } - - LLFace* facep = drawable->getFace(0); - if (!mDirtyMesh && !facep->getDirty()) - { - return TRUE; - } - - // U32 num_vertices = 0; - - updateMeshData(); - - mDirtyMesh = FALSE; return TRUE; } - //----------------------------------------------------------------------------- // updateShadowFaces() //----------------------------------------------------------------------------- @@ -5708,28 +5788,26 @@ void LLVOAvatar::removeChild(LLViewerObject *childp) detachObject(childp); } -//----------------------------------------------------------------------------- -// attachObject() -//----------------------------------------------------------------------------- -BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) +LLViewerJointAttachment* LLVOAvatar::getTargetAttachmentPoint(LLViewerObject* viewer_object) { S32 attachmentID = ATTACHMENT_ID_FROM_STATE(viewer_object->getState()); - //clamp((S32)(viewer_object->getState() & AGENT_ATTACH_MASK) >> AGENT_ATTACH_OFFSET, 1, 0xff); - - //if (mIsSelf) - //{ - // gSelectMgr->deselectObjectAndFamily(viewer_object); - //} LLViewerJointAttachment* attachment = mAttachmentPoints.getIfThere(attachmentID); if (!attachment) { - llwarns << "Tried to attach object to invalid attachment point: " << attachmentID << llendl; - return FALSE; + llwarns << "Object attachment point invalid: " << attachmentID << llendl; } -// LLQuaternion object_world_rot = viewer_object->getWorldRotation(); + return attachment; +} + +//----------------------------------------------------------------------------- +// attachObject() +//----------------------------------------------------------------------------- +BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) +{ + LLViewerJointAttachment* attachment = getTargetAttachmentPoint(viewer_object); if (!attachment->addObject(viewer_object)) { @@ -5742,10 +5820,6 @@ BOOL LLVOAvatar::attachObject(LLViewerObject *viewer_object) gSelectMgr->updatePointAt(); } -// LLQuaternion desired_rot = (object_world_rot * ~attachment->getWorldRotation()); - - lldebugs << "Attaching object (" << attachmentID << ") item_id=" << attachment->getItemID() << " task_id=" << viewer_object->getID() << "to " << attachment->getName() << llendl; - if (mIsSelf) { updateAttachmentVisibility(gAgent.getCameraMode()); @@ -5778,6 +5852,23 @@ void LLVOAvatar::lazyAttach() } } +void LLVOAvatar::resetHUDAttachments() +{ + for(LLViewerJointAttachment* attachment = mAttachmentPoints.getFirstData(); + attachment; + attachment = mAttachmentPoints.getNextData()) + { + if (attachment->getIsHUDAttachment()) + { + LLViewerObject* obj = attachment->getObject(); + if (obj && obj->mDrawable.notNull()) + { + gPipeline.markMoved(obj->mDrawable); + } + } + } +} + //----------------------------------------------------------------------------- // detachObject() //----------------------------------------------------------------------------- @@ -5788,7 +5879,7 @@ BOOL LLVOAvatar::detachObject(LLViewerObject *viewer_object) attachment = mAttachmentPoints.getNextData()) { // only one object per attachment point for now - if (attachment->getObject(0) == viewer_object) + if (attachment->getObject() == viewer_object) { LLUUID item_id = attachment->getItemID(); attachment->removeObject(viewer_object); @@ -5981,7 +6072,7 @@ LLViewerObject* LLVOAvatar::getWornAttachment( const LLUUID& inv_item_id ) { if( attachment_point->getItemID() == inv_item_id ) { - return attachment_point->getObject(0); + return attachment_point->getObject(); } } return NULL; @@ -6319,10 +6410,10 @@ const LLUUID& LLVOAvatar::getLocalTextureID( S32 index ) void LLVOAvatar::dumpTotalLocalTextureByteCount() { S32 total_gl_bytes = 0; - for( LLVOAvatar* cur = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - cur; - cur = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* cur = (LLVOAvatar*) *iter; S32 gl_bytes = 0; cur->getLocalTextureByteCount(&gl_bytes ); total_gl_bytes += gl_bytes; @@ -7722,7 +7813,7 @@ BOOL LLVOAvatar::hasHUDAttachment() attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) + if (attachment->getIsHUDAttachment() && attachment->getObject()) { return TRUE; } @@ -7737,9 +7828,9 @@ LLBBox LLVOAvatar::getHUDBBox() attachment; attachment = mAttachmentPoints.getNextData()) { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) + if (attachment->getIsHUDAttachment() && attachment->getObject()) { - LLViewerObject* hud_object = attachment->getObject(0); + LLViewerObject* hud_object = attachment->getObject(); // initialize bounding box to contain identity orientation and center point for attached object bbox.addPointLocal(hud_object->getPosition()); @@ -7757,52 +7848,6 @@ LLBBox LLVOAvatar::getHUDBBox() void LLVOAvatar::rebuildHUD() { - if (!mIsSelf) - { - return; - } - - for(LLViewerJointAttachment *attachment = mAttachmentPoints.getFirstData(); - attachment; - attachment = mAttachmentPoints.getNextData()) - { - if (attachment->getIsHUDAttachment() && attachment->getObject(0)) - { - LLViewerObject* hud_object = attachment->getObject(0); - LLDrawable* hud_drawable = hud_object->mDrawable; - - if (hud_drawable) - { - // this assumes that an AGP sync will happen because face has been backlisted, - // so that pool has been rebuilt this frame and is scheduled for a sync - for(S32 face_index = 0; face_index < hud_drawable->getNumFaces(); ++face_index) - { - LLFace* facep = hud_drawable->getFace(face_index); - if (facep->isState(LLFace::BACKLIST)) - { - facep->restore(); - } - } - } - for (U32 child_num = 0; child_num < hud_object->mChildList.size(); ++child_num) - { - LLViewerObject* childp = hud_object->mChildList[child_num]; - LLDrawable* child_drawable = childp->mDrawable; - - if (child_drawable) - { - for(S32 face_index = 0; face_index < child_drawable->getNumFaces(); ++face_index) - { - LLFace* facep = child_drawable->getFace(face_index); - if (facep->isState(LLFace::BACKLIST)) - { - facep->restore(); - } - } - } - } - } - } } //----------------------------------------------------------------------------- @@ -8059,8 +8104,7 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerImage *src_vi, { if (!aux_src->getData()) { - llwarns << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl; - src_vi->startImageDecode(); + llerrs << "No auxiliary source data for onBakedTextureMasksLoaded" << llendl; return; } @@ -8351,7 +8395,7 @@ void LLVOAvatar::dumpArchetypeXML( void* ) LLViewerImage* te_image = avatar->getTEImage( te ); if( te_image ) { - char uuid_str[UUID_STR_LENGTH]; + char uuid_str[UUID_STR_LENGTH]; /* Flawfinder: ignore */ te_image->getID().toString( uuid_str ); apr_file_printf( file, "\t\t\n", te, uuid_str); } @@ -8368,10 +8412,10 @@ void LLVOAvatar::dumpArchetypeXML( void* ) S32 LLVOAvatar::getUnbakedPixelAreaRank() { S32 rank = 1; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; if( inst == this ) { return rank; @@ -8390,16 +8434,15 @@ S32 LLVOAvatar::getUnbakedPixelAreaRank() // static void LLVOAvatar::cullAvatarsByPixelArea() { - LLVOAvatar::sInstances.bubbleSortList(); - - + std::sort(LLCharacter::sInstances.begin(), LLCharacter::sInstances.end(), CompareScreenAreaGreater()); + // Update the avatars that have changed status S32 rank = 1; - for( LLVOAvatar* inst = (LLVOAvatar*)LLCharacter::sInstances.getFirstData(); - inst; - inst = (LLVOAvatar*)LLCharacter::sInstances.getNextData() ) + for (std::vector::iterator iter = LLCharacter::sInstances.begin(); + iter != LLCharacter::sInstances.end(); ++iter) { + LLVOAvatar* inst = (LLVOAvatar*) *iter; BOOL culled; if( inst->isDead() ) { @@ -8589,8 +8632,6 @@ void LLVOAvatar::dumpLocalTextures() else { LLViewerImage* image = mLocalTexture[i]; - F32 data_progress = 0.0f; - F32 decode_progress = image->getDecodeProgress(&data_progress); llinfos << "LocTex " << names[i] << ": " << "Discard " << image->getDiscardLevel() << ", " @@ -8600,10 +8641,7 @@ void LLVOAvatar::dumpLocalTextures() // makes textures easier to steal << image->getID() << " " #endif - << "Data: " << (data_progress * 100) << "% " - << "Decode: " << (decode_progress * 100) << "% " - << "Priority: " << image->getDecodePriority() << " " - << (image->needsDecode() ? "pending decode" : "not pending decode") + << "Priority: " << image->getDecodePriority() << llendl; } } @@ -8705,7 +8743,7 @@ BOOL LLVOAvatarBoneInfo::parseXml(LLXmlTreeNode* node) } else { - llerrs << "Invalid node " << node->getName() << llendl; + llwarns << "Invalid node " << node->getName() << llendl; return FALSE; } @@ -8763,7 +8801,7 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) static LLStdStringHandle num_bones_string = LLXmlTree::addAttributeString("num_bones"); if (!node->getFastAttributeS32(num_bones_string, mNumBones)) { - llerrs << "Couldn't find number of bones." << llendl; + llwarns << "Couldn't find number of bones." << llendl; return FALSE; } @@ -8777,7 +8815,8 @@ BOOL LLVOAvatarSkeletonInfo::parseXml(LLXmlTreeNode* node) if (!info->parseXml(child)) { delete info; - llerrs << "Error parsing bone in skeleton file" << llendl; + llwarns << "Error parsing bone in skeleton file" << llendl; + return FALSE; } mBoneInfoList.push_back(info); } @@ -9099,7 +9138,7 @@ BOOL LLVOAvatarInfo::parseXmlDriverNodes(LLXmlTreeNode* root) void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) { - char filename[MAX_PATH]; + char filename[MAX_PATH]; /* Flawfinder: ignore */ // reset animated morphs setVisualParamWeight("Blink_Left", 0.f); @@ -9119,7 +9158,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) setVisualParamWeight("Hands_Spread_R", 0.f); updateVisualParams(); - sprintf(filename, "%s\\%s_skeleton.xsf", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_skeleton.xsf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9131,7 +9170,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) apr_file_printf(fp, "\n"); apr_file_close(fp); - sprintf(filename, "%s\\%s_mesh_body.xmf", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_mesh_body.xmf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ //gDirUtilp->getExpandedFilename(LL_PATH_CHARACTER,"avatar.cal").c_str() fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) @@ -9162,7 +9201,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) for (S32 i = 0; i < (has_skirt ? BAKED_TEXTURE_COUNT : BAKED_TEXTURE_COUNT - 1); i++) { - sprintf(filename, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), i); + snprintf(filename, MAX_PATH, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), i); /* Flawfinder: ignore */ LLViewerImage* viewer_imagep = mTEImages[sBakedTextureIndices[i]]; if (!viewer_imagep->getHasGLTexture()) @@ -9177,7 +9216,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) } // output image for hair - sprintf(filename, "%s\\%s_material_tex_5.tga", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_material_tex_5.tga", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ LLViewerImage* viewer_imagep = mTEImages[TEX_HAIR]; if (!viewer_imagep->getHasGLTexture()) { @@ -9192,7 +9231,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) } // save out attachments - sprintf(filename, "%s\\%s_mesh_attachments.xmf", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_mesh_attachments.xmf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9208,7 +9247,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); + LLViewerObject *attached_object = attachment->getObject(); if (attached_object && !attached_object->isDead() && attached_object->mDrawable.notNull() && attached_object->getPCode() == LL_PCODE_VOLUME) { @@ -9229,7 +9268,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) attachment; attachment = mAttachmentPoints.getNextData()) { - LLViewerObject *attached_object = attachment->getObject(0); + LLViewerObject *attached_object = attachment->getObject(); if (attached_object && !attached_object->isDead() && attached_object->getPCode() == LL_PCODE_VOLUME) { LLVOVolume* attached_volume = (LLVOVolume*)attached_object; @@ -9254,7 +9293,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) getSex() == SEX_MALE ? (LLKeyframeMotion*)findMotion(ANIM_AGENT_WALK) : (LLKeyframeMotion*)findMotion(ANIM_AGENT_FEMALE_WALK); if (FALSE)//(walk_motion) { - sprintf(filename, "%s\\%s_anim.xaf", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_anim.xaf", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9268,7 +9307,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) } // finally, write out .cfg file - sprintf(filename, "%s\\%s_avatar.cfg", path.c_str(), file_base.c_str()); + snprintf(filename, MAX_PATH, "%s\\%s_avatar.cfg", path.c_str(), file_base.c_str()); /* Flawfinder: ignore */ fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9289,7 +9328,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) for(S32 i = 0; i < 6; i++) { - sprintf(filename, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), i); + snprintf(filename, MAX_PATH, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), i); /* Flawfinder: ignore */ apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9316,7 +9355,7 @@ void LLVOAvatar::writeCAL3D(std::string& path, std::string& file_base) { LLMaterialExportInfo* export_info = material_it->second; - sprintf(filename, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), export_info->mMaterialIndex); + snprintf(filename, MAX_PATH, "%s\\%s_material_%d.xrf", path.c_str(), file_base.c_str(), export_info->mMaterialIndex); /* Flawfinder: ignore */ apr_file_t* fp = ll_apr_file_open(filename, LL_APR_W); if (!fp) { @@ -9441,3 +9480,58 @@ LLHost LLVOAvatar::getObjectHost() const return LLHost::invalid; } } + +BOOL LLVOAvatar::updateLOD() +{ + BOOL res = updateJointLODs(); + + LLFace* facep = mDrawable->getFace(0); + if (facep->mVertexBuffer.isNull() || + LLVertexBuffer::sEnableVBOs && + ((facep->mVertexBuffer->getUsage() == GL_STATIC_DRAW ? TRUE : FALSE) != + (facep->getPool()->getVertexShaderLevel() > 0 ? TRUE : FALSE))) + { + mDirtyMesh = TRUE; + } + + if (mDirtyMesh || mDrawable->isState(LLDrawable::REBUILD_GEOMETRY)) + { //LOD changed or new mesh created, allocate new vertex buffer if needed + updateMeshData(); + mDirtyMesh = FALSE; + mDrawable->clearState(LLDrawable::REBUILD_GEOMETRY); + } + + if (facep->getPool()->getVertexShaderLevel() <= 0) + { + //generate animated mesh + mLowerBodyLOD.updateGeometry(); + mUpperBodyLOD.updateGeometry(); + + if( isWearingWearableType( WT_SKIRT ) ) + { + mSkirtLOD.updateGeometry(); + } + + if (!mIsSelf || gAgent.needsRenderHead()) + { + mEyeLashLOD.updateGeometry(); + mHeadLOD.updateGeometry(); + mHairLOD.updateGeometry(); + } + } + + // Update the shadow, tractor, and text label geometry. + if (mDrawable->isState(LLDrawable::REBUILD_SHADOW)) + { + updateShadowFaces(); + mDrawable->clearState(LLDrawable::REBUILD_SHADOW); + } + + return res; +} + +U32 LLVOAvatar::getPartitionType() const +{ //avatars merely exist as drawables in the bridge partition + return LLPipeline::PARTITION_BRIDGE; +} + diff --git a/linden/indra/newview/llvoavatar.h b/linden/indra/newview/llvoavatar.h index f942273..ff37848 100644 --- a/linden/indra/newview/llvoavatar.h +++ b/linden/indra/newview/llvoavatar.h @@ -76,6 +76,13 @@ class LLDriverParamInfo; class LLHUDText; class LLHUDEffectSpiral; +class LLVertexBufferAvatar : public LLVertexBuffer +{ +public: + LLVertexBufferAvatar(); + virtual void setupVertexBuffer(U32 data_mask) const; +}; + typedef enum e_mesh_id { MESH_ID_HAIR, @@ -232,6 +239,25 @@ protected: virtual ~LLVOAvatar(); public: + + struct CompareScreenAreaGreater + { + bool operator()(const LLCharacter* const& lhs, const LLCharacter* const& rhs) + { + return lhs->getPixelArea() > rhs->getPixelArea(); + } + }; + + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_WEIGHT) | + (1 << LLVertexBuffer::TYPE_CLOTHWEIGHT) + } + eVertexDataMask; + LLVOAvatar(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); /*virtual*/ void markDead(); @@ -247,20 +273,24 @@ public: const EObjectUpdateType update_type, LLDataPacker *dp); virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + virtual BOOL updateLOD(); void setFootPlane(const LLVector4 &plane) { mFootPlane = plane; } /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. // Graphical stuff for objects - maybe broken out into render class later? - U32 renderSkinned(EAvatarRenderPass pass); + U32 renderFootShadows(); U32 renderRigid(); - + U32 renderSkinned(EAvatarRenderPass pass); + U32 renderTransparent(); void renderCollisionVolumes(); /*virtual*/ void updateTextures(LLAgent &agent); // If setting a baked texture, need to request it from a non-local sim. /*virtual*/ S32 setTETexture(const U8 te, const LLUUID& uuid); - + + virtual U32 getPartitionType() const; + void updateVisibility(BOOL force_invisible); void updateAttachmentVisibility(U32 camera_mode); void clampAttachmentPositions(); @@ -278,11 +308,14 @@ public: void updateShadowFaces(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); - void updateJointLODs(); + BOOL updateJointLODs(); void writeCAL3D(std::string& path, std::string& file_base); virtual void updateRegion(LLViewerRegion *regionp); + + + void updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax); //-------------------------------------------------------------------- // texture entry assignment @@ -342,7 +375,7 @@ public: virtual BOOL allocateCharacterJoints( U32 num ); virtual LLJoint *getCharacterJoint( U32 num ); virtual void requestStopMotion( LLMotion* motion ); - virtual F32 getPixelArea(); + virtual F32 getPixelArea() const; virtual LLPolyMesh* getHeadMesh(); virtual LLPolyMesh* getUpperBodyMesh(); virtual LLVector3d getPosGlobalFromAgent(const LLVector3 &position); @@ -362,7 +395,7 @@ public: // Other public functions //-------------------------------------------------------------------- BOOL allocateCollisionVolumes( U32 num ); - + void resetHUDAttachments(); static void getAnimLabels( LLDynamicArray* labels ); static void getAnimNames( LLDynamicArray* names ); @@ -439,6 +472,7 @@ public: virtual void addChild(LLViewerObject *childp); virtual void removeChild(LLViewerObject *childp); + LLViewerJointAttachment* getTargetAttachmentPoint(LLViewerObject* viewer_object); BOOL attachObject(LLViewerObject *viewer_object); BOOL detachObject(LLViewerObject *viewer_object); void lazyAttach(); @@ -543,7 +577,7 @@ public: //-------------------------------------------------------------------- // avatar definition name //-------------------------------------------------------------------- - char mAvatarDefinition[64]; + char mAvatarDefinition[64]; /* Flawfinder: ignore */ //-------------------------------------------------------------------- // skeleton for skinned avatar @@ -836,7 +870,6 @@ protected: F32 mRenderPriority; F32 mAdjustedPixelArea; - S32 mNumAGPVertices; LLWString mNameString; LLString mTitle; @@ -877,6 +910,8 @@ protected: U32 mLowerMaskTexName; BOOL mCulled; + F32 mMinPixelArea; // debug + F32 mMaxPixelArea; // debug //-------------------------------------------------------------------- // Global Colors @@ -903,6 +938,7 @@ protected: void requestLayerSetUpdate(LLVOAvatar::ELocTexIndex i); void addLocalTextureStats(LLVOAvatar::ELocTexIndex i, LLViewerImage* imagep, F32 texel_area_ratio, BOOL rendered, BOOL covered_by_baked); + void addBakedTextureStats( LLViewerImage* imagep, F32 pixel_area, F32 texel_area_ratio, S32 boost_level); static void onInitialBakedTextureLoaded( BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ); static void onBakedTextureLoaded(BOOL success, LLViewerImage *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata); void useBakedTexture(const LLUUID& id); diff --git a/linden/indra/newview/llvoclouds.cpp b/linden/indra/newview/llvoclouds.cpp index a4e424a..7d1d958 100644 --- a/linden/indra/newview/llvoclouds.cpp +++ b/linden/indra/newview/llvoclouds.cpp @@ -29,6 +29,8 @@ #include "llvoclouds.h" +#include "lldrawpoolalpha.h" + #include "llviewercontrol.h" #include "llagent.h" // to get camera position @@ -46,7 +48,7 @@ #include "viewer.h" LLVOClouds::LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, LL_VO_CLOUDS, regionp) +: LLAlphaObject(id, LL_VO_CLOUDS, regionp) { mCloudGroupp = NULL; mbCanSelect = FALSE; @@ -99,77 +101,132 @@ LLDrawable* LLVOClouds::createDrawable(LLPipeline *pipeline) mDrawable->setLit(FALSE); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_CLOUDS); - LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_CLOUDS); - - mDrawable->setNumFaces(1, pool, getTEImage(0)); - return mDrawable; } BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_CLOUDS); if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_CLOUDS))) return TRUE; - LLVector3 at; - LLVector3 up; - LLVector3 right; - LLVector3 normal(0.f,0.f,-1.f); - LLVector3 position_agent; - //LLVector3 v[4]; LLFace *facep; - const LLVector3 region_pos_agent = mRegionp->getOriginAgent(); - const LLVector3 camera_agent = gAgent.getCameraPositionAgent(); - LLVector3 center_offset = getPositionRegion(); - LLVector2 uvs[4]; - - uvs[0].setVec(0.f, 1.f); - uvs[1].setVec(0.f, 0.f); - uvs[2].setVec(1.f, 1.f); - uvs[3].setVec(1.f, 0.f); - - LLVector3 vtx[4]; - + S32 num_faces = mCloudGroupp->getNumPuffs(); - drawable->setNumFacesFast(num_faces, gPipeline.getPool(LLDrawPool::POOL_CLOUDS), getTEImage(0)); + if (num_faces > drawable->getNumFaces()) + { + drawable->setNumFacesFast(num_faces, NULL, getTEImage(0)); + } + + mDepth = (getPositionAgent()-gCamera->getOrigin())*gCamera->getAtAxis(); S32 face_indx = 0; for ( ; face_indx < num_faces; face_indx++) { facep = drawable->getFace(face_indx); - - LLStrider verticesp, normalsp; - LLStrider texCoordsp; - U32 *indicesp; - S32 index_offset; - - facep->setPrimType(LLTriangles); - facep->setSize(4, 6); - index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == index_offset) + if (isParticle()) { - return TRUE; + facep->setSize(1,1); } - + else + { + facep->setSize(4, 6); + } + facep->setTEOffset(face_indx); + facep->setTexture(getTEImage(0)); const LLCloudPuff &puff = mCloudGroupp->getPuff(face_indx); const LLVector3 puff_pos_agent = gAgent.getPosAgentFromGlobal(puff.getPositionGlobal()); - facep->mCenterAgent = puff_pos_agent; + facep->mCenterLocal = puff_pos_agent; + } + for ( ; face_indx < drawable->getNumFaces(); face_indx++) + { + facep = drawable->getFace(face_indx); + facep->setTEOffset(face_indx); + facep->setSize(0,0); + } + + drawable->movePartition(); + + return TRUE; +} + +BOOL LLVOClouds::isParticle() +{ + return FALSE; // gGLManager.mHasPointParameters; +} + +F32 LLVOClouds::getPartSize(S32 idx) +{ + return (CLOUD_PUFF_HEIGHT+CLOUD_PUFF_WIDTH)*0.5f; +} + +void LLVOClouds::getGeometry(S32 te, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp) +{ - LLVector3 from_camera_vec = gCamera->getAtAxis();//puff_pos_agent - camera_agent; - at = from_camera_vec; + if (te >= mCloudGroupp->getNumPuffs()) + { + return; + } + + LLDrawable* drawable = mDrawable; + LLFace *facep = drawable->getFace(te); + + if (!facep->hasGeometry()) + { + return; + } + + LLVector3 normal(0.f,0.f,-1.f); + + const LLCloudPuff &puff = mCloudGroupp->getPuff(te); + S32 index_offset = facep->getGeomIndex(); + LLColor4U color(255, 255, 255, (U8) (puff.getAlpha()*255)); + facep->setFaceColor(LLColor4(color)); + + + if (isParticle()) + { + *verticesp++ = facep->mCenterLocal; + *texcoordsp++ = LLVector2(0.5f, 0.5f); + *colorsp++ = color; + *normalsp++ = normal; + *indicesp++ = facep->getGeomIndex(); + } + else + { + LLVector3 up; + LLVector3 right; + LLVector3 at; + + const LLVector3& puff_pos_agent = facep->mCenterLocal; + LLVector2 uvs[4]; + + uvs[0].setVec(0.f, 1.f); + uvs[1].setVec(0.f, 0.f); + uvs[2].setVec(1.f, 1.f); + uvs[3].setVec(1.f, 0.f); + + LLVector3 vtx[4]; + + at = gCamera->getAtAxis(); right = at % LLVector3(0.f, 0.f, 1.f); right.normVec(); up = right % at; up.normVec(); right *= 0.5f*CLOUD_PUFF_WIDTH; up *= 0.5f*CLOUD_PUFF_HEIGHT;; - - facep->mCenterAgent = puff_pos_agent; - - LLColor4 color(1.f, 1.f, 1.f, puff.getAlpha()); - facep->setFaceColor(color); + *colorsp++ = color; + *colorsp++ = color; + *colorsp++ = color; + *colorsp++ = color; + vtx[0] = puff_pos_agent - right + up; vtx[1] = puff_pos_agent - right - up; vtx[2] = puff_pos_agent + right + up; @@ -180,10 +237,10 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) *verticesp++ = vtx[2]; *verticesp++ = vtx[3]; - *texCoordsp++ = uvs[0]; - *texCoordsp++ = uvs[1]; - *texCoordsp++ = uvs[2]; - *texCoordsp++ = uvs[3]; + *texcoordsp++ = uvs[0]; + *texcoordsp++ = uvs[1]; + *texcoordsp++ = uvs[2]; + *texcoordsp++ = uvs[3]; *normalsp++ = normal; *normalsp++ = normal; @@ -198,10 +255,28 @@ BOOL LLVOClouds::updateGeometry(LLDrawable *drawable) *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 2; } - for ( ; face_indx < drawable->getNumFaces(); face_indx++) +} + +U32 LLVOClouds::getPartitionType() const +{ + return LLPipeline::PARTITION_CLOUD; +} + +// virtual +void LLVOClouds::updateDrawable(BOOL force_damped) +{ + // Force an immediate rebuild on any update + if (mDrawable.notNull()) { - drawable->getFace(face_indx)->setSize(0,0); + mDrawable->updateXform(TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } + clearChanged(SHIFTED); +} - return TRUE; +LLCloudPartition::LLCloudPartition() +{ + mDrawableType = LLPipeline::RENDER_TYPE_CLOUDS; + mPartitionType = LLPipeline::PARTITION_CLOUD; } + diff --git a/linden/indra/newview/llvoclouds.h b/linden/indra/newview/llvoclouds.h index 1618ab6..a8846e9 100644 --- a/linden/indra/newview/llvoclouds.h +++ b/linden/indra/newview/llvoclouds.h @@ -38,7 +38,7 @@ class LLViewerCloudGroup; class LLCloudGroup; -class LLVOClouds : public LLViewerObject +class LLVOClouds : public LLAlphaObject { public: LLVOClouds(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp ); @@ -47,16 +47,29 @@ public: // Initialize data that's only inited once per class. static void initClass(); + void updateDrawable(BOOL force_damped); + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void getGeometry(S32 te, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. + BOOL isParticle(); + F32 getPartSize(S32 idx); /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area - + + void updateFaceSize(S32 idx) { } BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + virtual U32 getPartitionType() const; + void setCloudGroup(LLCloudGroup *cgp) { mCloudGroupp = cgp; } protected: LLCloudGroup *mCloudGroupp; diff --git a/linden/indra/newview/llvograss.cpp b/linden/indra/newview/llvograss.cpp index 58e5378..9201549 100644 --- a/linden/indra/newview/llvograss.cpp +++ b/linden/indra/newview/llvograss.cpp @@ -68,7 +68,7 @@ S32 LLVOGrass::sMaxGrassSpecies = 0; LLVOGrass::LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, pcode, regionp) +: LLAlphaObject(id, pcode, regionp) { mPatch = NULL; mLastPatchUpdateTime = 0; @@ -206,13 +206,13 @@ void LLVOGrass::initClass() BOOL have_all_grass = TRUE; LLString err; - char buffer[10]; + char buffer[10]; /* Flawfinder: ignore */ for (S32 i=0;igetViewHeightInPixels() / - (tan(gCamera->getView()) * range); + F32 pixels_per_meter = gCamera->getViewHeightInPixels() / (tan(gCamera->getView()) * range); - // Assume grass texture is a 1 meter by 1 meter sprite at the grass object's center - mPixelArea = (pixels_per_meter) * (pixels_per_meter); + // Assume grass texture is a 5 meter by 5 meter sprite at the grass object's center + mPixelArea = (pixels_per_meter) * (pixels_per_meter) * 25.f; } // BUG could speed this up by caching the relative_position and range calculations void LLVOGrass::updateTextures(LLAgent &agent) { - // dot_product = A B cos T - // BUT at_axis is unit, so dot_product = B cos T - LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent(); - F32 dot_product = relative_position * agent.getFrameAgent().getAtAxis(); - F32 cos_angle = dot_product / relative_position.magVec(); + F32 texel_area_ratio = 1.f; + F32 cos_angle = 1.f; if (getTEImage(0)) { - getTEImage(0)->addTextureStats(mPixelArea*20.f, 1.f, cos_angle); + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%4.0f", fsqrtf(mPixelArea))); + } + getTEImage(0)->addTextureStats(mPixelArea, texel_area_ratio, cos_angle); } } BOOL LLVOGrass::updateLOD() { + if (mDrawable->getNumFaces() <= 0) + { + return FALSE; + } + + LLFace* face = mDrawable->getFace(0); + F32 tan_angle = 0.f; S32 num_blades = 0; @@ -363,6 +370,7 @@ BOOL LLVOGrass::updateLOD() mNumBlades <<= 1; } + face->setSize(mNumBlades*8, mNumBlades*12); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); } else if (num_blades <= (mNumBlades >> 1)) @@ -372,6 +380,7 @@ BOOL LLVOGrass::updateLOD() mNumBlades >>=1; } + face->setSize(mNumBlades*8, mNumBlades*12); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); return TRUE; } @@ -382,53 +391,20 @@ BOOL LLVOGrass::updateLOD() LLDrawable* LLVOGrass::createDrawable(LLPipeline *pipeline) { pipeline->allocDrawable(this); -// mDrawable->setLit(FALSE); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GRASS); - - LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - - mDrawable->setNumFaces(1, pool, getTEImage(0)); - + return mDrawable; } BOOL LLVOGrass::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_GRASS); plantBlades(); return TRUE; } void LLVOGrass::plantBlades() { - mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); - mLastPatchUpdateTime = mPatch->getLastUpdateTime(); - - LLVector3 position; - // Create random blades of grass with gaussian distribution - F32 x,y,xf,yf,dzx,dzy; - - LLVector3 normal(0,0,1); - LLColor4U color(0,0,0,1); - - LLFace *face = mDrawable->getFace(0); - - LLStrider verticesp; - LLStrider normalsp; - LLStrider texCoordsp; - LLStrider colorsp; - - U32 *indicesp; - - face->setPool(face->getPool(), getTEImage(0)); - face->setState(LLFace::GLOBAL); - face->setSize(mNumBlades * 4, mNumBlades * 12); - face->setPrimType(LLTriangles); - S32 index_offset = face->getGeometryColors(verticesp,normalsp,texCoordsp,colorsp,indicesp); - if (-1 == index_offset) - { - return; - } - // It is possible that the species of a grass is not defined // This is bad, but not the end of the world. if (!sSpeciesTable.count(mSpecies)) @@ -437,9 +413,49 @@ void LLVOGrass::plantBlades() return; } + if (mDrawable->getNumFaces() < 1) + { + mDrawable->setNumFaces(1, NULL, getTEImage(0)); + } + + LLFace *face = mDrawable->getFace(0); + + face->setTexture(getTEImage(0)); + face->setState(LLFace::GLOBAL); + face->setSize(mNumBlades * 8, mNumBlades * 12); + face->mVertexBuffer = NULL; + face->setTEOffset(0); + face->mCenterLocal = mPosition + mRegionp->getOriginAgent(); + + mDepth = (face->mCenterLocal - gCamera->getOrigin())*gCamera->getAtAxis(); + mDrawable->setPosition(face->mCenterLocal); + mDrawable->movePartition(); + LLPipeline::sCompiles++; +} + +void LLVOGrass::getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp) +{ + mPatch = mRegionp->getLand().resolvePatchRegion(getPositionRegion()); + mLastPatchUpdateTime = mPatch->getLastUpdateTime(); + + LLVector3 position; + // Create random blades of grass with gaussian distribution + F32 x,y,xf,yf,dzx,dzy; + + LLColor4U color(255,255,255,255); + + LLFace *face = mDrawable->getFace(idx); + F32 width = sSpeciesTable[mSpecies]->mBladeSizeX; F32 height = sSpeciesTable[mSpecies]->mBladeSizeY; + U32 index_offset = face->getGeomIndex(); + for (S32 i = 0; i < mNumBlades; i++) { x = exp_x[i] * mScale.mV[VX]; @@ -449,70 +465,113 @@ void LLVOGrass::plantBlades() dzx = dz_x [i]; dzy = dz_y [i]; + LLVector3 v1,v2,v3; F32 blade_height= GRASS_BLADE_HEIGHT * height * w_mod[i]; - *texCoordsp++ = LLVector2(0, 0); - *texCoordsp++ = LLVector2(0, 0.98f); - *texCoordsp++ = LLVector2(1, 0); - *texCoordsp++ = LLVector2(1, 0.98f); + *texcoordsp++ = LLVector2(0, 0); + *texcoordsp++ = LLVector2(0, 0); + *texcoordsp++ = LLVector2(0, 0.98f); + *texcoordsp++ = LLVector2(0, 0.98f); + *texcoordsp++ = LLVector2(1, 0); + *texcoordsp++ = LLVector2(1, 0); + *texcoordsp++ = LLVector2(1, 0.98f); + *texcoordsp++ = LLVector2(1, 0.98f); position.mV[0] = mPosition.mV[VX] + x + xf; position.mV[1] = mPosition.mV[VY] + y + yf; - position.mV[2] = 0.f; position.mV[2] = mRegionp->getLand().resolveHeightRegion(position); - *verticesp++ = position + mRegionp->getOriginAgent(); + *verticesp++ = v1 = position + mRegionp->getOriginAgent(); + *verticesp++ = v1; + position.mV[0] += dzx; position.mV[1] += dzy; position.mV[2] += blade_height; - *verticesp++ = position + mRegionp->getOriginAgent(); + *verticesp++ = v2 = position + mRegionp->getOriginAgent(); + *verticesp++ = v2; position.mV[0] = mPosition.mV[VX] + x - xf; position.mV[1] = mPosition.mV[VY] + y - xf; - position.mV[2] = 0.f; position.mV[2] = mRegionp->getLand().resolveHeightRegion(position); - *verticesp++ = position + mRegionp->getOriginAgent(); + *verticesp++ = v3 = position + mRegionp->getOriginAgent(); + *verticesp++ = v3; + + LLVector3 normal1 = (v1-v2) % (v2-v3); + normal1.mV[VZ] = 0.75f; + normal1.normVec(); + LLVector3 normal2 = -normal1; + normal2.mV[VZ] = -normal2.mV[VZ]; position.mV[0] += dzx; position.mV[1] += dzy; position.mV[2] += blade_height; - *verticesp++ = position + mRegionp->getOriginAgent(); + *verticesp++ = v1 = position + mRegionp->getOriginAgent(); + *verticesp++ = v1; + + *(normalsp++) = normal1; + *(normalsp++) = normal2; + *(normalsp++) = normal1; + *(normalsp++) = normal2; - *(normalsp++) = normal; - *(normalsp++) = normal; - *(normalsp++) = normal; - *(normalsp++) = normal; + *(normalsp++) = normal1; + *(normalsp++) = normal2; + *(normalsp++) = normal1; + *(normalsp++) = normal2; *(colorsp++) = color; *(colorsp++) = color; *(colorsp++) = color; *(colorsp++) = color; + *(colorsp++) = color; + *(colorsp++) = color; + *(colorsp++) = color; + *(colorsp++) = color; *indicesp++ = index_offset + 0; - *indicesp++ = index_offset + 1; *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 4; - *indicesp++ = index_offset + 1; - *indicesp++ = index_offset + 3; *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 6; + *indicesp++ = index_offset + 4; - *indicesp++ = index_offset + 0; - *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 5; + *indicesp++ = index_offset + 3; - *indicesp++ = index_offset + 1; - *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; - index_offset += 4; + *indicesp++ = index_offset + 5; + *indicesp++ = index_offset + 7; + index_offset += 8; } LLPipeline::sCompiles++; - - face->mCenterLocal = mPosition; - } +U32 LLVOGrass::getPartitionType() const +{ + return LLPipeline::PARTITION_GRASS; +} +LLGrassPartition::LLGrassPartition() +{ + mDrawableType = LLPipeline::RENDER_TYPE_GRASS; + mPartitionType = LLPipeline::PARTITION_GRASS; + mLODPeriod = 16; + mDepthMask = TRUE; + mSlopRatio = 0.1f; + mRenderPass = LLRenderPass::PASS_GRASS; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; +} - - +// virtual +void LLVOGrass::updateDrawable(BOOL force_damped) +{ + // Force an immediate rebuild on any update + if (mDrawable.notNull()) + { + mDrawable->updateXform(TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + clearChanged(SHIFTED); +} diff --git a/linden/indra/newview/llvograss.h b/linden/indra/newview/llvograss.h index 50d5460..023db03 100644 --- a/linden/indra/newview/llvograss.h +++ b/linden/indra/newview/llvograss.h @@ -36,7 +36,7 @@ class LLSurfacePatch; class LLViewerImage; -class LLVOGrass : public LLViewerObject +class LLVOGrass : public LLAlphaObject { public: LLVOGrass(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); @@ -46,6 +46,8 @@ public: static void initClass(); static void cleanupClass(); + virtual U32 getPartitionType() const; + /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, void **user_data, U32 block_num, @@ -53,11 +55,19 @@ public: LLDataPacker *dp); static void import(FILE *file, LLMessageSystem *mesgsys, const LLVector3 &pos); /*virtual*/ void exportFile(FILE *file, const LLVector3 &position); - + + void updateDrawable(BOOL force_damped); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - + /*virtual*/ void getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp); + + void updateFaceSize(S32 idx) { } /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ BOOL updateLOD(); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area diff --git a/linden/indra/newview/llvoground.cpp b/linden/indra/newview/llvoground.cpp index 7001cb8..0ae6ed8 100644 --- a/linden/indra/newview/llvoground.cpp +++ b/linden/indra/newview/llvoground.cpp @@ -28,6 +28,7 @@ #include "llviewerprecompiledheaders.h" #include "llvoground.h" +#include "lldrawpoolground.h" #include "llviewercontrol.h" @@ -40,7 +41,7 @@ #include "pipeline.h" LLVOGround::LLVOGround(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, pcode, regionp) +: LLStaticViewerObject(id, pcode, regionp) { mbCanSelect = FALSE; } @@ -57,10 +58,10 @@ BOOL LLVOGround::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) return TRUE; } - if (mDrawable) + /*if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } + }*/ return TRUE; } @@ -75,7 +76,8 @@ LLDrawable *LLVOGround::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); - LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_GROUND); + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_GROUND); + LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND); mDrawable->addFace(poolp, NULL); @@ -87,15 +89,25 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) LLStrider verticesp; LLStrider normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; LLFace *face; + LLDrawPoolGround *poolp = (LLDrawPoolGround*) gPipeline.getPool(LLDrawPool::POOL_GROUND); + if (drawable->getNumFaces() < 1) - drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_GROUND), NULL); + drawable->addFace(poolp, NULL); face = drawable->getFace(0); - face->setPrimType(LLTriangles); - face->setSize(6, 12); + + if (face->mVertexBuffer.isNull()) + { + face->setSize(5, 12); + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolGround::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); + face->setGeomIndex(0); + face->setIndicesIndex(0); + } + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -117,68 +129,40 @@ BOOL LLVOGround::updateGeometry(LLDrawable *drawable) left_dir.normVec(); // Our center top point - LLVector3 center_top, center_bottom; - LLColor4 ground_color = gSky.getFogColor(); ground_color.mV[3] = 1.f; face->setFaceColor(ground_color); - if (gCamera->getOrigin().mV[VZ] < gAgent.getRegion()->getWaterHeight()) - { - // Underwater - //center_top = gCamera->getOrigin() + at_dir*gCamera->getFar(); - center_top = gCamera->getOrigin() - LLVector3(0, 0, 5); - center_bottom = gCamera->getOrigin() + at_dir*gCamera->getFar();; - //center_top.mV[VZ] = gAgent.getRegion()->getWaterHeight() + 0.5f; - center_bottom.mV[VZ] = -100.f; - } - else - { - // Above water - center_top = gCamera->getOrigin() - LLVector3(0, 0, 30); - if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) > 0)) - { - center_top.mV[VZ] = gAgent.getRegion()->getWaterHeight(); - } - //center_top = gCamera->getOrigin() + at_dir*9000.f; - center_bottom = gCamera->getOrigin() - at_dir*gCamera->getFar(); - //center_top.mV[VZ] = 0.f; - //center_bottom.mV[VZ] = gAgent.getRegion()->getWaterHeight(); - } - - *(verticesp++) = center_top + LLVector3(6000, 6000, 0); - *(verticesp++) = center_top + LLVector3(-6000, 6000, 0); - *(verticesp++) = center_top + LLVector3(-6000, -6000, 0); - - *(verticesp++) = center_top + LLVector3(-6000, -6000, 0); - *(verticesp++) = center_top + LLVector3(6000, -6000, 0); - *(verticesp++) = center_top + LLVector3(6000, 6000, 0); + *(verticesp++) = LLVector3(64, 64, 0); + *(verticesp++) = LLVector3(-64, 64, 0); + *(verticesp++) = LLVector3(-64, -64, 0); + *(verticesp++) = LLVector3(64, -64, 0); + *(verticesp++) = LLVector3(0, 0, -1024); // Triangles for each side *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 1; - *indicesp++ = index_offset + 3; + *indicesp++ = index_offset + 4; - *indicesp++ = index_offset + 0; - *indicesp++ = index_offset + 3; + *indicesp++ = index_offset + 1; *indicesp++ = index_offset + 2; + *indicesp++ = index_offset + 4; *indicesp++ = index_offset + 2; *indicesp++ = index_offset + 3; - *indicesp++ = index_offset + 5; + *indicesp++ = index_offset + 4; - *indicesp++ = index_offset + 2; - *indicesp++ = index_offset + 5; + *indicesp++ = index_offset + 3; + *indicesp++ = index_offset + 0; *indicesp++ = index_offset + 4; *(texCoordsp++) = LLVector2(0.f, 0.f); *(texCoordsp++) = LLVector2(1.f, 0.f); - *(texCoordsp++) = LLVector2(0.f, 1.f); *(texCoordsp++) = LLVector2(1.f, 1.f); - *(texCoordsp++) = LLVector2(0.f, 2.f); - *(texCoordsp++) = LLVector2(1.f, 2.f); - + *(texCoordsp++) = LLVector2(0.f, 1.f); + *(texCoordsp++) = LLVector2(0.5f, 0.5f); + LLPipeline::sCompiles++; return TRUE; } diff --git a/linden/indra/newview/llvoground.h b/linden/indra/newview/llvoground.h index e0d4700..5b995f8 100644 --- a/linden/indra/newview/llvoground.h +++ b/linden/indra/newview/llvoground.h @@ -34,7 +34,7 @@ #include "llviewerimage.h" #include "llviewerobject.h" -class LLVOGround : public LLViewerObject +class LLVOGround : public LLStaticViewerObject { protected: public: diff --git a/linden/indra/newview/llvopart.cpp b/linden/indra/newview/llvopart.cpp deleted file mode 100644 index 6b38cf9..0000000 --- a/linden/indra/newview/llvopart.cpp +++ /dev/null @@ -1,1358 +0,0 @@ -/** - * @file llvopart.cpp - * @brief Viewer-object derived particle system. - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llvopart.h" - -#include "llfasttimer.h" -#include "message.h" - -#include "llagent.h" -#include "lldrawable.h" -#include "llface.h" -#include "llsky.h" -#include "llviewercamera.h" -#include "llviewerimagelist.h" -#include "llviewerregion.h" -#include "pipeline.h" - -const F32 MAX_PART_LIFETIME = 120.f; - -extern U64 gFrameTime; - -LLVOPart::LLVOPart(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, pcode, regionp) -{ - mParticlesDead = FALSE; - setNumTEs(1); - setDefaultValues(); - - mbCanSelect = FALSE; // users can't select particle systems - mNumLiveParticles = 0; -} - - -LLVOPart::~LLVOPart() -{ - delete [] mParticleState; - mParticleState = NULL; - - delete [] mDeadArr; - mDeadArr = NULL; -} - -void LLVOPart::initClass() -{ -} - -U32 LLVOPart::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp) -{ - S32 dataSize; - U8 packed_psys_data[180]; - // Do base class updates... - mTimeLastFrame = gFrameTime; - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - - if (update_type == OUT_TERSE_IMPROVED) - { - // Nothing else needs to be done for the terse message. - return retval; - } - - dataSize = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); - - if(dataSize == sizeof(LLPartInitData)) - { - // Uncompressed particle. Is this used? JC - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, &mInitSysData, dataSize, block_num); - - if(mInitSysData.createMe) - { - if (mInitSysData.initialParticles >= mInitSysData.maxParticles) - { - mInitSysData.initialParticles = mInitSysData.maxParticles - 1; - } - setParticleParams(mInitSysData.bounce_b, - getPositionRegion().mV, - getRotation().mQ, - mInitSysData.maxParticles, - mInitSysData.mImageUuid, - mInitSysData.mFlags); - initializeParticlesAndConstraints(mInitSysData.initialParticles, - mInitSysData.diffEqAlpha, - mInitSysData.diffEqScale, - mInitSysData.scale_range, - mInitSysData.alpha_range, - mInitSysData.vel_offset, - mInitSysData.killPlaneZ, - mInitSysData.killPlaneNormal, - mInitSysData.bouncePlaneZ, - mInitSysData.bouncePlaneNormal, - mInitSysData.spawnRange, - mInitSysData.spawnFrequency, - mInitSysData.spawnFreqencyRange, - mInitSysData.spawnDirection, - mInitSysData.spawnDirectionRange, - mInitSysData.spawnVelocity, - mInitSysData.spawnVelocityRange, - mInitSysData.speedLimit, - mInitSysData.windWeight, - mInitSysData.currentGravity, - mInitSysData.gravityWeight, - mInitSysData.globalLifetime, - mInitSysData.individualLifetime, - mInitSysData.individualLifetimeRange, - mInitSysData.alphaDecay, - mInitSysData.scaleDecay, - mInitSysData.distanceDeath, - mInitSysData.dampMotionFactor, - mInitSysData.windDiffusionFactor); - setParticlesDistFadeout(mInitSysData.mDistBeginFadeout, - mInitSysData.mDistEndFadeout); - } - } - else if(dataSize > 4) - { - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, packed_psys_data, dataSize, block_num); - - LLPartSysCompressedPacket CompObjectData; - U32 sizeUsed; - - CompObjectData.fromUnsignedBytes(packed_psys_data, dataSize); - CompObjectData.toLLPartInitData(&mInitSysData, &sizeUsed); - - if(mInitSysData.createMe) - { - if (mInitSysData.initialParticles >= mInitSysData.maxParticles) - { - mInitSysData.initialParticles = mInitSysData.maxParticles - 1; - } - setParticleParams(mInitSysData.bounce_b, - getPositionRegion().mV, - getRotation().mQ, - mInitSysData.maxParticles, - mInitSysData.mImageUuid, - mInitSysData.mFlags); - initializeParticlesAndConstraints(mInitSysData.initialParticles, - mInitSysData.diffEqAlpha, - mInitSysData.diffEqScale, - mInitSysData.scale_range, - mInitSysData.alpha_range, - mInitSysData.vel_offset, - mInitSysData.killPlaneZ, - mInitSysData.killPlaneNormal, - mInitSysData.bouncePlaneZ, - mInitSysData.bouncePlaneNormal, - mInitSysData.spawnRange, - mInitSysData.spawnFrequency, - mInitSysData.spawnFreqencyRange, - mInitSysData.spawnDirection, - mInitSysData.spawnDirectionRange, - mInitSysData.spawnVelocity, - mInitSysData.spawnVelocityRange, - mInitSysData.speedLimit, - mInitSysData.windWeight, - mInitSysData.currentGravity, - mInitSysData.gravityWeight, - mInitSysData.globalLifetime, - mInitSysData.individualLifetime, - mInitSysData.individualLifetimeRange, - mInitSysData.alphaDecay, - mInitSysData.scaleDecay, - mInitSysData.distanceDeath, - mInitSysData.dampMotionFactor, - mInitSysData.windDiffusionFactor); - setParticlesDistFadeout(mInitSysData.mDistBeginFadeout, - mInitSysData.mDistEndFadeout); - } - } - - translateParticlesTo(getPositionRegion()); - rotateParticlesTo(getRotation()); - return retval; -} - - -BOOL LLVOPart::isActive() const -{ - return TRUE; -} - -BOOL LLVOPart::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - if (mDeathTimer.getElapsedTimeF32() > MAX_PART_LIFETIME) - { - //llinfos << "LLVOPart dead due to extended lifetime" << llendl; - return FALSE; - } - - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)) - { - if (!mDrawable) - { - llwarns << "LLVOPart idle with no drawable!" << llendl; - return FALSE; - } - // I don't know why you'd want to do ANYTHING with invisible particles. ??? - Doug - if(mFlags[PART_SYS_INVISIBLE_BYTE] & PART_SYS_INVISIBLE_BIT) - { - llwarns << "Invisible particle, killing" << llendl; - return FALSE; - } - - F64 delta_time = ((S64)(gFrameTime - mTimeLastFrame))*(1.0/((F64)USEC_PER_SEC)); - mParticlesDead = !iterateParticles((F32)delta_time); - - if(mParticlesDead) - { - return FALSE; - } - - translateParticlesTo(getPositionRegion()); - - mTimeLastFrame = gFrameTime; - setChanged(GEOMETRY); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - - } - LLViewerObject::idleUpdate(agent, world, time); - return TRUE; -} - - -void LLVOPart::updateTextures(LLAgent &agent) -{ - if (getTEImage(0)) - { - LLVector3 relative_position = getPositionAgent() - agent.getCameraPositionAgent(); - F32 dot_product = relative_position * agent.getFrameAgent().getAtAxis(); - F32 cos_angle = dot_product / relative_position.magVec(); - - if (cos_angle > 1.f) - { - cos_angle = 1.f; - } - - getTEImage(0)->addTextureStats(mPixelArea, 1.f, cos_angle); - } -} - - -LLDrawable* LLVOPart::createDrawable(LLPipeline *pipeline) -{ - pipeline->allocDrawable(this); - mDrawable->setLit(FALSE); - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - - LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - mDrawable->setNumFaces(mNumPart, pool, getTEImage(0)); - return mDrawable; -} - -BOOL LLVOPart::updateGeometry(LLDrawable *drawable) -{ - if (isChanged(LLPrimitive::GEOMETRY)) - { - LLFace *face; - - /////////////////////// - // - // Allocate/deallocate faces based on number of particles we need to render - // - // - if (drawable->getNumFaces()) - { - face = drawable->getFace(0); - drawable->setNumFaces(mNumPart, face->getPool(), getTEImage(0)); - } - else - { - LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - drawable->setNumFaces(mNumPart, pool, getTEImage(0)); - } - - LLVector3 light_norm; - - if (gSky.sunUp()) - { - light_norm = -gSky.getSunDirection(); - } - else - { - light_norm = -gSky.getMoonDirection(); - } - light_norm.normVec(); - - // Figure out the lighting for the particle system. - LLColor4 color(1.f,1.f,1.f,1.f); - LLVector3 at, left, up; - - at = gCamera->getAtAxis(); - left = gCamera->getLeftAxis(); - up = gCamera->getUpAxis(); - - LLVector3 v_agent[4]; - - LLMatrix3 cached_oo; - cached_oo.setRot(mOriginOrientation); - U32 i; - U32 cur_face = 0; - for (i = 0; i < mNumPart; i++) - { - face = drawable->getFace(cur_face++); - - if (0 != mDeadArr[i]) - { - face->setSize(0); - continue; // if this particle is dead, don't render it - } - - - LLStrider verticesp; - LLStrider normalsp; - LLStrider texCoordsp; - U32 *indicesp; - S32 index_offset; - - face->setPrimType(LLTriangles); - face->setSize(4, 6); - index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == index_offset) - { - llerrs << "Error allocating geometry!" << llendl; - } - - LLVector3 position_agent; - LLVector3 part_pos_local; - F32 alpha = 1.0f; - F32 scale = 1.0f; // elements of the particle system have random scales too! -- MDS - - position_agent = mSpawnPoint + getRegion()->getOriginAgent(); - - if(mFlags[PART_SYS_FOLLOW_VEL_BYTE] & PART_SYS_FOLLOW_VEL_BIT) - { - part_pos_local.mV[0] = mParticleState[i].position[0]*cached_oo.mMatrix[0][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[0][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[0][2]; - - part_pos_local.mV[1] = mParticleState[i].position[0]*cached_oo.mMatrix[1][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[1][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[1][2]; - - part_pos_local.mV[2] = mParticleState[i].position[0]*cached_oo.mMatrix[2][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[2][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[2][2]; - - scale = mParticleState[i].scale[0]; - alpha = mParticleState[i].alpha[0]; - - //26 September 2001 - alter alpha and scale as approach death - //j = death_offset_i(i); - scale *= ((1.f - mScaleDecay) + (mScaleDecay * mParticleState[i].deathOffset)); - alpha *= ((1.f - mAlphaDecay) + (mAlphaDecay * mParticleState[i].deathOffset)); - - up.mV[0] = -mParticleState[i].position[0]; - up.mV[1] = -mParticleState[i].position[1]; - up.mV[2] = -mParticleState[i].position[2]; // set "up" to trail velocity - - if(up.magVec() == 0.0f) // alleviate potential divide by zero bug - { - up.mV[2] += 1.0f; - } - - up.normVec(); - up = up - (up*at) * at; - - left = up % at; - - up *= scale * 0.5f; - left *= scale * 0.5f; - position_agent += part_pos_local; - face->mCenterAgent = position_agent; - v_agent[0] = position_agent + left + up; - v_agent[1] = position_agent - left + up; - v_agent[2] = position_agent - left - up; - v_agent[3] = position_agent + left - up; - *(texCoordsp) = LLVector2(0.f, 1.f); - texCoordsp++; - *(texCoordsp) = LLVector2(0.f, 0.f); - texCoordsp++; - *(texCoordsp) = LLVector2(1.f, 1.f); - texCoordsp++; - *(texCoordsp) = LLVector2(1.f, 0.f); - texCoordsp++; - } - else - { - part_pos_local.mV[0] = mParticleState[i].position[0]*cached_oo.mMatrix[0][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[0][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[0][2]; - - part_pos_local.mV[1] = mParticleState[i].position[0]*cached_oo.mMatrix[1][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[1][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[1][2]; - - part_pos_local.mV[2] = mParticleState[i].position[0]*cached_oo.mMatrix[2][0]+ - mParticleState[i].position[1]*cached_oo.mMatrix[2][1]+ - mParticleState[i].position[2]*cached_oo.mMatrix[2][2]; - - - scale = mParticleState[i].scale[0]; - alpha = mParticleState[i].alpha[0]; - - //26 September 2001 - alter alpha and scale as approach death - scale *= ((1.f - mScaleDecay) + (mScaleDecay * mParticleState[i].deathOffset)); - alpha *= ((1.f - mAlphaDecay) + (mAlphaDecay * mParticleState[i].deathOffset)); - - LLVector3 part_up = scale * 0.5f * up; - LLVector3 part_left = scale * 0.5f * left; - - position_agent += part_pos_local; - face->mCenterAgent = position_agent; - v_agent[0] = position_agent + part_left + part_up; - v_agent[1] = position_agent - part_left + part_up; - v_agent[2] = position_agent - part_left - part_up; - v_agent[3] = position_agent + part_left - part_up; - *(texCoordsp) = LLVector2(0.f, 1.f); - texCoordsp++; - *(texCoordsp) = LLVector2(0.f, 0.f); - texCoordsp++; - *(texCoordsp) = LLVector2(1.f, 1.f); - texCoordsp++; - *(texCoordsp) = LLVector2(1.f, 0.f); - texCoordsp++; - } - - color.mV[3] = alpha; - face->setFaceColor(color); - - *(verticesp++) = v_agent[1]; - *(verticesp++) = v_agent[2]; - *(verticesp++) = v_agent[0]; - *(verticesp++) = v_agent[3]; - - *(indicesp++) = index_offset + 0; - *(indicesp++) = index_offset + 2; - *(indicesp++) = index_offset + 1; - - *(indicesp++) = index_offset + 1; - *(indicesp++) = index_offset + 2; - *(indicesp++) = index_offset + 3; - } - LLPipeline::sCompiles++; - } - - return TRUE; -} - - -void LLVOPart::setDefaultValues() -{ - U32 i; - - // initialize to safe but meaningless values : no other constructors - mParticleState = NULL; - mNumPart = 0; - mAlpha = 1.0f; - mLastTime = mCurrTime = 0.0f; - //mOriginPosition[0] = mOriginPosition[1] = mOriginPosition[2] = 0.0f; - mOriginOrientation.setQuatInit(0.0f, 0.0f, 0.0f, 1.0f); - mDeadArr = NULL; - - mKillPlaneNormal.mV[VX] = 0.0f;//Straight up - needs to be unit - mKillPlaneNormal.mV[VY] = 0.0f; - mKillPlaneNormal.mV[VZ] = 1.0f; - - mBouncePlaneNormal.mV[VX] = 0.0f;//Straight up - needs to be unit - mBouncePlaneNormal.mV[VY] = 0.0f; - mBouncePlaneNormal.mV[VZ] = 1.0f; - - mSpawnPoint.mV[VX] = 0.0f; - mSpawnPoint.mV[VY] = 0.0f; - mSpawnPoint.mV[VZ] = 0.0f; - - mSpawnDirection.mV[VX] = 0.0f;//Straight up - needs to be unit - mSpawnDirection.mV[VY] = 0.0f; - mSpawnDirection.mV[VZ] = 1.0f; - - mCurrentWind.mV[VX] = 0.0f; - mCurrentWind.mV[VY] = 0.0f; - mCurrentWind.mV[VZ] = 0.0f; - - mCurrentWindMagnitude = 0.0f; - mCurrentWindMagnitudeSquareRoot = 0.0f; - - mCurrentGravity.mV[VX] = 0.0f;//Straight down - mCurrentGravity.mV[VY] = 0.0f; - mCurrentGravity.mV[VZ] = -9.81f; - - mVelocityOffset.mV[VX] = 0.0f; - mVelocityOffset.mV[VY] = 0.0f; - mVelocityOffset.mV[VZ] = 0.0f; - - for(i = 0; i < PART_SYS_BYTES_OF_FLAGS; i++) - { - mFlags[i] = 0x00; - } - - //set default action and kill flags - //These defaults are for an explosion - a short lived set of debris affected by gravity. - //Action flags default to PART_SYS_AFFECTED_BY_WIND + PART_SYS_AFFECTED_BY_GRAVITY + PART_SYS_DISTANCE_DEATH - mFlags[PART_SYS_ACTION_BYTE] = PART_SYS_AFFECTED_BY_WIND | PART_SYS_AFFECTED_BY_GRAVITY | PART_SYS_DISTANCE_DEATH; - mFlags[PART_SYS_KILL_BYTE] = PART_SYS_DISTANCE_DEATH + PART_SYS_TIME_DEATH; - - for (i = 0; i < 3; i++) - { - mDiffEqAlpha[i] = 0.0f; - mDiffEqScale[i] = 0.0f; - } - - mScale_range[0] = 1.00f; - mScale_range[1] = 5.00f; - mScale_range[2] = mScale_range[3] = 0.0f; - - mAlpha_range[0] = mAlpha_range[1] = 1.0f; - mAlpha_range[2] = mAlpha_range[3] = 0.0f; - - - mKillPlaneZ = 0.0f; - mBouncePlaneZ = 0.0f; - - mSpawnRange = 1.0f; - mSpawnFrequency = 0.0f; - mSpawnFrequencyRange = 0.0f; - mSpawnDirectionRange = 1.0f; //everywhere - mSpawnVelocity = 0.75f; - mSpawnVelocityRange = 0.25f; //velocity +/- 0.25 - mSpeedLimitSquared = 1.0f; - mWindWeight = 0.5f; //0.0f means looks like a heavy object (if gravity is on), 1.0f means light and fluffy - mGravityWeight = 0.5f; //0.0f means boyed by air, 1.0f means it's a lead weight - mGlobalLifetime = 0.0f; //Arbitrary, but default is no global die, so doesn't matter - mOriginalGlobalLifetime = 0.0f; - mIndividualLifetime = 5.0f; - if (mIndividualLifetime > 0.0f) - { - mOneOverIndividualLifetime = 1.0f / mIndividualLifetime; - } - else - { - mOneOverIndividualLifetime = 0.0f; - } - mIndividualLifetimeRange = 1.0f; //Particles last 5 secs +/- 1 - mAlphaDecay = 1.0f; //normal alpha fadeout - mScaleDecay = 0.0f; //no scale decay - mDistanceDeathSquared = 10.0f; //die if hit unit radius - if (mDistanceDeathSquared > 0.0f) - { - mOneOverDistanceDeathSquared = 1.0f / mDistanceDeathSquared; - } - else - { - mOneOverDistanceDeathSquared = 0.0f; - } - mDampMotionFactor = 0.0f; - - mWindDiffusionFactor.mV[VX] = 0.0f; - mWindDiffusionFactor.mV[VY] = 0.0f; - mWindDiffusionFactor.mV[VZ] = 0.0f; - - mUpdatePhysicsInputsTime = mCurrTime; -} - - -U8 LLVOPart::setParticlesDistFadeout(F32 beginFadeout, F32 endFadeout) -{ - // This doesn't do anything... - return 1; -} - -unsigned char LLVOPart::setParticleParams(F32 bounce_b, - const F32 o_pos[3], - const F32 o_or[3], - U32 n, - LLUUID image_uuid, - U8 flags[PART_SYS_BYTES_OF_FLAGS]) -{ - mBounceBehavior = bounce_b; - mSpawnPoint.setVec(o_pos[0], o_pos[1], o_pos[2]); - - mOriginOrientation.setQuatInit(o_or[0], o_or[1], o_or[2], - (F32)sqrt(1.0f - o_or[0]*o_or[0] - o_or[1]*o_or[1] - o_or[2]*o_or[2])); - - if(mNumPart < n ) - { - // this crazy logic is just in case "setParams" gets called multiple times - if(mNumPart != 0) - { - if(mParticleState != NULL) - { - delete [] mParticleState; - } - if(mDeadArr != NULL) - { - delete [] mDeadArr; - } - - mParticleState = NULL; - mDeadArr = NULL; - mNumPart = 0; - } - mNumPart = n; - //state_arr = new F32[n*FLOATS_PER_PARTICLE]; - mParticleState = new OneParticleData[n]; - mDeadArr = new U8[n]; - memset(mDeadArr,1,n); // initialize these to 1; - } - else - { - mNumPart = n; - } - - setTETexture(0, image_uuid); - - for(U32 i = 0; i< PART_SYS_BYTES_OF_FLAGS; i++) - { - mFlags[i] = flags[i]; - } - - return '\0'; // success -} - - -void LLVOPart::setParticleCountdownStateWaitingDead(const U32 particleNumber) -{ - F32 frequency; - - frequency = mSpawnFrequency; - // **** Hack! remainingLifetime counts up from negative, to avoid subtracts! - djs - mParticleState[particleNumber].remainingLifetime = -(((mSpawnFrequencyRange * 2.0f)*ll_frand()) + frequency - mSpawnFrequencyRange); -} - -//Can override later -void LLVOPart::spawnParticle(const U32 particleNumber) -{ - F32 randomUnitValue; - LLVector3 direction; - - if (particleNumber >= mNumPart) - { - llinfos << "Trying to spawn particle beyond initialized particles! " << particleNumber << " : " << mNumPart << llendl; - return; - } - - mDeadArr[particleNumber] = 0; // not dead yet! - - //j = pos_offset_i(particleNumber); - mParticleState[particleNumber].position[0] = 2.f*mSpawnRange*(ll_frand()) - mSpawnRange; - mParticleState[particleNumber].position[1] = 2.f*mSpawnRange*(ll_frand()) - mSpawnRange; - mParticleState[particleNumber].position[2] = 2.f*mSpawnRange*(ll_frand()) - mSpawnRange; - - //mParticleStateArray[j] = (pos_ranges[1] - pos_ranges[0])*(F32)rand()/((F32)RAND_MAX) + pos_ranges[0]; - //j++; - - //mParticleStateArray[j] = (pos_ranges[3] - pos_ranges[2])*(F32)rand()/((F32)RAND_MAX) + pos_ranges[2]; - //j++; - - //mParticleStateArray[j] = (pos_ranges[5] - pos_ranges[4])*(F32)rand()/((F32)RAND_MAX) + pos_ranges[4]; - - //Create the ranged direction vector first - then rotate by the actual direction and then scale - //Creating a random value about 1,0,0 - //1. pick a random angle YZ orientation through full circle. - randomUnitValue = (ll_frand()); - direction.mV[VY] = sinf(randomUnitValue * 2.0 * F_PI); - direction.mV[VZ] = cosf(randomUnitValue * 2.0 * F_PI); - - //2. pick a rotation to this angle to project into z which is scaled by mSpawnDirectionRange - randomUnitValue = (ll_frand()); - randomUnitValue *= mSpawnDirectionRange; - direction.mV[VY] = direction.mV[VY] * sinf(randomUnitValue * F_PI); - direction.mV[VZ] = direction.mV[VZ] * sinf(randomUnitValue * F_PI); - direction.mV[VX] = cosf(randomUnitValue * F_PI); //works as still dealing with a unit vector - - //3.To rotate into the spawn direction coord system, derive a yaw and pitch (roll doesnt matter) - //from the offset between the unit vector 1,0,0 and random direction. - {F32 length; - - //TODO - math behind this may be incorrect - //Assume the initial axis is +ve x - //derive pitch using the XZ or XY components. - //derive yaw using YZ components. - length = (mSpawnDirection.mV[VY]*mSpawnDirection.mV[VY]) + - (mSpawnDirection.mV[VZ]*mSpawnDirection.mV[VZ]); - if (length > 0.0f) - {//Only happens when spawn a particle, so can afford some heavy math. - F32 xYaw, yYaw, xPitch, yPitch; - LLVector3 tempResult, tempResult2; - - //Pitch is the XZ component (but if Z is 0 and Y is not, switch) - tempResult.setVec(mSpawnDirection.mV[VX], mSpawnDirection.mV[VY], mSpawnDirection.mV[VZ]); - if (0.0f != mSpawnDirection.mV[VZ]) - { - length = sqrtf((mSpawnDirection.mV[VX]*mSpawnDirection.mV[VX]) + - (mSpawnDirection.mV[VZ]*mSpawnDirection.mV[VZ])); - if (length > 0.0f) - { - xPitch = tempResult.mV[VX] / length; - yPitch = -tempResult.mV[VZ] / length; - } - else - {//length is 0, so no x component, so pitch must be PI/2 - xPitch = 0.0f; - yPitch = 1.0f; - } - - //To obtain yaw, remove pitch from the direction vector by inverse rotation (negate the yPitch) - tempResult2.mV[VX] = (tempResult.mV[VX] * xPitch) + (tempResult.mV[VZ] * (-yPitch)); - tempResult2.mV[VY] = tempResult.mV[VY]; - tempResult2.mV[VZ] = (tempResult.mV[VZ] * xPitch) - (tempResult.mV[VX] * (-yPitch)); - } - else - {//Need XY, because if XZ is zero there is no pitch, and yaw may not pick up the discrepancy. - //This also avoids roll, so less math. - length = sqrtf((mSpawnDirection.mV[VX]*mSpawnDirection.mV[VX]) + - (mSpawnDirection.mV[VY]*mSpawnDirection.mV[VY])); - if (length > 0.0f) - { - xPitch = tempResult.mV[VX] / length; - yPitch = -tempResult.mV[VY] / length; - } - else - {//length is 0, so no x component, so pitch must be PI/2 - xPitch = 0.0f; - yPitch = 1.0f; - } - - //To obtain yaw, remove pitch from the direction vector by inverse rotation (negate the yPitch) - tempResult2.mV[VX] = (tempResult.mV[VX] * xPitch) + (tempResult.mV[VY] * (-yPitch)); - tempResult2.mV[VY] = (tempResult.mV[VY] * xPitch) - (tempResult.mV[VX] * (-yPitch)); - tempResult2.mV[VZ] = tempResult.mV[VZ]; - } - - //Yaw is the YZ component - length = sqrtf((tempResult2.mV[VZ]*tempResult2.mV[VZ]) + - (tempResult2.mV[VY]*tempResult2.mV[VY])); - if (length > 0.0f) - { - xYaw = tempResult2.mV[VZ] / length; - yYaw = tempResult2.mV[VY] / length; - } - else - { - xYaw = 1.0f; - yYaw = 0.0f; - } - - //Now apply the rotations to the actual data in the same order as derived above (pitch first) - tempResult.setVec(direction.mV[VX], direction.mV[VY], direction.mV[VZ]); - //Remember which axis pitch was on, as need to apply in the same manner here for consistency. - if (0.0f != mSpawnDirection.mV[VZ]) - { - tempResult2.mV[VX] = (tempResult.mV[VX] * xPitch) + (tempResult.mV[VZ] * yPitch); - tempResult2.mV[VY] = tempResult.mV[VY]; - tempResult2.mV[VZ] = (tempResult.mV[VZ] * xPitch) - (tempResult.mV[VX] * yPitch); - } - else - { - tempResult2.mV[VX] = (tempResult.mV[VX] * xPitch) + (tempResult.mV[VY] * yPitch); - tempResult2.mV[VY] = (tempResult.mV[VY] * xPitch) - (tempResult.mV[VX] * yPitch); - tempResult2.mV[VZ] = tempResult.mV[VZ]; - } - direction.mV[VX] = tempResult2.mV[VX]; - direction.mV[VY] = (tempResult2.mV[VY] * xYaw) + (tempResult2.mV[VZ] * yYaw); - direction.mV[VZ] = (tempResult2.mV[VZ] * xYaw) - (tempResult2.mV[VY] * yYaw); - } - else - {//The is no YZ component, so we a pointing straight along X axis (default) & therefore no rotation - //However, direction may be reversed - if (mSpawnDirection.mV[VX] < 0.0f) - { - direction.mV[VX] = -direction.mV[VX]; - direction.mV[VZ] = -direction.mV[VZ]; - } - - } - } - - - //4. scale the vector by a random scale by mSpawnVelocityRange and offset by mSpawnVelocity - randomUnitValue = (ll_frand()); - randomUnitValue = (randomUnitValue * mSpawnVelocityRange) + mSpawnVelocity; - - mParticleState[particleNumber].velocity[0] = direction.mV[VX] * randomUnitValue; - mParticleState[particleNumber].velocity[1] = direction.mV[VY] * randomUnitValue; - mParticleState[particleNumber].velocity[2] = direction.mV[VZ] * randomUnitValue; - - //add in velocity offset to match what spawned these particles - mParticleState[particleNumber].velocity[0] += mVelocityOffset.mV[VX]; - mParticleState[particleNumber].velocity[1] += mVelocityOffset.mV[VY]; - mParticleState[particleNumber].velocity[2] += mVelocityOffset.mV[VZ]; - - mParticleState[particleNumber].acceleration[0] = 0.0f; - - mParticleState[particleNumber].acceleration[1] = 0.0f; - - mParticleState[particleNumber].acceleration[2] = 0.0f; - - mParticleState[particleNumber].scale[0] = (mScale_range[1] - mScale_range[0])*ll_frand() + mScale_range[0]; - mParticleState[particleNumber].scale[1] = (mScale_range[3] - mScale_range[2])*ll_frand() + mScale_range[2]; - mParticleState[particleNumber].scale[2] = 0.0f; - - mParticleState[particleNumber].alpha[0] = (mAlpha_range[1] - mAlpha_range[0])*ll_frand() + mAlpha_range[0]; - mParticleState[particleNumber].alpha[1] = (mAlpha_range[3] - mAlpha_range[2])*ll_frand() + mAlpha_range[2]; - mParticleState[particleNumber].alpha[2] = 0.0f; - - // **** Hack! remainingLifetime counts up from negative, to avoid subtracts! - djs - mParticleState[particleNumber].remainingLifetime = -((mIndividualLifetimeRange*2.0f)*ll_frand() + mIndividualLifetime - mIndividualLifetimeRange); - - //rest of the state - 0 for now - mParticleState[particleNumber].deathOffset = 0.0f; - mParticleState[particleNumber].localWind[0] = 0.0f; - mParticleState[particleNumber].localWind[1] = 0.0f; - mParticleState[particleNumber].localWind[2] = 0.0f; -} - -//Can override later -void LLVOPart::onParticleBounce(const U32 particleNumber) -{ - mParticleState[particleNumber].velocity[0] += - (1.0f + mBounceBehavior) * mBouncePlaneNormal.mV[0] * mParticleState[particleNumber].velocity[0]; - mParticleState[particleNumber].velocity[1] += - (1.0f + mBounceBehavior) * mBouncePlaneNormal.mV[1] * mParticleState[particleNumber].velocity[1]; - mParticleState[particleNumber].velocity[2] += - (1.0f + mBounceBehavior) * mBouncePlaneNormal.mV[2] * mParticleState[particleNumber].velocity[2]; - - - //Need to offset particle so above the plane, so it doesn't oscillate! - if (mParticleState[particleNumber].position[2] < mBouncePlaneZ) - { - mParticleState[particleNumber].position[2] = mBouncePlaneZ; - } -} - - -unsigned char LLVOPart::initializeParticlesAndConstraints(U32 initialParticles, - F32 diffEqAlpha[3], - F32 diffEqScale[3], - F32 scale_ranges[4], - F32 alpha_ranges[4], - F32 velocityOffset[3], - F32 killPlaneZ, - F32 killPlaneNormal[3], - F32 bouncePlaneZ, - F32 bouncePlaneNormal[3], - F32 spawnRange, - F32 spawnFrequency, - F32 spawnFrequencyRange, - F32 spawnDirection[3], - F32 spawnDirectionRange, - F32 spawnVelocity, - F32 spawnVelocityRange, - F32 speedLimit, - F32 windWeight, - F32 currentGravity[3], - F32 gravityWeight, - F32 globalLifetime, - F32 individualLifetime, - F32 individualLifetimeRange, - F32 alphaDecay, - F32 scaleDecay, - F32 distanceDeath, - F32 dampMotionFactor, - F32 windDiffusionFactor[3]) -{ - // initializes particles randomly within these ranges - // scale ranges and alpha ranges contain initial conditions plus rates of change - // of initial conditions My naming is incosistent (passing alpha derivatives with alpha - // values), but this class is wrapped by another one, and this function is called only once - U32 i; - - - for (i = 0; i < 3; i++) - { - mDiffEqAlpha[i] = diffEqAlpha[i]; - mDiffEqScale[i] = diffEqScale[i]; - } - - //First - store the initial conditions - for (i = 0; i < 4; i++) - { - mScale_range[i] = scale_ranges[i]; - mAlpha_range[i] = alpha_ranges[i]; - } - - mVelocityOffset.setVec(velocityOffset[0], velocityOffset[1], velocityOffset[2]); - - mKillPlaneZ = killPlaneZ; - mKillPlaneNormal.setVec(killPlaneNormal[0], killPlaneNormal[1], killPlaneNormal[2]); - mKillPlaneNormal.normVec(); - mBouncePlaneZ = bouncePlaneZ; - mBouncePlaneNormal.setVec(bouncePlaneNormal[0], bouncePlaneNormal[1], bouncePlaneNormal[2]); - mBouncePlaneNormal.normVec(); - - mSpawnRange = spawnRange; - - mSpawnFrequency = spawnFrequency; - mSpawnFrequencyRange = spawnFrequencyRange; - - mSpawnDirection.setVec(spawnDirection[0], spawnDirection[1], spawnDirection[2]); - mSpawnDirection.normVec(); - mSpawnDirectionRange = spawnDirectionRange; - - mSpawnVelocity = spawnVelocity; - mSpawnVelocityRange = spawnVelocityRange; - mSpeedLimitSquared = speedLimit * speedLimit; - if (mSpeedLimitSquared < 0.0000001f) - { - mSpeedLimitSquared = 0.0000001f; //speed must be finite +ve to avoid divide by zero - } - - mWindWeight = windWeight; - mCurrentGravity.setVec(currentGravity[0], currentGravity[1], currentGravity[2]); - mGravityWeight = gravityWeight; - - mGlobalLifetime = globalLifetime; - mOriginalGlobalLifetime = mGlobalLifetime; - mIndividualLifetime = individualLifetime; - if (mIndividualLifetime > 0.0f) - { - mOneOverIndividualLifetime = 1.0f / mIndividualLifetime; - } - else - { - mOneOverIndividualLifetime = 0.0f; - } - mIndividualLifetimeRange = individualLifetimeRange; - - mAlphaDecay = alphaDecay; - mScaleDecay = scaleDecay; - mDistanceDeathSquared = distanceDeath * distanceDeath; - if (mDistanceDeathSquared > 0.0f) - { - mOneOverDistanceDeathSquared = 1.0f / mDistanceDeathSquared; - } - else - { - mOneOverDistanceDeathSquared = 0.0f; - } - mDampMotionFactor = dampMotionFactor; - - mWindDiffusionFactor.setVec(windDiffusionFactor[0], windDiffusionFactor[1], windDiffusionFactor[2]); - //Scale the values down a lot, as can expand sprites incredibly fast - mWindDiffusionFactor *= 0.02f; - if (mWindDiffusionFactor.mV[VX] > 0.02f) - { - mWindDiffusionFactor.mV[VX] = 0.02f; - } - if (mWindDiffusionFactor.mV[VY] > 0.02f) - { - mWindDiffusionFactor.mV[VY] = 0.02f; - } - if (mWindDiffusionFactor.mV[VZ] > 0.02f) - { - mWindDiffusionFactor.mV[VZ] = 0.02f; - } - //llinfos << "Made a particle system" << llendl; - - for(i = 0; i < initialParticles; i++) - { - spawnParticle(i); - } - - for(i = initialParticles; i < mNumPart; i++) - { - //create initial conditions - dead waiting to live timer - setParticleCountdownStateWaitingDead(i); - } - return '\0'; // success -} - -U8 LLVOPart::iterateParticles(F32 deltaT) -{ - const F32 PART_SYS_UPDATE_PHYSICS_INPUTS_TIME = 0.2f; //How many seconds between querying wind force on a particle - - U32 i; //, pos_off, vel_off, scale_off, alpha_off, lifetime_off, death_off, local_wind_off; - F32 weightedDeathSum; - U8 any_leftQ = 0; - - F32 windWeightDT = mWindWeight*deltaT; - F32 gravityWeightDT = mGravityWeight*deltaT; - - mLastTime = mCurrTime; - mCurrTime += deltaT; - - if ((mCurrTime - mUpdatePhysicsInputsTime) > PART_SYS_UPDATE_PHYSICS_INPUTS_TIME) - { - // If needed, obtain latest wind for the whole system - mCurrentWind = mRegionp->mWind.getVelocity(getPositionRegion()); - mCurrentWindMagnitude = sqrt((mCurrentWind.mV[VX] * mCurrentWind.mV[VX]) + - (mCurrentWind.mV[VY] * mCurrentWind.mV[VY]) + - (mCurrentWind.mV[VZ] * mCurrentWind.mV[VZ])); - //don't know a max, so just make up a reasonably large value for now and cap. - mCurrentWindMagnitude = mCurrentWindMagnitude * 0.05f; - if (mCurrentWindMagnitude > 1.0f) - { - mCurrentWindMagnitude = 1.0f; - } - mCurrentWindMagnitudeSquareRoot = sqrtf(mCurrentWindMagnitude); - } - - //TO DO - LOD algorithm (as with display??) - for(i = 0; i < mNumPart; i++) - { - //lifetime_off = remaining_lifetime_offset_i(i); - if(0 != mDeadArr[i]) - { - //test for spawns amongst the dead as follows - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_SPAWN) - { - // **** Hack! remainingLifetime counts up from negative, to avoid subtracts! - djs - //if die below and spawn flag set, set mParticleState[i].remainingLifetime to a respawn random time - //based on mSpawnFrequency and mSpawnFrequencyRange - //in this section, if spawn flag set, count down - deltaT. If time is negative, call Spawn method, else continue - mParticleState[i].remainingLifetime += deltaT; - if (mParticleState[i].remainingLifetime > 0.0f) - { - spawnParticle(i); - } - } - - if(0 != mDeadArr[i]) - { - continue; // stop animating dead particles -- else they might come back alive! - // since we're not alive, do nothing to "any_leftQ" - } - } - - - //New way - apply external forces to each particle and then update - // position at .... - mParticleState[i].position[0] += mParticleState[i].velocity[0]*deltaT; // x position - mParticleState[i].position[1] += mParticleState[i].velocity[1]*deltaT; // y position - mParticleState[i].position[2] += mParticleState[i].velocity[2]*deltaT; // z position - - //then apply force if required - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_AFFECTED_BY_WIND) - { - mParticleState[i].velocity[0] += mCurrentWind.mV[0]*windWeightDT; - mParticleState[i].velocity[1] += mCurrentWind.mV[1]*windWeightDT; - mParticleState[i].velocity[2] += mCurrentWind.mV[2]*windWeightDT; - } - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_AFFECTED_BY_GRAVITY) - { - mParticleState[i].velocity[0] += mCurrentGravity.mV[0]*gravityWeightDT; - mParticleState[i].velocity[1] += mCurrentGravity.mV[1]*gravityWeightDT; - mParticleState[i].velocity[2] += mCurrentGravity.mV[2]*gravityWeightDT; - } - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_EVALUATE_WIND_PER_PARTICLE) - { - if ((mCurrTime - mUpdatePhysicsInputsTime) > PART_SYS_UPDATE_PHYSICS_INPUTS_TIME) - { - LLVector3 wind, current_position_region; - // If needed, obtain latest wind per particle - //Particle positions are relative to the object center. - current_position_region.setVec(getPositionRegion()); - current_position_region.mV[VX] += (mParticleState[i].position[0]); - current_position_region.mV[VY] += (mParticleState[i].position[1]); - current_position_region.mV[VZ] += (mParticleState[i].position[2]); - - wind = mRegionp->mWind.getVelocity(current_position_region); - mParticleState[i].localWind[0] = wind.mV[0]; - mParticleState[i].localWind[1] = wind.mV[1]; - mParticleState[i].localWind[2] = wind.mV[2]; - } - mParticleState[i].velocity[0] += mParticleState[i].localWind[0]*windWeightDT; - mParticleState[i].velocity[1] += mParticleState[i].localWind[1]*windWeightDT; - mParticleState[i].velocity[2] += mParticleState[i].localWind[2]*windWeightDT; - } - - //then apply drag if required - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_DAMP_MOTION) - { - F32 dampAmount; - - dampAmount = (mParticleState[i].velocity[0] * mParticleState[i].velocity[0]) + - (mParticleState[i].velocity[1] * mParticleState[i].velocity[1]) + - (mParticleState[i].velocity[2] * mParticleState[i].velocity[2]); - dampAmount = 1.0f - ((mSpeedLimitSquared - dampAmount) / mSpeedLimitSquared); - if (dampAmount < 0.0f) - { - dampAmount = 0.0f; - } - else if (dampAmount > 1.0f) - { - dampAmount = 1.0f; - } - - //Damp prop to deltaT - dampAmount = -1.f * dampAmount * mDampMotionFactor * deltaT; - - mParticleState[i].velocity[0] += dampAmount * mParticleState[i].velocity[0]; - mParticleState[i].velocity[1] += dampAmount * mParticleState[i].velocity[1]; - mParticleState[i].velocity[2] += dampAmount * mParticleState[i].velocity[2]; - } - - //check for bounces if required - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_BOUNCE) - {//Is the particle below the bounce plane?? - LLVector3 tempBounceTest; - tempBounceTest.setVec(mParticleState[i].position[0], mParticleState[i].position[1], mParticleState[i].position[2]); - tempBounceTest.mV[VZ] -= mBouncePlaneZ; - - //This is simplistic for now - if ((tempBounceTest.mV[VZ] < 0.0f) && (mParticleState[i].velocity[2] < 0.0f)) - { - onParticleBounce(i); - } - } - - //maintain the old way of updating scale and alpha - // clamp scale and alpha to reasonable values - // should this section of code only be called if we're *actually* animating scale and alpha? - mParticleState[i].alpha[2] = mDiffEqAlpha[0] + // constant term - mDiffEqAlpha[1]*mParticleState[i].alpha[0] + // zeroth derivative term - mDiffEqAlpha[2]*mParticleState[i].alpha[1]; // first derivative term - - mParticleState[i].scale[2] = mDiffEqScale[0] + // constant term - mDiffEqScale[1]*mParticleState[i].scale[0] + // zeroth derivative term - mDiffEqScale[2]*mParticleState[i].scale[1]; // first derivative term - - mParticleState[i].scale[0] += mParticleState[i].scale[1]*deltaT; // scale - - mParticleState[i].alpha[0] += mParticleState[i].alpha[1]*deltaT; // alpha - if (mParticleState[i].scale[0] < 0.0f) - { - mParticleState[i].scale[0] = 0.01f; - } - - if (mParticleState[i].alpha[0] < 0.0f) - { - mParticleState[i].alpha[0] = 0.0f; - } - else if (mParticleState[i].alpha[0] > 1.0f) - { - mParticleState[i].alpha[0] = 1.0f; - } - mParticleState[i].scale[1] += mParticleState[i].scale[2]*deltaT; - mParticleState[i].alpha[1] += mParticleState[i].alpha[2]*deltaT; - - //Is particle appearance affected by wind? - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_WIND_DIFFUSION) - { - F32 windMagnitude, windMagnitudeSqrt; - - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_EVALUATE_WIND_PER_PARTICLE) - { - windMagnitude = sqrt((mParticleState[i].localWind[0] * mParticleState[i].localWind[0]) + - (mParticleState[i].localWind[1] * mParticleState[i].localWind[1]) + - (mParticleState[i].localWind[2] * mParticleState[i].localWind[2])); - //don't know a max, so just make up a reasonably large value for now and cap. - windMagnitude = windMagnitude * 0.05f; - if (windMagnitude > 1.0f) - { - windMagnitude = 1.0f; - } - windMagnitudeSqrt = sqrt(mCurrentWindMagnitude); - } - else - { - windMagnitude = mCurrentWindMagnitude; - windMagnitudeSqrt = mCurrentWindMagnitudeSquareRoot; - } - - //ignore alpha for now, as it is reduced by distance death and life expectancy in any case. - //mParticleState[i].alpha[0] *= (1.0 - (windMagnitude * mWindDiffusionFactor.mV[VX])); - //Scaling prop to sqr root. Should really be cube root, as we are dealing with a volume, but - //heavy math, and sqr looks OK. - mParticleState[i].scale[0] *= (1.f + (windMagnitudeSqrt * mWindDiffusionFactor.mV[VX])); - } - - // we have to store the death of the particle somewhere - - //now test for death if life expires or hits edge of death radius (given flags enabled) - //aapply alpha and scale fade proportional to proximity to death - test for death flags and produce a weighted sum - //taking into account time to live and distance to death. - weightedDeathSum = 1.0f; - - if (mFlags[PART_SYS_KILL_BYTE] & PART_SYS_TIME_DEATH) - { - // **** Hack! remainingLifetime counts up from negative, to avoid subtracts! - djs - mParticleState[i].remainingLifetime += deltaT; - weightedDeathSum *= -1.f * (mParticleState[i].remainingLifetime * mOneOverIndividualLifetime); - if (mParticleState[i].remainingLifetime > 0.0f) - { - mDeadArr[i] = 1; - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_SPAWN) - { - setParticleCountdownStateWaitingDead(i); - } - weightedDeathSum = 0.0f; - } - else if (weightedDeathSum > 1.0f) - { - weightedDeathSum = 1.0f; - } - } - if (mFlags[PART_SYS_KILL_BYTE] & PART_SYS_DISTANCE_DEATH) - { - F32 radius; - radius = (mParticleState[i].position[0]*mParticleState[i].position[0] + - mParticleState[i].position[1]*mParticleState[i].position[1] + - mParticleState[i].position[2]*mParticleState[i].position[2]); - radius = (mDistanceDeathSquared - radius) * mOneOverDistanceDeathSquared; - weightedDeathSum = weightedDeathSum * radius; - if (radius <= 0.0f) - { - mDeadArr[i] = 1; - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_SPAWN) - { - setParticleCountdownStateWaitingDead(i); - } - weightedDeathSum = 0.0f; - } - else if (weightedDeathSum > 1.0f) - { - weightedDeathSum = 1.0f; - } - } - if (mFlags[PART_SYS_KILL_BYTE] & PART_SYS_KILL_PLANE) - { - if (mParticleState[i].position[2] <= mKillPlaneZ) - { - llinfos << "kill plane" << llendl; - mDeadArr[i] = 1; - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_SPAWN) - { - setParticleCountdownStateWaitingDead(i); - } - weightedDeathSum = 0.0f; - } - } - if (mFlags[PART_SYS_KILL_BYTE] & PART_SYS_GLOBAL_DIE) - { - weightedDeathSum = weightedDeathSum * (mGlobalLifetime / mOriginalGlobalLifetime); - } - - - mParticleState[i].deathOffset = weightedDeathSum; - - any_leftQ |= (1 - mDeadArr[i]); - } - - if (mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_SPAWN) - {//May be just waiting for new particles to be born, with none around currently - any_leftQ = TRUE; - } - - - if (mFlags[PART_SYS_KILL_BYTE] & PART_SYS_GLOBAL_DIE) - { - mGlobalLifetime -= deltaT; - if (mGlobalLifetime < 0.0f) - { - any_leftQ = FALSE; - } - } - - - if ((mCurrTime - mUpdatePhysicsInputsTime) > PART_SYS_UPDATE_PHYSICS_INPUTS_TIME) - {//Have to execute this at end of itterate, as several independent processes rely on the test being true. - mUpdatePhysicsInputsTime = mCurrTime; - } - - mNumLiveParticles = 0; - for ( i = 0; i < mNumPart; i++) - { - if (!mDeadArr[i]) - { - mNumLiveParticles++; - } - } - return any_leftQ; -} - -void LLVOPart::reverseTranslateParticlesAndPotentiallyKill(const LLVector3 &moveBy) -{ - U32 i;//pos_off; - - for(i = 0; i < mNumPart; i++) - { - if(0 == mDeadArr[i]) - { - //pos_off = pos_offset_i(i); - mParticleState[i].position[0] += moveBy.mV[VX]; - mParticleState[i].position[1] += moveBy.mV[VY]; - mParticleState[i].position[2] += moveBy.mV[VZ]; - - } - } -} - -void LLVOPart::translateParticlesBy(const LLVector3 &moveBy) -{ - if (!(mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_BOUNCE)) - {//Do not translate if bouncing is on, as the whole system shifts adding or subtractiong potential energy - - //If the object moves, the particles should not, otherwise will look like a rigid structure - reverseTranslateParticlesAndPotentiallyKill(moveBy); - - mSpawnPoint.mV[VX] += moveBy.mV[VX]; - mSpawnPoint.mV[VY] += moveBy.mV[VY]; - mSpawnPoint.mV[VZ] += moveBy.mV[VZ]; - } -} - - -void LLVOPart::translateParticlesTo(const LLVector3 &moveTo) -{ - LLVector3 moveBy; - - if (!(mFlags[PART_SYS_ACTION_BYTE] & PART_SYS_BOUNCE)) - {//Do not translate if bouncing is on, as the whole system shifts adding or subtractiong potential energy - - //If the object moves, the particles should not, otherwise will look like a rigid structure - moveBy.setVec(moveTo.mV[VX] - mSpawnPoint.mV[VX], moveTo.mV[VY] - mSpawnPoint.mV[VY], moveTo.mV[VZ] - mSpawnPoint.mV[VZ]); - reverseTranslateParticlesAndPotentiallyKill(moveBy); - - mSpawnPoint.mV[VX] = moveTo.mV[VX]; - mSpawnPoint.mV[VY] = moveTo.mV[VY]; - mSpawnPoint.mV[VZ] = moveTo.mV[VZ]; - } -} - - -void LLVOPart::rotateParticlesBy(const LLQuaternion &q) -{ - mOriginOrientation *= q; -} - - -void LLVOPart::rotateParticlesTo(const LLQuaternion &q) -{ - mOriginOrientation.setQuatInit(q.mQ[VX], q.mQ[VY], q.mQ[VZ], q.mQ[VW]); -} diff --git a/linden/indra/newview/llvopart.h b/linden/indra/newview/llvopart.h deleted file mode 100644 index 3f31de6..0000000 --- a/linden/indra/newview/llvopart.h +++ /dev/null @@ -1,281 +0,0 @@ -/** - * @file llvopart.h - * @brief Description of LLVOPart class - * - * Copyright (c) 2001-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#ifndef LL_LLVOPART_H -#define LL_LLVOPART_H - -#include "llviewerobject.h" -#include "v3math.h" -#include "llframetimer.h" -#include "partsyspacket.h" // for compressing / decompressing particle system data - -//28 September 2001 - try and make the internal structs more meaningful than a huge array of floats! -typedef struct OneParticleData -{ - F32 position[3]; - F32 velocity[3]; - F32 acceleration[3]; - F32 scale[3]; - F32 alpha[3]; - F32 remainingLifetime; - F32 deathOffset; - F32 localWind[3]; -}OneParticleData; - - - - - -/* viewer object for a particle system */ -const U32 PART_SYS_BYTES_OF_FLAGS = 8; - -class LLVOPart : public LLViewerObject -{ -public: - LLVOPart(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); - - ~LLVOPart(); - - // Initialize data that's only inited once per class. - static void initClass(); - - /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. - BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - - - /*virtual*/ U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); - - /*virtual*/ void updateTextures(LLAgent &agent); - - /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - -protected: - void setParticleCountdownStateWaitingDead(U32 particleNumber); - - //Override these methods for new particle classes - void spawnParticle(const U32 particleNumber); - void onParticleBounce(const U32 particleNumber); - - void setDefaultValues(); - - U8 setParticleParams(F32 bounce_b, - const F32 o_pos[3], const F32 o_or[3], U32 n, LLUUID image_uuid, U8 flags[PART_SYS_BYTES_OF_FLAGS]); - - U8 initializeParticlesAndConstraints(U32 initialNumberOfParticles, - F32 diffEqAlpha[3], - F32 diffEqScale[3], - F32 scale_ranges[4], - F32 alpha_ranges[4], - F32 velocityOffset[3], - F32 killPlaneZ, - F32 killPlaneNormal[3], - F32 bouncePlaneZ, - F32 bouncePlaneNormal[3], - F32 spawnRange, - F32 spawnFrequency, - F32 spawnFreqencyRange, - F32 spawnDirection[3], - F32 spawnDirectionRange, - F32 spawnVelocity, - F32 spawnVelocityRange, - F32 speedLimit, - F32 windWeight, - F32 currentGravity[3], - F32 gravityWeight, - F32 globalLifetime, - F32 individualLifetime, - F32 individualLifetimeRange, - F32 alphaDecay, - F32 scaleDecay, - F32 distanceDeath, - F32 dampMotionFactor, - F32 windDiffusionFactor[3]); - // initializes particles randomly within these ranges - // scale ranges and alpha ranges contain initial conditions plus rates of change - // of initial conditions My naming is inconsistent (passing alpha derivatives with alpha - // values), but this class is wrapped by another one, and this function is called only once - - U8 iterateParticles(F32 deltaT); // step by one deltaT, check for bounces and particle deaths - - void reverseTranslateParticlesAndPotentiallyKill(const LLVector3 &moveBy); - - void translateParticlesBy(const LLVector3 &moveBy); - void translateParticlesTo(const LLVector3 &moveTo); - void rotateParticlesBy(const LLQuaternion &q); - void rotateParticlesTo(const LLQuaternion &q); - - /////////////////////// - // - // Legacy, "dead" methods - U8 setParticlesDistFadeout(F32 beginFadeout, F32 endFadeout); - -protected: - LLFrameTimer mDeathTimer; - U32 mNumPart; // number of particles - U32 mNumLiveParticles; - BOOL mParticlesDead; // am I dead yet? (i.e. should I keep rendering?) - LLPartInitData mInitSysData; // data for initializing the particle system. - - U64 mTimeLastFrame; - - //27 September 2001 - LLParticleSystem no longer a seperate class, as does not allow access to all object facilities - //the following private data and methods used to be in LLParticleSystem - - F32 mCurrTime; // time value in simulator for particle system -- note: may be independent of simulator time - F32 mLastTime; // time last frame - - //26 September - these are replaced by alpha and scale parameters below - //F32 mDiffEq[18]; // constants for second-order differential equation describing particle motion - // MDS -- july, doubled the number of constants to handle scale, alpha and rotation - //26 September - just use mKillPlaneZ, as the rest really confusing to set sometimes - //F32 mKillParameters[6]; // take a dot-product of a particle's values - // with this and compare to zero to determine if its killed - // computational trick, only call it a "kill" when the dot product of - // the velocity with the first three values of this is below zero - - //26 September - use mBouncePlaneZ as the parameters are interesting but hard to manipulate predictably - //F32 mBounceParams[5]; // same as "mKillParameters" only they determine when an object bounces - // this is actually for generalized bouncing, might indicate decayed bouncing, or sliding behavior - - F32 mBounceBehavior; // first three are multiplied pointwise with x,y and z velocities, - // next three are added pointwise to x, y and z positions - - F32 mAlpha; // so I can fade out the whole system - - LLQuaternion mOriginOrientation; // quaternion for origin orientation - - // geometry / image data for particles visual representation - - //F32 *state_arr; // big array of velocity and position and acceleration - OneParticleData *mParticleState; // big array of velocity and position and acceleration - U8 *mDeadArr; // mDeadArr[i] == true if particle i is dead - - U8 mFlags[PART_SYS_BYTES_OF_FLAGS]; // just copy the flags from the initialization data - - - //New structures added as of 26 September 2001 - - //Have to remember the states if are to spawn new particles. - //These are from the original implementation, but now remembered! - F32 mDiffEqAlpha[3]; - F32 mDiffEqScale[3]; - F32 mScale_range[4]; - F32 mAlpha_range[4]; - LLVector3 mVelocityOffset; - - - //Incorporated in mFlags[PART_SYS_ACTION_BYTE] - //What actions will this system perform - bit mask of flags so can perform multiple operations. - //PART_SYS_SPAWN, - //PART_SYS_BOUNCE, - //PART_SYS_AFFECTED_BY_WIND, - //PART_SYS_AFFECTED_BY_GRAVITY, - //PART_SYS_EVALUATE_WIND_PER_PARTICLE, - //PART_SYS_APPLY_FORCE - //PART_SYS_DAMP_MOTION - //are valid flags. - - //Incorporated in mFlags[PART_SYS_KILL_BYTE] - //What actions will this system perform - bit mask of flags so can perform multiple operations. - //PART_SYS_KILL_PLANE, - //PART_SYS_GLOBAL_DIE, - //PART_SYS_DISTANCE_DEATH - //are valid flags. - - F32 mKillPlaneZ; - //For simplicity assume the XY plane, so this sets an altitude at which to die - LLVector3 mKillPlaneNormal; - //Normal direction to the kill plane - UNIT vector - F32 mBouncePlaneZ; - //For simplicity assume the XY plane, so this sets an altitude at which to bounce - LLVector3 mBouncePlaneNormal; - //Normal direction to the bounce plane - UNIT vector - LLVector3 mSpawnPoint; - //If new particles are created, this is where they come from - F32 mSpawnRange; - //Range of emission points about the mSpawnPoint - F32 mSpawnFrequency; - //Required if the system is to spawn new particles. - //This variable determines the time after a particle dies when it is respawned. - F32 mSpawnFrequencyRange; - //Determines the random range of time until a new particle is spawned. - LLVector3 mSpawnDirection; - //Direction vector giving the mean direction in which particles are spawned - F32 mSpawnDirectionRange; - //Direction limiting the angular range of emissions about the mean direction. 1.0f means everywhere, 0.0f means uni-directional - F32 mSpawnVelocity; - //The mean speed at which particles are emitted - F32 mSpawnVelocityRange; - //The range of speeds about the mean at which particles are emitted. - F32 mSpeedLimitSquared; - //Used to constrain particle maximum velocity (squared to minimize calcs) - LLVector3 mCurrentWind; - //Wind direction used in update calculations - F32 mCurrentWindMagnitude, mCurrentWindMagnitudeSquareRoot; - //Velocity of current wind and square root of it to save calculations - F32 mWindWeight; - //How much of an effect does wind have - LLVector3 mCurrentGravity; - //Gravity direction used in update calculations - F32 mGravityWeight; - //How much of an effect does gravity have - F32 mGlobalLifetime, mOriginalGlobalLifetime; - //If particles re-spawn, a system can exist forever. - //If (ActionFlags & PART_SYS_GLOBAL_DIE) is TRUE this variable is used to determine how long the system lasts. - F32 mIndividualLifetime; - //How long does each particle last if nothing else happens to it - F32 mOneOverIndividualLifetime; - //For fast reciprocals - F32 mIndividualLifetimeRange; - //Range of variation in individual lifetimes - F32 mAlphaDecay; - //By what factor does alpha decrease as the lifetime of a particle is approached. - F32 mScaleDecay; - //By what factor does scale decrease as the lifetime of a particle is approached. - F32 mDistanceDeathSquared; - //With the increased functionality, particle systems can expand to indefinite size - //(e.g. wind can chaotically move particles into a wide spread). - //To avoid particles exceeding normal object size constraints, - //set the PART_SYS_DISTANCE_DEATH flag, and set a distance value here, representing a radius around the spawn point. - //Square to reduce computation. - F32 mOneOverDistanceDeathSquared; - //For fast reciprocals - F32 mDampMotionFactor; - //How much to damp motion - LLVector3 mWindDiffusionFactor; - //How does wind affect the apearance of sprites - - F32 mUpdatePhysicsInputsTime; - //Internal value to determine whether the time is right to update physical environmental effects -}; - -#endif // LL_VO_PART_H diff --git a/linden/indra/newview/llvopartgroup.cpp b/linden/indra/newview/llvopartgroup.cpp index 150f5cd..a51ae9c 100644 --- a/linden/indra/newview/llvopartgroup.cpp +++ b/linden/indra/newview/llvopartgroup.cpp @@ -29,6 +29,8 @@ #include "llvopartgroup.h" +#include "lldrawpoolalpha.h" + #include "llfasttimer.h" #include "message.h" #include "v2math.h" @@ -47,7 +49,7 @@ const F32 MAX_PART_LIFETIME = 120.f; extern U64 gFrameTime; LLVOPartGroup::LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp), + : LLAlphaObject(id, pcode, regionp), mViewerPartGroupp(NULL) { setNumTEs(1); @@ -61,37 +63,37 @@ LLVOPartGroup::~LLVOPartGroup() { } + BOOL LLVOPartGroup::isActive() const { return TRUE; } +F32 LLVOPartGroup::getBinRadius() +{ + return mScale.mV[0]*2.f; +} + +void LLVOPartGroup::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) +{ + LLVector3 pos_agent = getPositionAgent(); + mExtents[0] = pos_agent - mScale; + mExtents[1] = pos_agent + mScale; + newMin = mExtents[0]; + newMax = mExtents[1]; + mDrawable->setPositionGroup(pos_agent); +} + BOOL LLVOPartGroup::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { - if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_PARTICLES)) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - } - - // Particle groups don't need any of default idleUpdate velocity interpolation stuff. - //LLViewerObject::idleUpdate(agent, world, time); return TRUE; } - void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) { // mPixelArea is calculated during render - - LLVector3 viewer_pos_agent = agent.getCameraPositionAgent(); - LLVector3 pos_agent = getRenderPosition(); - - F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; - F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; - F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; - F32 mid_scale = getMidScale(); - F32 range = sqrt(dx*dx + dy*dy + dz*dz); + F32 range = (getRenderPosition()-gCamera->getOrigin()).magVec(); if (range < 0.001f || isHUDAttachment()) // range == zero { @@ -105,7 +107,7 @@ void LLVOPartGroup::setPixelAreaAndAngle(LLAgent &agent) void LLVOPartGroup::updateTextures(LLAgent &agent) { - // Texture stats for particles will need to be updated in a different way... + // Texture stats for particles need to be updated in a different way... } @@ -114,37 +116,45 @@ LLDrawable* LLVOPartGroup::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_PARTICLES); - - LLDrawPool *pool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - mDrawable->setNumFaces(mViewerPartGroupp->getCount(), pool, getTEImage(0)); return mDrawable; } const F32 MAX_PARTICLE_AREA_SCALE = 0.02f; // some tuned constant, limits on how much particle area to draw -BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) +F32 LLVOPartGroup::getPartSize(S32 idx) { - LLFastTimer t(LLFastTimer::FTM_UPDATE_PARTICLES); - - LLVector3 at; - LLVector3 up; - LLVector3 right; - LLVector3 position_agent; - LLVector3 camera_agent = gAgent.getCameraPositionAgent(); - LLVector2 uvs[4]; + if (idx < (S32) mViewerPartGroupp->mParticles.size()) + { + return mViewerPartGroupp->mParticles[idx]->mScale.mV[0]; + } + + return 0.f; +} - uvs[0].setVec(0.f, 1.f); - uvs[1].setVec(0.f, 0.f); - uvs[2].setVec(1.f, 1.f); - uvs[3].setVec(1.f, 0.f); +BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) +{ + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_PARTICLES); - LLDrawPool *drawpool = gPipeline.getPool(LLDrawPool::POOL_ALPHA); + LLVector3 at; + LLVector3 position_agent; + LLVector3 camera_agent = gCamera->getOrigin(); + S32 num_parts = mViewerPartGroupp->getCount(); LLFace *facep; - + LLSpatialGroup* group = drawable->getSpatialGroup(); + if (!group && num_parts) + { + drawable->movePartition(); + group = drawable->getSpatialGroup(); + } + if (!num_parts) { - drawable->setNumFaces(0, drawpool, getTEImage(0)); + if (drawable->getNumFaces()) + { + group->dirtyGeom(); + } + drawable->setNumFaces(0, NULL, getTEImage(0)); LLPipeline::sCompiles++; return TRUE; } @@ -154,30 +164,30 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) return TRUE; } -// drawable->setNumFaces(num_parts, drawpool, getTEImage(0)); - drawable->setNumFacesFast(num_parts, drawpool, getTEImage(0)); - - LLVector3 normal(-gCamera->getXAxis()); // make point agent face camera - - LLStrider verticesp; - LLStrider normalsp; - LLStrider texCoordsp; - U32 *indicesp = 0; + if (num_parts > drawable->getNumFaces()) + { + drawable->setNumFacesFast(num_parts+num_parts/4, NULL, getTEImage(0)); + } - S32 vert_offset; F32 tot_area = 0; + BOOL is_particle = isParticle(); + F32 max_area = LLViewerPartSim::getMaxPartCount() * MAX_PARTICLE_AREA_SCALE; - + F32 pixel_meter_ratio = gCamera->getPixelMeterRatio(); + pixel_meter_ratio *= pixel_meter_ratio; + S32 count=0; - for (S32 i = 0; i < num_parts; i++) + S32 i; + F32 max_width = 0.f; + mDepth = 0.f; + + for (i = 0; i < num_parts; i++) { - const LLViewerPart &part = mViewerPartGroupp->mParticles[i]; + const LLViewerPart &part = *((LLViewerPart*) mViewerPartGroupp->mParticles[i]); LLVector3 part_pos_agent(part.mPosAgent); at = part_pos_agent - camera_agent; - //F32 invcamdist = 1.0f / at.magVec(); - //area += (part.mScale.mV[0]*invcamdist)*(part.mScale.mV[1]*invcamdist); F32 camera_dist_squared = at.magVecSquared(); F32 inv_camera_dist_squared; if (camera_dist_squared > 1.f) @@ -186,29 +196,124 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) inv_camera_dist_squared = 1.f; F32 area = part.mScale.mV[0] * part.mScale.mV[1] * inv_camera_dist_squared; tot_area += area; - if (tot_area > max_area) + + if (!is_particle && tot_area > max_area) { break; } - + count++; facep = drawable->getFace(i); + facep->setTEOffset(i); const F32 NEAR_PART_DIST_SQ = 5.f*5.f; // Only discard particles > 5 m from the camera const F32 MIN_PART_AREA = .005f*.005f; // only less than 5 mm x 5 mm at 1 m from camera - if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA) + + if (!is_particle) { - facep->setSize(0, 0); - continue; + if (camera_dist_squared > NEAR_PART_DIST_SQ && area < MIN_PART_AREA) + { + facep->setSize(0, 0); + continue; + } + + facep->setSize(4, 6); + } + else + { + facep->setSize(1,1); + } + + facep->setViewerObject(this); + + if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK) + { + facep->setState(LLFace::FULLBRIGHT); } - facep->setSize(4, 6); - facep->mCenterAgent = part_pos_agent; - vert_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == vert_offset) + else { - return TRUE; + facep->clearState(LLFace::FULLBRIGHT); } + + facep->mCenterLocal = part.mPosAgent; + facep->setFaceColor(part.mColor); + facep->setTexture(part.mImagep); + if (i == 0) + { + mExtents[0] = mExtents[1] = part.mPosAgent; + } + else + { + update_min_max(mExtents[0], mExtents[1], part.mPosAgent); + } + + max_width = llmax(max_width, part.mScale.mV[0]); + max_width = llmax(max_width, part.mScale.mV[1]); + + mPixelArea = tot_area * pixel_meter_ratio; + const F32 area_scale = 10.f; // scale area to increase priority a bit + facep->setVirtualSize(mPixelArea*area_scale); + } + for (i = count; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + facep->setTEOffset(i); + facep->setSize(0,0); + } + + LLVector3 y = gCamera->mYAxis; + LLVector3 z = gCamera->mZAxis; + + LLVector3 pad; + for (i = 0; i < 3; i++) + { + pad.mV[i] = llmax(max_width, max_width * (fabsf(y.mV[i]) + fabsf(z.mV[i]))); + } + + mExtents[0] -= pad; + mExtents[1] += pad; + + mDrawable->movePartition(); + LLPipeline::sCompiles++; + return TRUE; +} + +void LLVOPartGroup::getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp) +{ + if (idx >= (S32) mViewerPartGroupp->mParticles.size()) + { + return; + } + + const LLViewerPart &part = *((LLViewerPart*) (mViewerPartGroupp->mParticles[idx])); + + U32 vert_offset = mDrawable->getFace(idx)->getGeomIndex(); + + if (isParticle()) + { + LLVector3 part_pos_agent(part.mPosAgent); + + const LLVector3& normal = -gCamera->getXAxis(); + + *verticesp++ = part_pos_agent; + *normalsp++ = normal; + *colorsp++ = part.mColor; + *texcoordsp++ = LLVector2(0.5f, 0.5f); + *indicesp++ = vert_offset; + } + else + { + LLVector3 part_pos_agent(part.mPosAgent); + LLVector3 camera_agent = gAgent.getCameraPositionAgent(); + LLVector3 at = part_pos_agent - camera_agent; + LLVector3 up, right; + right = at % LLVector3(0.f, 0.f, 1.f); right.normVec(); up = right % at; @@ -236,31 +341,28 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) right *= 0.5f*part.mScale.mV[0]; up *= 0.5f*part.mScale.mV[1]; + const LLVector3& normal = -gCamera->getXAxis(); + *verticesp++ = part_pos_agent + up - right; *verticesp++ = part_pos_agent - up - right; *verticesp++ = part_pos_agent + up + right; *verticesp++ = part_pos_agent - up + right; - *texCoordsp++ = uvs[0]; - *texCoordsp++ = uvs[1]; - *texCoordsp++ = uvs[2]; - *texCoordsp++ = uvs[3]; + *colorsp++ = part.mColor; + *colorsp++ = part.mColor; + *colorsp++ = part.mColor; + *colorsp++ = part.mColor; + + *texcoordsp++ = LLVector2(0.f, 1.f); + *texcoordsp++ = LLVector2(0.f, 0.f); + *texcoordsp++ = LLVector2(1.f, 1.f); + *texcoordsp++ = LLVector2(1.f, 0.f); *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; *normalsp++ = normal; - if (part.mFlags & LLPartData::LL_PART_EMISSIVE_MASK) - { - facep->setState(LLFace::FULLBRIGHT); - } - else - { - facep->clearState(LLFace::FULLBRIGHT); - } - facep->setFaceColor(part.mColor); - *indicesp++ = vert_offset + 0; *indicesp++ = vert_offset + 1; *indicesp++ = vert_offset + 2; @@ -269,17 +371,149 @@ BOOL LLVOPartGroup::updateGeometry(LLDrawable *drawable) *indicesp++ = vert_offset + 3; *indicesp++ = vert_offset + 2; } - for (S32 j = count; j < drawable->getNumFaces(); j++) +} + +BOOL LLVOPartGroup::isParticle() +{ + return FALSE; //gGLManager.mHasPointParameters && mViewerPartGroupp->mUniformParticles; +} + +U32 LLVOPartGroup::getPartitionType() const +{ + return LLPipeline::PARTITION_PARTICLE; +} + +LLParticlePartition::LLParticlePartition() +: LLSpatialPartition(LLDrawPoolAlpha::VERTEX_DATA_MASK) +{ + mRenderPass = LLRenderPass::PASS_ALPHA; + mDrawableType = LLPipeline::RENDER_TYPE_PARTICLES; + mPartitionType = LLPipeline::PARTITION_PARTICLE; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; + mSlopRatio = 0.f; + mLODPeriod = 1; +} + +void LLParticlePartition::addGeometryCount(LLSpatialGroup* group, U32& vertex_count, U32& index_count) +{ + group->mBufferUsage = mBufferUsage; + + mFaceList.clear(); + + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { - drawable->getFace(j)->setSize(0,0); + LLDrawable* drawablep = *i; + + if (drawablep->isDead()) + { + continue; + } + + LLAlphaObject* obj = (LLAlphaObject*) drawablep->getVObj(); + obj->mDepth = 0.f; + + if (drawablep->isAnimating()) + { + group->mBufferUsage = GL_STREAM_DRAW_ARB; + } + + U32 count = 0; + for (S32 j = 0; j < drawablep->getNumFaces(); ++j) + { + drawablep->updateFaceSize(j); + + LLFace* facep = drawablep->getFace(j); + if (!facep->hasGeometry()) + { + continue; + } + + count++; + facep->mDistance = (facep->mCenterLocal - gCamera->getOrigin()) * gCamera->getAtAxis(); + obj->mDepth += facep->mDistance; + + mFaceList.push_back(facep); + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + } + + obj->mDepth /= count; } - - mPixelArea = tot_area * gCamera->getPixelMeterRatio() * gCamera->getPixelMeterRatio(); - const F32 area_scale = 10.f; // scale area to increase priority a bit - getTEImage(0)->addTextureStats(mPixelArea * area_scale); +} - LLPipeline::sCompiles++; +void LLParticlePartition::getGeometry(LLSpatialGroup* group) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); - return TRUE; + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareDistanceGreater()); + + U32 index_count = 0; + U32 vertex_count = 0; + + group->clearDrawMap(); + + LLVertexBuffer* buffer = group->mVertexBuffer; + + LLStrider indicesp; + LLStrider verticesp; + LLStrider normalsp; + LLStrider texcoordsp; + LLStrider colorsp; + + buffer->getVertexStrider(verticesp); + buffer->getNormalStrider(normalsp); + buffer->getColorStrider(colorsp); + buffer->getTexCoordStrider(texcoordsp); + buffer->getIndexStrider(indicesp); + + std::vector& draw_vec = group->mDrawMap[mRenderPass]; + + for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + LLAlphaObject* object = (LLAlphaObject*) facep->getViewerObject(); + facep->setGeomIndex(vertex_count); + facep->setIndicesIndex(index_count); + facep->mVertexBuffer = buffer; + facep->setPoolType(LLDrawPool::POOL_ALPHA); + object->getGeometry(facep->getTEOffset(), verticesp, normalsp, texcoordsp, colorsp, indicesp); + + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + S32 idx = draw_vec.size()-1; + + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + F32 vsize = facep->getVirtualSize(); + + if (idx >= 0 && draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == facep->getTexture() && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() < 4096 && + draw_vec[idx]->mFullbright == fullbright) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, vsize); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* info = new LLDrawInfo(start,end,count,offset,facep->getTexture(), buffer, fullbright); + info->mVSize = vsize; + draw_vec.push_back(info); + } + } + + mFaceList.clear(); +} + +F32 LLParticlePartition::calcPixelArea(LLSpatialGroup* group, LLCamera& camera) +{ + return 1024.f; } diff --git a/linden/indra/newview/llvopartgroup.h b/linden/indra/newview/llvopartgroup.h index fc6c1f3..3dc07c0 100644 --- a/linden/indra/newview/llvopartgroup.h +++ b/linden/indra/newview/llvopartgroup.h @@ -35,26 +35,50 @@ class LLViewerPartGroup; -class LLVOPartGroup : public LLViewerObject +class LLVOPartGroup : public LLAlphaObject { public: + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_COLOR) + } + eVertexDataMask; + LLVOPartGroup(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); ~LLVOPartGroup(); /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); + BOOL isParticle(); + virtual F32 getBinRadius(); + virtual void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); + virtual U32 getPartitionType() const; + /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + void getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp); + void updateFaceSize(S32 idx) { } + F32 getPartSize(S32 idx); void setViewerPartGroup(LLViewerPartGroup *part_groupp) { mViewerPartGroupp = part_groupp; } + LLViewerPartGroup* getViewerPartGroup() { return mViewerPartGroupp; } + protected: LLViewerPartGroup *mViewerPartGroupp; - + LLVector3 mExtents[2]; LLColor4 mDebugColor; }; diff --git a/linden/indra/newview/llvosky.cpp b/linden/indra/newview/llvosky.cpp index 559e846..4ed5353 100644 --- a/linden/indra/newview/llvosky.cpp +++ b/linden/indra/newview/llvosky.cpp @@ -440,7 +440,7 @@ void LLSkyTex::initEmpty(const S32 tex) } } - createTexture(tex); + createGLImage(tex); } @@ -467,10 +467,10 @@ void LLSkyTex::create(const F32 brightness_scale, const LLColor3& multiscatt) *pix = temp1.mAll; } } - createTexture(sCurrent); + createGLImage(sCurrent); } -void LLSkyTex::createTexture(S32 which) +void LLSkyTex::createGLImage(S32 which) { mImageGL[which]->createGLTexture(0, mImageRaw[which]); mImageGL[which]->setClamp(TRUE, TRUE); @@ -494,7 +494,7 @@ S32 LLVOSky::sTileResX = sResolution/NUM_TILES_X; S32 LLVOSky::sTileResY = sResolution/NUM_TILES_Y; LLVOSky::LLVOSky(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, pcode, regionp), +: LLStaticViewerObject(id, pcode, regionp), mSun(SUN_DISK_RADIUS), mMoon(MOON_DISK_RADIUS), mBrightnessScale(1.f), mBrightnessScaleNew(0.f), @@ -1054,11 +1054,9 @@ void LLVOSky::calcBrightnessScaleAndColors() } calculateColors(); // MSMSM Moved this down here per Milo Lindens suggestion, to fix orange flashing bug at sunset. - generateScatterMap(); } - void LLVOSky::calculateColors() { const F32 h = -0.1f; @@ -1068,14 +1066,13 @@ void LLVOSky::calculateColors() F32 sun_factor = 1; // Sun Diffuse - if (calcHitsEarth(mCameraPosAgent, tosun) < 0) - { - mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(tosun.mV[2], h); - } - else - { - mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(0, h); - } + F32 sun_height = tosun.mV[2]; + + if (sun_height <= 0.0) + sun_height = 0.0; + + mSunDiffuse = mBrightnessScaleGuess * mSun.getIntensity() * mTransp.calcTransp(sun_height, h); + mSunDiffuse = 1.0f * color_norm(mSunDiffuse); // Sun Ambient @@ -1188,8 +1185,6 @@ BOOL LLVOSky::updateSky() return TRUE; } - setPositionAgent(gAgent.getCameraPositionAgent()); - static S32 next_frame = 0; const S32 total_no_tiles = 6 * NUM_TILES; const S32 cycle_frame_no = total_no_tiles + 1; @@ -1253,21 +1248,27 @@ BOOL LLVOSky::updateSky() LLImageRaw* raw1 = mSkyTex[side].getImageRaw(TRUE); LLImageRaw* raw2 = mSkyTex[side].getImageRaw(FALSE); raw2->copy(raw1); - mSkyTex[side].createTexture(mSkyTex[side].getWhich(FALSE)); + mSkyTex[side].createGLImage(mSkyTex[side].getWhich(FALSE)); } next_frame = 0; //llSkyTex::stepCurrent(); } - std::vector > images; - for (S32 side = 0; side < 6; side++) + if (!gSavedSettings.getBOOL("RenderDynamicReflections")) { - images.push_back(mSkyTex[side].getImageRaw(FALSE)); + std::vector > images; + for (S32 side = 0; side < 6; side++) + { + images.push_back(mSkyTex[side].getImageRaw(FALSE)); + } + mCubeMap->init(images); } - mCubeMap->init(images); } } + gPipeline.markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + gPipeline.markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + mForceUpdate = FALSE; } else @@ -1306,7 +1307,8 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline) poolp->setSkyTex(mSkyTex); poolp->setSun(&mSun); poolp->setMoon(&mMoon); - + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_SKY); + for (S32 i = 0; i < 6; ++i) { mFace[FACE_SIDE0 + i] = mDrawable->addFace(poolp, NULL); @@ -1316,9 +1318,6 @@ LLDrawable *LLVOSky::createDrawable(LLPipeline *pipeline) mFace[FACE_MOON] = mDrawable->addFace(poolp, mMoonTexturep); mFace[FACE_BLOOM] = mDrawable->addFace(poolp, mBloomTexturep); - //mDrawable->addFace(poolp, LLViewerImage::sDefaultImagep); - gPipeline.markMaterialed(mDrawable); - return mDrawable; } @@ -1326,70 +1325,74 @@ BOOL LLVOSky::updateGeometry(LLDrawable *drawable) { if (mFace[FACE_REFLECTION] == NULL) { - mFace[FACE_REFLECTION] = drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL); + LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); + mFace[FACE_REFLECTION] = drawable->addFace(poolp, NULL); } mCameraPosAgent = drawable->getPositionAgent(); mEarthCenter.mV[0] = mCameraPosAgent.mV[0]; mEarthCenter.mV[1] = mCameraPosAgent.mV[1]; - LLVector3 v_agent[8]; for (S32 i = 0; i < 8; ++i) { F32 x_sgn = (i&1) ? 1.f : -1.f; F32 y_sgn = (i&2) ? 1.f : -1.f; F32 z_sgn = (i&4) ? 1.f : -1.f; - v_agent[i] = mCameraPosAgent + HORIZON_DIST * LLVector3(x_sgn, y_sgn, z_sgn); + v_agent[i] = HORIZON_DIST*0.25f * LLVector3(x_sgn, y_sgn, z_sgn); } LLStrider verticesp; LLStrider normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; LLFace *face; for (S32 side = 0; side < 6; ++side) { face = mFace[FACE_SIDE0 + side]; - face->setPrimType(LLTriangles); - face->setSize(4, 6); - index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == index_offset) + + if (face->mVertexBuffer.isNull()) { - return TRUE; + face->setSize(4, 6); + face->setGeomIndex(0); + face->setIndicesIndex(0); + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolSky::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(4, 6, TRUE); + + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); + + S32 vtx = 0; + S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X + S32 side_dir = side & 1; // even - 0, odd - 1 + S32 i_bit = (curr_bit + 2) % 3; + S32 j_bit = (i_bit + 2) % 3; + + LLVector3 axis; + axis.mV[curr_bit] = 1; + face->mCenterAgent = (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST; + + vtx = side_dir << curr_bit; + *(verticesp++) = v_agent[vtx]; + *(verticesp++) = v_agent[vtx | 1 << j_bit]; + *(verticesp++) = v_agent[vtx | 1 << i_bit]; + *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit]; + + *(texCoordsp++) = TEX00; + *(texCoordsp++) = TEX01; + *(texCoordsp++) = TEX10; + *(texCoordsp++) = TEX11; + + // Triangles for each side + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 1; + *indicesp++ = index_offset + 3; + + *indicesp++ = index_offset + 0; + *indicesp++ = index_offset + 3; + *indicesp++ = index_offset + 2; } - - S32 vtx = 0; - S32 curr_bit = side >> 1; // 0/1 = Z axis, 2/3 = Y, 4/5 = X - S32 side_dir = side & 1; // even - 0, odd - 1 - S32 i_bit = (curr_bit + 2) % 3; - S32 j_bit = (i_bit + 2) % 3; - - LLVector3 axis; - axis.mV[curr_bit] = 1; - face->mCenterAgent = mCameraPosAgent + (F32)((side_dir << 1) - 1) * axis * HORIZON_DIST; - - vtx = side_dir << curr_bit; - *(verticesp++) = v_agent[vtx]; - *(verticesp++) = v_agent[vtx | 1 << j_bit]; - *(verticesp++) = v_agent[vtx | 1 << i_bit]; - *(verticesp++) = v_agent[vtx | 1 << i_bit | 1 << j_bit]; - - *(texCoordsp++) = TEX00; - *(texCoordsp++) = TEX01; - *(texCoordsp++) = TEX10; - *(texCoordsp++) = TEX11; - - // Triangles for each side - *indicesp++ = index_offset + 0; - *indicesp++ = index_offset + 1; - *indicesp++ = index_offset + 3; - - *indicesp++ = index_offset + 0; - *indicesp++ = index_offset + 3; - *indicesp++ = index_offset + 2; } const LLVector3 &look_at = gCamera->getAtAxis(); @@ -1464,7 +1467,7 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons LLStrider verticesp; LLStrider normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; LLFace *facep; @@ -1512,8 +1515,16 @@ BOOL LLVOSky::updateHeavenlyBodyGeometry(LLDrawable *drawable, const S32 f, cons hb.setVisible(TRUE); facep = mFace[f]; - facep->setPrimType(LLTriangles); - facep->setSize(4, 6); + + if (facep->mVertexBuffer.isNull()) + { + facep->setSize(4, 6); + facep->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + facep->mVertexBuffer->allocateBuffer(facep->getGeomCount(), facep->getIndicesCount(), TRUE); + facep->setGeomIndex(0); + facep->setIndicesIndex(0); + } + index_offset = facep->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -1642,7 +1653,7 @@ void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable ) LLStrider verticesp; LLStrider normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; LLFace *face; @@ -1661,8 +1672,16 @@ void LLVOSky::updateSunHaloGeometry(LLDrawable *drawable ) v_glow_corner[3] = draw_pos + right - up; face = mFace[FACE_BLOOM]; - face->setPrimType(LLTriangles); - face->setSize(4, 6); + + if (face->mVertexBuffer.isNull()) + { + face->setSize(4, 6); + face->setGeomIndex(0); + face->setIndicesIndex(0); + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(4, 6, TRUE); + } + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -1896,15 +1915,23 @@ void LLVOSky::updateReflectionGeometry(LLDrawable *drawable, F32 H, dt_clip = -0.1f; } + LLFace *face = mFace[FACE_REFLECTION]; + + if (face->mVertexBuffer.isNull() || quads*4 != face->getGeomCount()) + { + face->setSize(quads * 4, quads * 6); + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(face->getGeomCount(), face->getIndicesCount(), TRUE); + face->setIndicesIndex(0); + face->setGeomIndex(0); + } + LLStrider verticesp; LLStrider normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; - LLFace *face = mFace[FACE_REFLECTION]; - - face->setPrimType(LLTriangles); - face->setSize(quads * 4, quads * 6); + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -2132,16 +2159,14 @@ void LLVOSky::updateFog(const F32 distance) color_gamma_correct(sky_fog_color); - if (!(gPipeline.getVertexShaderLevel(LLPipeline::SHADER_ENVIRONMENT) > LLDrawPool::SHADER_LEVEL_SCATTERING)) - { - render_fog_color = sky_fog_color; - } - + render_fog_color = sky_fog_color; + if (camera_height > water_height) { fog_distance = mFogRatio * distance; LLColor4 fog(render_fog_color); glFogfv(GL_FOG_COLOR, fog.mV); + mGLFogCol = fog; } else { @@ -2161,6 +2186,7 @@ void LLVOSky::updateFog(const F32 distance) LLColor4 fogCol = brightness * (color_frac * render_fog_color + (1.f - color_frac) * LLColor4(0.f, 0.2f, 0.3f, 1.f)); fogCol.setAlpha(1); glFogfv(GL_FOG_COLOR, (F32 *) &fogCol.mV); + mGLFogCol = fogCol; } mFogColor = sky_fog_color; diff --git a/linden/indra/newview/llvosky.h b/linden/indra/newview/llvosky.h index 1617c2a..0ca56dc 100644 --- a/linden/indra/newview/llvosky.h +++ b/linden/indra/newview/llvosky.h @@ -197,7 +197,7 @@ protected: } LLImageRaw* getImageRaw(BOOL curr=TRUE) { return mImageRaw[getWhich(curr)]; } - void createTexture(BOOL curr=TRUE); + void createGLImage(BOOL curr=TRUE); }; @@ -511,7 +511,7 @@ public: class LLCubeMap; -class LLVOSky : public LLViewerObject +class LLVOSky : public LLStaticViewerObject { public: enum @@ -593,6 +593,7 @@ public: LLColor4 getMoonAmbientColor() const { return mMoonAmbient; } const LLColor4& getTotalAmbientColor() const { return mTotalAmbient; } LLColor4 getFogColor() const { return mFogColor; } + LLColor4 getGLFogColor() const { return mGLFogCol; } LLVector3 calcUpVec(const LLVector3 &pos) const { @@ -729,6 +730,8 @@ protected: F32 sInterpVal; LLColor4 mFogColor; + LLColor4 mGLFogCol; + F32 mFogRatio; F32 mWorldScale; @@ -739,7 +742,7 @@ protected: LLColor3 mMoonDiffuse; LLColor4U mFadeColor; // Color to fade in from - LLCubeMap *mCubeMap; // Cube map for the sky + LLCubeMap *mCubeMap; // Cube map for the environment S32 mDrawRefl; LLFrameTimer mUpdateTimer; diff --git a/linden/indra/newview/llvostars.cpp b/linden/indra/newview/llvostars.cpp index 3fd3b91..a4568ce 100644 --- a/linden/indra/newview/llvostars.cpp +++ b/linden/indra/newview/llvostars.cpp @@ -37,11 +37,11 @@ #include "pipeline.h" const U32 NUMBER_OF_STARS = 1000; -const F32 DISTANCE_TO_STARS = HORIZON_DIST - 10.f; +const F32 DISTANCE_TO_STARS = (HORIZON_DIST - 10.f)*0.25f; LLVOStars::LLVOStars(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id, pcode, regionp) + : LLStaticViewerObject(id, pcode, regionp) { initStars(); } @@ -64,7 +64,7 @@ LLDrawable *LLVOStars::createDrawable(LLPipeline *pipeline) LLDrawPoolStars *poolp = (LLDrawPoolStars*) gPipeline.getPool(LLDrawPool::POOL_STARS); mFace = mDrawable->addFace(poolp, NULL); - mFace->setPrimType(GL_POINTS); + mDrawable->setRenderType(LLPipeline::RENDER_TYPE_STARS); mFace->setSize(NUMBER_OF_STARS, NUMBER_OF_STARS); return mDrawable; @@ -90,19 +90,27 @@ BOOL LLVOStars::updateStarGeometry(LLDrawable *drawable) LLStrider normalsp; LLStrider texCoordsp; LLStrider colorsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; + if (mFace->mVertexBuffer.isNull()) + { + mFace->mVertexBuffer = new LLVertexBuffer(LLDrawPoolStars::VERTEX_DATA_MASK, GL_STREAM_DRAW_ARB); + mFace->mVertexBuffer->allocateBuffer(mFace->getGeomCount(), mFace->getIndicesCount(), TRUE); + mFace->setGeomIndex(0); + mFace->setIndicesIndex(0); + } + index_offset = mFace->getGeometryColors(verticesp,normalsp,texCoordsp,colorsp, indicesp); if (-1 == index_offset) { return TRUE; } - LLVector3 cam_pos = gSky.mVOSkyp ? gSky.mVOSkyp->getPositionAgent() : drawable->getPositionAgent(); + for (U32 vtx = 0; vtx < NUMBER_OF_STARS; ++vtx) { - *(verticesp++) = mStarVertices[vtx] + cam_pos; + *(verticesp++) = mStarVertices[vtx]; *(colorsp++) = LLColor4U(mStarColors[vtx]); *(indicesp++) = index_offset + vtx; } @@ -173,7 +181,7 @@ void LLVOStars::updateStarColors() F32 sundir_factor = 1; LLVector3 tostar = *v_p; tostar.normVec(); - const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSun(); + const F32 how_close_to_sun = tostar * gSky.mVOSkyp->getToSunLast(); if (how_close_to_sun > sunclose_max) { sundir_factor = (1 - how_close_to_sun) / sunclose_range; diff --git a/linden/indra/newview/llvostars.h b/linden/indra/newview/llvostars.h index 88e792c..10b644e 100644 --- a/linden/indra/newview/llvostars.h +++ b/linden/indra/newview/llvostars.h @@ -35,7 +35,7 @@ class LLFace; -class LLVOStars : public LLViewerObject +class LLVOStars : public LLStaticViewerObject { public: LLVOStars(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); diff --git a/linden/indra/newview/llvosurfacepatch.cpp b/linden/indra/newview/llvosurfacepatch.cpp index d49d78c..88e610b 100644 --- a/linden/indra/newview/llvosurfacepatch.cpp +++ b/linden/indra/newview/llvosurfacepatch.cpp @@ -29,6 +29,8 @@ #include "llvosurfacepatch.h" +#include "lldrawpoolterrain.h" + #include "lldrawable.h" #include "llface.h" #include "llprimitive.h" @@ -41,8 +43,52 @@ #include "llvovolume.h" #include "pipeline.h" +//============================================================================ + +class LLVertexBufferTerrain : public LLVertexBuffer +{ +public: + LLVertexBufferTerrain() : + LLVertexBuffer(MAP_VERTEX | MAP_NORMAL | MAP_TEXCOORD | MAP_TEXCOORD2 | MAP_COLOR, GL_DYNAMIC_DRAW_ARB) + { + }; + + // virtual + void setupVertexBuffer(U32 data_mask) const + { + if (LLDrawPoolTerrain::getDetailMode() == 0) + { + LLVertexBuffer::setupVertexBuffer(data_mask); + } + else if (data_mask & LLVertexBuffer::MAP_TEXCOORD2) + { + U8* base = useVBOs() ? NULL : mMappedData; + + glVertexPointer(3,GL_FLOAT, mStride, (void*)(base + 0)); + glNormalPointer(GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_NORMAL])); + glColorPointer(4, GL_UNSIGNED_BYTE, mStride, (void*)(base + mOffsets[TYPE_COLOR])); + + glClientActiveTextureARB(GL_TEXTURE3_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE2_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE1_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + glClientActiveTextureARB(GL_TEXTURE0_ARB); + glTexCoordPointer(2,GL_FLOAT, mStride, (void*)(base + mOffsets[TYPE_TEXCOORD2])); + } + else + { + LLVertexBuffer::setupVertexBuffer(data_mask); + } + llglassertok(); + } +}; + +//============================================================================ + LLVOSurfacePatch::LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, LL_VO_SURFACE_PATCH, regionp) +: LLStaticViewerObject(id, LL_VO_SURFACE_PATCH, regionp) { // Terrain must draw during selection passes so it can block objects behind it. mbCanSelect = TRUE; @@ -95,9 +141,9 @@ void LLVOSurfacePatch::updateTextures(LLAgent &agent) } -LLDrawPool *LLVOSurfacePatch::getPool() +LLFacePool *LLVOSurfacePatch::getPool() { - mPool = gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture()); + mPool = (LLDrawPoolTerrain*) gPipeline.getPool(LLDrawPool::POOL_TERRAIN, mPatchp->getSurface()->getSTexture()); return mPool; } @@ -125,15 +171,18 @@ LLDrawable *LLVOSurfacePatch::createDrawable(LLPipeline *pipeline) range = 3; } - LLDrawPool *poolp = getPool(); + LLFacePool *poolp = getPool(); mDrawable->addFace(poolp, NULL); + return mDrawable; } BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TERRAIN); + S32 min_comp, max_comp, range; min_comp = lltrunc(mPatchp->getMinComposition()); max_comp = lltrunc(ceil(mPatchp->getMaxComposition())); @@ -185,57 +234,63 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) east_stride = render_stride; } + mLastLength = length; + mLastStride = render_stride; + mLastNorthStride = north_stride; + mLastEastStride = east_stride; + + return TRUE; +} + +void LLVOSurfacePatch::updateFaceSize(S32 idx) +{ + if (idx != 0) + { + llwarns << "Terrain partition requested invalid face!!!" << llendl; + return; + } + + LLFace* facep = mDrawable->getFace(idx); + S32 num_vertices = 0; S32 num_indices = 0; - S32 new_north_offset = 0; - S32 new_east_offset = 0; - - getGeomSizesMain(render_stride, num_vertices, num_indices); - new_north_offset = num_vertices; - getGeomSizesNorth(render_stride, north_stride, num_vertices, num_indices); - new_east_offset = num_vertices; - getGeomSizesEast(render_stride, east_stride, num_vertices, num_indices); - S32 new_num_vertices = num_vertices; - S32 new_num_indices = num_indices; - - LLFace *facep = NULL; - - // Update the allocated face - LLStrider verticesp; - LLStrider normalsp; - LLStrider texCoords0p; - LLStrider texCoords1p; - LLStrider colorsp; - U32* indicesp = NULL; - S32 index_offset; - - facep = mDrawable->getFace(0); - - facep->setSize(new_num_vertices, new_num_indices); - facep->setPrimType(LLTriangles); - - index_offset = facep->getGeometryTerrain( - verticesp, - normalsp, - colorsp, - texCoords0p, - texCoords1p, - indicesp); - if (-1 == index_offset) + + if (mLastStride) { - return TRUE; + getGeomSizesMain(mLastStride, num_vertices, num_indices); + getGeomSizesNorth(mLastStride, mLastNorthStride, num_vertices, num_indices); + getGeomSizesEast(mLastStride, mLastEastStride, num_vertices, num_indices); } - mDrawable->updateLightSet(); + facep->setSize(num_vertices, num_indices); +} + +BOOL LLVOSurfacePatch::updateLOD() +{ + //mDrawable->updateLightSet(); + mDrawable->setState(LLDrawable::LIGHTING_BUILT); + return TRUE; +} + +void LLVOSurfacePatch::getGeometry(LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &colorsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp) +{ + LLFace* facep = mDrawable->getFace(0); + + U32 index_offset = facep->getGeomIndex(); updateMainGeometry(facep, - verticesp, - normalsp, - colorsp, - texCoords0p, - texCoords1p, - indicesp, - index_offset); + verticesp, + normalsp, + colorsp, + texCoords0p, + texCoords1p, + indicesp, + index_offset); updateNorthGeometry(facep, verticesp, normalsp, @@ -252,24 +307,6 @@ BOOL LLVOSurfacePatch::updateGeometry(LLDrawable *drawable) texCoords1p, indicesp, index_offset); - - if (mLastLength != 0) - { - // lazy, should cache the geom sizes so we know the offsets. - num_vertices = 0; - num_indices = 0; - - } - - mLastLength = length; - mLastStride = render_stride; - mLastNorthStride = north_stride; - mLastEastStride = east_stride; - - mDrawable->setState(LLDrawable::LIGHTING_BUILT); - - LLPipeline::sCompiles++; - return TRUE; } void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, @@ -278,8 +315,8 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset) + LLStrider &indicesp, + U32 &index_offset) { S32 i, j, x, y; @@ -287,7 +324,7 @@ void LLVOSurfacePatch::updateMainGeometry(LLFace *facep, S32 num_vertices, num_indices; U32 index; - render_stride = mPatchp->getRenderStride(); + render_stride = mLastStride; patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); S32 vert_size = patch_size / render_stride; @@ -383,29 +420,20 @@ void LLVOSurfacePatch::updateNorthGeometry(LLFace *facep, LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset) + LLStrider &indicesp, + U32 &index_offset) { S32 vertex_count = 0; S32 i, x, y; S32 num_vertices, num_indices; - U32 render_stride = mPatchp->getRenderStride(); + U32 render_stride = mLastStride; S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); S32 length = patch_size / render_stride; S32 half_length = length / 2; - - U32 north_stride; - if (mPatchp->getNeighborPatch(NORTH)) - { - north_stride = mPatchp->getNeighborPatch(NORTH)->getRenderStride(); - } - else - { - north_stride = render_stride; - } - + U32 north_stride = mLastNorthStride; + /////////////////////////// // // Render the north strip @@ -605,27 +633,19 @@ void LLVOSurfacePatch::updateEastGeometry(LLFace *facep, LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset) + LLStrider &indicesp, + U32 &index_offset) { S32 i, x, y; S32 num_vertices, num_indices; - U32 render_stride = mPatchp->getRenderStride(); + U32 render_stride = mLastStride; S32 patch_size = mPatchp->getSurface()->getGridsPerPatchEdge(); S32 length = patch_size / render_stride; S32 half_length = length / 2; - U32 east_stride; - if (mPatchp->getNeighborPatch(EAST)) - { - east_stride = mPatchp->getNeighborPatch(EAST)->getRenderStride(); - } - else - { - east_stride = render_stride; - } + U32 east_stride = mLastEastStride; // Stride lengths are the same if (east_stride == render_stride) @@ -844,10 +864,6 @@ void LLVOSurfacePatch::setPatch(LLSurfacePatch *patchp) void LLVOSurfacePatch::dirtyPatch() { - if (mDrawable) - { - gPipeline.markMoved(mDrawable); - } mDirtiedPatch = TRUE; dirtyGeom(); mDirtyTerrain = TRUE; @@ -865,6 +881,8 @@ void LLVOSurfacePatch::dirtyGeom() if (mDrawable) { gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); + mDrawable->getFace(0)->mVertexBuffer = NULL; + mDrawable->movePartition(); } } @@ -937,7 +955,67 @@ void LLVOSurfacePatch::updateSpatialExtents(LLVector3& newMin, LLVector3 &newMax { LLVector3 posAgent = getPositionAgent(); LLVector3 scale = getScale(); - newMin = posAgent-scale; - newMax = posAgent+scale; + newMin = posAgent-scale*0.5f; + newMax = posAgent+scale*0.5f; mDrawable->setPositionGroup((newMin+newMax)*0.5f); } + +U32 LLVOSurfacePatch::getPartitionType() const +{ + return LLPipeline::PARTITION_TERRAIN; +} + +LLTerrainPartition::LLTerrainPartition() +: LLSpatialPartition(LLDrawPoolTerrain::VERTEX_DATA_MASK) +{ + mRenderByGroup = FALSE; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; + mDrawableType = LLPipeline::RENDER_TYPE_TERRAIN; + mPartitionType = LLPipeline::PARTITION_TERRAIN; +} + +LLVertexBuffer* LLTerrainPartition::createVertexBuffer(U32 type_mask, U32 usage) +{ + return new LLVertexBufferTerrain(); +} + +void LLTerrainPartition::getGeometry(LLSpatialGroup* group) +{ + LLVertexBuffer* buffer = group->mVertexBuffer; + + //get vertex buffer striders + LLStrider vertices; + LLStrider normals; + LLStrider texcoords2; + LLStrider texcoords; + LLStrider colors; + LLStrider indices; + + buffer->getVertexStrider(vertices); + buffer->getNormalStrider(normals); + buffer->getTexCoordStrider(texcoords); + buffer->getTexCoord2Strider(texcoords2); + buffer->getColorStrider(colors); + buffer->getIndexStrider(indices); + + U32 indices_index = 0; + U32 index_offset = 0; + + for (std::vector::iterator i = mFaceList.begin(); i != mFaceList.end(); ++i) + { + LLFace* facep = *i; + + facep->setIndicesIndex(indices_index); + facep->setGeomIndex(index_offset); + facep->mVertexBuffer = buffer; + + LLVOSurfacePatch* patchp = (LLVOSurfacePatch*) facep->getViewerObject(); + patchp->getGeometry(vertices, normals, colors, texcoords, texcoords2, indices); + + indices_index += facep->getIndicesCount(); + index_offset += facep->getGeomCount(); + } + + mFaceList.clear(); +} + diff --git a/linden/indra/newview/llvosurfacepatch.h b/linden/indra/newview/llvosurfacepatch.h index 3549571..75d57cb 100644 --- a/linden/indra/newview/llvosurfacepatch.h +++ b/linden/indra/newview/llvosurfacepatch.h @@ -35,9 +35,19 @@ class LLSurfacePatch; class LLDrawPool; class LLVector2; -class LLVOSurfacePatch : public LLViewerObject +class LLVOSurfacePatch : public LLStaticViewerObject { public: + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_COLOR) + } + eVertexDataMask; + LLVOSurfacePatch(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOSurfacePatch(); @@ -46,8 +56,18 @@ public: // Initialize data that's only inited once per class. static void initClass(); + virtual U32 getPartitionType() const; + /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ BOOL updateLOD(); + /*virtual*/ void updateFaceSize(S32 idx); + void getGeometry(LLStrider &verticesp, + LLStrider &normalsp, + LLStrider &colorsp, + LLStrider &texCoords0p, + LLStrider &texCoords1p, + LLStrider &indicesp); /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area @@ -63,8 +83,8 @@ public: BOOL mDirtiedPatch; protected: - LLDrawPool *mPool; - LLDrawPool *getPool(); + LLFacePool *mPool; + LLFacePool *getPool(); S32 mBaseComp; LLSurfacePatch *mPatchp; BOOL mDirtyTexture; @@ -89,24 +109,24 @@ protected: LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset); + LLStrider &indicesp, + U32 &index_offset); void updateNorthGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset); + LLStrider &indicesp, + U32 &index_offset); void updateEastGeometry(LLFace *facep, LLStrider &verticesp, LLStrider &normalsp, LLStrider &colorsp, LLStrider &texCoords0p, LLStrider &texCoords1p, - U32* &indicesp, - S32 &index_offset); + LLStrider &indicesp, + U32 &index_offset); }; #endif // LL_VOSURFACEPATCH_H diff --git a/linden/indra/newview/llvotextbubble.cpp b/linden/indra/newview/llvotextbubble.cpp index 96ffe6b..ee0359b 100644 --- a/linden/indra/newview/llvotextbubble.cpp +++ b/linden/indra/newview/llvotextbubble.cpp @@ -43,7 +43,7 @@ #include "pipeline.h" LLVOTextBubble::LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, pcode, regionp) +: LLAlphaObject(id, pcode, regionp) { setScale(LLVector3(1.5f, 1.5f, 0.25f)); mbCanSelect = FALSE; @@ -102,8 +102,10 @@ BOOL LLVOTextBubble::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) for (i = 0; i < getNumTEs(); i++) { setTEColor(i, color); + setTEFullbright(i, TRUE); } + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); return TRUE; } @@ -145,15 +147,14 @@ LLDrawable *LLVOTextBubble::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - LLDrawPool *poolp; + for (U32 i = 0; i < getNumTEs(); i++) { LLViewerImage *imagep; const LLTextureEntry *texture_entry = getTE(i); imagep = gImageList.getImage(texture_entry->getID()); - poolp = gPipeline.getPool(LLDrawPool::POOL_ALPHA); - mDrawable->addFace(poolp, imagep); + mDrawable->addFace((LLFacePool*) NULL, imagep); } return mDrawable; @@ -200,24 +201,65 @@ BOOL LLVOTextBubble::updateGeometry(LLDrawable *drawable) for (S32 i = 0; i < drawable->getNumFaces(); i++) { LLFace *face = drawable->getFace(i); - - if (i == 0) - { - face->setSize(0); - continue; - } - if (i == 2) - { - face->setSize(0); - continue; - } - - // Need to figure out how to readd logic to determine face dirty vs. entire object dirty. face->setTEOffset(i); - face->clearState(LLFace::GLOBAL); - face->genVolumeTriangles(*getVolume(), i, identity4, identity3); + face->setTexture(LLViewerImage::sSmokeImagep); + face->setState(LLFace::FULLBRIGHT); } + mVolumeChanged = FALSE; + mDrawable->movePartition(); return TRUE; } + +void LLVOTextBubble::updateFaceSize(S32 idx) +{ + LLFace* face = mDrawable->getFace(idx); + + if (idx == 0 || idx == 2) + { + face->setSize(0,0); + } + else + { + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + face->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); + } +} + +void LLVOTextBubble::getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp) +{ + if (idx == 0 || idx == 2) + { + return; + } + + const LLVolumeFace& face = getVolume()->getVolumeFace(idx); + + LLVector3 pos = getPositionAgent(); + LLColor4U color = LLColor4U(getTE(idx)->getColor()); + U32 offset = mDrawable->getFace(idx)->getGeomIndex(); + + for (U32 i = 0; i < face.mVertices.size(); i++) + { + *verticesp++ = face.mVertices[i].mPosition.scaledVec(getScale()) + pos; + *normalsp++ = face.mVertices[i].mNormal; + *texcoordsp++ = face.mVertices[i].mTexCoord; + *colorsp++ = color; + } + + for (U32 i = 0; i < face.mIndices.size(); i++) + { + *indicesp++ = face.mIndices[i] + offset; + } +} + +U32 LLVOTextBubble::getPartitionType() const +{ + return LLPipeline::PARTITION_PARTICLE; +} diff --git a/linden/indra/newview/llvotextbubble.h b/linden/indra/newview/llvotextbubble.h index b77ed1a..bd1d241 100644 --- a/linden/indra/newview/llvotextbubble.h +++ b/linden/indra/newview/llvotextbubble.h @@ -31,7 +31,7 @@ #include "llviewerobject.h" #include "llframetimer.h" -class LLVOTextBubble : public LLViewerObject +class LLVOTextBubble : public LLAlphaObject { public: LLVOTextBubble(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); @@ -44,6 +44,16 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); /*virtual*/ BOOL updateLOD(); + /*virtual*/ void updateFaceSize(S32 idx); + + /*virtual*/ void getGeometry(S32 idx, + LLStrider& verticesp, + LLStrider& normalsp, + LLStrider& texcoordsp, + LLStrider& colorsp, + LLStrider& indicesp); + + virtual U32 getPartitionType() const; LLColor4 mColor; S32 mLOD; diff --git a/linden/indra/newview/llvotree.cpp b/linden/indra/newview/llvotree.cpp index 9808a02..382f9a6 100644 --- a/linden/indra/newview/llvotree.cpp +++ b/linden/indra/newview/llvotree.cpp @@ -29,6 +29,8 @@ #include "llvotree.h" +#include "lldrawpooltree.h" + #include "llviewercontrol.h" #include "lldir.h" #include "llprimitive.h" @@ -38,7 +40,6 @@ #include "object_flags.h" #include "llagent.h" -#include "llagparray.h" #include "llcylinder.h" #include "lldrawable.h" #include "llface.h" @@ -231,13 +232,13 @@ void LLVOTree::initClass() BOOL have_all_trees = TRUE; LLString err; - char buffer[10]; + char buffer[10]; /* Flawfinder: ignore */ for (S32 i=0;iaddTextureStats(mPixelArea, texel_area_ratio, cos_angle); } @@ -421,14 +426,12 @@ LLDrawable* LLVOTree::createDrawable(LLPipeline *pipeline) mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE); - LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep); + LLDrawPoolTree *poolp = (LLDrawPoolTree*) gPipeline.getPool(LLDrawPool::POOL_TREE, mTreeImagep); // Just a placeholder for an actual object... - LLFace *facep = mDrawable->addFace(poolp, mTreeImagep, TRUE); + LLFace *facep = mDrawable->addFace(poolp, mTreeImagep); facep->setSize(1, 3); - gPipeline.markMaterialed(mDrawable); - updateRadius(); return mDrawable; @@ -441,6 +444,7 @@ const S32 LEAF_VERTICES = 16; BOOL LLVOTree::updateGeometry(LLDrawable *drawable) { + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_TREE); U32 i, j; const S32 MAX_SLICES = 32; @@ -463,20 +467,6 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) face->mCenterAgent = getPositionAgent(); face->mCenterLocal = face->mCenterAgent; - LLDrawPool *poolp = face->getPool(); - - if (poolp->getVertexCount()) - { - return TRUE; - } - - if (!face->getDirty()) - { - return FALSE; - } - - poolp->setDirty(); - for (lod = 0; lod < 4; lod++) { slices = sLODSlices[lod]; @@ -491,10 +481,17 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) LLStrider vertices; LLStrider normals; LLStrider tex_coords; - U32 *indicesp; + LLStrider indicesp; face->setSize(max_vertices, max_indices); + + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolTree::VERTEX_DATA_MASK, GL_STATIC_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(max_vertices, max_indices, TRUE); + face->setGeomIndex(0); + face->setIndicesIndex(0); + face->getGeometry(vertices, normals, tex_coords, indicesp); + S32 vertex_count = 0; S32 index_count = 0; @@ -793,17 +790,13 @@ BOOL LLVOTree::updateGeometry(LLDrawable *drawable) return TRUE; } -void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha) +U32 LLVOTree::drawBranchPipeline(U32* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha) { + U32 ret = 0; // // Draws a tree by recursing, drawing branches and then a 'leaf' texture. // If stop_level = -1, simply draws the whole tree as a billboarded texture // - - if (!draw_pool->getIndexCount()) - { - return; // safety net - } static F32 constant_twist; static F32 width = 0; @@ -827,15 +820,15 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop width = scale * length * aspect; glPushMatrix(); glScalef(width,width,scale * length); - //glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, draw_pool.getRawIndices() + sLODIndexOffset[trunk_LOD]); - glDrawRangeElements(GL_TRIANGLES, + glDrawElements(GL_TRIANGLES, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, indicesp + sLODIndexOffset[trunk_LOD]); + /*glDrawRangeElements(GL_TRIANGLES, sLODVertexOffset[trunk_LOD], sLODVertexOffset[trunk_LOD] + sLODVertexCount[trunk_LOD]-1, sLODIndexCount[trunk_LOD], GL_UNSIGNED_INT, - draw_pool->getRawIndices() + sLODIndexOffset[trunk_LOD]); + indicesp + sLODIndexOffset[trunk_LOD]);*/ stop_glerror(); - draw_pool->addIndicesDrawn(sLODIndexCount[trunk_LOD]); + ret += sLODIndexCount[trunk_LOD]; glPopMatrix(); } @@ -847,7 +840,7 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop glRotatef((constant_twist + ((i%2==0)?twist:-twist))*i, 0.f, 0.f, 1.f); glRotatef(droop, 0.f, 1.f, 0.f); glRotatef(20.f, 0.f, 0.f, 1.f); // rotate 20deg about axis of new branch to add some random variation - drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha); + ret += drawBranchPipeline(indicesp, trunk_LOD, stop_level, depth - 1, 0, scale*mScaleStep, twist, droop, branches, alpha); glPopMatrix(); } // Recurse to continue trunk @@ -856,7 +849,7 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop glPushMatrix(); glTranslatef(0.f, 0.f, scale * length); glRotatef(70.5f, 0.f, 0.f, 1.f); // rotate a bit around Z when ascending - drawBranchPipeline(draw_pool, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); + ret += drawBranchPipeline(indicesp, trunk_LOD, stop_level, depth, trunk_depth-1, scale*mScaleStep, twist, droop, branches, alpha); glPopMatrix(); } } @@ -871,15 +864,15 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop //width = scale * (TREE_BRANCH_ASPECT + TREE_LEAF_ASPECT); glScalef(scale*mLeafScale, scale*mLeafScale, scale*mLeafScale); //glScalef(1.5f*width*mLeafScale,1,1.5f*scale*mLeafScale); -// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices()); - glDrawRangeElements(GL_TRIANGLES, + glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, indicesp); + /*glDrawRangeElements(GL_TRIANGLES, 0, LEAF_VERTICES-1, LEAF_INDICES, GL_UNSIGNED_INT, - draw_pool->getRawIndices()); + indicesp);*/ stop_glerror(); - draw_pool->addIndicesDrawn(LEAF_INDICES); + ret += LEAF_INDICES; glPopMatrix(); } } @@ -897,21 +890,23 @@ void LLVOTree::drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop { glPushMatrix(); glScalef(mBillboardScale*mBillboardRatio, mBillboardScale*mBillboardRatio, mBillboardScale); -// glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, draw_pool.getRawIndices()); - glDrawRangeElements(GL_TRIANGLES, + glDrawElements(GL_TRIANGLES, LEAF_INDICES, GL_UNSIGNED_INT, indicesp); +/* glDrawRangeElements(GL_TRIANGLES, 0, LEAF_VERTICES-1, LEAF_INDICES, GL_UNSIGNED_INT, - draw_pool->getRawIndices()); + indicesp);*/ stop_glerror(); - draw_pool->addIndicesDrawn(LEAF_INDICES); + ret += LEAF_INDICES; glPopMatrix(); } glMatrixMode(GL_TEXTURE); glPopMatrix(); glMatrixMode(GL_MODELVIEW); } + + return ret; } void LLVOTree::updateRadius() @@ -923,3 +918,30 @@ void LLVOTree::updateRadius() mDrawable->setRadius(32.0f); } + +void LLVOTree::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) +{ + LLVector3 center = getRenderPosition(); + LLVector3 size = getScale(); + center.mV[2] += size.mV[2]; + + newMin.setVec(center-size); + newMax.setVec(center+size); + mDrawable->setPositionGroup((newMin + newMax) * 0.5f); +} + +U32 LLVOTree::getPartitionType() const +{ + return LLPipeline::PARTITION_TREE; +} + +LLTreePartition::LLTreePartition() +: LLSpatialPartition(0) +{ + mRenderByGroup = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_TREE; + mPartitionType = LLPipeline::PARTITION_TREE; + mSlopRatio = 0.f; + mLODPeriod = 1; +} + diff --git a/linden/indra/newview/llvotree.h b/linden/indra/newview/llvotree.h index 4d11d20..fb35dd9 100644 --- a/linden/indra/newview/llvotree.h +++ b/linden/indra/newview/llvotree.h @@ -39,6 +39,14 @@ class LLDrawPool; class LLVOTree : public LLViewerObject { public: + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) + } + eVertexDataMask; + LLVOTree(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOTree(); @@ -59,10 +67,13 @@ public: /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void updateSpatialExtents(LLVector3 &min, LLVector3 &max); + + virtual U32 getPartitionType() const; void updateRadius(); - void drawBranchPipeline(LLDrawPool *draw_pool, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha); + U32 drawBranchPipeline(U32* indicesp, S32 trunk_LOD, S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha); void drawBranch(S32 stop_level, U16 depth, U16 trunk_depth, F32 scale, F32 twist, F32 droop, F32 branches, F32 alpha, BOOL draw_leaves); diff --git a/linden/indra/newview/llvotreenew.cpp b/linden/indra/newview/llvotreenew.cpp deleted file mode 100644 index d7fc635..0000000 --- a/linden/indra/newview/llvotreenew.cpp +++ /dev/null @@ -1,1470 +0,0 @@ -/** - * @file llvotreenew.cpp - * @brief LLVOTreeNew class implementation - * - * Copyright (c) 2003-2007, Linden Research, Inc. - * - * The source code in this file ("Source Code") is provided by Linden Lab - * to you under the terms of the GNU General Public License, version 2.0 - * ("GPL"), unless you have obtained a separate licensing agreement - * ("Other License"), formally executed 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. - */ - -#include "llviewerprecompiledheaders.h" - -#include "llvotreenew.h" - -#include "llgl.h" -#include "llglheaders.h" -#include "lltree_common.h" -#include "lltreeparams.h" -#include "material_codes.h" -#include "object_flags.h" - -#include "llagent.h" -#include "llagparray.h" -#include "llviewercontrol.h" -#include "llcylinder.h" -#include "lldrawable.h" -#include "llface.h" -#include "llprimitive.h" -#include "llviewerimagelist.h" -#include "llviewerobjectlist.h" -#include "llviewerregion.h" -#include "llworld.h" -#include "noise.h" -#include "pipeline.h" - -U32 LLVOTreeNew::sNextVertexIndex[MAX_SPECIES]; -U32 LLVOTreeNew::sNextIndiceIndex[MAX_SPECIES]; -U32 LLVOTreeNew::sNextPartIndex[MAX_PARTS]; -LLVOTreeNew::TreePart LLVOTreeNew::sTreeParts[MAX_SPECIES][MAX_PARTS]; -LLUUID LLVOTreeNew::sTreeImageIDs[MAX_SPECIES]; -U32 LLVOTreeNew::sTreePartsUsed[MAX_SPECIES][MAX_PARTS][MAX_VARS]; -LLTreeParams LLVOTreeNew::sParameters; -F32 LLVOTreeNew::sRandNums[MAX_RAND_NUMS]; - -extern LLPipeline gPipeline; - -// Tree variables and functions - -LLVOTreeNew::LLVOTreeNew(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp): - LLViewerObject(id, pcode, regionp) -{ - mTotalIndices = 0; - mTotalVerts = 0; - mSpecies = 0; -} - - -LLVOTreeNew::~LLVOTreeNew() -{ - if (mData) - { - delete[] mData; - mData = NULL; - } -} - - -void LLVOTreeNew::initClass() -{ - U8 i; - - // for now just load the same texture in for every tree... - - for (i = 0; i < MAX_SPECIES; i++) - { - switch (i) { - case (0): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_pine_1.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_pine_1.tga") )); - break; - case (1): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_oak.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_oak.tga") )); - break; - case (2): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_tropical_1.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_tropical_1.tga") )); - break; - case (3): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_palm_1.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_palm_1.tga") )); - break; - case (4): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_dogwood.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_dogwood.tga") )); - break; - case (5): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_tropical_2.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_tropical_2.tga") )); - break; - case (6): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_palm_2.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_palm_2.tga") )); - break; - case (7): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_cypress_1.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_cypress_1.tga") )); - break; - case (8): - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_cypress_2.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_cypress_2.tga") )); - break; - default: - sTreeImageIDs[i] = LLUUID( gViewerArt.getString("tree_pine_2.tga") ); - //LLVOTreeNew::sTreeImagep[i] = gImageList.getImage(LLUUID( gViewerArt.getString("tree_pine_2.tga") )); - break; - } - } - - - //LLVOTreeNew::sParameters = LLTreeParams(); - - // initialize an array of random numbers that we'll be using - LLRandLagFib607 tree_rand; - for (i = 0; i < MAX_RAND_NUMS; i++) - sRandNums[i] = (F32)tree_rand(); -} - -/* -void LLVOTreeNew::cleanupTextures() -{ - S32 i; - for (i = 0; i < MAX_SPECIES; i++) - { - mTreeImagep = NULL; - } -} -*/ - -U32 LLVOTreeNew::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, EObjectUpdateType update_type, - LLDataPacker *dp) -{ - // Do base class updates... - U32 retval = LLViewerObject::processUpdateMessage(mesgsys, user_data, block_num, update_type, dp); - - if ( (getVelocity().magVecSquared() > 0.f) - ||(getAcceleration().magVecSquared() > 0.f) - ||(getAngularVelocity().magVecSquared() > 0.f)) - { - llinfos << "ACK! Moving tree!" << llendl; - setVelocity(LLVector3::zero); - setAcceleration(LLVector3::zero); - setAngularVelocity(LLVector3::zero); - } - - mSpecies = ((U8 *)mData)[0]; - mSpecies = 1; - - if (mSpecies >= MAX_SPECIES) - { - mSpecies = 0; - } - - - mTreeImagep = gImageList.getImage(sTreeImageIDs[mSpecies]); - if (mTreeImagep) - { - mTreeImagep->bindTexture(0); - mTreeImagep->setClamp(TRUE, TRUE); - } - - return retval; -} - - -BOOL LLVOTreeNew::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - return TRUE; -} - - -void LLVOTreeNew::render(LLAgent &agent) -{ - // nothing -} - - -void LLVOTreeNew::updateTextures(LLAgent &agent) -{ - LLVector3 position_local = getPositionAgent() - agent.getCameraPositionAgent(); - F32 dot_product = position_local * agent.getFrameAgent().getAtAxis(); - F32 cos_angle = dot_product / position_local.magVec(); - - if (cos_angle > 1.f) - { - cos_angle = 1.f; - } - - // temporary aggregate texture scale calculation - // this is less correct than the code above! - F32 texel_area_ratio = 0.5f; // When we're billboarded, we use less than the whole texture (about half?) - if (mTreeImagep) - { - mTreeImagep->addTextureStats(mPixelArea, texel_area_ratio, cos_angle); - } - -} - - -LLDrawable* LLVOTreeNew::createDrawable(LLPipeline *pipeline) -{ - - pipeline->allocDrawable(this); - mDrawable->setLit(FALSE); - - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_TREE); - //llinfos << "tree type: " << LLPipeline::RENDER_TYPE_TREE << llendl; - - //!! add the leaf texture to this - LLDrawPool *poolp = gPipeline.getPool(LLDrawPool::POOL_TREE_NEW, mTreeImagep); - - - //!! add a face for the bark texture... - //LLFace *facep = mDrawable->addFace(poolp, mTreeImagep, TRUE); - mDrawable->addFace(poolp, mTreeImagep, TRUE); - //facep->setSize(1, 3); - - //!! add a face for the leaf texture ?? - // - - gPipeline.markMaterialed(mDrawable); - - return mDrawable; -} - - - -BOOL LLVOTreeNew::updateGeometry(LLDrawable *drawable) -{ - - llinfos << "TREE SPECIES " << U32(mSpecies) << llendl; - - // create the basic geometry of the trunk and branch - - // get the face for the branches... - LLFace *face = drawable->getFace(0); - LLDrawPool *poolp = face->getPool(); - - if (!face->getDirty()) - { - return TRUE; - } - - poolp->setDirty(); - - U32 curVertexIndex, curTexCoordIndex, curNormalIndex; - U32 curIndiceIndex; -// U32 numVertsCreated = LLVOTreeNew::sNextVertexIndex[mSpecies]; - - //U32 vertexCount = poolp->getVertexCount(); - //llinfos << "TREE vertexCount = " << vertexCount << ", nextVertexIndex = " << mNextVertexIndex[mSpecies] << llendl; - //U32 indiceCount = poolp->getIndexCount(); - //llinfos << "TREE indiceCount = " << indiceCount << ", nextIndiceIndex = " << mNextIndiceIndex[mSpecies] << llendl; - - - if (poolp->getVertexCount() > 0) - { - //llinfos << "TREE not creating the arrays..." << llendl; - } - else - { - // create the drawpool arrays - // using some rough estimates - U32 numVerts = NUM_INIT_VERTS; - U32 numIndices = NUM_INIT_INDICES; - - face->setPrimType(LLTriangles); - face->setSize(numVerts, numIndices); - - // reset the next's since they may have been previously initialized... - LLVOTreeNew::sNextIndiceIndex[mSpecies] = 0; - LLVOTreeNew::sNextVertexIndex[mSpecies] = 0; - LLVOTreeNew::sNextPartIndex[mSpecies] = 0; - - //llinfos << "TREE creating the arrays..." << llendl; - } - - curVertexIndex = LLVOTreeNew::sNextVertexIndex[mSpecies]; - curTexCoordIndex = curVertexIndex; - curNormalIndex = curVertexIndex; - curIndiceIndex = LLVOTreeNew::sNextIndiceIndex[mSpecies]; - - //vertexCount = poolp->getVertexCount(); - //llinfos << "TREE vertexCount = " << vertexCount << ", nextVertexIndex = " << mNextVertexIndex[mSpecies] << llendl; - //indiceCount = poolp->getIndexCount(); - //llinfos << "TREE indiceCount = " << indiceCount << ", nextIndiceIndex = " << mNextIndiceIndex[mSpecies] << llendl; - - //llinfos << "TREE \t" << "\t curVertexIndex: \t" << curVertexIndex << llendl; - //llinfos << "TREE \t" << "\t curIndiceIndex: \t" << curIndiceIndex << llendl; - - LLStrider vertices; - LLStrider normals; - LLStrider tex_coords; - U32 *indices; - - face->getGeometry(vertices, normals, tex_coords, indices); - - // create different parts for the levels... - - // create the trunk... - F32 length, curve, radius, parentLength, parentRadius; - - length = parentLength = sParameters.mLength[0] * sParameters.mScale; - radius = parentRadius = length * sParameters.mRatio * sParameters.mScale0; - curve = sParameters.mCurve[0]; - createPart(0, length, radius, vertices, normals, tex_coords, indices, curVertexIndex, curTexCoordIndex, - curNormalIndex, curIndiceIndex); - - // create collection of curved branches... - //* - for (U8 i = 1; i <= sParameters.mLevels; i++) - { - length = sParameters.mLength[i] * parentLength; - radius = parentRadius * pow((length / parentLength), sParameters.mRatioPower); - - llinfos << "TREE creating (?) part with radius: " << radius << " and length: " << length << llendl; - - createPart(i, length, radius, vertices, normals, tex_coords, indices, curVertexIndex, curTexCoordIndex, - curNormalIndex, curIndiceIndex); - - parentRadius = radius; - parentLength = length; - - } - //*/ - - LLVOTreeNew::sNextVertexIndex[mSpecies] = curVertexIndex; - LLVOTreeNew::sNextIndiceIndex[mSpecies] = curIndiceIndex; - - // create a leaf...? - - return TRUE; -} - -F32 LLVOTreeNew::CalcZStep(TreePart *part, U8 section) -{ - F32 zStep; - - if (part->mLevel == 0 && section < sParameters.mFlareRes) - zStep = (sParameters.mFlarePercentage * part->mLength)/sParameters.mFlareRes; - else - zStep = ((1.f - sParameters.mFlarePercentage)*part->mLength) / (part->mCurveRes); - - return zStep; -} - -S32 LLVOTreeNew::findSimilarPart(U8 level) -{ - // see if there's a tree part that's similar... - for (U8 i = 0; i < sNextPartIndex[mSpecies]; i++) - { - TreePart *curPart = &(sTreeParts[mSpecies][i]); - // make sure older branch is at same 'level' and has - // similar lobe parameters (if at the trunk level) - if (curPart->mLevel == level && - (level != 0 || (llabs(curPart->mLobes - sParameters.mLobes) < MAX_LOBES_DIFF && llabs(curPart->mLobeDepth - sParameters.mLobeDepth) < MAX_LOBEDEPTH_DIFF))) - { - // check to see if older branch's curve, curveBack, and curveV - // are all close to the desired branch... - F32 curveDiff = llabs(curPart->mCurve - sParameters.mCurve[level]); - F32 curveBackDiff = llabs(curPart->mCurveBack - sParameters.mCurveBack[level]); - F32 curveVDiff = llabs(curPart->mCurveV - sParameters.mCurveV[level]); - if (curveDiff < MAX_CURVE_DIFF - && curveVDiff < MAX_CURVE_V_DIFF - && (curveBackDiff == 0 || curveBackDiff < MAX_CURVEBACK_DIFF) - ) - { - // already have a branch that's close enough - return i; - } - } - } - - return -1; -} - - -void LLVOTreeNew::createPart(U8 level, F32 length, F32 radius, LLStrider &vertices, LLStrider &normals, - LLStrider &tex_coords, U32 *indices, - U32 &curVertexIndex, U32 &curTexCoordIndex, - U32 &curNormalIndex, U32 &curIndiceIndex) -{ - U8 i, j, k; - - // check for a similar branch... - S32 selectedPart = findSimilarPart(level); - if (selectedPart > -1) return; - - // if we didn't find the branch, make different versions of it - // depending on how large curveV (curveVariance), make more branches... - S32 numVariants = 1; - numVariants += (S32)(sParameters.mCurveV[level]/CURVEV_DIVIDER); - - if (numVariants > MAX_VARS) numVariants = MAX_VARS; - if (level == 0) numVariants = 1; // just make one trunk - - llinfos << "TREE generating " << numVariants << " variants for curveV of " << sParameters.mCurveV[level] << " on level " << U32(level) << llendl; - - - // if we've hit the max part limit, just quit... - if (sNextPartIndex[mSpecies] == MAX_PARTS) - { - llinfos << "TREE SPECIES RAN OUT OF DRAWPOOL PART SPACE..." << llendl; - return; - } - - // put the first variant in its own mTreePart - TreePart *part = &(LLVOTreeNew::sTreeParts[mSpecies][LLVOTreeNew::sNextPartIndex[mSpecies]++]); - - // set the tree part params from the basic tree params... - part->mCurve = sParameters.mCurve[level];; - part->mCurveRes = sParameters.mCurveRes[level]; - part->mCurveBack = sParameters.mCurveBack[level]; - part->mCurveV = sParameters.mCurveV[level]; - part->mLobeDepth = sParameters.mLobeDepth; - part->mLobes = sParameters.mLobes; - part->mLength = length; - part->mRadius = radius; - part->mLevel = level; - part->mVertsPerSection = sParameters.mVertices[level]; - part->mNumVariants = 0; - - // enforce constraints on # of resolutions - if (sParameters.mFlareRes > MAX_FLARE) sParameters.mFlareRes = MAX_FLARE; - if (part->mCurveRes > MAX_RES) part->mCurveRes = MAX_RES; - - for (k = 0; k < numVariants; k++) - { - part->mNumVariants++; - - // set the part's vertices to the first vertex and first index of its parts - part->mIndiceIndex[k] = curIndiceIndex; - - // how many total sections in the branch - U8 numSections = (U8)(part->mCurveRes) + (level == 0 ? sParameters.mFlareRes : 0); - - U8 framesUsed = 0; - U8 flareFramesUsed = 0; - F32 stemZ; - F32 startingZ = 0; - - // create curveRes different versions of the branch, with each - // one having its origin base be a different flareRes or curveRes base - - U32 oldOffset = mRandOffset[level]; - - for (j = 0; j < numSections; j++) - { - mRandOffset[level] = oldOffset; - if (j != 0) part->mOffsets[k][j - (level == 0 ? sParameters.mFlareRes : 0)] = curIndiceIndex; - - F32 sectionRadius; - LLMatrix4 curFrame; - U8 curSection = 0; - - // our position in the branch - stemZ = startingZ; - - // Make branches from - // From 0th section...numSections - // 1st section...numSections - // 2nd section...numSections - - sectionRadius = CalculateSectionRadius(level, stemZ / part->mLength, part->mLength, part->mRadius); - - // create points that make up the bottom of the section... - createSection(curFrame, part, sectionRadius, stemZ, - vertices, tex_coords, indices, - curVertexIndex, curTexCoordIndex, curIndiceIndex, curSection++, j == 0 ? TRUE : FALSE); - - for (i = j; i < numSections; i++) - { - // do the curving... - F32 angle; - if (part->mCurveBack != 0) - { - if (part->mCurveRes / (i + 1.0) < 2) - angle = part->mCurve / part->mCurveRes / 2.f; - else - angle = part->mCurveBack / part->mCurveRes / 2.f; - } - else - { - if (part->mLevel == 0) - { - if (i <= sParameters.mFlareRes) angle = (sParameters.mFlarePercentage*part->mCurve)/sParameters.mFlareRes; - else angle = ((1.f - sParameters.mFlarePercentage)*part->mCurve)/part->mCurveRes; - } - else - angle = part->mCurve / part->mCurveRes; - - } - - // add in variance just for kicks... - angle += llfrand_signed(part->mCurveV/part->mCurveRes, mRandOffset[level + i]++); - - /* vertical attraction is based on height of branch which is unavailable information - if (level > 1) - angle += CalculateVerticalAttraction(level, curFrame); - //*/ - - angle *= DEG_TO_RAD; - - // translation... - F32 zStep; - zStep = CalcZStep(part, i); - stemZ += zStep; - - // set the next startingZ as current stemZ if at first level - if (i == j || (level == 0 && j == 0 && i == sParameters.mFlareRes - 1)) - startingZ = stemZ; - - LLQuaternion rotateQuat, oldRotateQuat, newRotateQuat; - LLMatrix4 localFrame, transFrame; - - rotateQuat.setQuat(angle, 1.0f, 0.0f, 0.0f); - oldRotateQuat.setQuat(curFrame); - newRotateQuat = oldRotateQuat * rotateQuat; - - transFrame.translate(LLVector3(0, 0, zStep)); - transFrame.rotate(newRotateQuat); - - localFrame.rotate(newRotateQuat); - localFrame.translate(curFrame.getTranslation()); - localFrame.translate(transFrame.getTranslation()); - - curFrame = localFrame; - - // store flare frames seperately - if (part->mLevel == 0 && i < sParameters.mFlareRes) - mTrunkFlareFrames[flareFramesUsed++] = curFrame; - else - part->mFrames[k][framesUsed++] = curFrame; - - // calc radius of section - if (part->mLength == 0) - sectionRadius = 0; - else - sectionRadius = CalculateSectionRadius(level, stemZ / part->mLength, part->mLength, part->mRadius); - - // create points that make up the section - createSection(curFrame, part, sectionRadius, stemZ, - vertices, tex_coords, indices, - curVertexIndex, curTexCoordIndex, curIndiceIndex, curSection++, j == 0 ? TRUE : FALSE); - } - - // only do one trunk w/ flaring. - if (level == 0 && j == 0) j = sParameters.mFlareRes - 1; - } - - // gen vertex normals now that we've created face normals for the first section... - genVertexNormals(part, normals, numSections, curNormalIndex); - } - -} - - - - -void LLVOTreeNew::createSection(LLMatrix4 &frame, TreePart *part, F32 sectionRadius, F32 stemZ, - LLStrider &vertices, LLStrider &tex_coords, U32 *indices, - U32 &curVertexIndex, U32 &curTexCoordIndex, U32 &curIndiceIndex, U8 curSection, BOOL firstBranch) -{ - - F32 angle; // Angle holds the angle in radians - // between two points in the section. - - LLVector3 localPoint; // LocalPoint is used to hold the points - // that are being created and added to - // the points list of the section (in - // local coordinates) - - LLVector3 globalPoint; // GlobalPoint is used to hold the points - // that are being created and added to - // the points list of the section (in - // global coordinates) - - F32 lobedSectionRadius; // The sectionradius rescaled using - // the lobing parameters - - F32 percentX, percentY; // The texture coords - - - - U8 numVerts = part->mVertsPerSection; - - // prevent empty triangles - if (sectionRadius < 0.0001) { - sectionRadius = 0.0001f; - } - - // Y texture coordinate - // stemZ is current position within mLength... - percentY = stemZ; - //percentY = stemZ/part->mLength; - - angle = (2 * F_PI) / numVerts; - for (U8 i = 0; i <= numVerts; i++) - { - // last vertex is same as first one... - if (i == numVerts) - { - // make first vertice the last vertice (wrap around so that our texture coords will be ok... - globalPoint = vertices[curVertexIndex - numVerts]; - } - else - { - // lobed = 1.0 + lobeDepth * sin(lobes * angle) - lobedSectionRadius = sectionRadius * (1.f + sParameters.mLobeDepth * sin(sParameters.mLobes * (i + 1) * angle)); - - localPoint.mV[0] = cos((i + 1.f) * angle) * lobedSectionRadius; - localPoint.mV[1] = sin((i + 1.f) * angle) * lobedSectionRadius; - localPoint.mV[2] = 0; - - globalPoint = localPoint * frame; - } - - if (curVertexIndex > NUM_INIT_VERTS) { - llinfos << "TREE ERROR NO MORE VERTS" << llendl; - return; - } - - // add to instanced data... - vertices[curVertexIndex++] = globalPoint; - mTotalVerts++; - - /* - // update the max x, y, and z of tree - if (globalPoint->mV[0] > mTree->mMaxX) { mTree->mMaxX = globalPoint->mV[0]; } - if (globalPoint->mV[1] > mTree->mMaxY) { mTree->mMaxY = globalPoint->mV[1]; } - if (globalPoint->mV[2] > mTree->mMaxZ) { mTree->mMaxZ = globalPoint->mV[2]; } - */ - - // TEXTURE COORDS - percentX = WIDTH_OF_BARK * (i/F32(numVerts));// * (2.0*F_PI*sectionRadius); - //percentX = * (i/F32(numVerts)); - tex_coords[curTexCoordIndex++] = LLVector2(percentX, percentY); - } - - // gen face normals and do texcoords... - if (curSection != 0) - genIndicesAndFaceNormalsForLastSection(part, numVerts, vertices, curVertexIndex, indices, curIndiceIndex, firstBranch); -} - - -// generate face normals for the last two cross sections in sectionlist -void LLVOTreeNew::genIndicesAndFaceNormalsForLastSection(TreePart *part, U8 numVerts, LLStrider &vertices, U32 curVertexIndex, U32 *indices, U32 &curIndiceIndex, BOOL firstBranch) -{ - - LLVector3 v1, v2; - LLVector3 vCross; - LLVector3 a, b, c, d; - - // offsets into the vertex array - U32 upperOffset = curVertexIndex - (numVerts + 1); - U32 lowerOffset = upperOffset - (numVerts + 1); - - // generate the normals for the triangles from the quads - // quad is defined by: - // upper[i].....upper[i+1] - // . . - // . . - // . . - // lower[i].....lower[i+1] - - // 10.......11 - // . . . - // . . . - // . . . - // 00 . . . 01 - - // b . . . d - // . . . - // . . . - // . . . - // a . . . c - - for (U8 j = 0; j < numVerts; j++ ) { - - U8 nextVert = j + 1; - - // do face normals for first version only - if (firstBranch) - { - // the points of the quad - a = vertices[lowerOffset]; // 00 - b = vertices[upperOffset]; // 10 - c = vertices[lowerOffset + nextVert]; // 01 - d = vertices[upperOffset + nextVert]; // 11 - - // 1st triangle - v1 = c - b; - v2 = a - b; - vCross = v1 % v2; - vCross.normVec(); - part->mFaceNormals.put(vCross); - - // 2nd triangle - v1 = c - b; - v2 = d - b; - vCross = v1 % v2; - vCross.normVec(); - part->mFaceNormals.put(vCross); - } - - if (curIndiceIndex + 6 > NUM_INIT_INDICES) - { - llinfos << "TREE ERROR NO MORE INDICES" << llendl; - return; - } - - indices[curIndiceIndex++] = lowerOffset + j; // 00 - indices[curIndiceIndex++] = lowerOffset + nextVert; // 01 - indices[curIndiceIndex++] = upperOffset + j; // 10 - if (firstBranch) { part->mNumTris++; } - - indices[curIndiceIndex++] = lowerOffset + nextVert; // 01 - indices[curIndiceIndex++] = upperOffset + nextVert; // 11 - indices[curIndiceIndex++] = upperOffset + j; // 10 - if (firstBranch) { part->mNumTris++; } - - mTotalIndices += 6; - //*/ - } -} - - - - -void LLVOTreeNew::genVertexNormals(TreePart *part, LLStrider &normals, U8 numSections, U32 curNormalIndex) -{ - LLVector3 vNormal; - - U8 numVerts = part->mVertsPerSection; - U16 numFaces = numVerts * 2; - - U32 curSectionFaceOffset, lowerSectionFaceOffset; - - U8 i; - U8 j; - - // for each section... - for (i = 0; i < numSections; i++) { - - U32 numFacesStored = part->mFaceNormals.count(); - // index into face normals for 0-ith face of section i... - curSectionFaceOffset = numFacesStored - (numSections - 1 - i)*numFaces; - lowerSectionFaceOffset = curSectionFaceOffset - numFaces; - - // for each vertex... - for (j = 0; j < numVerts; j++) { - - // if lowest level or highest level... - if (i == 0) { - // bottom 3 adjacent tris - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2 - 2) % numFaces]; - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2 - 1) % numFaces]; - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2) % numFaces]; - vNormal /= 3.0; - } else if (i == numSections - 1) { - // top 3 adj tris - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2 - 1) % numFaces]; - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2) % numFaces]; - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2 + 1) % numFaces]; - vNormal /= 3.0; - } - else - { - // otherwise avg the normals from the 6 adjacent tris - // avg the 6 normal vectors that are adjacent to it... - // vertex 0 is surrounded by... - // lower: 0, 1 .... n - // upper: n-1, n .... 0 - - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2 - 2) % numFaces]; - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2 - 1) % numFaces]; - vNormal += part->mFaceNormals[curSectionFaceOffset + (numFaces - j*2) % numFaces]; - - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2 - 1) % numFaces]; - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2) % numFaces]; - vNormal += part->mFaceNormals[lowerSectionFaceOffset + (numFaces - j*2 + 1) % numFaces]; - - vNormal /= 6.0; - } - normals[curNormalIndex] = vNormal; - curNormalIndex++; - } - // get first normal and use for the repeated last vertex... - normals[curNormalIndex] = normals[curNormalIndex - numVerts]; - curNormalIndex++; - } - - - // there are mCurveRes - 1 different starting points... - U8 offset = 0; - U8 curveres8 = (U8)part->mCurveRes; - for (i = 0; i < curveres8 - 1; i++) - { - U8 numSectionsInBranch = curveres8 - i; - U8 origOffset = i * numVerts; - - for (j = 0; j <= numSectionsInBranch * numVerts; j++) - normals[curNormalIndex + offset + j] = normals[curNormalIndex + origOffset + j]; - - offset += numSectionsInBranch * numVerts; - } - - -} - - - -//{ Pre: 0 <= y <= 1 -// Ret: The radius of the stem at the (normalized) y position along the stem. -// See for the exact calculations the paper "Creation and Rendering of -// Realistic Trees", by Jason Weber and Joseph Penn. } - - -F32 LLVOTreeNew::CalculateSectionRadius(U8 level, F32 y, F32 stemLength, F32 stemRadius) -{ - F32 y2, y3; - - F32 depth; // Scaling factor used for periodic tapering - F32 taperY; // Tapered radius along at the (normalized) y - // position along the stem - F32 unitTaper; // UnitTaper is used to determine the radius of - // the stem along a specified (normalized) - // position along the stem. - - F32 radius; // radius returned - - // { Calculate UnitTaper, a variable used to determine the radius of the - // stem along a specified (normalized) position Z along the stem } - - unitTaper = 0; - - F32 curTaper = sParameters.mTaper[level]; // cur taper for this level - - // 0 <= nTaper < 1 - // unitTaper = nTaper - // 1 <= nTaper < 2 - // unitTaper = 2 - nTaper - // 2 <= nTaper < 3 - // unitTaper = 0 - - if ( (curTaper >= 0) && (curTaper < 1) ) - unitTaper = curTaper; - else if ( (curTaper >= 1) && (curTaper < 2) ) - unitTaper = 2.f - curTaper; - else // should be 2 <= curTaper < 3 - unitTaper = 0; - - - // y is ratio of stemY/length...sometimes [something.mumble] / [something.mumble] != 1 when it should... - if (y > 1.0) - y = 1.0; - - // taperY = radius[stem] * (1 - unitTaper * y) - taperY = stemRadius * (1.f - unitTaper * y); - - // 0 <= curTaper <= 1 - // radius = taperY; - - if ( (curTaper >= 0) && (curTaper < 1) ) - { - radius = taperY; - } - else - { - // { (nTaper[ALevel] >= 1) and (nTaper[ALevel] <= 3) } - - // initialize y2 - y2 = (1 - y) * stemLength; - - // initialize depth - - if ( (curTaper < 2) || (y2 < taperY) ) - depth = 1; - else - depth = curTaper - 2; - - // initialize y3 - if ( curTaper < 2) - y3 = y2; - else - y3 = fabs(y2 - 2 * taperY * floor(y2 / (2 * taperY) + 0.5f)); - - // return the radius - if ( (curTaper < 2) && (y3 >= taperY) ) - radius = taperY; - else - radius = (1 - depth) * taperY + depth * sqrt(pow(taperY, 2) - pow(y3 - taperY, 2)); - } - - // calculate flaring - if (level == 0) - { - y2 = 1 - 8 * y; - if (y2 < 0) - y2 = 0; - - // flare = Flare * (100^y - 1) / 100 + 1 - radius = radius * (sParameters.mFlare * (pow((F32)100, y2) - 1) / 100 + 1); - } - - return radius; -} - -/* -F32 LLVOTreeNew::CalculateVerticalAttraction(U8 level, LLMatrix4 §ionFrame) -{ - LLVector3 transformY, transformZ; - LLVector3 unitY(0.0, 1.0, 0.0); - LLVector3 unitZ(0.0, 0.0, 1.0); - F32 declination, orientation; - - transformY = unitY * sectionFrame; - transformZ = unitZ * sectionFrame; - - declination = acos(transformZ.mV[1]); - orientation = acos(transformY.mV[1]); - - return (sParameters.mAttractionUp * declination * cos(orientation)) / sParameters.mCurveRes[level]; -} -//*/ - - -void LLVOTreeNew::drawTree(LLDrawPool &draw_pool) -{ - U8 i, j; - - // seed the drawtree thing with the object's uuid to make it original but predictable... - // don't re-seed the process random number generator. bad. - //gLindenLabRandomNumber.seed(0); - - // reset the rand offsets - for (i = 0; i < MAX_LEVELS; i++) mRandOffset[i] = 0; - - F32 trunkLength = sParameters.mLength[0] * sParameters.mScale; - //F32 trunkLength = sParameters.mLength[0] + llfrand_signed(sParameters.mLengthV[0])) * - // (sParameters.mScale + llfrand_signed(sParameters.mScaleV)); - F32 trunkRad = trunkLength * sParameters.mRatio * sParameters.mScale0; - -//* reset usage data on which part is grabbed - mNumTrisDrawn = 0; - for (i = 0; i < MAX_PARTS; i++) - for (j = 0; j < MAX_VARS; j++) - sTreePartsUsed[mSpecies][i][j] = 0; - - // reset segsplit error stuff... - for (j = 0; j < 3; j++) - mSegSplitsError[j] = 0; - - //llinfos << "\nTREE Starting" << llendl; - drawTree(draw_pool, LLMatrix4(), 0, 0, trunkLength, 0, trunkRad, 0, 0, 0, 0); - //llinfos << "\nTREE Ending" << llendl; - - /* - // print part usage info: - for (i = 0; i < MAX_PARTS; i++) - { - llinfos << "TREE part: " << U32(i) << ": " << llendl; - for (j = 0; j < MAX_VARS; j++) - llinfos << "\t variant " << U32(j) << ": [" << U32(sTreePartsUsed[mSpecies][i][j]) << "], " << llendl; - llinfos << "" << llendl; - } - //*/ - -/* - glTranslatef(0.0, 0.0, 5.0); - for (i = 0; i < sNextPartIndex[mSpecies]; i++) - { - TreePart *selectedPart = &(sTreeParts[mSpecies][i]); - glTranslatef(2.0, 0.0, 0.0); - - // draw a variant... - for (U8 k = 0; k < selectedPart->mNumVariants; k++) - { - // start at the indice index - U32 prevOffset = 0;//selectedPart->mIndiceIndex[k]; - - - if (selectedPart->mLevel == 0 && k == 0) - { - // draw the original one with flare... - glTranslatef(1.0, 0.0, 0.0); - glPushMatrix(); - glDrawElements(GL_TRIANGLES, selectedPart->mNumTris*3, GL_UNSIGNED_INT, draw_pool.getRawIndices() + selectedPart->mIndiceIndex[k]); - glPopMatrix(); - prevOffset += selectedPart->mNumTris*3; - } - - // draw each of the curveRes iterations... - for (j = 0; j < selectedPart->mCurveRes; j++) - { - U32 numTris = (selectedPart->mCurveRes - j) * selectedPart->mVertsPerSection * 2; - glTranslatef(0.0, 1.0, 0.0); - glPushMatrix(); - glDrawElements(GL_TRIANGLES, numTris*3, GL_UNSIGNED_INT, draw_pool.getRawIndices() + selectedPart->mIndiceIndex[k] + prevOffset); - glPopMatrix(); - prevOffset += numTris*3; - } - } - } -//*/ -} - -void LLVOTreeNew::drawTree(LLDrawPool &draw_pool, const LLMatrix4 &frame, U8 level, F32 offsetChild, - F32 curLength, F32 parentLength, F32 curRadius, F32 parentRadius, - U8 part, U8 variant, U8 startSection) -{ - U8 i, j, k; - - // if startSection != 0, we're doing a segsplit. - - // find the tree part most similar (if we're not doing a segsplit) - if (startSection == 0) - { - S32 similarNum = findSimilarPart(level); - if (similarNum < 0) part = level; - else part = similarNum; - } - - TreePart *selectedPart; - selectedPart = &(sTreeParts[mSpecies][part]); - - // pick a variant if we're not in a segsplit (and therefore already have one chosen) - //if (startSection == 0) variant = llrand_unsigned(selectedPart->mNumVariants + 1, mRandOffset[level]++); - //if (variant == selectedPart->mNumVariants) variant--; - // manual override - variant = 0; - - sTreePartsUsed[mSpecies][part][variant]++; - - //llinfos << "TREE part desired: " << U32(level) << ", " << sParameters.mLobeDepth << ", " << curAngleInt << llendl; - //llinfos << "TREE part found: " << U32(selectedPart->mLevel) << ", " << selectedPart->mLobeDepth << ", " << selectedPart->mAngle << llendl; - - // determine the scalers so that we meet the desired length/radius... - F32 lengthMultiplier = curLength / selectedPart->mLength; - F32 radiusMultiplier = curRadius / selectedPart->mRadius; - LLMatrix4 scaleMatrix; - scaleMatrix.mMatrix[0][0] = radiusMultiplier; - scaleMatrix.mMatrix[1][1] = radiusMultiplier; - scaleMatrix.mMatrix[2][2] = lengthMultiplier; - - // the global rotation this branch will take - LLQuaternion frameQuat; - frameQuat.setQuat(frame); - LLMatrix4 scaledFrame = frame; - scaledFrame *= scaleMatrix; - - // start from the previous startSection of the curveRes...try to go till we're at the end of the branch - // i is the current section we're looking at for segment splits - - F32 otherRotateAngle = llfrand_signed(360.0f, mRandOffset[level]++); - - U8 curSection = startSection; - for (i = startSection; i < selectedPart->mCurveRes - 1; i++) - { - curSection = i + 1; - - S32 segSplitsEffective = 0; - - // seg split code taken from confusing paragraph of Weber + Penn - F32 segSplit = llfrand_unsigned(sParameters.mSegSplits[level], mRandOffset[level]++); - segSplitsEffective = llround(segSplit + mSegSplitsError[level]); - mSegSplitsError[level] += segSplit - lltrunc(segSplit); - mSegSplitsError[level] -= (segSplitsEffective - segSplit); - - // if we've got a seg split, figure out the right rotated frames and send them off... - if (segSplitsEffective > 0) - { - // figure out the declination for this height... - LLVector3 unitZ(0.0f, 0.0f, 1.0f); - LLVector3 transformZ = unitZ * frame; - F32 declination = RAD_TO_DEG*acos(transformZ.mV[1]); - - F32 splitAngle = (sParameters.mSplitAngle[level] + llfrand_unsigned(sParameters.mSplitAngleV[level], mRandOffset[level]++)) - declination; - if (splitAngle < 0) - splitAngle = 0; - //splitAngle = sParameters.mDownAngle[2];//45.0f; - - // do each seg split... - for (j = 0; j < segSplitsEffective; j++) - { - otherRotateAngle += llround(20.0f + 0.75f*(30.0f + fabs(declination - 90.0f)) * pow(fabs((F32)llrand_signed(1, mRandOffset[level]++)), 2.0f)); - - //otherRotateAngle += sParameters.mDownAngle[1];//((j + 1) * 360.0)/(segSplitsEffective + 1); - - U32 frameOffset = 0; - if (startSection != 0) - { - // offset into the branch that begins with that startsection... - if (level == 0) frameOffset += (U32)selectedPart->mCurveRes - 1; - // i is our start section ... - for (k = 0; k < i; k++) - frameOffset += ((U32)selectedPart->mCurveRes - k); - - frameOffset--; - } - - LLMatrix4 segFrame; - segFrame = selectedPart->mFrames[variant][frameOffset + curSection - 1]; - segFrame *= scaleMatrix; - - LLVector3 segFrameTrans = segFrame.getTranslation(); - segFrameTrans.rotVec(frameQuat); - - LLQuaternion splitQuat, rotateQuat; - splitQuat.setQuat(splitAngle*DEG_TO_RAD, 1.0f, 0.0f, 0.0f); - rotateQuat.setQuat(otherRotateAngle*DEG_TO_RAD, 0.0f, 0.0f, 1.0f); - - LLMatrix4 splitFrame; - //splitFrame.rotate(splitQuat * rotateQuat * frameQuat); ?? - splitFrame.rotate(frameQuat * splitQuat * rotateQuat); - splitFrame.translate(segFrameTrans); - splitFrame.translate(frame.getTranslation()); - - // recurse from the current endsection as start section and with the new frame as base - drawTree(draw_pool, splitFrame, level, offsetChild, - curLength, parentLength, curRadius, parentRadius, - part, variant, curSection); - } - } - } - - - U32 startIndexOffset = 0; - - if (startSection != 0) - startIndexOffset = selectedPart->mOffsets[variant][startSection]; - - U32 numTris; - if (level == 0 && startSection == 0) - numTris = selectedPart->mNumTris; - else - numTris = 2 * selectedPart->mVertsPerSection * ((U8)selectedPart->mCurveRes - startSection); - - glPushMatrix(); - glMultMatrixf((float *)frame.mMatrix); - glScalef(radiusMultiplier, radiusMultiplier, lengthMultiplier); - - //glDrawElements(GL_TRIANGLES, selectedPart->mNumTris*3, GL_UNSIGNED_INT, draw_pool.getRawIndices() + selectedPart->mIndiceIndex + 0); - glDrawElements(GL_TRIANGLES, numTris*3, GL_UNSIGNED_INT, draw_pool.getRawIndices() + selectedPart->mIndiceIndex[variant] + startIndexOffset); - glPopMatrix(); - - mNumTrisDrawn += numTris; - - // figure out how many in next level of branches || leaves - U8 total = 0; - F32 baseLength = 0; - - if (level < sParameters.mLevels) - { - if (level == 0) - { - baseLength = sParameters.mBaseSize * (sParameters.mScale + llfrand_signed(sParameters.mScaleV, mRandOffset[level]++)); - total = llround( (1.f - sParameters.mBaseSize) * sParameters.mBranches[level]); - } - else if (level == 1) - { - F32 maxLength = sParameters.mLength[level] + llfrand_signed(sParameters.mLengthV[level], mRandOffset[level]++); - total = llround(sParameters.mBranches[level] * (0.2f + 0.8f * ( (curLength/parentLength)/maxLength ) ) ); - } - else - { - total = (llround(sParameters.mBranches[level] * (1.0f - 0.5f * (offsetChild/parentLength) ))); - } - } - else if (sParameters.mLevels == level) - { - // determine leaves - // see paper for more on: - // leaves_per_branch = Leaves * - // ShapeRatio ( 4 (tapered), offset[child]/length[parent] * quality) - - //total = (sParameters.mLeaves * sParameters.ShapeRatio(SR_CONICAL, offsetChild / curLength) * sParameters.mLeafQuality); - total = sParameters.mLeaves; - - } - - F32 fracPos, offsetPos, localPos; - F32 downAngle, rotateAngle; - U8 currentFrameSegment; // index of matrix transform of the closest cross section to new branch - LLMatrix4 localFrame, curPartFrame, nextPartFrame; - - // init stem rotate angle... - rotateAngle = llfrand_unsigned(360.0, mRandOffset[level]++); - - // grow the leaf or branch... - for (i = 0; i < total; i++) - { - // note: curLength is the 'parentLength' for all of these substems - localFrame.identity(); - - // find the fractional, offset and then local pos - if (level == 0) - fracPos = sParameters.mBaseSize + (i) * (1.0f - sParameters.mBaseSize) / (total); - else - fracPos = (i) * (1.0f / (total)); - - // offset into branch - offsetPos = fracPos*curLength; - - U32 frameOffset = 0; - if (startSection != 0) - { - if (level == 0) frameOffset = (U32)selectedPart->mCurveRes; - - for (k = 0; k < startSection; k++) - frameOffset += ((U32)selectedPart->mCurveRes - k); - } - - F32 curSegAt; - if (level == 0 && startSection == 0) - { - F32 effectiveFlarePercentage = sParameters.mFlarePercentage + (1.0f - sParameters.mFlarePercentage)/selectedPart->mCurveRes; - - if (fracPos < effectiveFlarePercentage) - { - if (fracPos > sParameters.mFlarePercentage) - currentFrameSegment = sParameters.mFlareRes - 1; - else - currentFrameSegment = lltrunc( (fracPos/sParameters.mFlarePercentage) / (1.0/sParameters.mFlareRes) ); - - if (currentFrameSegment == 0) - { - curPartFrame.identity(); - nextPartFrame = mTrunkFlareFrames[0]; - } - else - { - curPartFrame = mTrunkFlareFrames[currentFrameSegment - 1]; - if (currentFrameSegment == sParameters.mFlareRes - 1) nextPartFrame = selectedPart->mFrames[variant][0]; - else nextPartFrame = mTrunkFlareFrames[currentFrameSegment]; - } - - curSegAt = currentFrameSegment * (curLength * sParameters.mFlarePercentage)/sParameters.mFlareRes; - localPos = offsetPos - curSegAt; - } - else - { - // want to go from frameSegment 0 to (1-CurveRes)...don't want to have frame at tip - currentFrameSegment = lltrunc( ( (fracPos - effectiveFlarePercentage)/(1.0 - effectiveFlarePercentage) ) / (1.0 / (selectedPart->mCurveRes - 1)) ); - curSegAt = (sParameters.mFlarePercentage * curLength) + (currentFrameSegment + 1.0f) * ( (curLength*(1.0f - sParameters.mFlarePercentage)/(selectedPart->mCurveRes)) ); - localPos = offsetPos - curSegAt; - curPartFrame = selectedPart->mFrames[variant][currentFrameSegment]; - nextPartFrame = selectedPart->mFrames[variant][currentFrameSegment + 1]; - } - //llinfos << "TREE startsection: " << U32(startSection) << " currentSeg: " << U32(currentFrameSegment) << ", is at: " << curSegAt << ", fracpos: " << fracPos << ", offset: " << offsetPos << ", localpos: " << localPos << ", final: " << curSegAt + localPos << llendl; - } - else if (level == 0 && startSection != 0) - { - // if level is zero, don't deal with flared branch positions - if (fracPos < sParameters.mFlarePercentage) continue; - - // take FlarePercentage out of fracPos - fracPos = (fracPos - sParameters.mFlarePercentage)/(1 - sParameters.mFlarePercentage); - - currentFrameSegment = lltrunc(fracPos / (1.0 / selectedPart->mCurveRes)); - - // don't do branches below our split starting point - if (currentFrameSegment < startSection) continue; - - curSegAt = (sParameters.mFlarePercentage * curLength) + currentFrameSegment*((curLength - sParameters.mFlarePercentage*curLength)/(selectedPart->mCurveRes)); - localPos = offsetPos - curSegAt; - currentFrameSegment -= startSection; - - if (currentFrameSegment == 0) - { - curPartFrame.identity(); - nextPartFrame = selectedPart->mFrames[variant][frameOffset]; - } - else - { - curPartFrame = selectedPart->mFrames[variant][frameOffset + currentFrameSegment - 1]; - nextPartFrame = selectedPart->mFrames[variant][frameOffset + currentFrameSegment]; - } - } - else - { - currentFrameSegment = lltrunc(fracPos / (1.0 / selectedPart->mCurveRes)); - - // don't do branches below our split starting point - if (currentFrameSegment < startSection) continue; - - curSegAt = (currentFrameSegment) * (curLength/(selectedPart->mCurveRes)); - localPos = offsetPos - curSegAt; - currentFrameSegment -= startSection; - - if (currentFrameSegment == 0) - { - curPartFrame.identity(); - nextPartFrame = selectedPart->mFrames[variant][frameOffset]; - } - else - { - curPartFrame = selectedPart->mFrames[variant][frameOffset + currentFrameSegment - 1]; - nextPartFrame = selectedPart->mFrames[variant][frameOffset + currentFrameSegment]; - } - } - - if (sParameters.mDownAngle[level] >= 0) - downAngle = sParameters.mDownAngle[level] + llfrand_signed(sParameters.mDownAngleV[level], mRandOffset[level]++); - else - downAngle = sParameters.mDownAngle[level] + sParameters.mDownAngleV[level] * - (1 - 2.0f * sParameters.ShapeRatio(SR_CONICAL, (curLength - offsetPos) / (curLength - baseLength))); - - if (sParameters.mRotate[level] >= 0) - rotateAngle += (sParameters.mRotate[level] + llfrand_signed(sParameters.mRotateV[level], mRandOffset[level]++)); - else - rotateAngle += (180.0f + sParameters.mRotate[level] + llfrand_signed(sParameters.mRotateV[level], mRandOffset[level]++)); - - if (sParameters.mLevels == level) - { - downAngle = 0.0; - rotateAngle = 0.0; - } - -// manual overrides -// rotateAngle = sParameters.mRotate[0]; -// downAngle = sParameters.mDownAngle[0]; - - LLQuaternion downQuat, rotateQuat, nextQuat, curQuat; - downQuat.setQuat(DEG_TO_RAD*downAngle, 1.0, 0.0, 0.0); - rotateQuat.setQuat(DEG_TO_RAD*rotateAngle, 0.0, 0.0, 1.0); - nextQuat.setQuat(nextPartFrame); - curQuat.setQuat(curPartFrame); - - localFrame.identity(); - - // take the home frame, and rotate by the global frame, translate to the global start - curPartFrame.rotate(frameQuat); - - // rotate to the final angle and translate to the bottom of the branch - - localFrame.rotate(frameQuat * nextQuat * downQuat * rotateQuat); - // scale our parent frame to put stuff in the right location - curPartFrame *= scaleMatrix; - localFrame.translate(curPartFrame.getTranslation()); - //localFrame.translate(scaledFrame.getTranslation()); - localFrame.translate(frame.getTranslation()); - - // offset the branch by a bit and then rotate using current position, add the resulting translation - LLVector3 translateUp(0.0, 0.0, localPos); - translateUp.rotVec(nextQuat * frameQuat); - //translateUp.rotVec(nextQuat); - localFrame.translate(translateUp); - - - // BRANCHES... - if (level < sParameters.mLevels) - { - F32 subStemLength, maxChildLength; - F32 localRadius, subStemRadius; - - // determine a maximum length for this stem's children... - maxChildLength = sParameters.mLength[level+1] + llfrand_signed(sParameters.mLengthV[level+1], mRandOffset[level]++); - - // length of child branch - if (level == 0) - subStemLength = curLength * maxChildLength * - sParameters.ShapeRatio(sParameters.mShape, (curLength - offsetPos) / (curLength - baseLength)); - else - subStemLength = maxChildLength * (curLength - 0.6f * offsetPos); - - // radius of child branch - if (curLength == 0) - subStemRadius = 0; - else - subStemRadius = selectedPart->mRadius * pow((subStemLength / curLength), sParameters.mRatioPower); - - // don't have a radius that is larger than parent's - localRadius = CalculateSectionRadius(level, fracPos, selectedPart->mLength, selectedPart->mRadius); - localRadius *= radiusMultiplier; - - if ( (subStemRadius > localRadius) || (subStemRadius == 0) ) - subStemRadius = localRadius; - - if (subStemLength != 0) - drawTree(draw_pool, localFrame, level + 1, offsetPos, subStemLength, curLength, subStemRadius, curRadius, 0, 0, 0); - - } - // LEAVES - else if (sParameters.mLevels == level) - { - // for now just draw leaves stupidly... - - // draw square leaf (two tris) with the texture on it (then do it again for the other side) - mNumTrisDrawn += 4; -//* - F32 leafXscale = 1.0f; - F32 leafYscale = 1.0f; - - glPushMatrix(); - //LLVector3 position = localFrame.getTranslation(); - - //glTranslatef(position.mV[0], position.mV[1], position.mV[2]); - glMultMatrixf((float *)localFrame.mMatrix); - - glBegin(GL_QUADS); - - //* - // 00 - glTexCoord2f(0.5f, 0.5f); - glVertex3f(0.0f, 0.0f, 0.0f); - // 10 - glTexCoord2f(1.0f, 0.5f); - glVertex3f(0.0f, 0.0f, leafXscale); - // 11 - glTexCoord2f(1.0f, 1.0f); - glVertex3f(0.0f, leafYscale, leafXscale); - // 01 - glTexCoord2f(0.5f, 1.0f); - glVertex3f(0.0f, leafYscale, 0.0f); - //*/ - - // 10 - glTexCoord2f(1.0f, 0.5f); - glVertex3f(0.0f, 0.0f, leafXscale); - // 00 - glTexCoord2f(0.5f, 0.5f); - glVertex3f(0.0f, 0.0f, 0.0f); - // 01 - glTexCoord2f(0.5f, 1.0f); - glVertex3f(0.0f, leafYscale, 0.0f); - // 11 - glTexCoord2f(1.0f, 1.0f); - glVertex3f(0.0f, leafYscale, leafXscale); - - glEnd(); - glPopMatrix(); -//*/ - } - } - -} - - - - diff --git a/linden/indra/newview/llvovolume.cpp b/linden/indra/newview/llvovolume.cpp index 6791acd..f425687 100644 --- a/linden/indra/newview/llvovolume.cpp +++ b/linden/indra/newview/llvovolume.cpp @@ -42,7 +42,6 @@ #include "material_codes.h" #include "message.h" #include "object_flags.h" - #include "llagent.h" #include "lldrawable.h" #include "lldrawpoolsimple.h" @@ -64,14 +63,14 @@ #include "pipeline.h" const S32 MIN_QUIET_FRAMES_COALESCE = 30; - -//#define LLDEBUG_DISPLAY_LODS 1 +const F32 FORCE_SIMPLE_RENDER_AREA = 512.f; +const F32 FORCE_CULL_AREA = 8.f; BOOL gAnimateTextures = TRUE; +extern BOOL gHideSelectedObjects; F32 LLVOVolume::sLODFactor = 1.f; F32 LLVOVolume::sLODSlopDistanceFactor = 0.5f; //Changing this to zero, effectively disables the LOD transition slop -F32 LLVOVolume::sLODComplexityDistanceBias = 0.0f;//Changing this to zero makes all prims LOD equally regardless of complexity F32 LLVOVolume::sDistanceFactor = 1.0f; S32 LLVOVolume::sNumLODChanges = 0; @@ -79,17 +78,14 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re : LLViewerObject(id, pcode, regionp), mVolumeImpl(NULL) { + mTexAnimMode = 0; mRelativeXform.identity(); mRelativeXformInvTrans.identity(); mLOD = MIN_LOD; mInited = FALSE; - mAllTEsSame = FALSE; mTextureAnimp = NULL; mGlobalVolume = FALSE; - - mTextureAnimp = NULL; - mAllTEsSame = FALSE; mVObjRadius = LLVector3(1,1,0.5f).magVec(); mNumFaces = 0; } @@ -142,12 +138,19 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, mTextureAnimp->reset(); } } + mTexAnimMode = 0; mTextureAnimp->unpackTAMessage(mesgsys, block_num); } else { - delete mTextureAnimp; - mTextureAnimp = NULL; + if (mTextureAnimp) + { + delete mTextureAnimp; + mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; + } } // Unpack volume data @@ -193,8 +196,8 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, // Well, crap, there's something bogus in the data that we're unpacking. dp->dumpBufferToLog(); llwarns << "Flushing cache files" << llendl; - char mask[LL_MAX_PATH]; - sprintf(mask, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); + char mask[LL_MAX_PATH]; /* Flawfinder: ignore */ + snprintf(mask, LL_MAX_PATH, "%s*.slc", gDirUtilp->getDirDelimiter().c_str()); /* Flawfinder: ignore */ gDirUtilp->deleteFilesInDir(gDirUtilp->getExpandedFilename(LL_PATH_CACHE,"").c_str(),mask); // llerrs << "Bogus TE data in " << getID() << ", crashing!" << llendl; llwarns << "Bogus TE data in " << getID() << llendl; @@ -219,12 +222,16 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, mTextureAnimp->reset(); } } + mTexAnimMode = 0; mTextureAnimp->unpackTAMessage(*dp); } - else + else if (mTextureAnimp) { delete mTextureAnimp; mTextureAnimp = NULL; + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; } } else @@ -247,65 +254,142 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, } -BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +void LLVOVolume::animateTextures() { - LLViewerObject::idleUpdate(agent, world, time); - - /////////////////////// - // - // Do texture animation stuff - // - - if (mTextureAnimp && gAnimateTextures) + F32 off_s = 0.f, off_t = 0.f, scale_s = 1.f, scale_t = 1.f, rot = 0.f; + S32 result; + + if (result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot)) { - F32 off_s, off_t, scale_s, scale_t, rot; - S32 result; - if ((result = mTextureAnimp->animateTextures(off_s, off_t, scale_s, scale_t, rot))) + if (!mTexAnimMode) + { + mFaceMappingChanged = TRUE; + gPipeline.markTextured(mDrawable); + } + mTexAnimMode = result | mTextureAnimp->mMode; + + S32 start=0, end=mDrawable->getNumFaces()-1; + if (mTextureAnimp->mFace >= 0 && mTextureAnimp->mFace <= end) + { + start = end = mTextureAnimp->mFace; + } + + for (S32 i = start; i <= end; i++) { - U8 has_bump = 0; - if (mTextureAnimp->mFace <= -1) + LLQuaternion quat; + LLVector3 scale(1,1,1); + + LLFace* facep = mDrawable->getFace(i); + const LLTextureEntry* te = facep->getTextureEntry(); + LLMatrix4& tex_mat = facep->mTextureMatrix; + + if (!te) + { + continue; + } + if (!(result & LLViewerTextureAnim::ROTATE)) + { + te->getRotation(&rot); + } + { - S32 face; - for (face = 0; face < getNumTEs(); face++) + F32 axis = -1; + F32 s,t; + te->getScale(&s,&t); + if (s < 0) { - if (result & LLViewerTextureAnim::TRANSLATE) - { - setTEOffset(face, off_s, off_t); - } - if (result & LLViewerTextureAnim::SCALE) - { - setTEScale(face, scale_s, scale_t); - } - if (result & LLViewerTextureAnim::ROTATE) - { - setTERotation(face, rot); - } - has_bump |= getTE(face)->getBumpmap(); + axis = -axis; + } + if (t < 0) + { + axis = -axis; } + quat.setQuat(rot, 0, 0, axis); + } + + if (!(result & LLViewerTextureAnim::TRANSLATE)) + { + te->getOffset(&off_s,&off_t); + } + + LLVector3 trans(off_s+0.5f, off_t+0.5f, 0.f); + + tex_mat.identity(); + tex_mat.translate(LLVector3(-0.5f, -0.5f, 0.f)); + tex_mat.rotate(quat); + + if (!(result & LLViewerTextureAnim::SCALE)) + { + te->getScale(&scale_s, &scale_t); } - else if (mTextureAnimp->mFace < getNumTEs()) + + { + scale.setVec(scale_s, scale_t, 1.f); + LLMatrix4 mat; + mat.initAll(scale, LLQuaternion(), LLVector3()); + tex_mat *= mat; + } + + tex_mat.translate(trans); + } + } + else + { + if (mTexAnimMode && mTextureAnimp->mRate == 0) + { + U8 start, count; + + if (mTextureAnimp->mFace == -1) + { + start = 0; + count = getNumTEs(); + } + else + { + start = (U8) mTextureAnimp->mFace; + count = 1; + } + + for (S32 i = start; i < start + count; i++) { - if (result & LLViewerTextureAnim::TRANSLATE) + if (mTexAnimMode & LLViewerTextureAnim::TRANSLATE) { - setTEOffset(mTextureAnimp->mFace, off_s, off_t); + setTEOffset(i, mTextureAnimp->mOffS, mTextureAnimp->mOffT); } - if (result & LLViewerTextureAnim::SCALE) + if (mTexAnimMode & LLViewerTextureAnim::SCALE) { - setTEScale(mTextureAnimp->mFace, scale_s, scale_t); + setTEScale(i, mTextureAnimp->mScaleS, mTextureAnimp->mScaleT); } - if (result & LLViewerTextureAnim::ROTATE) + if (mTexAnimMode & LLViewerTextureAnim::ROTATE) { - setTERotation(mTextureAnimp->mFace, rot); + setTERotation(i, mTextureAnimp->mRot); } - has_bump |= getTE(mTextureAnimp->mFace)->getBumpmap(); - } -// mFaceMappingChanged = TRUE; - if (mDrawable->isVisible()) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE); } + + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; + mTexAnimMode = 0; } } +} +BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) +{ + LLViewerObject::idleUpdate(agent, world, time); + + if (mDead || mDrawable.isNull()) + { + return TRUE; + } + + /////////////////////// + // + // Do texture animation stuff + // + + if (mTextureAnimp && gAnimateTextures) + { + animateTextures(); + } // Dispatch to implementation if (mVolumeImpl) @@ -318,75 +402,45 @@ BOOL LLVOVolume::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) void LLVOVolume::updateTextures(LLAgent &agent) { - +// LLFastTimer t(LLFastTimer::FTM_TEMP6); + const F32 TEXTURE_AREA_REFRESH_TIME = 5.f; // seconds + if (mTextureUpdateTimer.getElapsedTimeF32() > TEXTURE_AREA_REFRESH_TIME) + { + if (mDrawable->isVisible()) + { + updateTextures(); + } + } } -//static -F32 LLVOVolume::getTextureVirtualSize(const LLFace* face) +void LLVOVolume::updateTextures() { - //LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; - //F32 pixel_area = 1.f/llmin(llmax(tdim.mV[0] * tdim.mV[1], 1.f), 10.f); - LLVector3 cross_vec = (face->mExtents[1] - face->mExtents[0]); - + // Update the pixel area of all faces - LLVector3 lookAt = (face->getPositionAgent()-gCamera->getOrigin()); - F32 dist = lookAt.normVec(); - - F32 face_area; - - if (face->isState(LLFace::GLOBAL)) - { - face_area = cross_vec.mV[0]*cross_vec.mV[1]*fabsf(lookAt.mV[2]) + - cross_vec.mV[1]*cross_vec.mV[2]*fabsf(lookAt.mV[0]) + - cross_vec.mV[0]*cross_vec.mV[2]*fabsf(lookAt.mV[1]); - } - else + if (!gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_SIMPLE)) { - face_area = cross_vec.mV[0]*cross_vec.mV[1] + - cross_vec.mV[1]*cross_vec.mV[2] + - cross_vec.mV[0]*cross_vec.mV[2]; + return; } - - if (face_area <= 0) + + if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull()) // || !mDrawable->isVisible()) { - return 0.f; + return; } - F32 view = llmax(lookAt*gCamera->getAtAxis(), 0.5f); - F32 dist_ramp = dist * view/face_area; - //ramp down distance for things closer than 16 m * lookAt - dist /= dist_ramp; - dist *= dist; - dist *= dist_ramp; - - F32 dist_ratio = face_area / llmax(dist, 0.1f); - F32 pixel_area = dist_ratio*gCamera->getScreenPixelArea(); + mTextureUpdateTimer.reset(); - return view*pixel_area; -} - -void LLVOVolume::updateTextures(S32 lod) -{ - // Update the image levels of all textures... - // First we do some quick checks. - - // This doesn't take into account whether the object is in front - // or behind... + F32 old_area = mPixelArea; + mPixelArea = 0.f; - if (LLViewerImage::sDontLoadVolumeTextures || mDrawable.isNull() || !mDrawable->isVisible()) - { - return; - } - const S32 num_faces = mDrawable->getNumFaces(); - + F32 min_vsize=999999999.f, max_vsize=0.f; for (S32 i = 0; i < num_faces; i++) { - const LLFace* face = mDrawable->getFace(i); + LLFace* face = mDrawable->getFace(i); const LLTextureEntry *te = face->getTextureEntry(); LLViewerImage *imagep = face->getTexture(); - - if (!imagep || !te) + if (!imagep || !te || + face->mExtents[0] == face->mExtents[1]) { continue; } @@ -395,25 +449,87 @@ void LLVOVolume::updateTextures(S32 lod) if (isHUDAttachment()) { - vsize = (F32) (imagep->getWidth(0) * imagep->getHeight(0)); + F32 area = (F32) gCamera->getScreenPixelArea(); + vsize = area; imagep->setBoostLevel(LLViewerImage::BOOST_HUD); + face->setPixelArea(area); // treat as full screen } else { vsize = getTextureVirtualSize(face); } + mPixelArea = llmax(mPixelArea, face->getPixelArea()); + face->setVirtualSize(vsize); imagep->addTextureStats(vsize); - - - U8 bump = te->getBumpmap(); - if( te && bump) + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) { - gBumpImageList.addTextureStats( bump, imagep->getID(), vsize, 1, 1); + if (vsize < min_vsize) min_vsize = vsize; + if (vsize > max_vsize) max_vsize = vsize; } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + F32 pri = imagep->getDecodePriority(); + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + F32 pri = mPixelArea; + if (pri < min_vsize) min_vsize = pri; + if (pri > max_vsize) max_vsize = pri; + } + } + + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_PRIORITY)) + { + setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + } + else if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_FACE_AREA)) + { + setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize))); + } + + if (mPixelArea == 0) + { //flexi phasing issues make this happen + mPixelArea = old_area; } } +F32 LLVOVolume::getTextureVirtualSize(LLFace* face) +{ + //get area of circle around face + LLVector3 center = face->getPositionAgent(); + LLVector3 size = (face->mExtents[1] - face->mExtents[0]) * 0.5f; + + F32 face_area = LLPipeline::calcPixelArea(center, size, *gCamera); + + face->setPixelArea(face_area); + + if (face_area <= 0) + { + return 0.f; + } + + //get area of circle in texture space + LLVector2 tdim = face->mTexExtents[1] - face->mTexExtents[0]; + F32 texel_area = (tdim * 0.5f).magVecSquared()*3.14159f; + if (texel_area <= 0) + { + // Probably animated, use default + texel_area = 1.f; + } + + //apply texel area to face area to get accurate ratio + face_area /= llclamp(texel_area, 1.f/64.f, 16.f); + + return face_area; +} + BOOL LLVOVolume::isActive() const { return !mStatic || mTextureAnimp || isAttachment() || (mVolumeImpl && mVolumeImpl->isActive()); @@ -455,7 +571,7 @@ void LLVOVolume::setScale(const LLVector3 &scale, BOOL damped) //since drawable transforms do not include scale, changing volume scale //requires an immediate rebuild of volume verts. - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_POSITION, TRUE); } } @@ -463,16 +579,7 @@ LLFace* LLVOVolume::addFace(S32 f) { const LLTextureEntry* te = getTE(f); LLViewerImage* imagep = getTEImage(f); - LLDrawPool* poolp; - if (isHUDAttachment()) - { - poolp = gPipeline.getPool(LLDrawPool::POOL_HUD); - } - else - { - poolp = LLPipeline::getPoolFromTE(te, imagep); - } - return mDrawable->addFace(poolp, imagep); + return mDrawable->addFace(te, imagep); } LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) @@ -480,7 +587,7 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setRenderType(LLPipeline::RENDER_TYPE_VOLUME); - S32 max_tes_to_set = calcAllTEsSame() ? 1 : getNumTEs(); + S32 max_tes_to_set = getNumTEs(); for (S32 i = 0; i < max_tes_to_set; i++) { LLFace* face = addFace(i); @@ -537,10 +644,6 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail } mGlobalVolume = (mVolumeImpl && mVolumeImpl->isVolumeGlobal()); - //MSMSM Recompute LOD here in case the object was just created, - // its LOD might be incorrectly set to minumum detail... - calcLOD(); - if (LLPrimitive::setVolume(volume_params, mLOD, (mVolumeImpl && mVolumeImpl->isVolumeUnique()))) { mFaceMappingChanged = TRUE; @@ -555,45 +658,12 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail return FALSE; } - -F32 LLVOVolume::computeLODProfilePathComplexityBias(){ - //compute a complexity cost from 0 to 1.0 where the 'simplest' prim has a cost of 0.0 - // and the 'heaviest' prim has a cost of 1.0 -// LLVolume* volume = getVolume(); - F32 complexity = 0.0f; -// const LLVolumeParams& params = volume->getParams(); -// U8 type = volume->getPathType(); -// U8 pcode = this->getPCode(); -// U8 proftype = volume->getProfileType(); - - //if(params.getHollow()>0.0f){// || (proftype == 1) || (proftype == 0)){ - //If it is hollow, or a cube/pyramid(subdivided), the complexity is roughly doubled - // complexity+=0.5f; - //} - - if(this->getVolume()->getProfile().mParams.getCurveType()==LL_PCODE_PROFILE_SQUARE && - this->getVolume()->getPath().mParams.getCurveType()==LL_PCODE_PATH_LINE) - { - //Object is a cube so bias it heavily since cubes are subdivided alot. -// this->setDebugText("CUBE"); - complexity += 1.0f; - } - -// if(params.getTwist() != params.getTwistBegin()){ - //if there is twist.. the complexity is bumped -// complexity+=0.25f; -// } -// if(type != LL_PCODE_PATH_LINE)//If the path is not a line it is more complex -// complexity+=0.2f; - return complexity * sLODComplexityDistanceBias; -} - S32 LLVOVolume::computeLODDetail(F32 distance, F32 radius) { S32 cur_detail; // We've got LOD in the profile, and in the twist. Use radius. F32 tan_angle = (LLVOVolume::sLODFactor*radius)/distance; - cur_detail = LLVolumeLODGroup::getDetailFromTan(tan_angle); + cur_detail = LLVolumeLODGroup::getDetailFromTan(llround(tan_angle, 0.01f)); return cur_detail; } @@ -603,62 +673,32 @@ BOOL LLVOVolume::calcLOD() { return FALSE; } + S32 cur_detail = 0; - /*if (isHUDAttachment()) + + F32 radius = mVolumep->mLODScaleBias.scaledVec(getScale()).magVec(); + F32 distance = mDrawable->mDistanceWRTCamera; + distance *= sDistanceFactor; + + F32 rampDist = LLVOVolume::sLODFactor * 2; + + if (distance < rampDist) { - cur_detail = LLVolumeLODGroup::NUM_LODS-1; // max detail + // Boost LOD when you're REALLY close + distance *= 1.0f/rampDist; + distance *= distance; + distance *= rampDist; } - else*/ - { - F32 radius = (mVolumep->mLODScaleBias.scaledVec(getScale())).magVec(); - F32 distance = mDrawable->mDistanceWRTCamera; - distance *= sDistanceFactor; - - F32 rampDist = LLVOVolume::sLODFactor * 2; - - if (distance < rampDist) - { - // Boost LOD when you're REALLY close - distance *= 1.0f/rampDist; - distance *= distance; - distance *= rampDist; - } - else - { - //Now adjust the computed distance by some factor based on the geometric complexity of the primitive - distance += computeLODProfilePathComplexityBias(); - } - // Compensate for field of view changing on FOV zoom. - distance *= gCamera->getView(); - - cur_detail = computeLODDetail(distance, radius); - - //update textures with what the real LOD is - updateTextures(cur_detail); + + // DON'T Compensate for field of view changing on FOV zoom. + distance *= 3.14159f/3.f; - if(cur_detail != mLOD) - { - // Here we test whether the LOD is increasing or decreasing to introduce a slop factor - if(cur_detail < mLOD) - { - // Viewer is moving away from the object - // so bias our LOD by adding a fixed amount to the distance. - // This will reduce the problem of LOD twitching when the - // user makes slight movements near the LOD transition threshhold. - F32 test_distance = distance - (distance*sLODSlopDistanceFactor/(1.0f+sLODFactor)); - if(test_distance < 0.0f) test_distance = 0.0f; - S32 potential_detail = computeLODDetail( test_distance, radius ); - if(potential_detail >= mLOD ) - { //The LOD has truly not changed - cur_detail = mLOD; - } - } - } - } + cur_detail = computeLODDetail(llround(distance, 0.01f), + llround(radius, 0.01f)); if (cur_detail != mLOD) { - mAppAngle = (F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG; + mAppAngle = llround((F32) atan2( mDrawable->getRadius(), mDrawable->mDistanceWRTCamera) * RAD_TO_DEG, 0.01f); mLOD = cur_detail; return TRUE; } @@ -676,17 +716,10 @@ BOOL LLVOVolume::updateLOD() } BOOL lod_changed = calcLOD(); - -#if LLDEBUG_DISPLAY_LODS - //MS Enable this to display LOD numbers on objects - std::ostringstream msg; - msg << cur_detail;//((cur_detailmDistanceWRTCamera << " , " << ((LLVOVolume::sLODFactor*mVObjRadius)/mDrawable->mDistanceWRTCamera); - this->setDebugText(msg.str()); -#endif - + if (lod_changed) { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, FALSE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE); mLODChanged = TRUE; } @@ -703,8 +736,8 @@ BOOL LLVOVolume::setDrawableParent(LLDrawable* parentp) if (!mDrawable->isRoot()) { - // parent is dynamic, so I'll need to share its drawable, must rebuild to share drawables - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + // rebuild vertices in parent relative space + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); if (mDrawable->isActive() && !parentp->isActive()) { @@ -723,7 +756,7 @@ void LLVOVolume::updateFaceFlags() { for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { - LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); + LLFace *face = mDrawable->getFace(i); BOOL fullbright = getTE(i)->getFullbright(); face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT); @@ -739,10 +772,17 @@ void LLVOVolume::updateFaceFlags() { face->setState(LLFace::HUD_RENDER); } - if (getAllTEsSame()) - { - break; // only 1 face - } + } +} + +void LLVOVolume::setParent(LLViewerObject* parent) +{ + LLViewerObject::setParent(parent); + if (mDrawable) + { + gPipeline.markMoved(mDrawable); + mVolumeChanged = TRUE; + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); } } @@ -750,104 +790,87 @@ void LLVOVolume::updateFaceFlags() void LLVOVolume::regenFaces() { // remove existing faces - // use mDrawable->getVOVolume() in case of shared drawables - mDrawable->getVOVolume()->deleteFaces(this); - mFaceIndexOffset = mDrawable->getNumFaces(); - // add new faces - mNumFaces = getAllTEsSame() ? 1 : getNumTEs(); + BOOL count_changed = mNumFaces != getNumTEs(); + + if (count_changed) + { + deleteFaces(); + // add new faces + mNumFaces = getNumTEs(); + } + for (S32 i = 0; i < mNumFaces; i++) { - LLFace* facep = addFace(i); - facep->setViewerObject(this); + LLFace* facep = count_changed ? addFace(i) : mDrawable->getFace(i); facep->setTEOffset(i); + facep->setTexture(getTEImage(i)); + facep->setViewerObject(this); + } + + if (!count_changed) + { + updateFaceFlags(); } - // Need to do this as texture entries may not correspond to faces any more! - mDrawable->updateTexture(); - gPipeline.markMaterialed(mDrawable); } -BOOL LLVOVolume::genTriangles(BOOL force_global) +BOOL LLVOVolume::genBBoxes(BOOL force_global) { BOOL res = TRUE; LLVector3 min,max; - if (getAllTEsSame()) + BOOL rebuild = mDrawable->isState(LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION); + + for (S32 i = 0; i < getVolume()->getNumFaces(); i++) { - setupSingleFace(mFaceIndexOffset); - LLFace *face = mDrawable->getFace(mFaceIndexOffset); - S32 num_faces = getVolume()->getNumFaces(); - res = face->genVolumeTriangles(*getVolume(), 0, num_faces-1, - mRelativeXform, mRelativeXformInvTrans, - mGlobalVolume | force_global); + LLFace *face = mDrawable->getFace(i); + res &= face->genVolumeBBoxes(*getVolume(), i, + mRelativeXform, mRelativeXformInvTrans, + mGlobalVolume | force_global); - if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) - { - min = face->mExtents[0]; - max = face->mExtents[1]; - } - mWereAllTEsSame = TRUE; - } - else - { - for (S32 i = 0; i < getVolume()->getNumFaces(); i++) + if (rebuild) { - LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); - res &= face->genVolumeTriangles(*getVolume(), i, - mRelativeXform, mRelativeXformInvTrans, - mGlobalVolume | force_global); - - if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) + if (i == 0) { - if (i == 0) - { - min = face->mExtents[0]; - max = face->mExtents[1]; - } - else + min = face->mExtents[0]; + max = face->mExtents[1]; + } + else + { + for (U32 i = 0; i < 3; i++) { - for (U32 i = 0; i < 3; i++) + if (face->mExtents[0].mV[i] < min.mV[i]) { - if (face->mExtents[0].mV[i] < min.mV[i]) - { - min.mV[i] = face->mExtents[0].mV[i]; - } - if (face->mExtents[1].mV[i] > max.mV[i]) - { - max.mV[i] = face->mExtents[1].mV[i]; - } + min.mV[i] = face->mExtents[0].mV[i]; + } + if (face->mExtents[1].mV[i] > max.mV[i]) + { + max.mV[i] = face->mExtents[1].mV[i]; } } } } - mWereAllTEsSame = FALSE; } - - if (mDrawable->isState(LLDrawable::REBUILD_VOLUME)) + + if (rebuild) { mDrawable->setSpatialExtents(min,max); - if (!isVolumeGlobal()) - { - mDrawable->setPositionGroup((min+max)*0.5f); - } - else - { - mDrawable->setPositionGroup(getPosition()); - } - - updateRadius(); - mDrawable->updateBinRadius(); - mDrawable->movePartition(); + mDrawable->setPositionGroup((min+max)*0.5f); + //bounding boxes changed, update texture priorities + updateTextures(); } - + + updateRadius(); + mDrawable->movePartition(); + return res; } -void LLVOVolume::updateRelativeXform(BOOL global_volume) +void LLVOVolume::updateRelativeXform() { if (mVolumeImpl) { - mVolumeImpl->updateRelativeXform(global_volume); + mVolumeImpl->updateRelativeXform(); return; } @@ -873,12 +896,25 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume) LLVector4(y_axis, 0.f), LLVector4(z_axis, 0.f), LLVector4(delta_pos, 1.f)); - - x_axis.normVec(); - y_axis.normVec(); - z_axis.normVec(); + - mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // compute inverse transpose for normals + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // mRelativeXformInvTrans.invert(); + // mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // grumble - invert is NOT a matrix invert, so we do it by hand: + + LLMatrix3 rot_inverse = LLMatrix3(~delta_rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / delta_scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / delta_scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / delta_scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); } else { @@ -905,34 +941,35 @@ void LLVOVolume::updateRelativeXform(BOOL global_volume) LLVector4(z_axis, 0.f), LLVector4(pos, 1.f)); - x_axis.normVec(); - y_axis.normVec(); - z_axis.normVec(); - - mRelativeXformInvTrans.setRows(x_axis, y_axis, z_axis); + // compute inverse transpose for normals + LLMatrix3 rot_inverse = LLMatrix3(~rot); + + LLMatrix3 scale_inverse; + scale_inverse.setRows(LLVector3(1.0, 0.0, 0.0) / scale.mV[VX], + LLVector3(0.0, 1.0, 0.0) / scale.mV[VY], + LLVector3(0.0, 0.0, 1.0) / scale.mV[VZ]); + + + mRelativeXformInvTrans = rot_inverse * scale_inverse; + + mRelativeXformInvTrans.transpose(); } } BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { LLFastTimer t(LLFastTimer::FTM_UPDATE_PRIMITIVES); - + if (mVolumeImpl != NULL) { LLFastTimer t(LLFastTimer::FTM_GEN_FLEX); BOOL res = mVolumeImpl->doUpdateGeometry(drawable); updateFaceFlags(); - if (res) - { - drawable->clearState(LLDrawable::REBUILD_GEOMETRY); - } - return res; } BOOL compiled = FALSE; - BOOL change_shared = FALSE; - + updateRelativeXform(); if (mDrawable.isNull()) // Not sure why this is happening, but it is... @@ -940,28 +977,23 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) return TRUE; // No update to complete } - calcAllTEsSame(); - - if (mVolumeChanged || mFaceMappingChanged || change_shared) + if (mVolumeChanged || mFaceMappingChanged ) { compiled = TRUE; mInited = TRUE; + if (mVolumeChanged) { LLFastTimer ftm(LLFastTimer::FTM_GEN_VOLUME); LLVolumeParams volume_params = getVolume()->getParams(); setVolume(volume_params, 0); - } - drawable->setState(LLDrawable::REBUILD_GEOMETRY); - if (mVolumeChanged || change_shared) - { - drawable->setState(LLDrawable::REBUILD_LIGHTING); + drawable->setState(LLDrawable::REBUILD_VOLUME); } { LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); regenFaces(); - genTriangles(FALSE); + genBBoxes(FALSE); } } else if (mLODChanged) @@ -983,9 +1015,9 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) if (new_lod != old_lod) { compiled = TRUE; - sNumLODChanges += (getAllTEsSame() ? 1 : getVolume()->getNumFaces()); + sNumLODChanges += getVolume()->getNumFaces(); - drawable->setState(LLDrawable::REBUILD_ALL); // for face->genVolumeTriangles() + drawable->setState(LLDrawable::REBUILD_VOLUME); // for face->genVolumeTriangles() { LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); @@ -993,7 +1025,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) { regenFaces(); } - genTriangles(FALSE); + genBBoxes(FALSE); } } } @@ -1003,7 +1035,7 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) compiled = TRUE; // All it did was move or we changed the texture coordinate offset LLFastTimer t(LLFastTimer::FTM_GEN_TRIANGLES); - genTriangles(FALSE); + genBBoxes(FALSE); } // Update face flags @@ -1018,11 +1050,16 @@ BOOL LLVOVolume::updateGeometry(LLDrawable *drawable) mLODChanged = FALSE; mFaceMappingChanged = FALSE; - drawable->clearState(LLDrawable::REBUILD_GEOMETRY); - return TRUE; } +void LLVOVolume::updateFaceSize(S32 idx) +{ + const LLVolumeFace& vol_face = getVolume()->getVolumeFace(idx); + LLFace* facep = mDrawable->getFace(idx); + facep->setSize(vol_face.mVertices.size(), vol_face.mIndices.size()); +} + BOOL LLVOVolume::isRootEdit() const { if (mParent && !((LLViewerObject*)mParent)->isAvatar()) @@ -1034,178 +1071,121 @@ BOOL LLVOVolume::isRootEdit() const void LLVOVolume::setTEImage(const U8 te, LLViewerImage *imagep) { -// llinfos << "SetTEImage:" << llendl; BOOL changed = (mTEImages[te] != imagep); LLViewerObject::setTEImage(te, imagep); - if (mDrawable.notNull()) + if (changed) { - if (changed) - { - calcAllTEsSame(); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } } S32 LLVOVolume::setTETexture(const U8 te, const LLUUID &uuid) { - BOOL changed = (uuid != getTE(te)->getID() || (uuid == LLUUID::null)); - S32 res = LLViewerObject::setTETexture(te, uuid); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEColor(const U8 te, const LLColor4 &color) { - BOOL changed = (color != getTE(te)->getColor()); S32 res = LLViewerObject::setTEColor(te, color); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); -// mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEBumpmap(const U8 te, const U8 bumpmap) { - BOOL changed = (bumpmap != getTE(te)->getBumpmap()); S32 res = LLViewerObject::setTEBumpmap(te, bumpmap); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTETexGen(const U8 te, const U8 texgen) { - BOOL changed = (texgen != getTE(te)->getTexGen()); S32 res = LLViewerObject::setTETexGen(te, texgen); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEShiny(const U8 te, const U8 shiny) { - BOOL changed = (shiny != getTE(te)->getShiny()); S32 res = LLViewerObject::setTEShiny(te, shiny); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEFullbright(const U8 te, const U8 fullbright) { - BOOL changed = (fullbright != getTE(te)->getFullbright()); S32 res = LLViewerObject::setTEFullbright(te, fullbright); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - if (!mDrawable->isState(LLDrawable::REBUILD_VOLUME)) - { - updateFaceFlags(); - } - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEMediaFlags(const U8 te, const U8 media_flags) { - bool changed = (media_flags != getTE(te)->getMediaFlags()); S32 res = LLViewerObject::setTEMediaFlags(te, media_flags); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEScale(const U8 te, const F32 s, const F32 t) { - F32 olds,oldt; - getTE(te)->getScale(&olds, &oldt); - bool changed = (s != olds || t != oldt); S32 res = LLViewerObject::setTEScale(te, s, t); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEScaleS(const U8 te, const F32 s) { - F32 olds,oldt; - getTE(te)->getScale(&olds, &oldt); - bool changed = (s != olds); S32 res = LLViewerObject::setTEScaleS(te, s); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } S32 LLVOVolume::setTEScaleT(const U8 te, const F32 t) { - F32 olds,oldt; - getTE(te)->getScale(&olds, &oldt); - bool changed = (t != oldt); S32 res = LLViewerObject::setTEScaleT(te, t); - if (mDrawable.notNull()) + if (res) { - if (changed) - { - calcAllTEsSame(); - mFaceMappingChanged = TRUE; - } + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } return res; } @@ -1214,137 +1194,11 @@ void LLVOVolume::updateTEData() { if (mDrawable.notNull()) { - calcAllTEsSame(); mFaceMappingChanged = TRUE; - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); + gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_MATERIAL, TRUE); } } -BOOL LLVOVolume::calcAllTEsSame() -{ - BOOL is_alpha = FALSE; - BOOL was_same = mAllTEsSame; - BOOL all_same = TRUE; - S32 num_tes = getNumTEs(); - - LLViewerImage *first_texturep = getTEImage(0); - if (!first_texturep) - { - return FALSE; - } - - const LLTextureEntry *tep = getTE(0); - if (!tep) - { - llwarns << "Volume with zero textures!" << llendl; - return FALSE; - } - - if (tep->getColor().mV[3] != 1.f) - { - is_alpha = TRUE; - } - const LLColor4 first_color = tep->getColor(); - const U8 first_bump = tep->getBumpShinyFullbright(); - const U8 first_media_flags = tep->getMediaTexGen(); - - if (first_texturep->getComponents() == 4) - { - is_alpha = TRUE; - } - - F32 s_scale, t_scale; - tep->getScale(&s_scale, &t_scale); - - for (S32 f = 1; f < num_tes; f++) - { - LLViewerImage *texturep = getTEImage(f); - if (texturep != first_texturep) - { - all_same = FALSE; - break; - } - - tep = getTE(f); - - if( tep->getBumpShinyFullbright() != first_bump ) - { - all_same = FALSE; - break; - } - - if (first_bump) - { - F32 cur_s, cur_t; - tep->getScale(&cur_s, &cur_t); - if ((cur_s != s_scale) || (cur_t != t_scale)) - { - all_same = FALSE; - break; - } - } - - if ((texturep->getComponents() == 4) || (tep->getColor().mV[3] != 1.f)) - { - if (!is_alpha) - { - all_same = FALSE; - break; - } - } - else if (is_alpha) - { - all_same = FALSE; - break; - } - - if (tep->getColor() != first_color) - { - all_same = FALSE; - break; - } - - if (tep->getMediaTexGen() != first_media_flags) - { - all_same = FALSE; - break; - } - } - - mAllTEsSame = all_same; - if (was_same != all_same) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); // rebuild NOW - mFaceMappingChanged = TRUE; - } - return mAllTEsSame; -} - -void LLVOVolume::setupSingleFace(S32 face_offset) -{ - S32 num_indices = 0; - S32 num_vertices = 0; - - if (mDrawable.isNull()) - { - llerrs << "setupSingleFace called with NULL mDrawable" << llendl; - } - if (face_offset >= mDrawable->getNumFaces()) - { - llerrs << "setupSingleFace called with invalid face_offset" << llendl; - } - - const S32 num_faces = getVolume()->getNumFaces(); - for (S32 i = 0; i < num_faces; i++) - { - const LLVolumeFace &vf = getVolume()->getVolumeFace(i); - num_vertices += vf.mVertices.size(); - num_indices += vf.mIndices.size(); - } - LLFace *facep = mDrawable->getFace(face_offset); - facep->setSize(num_vertices, num_indices); -} - //---------------------------------------------------------------------------- void LLVOVolume::setIsLight(BOOL is_light) @@ -1388,6 +1242,8 @@ void LLVOVolume::setLightColor(const LLColor3& color) { param_block->setColor(LLColor4(color, param_block->getColor().mV[3])); parameterChanged(LLNetworkData::PARAMS_LIGHT, true); + gPipeline.markTextured(mDrawable); + mFaceMappingChanged = TRUE; } } } @@ -1551,7 +1407,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL LLVector3 light_dir = light_pos - pos; F32 dist = light_dir.normVec(); F32 dp = norm * light_dir; - if ((gPipeline.getVertexShaderLevel(LLPipeline::SHADER_OBJECT) >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS)) + if ((gPipeline.getLightingDetail() > 2)) { if (dp <= 0) { @@ -1590,7 +1446,7 @@ F32 LLVOVolume::calcLightAtPoint(const LLVector3& pos, const LLVector3& norm, LL BOOL LLVOVolume::updateLighting(BOOL do_lighting) { LLMemType mt1(LLMemType::MTYPE_DRAWABLE); - +#if 0 if (mDrawable->isStatic()) { do_lighting = FALSE; @@ -1600,31 +1456,31 @@ BOOL LLVOVolume::updateLighting(BOOL do_lighting) const LLMatrix3& mat_normal = LLMatrix3(mDrawable->getWorldRotation()); LLVolume* volume = getVolume(); - if (getAllTEsSame()) + + for (S32 i = 0; i < volume->getNumFaces(); i++) { - LLFace *face = mDrawable->getFace(mFaceIndexOffset); - S32 num_faces = volume->getNumFaces(); + LLFace *face = mDrawable->getFace(i); if (face && face->getGeomCount()) { - face->genLighting(volume, mDrawable, 0, num_faces-1, mat_vert, mat_normal, do_lighting); - } - } - else - { - for (S32 i = 0; i < volume->getNumFaces(); i++) - { - LLFace *face = mDrawable->getFace(i + mFaceIndexOffset); - if (face && face->getGeomCount()) - { - face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting); - } + face->genLighting(volume, mDrawable, i, i, mat_vert, mat_normal, do_lighting); } } +#endif return TRUE; } //---------------------------------------------------------------------------- +U32 LLVOVolume::getVolumeInterfaceID() const +{ + if (mVolumeImpl) + { + return mVolumeImpl->getID(); + } + + return 0; +} + BOOL LLVOVolume::isFlexible() const { if (getParameterEntryInUse(LLNetworkData::PARAMS_FLEXIBLE)) @@ -1715,16 +1571,18 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p LLVector3 view_vector; view_vector = view_point; + //transform view vector into volume space + view_vector -= getRenderPosition(); + mDrawable->mDistanceWRTCamera = view_vector.magVec(); + LLQuaternion worldRot = getRenderRotation(); + view_vector = view_vector * ~worldRot; if (!isVolumeGlobal()) - { //transform view vector into volume space - view_vector -= getRenderPosition(); - LLQuaternion worldRot = getRenderRotation(); - view_vector = view_vector * ~worldRot; + { LLVector3 objScale = getScale(); LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); view_vector.scaleVec(invObjScale); } - + updateRelativeXform(); volume->generateSilhouetteVertices(nodep->mSilhouetteVertices, nodep->mSilhouetteNormals, nodep->mSilhouetteSegments, view_vector, mRelativeXform, mRelativeXformInvTrans); @@ -1732,33 +1590,15 @@ void LLVOVolume::generateSilhouette(LLSelectNode* nodep, const LLVector3& view_p } } -void LLVOVolume::deleteFaces(LLVOVolume* childp) +void LLVOVolume::deleteFaces() { - S32 face_count = childp->mNumFaces; - S32 start_index = childp->mFaceIndexOffset; + S32 face_count = mNumFaces; if (mDrawable.notNull()) { - mDrawable->deleteFaces(start_index, face_count); - } - if (mFaceIndexOffset > start_index) - { - mFaceIndexOffset -= face_count; + mDrawable->deleteFaces(0, face_count); } - for (U32 i = 0; i < mChildList.size(); i++) - { - LLViewerObject* siblingp = mChildList[i]; - if (siblingp != childp) - { - if (siblingp->getPCode() == LL_PCODE_VOLUME && - ((LLVOVolume*)siblingp)->mFaceIndexOffset > start_index) - { - ((LLVOVolume*)siblingp)->mFaceIndexOffset -= face_count; - } - } - } - childp->mFaceIndexOffset = 0; - childp->mNumFaces = 0; + mNumFaces = 0; } void LLVOVolume::updateRadius() @@ -1806,7 +1646,8 @@ const LLMatrix4 LLVOVolume::getRenderMatrix() const void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file_base, S32 joint_num, LLVector3& pos, LLQuaternion& rot, S32& material_index, S32& texture_index, std::multimap& material_map) { - LLPointer tga_image = new LLImageTGA; +#if 0 + LLImageTGA tga_image; if (mDrawable.isNull()) { @@ -1878,8 +1719,8 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file my_texture = texture_index++; //...and export texture as image file - char filename[MAX_PATH]; - sprintf(filename, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); + char filename[MAX_PATH]; /* Flawfinder: ignore */ + snprintf(filename, MAX_PATH, "%s\\%s_material_tex_%d.tga", path.c_str(), file_base.c_str(), my_texture); /* Flawfinder: ignore */ LLViewerImage* imagep = facep->getTexture(); if (imagep->getTexName() == 0) @@ -1887,10 +1728,10 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file llinfos << "No image data available for " << filename << llendl; continue; } - LLPointer raw_image = new LLImageRaw; + LLImageRaw raw_image; imagep->readBackRaw(-1, raw_image); - BOOL success = tga_image->encode(raw_image); - success = tga_image->save(filename); + BOOL success = tga_image.encode(raw_image); + success = tga_image.save(filename); } material_info = new LLMaterialExportInfo(my_material, my_texture, face_color); @@ -1931,6 +1772,7 @@ void LLVOVolume::writeCAL3D(apr_file_t* fp, std::string& path, std::string& file { ((LLVOVolume*)(LLViewerObject*)mChildList[i])->writeCAL3D(fp, path, file_base, joint_num, final_pos, final_rot, material_index, texture_index, material_map); } +#endif } //static @@ -1961,10 +1803,67 @@ void LLVOVolume::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_u } } +void LLVOVolume::setSelected(BOOL sel) +{ + LLViewerObject::setSelected(sel); + if (mDrawable.notNull()) + { + mDrawable->movePartition(); + } +} + void LLVOVolume::updateSpatialExtents(LLVector3& newMin, LLVector3& newMax) { } +F32 LLVOVolume::getBinRadius() +{ + F32 radius; + + const LLVector3* ext = mDrawable->getSpatialExtents(); + + BOOL shrink_wrap = mDrawable->isAnimating(); + BOOL alpha_wrap = FALSE; + + if (!isHUDAttachment()) + { + for (S32 i = 0; i < mDrawable->getNumFaces(); i++) + { + if (mDrawable->getFace(i)->getPoolType() == LLDrawPool::POOL_ALPHA) + { + alpha_wrap = TRUE; + break; + } + } + } + else + { + shrink_wrap = FALSE; + } + + if (alpha_wrap) + { + LLVector3 bounds = getScale(); + radius = llmin(bounds.mV[1], bounds.mV[2]); + radius = llmin(radius, bounds.mV[0]); + radius *= 0.5f; + } + else if (shrink_wrap) + { + radius = (ext[1]-ext[0]).magVec()*0.5f; + } + else if (mDrawable->isStatic()) + { + radius = 32.f; + } + else + { + radius = 8.f; + } + + return llclamp(radius, 0.5f, 256.f); +} + const LLVector3 LLVOVolume::getPivotPositionAgent() const { if (mVolumeImpl) @@ -1980,6 +1879,8 @@ void LLVOVolume::onShift(const LLVector3 &shift_vector) { mVolumeImpl->onShift(shift_vector); } + + updateRelativeXform(); } const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const @@ -1993,14 +1894,9 @@ const LLMatrix4& LLVOVolume::getWorldMatrix(LLXformMatrix* xform) const LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const { - if (isVolumeGlobal()) - { - return pos; - } - LLVector3 ret = pos - getRenderPosition(); ret = ret * ~getRenderRotation(); - LLVector3 objScale = getScale(); + LLVector3 objScale = isVolumeGlobal() ? LLVector3(1,1,1) : getScale(); LLVector3 invObjScale(1.f / objScale.mV[VX], 1.f / objScale.mV[VY], 1.f / objScale.mV[VZ]); ret.scaleVec(invObjScale); @@ -2009,7 +1905,7 @@ LLVector3 LLVOVolume::agentPositionToVolume(const LLVector3& pos) const LLVector3 LLVOVolume::agentDirectionToVolume(const LLVector3& dir) const { - return isVolumeGlobal() ? dir : (dir * ~getRenderRotation()); + return dir * ~getRenderRotation(); } LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const @@ -2024,6 +1920,9 @@ LLVector3 LLVOVolume::volumePositionToAgent(const LLVector3& dir) const BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) const { + return FALSE; + +#if 0 // needs to be rewritten to use face extents instead of volume bounds LLVolume* volume = getVolume(); BOOL ret = FALSE; if (volume) @@ -2043,4 +1942,561 @@ BOOL LLVOVolume::lineSegmentIntersect(const LLVector3& start, LLVector3& end) co } } return ret; +#endif +} + +U32 LLVOVolume::getPartitionType() const +{ + if (isHUDAttachment()) + { + return LLPipeline::PARTITION_HUD; + } + + return LLPipeline::PARTITION_VOLUME; +} + +LLVolumePartition::LLVolumePartition() +: LLSpatialPartition(LLVOVolume::VERTEX_DATA_MASK, FALSE) +{ + mLODPeriod = 16; + mDepthMask = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLPipeline::PARTITION_VOLUME; + mSlopRatio = 0.25f; + mBufferUsage = GL_DYNAMIC_DRAW_ARB; + mImageEnabled = TRUE; } + +LLVolumeBridge::LLVolumeBridge(LLDrawable* drawablep) +: LLSpatialBridge(drawablep, LLVOVolume::VERTEX_DATA_MASK) +{ + mDepthMask = FALSE; + mLODPeriod = 16; + mDrawableType = LLPipeline::RENDER_TYPE_VOLUME; + mPartitionType = LLPipeline::PARTITION_BRIDGE; + + mBufferUsage = GL_DYNAMIC_DRAW_ARB; + + mSlopRatio = 0.25f; +} + +void LLVolumeGeometryManager::registerFace(LLSpatialGroup* group, LLFace* facep, U32 type) +{ + LLMemType mt(LLMemType::MTYPE_SPACE_PARTITION); + + if (facep->getViewerObject()->isSelected() && gHideSelectedObjects) + { + return; + } + + //add face to drawmap + std::vector& draw_vec = group->mDrawMap[type]; + + S32 idx = draw_vec.size()-1; + + + BOOL fullbright = (type == LLRenderPass::PASS_FULLBRIGHT || + type == LLRenderPass::PASS_ALPHA) ? facep->isState(LLFace::FULLBRIGHT) : FALSE; + + const LLMatrix4* tex_mat = NULL; + if (type != LLRenderPass::PASS_SHINY && facep->isState(LLFace::TEXTURE_ANIM)) + { + tex_mat = &(facep->mTextureMatrix); + } + + U8 bump = (type == LLRenderPass::PASS_BUMP ? facep->getTextureEntry()->getBumpmap() : 0); + + //LLViewerImage* tex = facep->mAppAngle < FORCE_SIMPLE_RENDER_ANGLE ? NULL : facep->getTexture(); + LLViewerImage* tex = facep->getTexture(); + + if (type == LLRenderPass::PASS_GLOW) + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex, + facep->mVertexBuffer, fullbright, bump); + draw_info->mVSize = facep->getVirtualSize(); + draw_vec.push_back(draw_info); + LLVOVolume* volume = (LLVOVolume*) facep->getViewerObject(); + BOOL is_light = volume->mDrawable->isLight(); + +// U8 alpha = is_light ? 196 : 160; + LLColor3 col = is_light ? volume->getLightColor() : LLColor3(0,0,0); + LLColor4 col2 = facep->getRenderColor(); + draw_info->mGlowColor.setVec((U8) (col.mV[0]*col2.mV[0]*255), + (U8) (col.mV[1]*col2.mV[1]*255), + (U8) (col.mV[2]*col2.mV[2]*255), + 196); + draw_info->mTextureMatrix = tex_mat; + validate_draw_info(*draw_info); + } + else if (idx >= 0 && + draw_vec[idx]->mVertexBuffer == facep->mVertexBuffer && + draw_vec[idx]->mEnd == facep->getGeomIndex()-1 && + draw_vec[idx]->mTexture == tex && +#if LL_DARWIN + draw_vec[idx]->mEnd - draw_vec[idx]->mStart + facep->getGeomCount() <= (U32) gGLManager.mGLMaxVertexRange && + draw_vec[idx]->mCount + facep->getIndicesCount() <= (U32) gGLManager.mGLMaxIndexRange && +#endif + draw_vec[idx]->mFullbright == fullbright && + draw_vec[idx]->mBump == bump && + draw_vec[idx]->mTextureMatrix == tex_mat) + { + draw_vec[idx]->mCount += facep->getIndicesCount(); + draw_vec[idx]->mEnd += facep->getGeomCount(); + draw_vec[idx]->mVSize = llmax(draw_vec[idx]->mVSize, facep->getVirtualSize()); + validate_draw_info(*draw_vec[idx]); + } + else + { + U32 start = facep->getGeomIndex(); + U32 end = start + facep->getGeomCount()-1; + U32 offset = facep->getIndicesStart(); + U32 count = facep->getIndicesCount(); + LLDrawInfo* draw_info = new LLDrawInfo(start,end,count,offset,tex, + facep->mVertexBuffer, fullbright, bump); + draw_info->mVSize = facep->getVirtualSize(); + draw_vec.push_back(draw_info); + draw_info->mReflectionMap = group->mReflectionMap; + draw_info->mTextureMatrix = tex_mat; + validate_draw_info(*draw_info); + } +} + +void LLVolumeGeometryManager::getGeometry(LLSpatialGroup* group) +{ + +} + +void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group) +{ + if (group->changeLOD()) + { + group->mLastUpdateDistance = group->mDistance; + } + + group->mLastUpdateViewAngle = group->mViewAngle; + + if (!group->isState(LLSpatialGroup::GEOM_DIRTY | + LLSpatialGroup::ALPHA_DIRTY)) + { + return; + } + + group->mBuilt = 1.f; + LLFastTimer ftm(LLFastTimer::FTM_REBUILD_VBO); + + LLFastTimer ftm2(LLFastTimer::FTM_REBUILD_VOLUME_VB); + + //find reflection map + if (group->mSpatialPartition->mImageEnabled) + { + if (group->mReflectionMap.isNull()) + { + LLSpatialGroup* parent = group->getParent(); + while (parent && group->mReflectionMap.isNull()) + { + group->mReflectionMap = parent->mReflectionMap; + parent = parent->getParent(); + } + } + } + + group->clearDrawMap(); + + mFaceList.clear(); + + std::vector alpha_faces; + U32 vertex_count = 0; + U32 index_count = 0; + U32 useage = group->mSpatialPartition->mBufferUsage; + + //get all the faces into a list, putting alpha faces in their own list + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead()) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + useage = GL_STREAM_DRAW_ARB; + } + + LLVOVolume* vobj = drawablep->getVOVolume(); + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) + { + const LLTextureEntry* te = facep->getTextureEntry(); + LLViewerImage* tex = facep->getTexture(); + + BOOL force_simple = (facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA); + U32 type = gPipeline.getPoolTypeFromTE(te, tex); + if (type != LLDrawPool::POOL_ALPHA && force_simple) + { + type = LLDrawPool::POOL_SIMPLE; + } + facep->setPoolType(type); + + if (vobj->isHUDAttachment()) + { + facep->setState(LLFace::FULLBRIGHT); + } + + if (vobj->mTextureAnimp && vobj->mTexAnimMode) + { + if (vobj->mTextureAnimp->mFace <= -1) + { + S32 face; + for (face = 0; face < vobj->getNumTEs(); face++) + { + drawablep->getFace(face)->setState(LLFace::TEXTURE_ANIM); + } + } + else if (vobj->mTextureAnimp->mFace < vobj->getNumTEs()) + { + drawablep->getFace(vobj->mTextureAnimp->mFace)->setState(LLFace::TEXTURE_ANIM); + } + } + + if (type == LLDrawPool::POOL_ALPHA) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + alpha_faces.push_back(facep); + } + else + { + if (drawablep->isState(LLDrawable::REBUILD_VOLUME)) + { + facep->mLastUpdateTime = gFrameTimeSeconds; + } + mFaceList.push_back(facep); + } + } + else + { //face has no renderable geometry + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + //don't alpha wrap drawables that have only tiny tiny alpha faces + facep->setPoolType(LLDrawPool::POOL_SIMPLE); + } + + vobj->updateTextures(); + } + } + + group->mVertexCount = vertex_count; + group->mIndexCount = index_count; + group->mBufferUsage = useage; + + LLStrider vertices; + LLStrider normals; + LLStrider texcoords2; + LLStrider texcoords; + LLStrider colors; + LLStrider indices; + + //PROCESS NON-ALPHA FACES + { + //sort faces by texture + std::sort(mFaceList.begin(), mFaceList.end(), LLFace::CompareTextureAndTime()); + + std::vector::iterator face_iter = mFaceList.begin(); + + LLSpatialGroup::buffer_map_t buffer_map; + + while (face_iter != mFaceList.end()) + { + //pull off next face + LLFace* facep = *face_iter; + LLViewerImage* tex = facep->getTexture(); + + U32 index_count = facep->getIndicesCount(); + U32 geom_count = facep->getGeomCount(); + + //sum up vertices needed for this texture + std::vector::iterator i = face_iter; + ++i; + while (i != mFaceList.end() && (*i)->getTexture() == tex) + { + facep = *i; + ++i; + index_count += facep->getIndicesCount(); + geom_count += facep->getGeomCount(); + } + + //create/delete/resize vertex buffer if needed + LLVertexBuffer* buffer = NULL; + LLSpatialGroup::buffer_map_t::iterator found_iter = group->mBufferMap.find(tex); + if (found_iter != group->mBufferMap.end()) + { + buffer = found_iter->second; + } + + if (!buffer) + { //create new buffer if needed + buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { + if (LLVertexBuffer::sEnableVBOs && buffer->getUsage() != group->mBufferUsage) + { + buffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, + group->mBufferUsage); + buffer->allocateBuffer(geom_count, index_count, TRUE); + } + else + { + buffer->resizeBuffer(geom_count, index_count); + } + } + + BOOL clean = TRUE; + buffer_map[tex] = buffer; + + //add face geometry + + //get vertex buffer striders + buffer->getVertexStrider(vertices); + buffer->getNormalStrider(normals); + buffer->getTexCoordStrider(texcoords); + buffer->getTexCoord2Strider(texcoords2); + buffer->getColorStrider(colors); + buffer->getIndexStrider(indices); + + U32 indices_index = 0; + U32 index_offset = 0; + + while (face_iter < i) + { + facep = *face_iter; + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + U32 te_idx = facep->getTEOffset(); + facep->mIndicesIndex = indices_index; + facep->mGeomIndex = index_offset; + facep->mVertexBuffer = buffer; + { + if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) + { + clean = FALSE; + buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), + facep->getIndicesStart(), facep->getIndicesCount()); + } + } + + indices_index += facep->mIndicesCount; + + BOOL force_simple = facep->mPixelArea < FORCE_SIMPLE_RENDER_AREA; + BOOL fullbright = facep->isState(LLFace::FULLBRIGHT); + const LLTextureEntry* te = facep->getTextureEntry(); + + if (tex->getPrimaryFormat() == GL_ALPHA) + { + registerFace(group, facep, LLRenderPass::PASS_INVISIBLE); + } + else if (fullbright) + { + registerFace(group, facep, LLRenderPass::PASS_FULLBRIGHT); + } + else + { + registerFace(group, facep, LLRenderPass::PASS_SIMPLE); + } + + facep->setPoolType(LLDrawPool::POOL_SIMPLE); + + if (te->getShiny()) + { + registerFace(group, facep, LLRenderPass::PASS_SHINY); + } + + if (!force_simple && te->getBumpmap()) + { + registerFace(group, facep, LLRenderPass::PASS_BUMP); + } + + if (vobj->getIsLight()) + { + registerFace(group, facep, LLRenderPass::PASS_GLOW); + } + + + ++face_iter; + } + + if (clean) + { + buffer->markClean(); + } + } + + group->mBufferMap.clear(); + for (LLSpatialGroup::buffer_map_t::iterator i = buffer_map.begin(); i != buffer_map.end(); ++i) + { + group->mBufferMap[i->first] = i->second; + } + } + + //PROCESS ALPHA FACES + if (!alpha_faces.empty()) + { + //sort alpha faces by distance + std::sort(alpha_faces.begin(), alpha_faces.end(), LLFace::CompareDistanceGreater()); + + //store alpha faces in root vertex buffer + if (group->mVertexBuffer.isNull() || (LLVertexBuffer::sEnableVBOs && group->mBufferUsage != group->mVertexBuffer->getUsage())) + { + group->mVertexBuffer = createVertexBuffer(group->mSpatialPartition->mVertexDataMask, + group->mBufferUsage); + group->mVertexBuffer->allocateBuffer(group->mVertexCount, group->mIndexCount, true); + stop_glerror(); + } + else + { + group->mVertexBuffer->resizeBuffer(group->mVertexCount, group->mIndexCount); + stop_glerror(); + } + + //get vertex buffer striders + LLVertexBuffer* buffer = group->mVertexBuffer; + + BOOL clean = TRUE; + + buffer->getVertexStrider(vertices); + buffer->getNormalStrider(normals); + buffer->getTexCoordStrider(texcoords); + buffer->getTexCoord2Strider(texcoords2); + buffer->getColorStrider(colors); + buffer->getIndexStrider(indices); + + U32 index_offset = 0; + U32 indices_index = 0; + + for (std::vector::iterator i = alpha_faces.begin(); i != alpha_faces.end(); ++i) + { + LLFace* facep = *i; + LLDrawable* drawablep = facep->getDrawable(); + LLVOVolume* vobj = drawablep->getVOVolume(); + LLVolume* volume = vobj->getVolume(); + + U32 te_idx = facep->getTEOffset(); + facep->mIndicesIndex = indices_index; + facep->mGeomIndex = index_offset; + facep->mVertexBuffer = group->mVertexBuffer; + if (facep->getGeometryVolume(*volume, te_idx, vertices, normals, texcoords, texcoords2, colors, indices, + vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), index_offset)) + { + clean = FALSE; + buffer->markDirty(facep->getGeomIndex(), facep->getGeomCount(), + facep->getIndicesStart(), facep->getIndicesCount()); + } + + indices_index += facep->mIndicesCount; + + registerFace(group, facep, LLRenderPass::PASS_ALPHA); + } + + if (clean) + { + buffer->markClean(); + } + } + else + { + group->mVertexBuffer = NULL; + } + + //get all the faces into a list, putting alpha faces in their own list + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + drawablep->clearState(LLDrawable::REBUILD_ALL); + } + + group->mLastUpdateTime = gFrameTimeSeconds; + group->clearState(LLSpatialGroup::GEOM_DIRTY | LLSpatialGroup::MATRIX_DIRTY | + LLSpatialGroup::ALPHA_DIRTY); + + mFaceList.clear(); +} + +void LLGeometryManager::addGeometryCount(LLSpatialGroup* group, U32 &vertex_count, U32 &index_count) +{ + //initialize to default usage for this partition + U32 usage = group->mSpatialPartition->mBufferUsage; + + //clear off any old faces + mFaceList.clear(); + + //for each drawable + for (LLSpatialGroup::element_iter drawable_iter = group->getData().begin(); drawable_iter != group->getData().end(); ++drawable_iter) + { + LLDrawable* drawablep = *drawable_iter; + + if (drawablep->isDead()) + { + continue; + } + + if (drawablep->isAnimating()) + { //fall back to stream draw for animating verts + usage = GL_STREAM_DRAW_ARB; + } + + //for each face + for (S32 i = 0; i < drawablep->getNumFaces(); i++) + { + //sum up face verts and indices + drawablep->updateFaceSize(i); + LLFace* facep = drawablep->getFace(i); + if (facep->hasGeometry() && facep->mPixelArea > FORCE_CULL_AREA) + { + vertex_count += facep->getGeomCount(); + index_count += facep->getIndicesCount(); + + //remember face (for sorting) + mFaceList.push_back(facep); + } + else + { + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + } + } + } + + group->mBufferUsage = usage; +} + +LLHUDPartition::LLHUDPartition() +{ + mPartitionType = LLPipeline::PARTITION_HUD; + mDrawableType = LLPipeline::RENDER_TYPE_HUD; + mSlopRatio = 0.f; + mLODPeriod = 16; +} + +void LLHUDPartition::shift(const LLVector3 &offset) +{ + //HUD objects don't shift with region crossing. That would be silly. +} + + diff --git a/linden/indra/newview/llvovolume.h b/linden/indra/newview/llvovolume.h index 2c12f12..9fb8ca4 100644 --- a/linden/indra/newview/llvovolume.h +++ b/linden/indra/newview/llvovolume.h @@ -29,6 +29,7 @@ #define LL_LLVOVOLUME_H #include "llviewerobject.h" +#include "llspatialpartition.h" #include "llviewerimage.h" #include "llframetimer.h" #include "llapr.h" @@ -60,7 +61,8 @@ public: virtual bool isVolumeGlobal() const = 0; // Are we in global space? virtual bool isActive() const = 0; // Is this object currently active? virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const = 0; - virtual void updateRelativeXform(BOOL global_volume = FALSE) = 0; + virtual void updateRelativeXform() = 0; + virtual U32 getID() const = 0; }; // Class which embodies all Volume objects (with pcode LL_PCODE_VOLUME) @@ -69,18 +71,26 @@ class LLVOVolume : public LLViewerObject public: static void initClass(); static void preUpdateGeom(); - static F32 getTextureVirtualSize(const LLFace* face); - - BOOL mWereAllTEsSame; + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) | + (1 << LLVertexBuffer::TYPE_TEXCOORD2) | + (1 << LLVertexBuffer::TYPE_COLOR) + } + eVertexDataMask; + public: LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOVolume(); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); - void deleteFaces(LLVOVolume* childp); + void deleteFaces(); + void animateTextures(); /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ BOOL isActive() const; @@ -89,8 +99,7 @@ public: /*virtual*/ BOOL isHUDAttachment() const; void generateSilhouette(LLSelectNode* nodep, const LLVector3& view_point); - - BOOL getAllTEsSame() const { return mAllTEsSame; } + /*virtual*/ void setParent(LLViewerObject* parent); F32 getIndividualRadius() { return mRadius; } S32 getLOD() const { return mLOD; } const LLVector3 getPivotPositionAgent() const; @@ -105,6 +114,7 @@ public: BOOL getVolumeChanged() const { return mVolumeChanged; } + F32 getTextureVirtualSize(LLFace* face); /*virtual*/ F32 getRadius() const { return mVObjRadius; }; const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const; @@ -120,6 +130,7 @@ public: U32 block_num, const EObjectUpdateType update_type, LLDataPacker *dp); + /*virtual*/ void setSelected(BOOL sel); /*virtual*/ BOOL setDrawableParent(LLDrawable* parentp); /*virtual*/ void setScale(const LLVector3 &scale, BOOL damped); @@ -140,17 +151,19 @@ public: void setTexture(const S32 face); /*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false); - void updateRelativeXform(BOOL global_volume = FALSE); + void updateRelativeXform(); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); + /*virtual*/ void updateFaceSize(S32 idx); /*virtual*/ BOOL updateLOD(); void updateRadius(); /*virtual*/ void updateTextures(LLAgent &agent); - void updateTextures(S32 lod); + void updateTextures(); void updateFaceFlags(); void regenFaces(); - BOOL genTriangles(BOOL force_global); + BOOL genBBoxes(BOOL force_global); virtual void updateSpatialExtents(LLVector3& min, LLVector3& max); + virtual F32 getBinRadius(); virtual void writeCAL3D(apr_file_t* fp, std::string& path, std::string& file_base, @@ -161,6 +174,9 @@ public: S32& texture_index, std::multimap& material_map); + + virtual U32 getPartitionType() const; + // For Lights void setIsLight(BOOL is_light); void setLightColor(const LLColor3& color); @@ -178,6 +194,7 @@ public: F32 getLightDistance(const LLVector3& pos) const; // returns < 0 if inside radius // Flexible Objects + U32 getVolumeInterfaceID() const; virtual BOOL isFlexible() const; BOOL isVolumeGlobal() const; BOOL canBeFlexible() const; @@ -188,24 +205,21 @@ public: BOOL updateLighting(BOOL do_lighting); protected: - F32 computeLODProfilePathComplexityBias(); S32 computeLODDetail(F32 distance, F32 radius); BOOL calcLOD(); - void setupSingleFace(S32 face_offset); // Set up the face for combined volumes. LLFace* addFace(S32 face_index); void updateTEData(); - BOOL calcAllTEsSame(); public: LLViewerTextureAnim *mTextureAnimp; - + U8 mTexAnimMode; protected: friend class LLDrawable; - BOOL mAllTEsSame; // All TE's have the same pool/texture BOOL mFaceMappingChanged; BOOL mGlobalVolume; BOOL mInited; + LLFrameTimer mTextureUpdateTimer; S32 mLOD; BOOL mLODChanged; F32 mRadius; @@ -218,8 +232,6 @@ protected: // statics public: static F32 sLODSlopDistanceFactor;// Changing this to zero, effectively disables the LOD transition slop - static F32 sLODComplexityDistanceBias; // Changing this to zero makes all prims LOD at the same distance, - // regardless of complexity static F32 sLODFactor; // LOD scale factor static F32 sDistanceFactor; // LOD distance factor diff --git a/linden/indra/newview/llvowater.cpp b/linden/indra/newview/llvowater.cpp index 55a7020..a57aa8b 100644 --- a/linden/indra/newview/llvowater.cpp +++ b/linden/indra/newview/llvowater.cpp @@ -64,22 +64,8 @@ const F32 WAVE_STEP_INV = (1. / WAVE_STEP); const F32 g = 9.81f; // gravitational constant (m/s^2) -/////////////////////////////////// - -LLWaterSurface::LLWaterSurface() : - mInitialized(FALSE), - mWind(9, 0, 0), - mA(0.2f), - mVisc(0.001f), - mShininess(8.0f) -{} - - -LLWaterGrid *LLVOWater::sGrid = 0; - - LLVOWater::LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -: LLViewerObject(id, LL_VO_WATER, regionp) +: LLStaticViewerObject(id, LL_VO_WATER, regionp) { // Terrain must draw during selection passes so it can block objects behind it. mbCanSelect = FALSE; @@ -113,18 +99,6 @@ void LLVOWater::updateTextures(LLAgent &agent) { } -// virtual -void LLVOWater::updateDrawable(BOOL force_damped) -{ - // Force an immediate rebuild on any update - if (mDrawable.notNull()) - { - gPipeline.updateMoveNormalAsync(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - } - clearChanged(SHIFTED); -} - // Never gets called BOOL LLVOWater::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) { @@ -161,17 +135,13 @@ LLDrawable *LLVOWater::createDrawable(LLPipeline *pipeline) BOOL LLVOWater::updateGeometry(LLDrawable *drawable) { - return updateGeometryFlat(drawable); -} - - -BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable) -{ + LLFastTimer ftm(LLFastTimer::FTM_UPDATE_WATER); LLFace *face; if (drawable->getNumFaces() < 1) { - drawable->addFace(gPipeline.getPool(LLDrawPool::POOL_WATER), NULL); + LLDrawPoolWater *poolp = (LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER); + drawable->addFace(poolp, NULL); } face = drawable->getFace(0); @@ -180,15 +150,26 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable) LLStrider verticesp, normalsp; LLStrider texCoordsp; - U32 *indicesp; + LLStrider indicesp; S32 index_offset; S32 size = 16; - S32 num_quads = size*size; - - face->setPrimType(LLTriangles); - face->setSize(4*num_quads, 6*num_quads); + if (face->mVertexBuffer.isNull()) + { + S32 num_quads = size*size; + face->setSize(4*num_quads, 6*num_quads); + + face->mVertexBuffer = new LLVertexBuffer(LLDrawPoolWater::VERTEX_DATA_MASK, GL_DYNAMIC_DRAW_ARB); + face->mVertexBuffer->allocateBuffer(4*num_quads, 6*num_quads, TRUE); + face->setIndicesIndex(0); + face->setGeomIndex(0); + } + else + { + face->mVertexBuffer->resizeBuffer(face->getGeomCount(), face->getIndicesCount()); + } + index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); if (-1 == index_offset) { @@ -198,6 +179,7 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable) LLVector3 position_agent; position_agent = getPositionAgent(); face->mCenterAgent = position_agent; + face->mCenterLocal = position_agent; S32 x, y; F32 step_x = getScale().mV[0] / size; @@ -256,378 +238,20 @@ BOOL LLVOWater::updateGeometryFlat(LLDrawable *drawable) *indicesp++ = toffset + 2; } } - - - mDrawable->movePartition(); - LLPipeline::sCompiles++; - return TRUE; -} - - -BOOL LLVOWater::updateGeometryHeightFieldRoam(LLDrawable *drawable) -{ - LLVector3 position_agent = getPositionAgent(); - const LLVector3 region_size = getScale(); - const LLVector3 region_origin = position_agent - region_size * 0.5f; - - S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth; - S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth; - S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth; - S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth; - - static S32 res = (S32)sGrid->mPatchRes; - if (patch_origx < 0) - { - patch_dimx -= - patch_origx; - if (patch_dimx < 1) - { - return TRUE; - } - patch_origx = 0; - } - if (patch_origy < 0) - { - patch_dimy -= - patch_origy; - if (patch_dimy < 1) - { - return TRUE; - } - patch_origy = 0; - } - if (patch_origx >= res) - { - return TRUE; - } - if (patch_origy >= res) - { - return TRUE; - } - - patch_dimx = llmin(patch_dimx, res - patch_origx); - patch_dimy = llmin(patch_dimy, res - patch_origy); - - U32 num_of_tris = 0; - S32 px, py; - for (py = patch_origy; py < patch_origy + patch_dimy; py++) - { - for (px = patch_origx; px < patch_origx + patch_dimx; px++) - { - const U32 ind = py * sGrid->mPatchRes + px; - if (sGrid->mPatches[ind].visible() && sGrid->mTab[px][py] == 0) - { - num_of_tris += sGrid->mPatches[ind].numTris(); - sGrid->mTab[px][py] = this; - } - } - } - - if (num_of_tris == 0) - { - return TRUE; - } - - if (drawable->getNumFaces() < 1) - { - drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER), - gWorldp->getDefaultWaterTexture()); - } - - LLFace *face; - - face = drawable->getFace(0); - face->mCenterAgent = position_agent; - - LLStrider verticesp, normalsp; - LLStrider texCoordsp; - U32 *indicesp; - S32 index_offset; - - const F32 water_height = getRegion()->getWaterHeight(); - - face->setPrimType(LLTriangles); - face->setSize(3 * num_of_tris, 3 * num_of_tris); - index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == index_offset) - { - return TRUE; - } - - U32 num_of_vtx = 0; - - for (py = patch_origy; py < patch_origy + patch_dimy; py++) - { - for (px = patch_origx; px < patch_origx + patch_dimx; px++) - { - for (U8 h = 0; h < 2; h++) - { - const U32 ind = py * sGrid->mPatchRes + px; - if (!sGrid->mPatches[ind].visible() || sGrid->mTab[px][py] != this) - continue; - LLWaterTri* half = (LLWaterTri*) sGrid->mPatches[ind].half(h); - for (const LLWaterTri* tri = (LLWaterTri*) half->getFirstLeaf(); - tri != NULL; - tri = (LLWaterTri*) tri->getNextLeaf()) - { - /////// check for coordinates - *(verticesp++) = sGrid->vtx(tri->Lvtx(), water_height); - *(verticesp++) = sGrid->vtx(tri->Rvtx(), water_height); - *(verticesp++) = sGrid->vtx(tri->Tvtx(), water_height); - - *(normalsp++) = sGrid->norm(tri->Lvtx()); - *(normalsp++) = sGrid->norm(tri->Rvtx()); - *(normalsp++) = sGrid->norm(tri->Tvtx()); - - *(indicesp++) = index_offset + num_of_vtx + 0; - *(indicesp++) = index_offset + num_of_vtx + 1; - *(indicesp++) = index_offset + num_of_vtx + 2; - num_of_vtx += 3; - } - } - } - } - - - LLPipeline::sCompiles++; - return TRUE; -} - - - -BOOL LLVOWater::updateGeometryHeightFieldSimple(LLDrawable *drawable) -{ - LLVector3 position_agent = getPositionAgent(); - const LLVector3 region_size = getScale(); - const LLVector3 region_origin = position_agent - region_size * 0.5f; - - S32 patch_origx = llround(region_origin.mV[VX] - sGrid->mRegionOrigin.mV[VX]) / sGrid->mRegionWidth; - S32 patch_origy = llround(region_origin.mV[VY] - sGrid->mRegionOrigin.mV[VY]) / sGrid->mRegionWidth; - S32 patch_dimx = llround(region_size.mV[VX]) / sGrid->mRegionWidth; - S32 patch_dimy = llround(region_size.mV[VY]) / sGrid->mRegionWidth; - - static S32 res = sGrid->mPatchRes; - if (patch_origx < 0) - { - patch_dimx -= - patch_origx; - if (patch_dimx < 1) - { - return TRUE; - } - patch_origx = 0; - } - if (patch_origy < 0) - { - patch_dimy -= - patch_origy; - if (patch_dimy < 1) - { - return TRUE; - } - patch_origy = 0; - } - if (patch_origx >= res) - { - return TRUE; - } - if (patch_origy >= res) - { - return TRUE; - } - - patch_dimx = llmin(patch_dimx, res - patch_origx); - patch_dimy = llmin(patch_dimy, res - patch_origy); - - - U32 num_of_regions = 0; - S32 px, py; - - for (py = patch_origy; py < patch_origy + patch_dimy; py++) - { - for (px = patch_origx; px < patch_origx + patch_dimx; px++) - { - // if (sGrid->mTab[px][py] != 0) - // bool stop = true; - if (sGrid->mPatches[py * sGrid->mPatchRes + px].visible() && sGrid->mTab[px][py] == 0) - { - num_of_regions++; - sGrid->mTab[px][py] = this; - } - } - } - - if (num_of_regions == 0) - { - return TRUE; - } - - if (drawable->getNumFaces() < 1) - { - drawable->addFace((LLDrawPoolWater*) gPipeline.getPool(LLDrawPool::POOL_WATER), - gWorldp->getDefaultWaterTexture()); - } - - LLFace *face; - - face = drawable->getFace(0); - face->mCenterAgent = position_agent; - - LLStrider verticesp, normalsp; - LLStrider texCoordsp; - U32 *indicesp; - S32 index_offset; - - const F32 water_height = getRegion()->getWaterHeight(); - - const U32 steps_in_region = sGrid->mStepsInRegion / sGrid->mResDecrease; - const U32 num_quads = steps_in_region * steps_in_region * num_of_regions; - - face->setPrimType(LLTriangles); - face->setSize(4*num_quads, 6*num_quads); - index_offset = face->getGeometry(verticesp,normalsp,texCoordsp, indicesp); - if (-1 == index_offset) - { - return TRUE; - } - - U32 num_of_vtx = 0; - - for (py = patch_origy; py < patch_origy + patch_dimy; py++) - { - for (px = patch_origx; px < patch_origx + patch_dimx; px++) - { - if (!sGrid->mPatches[py * sGrid->mPatchRes + px].visible() || sGrid->mTab[px][py] != this) - { - continue; - } - - U32 orig_indx = px * sGrid->mStepsInRegion; - U32 orig_indy = py * sGrid->mStepsInRegion; - - for (U32 qy = 0; qy < steps_in_region; qy++) - { - for (U32 qx = 0; qx < steps_in_region; qx++) - { - const S32 x0 = orig_indx + qx * sGrid->mResDecrease; - const S32 y0 = orig_indy + qy * sGrid->mResDecrease; - const S32 x1 = x0 + sGrid->mResDecrease; - const S32 y1 = y0 + sGrid->mResDecrease; - - sGrid->setVertex(x0, y1, water_height, *(verticesp)); - verticesp++; - sGrid->setVertex(x0, y0, water_height, *(verticesp)); - verticesp++; - sGrid->setVertex(x1, y1, water_height, *(verticesp)); - verticesp++; - sGrid->setVertex(x1, y0, water_height, *(verticesp)); - verticesp++; - /* - *(verticesp++) = sGrid->vtx(x0, y1, water_height); - *(verticesp++) = sGrid->vtx(x0, y0, water_height); - *(verticesp++) = sGrid->vtx(x1, y1, water_height); - *(verticesp++) = sGrid->vtx(x1, y0, water_height); - */ - *(normalsp++) = sGrid->norm(x0, y1); - *(normalsp++) = sGrid->norm(x0, y0); - *(normalsp++) = sGrid->norm(x1, y1); - *(normalsp++) = sGrid->norm(x1, y0); - - const S32 curr_index_offset = index_offset + num_of_vtx; - - *indicesp++ = curr_index_offset + 0; - *indicesp++ = curr_index_offset + 1; - *indicesp++ = curr_index_offset + 2; - - *indicesp++ = curr_index_offset + 1; - *indicesp++ = curr_index_offset + 3; - *indicesp++ = curr_index_offset + 2; - num_of_vtx += 4; - } - } - } - } - - + mDrawable->movePartition(); LLPipeline::sCompiles++; return TRUE; } void LLVOWater::initClass() { - sGrid = new LLWaterGrid; } void LLVOWater::cleanupClass() { - if (sGrid) - { - sGrid->cleanup(); - delete sGrid; - sGrid = 0; - } -} - - -LLWaterGrid::LLWaterGrid() : mResIncrease(1)//0.5) -{ - init(); } - -void LLWaterGrid::init() -{ - //mRegionOrigin = LLVector3(-2 * mRegionWidth, -2 * mRegionWidth, 0); - mRegionWidth = 256; - mPatchRes = 5; - mMaxGridSize = mPatchRes * mRegionWidth; - mMinStep = (U32)(WAVE_STEP * mResIncrease); - - LLWaterTri::sMinStep = mMinStep; - LLWaterTri::sQueues = &mRoam; - - setGridDim(mMaxGridSize / mMinStep); - - mVtx = new LLVector3[mGridDim1 * mGridDim1]; - mNorms = new LLVector3[mGridDim1 * mGridDim1]; - - mPatches = new LLWaterPatch[mPatchRes * mPatchRes]; - - mStepsInRegion = mRegionWidth / mMinStep; - const U32 max_div_level = 2 * (U32)(log((F32)mStepsInRegion) / log(2.0f)); - - for (U32 y = 0; y < mPatchRes; y++) - { - for (U32 x = 0; x < mPatchRes; x++) - { - LLVector3 patch_center(mRegionWidth * (x + 0.5f), mRegionWidth * (y + 0.5f), 0); - - mPatches[y * mPatchRes + x].set(x * mStepsInRegion, y * mStepsInRegion, - mStepsInRegion, mRegionWidth, patch_center, max_div_level); - if (x > 0) - { - mPatches[y * mPatchRes + x].left()->setRight(mPatches[y * mPatchRes + x - 1].right()); - mPatches[y * mPatchRes + x - 1].right()->setRight(mPatches[y * mPatchRes + x].left()); - } - if (y > 0) - { - mPatches[y * mPatchRes + x].left()->setLeft(mPatches[(y - 1) * mPatchRes + x].right()); - mPatches[(y - 1) * mPatchRes + x].right()->setLeft(mPatches[y * mPatchRes + x].left()); - } - } - } -} - -void LLWaterGrid::cleanup() -{ - delete[] mVtx; - mVtx = NULL; - - delete[] mNorms; - mNorms = NULL; - - delete[] mPatches; - mPatches = NULL; -} - - void setVecZ(LLVector3& v) { v.mV[VX] = 0; @@ -635,413 +259,31 @@ void setVecZ(LLVector3& v) v.mV[VZ] = 1; } -void LLWaterGrid::update() -{ - static LLViewerRegion* prev_region = gAgent.getRegion(); - LLViewerRegion* region = gAgent.getRegion(); - - mRegionOrigin = region->getOriginAgent(); - mRegionOrigin.mV[VX] -= 2 * mRegionWidth; - mRegionOrigin.mV[VY] -= 2 * mRegionWidth; - mRegionOrigin.mV[VZ] = 0; - - const F32 clip_far = gCamera->getFar() - 31; - const F32 clip_far2 = clip_far * clip_far; - - const LLVector3 camera_pos = gAgent.getCameraPositionAgent(); - const LLVector3 look_at = gCamera->getAtAxis(); - - - if (camera_pos.mV[VZ] > 200) - { - mResDecrease = 4; - } - else if (camera_pos.mV[VZ] > 100) - { - mResDecrease = 2; - } - else - { - mResDecrease = 1; - } - - - //U32 mResDecrease = res_decrease; - U32 res_decrease = 1; - - const F32 res_change = mResIncrease;// * res_decrease ; - - F32 height; - - // Set the grid - - //U32 fractions = 1; - U32 fractions_res = res_decrease; - if (res_change < 1) - { - //fractions = llround(1. / res_change); - fractions_res = llround(1.f / mResIncrease); - } - - - //const U32 fractions_res = fractions * res_decrease; - - LLVector3 cur_pos; - U32 x, y; - U32 ind = 0; - for (y = 0; y < mGridDim1; y += fractions_res) - { - const F32 dispy = (F32)(y * mMinStep);//step; - for (x = 0; x < mGridDim1; x += fractions_res) - { - const F32 dispx = (F32)(x * mMinStep);//step; - cur_pos = mRegionOrigin; - cur_pos.mV[VX] += dispx; - cur_pos.mV[VY] += dispy; - - const F32 x_dist = cur_pos.mV[VX] - camera_pos.mV[VX]; - const F32 y_dist = cur_pos.mV[VY] - camera_pos.mV[VY]; - - if (x_dist * look_at.mV[VX] + y_dist * look_at.mV[VY] < 0) - { - mVtx[ind] = cur_pos; - setVecZ(mNorms[ind]); - ind++; - continue; - } - - const F32 dist_to_vtx2 = x_dist * x_dist + y_dist * y_dist; - if (dist_to_vtx2 > .81 * clip_far2) - { - mVtx[ind] = cur_pos; - setVecZ(mNorms[ind]); - ind++; - continue; - } - - mWater.getIntegerHeightAndNormal(llround(WAVE_STEP_INV * dispx), - llround(WAVE_STEP_INV * dispy), height, mNorms[ind]); - - cur_pos.mV[VZ] += height; - mVtx[ind] = cur_pos; - ind++; - } - } - - if (res_change < 1) - { - U32 fractions = llround(1.f / mResIncrease); - for (y = 0; y < mGridDim1; y += fractions_res) - { - for (x = 0; x < mGridDim; x += fractions_res) - { - const U32 ind00 = index(x, y); - const U32 ind01 = ind00 + fractions_res; - for (U32 frx = 1; frx < fractions; frx += res_decrease) - { - const U32 ind = ind00 + frx; - mNorms[ind] = LERP(mNorms[ind00], mNorms[ind01], frx * res_change); - mVtx[ind] = LERP( mVtx[ind00], mVtx[ind01], frx * res_change); - } - } - } - for (x = 0; x < mGridDim1; x += res_decrease) - { - for (y = 0; y < mGridDim; y += fractions_res) - { - const U32 ind00 = index(x, y); - const U32 ind10 = ind00 + fractions_res * mGridDim1;//(y + fractions) * quad_resx1 + x; - for (U32 fry = 1; fry < fractions; fry += res_decrease) - { - const U32 ind = ind00 + fry * mGridDim1;//(y + fry) * quad_resx1 + x; - mNorms[ind] = LERP(mNorms[ind00], mNorms[ind10], fry * res_change); - mVtx[ind] = LERP( mVtx[ind00], mVtx[ind10], fry * res_change); - } - } - } - } - - if (gUseRoam) - { - updateTree(camera_pos, look_at, clip_far, prev_region != region); - } - else - { - updateVisibility(camera_pos, look_at, clip_far); - } - - prev_region = region; - - - //mTab[0][0] = 0; - for (y = 0; y < mPatchRes; y++) - { - for (x = 0; x < mPatchRes; x++) - mTab[x][y] = 0; - } - -} - -void LLWaterGrid::updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far, - BOOL restart = FALSE) -{ - static S8 recalculate_frame = 0; - - if (restart) - { - recalculate_frame = 0; - } - - if (recalculate_frame == 0) - { - LLWaterTri::nextRound(); - setCamPosition(LLWaterTri::sCam, camera_pos); - LLWaterTri::sClipFar = clip_far; - - - const U32 step = (U32)(WAVE_STEP * mResIncrease * mResDecrease); - const U32 steps_in_region = mRegionWidth / step; - LLWaterTri::sMaxDivLevel = 2 * llround(log((F32)steps_in_region) / log(2.0f)); - - for (U32 y = 0; y < mPatchRes; y++) - { - for (U32 x = 0; x < mPatchRes; x++) - { - U32 patch_ind = y * mPatchRes + x; - mPatches[patch_ind].updateTree(camera_pos, look_at, mRegionOrigin); - } - } - - mRoam.process(); - - // debug - /* - for (y = 0; y < mPatchRes; y++) - { - for (U32 x = 0; x < mPatchRes; x++) - { - //mPatches[y * mPatchRes + x].checkUpToDate(); - //mPatches[y * mPatchRes + x].checkConsistensy(); - mPatches[y * mPatchRes + x].checkCount(); - } - } - */ - } - ++recalculate_frame; - recalculate_frame = recalculate_frame % 2; -} - -void LLWaterGrid::updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far) -{ - for (U32 y = 0; y < mPatchRes; y++) - { - for (U32 x = 0; x < mPatchRes; x++) - { - mPatches[y * mPatchRes + x].updateVisibility(camera_pos, look_at, mRegionOrigin); - } - } -} - - void LLVOWater::setUseTexture(const BOOL use_texture) { mUseTexture = use_texture; } -F32 LLWaterSurface::agentDepth() const +void LLVOWater::updateSpatialExtents(LLVector3 &newMin, LLVector3& newMax) { - const LLViewerRegion* region = gAgent.getRegion(); - LLVector3 position_agent = region->getOriginAgent();// getPositionAgent(); - const LLVector3 region_origin = position_agent; - const LLVector3 camera_pos = gAgent.getCameraPositionAgent(); + LLVector3 pos = getPositionAgent(); + LLVector3 scale = getScale(); - F32 height; - LLVector3 normal; + newMin = pos - scale * 0.5f; + newMax = pos + scale * 0.5f; - getHeightAndNormal(WAVE_STEP_INV * camera_pos.mV[VX], - WAVE_STEP_INV * camera_pos.mV[VY], height, normal); - F32 agent_water_height = gAgent.getRegion()->getWaterHeight(); - return camera_pos.mV[VZ] - (agent_water_height + height); + mDrawable->setPositionGroup((newMin + newMax) * 0.5f); } -//////////////////////////////////////////////// - - -void LLWaterSurface::getHeightAndNormal(F32 i, F32 j, F32& wave_height, LLVector3& normal) const -{ - S32 i_ind = llfloor(i); - S32 j_ind = llfloor(j); - F32 i_fr = i - i_ind; - F32 j_fr = j - j_ind; - - i_ind = i_ind % N_RES; - j_ind = j_ind % N_RES; - - S32 i_ind_next = i_ind + 1; - S32 j_ind_next = j_ind + 1; - if (i_ind_next == (S32)N_RES) i_ind_next = 0; - if (j_ind_next == (S32)N_RES) j_ind_next = 0; - - const F32 i_fr1 = 1 - i_fr; - const F32 j_fr1 = 1 - j_fr; - - const F32 hi0 = i_fr1 * height(i_ind, j_ind) + i_fr * height(i_ind_next, j_ind); - const F32 hi1 = i_fr1 * height(i_ind, j_ind_next) + i_fr * height(i_ind_next, j_ind_next); - wave_height = j_fr1 * hi0 + j_fr * hi1; - - normal = i_fr1 * mNorms[i_ind][j_ind]; - normal += i_fr * mNorms[i_ind_next][j_ind]; - LLVector3 vi1 = i_fr1 * mNorms[i_ind][j_ind_next]; - vi1 += i_fr * mNorms[i_ind_next][j_ind_next]; - normal *= j_fr1; - normal += j_fr * vi1; - - //normal.normVec(); -} - -void LLWaterSurface::getIntegerHeightAndNormal(S32 i, S32 j, F32& wave_height, LLVector3& normal) const -{ - S32 i_ind = i % N_RES; - S32 j_ind = j % N_RES; - - wave_height = height(i_ind, j_ind); - normal = mNorms[i_ind][j_ind]; +U32 LLVOWater::getPartitionType() const +{ + return LLPipeline::PARTITION_WATER; } -F32 LLWaterSurface::phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small) +LLWaterPartition::LLWaterPartition() +: LLSpatialPartition(0) { - F32 k2 = k * k; - F32 k_dot_wind = k * wind_n; - F32 spectrum = mA * (F32) exp(-1 / (L * L * k2)) / (k2 * k2) * (k_dot_wind * k_dot_wind / k2); - - if (k_dot_wind < 0) spectrum *= .25f; // scale down waves that move opposite to the wind - - F32 damp = (F32) exp(- k2 * L_small * L_small); - - return (spectrum * damp); + mRenderByGroup = FALSE; + mDrawableType = LLPipeline::RENDER_TYPE_WATER; + mPartitionType = LLPipeline::PARTITION_WATER; } - - - -void LLWaterSurface::initAmplitudes() -{ - U16 i, j; - LLVector2 k; - F32 sqrtPhillips; - - const LLVector2 wind(mWind.mV); - - LLVector2 wind_n = wind; - const F32 wind_vel = wind_n.normVec(); - - const F32 L = wind_vel * wind_vel / g; // largest wave arising from constant wind of speed wind_vel - - const F32 L_small = L / 70; // eliminate waves with very small length (L_small << L) - - - for (i = 0; i <= N_RES; i++) - { - k.mV[VX] = (- (S32)N_RES_HALF + i) * (F_TWO_PI / WIDTH); - for (j = 0; j <= N_RES; j++) - { - k.mV[VY] = (- (S32)N_RES_HALF + j) * (F_TWO_PI / WIDTH); - - const F32 k_mag = k.magVec(); - mOmega[i][j] = (F32) sqrt(g * k_mag); - - if (k_mag < F_APPROXIMATELY_ZERO) - sqrtPhillips = 0; - else - sqrtPhillips = (F32) sqrt(phillips(k, wind_n, L, L_small)); - - //const F32 r1 = rand() / (F32) RAND_MAX; - //const F32 r2 = rand() / (F32) RAND_MAX; - const F32 r1 = randGauss(0, 1); - const F32 r2 = randGauss(0, 1); - - mHtilda0[i][j].re = sqrtPhillips * r1 * OO_SQRT2; - mHtilda0[i][j].im = sqrtPhillips * r2 * OO_SQRT2; - - } - } - - mPlan.init(N_RES, N_RES); - mInitialized = 1; // initialization complete -} - -void LLWaterSurface::generateWaterHeightField(F64 t) -{ - S32 i, j; - S32 mi, mj; // -K indices - COMPLEX plus, minus; - - if (!mInitialized) initAmplitudes(); - - for (i = 0; i < (S32)N_RES_HALF; i++) - { - mi = N_RES - i; - for (j = 0; j < (S32)N_RES ; j++) - { - mj = N_RES - j; - - const F32 cos_wt = cosf(mOmega[i][j] * t); // = cos(-mOmega[i][j] * t) - const F32 sin_wt = sinf(mOmega[i][j] * t); // = -sin(-mOmega[i][j] * t) - plus.re = mHtilda0[i][j].re * cos_wt - mHtilda0[i][j].im * sin_wt; - plus.im = mHtilda0[i][j].re * sin_wt + mHtilda0[i][j].im * cos_wt; - minus.re = mHtilda0[mi][mj].re * cos_wt - mHtilda0[mi][mj].im * sin_wt; - minus.im = -mHtilda0[mi][mj].re * sin_wt - mHtilda0[mi][mj].im * cos_wt; - - // now sum the plus and minus waves to get the total wave amplitude h - mHtilda[i * N_RES + j].re = plus.re + minus.re; - mHtilda[i * N_RES + j].im = plus.im + minus.im; - if (mi < (S32)N_RES && mj < (S32)N_RES) - { - mHtilda[mi * N_RES + mj].re = plus.re + minus.re; - mHtilda[mi * N_RES + mj].im = -plus.im - minus.im; - } - } - } - - inverse_fft(mPlan, mHtilda, N_RES, N_RES); - - calcNormals(); -} - - -/* - * Computer normals by taking finite differences. - */ - -void LLWaterSurface::calcNormals() -{ - LLVector3 n; - - for (U32 i = 0; i < N_RES; i++) - { - for (U32 j = 0; j < N_RES; j++) - { - F32 px = heightWrapped(i + 1, j); - F32 mx = heightWrapped(i - 1, j); - F32 py = heightWrapped(i, j + 1); - F32 my = heightWrapped(i, j - 1); - F32 pxpy = heightWrapped(i + 1, j + 1); - F32 pxmy = heightWrapped(i + 1, j - 1); - F32 mxpy = heightWrapped(i - 1, j + 1); - F32 mxmy = heightWrapped(i - 1, j - 1); - - n.mV[VX] = -((2 * px + pxpy + pxmy) - (2 * mx + mxpy + mxmy)); - n.mV[VY] = -((2 * py + pxpy + mxpy) - (2 * my + pxmy + mxmy)); - n.mV[VZ] = 8 * WIDTH / (F32) N_RES; - n.normVec(); - - mNorms[i][j] = n; - } - } -} - -void LLVOWater::generateNewWaves(F64 time) -{ - getWaterSurface()->generateWaterHeightField(time); - sGrid->update(); -} - diff --git a/linden/indra/newview/llvowater.h b/linden/indra/newview/llvowater.h index 11dc0e5..20fda7e 100644 --- a/linden/indra/newview/llvowater.h +++ b/linden/indra/newview/llvowater.h @@ -35,195 +35,25 @@ #include "llwaterpatch.h" - const U32 N_RES = 16; //32 // number of subdivisions of wave tile const U8 WAVE_STEP = 8; -/* -#define N_DET 32 // number of subdivisions of wave tile for details - -class LLWaterDetail -{ -protected: - S32 mResolution; - LLViewerImage *mTex; - U8 *mTexData; - -public: - LLWaterDetail() : mResolution(N_DET), mTex(0), mTexData(0) {init();} - void init(); - - ~LLWaterDetail() - { - delete[] mTexData; - mTexData = NULL; - } - - - //void initEmpty(); - - void setPixel(const LLVector3 &norm, const S32 i, const S32 j) - { - S32 offset = (i * mResolution + j) * 3; - mTexData[offset] = llround(norm.mV[VX] * 255); - mTexData[offset+1] = llround(norm.mV[VX] * 255); - mTexData[offset+2] = llround(norm.mV[VX] * 255); - } - void setPixel(F32 x, F32 y, F32 z, const S32 i, const S32 j) - { - S32 offset = (i * mResolution + j) * 3; - mTexData[offset] = llround(x * 255); - mTexData[offset+1] = llround(y * 255); - mTexData[offset+2] = llround(z * 255); - } - - S32 getResolution() { return mResolution; } - - void createDetailBumpmap(F32* u, F32* v); - void createTexture() const { mTex->createTexture(); } - void bindTexture() const { mTex->bindTexture(); } - LLViewerImage* getTexture() const { return mTex; } -}; -*/ - -class LLWaterSurface -{ -protected: - BOOL mInitialized; - LLVector3 mWind; - F32 mA; - F32 mVisc; // viscosity of the fluid - F32 mShininess; - - //LLWaterDetail* mDetail; - - LLFFTPlan mPlan; - F32 mOmega[N_RES+1][N_RES+1]; // wave frequency - COMPLEX mHtilda0[N_RES+1][N_RES+1]; // wave amplitudes and phases at time 0. - LLVector3 mNorms[N_RES][N_RES]; - COMPLEX mHtilda[N_RES * N_RES]; - -public: - LLWaterSurface(); - ~LLWaterSurface() {} - - //void initSpecularLookup(); - - F32 phillips(const LLVector2& k, const LLVector2& wind_n, F32 L, F32 L_small); - - void initAmplitudes(); - - F32 height(S32 i, S32 j) const { return mHtilda[i * N_RES + j].re; } - F32 heightWrapped(S32 i, S32 j) const - { - return height((i + N_RES) % N_RES, (j + N_RES) % N_RES); - } - - void generateWaterHeightField(F64 time); - void calcNormals(); - - void getHeightAndNormal(F32 i, F32 j, F32& height, LLVector3& normal) const; - void getIntegerHeightAndNormal(S32 i, S32 j, F32& height, LLVector3& normal) const; - F32 agentDepth() const; - -// const LLWaterHeightField* hField() const { return &mHeightField; } - - //void generateDetail(F64 t); - //void fluidSolver(F32* u, F32* v, F32* u0, F32* v0, F64 dt); - - const LLVector3& getWind() const { return mWind; } - void setWind(const LLVector3& w) { mWind = w; } // initialized = 0? - F32 A() const { return mA; } - void setA(F32 a) { mA = a; } - F32 getShininess() const { return mShininess; } - //LLViewerImage* getSpecularLookup() const { return mSpecularLookup; } - //LLViewerImage* getDetail() const { return mDetail->getTexture(); } -}; - -class LLVOWater; - -class LLWaterGrid -{ -public: - LLWaterGrid(); - - void init(); - void cleanup(); - - LLWaterSurface* getWaterSurface() { return &mWater; } - - void update(); - void updateTree(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far, - BOOL restart); - void updateVisibility(const LLVector3 &camera_pos, const LLVector3 &look_at, F32 clip_far); - - LLVector3 mRegionOrigin; - - LLVector3* mVtx; - LLVector3* mNorms; - U32 mRegionWidth; - U32 mMaxGridSize; - U32 mPatchRes; - U32 mMinStep; - U32 mStepsInRegion; - LLWaterPatch* mPatches; - LLRoam mRoam; - F32 mResIncrease; - U32 mResDecrease; - - LLVOWater* mTab[5][5]; - - U32 gridDim() const { return mGridDim; } - U32 rowSize() const { return mGridDim1; } - void setGridDim(U32 gd) { mGridDim = gd; mGridDim1 = mGridDim + 1; } - U32 index(const LL2Coord& c) const { return c.y() * mGridDim1 + c.x(); } - U32 index(U32 x, U32 y) const { return y * mGridDim1 + x; } - - LLVector3 vtx(const LL2Coord& c, F32 raised) const - { - LLVector3 v = mVtx[index(c)]; - v.mV[VZ] += raised; - return v; - } - - LLVector3 vtx(U32 x, U32 y, F32 raised) const - { - LLVector3 v = mVtx[index(x, y)]; - v.mV[VZ] += raised; - return v; - } - - void setVertex(const U32 x, const U32 y, const F32 raised, LLVector3 &vertex) const - { - vertex = mVtx[index(x, y)]; - vertex.mV[VZ] += raised; - } - - void setCamPosition(LL2Coord& cam, const LLVector3& cam_pos) - { - cam.x() = llround((cam_pos.mV[VX] - mRegionOrigin.mV[VX]) / mMinStep); - cam.y() = llround((cam_pos.mV[VY] - mRegionOrigin.mV[VY]) / mMinStep); - } - - LLVector3 vtx(const LL2Coord& c) const { return mVtx[index(c)]; } - LLVector3 norm(const LL2Coord& c) const { return mNorms[index(c)]; } - LLVector3 vtx(U32 x, U32 y) const { return mVtx[index(x, y)]; } - LLVector3 norm(U32 x, U32 y) const { return mNorms[index(x, y)]; } - -protected: - LLWaterSurface mWater; - U32 mGridDim; - U32 mGridDim1; -}; - class LLSurface; class LLHeavenBody; class LLVOSky; class LLFace; -class LLVOWater : public LLViewerObject +class LLVOWater : public LLStaticViewerObject { public: + enum + { + VERTEX_DATA_MASK = (1 << LLVertexBuffer::TYPE_VERTEX) | + (1 << LLVertexBuffer::TYPE_NORMAL) | + (1 << LLVertexBuffer::TYPE_TEXCOORD) + } + eVertexDataMask; + LLVOWater(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp); virtual ~LLVOWater() {} @@ -236,24 +66,19 @@ public: /*virtual*/ BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); /*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline); /*virtual*/ BOOL updateGeometry(LLDrawable *drawable); - BOOL updateGeometryFlat(LLDrawable *drawable); - BOOL updateGeometryHeightFieldSimple(LLDrawable *drawable); - BOOL updateGeometryHeightFieldRoam(LLDrawable *drawable); + /*virtual*/ void updateSpatialExtents(LLVector3& newMin, LLVector3& newMax); - /*virtual*/ void updateDrawable(BOOL force_damped); /*virtual*/ void updateTextures(LLAgent &agent); /*virtual*/ void setPixelAreaAndAngle(LLAgent &agent); // generate accurate apparent angle and area + virtual U32 getPartitionType() const; + /*virtual*/ BOOL isActive() const; // Whether this object needs to do an idleUpdate. void setUseTexture(const BOOL use_texture); - static void generateNewWaves(F64 time); - static LLWaterSurface* getWaterSurface() { return sGrid->getWaterSurface(); }//return &mWater; } - static const LLWaterGrid* getGrid() { return sGrid; } protected: BOOL mUseTexture; - static LLWaterGrid *sGrid; }; #endif // LL_VOSURFACEPATCH_H diff --git a/linden/indra/newview/llwearable.cpp b/linden/indra/newview/llwearable.cpp index 310eae5..3e3f7ab 100644 --- a/linden/indra/newview/llwearable.cpp +++ b/linden/indra/newview/llwearable.cpp @@ -34,11 +34,13 @@ #include "llquantize.h" #include "llagent.h" +#include "llassetuploadresponders.h" #include "llviewerwindow.h" #include "llfloatercustomize.h" #include "llinventorymodel.h" #include "llviewerimagelist.h" #include "llviewerinventory.h" +#include "llviewerregion.h" #include "llvoavatar.h" #include "llwearable.h" @@ -148,10 +150,10 @@ EWearableType LLWearable::typeNameToType( const LLString& type_name ) } -const char* terse_F32_to_string( F32 f, char s[MAX_STRING] ) +const char* terse_F32_to_string( F32 f, char s[MAX_STRING] ) /* Flawfinder: ignore */ { char* r = s; - S32 len = sprintf( s, "%.2f", f ); + S32 len = snprintf( s, MAX_STRING, "%.2f", f ); /* Flawfinder: ignore */ // "1.20" -> "1.2" // "24.00" -> "24." @@ -230,7 +232,7 @@ BOOL LLWearable::exportFile( FILE* file ) return FALSE; } - char s[ MAX_STRING ]; + char s[ MAX_STRING ]; /* Flawfinder: ignore */ for( F32* param_weightp = mVisualParamMap.getFirstData(); param_weightp; param_weightp = mVisualParamMap.getNextData() ) { S32 param_id = mVisualParamMap.getCurrentKeyWithoutIncrement(); @@ -250,7 +252,7 @@ BOOL LLWearable::exportFile( FILE* file ) for( LLUUID* image_id = mTEMap.getFirstData(); image_id; image_id = mTEMap.getNextData() ) { S32 te = mTEMap.getCurrentKeyWithoutIncrement(); - char image_id_string[UUID_STR_LENGTH]; + char image_id_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */ image_id->toString( image_id_string ); if( fprintf( file, "%d %s\n", te, image_id_string) < 0 ) { @@ -268,7 +270,7 @@ BOOL LLWearable::importFile( FILE* file ) // *NOTE: changing the type or size of this buffer will require // changes in the fscanf() code below. You would be better off // rewriting this to use streams and not require an open FILE. - char text_buffer[2048]; + char text_buffer[2048]; /* Flawfinder: ignore */ S32 fields_read = 0; // read header and version @@ -289,7 +291,7 @@ BOOL LLWearable::importFile( FILE* file ) } // name - char next_char = fgetc( file ); + char next_char = fgetc( file ); /* Flawfinder: ignore */ if( '\n' == next_char ) { // no name @@ -298,8 +300,11 @@ BOOL LLWearable::importFile( FILE* file ) else { ungetc( next_char, file ); - fields_read = fscanf( file, "%2047[^\n]", text_buffer ); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) + fields_read = fscanf( /* Flawfinder: ignore */ + file, + "%2047[^\n]", + text_buffer); + if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ { llwarns << "Bad Wearable asset: early end of file" << llendl; return FALSE; @@ -309,7 +314,7 @@ BOOL LLWearable::importFile( FILE* file ) } // description - next_char = fgetc( file ); + next_char = fgetc( file ); /* Flawfinder: ignore */ if( '\n' == next_char ) { // no description @@ -318,8 +323,11 @@ BOOL LLWearable::importFile( FILE* file ) else { ungetc( next_char, file ); - fields_read = fscanf( file, "%2047[^\n]", text_buffer ); - if( (1 != fields_read) || (fgetc( file ) != '\n') ) + fields_read = fscanf( /* Flawfinder: ignore */ + file, + "%2047[^\n]", + text_buffer ); + if( (1 != fields_read) || (fgetc( file ) != '\n') ) /* Flawfinder: ignore */ { llwarns << "Bad Wearable asset: early end of file" << llendl; return FALSE; @@ -425,7 +433,10 @@ BOOL LLWearable::importFile( FILE* file ) for( i = 0; i < num_textures; i++ ) { S32 te = 0; - fields_read = fscanf( file, "%d %2047s\n", &te, text_buffer); + fields_read = fscanf( /* Flawfinder: ignore */ + file, + "%d %2047s\n", + &te, text_buffer); if( fields_read != 2 ) { llwarns << "Bad Wearable asset: bad texture, #" << i << llendl; @@ -863,11 +874,11 @@ void LLWearable::saveNewAsset() // llinfos << "LLWearable::saveNewAsset() type: " << getTypeName() << llendl; //dump(); - char new_asset_id_string[UUID_STR_LENGTH]; + char new_asset_id_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */ mAssetID.toString(new_asset_id_string); - char filename[LL_MAX_PATH]; - sprintf(filename, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str()); - FILE* fp = LLFile::fopen(filename, "wb"); + char filename[LL_MAX_PATH]; /* Flawfinder: ignore */ + snprintf(filename, LL_MAX_PATH, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str()); /* Flawfinder: ignore */ + FILE* fp = LLFile::fopen(filename, "wb"); /* Flawfinder: ignore */ BOOL successful_save = FALSE; if(fp && exportFile(fp)) { @@ -880,8 +891,9 @@ void LLWearable::saveNewAsset() } if(!successful_save) { - char buffer[2*MAX_STRING]; - sprintf(buffer, + char buffer[2*MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, /* Flawfinder: ignore */ + sizeof(buffer), "Unable to save '%s' to wearable file.", mName.c_str()); llwarns << buffer << llendl; @@ -895,11 +907,28 @@ void LLWearable::saveNewAsset() // save it out to database if( gAssetStorage ) { - LLWearableSaveData* data = new LLWearableSaveData; - data->mType = mType; - gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), - &LLWearable::onSaveNewAssetComplete, - (void*)data); + /* + std::string url = gAgent.getRegion()->getCapability("NewAgentInventory"); + if (!url.empty()) + { + llinfos << "Update Agent Inventory via capability" << llendl; + LLSD body; + body["folder_id"] = gInventory.findCategoryUUIDForType(getAssetType()); + body["asset_type"] = LLAssetType::lookup(getAssetType()); + body["inventory_type"] = LLInventoryType::lookup(LLInventoryType::IT_WEARABLE); + body["name"] = getName(); + body["description"] = getDescription(); + LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, filename)); + } + else + { + } + */ + LLWearableSaveData* data = new LLWearableSaveData; + data->mType = mType; + gAssetStorage->storeAssetData(filename, mTransactionID, getAssetType(), + &LLWearable::onSaveNewAssetComplete, + (void*)data); } } @@ -915,8 +944,9 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda } else { - char buffer[2*MAX_STRING]; - sprintf(buffer, + char buffer[2*MAX_STRING]; /* Flawfinder: ignore */ + snprintf(buffer, /* Flawfinder: ignore */ + sizeof(buffer), "Unable to save %s to central asset store.", type_name); llwarns << buffer << " Status: " << status << llendl; @@ -926,10 +956,10 @@ void LLWearable::onSaveNewAssetComplete(const LLUUID& new_asset_id, void* userda } // Delete temp file - char new_asset_id_string[UUID_STR_LENGTH]; + char new_asset_id_string[UUID_STR_LENGTH]; /* Flawfinder: ignore */ new_asset_id.toString(new_asset_id_string); - char src_filename[LL_MAX_PATH]; - sprintf(src_filename, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str()); + char src_filename[LL_MAX_PATH]; /* Flawfinder: ignore */ + snprintf(src_filename, LL_MAX_PATH, "%s.wbl", gDirUtilp->getExpandedFilename(LL_PATH_CACHE,new_asset_id_string).c_str()); /* Flawfinder: ignore */ LLFile::remove(src_filename); // delete the context data diff --git a/linden/indra/newview/llwearablelist.cpp b/linden/indra/newview/llwearablelist.cpp index 28af5eb..10079f8 100644 --- a/linden/indra/newview/llwearablelist.cpp +++ b/linden/indra/newview/llwearablelist.cpp @@ -105,7 +105,7 @@ void LLWearableList::processGetAssetReply( const char* filename, const LLAssetID if( status >= 0 ) { // read the file - FILE* fp = LLFile::fopen(filename, "rb"); + FILE* fp = LLFile::fopen(filename, "rb"); /*Flawfinder: ignore*/ if( !fp ) { llinfos << "Bad Wearable Asset: unable to open file: '" << filename << "'" << llendl; diff --git a/linden/indra/newview/llwebbrowserctrl.cpp b/linden/indra/newview/llwebbrowserctrl.cpp index 6d1ee28..7df2da4 100644 --- a/linden/indra/newview/llwebbrowserctrl.cpp +++ b/linden/indra/newview/llwebbrowserctrl.cpp @@ -45,15 +45,32 @@ const S32 MAX_TEXTURE_DIMENSION = 2048; LLWebBrowserCtrl::LLWebBrowserCtrl( const std::string& name, const LLRect& rect ) : LLUICtrl( name, rect, FALSE, NULL, NULL ), - mEmbeddedBrowserWindowId( 0 ), mTextureDepthBytes( 4 ), - mBorder( 0 ), + mEmbeddedBrowserWindowId( 0 ), + mBorder(NULL), mFrequentUpdates( true ), mOpenLinksInExternalBrowser( false ), - mHomePageUrl( "" ) + mHomePageUrl( "" ), + mIgnoreUIScale( true ) { + S32 screen_width = mIgnoreUIScale ? llround((F32)mRect.getWidth() * LLUI::sGLScaleFactor.mV[VX]) : mRect.getWidth(); + S32 screen_height = mIgnoreUIScale ? llround((F32)mRect.getHeight() * LLUI::sGLScaleFactor.mV[VY]) : mRect.getHeight(); + // create a new browser window - mEmbeddedBrowserWindowId = LLMozLib::getInstance()->createBrowserWindow( gViewerWindow->getPlatformWindow(), mRect.getWidth(), mRect.getHeight() ); + { +#if LL_LINUX + // Yuck, Mozilla init plays with the locale - push/pop + // the locale to protect it, as exotic/non-C locales + // causes our code lots of general critical weirdness + // and crashness. (SL-35450) + char *saved_locale = setlocale(LC_ALL, NULL); +#endif // LL_LINUX + mEmbeddedBrowserWindowId = LLMozLib::getInstance()->createBrowserWindow( gViewerWindow->getPlatformWindow(), screen_width, screen_height ); +#if LL_LINUX + if (saved_locale) + setlocale(LC_ALL, saved_locale); +#endif // LL_LINUX + } // change color to black so transisitons aren't so noticable (this should be in XML eventually) LLMozLib::getInstance()->setBackgroundColor( mEmbeddedBrowserWindowId, 0x00, 0x00, 0x00 ); @@ -62,7 +79,7 @@ LLWebBrowserCtrl::LLWebBrowserCtrl( const std::string& name, const LLRect& rect LLMozLib::getInstance()->addObserver( mEmbeddedBrowserWindowId, this ); // create a new texture (based on LLDynamic texture) that will be used to display the output - mWebBrowserImage = new LLWebBrowserTexture( mRect.getWidth(), mRect.getHeight(), this, mEmbeddedBrowserWindowId ); + mWebBrowserImage = new LLWebBrowserTexture( screen_width, screen_height, this, mEmbeddedBrowserWindowId ); LLRect border_rect( 0, mRect.getHeight() + 2, mRect.getWidth() + 2, 0 ); mBorder = new LLViewBorder( "web control border", border_rect, LLViewBorder::BEVEL_IN ); @@ -119,7 +136,8 @@ void LLWebBrowserCtrl::setOpenInExternalBrowser( bool valIn ) // BOOL LLWebBrowserCtrl::handleHover( S32 x, S32 y, MASK mask ) { - LLMozLib::getInstance()->mouseMove( mEmbeddedBrowserWindowId, x, mRect.getHeight() - y ); + convertInputCoords(x, y); + LLMozLib::getInstance()->mouseMove( mEmbeddedBrowserWindowId, x, y ); return TRUE; } @@ -142,7 +160,8 @@ BOOL LLWebBrowserCtrl::handleScrollWheel( S32 x, S32 y, S32 clicks ) // BOOL LLWebBrowserCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) { - LLMozLib::getInstance()->mouseUp( mEmbeddedBrowserWindowId, x, mRect.getHeight() - y ); + convertInputCoords(x, y); + LLMozLib::getInstance()->mouseUp( mEmbeddedBrowserWindowId, x, y ); gViewerWindow->setMouseCapture( 0, 0 ); @@ -153,7 +172,8 @@ BOOL LLWebBrowserCtrl::handleMouseUp( S32 x, S32 y, MASK mask ) // BOOL LLWebBrowserCtrl::handleMouseDown( S32 x, S32 y, MASK mask ) { - LLMozLib::getInstance()->mouseDown( mEmbeddedBrowserWindowId, x, mRect.getHeight() - y ); + convertInputCoords(x, y); + LLMozLib::getInstance()->mouseDown( mEmbeddedBrowserWindowId, x, y ); gViewerWindow->setMouseCapture( this, 0 ); @@ -184,9 +204,67 @@ void LLWebBrowserCtrl::onFocusLost() // BOOL LLWebBrowserCtrl::handleKey( KEY key, MASK mask, BOOL called_from_parent ) { - LLMozLib::getInstance()->keyPress( mEmbeddedBrowserWindowId, key ); + unsigned long nskey; + + // First, turn SL internal keycode enum into Mozilla keycode enum + + // We don't have to deal with printable characters here - they should + // go through handleUnicodeChar(). This table could be more complete + // than it is, but I think this covers all of the important + // non-printables. + switch (key) + { + case KEY_BACKSPACE: + nskey = LL_DOM_VK_BACK_SPACE; break; + case KEY_TAB: + nskey = LL_DOM_VK_TAB; break; + case KEY_RETURN: + nskey = LL_DOM_VK_RETURN; break; + case KEY_PAD_RETURN: + nskey = LL_DOM_VK_ENTER; break; + case KEY_ESCAPE: + nskey = LL_DOM_VK_ESCAPE; break; + case KEY_PAGE_UP: + nskey = LL_DOM_VK_PAGE_UP; break; + case KEY_PAGE_DOWN: + nskey = LL_DOM_VK_PAGE_DOWN; break; + case KEY_END: + nskey = LL_DOM_VK_END; break; + case KEY_HOME: + nskey = LL_DOM_VK_HOME; break; + case KEY_LEFT: + nskey = LL_DOM_VK_LEFT; break; + case KEY_UP: + nskey = LL_DOM_VK_UP; break; + case KEY_RIGHT: + nskey = LL_DOM_VK_RIGHT; break; + case KEY_DOWN: + nskey = LL_DOM_VK_DOWN; break; + case KEY_INSERT: + nskey = LL_DOM_VK_INSERT; break; + case KEY_DELETE: + nskey = LL_DOM_VK_DELETE; break; + default: + llinfos << "Don't know how to map LL keycode " << U32(key) + << " to DOM key. Ignoring." << llendl; + return FALSE; // don't know how to map this key. + } - return FALSE; + LLMozLib::getInstance()->keyPress( mEmbeddedBrowserWindowId, nskey ); + + return TRUE; +} + +BOOL LLWebBrowserCtrl::handleUnicodeChar(llwchar uni_char, BOOL called_from_parent) +{ + // only accept 'printable' characters, sigh... + if (uni_char >= 32 // discard 'control' characters + && uni_char != 127) // SDL thinks this is 'delete' - yuck. + { + LLMozLib::getInstance()->unicodeInput( mEmbeddedBrowserWindowId, uni_char ); + } + + return TRUE; } //////////////////////////////////////////////////////////////////////////////// @@ -208,9 +286,13 @@ void LLWebBrowserCtrl::onVisibilityChange ( BOOL curVisibilityIn ) // void LLWebBrowserCtrl::reshape( S32 width, S32 height, BOOL called_from_parent ) { + S32 screen_width = mIgnoreUIScale ? llround((F32)width * LLUI::sGLScaleFactor.mV[VX]) : width; + S32 screen_height = mIgnoreUIScale ? llround((F32)height * LLUI::sGLScaleFactor.mV[VX]) : height; // when floater is minimized, these sizes are negative - if ( height > 0 && width > 0 ) - mWebBrowserImage->resize( width, height ); + if ( screen_height > 0 && screen_width > 0 ) + { + mWebBrowserImage->resize( screen_width, screen_height ); + } LLUICtrl::reshape( width, height, called_from_parent ); } @@ -310,38 +392,60 @@ void LLWebBrowserCtrl::draw() LLGLSUIDefault gls_ui; LLGLDisable gls_alphaTest( GL_ALPHA_TEST ); - // scale texture to fit the space using texture coords - mWebBrowserImage->bindTexture(); - glColor4fv( LLColor4::white.mV ); - F32 max_u = ( F32 )mWebBrowserImage->getBrowserWidth() / ( F32 )mWebBrowserImage->getWidth(); - F32 max_v = ( F32 )mWebBrowserImage->getBrowserHeight() / ( F32 )mWebBrowserImage->getHeight(); - - // draw the browser - glBlendFunc( GL_ONE, GL_ZERO ); - glBegin( GL_QUADS ); + glPushMatrix(); { - glTexCoord2f( max_u, 0.f ); - glVertex2i( mRect.getWidth(), mRect.getHeight() ); + if (mIgnoreUIScale) + { + glLoadIdentity(); + // font system stores true screen origin, need to scale this by UI scale factor + // to get render origin for this view (with unit scale) + glTranslatef(floorf(LLFontGL::sCurOrigin.mX * LLUI::sGLScaleFactor.mV[VX]), + floorf(LLFontGL::sCurOrigin.mY * LLUI::sGLScaleFactor.mV[VY]), + LLFontGL::sCurOrigin.mZ); + } + + // scale texture to fit the space using texture coords + mWebBrowserImage->bindTexture(); + glColor4fv( LLColor4::white.mV ); + F32 max_u = ( F32 )mWebBrowserImage->getBrowserWidth() / ( F32 )mWebBrowserImage->getWidth(); + F32 max_v = ( F32 )mWebBrowserImage->getBrowserHeight() / ( F32 )mWebBrowserImage->getHeight(); + + // draw the browser + glBlendFunc( GL_ONE, GL_ZERO ); + glBegin( GL_QUADS ); + { + // render using web browser reported width and height, instead of trying to invert GL scale + glTexCoord2f( max_u, 0.f ); + glVertex2i( mWebBrowserImage->getBrowserWidth(), mWebBrowserImage->getBrowserHeight() ); - glTexCoord2f( 0.f, 0.f ); - glVertex2i( 0, mRect.getHeight() ); + glTexCoord2f( 0.f, 0.f ); + glVertex2i( 0, mWebBrowserImage->getBrowserHeight() ); - glTexCoord2f( 0.f, max_v ); - glVertex2i( 0, 0 ); + glTexCoord2f( 0.f, max_v ); + glVertex2i( 0, 0 ); - glTexCoord2f( max_u, max_v ); - glVertex2i( mRect.getWidth(), 0 ); + glTexCoord2f( max_u, max_v ); + glVertex2i( mWebBrowserImage->getBrowserWidth(), 0 ); + } + glEnd(); + glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); } - glEnd(); - glBlendFunc( GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA ); + glPopMatrix(); // highlight if keyboard focus here. (TODO: this needs some work) if ( mBorder->getVisible() ) mBorder->setKeyboardFocusHighlight( gFocusMgr.childHasKeyboardFocus( this ) ); + LLUICtrl::draw(); } +void LLWebBrowserCtrl::convertInputCoords(S32& x, S32& y) +{ + x = mIgnoreUIScale ? llround((F32)x * LLUI::sGLScaleFactor.mV[VX]) : x; + y = mIgnoreUIScale ? llround((F32)(mRect.getHeight() - y) * LLUI::sGLScaleFactor.mV[VY]) : (mRect.getHeight() - y); +} + //////////////////////////////////////////////////////////////////////////////// // virtual void LLWebBrowserCtrl::onNavigateBegin( const EventType& eventIn ) @@ -551,6 +655,8 @@ void LLWebBrowserTexture::resize( S32 new_width, S32 new_height ) if ( actual_rowspan < 1 || browser_depth < 2 ) return; + releaseGLTexture(); + S32 pagebuffer_width = actual_rowspan / browser_depth; // calculate the next power of 2 bigger than reqquested size for width and height @@ -635,6 +741,10 @@ LLView* LLWebBrowserCtrl::fromXML(LLXMLNodePtr node, LLView *parent, LLUICtrlFac LLWebBrowserCtrl* web_browser = new LLWebBrowserCtrl( name, rect ); + BOOL ignore_ui_scale = web_browser->getIgnoreUIScale(); + node->getAttributeBOOL("ignore_ui_scale", ignore_ui_scale); + web_browser->setIgnoreUIScale((bool)ignore_ui_scale); + web_browser->initFromXML(node, parent); web_browser->setHomePageUrl( start_url ); diff --git a/linden/indra/newview/llwebbrowserctrl.h b/linden/indra/newview/llwebbrowserctrl.h index bad6e88..e6f9005 100644 --- a/linden/indra/newview/llwebbrowserctrl.h +++ b/linden/indra/newview/llwebbrowserctrl.h @@ -192,8 +192,12 @@ class LLWebBrowserCtrl : bool getFrequentUpdates() { return mFrequentUpdates; }; void setFrequentUpdates( bool frequentUpdatesIn ) { mFrequentUpdates = frequentUpdatesIn; }; + void setIgnoreUIScale(bool ignore) { mIgnoreUIScale = ignore; } + bool getIgnoreUIScale() { return mIgnoreUIScale; } + // over-rides virtual BOOL handleKey( KEY key, MASK mask, BOOL called_from_parent ); + virtual BOOL handleUnicodeChar(llwchar uni_char, BOOL called_from_parent); virtual void reshape( S32 width, S32 height, BOOL called_from_parent ); virtual void draw(); virtual void onVisibilityChange ( BOOL curVisibilityIn ); @@ -214,6 +218,9 @@ class LLWebBrowserCtrl : virtual void onLocationChange( const EventType& eventIn ); virtual void onClickLinkHref( const EventType& eventIn ); virtual void onClickLinkSecondLife( const EventType& eventIn ); + + protected: + void convertInputCoords(S32& x, S32& y); private: LLWebBrowserCtrlEventEmitter< LLWebBrowserCtrlObserver > mEventEmitter; @@ -224,6 +231,7 @@ class LLWebBrowserCtrl : bool mFrequentUpdates; bool mOpenLinksInExternalBrowser; std::string mHomePageUrl; + bool mIgnoreUIScale; }; //////////////////////////////////////////////////////////////////////////////// diff --git a/linden/indra/newview/llworld.cpp b/linden/indra/newview/llworld.cpp index 18d4e48..cf85eab 100644 --- a/linden/indra/newview/llworld.cpp +++ b/linden/indra/newview/llworld.cpp @@ -62,7 +62,6 @@ U32 gAgentPauseSerialNum = 0; // Constants // const S32 MAX_NUMBER_OF_CLOUDS = 750; -const F32 MIN_IDLE_UPDATE_TIME = 0.025f; const S32 WORLD_PATCH_SIZE = 16; extern LLColor4U MAX_WATER_COLOR; @@ -82,7 +81,6 @@ LLWorld::LLWorld(const U32 grids_per_region, const F32 meters_per_grid) mLastPacketsOut = 0; mLastPacketsLost = 0; mLandFarClip = DEFAULT_FAR_PLANE; - mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; if (gNoRender) { @@ -635,31 +633,22 @@ void LLWorld::updateVisibilities() gCamera->setFar(cur_far_clip); } - -void LLWorld::updateRegions() +void LLWorld::updateRegions(F32 max_update_time) { LLViewerRegion *regionp; LLTimer update_timer; - + BOOL did_one = FALSE; + // Perform idle time updates for the regions (and associated surfaces) for (regionp = mRegionList.getFirstData(); regionp; regionp = mRegionList.getNextData()) { - update_timer.reset(); - if (!regionp->idleUpdate(update_timer, mIdleUpdateTime)) - { - // Didn't finish all the updates. Slightly increase the idle update time. - mIdleUpdateTime *= 1.05f; - } - else - { - mIdleUpdateTime *= 0.9f; - if (mIdleUpdateTime < MIN_IDLE_UPDATE_TIME) - { - mIdleUpdateTime = MIN_IDLE_UPDATE_TIME; - } - } + F32 max_time = max_update_time - update_timer.getElapsedTimeF32(); + if (did_one && max_time <= 0.f) + break; + max_time = llmin(max_time, max_update_time*.1f); + did_one |= regionp->idleUpdate(max_update_time); } } diff --git a/linden/indra/newview/llworld.h b/linden/indra/newview/llworld.h index 6645b94..b10b287 100644 --- a/linden/indra/newview/llworld.h +++ b/linden/indra/newview/llworld.h @@ -114,7 +114,7 @@ public: F32 getRegionMinHeight() const { return -mWidthInMeters; } F32 getRegionMaxHeight() const { return 3.f*mWidthInMeters; } - void updateRegions(); + void updateRegions(F32 max_update_time); void updateVisibilities(); void updateParticles(); void updateClouds(const F32 dt); @@ -159,7 +159,6 @@ private: const F32 mWidthInMeters; F32 mLandFarClip; // Far clip distance for land. - F32 mIdleUpdateTime; LLPatchVertexArray mLandPatch; S32 mLastPacketsIn; S32 mLastPacketsOut; diff --git a/linden/indra/newview/llworldmap.cpp b/linden/indra/newview/llworldmap.cpp index 6e010f7..0bdab0d 100644 --- a/linden/indra/newview/llworldmap.cpp +++ b/linden/indra/newview/llworldmap.cpp @@ -266,7 +266,6 @@ void LLWorldMap::setCurrentLayer(S32 layer, bool request_layer) if (!mMapLoaded[layer] || request_layer) { sendMapLayerRequest(); - sendItemRequest(MAP_ITEM_AGENT_COUNT); } if (mTelehubs.size() == 0 || @@ -506,8 +505,8 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) { U16 x_regions; U16 y_regions; - char name[MAX_STRING]; - U8 access; + char name[MAX_STRING]; /* Flawfinder: ignore */ + U8 access; /* Flawfinder: ignore */ U32 region_flags; U8 water_height; U8 agents; @@ -515,7 +514,7 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) msg->getU16Fast(_PREHASH_Data, _PREHASH_X, x_regions, block); msg->getU16Fast(_PREHASH_Data, _PREHASH_Y, y_regions, block); msg->getStringFast(_PREHASH_Data, _PREHASH_Name, MAX_STRING, name, block); - msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, access, block); + msg->getU8Fast(_PREHASH_Data, _PREHASH_Access, access, block); /* Flawfinder: ignore */ msg->getU32Fast(_PREHASH_Data, _PREHASH_RegionFlags, region_flags, block); msg->getU8Fast(_PREHASH_Data, _PREHASH_WaterHeight, water_height, block); msg->getU8Fast(_PREHASH_Data, _PREHASH_Agents, agents, block); @@ -564,7 +563,7 @@ void LLWorldMap::processMapBlockReply(LLMessageSystem* msg, void**) siminfo->mHandle = handle; siminfo->mName.assign( name ); - siminfo->mAccess = access; + siminfo->mAccess = access; /* Flawfinder: ignore */ siminfo->mRegionFlags = region_flags; siminfo->mWaterHeight = (F32) water_height; siminfo->mMapImageID[agent_flags] = image_id; @@ -621,7 +620,7 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) for (S32 block=0; blockgetU32Fast(_PREHASH_Data, _PREHASH_X, X, block); @@ -671,7 +670,7 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) case MAP_ITEM_PG_EVENT: // events case MAP_ITEM_MATURE_EVENT: { - char buffer[32]; + char buffer[32]; /* Flawfinder: ignore */ struct tm* timep; // Convert to Pacific, based on server's opinion of whether // it's daylight savings time there. @@ -680,7 +679,7 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) S32 display_hour = timep->tm_hour % 12; if (display_hour == 0) display_hour = 12; - sprintf(buffer, "%d:%02d %s", + snprintf(buffer, sizeof(buffer), "%d:%02d %s", /* Flawfinder: ignore */ display_hour, timep->tm_min, (timep->tm_hour < 12 ? "AM" : "PM") ); @@ -717,12 +716,6 @@ void LLWorldMap::processMapItemReply(LLMessageSystem* msg, void**) gWorldMap->mClassifieds.push_back(new_item); break; } - case MAP_ITEM_AGENT_COUNT: // agent counts - { - // We only ever receive one per region, i.e. this update superceeds any others - gWorldMap->mNumAgents[new_item.mRegionHandle] = new_item.mExtra; - break; - } case MAP_ITEM_AGENT_LOCATIONS: // agent locations { if (!siminfo) diff --git a/linden/indra/newview/llworldmapview.cpp b/linden/indra/newview/llworldmapview.cpp index 83e10d9..65a084d 100644 --- a/linden/indra/newview/llworldmapview.cpp +++ b/linden/indra/newview/llworldmapview.cpp @@ -167,8 +167,7 @@ LLWorldMapView::LLWorldMapView(const std::string& name, const LLRect& rect ) mMouseDownPanY( 0 ), mMouseDownX( 0 ), mMouseDownY( 0 ), - mSelectIDStart(0), - mAgentCountsUpdateTime(0) + mSelectIDStart(0) { sPixelsPerMeter = gMapScale / REGION_WIDTH_METERS; clearLastClick(); @@ -298,12 +297,6 @@ void LLWorldMapView::draw() F64 current_time = LLTimer::getElapsedSeconds(); - if (current_time - mAgentCountsUpdateTime > AGENT_COUNTS_UPDATE_TIME) - { - gWorldMap->sendItemRequest(MAP_ITEM_AGENT_COUNT); - mAgentCountsUpdateTime = current_time; - } - mVisibleRegions.clear(); // animate pan if necessary @@ -324,7 +317,6 @@ void LLWorldMapView::draw() { LLGLSNoTexture no_texture; - glMatrixMode(GL_MODELVIEW); // Clear the background alpha to 0 @@ -388,14 +380,12 @@ void LLWorldMapView::draw() current_image->setBoostLevel(LLViewerImage::BOOST_MAP_LAYER); current_image->setKnownDrawSize(llround(pix_width), llround(pix_height)); -#if 1 || LL_RELEASE_FOR_DOWNLOAD if (!current_image->getHasGLTexture()) { continue; // better to draw nothing than the default image } -#endif - LLTextureView::addDebugImage(current_image); +// LLTextureView::addDebugImage(current_image); // Draw using the texture. If we don't clamp we get artifact at // the edge. @@ -548,7 +538,7 @@ void LLWorldMapView::draw() overlayimage->setKnownDrawSize(draw_size, draw_size); } - LLTextureView::addDebugImage(simimage); +// LLTextureView::addDebugImage(simimage); if (sim_visible && info->mAlpha > 0.001f) { @@ -640,7 +630,7 @@ void LLWorldMapView::draw() // Draw the region name in the lower left corner LLFontGL* font = LLFontGL::sSansSerifSmall; - char mesg[MAX_STRING]; + char mesg[MAX_STRING]; /* Flawfinder: ignore */ if (gMapScale < sThresholdA) { mesg[0] = '\0'; @@ -658,11 +648,11 @@ void LLWorldMapView::draw() // LLViewerRegion::accessToShortString(info->mAccess) ); if (info->mAccess == SIM_ACCESS_DOWN) { - sprintf(mesg, "%s (Offline)", info->mName.c_str()); + snprintf(mesg, MAX_STRING, "%s (Offline)", info->mName.c_str()); /* Flawfinder: ignore */ } else { - sprintf(mesg, "%s", info->mName.c_str()); + snprintf(mesg, MAX_STRING, "%s", info->mName.c_str()); /* Flawfinder: ignore */ } } @@ -841,6 +831,39 @@ void LLWorldMapView::draw() updateVisibleBlocks(); } +//virtual +void LLWorldMapView::setVisible(BOOL visible) +{ + LLPanel::setVisible(visible); + if (!visible && gWorldMap) + { + for (S32 map = 0; map < MAP_SIM_IMAGE_TYPES; map++) + { + for (U32 layer_idx=0; layer_idxmMapLayers[map].size(); ++layer_idx) + { + if (gWorldMap->mMapLayers[map][layer_idx].LayerDefined) + { + LLWorldMapLayer *layer = &gWorldMap->mMapLayers[map][layer_idx]; + layer->LayerImage->setBoostLevel(0); + } + } + } + for (LLWorldMap::sim_info_map_t::iterator it = gWorldMap->mSimInfoMap.begin(); + it != gWorldMap->mSimInfoMap.end(); ++it) + { + LLSimInfo* info = (*it).second; + if (info->mCurrentImage.notNull()) + { + info->mCurrentImage->setBoostLevel(0); + } + if (info->mOverlayImage.notNull()) + { + info->mOverlayImage->setBoostLevel(0); + } + } + } +} + void LLWorldMapView::drawGenericItems(const LLWorldMap::item_info_list_t& items, LLPointer image) { LLWorldMap::item_info_list_t::const_iterator e; @@ -1912,7 +1935,7 @@ BOOL LLWorldMapView::handleDoubleClick( S32 x, S32 y, MASK mask ) { gFloaterWorldMap->close(); // This is an ungainly hack - char uuid_str[38]; + char uuid_str[38]; /* Flawfinder: ignore */ S32 event_id; id.toString(uuid_str); sscanf(&uuid_str[28], "%X", &event_id); diff --git a/linden/indra/newview/llworldmapview.h b/linden/indra/newview/llworldmapview.h index 5c18aab..f2912bd 100644 --- a/linden/indra/newview/llworldmapview.h +++ b/linden/indra/newview/llworldmapview.h @@ -52,8 +52,9 @@ class LLTextBox; #define SIM_MAP_AGENT_SCALE 20 // width in pixels, where we start drawing agents #define SIM_MAP_SCALE 90 // width in pixels, where we start drawing sim tiles +// Updates for agent locations. #define AGENTS_UPDATE_TIME 60.0 // in seconds -#define AGENT_COUNTS_UPDATE_TIME 60.0 // in seconds + class LLWorldMapView : public LLPanel { @@ -65,12 +66,13 @@ public: virtual ~LLWorldMapView(); virtual void reshape(S32 width, S32 height, BOOL called_from_parent = TRUE ); + virtual void setVisible(BOOL visible); virtual BOOL handleMouseDown(S32 x, S32 y, MASK mask); virtual BOOL handleMouseUp(S32 x, S32 y, MASK mask); virtual BOOL handleDoubleClick( S32 x, S32 y, MASK mask ); virtual BOOL handleHover( S32 x, S32 y, MASK mask ); - /*virtual*/ BOOL handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen ); + virtual BOOL handleToolTip( S32 x, S32 y, LLString& msg, LLRect* sticky_rect_screen ); bool checkItemHit(S32 x, S32 y, LLItemInfo& item, LLUUID* id, bool track); void handleClick(S32 x, S32 y, MASK mask, S32* hit_type, LLUUID* id); @@ -183,7 +185,6 @@ public: static BOOL sHandledLastClick; S32 mSelectIDStart; - F64 mAgentCountsUpdateTime; typedef std::vector handle_list_t; handle_list_t mVisibleRegions; // set every frame diff --git a/linden/indra/newview/llxmlrpctransaction.cpp b/linden/indra/newview/llxmlrpctransaction.cpp index 9b8a872..d84f5c6 100644 --- a/linden/indra/newview/llxmlrpctransaction.cpp +++ b/linden/indra/newview/llxmlrpctransaction.cpp @@ -155,7 +155,7 @@ public: std::string mStatusMessage; std::string mStatusURI; - char mCurlErrorBuffer[CURL_ERROR_SIZE]; + char mCurlErrorBuffer[CURL_ERROR_SIZE]; /* Flawfinder: ignore */ std::string mURI; char* mRequestText; @@ -343,9 +343,9 @@ bool LLXMLRPCTransaction::Impl::process() if (curl_msg->data.result != CURLE_OK) { setCurlStatus(curl_msg->data.result); - llalerts << "LLXMLRPCTransaction CURL error " + llwarns << "LLXMLRPCTransaction CURL error " << mCurlCode << ": " << mCurlErrorBuffer << llendl; - llalerts << "LLXMLRPCTransaction request URI: " + llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; return true; @@ -379,11 +379,11 @@ bool LLXMLRPCTransaction::Impl::process() { setStatus(LLXMLRPCTransaction::StatusXMLRPCError); - llalerts << "LLXMLRPCTransaction XMLRPC " + llwarns << "LLXMLRPCTransaction XMLRPC " << (hasError ? "error " : "fault ") << faultCode << ": " << faultString << llendl; - llalerts << "LLXMLRPCTransaction request URI: " + llwarns << "LLXMLRPCTransaction request URI: " << mURI << llendl; } @@ -427,9 +427,9 @@ void LLXMLRPCTransaction::Impl::setStatus(Status status, mStatusMessage = "Despite our best efforts, something unexpected has gone wrong. \n" " \n" - "Please check www.secondlife.com/status and the Second Life \n" - "Announcements forum to see if there is a known problem with \n" - "the service."; + "Please check www.secondlife.com/status \n" + "to see if there is a known problem with the service."; + mStatusURI = "http://secondlife.com/status/"; /* mStatusMessage = diff --git a/linden/indra/newview/lsl_guide.html b/linden/indra/newview/lsl_guide.html index e0faf7b..6f3796f 100644 --- a/linden/indra/newview/lsl_guide.html +++ b/linden/indra/newview/lsl_guide.html @@ -58,7 +58,7 @@ NAME="AEN16" >Donald KjerCopyright © 2007 Linden Lab

    A.234. llSetLocalRotllSetLinkPrimitiveParams
    A.235. llSetObjectDescllSetLinkTexture
    A.236. llSetObjectNamellSetLocalRot
    A.237. llSetParcelMusicURLllSetObjectDesc
    A.238. llSetPayPricellSetObjectName
    A.239. llSetPosllSetParcelMusicURL
    A.240. llSetPrimitiveParamsllSetPayPrice
    A.241. llSetRemoteScriptAccessPinllSetPos
    A.242. llSetRotllSetPrimitiveParams
    A.243. llSetScalellSetRemoteScriptAccessPin
    A.244. llSetScriptStatellSetRot
    A.245. llSetSitTextllSetScale
    A.246. llSetSoundQueueingllSetScriptState
    A.247. llSetStatusllSetSitText
    A.248. llSetTextllSetSoundQueueing
    A.249. llSetTexturellSetStatus
    A.250. llSetTextureAnimllSetText
    A.251. llSetTimerEventllSetTexture
    A.252. llSetTorquellSetTextureAnim
    A.253. llSetTouchTextllSetTimerEvent
    A.254. llSetVehicleFlagsllSetTorque
    A.255. llSetVehicleFloatParamllSetTouchText
    A.256. llSetVehicleTypellSetVehicleFlags
    A.257. llSetVehicleRotationParamllSetVehicleFloatParam
    A.258. llSetVehicleVectorParamllSetVehicleType
    A.259. llShoutllSetVehicleRotationParam
    A.260. llSinllSetVehicleVectorParam
    A.261. llSitTargetllShout
    A.262. llSleepllSin
    A.263. llSqrtllSitTarget
    A.264. llStartAnimationllSleep
    A.265. llStopAnimationllSqrt
    A.266. llStopHoverllStartAnimation
    A.267. llStopLookAtllStopAnimation
    A.268. llStopMoveToTargetllStopHover
    A.269. llStopPointAtllStopLookAt
    A.270. llStopSoundllStopMoveToTarget
    A.271. llStringLengthllStopPointAt
    A.272. llSubStringIndexllStopSound
    A.273. llStringToBase64llStringLength
    A.274. llTakeControlsllSubStringIndex
    A.275. llTanllStringToBase64
    A.276. llTargetllTakeControls
    A.277. llTargetOmegallTan
    A.278. llTargetRemovellTarget
    A.279. llTeleportAgentHomellTargetOmega
    A.280. llToLowerllTargetRemove
    A.281. llToUpperllTeleportAgentHome
    A.282. llTriggerSoundllToLower
    A.283. llTriggerSoundLimitedllToUpper
    A.284. llUnescapeURLllTriggerSound
    A.285. llUnSitllTriggerSoundLimited
    A.286. llVecDistllUnescapeURL
    A.287. llVecMagllUnSit
    A.288. llVecNormllVecDist
    A.289. llVolumeDetectllVecMag
    A.290. llWaterllVecNorm
    A.291. llWhisperllVolumeDetect
    A.292. llWindllWater
    A.293. llWhisper
    A.294. llWind
    A.295. llXorBase64Strings
    B. Events
    B.1. at_rot_target
    B.2. at_target
    B.3. attach
    B.4. changed
    B.5. collision
    B.6. collision_end
    B.7. collision_start
    B.8. control
    B.9. dataserver
    B.10. email
    B.11. land_collision
    B.12. land_collision_end
    B.13. land_collision_start
    B.14. link_message
    B.15. listen
    B.16. money
    B.17. moving_end
    B.18. moving_start
    B.19. no_sensor
    B.20. not_at_rot_target
    B.21. not_at_target
    B.22. object_rez
    B.23. on_rez
    B.24. run_time_permissions
    B.25. sensor
    B.26. state_entry
    B.27. state_exit
    B.28. timer
    B.29. touch
    B.30. touch_end
    B.31. touch_start
    B.32. remote_data
    C. Constants
    C.1. Boolean Constants
    C.2. Status Constants
    C.3. Object Type Constants
    C.4. Permission Constants
    C.5. Inventory Constants
    C.6. Pay Price Constants
    C.7. Attachment Constants
    C.8. Land Constants
    C.9. Link Constants
    C.10. Control Constants
    C.11. Change Constants
    C.12. Type Constants
    C.13. Agent Info Constants
    C.14. Texture Animation Constants
    C.15. Particle System Constants
    C.16. Agent Data Constants
    C.17. Float Constants
    C.18. Key Constant
    C.19. Miscellaneous Integer Constants
    C.20. Miscellaneous String Constants
    C.21. Vector Constant
    C.22. Rotation Constant
    C.23. Simulator Data Constants
    C.24. Vehicle Parameters
    C.25. Vehicle Flags
    C.26. Vehicle Types
    C.27. Primitive Constants
    C.28. XML-RPC Constants
    C.29. Permission Mask Constants
    C.30. Parcel Media Constants (Movies)

    There are many events that can be detected in your scripts by declaring a handler. The touch_start() event is raised when a @@ -3681,7 +3691,7 @@ CLASS="programlisting" non-zero integer. Once a conditional is determined to be true (non-zero), no further processing of 'else' conditionals will be considered. The NULL_KEY constant is counted as FALSE by conditional expressions.

    The state_entry event occurs whenever a new state is @@ -4107,7 +4117,7 @@ NAME="AEN440" >

    You will want to provide a state_exit() if you need to clean up any events that you have requested in the current state, but do @@ -4180,7 +4190,7 @@ state ListenState >

    The state_exit() handler is not called when an object is @@ -4318,21 +4328,21 @@ HREF="#AEN3615" >llSinllSqrtllTanllVecDistllVecMagllVecNormllStringLengthllSubStringIndexllStringToBase64llToLowerllToUpperllXorBase64StringsllShoutllWhisper

    Each scripted object can have one vehicle behavior that is configurable through the llSetVehicleType, llSetVehicleFloatParam, llSetVehicleVectorParam, llSetVehicleRotationParam, llSetVehicleFlags, and llSetForce, llSetTorque, and llMoveToTarget, and llTargetOmega at your own risk.

    Before any vehicle parameters can be set the vehicle behavior must first be enabled. It is enabled by calling llSetVehicleType with any VEHICLE_TYPE_*, except VEHICLE_TYPE_NONE which will disable the vehicle. See the vehicle type constants section for currently available types. More types @@ -5436,7 +5446,7 @@ HREF="#AEN990" of linear and/or angular deflection or not. The speed of the deflections are controlled by setting the relevant parameters using the llSetVehicleFloatParam script call. Each variety of deflection has a @@ -5495,7 +5505,7 @@ HREF="#AEN1070" to make motion smoother and easier to control. Their directions can be set using the llSetVehicleVectorParam call. For example, to make the vehicle try to move at 5 @@ -6391,7 +6401,7 @@ HREF="#AEN2773" >llLoopSound. This function Has no effect on sounds started with llTriggerSound.

    avatar at point attachment

    If an avatar is sitting on the sit target, return the avatar's key, NULL_KEY otherwise. This only will detect avatars sitting on sit targets defined with llSitTarget.

    id. Specify an empty string or NULL_KEY to not filter on the corresponding parameter.

    number. Returns NULL_KEY if number is not valid sensed object.

    id. Returns a bitfield of agent info constants.

    face is ALL_SIDES the value returned is the mean average of all faces.

    llResetTime. Use llSetTimerEvent if you want a reliable timing mechanism.

    face is ALL_SIDES the color returned is the mean average of each channel.

    type. Use the inventory constants to specify the type in the object inventory. Use the inventory constants to specify the mask for the specified inventory item. See Permission Mask Constants for more information. Example usage: @@ -8855,7 +8865,7 @@ CLASS="parameter" CLASS="parameter" >name is found. Use the inventory constants to compare against the return value.

    pos or NULL_KEY if public.

    Returns the type of the variable at name and returns the data through the dataserver event. The line count starts at zero. If the requested line is past the end of the notecard the dataserver event will return the constant EOF string. The key returned by this function is a unique identifier which will be supplied to the dataserver event in the name and returns this information through the dataserver event. The key returned by this function is a unique identifier which will be supplied to the dataserver event in the mask for the root object the task is attached to. See Permission Mask Constants for more information. Example usage: @@ -9677,7 +9687,7 @@ CLASS="FUNCDEF" >

    Returns avatar that has enabled permissions. Returns NULL_KEY if not enabled.

    parameters are identical to the rules of llSetPrimitiveParams, and the returned list is ordered as such. Most requested parameters do not require a value to be associated, except for texture-related requests (PRIM_TEXTURE, PRIM_COLOR, and PRIM_BUMP_SHINY) which require a side number to be specified as well. Valid parameters can be found in the Primitive Constants. Here is a simple example: @@ -10142,7 +10152,7 @@ CLASS="parameter" >status. The value will be one of the status constants.

    llResetTime. Use llSetTimerEvent if you want a reliable timing mechanism.

    destination. This call will fail if PERMISSION_DEBIT has not been set.

    ascending is TRUE. Note that sort only works in the head of each sort block is the same type.

    number parameter to specify which event you are controlling. Use boolean values to specify , this function plays a sound attached to an object, but will continuously loop that sound until llStopSound or volume to 0 is not the same as calling llStopSound; a sound with 0 volume will continue to loop. To restart the sound from the beginning, call llStopSound before calling llLoopSound again.

    llGetLinkNumber or a link constant.

    size area. The parameters can be chosen from the land constants.

    face is ALL_SIDES this function sets the texture offsets for all faces.

    Returns TRUE if id is over land owned by the object owner, FALSE otherwise.

    command can be one of PARCEL_MEDIA_COMMAND_STOP, PARCEL_MEDIA_COMMAND_PAUSE, PARCEL_MEDIA_COMMAND_PLAY, PARCEL_MEDIA_COMMAND_LOOP, PARCEL_MEDIA_COMMAND_TEXTURE, PARCEL_MEDIA_COMMAND_URL, PARCEL_MEDIA_COMMAND_TIME, PARCEL_MEDIA_COMMAND_AGENT, PARCEL_MEDIA_COMMAND_UNLOAD, or PARCEL_MEDIA_COMMAND_AUTO_ALIGN.

    command can be one of PARCEL_MEDIA_COMMAND_TEXTURE or PARCEL_MEDIA_COMMAND_URL.

    are specified as an ordered list of parameter and value. Valid parameters and their expected values can be found in the particle system constants. Here is a simple example: @@ -12959,7 +12969,7 @@ CLASS="FUNCDEF" CLASS="parameter" >pass is TRUE, land and object collisions are passed from children on to parents.

    pass is TRUE, touches are passed from children on to parents.

    Plays a sound once. The sound will be attached to an object and follow object movement. Only one sound may be attached to an object at a time, and attaching a new sound or calling llStopSound will stop the previously attached sound. A second call to llPlaySound with the @@ -13039,7 +13049,7 @@ CLASS="parameter" the new volume will be used, which allows control over the volume of already playing sounds. To restart the sound from the beginning, call llStopSound before calling llPlaySound again.

    flags to FALSE. Valid parameters can be found in the vehicle flags constants section.

    id. If and when the information is collected, the dataserver event is called with the returned key returned from this function @@ -13500,7 +13510,7 @@ CLASS="parameter" >requested parameter. See the agent data constants for details about valid values of data and what each will return in the dataserver event.

    name. When data is available the dataserver event will be raised with the key returned from this function in the @@ -13597,7 +13607,7 @@ CLASS="parameter" >perm parameter should be a permission constant. Multiple permissions can be requested @@ -13605,7 +13615,7 @@ HREF="#AEN5313" permissions requests can only go to object owner. This call will not stop script execution - if the specified avatar grants the requested permissions, the run_time_permissions event will be called.

    sim_name. When the information is collected, the dataserver event is called with the returned key returned from this function @@ -13651,7 +13661,7 @@ CLASS="parameter" >requested parameter. See the simulator data constants for details about valid values of data and what each will return in the dataserver event.

    param value will be available to the newly created object in the on_rez event or through the param value will be available to the newly created object in the on_rez event or through the face ALL_SIDES, rotate the texture of all faces.

    Returns TRUE if the object or agent is in the same simulator and has the same active group as this object. Otherwise, returns FALSE.

    scale_t respectively. If face is ALL_SIDES, scale the texture to all faces.

    arc radians of forward vector. Specifying a blank name or NULL_KEY id will not filter results for any particular name or id. A range of 0.0 does not perform a @@ -14540,16 +14550,16 @@ HREF="#AEN6023" CLASS="parameter" >type parameter should be an object type constant value. If anything is found during the scan, a sensor event is triggered. A maximum of 16 items are passed to this event. If nothing is found during the scan, a no sensor event is triggered instead.

    rate seconds. Specifying a blank name or NULL_KEY id will not filter results for any particular name or id. A range of 0.0 cancels the @@ -14639,16 +14649,16 @@ HREF="#AEN6023" CLASS="parameter" >type parameter should be an object type constant value. If anything is found during the scan, a sensor event is triggered. A maximum of 16 items are passed to this event. If nothing is found during the scan, a no sensor event is triggered instead.

    face. If face is ALL_SIDES, set the alpha to all faces. The face. If face is ALL_SIDES, set the alpha to all faces.

    force. The vector is in local coordinates if local is TRUE, global if FALSE.

    torque. The vectors are in local coordinates if local is TRUE, global if FALSE.

    water is TRUE.

    Sets the alpha of the linked child - specified by linknumber. A value of 0 means - no link, 1 the root, 2 for first child, etc. If - of a prim in the link set. + The linknumber is ALL_SIDES, set the alpha of - all objects in the linked set. If linknum + parameter is either the linked number available through llGetLinkNumber or a link constant. + If face is ALL_SIDES, set the alpha of all faces.

    Sets the color of the linked child - specified by linknumber. A value of 0 means - no link, 1 the root, 2 for first child, etc. If - of a prim in the link set. + The linknumber is ALL_SIDES, set the color of - all objects in the linked set. If linknum + parameter is either the linked number available through llGetLinkNumber or a link constant. + If face is ALL_SIDES, set the color of all faces.

    A.234. llSetLocalRotA.234. llSetLinkPrimitiveParams
    llSetLinkPrimitiveParams(integer linknumber, list rules);

    Sets the primitive parameters of a prim in the link set. + The linknum + parameter is either the linked number available through llGetLinkNumber or a link constant. + The rules + list is identical to that of + llSetPrimitiveParams.


    A.235. llSetLinkTexture

    llSetLinkTexture(integer linknumber, string texture, integer face);

    Sets the texture of a prim in the link set. + The linknum + parameter is either the linked number available through llGetLinkNumber or a link constant. + If face is + ALL_SIDES, set the texture + of all faces.


    A.236. llSetLocalRot

    llSetLocalRot(rotation rot);


    A.235. llSetObjectDescA.237. llSetObjectDesc


    A.236. llSetObjectNameA.238. llSetObjectName


    A.237. llSetParcelMusicURLA.239. llSetParcelMusicURL


    A.238. llSetPayPriceA.240. llSetPayPrice

    Sets the default pay price and optionally the quick pay buttons for the 'Pay' window when someone pays this object. See also Pay Button Constants.


    A.239. llSetPosA.241. llSetPos


    A.240. llSetPrimitiveParamsA.242. llSetPrimitiveParams

    are specified as an ordered list of parameter and value(s). Valid parameters and their expected values can be found in the Primitive Constants. Here is a simple example: @@ -15340,7 +15447,7 @@ CLASS="informalexample" >


    A.241. llSetRemoteScriptAccessPinA.243. llSetRemoteScriptAccessPin


    A.242. llSetRotA.244. llSetRot


    A.243. llSetScaleA.245. llSetScale


    A.244. llSetScriptStateA.246. llSetScriptState


    A.245. llSetSitTextA.247. llSetSitText


    A.246. llSetSoundQueueingA.248. llSetSoundQueueing

    , etc., (attached sounds) interrupt the playing sound. The default for objects is FALSE. Setting this value to TRUE will make the sound wait until the current playing sound reaches its end. The queue is one @@ -15550,15 +15657,15 @@ CLASS="section" >


    A.247. llSetStatusA.249. llSetStatus

    value. Use status constants for the values of


    A.248. llSetTextA.250. llSetText


    A.249. llSetTextureA.251. llSetTexture

    face. If face is ALL_SIDES, set the texture to all faces.


    A.250. llSetTextureAnimA.252. llSetTextureAnim

    Animates a texture by setting the texture scale and offset. The mode is a mask of texture animation constants. You can only have one texture animation on an @@ -15702,17 +15809,17 @@ HREF="#AEN5770" reset it.

    You can only do one traditional animation, ROTATE or SCALE at a time, you cannot combine masks. In the case of ROTATE or SCALE, face is ALL_SIDES, all textures on the object are animated.


    A.251. llSetTimerEventA.253. llSetTimerEvent

    Sets the timer event to be triggered every sec seconds. Passing in 0.0 stops further timer events.


    A.252. llSetTorqueA.254. llSetTorque

    torque. The vector is in local coordinates if local is TRUE, global if FALSE.


    A.253. llSetTouchTextA.255. llSetTouchText


    A.254. llSetVehicleFlagsA.256. llSetVehicleFlags

    flags to TRUE. Valid parameters can be found in the vehicle flags constants section.


    A.255. llSetVehicleFloatParamA.257. llSetVehicleFloatParam

    param_value. Valid parameters and their expected values can be found in the vehicle parameter constants section.


    A.256. llSetVehicleTypeA.258. llSetVehicleType

    type. Valid types and an explanation of their characteristics can be found in the vehicle type constants section.


    A.257. llSetVehicleRotationParamA.259. llSetVehicleRotationParam

    param_value. Valid parameters can be found in the vehicle parameter constants section.


    A.258. llSetVehicleVectorParamA.260. llSetVehicleVectorParam

    param_value. Valid parameters can be found in the vehicle parameter constants section.


    A.259. llShoutA.261. llShout


    A.260. llSinA.262. llSin


    A.261. llSitTargetA.263. llSitTarget

    offset == ZERO_VECTOR clear the sit target.


    A.262. llSleepA.264. llSleep


    A.263. llSqrtA.265. llSqrt


    A.264. llStartAnimationA.266. llStartAnimation


    A.265. llStopAnimationA.267. llStopAnimation


    A.266. llStopHoverA.268. llStopHover


    A.267. llStopLookAtA.269. llStopLookAt


    A.268. llStopMoveToTargetA.270. llStopMoveToTarget


    A.269. llStopPointAtA.271. llStopPointAt


    A.270. llStopSoundA.272. llStopSound

    llLoopSound. Has no effect on sounds started with llTriggerSound.


    A.271. llStringLengthA.273. llStringLength


    A.272. llSubStringIndexA.274. llSubStringIndex


    A.273. llStringToBase64A.275. llStringToBase64


    A.274. llTakeControlsA.276. llTakeControls

    pass_on is TRUE, also send input to avatar.


    A.275. llTanA.277. llTan


    A.276. llTargetA.278. llTarget


    A.277. llTargetOmegaA.279. llTargetOmega


    A.278. llTargetRemoveA.280. llTargetRemove


    A.279. llTeleportAgentHomeA.281. llTeleportAgentHome


    A.280. llToLowerA.282. llToLower


    A.281. llToUpperA.283. llToUpper


    A.282. llTriggerSoundA.284. llTriggerSound

    llTriggerSound does not affect the attached sounds created by


    A.283. llTriggerSoundLimitedA.285. llTriggerSoundLimited

    llTriggerSound does not affect the attached sounds created by


    A.284. llUnescapeURLA.286. llUnescapeURL


    A.285. llUnSitA.287. llUnSit


    A.286. llVecDistA.288. llVecDist


    A.287. llVecMagA.289. llVecMag


    A.288. llVecNormA.290. llVecNorm


    A.289. llVolumeDetectA.291. llVolumeDetect


    A.290. llWaterA.292. llWater


    A.291. llWhisperA.293. llWhisper


    A.292. llWindA.294. llWind


    A.293. llXorBase64StringsA.295. llXorBase64Strings


    Appendix B. Events


    B.1. at_rot_target


    B.2. at_target

    This event is triggered when a script comes within a defined range from a target position. The range and position are set by a call to llTarget.


    B.3. attach

    NULL_KEY.


    B.4. changed

    changed will be a bitfield of change constants.


    B.5. collision


    B.6. collision_end


    B.7. collision_start


    B.8. control

    edges are bitfields of control constants.


    B.9. dataserver


    B.10. email


    B.11. land_collision


    B.12. land_collision_end


    B.13. land_collision_start


    B.14. link_message


    B.15. listen


    B.16. money


    B.17. moving_end


    B.18. moving_start


    B.19. no_sensor


    B.20. not_at_rot_target


    B.21. not_at_target

    When a target is set via the llTarget library call, but the script is outside the specified range this event is raised.


    B.22. object_rez


    B.23. on_rez


    B.24. run_time_permissions

    library function is used to request these permissions and the various permissions integer constants can be supplied. The integer returned to this @@ -18486,7 +18593,7 @@ CLASS="section" >


    B.25. sensor


    B.26. state_entry


    B.27. state_exit


    B.28. timer

    This event is raised at regular intervals set by the llSetTimerEvent library function.


    B.29. touch


    B.30. touch_end


    B.31. touch_start


    B.32. remote_data


    Appendix C. Constants


    C.1. Boolean Constants


    C.2. Status Constants

    The status constants are used in the llSetStatus and


    C.3. Object Type Constants


    C.4. Permission Constants

    llGetPermissions, and explicitly passed to the run_time_permissions event. For many of the basic library functions to work, a @@ -19068,7 +19175,7 @@ HREF="#AEN2342" >

    If this permission enabled, the object can successfully call the llTakeControls library call.

    If this permission is enabled, the object can successfully call llStartAnimation for the avatar that owns this object.


    C.5. Inventory Constants


    C.6. Pay Price Constants


    C.7. Attachment Constants


    C.8. Land Constants


    C.9. Link Constants


    C.10. Control Constants

    These constants are used in llTakeControls as well as the control event handler.


    C.11. Change Constants

    These constants are used in the changed event handler.


    C.12. Type Constants


    C.13. Agent Info Constants


    C.14. Texture Animation Constants

    These constants are used in the llSetTextureAnim api to control the animation mode.


    C.15. Particle System Constants


    C.16. Agent Data Constants

    api to collect information about an agent which will be provided in the dataserver event.


    C.17. Float Constants


    C.18. Key Constant


    C.19. Miscellaneous Integer Constants


    C.20. Miscellaneous String Constants

    There is one uncategorized string constant which is used in the dataserver event: EOF


    C.21. Vector Constant


    C.22. Rotation Constant


    C.23. Simulator Data Constants

    api to collect information about a simulator which will be provided in the dataserver event.


    C.24. Vehicle Parameters


    C.25. Vehicle Flags


    C.26. Vehicle Types

    Another vehicle that bounces along the ground but needs the motors to be driven from external controls or timer events.


    C.27. Primitive Constants

    These constants are used in calls to the llSetPrimitiveParams and


    C.28. XML-RPC Constants


    C.29. Permission Mask Constants


    C.30. Parcel Media Constants (Movies)

    /Contents/MacOS/ directory exists (it may not be there yet on a clean build)\nmkdir -p \"${MACOS_DIRECTORY}\"\n\n# Expand the tar file containing the assorted mozilla bits into /Contents/MacOS/\ntar -zx -C \"${MACOS_DIRECTORY}\" -f \"${SRCROOT}/mozilla-universal-darwin.tgz\"\n\n# replace the default theme with our custom theme (so scrollbars work).\ncp \"${SRCROOT}/mozilla-theme/classic.jar\" \"${SRCROOT}/mozilla-theme/classic.manifest\" \"${MACOS_DIRECTORY}/chrome\"\n\n#copy over the universal llkdu dynamic library to the resource directory if it doesn't already exist\nif [ ! -f \"${RESOURCES_DIRECTORY}/libllkdu.dylib\" ]\nthen\n\tcp \"${SRCROOT}/../../libraries/universal-darwin/lib_release/libllkdu.dylib\" \"${RESOURCES_DIRECTORY}\"\nfi "; + shellScript = "# exit on any error\nset -e\n\n# Copy the necessary resources into the build directory.\npython viewer_manifest.py --actions=\"copy\" --configuration=\"${CONFIGURATION}\" \"${BUILT_PRODUCTS_DIR}/${PRODUCT_NAME}.app\"\n"; }; FD53B40409BDF9F600BFE3BC /* ShellScript */ = { isa = PBXShellScriptBuildPhase; @@ -3963,7 +3983,7 @@ ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "LIBS=\"apr-1 aprutil-1 expat ogg vorbis fmod freetype llcurl lljpeg openjpeg vorbisenc vorbisfile xmlrpc\"\nLIBDIR=\"${SRCROOT}/../../libraries\"\n\ncd \"${LIBDIR}\"\n\nif [ \\! -e ppc-darwin ]\nthen\n\tln -s powerpc-darwin ppc-darwin\nfi\n\nmkdir -p \"${BUILT_PRODUCTS_DIR}\"\n\nfor i in ${LIBS}; do\n\tNEED_UPDATE=false\n\tARCH_COUNT=0\n\tOUT=\"${BUILT_PRODUCTS_DIR}/lib$i.a\"\n\tTEST_ARCH=`echo \"${ARCHS}\" | grep i386`\n\tif [ -n \"$TEST_ARCH\" ]; then\n\t\tIN_i386=\"i386-darwin/lib_release/lib$i.a\"\n\t\tARCH_COUNT=`expr $ARCH_COUNT \"+\" 1`\n\t\tif [ \"$IN_i386\" -nt \"$OUT\" ]; then\n\t\t\tNEED_UPDATE=true\n\t\tfi\n\tfi\n\tTEST_ARCH=`echo \"${ARCHS}\" | grep ppc`\n\tif [ -n \"$TEST_ARCH\" ]; then\n\t\tIN_ppc=\"ppc-darwin/lib_release/lib$i.a\"\n\t\tARCH_COUNT=`expr $ARCH_COUNT \"+\" 1`\n\t\tif [ \"$IN_ppc\" -nt \"$OUT\" ]; then\n\t\t\tNEED_UPDATE=true\n\t\tfi\n\tfi\n\tif [ $ARCH_COUNT -eq 0 ]; then\n\t\techo \"No supported architectures found.\"\n\t\texit 1\n\tfi\n\tif [ ! -f \"$OUT\" -o NEED_UPDATE = \"true\" ]; then\n\t\techo Preparing third party library lib$i.a\n\t\tif [ $ARCH_COUNT -eq 1 ]; then\n\t\t\tIN=\"$IN_i386\"\"$IN_ppc\"\n\t\t\t#echo cp \"$IN\" \"$OUT\"\n\t\t\tcp \"$IN\" \"$OUT\"\n\t\telse\n\t\t\t#echo libtool -static -o \"$OUT\" \"$IN_i386\" \"$IN_ppc\"\n\t\t\tlibtool -static -o \"$OUT\" \"$IN_i386\" \"$IN_ppc\"\n\t\tfi\n\t\tranlib \"$OUT\"\n\telse\n\t\techo Third party library lib$i.a is up to date\n\tfi\ndone\n"; + shellScript = "# Glue together intel and ppc versions of .a files\nLIBS=\"apr-1 aprutil-1 expat ogg vorbis fmod freetype cares llcurl lljpeg openjpeg vorbisenc vorbisfile xmlrpc\"\nLIBDIR=\"${SRCROOT}/../../libraries\"\n\ncd \"${LIBDIR}\"\n\nif [ \\! -e ppc-darwin ]\nthen\n\tln -s powerpc-darwin ppc-darwin\nfi\n\nmkdir -p \"${BUILT_PRODUCTS_DIR}\"\n\nfor i in ${LIBS}; do\n\tNEED_UPDATE=false\n\tARCH_COUNT=0\n\tOUT=\"${BUILT_PRODUCTS_DIR}/lib$i.a\"\n\tTEST_ARCH=`echo \"${ARCHS}\" | grep i386`\n\tif [ -n \"$TEST_ARCH\" ]; then\n\t\tIN_i386=\"i386-darwin/lib_release/lib$i.a\"\n\t\tARCH_COUNT=`expr $ARCH_COUNT \"+\" 1`\n\t\tif [ \"$IN_i386\" -nt \"$OUT\" ]; then\n\t\t\tNEED_UPDATE=true\n\t\tfi\n\tfi\n\tTEST_ARCH=`echo \"${ARCHS}\" | grep ppc`\n\tif [ -n \"$TEST_ARCH\" ]; then\n\t\tIN_ppc=\"ppc-darwin/lib_release/lib$i.a\"\n\t\tARCH_COUNT=`expr $ARCH_COUNT \"+\" 1`\n\t\tif [ \"$IN_ppc\" -nt \"$OUT\" ]; then\n\t\t\tNEED_UPDATE=true\n\t\tfi\n\tfi\n\tif [ $ARCH_COUNT -eq 0 ]; then\n\t\techo \"No supported architectures found.\"\n\t\texit 1\n\tfi\n\tif [ ! -f \"$OUT\" -o NEED_UPDATE = \"true\" ]; then\n\t\techo Preparing third party library lib$i.a\n\t\tif [ $ARCH_COUNT -eq 1 ]; then\n\t\t\tIN=\"$IN_i386\"\"$IN_ppc\"\n\t\t\t#echo cp \"$IN\" \"$OUT\"\n\t\t\tcp \"$IN\" \"$OUT\"\n\t\telse\n\t\t\t#echo libtool -static -o \"$OUT\" \"$IN_i386\" \"$IN_ppc\"\n\t\t\tlibtool -static -o \"$OUT\" \"$IN_i386\" \"$IN_ppc\"\n\t\tfi\n\t\tranlib \"$OUT\"\n\telse\n\t\techo Third party library lib$i.a is up to date\n\tfi\ndone\n"; }; /* End PBXShellScriptBuildPhase section */ @@ -3994,13 +4014,11 @@ 5503BB3F05446B20003D051F /* llwaterpatch.cpp in Sources */, 5503BB4005446B20003D051F /* llvowater.cpp in Sources */, 5503BB4105446B20003D051F /* llvovolume.cpp in Sources */, - 5503BB4205446B20003D051F /* llvotreenew.cpp in Sources */, 5503BB4305446B20003D051F /* llvotree.cpp in Sources */, 5503BB4405446B20003D051F /* llvotextbubble.cpp in Sources */, 5503BB4505446B20003D051F /* llvosurfacepatch.cpp in Sources */, 5503BB4605446B20003D051F /* llvosky.cpp in Sources */, 5503BB4705446B20003D051F /* llvopartgroup.cpp in Sources */, - 5503BB4805446B20003D051F /* llvopart.cpp in Sources */, 5503BB4905446B20003D051F /* llvoground.cpp in Sources */, 5503BB4A05446B20003D051F /* llvograss.cpp in Sources */, 5503BB4B05446B20003D051F /* llvoclouds.cpp in Sources */, @@ -4047,7 +4065,6 @@ 5503BB7D05446B20003D051F /* llconsole.cpp in Sources */, 5503BB7E05446B20003D051F /* lllandmarklist.cpp in Sources */, 5503BB7F05446B20003D051F /* llfloaterbuildoptions.cpp in Sources */, - 5503BB8105446B20003D051F /* llfloateraccounthistory.cpp in Sources */, 5503BB8605446B20003D051F /* lluserauth.cpp in Sources */, 5503BB8705446B20003D051F /* llurl.cpp in Sources */, 5503BB8805446B20003D051F /* lluploaddialog.cpp in Sources */, @@ -4068,7 +4085,6 @@ 5503BBA005446B20003D051F /* lldrawpoolalpha.cpp in Sources */, 5503BBA105446B20003D051F /* lltexturetable.cpp in Sources */, 5503BBA205446B20003D051F /* lltexturectrl.cpp in Sources */, - 5503BBA305446B20003D051F /* lltexturebar.cpp in Sources */, 5503BBA405446B20003D051F /* llpanelobject.cpp in Sources */, 5503BBA505446B20003D051F /* llpanelnetwork.cpp in Sources */, 5503BBA605446B20003D051F /* lldrawpool.cpp in Sources */, @@ -4134,7 +4150,6 @@ 5503BBFD05446B20003D051F /* llhoverview.cpp in Sources */, 5503BBFE05446B20003D051F /* llcylinder.cpp in Sources */, 5503BBFF05446B20003D051F /* llhippo.cpp in Sources */, - 5503BC0105446B20003D051F /* llpanelmoney.cpp in Sources */, 5503BC0305446B20003D051F /* llfloateravatarinfo.cpp in Sources */, 5503BC0405446B20003D051F /* llcallingcard.cpp in Sources */, 5503BC0505446B20003D051F /* llhudeffectbeam.cpp in Sources */, @@ -4149,7 +4164,6 @@ 5503BC1005446B20003D051F /* llnamelistctrl.cpp in Sources */, 5503BC1205446B20003D051F /* llmaniptranslate.cpp in Sources */, 5503BC1305446B20003D051F /* llmanipscale.cpp in Sources */, - 5503BC1405446B20003D051F /* lldrawpooltreenew.cpp in Sources */, 5503BC1505446B20003D051F /* head.cpp in Sources */, 5503BC1705446B20003D051F /* llfloaternamedesc.cpp in Sources */, 5503BC1805446B20003D051F /* llpanelplace.cpp in Sources */, @@ -4334,7 +4348,6 @@ 99BB516F099AC1E9004BF9F2 /* llviewchildren.cpp in Sources */, 99BB5172099AC1FC004BF9F2 /* llcurrencyuimanager.cpp in Sources */, 99BB5176099AC2A4004BF9F2 /* llconfirmationmanager.cpp in Sources */, - 99B0682909A54FBB00F4AD09 /* lldrawpoolhud.cpp in Sources */, FD6C9A2909C758BC00AA1849 /* llfloaterscriptdebug.cpp in Sources */, FD6C9A2A09C758BC00AA1849 /* llfloatertelehub.cpp in Sources */, FD6C9A2B09C758BC00AA1849 /* llfollowcam.cpp in Sources */, @@ -4353,7 +4366,6 @@ A3077C0909DCB8140059ED75 /* llfloaterhtmlhelp.cpp in Sources */, A3077C0B09DCB8140059ED75 /* llpanelvolume.cpp in Sources */, A3077C0C09DCB8140059ED75 /* llvostars.cpp in Sources */, - FD870C5009EAC19700F5956C /* lldrawpoolclouds.cpp in Sources */, 1AFA409C0A2DFC7F00C13F70 /* llviewernetwork.cpp in Sources */, 1AFA409F0A2DFC8700C13F70 /* llprefsim.cpp in Sources */, 1AFA40A20A2DFC9000C13F70 /* llprefschat.cpp in Sources */, @@ -4389,25 +4401,29 @@ C64F673F0AFBED80009732B5 /* lllogchat.cpp in Sources */, C64F67420AFBED91009732B5 /* lldirpicker.cpp in Sources */, 1AF7C1E40AF6C44800C4BF4A /* llweb.cpp in Sources */, + AA02B9BC0B0CE44D00F2996D /* lltexturefetch.cpp in Sources */, FD59ED5F0AF2AF460086642A /* llassetuploadresponders.cpp in Sources */, FDCB54F60AFBC5060033B433 /* llhttpnode.cpp in Sources */, FDCB55290AFBD4310033B433 /* lleventpoll.cpp in Sources */, FDFAD3EA0AFFBB230048A0C7 /* llsdmessagesystem.cpp in Sources */, + AA348DFA0B0EAB31002C3015 /* llcurl.cpp in Sources */, + AAF5FFD20B13F71900D28A84 /* lltexturecache.cpp in Sources */, C1F5D0A50B138AEB00827F1D /* lluserrelations.cpp in Sources */, D62830DB0B4DC76300F8830F /* llimagej2coj.cpp in Sources */, + AAE98CC20B38FE0800E2F204 /* llimageworker.cpp in Sources */, 1AEF0A580B2DFE67003F107C /* llctrlselectioninterface.cpp in Sources */, 1AEF0A5B0B2DFE72003F107C /* llrootview.cpp in Sources */, + A30273570B3A13D800704420 /* llvertexbuffer.cpp in Sources */, 1A1F130C0B3919F100845A6C /* lleditmenuhandler.cpp in Sources */, C16C08500B4AE6C7009AD67F /* llfloaterinspect.cpp in Sources */, - D628316C0B4F3FA200F8830F /* llagpmempool.cpp in Sources */, - D628316D0B4F3FA200F8830F /* llagpmempoolapple.cpp in Sources */, - D628316E0B4F3FA200F8830F /* llagpmempoolarb.cpp in Sources */, - D62831710B4F3FA200F8830F /* llfont.cpp in Sources */, - D62831720B4F3FA200F8830F /* llfontgl.cpp in Sources */, - D62831730B4F3FA200F8830F /* llgldbg.cpp in Sources */, - D62831740B4F3FA200F8830F /* llimagegl.cpp in Sources */, - D62831760B4F3FA200F8830F /* llvertexprogramgl.cpp in Sources */, - D62831780B4F3FA200F8830F /* text_out.cpp in Sources */, + A32748C10B5F38A80099BE18 /* llfont.cpp in Sources */, + A32748BF0B5F38A00099BE18 /* llfontgl.cpp in Sources */, + A32748C00B5F38A20099BE18 /* llimagegl.cpp in Sources */, + A3274AD20B5F39130099BE18 /* text_out.cpp in Sources */, + 1A02016F0B7A85DE00D5C589 /* llbase64.cpp in Sources */, + 1A0201850B7A861200D5C589 /* llblowfishcipher.cpp in Sources */, + 1A0201860B7A861200D5C589 /* llnullcipher.cpp in Sources */, + 1A0201870B7A861200D5C589 /* llxorcipher.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4437,8 +4453,6 @@ 619222E8074A9B5B005E1F34 /* bitpack.cpp in Sources */, 619222F0074A9B5B005E1F34 /* llcriticaldamp.cpp in Sources */, 619222F8074A9B5B005E1F34 /* llerror.cpp in Sources */, - 619222FA074A9B5B005E1F34 /* llerrorbuffer.cpp in Sources */, - 619222FC074A9B5B005E1F34 /* llerrorstream.cpp in Sources */, 619222FE074A9B5B005E1F34 /* llfasttimer.cpp in Sources */, 61922300074A9B5B005E1F34 /* llfixedbuffer.cpp in Sources */, 61922302074A9B5B005E1F34 /* llframetimer.cpp in Sources */, @@ -4582,6 +4596,10 @@ D651349D0B3C40870042C56E /* llqueuedthread.cpp in Sources */, 91469E7B0B4486C10009E8F9 /* llmime.cpp in Sources */, 913B26990B4DDCDA0030C3EC /* lllandmark.cpp in Sources */, + DA9C40E00B54B4BA00DD6F44 /* llformat.cpp in Sources */, + DA9C41140B54B8CA00DD6F44 /* lllivefile.cpp in Sources */, + 1A97C4560B8BCF9C00331A24 /* llliveappconfig.cpp in Sources */, + 1A9897E90B98E2F4005C45D7 /* llbase32.cpp in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -4679,8 +4697,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = AutoUpdater; }; name = Universal; @@ -4694,8 +4714,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = crashreporter; }; name = Universal; @@ -4715,8 +4737,10 @@ "$(LIBRARY_SEARCH_PATHS)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; OTHER_LDFLAGS = ""; PRODUCT_NAME = "Second Life"; SEPARATE_STRIP = YES; @@ -4857,8 +4881,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = crashreporter; }; name = Development; @@ -4872,8 +4898,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = crashreporter; }; name = Deployment; @@ -4887,8 +4915,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = AutoUpdater; }; name = Development; @@ -4902,8 +4932,10 @@ LIBRARY_SEARCH_PATHS = ( "$(inherited)", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; PRODUCT_NAME = AutoUpdater; }; name = Deployment; @@ -4923,8 +4955,10 @@ "$(LIBRARY_SEARCH_PATHS)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; OTHER_LDFLAGS = "-weak-lllmozlib"; PRODUCT_NAME = "Second Life"; SHARED_PRECOMPS_DIR = "$(BUILD_DIR)/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders"; @@ -4953,8 +4987,10 @@ "$(LIBRARY_SEARCH_PATHS)", "$(SRCROOT)/../../libraries/universal-darwin/lib_release", "$(LIBRARY_SEARCH_PATHS_QUOTED_1)", + "$(LIBRARY_SEARCH_PATHS_QUOTED_2)", ); LIBRARY_SEARCH_PATHS_QUOTED_1 = "\"$(SRCROOT)/build/Universal\""; + LIBRARY_SEARCH_PATHS_QUOTED_2 = "\"$(SRCROOT)/build/Universal\""; OTHER_LDFLAGS = "-lllmozlib"; PRODUCT_NAME = "Second Life"; SHARED_PRECOMPS_DIR = "$(BUILD_DIR)/Caches/com.apple.Xcode.$(UID)/SharedPrecompiledHeaders"; diff --git a/linden/indra/newview/macview_Prefix.h b/linden/indra/newview/macview_Prefix.h index 651cc88..ddfcfec 100644 --- a/linden/indra/newview/macview_Prefix.h +++ b/linden/indra/newview/macview_Prefix.h @@ -130,17 +130,15 @@ #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" #include "lldrawpooltree.h" -#include "lldrawpooltreenew.h" #include "lldrawpoolterrain.h" #include "lldrawpoolsky.h" #include "lldrawpoolwater.h" #include "lldrawpoolground.h" #include "lldrawpoolbump.h" -#include "llvotreenew.h" /////////////////// From llface.cpp #include "llgl.h" -#include "llviewerimagelist.h" +#include "llviewerimage.h" #include "llsky.h" #include "llvosky.h" #include "llcontrol.h" diff --git a/linden/indra/newview/moviemaker.cpp b/linden/indra/newview/moviemaker.cpp index 1054f1a..0f60bb1 100644 --- a/linden/indra/newview/moviemaker.cpp +++ b/linden/indra/newview/moviemaker.cpp @@ -52,7 +52,7 @@ HBITMAP LoadBMPFromFB( int w, int h ); MovieMaker::MovieMaker() { - sprintf( fname, "movie.avi" ); + snprintf( fname, sizeof(fname), "movie.avi" ); /* Flawfinder: ignore */ width = -1; height = -1; @@ -104,7 +104,8 @@ MovieMaker::~MovieMaker() void MovieMaker::StartCapture( char *name , int x, int y) { - strcpy( fname, name ); + strncpy( fname, name, sizeof(fname) -1 ); /* Flawfinder: ignore */ + fname[sizeof(fname) -1] = '\0'; // Get the width and height. width = x; @@ -498,7 +499,7 @@ MovieMaker::~MovieMaker() void MovieMaker::StartCapture( char *name , int x, int y) { - strncpy( fname, name, sizeof(fname)); + strncpy( fname, name, sizeof(fname)); /* Flawfinder: ignore */ width = x; height = y; @@ -577,7 +578,7 @@ OSStatus MovieMaker::setupMovie() if (error == noErr) { // This is stoopid. I have to take the passed full path, create the file so I can get an FSRef, and Get Info to get the FSSpec for QuickTime. Could Apple make this any more difficult... - FILE *file = LLFile::fopen(fname, "w"); + FILE* file = LLFile::fopen(fname, "w"); /* Flawfinder: ignore */ if (file) { fclose(file); diff --git a/linden/indra/newview/moviemaker.h b/linden/indra/newview/moviemaker.h index ff1aa9b..0f1c79f 100644 --- a/linden/indra/newview/moviemaker.h +++ b/linden/indra/newview/moviemaker.h @@ -83,7 +83,7 @@ public: class MovieMaker { private: - char fname[64]; + char fname[64]; /*Flawfinder: ignore*/ Movie movie; short movieResRef; diff --git a/linden/indra/newview/newview.vcproj b/linden/indra/newview/newview.vcproj index 8eec1bb..99e182c 100644 --- a/linden/indra/newview/newview.vcproj +++ b/linden/indra/newview/newview.vcproj @@ -79,7 +79,7 @@ CharacterSet="1"> - - - - - - - - - - - - + RelativePath=".\lltexturecache.cpp"> @@ -1209,9 +1190,6 @@ RelativePath=".\llvolumesliderctrl.cpp"> - - - - - - - - - - - - - - - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/linden/indra/newview/pipeline.cpp b/linden/indra/newview/pipeline.cpp index a7b4d47..1a5b4f1 100644 --- a/linden/indra/newview/pipeline.cpp +++ b/linden/indra/newview/pipeline.cpp @@ -32,12 +32,12 @@ // library includes #include "audioengine.h" // For MAX_BUFFERS for debugging. #include "imageids.h" -#include "llagpmempool.h" #include "llerror.h" #include "llviewercontrol.h" #include "llfasttimer.h" #include "llfontgl.h" #include "llmemory.h" +#include "llmemtype.h" #include "llnamevalue.h" #include "llprimitive.h" #include "llvolume.h" @@ -45,17 +45,17 @@ #include "timing.h" #include "v3color.h" #include "llui.h" +#include "llglheaders.h" // newview includes #include "llagent.h" -#include "llagparray.h" #include "lldrawable.h" #include "lldrawpoolalpha.h" #include "lldrawpoolavatar.h" #include "lldrawpoolground.h" #include "lldrawpoolsimple.h" +#include "lldrawpoolbump.h" #include "lldrawpooltree.h" -#include "lldrawpoolhud.h" #include "lldrawpoolwater.h" #include "llface.h" #include "llfeaturemanager.h" @@ -82,10 +82,13 @@ #include "llvosky.h" #include "llvotree.h" #include "llvovolume.h" +#include "llvosurfacepatch.h" +#include "llvowater.h" +#include "llvotree.h" +#include "llvopartgroup.h" #include "llworld.h" #include "viewer.h" -#include "llagpmempoolarb.h" -#include "llagparray.inl" +#include "llcubemap.h" #ifdef _DEBUG // Debug indices is disabled for now for debug performance - djs 4/24/02 @@ -94,6 +97,8 @@ //#define DEBUG_INDICES #endif +#define AGGRESSIVE_OCCLUSION 0 + const F32 BACKLIGHT_DAY_MAGNITUDE_AVATAR = 0.2f; const F32 BACKLIGHT_NIGHT_MAGNITUDE_AVATAR = 0.1f; const F32 BACKLIGHT_DAY_MAGNITUDE_OBJECT = 0.1f; @@ -117,18 +122,12 @@ extern S32 gBoxFrame; extern BOOL gRenderLightGlows; extern BOOL gHideSelectedObjects; - BOOL gAvatarBacklight = FALSE; -F32 gMinObjectDistance = MIN_NEAR_PLANE; S32 gTrivialAccepts = 0; BOOL gRenderForSelect = FALSE; -BOOL gUsePickAlpha = TRUE; -F32 gPickAlphaThreshold = 0.f; -F32 gPickAlphaTargetThreshold = 0.f; - //glsl parameter tables const char* LLPipeline::sReservedAttribs[] = { @@ -177,6 +176,13 @@ const char* LLPipeline::sTerrainUniforms[] = U32 LLPipeline::sTerrainUniformCount = sizeof(LLPipeline::sTerrainUniforms)/sizeof(char*); +const char* LLPipeline::sShinyUniforms[] = +{ + "origin" +}; + +U32 LLPipeline::sShinyUniformCount = sizeof(LLPipeline::sShinyUniforms)/sizeof(char*); + const char* LLPipeline::sWaterUniforms[] = { "screenTex", @@ -193,8 +199,6 @@ const char* LLPipeline::sWaterUniforms[] = U32 LLPipeline::sWaterUniformCount = sizeof(LLPipeline::sWaterUniforms)/sizeof(char*); -// the SSE variable is dependent on software blending being enabled. - //---------------------------------------- void stamp(F32 x, F32 y, F32 xs, F32 ys) @@ -216,40 +220,35 @@ void stamp(F32 x, F32 y, F32 xs, F32 ys) //---------------------------------------- S32 LLPipeline::sCompiles = 0; -S32 LLPipeline::sAGPMaxPoolSize = 1 << 25; // 32MB + +BOOL LLPipeline::sShowHUDAttachments = TRUE; BOOL LLPipeline::sRenderPhysicalBeacons = FALSE; BOOL LLPipeline::sRenderScriptedBeacons = FALSE; BOOL LLPipeline::sRenderParticleBeacons = FALSE; BOOL LLPipeline::sRenderSoundBeacons = FALSE; +BOOL LLPipeline::sUseOcclusion = FALSE; +BOOL LLPipeline::sSkipUpdate = FALSE; +BOOL LLPipeline::sDynamicReflections = FALSE; LLPipeline::LLPipeline() : + mCubeBuffer(NULL), + mCubeList(0), mVertexShadersEnabled(FALSE), mVertexShadersLoaded(0), mLastRebuildPool(NULL), mAlphaPool(NULL), + mAlphaPoolPostWater(NULL), mSkyPool(NULL), mStarsPool(NULL), - mCloudsPool(NULL), mTerrainPool(NULL), mWaterPool(NULL), mGroundPool(NULL), - mHUDPool(NULL), - mAGPMemPool(NULL), - mGlobalFence(0), - mBufferIndex(0), - mBufferCount(kMaxBufferCount), - mUseOcclusionCulling(FALSE), + mSimplePool(NULL), + mBumpPool(NULL), mLightMask(0), mLightMovingMask(0) { - for(S32 i = 0; i < kMaxBufferCount; i++) - { - mBufferMemory[i] = NULL; - } - for (S32 i = 0; i < kMaxBufferCount; i++) - { - mBufferFence[i] = 0; - } + } void LLPipeline::init() @@ -258,8 +257,25 @@ void LLPipeline::init() stop_glerror(); - mAGPBound = FALSE; - mObjectPartition = new LLSpatialPartition; + //create object partitions + //MUST MATCH declaration of eObjectPartitions + mObjectPartition.push_back(new LLVolumePartition()); //PARTITION_VOLUME + mObjectPartition.push_back(new LLBridgePartition()); //PARTITION_BRIDGE + mObjectPartition.push_back(new LLHUDPartition()); //PARTITION_HUD + mObjectPartition.push_back(new LLTerrainPartition()); //PARTITION_TERRAIN + mObjectPartition.push_back(new LLWaterPartition()); //PARTITION_WATER + mObjectPartition.push_back(new LLTreePartition()); //PARTITION_TREE + mObjectPartition.push_back(new LLParticlePartition()); //PARTITION_PARTICLE + mObjectPartition.push_back(new LLCloudPartition()); //PARTITION_CLOUD + mObjectPartition.push_back(new LLGrassPartition()); //PARTITION_GRASS + mObjectPartition.push_back(NULL); //PARTITION_NONE + + //create render pass pools + getPool(LLDrawPool::POOL_ALPHA); + getPool(LLDrawPool::POOL_ALPHA_POST_WATER); + getPool(LLDrawPool::POOL_SIMPLE); + getPool(LLDrawPool::POOL_BUMP); + mTrianglesDrawnStat.reset(); resetFrameStats(); @@ -268,43 +284,15 @@ void LLPipeline::init() mRenderFeatureMask = 0; // All features start off mRenderDebugMask = 0; // All debug starts off + mOldRenderDebugMask = mRenderDebugMask; + mBackfaceCull = TRUE; - // Disable AGP initially. - mRenderFeatureMask &= ~RENDER_FEATURE_AGP; - stop_glerror(); // Enable features - - mUseVBO = gSavedSettings.getBOOL("RenderUseVBO"); - - // Allocate the shared buffers for software skinning - for(S32 i=0; i < mBufferCount; i++) - { - mBufferMemory[i] = new LLAGPArray; - mBufferMemory[i]->reserve_block(AVATAR_VERTEX_BYTES*AVATAR_BUFFER_ELEMENTS); - } - - if (gFeatureManagerp->isFeatureAvailable("RenderAGP")) - { - setUseAGP(gSavedSettings.getBOOL("RenderUseAGP") && gGLManager.mHasAnyAGP); - } - else - { - setUseAGP(FALSE); - } - stop_glerror(); - - for(S32 i=0; i < mBufferCount; i++) - { - if (!mBufferMemory[i]->isAGP() && usingAGP()) - { - llwarns << "pipeline buffer memory is non-AGP when AGP available!" << llendl; - } - } - + setShaders(); } @@ -327,7 +315,17 @@ void LLPipeline::cleanup() { pool_set_t::iterator curiter = iter++; LLDrawPool* poolp = *curiter; - if (poolp->mReferences.empty()) + if (poolp->isFacePool()) + { + LLFacePool* face_pool = (LLFacePool*) poolp; + if (face_pool->mReferences.empty()) + { + mPools.erase(curiter); + removeFromQuickLookup( poolp ); + delete poolp; + } + } + else { mPools.erase(curiter); removeFromQuickLookup( poolp ); @@ -335,10 +333,6 @@ void LLPipeline::cleanup() } } - if (!mSimplePools.empty()) - { - llwarns << "Simple Pools not cleaned up" << llendl; - } if (!mTerrainPools.empty()) { llwarns << "Terrain Pools not cleaned up" << llendl; @@ -347,208 +341,105 @@ void LLPipeline::cleanup() { llwarns << "Tree Pools not cleaned up" << llendl; } - if (!mTreeNewPools.empty()) - { - llwarns << "TreeNew Pools not cleaned up" << llendl; - } - if (!mBumpPools.empty()) - { - llwarns << "Bump Pools not cleaned up" << llendl; - } + delete mAlphaPool; mAlphaPool = NULL; + delete mAlphaPoolPostWater; + mAlphaPoolPostWater = NULL; delete mSkyPool; mSkyPool = NULL; delete mStarsPool; mStarsPool = NULL; - delete mCloudsPool; - mCloudsPool = NULL; delete mTerrainPool; mTerrainPool = NULL; delete mWaterPool; mWaterPool = NULL; delete mGroundPool; mGroundPool = NULL; - delete mHUDPool; - mHUDPool = NULL; - - mBloomImagep = NULL; - mBloomImage2p = NULL; - mFaceSelectImagep = NULL; - mAlphaSizzleImagep = NULL; + delete mSimplePool; + mSimplePool = NULL; + delete mBumpPool; + mBumpPool = NULL; - for(S32 i=0; i < mBufferCount; i++) + if (mCubeBuffer) { - delete mBufferMemory[i]; - mBufferMemory[i] = NULL; + delete mCubeBuffer; + mCubeBuffer = NULL; } - delete mObjectPartition; - mObjectPartition = NULL; - - if (mAGPMemPool && mGlobalFence) + if (mCubeList) { - mAGPMemPool->deleteFence(mGlobalFence); - mGlobalFence = 0; + glDeleteLists(mCubeList, 1); + mCubeList = 0; } - delete mAGPMemPool; - mAGPMemPool = NULL; -} -//============================================================================ - -BOOL LLPipeline::initAGP() -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - mAGPMemPool = LLAGPMemPool::createPool(sAGPMaxPoolSize, mUseVBO); + mBloomImagep = NULL; + mBloomImage2p = NULL; + mFaceSelectImagep = NULL; + mAlphaSizzleImagep = NULL; - if (!mAGPMemPool) - { - llinfos << "Warning! Couldn't allocate AGP memory!" << llendl; - llinfos << "Disabling AGP!" << llendl; - mAGPMemPool = NULL; - mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag - return FALSE; - } - else if (!mAGPMemPool->getSize()) - { - llinfos << "Warning! Unable to allocate AGP memory! Disabling AGP" << llendl; - delete mAGPMemPool; - mAGPMemPool = NULL; - mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag - return FALSE; - } - else + for (S32 i = 0; i < NUM_PARTITIONS-1; i++) { - llinfos << "Allocated " << mAGPMemPool->getSize() << " bytes of AGP memory" << llendl; - mAGPMemPool->bind(); - - if (mAGPMemPool->getSize() < MIN_AGP_SIZE) - { - llwarns << "Not enough AGP memory!" << llendl; - delete mAGPMemPool; - mAGPMemPool = NULL; - mRenderFeatureMask &= ~RENDER_FEATURE_AGP; // Need to disable the using AGP flag - return FALSE; - } - - - if (mAGPMemPool) - { - // Create the fence that we use for global synchronization. - mGlobalFence = mAGPMemPool->createFence(); - } - return TRUE; + delete mObjectPartition[i]; } + mObjectPartition.clear(); + mVisibleList.clear(); + mVisibleGroups.clear(); + mDrawableGroups.clear(); + mActiveGroups.clear(); + mVisibleBridge.clear(); + mMovedBridge.clear(); + mOccludedBridge.clear(); + mAlphaGroups.clear(); + clearRenderMap(); } -void LLPipeline::cleanupAGP() -{ - int i; - for(i=0; i < mBufferCount; i++) - { - mBufferMemory[i]->deleteFence(mBufferFence[i]); - mBufferMemory[i]->setUseAGP(FALSE); - } - - flushAGPMemory(); - if (mAGPMemPool && mGlobalFence) - { - mAGPMemPool->deleteFence(mGlobalFence); - mGlobalFence = 0; - } - delete mAGPMemPool; - mAGPMemPool = NULL; -} +//============================================================================ -BOOL LLPipeline::usingAGP() const +void LLPipeline::destroyGL() { - return (mRenderFeatureMask & RENDER_FEATURE_AGP) ? TRUE : FALSE; -} + stop_glerror(); + unloadShaders(); + mHighlightFaces.clear(); + mVisibleList.clear(); + mVisibleGroups.clear(); + mDrawableGroups.clear(); + mActiveGroups.clear(); + mVisibleBridge.clear(); + mOccludedBridge.clear(); + mAlphaGroups.clear(); + clearRenderMap(); + resetVertexBuffers(); -void LLPipeline::setUseAGP(const BOOL use_agp) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - if (use_agp == usingAGP()) + if (mCubeBuffer) { - return; + delete mCubeBuffer; + mCubeBuffer = NULL; } - else if (use_agp) - { - mRenderFeatureMask |= RENDER_FEATURE_AGP; - initAGP(); - // Forces us to allocate an AGP memory block immediately. - int i; - for(i=0; i < mBufferCount; i++) - { - mBufferMemory[i]->setUseAGP(use_agp); - mBufferMemory[i]->realloc(mBufferMemory[i]->getMax()); - mBufferFence[i] = mBufferMemory[i]->createFence(); - } - - // Must be done AFTER you initialize AGP - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->setUseAGP(use_agp); - } - } - else + if (mCubeList) { - unbindAGP(); - mRenderFeatureMask &= ~RENDER_FEATURE_AGP; - - // Must be done BEFORE you blow away AGP - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->setUseAGP(use_agp); - } - - int i; - for(i=0; i < mBufferCount; i++) - { - if (mBufferMemory[i]) - { - mBufferMemory[i]->setUseAGP(use_agp); - mBufferMemory[i]->deleteFence(mBufferFence[i]); - mBufferFence[i] = 0; - } - else - { - llerrs << "setUseAGP without buffer memory" << llendl; - } - } - - cleanupAGP(); + glDeleteLists(mCubeList, 1); + mCubeList = 0; } - -} - -//============================================================================ - -void LLPipeline::destroyGL() -{ - setUseAGP(FALSE); - stop_glerror(); - unloadShaders(); - mHighlightFaces.reset(); } void LLPipeline::restoreGL() { + resetVertexBuffers(); + if (mVertexShadersEnabled) { setShaders(); } - if (mObjectPartition) + for (U32 i = 0; i < mObjectPartition.size()-1; i++) { - mObjectPartition->restoreGL(); + if (mObjectPartition[i]) + { + mObjectPartition[i]->restoreGL(); + } } } @@ -616,8 +507,8 @@ GLhandleARB LLPipeline::loadShader(const LLString& filename, S32 cls, GLenum typ fname << gDirUtilp->getExpandedFilename(LL_PATH_APP_SETTINGS, "shaders/class"); fname << gpu_class << "/" << filename; - llinfos << "Looking in " << fname.str().c_str() << llendl; - file = fopen(fname.str().c_str(), "r"); +// llinfos << "Looking in " << fname.str().c_str() << llendl; + file = fopen(fname.str().c_str(), "r"); /* Flawfinder: ignore */ if (file) { break; // done @@ -791,6 +682,11 @@ BOOL LLPipeline::validateProgramObject(GLhandleARB obj) void LLPipeline::setShaders() { + sDynamicReflections = gSavedSettings.getBOOL("RenderDynamicReflections"); + + //hack to reset buffers that change behavior with shaders + resetVertexBuffers(); + if (gViewerWindow) { gViewerWindow->setCursor(UI_CURSOR_WAIT); @@ -809,6 +705,8 @@ void LLPipeline::setShaders() { S32 light_class = 2; S32 env_class = 2; + S32 obj_class = 0; + if (getLightingDetail() == 0) { light_class = 1; @@ -818,7 +716,11 @@ void LLPipeline::setShaders() mMaxVertexShaderLevel[SHADER_LIGHTING] = light_class; mVertexShaderLevel[SHADER_ENVIRONMENT] = env_class; mMaxVertexShaderLevel[SHADER_ENVIRONMENT] = env_class; + mVertexShaderLevel[SHADER_OBJECT] = obj_class; + mMaxVertexShaderLevel[SHADER_OBJECT] = obj_class; + BOOL loaded = loadShadersLighting(); + if (loaded) { mVertexShadersEnabled = TRUE; @@ -826,7 +728,7 @@ void LLPipeline::setShaders() // Load all shaders to set max levels loadShadersEnvironment(); - + loadShadersObject(); // Load max avatar shaders to set the max level mVertexShaderLevel[SHADER_AVATAR] = 3; mMaxVertexShaderLevel[SHADER_AVATAR] = 3; @@ -898,6 +800,7 @@ BOOL LLPipeline::canUseVertexShaders() void LLPipeline::unloadShaders() { mObjectSimpleProgram.unload(); + mObjectShinyProgram.unload(); mObjectBumpProgram.unload(); mObjectAlphaProgram.unload(); mWaterProgram.unload(); @@ -939,7 +842,8 @@ BOOL LLPipeline::loadShaders() light_class = 2; // Use medium lighting shader } mVertexShaderLevel[SHADER_LIGHTING] = light_class; - mVertexShaderLevel[SHADER_OBJECT] = llmin(mMaxVertexShaderLevel[SHADER_OBJECT], gSavedSettings.getS32("VertexShaderLevelObject")); + //mVertexShaderLevel[SHADER_OBJECT] = llmin(mMaxVertexShaderLevel[SHADER_OBJECT], gSavedSettings.getS32("VertexShaderLevelObject")); + mVertexShaderLevel[SHADER_OBJECT] = 0; mVertexShaderLevel[SHADER_AVATAR] = llmin(mMaxVertexShaderLevel[SHADER_AVATAR], gSavedSettings.getS32("VertexShaderLevelAvatar")); mVertexShaderLevel[SHADER_ENVIRONMENT] = llmin(mMaxVertexShaderLevel[SHADER_ENVIRONMENT], gSavedSettings.getS32("VertexShaderLevelEnvironment")); mVertexShaderLevel[SHADER_INTERFACE] = mMaxVertexShaderLevel[SHADER_INTERFACE]; @@ -1120,12 +1024,14 @@ BOOL LLPipeline::loadShadersObject() if (mVertexShaderLevel[SHADER_OBJECT] == 0) { + mObjectShinyProgram.unload(); mObjectSimpleProgram.unload(); mObjectBumpProgram.unload(); mObjectAlphaProgram.unload(); return FALSE; } - + +#if 0 if (success) { //load object (volume/tree) vertex shader @@ -1186,6 +1092,28 @@ BOOL LLPipeline::loadShadersObject() llwarns << "Failed to load " << alphavertex << llendl; } } +#endif + + if (success) + { + //load shiny vertex shader + std::string shinyvertex = "objects/shinyV.glsl"; + std::string shinyfragment = "objects/shinyF.glsl"; + mObjectShinyProgram.mProgramObject = glCreateProgramObjectARB(); + mObjectShinyProgram.attachObjects(baseObjects, baseCount); + mObjectShinyProgram.attachObject(loadShader(shinyvertex, SHADER_OBJECT, GL_VERTEX_SHADER_ARB)); + mObjectShinyProgram.attachObject(loadShader(shinyfragment, SHADER_OBJECT, GL_FRAGMENT_SHADER_ARB)); + + success = mObjectShinyProgram.mapAttributes(); + if (success) + { + success = mObjectShinyProgram.mapUniforms(LLPipeline::sShinyUniforms, LLPipeline::sShinyUniformCount); + } + if( !success ) + { + llwarns << "Failed to load " << shinyvertex << llendl; + } + } if( !success ) { @@ -1342,11 +1270,11 @@ void LLPipeline::enableShadows(const BOOL enable_shadows) S32 LLPipeline::getMaxLightingDetail() const { - if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) + /*if (mVertexShaderLevel[SHADER_OBJECT] >= LLDrawPoolSimple::SHADER_LEVEL_LOCAL_LIGHTS) { return 3; } - else + else*/ { return 1; } @@ -1376,79 +1304,62 @@ S32 LLPipeline::setLightingDetail(S32 level) return mLightingDetail; } -LLAGPMemBlock *LLPipeline::allocAGPFromPool(const S32 bytes, const U32 target) +class LLOctreeDirtyTexture : public LLOctreeTraveler { - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - if (!mAGPMemPool) - { - llwarns << "Attempting to allocate AGP memory when AGP disabled!" << llendl; - return NULL; - } - else +public: + const std::set& mTextures; + + LLOctreeDirtyTexture(const std::set& textures) : mTextures(textures) { } + + virtual void visit(const LLOctreeState* state) { - if (mUseVBO) + LLSpatialGroup* group = (LLSpatialGroup*) state->getNode()->getListener(0); + + if (!group->isState(LLSpatialGroup::GEOM_DIRTY) && !group->getData().empty()) { - return ((LLAGPMemPoolARB*) mAGPMemPool)->allocBlock(bytes, target); + for (LLSpatialGroup::draw_map_t::iterator i = group->mDrawMap.begin(); i != group->mDrawMap.end(); ++i) + { + for (std::vector::iterator j = i->second.begin(); j != i->second.end(); ++j) + { + LLDrawInfo* params = *j; + if (mTextures.find(params->mTexture) != mTextures.end()) + { + group->setState(LLSpatialGroup::GEOM_DIRTY); + } + } + } } - else + + for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) { - return mAGPMemPool->allocBlock(bytes); + LLSpatialBridge* bridge = *i; + traverse(bridge->mOctree); } } -} - - -void LLPipeline::unbindAGP() -{ - if (mAGPMemPool && mAGPBound) - { - mAGPMemPool->disable(); - mAGPBound = FALSE; - } -} - -void LLPipeline::bindAGP() -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - if (mAGPMemPool && !mAGPBound && usingAGP()) - { - mAGPMemPool->enable(); - mAGPBound = TRUE; - } -} - -U8* LLPipeline::bufferGetScratchMemory(void) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - return(mBufferMemory[mBufferIndex]->getScratchMemory()); -} - -void LLPipeline::bufferWaitFence(void) -{ - mBufferMemory[mBufferIndex]->waitFence(mBufferFence[mBufferIndex]); -} - -void LLPipeline::bufferSendFence(void) -{ - mBufferMemory[mBufferIndex]->sendFence(mBufferFence[mBufferIndex]); -} +}; -void LLPipeline::bufferRotate(void) +// Called when a texture changes # of channels (causes faces to move to alpha pool) +void LLPipeline::dirtyPoolObjectTextures(const std::set& textures) { - mBufferIndex++; - if(mBufferIndex >= mBufferCount) - mBufferIndex = 0; -} + // *TODO: This is inefficient and causes frame spikes; need a better way to do this + // Most of the time is spent in dirty.traverse. -// Called when a texture changes # of channels (rare, may cause faces to move to alpha pool) -void LLPipeline::dirtyPoolObjectTextures(const LLViewerImage *texturep) -{ for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { LLDrawPool *poolp = *iter; - poolp->dirtyTexture(texturep); + if (poolp->isFacePool()) + { + ((LLFacePool*) poolp)->dirtyTextures(textures); + } + } + + LLOctreeDirtyTexture dirty(textures); + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i]) + { + dirty.traverse(mObjectPartition[i]->mOctree); + } } } @@ -1458,33 +1369,29 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) switch( type ) { case LLDrawPool::POOL_SIMPLE: - poolp = get_if_there(mSimplePools, (uintptr_t)tex0, (LLDrawPool*)0 ); + poolp = mSimplePool; break; case LLDrawPool::POOL_TREE: poolp = get_if_there(mTreePools, (uintptr_t)tex0, (LLDrawPool*)0 ); break; - case LLDrawPool::POOL_TREE_NEW: - poolp = get_if_there(mTreeNewPools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - case LLDrawPool::POOL_TERRAIN: poolp = get_if_there(mTerrainPools, (uintptr_t)tex0, (LLDrawPool*)0 ); break; case LLDrawPool::POOL_BUMP: - poolp = get_if_there(mBumpPools, (uintptr_t)tex0, (LLDrawPool*)0 ); - break; - - case LLDrawPool::POOL_MEDIA: - poolp = get_if_there(mMediaPools, (uintptr_t)tex0, (LLDrawPool*)0 ); + poolp = mBumpPool; break; case LLDrawPool::POOL_ALPHA: poolp = mAlphaPool; break; + case LLDrawPool::POOL_ALPHA_POST_WATER: + poolp = mAlphaPoolPostWater; + break; + case LLDrawPool::POOL_AVATAR: break; // Do nothing @@ -1496,10 +1403,6 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) poolp = mStarsPool; break; - case LLDrawPool::POOL_CLOUDS: - poolp = mCloudsPool; - break; - case LLDrawPool::POOL_WATER: poolp = mWaterPool; break; @@ -1508,10 +1411,6 @@ LLDrawPool *LLPipeline::findPool(const U32 type, LLViewerImage *tex0) poolp = mGroundPool; break; - case LLDrawPool::POOL_HUD: - poolp = mHUDPool; - break; - default: llassert(0); llerrs << "Invalid Pool Type in LLPipeline::findPool() type=" << type << llendl; @@ -1542,29 +1441,37 @@ LLDrawPool *LLPipeline::getPool(const U32 type, LLViewerImage *tex0) LLDrawPool* LLPipeline::getPoolFromTE(const LLTextureEntry* te, LLViewerImage* imagep) { LLMemType mt(LLMemType::MTYPE_PIPELINE); + U32 type = getPoolTypeFromTE(te, imagep); + return gPipeline.getPool(type, imagep); +} + +//static +U32 LLPipeline::getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + + if (!te || !imagep) + { + return 0; + } + bool alpha = te->getColor().mV[3] < 0.999f; if (imagep) { alpha = alpha || (imagep->getComponents() == 4) || (imagep->getComponents() == 2); } -#if 0 // Not currently used - if (te->getMediaFlags() == LLTextureEntry::MF_WEB_PAGE) - { - return gPipeline.getPool(LLDrawPool::POOL_MEDIA, imagep); - } - else -#endif + if (alpha) { - return gPipeline.getPool(LLDrawPool::POOL_ALPHA); + return LLDrawPool::POOL_ALPHA; } else if ((te->getBumpmap() || te->getShiny())) { - return gPipeline.getPool(LLDrawPool::POOL_BUMP, imagep); + return LLDrawPool::POOL_BUMP; } else { - return gPipeline.getPool(LLDrawPool::POOL_SIMPLE, imagep); + return LLDrawPool::POOL_SIMPLE; } } @@ -1595,14 +1502,20 @@ void LLPipeline::allocDrawable(LLViewerObject *vobj) } -void LLPipeline::unlinkDrawable(LLDrawable *drawablep) +void LLPipeline::unlinkDrawable(LLDrawable *drawable) { LLFastTimer t(LLFastTimer::FTM_PIPELINE); + + LLPointer drawablep = drawable; // make sure this doesn't get deleted before we are done // Based on flags, remove the drawable from the queues that it's on. if (drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - mMovedList.erase(drawablep); + LLDrawable::drawable_vector_t::iterator iter = std::find(mMovedList.begin(), mMovedList.end(), drawablep); + if (iter != mMovedList.end()) + { + mMovedList.erase(iter); + } } if (drawablep->getSpatialGroup()) @@ -1632,9 +1545,6 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) llassert(drawablep); - //mCompleteSet.put(drawable); - //gResyncObjects = TRUE; - if (vobj->getParent()) { vobj->setDrawableParent(((LLViewerObject*)vobj->getParent())->mDrawable); // LLPipeline::addObject 1 @@ -1644,28 +1554,6 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) vobj->setDrawableParent(NULL); // LLPipeline::addObject 2 } - - if ((!drawablep->getVOVolume()) && - (vobj->getPCode() != LLViewerObject::LL_VO_SKY) && - (vobj->getPCode() != LLViewerObject::LL_VO_STARS) && - (vobj->getPCode() != LLViewerObject::LL_VO_GROUND)) - { - drawablep->getSpatialPartition()->put(drawablep); - if (!drawablep->getSpatialGroup()) - { -#ifdef LL_RELEASE_FOR_DOWNLOAD - llwarns << "Failure adding drawable to object partition!" << llendl; -#else - llerrs << "Failure adding drawable to object partition!" << llendl; -#endif - } - } - else - { - markMoved(drawablep); - } - - markMaterialed(drawablep); markRebuild(drawablep, LLDrawable::REBUILD_ALL, TRUE); return 1; @@ -1674,11 +1562,27 @@ U32 LLPipeline::addObject(LLViewerObject *vobj) void LLPipeline::resetFrameStats() { + mCompilesStat.addValue(sCompiles); + mLightingChangesStat.addValue(mLightingChanges); + mGeometryChangesStat.addValue(mGeometryChanges); + mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); + mVerticesRelitStat.addValue(mVerticesRelit); + mNumVisibleFacesStat.addValue(mNumVisibleFaces); + mNumVisibleDrawablesStat.addValue((S32)mVisibleList.size()); + + mTrianglesDrawn = 0; sCompiles = 0; mVerticesRelit = 0; mLightingChanges = 0; mGeometryChanges = 0; mNumVisibleFaces = 0; + + if (mOldRenderDebugMask != mRenderDebugMask) + { + gObjectList.clearDebugText(); + mOldRenderDebugMask = mRenderDebugMask; + } + } //external functions for asynchronous updating @@ -1703,7 +1607,7 @@ void LLPipeline::updateMoveDampedAsync(LLDrawable* drawablep) // Put on move list so that EARLY_MOVE gets cleared if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - mMovedList.insert(drawablep); + mMovedList.push_back(drawablep); drawablep->setState(LLDrawable::ON_MOVE_LIST); } } @@ -1729,28 +1633,17 @@ void LLPipeline::updateMoveNormalAsync(LLDrawable* drawablep) // Put on move list so that EARLY_MOVE gets cleared if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - mMovedList.insert(drawablep); + mMovedList.push_back(drawablep); drawablep->setState(LLDrawable::ON_MOVE_LIST); } } -void LLPipeline::updateMove() +void LLPipeline::updateMovedList(LLDrawable::drawable_vector_t& moved_list) { - mObjectPartition->mOctree->validate(); - LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - if (gSavedSettings.getBOOL("FreezeTime")) + for (LLDrawable::drawable_vector_t::iterator iter = moved_list.begin(); + iter != moved_list.end(); ) { - return; - } - - mMoveChangesStat.addValue((F32)mMovedList.size()); - - for (LLDrawable::drawable_set_t::iterator iter = mMovedList.begin(); - iter != mMovedList.end(); ) - { - LLDrawable::drawable_set_t::iterator curiter = iter++; + LLDrawable::drawable_vector_t::iterator curiter = iter++; LLDrawable *drawablep = *curiter; BOOL done = TRUE; if (!drawablep->isDead() && (!drawablep->isState(LLDrawable::EARLY_MOVE))) @@ -1760,10 +1653,36 @@ void LLPipeline::updateMove() drawablep->clearState(LLDrawable::EARLY_MOVE | LLDrawable::MOVE_UNDAMPED); if (done) { - mMovedList.erase(curiter); drawablep->clearState(LLDrawable::ON_MOVE_LIST); + iter = moved_list.erase(curiter); + } + } +} + +void LLPipeline::updateMove() +{ + //LLFastTimer t(LLFastTimer::FTM_UPDATE_MOVE); + LLMemType mt(LLMemType::MTYPE_PIPELINE); + + if (gSavedSettings.getBOOL("FreezeTime")) + { + return; + } + + mMoveChangesStat.addValue((F32)mMovedList.size()); + + for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); + iter != mRetexturedList.end(); ++iter) + { + LLDrawable* drawablep = *iter; + if (drawablep && !drawablep->isDead()) + { + drawablep->updateTexture(); } } + mRetexturedList.clear(); + + updateMovedList(mMovedList); for (LLDrawable::drawable_set_t::iterator iter = mActiveQ.begin(); iter != mActiveQ.end(); ) @@ -1772,7 +1691,8 @@ void LLPipeline::updateMove() LLDrawable* drawablep = *curiter; if (drawablep && !drawablep->isDead()) { - if (drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && + if (drawablep->isRoot() && + drawablep->mQuietCount++ > MAX_ACTIVE_OBJECT_QUIET_FRAMES && (!drawablep->getParent() || !drawablep->getParent()->isActive())) { drawablep->makeStatic(); // removes drawable and its children from mActiveQ @@ -1785,172 +1705,164 @@ void LLPipeline::updateMove() } } - for (LLDrawable::drawable_set_t::iterator iter = mRetexturedList.begin(); - iter != mRetexturedList.end(); ++iter) - { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) - { - drawablep->updateTexture(); - } - } - mRetexturedList.clear(); - - for (LLDrawable::drawable_set_t::iterator iter = mRematerialedList.begin(); - iter != mRematerialedList.end(); ++iter) + //balance octrees { - LLDrawable* drawablep = *iter; - if (drawablep && !drawablep->isDead()) + LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); + for (U32 i = 0; i < mObjectPartition.size()-1; i++) { - drawablep->updateMaterial(); + if (mObjectPartition[i]) + { + mObjectPartition[i]->mOctree->balance(); + } } } - mRematerialedList.clear(); - - if (mObjectPartition->mOctree) - { - //balance octree - LLFastTimer ot(LLFastTimer::FTM_OCTREE_BALANCE); - mObjectPartition->mOctree->validate(); - mObjectPartition->mOctree->balance(); - mObjectPartition->mOctree->validate(); - } } ///////////////////////////////////////////////////////////////////////////// // Culling and occlusion testing ///////////////////////////////////////////////////////////////////////////// -void LLPipeline::updateCull() +//static +F32 LLPipeline::calcPixelArea(LLVector3 center, LLVector3 size, LLCamera &camera) { - LLFastTimer t(LLFastTimer::FTM_CULL); - LLMemType mt(LLMemType::MTYPE_PIPELINE); + LLVector3 lookAt = center - camera.getOrigin(); + F32 dist = lookAt.magVec(); - LLDrawable::incrementVisible(); - mVisibleList.resize(0); - mVisibleList.reserve(ESTIMATED_VISIBLE_OBJECT_COUNT); - - gTrivialAccepts = 0; - - if (mObjectPartition) + //ramp down distance for nearby objects + if (dist < 16.f) { - if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) - { - mObjectPartition->processOcclusion(gCamera); - stop_glerror(); - } - mObjectPartition->cull(*gCamera); + dist /= 16.f; + dist *= dist; + dist *= 16.f; } - - // Hack for avatars - warning - this is really FRAGILE! - djs 05/06/02 - LLVOAvatar::updateAllAvatarVisiblity(); - - // If there are any other hacks here, make sure to add them to the - // standard pick code. - gMinObjectDistance = llclamp(gMinObjectDistance, MIN_NEAR_PLANE, MAX_NEAR_PLANE); + //get area of circle around node + F32 app_angle = atanf(size.magVec()/dist); + F32 radius = app_angle*LLDrawable::sCurPixelAngle; + return radius*radius * 3.14159f; +} - F32 water_height = gAgent.getRegion()->getWaterHeight(); - F32 camera_height = gAgent.getCameraPositionAgent().mV[2]; - if (fabs(camera_height - water_height) < 2.f) - { - gMinObjectDistance = MIN_NEAR_PLANE; - } +void LLPipeline::updateCull(LLCamera& camera) +{ + LLFastTimer t(LLFastTimer::FTM_CULL); + LLMemType mt(LLMemType::MTYPE_PIPELINE); - gCamera->setNear(gMinObjectDistance); + mVisibleList.clear(); + mVisibleGroups.clear(); + mDrawableGroups.clear(); + mActiveGroups.clear(); + gTrivialAccepts = 0; + mVisibleBridge.clear(); - // Disable near clip stuff for now... + processOcclusion(camera); - // now push it back out to max value - gMinObjectDistance = MIN_NEAR_PLANE; + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType)) + { + mObjectPartition[i]->cull(camera); + } + } if (gSky.mVOSkyp.notNull() && gSky.mVOSkyp->mDrawable.notNull()) { // Hack for sky - always visible. - gSky.mVOSkyp->mDrawable->setVisible(*gCamera); - mVisibleList.push_back(gSky.mVOSkyp->mDrawable); - gSky.updateCull(); - stop_glerror(); + if (hasRenderType(LLPipeline::RENDER_TYPE_SKY)) + { + gSky.mVOSkyp->mDrawable->setVisible(camera); + mVisibleList.push_back(gSky.mVOSkyp->mDrawable); + gSky.updateCull(); + stop_glerror(); + } } else { llinfos << "No sky drawable!" << llendl; } - if (gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull()) + if (hasRenderType(LLPipeline::RENDER_TYPE_GROUND) && gSky.mVOGroundp.notNull() && gSky.mVOGroundp->mDrawable.notNull()) { - gSky.mVOGroundp->mDrawable->setVisible(*gCamera); + gSky.mVOGroundp->mDrawable->setVisible(camera); mVisibleList.push_back(gSky.mVOGroundp->mDrawable); } +} - // add all HUD attachments - LLVOAvatar* my_avatarp = gAgent.getAvatarObject(); - if (my_avatarp && my_avatarp->hasHUDAttachment()) +void LLPipeline::markNotCulled(LLSpatialGroup* group, LLCamera& camera, BOOL active) +{ + if (group->getData().empty()) + { + return; + } + + if (!sSkipUpdate) { - for (LLViewerJointAttachment* attachmentp = my_avatarp->mAttachmentPoints.getFirstData(); - attachmentp; - attachmentp = my_avatarp->mAttachmentPoints.getNextData()) - { - if (attachmentp->getIsHUDAttachment() && attachmentp->getObject(0)) - { - LLViewerObject* objectp = attachmentp->getObject(0); - markVisible(objectp->mDrawable); - objectp->mDrawable->updateDistance(*gCamera); - for (S32 i = 0; i < (S32)objectp->mChildList.size(); i++) - { - LLViewerObject* childp = objectp->mChildList[i]; - if (childp->mDrawable.notNull()) - { - markVisible(childp->mDrawable); - childp->mDrawable->updateDistance(*gCamera); - } - } - } - } + group->updateDistance(camera); } -} + + const F32 MINIMUM_PIXEL_AREA = 16.f; -void LLPipeline::markNotCulled(LLDrawable* drawablep, LLCamera& camera) -{ - if (drawablep->isVisible()) + if (group->mPixelArea < MINIMUM_PIXEL_AREA) { return; } - // Tricky render mode to hide selected objects, but we definitely - // don't want to do any unnecessary pointer dereferences. JC - if (gHideSelectedObjects) - { - if (drawablep->getVObj() && drawablep->getVObj()->isSelected()) + group->mLastRenderTime = gFrameTimeSeconds; + if (!group->mSpatialPartition->mRenderByGroup) + { //render by drawable + mDrawableGroups.push_back(group); + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { - return; + markVisible(*i, camera); } } - - if (drawablep && (hasRenderType(drawablep->mRenderType))) - { - if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) + else + { //render by group + if (active) { - mVisibleList.push_back(drawablep); - drawablep->setVisible(camera, NULL, FALSE); + mActiveGroups.push_back(group); } - else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) + else { - // clear invisible flag here to avoid single frame glitch - drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); + mVisibleGroups.push_back(group); + for (LLSpatialGroup::bridge_list_t::iterator i = group->mBridgeList.begin(); i != group->mBridgeList.end(); ++i) + { + LLSpatialBridge* bridge = *i; + markVisible(bridge, camera); + } } } } -void LLPipeline::doOcclusion() +void LLPipeline::doOcclusion(LLCamera& camera) { - if (gSavedSettings.getBOOL("UseOcclusion") && gGLManager.mHasOcclusionQuery) + if (sUseOcclusion) { - mObjectPartition->doOcclusion(gCamera); + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType)) + { + mObjectPartition[i]->doOcclusion(&camera); + } + } + +#if AGGRESSIVE_OCCLUSION + for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + glPushMatrix(); + glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + LLCamera trans = bridge->transformCamera(camera); + bridge->doOcclusion(&trans); + glPopMatrix(); + mOccludedBridge.push_back(bridge); + } + } +#endif } } - BOOL LLPipeline::updateDrawableGeom(LLDrawable* drawablep, BOOL priority) { BOOL update_complete = drawablep->updateGeometry(priority); @@ -1975,19 +1887,31 @@ void LLPipeline::updateGeom(F32 max_dtime) LLVOVolume::preUpdateGeom(); // Iterate through all drawables on the priority build queue, - for (LLDrawable::drawable_set_t::iterator iter = mBuildQ1.begin(); + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ1.begin(); iter != mBuildQ1.end();) { - LLDrawable::drawable_set_t::iterator curiter = iter++; + LLDrawable::drawable_list_t::iterator curiter = iter++; LLDrawable* drawablep = *curiter; - BOOL update_complete = TRUE; if (drawablep && !drawablep->isDead()) { - update_complete = updateDrawableGeom(drawablep, TRUE); + if (drawablep->isState(LLDrawable::IN_REBUILD_Q2)) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q2); + LLDrawable::drawable_list_t::iterator find = std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep); + if (find != mBuildQ2.end()) + { + mBuildQ2.erase(find); + } + } + + if (updateDrawableGeom(drawablep, TRUE)) + { + drawablep->clearState(LLDrawable::IN_REBUILD_Q1); + mBuildQ1.erase(curiter); + } } - if (update_complete) + else { - drawablep->clearState(LLDrawable::IN_REBUILD_Q1); mBuildQ1.erase(curiter); } } @@ -1998,20 +1922,34 @@ void LLPipeline::updateGeom(F32 max_dtime) { min_count = mBuildQ2.size(); } - else - { - mBuildQ2.sort(LLDrawable::CompareDistanceGreaterVisibleFirst()); - } - + S32 count = 0; max_dtime = llmax(update_timer.getElapsedTimeF32()+0.001f, max_dtime); - + LLSpatialGroup* last_group = NULL; + LLSpatialBridge* last_bridge = NULL; + for (LLDrawable::drawable_list_t::iterator iter = mBuildQ2.begin(); iter != mBuildQ2.end(); ) { LLDrawable::drawable_list_t::iterator curiter = iter++; LLDrawable* drawablep = *curiter; + + LLSpatialBridge* bridge = drawablep->isRoot() ? drawablep->getSpatialBridge() : + drawablep->getParent()->getSpatialBridge(); + + if (drawablep->getSpatialGroup() != last_group && + (!last_bridge || bridge != last_bridge) && + (update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count) + { + break; + } + + //make sure updates don't stop in the middle of a spatial group + //to avoid thrashing (objects are enqueued by group) + last_group = drawablep->getSpatialGroup(); + last_bridge = bridge; + BOOL update_complete = TRUE; if (drawablep && !drawablep->isDead()) { @@ -2023,14 +1961,12 @@ void LLPipeline::updateGeom(F32 max_dtime) drawablep->clearState(LLDrawable::IN_REBUILD_Q2); mBuildQ2.erase(curiter); } - if ((update_timer.getElapsedTimeF32() >= max_dtime) && count > min_count) - { - break; - } - } + } + + updateMovedList(mMovedBridge); } -void LLPipeline::markVisible(LLDrawable *drawablep) +void LLPipeline::markVisible(LLDrawable *drawablep, LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); if(!drawablep || drawablep->isDead()) @@ -2038,11 +1974,36 @@ void LLPipeline::markVisible(LLDrawable *drawablep) llwarns << "LLPipeline::markVisible called with NULL drawablep" << llendl; return; } - if (!drawablep->isVisible()) + + +#if LL_DEBUG + if (drawablep->isSpatialBridge()) + { + if (std::find(mVisibleBridge.begin(), mVisibleBridge.end(), (LLSpatialBridge*) drawablep) != + mVisibleBridge.end()) + { + llerrs << "Spatial bridge marked visible redundantly." << llendl; + } + } + else + { + if (std::find(mVisibleList.begin(), mVisibleList.end(), drawablep) != + mVisibleList.end()) + { + llerrs << "Drawable marked visible redundantly." << llendl; + } + } +#endif + + if (drawablep->isSpatialBridge()) + { + mVisibleBridge.push_back((LLSpatialBridge*) drawablep); + } + else { - drawablep->setVisible(*gCamera); mVisibleList.push_back(drawablep); } + drawablep->setVisible(camera); } void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) @@ -2066,10 +2027,17 @@ void LLPipeline::markMoved(LLDrawable *drawablep, BOOL damped_motion) markMoved(drawablep->getParent(), damped_motion); } - + if (!drawablep->isState(LLDrawable::ON_MOVE_LIST)) { - mMovedList.insert(drawablep); + if (drawablep->isSpatialBridge()) + { + mMovedBridge.push_back(drawablep); + } + else + { + mMovedList.push_back(drawablep); + } drawablep->setState(LLDrawable::ON_MOVE_LIST); } if (damped_motion == FALSE) @@ -2118,30 +2086,28 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) } mShiftList.resize(0); - mObjectPartition->shift(offset); -} - -void LLPipeline::markTextured(LLDrawable *drawablep) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!drawablep->isDead()) + for (U32 i = 0; i < mObjectPartition.size()-1; i++) { - mRetexturedList.insert(drawablep); + if (mObjectPartition[i]) + { + mObjectPartition[i]->shift(offset); + } } } -void LLPipeline::markMaterialed(LLDrawable *drawablep) +void LLPipeline::markTextured(LLDrawable *drawablep) { LLMemType mt(LLMemType::MTYPE_PIPELINE); - if (!drawablep->isDead()) + if (drawablep && !drawablep->isDead()) { - mRematerialedList.insert(drawablep); + mRetexturedList.insert(drawablep); } } void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag, BOOL priority) { LLMemType mt(LLMemType::MTYPE_PIPELINE); + if (drawablep && !drawablep->isDead()) { if (!drawablep->isState(LLDrawable::BUILT)) @@ -2150,15 +2116,18 @@ void LLPipeline::markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags f } if (priority) { - mBuildQ1.insert(drawablep); - drawablep->setState(LLDrawable::IN_REBUILD_Q1); // flag is not needed, just for debugging + if (!drawablep->isState(LLDrawable::IN_REBUILD_Q1)) + { + mBuildQ1.push_back(drawablep); + drawablep->setState(LLDrawable::IN_REBUILD_Q1); // mark drawable as being in priority queue + } } else if (!drawablep->isState(LLDrawable::IN_REBUILD_Q2)) { mBuildQ2.push_back(drawablep); drawablep->setState(LLDrawable::IN_REBUILD_Q2); // need flag here because it is just a list } - if (flag & LLDrawable::REBUILD_VOLUME) + if (flag & (LLDrawable::REBUILD_VOLUME | LLDrawable::REBUILD_POSITION)) { drawablep->getVObj()->setChanged(LLXform::SILHOUETTE); } @@ -2185,111 +2154,400 @@ void LLPipeline::markRelight(LLDrawable *drawablep, const BOOL priority) } } -void LLPipeline::stateSort() +void LLPipeline::stateSort(LLCamera& camera) { LLFastTimer ftm(LLFastTimer::FTM_STATESORT); LLMemType mt(LLMemType::MTYPE_PIPELINE); + for (LLSpatialGroup::sg_vector_t::iterator iter = mVisibleGroups.begin(); iter != mVisibleGroups.end(); ++iter) + { + stateSort(*iter, camera); + } + + for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead()) + { + stateSort(bridge, camera); + } + } + for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); iter != mVisibleList.end(); iter++) { LLDrawable *drawablep = *iter; - if (drawablep->isDead()) + if (!drawablep->isDead()) { - continue; + stateSort(drawablep, camera); } + } + + for (LLSpatialGroup::sg_vector_t::iterator iter = mActiveGroups.begin(); iter != mActiveGroups.end(); ++iter) + { + stateSort(*iter, camera); + } + + postSort(camera); +} - if (!drawablep->isActive()) +void LLPipeline::stateSort(LLSpatialGroup* group, LLCamera& camera) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + if (!sSkipUpdate && group->changeLOD()) + { + for (LLSpatialGroup::element_iter i = group->getData().begin(); i != group->getData().end(); ++i) { - drawablep->updateDistance(*gCamera); + LLDrawable* drawablep = *i; + stateSort(drawablep, camera); } + } + +#if !LL_DARWIN + if (gFrameTimeSeconds - group->mLastUpdateTime > 4.f) + { + group->makeStatic(); + } +#endif +} - /* - if (!drawablep->isState(LLDrawable::BUILT)) +void LLPipeline::stateSort(LLSpatialBridge* bridge, LLCamera& camera) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + if (!sSkipUpdate) + { + bridge->updateDistance(camera); + } +} + +void LLPipeline::stateSort(LLDrawable* drawablep, LLCamera& camera) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + LLFastTimer ftm(LLFastTimer::FTM_STATESORT_DRAWABLE); + + if (drawablep->isDead() || !hasRenderType(drawablep->getRenderType())) + { + return; + } + + if (gHideSelectedObjects) + { + if (drawablep->getVObj() && + drawablep->getVObj()->isSelected()) { - // This geometry hasn't been rebuilt but it's visible, make sure it gets put on the rebuild list. - llerrs << "Visible object " << drawablep << ":" << drawablep->getVObj()->getPCodeString(); - llcont << " visible but not built, put on rebuild" << llendl; - markRebuild(drawablep); - continue; + return; } - */ + } - for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); - iter != drawablep->mFaces.end(); iter++) + if (drawablep && (hasRenderType(drawablep->mRenderType))) + { + if (!drawablep->isState(LLDrawable::INVISIBLE|LLDrawable::FORCE_INVISIBLE)) { - LLFace* facep = *iter; - if (facep->hasGeometry()) - { - facep->getPool()->enqueue(facep); - } + drawablep->setVisible(camera, NULL, FALSE); } - - if (sRenderPhysicalBeacons) - { - // Only show the beacon on the root object. - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - && !vobj->getParent() - && vobj->usePhysics()) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); - } + else if (drawablep->isState(LLDrawable::CLEAR_INVISIBLE)) + { + // clear invisible flag here to avoid single frame glitch + drawablep->clearState(LLDrawable::FORCE_INVISIBLE|LLDrawable::CLEAR_INVISIBLE); } + } - if (sRenderScriptedBeacons) + if (!drawablep->isActive() && drawablep->isVisible()) + { + if (!sSkipUpdate) { - // Only show the beacon on the root object. - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && !vobj->isAvatar() - && !vobj->getParent() - && vobj->flagScripted()) - { - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); - } + drawablep->updateDistance(camera); } + } + else if (drawablep->isAvatar() && drawablep->isVisible()) + { + LLVOAvatar* vobj = (LLVOAvatar*) drawablep->getVObj(); + vobj->updateVisibility(FALSE); + } + + for (LLDrawable::face_list_t::iterator iter = drawablep->mFaces.begin(); + iter != drawablep->mFaces.end(); iter++) + { + LLFace* facep = *iter; - if (sRenderParticleBeacons) + if (facep->hasGeometry()) { - // Look for attachments, objects, etc. - LLViewerObject *vobj = drawablep->getVObj(); - if (vobj - && vobj->isParticleSource()) + if (facep->getPool()) + { + facep->getPool()->enqueue(facep); + } + else { - LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); - gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f)); + break; } } + } + + + mNumVisibleFaces += drawablep->getNumFaces(); +} + + +void LLPipeline::forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*)) +{ + for (LLSpatialGroup::sg_vector_t::iterator i = groups.begin(); i != groups.end(); ++i) + { + for (LLSpatialGroup::element_iter j = (*i)->getData().begin(); j != (*i)->getData().end(); ++j) + { + func(*j); + } + } +} + +void LLPipeline::forAllVisibleDrawables(void (*func)(LLDrawable*)) +{ + forAllDrawables(mDrawableGroups, func); + forAllDrawables(mVisibleGroups, func); + forAllDrawables(mActiveGroups, func); +} + +//function for creating scripted beacons +void renderScriptedBeacons(LLDrawable* drawablep) +{ + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->flagScripted()) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(1.f, 0.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); + } +} + +void renderPhysicalBeacons(LLDrawable* drawablep) +{ + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && !vobj->isAvatar() + && !vobj->getParent() + && vobj->usePhysics()) + { + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", LLColor4(0.f, 1.f, 0.f, 0.5f), LLColor4(1.f, 1.f, 1.f, 0.5f)); + } +} + +void renderParticleBeacons(LLDrawable* drawablep) +{ + // Look for attachments, objects, etc. + LLViewerObject *vobj = drawablep->getVObj(); + if (vobj + && vobj->isParticleSource()) + { + LLColor4 light_blue(0.5f, 0.5f, 1.f, 0.5f); + gObjectList.addDebugBeacon(vobj->getPositionAgent(), "", light_blue, LLColor4(1.f, 1.f, 1.f, 0.5f)); + } +} + +void LLPipeline::highlightPhysical(LLDrawable* drawablep) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + LLViewerObject *vobj; + vobj = drawablep->getVObj(); + if (vobj && !vobj->isAvatar()) + { + if (!vobj->isAvatar() && + (vobj->usePhysics() || vobj->flagHandleTouch())) + { + S32 face_id; + for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) + { + gPipeline.mHighlightFaces.push_back(drawablep->getFace(face_id) ); + } + } + } +} + +void LLPipeline::postSort(LLCamera& camera) +{ + LLMemType mt(LLMemType::MTYPE_PIPELINE); + LLFastTimer ftm(LLFastTimer::FTM_STATESORT_POSTSORT); + //reset render data sets + clearRenderMap(); + mAlphaGroups.clear(); + mAlphaGroupsPostWater.clear(); + + if (!gSavedSettings.getBOOL("RenderRippleWater") && hasRenderType(LLDrawPool::POOL_ALPHA)) + { //turn off clip plane for non-ripple water + toggleRenderType(LLDrawPool::POOL_ALPHA); + } + + F32 water_height = gAgent.getRegion()->getWaterHeight(); + BOOL above_water = gCamera->getOrigin().mV[2] > water_height ? TRUE : FALSE; + + //prepare occlusion geometry + if (sUseOcclusion) + { + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType)) + { + mObjectPartition[i]->buildOcclusion(); + } + } + +#if AGGRESSIVE_OCCLUSION + for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + bridge->buildOcclusion(); + } + } +#endif + } + + + if (!sSkipUpdate) + { + //rebuild drawable geometry + for (LLSpatialGroup::sg_vector_t::iterator i = mDrawableGroups.begin(); i != mDrawableGroups.end(); ++i) + { + LLSpatialGroup* group = *i; + group->rebuildGeom(); + } + } - // Draw physical objects in red. - if (gHUDManager->getShowPhysical()) + //build render map + for (LLSpatialGroup::sg_vector_t::iterator i = mVisibleGroups.begin(); i != mVisibleGroups.end(); ++i) + { + LLSpatialGroup* group = *i; + if (!sSkipUpdate) + { + group->rebuildGeom(); + } + for (LLSpatialGroup::draw_map_t::iterator j = group->mDrawMap.begin(); j != group->mDrawMap.end(); ++j) { - LLViewerObject *vobj; - vobj = drawablep->getVObj(); - if (vobj && !vobj->isAvatar()) + std::vector& src_vec = j->second; + std::vector& dest_vec = mRenderMap[j->first]; + + for (std::vector::iterator k = src_vec.begin(); k != src_vec.end(); ++k) + { + dest_vec.push_back(*k); + } + } + + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); + + if (alpha != group->mDrawMap.end()) + { //store alpha groups for sorting + if (!sSkipUpdate) + { + group->updateDistance(camera); + } + + if (hasRenderType(LLDrawPool::POOL_ALPHA)) { - if (!vobj->isAvatar() && - (vobj->usePhysics() || vobj->flagHandleTouch())) + BOOL above = group->mObjectBounds[0].mV[2] + group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE; + BOOL below = group->mObjectBounds[0].mV[2] - group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE; + + if (below == above_water || above == below) { - if (!drawablep->isVisible()) - { - // Skip objects that aren't visible. - continue; - } - S32 face_id; - for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) - { - mHighlightFaces.put(drawablep->getFace(face_id) ); - } + mAlphaGroups.push_back(group); + } + + if (above == above_water || below == above) + { + mAlphaGroupsPostWater.push_back(group); } } + else + { + mAlphaGroupsPostWater.push_back(group); + } } - - mNumVisibleFaces += drawablep->getNumFaces(); } + //store active alpha groups + for (LLSpatialGroup::sg_vector_t::iterator i = mActiveGroups.begin(); i != mActiveGroups.end(); ++i) + { + LLSpatialGroup* group = *i; + if (!sSkipUpdate) + { + group->rebuildGeom(); + } + LLSpatialGroup::draw_map_t::iterator alpha = group->mDrawMap.find(LLRenderPass::PASS_ALPHA); + + if (alpha != group->mDrawMap.end()) + { + LLSpatialBridge* bridge = group->mSpatialPartition->asBridge(); + LLCamera trans_camera = bridge->transformCamera(camera); + if (!sSkipUpdate) + { + group->updateDistance(trans_camera); + } + + if (hasRenderType(LLDrawPool::POOL_ALPHA)) + { + LLSpatialGroup* bridge_group = bridge->getSpatialGroup(); + BOOL above = bridge_group->mObjectBounds[0].mV[2] + bridge_group->mObjectBounds[1].mV[2] > water_height ? TRUE : FALSE; + BOOL below = bridge_group->mObjectBounds[0].mV[2] - bridge_group->mObjectBounds[1].mV[2] < water_height ? TRUE : FALSE; + + + if (below == above_water || above == below) + { + mAlphaGroups.push_back(group); + } + + if (above == above_water || below == above) + { + mAlphaGroupsPostWater.push_back(group); + } + } + else + { + mAlphaGroupsPostWater.push_back(group); + } + } + } + + //sort by texture or bump map + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; ++i) + { + if (!mRenderMap[i].empty()) + { + if (i == LLRenderPass::PASS_BUMP) + { + std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareBump()); + } + else + { + std::sort(mRenderMap[i].begin(), mRenderMap[i].end(), LLDrawInfo::CompareTexturePtr()); + } + } + } + + std::sort(mAlphaGroups.begin(), mAlphaGroups.end(), LLSpatialGroup::CompareDepthGreater()); + std::sort(mAlphaGroupsPostWater.begin(), mAlphaGroupsPostWater.end(), LLSpatialGroup::CompareDepthGreater()); + + if (sRenderScriptedBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderScriptedBeacons); + } + + if (sRenderPhysicalBeacons) + { + // Only show the beacon on the root object. + forAllVisibleDrawables(renderPhysicalBeacons); + } + + if (sRenderParticleBeacons) + { + forAllVisibleDrawables(renderParticleBeacons); + } + + // Draw physical objects in red. + if (gHUDManager->getShowPhysical()) + { + forAllVisibleDrawables(highlightPhysical); + } + // If god mode, also show audio cues if (sRenderSoundBeacons && gAudiop) { @@ -2312,66 +2570,19 @@ void LLPipeline::stateSort() LLFloaterTelehub::addBeacons(); } - mSelectedFaces.reset(); + mSelectedFaces.clear(); // Draw face highlights for selected faces. if (gSelectMgr->getTEMode()) { LLViewerObject *vobjp; S32 te; - gSelectMgr->getFirstTE(&vobjp,&te); + gSelectMgr->getSelection()->getFirstTE(&vobjp,&te); while (vobjp) { - LLDrawable *drawablep = vobjp->mDrawable; - if (!drawablep || drawablep->isDead() || (!vobjp->isHUDAttachment() && !drawablep->isVisible())) - { - llwarns << "Dead drawable on selected face list!" << llendl; - } - else - { - LLVOVolume *volp = drawablep->getVOVolume(); - if (volp) - { - if (volp->getAllTEsSame()) - { - SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); - faceinfo->mFacep = drawablep->getFace(vobjp->getFaceIndexOffset()); - faceinfo->mTE = te; - } - else - { - // This is somewhat inefficient, but works correctly. - S32 face_id; - for (face_id = 0; face_id < vobjp->getVolume()->getNumFaces(); face_id++) - { - LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset()); - if (te == facep->getTEOffset()) - { - SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); - faceinfo->mFacep = facep; - faceinfo->mTE = -1; - } - } - } - } - else - { - // This is somewhat inefficient, but works correctly. - S32 face_id; - for (face_id = 0; face_id < drawablep->getNumFaces(); face_id++) - { - LLFace *facep = drawablep->getFace(face_id + vobjp->getFaceIndexOffset()); - if (te == facep->getTEOffset()) - { - SelectedFaceInfo* faceinfo = mSelectedFaces.reserve_block(1); - faceinfo->mFacep = facep; - faceinfo->mTE = -1; - } - } - } - } - gSelectMgr->getNextTE(&vobjp,&te); + mSelectedFaces.push_back(vobjp->mDrawable->getFace(te)); + gSelectMgr->getSelection()->getNextTE(&vobjp,&te); } } } @@ -2383,13 +2594,13 @@ static void render_hud_elements() gPipeline.disableLights(); gPipeline.renderDebug(); - + LLGLDisable fog(GL_FOG); LLGLSUIDefault gls_ui; if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI)) { - gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD bersion in render_ui_3d() + gViewerWindow->renderSelections(FALSE, FALSE, FALSE); // For HUD version in render_ui_3d() // Draw the tracking overlays LLTracker::render3D(); @@ -2404,7 +2615,7 @@ static void render_hud_elements() gParcelMgr->render(); gParcelMgr->renderParcelCollision(); } - + // Render debugging beacons. gObjectList.renderObjectBeacons(); LLHUDObject::renderAll(); @@ -2415,11 +2626,15 @@ static void render_hud_elements() // This is only set when not rendering the UI, for parcel snapshots gParcelMgr->render(); } - + else if (gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_HUD)) + { + LLHUDText::renderAllHUD(); + } } void LLPipeline::renderHighlights() { + LLMemType mt(LLMemType::MTYPE_PIPELINE); // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) // Render highlighted faces. LLColor4 color(1.f, 1.f, 1.f, 0.5f); @@ -2441,48 +2656,15 @@ void LLPipeline::renderHighlights() } mFaceSelectImagep->addTextureStats((F32)MAX_IMAGE_AREA); - for (S32 i = 0; i < mSelectedFaces.count(); i++) + for (U32 i = 0; i < mSelectedFaces.size(); i++) { - LLFace *facep = mSelectedFaces[i].mFacep; + LLFace *facep = mSelectedFaces[i]; if (!facep || facep->getDrawable()->isDead()) { llerrs << "Bad face on selection" << llendl; } - LLDrawPool* poolp = facep->getPool(); - - if (!poolp->canUseAGP()) - { - unbindAGP(); - } - else if (usingAGP()) - { - bindAGP(); - } - - if (mSelectedFaces[i].mTE == -1) - { - // Yes, I KNOW this is stupid... - poolp->renderFaceSelected(facep, mFaceSelectImagep, color); - } - else - { - LLVOVolume *volp = (LLVOVolume *)facep->getViewerObject(); - // Do the special coalesced face mode. - S32 j; - S32 offset = 0; - S32 count = volp->getVolume()->getVolumeFace(0).mIndices.size(); - for (j = 0; j <= mSelectedFaces[i].mTE; j++) - { - count = volp->getVolume()->getVolumeFace(j).mIndices.size(); - if (j < mSelectedFaces[i].mTE) - { - offset += count; - } - } - - poolp->renderFaceSelected(facep, mFaceSelectImagep, color, offset, count); - } + facep->renderSelected(mFaceSelectImagep, color); } } @@ -2490,26 +2672,16 @@ void LLPipeline::renderHighlights() { // Paint 'em red! color.setVec(1.f, 0.f, 0.f, 0.5f); - for (S32 i = 0; i < mHighlightFaces.count(); i++) + for (U32 i = 0; i < mHighlightFaces.size(); i++) { LLFace* facep = mHighlightFaces[i]; - LLDrawPool* poolp = facep->getPool(); - if (!poolp->canUseAGP()) - { - unbindAGP(); - } - else if (usingAGP()) - { - bindAGP(); - } - - poolp->renderFaceSelected(facep, LLViewerImage::sNullImagep, color); + facep->renderSelected(LLViewerImage::sNullImagep, color); } } // Contains a list of the faces of objects that are physical or // have touch-handlers. - mHighlightFaces.reset(); + mHighlightFaces.clear(); if (mVertexShaderLevel[SHADER_INTERFACE] > 0) { @@ -2517,11 +2689,11 @@ void LLPipeline::renderHighlights() } } -void LLPipeline::renderGeom() +void LLPipeline::renderGeom(LLCamera& camera) { LLMemType mt(LLMemType::MTYPE_PIPELINE); LLFastTimer t(LLFastTimer::FTM_RENDER_GEOMETRY); - + if (!mAlphaSizzleImagep) { mAlphaSizzleImagep = gImageList.getImage(LLUUID(gViewerArt.getString("alpha_sizzle.tga")), MIPMAP_TRUE, TRUE); @@ -2533,6 +2705,8 @@ void LLPipeline::renderGeom() // // + glEnableClientState(GL_VERTEX_ARRAY); + stop_glerror(); gFrameStats.start(LLFrameStats::RENDER_SYNC); @@ -2540,6 +2714,7 @@ void LLPipeline::renderGeom() #ifndef LL_RELEASE_FOR_DOWNLOAD LLGLState::checkStates(); LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); #endif if (mRenderDebugMask & RENDER_DEBUG_VERIFY) { @@ -2549,27 +2724,23 @@ void LLPipeline::renderGeom() } } - if (mAGPMemPool) { - mAGPMemPool->waitFence(mGlobalFence); + //LLFastTimer ftm(LLFastTimer::FTM_TEMP6); + LLVertexBuffer::startRender(); } - unbindAGP(); for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { LLDrawPool *poolp = *iter; if (hasRenderType(poolp->getType())) { poolp->prerender(); - poolp->syncAGP(); } } gFrameStats.start(LLFrameStats::RENDER_GEOM); // Initialize lots of GL state to "safe" values - mTrianglesDrawn = 0; - glMatrixMode(GL_TEXTURE); glLoadIdentity(); glMatrixMode(GL_MODELVIEW); @@ -2577,13 +2748,13 @@ void LLPipeline::renderGeom() LLGLSPipeline gls_pipeline; LLGLState gls_color_material(GL_COLOR_MATERIAL, mLightingDetail < 2); - LLGLState normalize(GL_NORMALIZE, TRUE); + // LLGLState normalize(GL_NORMALIZE, TRUE); // Toggle backface culling for debugging LLGLEnable cull_face(mBackfaceCull ? GL_CULL_FACE : 0); // Set fog LLGLEnable fog_enable(hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_FOG) ? GL_FOG : 0); - + gSky.updateFog(camera.getFar()); LLViewerImage::sDefaultImagep->bind(0); LLViewerImage::sDefaultImagep->setClamp(FALSE, FALSE); @@ -2592,19 +2763,20 @@ void LLPipeline::renderGeom() // // Actually render all of the geometry // - // - + // stop_glerror(); - BOOL non_agp = FALSE; BOOL did_hud_elements = FALSE; - + BOOL occlude = sUseOcclusion; + U32 cur_type = 0; - S32 skipped_vertices = 0; + if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PICKING)) + { + gObjectList.renderObjectsForSelect(camera); + } + else { LLFastTimer t(LLFastTimer::FTM_POOLS); - BOOL occlude = TRUE; - calcNearbyLights(); pool_set_t::iterator iter1 = mPools.begin(); @@ -2614,80 +2786,27 @@ void LLPipeline::renderGeom() cur_type = poolp->getType(); - if (cur_type >= LLDrawPool::POOL_TREE && occlude) - { //all the occluders have been drawn, do occlusion queries - if (mVertexShadersEnabled) - { - glUseProgramObjectARB(0); - } - doOcclusion(); + if (occlude && cur_type > LLDrawPool::POOL_AVATAR) + { occlude = FALSE; + doOcclusion(camera); } - - if (cur_type >= LLDrawPool::POOL_HUD && !did_hud_elements) + + if (cur_type > LLDrawPool::POOL_ALPHA_POST_WATER && !did_hud_elements) { renderHighlights(); // Draw 3D UI elements here (before we clear the Z buffer in POOL_HUD) - if (mVertexShadersEnabled) - { - glUseProgramObjectARB(0); - } render_hud_elements(); did_hud_elements = TRUE; } pool_set_t::iterator iter2 = iter1; - if (hasRenderType(poolp->getType())) + if (hasRenderType(poolp->getType()) && poolp->getNumPasses() > 0) { LLFastTimer t(LLFastTimer::FTM_POOLRENDER); setupHWLights(poolp); - - if (mVertexShadersEnabled && poolp->getVertexShaderLevel() == 0) - { - glUseProgramObjectARB(0); - } - else if (mVertexShadersEnabled) - { - mMaterialIndex = mSpecularIndex = 0; - switch(cur_type) - { - case LLDrawPool::POOL_SKY: - case LLDrawPool::POOL_STARS: - case LLDrawPool::POOL_CLOUDS: - glUseProgramObjectARB(0); - break; - case LLDrawPool::POOL_TERRAIN: - mTerrainProgram.bind(); - break; - case LLDrawPool::POOL_GROUND: - mGroundProgram.bind(); - break; - case LLDrawPool::POOL_TREE: - case LLDrawPool::POOL_TREE_NEW: - case LLDrawPool::POOL_SIMPLE: - case LLDrawPool::POOL_MEDIA: - mObjectSimpleProgram.bind(); - break; - case LLDrawPool::POOL_BUMP: - mObjectBumpProgram.bind(); - break; - case LLDrawPool::POOL_AVATAR: - glUseProgramObjectARB(0); - break; - case LLDrawPool::POOL_WATER: - glUseProgramObjectARB(0); - break; - case LLDrawPool::POOL_ALPHA: - mObjectAlphaProgram.bind(); - break; - case LLDrawPool::POOL_HUD: - default: - glUseProgramObjectARB(0); - break; - } - } - + for( S32 i = 0; i < poolp->getNumPasses(); i++ ) { poolp->beginRenderPass(i); @@ -2698,33 +2817,19 @@ void LLPipeline::renderGeom() { break; } - if (p->getType() != LLDrawPool::POOL_AVATAR - && p->getType() != LLDrawPool::POOL_ALPHA - && p->getType() != LLDrawPool::POOL_HUD - && (!p->getIndexCount() || !p->getVertexCount())) - { - continue; - } - - if (p->canUseAGP() && usingAGP()) - { - bindAGP(); - } - else - { - //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl; - unbindAGP(); - non_agp = TRUE; - } - + p->resetTrianglesDrawn(); p->render(i); mTrianglesDrawn += p->getTrianglesDrawn(); - skipped_vertices += p->mSkippedVertices; - p->mSkippedVertices = 0; } poolp->endRenderPass(i); #ifndef LL_RELEASE_FOR_DOWNLOAD + GLint depth; + glGetIntegerv(GL_MODELVIEW_STACK_DEPTH, &depth); + if (depth > 3) + { + llerrs << "GL matrix stack corrupted!" << llendl; + } LLGLState::checkStates(); LLGLState::checkTextureChannels(); LLGLState::checkClientArrays(); @@ -2746,21 +2851,18 @@ void LLPipeline::renderGeom() iter1 = iter2; stop_glerror(); } - - if (occlude) - { - if (mVertexShadersEnabled) - { - glUseProgramObjectARB(0); - } - doOcclusion(); - } } - stop_glerror(); - - if (mVertexShadersEnabled) + +#ifndef LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); +#endif + + if (occlude) { - glUseProgramObjectARB(0); + doOcclusion(camera); + occlude = FALSE; } if (!did_hud_elements) @@ -2768,32 +2870,49 @@ void LLPipeline::renderGeom() renderHighlights(); render_hud_elements(); } + + stop_glerror(); - static S32 agp_mix_count = 0; - if (non_agp && usingAGP()) - { - if (0 == agp_mix_count % 16) - { - lldebugs << "Mixing AGP and non-AGP pools, slow!" << llendl; - } - agp_mix_count++; - } - else { - agp_mix_count = 0; + LLVertexBuffer::stopRender(); } - + +#ifndef LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); +#endif + // Contains a list of the faces of objects that are physical or // have touch-handlers. - mHighlightFaces.reset(); + mHighlightFaces.clear(); +} - // This wait is in case we try to do multiple renders of a frame, - // I don't know what happens when we send a fence multiple times without - // checking it. - if (mAGPMemPool) +void LLPipeline::processOcclusion(LLCamera& camera) +{ + //process occlusion (readback) + if (sUseOcclusion) { - mAGPMemPool->waitFence(mGlobalFence); - mAGPMemPool->sendFence(mGlobalFence); + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType)) + { + mObjectPartition[i]->processOcclusion(&camera); + } + } + +#if AGGRESSIVE_OCCLUSION + for (LLSpatialBridge::bridge_vector_t::iterator i = mOccludedBridge.begin(); i != mOccludedBridge.end(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + LLCamera trans = bridge->transformCamera(camera); + bridge->processOcclusion(&trans); + } + } +#endif + mOccludedBridge.clear(); } } @@ -2802,13 +2921,30 @@ void LLPipeline::renderDebug() LLMemType mt(LLMemType::MTYPE_PIPELINE); // Disable all client state - glDisableClientState(GL_VERTEX_ARRAY); - glDisableClientState(GL_TEXTURE_COORD_ARRAY); + glDisableClientState(GL_TEXTURE_COORD_ARRAY); glDisableClientState(GL_NORMAL_ARRAY); - glDisableClientState(GL_VERTEX_ARRAY); + glDisableClientState(GL_COLOR_ARRAY); // Debug stuff. - mObjectPartition->renderDebug(); + for (U32 i = 0; i < mObjectPartition.size(); i++) + { + if (mObjectPartition[i] && hasRenderType(mObjectPartition[i]->mDrawableType)) + { + mObjectPartition[i]->renderDebug(); + } + } + + for (LLSpatialBridge::bridge_vector_t::iterator i = mVisibleBridge.begin(); i != mVisibleBridge.end(); ++i) + { + LLSpatialBridge* bridge = *i; + if (!bridge->isDead() && hasRenderType(bridge->mDrawableType)) + { + glPushMatrix(); + glMultMatrixf((F32*)bridge->mDrawable->getRenderMatrix().mMatrix); + bridge->renderDebug(); + glPopMatrix(); + } + } if (mRenderDebugMask & LLPipeline::RENDER_DEBUG_LIGHT_TRACE) { @@ -2855,81 +2991,6 @@ void LLPipeline::renderDebug() } } - mCompilesStat.addValue(sCompiles); - mLightingChangesStat.addValue(mLightingChanges); - mGeometryChangesStat.addValue(mGeometryChanges); - mTrianglesDrawnStat.addValue(mTrianglesDrawn/1000.f); - mVerticesRelitStat.addValue(mVerticesRelit); - mNumVisibleFacesStat.addValue(mNumVisibleFaces); - mNumVisibleDrawablesStat.addValue((S32)mVisibleList.size()); - - if (gRenderLightGlows) - { - displaySSBB(); - } - - /*if (mRenderDebugMask & RENDER_DEBUG_BBOXES) - { - LLGLSPipelineAlpha gls_pipeline_alpha; - LLGLSNoTexture no_texture; - - for (LLDrawable::drawable_vector_t::iterator iter = mVisibleList.begin(); iter != mVisibleList.end(); iter++) - { - LLDrawable *drawablep = *iter; - if (drawablep->isDead()) - { - continue; - } - LLVector3 min, max; - - if (drawablep->getVObj() && drawablep->getVObj()->getPCode() == LLViewerObject::LL_VO_SURFACE_PATCH) - { - // Render drawable bbox - drawablep->getBounds(min, max); - glColor4f(0.f, 1.f, 0.f, 0.25f); - render_bbox(min, max); - - // Render object bbox - LLVector3 scale = drawablep->getVObj()->getScale(); - LLVector3 pos = drawablep->getVObj()->getPositionAgent(); - min = pos - scale * 0.5f; - max = pos + scale * 0.5f; - glColor4f(1.f, 0.f, 0.f, 0.25f); - render_bbox(min, max); - } - } - }*/ - - /* - // Debugging code for parcel sound. - F32 x, y; - - LLGLSNoTexture gls_no_texture; - - glBegin(GL_POINTS); - if (gAgent.getRegion()) - { - // Draw the composition layer for the region that I'm in. - for (x = 0; x <= 260; x++) - { - for (y = 0; y <= 260; y++) - { - if (gParcelMgr->isSoundLocal(gAgent.getRegion()->getOriginGlobal() + LLVector3d(x, y, 0.f))) - { - glColor4f(1.f, 0.f, 0.f, 1.f); - } - else - { - glColor4f(0.f, 0.f, 1.f, 1.f); - } - - glVertex3f(x, y, gAgent.getRegion()->getLandHeightRegion(LLVector3(x, y, 0.f))); - } - } - } - glEnd(); - */ - if (mRenderDebugMask & RENDER_DEBUG_COMPOSITION) { // Debug composition layers @@ -2962,358 +3023,163 @@ void LLPipeline::renderDebug() } glEnd(); } - - if (mRenderDebugMask & RENDER_DEBUG_AGP_MEM) - { - displayAGP(); - } - - if (mRenderDebugMask & RENDER_DEBUG_POOLS) - { - displayPools(); - } - -// if (mRenderDebugMask & RENDER_DEBUG_QUEUES) -// { -// displayQueues(); -// } - - if (mRenderDebugMask & RENDER_DEBUG_MAP) - { - displayMap(); - } } - - - -BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max) +void LLPipeline::renderForSelect(std::set& objects) { - min.setVec(1000,1000); - max.setVec(-1000,-1000); - - if (box.mMatrix[3][3] <= 0.0f) return FALSE; + LLMemType mt(LLMemType::MTYPE_PIPELINE); + + LLVertexBuffer::startRender(); + + glMatrixMode(GL_MODELVIEW); - const F32 vec[8][3] = { - { -0.5f,-0.5f,-0.5f }, - { -0.5f,-0.5f,+0.5f }, - { -0.5f,+0.5f,-0.5f }, - { -0.5f,+0.5f,+0.5f }, - { +0.5f,-0.5f,-0.5f }, - { +0.5f,-0.5f,+0.5f }, - { +0.5f,+0.5f,-0.5f }, - { +0.5f,+0.5f,+0.5f } }; - - LLVector4 v; + LLGLSDefault gls_default; + LLGLSObjectSelect gls_object_select; + LLGLDepthTest gls_depth(GL_TRUE,GL_TRUE); + disableLights(); + + glEnableClientState ( GL_VERTEX_ARRAY ); - for (S32 i=0;i<8;i++) + //for each drawpool +#ifndef LL_RELEASE_FOR_DOWNLOAD + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + U32 last_type = 0; +#endif + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { - v.setVec(vec[i][0],vec[i][1],vec[i][2],1); - v = v * box; - F32 iw = 1.0f / v.mV[3]; - v.mV[0] *= iw; - v.mV[1] *= iw; - - min.mV[0] = llmin(min.mV[0],v.mV[0]); - max.mV[0] = llmax(max.mV[0],v.mV[0]); - - min.mV[1] = llmin(min.mV[1],v.mV[1]); - max.mV[1] = llmax(max.mV[1],v.mV[1]); + LLDrawPool *poolp = *iter; + if (poolp->isFacePool() && hasRenderType(poolp->getType())) + { + LLFacePool* face_pool = (LLFacePool*) poolp; + face_pool->renderForSelect(); + +#ifndef LL_RELEASE_FOR_DOWNLOAD + if (poolp->getType() != last_type) + { + last_type = poolp->getType(); + LLGLState::checkStates(); + LLGLState::checkTextureChannels(); + LLGLState::checkClientArrays(); + } +#endif + } } - /* - min.mV[0] = max.mV[0] = box.mMatrix[3][0]; - min.mV[1] = max.mV[1] = box.mMatrix[3][1]; - F32 iw = 1.0f / box.mMatrix[3][3]; - - F32 f0 = (fabs(box.mMatrix[0][0])+fabs(box.mMatrix[1][0])+fabs(box.mMatrix[2][0])) * 0.5f; - F32 f1 = (fabs(box.mMatrix[0][1])+fabs(box.mMatrix[1][1])+fabs(box.mMatrix[2][1])) * 0.5f; - F32 f2 = (fabs(box.mMatrix[0][2])+fabs(box.mMatrix[1][2])+fabs(box.mMatrix[2][2])) * 0.5f; - - min.mV[0] -= f0; - min.mV[1] -= f1; - - max.mV[0] += f0; - max.mV[1] += f1; - - min.mV[0] *= iw; - min.mV[1] *= iw; - - max.mV[0] *= iw; - max.mV[1] *= iw; - */ - return TRUE; -} - -void LLPipeline::displaySSBB() -{ - LLMatrix4 proj; - LLMatrix4 cfr(OGL_TO_CFR_ROTATION); - LLMatrix4 camera; - LLMatrix4 comb; - - gCamera->getMatrixToLocal(camera); - - if (!mBloomImagep) + LLGLEnable tex(GL_TEXTURE_2D); + glEnableClientState(GL_TEXTURE_COORD_ARRAY); + LLGLEnable alpha_test(GL_ALPHA_TEST); + if (gPickTransparent) { - mBloomImagep = gImageList.getImage(IMG_BLOOM1); + glAlphaFunc(GL_GEQUAL, 0.0f); + } + else + { + glAlphaFunc(GL_GREATER, 0.2f); } - // don't write to depth buffer with light glows so that chat bubbles can pop through - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - LLViewerImage::bindTexture(mBloomImagep); - - glGetFloatv(GL_PROJECTION_MATRIX,(float*)proj.mMatrix); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_COMBINE_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_RGB_ARB, GL_REPLACE); + glTexEnvi(GL_TEXTURE_ENV, GL_COMBINE_ALPHA_ARB, GL_MODULATE); - LLGLSPipelineAlpha gls_pipeline_alpha; + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_RGB_ARB, GL_PRIMARY_COLOR); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_RGB_ARB, GL_SRC_COLOR); - //glScalef(0.25,0.25,0.25); + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE0_ALPHA_ARB, GL_TEXTURE); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND0_ALPHA_ARB, GL_SRC_ALPHA); - S32 sizex = gViewerWindow->getWindowWidth() / 2; - S32 sizey = gViewerWindow->getWindowHeight() / 2; + glTexEnvi(GL_TEXTURE_ENV, GL_SOURCE1_ALPHA_ARB, GL_PRIMARY_COLOR_ARB); + glTexEnvi(GL_TEXTURE_ENV, GL_OPERAND1_ALPHA_ARB, GL_SRC_ALPHA); - F32 aspect = (float)sizey / (float)sizex; + U32 prim_mask = LLVertexBuffer::MAP_VERTEX | + LLVertexBuffer::MAP_TEXCOORD; - for (LLDrawable::drawable_set_t::iterator iter = mLights.begin(); - iter != mLights.end(); iter++) + for (std::set::iterator i = objects.begin(); i != objects.end(); ++i) { - LLDrawable *lightp = *iter; - if (lightp->isDead()) + LLViewerObject* vobj = *i; + LLDrawable* drawable = vobj->mDrawable; + if (vobj->isDead() || + vobj->isHUDAttachment() || + (gHideSelectedObjects && vobj->isSelected()) || + drawable->isDead() || + !hasRenderType(drawable->getRenderType())) { continue; } - - LLMatrix4 mat = lightp->mXform.getWorldMatrix(); - mat *= camera; - mat *= cfr; - mat *= proj; - - U8 color[64]; - - LLVector2 min,max; - if (mat.mMatrix[3][3] < 160 && compute_min_max(mat,min,max)) + for (S32 j = 0; j < drawable->getNumFaces(); ++j) { - F32 cx = (max.mV[0] + min.mV[0]) * 0.5f; - F32 cy = (max.mV[1] + min.mV[1]) * 0.5f; - F32 sx = (max.mV[0] - min.mV[0]) * 2.0f; - F32 sy = (max.mV[1] - min.mV[1]) * 2.0f; - S32 x = (S32)(cx * (F32)sizex) + sizex; - S32 y = (S32)(cy * (F32)sizey) + sizey; - - if (cx > -1 && cx < 1 && cy > -1 && cy < 1) + LLFace* facep = drawable->getFace(j); + if (!facep->getPool()) { - glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]); - - S32 total = 0; - for (S32 i=0;i<64;i++) - { - total += color[i]; - } - total /= 64; - - sx = (sy = (sx + sy) * 0.5f * ((float)total/255.0f)) * aspect; - - - if (total > 60) - { - color[3+32] = total >> 1; - glBegin(GL_QUADS); - glColor4ubv(&color[32]); - glTexCoord2f(0,0); - glVertex3f(cx-sx,cy-sy,0); - glTexCoord2f(1,0); - glVertex3f(cx+sx,cy-sy,0); - glTexCoord2f(1,1); - glVertex3f(cx+sx,cy+sy,0); - glTexCoord2f(0,1); - glVertex3f(cx-sx,cy+sy,0); - glEnd(); - } + facep->renderForSelect(prim_mask); } } - } - // sun + // pick HUD objects + LLVOAvatar* avatarp = gAgent.getAvatarObject(); + if (avatarp && sShowHUDAttachments) { - LLVector4 sdir(gSky.getSunDirection() * 10000.0f + gAgent.getPositionAgent()); - sdir.mV[3] = 1.0f; - sdir = sdir * camera; - sdir = sdir * cfr; - sdir = sdir * proj; // todo: preconcat + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); - sdir.mV[0] /= sdir.mV[3]; - sdir.mV[1] /= sdir.mV[3]; - - U8 color[64]; - - if (sdir.mV[3] > 0) + setup_hud_matrices(TRUE); + LLViewerJointAttachment* attachmentp; + for (attachmentp = avatarp->mAttachmentPoints.getFirstData(); + attachmentp; + attachmentp = avatarp->mAttachmentPoints.getNextData()) { - F32 cx = sdir.mV[0]; - F32 cy = sdir.mV[1]; - F32 sx, sy; - S32 x = (S32)(cx * (F32)sizex) + sizex; - S32 y = (S32)(cy * (F32)sizey) + sizey; - - if (cx > -1 && cx < 1 && cy > -1 && cy < 1) + if (attachmentp->getIsHUDAttachment()) { - glReadPixels(x-2,y-2,4,4,GL_RGBA,GL_UNSIGNED_BYTE,&color[0]); - - S32 total = 0; - for (S32 i=0;i<64;i++) + LLViewerObject* objectp = attachmentp->getObject(); + if (objectp) { - total += color[i]; - } - total >>= 7; - - sx = (sy = ((float)total/255.0f)) * aspect; - - const F32 fix = -0.1f; + LLDrawable* drawable = objectp->mDrawable; + if (drawable->isDead()) + { + continue; + } - color[32] = (U8)(color[32] * 0.5f + 255 * 0.5f); - color[33] = (U8)(color[33] * 0.5f + 255 * 0.5f); - color[34] = (U8)(color[34] * 0.5f + 255 * 0.5f); + for (S32 j = 0; j < drawable->getNumFaces(); ++j) + { + LLFace* facep = drawable->getFace(j); + if (!facep->getPool()) + { + facep->renderForSelect(prim_mask); + } + } - if (total > 80) - { - color[32+3] = (U8)total; - glBegin(GL_QUADS); - glColor4ubv(&color[32]); - glTexCoord2f(0,0); - glVertex3f(cx-sx,cy-sy+fix,0); - glTexCoord2f(1,0); - glVertex3f(cx+sx,cy-sy+fix,0); - glTexCoord2f(1,1); - glVertex3f(cx+sx,cy+sy+fix,0); - glTexCoord2f(0,1); - glVertex3f(cx-sx,cy+sy+fix,0); - glEnd(); - } + //render child faces + for (U32 k = 0; k < drawable->getChildCount(); ++k) + { + LLDrawable* child = drawable->getChild(k); + for (S32 l = 0; l < child->getNumFaces(); ++l) + { + LLFace* facep = child->getFace(l); + if (!facep->getPool()) + { + facep->renderForSelect(prim_mask); + } + } + } + } } } - } - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - -void LLPipeline::displayMap() -{ - LLGLSPipelineAlpha gls_pipeline_alpha; - LLGLSNoTexture no_texture; - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - - glTranslatef(-1,-1,0); - glScalef(2,2,0); - - glColor4f(0,0,0,0.5); - glBegin(GL_QUADS); - glVertex3f(0,0,0); - glVertex3f(1,0,0); - glVertex3f(1,1,0); - glVertex3f(0,1,0); - glEnd(); - - static F32 totalW = 1.5f; - static F32 offset = 0.5f; - static F32 scale = 1.0f; - - S32 mousex = gViewerWindow->getCurrentMouseX(); - S32 mousey = gViewerWindow->getCurrentMouseY(); - S32 w = gViewerWindow->getWindowWidth(); - S32 h = gViewerWindow->getWindowHeight(); - - if (mousex < 20 && offset > 0) offset -= (20 - mousex) * 0.02f; - if (mousex > (w - 20)) offset += (20 - (w - mousex)) * 0.02f; - if (offset > (totalW-1)) offset = (totalW-1); - - if (mousey < 20 && scale > 0.1) scale -= (20 - mousey) * 0.001f; - if (mousey > (h - 20) && scale < 1.0f) scale += (20 - (h - mousey)) * 0.001f; - glScalef(scale*scale,scale,1); - glTranslatef(-offset,0,0); - //totalW = mStaticTree->render2D(0,0.8f/scale); - //mDynamicTree->render2D(0,0.4f/scale); - - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); - glPopMatrix(); -} - -void LLPipeline::renderForSelect() -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - //for each drawpool - - glMatrixMode(GL_MODELVIEW); - - LLGLSDefault gls_default; - LLGLSObjectSelect gls_object_select; - LLGLDepthTest gls_depth(GL_TRUE); - disableLights(); - - glEnableClientState ( GL_VERTEX_ARRAY ); - glDisableClientState( GL_NORMAL_ARRAY ); - glDisableClientState( GL_TEXTURE_COORD_ARRAY ); - -#ifndef LL_RELEASE_FOR_DOWNLOAD - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - U32 last_type = 0; -#endif - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (poolp->canUseAGP() && usingAGP()) - { - bindAGP(); - } - else - { - //llinfos << "Rendering pool type " << p->getType() << " without AGP!" << llendl; - unbindAGP(); - } - poolp->renderForSelect(); -#ifndef LL_RELEASE_FOR_DOWNLOAD - if (poolp->getType() != last_type) - { - last_type = poolp->getType(); - LLGLState::checkStates(); - LLGLState::checkTextureChannels(); - LLGLState::checkClientArrays(); - } -#endif + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); } - // Disable all of the client state - glDisableClientState( GL_VERTEX_ARRAY ); - - if (mAGPMemPool) - { - mAGPMemPool->waitFence(mGlobalFence); - mAGPMemPool->sendFence(mGlobalFence); - } + glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE); + glDisableClientState( GL_TEXTURE_COORD_ARRAY ); + + LLVertexBuffer::stopRender(); } void LLPipeline::renderFaceForUVSelect(LLFace* facep) @@ -3325,7 +3191,6 @@ void LLPipeline::rebuildPools() { LLMemType mt(LLMemType::MTYPE_PIPELINE); S32 max_count = mPools.size(); - S32 num_rebuilds = 0; pool_set_t::iterator iter1 = mPools.upper_bound(mLastRebuildPool); while(max_count > 0 && mPools.size() > 0) // && num_rebuilds < MAX_REBUILDS) { @@ -3334,8 +3199,8 @@ void LLPipeline::rebuildPools() iter1 = mPools.begin(); } LLDrawPool* poolp = *iter1; - num_rebuilds += poolp->rebuild(); - if (poolp->mReferences.empty()) + + if (poolp->isDead()) { mPools.erase(iter1++); removeFromQuickLookup( poolp ); @@ -3365,27 +3230,35 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) switch( new_poolp->getType() ) { case LLDrawPool::POOL_SIMPLE: - mSimplePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + if (mSimplePool) + { + llassert(0); + llwarns << "Ignoring duplicate simple pool." << llendl; + } + else + { + mSimplePool = (LLRenderPass*) new_poolp; + } break; case LLDrawPool::POOL_TREE: mTreePools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; break; - - case LLDrawPool::POOL_TREE_NEW: - mTreeNewPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; case LLDrawPool::POOL_TERRAIN: mTerrainPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; break; case LLDrawPool::POOL_BUMP: - mBumpPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; - break; - - case LLDrawPool::POOL_MEDIA: - mMediaPools[ uintptr_t(new_poolp->getTexture()) ] = new_poolp ; + if (mBumpPool) + { + llassert(0); + llwarns << "Ignoring duplicate bump pool." << llendl; + } + else + { + mBumpPool = new_poolp; + } break; case LLDrawPool::POOL_ALPHA: @@ -3396,570 +3269,172 @@ void LLPipeline::addToQuickLookup( LLDrawPool* new_poolp ) } else { - mAlphaPool = new_poolp; - } - break; - - case LLDrawPool::POOL_AVATAR: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - if( mSkyPool ) - { - llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl; - } - else - { - mSkyPool = new_poolp; - } - break; - - case LLDrawPool::POOL_STARS: - if( mStarsPool ) - { - llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Stars pool" << llendl; - } - else - { - mStarsPool = new_poolp; - } - break; - - case LLDrawPool::POOL_CLOUDS: - if( mCloudsPool ) - { - llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Clouds pool" << llendl; - } - else - { - mCloudsPool = new_poolp; - } - break; - - case LLDrawPool::POOL_WATER: - if( mWaterPool ) - { - llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl; - } - else - { - mWaterPool = new_poolp; - } - break; - - case LLDrawPool::POOL_GROUND: - if( mGroundPool ) - { - llassert(0); - llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl; - } - else - { - mGroundPool = new_poolp; - } - break; - - case LLDrawPool::POOL_HUD: - if( mHUDPool ) - { - llerrs << "LLPipeline::addPool(): Duplicate HUD Pool!" << llendl; - } - mHUDPool = new_poolp; - break; - - default: - llassert(0); - llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl; - break; - } -} - -void LLPipeline::removePool( LLDrawPool* poolp ) -{ - removeFromQuickLookup(poolp); - mPools.erase(poolp); - delete poolp; -} - -void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - switch( poolp->getType() ) - { - case LLDrawPool::POOL_SIMPLE: - #ifdef _DEBUG - { - BOOL found = mSimplePools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mSimplePools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_TREE: - #ifdef _DEBUG - { - BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTreePools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_TREE_NEW: - #ifdef _DEBUG - { - BOOL found = mTreeNewPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTreeNewPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_TERRAIN: - #ifdef _DEBUG - { - BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_BUMP: - #ifdef _DEBUG - { - BOOL found = mBumpPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mBumpPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_MEDIA: - #ifdef _DEBUG - { - BOOL found = mMediaPools.erase( (uintptr_t)poolp->getTexture() ); - llassert( found ); - } - #else - mMediaPools.erase( (uintptr_t)poolp->getTexture() ); - #endif - break; - - case LLDrawPool::POOL_ALPHA: - llassert( poolp == mAlphaPool ); - mAlphaPool = NULL; - break; - - case LLDrawPool::POOL_AVATAR: - break; // Do nothing - - case LLDrawPool::POOL_SKY: - llassert( poolp == mSkyPool ); - mSkyPool = NULL; - break; - - case LLDrawPool::POOL_STARS: - llassert( poolp == mStarsPool ); - mStarsPool = NULL; - break; - - case LLDrawPool::POOL_CLOUDS: - llassert( poolp == mCloudsPool ); - mCloudsPool = NULL; - break; - - case LLDrawPool::POOL_WATER: - llassert( poolp == mWaterPool ); - mWaterPool = NULL; - break; - - case LLDrawPool::POOL_GROUND: - llassert( poolp == mGroundPool ); - mGroundPool = NULL; - break; - - case LLDrawPool::POOL_HUD: - llassert( poolp == mHUDPool ); - mHUDPool = NULL; - break; - - default: - llassert(0); - llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl; - break; - } -} - -void LLPipeline::flushAGPMemory() -{ - LLMemType mt(LLMemType::MTYPE_PIPELINE); - - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->flushAGP(); - } -} - -void LLPipeline::resetDrawOrders() -{ - // Iterate through all of the draw pools and rebuild them. - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - poolp->resetDrawOrders(); - } -} - -//------------------------------- - - -LLViewerObject *LLPipeline::nearestObjectAt(F32 yaw, F32 pitch) -{ - // Stub to find nearest Object at given yaw and pitch - - /* - LLEdge *vd = NULL; - - if (vd) - { - return (LLViewerObject*)vd->mDrawablep->getVObj(); - } - */ - - return NULL; -} - -void LLPipeline::printPools() -{ - /* - // Iterate through all of the draw pools and rebuild them. - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - if (pool->mTexturep[0]) - { - llinfos << "Op pool " << pool->mTexturep[0]->mID << llendflush; - } - else - { - llinfos << "Opaque pool NULL" << llendflush; - } - llinfos << " Vertices: \t" << pool->getVertexCount() << llendl; - } - - - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - llinfos << "Al pool " << pool; - llcont << " Vertices: \t" << pool->getVertexCount() << llendl; - } - - pool = mHighlightPools.getFirst(); - llinfos << "Si pool " << pool; - llcont << " Vertices: \t" << pool->getVertexCount() << llendl; - */ -} - - -void LLPipeline::displayPools() -{ - // Needs to be fixed to handle chained pools - djs - LLUI::setLineWidth(1.0); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - LLGLSPipelineAlpha gls_pipeline_alpha; - LLGLSNoTexture no_texture; - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - glScalef(2,2,1); - glTranslatef(-0.5f,-0.5f,0); - - F32 x = 0.0f, y = 0.05f; - F32 xs = 0.01f, ys = 0.01f; - F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; - - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLGLSTexture gls_texture; - LLDrawPool *poolp = *iter; - if (poolp->getDebugTexture()) - { - poolp->getDebugTexture()->bind(); - glColor4f(1,1,1,1); - stamp(x,y,xs*4,ys*4); - } - - LLGLSNoTexture no_texture; - - F32 a = 1.f - (F32)poolp->mRebuildTime / (F32)poolp->mRebuildFreq; - glColor4f(a,a,a,1); - stamp(x,y,xs,ys); - - x = (xs + xs2) * 4.0f; - - F32 h = ys * 0.5f; - - S32 total = 0; - - for (std::vector::iterator iter = poolp->mReferences.begin(); - iter != poolp->mReferences.end(); iter++) - { - LLFace *face = *iter; - F32 w = xs; - - if (!face || !face->getDrawable()) - { - w = 16 / 3000.0f; - - stamp(x,y,w,h); - - if (x+w > 0.95f) - { - x = (xs + xs2) * 4.0f; - y += h + ys2; - } - else - { - if (w) x += w + xs2; - } - - continue; - } - - if (face->getDrawable()->isVisible()) - { - if (face->isState(LLFace::BACKLIST)) - { - glColor4f(1,0,1,1); - } - else if (total > poolp->getMaxVertices()) - { - glColor4f(1,0,0,1); - } - else - { - glColor4f(0,1,0,1); - total += face->getGeomCount(); - } - } - else - { - if (face->isState(LLFace::BACKLIST)) - { - glColor4f(0,0,1,1); - } - else - { - glColor4f(1,1,0,1); - } - } - - w = face->getGeomCount() / 3000.0f; - - stamp(x,y,w,h); - - if (x+w > 0.95f) - { - x = (xs + xs2) * 4.0f; - y += h + ys2; - } - else - { - if (w) x += w + xs2; - } - } - - y += ys + ys2; - x = 0; - } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); -} - -static F32 xs = 0.01f, ys = 0.01f; -static F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; -static F32 winx, winy; - -void displayDrawable(F32 &x, F32 &y, LLDrawable *drawable, F32 alpha = 0.5f) -{ - F32 w = 0; - F32 h = ys * 0.5f; - - if (drawable && !drawable->isDead()) - { - for (S32 f=0;f < drawable->getNumFaces(); f++) - { - w += drawable->getFace(f)->getGeomCount() / 30000.0f; + mAlphaPool = new_poolp; } - w+=xs; - glColor4f(1,1,0, alpha); - } - else - { - w = 0.01f; - glColor4f(0,0,0,alpha); - } + break; -// const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF_SMALL ); + case LLDrawPool::POOL_ALPHA_POST_WATER: + if( mAlphaPoolPostWater ) + { + llassert(0); + llwarns << "LLPipeline::addPool(): Ignoring duplicate Alpha pool" << llendl; + } + else + { + mAlphaPoolPostWater = new_poolp; + } + break; -// U8 pcode = drawable->getVObj()->getPCode(); + case LLDrawPool::POOL_AVATAR: + break; // Do nothing - //char *string = (char*)LLPrimitive::pCodeToString(pcode); - //if (pcode == 0x3e) string = "terrain"; - //else if (pcode == 0x2e) string = "cloud"; - //string[3] = 0; + case LLDrawPool::POOL_SKY: + if( mSkyPool ) + { + llassert(0); + llwarns << "LLPipeline::addPool(): Ignoring duplicate Sky pool" << llendl; + } + else + { + mSkyPool = new_poolp; + } + break; - stamp(x * winx,y * winy,w * winx,h * winy); + case LLDrawPool::POOL_STARS: + if( mStarsPool ) + { + llassert(0); + llwarns << "LLPipeline::addPool(): Ignoring duplicate Stars pool" << llendl; + } + else + { + mStarsPool = new_poolp; + } + break; + + case LLDrawPool::POOL_WATER: + if( mWaterPool ) + { + llassert(0); + llwarns << "LLPipeline::addPool(): Ignoring duplicate Water pool" << llendl; + } + else + { + mWaterPool = new_poolp; + } + break; - /* - glColor4f(0,0,0,1); - font->render(string,x*winx+1,y*winy+1); - LLGLSNoTexture no_texture; - */ + case LLDrawPool::POOL_GROUND: + if( mGroundPool ) + { + llassert(0); + llwarns << "LLPipeline::addPool(): Ignoring duplicate Ground Pool" << llendl; + } + else + { + mGroundPool = new_poolp; + } + break; - if (x+w > 0.95f) - { - x = (xs + xs2) * 4.0f; - y += h + ys2; - } - else - { - if (w) x += w + xs2; + default: + llassert(0); + llwarns << "Invalid Pool Type in LLPipeline::addPool()" << llendl; + break; } - } -#if 0 // No longer up date - -void displayQueue(F32 &x, F32 &y, LLDynamicArray& processed, LLDynamicQueuePtr >& remaining) +void LLPipeline::removePool( LLDrawPool* poolp ) { - S32 i; - for (i=0;iisDead()) - { - displayDrawable(x,y,drawable,0.5); - } - } - - y += ys * 4; - x = (xs + xs2) * 4.0f; - + removeFromQuickLookup(poolp); + mPools.erase(poolp); + delete poolp; } -void LLPipeline::displayQueues() +void LLPipeline::removeFromQuickLookup( LLDrawPool* poolp ) { - LLUI::setLineWidth(1.0); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - LLGLSPipelineAlpha gls_pipeline_alpha; - LLGLSNoTexture no_texture; - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); + LLMemType mt(LLMemType::MTYPE_PIPELINE); + switch( poolp->getType() ) + { + case LLDrawPool::POOL_SIMPLE: + llassert(mSimplePool == poolp); + mSimplePool = NULL; + break; - glScalef(2,2,1); - glTranslatef(-0.5f,-0.5f,0); + case LLDrawPool::POOL_TREE: + #ifdef _DEBUG + { + BOOL found = mTreePools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTreePools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; - winx = (F32)gViewerWindow->getWindowWidth(); - winy = (F32)gViewerWindow->getWindowHeight(); + case LLDrawPool::POOL_TERRAIN: + #ifdef _DEBUG + { + BOOL found = mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + llassert( found ); + } + #else + mTerrainPools.erase( (uintptr_t)poolp->getTexture() ); + #endif + break; - glScalef(1.0f/winx,1.0f/winy,1); + case LLDrawPool::POOL_BUMP: + llassert( poolp == mBumpPool ); + mBumpPool = NULL; + break; + + case LLDrawPool::POOL_ALPHA: + llassert( poolp == mAlphaPool ); + mAlphaPool = NULL; + break; - F32 x = (xs + xs2) * 4.0f; - F32 y = 0.1f; + case LLDrawPool::POOL_ALPHA_POST_WATER: + llassert( poolp == mAlphaPoolPostWater ); + mAlphaPoolPostWater = NULL; + break; - const LLFontGL* font = gResMgr->getRes( LLFONT_SANSSERIF ); + case LLDrawPool::POOL_AVATAR: + break; // Do nothing - font->renderUTF8("Build1", 0,0,(S32)(y*winy),LLColor4(1,1,1,1)); - displayQueue(x,y, gBuildProcessed, mBuildQ1); + case LLDrawPool::POOL_SKY: + llassert( poolp == mSkyPool ); + mSkyPool = NULL; + break; - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); + case LLDrawPool::POOL_STARS: + llassert( poolp == mStarsPool ); + mStarsPool = NULL; + break; -} + case LLDrawPool::POOL_WATER: + llassert( poolp == mWaterPool ); + mWaterPool = NULL; + break; -#endif + case LLDrawPool::POOL_GROUND: + llassert( poolp == mGroundPool ); + mGroundPool = NULL; + break; -// static -void render_bbox(const LLVector3 &min, const LLVector3 &max) -{ - S32 i; - LLVector3 verticesp[16]; - - verticesp[0].setVec(min.mV[0],min.mV[1],max.mV[2]); - verticesp[1].setVec(min.mV[0],min.mV[1],min.mV[2]); - verticesp[2].setVec(min.mV[0],max.mV[1],min.mV[2]); - verticesp[3].setVec(min.mV[0],max.mV[1],max.mV[2]); - verticesp[4].setVec(max.mV[0],max.mV[1],max.mV[2]); - verticesp[5].setVec(max.mV[0],max.mV[1],min.mV[2]); - verticesp[6].setVec(max.mV[0],min.mV[1],min.mV[2]); - verticesp[7].setVec(max.mV[0],min.mV[1],max.mV[2]); - verticesp[8 ] = verticesp[0]; - verticesp[9 ] = verticesp[1]; - verticesp[10] = verticesp[6]; - verticesp[11] = verticesp[7]; - verticesp[12] = verticesp[4]; - verticesp[13] = verticesp[5]; - verticesp[14] = verticesp[2]; - verticesp[15] = verticesp[3]; - - LLGLSNoTexture gls_no_texture; - { - LLUI::setLineWidth(1.f); - glBegin(GL_LINE_LOOP); - for (i = 0; i < 16; i++) - { - glVertex3fv(verticesp[i].mV); - } - glEnd(); + default: + llassert(0); + llwarns << "Invalid Pool Type in LLPipeline::removeFromQuickLookup() type=" << poolp->getType() << llendl; + break; } +} + +void LLPipeline::resetDrawOrders() +{ + // Iterate through all of the draw pools and rebuild them. + for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) { - LLGLDepthTest gls_depth(GL_TRUE); - LLUI::setLineWidth(3.0f); - glBegin(GL_LINE_LOOP); - for (i = 0; i < 16; i++) - { - glVertex3fv(verticesp[i].mV); - } - glEnd(); + LLDrawPool *poolp = *iter; + poolp->resetDrawOrders(); } - LLUI::setLineWidth(1.0f); } //============================================================================ @@ -4173,8 +3648,6 @@ void LLPipeline::setupHWLights(LLDrawPool* pool) { const LLColor4 black(0,0,0,1); - setLightingDetail(-1); // update - // Ambient LLColor4 ambient = gSky.getTotalAmbientColor(); glLightModelfv(GL_LIGHT_MODEL_AMBIENT,ambient.mV); @@ -4430,270 +3903,45 @@ class LLVOBranch; class LLVOLeaf; class Foo; -template<> char* LLAGPArray::sTypeName = "U8 [AGP]"; -template<> char* LLAGPArray::sTypeName = "U32 [AGP]"; -template<> char* LLAGPArray::sTypeName = "F32 [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLColor4 [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLColor4U [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLVector4 [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLVector3 [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLVector2 [AGP]"; -template<> char* LLAGPArray::sTypeName = "LLFace* [AGP]"; - void scale_stamp(const F32 x, const F32 y, const F32 xs, const F32 ys) { stamp(0.25f + 0.5f*x, 0.5f + 0.45f*y, 0.5f*xs, - 0.45f*ys); -} - -void drawBars(const F32 begin, const F32 end, const F32 height = 1.f) -{ - if (begin >= 0 && end <=1) - { - F32 lines = 40.0f; - S32 ibegin = (S32)(begin * lines); - S32 iend = (S32)(end * lines); - F32 fbegin = begin * lines - ibegin; - F32 fend = end * lines - iend; - - F32 line_height = height/lines; - - if (iend == ibegin) - { - scale_stamp(fbegin, (F32)ibegin/lines,fend-fbegin, line_height); - } - else - { - // Beginning row - scale_stamp(fbegin, (F32)ibegin/lines, 1.0f-fbegin, line_height); - - // End row - scale_stamp(0.0, (F32)iend/lines, fend, line_height); - - // Middle rows - for (S32 l = (ibegin+1); l < iend; l++) - { - scale_stamp(0.0f, (F32)l/lines, 1.0f, line_height); - } - } - } -} - -void LLPipeline::displayAGP() -{ - LLUI::setLineWidth(1.0); - glMatrixMode(GL_PROJECTION); - glPushMatrix(); - glLoadIdentity(); - glMatrixMode(GL_MODELVIEW); - glPushMatrix(); - glLoadIdentity(); - - LLGLSPipelineAlpha gls_alpha; - LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE); - - LLImageGL::unbindTexture(0, GL_TEXTURE_2D); - glScalef(2,2,1); - glTranslatef(-0.5f,-0.5f,0); - - glColor4f(0,0,0,0.5f); - scale_stamp(0,0,1,1); - - F32 x = 0.0f, y = 0.05f; - F32 xs = 0.015f, ys = 0.015f; - F32 xs2 = xs*0.1f, ys2 = ys * 0.1f; - F32 w = xs+xs2, h = ys + ys2; - S32 i=0; - - F32 agp_size = 1.f; - if (mAGPMemPool) - { - agp_size = (F32)mAGPMemPool->getSize(); - } - - x = (xs + xs2) * 4.0f; - - static float c = 0.0f; - c += 0.0001f; - - LLAGPMemBlock *blockp = mBufferMemory[mBufferIndex]->getAGPMemBlock(); - - pool_set_t::iterator iter = mPools.begin(); - LLDrawPool *poolp = *iter; - - // Dump the shared AGP buffer - if (blockp) - { - F32 begin = blockp->getOffset()/agp_size; - F32 end = begin + (blockp->getSize()/agp_size); - F32 used = begin + (poolp->mMemory.count()/agp_size); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.5f, 0.5f, 0.5f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.5f, 0.5f, 0.5f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.5f, 0.5f, 0.5f, 0.5f); - drawBars(begin,used, 0.5f); - - glColor4f(0.5f, 0.5f, 0.5f, 0.5f); - drawBars(begin,end, 0.25f); - } - - S32 used_bytes = 0; - S32 total_bytes = 0; - while (iter != mPools.end()) - { - poolp = *iter++; - - BOOL synced = FALSE; - i++; - total_bytes += poolp->mMemory.getMax(); - used_bytes += poolp->mMemory.count(); - LLViewerImage *texturep = poolp->getDebugTexture(); - - - if (poolp->mMemory.mSynced) - { - poolp->mMemory.mSynced = FALSE; - synced = TRUE; - } - - LLAGPMemBlock *blockp = poolp->mMemory.getAGPMemBlock(); - if (blockp) - { - F32 begin = blockp->getOffset()/agp_size; - F32 end = begin + (blockp->getSize()/agp_size); - F32 used = begin + (poolp->mMemory.count()/agp_size); - - LLViewerImage::bindTexture(NULL); - glColor4f(1.f, 0.5f, 0.5f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(texturep); - glColor4f(1.f, 0.75f, 0.75f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(NULL); - glColor4f(1.f, 0.75f, 0.75f, 1.f); - drawBars(begin,used, 0.5f); - - glColor3fv(poolp->getDebugColor().mV); - drawBars(begin,end, 0.25f); - - if (synced) - { - LLViewerImage::bindTexture(NULL); - glColor4f(1.f, 1.f, 1.f, 0.4f); - drawBars(begin,end); - } - } - - synced = FALSE; - if (poolp->mWeights.mSynced) - { - poolp->mWeights.mSynced = FALSE; - synced = TRUE; - } - blockp = poolp->mWeights.getAGPMemBlock(); - if (blockp) - { - F32 begin = blockp->getOffset()/agp_size; - F32 end = begin + (blockp->getSize()/agp_size); - F32 used = begin + (poolp->mWeights.count()*sizeof(float)/agp_size); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.0f, 0.f, 0.75f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(texturep); - glColor4f(0.0, 0.f, 0.75f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.0, 0.f, 0.75f, 1.f); - drawBars(begin,used, 0.5f); + 0.45f*ys); +} - LLViewerImage::bindTexture(NULL); - glColor3fv(poolp->getDebugColor().mV); - drawBars(begin,end, 0.25f); +void drawBars(const F32 begin, const F32 end, const F32 height = 1.f) +{ + if (begin >= 0 && end <=1) + { + F32 lines = 40.0f; + S32 ibegin = (S32)(begin * lines); + S32 iend = (S32)(end * lines); + F32 fbegin = begin * lines - ibegin; + F32 fend = end * lines - iend; - if (synced) - { - LLViewerImage::bindTexture(NULL); - glColor4f(1.f, 1.f, 1.f, 0.4f); - drawBars(begin,end); - } - } + F32 line_height = height/lines; - synced = FALSE; - if (poolp->mClothingWeights.mSynced) + if (iend == ibegin) { - poolp->mClothingWeights.mSynced = FALSE; - synced = TRUE; + scale_stamp(fbegin, (F32)ibegin/lines,fend-fbegin, line_height); } - blockp = poolp->mClothingWeights.getAGPMemBlock(); - if (blockp) + else { - F32 begin = blockp->getOffset()/agp_size; - F32 end = begin + (blockp->getSize()/agp_size); - F32 used = begin + (poolp->mClothingWeights.count()*sizeof(LLVector4)/agp_size); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.75f, 0.f, 0.75f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(texturep); - glColor4f(0.75f, 0.f, 0.75f, 0.5f); - drawBars(begin,end); - - LLViewerImage::bindTexture(NULL); - glColor4f(0.75f, 0.f, 0.75f, 0.5f); - drawBars(begin,used, 0.5f); + // Beginning row + scale_stamp(fbegin, (F32)ibegin/lines, 1.0f-fbegin, line_height); - LLViewerImage::bindTexture(NULL); - glColor3fv(poolp->getDebugColor().mV); - drawBars(begin,end, 0.25f); + // End row + scale_stamp(0.0, (F32)iend/lines, fend, line_height); - if (synced) + // Middle rows + for (S32 l = (ibegin+1); l < iend; l++) { - LLViewerImage::bindTexture(NULL); - glColor4f(1.f, 1.f, 1.f, 0.5f); - drawBars(begin,end); + scale_stamp(0.0f, (F32)l/lines, 1.0f, line_height); } } - - // - // Stamps on bottom of screen - // - LLViewerImage::bindTexture(texturep); - glColor4f(1.f, 1.f, 1.f, 1.f); - stamp(x,y,xs,ys); - - LLViewerImage::bindTexture(NULL); - glColor3fv(poolp->getDebugColor().mV); - stamp(x,y,xs, ys*0.25f); - if (x+w > 0.95f) - { - x = (xs + xs2) * 4.0f; - y += h; - } - else - { - x += w + xs2; - } } - - glPopMatrix(); - glMatrixMode(GL_PROJECTION); - glPopMatrix(); - glMatrixMode(GL_MODELVIEW); } void LLPipeline::findReferences(LLDrawable *drawablep) @@ -4706,7 +3954,7 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { llinfos << "In mLights" << llendl; } - if (mMovedList.find(drawablep) != mMovedList.end()) + if (std::find(mMovedList.begin(), mMovedList.end(), drawablep) != mMovedList.end()) { llinfos << "In mMovedList" << llendl; } @@ -4718,18 +3966,14 @@ void LLPipeline::findReferences(LLDrawable *drawablep) { llinfos << "In mRetexturedList" << llendl; } - if (mRematerialedList.find(drawablep) != mRematerialedList.end()) - { - llinfos << "In mRematerialedList" << llendl; - } - + if (mActiveQ.find(drawablep) != mActiveQ.end()) { llinfos << "In mActiveQ" << llendl; } - if (mBuildQ1.find(drawablep) != mBuildQ1.end()) + if (std::find(mBuildQ1.begin(), mBuildQ1.end(), drawablep) != mBuildQ1.end()) { - llinfos << "In mBuildQ2" << llendl; + llinfos << "In mBuildQ1" << llendl; } if (std::find(mBuildQ2.begin(), mBuildQ2.end(), drawablep) != mBuildQ2.end()) { @@ -4737,19 +3981,7 @@ void LLPipeline::findReferences(LLDrawable *drawablep) } S32 count; - /* - count = mStaticTree->count(drawablep); - if (count) - { - llinfos << "In mStaticTree: " << count << " references" << llendl; - } - - count = mDynamicTree->count(drawablep); - if (count) - { - llinfos << "In mStaticTree: " << count << " references" << llendl; - } - */ + count = gObjectList.findReferences(drawablep); if (count) { @@ -4776,53 +4008,6 @@ BOOL LLPipeline::verify() return ok; } -S32 LLPipeline::getAGPMemUsage() -{ - if (mAGPMemPool) - { - return mAGPMemPool->getSize(); - } - else - { - return 0; - } -} - -S32 LLPipeline::getMemUsage(const BOOL print) -{ - S32 mem_usage = 0; - - if (mAGPMemPool) - { - S32 agp_usage = 0; - agp_usage = mAGPMemPool->getSize(); - if (print) - { - llinfos << "AGP Mem: " << agp_usage << llendl; - llinfos << "AGP Mem used: " << mAGPMemPool->getTotalAllocated() << llendl; - } - mem_usage += agp_usage; - } - - - S32 pool_usage = 0; - for (pool_set_t::iterator iter = mPools.begin(); iter != mPools.end(); ++iter) - { - LLDrawPool *poolp = *iter; - pool_usage += poolp->getMemUsage(print); - } - - if (print) - { - llinfos << "Pool Mem: " << pool_usage << llendl; - } - - mem_usage += pool_usage; - - return mem_usage; - -} - ////////////////////////////// // // Collision detection @@ -4933,8 +4118,8 @@ void LLPipeline::setLight(LLDrawable *drawablep, BOOL is_light) } else { - mLights.erase(drawablep); drawablep->clearState(LLDrawable::LIGHT); + mLights.erase(drawablep); } markRelight(drawablep); } @@ -4953,9 +4138,16 @@ void LLPipeline::setActive(LLDrawable *drawablep, BOOL active) } //static -void LLPipeline::toggleRenderType(void* data) +void LLPipeline::toggleRenderType(U32 type) { - S32 type = (S32)(intptr_t)data; + U32 bit = (1<pickDrawable(start, end, collision); + LLDrawable* drawable = mObjectPartition[PARTITION_VOLUME]->pickDrawable(start, end, collision); return drawable ? drawable->getVObj() : NULL; } +LLSpatialPartition* LLPipeline::getSpatialPartition(LLViewerObject* vobj) +{ + if (vobj) + { + return getSpatialPartition(vobj->getPartitionType()); + } + return NULL; +} + +LLSpatialPartition* LLPipeline::getSpatialPartition(U32 type) +{ + if (type < mObjectPartition.size()) + { + return mObjectPartition[type]; + } + return NULL; +} + +void LLPipeline::clearRenderMap() +{ + for (U32 i = 0; i < LLRenderPass::NUM_RENDER_TYPES; i++) + { + mRenderMap[i].clear(); + } +} + + +void LLPipeline::resetVertexBuffers(LLDrawable* drawable) +{ + for (S32 i = 0; i < drawable->getNumFaces(); i++) + { + LLFace* facep = drawable->getFace(i); + facep->mVertexBuffer = NULL; + facep->mLastVertexBuffer = NULL; + } +} + +void LLPipeline::resetVertexBuffers() +{ + for (U32 i = 0; i < mObjectPartition.size(); ++i) + { + if (mObjectPartition[i]) + { + mObjectPartition[i]->resetVertexBuffers(); + } + } + + resetDrawOrders(); + + if (gSky.mVOSkyp.notNull()) + { + resetVertexBuffers(gSky.mVOSkyp->mDrawable); + resetVertexBuffers(gSky.mVOGroundp->mDrawable); + resetVertexBuffers(gSky.mVOStarsp->mDrawable); + markRebuild(gSky.mVOSkyp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + markRebuild(gSky.mVOGroundp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + markRebuild(gSky.mVOStarsp->mDrawable, LLDrawable::REBUILD_ALL, TRUE); + } + + if (LLVertexBuffer::sGLCount > 0) + { + LLVertexBuffer::cleanupClass(); + } +} + +void LLPipeline::renderObjects(U32 type, U32 mask, BOOL texture) +{ + mSimplePool->renderStatic(type, mask, texture); + mSimplePool->renderActive(type, mask, texture); +} + +void LLPipeline::setUseVBO(BOOL use_vbo) +{ + if (use_vbo != LLVertexBuffer::sEnableVBOs) + { + if (use_vbo) + { + llinfos << "Enabling VBO." << llendl; + } + else + { + llinfos << "Disabling VBO." << llendl; + } + + resetVertexBuffers(); + LLVertexBuffer::initClass(use_vbo); + } +} + +void apply_cube_face_rotation(U32 face) +{ + switch (face) + { + case 0: + glRotatef(90.f, 0, 1, 0); + glRotatef(180.f, 1, 0, 0); + break; + case 2: + glRotatef(-90.f, 1, 0, 0); + break; + case 4: + glRotatef(180.f, 0, 1, 0); + glRotatef(180.f, 0, 0, 1); + break; + case 1: + glRotatef(-90.f, 0, 1, 0); + glRotatef(180.f, 1, 0, 0); + break; + case 3: + glRotatef(90, 1, 0, 0); + break; + case 5: + glRotatef(180, 0, 0, 1); + break; + } +} +void LLPipeline::generateReflectionMap(LLCubeMap* cube_map, LLCamera& cube_cam, GLsizei res) +{ + //render dynamic cube map + U32 type_mask = gPipeline.getRenderTypeMask(); + BOOL use_occlusion = LLPipeline::sUseOcclusion; + LLPipeline::sUseOcclusion = FALSE; + LLPipeline::sSkipUpdate = TRUE; + static GLuint blur_tex = 0; + if (!blur_tex) + { + glGenTextures(1, &blur_tex); + } + + BOOL toggle_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI); + if (toggle_ui) + { + gPipeline.toggleRenderDebugFeature((void*) LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + + U32 cube_mask = (1 << LLPipeline::RENDER_TYPE_SIMPLE) | + (1 << LLPipeline::RENDER_TYPE_WATER) | + (1 << LLPipeline::RENDER_TYPE_BUMP) | + (1 << LLPipeline::RENDER_TYPE_ALPHA) | + (1 << LLPipeline::RENDER_TYPE_TREE) | + (1 << LLDrawPool::POOL_ALPHA_POST_WATER) | + //(1 << LLPipeline::RENDER_TYPE_PARTICLES) | + (1 << LLPipeline::RENDER_TYPE_CLOUDS) | + //(1 << LLPipeline::RENDER_TYPE_STARS) | + //(1 << LLPipeline::RENDER_TYPE_AVATAR) | + (1 << LLPipeline::RENDER_TYPE_GRASS) | + (1 << LLPipeline::RENDER_TYPE_VOLUME) | + (1 << LLPipeline::RENDER_TYPE_TERRAIN) | + (1 << LLPipeline::RENDER_TYPE_SKY) | + (1 << LLPipeline::RENDER_TYPE_GROUND); + + LLDrawPoolWater::sSkipScreenCopy = TRUE; + cube_mask = cube_mask & type_mask; + gPipeline.setRenderTypeMask(cube_mask); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glViewport(0,0,res,res); + + glClearColor(0,0,0,0); + + U32 cube_face[] = + { + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, + }; + + LLVector3 origin = cube_cam.getOrigin(); + + gPipeline.calcNearbyLights(); + + for (S32 i = 0; i < 6; i++) + { + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + gluPerspective(90.f, 1.f, 0.1f, 1024.f); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + apply_cube_face_rotation(i); + + + glTranslatef(-origin.mV[0], -origin.mV[1], -origin.mV[2]); + cube_cam.setOrigin(origin); + LLViewerCamera::updateFrustumPlanes(cube_cam); + cube_cam.setOrigin(gCamera->getOrigin()); + gPipeline.updateCull(cube_cam); + gPipeline.stateSort(cube_cam); + + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + gPipeline.renderGeom(cube_cam); + + cube_map->enable(0); + cube_map->bind(); + glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, 0, res, res, 0); + cube_map->disable(); + } + + cube_cam.setOrigin(origin); + gPipeline.resetDrawOrders(); + gPipeline.mShinyOrigin.setVec(cube_cam.getOrigin(), cube_cam.getFar()*2.f); + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + gPipeline.setRenderTypeMask(type_mask); + LLPipeline::sUseOcclusion = use_occlusion; + LLPipeline::sSkipUpdate = FALSE; + + if (toggle_ui) + { + gPipeline.toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI); + } + glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); + LLDrawPoolWater::sSkipScreenCopy = FALSE; +} + +//send cube map vertices and texture coordinates +void render_cube_map() +{ + + U32 idx[36]; + + idx[0] = 1; idx[1] = 0; idx[2] = 2; //front + idx[3] = 3; idx[4] = 2; idx[5] = 0; + + idx[6] = 4; idx[7] = 5; idx[8] = 1; //top + idx[9] = 0; idx[10] = 1; idx[11] = 5; + + idx[12] = 5; idx[13] = 4; idx[14] = 6; //back + idx[15] = 7; idx[16] = 6; idx[17] = 4; + + idx[18] = 6; idx[19] = 7; idx[20] = 3; //bottom + idx[21] = 2; idx[22] = 3; idx[23] = 7; + + idx[24] = 0; idx[25] = 5; idx[26] = 3; //left + idx[27] = 6; idx[28] = 3; idx[29] = 5; + + idx[30] = 4; idx[31] = 1; idx[32] = 7; //right + idx[33] = 2; idx[34] = 7; idx[35] = 1; + + LLVector3 vert[8]; + LLVector3 r = LLVector3(1,1,1); + + vert[0] = r.scaledVec(LLVector3(-1,1,1)); // 0 - left top front + vert[1] = r.scaledVec(LLVector3(1,1,1)); // 1 - right top front + vert[2] = r.scaledVec(LLVector3(1,-1,1)); // 2 - right bottom front + vert[3] = r.scaledVec(LLVector3(-1,-1,1)); // 3 - left bottom front + + vert[4] = r.scaledVec(LLVector3(1,1,-1)); // 4 - left top back + vert[5] = r.scaledVec(LLVector3(-1,1,-1)); // 5 - right top back + vert[6] = r.scaledVec(LLVector3(-1,-1,-1)); // 6 - right bottom back + vert[7] = r.scaledVec(LLVector3(1,-1,-1)); // 7 -left bottom back + + glBegin(GL_TRIANGLES); + for (U32 i = 0; i < 36; i++) + { + glTexCoord3fv(vert[idx[i]].mV); + glVertex3fv(vert[idx[i]].mV); + } + glEnd(); +} + +void LLPipeline::blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res) +{ + LLGLEnable cube(GL_TEXTURE_CUBE_MAP_ARB); + LLGLDepthTest depth(GL_FALSE); + + glMatrixMode(GL_PROJECTION); + glPushMatrix(); + glLoadIdentity(); + gluPerspective(90.f+45.f/res, 1.f, 0.1f, 1024.f); + glMatrixMode(GL_MODELVIEW); + glPushMatrix(); + + glViewport(0, 0, res, res); + LLGLEnable blend(GL_BLEND); + + S32 kernel = 2; + F32 step = 90.f/res; + F32 alpha = 1.f/((kernel*2+1)); + + glColor4f(1,1,1,alpha); + + S32 x = 0; + + U32 cube_face[] = + { + GL_TEXTURE_CUBE_MAP_POSITIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_X_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Y_ARB, + GL_TEXTURE_CUBE_MAP_POSITIVE_Z_ARB, + GL_TEXTURE_CUBE_MAP_NEGATIVE_Z_ARB, + }; + + LLVector3 axis[] = + { + LLVector3(1,0,0), + LLVector3(0,1,0), + LLVector3(0,0,1) + }; + + + glBlendFunc(GL_SRC_ALPHA_SATURATE, GL_ONE); + //3-axis blur + for (U32 j = 0; j < 3; j++) + { + glViewport(0,0,res, res*6); + glClear(GL_COLOR_BUFFER_BIT); + if (j == 0) + { + cube_in->bind(); + } + + for (U32 i = 0; i < 6; i++) + { + glViewport(0,i*res, res, res); + glLoadIdentity(); + apply_cube_face_rotation(i); + for (x = -kernel; x <= kernel; ++x) + { + glPushMatrix(); + glRotatef(x*step, axis[j].mV[0], axis[j].mV[1], axis[j].mV[2]); + render_cube_map(); + glPopMatrix(); + } + } + + //readback + if (j == 0) + { + cube_out->bind(); + } + for (U32 i = 0; i < 6; i++) + { + glCopyTexImage2D(cube_face[i], 0, GL_RGB, 0, i*res, res, res, 0); + } + } + glMatrixMode(GL_PROJECTION); + glPopMatrix(); + glMatrixMode(GL_MODELVIEW); + glPopMatrix(); + + glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA); +} + + diff --git a/linden/indra/newview/pipeline.h b/linden/indra/newview/pipeline.h index 5d00959..158c420 100644 --- a/linden/indra/newview/pipeline.h +++ b/linden/indra/newview/pipeline.h @@ -28,7 +28,6 @@ #ifndef LL_PIPELINE_H #define LL_PIPELINE_H -#include "llagparray.h" #include "lldarrayptr.h" #include "lldqueueptr.h" #include "llstat.h" @@ -50,8 +49,7 @@ class LLAgent; class LLDisplayPrimitive; class LLTextureEntry; class LLRenderFunc; -class LLAGPMemPool; -class LLAGPMemBlock; +class LLCubeMap; typedef enum e_avatar_skinning_method { @@ -62,6 +60,7 @@ typedef enum e_avatar_skinning_method BOOL compute_min_max(LLMatrix4& box, LLVector2& min, LLVector2& max); // Shouldn't be defined here! bool LLRayAABB(const LLVector3 ¢er, const LLVector3 &size, const LLVector3& origin, const LLVector3& dir, LLVector3 &coord, F32 epsilon = 0); BOOL LLLineSegmentAABB(const LLVector3& start, const LLVector3& end, const LLVector3& center, const LLVector3& size); +BOOL setup_hud_matrices(BOOL for_select); class LLGLSLShader { @@ -91,7 +90,6 @@ public: void bind(); void unbind(); - GLhandleARB mProgramObject; std::vector mAttribute; std::vector mUniform; @@ -107,6 +105,11 @@ public: void destroyGL(); void restoreGL(); + void resetVertexBuffers(); + void resetVertexBuffers(LLDrawable* drawable); + void setUseVBO(BOOL use_vbo); + void generateReflectionMap(LLCubeMap* cube_map, LLCamera& camera, GLsizei res); + void blurReflectionMap(LLCubeMap* cube_in, LLCubeMap* cube_out, U32 res); void init(); void cleanup(); @@ -121,6 +124,7 @@ public: /// @brief Figures out draw pool type from texture entry. Creates pool if necessary. static LLDrawPool* getPoolFromTE(const LLTextureEntry* te, LLViewerImage* te_image); + static U32 getPoolTypeFromTE(const LLTextureEntry* te, LLViewerImage* imagep); void addPool(LLDrawPool *poolp); // Only to be used by LLDrawPool classes for splitting pools! void removePool( LLDrawPool* poolp ); @@ -130,28 +134,25 @@ public: void unlinkDrawable(LLDrawable*); // Object related methods - void markVisible(LLDrawable *drawablep); - void doOcclusion(); - void markNotCulled(LLDrawable* drawablep, LLCamera& camera); + void markVisible(LLDrawable *drawablep, LLCamera& camera); + void doOcclusion(LLCamera& camera); + void markNotCulled(LLSpatialGroup* group, LLCamera &camera, BOOL active = FALSE); void markMoved(LLDrawable *drawablep, BOOL damped_motion = FALSE); void markShift(LLDrawable *drawablep); void markTextured(LLDrawable *drawablep); - void markMaterialed(LLDrawable *drawablep); void markRebuild(LLDrawable *drawablep, LLDrawable::EDrawableFlags flag = LLDrawable::REBUILD_ALL, BOOL priority = FALSE); void markRelight(LLDrawable *drawablep, const BOOL now = FALSE); //get the object between start and end that's closest to start. Return the point of collision in collision. LLViewerObject* pickObject(const LLVector3 &start, const LLVector3 &end, LLVector3 &collision); - - void dirtyPoolObjectTextures(const LLViewerImage *texture); // Something about this texture has changed. Dirty it. + + // Something about these textures has changed. Dirty them. + void dirtyPoolObjectTextures(const std::set& textures); void resetDrawOrders(); U32 addObject(LLViewerObject *obj); - BOOL usingAGP() const; - void setUseAGP(const BOOL use_agp); // Attempt to use AGP; - void enableShadows(const BOOL enable_shadows); // void setLocalLighting(const BOOL local_lighting); @@ -174,61 +175,42 @@ public: BOOL validateProgramObject(GLhandleARB obj); GLhandleARB loadShader(const LLString& filename, S32 cls, GLenum type); - void setUseOcclusionCulling(BOOL b) { mUseOcclusionCulling = b; } - BOOL getUseOcclusionCulling() const { return mUseOcclusionCulling; } - - BOOL initAGP(); - void cleanupAGP(); - LLAGPMemBlock *allocAGPFromPool(const S32 bytes, const U32 target); // Static flag is ignored for now. - void flushAGPMemory(); // Clear all AGP memory blocks (to pack & reduce fragmentation) - // phases void resetFrameStats(); void updateMoveDampedAsync(LLDrawable* drawablep); void updateMoveNormalAsync(LLDrawable* drawablep); + void updateMovedList(LLDrawable::drawable_vector_t& move_list); void updateMove(); - void updateCull(); + void updateCull(LLCamera& camera); void updateGeom(F32 max_dtime); - void stateSort(); + //calculate pixel area of given box from vantage point of given camera + static F32 calcPixelArea(LLVector3 center, LLVector3 size, LLCamera& camera); - void renderGeom(); + void stateSort(LLCamera& camera); + void stateSort(LLSpatialGroup* group, LLCamera& camera); + void stateSort(LLSpatialBridge* bridge, LLCamera& camera); + void stateSort(LLDrawable* drawablep, LLCamera& camera); + void postSort(LLCamera& camera); + void forAllDrawables(LLSpatialGroup::sg_vector_t& groups, void (*func)(LLDrawable*)); + void forAllVisibleDrawables(void (*func)(LLDrawable*)); + static void highlightPhysical(LLDrawable* drawablep); + + void renderObjects(U32 type, U32 mask, BOOL texture = TRUE); + + void renderGeom(LLCamera& camera); void renderHighlights(); void renderDebug(); + void processOcclusion(LLCamera& camera); - void renderForSelect(); + void renderForSelect(std::set& objects); void renderFaceForUVSelect(LLFace* facep); void rebuildPools(); // Rebuild pools - // bindAGP and unbindAGP are used to bind AGP memory. - // AGP should never be bound if you're writing/copying data to AGP. - // bindAGP will do the correct thing if AGP rendering has been disabled globally. - void bindAGP(); - void unbindAGP(); - inline BOOL isAGPBound() const { return mAGPBound; } - - void setupVisibility(); - void computeVisibility(); - - LLViewerObject *nearestObjectAt(F32 yaw, F32 pitch); // CCW yaw from +X = 0 radians, pitch down from +Y = 0 radians, NULL if no object - - void displayPools(); - void displayAGP(); - void displayMap(); - void displaySSBB(); - void displayQueues(); - void printPools(); - void findReferences(LLDrawable *drawablep); // Find the lists which have references to this object BOOL verify(); // Verify that all data in the pipeline is "correct" - // just the AGP part - S32 getAGPMemUsage(); - - // all pools - S32 getMemUsage(const BOOL print = FALSE); - S32 getVisibleCount() const { return mVisibleList.size(); } S32 getLightCount() const { return mLights.size(); } @@ -253,18 +235,15 @@ public: BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderFeatureMask(const U32 mask) const { return (mRenderFeatureMask & mask) ? TRUE : FALSE; } BOOL hasRenderDebugMask(const U32 mask) const { return (mRenderDebugMask & mask) ? TRUE : FALSE; } - - // Vertex buffer stuff? - U8* bufferGetScratchMemory(void); - void bufferWaitFence(void); - void bufferSendFence(void); - void bufferRotate(void); + void setRenderTypeMask(const U32 mask) { mRenderTypeMask = mask; } + U32 getRenderTypeMask() const { return mRenderTypeMask; } + static void toggleRenderType(U32 type); // For UI control of render features - static void toggleRenderType(void* data); + static BOOL hasRenderTypeControl(void* data); static void toggleRenderDebug(void* data); static void toggleRenderDebugFeature(void* data); - static BOOL toggleRenderTypeControl(void* data); + static void toggleRenderTypeControl(void* data); static BOOL toggleRenderTypeControlNegated(void* data); static BOOL toggleRenderDebugControl(void* data); static BOOL toggleRenderDebugFeatureControl(void* data); @@ -314,20 +293,17 @@ public: RENDER_TYPE_GROUND = LLDrawPool::POOL_GROUND, RENDER_TYPE_TERRAIN = LLDrawPool::POOL_TERRAIN, RENDER_TYPE_SIMPLE = LLDrawPool::POOL_SIMPLE, - RENDER_TYPE_MEDIA = LLDrawPool::POOL_MEDIA, RENDER_TYPE_BUMP = LLDrawPool::POOL_BUMP, RENDER_TYPE_AVATAR = LLDrawPool::POOL_AVATAR, RENDER_TYPE_TREE = LLDrawPool::POOL_TREE, - RENDER_TYPE_TREE_NEW = LLDrawPool::POOL_TREE_NEW, RENDER_TYPE_WATER = LLDrawPool::POOL_WATER, - RENDER_TYPE_CLOUDS = LLDrawPool::POOL_CLOUDS, RENDER_TYPE_ALPHA = LLDrawPool::POOL_ALPHA, - RENDER_TYPE_HUD = LLDrawPool::POOL_HUD, - // Following are object types (only used in drawable mRenderType) + RENDER_TYPE_HUD = LLDrawPool::NUM_POOL_TYPES, RENDER_TYPE_VOLUME, RENDER_TYPE_GRASS, RENDER_TYPE_PARTICLES, + RENDER_TYPE_CLOUDS, }; enum LLRenderDebugFeatureMask @@ -341,13 +317,12 @@ public: RENDER_DEBUG_FEATURE_FOG = 0x0020, RENDER_DEBUG_FEATURE_PALETTE = 0x0040, RENDER_DEBUG_FEATURE_FR_INFO = 0x0080, - RENDER_DEBUG_FEATURE_CHAIN_FACES = 0x0100 + RENDER_DEBUG_FEATURE_FOOT_SHADOWS = 0x0100, }; enum LLRenderFeatureMask { - RENDER_FEATURE_AGP = 0x01, -// RENDER_FEATURE_LOCAL_LIGHTING = 0x02, + RENDER_FEATURE_LOCAL_LIGHTING = 0x02, RENDER_FEATURE_OBJECT_BUMP = 0x04, RENDER_FEATURE_AVATAR_BUMP = 0x08, // RENDER_FEATURE_SHADOWS = 0x10, @@ -356,26 +331,46 @@ public: enum LLRenderDebugMask { - RENDER_DEBUG_LIGHT_TRACE = 0x0001, - RENDER_DEBUG_POOLS = 0x0002, - RENDER_DEBUG_MAP = 0x0004, - RENDER_DEBUG_AGP_MEM = 0x0008, - RENDER_DEBUG_QUEUES = 0x0010, - RENDER_DEBUG_COMPOSITION = 0x0020, - RENDER_DEBUG_SSBB = 0x0040, - RENDER_DEBUG_VERIFY = 0x0080, - RENDER_DEBUG_SHADOW_MAP = 0x0100, - RENDER_DEBUG_BBOXES = 0x0200, - RENDER_DEBUG_OCTREE = 0x0400, - RENDER_DEBUG_FACE_CHAINS = 0x0800, - RENDER_DEBUG_OCCLUSION = 0x1000, - RENDER_DEBUG_POINTS = 0x2000, - RENDER_DEBUG_TEXTURE_PRIORITY = 0x4000, + RENDER_DEBUG_LIGHT_TRACE = 0x00001, + RENDER_DEBUG_COMPOSITION = 0x00020, + RENDER_DEBUG_VERIFY = 0x00080, + RENDER_DEBUG_SHADOW_MAP = 0x00100, + RENDER_DEBUG_BBOXES = 0x00200, + RENDER_DEBUG_OCTREE = 0x00400, + RENDER_DEBUG_PICKING = 0x00800, + RENDER_DEBUG_OCCLUSION = 0x01000, + RENDER_DEBUG_POINTS = 0x02000, + RENDER_DEBUG_TEXTURE_PRIORITY = 0x04000, + RENDER_DEBUG_TEXTURE_AREA = 0x08000, + RENDER_DEBUG_FACE_AREA = 0x10000, + RENDER_DEBUG_PARTICLES = 0x20000, + RENDER_DEBUG_TEXTURE_ANIM = 0x40000, }; LLPointer mAlphaSizzleImagep; - LLSpatialPartition *mObjectPartition; + //MUST MATCH THE ORDER OF DECLARATION IN LLPipeline::init() + typedef enum + { + PARTITION_VOLUME = 0, + PARTITION_BRIDGE, + PARTITION_HUD, + PARTITION_TERRAIN, + PARTITION_WATER, + PARTITION_TREE, + PARTITION_PARTICLE, + PARTITION_CLOUD, + PARTITION_GRASS, + PARTITION_NONE, + NUM_PARTITIONS + } eObjectPartitions; + +private: + std::vector mObjectPartition; +public: + + LLSpatialPartition* getSpatialPartition(LLViewerObject* vobj); + LLSpatialPartition* getSpatialPartition(U32 index); BOOL mBackfaceCull; S32 mTrianglesDrawn; @@ -394,10 +389,16 @@ public: LLStat mNumVisibleFacesStat; LLStat mNumVisibleDrawablesStat; - static S32 sAGPMaxPoolSize; static S32 sCompiles; - BOOL mUseVBO; // Use ARB vertex buffer objects, if available + static BOOL sShowHUDAttachments; + static BOOL sUseOcclusion; + static BOOL sSkipUpdate; //skip lod updates + static BOOL sDynamicReflections; + + //cube map for anti-aliasing reflections + LLCubeMap* mCubeBuffer; + GLuint mCubeList; class LLScatterShader { @@ -432,15 +433,25 @@ public: GLSL_SPECULAR_MAP, GLSL_BUMP_MAP, GLSL_ENVIRONMENT_MAP, - GLSL_SCATTER_MAP, GLSL_END_RESERVED_UNIFORMS } eGLSLReservedUniforms; + static const char* sShinyUniforms[]; + static U32 sShinyUniformCount; + + typedef enum + { + GLSL_SHINY_ORIGIN = GLSL_END_RESERVED_UNIFORMS + } eShinyUniforms; + + LLVector4 mShinyOrigin; + //object shaders LLGLSLShader mObjectSimpleProgram; LLGLSLShader mObjectAlphaProgram; LLGLSLShader mObjectBumpProgram; - + LLGLSLShader mObjectShinyProgram; + //water parameters static const char* sWaterUniforms[]; static U32 sWaterUniformCount; @@ -515,15 +526,17 @@ public: LLColor4 mSunDiffuse; LLVector3 mSunDir; + + LLSpatialGroup::sg_vector_t mActiveGroups; + std::vector mRenderMap[LLRenderPass::NUM_RENDER_TYPES]; + std::vector mAlphaGroups; + std::vector mAlphaGroupsPostWater; + LLSpatialGroup::sg_vector_t mVisibleGroups; + LLSpatialGroup::sg_vector_t mDrawableGroups; + + void clearRenderMap(); protected: - class SelectedFaceInfo - { - public: - LLFace *mFacep; - S32 mTE; - }; - BOOL mVertexShadersEnabled; S32 mVertexShadersLoaded; // 0 = no, 1 = yes, -1 = failed S32 mVertexShaderLevel[SHADER_COUNT]; @@ -534,12 +547,16 @@ protected: U32 mRenderDebugFeatureMask; U32 mRenderDebugMask; + U32 mOldRenderDebugMask; + ///////////////////////////////////////////// // // LLDrawable::drawable_vector_t mVisibleList; - LLDrawable::drawable_set_t mMovedList; - + LLSpatialBridge::bridge_vector_t mVisibleBridge; + LLSpatialBridge::bridge_vector_t mOccludedBridge; + LLDrawable::drawable_vector_t mMovedList; + LLDrawable::drawable_vector_t mMovedBridge; LLDrawable::drawable_vector_t mShiftList; ///////////////////////////////////////////// @@ -578,13 +595,12 @@ protected: // // Different queues of drawables being processed. // - LLDrawable::drawable_set_t mBuildQ1; // priority + LLDrawable::drawable_list_t mBuildQ1; // priority LLDrawable::drawable_list_t mBuildQ2; // non-priority LLDrawable::drawable_set_t mActiveQ; LLDrawable::drawable_set_t mRetexturedList; - LLDrawable::drawable_set_t mRematerialedList; ////////////////////////////////////////////////// // @@ -617,45 +633,27 @@ protected: LLDrawPool* mLastRebuildPool; // For quick-lookups into mPools (mapped by texture pointer) - std::map mSimplePools; std::map mTerrainPools; std::map mTreePools; - std::map mTreeNewPools; - std::map mBumpPools; - std::map mMediaPools; LLDrawPool* mAlphaPool; + LLDrawPool* mAlphaPoolPostWater; LLDrawPool* mSkyPool; LLDrawPool* mStarsPool; - LLDrawPool* mCloudsPool; LLDrawPool* mTerrainPool; LLDrawPool* mWaterPool; LLDrawPool* mGroundPool; - LLDrawPool* mHUDPool; + LLRenderPass* mSimplePool; + LLDrawPool* mBumpPool; // Note: no need to keep an quick-lookup to avatar pools, since there's only one per avatar - LLDynamicArray mHighlightFaces; // highlight faces on physical objects - LLDynamicArray mSelectedFaces; + std::vector mHighlightFaces; // highlight faces on physical objects + std::vector mSelectedFaces; LLPointer mFaceSelectImagep; LLPointer mBloomImagep; LLPointer mBloomImage2p; - - BOOL mAGPBound; - LLAGPMemPool *mAGPMemPool; - U32 mGlobalFence; - - // Round-robin AGP buffers for use by the software skinner - enum - { - kMaxBufferCount = 4 - }; - S32 mBufferIndex; - S32 mBufferCount; - LLAGPArray *mBufferMemory[kMaxBufferCount]; - U32 mBufferFence[kMaxBufferCount]; - BOOL mUseOcclusionCulling; // object-object occlusion culling U32 mLightMask; U32 mLightMovingMask; S32 mLightingDetail; @@ -671,8 +669,5 @@ void render_bbox(const LLVector3 &min, const LLVector3 &max); extern LLPipeline gPipeline; extern BOOL gRenderForSelect; -extern F32 gPickAlphaThreshold; -extern F32 gPickAlphaTargetThreshold; -extern BOOL gUsePickAlpha; #endif diff --git a/linden/indra/newview/releasenotes.txt b/linden/indra/newview/releasenotes.txt index 01f16b3..b8822dc 100644 --- a/linden/indra/newview/releasenotes.txt +++ b/linden/indra/newview/releasenotes.txt @@ -1,3 +1,109 @@ +Release Notes for Second Life 1.14.0(0) March 27, 2007 +===================================== +New feature: +* Linux client features embedded Mozilla + +Changes: +* Texture Pipeline Architecture +** Significant redesign of texture pipeline +** Improved texture caching +** Unlimited texture cache size +** Cache location can be changed +** Textures from last scene are pre fetched, improving loading speed of inital scene +* Render Pipeline Architecture +** Significant changes to render pipeline +** Introduction of Vertex Buffer Objects for improved stability +** Better batching of geometry for improved render performance (on some systems) +** Alpha sorting changes to improve performance +** Modified texture animations to use hardware acceleration +** Light objects now affect themselves. +*** NOTE: This may cause some objects that are lights to "wash out" requiring some content to be adjusted +* Setting an object for sale enables "Buy Copy" by default instead of "Buy Original" +* User inworld money transaction history floater removed +** Transaction history can be viewed via secondlife.com +* Moving your avatar no longer deselects objects in build mode automatically +* Removed old reference to Announcements forum in a login error message +* Added Port setting in preferences to specify UDP port (ala -port argument) +* Added setting to change cache location +* Added 'Empty Lost and Found' option +* Added 'Use Custom Port' option to Preferences to specify network port +* Objects set for sale are Buy Copy by default (instead of Buy Original) +* Increased Classified's maximum L$ payable from 99999 to 999999 +* Added '?' button next to Partner field explaining partnering +** Added display that shows intersection of prims with translation plane when building. + +LSL changes: +* New script commands +** void llSetLinkPrimitiveParams( integer linknumber, list rules ) +** void llSetLinkTexture( integer linknumber, string texture, integer face ) +* More documentation is available using Help > Scripting Guide... +* The following 4 particle commands have been deprecated for some time, and are now approximated by llParticleSystem +** llMakeExplosion http://wiki.secondlife.com/wiki/LlMakeExplosion +** llMakeFire http://wiki.secondlife.com/wiki/LlMakeFire +** llMakeFountain http://wiki.secondlife.com/wiki/LlMakeFountain +** llMakeSmoke http://wiki.secondlife.com/wiki/LlMakeSmoke + +Bug fixes: +* Fixed texturing all sides of multi-prim object failing under high latency +* Fixed sitting avatar standing when clothes are dragged onto the avatar +* Fixed llGiveInventoryList spamming owner with messages +* Fixed group members ability to set home to land only set to group (not deeded) +* Fixed objects from library being placed back in Library after editing +* Fixed loss of no-copy textures when applied to a prim +* Fixed delivery of Email to IM messages greater than 998 characters +* Fixed attachments leaving inventory after detaching +* Fixed Alt-menu taking focus after Alt-zooming +* Fixed menus not closing when something else is clicked +* Fixed Friends list not showing online friends on login if "Can see my online status" is disabled +* Fixed World -> Buy Land menu failures +* Fixed LSL email converting numbers in the email body to 0 +* Fixed focus issues when closing a window +* Fixed closed status of folders when opened in inventory +* Fixed a method of sitting on other avatars +* Fixed double-clicking on TOS switching to a different text display +* Fixed rezzed objects appearing at <0,0,0> if you have create rights but do not wear your title +* Fixed Offer Teleport appearing in your own profile +* Fixed Ctrl-P failing to open Preferences if Inventory has focus +* Fixed ability to set sale info on no-modify items +* Fixed ability to further limit permissions on items if they are already no-modify +* Fixed Object Entry rules also preventing rezzing from inventory +* Fixed single-click behavior for objects +* Fixed object selection while crossing region boundary +* Fixed textures leaving their window when resized +* Fixed single items being created in tabbed windows +* Fixed menus not closing when clicked a second time +* Fixed resizing of landmarks +* Fixed textures being applied to all sides when using Select Texture +* Fixed objects not deleting if they contain no-copy items +* Fixed Pay dialog while in busy mode +* Fixed loss of no-copy objects when using llGiveInventory() on a busy avatar +* Fixed script editor not regaining focus when function dropdown is used +* Fixed opening multiple inventory items not using tabbed windows +* Fixed a client crash when opening multiple inventory items (including a script) +* Fixed notecards opened in a tabbed window extending outside the preview window +* Fixed blurry web browser widgets when UI Scale is not 1.0 +* Fixed focus not moving to next window when using Ctrl-W on detached IMs or Appearance +* Fixed Ctrl-W not closing snapshot floater +* Fixed widget overlap in group proposal tab of a searched group +* Fixed a client crash when deleting objects +* Fixed Capslock key detection +* Fixed context menu for items in an object +* Fixed avatar animations not changing when editing an attachment +* Fixed object counts in About Land changing when object loses focus +* Fixed ESC key behavior (closing tools and resetting camera) +* Fixed obscured status bar when debug is off +* Fixed client crash in People Search with Picks tab +* Fixed incorrect prim count in Buy dialog when using prim multipliers +* Fixed build button on toolbar remaining disabled when Create Objects is set to group +* Fixed a client crash while taking an object +* Fixed a script runtime error when using a list inside a while or do-while loop +* Fixed renaming a no-copy clothing item failing during Make New Outfit +* Fixed objects failing to attach when selected from a distance +* Fixed rare texture swapping on Mac +* Fixed non-Latin characters such as Japanese Kanji appearing as small square dots +* Fixed textures in the distance not reducing priority +* Avatars out of view are no longer animated + Release Notes for Second Life 1.13.3(2) January 30, 2007 ===================================== Changes: @@ -116,7 +222,6 @@ Release Notes for Second Life 1.13.1(6) December 21, 2006 Bug fixes: * Don't display an erroneous 'Critical Message' during login for new residents - Release Notes for Second Life 1.13.1(5) December 15, 2006 ===================================== New features: @@ -139,7 +244,6 @@ Bug fixes: * Fixed Home key not toggling fly when chat field is empty * Fixed Friends list multi-selection - Release Notes for Second Life 1.13.1(4) December 13, 2006 ===================================== UI changes: @@ -221,35 +325,6 @@ Bug fixes: * Fixed a memory leak on the Intel Mac * Fixed greyed Terms of Service agree/disagree options if user cancelled TOS notice -Release Notes for Second Life 1.13.1(0) December 8, 2006 -===================================== -Changes: -* 'Access from Mainland' renamed to 'Public Access' in Estate Tools -* 'Contact Support' link added to Help menu pointing to Second Life Knowledge Base contact page - -Bug fixes: -* Fixed duplicate IMs or IM-to-email being sent (repeatedly) -* Fixed objects disappearing if they were made flexible via script -* Fixed a cause of failed estate-to-estate teleports -* Generalized flexi implementation for attachments and non-attachments -* Fixed several integer fields being displayed as float values -* Fixed pie menu options for non-English languages -* Fixed group notice panel not accepting text -* Removed incorrect notice that friends could track each other on the map (they cannot) -* Fixed bug affecting color of scripted/resident chat -* Temp objects can enter full parcels -* Fixed client crash when closing tabbed gestures without saving -* Fixed boolean values in Debug Settings not remembering the correct values -* Fixed strange characters in popup messages in Preferences -* Fixed incorrect counts for simulator prim usage -* Fixed floating point drift (and prim drift) in llTargetOmega -* Fixed textures on HUDs not rezing until right-clicked -* Fixed friends list scrolling to the top after a change -* Fixed a crash caused by tearing off menus in the script editor -* Fixed ability to add yourself to your friends list -* Fixed offline notification that a resident left your group (should not send email) -* Fixed object contents 'Copy to Inventory' and 'Copy and Wear' - Release Notes for Second Life 1.13.0(10) December 4, 2006 ===================================== Bug fixes: @@ -369,7 +444,6 @@ Bug fixes: * Fixed a client crash when right-clicking a payment notification window * Fixed a client crash for llLoadURL - Release Notes for Second Life 1.12.3(6) November 1, 2006 ===================================== Other changes: @@ -399,7 +473,6 @@ Linux fixes: * Assorted library fixes * Work around an X bug in full-screen mouse handling - Release Notes for Second Life 1.12.3(4) October 25, 2006 ===================================== New features: @@ -472,11 +545,11 @@ Bug fixes: * Lots of changes to make the client/server protocols more secure Linux client fixes: -* MMX-enhanced image decoding -* Resolve crash: 'undefined symbol: glXGetProcAddress' -* No longer lose streaming music after visiting a dead stream -* Startup script now exposes alpha-testing configuration options -* Disable troublesome GL extensions by default. See startup script to enable. + * MMX-enhanced image decoding + * Resolve crash: 'undefined symbol: glXGetProcAddress' + * No longer lose streaming music after visiting a dead stream + * Startup script now exposes alpha-testing configuration options + * Disable troublesome GL extensions by default. See startup script to enable. Release Notes for Second Life 1.12.1(13) September 27, 2006 ===================================== @@ -484,12 +557,6 @@ Bug fixes: * Fixed Macintosh autoupdater ** Older clients should use the website download if issues are experienced -Linux client fixes: -* Shiny, Ripple Water, Occlusion Culling, Anisotropic Filtering, Avatar Vertex Programs where supported by drivers -* On-disk cache persists properly across sessions -* Screenshots save on-disk to resident profile directory -* Client less prone to blocking window manager key combos - Release Notes for Second Life 1.12.1(12) September 27, 2006 ===================================== Other changes: @@ -590,35 +657,6 @@ Bug fixes: Release Notes for Second Life 1.12.1(6) September 13, 2006 ===================================== -Linux client fixes: -* Cut & Paste is now supported -* Work around window managers stopping SL from seeing Alt Zoom (or Ctrl Drag) -* Improved default Unicode font rendering -** Easier for user to substitute own fallback unicode.ttf file -* Bundle libvorbisenc, libcurl, more -* Key repeating was not working correctly -* Fix clicking on the world immediately after a desktop switch -* Show last screenshot during login -* Fix crash when switching from fullscreen mode -* Fix hang or crash on linux client shutdown -* Fix 'Failed to set locale en_US.iso8859-1' warnings -* Embed icon for the window manager -* '$L' was not appearing before Linden $$ balance in corner screen -* Stop the client logging to syslog - -Release Notes for Second Life 1.12.0 (linux-51742) August 29, 2006 -===================================== -Linux client fixes: -* Audio support on Linux -* Context-sensitive cursors for Linux -* Crash when emailing a postcard -* Group title appears twice -* Linux Client doesn't notice when it is minimized -* Gamma settings fail to work and save -* Linux Client tries to run Mac auto-updater - -Release Notes for Second Life 1.12.1(5) September 11, 2006 -===================================== New features: * Estate access and ban lists boosted up to 300 entries (previously 63) * Estate land management now allows subdividing and joining of parcels @@ -897,500 +935,3 @@ Bug fixes: Linux client fixes: * No linux client specific fixes in this version -Release Notes for Second Life 1.11.3(2) August 9, 2006 -===================================== -* Resolved an incompatibility with older scripts causing regions to crash -* Fixed an issue with agent presence that caused Residents to be unable to see one another - -Release Notes for Second Life 1.11.3(1) August 9, 2006 -===================================== -Other changes: -* System Sound Effects have been decoupled from the Audio Stream -** This allows system sounds like typing to be muted while listening to live performances and so forth -** Sound Effects volume can now be set in Preferences -> Audio & Video -> Sound Effects Volume -** Streaming Audio volume is set as it was before using the in-world Audio Control panel - -Bug fixes: -* Preferences no longer save when user profile has non-ASCII character in its path -* Resolved client crash when clicking Preferences -> Popups -> Reset 'Show next time' Dialogs -* CTRL-ENTER once again activates Chat Shout -* Drop-down boxes now respond to control keys as expected -* Resolved client crash related to mute lists -* Resolved client crash related to applying color to an object -* Scroll wheel once again causes Chat History window to scroll -* Drag-selecting text in a type-in field no longer causes selected text to be stuck -* World Map once again correctly accepts coordinates for pin-point teleporting -* First name in a search query is once again automatically highlighted when search is performed -* Resolved a bug which caused an orange flicker to occur (most noticeable during sunset and sunrise) -* Upper-case file extensions are now recognized when uploading files and no longer cause an error -* Large chat history, notecards and scripts no longer negatively impact viewer framerate -* Text is no longer cut off in Search -> Land Sales -* The mouse scroll wheel now works again within chat history -* Fixed a lighting bug causing avatars to flicker - most notable at sunset -* Several exploits have been identified and addressed -* Restored 'click here to turn off this email' link to outgoing email - -Linux client fixes: -* No Linux client specific fixes in this version - -Release Notes for Second Life 1.11.2(4) August 1, 2006 -===================================== -Other changes: -* Asset compression expanded to cover objects -* llRequestAgentData can now return the resident's account type -** Example usage: llRequestAgentData(llGetOwner(), DATA_PAYINFO); -** No Payment Info on File: 0 -** Payment Info on File: 1 -** No Payment Info on File AND Payment Info Used: 2 (Only Beta/Lifetime users fall under this status) -** Payment Info on File AND Payment Info Used: 3 -* Added PARCEL_FLAG_RESTRICT_PUSHOBJECT to llGetParcelFlags, and REGION_FLAG_RESTRICT_PUSHOBJECT to llGetRegionFlags() -* Right-click -> Teleport option added to landmarks -* 'Muted Residents' renamed to 'Mute List', as it can contain muted objects as well -* Ctrl-\ can now be used to focus the camera on the last agent or object that said something in chat - -Bug fixes: -* Fixed several exploits -* Friends list now sorts by online status -* Both the scripted object and the target of llPushObject must be in push-allowed areas -* Corrected the color of system messages -* d right-clicking the edges of the viewer window automatically selecting pie menu items -* Minimap now fits within its window when taking high-res snapshots -* Telehub spawnpoint removal no longer fails for Estate Owners/Managers -* Fixed a bug where the clear search button was not visible -* Send Postcard floater now gets active focus when 'Keep open after saving' is checked -* Fixed a bug where residents would teleport to the wrong location when using the my land window after using the sort tabs -* Double-clicking on map icon ('event') no longer opens wrong panel in Search floater -* Fixed a bug with slow window resize -* Dragging past the end of text field once again scrolls text -* Fixed a bug where the avatar picker name field doesn't have focus on show -* Ctrl+F opening search now puts focus in 'All' tab's 'Find' text box -* About Land floater no longer goes blank in some use cases -* Resolved issue which caused Minimap window, Build window and Object Edit window to not appear in snapshots when Show UI is selected -* 'Update Automatically' no longer clears the 'Send postcard' window from the screen -* Fonts now render properly with UI scaling on in fullscreen on Macbook Pro -* Linden Locations shouldn't appear in Popular Places -* Text in Search > Landsales no longer missing -* Fixed a bug with keyboard selection of radio buttons -* Escape now closes menus -* Land sales description now displays correctly in Search > Land Sales -* Snapshot window now follows the same position rules as other windows -* Friends list now sorts by online status -* Toolbar buttons no longer retain focus after use -* UI layout tweaks to the About Land > Options > Show in Find Places drop-down menu -* Improved the experience for uploading a snapshot as a texture -* Fixed a bug with snapshot floater's settings not being persisted -* Made double-click process as a normal click if not handled specially -* Disabled using ALT-Enter to trigger buttons, etc -* Converted media remote control to be a panel to allow tab focusing - -Release Notes for Second Life 1.11.1(2) August 1, 2006 -===================================== -Bugs fixed: -* Fixed an exploit - -Release Notes for Second Life 1.11.1(1) July 26, 2006 -===================================== -New features: -* Additional right-click functionality for inventory folders containing wearables -** 'Add to Outfit' puts accessories on your avatar without removing existing ones -*** This is also activated by shift-dragging the folder onto your avatar -** 'Replace Outfit' removes existing outfit and wears contents of folder -** 'Take Off' removes ONLY worn items in the folder -* Region/Estate and About Land now feature the option 'Restricted Pushing' -** When pushing is restricted, only the following calls of llPushObject will succeed on the land: -*** Any push called against the owner of the scripted object -*** An object owned by the landowner -*** An object deeded (or Set) to the same group the land parcel is deeded (or Set) -** Region/Estate edits this setting on a per-region basis, not per-estate - -Other changes: -* llGiveInventory() box now supports an option to mute the giving agent (user or object) -* llPushObject() functionality can now be disabled on a parcel or region -* Sounds triggered by muted residents are now muted - -Bug fixes: -* Banned users cannot be heard from your parcel -* Texture tab and picker no longer preview textures on objects you don't own -* Fixed a bug where IM and Chat history text is blurred on some ATI cards -* Fixed a bug where skirt mesh blocks attachment editing on legs -* Group names, parcel names, classified names are now filtered to ASCII characters -* All default gestures no longer deactivated upon first relogin -* 'Stop Flying' button is now disabled when flying over No Fly land -* Right-click IM calling cards now works consistently -* Fixed a bug where scrollbars failed to appear when IM window holds more IMs than IM panel can display -* Fixed a bug where multi-select of faces does not always display the last selected face properties -* Fixed a bug where color settings revert to black when changed from defaults -* Fixed a bug where clicking set in about land / forsale doesnt automatically show the calling cards -* Hitting enter while chat history has focus now focuses the chat bar - -Linux client fixes: -* No linux client-specific fixes in this release - -Release Notes for Second Life 1.11.0(12) July 23, 2006 -===================================== -Bug fixes: -* Resolved a server side exploit - -Linux client fixes: -* No linux client specific fixes in this release - -Release Notes for Second Life 1.11.0(11) July 21, 2006 -===================================== -Bug fixes: -* Resolved a bug that caused script events to be triggered on region crossing -* Fixed a bug that caused Estate Tools to return objects other than those selected -* Fixed a bug that dropped focus while deleting a (no copy) object -* Fixed a bug that caused the parcel Ban list to clear -* Fixed a viewer crash/lockup caused by viewing profiles -* Fixed a viewer crash when double-clicking a group in the 'My Land...' window -* Fixed a bug that caused the Delete key to incorrectly delete an object when editing text values in the Edit window - -Linux client fixes: -* No linux client specific fixes in this release - -Release Notes for Second Life 1.11.0(10) July 19, 2006 -===================================== -Bug fixes: -* Resolved a simulator crash caused by script emails -* Fixed a bug where poseballs and vehichles would stop working after region restart - -Release Notes for Second Life 1.11.0(9) July 19, 2006 -===================================== -Features: -* Zoomable UI -** The entire UI can be scaled (including in-world text, manipulators, etc) by a user-supplied scale value (Preferences->Graphics->UI Size) -** When running fullscreen, the additional option 'Use resolution independent scale' should ensure that the UI looks the same at all resolutions -** Additionally, changing to a resolution with a different aspect ratio than your monitor's aspect ratio should not result in any squashing or stretching of your display -* Improved Snapshot functionality -** When taking a snapshot, the world will freeze in place and the snapshot will be previewed over the entire screen (but under UI elements) -** The camera tool will be active by default, allowing you to click and drag to move the camera around while objects/avatars/etc are frozen in place, without having to hold down ALT -** You can also change snapshot parameters (resolution, JPEG compression level) and the snapshot will update on the fly -** Any time the camera moves or a parameter is changed, the existing snapshot will 'drop' away and be replaced by a new one -** You can also take snapshot of arbitrary resolution, up to 6000x6000 -*** Be aware that the larger the snapshot is, the more system resources are needed to create it -- you can potentially run out of memory and crash if taking very large snapshots on a low-end system -* Eyedropper tool -** Added the ability to pick colors and textures from objects in view (and that you own) inside the color picker and texture picker -** When depressed, the button changes the mouse cursor and activates a 'pipette' or 'eyedropper' tool -** The user can then click on another object in world to grab the texture/color of the face that they clicked -* Gestural pie menus -** Pie menus now provide a gradually faded border when the right mouse button is down to suggest that you can use them by moving the mouse in a given direction, which is faster and easier than clicking on a pie wedge directly -** Also, pie sub-menus can be accessed with gestures, making it possible to chain gestures together to perform any operation in the pie menu by memory -* Tear-off menus -** Added ability to click on a double line at the top of any menu or sub-menu and pin it in place on the UI as a 'floater' -** All of the menu items should still work, as well as branching menus, etc. -** Closing the floater will make it disappear -** Accessing a detached menu via its parent menu will bring the floating menu to the foreground, but not reposition it - -Other changes: -* Usability changes to Find/Search menu -** 'Find' has been renamed 'Search' in the Toolbar, Edit menu, Directory window, and F1 Help -** Search is still opened with the keyboard shortcut Ctrl-F -** Searches defaults to 'Show Mature Content ON' for sims, parcels, events, classifieds, etc. -** The 'Name' column for each listing of returned search results is now wider. -** The second column for each listing of returned search results (i.e. Dwell, Price, etc.) has its font size reduced to make additional space -* Improved text field support for INSERT key -* 'Avatar' ruler mode has been changed to 'Attachment' ruler mode -** Attachment rotations in 'Attachment' ruler mode are relative to the attach point instead of the root of the avatar -** This should make adjusting attachments easier without using 'pose stands' -* Ctrl-tab moves keyboard focus between UI floaters -* Tab key moves focus to the toolbar if nothing else has focus -* Dragging an inventory item over the scrollbar allows you to directly scroll the inventory window -* Hitting Enter when the chat line is blank will close the chat bar - -Bug fixes: -* Scrolling windows should no longer catch scrolling events when they're not the active window -* Fixed a bug that caused the fullscreen/windowed shortcut (Alt-Enter) to work incorrectly -* Landowners can no longer ban themselves from their own land based on payment information -* Fixed snapshot previews in Bug Reports and Postcards -* Changing the snapshot resolution causes the previously captured image to disappear -* Snapshot mode is automatically exited when teleporting -* Fixed a bug that caused snapshot buttons to become greyed out when zooming -* Fixed a bug with zoomed snapshots -* Fixed a bug that caused the UI to blur in a screenshot -* Fixed a bug that caused the UI and HUDs to tile in high-res snapshots -* Fixed a bug that caused the Texture Picker to automatically select a texture -* Fixed a bug with the sky when right-clicking objects in the dark -* Fixed a bug that caused uploaded textures to preview incorrectly -* Fixed a bug that caused the edit window to be dragged to the bottom of the screen when minimized -* Nametags now scale properly with UI changes -* Changed UI Scale label to be consistent across the interface -* Objects can now be dragged from Recent Items to All Items -* Mouselook mode works correctly when exiting snapshot mode -* Removed extraneous headers from Estate -> Debug -> Top Scripts / Top Colliders -* Fixed the interface tiling when taking high-res snapshots -* Fixed an ugly rectangle around the Terms of Service buttons -* Fixed a column width issue with Land Sales -* Removed the option to flag a Teen Second Life event as Mature -* Fixed a bug that caused UI elements to scale incorrectly when changing windowed resolutions -* Fixed a bug that caused a blank Friends list -* Improved font rendering for UI, HUD, and avatar names -* Region/Estate -> Debug -> Top Colliders now displays properly -* Improved UI font scaling to better match window scaling -* Improved UI appearance at 800x600 resolution -* Help -> About Second Life displays the proper information -* Fixed several bugs with snapshots and HUDs -* Fixed a crash issue with snapshots -* Snapshot buttons are no longer clipped -* Fixed a glowing eyes issue with Bump Mapped avatar rendering -* Fixed a bug that caused the Color Picker text values to have no effect -* Fixed a bug that caused the Chat bar to appear when other windows had focus -* Fixed a bug that caused chat bubbles to go offscreen -* Fixed a bug that caused inventory Rename to lose keyboard focus -* Script comments are once again orange -* Profile can now be viewed after searching for one Resident in the finder -* Preferences > Network > Clear Cache > Apply no longer starts parcel music stream -* Fixed a bug where objects specifically requested to be returned were skipped if an avatar was sitting on them -* Autoreturn now functions properly after a parcel is subdivided -* Parcel object limits are calculated properly when a parcel is subdivided and claimed by a new owner. -* Terms of Service defaults to 'I Disagree' - -MacOS client fixes: -* Resolved an Intel Mac crash issue - -Linux client fixes: -* No linux client specific fixes in this release - -Release Notes for Second Life 1.10.6(1) July 12, 2006 -===================================== -* Resolved a server-side crash issue - -Release Notes for Second Life 1.10.6(0) July 12, 2006 -===================================== -Changes: -* The PvP History option has been replaced by 'Bumps, Hits, & Pushes' under the Help menu -** This window does not open automatically; residents can open and view it manually -** Entries in Bumps, Hits, & Pushes are now timestamped -** Residents should use Help -> Report Abuse to provide detailed information regarding Abuse cases -* 'Find' changed to 'Search' on the toolbar, default for new users is to search 'All' content types -* Parcel 'access denied' lines now fade significantly faster with distance -* Parcel owners can ban users based on account settings -* Chat from banned users cannot be heard from your parcel - -Bug fixes: -* The 'Open' option appears when right-clicking a child prim of an object with contents -* The Linden Locations list now shows Mature areas -* Fixed a bug that prevented some offline IMs from appearing -* Fixed a bug with the INSERT key and text fields -* Fixed texture preview for skirts (was zoomed in too tight) -* AGP enabled for additional graphics cards -* Small flexi objects are now rendered correctly -* Stars are back! - -Linux client fixes: -* No linux client specific fixes in this release - -Release Notes for Second Life 1.10.5(2) June 30, 2006 -===================================== -Bug fixes: -* Fixed an exploit - -Release Notes for Second Life 1.10.5(1) June 28, 2006 -===================================== -New features: -* Each resident's profile now includes a field revealing whether the resident has provided payment information to Linden Lab. -** The profile's 'Account' field includes account status: 'Resident' or 'Linden Lab Employee' and, in the case of 'Resident' status one of three status entries: -*** 'No Payment Info on File' - account was created with no credit card or Paypal -*** 'Payment Info on File' - account has provided a credit card or Paypal -*** 'Payment Info Used' - credit card or Paypal on account has successfully been billed -** We plan to provide features in future updates to mark specific parts of the Second Life world (or allow residents to mark their own land) as accessible only to accounts with payment information. - -Other changes: -* The 'Report PvP Abuse' option has been removed from the Help menu -** Residents can and should continue to report harrassing PvP abuse via 'Report Abuse' under Help -** Residents should provide as much relevant information as possible when filing Abuse Reports -* Residents explicitly banned from a land parcel cannot fly in that parcel's airspace, to a height of 768m -** Residents not explicitly banned, but not on the access list, can fly over the parcel at an altitude greater than 50m -* More categories have been added to the Places menu -* The Library is displayed at the bottom of the Inventory for quicker access to one's own Inventory -* Snapshots to disk are now taken with CTRL+` instead of just the ` key -* 'Copy and Wear' now behaves identically to dragging a folder from inventory onto your avatar -** Existing clothing and attachments will be removed - -Bug fixes: -* Transferring an island to a new owner no longer causes objects on group-owned land to be returned automatically -* The Open option is not displayed when the object has no contents -* PCI-Express cards should no longer give errors that AGP is disabled -* Corrected several error messages about incorrect driver versions -* The version number of an optional update is now displayed -* Fixed a bug that caused some objects to be missed by rectangle-select -* Fixed a display bug with transparent avatar textures in Upload Preview -* Doubled the space available to display the estate name in Region/Estate - -Linux client fixes: -* No linux client specific fixes in this release - -Release Notes for Second Life 1.10.4(4) June 21, 2006 -===================================== -Other changes: -* Various usability changes to the inventory Recent Items - -Bug Fixes: -* The autoupdate utility now remembers the SLURL you just used and passes it to SL after updating -* Fixed a bug with flexible attachments made with Twist Begin -* Fixed a bug that prevented typing in or exiting from Mouselook -* Fixed some viewer crashes - -Release Notes for Second Life 1.10.2(0) June 1, 2006 -===================================== -New features: -* Added the Inventory 'Recent Items' tab -** Shows items you've received recently (i.e. since your last login) -** Recent Items can be filtered separately from All Items - -Release Notes for Second Life 1.10.1(0) May 31, 2006 -===================================== -Features: -* F1 Help using Mozilla -** Help for all Second Life users now available in a Mozilla window accessed by pressing F1 - -Bug fixes: -* Improved avatar lighting to more closely match in 'nearby lights' and 'sun/moon only' modes -* Improved flexible attachment behavior while crossing a region boundary - -Release Notes for Second Life 1.10.0(34) May 26, 2006 -===================================== -Bug fixes: -* Resolved a compatibility issue for PowerPC users running Mac OS X 10.3.9 -* Fixed a bug causing HUD objects to work incorrectly -* Fixed a bug causing child prims on new HUD objects to remain invisible -* Fixed a bug causing objects to disappear due to occlusion culling -* Other residents should now be heard after unmuting them and relogging -* The Mac autoupdate utility should properly show download progress - -Release Notes for Second Life 1.10.0(33) May 24, 2006 -===================================== -* Resolved an issue that caused group invitations to Officers to offer Member status instead -* First Land no longer misidentified and therefore able to be bought by Residents who have already owned land - -Release Notes for Second Life 1.10.0(32) May 24, 2006 -===================================== -Features: -* Hardware lighting -** Any primitive in Second Life may be turned into a light -*** Light properties are radius, color, intensity, and falloff -** New options in the Preference panel indicate the type of lighting you want to use -*** 'Sun or Moon only' is best for low-performance hardware -**** Everything in-world is lit in real time by the sun or moon only -*** 'Nearby Lights' is available for any hardware configuration -**** Everything in-world is lit by sun or moon and up to six nearby light sources -** More information about the new lighting system is available here: -*** http://forums.secondlife.com/showthread.php?t=100128 - -* Flexible objects -** Cube, prism and cylinder primitive types can now be made flexible as a client-side effect -** Simulation parameters for material and responsiveness to gravity and wind -** Objects that are flexible cannot be physical and are always phantom -** Use of these is currently limited to preserve framerate as they increase amount of client-side processing - -* Occlusion culling -** Frame rate is improved when objects that would normally be rendered are hidden from view -** FPS will be significantly improved when inside a structure -*** Windows or other transparent surfaces will decrease effectiveness as objects in view will be rendered, whether or not they are within the structure -** Toggle with CTRL-SHIFT-o on all platforms - -* New 'Click Action' functionality for objects -** Object creators can select a default left-click action for objects: -*** Touch (default), Sit, Buy, Pay, or Open -** These actions happen immediately when a resident left-clicks on the object, without a menu -** Builders set the action in the build tools 'General' panel, at the bottom -** Click actions override touch events for scripts -*** If you want the touch behavior, be sure 'touch (default)' is the click action -** You can't set 'Buy' as the action unless an object is for sale -** 'Sit' should be useful for both chairs and vehicles -** 'Open' should be useful for vendors that sell packaged objects - -* Updated functionality for the Top Scripts/Top Colliders dialog -** Improvements allow Estate owners to return or disable offending objects -*** Disabling an object makes it non-physical and disables all scripts - -* Classified ads now have an auto-renew option -** Checking the 'Auto renew each week' checkbox in Profile > Classifieds will cause your classified to be republished instead of expiring after one week -** You will be charged the same listing price as the initial classified -** To change the listing price, you need to make a new classified - -* Universal Binary installer for Mac clients is now standard -** PowerPC and Intel Mac versions are now bundled together in one 'Universal Binary' installer -** Minimum required version for Second Life is now 10.3.9 - -* The Login screen now features a box to select the region to log into -** This has the same effect as using a SLURL to log into a region - - -New LSL functions: - -* llHTTPRequest -** Added new LSL call & event to support HTTP access from external scripts -** LSL Function usage: -*** key llHTTPRequest(string , list , string ) -**** Send HTTP request to with and , returning key uniquely identifying the request -**** Currently, the only supported parameter is the following key/value pair: HTTP_METHOD, -** LSL Event usage: -*** http_response(key , integer , list , string ) -**** Called when a pending HTTP request completes with the HTTP , and response -**** This facility supports GET, PUT and POST methods, X-SecondLife-headers, text/* MIME types, and transcoding of body contents to LSL's Unicode strings - -* llGetParcelFlags -** Get the parcel flags (PARCEL_FLAG_*) for the parcel including the point pos -** Returns an integer that is a bit field of flags -** This bitfield can be ANDed with a flag to see if that flag is set for that parcel -** Usage: -*** integer llGetParcelFlags(vector pos) -** Example: -*** if (llGetParcelFlags() & PARCEL_FLAG_ALLOW_CREATE_OBJECTS) llOwnerSay('You may create objects in this parcel!'); -** Bitfields: -*** PARCEL_FLAG_ALLOW_FLY -**** Used to determine if a parcel allows flying -*** PARCEL_FLAG_ALLOW_SCRIPTS -**** Used to determine if a parcel allows outside scripts -*** PARCEL_FLAG_ALLOW_LANDMARK -**** Used to determine if a parcel allows landmarks to be created -*** PARCEL_FLAG_ALLOW_TERRAFORM -**** Used to determine if a parcel allows anyone to terraform the land -*** PARCEL_FLAG_ALLOW_DAMAGE -**** Used to determine if a parcel allows damage -*** PARCEL_FLAG_ALLOW_CREATE_OBJECTS -**** Used to determine if a parcel allows anyone to create objects -*** PARCEL_FLAG_USE_ACCESS_GROUP -**** Used to determine if a parcel limits access to a group -*** PARCEL_FLAG_USE_ACCESS_LIST -**** Used to determine if a parcel limits access to a list of residents -*** PARCEL_FLAG_USE_BAN_LIST -**** Used to determine if a parcel uses a ban list -*** PARCEL_FLAG_USE_LAND_PASS_LIST -**** Used to determine if a parcel allows passes to be purchased -*** PARCEL_FLAG_LOCAL_SOUND_ONLY -**** Used to determine parcel restricts spatialized sound to the parcel - -Other changes: -* Performance enhancements for audio streaming -* Texture loading performance improvements -* Improved 'Interest List' functionality keeps objects from being reloaded in view so often -* Objects that were set Material Light prior to 1.9.1 will be listed as 'Fullbright(Legacy)' -** Once this setting is changed for an object, it cannot be set back to this value except via script -* Added 'Wear' and 'Take' options to 'Open' menu for objects -* 'Pay' now included in left-click options for objects -* Improvements to the Properties window for objects -* Added region rating to listings in the Find menu -* Initial load of Events page defaults to current and upcoming events -* World map now puts focus on 'Teleport' button after entering a region name and pressing 'Enter' -* Mouselook now shows region, position, and damage at the top of the screen, but does not show currency, time, or packet loss -* IMs now include time stamp for local time when message was received - - -Bug fixes: -* Offline IMs should appear correctly while logging in -* Second Life starts correctly when file pathnames include special characters (including non-English operating systems) -* Fixed a cause of failure for offline inventory offers -* The 'Purchase' button now greys out while your transaction is being processed -* Edit axes no longer display behind the object being edited -* Left-click 'buy' now disables when the object is no longer for sale -* Residents you have muted can no longer offer you teleports -* Fixed a bug that caused the mouse pointer to move incorrectly while dragging HUD attachments -* Estate telehubs now override parcel landing points -* Fixed a bug that made water turn invisible -* Low-end video cards no longer display only one terrain texture -* llMapDestination now properly clamps to 768m on the Z-axis -* Avatar flying state is persistent across a teleport -* Fixed an bug that affected uploads of sounds -* Fixed a bug that caused SLURLs to fail with Internet Explorer - diff --git a/linden/indra/newview/res/newViewRes.rc b/linden/indra/newview/res/newViewRes.rc index 41c2af1..eeeb1eb 100644 --- a/linden/indra/newview/res/newViewRes.rc +++ b/linden/indra/newview/res/newViewRes.rc @@ -227,8 +227,8 @@ TOOLPIPETTE CURSOR "toolpipette.cur" // VS_VERSION_INFO VERSIONINFO - FILEVERSION 1,13,3,2 - PRODUCTVERSION 1,13,3,2 + FILEVERSION 1,14,0,0 + PRODUCTVERSION 1,14,0,0 FILEFLAGSMASK 0x3fL #ifdef _DEBUG FILEFLAGS 0x1L @@ -245,12 +245,12 @@ BEGIN BEGIN VALUE "CompanyName", "Linden Lab" VALUE "FileDescription", "Second Life" - VALUE "FileVersion", "1.13.3.57442" + VALUE "FileVersion", "1.14.0.0" VALUE "InternalName", "Second Life" - VALUE "LegalCopyright", "Copyright © 2001-2006, Linden Research, Inc." + VALUE "LegalCopyright", "Copyright © 2001-2007, Linden Research, Inc." VALUE "OriginalFilename", "SecondLife.exe" VALUE "ProductName", "Second Life" - VALUE "ProductVersion", "1.13.3.57442" + VALUE "ProductVersion", "1.14.0.0" END END BLOCK "VarFileInfo" diff --git a/linden/indra/newview/restore_login_page.bat b/linden/indra/newview/restore_login_page.bat deleted file mode 100644 index 05a4925..0000000 --- a/linden/indra/newview/restore_login_page.bat +++ /dev/null @@ -1,22 +0,0 @@ -@echo off - -REM ============================================================ -REM restore_login_page -REM ============================================================ -REM -REM Purpose: -REM -REM Undo the work of set_login_page. -REM - -set ORIGINAL=skins\xui\en-us\panel_login.xml -set TEMPFILE=.\panel_login.xml - -if not exist %TEMPFILE% goto end - -echo Restoring login page in %ORIGINAL% - -copy /Y %TEMPFILE% %ORIGINAL% -del %TEMPFILE% - -:END diff --git a/linden/indra/newview/rsyncfiles.txt b/linden/indra/newview/rsyncfiles.txt deleted file mode 100644 index 0763c5c..0000000 --- a/linden/indra/newview/rsyncfiles.txt +++ /dev/null @@ -1,22 +0,0 @@ -- *.cpp -- *.c -- *.h -- .svn/ -- CVS/ -- .cvsignore -- .DS_Store -- /app_settings/mozilla/ -- /app_settings/mozilla_debug/ -+ /app_settings/ -+ /character/ -+ /help/ -+ /trial/ -+ /fonts/ -+ /skins/ -+ /cursors_mac/ -+ /featuretable.txt -+ /featuretable_mac.txt -+ /releasenotes.txt -+ /lsl_guide.html -+ /secondlife.icns -+ /gpu_table.txt diff --git a/linden/indra/newview/secondlife setup build aditi.bat b/linden/indra/newview/secondlife setup build aditi.bat index 68a2e38..cb52caf 100644 --- a/linden/indra/newview/secondlife setup build aditi.bat +++ b/linden/indra/newview/secondlife setup build aditi.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DADITI - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=aditi diff --git a/linden/indra/newview/secondlife setup build agni.bat b/linden/indra/newview/secondlife setup build agni.bat index 2b2ce29..fe9dd4f 100644 --- a/linden/indra/newview/secondlife setup build agni.bat +++ b/linden/indra/newview/secondlife setup build agni.bat @@ -1,11 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/ -set ARGS= - -@rem To build optional "update" installer (doesn't have static VFS): -@rem -@rem set ARGS=/DUPDATE - -@"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" \ No newline at end of file diff --git a/linden/indra/newview/secondlife setup build dmz.bat b/linden/indra/newview/secondlife setup build dmz.bat index 9ab6fae..5d5a614 100644 --- a/linden/indra/newview/secondlife setup build dmz.bat +++ b/linden/indra/newview/secondlife setup build dmz.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DDMZ - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=dmz diff --git a/linden/indra/newview/secondlife setup build durga.bat b/linden/indra/newview/secondlife setup build durga.bat index 5bcc744..3ba6bd7 100644 --- a/linden/indra/newview/secondlife setup build durga.bat +++ b/linden/indra/newview/secondlife setup build durga.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DDURGA - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=durga diff --git a/linden/indra/newview/secondlife setup build firstlook.bat b/linden/indra/newview/secondlife setup build firstlook.bat index 099f4fc..73e47ec 100644 --- a/linden/indra/newview/secondlife setup build firstlook.bat +++ b/linden/indra/newview/secondlife setup build firstlook.bat @@ -1,11 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/firstlook/ -set ARGS=/DFIRSTLOOK - -@rem To build optional "update" installer (doesn't have static VFS): -@rem -@rem set ARGS=/DUPDATE - -@"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=firstlook diff --git a/linden/indra/newview/secondlife setup build ganga.bat b/linden/indra/newview/secondlife setup build ganga.bat index db1a3ad..f2cff72 100644 --- a/linden/indra/newview/secondlife setup build ganga.bat +++ b/linden/indra/newview/secondlife setup build ganga.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LONGPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DGANGA - -"secondlife setup build.bat" %LONGPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=ganga \ No newline at end of file diff --git a/linden/indra/newview/secondlife setup build museum.bat b/linden/indra/newview/secondlife setup build museum.bat deleted file mode 100644 index e1ec644..0000000 --- a/linden/indra/newview/secondlife setup build museum.bat +++ /dev/null @@ -1,7 +0,0 @@ -@rem Invoke the script which preps then runs the installer. -@rem This batch file is customized per grid. - -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DMUSEUM - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% diff --git a/linden/indra/newview/secondlife setup build shakti.bat b/linden/indra/newview/secondlife setup build shakti.bat index 7d5a13c..37aff9b 100644 --- a/linden/indra/newview/secondlife setup build shakti.bat +++ b/linden/indra/newview/secondlife setup build shakti.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DSHAKTI - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=shakti \ No newline at end of file diff --git a/linden/indra/newview/secondlife setup build siva.bat b/linden/indra/newview/secondlife setup build siva.bat index 300df17..ae66128 100644 --- a/linden/indra/newview/secondlife setup build siva.bat +++ b/linden/indra/newview/secondlife setup build siva.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DSIVA - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=siva diff --git a/linden/indra/newview/secondlife setup build soma.bat b/linden/indra/newview/secondlife setup build soma.bat index eed8e5b..c7a9f64 100644 --- a/linden/indra/newview/secondlife setup build soma.bat +++ b/linden/indra/newview/secondlife setup build soma.bat @@ -1,7 +1,4 @@ @rem Invoke the script which preps then runs the installer. @rem This batch file is customized per grid. -set LOGINPAGEURL=http://secondlife.com/app/login/beta/ -set ARGS=/DSOMA - -"secondlife setup build.bat" %LOGINPAGEURL% %ARGS% +@"secondlife setup build.bat" --grid=soma diff --git a/linden/indra/newview/secondlife setup build.bat b/linden/indra/newview/secondlife setup build.bat index 169071f..df6dc72 100644 --- a/linden/indra/newview/secondlife setup build.bat +++ b/linden/indra/newview/secondlife setup build.bat @@ -12,63 +12,9 @@ @REM "secondlife setup build.bat" http://secondlife.com/app/login/beta/ /DADITI @REM -@IF EXIST ReleaseForDownload\Secondlife.exe GOTO RELEASE_EXE -@IF EXIST Secondlife.exe GOTO LOCAL_EXE -@IF EXIST ReleaseNoOpt\newview_noopt.exe GOTO RELEASE_NOOPT_EXE - -@echo Could not find Secondlife.exe! -@pause -exit 0 - -:RELEASE_NOOPT_EXE -@echo Cound not find SecondLife.exe. -@echo Using newview_noopt.exe - DEVELOPMENT BUILD! -@pause -SET EXEFILE=ReleaseNoOpt\newview_noopt.exe -SET KDUDLL=ReleaseNoOpt\llkdu.dll -GOTO CONTINUE - -:RELEASE_EXE -SET EXEFILE=ReleaseForDownload\Secondlife.exe -SET KDUDLL=ReleaseForDownload\llkdu.dll -GOTO CONTINUE - -:LOCAL_EXE -SET EXEFILE=Secondlife.exe -SET KDUDLL=..\..\libraries\i686-win32\lib_release\llkdu.dll -:CONTINUE - -@rem Set login page to reflect beta grid status -call "set_login_page.bat" %1 - -@rem Extract version information. -branding\ResHacker -extract %EXEFILE%, branding\version.rc, versioninfo, 1, - -@rem Process version information. -cd branding -grep FILEVERSION version.rc | gawk "{ print $2; }" > version.txt -gawk -F , "{ print \"!define VERSION_MAJOR \" $1; }" version.txt > version.include -gawk -F , "{ print \"!define VERSION_MINOR \" $2; }" version.txt >> version.include -gawk -F , "{ print \"!define VERSION_PATCH \" $3; }" version.txt >> version.include -gawk -F , "{ print \"!define VERSION_BUILD \" $4; }" version.txt >> version.include -echo !define EXE_LOCATION %EXEFILE% >> version.include -echo !define KDU_DLL %KDUDLL% >> version.include - -cd .. -@rem Build installer -"C:\Program Files\NSIS\makensis" %2 %3 %4 %5 %6 %7 %8 %9 "secondlife setup.nsi" - -@rem Clean up -del branding\version.include -del branding\version.rc -del branding\version.txt -del branding\ResHacker.log -del branding\ResHacker.ini - -@rem Restore login page changes to avoid accidental commits -call "restore_login_page.bat" - +@rem use manifest to build installer +@"viewer_manifest.py" %1 %2 %3 %4 %5 %6 %7 %8 @rem pause diff --git a/linden/indra/newview/set_login_page.bat b/linden/indra/newview/set_login_page.bat deleted file mode 100644 index 5cbb77f..0000000 --- a/linden/indra/newview/set_login_page.bat +++ /dev/null @@ -1,45 +0,0 @@ -@echo off - -REM ============================================================ -REM set_login_page -REM ============================================================ -REM -REM Purpose: -REM -REM Modify the login page (panel_login.xml) to point to a -REM specific URL for a viewer build, e.g. a viewer pointing -REM at a beta grid. -REM -REM Usage: -REM -REM set_login_page.bat url -REM -REM Example: -REM -REM set_login_page.bat http://secondlife.com/app/login/beta/ -REM -REM Notes: -REM -REM * Depends on branding\gawk.exe -REM * gawk.exe needs to be a Win32 executable (not Win16) -REM * It's pretty dumb, and replaces the regular expression: -REM http://secondlife.com/app/login/.* - -set ORIGINAL=skins\xui\en-us\panel_login.xml -set TEMPFILE=.\panel_login.xml -set LOGINPAGEURL=%1 - -IF defined LOGINPAGEURL GOTO do_replace -goto end - -:do_replace - -echo Setting login page in %ORIGINAL% to "%LOGINPAGEURL%" - -copy %ORIGINAL% %TEMPFILE% -branding\gawk.exe --assign=uri=%LOGINPAGEURL% "{ gsub( /http:\/\/secondlife\.com\/app\/login\/.*/, uri ); print; }" %TEMPFILE% > %ORIGINAL% - -REM Leave tempfile in place so it can be restored -REM del %TEMPFILE% - -:END diff --git a/linden/indra/newview/skins/textures/textures.xml b/linden/indra/newview/skins/textures/textures.xml new file mode 100644 index 0000000..5bfb4d8 --- /dev/null +++ b/linden/indra/newview/skins/textures/textures.xml @@ -0,0 +1,391 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/linden/indra/newview/skins/xui/de/floater_account_history.xml b/linden/indra/newview/skins/xui/de/floater_account_history.xml deleted file mode 100644 index a6c3e32..0000000 --- a/linden/indra/newview/skins/xui/de/floater_account_history.xml +++ /dev/null @@ -1,4 +0,0 @@ - - -