summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/CMakeLists.txt10
-rw-r--r--indra/newview/app_settings/settings.xml14
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl2
-rw-r--r--indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl4
-rw-r--r--indra/newview/licenses-win32.txt69
-rw-r--r--indra/newview/llassetuploadresponders.cpp720
-rw-r--r--indra/newview/llassetuploadresponders.h50
-rw-r--r--indra/newview/lldrawable.h6
-rw-r--r--indra/newview/lldrawpoolbump.cpp12
-rw-r--r--indra/newview/lldrawpoolbump.h2
-rw-r--r--indra/newview/llface.cpp2
-rw-r--r--indra/newview/llfilepicker.cpp28
-rw-r--r--indra/newview/llfilepicker.h4
-rw-r--r--indra/newview/llhudtext.cpp12
-rw-r--r--indra/newview/llhudtext.h1
-rw-r--r--indra/newview/llinventorybridge.cpp10510
-rw-r--r--indra/newview/llinventorybridge.h35
-rw-r--r--indra/newview/llpanelgroupnotices.cpp1
-rw-r--r--indra/newview/llpanelobjectinventory.cpp112
-rw-r--r--indra/newview/llselectmgr.cpp80
-rw-r--r--indra/newview/llselectmgr.h1
-rw-r--r--indra/newview/llspatialpartition.cpp1
-rw-r--r--indra/newview/llspatialpartition.h1
-rw-r--r--indra/newview/lltexturectrl.cpp6
-rw-r--r--indra/newview/lltooldraganddrop.cpp11
-rw-r--r--indra/newview/llviewerassettype.cpp2
-rw-r--r--indra/newview/llviewerdisplay.cpp8
-rw-r--r--indra/newview/llviewerfloaterreg.cpp6
-rw-r--r--indra/newview/llviewermenu.cpp2
-rw-r--r--indra/newview/llviewermenufile.cpp451
-rw-r--r--indra/newview/llviewermenufile.h83
-rw-r--r--indra/newview/llviewermessage.cpp1
-rw-r--r--indra/newview/llviewerregion.cpp2
-rw-r--r--indra/newview/llviewertexteditor.cpp1
-rw-r--r--indra/newview/llviewertexture.cpp2
-rw-r--r--indra/newview/llviewerwindow.cpp134
-rw-r--r--indra/newview/llvovolume.cpp204
-rw-r--r--indra/newview/llvovolume.h10
-rw-r--r--indra/newview/pipeline.cpp280
-rw-r--r--indra/newview/pipeline.h33
-rw-r--r--indra/newview/skins/default/textures/textures.xml2
-rw-r--r--indra/newview/skins/default/xui/en/floater_about.xml3
-rw-r--r--indra/newview/skins/default/xui/en/floater_inventory.xml21
-rw-r--r--indra/newview/skins/default/xui/en/floater_tools.xml3
-rw-r--r--indra/newview/skins/default/xui/en/menu_viewer.xml7396
-rw-r--r--indra/newview/skins/default/xui/en/notifications.xml25
-rw-r--r--indra/newview/skins/default/xui/en/panel_main_inventory.xml26
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml1
-rwxr-xr-xindra/newview/viewer_manifest.py7
49 files changed, 11012 insertions, 9385 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 649d86aaa6..e0fa0f2136 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -37,11 +37,13 @@ include(UnixInstall)
include(LLKDU)
include(ViewerMiscLibs)
include(LLLogin)
+include(GLOD)
include(CMakeCopyIfDifferent)
include_directories(
${DBUSGLIB_INCLUDE_DIRS}
${ELFIO_INCLUDE_DIR}
+ ${GLOD_INCLUDE_DIR}
${LLAUDIO_INCLUDE_DIRS}
${LLCHARACTER_INCLUDE_DIRS}
${LLCOMMON_INCLUDE_DIRS}
@@ -60,6 +62,8 @@ include_directories(
${LSCRIPT_INCLUDE_DIRS}
${LSCRIPT_INCLUDE_DIRS}/lscript_compile
${LLLOGIN_INCLUDE_DIRS}
+ ${LIBS_PREBUILT_DIR}/include/collada
+ ${LIBS_PREBUILT_DIR}/include/collada/1.4
)
set(viewer_SOURCE_FILES
@@ -174,6 +178,7 @@ set(viewer_SOURCE_FILES
llfloaterhelpbrowser.cpp
llfloaterhud.cpp
llfloaterimagepreview.cpp
+ llfloaterimportcollada.cpp
llfloaterinspect.cpp
llfloaterinventory.cpp
llfloaterjoystick.cpp
@@ -184,6 +189,7 @@ set(viewer_SOURCE_FILES
llfloatermediabrowser.cpp
llfloatermediasettings.cpp
llfloatermemleak.cpp
+ llfloatermodelpreview.cpp
llfloaternamedesc.cpp
llfloaternearbymedia.cpp
llfloaternotificationsconsole.cpp
@@ -670,6 +676,7 @@ set(viewer_HEADER_FILES
llfloaterhelpbrowser.h
llfloaterhud.h
llfloaterimagepreview.h
+ llfloaterimportcollada.h
llfloaterinspect.h
llfloaterinventory.h
llfloaterjoystick.h
@@ -680,6 +687,7 @@ set(viewer_HEADER_FILES
llfloatermediabrowser.h
llfloatermediasettings.h
llfloatermemleak.h
+ llfloatermodelpreview.h
llfloaternamedesc.h
llfloaternearbymedia.h
llfloaternotificationsconsole.h
@@ -1183,6 +1191,7 @@ if (WINDOWS)
${DINPUT_LIBRARY}
${DXGUID_LIBRARY}
kernel32
+ libboost_system
odbc32
odbccp32
ole32
@@ -1505,6 +1514,7 @@ target_link_libraries(${VIEWER_BINARY_NAME}
${DBUSGLIB_LIBRARIES}
${OPENGL_LIBRARIES}
${FMODWRAPPER_LIBRARY}
+ ${GLOD_LIBRARIES}
${OPENGL_LIBRARIES}
${SDL_LIBRARY}
${SMARTHEAP_LIBRARY}
diff --git a/indra/newview/app_settings/settings.xml b/indra/newview/app_settings/settings.xml
index 55ff255c38..1e0ba9da3d 100644
--- a/indra/newview/app_settings/settings.xml
+++ b/indra/newview/app_settings/settings.xml
@@ -7384,7 +7384,19 @@
<key>Value</key>
<integer>0</integer>
</map>
- <key>SafeMode</key>
+ <key>MeshThreadCount</key>
+ <map>
+ <key>Comment</key>
+ <string>Number of threads to use for loading meshes.</string>
+ <key>Persist</key>
+ <integer>1</integer>
+ <key>Type</key>
+ <string>U32</string>
+ <key>Value</key>
+ <integer>8</integer>
+ </map>
+
+ <key>SafeMode</key>
<map>
<key>Comment</key>
<string>Reset preferences, run in safe mode.</string>
diff --git a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
index 651959413c..45884d5732 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/multiSpotLightF.glsl
@@ -137,7 +137,7 @@ void main()
}
//float diff = clamp((proj_range-proj_focus)/proj_range, 0.0, 1.0);
- vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_ambient_lod);
+ vec4 amb_plcol = texture2DLod(projectionMap, proj_tc.xy, proj_lod);
amb_da += (da*da*0.5+0.5)*proj_ambiance;
diff --git a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
index a0026edcd2..4333cc64a7 100644
--- a/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
+++ b/indra/newview/app_settings/shaders/class2/deferred/sunLightF.glsl
@@ -224,11 +224,11 @@ void main()
//spotlight shadow 1
vec4 lpos = shadow_matrix[4]*spos;
- gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.1).x;
+ gl_FragColor[2] = pcfShadow(shadowMap4, lpos, 0.8).x;
//spotlight shadow 2
lpos = shadow_matrix[5]*spos;
- gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.1).x;
+ gl_FragColor[3] = pcfShadow(shadowMap5, lpos, 0.8).x;
//gl_FragColor.rgb = pos.xyz;
//gl_FragColor.b = shadow;
diff --git a/indra/newview/licenses-win32.txt b/indra/newview/licenses-win32.txt
index 7e6d4b4561..8736626907 100644
--- a/indra/newview/licenses-win32.txt
+++ b/indra/newview/licenses-win32.txt
@@ -769,3 +769,72 @@ 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.
+
+
+=============
+GLOD license
+=============
+The GLOD Open-Source License Version 1.0 June 16, 2004
+
+Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns
+Hopkins University and David Luebke, Brenden Schubert, University of
+Virginia. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, is 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 and
+ request.
+
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer and
+ request in the documentation and/or other materials provided with
+ the distribution.
+
+3. The name "GLOD" must not be used to endorse or promote products
+ derived from this software without prior written permission.
+
+4. Redistributions of any modified version of this source, whether in
+ source or binary form , must include a form of the following
+ acknowledgment: "This product is derived from the GLOD library,
+ which is available from http://www.cs.jhu.edu/~graphics/GLOD."
+
+5. Redistributions of any modified version of this source in binary
+ form must provide, free of charge, access to the modified version
+ of the code.
+
+6. This license shall be governed by and construed and enforced in
+ accordance with the laws of the State of Maryland, without
+ reference to its conflicts of law provisions. The exclusive
+ jurisdiction and venue for all legal actions relating to this
+ license shall be in courts of competent subject matter jurisdiction
+ located in the State of Maryland.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, GLOD IS PROVIDED
+UNDER THIS LICENSE ON AN AS IS BASIS, WITHOUT WARRANTY OF ANY KIND,
+EITHER EXPRESSED OR IMPLIED, INCLUDING, WITHOUT LIMITATION, WARRANTIES
+THAT GLOD IS FREE OF DEFECTS, MERCHANTABLE, FIT FOR A PARTICULAR
+PURPOSE OR NON-INFRINGING. ALL WARRANTIES ARE DISCLAIMED AND THE
+ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE CODE IS WITH
+YOU. SHOULD ANY CODE PROVE DEFECTIVE IN ANY RESPECT, YOU (NOT THE
+COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR) ASSUME THE COST OF ANY
+NECESSARY SERVICING, REPAIR OR CORRECTION. THIS DISCLAIMER OF WARRANTY
+CONSTITUTES AN ESSENTIAL PART OF THIS LICENSE. NO USE OF ANY CODE IS
+AUTHORIZED HEREUNDER EXCEPT UNDER THIS DISCLAIMER.
+
+TO THE MAXIMUM EXTENT PERMITTED BY APPLICABLE LAW, IN NO EVENT SHALL
+THE COPYRIGHT HOLDER OR ANY OTHER CONTRIBUTOR BE LIABLE FOR ANY
+SPECIAL, INCIDENTAL, INDIRECT, OR CONSEQUENTIAL DAMAGES FOR LOSS OF
+PROFITS, REVENUE, OR FOR LOSS OF INFORMATION OR ANY OTHER LOSS.
+
+YOU EXPRESSLY AGREE TO FOREVER INDEMNIFY, DEFEND AND HOLD HARMLESS THE
+COPYRIGHT HOLDERS AND CONTRIBUTORS OF GLOD AGAINST ALL CLAIMS,
+DEMANDS, SUITS OR OTHER ACTIONS ARISING DIRECTLY OR INDIRECTLY FROM
+YOUR ACCEPTANCE AND USE OF GLOD.
+
+Although NOT REQUIRED, we would appreciate it if active users of GLOD
+put a link on their web site to the GLOD web site when possible.
+
+
diff --git a/indra/newview/llassetuploadresponders.cpp b/indra/newview/llassetuploadresponders.cpp
index 4d85ecb97c..1c06f7d31c 100644
--- a/indra/newview/llassetuploadresponders.cpp
+++ b/indra/newview/llassetuploadresponders.cpp
@@ -43,6 +43,7 @@
#include "llinventorymodel.h"
#include "llinventorypanel.h"
#include "llfloaterinventory.h"
+#include "llfloaterimportcollada.h"
#include "llpermissionsflags.h"
#include "llpreviewnotecard.h"
#include "llpreviewscript.h"
@@ -65,6 +66,7 @@
#include "llfocusmgr.h"
#include "llscrolllistctrl.h"
#include "llsdserialize.h"
+#include "llsdutil.h"
#include "llvfs.h"
// When uploading multiple files, don't display any of them when uploading more than this number.
@@ -72,6 +74,120 @@ static const S32 FILE_COUNT_DISPLAY_THRESHOLD = 5;
void dialog_refresh_all();
+static void on_new_single_inventory_upload_complete(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType inventory_type,
+ const std::string inventory_type_string,
+ const LLUUID& item_folder_id,
+ const std::string& item_name,
+ const std::string& item_description,
+ const LLSD& server_response,
+ S32 upload_price)
+{
+ if ( upload_price > 0 )
+ {
+ // this upload costed us L$, update our balance
+ // and display something saying that it cost L$
+ LLStatusBar::sendMoneyBalanceRequest();
+
+ LLSD args;
+ args["AMOUNT"] = llformat("%d", upload_price);
+ LLNotifications::instance().add("UploadPayment", args);
+ }
+
+ // Actually add the upload to viewer inventory
+ llinfos << "Adding " << server_response["new_inventory_item"].asUUID()
+ << " " << server_response["new_asset"].asUUID()
+ << " to inventory." << llendl;
+
+ if( item_folder_id.notNull() )
+ {
+ U32 everyone_perms = PERM_NONE;
+ U32 group_perms = PERM_NONE;
+ U32 next_owner_perms = PERM_ALL;
+ if( server_response.has("new_next_owner_mask") )
+ {
+ // The server provided creation perms so use them.
+ // Do not assume we got the perms we asked for in
+ // since the server may not have granted them all.
+ everyone_perms = server_response["new_everyone_mask"].asInteger();
+ group_perms = server_response["new_group_mask"].asInteger();
+ next_owner_perms = server_response["new_next_owner_mask"].asInteger();
+ }
+ else
+ {
+ // The server doesn't provide creation perms
+ // so use old assumption-based perms.
+ if( inventory_type_string != "snapshot")
+ {
+ next_owner_perms = PERM_MOVE | PERM_TRANSFER;
+ }
+ }
+
+ LLPermissions new_perms;
+ new_perms.init(
+ gAgent.getID(),
+ gAgent.getID(),
+ LLUUID::null,
+ LLUUID::null);
+
+ new_perms.initMasks(
+ PERM_ALL,
+ PERM_ALL,
+ everyone_perms,
+ group_perms,
+ next_owner_perms);
+
+ S32 creation_date_now = time_corrected();
+ LLPointer<LLViewerInventoryItem> item = new LLViewerInventoryItem(
+ server_response["new_inventory_item"].asUUID(),
+ item_folder_id,
+ new_perms,
+ server_response["new_asset"].asUUID(),
+ asset_type,
+ inventory_type,
+ item_name,
+ item_description,
+ 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.
+ LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
+ if ( view )
+ {
+ LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
+
+ view->getPanel()->setSelection(
+ server_response["new_inventory_item"].asUUID(),
+ TAKE_FOCUS_NO);
+
+ if(
+ (LLAssetType::AT_TEXTURE == asset_type ||
+ LLAssetType::AT_SOUND == asset_type) &&
+ (LLFilePicker::instance().getFileCount() <=
+ FILE_COUNT_DISPLAY_THRESHOLD) )
+ {
+ view->getPanel()->openSelected();
+ }
+
+ // restore keyboard focus
+ gFocusMgr.setKeyboardFocus(focus);
+ }
+ }
+ else
+ {
+ llwarns << "Can't find a folder to put it in" << llendl;
+ }
+
+ // remove the "Uploading..." message
+ LLUploadDialog::modalUploadFinished();
+}
+
LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
const LLUUID& vfile_id,
LLAssetType::EType asset_type)
@@ -89,9 +205,10 @@ LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
}
}
-LLAssetUploadResponder::LLAssetUploadResponder(const LLSD &post_data,
- const std::string& file_name,
- LLAssetType::EType asset_type)
+LLAssetUploadResponder::LLAssetUploadResponder(
+ const LLSD &post_data,
+ const std::string& file_name,
+ LLAssetType::EType asset_type)
: LLHTTPClient::Responder(),
mPostData(post_data),
mFileName(file_name),
@@ -197,15 +314,19 @@ 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 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, LLAssetType::EType asset_type)
-: LLAssetUploadResponder(post_data, file_name, asset_type)
+LLNewAgentInventoryResponder::LLNewAgentInventoryResponder(
+ const LLSD& post_data,
+ const std::string& file_name,
+ LLAssetType::EType asset_type)
+ : LLAssetUploadResponder(post_data, file_name, asset_type)
{
}
@@ -220,96 +341,31 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
LLAssetType::EType asset_type = LLAssetType::lookup(mPostData["asset_type"].asString());
LLInventoryType::EType inventory_type = LLInventoryType::lookup(mPostData["inventory_type"].asString());
- S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
+ S32 expected_upload_cost = 0;
// Update L$ 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)
+ asset_type == LLAssetType::AT_ANIMATION ||
+ asset_type == LLAssetType::AT_MESH)
{
- LLStatusBar::sendMoneyBalanceRequest();
-
- LLSD args;
- args["AMOUNT"] = llformat("%d", expected_upload_cost);
- LLNotifications::instance().add("UploadPayment", args);
+ expected_upload_cost =
+ LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
}
- // 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())
- {
- //std::ostringstream out;
- //LLSDXMLFormatter *formatter = new LLSDXMLFormatter;
- //formatter->format(mPostData, out, LLSDFormatter::OPTIONS_PRETTY);
- //llinfos << "Post Data: " << out.str() << llendl;
+ on_new_single_inventory_upload_complete(
+ asset_type,
+ inventory_type,
+ mPostData["asset_type"].asString(),
+ mPostData["folder_id"].asUUID(),
+ mPostData["name"],
+ mPostData["description"],
+ content,
+ expected_upload_cost);
- U32 everyone_perms = PERM_NONE;
- U32 group_perms = PERM_NONE;
- U32 next_owner_perms = PERM_ALL;
- if(content.has("new_next_owner_mask"))
- {
- // This is a new sim that provides creation perms so use them.
- // Do not assume we got the perms we asked for in mPostData
- // since the sim may not have granted them all.
- everyone_perms = content["new_everyone_mask"].asInteger();
- group_perms = content["new_group_mask"].asInteger();
- next_owner_perms = content["new_next_owner_mask"].asInteger();
- }
- else
- {
- // This old sim doesn't provide creation perms so use old assumption-based perms.
- if(mPostData["inventory_type"].asString() != "snapshot")
- {
- next_owner_perms = PERM_MOVE | PERM_TRANSFER;
- }
- }
- LLPermissions new_perms;
- new_perms.init(gAgent.getID(), gAgent.getID(), LLUUID::null, LLUUID::null);
- new_perms.initMasks(PERM_ALL, PERM_ALL, everyone_perms, group_perms, next_owner_perms);
- S32 creation_date_now = time_corrected();
- LLPointer<LLViewerInventoryItem> item
- = new LLViewerInventoryItem(content["new_inventory_item"].asUUID(),
- mPostData["folder_id"].asUUID(),
- new_perms,
- 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.
- LLFloaterInventory* view = LLFloaterInventory::getActiveInventory();
- if(view)
- {
- LLFocusableElement* focus = gFocusMgr.getKeyboardFocus();
-
- view->getPanel()->setSelection(content["new_inventory_item"].asUUID(), TAKE_FOCUS_NO);
- if((LLAssetType::AT_TEXTURE == asset_type || LLAssetType::AT_SOUND == asset_type)
- && LLFilePicker::instance().getFileCount() <= FILE_COUNT_DISPLAY_THRESHOLD)
- {
- view->getPanel()->openSelected();
- }
- //LLFloaterInventory::dumpSelectionInformation((void*)view);
- // restore keyboard focus
- gFocusMgr.setKeyboardFocus(focus);
- }
- }
- else
- {
- llwarns << "Can't find a folder to put it in" << llendl;
- }
+ // continue uploading for bulk uploads
- // 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.
@@ -326,19 +382,42 @@ void LLNewAgentInventoryResponder::uploadComplete(const LLSD& content)
// Continuing the horrible hack above, we need to extract the originally requested permissions data, if any,
// and use them for each next file to be uploaded. Note the requested perms are not the same as the
- // granted ones found in the given "content" structure but can still be found in mPostData. -MG
- U32 everyone_perms = mPostData.has("everyone_mask") ? mPostData.get("everyone_mask" ).asInteger() : PERM_NONE;
- U32 group_perms = mPostData.has("group_mask") ? mPostData.get("group_mask" ).asInteger() : PERM_NONE;
- U32 next_owner_perms = mPostData.has("next_owner_mask") ? mPostData.get("next_owner_mask").asInteger() : PERM_NONE;
+ U32 everyone_perms =
+ content.has("everyone_mask") ?
+ content["everyone_mask"].asInteger() :
+ PERM_NONE;
+
+ U32 group_perms =
+ content.has("group_mask") ?
+ content["group_mask"].asInteger() :
+ PERM_NONE;
+
+ U32 next_owner_perms =
+ content.has("next_owner_mask") ?
+ content["next_owner_mask"].asInteger() :
+ PERM_NONE;
+
std::string display_name = LLStringUtil::null;
LLAssetStorage::LLStoreAssetCallback callback = NULL;
void *userdata = NULL;
- upload_new_resource(next_file, asset_name, asset_name,
- 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- next_owner_perms, group_perms,
- everyone_perms, display_name,
- callback, expected_upload_cost, userdata);
+
+ upload_new_resource(
+ next_file,
+ asset_name,
+ asset_name,
+ 0,
+ LLFolderType::FT_NONE,
+ LLInventoryType::IT_NONE,
+ next_owner_perms,
+ group_perms,
+ everyone_perms,
+ display_name,
+ callback,
+ LLGlobalEconomy::Singleton::getInstance()->getPriceUpload(),
+ userdata);
}
+
+ LLImportColladaAssetCache::getInstance()->assetUploaded(mVFileID, content["new_asset"], TRUE);
}
LLSendTexLayerResponder::LLSendTexLayerResponder(const LLSD& post_data,
@@ -392,17 +471,19 @@ void LLSendTexLayerResponder::error(U32 statusNum, const std::string& reason)
mBakedUploadData = NULL; // deleted in onTextureUploadComplete()
}
-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 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,
- LLAssetType::EType asset_type)
-: LLAssetUploadResponder(post_data, file_name, asset_type)
+LLUpdateAgentInventoryResponder::LLUpdateAgentInventoryResponder(
+ const LLSD& post_data,
+ const std::string& file_name,
+ LLAssetType::EType asset_type)
+ : LLAssetUploadResponder(post_data, file_name, asset_type)
{
}
@@ -585,3 +666,430 @@ void LLUpdateTaskInventoryResponder::uploadComplete(const LLSD& content)
break;
}
}
+
+
+/////////////////////////////////////////////////////
+// LLNewAgentInventoryVariablePriceResponder::Impl //
+/////////////////////////////////////////////////////
+class LLNewAgentInventoryVariablePriceResponder::Impl
+{
+public:
+ Impl(
+ const LLUUID& vfile_id,
+ const LLSD& inventory_data) :
+ mVFileID(vfile_id),
+ mInventoryData(inventory_data)
+ {
+ }
+
+ Impl(
+ const std::string& file_name,
+ const LLSD& inventory_data) :
+ mFileName(file_name),
+ mInventoryData(inventory_data)
+ {
+ }
+
+ std::string getFilenameOrIDString() const
+ {
+ return (mFileName.empty() ? mVFileID.asString() : mFileName);
+ }
+
+ LLUUID getVFileID() const
+ {
+ return mVFileID;
+ }
+
+ std::string getFilename() const
+ {
+ return mFileName;
+ }
+
+ LLAssetType::EType getAssetType() const
+ {
+ return LLAssetType::lookup(
+ mInventoryData["asset_type"].asString());
+ }
+
+ LLInventoryType::EType getInventoryType() const
+ {
+ return LLInventoryType::lookup(
+ mInventoryData["inventory_type"].asString());
+ }
+
+ std::string getInventoryTypeString() const
+ {
+ return mInventoryData["inventory_type"].asString();
+ }
+
+ LLUUID getFolderID() const
+ {
+ return mInventoryData["folder_id"].asUUID();
+ }
+
+ std::string getItemName() const
+ {
+ return mInventoryData["name"].asString();
+ }
+
+ std::string getItemDescription() const
+ {
+ return mInventoryData["description"].asString();
+ }
+
+ void displayCannotUploadReason(const std::string& reason)
+ {
+ LLSD args;
+ args["FILE"] = getFilenameOrIDString();
+ args["REASON"] = reason;
+
+
+ LLNotifications::instance().add("CannotUploadReason", args);
+ LLUploadDialog::modalUploadFinished();
+ }
+
+ void onApplicationLevelError(const LLSD& error)
+ {
+ static const std::string _IDENTIFIER = "identifier";
+
+ static const std::string _INSUFFICIENT_FUNDS =
+ "NewAgentInventory_InsufficientLindenDollarBalance";
+ static const std::string _MISSING_REQUIRED_PARAMETER =
+ "NewAgentInventory_MissingRequiredParamater";
+ static const std::string _INVALID_REQUEST_BODY =
+ "NewAgentInventory_InvalidRequestBody";
+ static const std::string _RESOURCE_COST_DIFFERS =
+ "NewAgentInventory_ResourceCostDiffers";
+
+ static const std::string _MISSING_PARAMETER = "missing_parameter";
+ static const std::string _INVALID_PARAMETER = "invalid_parameter";
+ static const std::string _MISSING_RESOURCE = "missing_resource";
+ static const std::string _INVALID_RESOURCE = "invalid_resource";
+
+ // TODO* Add the other error_identifiers
+
+ std::string error_identifier = error[_IDENTIFIER].asString();
+
+ // TODO*: Pull these user visible strings from an xml file
+ // to be localized
+ if ( _INSUFFICIENT_FUNDS == error_identifier )
+ {
+ displayCannotUploadReason("You do not have a sufficient L$ balance to complete this upload.");
+ }
+ else if ( _MISSING_REQUIRED_PARAMETER == error_identifier )
+ {
+ // Missing parameters
+ if (error.has(_MISSING_PARAMETER) )
+ {
+ std::string message =
+ "Upload request was missing required parameter '[P]'";
+ LLStringUtil::replaceString(
+ message,
+ "[P]",
+ error[_MISSING_PARAMETER].asString());
+
+ displayCannotUploadReason(message);
+ }
+ else
+ {
+ std::string message =
+ "Upload request was missing a required parameter";
+ displayCannotUploadReason(message);
+ }
+ }
+ else if ( _INVALID_REQUEST_BODY == error_identifier )
+ {
+ // Invalid request body, check to see if
+ // a particular parameter was invalid
+ if ( error.has(_INVALID_PARAMETER) )
+ {
+ std::string message = "Upload parameter '[P]' is invalid.";
+ LLStringUtil::replaceString(
+ message,
+ "[P]",
+ error[_INVALID_PARAMETER].asString());
+
+ // See if the server also responds with what resource
+ // is missing.
+ if ( error.has(_MISSING_RESOURCE) )
+ {
+ message += "\nMissing resource '[R]'.";
+
+ LLStringUtil::replaceString(
+ message,
+ "[R]",
+ error[_MISSING_RESOURCE].asString());
+ }
+ else if ( error.has(_INVALID_RESOURCE) )
+ {
+ message += "\nInvalid resource '[R]'.";
+
+ LLStringUtil::replaceString(
+ message,
+ "[R]",
+ error[_INVALID_RESOURCE].asString());
+ }
+
+ displayCannotUploadReason(message);
+ }
+ else
+ {
+ std::string message = "Upload request was malformed";
+ displayCannotUploadReason(message);
+ }
+ }
+ else if ( _RESOURCE_COST_DIFFERS == error_identifier )
+ {
+ displayCannotUploadReason("The resource cost associated with this upload is not consistent with the server.");
+ }
+ else
+ {
+ displayCannotUploadReason("Unknown Error");
+ }
+ }
+
+ void onTransportError()
+ {
+ displayCannotUploadReason(
+ "The server is experiencing unexpected difficulties.");
+ }
+
+ void onTransportError(const LLSD& error)
+ {
+ static const std::string _IDENTIFIER = "identifier";
+
+ static const std::string _SERVER_ERROR_AFTER_CHARGE =
+ "NewAgentInventory_ServerErrorAfterCharge";
+
+ std::string error_identifier = error[_IDENTIFIER].asString();
+
+ // TODO*: Pull the user visible strings from an xml file
+ // to be localized
+
+ if ( _SERVER_ERROR_AFTER_CHARGE == error_identifier )
+ {
+ displayCannotUploadReason(
+ "The server is experiencing unexpected difficulties. You may have been charged for the upload.");
+ }
+ else
+ {
+ displayCannotUploadReason(
+ "The server is experiencing unexpected difficulties.");
+ }
+ }
+
+ bool uploadConfirmationCallback(
+ const LLSD& notification,
+ const LLSD& response,
+ boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder> responder)
+ {
+ S32 option;
+ std::string confirmation_url;
+
+ option = LLNotification::getSelectedOption(
+ notification,
+ response);
+
+ confirmation_url =
+ notification["payload"]["confirmation_url"].asString();
+
+ // Yay! We are confirming or cancelling our upload
+ switch(option)
+ {
+ case 0:
+ {
+ if ( getFilename().empty() )
+ {
+ // we have no filename, use virtual file ID instead
+ LLHTTPClient::postFile(
+ confirmation_url,
+ getVFileID(),
+ getAssetType(),
+ responder);
+ }
+ else
+ {
+ LLHTTPClient::postFile(
+ confirmation_url,
+ getFilename(),
+ responder);
+ }
+ }
+ break;
+ case 1:
+ default:
+ break;
+ }
+
+ return false;
+ }
+
+private:
+ std::string mFileName;
+
+ LLSD mInventoryData;
+ LLUUID mVFileID;
+};
+
+///////////////////////////////////////////////
+// LLNewAgentInventoryVariablePriceResponder //
+///////////////////////////////////////////////
+LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
+ const LLUUID& vfile_id,
+ const LLSD& inventory_info)
+{
+ mImpl = new Impl(
+ vfile_id,
+ inventory_info);
+}
+
+LLNewAgentInventoryVariablePriceResponder::LLNewAgentInventoryVariablePriceResponder(
+ const std::string& file_name,
+ const LLSD& inventory_info)
+{
+ mImpl = new Impl(
+ file_name,
+ inventory_info);
+}
+
+LLNewAgentInventoryVariablePriceResponder::~LLNewAgentInventoryVariablePriceResponder()
+{
+ delete mImpl;
+}
+
+void LLNewAgentInventoryVariablePriceResponder::errorWithContent(
+ U32 statusNum,
+ const std::string& reason,
+ const LLSD& content)
+{
+ llinfos << "LLNewAgentInventoryVariablePrice::error " << statusNum
+ << " reason: " << reason << llendl;
+
+ if ( content.has("error") )
+ {
+ static const std::string _ERROR = "error";
+
+ mImpl->onTransportError(content[_ERROR]);
+ }
+ else
+ {
+ mImpl->onTransportError();
+ }
+}
+
+void LLNewAgentInventoryVariablePriceResponder::result(const LLSD& content)
+{
+ // Parse out application level errors and the appropriate
+ // responses for them
+ static const std::string _ERROR = "error";
+ static const std::string _STATE = "state";
+
+ static const std::string _COMPLETE = "complete";
+ static const std::string _CONFIRM_UPLOAD = "confirm_upload";
+
+ static const std::string _UPLOAD_PRICE = "upload_price";
+ static const std::string _RSVP = "rsvp";
+
+ // Check for application level errors
+ if ( content.has(_ERROR) )
+ {
+ onApplicationLevelError(content[_ERROR]);
+ return;
+ }
+
+ std::string state = content[_STATE];
+ LLAssetType::EType asset_type = mImpl->getAssetType();
+
+ if ( _COMPLETE == state )
+ {
+ // rename file in VFS with new asset id
+ if (mImpl->getFilename().empty())
+ {
+ // rename the file in the VFS to the actual asset id
+ // llinfos << "Changing uploaded asset UUID to " << content["new_asset"].asUUID() << llendl;
+ gVFS->renameFile(
+ mImpl->getVFileID(),
+ asset_type,
+ content["new_asset"].asUUID(),
+ asset_type);
+ }
+
+ on_new_single_inventory_upload_complete(
+ asset_type,
+ mImpl->getInventoryType(),
+ mImpl->getInventoryTypeString(),
+ mImpl->getFolderID(),
+ mImpl->getItemName(),
+ mImpl->getItemDescription(),
+ content,
+ content["upload_price"].asInteger());
+
+ // TODO* Add bulk (serial) uploading or add
+ // a super class of this that does so
+ }
+ else if ( _CONFIRM_UPLOAD == state )
+ {
+ showConfirmationDialog(
+ content[_UPLOAD_PRICE].asInteger(),
+ content[_RSVP].asString());
+ }
+ else
+ {
+ onApplicationLevelError("");
+ }
+}
+
+void LLNewAgentInventoryVariablePriceResponder::onApplicationLevelError(
+ const LLSD& error)
+{
+ mImpl->onApplicationLevelError(error);
+}
+
+void LLNewAgentInventoryVariablePriceResponder::showConfirmationDialog(
+ S32 upload_price,
+ const std::string& confirmation_url)
+{
+ if ( 0 == upload_price )
+ {
+ // don't show confirmation dialog for free uploads, I mean,
+ // they're free!
+ LLSD body;
+ body["confirm_upload"] = true;
+ body["expected_upload_price"] = upload_price;
+
+ LLHTTPClient::post(confirmation_url, body, this);
+ }
+ else
+ {
+ LLSD substitutions;
+ LLSD payload;
+
+ substitutions["PRICE"] = upload_price;
+
+ payload["confirmation_url"] = confirmation_url;
+
+ // The creating of a new instrusive_ptr(this)
+ // creates a new boost::intrusive_ptr
+ // which is a copy of this. This code is required because
+ // 'this' is always of type Class* and not the intrusive_ptr,
+ // and thus, a reference to 'this' is not registered
+ // by using just plain 'this'.
+
+ // Since LLNewAgentInventoryVariablePriceResponder is a
+ // reference counted class, it is possible (since the
+ // reference to a plain 'this' would be missed here) that,
+ // when using plain ol' 'this', that this object
+ // would be deleted before the callback is triggered
+ // and cause sadness.
+ LLNotifications::instance().add(
+ "UploadCostConfirmation",
+ substitutions,
+ payload,
+ boost::bind(
+ &LLNewAgentInventoryVariablePriceResponder::Impl::uploadConfirmationCallback,
+ mImpl,
+ _1,
+ _2,
+ boost::intrusive_ptr<LLNewAgentInventoryVariablePriceResponder>(this)));
+ }
+}
diff --git a/indra/newview/llassetuploadresponders.h b/indra/newview/llassetuploadresponders.h
index e656351305..9102f1597e 100644
--- a/indra/newview/llassetuploadresponders.h
+++ b/indra/newview/llassetuploadresponders.h
@@ -61,17 +61,57 @@ protected:
std::string mFileName;
};
+
+// TODO*: Remove this once deprecated
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,
- LLAssetType::EType asset_type);
+ LLNewAgentInventoryResponder(
+ const LLSD& post_data,
+ const LLUUID& vfile_id,
+ LLAssetType::EType asset_type);
+ LLNewAgentInventoryResponder(
+ const LLSD& post_data,
+ const std::string& file_name,
+ LLAssetType::EType asset_type);
virtual void uploadComplete(const LLSD& content);
};
+// A base class which goes through and performs some default
+// actions for variable price uploads. If more specific actions
+// are needed (such as different confirmation messages, etc.)
+// the functions onApplicationLevelError and showConfirmationDialog.
+class LLNewAgentInventoryVariablePriceResponder :
+ public LLHTTPClient::Responder
+{
+public:
+ LLNewAgentInventoryVariablePriceResponder(
+ const LLUUID& vfile_id,
+ const LLSD& inventory_info);
+
+ LLNewAgentInventoryVariablePriceResponder(
+ const std::string& file_name,
+ const LLSD& inventory_info);
+
+ virtual ~LLNewAgentInventoryVariablePriceResponder();
+
+ void errorWithContent(
+ U32 statusNum,
+ const std::string& reason,
+ const LLSD& content);
+ void result(const LLSD& content);
+
+ virtual void onApplicationLevelError(
+ const LLSD& error);
+ virtual void showConfirmationDialog(
+ S32 upload_price,
+ const std::string& confirmation_url);
+
+private:
+ class Impl;
+ Impl* mImpl;
+};
+
class LLBakedUploadData;
class LLSendTexLayerResponder : public LLAssetUploadResponder
{
diff --git a/indra/newview/lldrawable.h b/indra/newview/lldrawable.h
index 5a10b688da..27c9ab319a 100644
--- a/indra/newview/lldrawable.h
+++ b/indra/newview/lldrawable.h
@@ -314,8 +314,10 @@ private:
inline LLFace* LLDrawable::getFace(const S32 i) const
{
- llassert((U32)i < mFaces.size());
- llassert(mFaces[i]);
+ if ((U32) i >= mFaces.size())
+ {
+ return NULL;
+ }
return mFaces[i];
}
diff --git a/indra/newview/lldrawpoolbump.cpp b/indra/newview/lldrawpoolbump.cpp
index 5f845c3721..4778865c4b 100644
--- a/indra/newview/lldrawpoolbump.cpp
+++ b/indra/newview/lldrawpoolbump.cpp
@@ -701,6 +701,18 @@ void LLDrawPoolBump::endBump()
gGL.setSceneBlendType(LLRender::BT_ALPHA);
}
+S32 LLDrawPoolBump::getNumDeferredPasses()
+{
+ if (gSavedSettings.getBOOL("RenderObjectBump"))
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
void LLDrawPoolBump::beginDeferredPass(S32 pass)
{
if (!gPipeline.hasRenderBatches(LLRenderPass::PASS_BUMP))
diff --git a/indra/newview/lldrawpoolbump.h b/indra/newview/lldrawpoolbump.h
index bf940cf1e4..2019f1df26 100644
--- a/indra/newview/lldrawpoolbump.h
+++ b/indra/newview/lldrawpoolbump.h
@@ -79,7 +79,7 @@ public:
void renderBump();
void endBump();
- virtual S32 getNumDeferredPasses() { return 1; }
+ virtual S32 getNumDeferredPasses();
/*virtual*/ void beginDeferredPass(S32 pass);
/*virtual*/ void endDeferredPass(S32 pass);
/*virtual*/ void renderDeferred(S32 pass);
diff --git a/indra/newview/llface.cpp b/indra/newview/llface.cpp
index c54b83d865..16c1aea684 100644
--- a/indra/newview/llface.cpp
+++ b/indra/newview/llface.cpp
@@ -1057,7 +1057,7 @@ BOOL LLFace::getGeometryVolume(const LLVolume& volume,
if (full_rebuild)
{
mVertexBuffer->getIndexStrider(indicesp, mIndicesIndex);
- for (U16 i = 0; i < num_indices; i++)
+ for (S32 i = 0; i < num_indices; i++)
{
*indicesp++ = vf.mIndices[i] + index_offset;
}
diff --git a/indra/newview/llfilepicker.cpp b/indra/newview/llfilepicker.cpp
index 028e1cc098..8dfb333530 100644
--- a/indra/newview/llfilepicker.cpp
+++ b/indra/newview/llfilepicker.cpp
@@ -55,12 +55,14 @@ LLFilePicker LLFilePicker::sInstance;
#define SOUND_FILTER L"Sounds (*.wav)\0*.wav\0"
#define IMAGE_FILTER L"Images (*.tga; *.bmp; *.jpg; *.jpeg; *.png)\0*.tga;*.bmp;*.jpg;*.jpeg;*.png\0"
#define ANIM_FILTER L"Animations (*.bvh)\0*.bvh\0"
+#define COLLADA_FILTER L"Scene (*.dae)\0*.dae\0"
#ifdef _CORY_TESTING
#define GEOMETRY_FILTER L"SL Geometry (*.slg)\0*.slg\0"
#endif
#define XML_FILTER L"XML files (*.xml)\0*.xml\0"
#define SLOBJECT_FILTER L"Objects (*.slobject)\0*.slobject\0"
#define RAW_FILTER L"RAW files (*.raw)\0*.raw\0"
+#define MODEL_FILTER L"Model files (*.dae)\0*.dae\0"
#endif
//
@@ -175,6 +177,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = ANIM_FILTER \
L"\0";
break;
+ case FFLOAD_COLLADA:
+ mOFN.lpstrFilter = COLLADA_FILTER \
+ L"\0";
+ break;
#ifdef _CORY_TESTING
case FFLOAD_GEOMETRY:
mOFN.lpstrFilter = GEOMETRY_FILTER \
@@ -193,6 +199,10 @@ BOOL LLFilePicker::setupFilter(ELoadFilter filter)
mOFN.lpstrFilter = RAW_FILTER \
L"\0";
break;
+ case FFLOAD_MODEL:
+ mOFN.lpstrFilter = MODEL_FILTER \
+ L"\0";
+ break;
default:
res = FALSE;
break;
@@ -542,6 +552,15 @@ Boolean LLFilePicker::navOpenFilterProc(AEDesc *theItem, void *info, void *callB
result = false;
}
}
+ else if (filter == FFLOAD_COLLADA)
+ {
+ if (fileInfo.filetype != 'DAE ' &&
+ (fileInfo.extension && (CFStringCompare(fileInfo.extension, CFSTR("dae"), kCFCompareCaseInsensitive) != kCFCompareEqualTo))
+ )
+ {
+ result = false;
+ }
+ }
#ifdef _CORY_TESTING
else if (filter == FFLOAD_GEOMETRY)
{
@@ -1088,6 +1107,12 @@ static std::string add_bvh_filter_to_gtkchooser(GtkWindow *picker)
LLTrans::getString("animation_files") + " (*.bvh)");
}
+static std::string add_collada_filter_to_gtkchooser(GtkWindow *picker)
+{
+ return add_simple_pattern_filter_to_gtkchooser(picker, "*.dae",
+ LLTrans::getString("scene_files") + " (*.dae)");
+}
+
static std::string add_imageload_filter_to_gtkchooser(GtkWindow *picker)
{
GtkFileFilter *gfilter = gtk_file_filter_new();
@@ -1212,6 +1237,9 @@ BOOL LLFilePicker::getOpenFile( ELoadFilter filter )
case FFLOAD_ANIM:
filtername = add_bvh_filter_to_gtkchooser(picker);
break;
+ case FFLOAD_COLLADA:
+ filtername = add_collada_filter_to_gtkchooser(picker);
+ break;
case FFLOAD_IMAGE:
filtername = add_imageload_filter_to_gtkchooser(picker);
break;
diff --git a/indra/newview/llfilepicker.h b/indra/newview/llfilepicker.h
index ab2455620f..10736c7dd0 100644
--- a/indra/newview/llfilepicker.h
+++ b/indra/newview/llfilepicker.h
@@ -93,6 +93,8 @@ public:
FFLOAD_XML = 6,
FFLOAD_SLOBJECT = 7,
FFLOAD_RAW = 8,
+ FFLOAD_MODEL = 9,
+ FFLOAD_COLLADA = 10,
};
enum ESaveFilter
@@ -198,4 +200,6 @@ public:
~LLFilePicker();
};
+const std::string upload_pick(void* data);
+
#endif
diff --git a/indra/newview/llhudtext.cpp b/indra/newview/llhudtext.cpp
index 55019f91f8..58637329d7 100644
--- a/indra/newview/llhudtext.cpp
+++ b/indra/newview/llhudtext.cpp
@@ -567,6 +567,18 @@ void LLHUDText::setStringUTF8(const std::string &wtext)
setString(utf8str_to_wstring(wtext));
}
+std::string LLHUDText::getString()
+{
+ std::ostringstream ostr;
+ for (U32 i = 0; i < mTextSegments.size(); ++i)
+ {
+ const std::string str = wstring_to_utf8str(mTextSegments[i].getText());
+ ostr << str;
+ }
+
+ return ostr.str();
+}
+
void LLHUDText::setString(const LLWString &wtext)
{
mTextSegments.clear();
diff --git a/indra/newview/llhudtext.h b/indra/newview/llhudtext.h
index dc14a8c764..4787a15eaf 100644
--- a/indra/newview/llhudtext.h
+++ b/indra/newview/llhudtext.h
@@ -90,6 +90,7 @@ public:
public:
void setStringUTF8(const std::string &utf8string);
+ std::string getString();
void setString(const LLWString &wstring);
void clearString();
void addLine(const std::string &text, const LLColor4& color, const LLFontGL::StyleFlags style = LLFontGL::NORMAL);
diff --git a/indra/newview/llinventorybridge.cpp b/indra/newview/llinventorybridge.cpp
index 1bc9297bba..70e2daad0d 100644
--- a/indra/newview/llinventorybridge.cpp
+++ b/indra/newview/llinventorybridge.cpp
@@ -1,5209 +1,5301 @@
-/**
- * @file llinventorybridge.cpp
- * @brief Implementation of the Inventory-Folder-View-Bridge classes.
- *
- * $LicenseInfo:firstyear=2001&license=viewergpl$
- *
- * Copyright (c) 2001-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
-
-#include "llviewerprecompiledheaders.h"
-
-#include <utility> // for std::pair<>
-
-#include "llfloaterinventory.h"
-#include "llinventorybridge.h"
-
-#include "message.h"
-
-#include "llagent.h"
-#include "llagentwearables.h"
-#include "llcallingcard.h"
-#include "llcheckboxctrl.h" // for radio buttons
-#include "llfloaterreg.h"
-#include "llradiogroup.h"
-#include "llspinctrl.h"
-#include "lltextbox.h"
-#include "llui.h"
-
-#include "llviewercontrol.h"
-#include "llfirstuse.h"
-#include "llfoldertype.h"
-#include "llfloaterchat.h"
-#include "llfloatercustomize.h"
-#include "llfloaterproperties.h"
-#include "llfloaterworldmap.h"
-#include "llfocusmgr.h"
-#include "llfolderview.h"
-#include "llfriendcard.h"
-#include "llavataractions.h"
-#include "llgesturemgr.h"
-#include "lliconctrl.h"
-#include "llinventoryfunctions.h"
-#include "llinventorymodel.h"
-#include "llinventorypanel.h"
-#include "llinventoryclipboard.h"
-#include "lllineeditor.h"
-#include "llmenugl.h"
-#include "llpreviewanim.h"
-#include "llpreviewgesture.h"
-#include "llpreviewnotecard.h"
-#include "llpreviewscript.h"
-#include "llpreviewsound.h"
-#include "llpreviewtexture.h"
-#include "llresmgr.h"
-#include "llscrollcontainer.h"
-#include "llimview.h"
-#include "lltooldraganddrop.h"
-#include "llviewerfoldertype.h"
-#include "llviewertexturelist.h"
-#include "llviewerinventory.h"
-#include "llviewerobjectlist.h"
-#include "llviewerwindow.h"
-#include "llvoavatar.h"
-#include "llwearable.h"
-#include "llwearablelist.h"
-#include "llviewerassettype.h"
-#include "llviewermessage.h"
-#include "llviewerregion.h"
-#include "llvoavatarself.h"
-#include "lltabcontainer.h"
-#include "lluictrlfactory.h"
-#include "llselectmgr.h"
-#include "llsidetray.h"
-#include "llfloateropenobject.h"
-#include "lltrans.h"
-#include "llappearancemgr.h"
-#include "llimfloater.h"
-
-using namespace LLOldEvents;
-
-// Helpers
-// bug in busy count inc/dec right now, logic is complex... do we really need it?
-void inc_busy_count()
-{
-// gViewerWindow->getWindow()->incBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-void dec_busy_count()
-{
-// gViewerWindow->getWindow()->decBusyCount();
-// check balance of these calls if this code is changed to ever actually
-// *do* something!
-}
-
-// Function declarations
-void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
-void remove_inventory_category_from_avatar(LLInventoryCategory* category);
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
-bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
-
-std::string ICON_NAME[ICON_NAME_COUNT] =
-{
- "Inv_Texture",
- "Inv_Sound",
- "Inv_CallingCard",
- "Inv_CallingCard",
- "Inv_Landmark",
- "Inv_Landmark",
- "Inv_Script",
- "Inv_Clothing",
- "Inv_Object",
- "Inv_Object",
- "Inv_Notecard",
- "Inv_Skin",
- "Inv_Snapshot",
-
- "Inv_BodyShape",
- "Inv_Skin",
- "Inv_Hair",
- "Inv_Eye",
- "Inv_Shirt",
- "Inv_Pants",
- "Inv_Shoe",
- "Inv_Socks",
- "Inv_Jacket",
- "Inv_Gloves",
- "Inv_Undershirt",
- "Inv_Underpants",
- "Inv_Skirt",
- "Inv_Alpha",
- "Inv_Tattoo",
-
- "Inv_Animation",
- "Inv_Gesture",
-
- "inv_item_linkitem.tga",
- "inv_item_linkfolder.tga"
-};
-
-
-// +=================================================+
-// | LLInventoryPanelObserver |
-// +=================================================+
-void LLInventoryPanelObserver::changed(U32 mask)
-{
- mIP->modelChanged(mask);
-}
-
-
-// +=================================================+
-// | LLInvFVBridge |
-// +=================================================+
-
-LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
-mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
-{
- mInventoryPanel = inventory->getHandle();
-}
-
-const std::string& LLInvFVBridge::getName() const
-{
- LLInventoryObject* obj = getInventoryObject();
- if(obj)
- {
- return obj->getName();
- }
- return LLStringUtil::null;
-}
-
-const std::string& LLInvFVBridge::getDisplayName() const
-{
- return getName();
-}
-
-// Folders have full perms
-PermissionMask LLInvFVBridge::getPermissionMask() const
-{
-
- return PERM_ALL;
-}
-
-// virtual
-LLFolderType::EType LLInvFVBridge::getPreferredType() const
-{
- return LLFolderType::FT_NONE;
-}
-
-
-// Folders don't have creation dates.
-time_t LLInvFVBridge::getCreationDate() const
-{
- return 0;
-}
-
-// Can be destoryed (or moved to trash)
-BOOL LLInvFVBridge::isItemRemovable()
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-// Sends an update to all link items that point to the base item.
-void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
-
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- if (itemp->getIsLinkType())
- {
- return;
- }
-
- LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
- for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
- iter != item_array.end();
- iter++)
- {
- LLViewerInventoryItem *linked_item = (*iter);
- if (linked_item->getUUID() == item_id) continue;
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
- new_item->rename(new_name);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
- // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
- }
- model->notifyObservers();
-}
-
-// Can be moved to another folder
-BOOL LLInvFVBridge::isItemMovable() const
-{
- return TRUE;
-}
-
-/*virtual*/
-/**
- * @brief Adds this item into clipboard storage
- */
-void LLInvFVBridge::cutToClipboard()
-{
- if(isItemMovable())
- {
- LLInventoryClipboard::instance().cut(mUUID);
- }
-}
-// *TODO: make sure this does the right thing
-void LLInvFVBridge::showProperties()
-{
- LLSD key;
- key["id"] = mUUID;
- LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
-
- // Disable old properties floater; this is replaced by the sidepanel.
- /*
- LLFloaterReg::showInstance("properties", mUUID);
- */
-}
-
-void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
-{
- // Deactivate gestures when moving them into Trash
- LLInvFVBridge* bridge;
- LLInventoryModel* model = getInventoryModel();
- LLViewerInventoryItem* item = NULL;
- LLViewerInventoryCategory* cat = NULL;
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- S32 count = batch.count();
- S32 i,j;
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
- if (item)
- {
- if(LLAssetType::AT_GESTURE == item->getType())
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
- }
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
- if (cat)
- {
- gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
- for (j=0; j<descendent_items.count(); j++)
- {
- if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
- {
- LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
- }
- }
- }
- }
- removeBatchNoCheck(batch);
-}
-
-void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
-{
- // this method moves a bunch of items and folders to the trash. As
- // per design guidelines for the inventory model, the message is
- // built and the accounting is performed first. After all of that,
- // we call LLInventoryModel::moveObject() to move everything
- // around.
- LLInvFVBridge* bridge;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLMessageSystem* msg = gMessageSystem;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- LLViewerInventoryItem* item = NULL;
- LLViewerInventoryCategory* cat = NULL;
- std::vector<LLUUID> move_ids;
- LLInventoryModel::update_map_t update;
- bool start_new_message = true;
- S32 count = batch.count();
- S32 i;
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
- if(item)
- {
- if(item->getParentUUID() == trash_id) continue;
- move_ids.push_back(item->getUUID());
- LLPreview::hide(item->getUUID());
- --update[item->getParentUUID()];
- ++update[trash_id];
- if(start_new_message)
- {
- start_new_message = false;
- msg->newMessageFast(_PREHASH_MoveInventoryItem);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addBOOLFast(_PREHASH_Stamp, TRUE);
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
- msg->addUUIDFast(_PREHASH_FolderID, trash_id);
- msg->addString("NewName", NULL);
- if(msg->isSendFullFast(_PREHASH_InventoryData))
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- }
- }
- if(!start_new_message)
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- for(i = 0; i < count; ++i)
- {
- bridge = (LLInvFVBridge*)(batch.get(i));
- if(!bridge || !bridge->isItemRemovable()) continue;
- cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
- if(cat)
- {
- if(cat->getParentUUID() == trash_id) continue;
- move_ids.push_back(cat->getUUID());
- --update[cat->getParentUUID()];
- ++update[trash_id];
- if(start_new_message)
- {
- start_new_message = false;
- msg->newMessageFast(_PREHASH_MoveInventoryFolder);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->addBOOL("Stamp", TRUE);
- }
- msg->nextBlockFast(_PREHASH_InventoryData);
- msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
- msg->addUUIDFast(_PREHASH_ParentID, trash_id);
- if(msg->isSendFullFast(_PREHASH_InventoryData))
- {
- start_new_message = true;
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- update.clear();
- }
- }
- }
- if(!start_new_message)
- {
- gAgent.sendReliableMessage();
- gInventory.accountForUpdate(update);
- }
-
- // move everything.
- std::vector<LLUUID>::iterator it = move_ids.begin();
- std::vector<LLUUID>::iterator end = move_ids.end();
- for(; it != end; ++it)
- {
- gInventory.moveObject((*it), trash_id);
- }
-
- // notify inventory observers.
- model->notifyObservers();
-}
-
-BOOL LLInvFVBridge::isClipboardPasteable() const
-{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
- {
- return FALSE;
- }
- LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- const LLUUID &agent_id = gAgent.getID();
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &item_id = objects.get(i);
-
- // Can't paste folders
- const LLInventoryCategory *cat = model->getCategory(item_id);
- if (cat)
- {
- return FALSE;
- }
-
- const LLInventoryItem *item = model->getItem(item_id);
- if (item)
- {
- if (!item->getPermissions().allowCopyBy(agent_id))
- {
- return FALSE;
- }
- }
- }
- return TRUE;
-}
-
-BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
-{
- if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
- {
- return FALSE;
- }
- const LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLInventoryItem *item = model->getItem(objects.get(i));
- if (item)
- {
- if (!LLAssetType::lookupCanLink(item->getActualType()))
- {
- return FALSE;
- }
- }
- const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
- if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
- {
- return FALSE;
- }
- }
- return TRUE;
-}
-
-void hide_context_entries(LLMenuGL& menu,
- const std::vector<std::string> &entries_to_show,
- const std::vector<std::string> &disabled_entries)
-{
- const LLView::child_list_t *list = menu.getChildList();
-
- LLView::child_list_t::const_iterator itor;
- for (itor = list->begin(); itor != list->end(); ++itor)
- {
- std::string name = (*itor)->getName();
-
- // descend into split menus:
- LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
- if ((name == "More") && branchp)
- {
- hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
- }
-
-
- bool found = false;
- std::vector<std::string>::const_iterator itor2;
- for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
- {
- if (*itor2 == name)
- {
- found = true;
- }
- }
- if (!found)
- {
- (*itor)->setVisible(FALSE);
- }
- else
- {
- for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
- {
- if (*itor2 == name)
- {
- (*itor)->setEnabled(FALSE);
- }
- }
- }
- }
-}
-
-// Helper for commonly-used entries
-void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
- std::vector<std::string> &items,
- std::vector<std::string> &disabled_items, U32 flags)
-{
- items.push_back(std::string("Rename"));
- if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Rename"));
- }
-
- if (show_asset_id)
- {
- items.push_back(std::string("Copy Asset UUID"));
- if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
- || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Copy Asset UUID"));
- }
- }
-
- items.push_back(std::string("Copy Separator"));
-
- items.push_back(std::string("Copy"));
- if (!isItemCopyable())
- {
- disabled_items.push_back(std::string("Copy"));
- }
-
- items.push_back(std::string("Paste"));
- if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Paste"));
- }
-
- items.push_back(std::string("Paste As Link"));
- if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Paste As Link"));
- }
- items.push_back(std::string("Paste Separator"));
-
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
-
- // If multiple items are selected, disable properties (if it exists).
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Properties"));
- }
-}
-
-void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("PurgeItem"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("PurgeItem"));
- }
- items.push_back(std::string("RestoreItem"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// *TODO: remove this
-BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
-{
- BOOL rv = FALSE;
-
- const LLInventoryObject* obj = getInventoryObject();
-
- if(obj)
- {
- *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
- if(*type == DAD_NONE)
- {
- return FALSE;
- }
-
- *id = obj->getUUID();
- //object_ids.put(obj->getUUID());
-
- if (*type == DAD_CATEGORY)
- {
- gInventory.startBackgroundFetch(obj->getUUID());
- }
-
- rv = TRUE;
- }
-
- return rv;
-}
-
-LLInventoryObject* LLInvFVBridge::getInventoryObject() const
-{
- LLInventoryObject* obj = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- obj = (LLInventoryObject*)model->getObject(mUUID);
- }
- return obj;
-}
-
-LLInventoryModel* LLInvFVBridge::getInventoryModel() const
-{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- return panel ? panel->getModel() : NULL;
-}
-
-BOOL LLInvFVBridge::isInTrash() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- return model->isObjectDescendentOf(mUUID, trash_id);
-}
-
-BOOL LLInvFVBridge::isLinkedObjectInTrash() const
-{
- if (isInTrash()) return TRUE;
-
- const LLInventoryObject *obj = getInventoryObject();
- if (obj && obj->getIsLinkType())
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
- }
- return FALSE;
-}
-
-BOOL LLInvFVBridge::isAgentInventory() const
-{
- const LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- if(gInventory.getRootFolderID() == mUUID) return TRUE;
- return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
-}
-
-BOOL LLInvFVBridge::isCOFFolder() const
-{
- const LLInventoryModel* model = getInventoryModel();
- if(!model) return TRUE;
- const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL LLInvFVBridge::isItemPermissive() const
-{
- return FALSE;
-}
-
-// static
-void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
- LLViewerInventoryItem* item,
- const LLUUID& new_parent,
- BOOL restamp)
-{
- if(item->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->setParent(new_parent);
- new_item->updateParentOnServer(restamp);
- model->updateItem(new_item);
- model->notifyObservers();
- }
-}
-
-// static
-void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
- LLViewerInventoryCategory* cat,
- const LLUUID& new_parent,
- BOOL restamp)
-{
- if(cat->getParentUUID() != new_parent)
- {
- LLInventoryModel::update_list_t update;
- LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
- update.push_back(old_folder);
- LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
- update.push_back(new_folder);
- gInventory.accountForUpdate(update);
-
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->setParent(new_parent);
- new_cat->updateParentOnServer(restamp);
- model->updateCategory(new_cat);
- model->notifyObservers();
- }
-}
-
-
-const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
-{
- const std::string rv= LLInventoryType::lookup(inv_type);
- if(rv.empty())
- {
- return std::string("<invalid>");
- }
- return rv;
-}
-
-LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
- LLAssetType::EType actual_asset_type,
- LLInventoryType::EType inv_type,
- LLInventoryPanel* inventory,
- const LLUUID& uuid,
- U32 flags)
-{
- LLInvFVBridge* new_listener = NULL;
- switch(asset_type)
- {
- case LLAssetType::AT_TEXTURE:
- if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLTextureBridge(inventory, uuid, inv_type);
- break;
-
- case LLAssetType::AT_SOUND:
- if(!(inv_type == LLInventoryType::IT_SOUND))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLSoundBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_LANDMARK:
- if(!(inv_type == LLInventoryType::IT_LANDMARK))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLandmarkBridge(inventory, uuid, flags);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLCallingCardBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_SCRIPT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLScriptBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_OBJECT:
- if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
- break;
-
- case LLAssetType::AT_NOTECARD:
- if(!(inv_type == LLInventoryType::IT_NOTECARD))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLNotecardBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_ANIMATION:
- if(!(inv_type == LLInventoryType::IT_ANIMATION))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLAnimationBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_GESTURE:
- if(!(inv_type == LLInventoryType::IT_GESTURE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLGestureBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_LSL_TEXT:
- if(!(inv_type == LLInventoryType::IT_LSL))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLLSLTextBridge(inventory, uuid);
- break;
-
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- if(!(inv_type == LLInventoryType::IT_WEARABLE))
- {
- llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
- }
- new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
- break;
- case LLAssetType::AT_CATEGORY:
- case LLAssetType::AT_ROOT_CATEGORY:
- if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
- {
- // Create a link folder handler instead.
- new_listener = new LLLinkFolderBridge(inventory, uuid);
- break;
- }
- new_listener = new LLFolderBridge(inventory, uuid);
- break;
- case LLAssetType::AT_LINK:
- // Only should happen for broken links.
- new_listener = new LLLinkItemBridge(inventory, uuid);
- break;
- case LLAssetType::AT_LINK_FOLDER:
- // Only should happen for broken links.
- new_listener = new LLLinkItemBridge(inventory, uuid);
- break;
- default:
- llinfos << "Unhandled asset type (llassetstorage.h): "
- << (S32)asset_type << llendl;
- break;
- }
-
- if (new_listener)
- {
- new_listener->mInvType = inv_type;
- }
-
- return new_listener;
-}
-
-void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
-{
- LLInventoryCategory* cat = model->getCategory(uuid);
- if (cat)
- {
- model->purgeDescendentsOf(uuid);
- model->notifyObservers();
- }
- LLInventoryObject* obj = model->getObject(uuid);
- if (obj)
- {
- model->purgeObject(uuid);
- model->notifyObservers();
- }
-}
-
-// +=================================================+
-// | InventoryFVBridgeBuilder |
-// +=================================================+
-LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
- LLAssetType::EType actual_asset_type,
- LLInventoryType::EType inv_type,
- LLInventoryPanel* inventory,
- const LLUUID& uuid,
- U32 flags /* = 0x00 */) const
-{
- return LLInvFVBridge::createBridge(asset_type,
- actual_asset_type,
- inv_type,
- inventory,
- uuid,
- flags);
-}
-
-// +=================================================+
-// | LLItemBridge |
-// +=================================================+
-
-void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("goto" == action)
- {
- gotoItem(folder);
- }
- if ("open" == action)
- {
- openItem();
- return;
- }
- else if ("properties" == action)
- {
- showProperties();
- return;
- }
- else if ("purge" == action)
- {
- purgeItem(model, mUUID);
- return;
- }
- else if ("restoreToWorld" == action)
- {
- restoreToWorld();
- return;
- }
- else if ("restore" == action)
- {
- restoreItem();
- return;
- }
- else if ("copy_uuid" == action)
- {
- // Single item only
- LLInventoryItem* item = model->getItem(mUUID);
- if(!item) return;
- LLUUID asset_id = item->getAssetUUID();
- std::string buffer;
- asset_id.toString(buffer);
-
- gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
- return;
- }
- else if ("copy" == action)
- {
- copyToClipboard();
- return;
- }
- else if ("paste" == action)
- {
- // Single item only
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
- if (!folder_view_itemp) return;
-
- folder_view_itemp->getListener()->pasteFromClipboard();
- return;
- }
- else if ("paste_link" == action)
- {
- // Single item only
- LLInventoryItem* itemp = model->getItem(mUUID);
- if (!itemp) return;
-
- LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
- if (!folder_view_itemp) return;
-
- folder_view_itemp->getListener()->pasteLinkFromClipboard();
- return;
- }
-}
-
-void LLItemBridge::selectItem()
-{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
- if(item && !item->isComplete())
- {
- item->fetchFromServer();
- }
-}
-
-void LLItemBridge::restoreItem()
-{
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
- if(item)
- {
- LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
- // do not restamp on restore.
- LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
- }
-}
-
-void LLItemBridge::restoreToWorld()
-{
- LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
- if (itemp)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessage("RezRestoreToWorld");
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
-
- msg->nextBlockFast(_PREHASH_InventoryData);
- itemp->packMessage(msg);
- msg->sendReliable(gAgent.getRegion()->getHost());
- }
-
- //Similar functionality to the drag and drop rez logic
- BOOL remove_from_inventory = FALSE;
-
- //remove local inventory copy, sim will deal with permissions and removing the item
- //from the actual inventory if its a no-copy etc
- if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
- {
- remove_from_inventory = TRUE;
- }
-
- // Check if it's in the trash. (again similar to the normal rez logic)
- const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
- if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
- {
- remove_from_inventory = TRUE;
- }
-
- if(remove_from_inventory)
- {
- gInventory.deleteObject(itemp->getUUID());
- gInventory.notifyObservers();
- }
-}
-
-void LLItemBridge::gotoItem(LLFolderView *folder)
-{
- LLInventoryObject *obj = getInventoryObject();
- if (obj && obj->getIsLinkType())
- {
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
- if (active_panel)
- {
- active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
- }
- }
-}
-
-LLUIImagePtr LLItemBridge::getIcon() const
-{
- return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
-}
-
-PermissionMask LLItemBridge::getPermissionMask() const
-{
- LLViewerInventoryItem* item = getItem();
- PermissionMask perm_mask = 0;
- if(item)
- {
- BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
- BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
- BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
-
- if (copy) perm_mask |= PERM_COPY;
- if (mod) perm_mask |= PERM_MODIFY;
- if (xfer) perm_mask |= PERM_TRANSFER;
-
- }
- return perm_mask;
-}
-
-const std::string& LLItemBridge::getDisplayName() const
-{
- if(mDisplayName.empty())
- {
- buildDisplayName(getItem(), mDisplayName);
- }
- return mDisplayName;
-}
-
-void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
-{
- if(item)
- {
- name.assign(item->getName());
- }
- else
- {
- name.assign(LLStringUtil::null);
- }
-}
-
-LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
-{
- U8 font = LLFontGL::NORMAL;
-
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- // llinfos << "BOLD" << llendl;
- font |= LLFontGL::BOLD;
- }
-
- const LLViewerInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- font |= LLFontGL::ITALIC;
- }
- return (LLFontGL::StyleFlags)font;
-}
-
-std::string LLItemBridge::getLabelSuffix() const
-{
- // String table is loaded before login screen and inventory items are
- // loaded after login, so LLTrans should be ready.
- static std::string NO_COPY =LLTrans::getString("no_copy");
- static std::string NO_MOD = LLTrans::getString("no_modify");
- static std::string NO_XFER = LLTrans::getString("no_transfer");
- static std::string LINK = LLTrans::getString("link");
- static std::string BROKEN_LINK = LLTrans::getString("broken_link");
- std::string suffix;
- LLInventoryItem* item = getItem();
- if(item)
- {
- // it's a bit confusing to put nocopy/nomod/etc on calling cards.
- if(LLAssetType::AT_CALLINGCARD != item->getType()
- && item->getPermissions().getOwner() == gAgent.getID())
- {
- BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
- if (broken_link) return BROKEN_LINK;
-
- BOOL link = item->getIsLinkType();
- if (link) return LINK;
-
- BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
- if (!copy)
- {
- suffix += NO_COPY;
- }
- BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
- if (!mod)
- {
- suffix += NO_MOD;
- }
- BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
- gAgent.getID());
- if (!xfer)
- {
- suffix += NO_XFER;
- }
- }
- }
- return suffix;
-}
-
-time_t LLItemBridge::getCreationDate() const
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- return item->getCreationDate();
- }
- return 0;
-}
-
-
-BOOL LLItemBridge::isItemRenameable() const
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- // (For now) Don't allow calling card rename since that may confuse users as to
- // what the calling card points to.
- if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
- {
- return FALSE;
- }
- return (item->getPermissions().allowModifyBy(gAgent.getID()));
- }
- return FALSE;
-}
-
-BOOL LLItemBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLPreview::dirty(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item && (item->getName() != new_name))
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
-
- model->notifyObservers();
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-
-BOOL LLItemBridge::removeItem()
-{
- if(!isItemRemovable())
- {
- return FALSE;
- }
- // move it to the trash
- LLPreview::hide(mUUID, TRUE);
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- LLViewerInventoryItem* item = getItem();
-
- // if item is not already in trash
- if(item && !model->isObjectDescendentOf(mUUID, trash_id))
- {
- // move to trash, and restamp
- LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
- // delete was successful
- return TRUE;
- }
- else
- {
- // tried to delete already item in trash (should purge?)
- return FALSE;
- }
-}
-
-BOOL LLItemBridge::isItemCopyable() const
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- // can't copy worn objects. DEV-15183
- LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
- if( !avatarp )
- {
- return FALSE;
- }
-
- if(avatarp->isWearingAttachment(mUUID))
- {
- return FALSE;
- }
-
- // All items can be copied, not all can be pasted.
- // The only time an item can't be copied is if it's a link
- // return (item->getPermissions().allowCopyBy(gAgent.getID()));
- if (item->getIsLinkType())
- {
- return FALSE;
- }
- return TRUE;
- }
- return FALSE;
-}
-BOOL LLItemBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
- }
- return FALSE;
-}
-
-LLViewerInventoryItem* LLItemBridge::getItem() const
-{
- LLViewerInventoryItem* item = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- item = (LLViewerInventoryItem*)model->getItem(mUUID);
- }
- return item;
-}
-
-BOOL LLItemBridge::isItemPermissive() const
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- U32 mask = item->getPermissions().getMaskBase();
- if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-// +=================================================+
-// | LLFolderBridge |
-// +=================================================+
-
-LLFolderBridge* LLFolderBridge::sSelf=NULL;
-
-// Can be moved to another folder
-BOOL LLFolderBridge::isItemMovable() const
-{
- LLInventoryObject* obj = getInventoryObject();
- if(obj)
- {
- return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
- }
- return FALSE;
-}
-
-void LLFolderBridge::selectItem()
-{
-}
-
-
-// Can be destroyed (or moved to trash)
-BOOL LLFolderBridge::isItemRemovable()
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- {
- return FALSE;
- }
-
- if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
- {
- return FALSE;
- }
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( !avatar )
- {
- return FALSE;
- }
-
- LLInventoryCategory* category = model->getCategory(mUUID);
- if( !category )
- {
- return FALSE;
- }
-
- if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
- {
- return FALSE;
- }
-
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for( i = 0; i < descendent_categories.count(); i++ )
- {
- LLInventoryCategory* category = descendent_categories[i];
- if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
- {
- return FALSE;
- }
- }
-
- for( i = 0; i < descendent_items.count(); i++ )
- {
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
- {
- if(gAgentWearables.isWearingItem(item->getUUID()))
- {
- return FALSE;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if(avatar->isWearingAttachment(item->getUUID()))
- {
- return FALSE;
- }
- }
- }
-
- return TRUE;
-}
-
-BOOL LLFolderBridge::isUpToDate() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if( !category )
- {
- return FALSE;
- }
-
- return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
-}
-
-BOOL LLFolderBridge::isItemCopyable() const
-{
- return TRUE;
-}
-
-BOOL LLFolderBridge::copyToClipboard() const
-{
- if(isItemCopyable())
- {
- LLInventoryClipboard::instance().add(mUUID);
- return TRUE;
- }
- return FALSE;
-}
-
-BOOL LLFolderBridge::isClipboardPasteable() const
-{
- if ( ! LLInvFVBridge::isClipboardPasteable() )
- return FALSE;
-
- // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
- if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
- {
- LLInventoryModel* model = getInventoryModel();
- if ( !model )
- {
- return FALSE;
- }
-
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- const LLViewerInventoryCategory *current_cat = getCategory();
-
- // Search for the direct descendent of current Friends subfolder among all pasted items,
- // and return false if is found.
- for(S32 i = objects.count() - 1; i >= 0; --i)
- {
- const LLUUID &obj_id = objects.get(i);
- if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
- {
- return FALSE;
- }
- }
-
- }
- return TRUE;
-}
-
-BOOL LLFolderBridge::isClipboardPasteableAsLink() const
-{
- // Check normal paste-as-link permissions
- if (!LLInvFVBridge::isClipboardPasteableAsLink())
- {
- return FALSE;
- }
-
- const LLInventoryModel* model = getInventoryModel();
- if (!model)
- {
- return FALSE;
- }
-
- const LLViewerInventoryCategory *current_cat = getCategory();
- if (current_cat)
- {
- const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
- const LLUUID &current_cat_id = current_cat->getUUID();
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &obj_id = objects.get(i);
- const LLInventoryCategory *cat = model->getCategory(obj_id);
- if (cat)
- {
- const LLUUID &cat_id = cat->getUUID();
- // Don't allow recursive pasting
- if ((cat_id == current_cat_id) ||
- model->isObjectDescendentOf(current_cat_id, cat_id))
- {
- return FALSE;
- }
- }
- // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
- if ( is_in_friend_folder )
- {
- // If object is direct descendent of current Friends subfolder than return false.
- // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
- // in case type of obj_id is LLInventoryItem.
- if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
- {
- return FALSE;
- }
- }
- }
- }
- return TRUE;
-
-}
-
-BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
- BOOL drop)
-{
- // This should never happen, but if an inventory item is incorrectly parented,
- // the UI will get confused and pass in a NULL.
- if(!inv_cat) return FALSE;
-
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
-
- // cannot drag categories into library
- if(!isAgentInventory())
- {
- return FALSE;
- }
-
- // check to make sure source is agent inventory, and is represented there.
- LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
- && (LLToolDragAndDrop::SOURCE_AGENT == source);
-
- BOOL accept = FALSE;
- S32 i;
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- if(is_agent_inventory)
- {
- const LLUUID& cat_id = inv_cat->getUUID();
-
- // Is the destination the trash?
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id)
- || model->isObjectDescendentOf(mUUID, trash_id);
- BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()));
- const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
- if (move_is_into_current_outfit || move_is_into_outfit)
- {
- // BAP - restrictions?
- is_movable = true;
- }
-
- if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
- {
- is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
- }
-
- if( is_movable )
- {
- gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
-
- for( i = 0; i < descendent_categories.count(); i++ )
- {
- LLInventoryCategory* category = descendent_categories[i];
- if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
- {
- // ...can't move "special folders" like Textures
- is_movable = FALSE;
- break;
- }
- }
-
- if( is_movable )
- {
- if( move_is_into_trash )
- {
- for( i = 0; i < descendent_items.count(); i++ )
- {
- LLInventoryItem* item = descendent_items[i];
- if( (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART) )
- {
- if( gAgentWearables.isWearingItem( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
- }
- else
- if( item->getType() == LLAssetType::AT_OBJECT )
- {
- if( avatar->isWearingAttachment( item->getUUID() ) )
- {
- is_movable = FALSE; // It's generally movable, but not into the trash!
- break;
- }
- }
- }
- }
- }
- }
-
-
- accept = is_movable
- && (mUUID != cat_id) // Can't move a folder into itself
- && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
- && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
- if(accept && drop)
- {
- // Look for any gestures and deactivate them
- if (move_is_into_trash)
- {
- for (i = 0; i < descendent_items.count(); i++)
- {
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
- }
- // if target is an outfit or current outfit folder we use link
- if (move_is_into_current_outfit || move_is_into_outfit)
- {
-#if SUPPORT_ENSEMBLES
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceManager::wearEnsemble(inv_cat);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_cat->getUUID(),
- mUUID,
- inv_cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- cb);
- }
-#endif
- }
- else
- {
-
- // Reparent the folder and restamp children if it's moving
- // into trash.
- LLInvFVBridge::changeCategoryParent(
- model,
- (LLViewerInventoryCategory*)inv_cat,
- mUUID,
- move_is_into_trash);
- }
- }
- }
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
- {
- // content category has same ID as object itself
- LLUUID object_id = inv_cat->getUUID();
- LLUUID category_id = mUUID;
- accept = move_inv_category_world_to_agent(object_id, category_id, drop);
- }
- return accept;
-}
-
-void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
-{
- const char* dialog = NULL;
- if (object->flagScripted())
- {
- dialog = "MoveInventoryFromScriptedObject";
- }
- else
- {
- dialog = "MoveInventoryFromObject";
- }
- LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
-}
-
-// Move/copy all inventory items from the Contents folder of an in-world
-// object to the agent's inventory, inside a given category.
-BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
- const LLUUID& category_id,
- BOOL drop,
- void (*callback)(S32, void*),
- void* user_data)
-{
- // Make sure the object exists. If we allowed dragging from
- // anonymous objects, it would be possible to bypass
- // permissions.
- // content category has same ID as object itself
- LLViewerObject* object = gObjectList.findObject(object_id);
- if(!object)
- {
- llinfos << "Object not found for drop." << llendl;
- return FALSE;
- }
-
- // this folder is coming from an object, as there is only one folder in an object, the root,
- // we need to collect the entire contents and handle them as a group
- InventoryObjectList inventory_objects;
- object->getInventoryContents(inventory_objects);
-
- if (inventory_objects.empty())
- {
- llinfos << "Object contents not found for drop." << llendl;
- return FALSE;
- }
-
- BOOL accept = TRUE;
- BOOL is_move = FALSE;
-
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- InventoryObjectList::iterator it = inventory_objects.begin();
- InventoryObjectList::iterator end = inventory_objects.end();
- for ( ; it != end; ++it)
- {
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
- if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
- && perm.allowTransferTo(gAgent.getID())))
-// || gAgent.isGodlike())
- {
- accept = TRUE;
- }
- else if(object->permYouOwner())
- {
- // If the object cannot be copied, but the object the
- // inventory is owned by the agent, then the item can be
- // moved from the task to agent inventory.
- is_move = TRUE;
- accept = TRUE;
- }
- else
- {
- accept = FALSE;
- break;
- }
- }
-
- if(drop && accept)
- {
- it = inventory_objects.begin();
- InventoryObjectList::iterator first_it = inventory_objects.begin();
- LLMoveInv* move_inv = new LLMoveInv;
- move_inv->mObjectID = object_id;
- move_inv->mCategoryID = category_id;
- move_inv->mCallback = callback;
- move_inv->mUserData = user_data;
-
- for ( ; it != end; ++it)
- {
- two_uuids_t two(category_id, (*it)->getUUID());
- move_inv->mMoveList.push_back(two);
- }
-
- if(is_move)
- {
- // Callback called from within here.
- warn_move_inventory(object, move_inv);
- }
- else
- {
- LLNotification::Params params("MoveInventoryFromObject");
- params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
- return accept;
-}
-
-bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- // Valid COF items are:
- // - links to wearables (body parts or clothing)
- // - links to attachments
- // - links to gestures
- // - links to ensemble folders
- LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
- if (linked_item)
- {
- LLAssetType::EType type = linked_item->getType();
- return (type == LLAssetType::AT_CLOTHING ||
- type == LLAssetType::AT_BODYPART ||
- type == LLAssetType::AT_GESTURE ||
- type == LLAssetType::AT_OBJECT);
- }
- else
- {
- LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
- // BAP remove AT_NONE support after ensembles are fully working?
- return (linked_category &&
- ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
- (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
- }
-}
-
-
-bool LLFindWearables::operator()(LLInventoryCategory* cat,
- LLInventoryItem* item)
-{
- if(item)
- {
- if((item->getType() == LLAssetType::AT_CLOTHING)
- || (item->getType() == LLAssetType::AT_BODYPART))
- {
- return TRUE;
- }
- }
- return FALSE;
-}
-
-
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
-{
-public:
- LLRightClickInventoryFetchObserver() :
- mCopyItems(false)
- { };
- LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
- mCatID(cat_id),
- mCopyItems(copy_items)
- { };
- virtual void done()
- {
- // we've downloaded all the items, so repaint the dialog
- LLFolderBridge::staticFolderOptionsMenu();
-
- gInventory.removeObserver(this);
- delete this;
- }
-
-
-protected:
- LLUUID mCatID;
- bool mCopyItems;
-
-};
-
-//Used by LLFolderBridge as callback for directory recursion.
-class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
-{
-public:
- LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
- ~LLRightClickInventoryFetchDescendentsObserver() {}
- virtual void done();
-protected:
- bool mCopyItems;
-};
-
-void LLRightClickInventoryFetchDescendentsObserver::done()
-{
- // Avoid passing a NULL-ref as mCompleteFolders.front() down to
- // gInventory.collectDescendents()
- if( mCompleteFolders.empty() )
- {
- llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-
- // What we do here is get the complete information on the items in
- // the library, and set up an observer that will wait for that to
- // happen.
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- gInventory.collectDescendents(mCompleteFolders.front(),
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH);
- S32 count = item_array.count();
-#if 0 // HACK/TODO: Why?
- // This early causes a giant menu to get produced, and doesn't seem to be needed.
- if(!count)
- {
- llwarns << "Nothing fetched in category " << mCompleteFolders.front()
- << llendl;
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
- return;
- }
-#endif
-
- LLRightClickInventoryFetchObserver* outfit;
- outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
- LLInventoryFetchObserver::item_ref_t ids;
- for(S32 i = 0; i < count; ++i)
- {
- ids.push_back(item_array.get(i)->getUUID());
- }
-
- // clean up, and remove this as an observer since the call to the
- // outfit could notify observers and throw us into an infinite
- // loop.
- dec_busy_count();
- gInventory.removeObserver(this);
- delete this;
-
- // increment busy count and either tell the inventory to check &
- // call done, or add this object to the inventory for observation.
- inc_busy_count();
-
- // do the fetch
- outfit->fetchItems(ids);
- outfit->done(); //Not interested in waiting and this will be right 99% of the time.
-//Uncomment the following code for laggy Inventory UI.
-/* if(outfit->isEverythingComplete())
- {
- // everything is already here - call done.
- outfit->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(outfit);
- }*/
-}
-
-
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-// Class LLInventoryWearObserver
-//
-// Observer for "copy and wear" operation to support knowing
-// when the all of the contents have been added to inventory.
-//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-class LLInventoryCopyAndWearObserver : public LLInventoryObserver
-{
-public:
- LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
- virtual ~LLInventoryCopyAndWearObserver() {}
- virtual void changed(U32 mask);
-
-protected:
- LLUUID mCatID;
- int mContentsCount;
- BOOL mFolderAdded;
-};
-
-
-
-void LLInventoryCopyAndWearObserver::changed(U32 mask)
-{
- if((mask & (LLInventoryObserver::ADD)) != 0)
- {
- if (!mFolderAdded)
- {
- const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
-
- std::set<LLUUID>::const_iterator id_it = changed_items.begin();
- std::set<LLUUID>::const_iterator id_end = changed_items.end();
- for (;id_it != id_end; ++id_it)
- {
- if ((*id_it) == mCatID)
- {
- mFolderAdded = TRUE;
- break;
- }
- }
- }
-
- if (mFolderAdded)
- {
- LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
-
- if (NULL == category)
- {
- llwarns << "gInventory.getCategory(" << mCatID
- << ") was NULL" << llendl;
- }
- else
- {
- if (category->getDescendentCount() ==
- mContentsCount)
- {
- gInventory.removeObserver(this);
- LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
- delete this;
- }
- }
- }
-
- }
-}
-
-
-
-void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("open" == action)
- {
- openItem();
- return;
- }
- else if ("paste" == action)
- {
- pasteFromClipboard();
- return;
- }
- else if ("paste_link" == action)
- {
- pasteLinkFromClipboard();
- return;
- }
- else if ("properties" == action)
- {
- showProperties();
- return;
- }
- else if ("replaceoutfit" == action)
- {
- modifyOutfit(FALSE);
- return;
- }
-#if SUPPORT_ENSEMBLES
- else if ("wearasensemble" == action)
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
- LLAppearanceManager::wearEnsemble(cat,true);
- return;
- }
-#endif
- else if ("addtooutfit" == action)
- {
- modifyOutfit(TRUE);
- return;
- }
- else if ("copy" == action)
- {
- copyToClipboard();
- return;
- }
- else if ("removefromoutfit" == action)
- {
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
-
- remove_inventory_category_from_avatar ( cat );
- return;
- }
- else if ("purge" == action)
- {
- purgeItem(model, mUUID);
- return;
- }
- else if ("restore" == action)
- {
- restoreItem();
- return;
- }
-}
-
-void LLFolderBridge::openItem()
-{
- lldebugs << "LLFolderBridge::openItem()" << llendl;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- if(mUUID.isNull()) return;
- bool fetching_inventory = model->fetchDescendentsOf(mUUID);
- // Only change folder type if we have the folder contents.
- if (!fetching_inventory)
- {
- // Disabling this for now, it's causing crash when new items are added to folders
- // since folder type may change before new item item has finished processing.
- // determineFolderType();
- }
-}
-
-void LLFolderBridge::closeItem()
-{
- determineFolderType();
-}
-
-void LLFolderBridge::determineFolderType()
-{
- if (isUpToDate())
- {
- LLInventoryModel* model = getInventoryModel();
- LLViewerInventoryCategory* category = model->getCategory(mUUID);
- category->determineFolderType();
- }
-}
-
-BOOL LLFolderBridge::isItemRenameable() const
-{
- LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
- if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
- && (cat->getOwnerID() == gAgent.getID()))
- {
- return TRUE;
- }
- return FALSE;
-}
-
-void LLFolderBridge::restoreItem()
-{
- LLViewerInventoryCategory* cat;
- cat = (LLViewerInventoryCategory*)getCategory();
- if(cat)
- {
- LLInventoryModel* model = getInventoryModel();
- const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
- // do not restamp children on restore
- LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
- }
-}
-
-LLFolderType::EType LLFolderBridge::getPreferredType() const
-{
- LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- preferred_type = cat->getPreferredType();
- }
-
- return preferred_type;
-}
-
-// Icons for folders are based on the preferred type
-LLUIImagePtr LLFolderBridge::getIcon() const
-{
- LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- preferred_type = cat->getPreferredType();
- }
- return getIcon(preferred_type);
-}
-
-LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
-{
- // we only have one folder image now
- return LLUI::getUIImage("Inv_FolderClosed");
-}
-
-BOOL LLFolderBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryCategory* cat = getCategory();
- if(cat && (cat->getName() != new_name))
- {
- LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
- new_cat->rename(new_name);
- new_cat->updateServer(FALSE);
- model->updateCategory(new_cat);
-
- model->notifyObservers();
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-BOOL LLFolderBridge::removeItem()
-{
- if(!isItemRemovable())
- {
- return FALSE;
- }
- // move it to the trash
- LLPreview::hide(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
-
- // Look for any gestures and deactivate them
- LLInventoryModel::cat_array_t descendent_categories;
- LLInventoryModel::item_array_t descendent_items;
- gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
-
- S32 i;
- for (i = 0; i < descendent_items.count(); i++)
- {
- LLInventoryItem* item = descendent_items[i];
- if (item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(item->getUUID()))
- {
- LLGestureManager::instance().deactivateGesture(item->getUUID());
- }
- }
-
- // go ahead and do the normal remove if no 'last calling
- // cards' are being removed.
- LLViewerInventoryCategory* cat = getCategory();
- if(cat)
- {
- LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
- }
-
- return TRUE;
-}
-
-void LLFolderBridge::pasteFromClipboard()
-{
- LLInventoryModel* model = getInventoryModel();
- if(model && isClipboardPasteable())
- {
- LLInventoryItem* item = NULL;
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- const LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
- {
- item = model->getItem(objects.get(i));
- if (item)
- {
- if(LLInventoryClipboard::instance().isCutMode())
- {
- // move_inventory_item() is not enough,
- //we have to update inventory locally too
- changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
- }
- else
- {
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- parent_id,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
- }
-}
-
-void LLFolderBridge::pasteLinkFromClipboard()
-{
- const LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- LLDynamicArray<LLUUID> objects;
- LLInventoryClipboard::instance().retrieve(objects);
- S32 count = objects.count();
- LLUUID parent_id(mUUID);
- for(S32 i = 0; i < count; i++)
- {
- const LLUUID &object_id = objects.get(i);
-#if SUPPORT_ENSEMBLES
- if (LLInventoryCategory *cat = model->getCategory(object_id))
- {
- link_inventory_item(
- gAgent.getID(),
- cat->getUUID(),
- parent_id,
- cat->getName(),
- LLAssetType::AT_LINK_FOLDER,
- LLPointer<LLInventoryCallback>(NULL));
- }
- else
-#endif
- if (LLInventoryItem *item = model->getItem(object_id))
- {
- link_inventory_item(
- gAgent.getID(),
- item->getUUID(),
- parent_id,
- item->getName(),
- LLAssetType::AT_LINK,
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
-}
-
-void LLFolderBridge::staticFolderOptionsMenu()
-{
- if (!sSelf) return;
- sSelf->folderOptionsMenu();
-}
-
-void LLFolderBridge::folderOptionsMenu()
-{
- std::vector<std::string> disabled_items;
-
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
-
- const LLInventoryCategory* category = model->getCategory(mUUID);
- LLFolderType::EType type = category->getPreferredType();
- const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type);
- // BAP change once we're no longer treating regular categories as ensembles.
- const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
- LLFolderType::lookupIsEnsembleType(type));
-
- // calling card related functionality for folders.
-
- // Only enable calling-card related options for non-default folders.
- if (!is_default_folder)
- {
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
- {
- mItems.push_back(std::string("Calling Card Separator"));
- mItems.push_back(std::string("Conference Chat Folder"));
- mItems.push_back(std::string("IM All Contacts In Folder"));
- }
- }
-
- // wearables related functionality for folders.
- //is_wearable
- LLFindWearables is_wearable;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
- if (mWearables ||
- checkFolderForContentsOfType(model, is_wearable) ||
- checkFolderForContentsOfType(model, is_object) ||
- checkFolderForContentsOfType(model, is_gesture) )
- {
- mItems.push_back(std::string("Folder Wearables Separator"));
-
- // Only enable add/replace outfit for non-default folders.
- if (!is_default_folder)
- {
- mItems.push_back(std::string("Add To Outfit"));
- mItems.push_back(std::string("Replace Outfit"));
- }
- if (is_ensemble)
- {
- mItems.push_back(std::string("Wear As Ensemble"));
- }
- mItems.push_back(std::string("Take Off Items"));
- }
- hide_context_entries(*mMenu, mItems, disabled_items);
-}
-
-BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
-{
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- model->collectDescendentsIf(mUUID,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_type);
- return ((item_array.count() > 0) ? TRUE : FALSE );
-}
-
-// Flags unused
-void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- mItems.clear();
- mDisabledItems.clear();
-
- lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
-// std::vector<std::string> disabled_items;
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
-
- mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
- mDisabledItems.clear(); //adding code to clear out disabled members from previous
- if (lost_and_found_id == mUUID)
- {
- // This is the lost+found folder.
- mItems.push_back(std::string("Empty Lost And Found"));
- }
-
- if(trash_id == mUUID)
- {
- // This is the trash.
- mItems.push_back(std::string("Empty Trash"));
- }
- else if(model->isObjectDescendentOf(mUUID, trash_id))
- {
- // This is a folder in the trash.
- mItems.clear(); // clear any items that used to exist
- mItems.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- mDisabledItems.push_back(std::string("Purge Item"));
- }
-
- mItems.push_back(std::string("Restore Item"));
- }
- else if(isAgentInventory()) // do not allow creating in library
- {
- LLViewerInventoryCategory *cat = getCategory();
- // BAP removed protected check to re-enable standard ops in untyped folders.
- // Not sure what the right thing is to do here.
- if (!isCOFFolder() && cat /*&&
- LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
- {
- // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
- if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
- mItems.push_back(std::string("New Folder"));
- mItems.push_back(std::string("New Script"));
- mItems.push_back(std::string("New Note"));
- mItems.push_back(std::string("New Gesture"));
- mItems.push_back(std::string("New Clothes"));
- mItems.push_back(std::string("New Body Parts"));
- mItems.push_back(std::string("Change Type"));
-
- LLViewerInventoryCategory *cat = getCategory();
- if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
- {
- mDisabledItems.push_back(std::string("Change Type"));
- }
-
- getClipboardEntries(false, mItems, mDisabledItems, flags);
- }
- else
- {
- // Want some but not all of the items from getClipboardEntries for outfits.
- if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
- {
- mItems.push_back(std::string("Rename"));
- mItems.push_back(std::string("Delete"));
- }
- }
-
- //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
- mCallingCards = mWearables = FALSE;
-
- LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
- if (checkFolderForContentsOfType(model, is_callingcard))
- {
- mCallingCards=TRUE;
- }
-
- LLFindWearables is_wearable;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
-
- if (checkFolderForContentsOfType(model, is_wearable) ||
- checkFolderForContentsOfType(model, is_object) ||
- checkFolderForContentsOfType(model, is_gesture) )
- {
- mWearables=TRUE;
- }
-
- mMenu = &menu;
- sSelf = this;
- LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
-
- LLInventoryFetchDescendentsObserver::folder_ref_t folders;
- LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- if (category)
- {
- folders.push_back(category->getUUID());
- }
- fetch->fetchDescendents(folders);
- inc_busy_count();
- if(fetch->isEverythingComplete())
- {
- // everything is already here - call done.
- fetch->done();
- }
- else
- {
- // it's all on it's way - add an observer, and the inventory
- // will call done for us when everything is here.
- gInventory.addObserver(fetch);
- }
- }
- else
- {
- mItems.push_back(std::string("--no options--"));
- mDisabledItems.push_back(std::string("--no options--"));
- }
- hide_context_entries(menu, mItems, mDisabledItems);
-}
-
-BOOL LLFolderBridge::hasChildren() const
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
- LLInventoryModel::EHasChildren has_children;
- has_children = gInventory.categoryHasChildren(mUUID);
- return has_children != LLInventoryModel::CHILDREN_NO;
-}
-
-BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data)
-{
- //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
- BOOL accept = FALSE;
- switch(cargo_type)
- {
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_CALLINGCARD:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_CLOTHING:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- case DAD_LINK:
- accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
- drop);
- break;
- case DAD_CATEGORY:
- if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
- {
- accept = FALSE;
- }
- else
- {
- accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
- }
- break;
- default:
- break;
- }
- return accept;
-}
-
-LLViewerInventoryCategory* LLFolderBridge::getCategory() const
-{
- LLViewerInventoryCategory* cat = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
- }
- return cat;
-}
-
-
-// static
-void LLFolderBridge::pasteClipboard(void* user_data)
-{
- LLFolderBridge* self = (LLFolderBridge*)user_data;
- if(self) self->pasteFromClipboard();
-}
-
-void LLFolderBridge::createNewCategory(void* user_data)
-{
- LLFolderBridge* bridge = (LLFolderBridge*)user_data;
- if(!bridge) return;
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
- if (!panel) return;
- LLInventoryModel* model = panel->getModel();
- if(!model) return;
- LLUUID id;
- id = model->createNewCategory(bridge->getUUID(),
- LLFolderType::FT_NONE,
- LLStringUtil::null);
- model->notifyObservers();
-
- // At this point, the bridge has probably been deleted, but the
- // view is still there.
- panel->setSelection(id, TAKE_FOCUS_YES);
-}
-
-void LLFolderBridge::createNewShirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
-}
-
-void LLFolderBridge::createNewPants(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
-}
-
-void LLFolderBridge::createNewShoes(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
-}
-
-void LLFolderBridge::createNewSocks(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
-}
-
-void LLFolderBridge::createNewJacket(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
-}
-
-void LLFolderBridge::createNewSkirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
-}
-
-void LLFolderBridge::createNewGloves(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
-}
-
-void LLFolderBridge::createNewUndershirt(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
-}
-
-void LLFolderBridge::createNewUnderpants(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
-}
-
-void LLFolderBridge::createNewShape(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
-}
-
-void LLFolderBridge::createNewSkin(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
-}
-
-void LLFolderBridge::createNewHair(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
-}
-
-void LLFolderBridge::createNewEyes(void* user_data)
-{
- LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
-}
-
-// static
-void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
-{
- if(!bridge) return;
- LLUUID parent_id = bridge->getUUID();
- createWearable(parent_id, type);
-}
-
-// Separate function so can be called by global menu as well as right-click
-// menu.
-// static
-void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type)
-{
- LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
- LLAssetType::EType asset_type = wearable->getAssetType();
- LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
- create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
- parent_id, wearable->getTransactionID(), wearable->getName(),
- wearable->getDescription(), asset_type, inv_type, wearable->getType(),
- wearable->getPermissions().getMaskNextOwner(),
- LLPointer<LLInventoryCallback>(NULL));
-}
-
-void LLFolderBridge::modifyOutfit(BOOL append)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return;
- LLViewerInventoryCategory* cat = getCategory();
- if(!cat) return;
-
- // BAP - was:
- // wear_inventory_category_on_avatar( cat, append );
- LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
-}
-
-// helper stuff
-bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
-{
- LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
- LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- if(option == 0 && object)
- {
- if (cat_and_wear && cat_and_wear->mWear)
- {
- InventoryObjectList inventory_objects;
- object->getInventoryContents(inventory_objects);
- int contents_count = inventory_objects.size()-1; //subtract one for containing folder
-
- LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
- gInventory.addObserver(inventoryObserver);
- }
-
- two_uuids_list_t::iterator move_it;
- for (move_it = move_inv->mMoveList.begin();
- move_it != move_inv->mMoveList.end();
- ++move_it)
- {
- object->moveInventory(move_it->first, move_it->second);
- }
-
- // update the UI.
- dialog_refresh_all();
- }
-
- if (move_inv->mCallback)
- {
- move_inv->mCallback(option, move_inv->mUserData);
- }
-
- delete move_inv;
- return false;
-}
-
-/*
-Next functions intended to reorder items in the inventory folder and save order on server
-Is now used for Favorites folder.
-
-*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
-*/
-void saveItemsOrder(LLInventoryModel::item_array_t& items)
-{
- int sortField = 0;
-
- // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
- {
- LLViewerInventoryItem* item = *i;
-
- item->setSortField(++sortField);
- item->setComplete(TRUE);
- item->updateServer(FALSE);
-
- gInventory.updateItem(item);
- }
-
- gInventory.notifyObservers();
-}
-
-LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
-{
- LLInventoryModel::item_array_t::iterator result = items.end();
-
- for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
- {
- if ((*i)->getUUID() == id)
- {
- result = i;
- break;
- }
- }
-
- return result;
-}
-
-void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
-{
- LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
- LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
-
- items.erase(findItemByUUID(items, srcItem->getUUID()));
- items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
-}
-
-BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
- BOOL drop)
-{
- LLInventoryModel* model = getInventoryModel();
- if(!model) return FALSE;
-
- // cannot drag into library
- if(!isAgentInventory())
- {
- return FALSE;
- }
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
-
- LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
- BOOL accept = FALSE;
- LLViewerObject* object = NULL;
- if(LLToolDragAndDrop::SOURCE_AGENT == source)
- {
-
- BOOL is_movable = TRUE;
- switch( inv_item->getActualType() )
- {
- case LLAssetType::AT_ROOT_CATEGORY:
- is_movable = FALSE;
- break;
-
- case LLAssetType::AT_CATEGORY:
- is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
- break;
- default:
- break;
- }
-
- const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
- const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
- BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
- BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
-
- if(is_movable && move_is_into_trash)
- {
- switch(inv_item->getType())
- {
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
- break;
-
- case LLAssetType::AT_OBJECT:
- is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
- break;
- default:
- break;
- }
- }
-
- if ( is_movable )
- {
- // Don't allow creating duplicates in the Calling Card/Friends
- // subfolders, see bug EXT-1599. Check is item direct descendent
- // of target folder and forbid item's movement if it so.
- // Note: isItemDirectDescendentOfCategory checks if
- // passed category is in the Calling Card/Friends folder
- is_movable = ! LLFriendCardsManager::instance()
- .isObjDirectDescendentOfCategory (inv_item, getCategory());
- }
-
- const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
-
- // we can move item inside a folder only if this folder is Favorites. See EXT-719
- accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
- if(accept && drop)
- {
- if (inv_item->getType() == LLAssetType::AT_GESTURE
- && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
- {
- LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
- }
- // If an item is being dragged between windows, unselect
- // everything in the active window so that we don't follow
- // the selection to its new location (which is very
- // annoying).
- if (LLFloaterInventory::getActiveInventory())
- {
- LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- if (active_panel && (panel != active_panel))
- {
- active_panel->unSelectAll();
- }
- }
-
- // if dragging from/into favorites folder only reorder items
- if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
- {
- LLInventoryModel::cat_array_t cats;
- LLInventoryModel::item_array_t items;
- LLIsType is_type(LLAssetType::AT_LANDMARK);
- model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
-
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
- if (itemp)
- {
- LLUUID srcItemId = inv_item->getUUID();
- LLUUID destItemId = itemp->getListener()->getUUID();
-
- // update order
- updateItemsOrder(items, srcItemId, destItemId);
-
- saveItemsOrder(items);
- }
- }
- else if (favorites_id == mUUID) // if target is the favorites folder we use copy
- {
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- else if (move_is_into_current_outfit || move_is_into_outfit)
- {
- // BAP - should skip if dup.
- if (move_is_into_current_outfit)
- {
- LLAppearanceManager::wearItem(inv_item);
- }
- else
- {
- LLPointer<LLInventoryCallback> cb = NULL;
- link_inventory_item(
- gAgent.getID(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLAssetType::AT_LINK,
- cb);
- }
- }
- else
- {
- // restamp if the move is into the trash.
- LLInvFVBridge::changeItemParent(
- model,
- (LLViewerInventoryItem*)inv_item,
- mUUID,
- move_is_into_trash);
- }
- }
- }
- else if(LLToolDragAndDrop::SOURCE_WORLD == source)
- {
- // Make sure the object exists. If we allowed dragging from
- // anonymous objects, it would be possible to bypass
- // permissions.
- object = gObjectList.findObject(inv_item->getParentUUID());
- if(!object)
- {
- llinfos << "Object not found for drop." << llendl;
- return FALSE;
- }
-
- // coming from a task. Need to figure out if the person can
- // move/copy this item.
- LLPermissions perm(inv_item->getPermissions());
- BOOL is_move = FALSE;
- if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
- && perm.allowTransferTo(gAgent.getID())))
-// || gAgent.isGodlike())
-
- {
- accept = TRUE;
- }
- else if(object->permYouOwner())
- {
- // If the object cannot be copied, but the object the
- // inventory is owned by the agent, then the item can be
- // moved from the task to agent inventory.
- is_move = TRUE;
- accept = TRUE;
- }
- if(drop && accept)
- {
- LLMoveInv* move_inv = new LLMoveInv;
- move_inv->mObjectID = inv_item->getParentUUID();
- two_uuids_t item_pair(mUUID, inv_item->getUUID());
- move_inv->mMoveList.push_back(item_pair);
- move_inv->mCallback = NULL;
- move_inv->mUserData = NULL;
- if(is_move)
- {
- warn_move_inventory(object, move_inv);
- }
- else
- {
- LLNotification::Params params("MoveInventoryFromObject");
- params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
- LLNotifications::instance().forceResponse(params, 0);
- }
- }
-
- }
- else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
- {
- accept = TRUE;
- if(drop)
- {
- copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
- LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
- }
- }
- else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
- if(item && item->isComplete())
- {
- accept = TRUE;
- if(drop)
- {
- copy_inventory_item(
- gAgent.getID(),
- inv_item->getPermissions().getOwner(),
- inv_item->getUUID(),
- mUUID,
- std::string(),
- LLPointer<LLInventoryCallback>(NULL));
- }
- }
- }
- else
- {
- llwarns << "unhandled drag source" << llendl;
- }
- return accept;
-}
-
-// +=================================================+
-// | LLScriptBridge (DEPRECTED) |
-// +=================================================+
-
-LLUIImagePtr LLScriptBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
-}
-
-// +=================================================+
-// | LLTextureBridge |
-// +=================================================+
-
-LLUIImagePtr LLTextureBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
-}
-
-void LLTextureBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-}
-
-void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- items.push_back(std::string("Texture Separator"));
- items.push_back(std::string("Save As"));
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// virtual
-void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("save_as" == action)
- {
- LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
- LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
- if (preview_texture)
- {
- preview_texture->openToSave();
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-// +=================================================+
-// | LLSoundBridge |
-// +=================================================+
-
-LLUIImagePtr LLSoundBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
-}
-
-void LLSoundBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
-// Changed this back to the way it USED to work:
-// only open the preview dialog through the contextual right-click menu
-// double-click just plays the sound
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- openSoundPreview((void*)this);
- //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
- }
-*/
-}
-
-void LLSoundBridge::previewItem()
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- send_sound_trigger(item->getAssetUUID(), 1.0);
- }
-}
-
-void LLSoundBridge::openSoundPreview(void* which)
-{
- LLSoundBridge *me = (LLSoundBridge *)which;
- LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
-}
-
-void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Sound Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Sound Separator"));
- items.push_back(std::string("Sound Play"));
-
- hide_context_entries(menu, items, disabled_items);
-}
-
-// +=================================================+
-// | LLLandmarkBridge |
-// +=================================================+
-
-LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
-LLItemBridge(inventory, uuid)
-{
- mVisited = FALSE;
- if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
- {
- mVisited = TRUE;
- }
-}
-
-LLUIImagePtr LLLandmarkBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
-}
-
-void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Landmark Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Landmark Separator"));
- items.push_back(std::string("About Landmark"));
-
- // Disable "About Landmark" menu item for
- // multiple landmarks selected. Only one landmark
- // info panel can be shown at a time.
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("About Landmark"));
- }
-
- hide_context_entries(menu, items, disabled_items);
-}
-
-// Convenience function for the two functions below.
-void teleport_via_landmark(const LLUUID& asset_id)
-{
- gAgent.teleportViaLandmark( asset_id );
-
- // we now automatically track the landmark you're teleporting to
- // because you'll probably arrive at a telehub instead
- LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
- if( floater_world_map )
- {
- floater_world_map->trackLandmark( asset_id );
- }
-}
-
-// virtual
-void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("teleport" == action)
- {
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- teleport_via_landmark(item->getAssetUUID());
- }
- }
- else if ("about" == action)
- {
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- LLSD key;
- key["type"] = "landmark";
- key["id"] = item->getUUID();
-
- LLSideTray::getInstance()->showPanel("panel_places", key);
- }
- }
- else
- {
- LLItemBridge::performAction(folder, model, action);
- }
-}
-
-static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
-{
- S32 option = LLNotification::getSelectedOption(notification, response);
-
- LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
- if (option == 0)
- {
- teleport_via_landmark(asset_id);
- }
-
- return false;
-}
-static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
-
-
-void LLLandmarkBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- // open_landmark(item);
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
- }
-*/
-}
-
-
-// +=================================================+
-// | LLCallingCardObserver |
-// +=================================================+
-void LLCallingCardObserver::changed(U32 mask)
-{
- mBridgep->refreshFolderViewItem();
-}
-
-// +=================================================+
-// | LLCallingCardBridge |
-// +=================================================+
-
-LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
- LLItemBridge(inventory, uuid)
-{
- mObserver = new LLCallingCardObserver(this);
- LLAvatarTracker::instance().addObserver(mObserver);
-}
-
-LLCallingCardBridge::~LLCallingCardBridge()
-{
- LLAvatarTracker::instance().removeObserver(mObserver);
- delete mObserver;
-}
-
-void LLCallingCardBridge::refreshFolderViewItem()
-{
- LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
- LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
- if (itemp)
- {
- itemp->refresh();
- }
-}
-
-// virtual
-void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("begin_im" == action)
- {
- LLViewerInventoryItem *item = getItem();
- if (item && (item->getCreatorUUID() != gAgent.getID()) &&
- (!item->getCreatorUUID().isNull()))
- {
- std::string callingcard_name;
- gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
- LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
- if (session_id != LLUUID::null)
- {
- LLIMFloater::show(session_id);
- }
- }
- }
- else if ("lure" == action)
- {
- LLViewerInventoryItem *item = getItem();
- if (item && (item->getCreatorUUID() != gAgent.getID()) &&
- (!item->getCreatorUUID().isNull()))
- {
- LLAvatarActions::offerTeleport(item->getCreatorUUID());
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-LLUIImagePtr LLCallingCardBridge::getIcon() const
-{
- BOOL online = FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
- }
- return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
-}
-
-std::string LLCallingCardBridge::getLabelSuffix() const
-{
- LLViewerInventoryItem* item = getItem();
- if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
- {
- return LLItemBridge::getLabelSuffix() + " (online)";
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-void LLCallingCardBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if(item && !item->getCreatorUUID().isNull())
- {
- LLAvatarActions::showProfile(item->getCreatorUUID());
- }
-*/
-}
-
-void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- LLInventoryItem* item = getItem();
- BOOL good_card = (item
- && (LLUUID::null != item->getCreatorUUID())
- && (item->getCreatorUUID() != gAgent.getID()));
- BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
- items.push_back(std::string("Send Instant Message Separator"));
- items.push_back(std::string("Send Instant Message"));
- items.push_back(std::string("Offer Teleport..."));
- items.push_back(std::string("Conference Chat"));
-
- if (!good_card)
- {
- disabled_items.push_back(std::string("Send Instant Message"));
- }
- if (!good_card || !user_online)
- {
- disabled_items.push_back(std::string("Offer Teleport..."));
- disabled_items.push_back(std::string("Conference Chat"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
- EDragAndDropType cargo_type,
- void* cargo_data)
-{
- LLViewerInventoryItem* item = getItem();
- BOOL rv = FALSE;
- if(item)
- {
- // check the type
- switch(cargo_type)
- {
- case DAD_TEXTURE:
- case DAD_SOUND:
- case DAD_LANDMARK:
- case DAD_SCRIPT:
- case DAD_CLOTHING:
- case DAD_OBJECT:
- case DAD_NOTECARD:
- case DAD_BODYPART:
- case DAD_ANIMATION:
- case DAD_GESTURE:
- {
- LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
- const LLPermissions& perm = inv_item->getPermissions();
- if(gInventory.getItem(inv_item->getUUID())
- && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
- {
- rv = TRUE;
- if(drop)
- {
- LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
- (LLInventoryItem*)cargo_data);
- }
- }
- else
- {
- // It's not in the user's inventory (it's probably in
- // an object's contents), so disallow dragging it here.
- // You can't give something you don't yet have.
- rv = FALSE;
- }
- break;
- }
- case DAD_CATEGORY:
- {
- LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
- if( gInventory.getCategory( inv_cat->getUUID() ) )
- {
- rv = TRUE;
- if(drop)
- {
- LLToolDragAndDrop::giveInventoryCategory(
- item->getCreatorUUID(),
- inv_cat);
- }
- }
- else
- {
- // It's not in the user's inventory (it's probably in
- // an object's contents), so disallow dragging it here.
- // You can't give something you don't yet have.
- rv = FALSE;
- }
- break;
- }
- default:
- break;
- }
- }
- return rv;
-}
-
-BOOL LLCallingCardBridge::removeItem()
-{
- if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
- {
- LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
- return FALSE;
- }
- else
- {
- return LLItemBridge::removeItem();
- }
-}
-// +=================================================+
-// | LLNotecardBridge |
-// +=================================================+
-
-LLUIImagePtr LLNotecardBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
-}
-
-void LLNotecardBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
- }
-*/
-}
-
-
-// +=================================================+
-// | LLGestureBridge |
-// +=================================================+
-
-LLUIImagePtr LLGestureBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
-}
-
-LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
-{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
- {
- return LLFontGL::BOLD;
- }
- else
- {
- return LLFontGL::NORMAL;
- }
-}
-
-std::string LLGestureBridge::getLabelSuffix() const
-{
- if( LLGestureManager::instance().isGestureActive(mUUID) )
- {
- return LLItemBridge::getLabelSuffix() + " (active)";
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-// virtual
-void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("activate" == action)
- {
- LLGestureManager::instance().activateGesture(mUUID);
-
- LLViewerInventoryItem* item = gInventory.getItem(mUUID);
- if (!item) return;
-
- // Since we just changed the suffix to indicate (active)
- // the server doesn't need to know, just the viewer.
- gInventory.updateItem(item);
- gInventory.notifyObservers();
- }
- else if ("deactivate" == action)
- {
- LLGestureManager::instance().deactivateGesture(mUUID);
-
- LLViewerInventoryItem* item = gInventory.getItem(mUUID);
- if (!item) return;
-
- // Since we just changed the suffix to indicate (active)
- // the server doesn't need to know, just the viewer.
- gInventory.updateItem(item);
- gInventory.notifyObservers();
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLGestureBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
- }
-*/
-}
-
-BOOL LLGestureBridge::removeItem()
-{
- // Force close the preview window, if it exists
- LLGestureManager::instance().deactivateGesture(mUUID);
- return LLItemBridge::removeItem();
-}
-
-void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- items.push_back(std::string("Gesture Separator"));
- items.push_back(std::string("Activate"));
- items.push_back(std::string("Deactivate"));
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// +=================================================+
-// | LLAnimationBridge |
-// +=================================================+
-
-LLUIImagePtr LLAnimationBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
-}
-
-void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Animation Open"));
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
- }
-
- items.push_back(std::string("Animation Separator"));
- items.push_back(std::string("Animation Play"));
- items.push_back(std::string("Animation Audition"));
-
- hide_context_entries(menu, items, disabled_items);
-
-}
-
-// virtual
-void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ((action == "playworld") || (action == "playlocal"))
- {
- if (getItem())
- {
- LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
- if ("playworld" == action) activate = LLPreviewAnim::PLAY;
- if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
-
- LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
- if (preview)
- {
- preview->activate(activate);
- }
- }
- }
- else
- {
- LLItemBridge::performAction(folder, model, action);
- }
-}
-
-void LLAnimationBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-/*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-*/
-}
-
-// +=================================================+
-// | LLObjectBridge |
-// +=================================================+
-
-// static
-LLUUID LLObjectBridge::sContextMenuItemID;
-
-LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
-LLItemBridge(inventory, uuid), mInvType(type)
-{
- mAttachPt = (flags & 0xff); // low bye of inventory flags
-
- mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
-}
-
-BOOL LLObjectBridge::isItemRemovable()
-{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if(!avatar) return FALSE;
- if(avatar->isWearingAttachment(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
-LLUIImagePtr LLObjectBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
-}
-
-LLInventoryObject* LLObjectBridge::getObject() const
-{
- LLInventoryObject* object = NULL;
- LLInventoryModel* model = getInventoryModel();
- if(model)
- {
- object = (LLInventoryObject*)model->getObject(mUUID);
- }
- return object;
-}
-
-// virtual
-void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("attach" == action)
- {
- LLUUID object_id = mUUID;
- LLViewerInventoryItem* item;
- item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
- if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
- {
- rez_attachment(item, NULL);
- }
- else if(item && item->isComplete())
- {
- // must be in library. copy it to our inventory and put it on.
- LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- gFocusMgr.setKeyboardFocus(NULL);
- }
- else if ("detach" == action)
- {
- LLInventoryItem* item = gInventory.getItem(mUUID);
- if(item)
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
- }
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj =
- gObjectList.findObject(item->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found - ignoring" << llendl;
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLObjectBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
-
- LLSD key;
- key["id"] = mUUID;
- LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
-
- // Disable old properties floater; this is replaced by the sidepanel.
- /*
- LLFloaterReg::showInstance("properties", mUUID);
- */
-}
-
-LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
-{
- U8 font = LLFontGL::NORMAL;
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
- {
- font |= LLFontGL::BOLD;
- }
-
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- font |= LLFontGL::ITALIC;
- }
-
- return (LLFontGL::StyleFlags)font;
-}
-
-std::string LLObjectBridge::getLabelSuffix() const
-{
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar && avatar->isWearingAttachment( mUUID ) )
- {
- std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
- LLStringUtil::toLower(attachment_point_name);
-
- LLStringUtil::format_map_t args;
- args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
- return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
-{
- LLSD payload;
- payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
-
- S32 attach_pt = 0;
- if (gAgent.getAvatarObject() && attachment)
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
- iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
- {
- if (iter->second == attachment)
- {
- attach_pt = iter->first;
- break;
- }
- }
- }
-
- payload["attachment_point"] = attach_pt;
-
-#if !ENABLE_MULTIATTACHMENTS
- if (attachment && attachment->getNumObjects() > 0)
- {
- LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
- }
- else
-#endif
- {
- LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
- }
-}
-
-bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
-{
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
-
- if (!avatarp->canAttachMoreObjects())
- {
- LLSD args;
- args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
- LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
- return false;
- }
-
- S32 option = LLNotification::getSelectedOption(notification, response);
- if (option == 0/*YES*/)
- {
- LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
-
- if (itemp)
- {
- LLMessageSystem* msg = gMessageSystem;
- msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
- msg->nextBlockFast(_PREHASH_AgentData);
- msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
- msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
- msg->nextBlockFast(_PREHASH_ObjectData);
- msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
- msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
- U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
-#if ENABLE_MULTIATTACHMENTS
- attachment_pt |= ATTACHMENT_ADD;
-#endif
- msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
- pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
- msg->addStringFast(_PREHASH_Name, itemp->getName());
- msg->addStringFast(_PREHASH_Description, itemp->getDescription());
- msg->sendReliable(gAgent.getRegion()->getHost());
- }
- }
- return false;
-}
-static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
-
-void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- LLInventoryItem* item = getItem();
- if (item && item->getIsLinkType())
- {
- items.push_back(std::string("Goto Link"));
- }
-
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- LLObjectBridge::sContextMenuItemID = mUUID;
-
- if(item)
- {
- LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
- if( !avatarp )
- {
- return;
- }
-
- if( avatarp->isWearingAttachment( mUUID ) )
- {
- items.push_back(std::string("Detach From Yourself"));
- }
- else
- if( !isInTrash() && !isLinkedObjectInTrash() )
- {
- items.push_back(std::string("Attach Separator"));
- items.push_back(std::string("Object Wear"));
- items.push_back(std::string("Attach To"));
- items.push_back(std::string("Attach To HUD"));
- // commented out for DEV-32347
- //items.push_back(std::string("Restore to Last Position"));
-
- if (!avatarp->canAttachMoreObjects())
- {
- disabled_items.push_back(std::string("Object Wear"));
- disabled_items.push_back(std::string("Attach To"));
- disabled_items.push_back(std::string("Attach To HUD"));
- }
- LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
- LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
- LLVOAvatar *avatarp = gAgent.getAvatarObject();
- if (attach_menu
- && (attach_menu->getChildCount() == 0)
- && attach_hud_menu
- && (attach_hud_menu->getChildCount() == 0)
- && avatarp)
- {
- for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
- iter != avatarp->mAttachmentPoints.end(); )
- {
- LLVOAvatar::attachment_map_t::iterator curiter = iter++;
- LLViewerJointAttachment* attachment = curiter->second;
- LLMenuItemCallGL::Params p;
- std::string submenu_name = attachment->getName();
- if (LLTrans::getString(submenu_name) != "")
- {
- p.name = (" ")+LLTrans::getString(submenu_name)+" ";
- }
- else
- {
- p.name = submenu_name;
- }
- LLSD cbparams;
- cbparams["index"] = curiter->first;
- cbparams["label"] = attachment->getName();
- p.on_click.function_name = "Inventory.AttachObject";
- p.on_click.parameter = LLSD(attachment->getName());
- p.on_enable.function_name = "Attachment.Label";
- p.on_enable.parameter = cbparams;
- LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
- LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
- }
- }
- }
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-BOOL LLObjectBridge::renameItem(const std::string& new_name)
-{
- if(!isItemRenameable())
- return FALSE;
- LLPreview::dirty(mUUID);
- LLInventoryModel* model = getInventoryModel();
- if(!model)
- return FALSE;
- LLViewerInventoryItem* item = getItem();
- if(item && (item->getName() != new_name))
- {
- LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
- new_item->rename(new_name);
- buildDisplayName(new_item, mDisplayName);
- new_item->updateServer(FALSE);
- model->updateItem(new_item);
-
- model->notifyObservers();
-
- LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
- if( avatar )
- {
- LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
- if( obj )
- {
- LLSelectMgr::getInstance()->deselectAll();
- LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
- LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
- LLSelectMgr::getInstance()->deselectAll();
- }
- }
- }
- // return FALSE because we either notified observers (& therefore
- // rebuilt) or we didn't update.
- return FALSE;
-}
-
-// +=================================================+
-// | LLLSLTextBridge |
-// +=================================================+
-
-LLUIImagePtr LLLSLTextBridge::getIcon() const
-{
- return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
-}
-
-void LLLSLTextBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
- /*
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
- }
- */
-}
-
-// +=================================================+
-// | LLWearableBridge |
-// +=================================================+
-
-// *NOTE: hack to get from avatar inventory to avatar
-void wear_inventory_item_on_avatar( LLInventoryItem* item )
-{
- if(item)
- {
- lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLAppearanceManager::wearItem(item);
- }
-}
-
-void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
-{
- if(item)
- {
- lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
- << " )" << llendl;
-
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onWearAddOnAvatarArrived,
- new LLUUID(item->getUUID()));
- }
-}
-
-void remove_inventory_category_from_avatar( LLInventoryCategory* category )
-{
- if(!category) return;
- lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
- << " )" << llendl;
-
-
- if( gFloaterCustomize )
- {
- gFloaterCustomize->askToSaveIfDirty(
- boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
- }
- else
- {
- remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
- }
-}
-
-struct OnRemoveStruct
-{
- LLUUID mUUID;
- OnRemoveStruct(const LLUUID& uuid):
- mUUID(uuid)
- {
- }
-};
-
-void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
-{
-
- // Find all the wearables that are in the category's subtree.
- lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
- if(proceed)
- {
- LLInventoryModel::cat_array_t cat_array;
- LLInventoryModel::item_array_t item_array;
- LLFindWearables is_wearable;
- gInventory.collectDescendentsIf(category_id,
- cat_array,
- item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_wearable);
- S32 i;
- S32 wearable_count = item_array.count();
-
- LLInventoryModel::cat_array_t obj_cat_array;
- LLInventoryModel::item_array_t obj_item_array;
- LLIsType is_object( LLAssetType::AT_OBJECT );
- gInventory.collectDescendentsIf(category_id,
- obj_cat_array,
- obj_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_object);
- S32 obj_count = obj_item_array.count();
-
- // Find all gestures in this folder
- LLInventoryModel::cat_array_t gest_cat_array;
- LLInventoryModel::item_array_t gest_item_array;
- LLIsType is_gesture( LLAssetType::AT_GESTURE );
- gInventory.collectDescendentsIf(category_id,
- gest_cat_array,
- gest_item_array,
- LLInventoryModel::EXCLUDE_TRASH,
- is_gesture);
- S32 gest_count = gest_item_array.count();
-
- if (wearable_count > 0) //Loop through wearables. If worn, remove.
- {
- for(i = 0; i < wearable_count; ++i)
- {
- if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
- {
- LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
- item_array.get(i)->getName(),
- item_array.get(i)->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(item_array.get(i)->getUUID()));
-
- }
- }
- }
-
-
- if (obj_count > 0)
- {
- for(i = 0; i < obj_count; ++i)
- {
- gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
- gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
- gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
- gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
-
- gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
-
- // this object might have been selected, so let the selection manager know it's gone now
- LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
- if (found_obj)
- {
- LLSelectMgr::getInstance()->remove(found_obj);
- }
- else
- {
- llwarns << "object not found, ignoring" << llendl;
- }
- }
- }
-
- if (gest_count > 0)
- {
- for(i = 0; i < gest_count; ++i)
- {
- if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
- {
- LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
- gInventory.updateItem( gest_item_array.get(i) );
- gInventory.notifyObservers();
- }
-
- }
- }
- }
-}
-
-BOOL LLWearableBridge::renameItem(const std::string& new_name)
-{
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- gAgentWearables.setWearableName( mUUID, new_name );
- }
- return LLItemBridge::renameItem(new_name);
-}
-
-BOOL LLWearableBridge::isItemRemovable()
-{
- if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
- return LLInvFVBridge::isItemRemovable();
-}
-
-std::string LLWearableBridge::getLabelSuffix() const
-{
- if( gAgentWearables.isWearingItem( mUUID ) )
- {
- return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
- }
- else
- {
- return LLItemBridge::getLabelSuffix();
- }
-}
-
-LLUIImagePtr LLWearableBridge::getIcon() const
-{
- return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
-}
-
-// virtual
-void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("wear" == action)
- {
- wearOnAvatar();
- }
- else if ("wear_add" == action)
- {
- wearAddOnAvatar();
- }
- else if ("edit" == action)
- {
- editOnAvatar();
- return;
- }
- else if ("take_off" == action)
- {
- if(gAgentWearables.isWearingItem(mUUID))
- {
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- LLWearableBridge::onRemoveFromAvatarArrived,
- new OnRemoveStruct(mUUID));
- }
- }
- }
- else LLItemBridge::performAction(folder, model, action);
-}
-
-void LLWearableBridge::openItem()
-{
- LLViewerInventoryItem* item = getItem();
-
- if (item)
- {
- LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
- }
- /*
- if( isInTrash() )
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if( !gAgentWearables.isWearingItem( mUUID ) )
- {
- wearOnAvatar();
- }
- }
- else
- {
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
- }
- */
-}
-
-void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
- BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
-
- // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
- LLViewerInventoryItem* item = getItem();
- if( !no_open && item )
- {
- no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
- (item->getType() == LLAssetType::AT_BODYPART);
- }
- if (!no_open)
- {
- items.push_back(std::string("Open"));
- }
-
- if (item && item->getIsLinkType())
- {
- items.push_back(std::string("Goto Link"));
- }
-
- items.push_back(std::string("Properties"));
-
- getClipboardEntries(true, items, disabled_items, flags);
-
- items.push_back(std::string("Wearable Separator"));
-
- items.push_back(std::string("Wearable Wear"));
- items.push_back(std::string("Wearable Add"));
- items.push_back(std::string("Wearable Edit"));
-
- if ((flags & FIRST_SELECTED_ITEM) == 0)
- {
- disabled_items.push_back(std::string("Wearable Edit"));
- }
- // Don't allow items to be worn if their baseobj is in the trash.
- if (isLinkedObjectInTrash())
- {
- disabled_items.push_back(std::string("Wearable Wear"));
- disabled_items.push_back(std::string("Wearable Add"));
- disabled_items.push_back(std::string("Wearable Edit"));
- }
-
- // Disable wear and take off based on whether the item is worn.
- if(item)
- {
- switch (item->getType())
- {
- case LLAssetType::AT_CLOTHING:
- items.push_back(std::string("Take Off"));
- case LLAssetType::AT_BODYPART:
- if (gAgentWearables.isWearingItem(item->getUUID()))
- {
- disabled_items.push_back(std::string("Wearable Wear"));
- disabled_items.push_back(std::string("Wearable Add"));
- }
- else
- {
- disabled_items.push_back(std::string("Take Off"));
- }
- break;
- default:
- break;
- }
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-// Called from menus
-// static
-BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return FALSE;
- if(!self->isAgentInventory())
- {
- LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
- if(!item || !item->isComplete()) return FALSE;
- }
- return (!gAgentWearables.isWearingItem(self->mUUID));
-}
-
-// Called from menus
-// static
-void LLWearableBridge::onWearOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- self->wearOnAvatar();
-}
-
-void LLWearableBridge::wearOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
- }
-}
-
-void LLWearableBridge::wearAddOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_add_inventory_item_on_avatar(item);
- }
- }
-}
-
-// static
-void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
-{
- LLUUID* item_id = (LLUUID*) userdata;
- if(wearable)
- {
- LLViewerInventoryItem* item = NULL;
- item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
- if(item)
- {
- if(item->getAssetUUID() == wearable->getAssetID())
- {
- gAgentWearables.setWearableItem(item, wearable);
- gInventory.notifyObservers();
- //self->getFolderItem()->refreshFromRoot();
- }
- else
- {
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
- }
- }
- }
- delete item_id;
-}
-
-// static
-// BAP remove the "add" code path once everything is fully COF-ified.
-void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
-{
- LLUUID* item_id = (LLUUID*) userdata;
- if(wearable)
- {
- LLViewerInventoryItem* item = NULL;
- item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
- if(item)
- {
- if(item->getAssetUUID() == wearable->getAssetID())
- {
- bool do_append = true;
- gAgentWearables.setWearableItem(item, wearable, do_append);
- gInventory.notifyObservers();
- //self->getFolderItem()->refreshFromRoot();
- }
- else
- {
- llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
- }
- }
- }
- delete item_id;
-}
-
-// static
-BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return FALSE;
-
- return (gAgentWearables.isWearingItem(self->mUUID));
-}
-
-// static
-void LLWearableBridge::onEditOnAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(self)
- {
- self->editOnAvatar();
- }
-}
-
-void LLWearableBridge::editOnAvatar()
-{
- const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
- if( wearable )
- {
- // Set the tab to the right wearable.
- if (gFloaterCustomize)
- gFloaterCustomize->setCurrentWearableType( wearable->getType() );
-
- if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
- {
- // Start Avatar Customization
- gAgent.changeCameraToCustomizeAvatar();
- }
- }
-}
-
-// static
-BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
- {
- return gAgentWearables.isWearingItem( self->mUUID );
- }
- return FALSE;
-}
-
-// static
-void LLWearableBridge::onRemoveFromAvatar(void* user_data)
-{
- LLWearableBridge* self = (LLWearableBridge*)user_data;
- if(!self) return;
- if(gAgentWearables.isWearingItem(self->mUUID))
- {
- LLViewerInventoryItem* item = self->getItem();
- if (item)
- {
- LLUUID parent_id = item->getParentUUID();
- LLWearableList::instance().getAsset(item->getAssetUUID(),
- item->getName(),
- item->getType(),
- onRemoveFromAvatarArrived,
- new OnRemoveStruct(LLUUID(self->mUUID)));
- }
- }
-}
-
-// static
-void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
- void* userdata)
-{
- OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
- const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
- if(wearable)
- {
- if( gAgentWearables.isWearingItem( item_id ) )
- {
- EWearableType type = wearable->getType();
-
- if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
- //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
- {
- // MULTI_WEARABLE: FIXME HACK - always remove all
- bool do_remove_all = false;
- gAgentWearables.removeWearable( type, do_remove_all, 0 );
- }
- }
- }
-
- // Find and remove this item from the COF.
- LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF());
- llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
- for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
- iter != items.end();
- ++iter)
- {
- const LLViewerInventoryItem *linked_item = (*iter);
- const LLUUID &item_id = linked_item->getUUID();
- gInventory.purgeObject(item_id);
- }
- gInventory.notifyObservers();
-
- delete on_remove_struct;
-}
-
-LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
-{
- LLInvFVBridgeAction* action = NULL;
- switch(asset_type)
- {
- case LLAssetType::AT_TEXTURE:
- action = new LLTextureBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_SOUND:
- action = new LLSoundBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_LANDMARK:
- action = new LLLandmarkBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_CALLINGCARD:
- action = new LLCallingCardBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_OBJECT:
- action = new LLObjectBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_NOTECARD:
- action = new LLNotecardBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_ANIMATION:
- action = new LLAnimationBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_GESTURE:
- action = new LLGestureBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_LSL_TEXT:
- action = new LLLSLTextBridgeAction(uuid,model);
- break;
-
- case LLAssetType::AT_CLOTHING:
- case LLAssetType::AT_BODYPART:
- action = new LLWearableBridgeAction(uuid,model);
-
- break;
-
- default:
- break;
- }
- return action;
-}
-
-//static
-void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
- const LLUUID& uuid,LLInventoryModel* model)
-{
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
- if(action)
- {
- action->doIt();
- delete action;
- }
-}
-
-//static
-void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
-{
- LLAssetType::EType asset_type = model->getItem(uuid)->getType();
- LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
- if(action)
- {
- action->doIt();
- delete action;
- }
-}
-
-LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
-{
- if(mModel)
- return (LLViewerInventoryItem*)mModel->getItem(mUUID);
- return NULL;
-}
-
-//virtual
-void LLTextureBridgeAction::doIt()
-{
- if (getItem())
- {
- LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLSoundBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLLandmarkBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if( item )
- {
- // Opening (double-clicking) a landmark immediately teleports,
- // but warns you the first time.
- LLSD payload;
- payload["asset_id"] = item->getAssetUUID();
- LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLCallingCardBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if(item && item->getCreatorUUID().notNull())
- {
- LLAvatarActions::showProfile(item->getCreatorUUID());
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void
-LLNotecardBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLGestureBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
- preview->setFocus(TRUE);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-//virtual
-void LLAnimationBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLObjectBridgeAction::doIt()
-{
- LLFloaterReg::showInstance("properties", mUUID);
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-//virtual
-void LLLSLTextBridgeAction::doIt()
-{
- LLViewerInventoryItem* item = getItem();
- if (item)
- {
- LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-
-BOOL LLWearableBridgeAction::isInTrash() const
-{
- if(!mModel) return FALSE;
- const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
- return mModel->isObjectDescendentOf(mUUID, trash_id);
-}
-
-BOOL LLWearableBridgeAction::isAgentInventory() const
-{
- if(!mModel) return FALSE;
- if(gInventory.getRootFolderID() == mUUID) return TRUE;
- return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
-}
-
-void LLWearableBridgeAction::wearOnAvatar()
-{
- // Don't wear anything until initial wearables are loaded, can
- // destroy clothing items.
- if (!gAgentWearables.areWearablesLoaded())
- {
- LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
- return;
- }
-
- LLViewerInventoryItem* item = getItem();
- if(item)
- {
- if(!isAgentInventory())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else
- {
- wear_inventory_item_on_avatar(item);
- }
- }
-}
-
-//virtual
-void LLWearableBridgeAction::doIt()
-{
- if(isInTrash())
- {
- LLNotifications::instance().add("CannotWearTrash");
- }
- else if(isAgentInventory())
- {
- if(!gAgentWearables.isWearingItem(mUUID))
- {
- wearOnAvatar();
- }
- }
- else
- {
- // must be in the inventory library. copy it to our inventory
- // and put it on right away.
- LLViewerInventoryItem* item = getItem();
- if(item && item->isComplete())
- {
- LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
- copy_inventory_item(
- gAgent.getID(),
- item->getPermissions().getOwner(),
- item->getUUID(),
- LLUUID::null,
- std::string(),
- cb);
- }
- else if(item)
- {
- // *TODO: We should fetch the item details, and then do
- // the operation above.
- LLNotifications::instance().add("CannotWearInfoNotComplete");
- }
- }
-
- LLInvFVBridgeAction::doIt();
-}
-
-// +=================================================+
-// | LLLinkItemBridge |
-// +=================================================+
-// For broken links
-
-std::string LLLinkItemBridge::sPrefix("Link: ");
-
-
-LLUIImagePtr LLLinkItemBridge::getIcon() const
-{
- if (LLViewerInventoryItem *item = getItem())
- {
- return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
- }
- return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
-}
-
-void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- // *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-
-// +=================================================+
-// | LLLinkBridge |
-// +=================================================+
-// For broken links.
-
-std::string LLLinkFolderBridge::sPrefix("Link: ");
-
-
-LLUIImagePtr LLLinkFolderBridge::getIcon() const
-{
- LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
- if (LLViewerInventoryItem *item = getItem())
- {
- if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
- {
- preferred_type = cat->getPreferredType();
- }
- }
- return LLFolderBridge::getIcon(preferred_type);
-}
-
-void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
-{
- // *TODO: Translate
- lldebugs << "LLLink::buildContextMenu()" << llendl;
- std::vector<std::string> items;
- std::vector<std::string> disabled_items;
-
- if(isInTrash())
- {
- items.push_back(std::string("Purge Item"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Purge Item"));
- }
-
- items.push_back(std::string("Restore Item"));
- }
- else
- {
- items.push_back(std::string("Goto Link"));
- items.push_back(std::string("Delete"));
- if (!isItemRemovable())
- {
- disabled_items.push_back(std::string("Delete"));
- }
- }
- hide_context_entries(menu, items, disabled_items);
-}
-
-void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
-{
- if ("goto" == action)
- {
- gotoItem(folder);
- return;
- }
- LLItemBridge::performAction(folder,model,action);
-}
-
-void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
-{
- const LLUUID &cat_uuid = getFolderID();
- if (!cat_uuid.isNull())
- {
- if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
- {
- if (LLInventoryModel* model = getInventoryModel())
- {
- model->fetchDescendentsOf(cat_uuid);
- }
- base_folder->setOpen(TRUE);
- folder->setSelectionFromRoot(base_folder,TRUE);
- folder->scrollToShowSelection();
- }
- }
-}
-
-const LLUUID &LLLinkFolderBridge::getFolderID() const
-{
- if (LLViewerInventoryItem *link_item = getItem())
- {
- if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
- {
- const LLUUID& cat_uuid = cat->getUUID();
- return cat_uuid;
- }
- }
- return LLUUID::null;
-}
+/**
+ * @file llinventorybridge.cpp
+ * @brief Implementation of the Inventory-Folder-View-Bridge classes.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewergpl$
+ *
+ * Copyright (c) 2001-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include <utility> // for std::pair<>
+
+#include "llfloaterinventory.h"
+#include "llinventorybridge.h"
+
+#include "message.h"
+
+#include "llagent.h"
+#include "llagentwearables.h"
+#include "llcallingcard.h"
+#include "llcheckboxctrl.h" // for radio buttons
+#include "llfloaterreg.h"
+#include "llradiogroup.h"
+#include "llspinctrl.h"
+#include "lltextbox.h"
+#include "llui.h"
+
+#include "llviewercontrol.h"
+#include "llfirstuse.h"
+#include "llfoldertype.h"
+#include "llfloaterchat.h"
+#include "llfloatercustomize.h"
+#include "llfloaterproperties.h"
+#include "llfloaterworldmap.h"
+#include "llfocusmgr.h"
+#include "llfolderview.h"
+#include "llfriendcard.h"
+#include "llavataractions.h"
+#include "llgesturemgr.h"
+#include "lliconctrl.h"
+#include "llinventoryfunctions.h"
+#include "llinventorymodel.h"
+#include "llinventorypanel.h"
+#include "llinventoryclipboard.h"
+#include "lllineeditor.h"
+#include "llmenugl.h"
+#include "llpreviewanim.h"
+#include "llpreviewgesture.h"
+#include "llpreviewnotecard.h"
+#include "llpreviewscript.h"
+#include "llpreviewsound.h"
+#include "llpreviewtexture.h"
+#include "llresmgr.h"
+#include "llscrollcontainer.h"
+#include "llimview.h"
+#include "lltooldraganddrop.h"
+#include "llviewerfoldertype.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+#include "llviewerwindow.h"
+#include "llvoavatar.h"
+#include "llwearable.h"
+#include "llwearablelist.h"
+#include "llviewerassettype.h"
+#include "llviewermessage.h"
+#include "llviewerregion.h"
+#include "llvoavatarself.h"
+#include "lltabcontainer.h"
+#include "lluictrlfactory.h"
+#include "llselectmgr.h"
+#include "llsidetray.h"
+#include "llfloateropenobject.h"
+#include "lltrans.h"
+#include "llappearancemgr.h"
+#include "llimfloater.h"
+
+using namespace LLOldEvents;
+
+// Helpers
+// bug in busy count inc/dec right now, logic is complex... do we really need it?
+void inc_busy_count()
+{
+// gViewerWindow->getWindow()->incBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+void dec_busy_count()
+{
+// gViewerWindow->getWindow()->decBusyCount();
+// check balance of these calls if this code is changed to ever actually
+// *do* something!
+}
+
+// Function declarations
+void wear_add_inventory_item_on_avatar(LLInventoryItem* item);
+void remove_inventory_category_from_avatar(LLInventoryCategory* category);
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id);
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv*);
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response);
+
+std::string ICON_NAME[ICON_NAME_COUNT] =
+{
+ "Inv_Texture",
+ "Inv_Sound",
+ "Inv_CallingCard",
+ "Inv_CallingCard",
+ "Inv_Landmark",
+ "Inv_Landmark",
+ "Inv_Script",
+ "Inv_Clothing",
+ "Inv_Object",
+ "Inv_Object",
+ "Inv_Notecard",
+ "Inv_Skin",
+ "Inv_Snapshot",
+
+ "Inv_BodyShape",
+ "Inv_Skin",
+ "Inv_Hair",
+ "Inv_Eye",
+ "Inv_Shirt",
+ "Inv_Pants",
+ "Inv_Shoe",
+ "Inv_Socks",
+ "Inv_Jacket",
+ "Inv_Gloves",
+ "Inv_Undershirt",
+ "Inv_Underpants",
+ "Inv_Skirt",
+ "Inv_Alpha",
+ "Inv_Tattoo",
+
+ "Inv_Animation",
+ "Inv_Gesture",
+
+ "inv_item_linkitem.tga",
+ "inv_item_linkfolder.tga",
+
+ "inv_item_mesh.tga"
+};
+
+
+// +=================================================+
+// | LLInventoryPanelObserver |
+// +=================================================+
+void LLInventoryPanelObserver::changed(U32 mask)
+{
+ mIP->modelChanged(mask);
+}
+
+
+// +=================================================+
+// | LLInvFVBridge |
+// +=================================================+
+
+LLInvFVBridge::LLInvFVBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+mUUID(uuid), mInvType(LLInventoryType::IT_NONE)
+{
+ mInventoryPanel = inventory->getHandle();
+}
+
+const std::string& LLInvFVBridge::getName() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return obj->getName();
+ }
+ return LLStringUtil::null;
+}
+
+const std::string& LLInvFVBridge::getDisplayName() const
+{
+ return getName();
+}
+
+// Folders have full perms
+PermissionMask LLInvFVBridge::getPermissionMask() const
+{
+
+ return PERM_ALL;
+}
+
+// virtual
+LLFolderType::EType LLInvFVBridge::getPreferredType() const
+{
+ return LLFolderType::FT_NONE;
+}
+
+
+// Folders don't have creation dates.
+time_t LLInvFVBridge::getCreationDate() const
+{
+ return 0;
+}
+
+// Can be destoryed (or moved to trash)
+BOOL LLInvFVBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+// Sends an update to all link items that point to the base item.
+void LLInvFVBridge::renameLinkedItems(const LLUUID &item_id, const std::string& new_name)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ if (itemp->getIsLinkType())
+ {
+ return;
+ }
+
+ LLInventoryModel::item_array_t item_array = model->collectLinkedItems(item_id);
+ for (LLInventoryModel::item_array_t::iterator iter = item_array.begin();
+ iter != item_array.end();
+ iter++)
+ {
+ LLViewerInventoryItem *linked_item = (*iter);
+ if (linked_item->getUUID() == item_id) continue;
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(linked_item);
+ new_item->rename(new_name);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+ // model->addChangedMask(LLInventoryObserver::LABEL, linked_item->getUUID());
+ }
+ model->notifyObservers();
+}
+
+// Can be moved to another folder
+BOOL LLInvFVBridge::isItemMovable() const
+{
+ return TRUE;
+}
+
+/*virtual*/
+/**
+ * @brief Adds this item into clipboard storage
+ */
+void LLInvFVBridge::cutToClipboard()
+{
+ if(isItemMovable())
+ {
+ LLInventoryClipboard::instance().cut(mUUID);
+ }
+}
+// *TODO: make sure this does the right thing
+void LLInvFVBridge::showProperties()
+{
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+}
+
+void LLInvFVBridge::removeBatch(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // Deactivate gestures when moving them into Trash
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ S32 count = batch.count();
+ S32 i,j;
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if (item)
+ {
+ if(LLAssetType::AT_GESTURE == item->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if (cat)
+ {
+ gInventory.collectDescendents( cat->getUUID(), descendent_categories, descendent_items, FALSE );
+ for (j=0; j<descendent_items.count(); j++)
+ {
+ if(LLAssetType::AT_GESTURE == descendent_items[j]->getType())
+ {
+ LLGestureManager::instance().deactivateGesture(descendent_items[j]->getUUID());
+ }
+ }
+ }
+ }
+ removeBatchNoCheck(batch);
+}
+
+void LLInvFVBridge::removeBatchNoCheck(LLDynamicArray<LLFolderViewEventListener*>& batch)
+{
+ // this method moves a bunch of items and folders to the trash. As
+ // per design guidelines for the inventory model, the message is
+ // built and the accounting is performed first. After all of that,
+ // we call LLInventoryModel::moveObject() to move everything
+ // around.
+ LLInvFVBridge* bridge;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLMessageSystem* msg = gMessageSystem;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = NULL;
+ LLViewerInventoryCategory* cat = NULL;
+ std::vector<LLUUID> move_ids;
+ LLInventoryModel::update_map_t update;
+ bool start_new_message = true;
+ S32 count = batch.count();
+ S32 i;
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ item = (LLViewerInventoryItem*)model->getItem(bridge->getUUID());
+ if(item)
+ {
+ if(item->getParentUUID() == trash_id) continue;
+ move_ids.push_back(item->getUUID());
+ LLPreview::hide(item->getUUID());
+ --update[item->getParentUUID()];
+ ++update[trash_id];
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(_PREHASH_MoveInventoryItem);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOLFast(_PREHASH_Stamp, TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_ItemID, item->getUUID());
+ msg->addUUIDFast(_PREHASH_FolderID, trash_id);
+ msg->addString("NewName", NULL);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ for(i = 0; i < count; ++i)
+ {
+ bridge = (LLInvFVBridge*)(batch.get(i));
+ if(!bridge || !bridge->isItemRemovable()) continue;
+ cat = (LLViewerInventoryCategory*)model->getCategory(bridge->getUUID());
+ if(cat)
+ {
+ if(cat->getParentUUID() == trash_id) continue;
+ move_ids.push_back(cat->getUUID());
+ --update[cat->getParentUUID()];
+ ++update[trash_id];
+ if(start_new_message)
+ {
+ start_new_message = false;
+ msg->newMessageFast(_PREHASH_MoveInventoryFolder);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addBOOL("Stamp", TRUE);
+ }
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addUUIDFast(_PREHASH_FolderID, cat->getUUID());
+ msg->addUUIDFast(_PREHASH_ParentID, trash_id);
+ if(msg->isSendFullFast(_PREHASH_InventoryData))
+ {
+ start_new_message = true;
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ update.clear();
+ }
+ }
+ }
+ if(!start_new_message)
+ {
+ gAgent.sendReliableMessage();
+ gInventory.accountForUpdate(update);
+ }
+
+ // move everything.
+ std::vector<LLUUID>::iterator it = move_ids.begin();
+ std::vector<LLUUID>::iterator end = move_ids.end();
+ for(; it != end; ++it)
+ {
+ gInventory.moveObject((*it), trash_id);
+ }
+
+ // notify inventory observers.
+ model->notifyObservers();
+}
+
+BOOL LLInvFVBridge::isClipboardPasteable() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLUUID &agent_id = gAgent.getID();
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &item_id = objects.get(i);
+
+ // Can't paste folders
+ const LLInventoryCategory *cat = model->getCategory(item_id);
+ if (cat)
+ {
+ return FALSE;
+ }
+
+ const LLInventoryItem *item = model->getItem(item_id);
+ if (item)
+ {
+ if (!item->getPermissions().allowCopyBy(agent_id))
+ {
+ return FALSE;
+ }
+ }
+ }
+ return TRUE;
+}
+
+BOOL LLInvFVBridge::isClipboardPasteableAsLink() const
+{
+ if (!LLInventoryClipboard::instance().hasContents() || !isAgentInventory())
+ {
+ return FALSE;
+ }
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLInventoryItem *item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if (!LLAssetType::lookupCanLink(item->getActualType()))
+ {
+ return FALSE;
+ }
+ }
+ const LLViewerInventoryCategory *cat = model->getCategory(objects.get(i));
+ if (cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+ return TRUE;
+}
+
+void hide_context_entries(LLMenuGL& menu,
+ const std::vector<std::string> &entries_to_show,
+ const std::vector<std::string> &disabled_entries)
+{
+ const LLView::child_list_t *list = menu.getChildList();
+
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+
+ // descend into split menus:
+ LLMenuItemBranchGL* branchp = dynamic_cast<LLMenuItemBranchGL*>(*itor);
+ if ((name == "More") && branchp)
+ {
+ hide_context_entries(*branchp->getBranch(), entries_to_show, disabled_entries);
+ }
+
+
+ bool found = false;
+ std::vector<std::string>::const_iterator itor2;
+ for (itor2 = entries_to_show.begin(); itor2 != entries_to_show.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ found = true;
+ }
+ }
+ if (!found)
+ {
+ (*itor)->setVisible(FALSE);
+ }
+ else
+ {
+ for (itor2 = disabled_entries.begin(); itor2 != disabled_entries.end(); ++itor2)
+ {
+ if (*itor2 == name)
+ {
+ (*itor)->setEnabled(FALSE);
+ }
+ }
+ }
+ }
+}
+
+// Helper for commonly-used entries
+void LLInvFVBridge::getClipboardEntries(bool show_asset_id,
+ std::vector<std::string> &items,
+ std::vector<std::string> &disabled_items, U32 flags)
+{
+ items.push_back(std::string("Rename"));
+ if (!isItemRenameable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Rename"));
+ }
+
+ if (show_asset_id)
+ {
+ items.push_back(std::string("Copy Asset UUID"));
+ if ( (! ( isItemPermissive() || gAgent.isGodlike() ) )
+ || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Copy Asset UUID"));
+ }
+ }
+
+ items.push_back(std::string("Copy Separator"));
+
+ items.push_back(std::string("Copy"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Copy"));
+ }
+
+ items.push_back(std::string("Paste"));
+ if (!isClipboardPasteable() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste"));
+ }
+
+ items.push_back(std::string("Paste As Link"));
+ if (!isClipboardPasteableAsLink() || (flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Paste As Link"));
+ }
+ items.push_back(std::string("Paste Separator"));
+
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+
+ // If multiple items are selected, disable properties (if it exists).
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Properties"));
+ }
+}
+
+void LLInvFVBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLInvFVBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("PurgeItem"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("PurgeItem"));
+ }
+ items.push_back(std::string("RestoreItem"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// *TODO: remove this
+BOOL LLInvFVBridge::startDrag(EDragAndDropType* type, LLUUID* id) const
+{
+ BOOL rv = FALSE;
+
+ const LLInventoryObject* obj = getInventoryObject();
+
+ if(obj)
+ {
+ *type = LLViewerAssetType::lookupDragAndDropType(obj->getActualType());
+ if(*type == DAD_NONE)
+ {
+ return FALSE;
+ }
+
+ *id = obj->getUUID();
+ //object_ids.put(obj->getUUID());
+
+ if (*type == DAD_CATEGORY)
+ {
+ gInventory.startBackgroundFetch(obj->getUUID());
+ }
+
+ rv = TRUE;
+ }
+
+ return rv;
+}
+
+LLInventoryObject* LLInvFVBridge::getInventoryObject() const
+{
+ LLInventoryObject* obj = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ obj = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return obj;
+}
+
+LLInventoryModel* LLInvFVBridge::getInventoryModel() const
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ return panel ? panel->getModel() : NULL;
+}
+
+BOOL LLInvFVBridge::isInTrash() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLInvFVBridge::isLinkedObjectInTrash() const
+{
+ if (isInTrash()) return TRUE;
+
+ const LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return model->isObjectDescendentOf(obj->getLinkedUUID(), trash_id);
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isAgentInventory() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+BOOL LLInvFVBridge::isCOFFolder() const
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(!model) return TRUE;
+ const LLUUID cof_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ if (mUUID == cof_id || model->isObjectDescendentOf(mUUID, cof_id))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLInvFVBridge::isItemPermissive() const
+{
+ return FALSE;
+}
+
+// static
+void LLInvFVBridge::changeItemParent(LLInventoryModel* model,
+ LLViewerInventoryItem* item,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(item->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->setParent(new_parent);
+ new_item->updateParentOnServer(restamp);
+ model->updateItem(new_item);
+ model->notifyObservers();
+ }
+}
+
+// static
+void LLInvFVBridge::changeCategoryParent(LLInventoryModel* model,
+ LLViewerInventoryCategory* cat,
+ const LLUUID& new_parent,
+ BOOL restamp)
+{
+ if(cat->getParentUUID() != new_parent)
+ {
+ LLInventoryModel::update_list_t update;
+ LLInventoryModel::LLCategoryUpdate old_folder(cat->getParentUUID(), -1);
+ update.push_back(old_folder);
+ LLInventoryModel::LLCategoryUpdate new_folder(new_parent, 1);
+ update.push_back(new_folder);
+ gInventory.accountForUpdate(update);
+
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->setParent(new_parent);
+ new_cat->updateParentOnServer(restamp);
+ model->updateCategory(new_cat);
+ model->notifyObservers();
+ }
+}
+
+
+const std::string safe_inv_type_lookup(LLInventoryType::EType inv_type)
+{
+ const std::string rv= LLInventoryType::lookup(inv_type);
+ if(rv.empty())
+ {
+ return std::string("<invalid>");
+ }
+ return rv;
+}
+
+LLInvFVBridge* LLInvFVBridge::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags)
+{
+ LLInvFVBridge* new_listener = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ if(!(inv_type == LLInventoryType::IT_TEXTURE || inv_type == LLInventoryType::IT_SNAPSHOT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLTextureBridge(inventory, uuid, inv_type);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ if(!(inv_type == LLInventoryType::IT_SOUND))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLSoundBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ if(!(inv_type == LLInventoryType::IT_LANDMARK))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLandmarkBridge(inventory, uuid, flags);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ if(!(inv_type == LLInventoryType::IT_CALLINGCARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLCallingCardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_SCRIPT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLScriptBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ if(!(inv_type == LLInventoryType::IT_OBJECT || inv_type == LLInventoryType::IT_ATTACHMENT))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLObjectBridge(inventory, uuid, inv_type, flags);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ if(!(inv_type == LLInventoryType::IT_NOTECARD))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLNotecardBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ if(!(inv_type == LLInventoryType::IT_ANIMATION))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLAnimationBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ if(!(inv_type == LLInventoryType::IT_GESTURE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLGestureBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ if(!(inv_type == LLInventoryType::IT_LSL))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLLSLTextBridge(inventory, uuid);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ if(!(inv_type == LLInventoryType::IT_WEARABLE))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLWearableBridge(inventory, uuid, asset_type, inv_type, (EWearableType)flags);
+ break;
+ case LLAssetType::AT_CATEGORY:
+ case LLAssetType::AT_ROOT_CATEGORY:
+ if (actual_asset_type == LLAssetType::AT_LINK_FOLDER)
+ {
+ // Create a link folder handler instead.
+ new_listener = new LLLinkFolderBridge(inventory, uuid);
+ break;
+ }
+ new_listener = new LLFolderBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_LINK_FOLDER:
+ // Only should happen for broken links.
+ new_listener = new LLLinkItemBridge(inventory, uuid);
+ break;
+ case LLAssetType::AT_MESH:
+ if(!(inv_type == LLInventoryType::IT_MESH))
+ {
+ llwarns << LLAssetType::lookup(asset_type) << " asset has inventory type " << safe_inv_type_lookup(inv_type) << " on uuid " << uuid << llendl;
+ }
+ new_listener = new LLMeshBridge(inventory, uuid);
+ break;
+
+ default:
+ llinfos << "Unhandled asset type (llassetstorage.h): "
+ << (S32)asset_type << llendl;
+ break;
+ }
+
+ if (new_listener)
+ {
+ new_listener->mInvType = inv_type;
+ }
+
+ return new_listener;
+}
+
+void LLInvFVBridge::purgeItem(LLInventoryModel *model, const LLUUID &uuid)
+{
+ LLInventoryCategory* cat = model->getCategory(uuid);
+ if (cat)
+ {
+ model->purgeDescendentsOf(uuid);
+ model->notifyObservers();
+ }
+ LLInventoryObject* obj = model->getObject(uuid);
+ if (obj)
+ {
+ model->purgeObject(uuid);
+ model->notifyObservers();
+ }
+}
+
+// +=================================================+
+// | InventoryFVBridgeBuilder |
+// +=================================================+
+LLInvFVBridge* LLInventoryFVBridgeBuilder::createBridge(LLAssetType::EType asset_type,
+ LLAssetType::EType actual_asset_type,
+ LLInventoryType::EType inv_type,
+ LLInventoryPanel* inventory,
+ const LLUUID& uuid,
+ U32 flags /* = 0x00 */) const
+{
+ return LLInvFVBridge::createBridge(asset_type,
+ actual_asset_type,
+ inv_type,
+ inventory,
+ uuid,
+ flags);
+}
+
+// +=================================================+
+// | LLItemBridge |
+// +=================================================+
+
+void LLItemBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ }
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restoreToWorld" == action)
+ {
+ restoreToWorld();
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+ else if ("copy_uuid" == action)
+ {
+ // Single item only
+ LLInventoryItem* item = model->getItem(mUUID);
+ if(!item) return;
+ LLUUID asset_id = item->getAssetUUID();
+ std::string buffer;
+ asset_id.toString(buffer);
+
+ gViewerWindow->mWindow->copyTextToClipboard(utf8str_to_wstring(buffer));
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ // Single item only
+ LLInventoryItem* itemp = model->getItem(mUUID);
+ if (!itemp) return;
+
+ LLFolderViewItem* folder_view_itemp = folder->getItemByID(itemp->getParentUUID());
+ if (!folder_view_itemp) return;
+
+ folder_view_itemp->getListener()->pasteLinkFromClipboard();
+ return;
+ }
+}
+
+void LLItemBridge::selectItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item && !item->isComplete())
+ {
+ item->fetchFromServer();
+ }
+}
+
+void LLItemBridge::restoreItem()
+{
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)getItem();
+ if(item)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(item->getType()));
+ // do not restamp on restore.
+ LLInvFVBridge::changeItemParent(model, item, new_parent, FALSE);
+ }
+}
+
+void LLItemBridge::restoreToWorld()
+{
+ LLViewerInventoryItem* itemp = (LLViewerInventoryItem*)getItem();
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessage("RezRestoreToWorld");
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ itemp->packMessage(msg);
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+
+ //Similar functionality to the drag and drop rez logic
+ BOOL remove_from_inventory = FALSE;
+
+ //remove local inventory copy, sim will deal with permissions and removing the item
+ //from the actual inventory if its a no-copy etc
+ if(!itemp->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ // Check if it's in the trash. (again similar to the normal rez logic)
+ const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ if(gInventory.isObjectDescendentOf(itemp->getUUID(), trash_id))
+ {
+ remove_from_inventory = TRUE;
+ }
+
+ if(remove_from_inventory)
+ {
+ gInventory.deleteObject(itemp->getUUID());
+ gInventory.notifyObservers();
+ }
+}
+
+void LLItemBridge::gotoItem(LLFolderView *folder)
+{
+ LLInventoryObject *obj = getInventoryObject();
+ if (obj && obj->getIsLinkType())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ if (active_panel)
+ {
+ active_panel->setSelection(obj->getLinkedUUID(), TAKE_FOCUS_NO);
+ }
+ }
+}
+
+LLUIImagePtr LLItemBridge::getIcon() const
+{
+ return LLUI::getUIImage(ICON_NAME[OBJECT_ICON_NAME]);
+}
+
+PermissionMask LLItemBridge::getPermissionMask() const
+{
+ LLViewerInventoryItem* item = getItem();
+ PermissionMask perm_mask = 0;
+ if(item)
+ {
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+
+ if (copy) perm_mask |= PERM_COPY;
+ if (mod) perm_mask |= PERM_MODIFY;
+ if (xfer) perm_mask |= PERM_TRANSFER;
+
+ }
+ return perm_mask;
+}
+
+const std::string& LLItemBridge::getDisplayName() const
+{
+ if(mDisplayName.empty())
+ {
+ buildDisplayName(getItem(), mDisplayName);
+ }
+ return mDisplayName;
+}
+
+void LLItemBridge::buildDisplayName(LLInventoryItem* item, std::string& name)
+{
+ if(item)
+ {
+ name.assign(item->getName());
+ }
+ else
+ {
+ name.assign(LLStringUtil::null);
+ }
+}
+
+LLFontGL::StyleFlags LLItemBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ // llinfos << "BOLD" << llendl;
+ font |= LLFontGL::BOLD;
+ }
+
+ const LLViewerInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLItemBridge::getLabelSuffix() const
+{
+ // String table is loaded before login screen and inventory items are
+ // loaded after login, so LLTrans should be ready.
+ static std::string NO_COPY =LLTrans::getString("no_copy");
+ static std::string NO_MOD = LLTrans::getString("no_modify");
+ static std::string NO_XFER = LLTrans::getString("no_transfer");
+ static std::string LINK = LLTrans::getString("link");
+ static std::string BROKEN_LINK = LLTrans::getString("broken_link");
+ std::string suffix;
+ LLInventoryItem* item = getItem();
+ if(item)
+ {
+ // it's a bit confusing to put nocopy/nomod/etc on calling cards.
+ if(LLAssetType::AT_CALLINGCARD != item->getType()
+ && item->getPermissions().getOwner() == gAgent.getID())
+ {
+ BOOL broken_link = LLAssetType::lookupIsLinkType(item->getType());
+ if (broken_link) return BROKEN_LINK;
+
+ BOOL link = item->getIsLinkType();
+ if (link) return LINK;
+
+ BOOL copy = item->getPermissions().allowCopyBy(gAgent.getID());
+ if (!copy)
+ {
+ suffix += NO_COPY;
+ }
+ BOOL mod = item->getPermissions().allowModifyBy(gAgent.getID());
+ if (!mod)
+ {
+ suffix += NO_MOD;
+ }
+ BOOL xfer = item->getPermissions().allowOperationBy(PERM_TRANSFER,
+ gAgent.getID());
+ if (!xfer)
+ {
+ suffix += NO_XFER;
+ }
+ }
+ }
+ return suffix;
+}
+
+time_t LLItemBridge::getCreationDate() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ return item->getCreationDate();
+ }
+ return 0;
+}
+
+
+BOOL LLItemBridge::isItemRenameable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ // (For now) Don't allow calling card rename since that may confuse users as to
+ // what the calling card points to.
+ if (item->getInventoryType() == LLInventoryType::IT_CALLINGCARD)
+ {
+ return FALSE;
+ }
+ return (item->getPermissions().allowModifyBy(gAgent.getID()));
+ }
+ return FALSE;
+}
+
+BOOL LLItemBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+
+BOOL LLItemBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID, TRUE);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ LLViewerInventoryItem* item = getItem();
+
+ // if item is not already in trash
+ if(item && !model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // move to trash, and restamp
+ LLInvFVBridge::changeItemParent(model, item, trash_id, TRUE);
+ // delete was successful
+ return TRUE;
+ }
+ else
+ {
+ // tried to delete already item in trash (should purge?)
+ return FALSE;
+ }
+}
+
+BOOL LLItemBridge::isItemCopyable() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ // can't copy worn objects. DEV-15183
+ LLVOAvatarSelf *avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return FALSE;
+ }
+
+ if(avatarp->isWearingAttachment(mUUID))
+ {
+ return FALSE;
+ }
+
+ // All items can be copied, not all can be pasted.
+ // The only time an item can't be copied is if it's a link
+ // return (item->getPermissions().allowCopyBy(gAgent.getID()));
+ if (item->getIsLinkType())
+ {
+ return FALSE;
+ }
+ return TRUE;
+ }
+ return FALSE;
+}
+BOOL LLItemBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+LLViewerInventoryItem* LLItemBridge::getItem() const
+{
+ LLViewerInventoryItem* item = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ item = (LLViewerInventoryItem*)model->getItem(mUUID);
+ }
+ return item;
+}
+
+BOOL LLItemBridge::isItemPermissive() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ U32 mask = item->getPermissions().getMaskBase();
+ if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+// +=================================================+
+// | LLFolderBridge |
+// +=================================================+
+
+LLFolderBridge* LLFolderBridge::sSelf=NULL;
+
+// Can be moved to another folder
+BOOL LLFolderBridge::isItemMovable() const
+{
+ LLInventoryObject* obj = getInventoryObject();
+ if(obj)
+ {
+ return (!LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)obj)->getPreferredType()));
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::selectItem()
+{
+}
+
+
+// Can be destroyed (or moved to trash)
+BOOL LLFolderBridge::isItemRemovable()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ {
+ return FALSE;
+ }
+
+ if(!model->isObjectDescendentOf(mUUID, gInventory.getRootFolderID()))
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( !avatar )
+ {
+ return FALSE;
+ }
+
+ LLInventoryCategory* category = model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ return FALSE;
+ }
+ }
+
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if(gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if(avatar->isWearingAttachment(item->getUUID()))
+ {
+ return FALSE;
+ }
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isUpToDate() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if( !category )
+ {
+ return FALSE;
+ }
+
+ return category->getVersion() != LLViewerInventoryCategory::VERSION_UNKNOWN;
+}
+
+BOOL LLFolderBridge::isItemCopyable() const
+{
+ return TRUE;
+}
+
+BOOL LLFolderBridge::copyToClipboard() const
+{
+ if(isItemCopyable())
+ {
+ LLInventoryClipboard::instance().add(mUUID);
+ return TRUE;
+ }
+ return FALSE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteable() const
+{
+ if ( ! LLInvFVBridge::isClipboardPasteable() )
+ return FALSE;
+
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( LLFriendCardsManager::instance().isCategoryInFriendFolder( getCategory() ) )
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if ( !model )
+ {
+ return FALSE;
+ }
+
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ const LLViewerInventoryCategory *current_cat = getCategory();
+
+ // Search for the direct descendent of current Friends subfolder among all pasted items,
+ // and return false if is found.
+ for(S32 i = objects.count() - 1; i >= 0; --i)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+
+ }
+ return TRUE;
+}
+
+BOOL LLFolderBridge::isClipboardPasteableAsLink() const
+{
+ // Check normal paste-as-link permissions
+ if (!LLInvFVBridge::isClipboardPasteableAsLink())
+ {
+ return FALSE;
+ }
+
+ const LLInventoryModel* model = getInventoryModel();
+ if (!model)
+ {
+ return FALSE;
+ }
+
+ const LLViewerInventoryCategory *current_cat = getCategory();
+ if (current_cat)
+ {
+ const BOOL is_in_friend_folder = LLFriendCardsManager::instance().isCategoryInFriendFolder( current_cat );
+ const LLUUID &current_cat_id = current_cat->getUUID();
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &obj_id = objects.get(i);
+ const LLInventoryCategory *cat = model->getCategory(obj_id);
+ if (cat)
+ {
+ const LLUUID &cat_id = cat->getUUID();
+ // Don't allow recursive pasting
+ if ((cat_id == current_cat_id) ||
+ model->isObjectDescendentOf(current_cat_id, cat_id))
+ {
+ return FALSE;
+ }
+ }
+ // Don't allow pasting duplicates to the Calling Card/Friends subfolders, see bug EXT-1599
+ if ( is_in_friend_folder )
+ {
+ // If object is direct descendent of current Friends subfolder than return false.
+ // Note: We can't use 'const LLInventoryCategory *cat', because it may be null
+ // in case type of obj_id is LLInventoryItem.
+ if ( LLFriendCardsManager::instance().isObjDirectDescendentOfCategory(model->getObject(obj_id), current_cat) )
+ {
+ return FALSE;
+ }
+ }
+ }
+ }
+ return TRUE;
+
+}
+
+BOOL LLFolderBridge::dragCategoryIntoFolder(LLInventoryCategory* inv_cat,
+ BOOL drop)
+{
+ // This should never happen, but if an inventory item is incorrectly parented,
+ // the UI will get confused and pass in a NULL.
+ if(!inv_cat) return FALSE;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ // cannot drag categories into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ // check to make sure source is agent inventory, and is represented there.
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL is_agent_inventory = (model->getCategory(inv_cat->getUUID()) != NULL)
+ && (LLToolDragAndDrop::SOURCE_AGENT == source);
+
+ BOOL accept = FALSE;
+ S32 i;
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ if(is_agent_inventory)
+ {
+ const LLUUID& cat_id = inv_cat->getUUID();
+
+ // Is the destination the trash?
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id)
+ || model->isObjectDescendentOf(mUUID, trash_id);
+ BOOL is_movable = (!LLFolderType::lookupIsProtectedType(inv_cat->getPreferredType()));
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - restrictions?
+ is_movable = true;
+ }
+
+ if (mUUID == gInventory.findCategoryUUIDForType(LLFolderType::FT_FAVORITE))
+ {
+ is_movable = FALSE; // It's generally movable but not into Favorites folder. EXT-1604
+ }
+
+ if( is_movable )
+ {
+ gInventory.collectDescendents( cat_id, descendent_categories, descendent_items, FALSE );
+
+ for( i = 0; i < descendent_categories.count(); i++ )
+ {
+ LLInventoryCategory* category = descendent_categories[i];
+ if(LLFolderType::lookupIsProtectedType(category->getPreferredType()))
+ {
+ // ...can't move "special folders" like Textures
+ is_movable = FALSE;
+ break;
+ }
+ }
+
+ if( is_movable )
+ {
+ if( move_is_into_trash )
+ {
+ for( i = 0; i < descendent_items.count(); i++ )
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if( (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART) )
+ {
+ if( gAgentWearables.isWearingItem( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ else
+ if( item->getType() == LLAssetType::AT_OBJECT )
+ {
+ if( avatar->isWearingAttachment( item->getUUID() ) )
+ {
+ is_movable = FALSE; // It's generally movable, but not into the trash!
+ break;
+ }
+ }
+ }
+ }
+ }
+ }
+
+
+ accept = is_movable
+ && (mUUID != cat_id) // Can't move a folder into itself
+ && (mUUID != inv_cat->getParentUUID()) // Avoid moves that would change nothing
+ && !(model->isObjectDescendentOf(mUUID, cat_id)); // Avoid circularity
+ if(accept && drop)
+ {
+ // Look for any gestures and deactivate them
+ if (move_is_into_trash)
+ {
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+ }
+ // if target is an outfit or current outfit folder we use link
+ if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+#if SUPPORT_ENSEMBLES
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearEnsemble(inv_cat);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_cat->getUUID(),
+ mUUID,
+ inv_cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ cb);
+ }
+#endif
+ }
+ else
+ {
+
+ // Reparent the folder and restamp children if it's moving
+ // into trash.
+ LLInvFVBridge::changeCategoryParent(
+ model,
+ (LLViewerInventoryCategory*)inv_cat,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // content category has same ID as object itself
+ LLUUID object_id = inv_cat->getUUID();
+ LLUUID category_id = mUUID;
+ accept = move_inv_category_world_to_agent(object_id, category_id, drop);
+ }
+ return accept;
+}
+
+void warn_move_inventory(LLViewerObject* object, LLMoveInv* move_inv)
+{
+ const char* dialog = NULL;
+ if (object->flagScripted())
+ {
+ dialog = "MoveInventoryFromScriptedObject";
+ }
+ else
+ {
+ dialog = "MoveInventoryFromObject";
+ }
+ LLNotifications::instance().add(dialog, LLSD(), LLSD(), boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+}
+
+// Move/copy all inventory items from the Contents folder of an in-world
+// object to the agent's inventory, inside a given category.
+BOOL move_inv_category_world_to_agent(const LLUUID& object_id,
+ const LLUUID& category_id,
+ BOOL drop,
+ void (*callback)(S32, void*),
+ void* user_data)
+{
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ // content category has same ID as object itself
+ LLViewerObject* object = gObjectList.findObject(object_id);
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // this folder is coming from an object, as there is only one folder in an object, the root,
+ // we need to collect the entire contents and handle them as a group
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+
+ if (inventory_objects.empty())
+ {
+ llinfos << "Object contents not found for drop." << llendl;
+ return FALSE;
+ }
+
+ BOOL accept = TRUE;
+ BOOL is_move = FALSE;
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ InventoryObjectList::iterator it = inventory_objects.begin();
+ InventoryObjectList::iterator end = inventory_objects.end();
+ for ( ; it != end; ++it)
+ {
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(((LLInventoryItem*)((LLInventoryObject*)(*it)))->getPermissions());
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ else
+ {
+ accept = FALSE;
+ break;
+ }
+ }
+
+ if(drop && accept)
+ {
+ it = inventory_objects.begin();
+ InventoryObjectList::iterator first_it = inventory_objects.begin();
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = object_id;
+ move_inv->mCategoryID = category_id;
+ move_inv->mCallback = callback;
+ move_inv->mUserData = user_data;
+
+ for ( ; it != end; ++it)
+ {
+ two_uuids_t two(category_id, (*it)->getUUID());
+ move_inv->mMoveList.push_back(two);
+ }
+
+ if(is_move)
+ {
+ // Callback called from within here.
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+ return accept;
+}
+
+bool LLFindCOFValidItems::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ // Valid COF items are:
+ // - links to wearables (body parts or clothing)
+ // - links to attachments
+ // - links to gestures
+ // - links to ensemble folders
+ LLViewerInventoryItem *linked_item = ((LLViewerInventoryItem*)item)->getLinkedItem(); // BAP - safe?
+ if (linked_item)
+ {
+ LLAssetType::EType type = linked_item->getType();
+ return (type == LLAssetType::AT_CLOTHING ||
+ type == LLAssetType::AT_BODYPART ||
+ type == LLAssetType::AT_GESTURE ||
+ type == LLAssetType::AT_OBJECT);
+ }
+ else
+ {
+ LLViewerInventoryCategory *linked_category = ((LLViewerInventoryItem*)item)->getLinkedCategory(); // BAP - safe?
+ // BAP remove AT_NONE support after ensembles are fully working?
+ return (linked_category &&
+ ((linked_category->getPreferredType() == LLFolderType::FT_NONE) ||
+ (LLFolderType::lookupIsEnsembleType(linked_category->getPreferredType()))));
+ }
+}
+
+
+bool LLFindWearables::operator()(LLInventoryCategory* cat,
+ LLInventoryItem* item)
+{
+ if(item)
+ {
+ if((item->getType() == LLAssetType::AT_CLOTHING)
+ || (item->getType() == LLAssetType::AT_BODYPART))
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchObserver : public LLInventoryFetchObserver
+{
+public:
+ LLRightClickInventoryFetchObserver() :
+ mCopyItems(false)
+ { };
+ LLRightClickInventoryFetchObserver(const LLUUID& cat_id, bool copy_items) :
+ mCatID(cat_id),
+ mCopyItems(copy_items)
+ { };
+ virtual void done()
+ {
+ // we've downloaded all the items, so repaint the dialog
+ LLFolderBridge::staticFolderOptionsMenu();
+
+ gInventory.removeObserver(this);
+ delete this;
+ }
+
+
+protected:
+ LLUUID mCatID;
+ bool mCopyItems;
+
+};
+
+//Used by LLFolderBridge as callback for directory recursion.
+class LLRightClickInventoryFetchDescendentsObserver : public LLInventoryFetchDescendentsObserver
+{
+public:
+ LLRightClickInventoryFetchDescendentsObserver(bool copy_items) : mCopyItems(copy_items) {}
+ ~LLRightClickInventoryFetchDescendentsObserver() {}
+ virtual void done();
+protected:
+ bool mCopyItems;
+};
+
+void LLRightClickInventoryFetchDescendentsObserver::done()
+{
+ // Avoid passing a NULL-ref as mCompleteFolders.front() down to
+ // gInventory.collectDescendents()
+ if( mCompleteFolders.empty() )
+ {
+ llwarns << "LLRightClickInventoryFetchDescendentsObserver::done with empty mCompleteFolders" << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+
+ // What we do here is get the complete information on the items in
+ // the library, and set up an observer that will wait for that to
+ // happen.
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ gInventory.collectDescendents(mCompleteFolders.front(),
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH);
+ S32 count = item_array.count();
+#if 0 // HACK/TODO: Why?
+ // This early causes a giant menu to get produced, and doesn't seem to be needed.
+ if(!count)
+ {
+ llwarns << "Nothing fetched in category " << mCompleteFolders.front()
+ << llendl;
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+ return;
+ }
+#endif
+
+ LLRightClickInventoryFetchObserver* outfit;
+ outfit = new LLRightClickInventoryFetchObserver(mCompleteFolders.front(), mCopyItems);
+ LLInventoryFetchObserver::item_ref_t ids;
+ for(S32 i = 0; i < count; ++i)
+ {
+ ids.push_back(item_array.get(i)->getUUID());
+ }
+
+ // clean up, and remove this as an observer since the call to the
+ // outfit could notify observers and throw us into an infinite
+ // loop.
+ dec_busy_count();
+ gInventory.removeObserver(this);
+ delete this;
+
+ // increment busy count and either tell the inventory to check &
+ // call done, or add this object to the inventory for observation.
+ inc_busy_count();
+
+ // do the fetch
+ outfit->fetchItems(ids);
+ outfit->done(); //Not interested in waiting and this will be right 99% of the time.
+//Uncomment the following code for laggy Inventory UI.
+/* if(outfit->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ outfit->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(outfit);
+ }*/
+}
+
+
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+// Class LLInventoryWearObserver
+//
+// Observer for "copy and wear" operation to support knowing
+// when the all of the contents have been added to inventory.
+//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+class LLInventoryCopyAndWearObserver : public LLInventoryObserver
+{
+public:
+ LLInventoryCopyAndWearObserver(const LLUUID& cat_id, int count) :mCatID(cat_id), mContentsCount(count), mFolderAdded(FALSE) {}
+ virtual ~LLInventoryCopyAndWearObserver() {}
+ virtual void changed(U32 mask);
+
+protected:
+ LLUUID mCatID;
+ int mContentsCount;
+ BOOL mFolderAdded;
+};
+
+
+
+void LLInventoryCopyAndWearObserver::changed(U32 mask)
+{
+ if((mask & (LLInventoryObserver::ADD)) != 0)
+ {
+ if (!mFolderAdded)
+ {
+ const std::set<LLUUID>& changed_items = gInventory.getChangedIDs();
+
+ std::set<LLUUID>::const_iterator id_it = changed_items.begin();
+ std::set<LLUUID>::const_iterator id_end = changed_items.end();
+ for (;id_it != id_end; ++id_it)
+ {
+ if ((*id_it) == mCatID)
+ {
+ mFolderAdded = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (mFolderAdded)
+ {
+ LLViewerInventoryCategory* category = gInventory.getCategory(mCatID);
+
+ if (NULL == category)
+ {
+ llwarns << "gInventory.getCategory(" << mCatID
+ << ") was NULL" << llendl;
+ }
+ else
+ {
+ if (category->getDescendentCount() ==
+ mContentsCount)
+ {
+ gInventory.removeObserver(this);
+ LLAppearanceManager::wearInventoryCategory(category, FALSE, TRUE);
+ delete this;
+ }
+ }
+ }
+
+ }
+}
+
+
+
+void LLFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("open" == action)
+ {
+ openItem();
+ return;
+ }
+ else if ("paste" == action)
+ {
+ pasteFromClipboard();
+ return;
+ }
+ else if ("paste_link" == action)
+ {
+ pasteLinkFromClipboard();
+ return;
+ }
+ else if ("properties" == action)
+ {
+ showProperties();
+ return;
+ }
+ else if ("replaceoutfit" == action)
+ {
+ modifyOutfit(FALSE);
+ return;
+ }
+#if SUPPORT_ENSEMBLES
+ else if ("wearasensemble" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+ LLAppearanceManager::wearEnsemble(cat,true);
+ return;
+ }
+#endif
+ else if ("addtooutfit" == action)
+ {
+ modifyOutfit(TRUE);
+ return;
+ }
+ else if ("copy" == action)
+ {
+ copyToClipboard();
+ return;
+ }
+ else if ("removefromoutfit" == action)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ remove_inventory_category_from_avatar ( cat );
+ return;
+ }
+ else if ("purge" == action)
+ {
+ purgeItem(model, mUUID);
+ return;
+ }
+ else if ("restore" == action)
+ {
+ restoreItem();
+ return;
+ }
+}
+
+void LLFolderBridge::openItem()
+{
+ lldebugs << "LLFolderBridge::openItem()" << llendl;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ if(mUUID.isNull()) return;
+ bool fetching_inventory = model->fetchDescendentsOf(mUUID);
+ // Only change folder type if we have the folder contents.
+ if (!fetching_inventory)
+ {
+ // Disabling this for now, it's causing crash when new items are added to folders
+ // since folder type may change before new item item has finished processing.
+ // determineFolderType();
+ }
+}
+
+void LLFolderBridge::closeItem()
+{
+ determineFolderType();
+}
+
+void LLFolderBridge::determineFolderType()
+{
+ if (isUpToDate())
+ {
+ LLInventoryModel* model = getInventoryModel();
+ LLViewerInventoryCategory* category = model->getCategory(mUUID);
+ category->determineFolderType();
+ }
+}
+
+BOOL LLFolderBridge::isItemRenameable() const
+{
+ LLViewerInventoryCategory* cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat && !LLFolderType::lookupIsProtectedType(cat->getPreferredType())
+ && (cat->getOwnerID() == gAgent.getID()))
+ {
+ return TRUE;
+ }
+ return FALSE;
+}
+
+void LLFolderBridge::restoreItem()
+{
+ LLViewerInventoryCategory* cat;
+ cat = (LLViewerInventoryCategory*)getCategory();
+ if(cat)
+ {
+ LLInventoryModel* model = getInventoryModel();
+ const LLUUID new_parent = model->findCategoryUUIDForType(LLFolderType::assetTypeToFolderType(cat->getType()));
+ // do not restamp children on restore
+ LLInvFVBridge::changeCategoryParent(model, cat, new_parent, FALSE);
+ }
+}
+
+LLFolderType::EType LLFolderBridge::getPreferredType() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+
+ return preferred_type;
+}
+
+// Icons for folders are based on the preferred type
+LLUIImagePtr LLFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ return getIcon(preferred_type);
+}
+
+LLUIImagePtr LLFolderBridge::getIcon(LLFolderType::EType preferred_type)
+{
+ // we only have one folder image now
+ return LLUI::getUIImage("Inv_FolderClosed");
+ /*case LLAssetType::AT_MESH:
+ control = "inv_folder_mesh.tga";
+ break;*/
+}
+
+BOOL LLFolderBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat && (cat->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryCategory> new_cat = new LLViewerInventoryCategory(cat);
+ new_cat->rename(new_name);
+ new_cat->updateServer(FALSE);
+ model->updateCategory(new_cat);
+
+ model->notifyObservers();
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+BOOL LLFolderBridge::removeItem()
+{
+ if(!isItemRemovable())
+ {
+ return FALSE;
+ }
+ // move it to the trash
+ LLPreview::hide(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+
+ // Look for any gestures and deactivate them
+ LLInventoryModel::cat_array_t descendent_categories;
+ LLInventoryModel::item_array_t descendent_items;
+ gInventory.collectDescendents( mUUID, descendent_categories, descendent_items, FALSE );
+
+ S32 i;
+ for (i = 0; i < descendent_items.count(); i++)
+ {
+ LLInventoryItem* item = descendent_items[i];
+ if (item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(item->getUUID()))
+ {
+ LLGestureManager::instance().deactivateGesture(item->getUUID());
+ }
+ }
+
+ // go ahead and do the normal remove if no 'last calling
+ // cards' are being removed.
+ LLViewerInventoryCategory* cat = getCategory();
+ if(cat)
+ {
+ LLInvFVBridge::changeCategoryParent(model, cat, trash_id, TRUE);
+ }
+
+ return TRUE;
+}
+
+void LLFolderBridge::pasteFromClipboard()
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(model && isClipboardPasteable())
+ {
+ LLInventoryItem* item = NULL;
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ const LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ item = model->getItem(objects.get(i));
+ if (item)
+ {
+ if(LLInventoryClipboard::instance().isCutMode())
+ {
+ // move_inventory_item() is not enough,
+ //we have to update inventory locally too
+ changeItemParent(model, dynamic_cast<LLViewerInventoryItem*>(item), parent_id, FALSE);
+ }
+ else
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ parent_id,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ }
+}
+
+void LLFolderBridge::pasteLinkFromClipboard()
+{
+ const LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ LLDynamicArray<LLUUID> objects;
+ LLInventoryClipboard::instance().retrieve(objects);
+ S32 count = objects.count();
+ LLUUID parent_id(mUUID);
+ for(S32 i = 0; i < count; i++)
+ {
+ const LLUUID &object_id = objects.get(i);
+#if SUPPORT_ENSEMBLES
+ if (LLInventoryCategory *cat = model->getCategory(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ cat->getUUID(),
+ parent_id,
+ cat->getName(),
+ LLAssetType::AT_LINK_FOLDER,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else
+#endif
+ if (LLInventoryItem *item = model->getItem(object_id))
+ {
+ link_inventory_item(
+ gAgent.getID(),
+ item->getUUID(),
+ parent_id,
+ item->getName(),
+ LLAssetType::AT_LINK,
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+}
+
+void LLFolderBridge::staticFolderOptionsMenu()
+{
+ if (!sSelf) return;
+ sSelf->folderOptionsMenu();
+}
+
+void LLFolderBridge::folderOptionsMenu()
+{
+ std::vector<std::string> disabled_items;
+
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+
+ const LLInventoryCategory* category = model->getCategory(mUUID);
+ LLFolderType::EType type = category->getPreferredType();
+ const bool is_default_folder = category && LLFolderType::lookupIsProtectedType(type);
+ // BAP change once we're no longer treating regular categories as ensembles.
+ const bool is_ensemble = category && (type == LLFolderType::FT_NONE ||
+ LLFolderType::lookupIsEnsembleType(type));
+
+ // calling card related functionality for folders.
+
+ // Only enable calling-card related options for non-default folders.
+ if (!is_default_folder)
+ {
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (mCallingCards || checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mItems.push_back(std::string("Calling Card Separator"));
+ mItems.push_back(std::string("Conference Chat Folder"));
+ mItems.push_back(std::string("IM All Contacts In Folder"));
+ }
+ }
+
+ // wearables related functionality for folders.
+ //is_wearable
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (mWearables ||
+ checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mItems.push_back(std::string("Folder Wearables Separator"));
+
+ // Only enable add/replace outfit for non-default folders.
+ if (!is_default_folder)
+ {
+ mItems.push_back(std::string("Add To Outfit"));
+ mItems.push_back(std::string("Replace Outfit"));
+ }
+ if (is_ensemble)
+ {
+ mItems.push_back(std::string("Wear As Ensemble"));
+ }
+ mItems.push_back(std::string("Take Off Items"));
+ }
+ hide_context_entries(*mMenu, mItems, disabled_items);
+}
+
+BOOL LLFolderBridge::checkFolderForContentsOfType(LLInventoryModel* model, LLInventoryCollectFunctor& is_type)
+{
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ model->collectDescendentsIf(mUUID,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_type);
+ return ((item_array.count() > 0) ? TRUE : FALSE );
+}
+
+// Flags unused
+void LLFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ mItems.clear();
+ mDisabledItems.clear();
+
+ lldebugs << "LLFolderBridge::buildContextMenu()" << llendl;
+// std::vector<std::string> disabled_items;
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ const LLUUID lost_and_found_id = model->findCategoryUUIDForType(LLFolderType::FT_LOST_AND_FOUND);
+
+ mItems.clear(); //adding code to clear out member Items (which means Items should not have other data here at this point)
+ mDisabledItems.clear(); //adding code to clear out disabled members from previous
+ if (lost_and_found_id == mUUID)
+ {
+ // This is the lost+found folder.
+ mItems.push_back(std::string("Empty Lost And Found"));
+ }
+
+ if(trash_id == mUUID)
+ {
+ // This is the trash.
+ mItems.push_back(std::string("Empty Trash"));
+ }
+ else if(model->isObjectDescendentOf(mUUID, trash_id))
+ {
+ // This is a folder in the trash.
+ mItems.clear(); // clear any items that used to exist
+ mItems.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ mDisabledItems.push_back(std::string("Purge Item"));
+ }
+
+ mItems.push_back(std::string("Restore Item"));
+ }
+ else if(isAgentInventory()) // do not allow creating in library
+ {
+ LLViewerInventoryCategory *cat = getCategory();
+ // BAP removed protected check to re-enable standard ops in untyped folders.
+ // Not sure what the right thing is to do here.
+ if (!isCOFFolder() && cat /*&&
+ LLAssetType::lookupIsProtectedCategoryType(cat->getPreferredType())*/)
+ {
+ // Do not allow to create 2-level subfolder in the Calling Card/Friends folder. EXT-694.
+ if (!LLFriendCardsManager::instance().isCategoryInFriendFolder(cat))
+ mItems.push_back(std::string("New Folder"));
+ mItems.push_back(std::string("New Script"));
+ mItems.push_back(std::string("New Note"));
+ mItems.push_back(std::string("New Gesture"));
+ mItems.push_back(std::string("New Clothes"));
+ mItems.push_back(std::string("New Body Parts"));
+ mItems.push_back(std::string("Change Type"));
+
+ LLViewerInventoryCategory *cat = getCategory();
+ if (cat && LLFolderType::lookupIsProtectedType(cat->getPreferredType()))
+ {
+ mDisabledItems.push_back(std::string("Change Type"));
+ }
+
+ getClipboardEntries(false, mItems, mDisabledItems, flags);
+ }
+ else
+ {
+ // Want some but not all of the items from getClipboardEntries for outfits.
+ if (cat && cat->getPreferredType()==LLFolderType::FT_OUTFIT)
+ {
+ mItems.push_back(std::string("Rename"));
+ mItems.push_back(std::string("Delete"));
+ }
+ }
+
+ //Added by spatters to force inventory pull on right-click to display folder options correctly. 07-17-06
+ mCallingCards = mWearables = FALSE;
+
+ LLIsType is_callingcard(LLAssetType::AT_CALLINGCARD);
+ if (checkFolderForContentsOfType(model, is_callingcard))
+ {
+ mCallingCards=TRUE;
+ }
+
+ LLFindWearables is_wearable;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+
+ if (checkFolderForContentsOfType(model, is_wearable) ||
+ checkFolderForContentsOfType(model, is_object) ||
+ checkFolderForContentsOfType(model, is_gesture) )
+ {
+ mWearables=TRUE;
+ }
+
+ mMenu = &menu;
+ sSelf = this;
+ LLRightClickInventoryFetchDescendentsObserver* fetch = new LLRightClickInventoryFetchDescendentsObserver(FALSE);
+
+ LLInventoryFetchDescendentsObserver::folder_ref_t folders;
+ LLViewerInventoryCategory* category = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ if (category)
+ {
+ folders.push_back(category->getUUID());
+ }
+ fetch->fetchDescendents(folders);
+ inc_busy_count();
+ if(fetch->isEverythingComplete())
+ {
+ // everything is already here - call done.
+ fetch->done();
+ }
+ else
+ {
+ // it's all on it's way - add an observer, and the inventory
+ // will call done for us when everything is here.
+ gInventory.addObserver(fetch);
+ }
+ }
+ else
+ {
+ mItems.push_back(std::string("--no options--"));
+ mDisabledItems.push_back(std::string("--no options--"));
+ }
+ hide_context_entries(menu, mItems, mDisabledItems);
+}
+
+BOOL LLFolderBridge::hasChildren() const
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+ LLInventoryModel::EHasChildren has_children;
+ has_children = gInventory.categoryHasChildren(mUUID);
+ return has_children != LLInventoryModel::CHILDREN_NO;
+}
+
+BOOL LLFolderBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ //llinfos << "LLFolderBridge::dragOrDrop()" << llendl;
+ BOOL accept = FALSE;
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_CALLINGCARD:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_CLOTHING:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_LINK:
+ case DAD_MESH:
+ accept = dragItemIntoFolder((LLInventoryItem*)cargo_data,
+ drop);
+ break;
+ case DAD_CATEGORY:
+ if (LLFriendCardsManager::instance().isAnyFriendCategory(mUUID))
+ {
+ accept = FALSE;
+ }
+ else
+ {
+ accept = dragCategoryIntoFolder((LLInventoryCategory*)cargo_data, drop);
+ }
+ break;
+ default:
+ break;
+ }
+ return accept;
+}
+
+LLViewerInventoryCategory* LLFolderBridge::getCategory() const
+{
+ LLViewerInventoryCategory* cat = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ cat = (LLViewerInventoryCategory*)model->getCategory(mUUID);
+ }
+ return cat;
+}
+
+
+// static
+void LLFolderBridge::pasteClipboard(void* user_data)
+{
+ LLFolderBridge* self = (LLFolderBridge*)user_data;
+ if(self) self->pasteFromClipboard();
+}
+
+void LLFolderBridge::createNewCategory(void* user_data)
+{
+ LLFolderBridge* bridge = (LLFolderBridge*)user_data;
+ if(!bridge) return;
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(bridge->mInventoryPanel.get());
+ if (!panel) return;
+ LLInventoryModel* model = panel->getModel();
+ if(!model) return;
+ LLUUID id;
+ id = model->createNewCategory(bridge->getUUID(),
+ LLFolderType::FT_NONE,
+ LLStringUtil::null);
+ model->notifyObservers();
+
+ // At this point, the bridge has probably been deleted, but the
+ // view is still there.
+ panel->setSelection(id, TAKE_FOCUS_YES);
+}
+
+void LLFolderBridge::createNewShirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHIRT);
+}
+
+void LLFolderBridge::createNewPants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_PANTS);
+}
+
+void LLFolderBridge::createNewShoes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHOES);
+}
+
+void LLFolderBridge::createNewSocks(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SOCKS);
+}
+
+void LLFolderBridge::createNewJacket(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_JACKET);
+}
+
+void LLFolderBridge::createNewSkirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIRT);
+}
+
+void LLFolderBridge::createNewGloves(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_GLOVES);
+}
+
+void LLFolderBridge::createNewUndershirt(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERSHIRT);
+}
+
+void LLFolderBridge::createNewUnderpants(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_UNDERPANTS);
+}
+
+void LLFolderBridge::createNewShape(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SHAPE);
+}
+
+void LLFolderBridge::createNewSkin(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_SKIN);
+}
+
+void LLFolderBridge::createNewHair(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_HAIR);
+}
+
+void LLFolderBridge::createNewEyes(void* user_data)
+{
+ LLFolderBridge::createWearable((LLFolderBridge*)user_data, WT_EYES);
+}
+
+// static
+void LLFolderBridge::createWearable(LLFolderBridge* bridge, EWearableType type)
+{
+ if(!bridge) return;
+ LLUUID parent_id = bridge->getUUID();
+ createWearable(parent_id, type);
+}
+
+// Separate function so can be called by global menu as well as right-click
+// menu.
+// static
+void LLFolderBridge::createWearable(const LLUUID &parent_id, EWearableType type)
+{
+ LLWearable* wearable = LLWearableList::instance().createNewWearable(type);
+ LLAssetType::EType asset_type = wearable->getAssetType();
+ LLInventoryType::EType inv_type = LLInventoryType::IT_WEARABLE;
+ create_inventory_item(gAgent.getID(), gAgent.getSessionID(),
+ parent_id, wearable->getTransactionID(), wearable->getName(),
+ wearable->getDescription(), asset_type, inv_type, wearable->getType(),
+ wearable->getPermissions().getMaskNextOwner(),
+ LLPointer<LLInventoryCallback>(NULL));
+}
+
+void LLFolderBridge::modifyOutfit(BOOL append)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return;
+ LLViewerInventoryCategory* cat = getCategory();
+ if(!cat) return;
+
+ // BAP - was:
+ // wear_inventory_category_on_avatar( cat, append );
+ LLAppearanceManager::wearInventoryCategory( cat, FALSE, append );
+}
+
+// helper stuff
+bool move_task_inventory_callback(const LLSD& notification, const LLSD& response, LLMoveInv* move_inv)
+{
+ LLFloaterOpenObject::LLCatAndWear* cat_and_wear = (LLFloaterOpenObject::LLCatAndWear* )move_inv->mUserData;
+ LLViewerObject* object = gObjectList.findObject(move_inv->mObjectID);
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ if(option == 0 && object)
+ {
+ if (cat_and_wear && cat_and_wear->mWear)
+ {
+ InventoryObjectList inventory_objects;
+ object->getInventoryContents(inventory_objects);
+ int contents_count = inventory_objects.size()-1; //subtract one for containing folder
+
+ LLInventoryCopyAndWearObserver* inventoryObserver = new LLInventoryCopyAndWearObserver(cat_and_wear->mCatID, contents_count);
+ gInventory.addObserver(inventoryObserver);
+ }
+
+ two_uuids_list_t::iterator move_it;
+ for (move_it = move_inv->mMoveList.begin();
+ move_it != move_inv->mMoveList.end();
+ ++move_it)
+ {
+ object->moveInventory(move_it->first, move_it->second);
+ }
+
+ // update the UI.
+ dialog_refresh_all();
+ }
+
+ if (move_inv->mCallback)
+ {
+ move_inv->mCallback(option, move_inv->mUserData);
+ }
+
+ delete move_inv;
+ return false;
+}
+
+/*
+Next functions intended to reorder items in the inventory folder and save order on server
+Is now used for Favorites folder.
+
+*TODO: refactoring is needed with Favorites Bar functionality. Probably should be moved in LLInventoryModel
+*/
+void saveItemsOrder(LLInventoryModel::item_array_t& items)
+{
+ int sortField = 0;
+
+ // current order is saved by setting incremental values (1, 2, 3, ...) for the sort field
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ LLViewerInventoryItem* item = *i;
+
+ item->setSortField(++sortField);
+ item->setComplete(TRUE);
+ item->updateServer(FALSE);
+
+ gInventory.updateItem(item);
+ }
+
+ gInventory.notifyObservers();
+}
+
+LLInventoryModel::item_array_t::iterator findItemByUUID(LLInventoryModel::item_array_t& items, const LLUUID& id)
+{
+ LLInventoryModel::item_array_t::iterator result = items.end();
+
+ for (LLInventoryModel::item_array_t::iterator i = items.begin(); i != items.end(); ++i)
+ {
+ if ((*i)->getUUID() == id)
+ {
+ result = i;
+ break;
+ }
+ }
+
+ return result;
+}
+
+void updateItemsOrder(LLInventoryModel::item_array_t& items, const LLUUID& srcItemId, const LLUUID& destItemId)
+{
+ LLViewerInventoryItem* srcItem = gInventory.getItem(srcItemId);
+ LLViewerInventoryItem* destItem = gInventory.getItem(destItemId);
+
+ items.erase(findItemByUUID(items, srcItem->getUUID()));
+ items.insert(findItemByUUID(items, destItem->getUUID()), srcItem);
+}
+
+BOOL LLFolderBridge::dragItemIntoFolder(LLInventoryItem* inv_item,
+ BOOL drop)
+{
+ LLInventoryModel* model = getInventoryModel();
+ if(!model) return FALSE;
+
+ // cannot drag into library
+ if(!isAgentInventory())
+ {
+ return FALSE;
+ }
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+
+ LLToolDragAndDrop::ESource source = LLToolDragAndDrop::getInstance()->getSource();
+ BOOL accept = FALSE;
+ LLViewerObject* object = NULL;
+ if(LLToolDragAndDrop::SOURCE_AGENT == source)
+ {
+
+ BOOL is_movable = TRUE;
+ switch( inv_item->getActualType() )
+ {
+ case LLAssetType::AT_ROOT_CATEGORY:
+ is_movable = FALSE;
+ break;
+
+ case LLAssetType::AT_CATEGORY:
+ is_movable = !LLFolderType::lookupIsProtectedType(((LLInventoryCategory*)inv_item)->getPreferredType());
+ break;
+ default:
+ break;
+ }
+
+ const LLUUID trash_id = model->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ BOOL move_is_into_trash = (mUUID == trash_id) || model->isObjectDescendentOf(mUUID, trash_id);
+ const LLUUID current_outfit_id = model->findCategoryUUIDForType(LLFolderType::FT_CURRENT_OUTFIT);
+ BOOL move_is_into_current_outfit = (mUUID == current_outfit_id);
+ BOOL move_is_into_outfit = (getCategory() && getCategory()->getPreferredType()==LLFolderType::FT_OUTFIT);
+
+ if(is_movable && move_is_into_trash)
+ {
+ switch(inv_item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ is_movable = !gAgentWearables.isWearingItem(inv_item->getUUID());
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ is_movable = !avatar->isWearingAttachment(inv_item->getUUID());
+ break;
+ default:
+ break;
+ }
+ }
+
+ if ( is_movable )
+ {
+ // Don't allow creating duplicates in the Calling Card/Friends
+ // subfolders, see bug EXT-1599. Check is item direct descendent
+ // of target folder and forbid item's movement if it so.
+ // Note: isItemDirectDescendentOfCategory checks if
+ // passed category is in the Calling Card/Friends folder
+ is_movable = ! LLFriendCardsManager::instance()
+ .isObjDirectDescendentOfCategory (inv_item, getCategory());
+ }
+
+ const LLUUID& favorites_id = model->findCategoryUUIDForType(LLFolderType::FT_FAVORITE);
+
+ // we can move item inside a folder only if this folder is Favorites. See EXT-719
+ accept = is_movable && ((mUUID != inv_item->getParentUUID()) || (mUUID == favorites_id));
+ if(accept && drop)
+ {
+ if (inv_item->getType() == LLAssetType::AT_GESTURE
+ && LLGestureManager::instance().isGestureActive(inv_item->getUUID()) && move_is_into_trash)
+ {
+ LLGestureManager::instance().deactivateGesture(inv_item->getUUID());
+ }
+ // If an item is being dragged between windows, unselect
+ // everything in the active window so that we don't follow
+ // the selection to its new location (which is very
+ // annoying).
+ if (LLFloaterInventory::getActiveInventory())
+ {
+ LLInventoryPanel* active_panel = LLFloaterInventory::getActiveInventory()->getPanel();
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ if (active_panel && (panel != active_panel))
+ {
+ active_panel->unSelectAll();
+ }
+ }
+
+ // if dragging from/into favorites folder only reorder items
+ if ((mUUID == inv_item->getParentUUID()) && (favorites_id == mUUID))
+ {
+ LLInventoryModel::cat_array_t cats;
+ LLInventoryModel::item_array_t items;
+ LLIsType is_type(LLAssetType::AT_LANDMARK);
+ model->collectDescendentsIf(favorites_id, cats, items, LLInventoryModel::EXCLUDE_TRASH, is_type);
+
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getDraggingOverItem() : NULL;
+ if (itemp)
+ {
+ LLUUID srcItemId = inv_item->getUUID();
+ LLUUID destItemId = itemp->getListener()->getUUID();
+
+ // update order
+ updateItemsOrder(items, srcItemId, destItemId);
+
+ saveItemsOrder(items);
+ }
+ }
+ else if (favorites_id == mUUID) // if target is the favorites folder we use copy
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ else if (move_is_into_current_outfit || move_is_into_outfit)
+ {
+ // BAP - should skip if dup.
+ if (move_is_into_current_outfit)
+ {
+ LLAppearanceManager::wearItem(inv_item);
+ }
+ else
+ {
+ LLPointer<LLInventoryCallback> cb = NULL;
+ link_inventory_item(
+ gAgent.getID(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLAssetType::AT_LINK,
+ cb);
+ }
+ }
+ else
+ {
+ // restamp if the move is into the trash.
+ LLInvFVBridge::changeItemParent(
+ model,
+ (LLViewerInventoryItem*)inv_item,
+ mUUID,
+ move_is_into_trash);
+ }
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_WORLD == source)
+ {
+ // Make sure the object exists. If we allowed dragging from
+ // anonymous objects, it would be possible to bypass
+ // permissions.
+ object = gObjectList.findObject(inv_item->getParentUUID());
+ if(!object)
+ {
+ llinfos << "Object not found for drop." << llendl;
+ return FALSE;
+ }
+
+ // coming from a task. Need to figure out if the person can
+ // move/copy this item.
+ LLPermissions perm(inv_item->getPermissions());
+ BOOL is_move = FALSE;
+ if((perm.allowCopyBy(gAgent.getID(), gAgent.getGroupID())
+ && perm.allowTransferTo(gAgent.getID())))
+// || gAgent.isGodlike())
+
+ {
+ accept = TRUE;
+ }
+ else if(object->permYouOwner())
+ {
+ // If the object cannot be copied, but the object the
+ // inventory is owned by the agent, then the item can be
+ // moved from the task to agent inventory.
+ is_move = TRUE;
+ accept = TRUE;
+ }
+ if(drop && accept)
+ {
+ LLMoveInv* move_inv = new LLMoveInv;
+ move_inv->mObjectID = inv_item->getParentUUID();
+ two_uuids_t item_pair(mUUID, inv_item->getUUID());
+ move_inv->mMoveList.push_back(item_pair);
+ move_inv->mCallback = NULL;
+ move_inv->mUserData = NULL;
+ if(is_move)
+ {
+ warn_move_inventory(object, move_inv);
+ }
+ else
+ {
+ LLNotification::Params params("MoveInventoryFromObject");
+ params.functor.function(boost::bind(move_task_inventory_callback, _1, _2, move_inv));
+ LLNotifications::instance().forceResponse(params, 0);
+ }
+ }
+
+ }
+ else if(LLToolDragAndDrop::SOURCE_NOTECARD == source)
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_from_notecard(LLToolDragAndDrop::getInstance()->getObjectID(),
+ LLToolDragAndDrop::getInstance()->getSourceID(), inv_item);
+ }
+ }
+ else if(LLToolDragAndDrop::SOURCE_LIBRARY == source)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_item;
+ if(item && item->isComplete())
+ {
+ accept = TRUE;
+ if(drop)
+ {
+ copy_inventory_item(
+ gAgent.getID(),
+ inv_item->getPermissions().getOwner(),
+ inv_item->getUUID(),
+ mUUID,
+ std::string(),
+ LLPointer<LLInventoryCallback>(NULL));
+ }
+ }
+ }
+ else
+ {
+ llwarns << "unhandled drag source" << llendl;
+ }
+ return accept;
+}
+
+// +=================================================+
+// | LLScriptBridge (DEPRECTED) |
+// +=================================================+
+
+LLUIImagePtr LLScriptBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+// +=================================================+
+// | LLTextureBridge |
+// +=================================================+
+
+LLUIImagePtr LLTextureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_TEXTURE, mInvType, 0, FALSE);
+}
+
+void LLTextureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+}
+
+void LLTextureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLTextureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Texture Separator"));
+ items.push_back(std::string("Save As"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// virtual
+void LLTextureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("save_as" == action)
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ LLPreviewTexture* preview_texture = LLFloaterReg::findTypedInstance<LLPreviewTexture>("preview_texture", mUUID);
+ if (preview_texture)
+ {
+ preview_texture->openToSave();
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+// +=================================================+
+// | LLSoundBridge |
+// +=================================================+
+
+LLUIImagePtr LLSoundBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SOUND, LLInventoryType::IT_SOUND, 0, FALSE);
+}
+
+void LLSoundBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+// Changed this back to the way it USED to work:
+// only open the preview dialog through the contextual right-click menu
+// double-click just plays the sound
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ openSoundPreview((void*)this);
+ //send_uuid_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+*/
+}
+
+void LLSoundBridge::previewItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ send_sound_trigger(item->getAssetUUID(), 1.0);
+ }
+}
+
+void LLSoundBridge::openSoundPreview(void* which)
+{
+ LLSoundBridge *me = (LLSoundBridge *)which;
+ LLFloaterReg::showInstance("preview_sound", LLSD(me->mUUID), TAKE_FOCUS_YES);
+}
+
+void LLSoundBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLSoundBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Sound Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Sound Separator"));
+ items.push_back(std::string("Sound Play"));
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLLandmarkBridge |
+// +=================================================+
+
+LLLandmarkBridge::LLLandmarkBridge(LLInventoryPanel* inventory, const LLUUID& uuid, U32 flags/* = 0x00*/) :
+LLItemBridge(inventory, uuid)
+{
+ mVisited = FALSE;
+ if (flags & LLInventoryItem::II_FLAGS_LANDMARK_VISITED)
+ {
+ mVisited = TRUE;
+ }
+}
+
+LLUIImagePtr LLLandmarkBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_LANDMARK, LLInventoryType::IT_LANDMARK, mVisited, FALSE);
+}
+
+void LLLandmarkBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLLandmarkBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Landmark Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Landmark Separator"));
+ items.push_back(std::string("About Landmark"));
+
+ // Disable "About Landmark" menu item for
+ // multiple landmarks selected. Only one landmark
+ // info panel can be shown at a time.
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("About Landmark"));
+ }
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Convenience function for the two functions below.
+void teleport_via_landmark(const LLUUID& asset_id)
+{
+ gAgent.teleportViaLandmark( asset_id );
+
+ // we now automatically track the landmark you're teleporting to
+ // because you'll probably arrive at a telehub instead
+ LLFloaterWorldMap* floater_world_map = LLFloaterWorldMap::getInstance();
+ if( floater_world_map )
+ {
+ floater_world_map->trackLandmark( asset_id );
+ }
+}
+
+// virtual
+void LLLandmarkBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("teleport" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ teleport_via_landmark(item->getAssetUUID());
+ }
+ }
+ else if ("about" == action)
+ {
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLSD key;
+ key["type"] = "landmark";
+ key["id"] = item->getUUID();
+
+ LLSideTray::getInstance()->showPanel("panel_places", key);
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+static bool open_landmark_callback(const LLSD& notification, const LLSD& response)
+{
+ S32 option = LLNotification::getSelectedOption(notification, response);
+
+ LLUUID asset_id = notification["payload"]["asset_id"].asUUID();
+ if (option == 0)
+ {
+ teleport_via_landmark(asset_id);
+ }
+
+ return false;
+}
+static LLNotificationFunctorRegistration open_landmark_callback_reg("TeleportFromLandmark", open_landmark_callback);
+
+
+void LLLandmarkBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ // open_landmark(item);
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLCallingCardObserver |
+// +=================================================+
+void LLCallingCardObserver::changed(U32 mask)
+{
+ mBridgep->refreshFolderViewItem();
+}
+
+// +=================================================+
+// | LLCallingCardBridge |
+// +=================================================+
+
+LLCallingCardBridge::LLCallingCardBridge( LLInventoryPanel* inventory, const LLUUID& uuid ) :
+ LLItemBridge(inventory, uuid)
+{
+ mObserver = new LLCallingCardObserver(this);
+ LLAvatarTracker::instance().addObserver(mObserver);
+}
+
+LLCallingCardBridge::~LLCallingCardBridge()
+{
+ LLAvatarTracker::instance().removeObserver(mObserver);
+ delete mObserver;
+}
+
+void LLCallingCardBridge::refreshFolderViewItem()
+{
+ LLInventoryPanel* panel = dynamic_cast<LLInventoryPanel*>(mInventoryPanel.get());
+ LLFolderViewItem* itemp = panel ? panel->getRootFolder()->getItemByID(mUUID) : NULL;
+ if (itemp)
+ {
+ itemp->refresh();
+ }
+}
+
+// virtual
+void LLCallingCardBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("begin_im" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ std::string callingcard_name;
+ gCacheName->getFullName(item->getCreatorUUID(), callingcard_name);
+ LLUUID session_id = gIMMgr->addSession(callingcard_name, IM_NOTHING_SPECIAL, item->getCreatorUUID());
+ if (session_id != LLUUID::null)
+ {
+ LLIMFloater::show(session_id);
+ }
+ }
+ }
+ else if ("lure" == action)
+ {
+ LLViewerInventoryItem *item = getItem();
+ if (item && (item->getCreatorUUID() != gAgent.getID()) &&
+ (!item->getCreatorUUID().isNull()))
+ {
+ LLAvatarActions::offerTeleport(item->getCreatorUUID());
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+LLUIImagePtr LLCallingCardBridge::getIcon() const
+{
+ BOOL online = FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ online = LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID());
+ }
+ return get_item_icon(LLAssetType::AT_CALLINGCARD, LLInventoryType::IT_CALLINGCARD, online, FALSE);
+}
+
+std::string LLCallingCardBridge::getLabelSuffix() const
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item && LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (online)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void LLCallingCardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if(item && !item->getCreatorUUID().isNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+*/
+}
+
+void LLCallingCardBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLCallingCardBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLInventoryItem* item = getItem();
+ BOOL good_card = (item
+ && (LLUUID::null != item->getCreatorUUID())
+ && (item->getCreatorUUID() != gAgent.getID()));
+ BOOL user_online = (LLAvatarTracker::instance().isBuddyOnline(item->getCreatorUUID()));
+ items.push_back(std::string("Send Instant Message Separator"));
+ items.push_back(std::string("Send Instant Message"));
+ items.push_back(std::string("Offer Teleport..."));
+ items.push_back(std::string("Conference Chat"));
+
+ if (!good_card)
+ {
+ disabled_items.push_back(std::string("Send Instant Message"));
+ }
+ if (!good_card || !user_online)
+ {
+ disabled_items.push_back(std::string("Offer Teleport..."));
+ disabled_items.push_back(std::string("Conference Chat"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLCallingCardBridge::dragOrDrop(MASK mask, BOOL drop,
+ EDragAndDropType cargo_type,
+ void* cargo_data)
+{
+ LLViewerInventoryItem* item = getItem();
+ BOOL rv = FALSE;
+ if(item)
+ {
+ // check the type
+ switch(cargo_type)
+ {
+ case DAD_TEXTURE:
+ case DAD_SOUND:
+ case DAD_LANDMARK:
+ case DAD_SCRIPT:
+ case DAD_CLOTHING:
+ case DAD_OBJECT:
+ case DAD_NOTECARD:
+ case DAD_BODYPART:
+ case DAD_ANIMATION:
+ case DAD_GESTURE:
+ case DAD_MESH:
+ {
+ LLInventoryItem* inv_item = (LLInventoryItem*)cargo_data;
+ const LLPermissions& perm = inv_item->getPermissions();
+ if(gInventory.getItem(inv_item->getUUID())
+ && perm.allowOperationBy(PERM_TRANSFER, gAgent.getID()))
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventory(item->getCreatorUUID(),
+ (LLInventoryItem*)cargo_data);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ case DAD_CATEGORY:
+ {
+ LLInventoryCategory* inv_cat = (LLInventoryCategory*)cargo_data;
+ if( gInventory.getCategory( inv_cat->getUUID() ) )
+ {
+ rv = TRUE;
+ if(drop)
+ {
+ LLToolDragAndDrop::giveInventoryCategory(
+ item->getCreatorUUID(),
+ inv_cat);
+ }
+ }
+ else
+ {
+ // It's not in the user's inventory (it's probably in
+ // an object's contents), so disallow dragging it here.
+ // You can't give something you don't yet have.
+ rv = FALSE;
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return rv;
+}
+
+BOOL LLCallingCardBridge::removeItem()
+{
+ if (LLFriendCardsManager::instance().isItemInAnyFriendsList(getItem()))
+ {
+ LLAvatarActions::removeFriendDialog(getItem()->getCreatorUUID());
+ return FALSE;
+ }
+ else
+ {
+ return LLItemBridge::removeItem();
+ }
+}
+// +=================================================+
+// | LLNotecardBridge |
+// +=================================================+
+
+LLUIImagePtr LLNotecardBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_NOTECARD, LLInventoryType::IT_NOTECARD, 0, FALSE);
+}
+
+void LLNotecardBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+
+// +=================================================+
+// | LLGestureBridge |
+// +=================================================+
+
+LLUIImagePtr LLGestureBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_GESTURE, LLInventoryType::IT_GESTURE, 0, FALSE);
+}
+
+LLFontGL::StyleFlags LLGestureBridge::getLabelStyle() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLFontGL::BOLD;
+ }
+ else
+ {
+ return LLFontGL::NORMAL;
+ }
+}
+
+std::string LLGestureBridge::getLabelSuffix() const
+{
+ if( LLGestureManager::instance().isGestureActive(mUUID) )
+ {
+ return LLItemBridge::getLabelSuffix() + " (active)";
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+// virtual
+void LLGestureBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("activate" == action)
+ {
+ LLGestureManager::instance().activateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else if ("deactivate" == action)
+ {
+ LLGestureManager::instance().deactivateGesture(mUUID);
+
+ LLViewerInventoryItem* item = gInventory.getItem(mUUID);
+ if (!item) return;
+
+ // Since we just changed the suffix to indicate (active)
+ // the server doesn't need to know, just the viewer.
+ gInventory.updateItem(item);
+ gInventory.notifyObservers();
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLGestureBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+*/
+}
+
+BOOL LLGestureBridge::removeItem()
+{
+ // Force close the preview window, if it exists
+ LLGestureManager::instance().deactivateGesture(mUUID);
+ return LLItemBridge::removeItem();
+}
+
+void LLGestureBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLGestureBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Gesture Separator"));
+ items.push_back(std::string("Activate"));
+ items.push_back(std::string("Deactivate"));
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// +=================================================+
+// | LLAnimationBridge |
+// +=================================================+
+
+LLUIImagePtr LLAnimationBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_ANIMATION, LLInventoryType::IT_ANIMATION, 0, FALSE);
+}
+
+void LLAnimationBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ lldebugs << "LLAnimationBridge::buildContextMenu()" << llendl;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Animation Open"));
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+ items.push_back(std::string("Animation Separator"));
+ items.push_back(std::string("Animation Play"));
+ items.push_back(std::string("Animation Audition"));
+
+ hide_context_entries(menu, items, disabled_items);
+
+}
+
+// virtual
+void LLAnimationBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ((action == "playworld") || (action == "playlocal"))
+ {
+ if (getItem())
+ {
+ LLPreviewAnim::e_activation_type activate = LLPreviewAnim::NONE;
+ if ("playworld" == action) activate = LLPreviewAnim::PLAY;
+ if ("playlocal" == action) activate = LLPreviewAnim::AUDITION;
+
+ LLPreviewAnim* preview = LLFloaterReg::showTypedInstance<LLPreviewAnim>("preview_anim", LLSD(mUUID));
+ if (preview)
+ {
+ preview->activate(activate);
+ }
+ }
+ }
+ else
+ {
+ LLItemBridge::performAction(folder, model, action);
+ }
+}
+
+void LLAnimationBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+/*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+*/
+}
+
+// +=================================================+
+// | LLObjectBridge |
+// +=================================================+
+
+// static
+LLUUID LLObjectBridge::sContextMenuItemID;
+
+LLObjectBridge::LLObjectBridge(LLInventoryPanel* inventory, const LLUUID& uuid, LLInventoryType::EType type, U32 flags) :
+LLItemBridge(inventory, uuid), mInvType(type)
+{
+ mAttachPt = (flags & 0xff); // low bye of inventory flags
+
+ mIsMultiObject = ( flags & LLInventoryItem::II_FLAGS_OBJECT_HAS_MULTIPLE_ITEMS ) ? TRUE: FALSE;
+}
+
+BOOL LLObjectBridge::isItemRemovable()
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if(!avatar) return FALSE;
+ if(avatar->isWearingAttachment(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+LLUIImagePtr LLObjectBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_OBJECT, mInvType, mAttachPt, mIsMultiObject );
+}
+
+LLInventoryObject* LLObjectBridge::getObject() const
+{
+ LLInventoryObject* object = NULL;
+ LLInventoryModel* model = getInventoryModel();
+ if(model)
+ {
+ object = (LLInventoryObject*)model->getObject(mUUID);
+ }
+ return object;
+}
+
+// virtual
+void LLObjectBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("attach" == action)
+ {
+ LLUUID object_id = mUUID;
+ LLViewerInventoryItem* item;
+ item = (LLViewerInventoryItem*)gInventory.getItem(object_id);
+ if(item && gInventory.isObjectDescendentOf(object_id, gInventory.getRootFolderID()))
+ {
+ rez_attachment(item, NULL);
+ }
+ else if(item && item->isComplete())
+ {
+ // must be in library. copy it to our inventory and put it on.
+ LLPointer<LLInventoryCallback> cb = new RezAttachmentCallback(0);
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+ else if ("detach" == action)
+ {
+ LLInventoryItem* item = gInventory.getItem(mUUID);
+ if(item)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, item->getLinkedUUID());
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost());
+ }
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj =
+ gObjectList.findObject(item->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found - ignoring" << llendl;
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLObjectBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+
+ LLSD key;
+ key["id"] = mUUID;
+ LLSideTray::getInstance()->showPanel("sidepanel_inventory", key);
+
+ // Disable old properties floater; this is replaced by the sidepanel.
+ /*
+ LLFloaterReg::showInstance("properties", mUUID);
+ */
+}
+
+LLFontGL::StyleFlags LLObjectBridge::getLabelStyle() const
+{
+ U8 font = LLFontGL::NORMAL;
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ font |= LLFontGL::BOLD;
+ }
+
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ font |= LLFontGL::ITALIC;
+ }
+
+ return (LLFontGL::StyleFlags)font;
+}
+
+std::string LLObjectBridge::getLabelSuffix() const
+{
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar && avatar->isWearingAttachment( mUUID ) )
+ {
+ std::string attachment_point_name = avatar->getAttachedPointName(mUUID);
+ LLStringUtil::toLower(attachment_point_name);
+
+ LLStringUtil::format_map_t args;
+ args["[ATTACHMENT_POINT]"] = attachment_point_name.c_str();
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("WornOnAttachmentPoint", args);
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+void rez_attachment(LLViewerInventoryItem* item, LLViewerJointAttachment* attachment)
+{
+ LLSD payload;
+ payload["item_id"] = item->getLinkedUUID(); // Wear the base object in case this is a link.
+
+ S32 attach_pt = 0;
+ if (gAgent.getAvatarObject() && attachment)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = gAgent.getAvatarObject()->mAttachmentPoints.begin();
+ iter != gAgent.getAvatarObject()->mAttachmentPoints.end(); ++iter)
+ {
+ if (iter->second == attachment)
+ {
+ attach_pt = iter->first;
+ break;
+ }
+ }
+ }
+
+ payload["attachment_point"] = attach_pt;
+
+#if !ENABLE_MULTIATTACHMENTS
+ if (attachment && attachment->getNumObjects() > 0)
+ {
+ LLNotifications::instance().add("ReplaceAttachment", LLSD(), payload, confirm_replace_attachment_rez);
+ }
+ else
+#endif
+ {
+ LLNotifications::instance().forceResponse(LLNotification::Params("ReplaceAttachment").payload(payload), 0/*YES*/);
+ }
+}
+
+bool confirm_replace_attachment_rez(const LLSD& notification, const LLSD& response)
+{
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ LLSD args;
+ args["MAX_ATTACHMENTS"] = llformat("%d", MAX_AGENT_ATTACHMENTS);
+ LLNotifications::instance().add("MaxAttachmentsOnOutfit", args);
+ return false;
+ }
+
+ S32 option = LLNotification::getSelectedOption(notification, response);
+ if (option == 0/*YES*/)
+ {
+ LLViewerInventoryItem* itemp = gInventory.getItem(notification["payload"]["item_id"].asUUID());
+
+ if (itemp)
+ {
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezSingleAttachmentFromInv);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addUUIDFast(_PREHASH_ItemID, itemp->getUUID());
+ msg->addUUIDFast(_PREHASH_OwnerID, itemp->getPermissions().getOwner());
+ U8 attachment_pt = notification["payload"]["attachment_point"].asInteger();
+#if ENABLE_MULTIATTACHMENTS
+ attachment_pt |= ATTACHMENT_ADD;
+#endif
+ msg->addU8Fast(_PREHASH_AttachmentPt, attachment_pt);
+ pack_permissions_slam(msg, itemp->getFlags(), itemp->getPermissions());
+ msg->addStringFast(_PREHASH_Name, itemp->getName());
+ msg->addStringFast(_PREHASH_Description, itemp->getDescription());
+ msg->sendReliable(gAgent.getRegion()->getHost());
+ }
+ }
+ return false;
+}
+static LLNotificationFunctorRegistration confirm_replace_attachment_rez_reg("ReplaceAttachment", confirm_replace_attachment_rez);
+
+void LLObjectBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ LLInventoryItem* item = getItem();
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ LLObjectBridge::sContextMenuItemID = mUUID;
+
+ if(item)
+ {
+ LLVOAvatarSelf* avatarp = gAgent.getAvatarObject();
+ if( !avatarp )
+ {
+ return;
+ }
+
+ if( avatarp->isWearingAttachment( mUUID ) )
+ {
+ items.push_back(std::string("Detach From Yourself"));
+ }
+ else
+ if( !isInTrash() && !isLinkedObjectInTrash() )
+ {
+ items.push_back(std::string("Attach Separator"));
+ items.push_back(std::string("Object Wear"));
+ items.push_back(std::string("Attach To"));
+ items.push_back(std::string("Attach To HUD"));
+ // commented out for DEV-32347
+ //items.push_back(std::string("Restore to Last Position"));
+
+ if (!avatarp->canAttachMoreObjects())
+ {
+ disabled_items.push_back(std::string("Object Wear"));
+ disabled_items.push_back(std::string("Attach To"));
+ disabled_items.push_back(std::string("Attach To HUD"));
+ }
+ LLMenuGL* attach_menu = menu.findChildMenuByName("Attach To", TRUE);
+ LLMenuGL* attach_hud_menu = menu.findChildMenuByName("Attach To HUD", TRUE);
+ LLVOAvatar *avatarp = gAgent.getAvatarObject();
+ if (attach_menu
+ && (attach_menu->getChildCount() == 0)
+ && attach_hud_menu
+ && (attach_hud_menu->getChildCount() == 0)
+ && avatarp)
+ {
+ for (LLVOAvatar::attachment_map_t::iterator iter = avatarp->mAttachmentPoints.begin();
+ iter != avatarp->mAttachmentPoints.end(); )
+ {
+ LLVOAvatar::attachment_map_t::iterator curiter = iter++;
+ LLViewerJointAttachment* attachment = curiter->second;
+ LLMenuItemCallGL::Params p;
+ std::string submenu_name = attachment->getName();
+ if (LLTrans::getString(submenu_name) != "")
+ {
+ p.name = (" ")+LLTrans::getString(submenu_name)+" ";
+ }
+ else
+ {
+ p.name = submenu_name;
+ }
+ LLSD cbparams;
+ cbparams["index"] = curiter->first;
+ cbparams["label"] = attachment->getName();
+ p.on_click.function_name = "Inventory.AttachObject";
+ p.on_click.parameter = LLSD(attachment->getName());
+ p.on_enable.function_name = "Attachment.Label";
+ p.on_enable.parameter = cbparams;
+ LLView* parent = attachment->getIsHUDAttachment() ? attach_hud_menu : attach_menu;
+ LLUICtrlFactory::create<LLMenuItemCallGL>(p, parent);
+ }
+ }
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+BOOL LLObjectBridge::renameItem(const std::string& new_name)
+{
+ if(!isItemRenameable())
+ return FALSE;
+ LLPreview::dirty(mUUID);
+ LLInventoryModel* model = getInventoryModel();
+ if(!model)
+ return FALSE;
+ LLViewerInventoryItem* item = getItem();
+ if(item && (item->getName() != new_name))
+ {
+ LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
+ new_item->rename(new_name);
+ buildDisplayName(new_item, mDisplayName);
+ new_item->updateServer(FALSE);
+ model->updateItem(new_item);
+
+ model->notifyObservers();
+
+ LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
+ if( avatar )
+ {
+ LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
+ if( obj )
+ {
+ LLSelectMgr::getInstance()->deselectAll();
+ LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
+ LLSelectMgr::getInstance()->selectionSetObjectName( new_name );
+ LLSelectMgr::getInstance()->deselectAll();
+ }
+ }
+ }
+ // return FALSE because we either notified observers (& therefore
+ // rebuilt) or we didn't update.
+ return FALSE;
+}
+
+// +=================================================+
+// | LLLSLTextBridge |
+// +=================================================+
+
+LLUIImagePtr LLLSLTextBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_SCRIPT, LLInventoryType::IT_LSL, 0, FALSE);
+}
+
+void LLLSLTextBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+ */
+}
+
+// +=================================================+
+// | LLWearableBridge |
+// +=================================================+
+
+// *NOTE: hack to get from avatar inventory to avatar
+void wear_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLAppearanceManager::wearItem(item);
+ }
+}
+
+void wear_add_inventory_item_on_avatar( LLInventoryItem* item )
+{
+ if(item)
+ {
+ lldebugs << "wear_add_inventory_item_on_avatar( " << item->getName()
+ << " )" << llendl;
+
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onWearAddOnAvatarArrived,
+ new LLUUID(item->getUUID()));
+ }
+}
+
+void remove_inventory_category_from_avatar( LLInventoryCategory* category )
+{
+ if(!category) return;
+ lldebugs << "remove_inventory_category_from_avatar( " << category->getName()
+ << " )" << llendl;
+
+
+ if( gFloaterCustomize )
+ {
+ gFloaterCustomize->askToSaveIfDirty(
+ boost::bind(remove_inventory_category_from_avatar_step2, _1, category->getUUID()));
+ }
+ else
+ {
+ remove_inventory_category_from_avatar_step2(TRUE, category->getUUID() );
+ }
+}
+
+struct OnRemoveStruct
+{
+ LLUUID mUUID;
+ OnRemoveStruct(const LLUUID& uuid):
+ mUUID(uuid)
+ {
+ }
+};
+
+void remove_inventory_category_from_avatar_step2( BOOL proceed, LLUUID category_id)
+{
+
+ // Find all the wearables that are in the category's subtree.
+ lldebugs << "remove_inventory_category_from_avatar_step2()" << llendl;
+ if(proceed)
+ {
+ LLInventoryModel::cat_array_t cat_array;
+ LLInventoryModel::item_array_t item_array;
+ LLFindWearables is_wearable;
+ gInventory.collectDescendentsIf(category_id,
+ cat_array,
+ item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_wearable);
+ S32 i;
+ S32 wearable_count = item_array.count();
+
+ LLInventoryModel::cat_array_t obj_cat_array;
+ LLInventoryModel::item_array_t obj_item_array;
+ LLIsType is_object( LLAssetType::AT_OBJECT );
+ gInventory.collectDescendentsIf(category_id,
+ obj_cat_array,
+ obj_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_object);
+ S32 obj_count = obj_item_array.count();
+
+ // Find all gestures in this folder
+ LLInventoryModel::cat_array_t gest_cat_array;
+ LLInventoryModel::item_array_t gest_item_array;
+ LLIsType is_gesture( LLAssetType::AT_GESTURE );
+ gInventory.collectDescendentsIf(category_id,
+ gest_cat_array,
+ gest_item_array,
+ LLInventoryModel::EXCLUDE_TRASH,
+ is_gesture);
+ S32 gest_count = gest_item_array.count();
+
+ if (wearable_count > 0) //Loop through wearables. If worn, remove.
+ {
+ for(i = 0; i < wearable_count; ++i)
+ {
+ if( gAgentWearables.isWearingItem (item_array.get(i)->getUUID()) )
+ {
+ LLWearableList::instance().getAsset(item_array.get(i)->getAssetUUID(),
+ item_array.get(i)->getName(),
+ item_array.get(i)->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(item_array.get(i)->getUUID()));
+
+ }
+ }
+ }
+
+
+ if (obj_count > 0)
+ {
+ for(i = 0; i < obj_count; ++i)
+ {
+ gMessageSystem->newMessageFast(_PREHASH_DetachAttachmentIntoInv);
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData );
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_ItemID, obj_item_array.get(i)->getUUID() );
+
+ gMessageSystem->sendReliable( gAgent.getRegion()->getHost() );
+
+ // this object might have been selected, so let the selection manager know it's gone now
+ LLViewerObject *found_obj = gObjectList.findObject( obj_item_array.get(i)->getUUID());
+ if (found_obj)
+ {
+ LLSelectMgr::getInstance()->remove(found_obj);
+ }
+ else
+ {
+ llwarns << "object not found, ignoring" << llendl;
+ }
+ }
+ }
+
+ if (gest_count > 0)
+ {
+ for(i = 0; i < gest_count; ++i)
+ {
+ if ( LLGestureManager::instance().isGestureActive( gest_item_array.get(i)->getUUID()) )
+ {
+ LLGestureManager::instance().deactivateGesture( gest_item_array.get(i)->getUUID() );
+ gInventory.updateItem( gest_item_array.get(i) );
+ gInventory.notifyObservers();
+ }
+
+ }
+ }
+ }
+}
+
+BOOL LLWearableBridge::renameItem(const std::string& new_name)
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ gAgentWearables.setWearableName( mUUID, new_name );
+ }
+ return LLItemBridge::renameItem(new_name);
+}
+
+BOOL LLWearableBridge::isItemRemovable()
+{
+ if (gAgentWearables.isWearingItem(mUUID)) return FALSE;
+ return LLInvFVBridge::isItemRemovable();
+}
+
+std::string LLWearableBridge::getLabelSuffix() const
+{
+ if( gAgentWearables.isWearingItem( mUUID ) )
+ {
+ return LLItemBridge::getLabelSuffix() + LLTrans::getString("worn");
+ }
+ else
+ {
+ return LLItemBridge::getLabelSuffix();
+ }
+}
+
+LLUIImagePtr LLWearableBridge::getIcon() const
+{
+ return get_item_icon(mAssetType, mInvType, mWearableType, FALSE);
+}
+
+// virtual
+void LLWearableBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("wear" == action)
+ {
+ wearOnAvatar();
+ }
+ else if ("wear_add" == action)
+ {
+ wearAddOnAvatar();
+ }
+ else if ("edit" == action)
+ {
+ editOnAvatar();
+ return;
+ }
+ else if ("take_off" == action)
+ {
+ if(gAgentWearables.isWearingItem(mUUID))
+ {
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ LLWearableBridge::onRemoveFromAvatarArrived,
+ new OnRemoveStruct(mUUID));
+ }
+ }
+ }
+ else LLItemBridge::performAction(folder, model, action);
+}
+
+void LLWearableBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ LLInvFVBridgeAction::doAction(item->getType(),mUUID,getInventoryModel());
+ }
+ /*
+ if( isInTrash() )
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if( !gAgentWearables.isWearingItem( mUUID ) )
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+ */
+}
+
+void LLWearableBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLWearableBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ { // FWIW, it looks like SUPPRESS_OPEN_ITEM is not set anywhere
+ BOOL no_open = ((flags & SUPPRESS_OPEN_ITEM) == SUPPRESS_OPEN_ITEM);
+
+ // If we have clothing, don't add "Open" as it's the same action as "Wear" SL-18976
+ LLViewerInventoryItem* item = getItem();
+ if( !no_open && item )
+ {
+ no_open = (item->getType() == LLAssetType::AT_CLOTHING) ||
+ (item->getType() == LLAssetType::AT_BODYPART);
+ }
+ if (!no_open)
+ {
+ items.push_back(std::string("Open"));
+ }
+
+ if (item && item->getIsLinkType())
+ {
+ items.push_back(std::string("Goto Link"));
+ }
+
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+
+ items.push_back(std::string("Wearable Separator"));
+
+ items.push_back(std::string("Wearable Wear"));
+ items.push_back(std::string("Wearable Add"));
+ items.push_back(std::string("Wearable Edit"));
+
+ if ((flags & FIRST_SELECTED_ITEM) == 0)
+ {
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+ // Don't allow items to be worn if their baseobj is in the trash.
+ if (isLinkedObjectInTrash())
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ disabled_items.push_back(std::string("Wearable Edit"));
+ }
+
+ // Disable wear and take off based on whether the item is worn.
+ if(item)
+ {
+ switch (item->getType())
+ {
+ case LLAssetType::AT_CLOTHING:
+ items.push_back(std::string("Take Off"));
+ case LLAssetType::AT_BODYPART:
+ if (gAgentWearables.isWearingItem(item->getUUID()))
+ {
+ disabled_items.push_back(std::string("Wearable Wear"));
+ disabled_items.push_back(std::string("Wearable Add"));
+ }
+ else
+ {
+ disabled_items.push_back(std::string("Take Off"));
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+// Called from menus
+// static
+BOOL LLWearableBridge::canWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+ if(!self->isAgentInventory())
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)self->getItem();
+ if(!item || !item->isComplete()) return FALSE;
+ }
+ return (!gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// Called from menus
+// static
+void LLWearableBridge::onWearOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ self->wearOnAvatar();
+}
+
+void LLWearableBridge::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+void LLWearableBridge::wearAddOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_add_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onWearOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ gAgentWearables.setWearableItem(item, wearable);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+// BAP remove the "add" code path once everything is fully COF-ified.
+void LLWearableBridge::onWearAddOnAvatarArrived( LLWearable* wearable, void* userdata )
+{
+ LLUUID* item_id = (LLUUID*) userdata;
+ if(wearable)
+ {
+ LLViewerInventoryItem* item = NULL;
+ item = (LLViewerInventoryItem*)gInventory.getItem(*item_id);
+ if(item)
+ {
+ if(item->getAssetUUID() == wearable->getAssetID())
+ {
+ bool do_append = true;
+ gAgentWearables.setWearableItem(item, wearable, do_append);
+ gInventory.notifyObservers();
+ //self->getFolderItem()->refreshFromRoot();
+ }
+ else
+ {
+ llinfos << "By the time wearable asset arrived, its inv item already pointed to a different asset." << llendl;
+ }
+ }
+ }
+ delete item_id;
+}
+
+// static
+BOOL LLWearableBridge::canEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return FALSE;
+
+ return (gAgentWearables.isWearingItem(self->mUUID));
+}
+
+// static
+void LLWearableBridge::onEditOnAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(self)
+ {
+ self->editOnAvatar();
+ }
+}
+
+void LLWearableBridge::editOnAvatar()
+{
+ const LLWearable* wearable = gAgentWearables.getWearableFromItemID(mUUID);
+ if( wearable )
+ {
+ // Set the tab to the right wearable.
+ if (gFloaterCustomize)
+ gFloaterCustomize->setCurrentWearableType( wearable->getType() );
+
+ if( CAMERA_MODE_CUSTOMIZE_AVATAR != gAgent.getCameraMode() )
+ {
+ // Start Avatar Customization
+ gAgent.changeCameraToCustomizeAvatar();
+ }
+ }
+}
+
+// static
+BOOL LLWearableBridge::canRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if( self && (LLAssetType::AT_BODYPART != self->mAssetType) )
+ {
+ return gAgentWearables.isWearingItem( self->mUUID );
+ }
+ return FALSE;
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatar(void* user_data)
+{
+ LLWearableBridge* self = (LLWearableBridge*)user_data;
+ if(!self) return;
+ if(gAgentWearables.isWearingItem(self->mUUID))
+ {
+ LLViewerInventoryItem* item = self->getItem();
+ if (item)
+ {
+ LLUUID parent_id = item->getParentUUID();
+ LLWearableList::instance().getAsset(item->getAssetUUID(),
+ item->getName(),
+ item->getType(),
+ onRemoveFromAvatarArrived,
+ new OnRemoveStruct(LLUUID(self->mUUID)));
+ }
+ }
+}
+
+// static
+void LLWearableBridge::onRemoveFromAvatarArrived(LLWearable* wearable,
+ void* userdata)
+{
+ OnRemoveStruct *on_remove_struct = (OnRemoveStruct*) userdata;
+ const LLUUID &item_id = gInventory.getLinkedItemID(on_remove_struct->mUUID);
+ if(wearable)
+ {
+ if( gAgentWearables.isWearingItem( item_id ) )
+ {
+ EWearableType type = wearable->getType();
+
+ if( !(type==WT_SHAPE || type==WT_SKIN || type==WT_HAIR || type==WT_EYES ) ) //&&
+ //!((!gAgent.isTeen()) && ( type==WT_UNDERPANTS || type==WT_UNDERSHIRT )) )
+ {
+ // MULTI_WEARABLE: FIXME HACK - always remove all
+ bool do_remove_all = false;
+ gAgentWearables.removeWearable( type, do_remove_all, 0 );
+ }
+ }
+ }
+
+ // Find and remove this item from the COF.
+ LLInventoryModel::item_array_t items = gInventory.collectLinkedItems(item_id, LLAppearanceManager::getCOF());
+ llassert(items.size() == 1); // Should always have one and only one item linked to this in the COF.
+ for (LLInventoryModel::item_array_t::const_iterator iter = items.begin();
+ iter != items.end();
+ ++iter)
+ {
+ const LLViewerInventoryItem *linked_item = (*iter);
+ const LLUUID &item_id = linked_item->getUUID();
+ gInventory.purgeObject(item_id);
+ }
+ gInventory.notifyObservers();
+
+ delete on_remove_struct;
+}
+
+
+// +=================================================+
+// | LLMeshBridge |
+// +=================================================+
+
+LLUIImagePtr LLMeshBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
+}
+
+void LLMeshBridge::openItem()
+{
+ LLViewerInventoryItem* item = getItem();
+
+ if (item)
+ {
+ // open mesh
+ }
+}
+
+void LLMeshBridge::previewItem()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ // preview mesh
+ }
+}
+
+
+void LLMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ lldebugs << "LLMeshBridge::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Properties"));
+
+ getClipboardEntries(true, items, disabled_items, flags);
+ }
+
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+
+LLInvFVBridgeAction* LLInvFVBridgeAction::createAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = NULL;
+ switch(asset_type)
+ {
+ case LLAssetType::AT_TEXTURE:
+ action = new LLTextureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_SOUND:
+ action = new LLSoundBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LANDMARK:
+ action = new LLLandmarkBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CALLINGCARD:
+ action = new LLCallingCardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_OBJECT:
+ action = new LLObjectBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_NOTECARD:
+ action = new LLNotecardBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_ANIMATION:
+ action = new LLAnimationBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_GESTURE:
+ action = new LLGestureBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_LSL_TEXT:
+ action = new LLLSLTextBridgeAction(uuid,model);
+ break;
+
+ case LLAssetType::AT_CLOTHING:
+ case LLAssetType::AT_BODYPART:
+ action = new LLWearableBridgeAction(uuid,model);
+
+ break;
+
+ case LLAssetType::AT_MESH:
+ action = new LLMeshBridgeAction(uuid,model);
+ break;
+
+
+
+ default:
+ break;
+ }
+ return action;
+}
+
+//static
+void LLInvFVBridgeAction::doAction(LLAssetType::EType asset_type,
+ const LLUUID& uuid,LLInventoryModel* model)
+{
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+//static
+void LLInvFVBridgeAction::doAction(const LLUUID& uuid, LLInventoryModel* model)
+{
+ LLAssetType::EType asset_type = model->getItem(uuid)->getType();
+ LLInvFVBridgeAction* action = createAction(asset_type,uuid,model);
+ if(action)
+ {
+ action->doIt();
+ delete action;
+ }
+}
+
+LLViewerInventoryItem* LLInvFVBridgeAction::getItem() const
+{
+ if(mModel)
+ return (LLViewerInventoryItem*)mModel->getItem(mUUID);
+ return NULL;
+}
+
+//virtual
+void LLTextureBridgeAction::doIt()
+{
+ if (getItem())
+ {
+ LLFloaterReg::showInstance("preview_texture", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLSoundBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ LLFloaterReg::showInstance("preview_sound", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLandmarkBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if( item )
+ {
+ // Opening (double-clicking) a landmark immediately teleports,
+ // but warns you the first time.
+ LLSD payload;
+ payload["asset_id"] = item->getAssetUUID();
+ LLNotifications::instance().add("TeleportFromLandmark", LLSD(), payload);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLCallingCardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->getCreatorUUID().notNull())
+ {
+ LLAvatarActions::showProfile(item->getCreatorUUID());
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void
+LLNotecardBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_notecard", LLSD(item->getUUID()), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLGestureBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLPreviewGesture* preview = LLPreviewGesture::show(mUUID, LLUUID::null);
+ preview->setFocus(TRUE);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLAnimationBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_anim", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLObjectBridgeAction::doIt()
+{
+ LLFloaterReg::showInstance("properties", mUUID);
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+//virtual
+void LLLSLTextBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if (item)
+ {
+ LLFloaterReg::showInstance("preview_script", LLSD(mUUID), TAKE_FOCUS_YES);
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+
+BOOL LLWearableBridgeAction::isInTrash() const
+{
+ if(!mModel) return FALSE;
+ const LLUUID trash_id = mModel->findCategoryUUIDForType(LLFolderType::FT_TRASH);
+ return mModel->isObjectDescendentOf(mUUID, trash_id);
+}
+
+BOOL LLWearableBridgeAction::isAgentInventory() const
+{
+ if(!mModel) return FALSE;
+ if(gInventory.getRootFolderID() == mUUID) return TRUE;
+ return mModel->isObjectDescendentOf(mUUID, gInventory.getRootFolderID());
+}
+
+void LLWearableBridgeAction::wearOnAvatar()
+{
+ // Don't wear anything until initial wearables are loaded, can
+ // destroy clothing items.
+ if (!gAgentWearables.areWearablesLoaded())
+ {
+ LLNotifications::instance().add("CanNotChangeAppearanceUntilLoaded");
+ return;
+ }
+
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ if(!isAgentInventory())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else
+ {
+ wear_inventory_item_on_avatar(item);
+ }
+ }
+}
+
+//virtual
+void LLWearableBridgeAction::doIt()
+{
+ if(isInTrash())
+ {
+ LLNotifications::instance().add("CannotWearTrash");
+ }
+ else if(isAgentInventory())
+ {
+ if(!gAgentWearables.isWearingItem(mUUID))
+ {
+ wearOnAvatar();
+ }
+ }
+ else
+ {
+ // must be in the inventory library. copy it to our inventory
+ // and put it on right away.
+ LLViewerInventoryItem* item = getItem();
+ if(item && item->isComplete())
+ {
+ LLPointer<LLInventoryCallback> cb = new WearOnAvatarCallback();
+ copy_inventory_item(
+ gAgent.getID(),
+ item->getPermissions().getOwner(),
+ item->getUUID(),
+ LLUUID::null,
+ std::string(),
+ cb);
+ }
+ else if(item)
+ {
+ // *TODO: We should fetch the item details, and then do
+ // the operation above.
+ LLNotifications::instance().add("CannotWearInfoNotComplete");
+ }
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+//virtual
+void LLMeshBridgeAction::doIt()
+{
+ LLViewerInventoryItem* item = getItem();
+ if(item)
+ {
+ // do it
+ }
+
+ LLInvFVBridgeAction::doIt();
+}
+
+// +=================================================+
+// | LLLinkItemBridge |
+// +=================================================+
+// For broken links
+
+std::string LLLinkItemBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkItemBridge::getIcon() const
+{
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ return get_item_icon(item->getActualType(), LLInventoryType::IT_NONE, 0, FALSE);
+ }
+ return get_item_icon(LLAssetType::AT_LINK, LLInventoryType::IT_NONE, 0, FALSE);
+}
+
+void LLLinkItemBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+
+// +=================================================+
+// | LLLinkBridge |
+// +=================================================+
+// For broken links.
+
+std::string LLLinkFolderBridge::sPrefix("Link: ");
+
+
+LLUIImagePtr LLLinkFolderBridge::getIcon() const
+{
+ LLFolderType::EType preferred_type = LLFolderType::FT_NONE;
+ if (LLViewerInventoryItem *item = getItem())
+ {
+ if (const LLViewerInventoryCategory* cat = item->getLinkedCategory())
+ {
+ preferred_type = cat->getPreferredType();
+ }
+ }
+ return LLFolderBridge::getIcon(preferred_type);
+}
+
+void LLLinkFolderBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ // *TODO: Translate
+ lldebugs << "LLLink::buildContextMenu()" << llendl;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(isInTrash())
+ {
+ items.push_back(std::string("Purge Item"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Purge Item"));
+ }
+
+ items.push_back(std::string("Restore Item"));
+ }
+ else
+ {
+ items.push_back(std::string("Goto Link"));
+ items.push_back(std::string("Delete"));
+ if (!isItemRemovable())
+ {
+ disabled_items.push_back(std::string("Delete"));
+ }
+ }
+ hide_context_entries(menu, items, disabled_items);
+}
+
+void LLLinkFolderBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if ("goto" == action)
+ {
+ gotoItem(folder);
+ return;
+ }
+ LLItemBridge::performAction(folder,model,action);
+}
+
+void LLLinkFolderBridge::gotoItem(LLFolderView *folder)
+{
+ const LLUUID &cat_uuid = getFolderID();
+ if (!cat_uuid.isNull())
+ {
+ if (LLFolderViewItem *base_folder = folder->getItemByID(cat_uuid))
+ {
+ if (LLInventoryModel* model = getInventoryModel())
+ {
+ model->fetchDescendentsOf(cat_uuid);
+ }
+ base_folder->setOpen(TRUE);
+ folder->setSelectionFromRoot(base_folder,TRUE);
+ folder->scrollToShowSelection();
+ }
+ }
+}
+
+const LLUUID &LLLinkFolderBridge::getFolderID() const
+{
+ if (LLViewerInventoryItem *link_item = getItem())
+ {
+ if (const LLViewerInventoryCategory *cat = link_item->getLinkedCategory())
+ {
+ const LLUUID& cat_uuid = cat->getUUID();
+ return cat_uuid;
+ }
+ }
+ return LLUUID::null;
+}
diff --git a/indra/newview/llinventorybridge.h b/indra/newview/llinventorybridge.h
index 3ffeb55d6c..f9bd91f141 100644
--- a/indra/newview/llinventorybridge.h
+++ b/indra/newview/llinventorybridge.h
@@ -80,6 +80,8 @@ enum EInventoryIcon
LINKITEM_ICON_NAME,
LINKFOLDER_ICON_NAME,
+
+ MESH_ICON_NAME,
ICON_NAME_COUNT
};
@@ -612,7 +614,6 @@ protected:
static std::string sPrefix;
};
-
class LLLinkFolderBridge : public LLItemBridge
{
friend class LLInvFVBridge;
@@ -633,6 +634,25 @@ protected:
static std::string sPrefix;
};
+
+
+class LLMeshBridge : public LLItemBridge
+{
+ friend class LLInvFVBridge;
+public:
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual void previewItem();
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+
+protected:
+ LLMeshBridge(LLInventoryPanel* inventory, const LLUUID& uuid) :
+ LLItemBridge(inventory, uuid) {}
+};
+
+
+
+
//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
// Class LLInvFVBridgeAction (& its derived classes)
//
@@ -793,6 +813,19 @@ protected:
};
+class LLMeshBridgeAction: public LLInvFVBridgeAction
+{
+ friend class LLInvFVBridgeAction;
+public:
+ virtual void doIt() ;
+ virtual ~LLMeshBridgeAction(){}
+protected:
+ LLMeshBridgeAction(const LLUUID& id,LLInventoryModel* model):LLInvFVBridgeAction(id,model){}
+
+};
+
+
+
void wear_inventory_item_on_avatar(LLInventoryItem* item);
class LLViewerJointAttachment;
diff --git a/indra/newview/llpanelgroupnotices.cpp b/indra/newview/llpanelgroupnotices.cpp
index 22138a81ec..4b205b4e0c 100644
--- a/indra/newview/llpanelgroupnotices.cpp
+++ b/indra/newview/llpanelgroupnotices.cpp
@@ -158,6 +158,7 @@ BOOL LLGroupDropTarget::handleDragAndDrop(S32 x, S32 y, MASK mask, BOOL drop,
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_CALLINGCARD:
+ case DAD_MESH:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llpanelobjectinventory.cpp b/indra/newview/llpanelobjectinventory.cpp
index a5e9407a41..90c511a007 100644
--- a/indra/newview/llpanelobjectinventory.cpp
+++ b/indra/newview/llpanelobjectinventory.cpp
@@ -816,6 +816,7 @@ BOOL LLTaskCategoryBridge::dragOrDrop(MASK mask, BOOL drop,
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_CALLINGCARD:
+ case DAD_MESH:
accept = LLToolDragAndDrop::isInventoryDropAcceptable(object, (LLViewerInventoryItem*)cargo_data);
if(accept && drop)
{
@@ -1392,6 +1393,117 @@ LLUIImagePtr LLTaskWearableBridge::getIcon() const
return get_item_icon(mAssetType, LLInventoryType::IT_WEARABLE, mFlags, FALSE );
}
+///----------------------------------------------------------------------------
+/// Class LLTaskMeshBridge
+///----------------------------------------------------------------------------
+
+class LLTaskMeshBridge : public LLTaskInvFVBridge
+{
+public:
+ LLTaskMeshBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name);
+
+ virtual LLUIImagePtr getIcon() const;
+ virtual void openItem();
+ virtual void performAction(LLFolderView* folder, LLInventoryModel* model, std::string action);
+ virtual void buildContextMenu(LLMenuGL& menu, U32 flags);
+};
+
+LLTaskMeshBridge::LLTaskMeshBridge(
+ LLPanelObjectInventory* panel,
+ const LLUUID& uuid,
+ const std::string& name) :
+ LLTaskInvFVBridge(panel, uuid, name)
+{
+}
+
+LLUIImagePtr LLTaskMeshBridge::getIcon() const
+{
+ return get_item_icon(LLAssetType::AT_MESH, LLInventoryType::IT_MESH, 0, FALSE);
+}
+
+void LLTaskMeshBridge::openItem()
+{
+ // open mesh
+}
+
+
+// virtual
+void LLTaskMeshBridge::performAction(LLFolderView* folder, LLInventoryModel* model, std::string action)
+{
+ if (action == "mesh action")
+ {
+ LLInventoryItem* item = findItem();
+ if(item)
+ {
+ // do action
+ }
+ }
+ LLTaskInvFVBridge::performAction(folder, model, action);
+}
+
+void LLTaskMeshBridge::buildContextMenu(LLMenuGL& menu, U32 flags)
+{
+ LLInventoryItem* item = findItem();
+ if(!item) return;
+ std::vector<std::string> items;
+ std::vector<std::string> disabled_items;
+
+ if(item->getPermissions().getOwner() != gAgent.getID()
+ && item->getSaleInfo().isForSale())
+ {
+ items.push_back(std::string("Task Buy"));
+
+ std::string label= LLTrans::getString("Buy");
+ // Check the price of the item.
+ S32 price = getPrice();
+ if (-1 == price)
+ {
+ llwarns << "label_buy_task_bridged_item: Invalid price" << llendl;
+ }
+ else
+ {
+ std::ostringstream info;
+ info << LLTrans::getString("BuyforL$") << price;
+ label.assign(info.str());
+ }
+
+ const LLView::child_list_t *list = menu.getChildList();
+ LLView::child_list_t::const_iterator itor;
+ for (itor = list->begin(); itor != list->end(); ++itor)
+ {
+ std::string name = (*itor)->getName();
+ LLMenuItemCallGL* menu_itemp = dynamic_cast<LLMenuItemCallGL*>(*itor);
+ if (name == "Task Buy" && menu_itemp)
+ {
+ menu_itemp->setLabel(label);
+ }
+ }
+ }
+ else
+ {
+ items.push_back(std::string("Task Open"));
+ if (!isItemCopyable())
+ {
+ disabled_items.push_back(std::string("Task Open"));
+ }
+ }
+ items.push_back(std::string("Task Properties"));
+ if(isItemRenameable())
+ {
+ items.push_back(std::string("Task Rename"));
+ }
+ if(isItemRemovable())
+ {
+ items.push_back(std::string("Task Remove"));
+ }
+
+
+ hide_context_entries(menu, items, disabled_items);
+}
+
///----------------------------------------------------------------------------
/// LLTaskInvFVBridge impl
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index 4cb561381d..e0e4dcb45d 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -174,7 +174,6 @@ LLObjectSelection *get_null_object_selection()
return sNullSelection;
}
-
//-----------------------------------------------------------------------------
// LLSelectMgr()
//-----------------------------------------------------------------------------
@@ -5318,6 +5317,78 @@ BOOL LLSelectNode::allowOperationOnNode(PermissionBit op, U64 group_proxy_power)
return (mPermissions->allowOperationBy(op, proxy_agent_id, group_id));
}
+void LLSelectNode::renderOneWireframe(const LLColor4& color)
+{
+ LLViewerObject* objectp = getObject();
+ if (!objectp)
+ {
+ return;
+ }
+
+ LLDrawable* drawable = objectp->mDrawable;
+ if(!drawable)
+ {
+ return;
+ }
+
+ glMatrixMode(GL_MODELVIEW);
+ gGL.pushMatrix();
+
+ BOOL is_hud_object = objectp->isHUDAttachment();
+
+ if (!is_hud_object)
+ {
+ glLoadIdentity();
+ glMultMatrixd(gGLModelView);
+ }
+
+ if (drawable->isActive())
+ {
+ glMultMatrixf((F32*) objectp->getRenderMatrix().mMatrix);
+ }
+
+ glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
+
+ if (LLSelectMgr::sRenderHiddenSelections) // && gFloaterTools && gFloaterTools->getVisible())
+ {
+ gGL.blendFunc(LLRender::BF_SOURCE_COLOR, LLRender::BF_ONE);
+ LLGLEnable fog(GL_FOG);
+ glFogi(GL_FOG_MODE, GL_LINEAR);
+ float d = (LLViewerCamera::getInstance()->getPointOfInterest()-LLViewerCamera::getInstance()->getOrigin()).magVec();
+ LLColor4 fogCol = color * (F32)llclamp((LLSelectMgr::getInstance()->getSelectionCenterGlobal()-gAgent.getCameraPositionGlobal()).magVec()/(LLSelectMgr::getInstance()->getBBoxOfSelection().getExtentLocal().magVec()*4), 0.0, 1.0);
+ glFogf(GL_FOG_START, d);
+ glFogf(GL_FOG_END, d*(1 + (LLViewerCamera::getInstance()->getView() / LLViewerCamera::getInstance()->getDefaultFOV())));
+ glFogfv(GL_FOG_COLOR, fogCol.mV);
+
+ LLGLDepthTest gls_depth(GL_TRUE, GL_FALSE, GL_GEQUAL);
+ gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT);
+ {
+ glColor4f(color.mV[VRED], color.mV[VGREEN], color.mV[VBLUE], 0.4f);
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ pushVerts(face, LLVertexBuffer::MAP_VERTEX);
+ }
+ }
+ }
+
+ gGL.flush();
+ gGL.setSceneBlendType(LLRender::BT_ALPHA);
+
+ glColor4f(color.mV[VRED]*2, color.mV[VGREEN]*2, color.mV[VBLUE]*2, LLSelectMgr::sHighlightAlpha*2);
+ LLGLEnable offset(GL_POLYGON_OFFSET_LINE);
+ glPolygonOffset(3.f, 2.f);
+ glLineWidth(3.f);
+ for (S32 i = 0; i < drawable->getNumFaces(); ++i)
+ {
+ LLFace* face = drawable->getFace(i);
+ pushVerts(face, LLVertexBuffer::MAP_VERTEX);
+ }
+ glLineWidth(1.f);
+ glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
+ gGL.popMatrix();
+}
+
//-----------------------------------------------------------------------------
// renderOneSilhouette()
//-----------------------------------------------------------------------------
@@ -5335,6 +5406,13 @@ void LLSelectNode::renderOneSilhouette(const LLColor4 &color)
return;
}
+ LLVOVolume* vobj = drawable->getVOVolume();
+ if (vobj && vobj->isMesh())
+ {
+ renderOneWireframe(color);
+ return;
+ }
+
if (!mSilhouetteExists)
{
return;
diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h
index 2050a73f26..73bd7b805d 100644
--- a/indra/newview/llselectmgr.h
+++ b/indra/newview/llselectmgr.h
@@ -140,6 +140,7 @@ public:
BOOL isTESelected(S32 te_index);
S32 getLastSelectedTE();
S32 getTESelectMask() { return mTESelectMask; }
+ void renderOneWireframe(const LLColor4& color);
void renderOneSilhouette(const LLColor4 &color);
void setTransient(BOOL transient) { mTransient = transient; }
BOOL isTransient() { return mTransient; }
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index 8c5439d47e..880e690e53 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2294,7 +2294,6 @@ void pushVerts(LLFace* face, U32 mask)
U16 offset = face->getIndicesStart();
buffer->drawRange(LLRender::TRIANGLES, start, end, count, offset);
}
-
}
void pushBufferVerts(LLVertexBuffer* buffer, U32 mask)
diff --git a/indra/newview/llspatialpartition.h b/indra/newview/llspatialpartition.h
index 64c2a9acbc..1d9127639a 100644
--- a/indra/newview/llspatialpartition.h
+++ b/indra/newview/llspatialpartition.h
@@ -59,6 +59,7 @@ class LLTextureAtlasSlot;
S32 AABBSphereIntersect(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &rad);
S32 AABBSphereIntersectR2(const LLVector3& min, const LLVector3& max, const LLVector3 &origin, const F32 &radius_squared);
+void pushVerts(LLFace* face, U32 mask);
// get index buffer for binary encoded axis vertex buffer given a box at center being viewed by given camera
U8* get_box_fan_indices(LLCamera* camera, const LLVector3& center);
diff --git a/indra/newview/lltexturectrl.cpp b/indra/newview/lltexturectrl.cpp
index de00ca8420..f8711cefb5 100644
--- a/indra/newview/lltexturectrl.cpp
+++ b/indra/newview/lltexturectrl.cpp
@@ -291,7 +291,7 @@ BOOL LLFloaterTexturePicker::handleDragAndDrop(
{
BOOL handled = FALSE;
- if (cargo_type == DAD_TEXTURE)
+ if ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH))
{
LLInventoryItem *item = (LLInventoryItem *)cargo_data;
@@ -1154,7 +1154,9 @@ BOOL LLTextureCtrl::handleDragAndDrop(S32 x, S32 y, MASK mask,
// returns true, then the cast was valid, and we can perform
// the third test without problems.
LLInventoryItem* item = (LLInventoryItem*)cargo_data;
- if (getEnabled() && (cargo_type == DAD_TEXTURE) && allowDrop(item))
+ if (getEnabled() &&
+ ((cargo_type == DAD_TEXTURE) || (cargo_type == DAD_MESH)) &&
+ allowDrop(item))
{
if (drop)
{
diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp
index 959cb3f182..ec21710d52 100644
--- a/indra/newview/lltooldraganddrop.cpp
+++ b/indra/newview/lltooldraganddrop.cpp
@@ -483,6 +483,16 @@ LLToolDragAndDrop::dragOrDrop3dImpl LLToolDragAndDrop::sDragAndDrop3d[DAD_COUNT]
&LLToolDragAndDrop::dad3dNULL, // Dest: DT_OBJECT
&LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
},
+
+
+// Source: DAD_MESH
+ {
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_NONE
+ &LLToolDragAndDrop::dad3dNULL, // Dest: DT_SELF
+ &LLToolDragAndDrop::dad3dGiveInventory, // Dest: DT_AVATAR
+ &LLToolDragAndDrop::dad3dUpdateInventory, // Dest: DT_OBJECT
+ &LLToolDragAndDrop::dad3dNULL,//dad3dAssetOnLand, // Dest: DT_LAND
+ },
};
LLToolDragAndDrop::LLToolDragAndDrop()
@@ -2006,6 +2016,7 @@ bool LLToolDragAndDrop::handleGiveDragAndDrop(LLUUID dest_agent, LLUUID session_
case DAD_ANIMATION:
case DAD_GESTURE:
case DAD_CALLINGCARD:
+ case DAD_MESH:
{
LLViewerInventoryItem* inv_item = (LLViewerInventoryItem*)cargo_data;
if(gInventory.getItem(inv_item->getUUID())
diff --git a/indra/newview/llviewerassettype.cpp b/indra/newview/llviewerassettype.cpp
index c974171c2c..a74ae827e2 100644
--- a/indra/newview/llviewerassettype.cpp
+++ b/indra/newview/llviewerassettype.cpp
@@ -86,6 +86,8 @@ LLViewerAssetDictionary::LLViewerAssetDictionary()
addEntry(LLViewerAssetType::AT_LINK, new ViewerAssetEntry(DAD_LINK));
addEntry(LLViewerAssetType::AT_LINK_FOLDER, new ViewerAssetEntry(DAD_LINK));
+ addEntry(LLViewerAssetType::AT_MESH, new ViewerAssetEntry(DAD_MESH));
+
addEntry(LLViewerAssetType::AT_NONE, new ViewerAssetEntry(DAD_NONE));
};
diff --git a/indra/newview/llviewerdisplay.cpp b/indra/newview/llviewerdisplay.cpp
index e0bb8fedeb..5e36807799 100644
--- a/indra/newview/llviewerdisplay.cpp
+++ b/indra/newview/llviewerdisplay.cpp
@@ -870,12 +870,6 @@ void display(BOOL rebuild, F32 zoom_factor, int subfield, BOOL for_snapshot)
}
}
- /// We copy the frame buffer straight into a texture here,
- /// and then display it again with compositor effects.
- /// Using render to texture would be faster/better, but I don't have a
- /// grasp of their full display stack just yet.
- // gPostProcess->apply(gViewerWindow->getWindowDisplayWidth(), gViewerWindow->getWindowDisplayHeight());
-
if (LLPipeline::sRenderDeferred && !LLPipeline::sUnderWaterRender)
{
gPipeline.renderDeferredLighting();
@@ -1098,7 +1092,7 @@ void render_ui(F32 zoom_factor, int subfield)
{
gPipeline.renderBloom(gSnapshot, zoom_factor, subfield);
}
-
+
render_hud_elements();
render_hud_attachments();
}
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index edbac69e1b..f184b88145 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -73,6 +73,7 @@
#include "llimpanel.h"
#include "llfloaterinspect.h"
#include "llfloaterinventory.h"
+#include "llfloaterimportcollada.h"
#include "llfloaterjoystick.h"
#include "llfloaterlagmeter.h"
#include "llfloaterland.h"
@@ -123,6 +124,8 @@
#include "llpreviewsound.h"
#include "llpreviewtexture.h"
#include "llsyswellwindow.h"
+#include "llfloatermodelpreview.h"
+
// *NOTE: Please add files in alphabetical order to keep merges easy.
@@ -170,6 +173,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("hud", "floater_hud.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterHUD>);
LLFloaterReg::add("impanel", "floater_im_session.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIMFloater>);
+ LLFloaterReg::add("import_collada", "floater_import_collada.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImportCollada>);
LLFloaterReg::add("incoming_call", "floater_incoming_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLIncomingCallDialog>);
LLFloaterReg::add("inventory", "floater_inventory.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInventory>);
LLFloaterReg::add("inspect", "floater_inspect.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterInspect>);
@@ -240,7 +244,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("upload_anim", "floater_animation_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterAnimPreview>, "upload");
LLFloaterReg::add("upload_image", "floater_image_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterImagePreview>, "upload");
LLFloaterReg::add("upload_sound", "floater_sound_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSoundPreview>, "upload");
-
+ LLFloaterReg::add("upload_model", "floater_model_preview.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterModelPreview>, "upload");
LLFloaterReg::add("voice_call", "floater_call.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterCall>);
LLFloaterReg::add("whitelist_entry", "floater_whitelist_entry.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterWhiteListEntry>);
diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp
index 97879046a0..4568919770 100644
--- a/indra/newview/llviewermenu.cpp
+++ b/indra/newview/llviewermenu.cpp
@@ -270,7 +270,6 @@ LLMenuItemCallGL* gBusyMenu = NULL;
// Local prototypes
// File Menu
-const char* upload_pick(void* data);
void handle_compress_image(void*);
@@ -551,6 +550,7 @@ void init_menus()
gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", upload_cost);
gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", upload_cost);
gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", upload_cost);
+ gMenuHolder->childSetLabelArg("Upload Model", "[COST]", upload_cost);
gAFKMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Away", TRUE);
gBusyMenu = gMenuBarView->getChild<LLMenuItemCallGL>("Set Busy", TRUE);
diff --git a/indra/newview/llviewermenufile.cpp b/indra/newview/llviewermenufile.cpp
index d17c7e486f..505d2afb69 100644
--- a/indra/newview/llviewermenufile.cpp
+++ b/indra/newview/llviewermenufile.cpp
@@ -39,6 +39,8 @@
#include "llfilepicker.h"
#include "llfloaterreg.h"
#include "llfloaterbuycurrency.h"
+#include "llfloaterimportcollada.h"
+#include "llfloatermodelpreview.h"
#include "llfloatersnapshot.h"
#include "llinventorymodel.h" // gInventory
#include "llresourcedata.h"
@@ -55,13 +57,14 @@
#include "llappviewer.h"
#include "lluploaddialog.h"
#include "lltrans.h"
-
+#include "llfloaterimportcollada.h"
// linden libraries
#include "llassetuploadresponders.h"
#include "lleconomy.h"
#include "llhttpclient.h"
#include "llsdserialize.h"
+#include "llsdutil.h"
#include "llstring.h"
#include "lltransactiontypes.h"
#include "lluuid.h"
@@ -101,6 +104,7 @@ static std::string XML_EXTENSIONS = "xml";
static std::string SLOBJECT_EXTENSIONS = "slobject";
#endif
static std::string ALL_FILE_EXTENSIONS = "*.*";
+static std::string MODEL_EXTENSIONS = "dae";
std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
{
@@ -115,6 +119,8 @@ std::string build_extensions_string(LLFilePicker::ELoadFilter filter)
return ANIM_EXTENSIONS;
case LLFilePicker::FFLOAD_SLOBJECT:
return SLOBJECT_EXTENSIONS;
+ case LLFilePicker::FFLOAD_MODEL:
+ return MODEL_EXTENSIONS;
#ifdef _CORY_TESTING
case LLFilePicker::FFLOAD_GEOMETRY:
return GEOMETRY_EXTENSIONS;
@@ -258,6 +264,29 @@ class LLFileUploadImage : public view_listener_t
}
};
+class LLFileUploadScene : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ std::string filename = upload_pick((void *)LLFilePicker::FFLOAD_COLLADA);
+ if (!filename.empty())
+ {
+ LLImportCollada::getInstance()->importFile(filename);
+ }
+ return TRUE;
+ }
+};
+
+class LLFileUploadModel : public view_listener_t
+{
+ bool handleEvent(const LLSD& userdata)
+ {
+ LLFloaterReg::showInstance("upload_model");
+
+ return TRUE;
+ }
+};
+
class LLFileUploadSound : public view_listener_t
{
bool handleEvent(const LLSD& userdata)
@@ -319,10 +348,21 @@ class LLFileUploadBulk : public view_listener_t
LLAssetStorage::LLStoreAssetCallback callback = NULL;
S32 expected_upload_cost = LLGlobalEconomy::Singleton::getInstance()->getPriceUpload();
void *userdata = NULL;
- upload_new_resource(filename, asset_name, asset_name, 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- LLFloaterPerms::getNextOwnerPerms(), LLFloaterPerms::getGroupPerms(), LLFloaterPerms::getEveryonePerms(),
- display_name,
- callback, expected_upload_cost, userdata);
+
+ upload_new_resource(
+ filename,
+ asset_name,
+ asset_name,
+ 0,
+ LLFolderType::FT_NONE,
+ LLInventoryType::IT_NONE,
+ LLFloaterPerms::getNextOwnerPerms(),
+ LLFloaterPerms::getGroupPerms(),
+ LLFloaterPerms::getEveryonePerms(),
+ display_name,
+ callback,
+ expected_upload_cost,
+ userdata);
// *NOTE: Ew, we don't iterate over the file list here,
// we handle the next files in upload_done_callback()
@@ -491,17 +531,20 @@ void handle_compress_image(void*)
}
}
-void upload_new_resource(const std::string& src_filename, std::string name,
- std::string desc, S32 compression_info,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- LLAssetStorage::LLStoreAssetCallback callback,
- S32 expected_upload_cost,
- void *userdata)
+LLUUID upload_new_resource(
+ const std::string& src_filename,
+ std::string name,
+ std::string desc,
+ S32 compression_info,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ LLAssetStorage::LLStoreAssetCallback callback,
+ S32 expected_upload_cost,
+ void *userdata)
{
// Generate the temporary UUID.
std::string filename = gDirUtilp->getTempFilename();
@@ -526,7 +569,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
short_name.c_str());
args["FILE"] = short_name;
upload_error(error_message, "NofileExtension", filename, args);
- return;
+ return LLUUID();
}
else if( exten == "bmp")
{
@@ -540,7 +583,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
args["FILE"] = src_filename;
args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
- return;
+ return LLUUID();
}
}
else if( exten == "tga")
@@ -555,7 +598,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
args["FILE"] = src_filename;
args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
- return;
+ return LLUUID();
}
}
else if( exten == "jpg" || exten == "jpeg")
@@ -570,7 +613,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
args["FILE"] = src_filename;
args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
- return;
+ return LLUUID();
}
}
else if( exten == "png")
@@ -585,7 +628,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
args["FILE"] = src_filename;
args["ERROR"] = LLImage::getLastError();
upload_error(error_message, "ProblemWithFile", filename, args);
- return;
+ return LLUUID();
}
}
else if(exten == "wav")
@@ -613,7 +656,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
upload_error(error_message, "UnknownVorbisEncodeFailure", filename, args);
break;
}
- return;
+ return LLUUID();
}
}
else if(exten == "tmp")
@@ -653,7 +696,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
error_message = llformat("corrupt resource file: %s", src_filename.c_str());
args["FILE"] = src_filename;
upload_error(error_message, "CorruptResourceFile", filename, args);
- return;
+ return LLUUID();
}
if (2 == tokens_read)
@@ -681,7 +724,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
error_message = llformat("unknown linden resource file version in file: %s", src_filename.c_str());
args["FILE"] = src_filename;
upload_error(error_message, "UnknownResourceFileVersion", filename, args);
- return;
+ return LLUUID();
}
}
else
@@ -723,7 +766,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
error_message = llformat( "Unable to create output file: %s", filename.c_str());
args["FILE"] = filename;
upload_error(error_message, "UnableToCreateOutputFile", filename, args);
- return;
+ return LLUUID();
}
fclose(in);
@@ -737,7 +780,7 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
error_message = llformat("We do not currently support bulk upload of animation files\n");
upload_error(error_message, "DoNotSupportBulkAnimationUpload", filename, args);
- return;
+ return LLUUID();
}
else
{
@@ -783,9 +826,21 @@ void upload_new_resource(const std::string& src_filename, std::string name,
{
t_disp_name = src_filename;
}
- upload_new_resource(tid, asset_type, name, desc, compression_info, // tid
- destination_folder_type, inv_type, next_owner_perms, group_perms, everyone_perms,
- display_name, callback, expected_upload_cost, userdata);
+ upload_new_resource(
+ tid,
+ asset_type,
+ name,
+ desc,
+ compression_info, // tid
+ destination_folder_type,
+ inv_type,
+ next_owner_perms,
+ group_perms,
+ everyone_perms,
+ display_name,
+ callback,
+ expected_upload_cost,
+ userdata);
}
else
{
@@ -799,9 +854,15 @@ void upload_new_resource(const std::string& src_filename, std::string name,
}
LLFilePicker::instance().reset();
}
+
+ return uuid;
}
-void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExtStat ext_status) // StoreAssetData callback (fixed)
+void upload_done_callback(
+ const LLUUID& uuid,
+ void* user_data,
+ S32 result,
+ LLExtStat ext_status) // StoreAssetData callback (fixed)
{
LLResourceData* data = (LLResourceData*)user_data;
S32 expected_upload_cost = data ? data->mExpectedUploadCost : 0;
@@ -902,70 +963,97 @@ void upload_done_callback(const LLUUID& uuid, void* user_data, S32 result, LLExt
std::string display_name = LLStringUtil::null;
LLAssetStorage::LLStoreAssetCallback callback = NULL;
void *userdata = NULL;
- upload_new_resource(next_file, asset_name, asset_name, // file
- 0, LLFolderType::FT_NONE, LLInventoryType::IT_NONE,
- PERM_NONE, PERM_NONE, PERM_NONE,
- display_name,
- callback,
- expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost
- userdata);
+ upload_new_resource(
+ next_file,
+ asset_name,
+ asset_name, // file
+ 0,
+ LLFolderType::FT_NONE,
+ LLInventoryType::IT_NONE,
+ PERM_NONE,
+ PERM_NONE,
+ PERM_NONE,
+ display_name,
+ callback,
+ expected_upload_cost, // assuming next in a group of uploads is of roughly the same type, i.e. same upload cost
+ userdata);
}
}
-void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_type,
- std::string name,
- std::string desc, S32 compression_info,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- LLAssetStorage::LLStoreAssetCallback callback,
- S32 expected_upload_cost,
- void *userdata)
+static LLAssetID upload_new_resource_prep(
+ const LLTransactionID& tid,
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType& inventory_type,
+ std::string& name,
+ const std::string& display_name,
+ std::string& description)
{
- if(gDisconnected)
- {
- return ;
- }
+ LLAssetID uuid = generate_asset_id_for_new_upload(tid);
- LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
-
- if( LLAssetType::AT_SOUND == asset_type )
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_SOUND_COUNT );
- }
- else
- if( LLAssetType::AT_TEXTURE == asset_type )
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_TEXTURE_COUNT );
- }
- else
- if( LLAssetType::AT_ANIMATION == asset_type)
- {
- LLViewerStats::getInstance()->incStat(LLViewerStats::ST_UPLOAD_ANIM_COUNT );
- }
+ increase_new_upload_stats(asset_type);
- if(LLInventoryType::IT_NONE == inv_type)
- {
- inv_type = LLInventoryType::defaultForAssetType(asset_type);
- }
- LLStringUtil::stripNonprintable(name);
- LLStringUtil::stripNonprintable(desc);
- if(name.empty())
- {
- name = "(No Name)";
- }
- if(desc.empty())
- {
- desc = "(No Description)";
- }
-
- // At this point, we're ready for the upload.
- std::string upload_message = "Uploading...\n\n";
- upload_message.append(display_name);
- LLUploadDialog::modalUploadDialog(upload_message);
+ assign_defaults_and_show_upload_message(
+ asset_type,
+ inventory_type,
+ name,
+ display_name,
+ description);
+
+ return uuid;
+}
+
+LLSD generate_new_resource_upload_capability_body(
+ LLAssetType::EType asset_type,
+ const std::string& name,
+ const std::string& desc,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms)
+{
+ LLSD body;
+
+ body["folder_id"] = gInventory.findCategoryUUIDForType(
+ (destination_folder_type == LLFolderType::FT_NONE) ?
+ (LLFolderType::EType) asset_type :
+ destination_folder_type);
+
+ body["asset_type"] = LLAssetType::lookup(asset_type);
+ body["inventory_type"] = LLInventoryType::lookup(inv_type);
+ body["name"] = name;
+ body["description"] = desc;
+ body["next_owner_mask"] = LLSD::Integer(next_owner_perms);
+ body["group_mask"] = LLSD::Integer(group_perms);
+ body["everyone_mask"] = LLSD::Integer(everyone_perms);
+
+ return body;
+}
+
+void upload_new_resource(
+ const LLTransactionID &tid,
+ LLAssetType::EType asset_type,
+ std::string name,
+ std::string desc,
+ S32 compression_info,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ LLAssetStorage::LLStoreAssetCallback callback,
+ S32 expected_upload_cost,
+ void *userdata)
+{
+ LLAssetID uuid =
+ upload_new_resource_prep(
+ tid,
+ asset_type,
+ inv_type,
+ name,
+ display_name,
+ desc);
llinfos << "*** Uploading: " << llendl;
llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
@@ -975,26 +1063,32 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty
llinfos << "Expected Upload Cost: " << expected_upload_cost << llendl;
lldebugs << "Folder: " << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type) << llendl;
lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
- std::string url = gAgent.getRegion()->getCapability("NewFileAgentInventory");
- if (!url.empty())
+
+ std::string url = gAgent.getRegion()->getCapability(
+ "NewFileAgentInventory");
+
+ if ( !url.empty() )
{
llinfos << "New Agent Inventory via capability" << llendl;
- LLSD body;
- body["folder_id"] = gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? LLFolderType::assetTypeToFolderType(asset_type) : destination_folder_type);
- body["asset_type"] = LLAssetType::lookup(asset_type);
- body["inventory_type"] = LLInventoryType::lookup(inv_type);
- body["name"] = name;
- body["description"] = desc;
- body["next_owner_mask"] = LLSD::Integer(next_owner_perms);
- body["group_mask"] = LLSD::Integer(group_perms);
- body["everyone_mask"] = LLSD::Integer(everyone_perms);
- body["expected_upload_cost"] = LLSD::Integer(expected_upload_cost);
-
- //std::ostringstream llsdxml;
- //LLSDSerialize::toPrettyXML(body, llsdxml);
- //llinfos << "posting body to capability: " << llsdxml.str() << llendl;
- LLHTTPClient::post(url, body, new LLNewAgentInventoryResponder(body, uuid, asset_type));
+ LLSD body;
+ body = generate_new_resource_upload_capability_body(
+ asset_type,
+ name,
+ desc,
+ destination_folder_type,
+ inv_type,
+ next_owner_perms,
+ group_perms,
+ everyone_perms);
+
+ LLHTTPClient::post(
+ url,
+ body,
+ new LLNewAgentInventoryResponder(
+ body,
+ uuid,
+ asset_type));
}
else
{
@@ -1032,18 +1126,157 @@ void upload_new_resource(const LLTransactionID &tid, LLAssetType::EType asset_ty
{
asset_callback = callback;
}
- gAssetStorage->storeAssetData(data->mAssetInfo.mTransactionID, data->mAssetInfo.mType,
- asset_callback,
- (void*)data,
- FALSE);
+ gAssetStorage->storeAssetData(
+ data->mAssetInfo.mTransactionID,
+ data->mAssetInfo.mType,
+ asset_callback,
+ (void*)data,
+ FALSE);
}
}
+BOOL upload_new_variable_price_resource(
+ const LLTransactionID &tid,
+ LLAssetType::EType asset_type,
+ std::string name,
+ std::string desc,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ const LLSD& asset_resources)
+{
+ LLAssetID uuid =
+ upload_new_resource_prep(
+ tid,
+ asset_type,
+ inv_type,
+ name,
+ display_name,
+ desc);
+
+ llinfos << "*** Uploading: " << llendl;
+ llinfos << "Type: " << LLAssetType::lookup(asset_type) << llendl;
+ llinfos << "UUID: " << uuid << llendl;
+ llinfos << "Name: " << name << llendl;
+ llinfos << "Desc: " << desc << llendl;
+ lldebugs << "Folder: "
+ << gInventory.findCategoryUUIDForType((destination_folder_type == LLFolderType::FT_NONE) ? (LLFolderType::EType)asset_type : destination_folder_type) << llendl;
+ lldebugs << "Asset Type: " << LLAssetType::lookup(asset_type) << llendl;
+
+ std::string url = gAgent.getRegion()->getCapability(
+ "NewFileAgentInventoryVariablePrice");
+
+ if ( !url.empty() )
+ {
+ llinfos << "New Agent Inventory variable price upload"
+ << llendl;
+
+ // Each of the two capabilities has similar data, so
+ // let's reuse that code
+
+ LLSD body;
+
+ body = generate_new_resource_upload_capability_body(
+ asset_type,
+ name,
+ desc,
+ destination_folder_type,
+ inv_type,
+ next_owner_perms,
+ group_perms,
+ everyone_perms);
+
+ body["asset_resources"] = asset_resources;
+
+ LLHTTPClient::post(
+ url,
+ body,
+ new LLNewAgentInventoryVariablePriceResponder(
+ uuid,
+ body));
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid)
+{
+ if ( gDisconnected )
+ {
+ LLAssetID rv;
+
+ rv.setNull();
+ return rv;
+ }
+
+ LLAssetID uuid = tid.makeAssetID(gAgent.getSecureSessionID());
+
+ return uuid;
+}
+
+void increase_new_upload_stats(LLAssetType::EType asset_type)
+{
+ if ( LLAssetType::AT_SOUND == asset_type )
+ {
+ LLViewerStats::getInstance()->incStat(
+ LLViewerStats::ST_UPLOAD_SOUND_COUNT );
+ }
+ else if ( LLAssetType::AT_TEXTURE == asset_type )
+ {
+ LLViewerStats::getInstance()->incStat(
+ LLViewerStats::ST_UPLOAD_TEXTURE_COUNT );
+ }
+ else if ( LLAssetType::AT_ANIMATION == asset_type )
+ {
+ LLViewerStats::getInstance()->incStat(
+ LLViewerStats::ST_UPLOAD_ANIM_COUNT );
+ }
+}
+
+void assign_defaults_and_show_upload_message(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType& inventory_type,
+ std::string& name,
+ const std::string& display_name,
+ std::string& description)
+{
+ if ( LLInventoryType::IT_NONE == inventory_type )
+ {
+ inventory_type = LLInventoryType::defaultForAssetType(asset_type);
+ }
+ LLStringUtil::stripNonprintable(name);
+ LLStringUtil::stripNonprintable(description);
+
+ if ( name.empty() )
+ {
+ name = "(No Name)";
+ }
+ if ( description.empty() )
+ {
+ description = "(No Description)";
+ }
+
+ // At this point, we're ready for the upload.
+ std::string upload_message = "Uploading...\n\n";
+ upload_message.append(display_name);
+ LLUploadDialog::modalUploadDialog(upload_message);
+}
+
+
void init_menu_file()
{
view_listener_t::addCommit(new LLFileUploadImage(), "File.UploadImage");
view_listener_t::addCommit(new LLFileUploadSound(), "File.UploadSound");
view_listener_t::addCommit(new LLFileUploadAnim(), "File.UploadAnim");
+ view_listener_t::addCommit(new LLFileUploadModel(), "File.UploadModel");
+ view_listener_t::addCommit(new LLFileUploadScene(), "File.UploadScene");
view_listener_t::addCommit(new LLFileUploadBulk(), "File.UploadBulk");
view_listener_t::addCommit(new LLFileCloseWindow(), "File.CloseWindow");
view_listener_t::addCommit(new LLFileCloseAllWindows(), "File.CloseAllWindows");
diff --git a/indra/newview/llviewermenufile.h b/indra/newview/llviewermenufile.h
index da78537a29..800325df0b 100644
--- a/indra/newview/llviewermenufile.h
+++ b/indra/newview/llviewermenufile.h
@@ -41,33 +41,62 @@ class LLTransactionID;
void init_menu_file();
-void upload_new_resource(const std::string& src_filename,
- std::string name,
- std::string desc,
- S32 compression_info,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- LLAssetStorage::LLStoreAssetCallback callback,
- S32 expected_upload_cost,
- void *userdata);
+LLUUID upload_new_resource(
+ const std::string& src_filename,
+ std::string name,
+ std::string desc,
+ S32 compression_info,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ LLAssetStorage::LLStoreAssetCallback callback,
+ S32 expected_upload_cost,
+ void *userdata);
-void upload_new_resource(const LLTransactionID &tid,
- LLAssetType::EType type,
- std::string name,
- std::string desc,
- S32 compression_info,
- LLFolderType::EType destination_folder_type,
- LLInventoryType::EType inv_type,
- U32 next_owner_perms,
- U32 group_perms,
- U32 everyone_perms,
- const std::string& display_name,
- LLAssetStorage::LLStoreAssetCallback callback,
- S32 expected_upload_cost,
- void *userdata);
+void upload_new_resource(
+ const LLTransactionID &tid,
+ LLAssetType::EType type,
+ std::string name,
+ std::string desc,
+ S32 compression_info,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ LLAssetStorage::LLStoreAssetCallback callback,
+ S32 expected_upload_cost,
+ void *userdata);
+
+// TODO* : Move all uploads to use this new function
+// since at some point, that upload path will be deprecated and no longer
+// used
+
+// We make a new function here to ensure that previous code is not broken
+BOOL upload_new_variable_price_resource(
+ const LLTransactionID& tid,
+ LLAssetType::EType type,
+ std::string name,
+ std::string desc,
+ LLFolderType::EType destination_folder_type,
+ LLInventoryType::EType inv_type,
+ U32 next_owner_perms,
+ U32 group_perms,
+ U32 everyone_perms,
+ const std::string& display_name,
+ const LLSD& asset_resources);
+
+LLAssetID generate_asset_id_for_new_upload(const LLTransactionID& tid);
+void increase_new_upload_stats(LLAssetType::EType asset_type);
+void assign_defaults_and_show_upload_message(
+ LLAssetType::EType asset_type,
+ LLInventoryType::EType& inventory_type,
+ std::string& name,
+ const std::string& display_name,
+ std::string& description);
#endif
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index ea1097c477..f71bb2ce89 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4524,6 +4524,7 @@ void process_economy_data(LLMessageSystem *msg, void** /*user_data*/)
gMenuHolder->childSetLabelArg("Upload Image", "[COST]", llformat("%d", upload_cost));
gMenuHolder->childSetLabelArg("Upload Sound", "[COST]", llformat("%d", upload_cost));
+ gMenuHolder->childSetLabelArg("Upload Model", "[COST]", llformat("%d", upload_cost));
gMenuHolder->childSetLabelArg("Upload Animation", "[COST]", llformat("%d", upload_cost));
gMenuHolder->childSetLabelArg("Bulk Upload", "[COST]", llformat("%d", upload_cost));
}
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d1c9840a97..8317837520 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1437,6 +1437,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewFileAgentInventory");
+ capabilityNames.append("NewFileAgentInventoryVariablePrice");
+ capabilityNames.append("ObjectAdd");
capabilityNames.append("ParcelPropertiesUpdate");
capabilityNames.append("ParcelMediaURLFilterList");
capabilityNames.append("ParcelNavigateMedia");
diff --git a/indra/newview/llviewertexteditor.cpp b/indra/newview/llviewertexteditor.cpp
index 6f8818be6e..dd310a8813 100644
--- a/indra/newview/llviewertexteditor.cpp
+++ b/indra/newview/llviewertexteditor.cpp
@@ -533,6 +533,7 @@ LLUIImagePtr LLEmbeddedItems::getItemImage(llwchar ext_char) const
case LLAssetType::AT_BODYPART: img_name = "Inv_Skin"; break;
case LLAssetType::AT_ANIMATION: img_name = "Inv_Animation"; break;
case LLAssetType::AT_GESTURE: img_name = "Inv_Gesture"; break;
+ case LLAssetType::AT_MESH: img_name = "inv_item_mesh.tga"; break;
default: llassert(0);
}
diff --git a/indra/newview/llviewertexture.cpp b/indra/newview/llviewertexture.cpp
index 9923c9ac74..b812ab4fe6 100644
--- a/indra/newview/llviewertexture.cpp
+++ b/indra/newview/llviewertexture.cpp
@@ -680,7 +680,7 @@ BOOL LLViewerTexture::createGLTexture(S32 discard_level, const LLImageRaw* image
llassert_always(mGLTexturep.notNull()) ;
BOOL ret = mGLTexturep->createGLTexture(discard_level, imageraw, usename, to_create, category) ;
-
+
if(ret)
{
mFullWidth = mGLTexturep->getCurrentWidth() ;
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 29ce2510f2..dc2567d94b 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -3698,140 +3698,6 @@ void LLViewerWindow::playSnapshotAnimAndSound()
BOOL LLViewerWindow::thumbnailSnapshot(LLImageRaw *raw, S32 preview_width, S32 preview_height, BOOL show_ui, BOOL do_rebuild, ESnapshotType type)
{
return rawSnapshot(raw, preview_width, preview_height, FALSE, FALSE, show_ui, do_rebuild, type);
-
- // *TODO below code was broken in deferred pipeline
- /*
- if ((!raw) || preview_width < 10 || preview_height < 10)
- {
- return FALSE;
- }
-
- if(gResizeScreenTexture) //the window is resizing
- {
- return FALSE ;
- }
-
- setCursor(UI_CURSOR_WAIT);
-
- // Hide all the UI widgets first and draw a frame
- BOOL prev_draw_ui = gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI);
-
- if ( prev_draw_ui != show_ui)
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
-
- BOOL hide_hud = !gSavedSettings.getBOOL("RenderHUDInSnapshot") && LLPipeline::sShowHUDAttachments;
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = FALSE;
- }
-
- S32 render_name = gSavedSettings.getS32("RenderName");
- gSavedSettings.setS32("RenderName", 0);
- LLVOAvatar::updateFreezeCounter(1) ; //pause avatar updating for one frame
-
- S32 w = preview_width ;
- S32 h = preview_height ;
- LLVector2 display_scale = mDisplayScale ;
- mDisplayScale.setVec((F32)w / mWindowRect.getWidth(), (F32)h / mWindowRect.getHeight()) ;
- LLRect window_rect = mWindowRect;
- mWindowRect.set(0, h, w, 0);
-
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
- glClearColor(0.f, 0.f, 0.f, 0.f);
- glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
- setup3DRender();
-
- LLFontGL::setFontDisplay(FALSE) ;
- LLHUDText::setDisplayText(FALSE) ;
- if (type == SNAPSHOT_TYPE_OBJECT_ID)
- {
- gObjectList.renderPickList(gViewerWindow->getVirtualWindowRect(), FALSE, FALSE);
- }
- else
- {
- display(do_rebuild, 1.0f, 0, TRUE);
- render_ui();
- }
-
- S32 glformat, gltype, glpixel_length ;
- if(SNAPSHOT_TYPE_DEPTH == type)
- {
- glpixel_length = 4 ;
- glformat = GL_DEPTH_COMPONENT ;
- gltype = GL_FLOAT ;
- }
- else
- {
- glpixel_length = 3 ;
- glformat = GL_RGB ;
- gltype = GL_UNSIGNED_BYTE ;
- }
-
- raw->resize(w, h, glpixel_length);
- glReadPixels(0, 0, w, h, glformat, gltype, raw->getData());
-
- if(SNAPSHOT_TYPE_DEPTH == type)
- {
- LLViewerCamera* camerap = LLViewerCamera::getInstance();
- F32 depth_conversion_factor_1 = (camerap->getFar() + camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
- F32 depth_conversion_factor_2 = (camerap->getFar() - camerap->getNear()) / (2.f * camerap->getFar() * camerap->getNear());
-
- //calculate the depth
- for (S32 y = 0 ; y < h ; y++)
- {
- for(S32 x = 0 ; x < w ; x++)
- {
- S32 i = (w * y + x) << 2 ;
-
- F32 depth_float_i = *(F32*)(raw->getData() + i);
-
- F32 linear_depth_float = 1.f / (depth_conversion_factor_1 - (depth_float_i * depth_conversion_factor_2));
- U8 depth_byte = F32_to_U8(linear_depth_float, camerap->getNear(), camerap->getFar());
- *(raw->getData() + i + 0) = depth_byte;
- *(raw->getData() + i + 1) = depth_byte;
- *(raw->getData() + i + 2) = depth_byte;
- *(raw->getData() + i + 3) = 255;
- }
- }
- }
-
- LLFontGL::setFontDisplay(TRUE) ;
- LLHUDText::setDisplayText(TRUE) ;
- mDisplayScale.setVec(display_scale) ;
- mWindowRect = window_rect;
- setup3DRender();
- gDisplaySwapBuffers = FALSE;
- gDepthDirty = TRUE;
-
- // POST SNAPSHOT
- if (!gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- LLPipeline::toggleRenderDebugFeature((void*)LLPipeline::RENDER_DEBUG_FEATURE_UI);
- }
-
- if (hide_hud)
- {
- LLPipeline::sShowHUDAttachments = TRUE;
- }
-
- setCursor(UI_CURSOR_ARROW);
-
- if (do_rebuild)
- {
- // If we had to do a rebuild, that means that the lists of drawables to be rendered
- // was empty before we started.
- // Need to reset these, otherwise we call state sort on it again when render gets called the next time
- // and we stand a good chance of crashing on rebuild because the render drawable arrays have multiple copies of
- // objects on them.
- gPipeline.resetDrawOrders();
- }
-
- gSavedSettings.setS32("RenderName", render_name);
-
- return TRUE;*/
}
// Saves the image from the screen to the specified filename and path.
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index 5ac6dcce5a..e38b0c62f3 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -36,6 +36,8 @@
#include "llvovolume.h"
+#include <sstream>
+
#include "llviewercontrol.h"
#include "lldir.h"
#include "llflexibleobject.h"
@@ -59,6 +61,7 @@
#include "lltexturefetch.h"
#include "llviewercamera.h"
#include "llviewertexturelist.h"
+#include "llviewerobjectlist.h"
#include "llviewerregion.h"
#include "llviewertextureanim.h"
#include "llworld.h"
@@ -87,6 +90,12 @@ LLPointer<LLObjectMediaNavigateClient> LLVOVolume::sObjectMediaNavigateClient =
static LLFastTimer::DeclareTimer FTM_GEN_TRIANGLES("Generate Triangles");
static LLFastTimer::DeclareTimer FTM_GEN_VOLUME("Generate Volumes");
+static LLFastTimer::DeclareTimer FTM_BUILD_MESH("Mesh");
+static LLFastTimer::DeclareTimer FTM_MESH_VFS("VFS");
+static LLFastTimer::DeclareTimer FTM_MESH_STREAM("Stream");
+static LLFastTimer::DeclareTimer FTM_MESH_FACES("Faces");
+static LLFastTimer::DeclareTimer FTM_VOLUME_TEXTURES("Volume Textures");
+
// Implementation class of LLMediaDataClientObject. See llmediadataclient.h
class LLMediaDataClientObjectImpl : public LLMediaDataClientObject
@@ -153,6 +162,7 @@ LLVOVolume::LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *re
mRelativeXformInvTrans.setIdentity();
mLOD = MIN_LOD;
+ mMeshSculptLevel = -2;
mTextureAnimp = NULL;
mVObjRadius = LLVector3(1,1,0.5f).length();
mNumFaces = 0;
@@ -576,6 +586,7 @@ void LLVOVolume::updateTextures()
void LLVOVolume::updateTextureVirtualSize()
{
+ LLFastTimer ftm(FTM_VOLUME_TEXTURES);
// Update the pixel area of all faces
if(mDrawable.isNull() || !mDrawable->isVisible())
@@ -667,46 +678,70 @@ void LLVOVolume::updateTextureVirtualSize()
if (isSculpted())
{
LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
- LLUUID id = sculpt_params->getSculptTexture();
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- if (mSculptTexture.notNull())
+ LLUUID id = sculpt_params->getSculptTexture();
+ U8 sculpt_type = sculpt_params->getSculptType();
+
+ if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
+ // mesh is a mesh
{
- mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
- (S32)LLViewerTexture::BOOST_SCULPTED));
- mSculptTexture->setForSculpt() ;
-
- if(!mSculptTexture->isCachedRawImageReady())
+ if (mMeshSculptLevel == -2)
+ {
+ // get the asset please
+ gPipeline.loadMesh(this, id);
+ /*gAssetStorage->getAssetData(id, LLAssetType::AT_MESH, (LLGetAssetCallback)NULL, NULL, TRUE);
+
+ if (gAssetStorage->hasLocalAsset(id, LLAssetType::AT_MESH))
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
+ mSculptChanged = TRUE;
+ }*/
+ }
+ }
+
+ else
+ // mesh is a sculptie
+ {
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+
+ if (mSculptTexture.notNull())
{
- S32 lod = llmin(mLOD, 3);
- F32 lodf = ((F32)(lod + 1.0f)/4.f);
- F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
- mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
+ mSculptTexture->setBoostLevel(llmax((S32)mSculptTexture->getBoostLevel(),
+ (S32)LLViewerTexture::BOOST_SCULPTED));
+ mSculptTexture->setForSculpt() ;
- //if the sculpty very close to the view point, load first
- {
- LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin();
- F32 dist = lookAt.normVec() ;
- F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
- mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
+ if(!mSculptTexture->isCachedRawImageReady())
+ {
+ S32 lod = llmin(mLOD, 3);
+ F32 lodf = ((F32)(lod + 1.0f)/4.f);
+ F32 tex_size = lodf * LLViewerTexture::sMaxSculptRez ;
+ mSculptTexture->addTextureStats(2.f * tex_size * tex_size, FALSE);
+
+ //if the sculpty very close to the view point, load first
+ {
+ LLVector3 lookAt = getPositionAgent() - LLViewerCamera::getInstance()->getOrigin();
+ F32 dist = lookAt.normVec() ;
+ F32 cos_angle_to_view_dir = lookAt * LLViewerCamera::getInstance()->getXAxis() ;
+ mSculptTexture->setAdditionalDecodePriority(0.8f * LLFace::calcImportanceToCamera(cos_angle_to_view_dir, dist)) ;
+ }
}
- }
- S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
- S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
+ S32 texture_discard = mSculptTexture->getDiscardLevel(); //try to match the texture
+ S32 current_discard = getVolume() ? getVolume()->getSculptLevel() : -2 ;
- if (texture_discard >= 0 && //texture has some data available
- (texture_discard < current_discard || //texture has more data than last rebuild
- current_discard < 0)) //no previous rebuild
- {
- gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
- mSculptChanged = TRUE;
- }
+ if (texture_discard >= 0 && //texture has some data available
+ (texture_discard < current_discard || //texture has more data than last rebuild
+ current_discard < 0)) //no previous rebuild
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, FALSE);
+ mSculptChanged = TRUE;
+ }
- if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
- {
- setDebugText(llformat("T%d C%d V%d\n%dx%d",
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_SCULPTED))
+ {
+ setDebugText(llformat("T%d C%d V%d\n%dx%d",
texture_discard, current_discard, getVolume()->getSculptLevel(),
mSculptTexture->getHeight(), mSculptTexture->getWidth()));
+ }
}
}
}
@@ -724,7 +759,7 @@ void LLVOVolume::updateTextureVirtualSize()
*LLViewerCamera::getInstance()));
}
}
-
+
if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_TEXTURE_AREA))
{
setDebugText(llformat("%.0f:%.0f", fsqrtf(min_vsize),fsqrtf(max_vsize)));
@@ -820,8 +855,10 @@ LLDrawable *LLVOVolume::createDrawable(LLPipeline *pipeline)
return mDrawable;
}
-BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume)
+BOOL LLVOVolume::setVolume(const LLVolumeParams &params, const S32 detail, bool unique_volume)
{
+ LLVolumeParams volume_params = params;
+
// Check if we need to change implementations
bool is_flexible = (volume_params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE);
if (is_flexible)
@@ -860,19 +897,37 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
if (isSculpted())
{
- mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
- if (mSculptTexture.notNull())
+ // if it's a mesh
+ if ((volume_params.getSculptType() & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
{
- //ignore sculpt GL usage since bao fixed this in a separate branch
- if (!gGLActive)
+ if (getVolume()->getNumVolumeFaces() == 0)
{
- gGLActive = TRUE;
- sculpt();
- gGLActive = FALSE;
+ //mesh is not loaded, request pipeline load this mesh
+ LLUUID asset_id = volume_params.getSculptID();
+ gPipeline.loadMesh(this, asset_id, detail);
}
else
{
- sculpt();
+ mMeshSculptLevel = 1;
+ }
+ }
+ else // otherwise is sculptie
+ {
+ mSculptTexture = LLViewerTextureManager::getFetchedTexture(volume_params.getSculptID(), TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+
+ if (mSculptTexture.notNull())
+ {
+ //ignore sculpt GL usage since bao fixed this in a separate branch
+ if (!gGLActive)
+ {
+ gGLActive = TRUE;
+ sculpt();
+ gGLActive = FALSE;
+ }
+ else
+ {
+ sculpt();
+ }
}
}
}
@@ -886,6 +941,14 @@ BOOL LLVOVolume::setVolume(const LLVolumeParams &volume_params, const S32 detail
return FALSE;
}
+
+
+void LLVOVolume::notifyMeshLoaded()
+{
+ mSculptChanged = TRUE;
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY);
+}
+
// sculpt replaces generate() for sculpted surfaces
void LLVOVolume::sculpt()
{
@@ -1060,6 +1123,11 @@ void LLVOVolume::updateFaceFlags()
for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
{
LLFace *face = mDrawable->getFace(i);
+ if (!face)
+ {
+ return;
+ }
+
BOOL fullbright = getTE(i)->getFullbright();
face->clearState(LLFace::FULLBRIGHT | LLFace::HUD_RENDER | LLFace::LIGHT);
@@ -1132,6 +1200,10 @@ BOOL LLVOVolume::genBBoxes(BOOL force_global)
for (S32 i = 0; i < getVolume()->getNumFaces(); i++)
{
LLFace *face = mDrawable->getFace(i);
+ if (!face)
+ {
+ continue;
+ }
res &= face->genVolumeBBoxes(*getVolume(), i,
mRelativeXform, mRelativeXformInvTrans,
(mVolumeImpl && mVolumeImpl->isVolumeGlobal()) || force_global);
@@ -2373,6 +2445,23 @@ BOOL LLVOVolume::isSculpted() const
return FALSE;
}
+BOOL LLVOVolume::isMesh() const
+{
+ if (isSculpted())
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ U8 sculpt_type = sculpt_params->getSculptType();
+
+ if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
+ // mesh is a mesh
+ {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
BOOL LLVOVolume::hasLightTexture() const
{
if (getParameterEntryInUse(LLNetworkData::PARAMS_LIGHT_IMAGE))
@@ -2578,6 +2667,30 @@ F32 LLVOVolume::getBinRadius()
{
F32 radius;
+ F32 scale = 1.f;
+
+ if (isSculpted())
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLUUID id = sculpt_params->getSculptTexture();
+ U8 sculpt_type = sculpt_params->getSculptType();
+
+ if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH)
+ // mesh is a mesh
+ {
+ LLVolume* volume = getVolume();
+ U32 vert_count = 0;
+
+ for (S32 i = 0; i < volume->getNumVolumeFaces(); ++i)
+ {
+ const LLVolumeFace& face = volume->getVolumeFace(i);
+ vert_count += face.mVertices.size();
+ }
+
+ scale = 1.f/llmax(vert_count/1024.f, 1.f);
+ }
+ }
+
const LLVector3* ext = mDrawable->getSpatialExtents();
BOOL shrink_wrap = mDrawable->isAnimating();
@@ -2636,7 +2749,7 @@ F32 LLVOVolume::getBinRadius()
radius = 8.f;
}
- return llclamp(radius, 0.5f, 256.f);
+ return llclamp(radius*scale, 0.5f, 256.f);
}
const LLVector3 LLVOVolume::getPivotPositionAgent() const
@@ -3228,6 +3341,11 @@ void LLVolumeGeometryManager::rebuildMesh(LLSpatialGroup* group)
face->getGeometryVolume(*volume, face->getTEOffset(),
vobj->getRelativeXform(), vobj->getRelativeXformInvTrans(), face->getGeomIndex());
}
+
+ if (!face)
+ {
+ llerrs << "WTF?" << llendl;
+ }
}
drawablep->clearState(LLDrawable::REBUILD_ALL);
@@ -3512,7 +3630,7 @@ void LLVolumeGeometryManager::genDrawInfo(LLSpatialGroup* group, U32 mask, std::
}
else
{
- if (LLPipeline::sRenderDeferred && te->getBumpmap())
+ if (LLPipeline::sRenderDeferred && LLPipeline::sRenderBump && te->getBumpmap())
{
registerFace(group, facep, LLRenderPass::PASS_BUMP);
}
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index 784ef16ba3..9b8248e4f2 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -182,6 +182,11 @@ public:
/*virtual*/ BOOL setVolume(const LLVolumeParams &volume_params, const S32 detail, bool unique_volume = false);
void sculpt();
+ static void rebuildMeshAssetCallback(LLVFS *vfs,
+ const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status);
+
void updateRelativeXform();
/*virtual*/ BOOL updateGeometry(LLDrawable *drawable);
/*virtual*/ void updateFaceSize(S32 idx);
@@ -227,6 +232,7 @@ public:
U32 getVolumeInterfaceID() const;
virtual BOOL isFlexible() const;
virtual BOOL isSculpted() const;
+ virtual BOOL isMesh() const;
virtual BOOL hasLightTexture() const;
BOOL isVolumeGlobal() const;
@@ -251,6 +257,7 @@ public:
void mediaNavigated(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, std::string new_location);
void mediaEvent(LLViewerMediaImpl *impl, LLPluginClassMedia* plugin, LLViewerMediaObserver::EMediaEvent event);
+
// Sync the given media data with the impl and the given te
void syncMediaData(S32 te, const LLSD &media_data, bool merge, bool ignore_agent);
@@ -266,6 +273,8 @@ public:
LLVector3 getApproximateFaceNormal(U8 face_id);
+ void notifyMeshLoaded();
+
protected:
S32 computeLODDetail(F32 distance, F32 radius);
BOOL calcLOD();
@@ -286,6 +295,7 @@ private:
LLFrameTimer mTextureUpdateTimer;
S32 mLOD;
BOOL mLODChanged;
+ S32 mMeshSculptLevel;
BOOL mSculptChanged;
F32 mSpotLightPriority;
LLMatrix4 mRelativeXform;
diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp
index ba1732bc92..2cda9dda01 100644
--- a/indra/newview/pipeline.cpp
+++ b/indra/newview/pipeline.cpp
@@ -342,6 +342,8 @@ LLPipeline::LLPipeline() :
mGlowPool(NULL),
mBumpPool(NULL),
mWLSkyPool(NULL),
+ mMeshMutex(NULL),
+ mMeshThreadCount(0),
mLightMask(0),
mLightMovingMask(0),
mLightingDetail(0)
@@ -399,6 +401,7 @@ void LLPipeline::init()
stop_glerror();
+ mMeshMutex = new LLMutex(NULL);
for (U32 i = 0; i < 2; ++i)
{
mSpotLightFade[i] = 1.f;
@@ -473,6 +476,9 @@ void LLPipeline::cleanup()
//delete mWLSkyPool;
mWLSkyPool = NULL;
+ delete mMeshMutex;
+ mMeshMutex = NULL;
+
releaseGLBuffers();
mBloomImagep = NULL;
@@ -1786,6 +1792,8 @@ void LLPipeline::rebuildPriorityGroups()
assertInitialized();
+ notifyLoadedMeshes();
+
// Iterate through all drawables on the priority build queue,
for (LLSpatialGroup::sg_list_t::iterator iter = mGroupQ1.begin();
iter != mGroupQ1.end(); ++iter)
@@ -1796,6 +1804,7 @@ void LLPipeline::rebuildPriorityGroups()
}
mGroupQ1.clear();
+
}
void LLPipeline::rebuildGroups()
@@ -3414,27 +3423,14 @@ void LLPipeline::renderGeomPostDeferred(LLCamera& camera)
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
- renderHighlights();
- mHighlightFaces.clear();
-
- renderDebug();
-
- LLVertexBuffer::unbind();
-
- if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
- {
- // Render debugging beacons.
- gObjectList.renderObjectBeacons();
- LLHUDObject::renderAll();
- gObjectList.resetObjectBeacons();
- }
-
if (occlude)
{
occlude = FALSE;
gGLLastMatrix = NULL;
glLoadMatrixd(gGLModelView);
doOcclusion(camera);
+ gGLLastMatrix = NULL;
+ glLoadMatrixd(gGLModelView);
}
}
@@ -5831,6 +5827,12 @@ void LLPipeline::renderBloom(BOOL for_snapshot, F32 zoom_factor, int subfield)
gGL.getTexUnit(0)->activate();
gGL.getTexUnit(0)->setTextureBlendType(LLTexUnit::TB_MULT);
+
+ if (LLRenderTarget::sUseFBO)
+ { //copy depth buffer from mScreen to framebuffer
+ LLRenderTarget::copyContentsToFramebuffer(mScreen, 0, 0, mScreen.getWidth(), mScreen.getHeight(),
+ 0, 0, mScreen.getWidth(), mScreen.getHeight(), GL_DEPTH_BUFFER_BIT, GL_NEAREST);
+ }
}
@@ -6907,6 +6909,24 @@ void LLPipeline::renderDeferredLighting()
mRenderTypeMask = render_mask;
}
+ {
+ //render highlights, etc.
+ renderHighlights();
+ mHighlightFaces.clear();
+
+ renderDebug();
+
+ LLVertexBuffer::unbind();
+
+ if (gPipeline.hasRenderDebugFeatureMask(LLPipeline::RENDER_DEBUG_FEATURE_UI))
+ {
+ // Render debugging beacons.
+ gObjectList.renderObjectBeacons();
+ LLHUDObject::renderAll();
+ gObjectList.resetObjectBeacons();
+ }
+ }
+
mScreen.flush();
}
@@ -7236,18 +7256,12 @@ void LLPipeline::generateWaterReflection(LLCamera& camera_in)
LLGLDisable cull(GL_CULL_FACE);
updateCull(camera, ref_result, 1);
stateSort(camera, ref_result);
- gGL.setColorMask(true, true);
- mWaterRef.clear();
- gGL.setColorMask(true, false);
-
- }
- else
- {
- gGL.setColorMask(true, true);
- mWaterRef.clear();
- gGL.setColorMask(true, false);
- }
-
+ }
+
+ gGL.setColorMask(true, true);
+ mWaterRef.clear();
+ gGL.setColorMask(true, false);
+
ref_mask = mRenderTypeMask;
mRenderTypeMask = mask;
}
@@ -8882,3 +8896,215 @@ LLCullResult::sg_list_t::iterator LLPipeline::endAlphaGroups()
}
+void LLPipeline::loadMesh(LLVOVolume* vobj, LLUUID mesh_id, S32 detail)
+{
+ {
+ LLMutexLock lock(mMeshMutex);
+ //add volume to list of loading meshes
+ mesh_load_map::iterator iter = mLoadingMeshes.find(mesh_id);
+ if (iter != mLoadingMeshes.end())
+ { //request pending for this mesh, append volume id to list
+ iter->second.insert(vobj->getID());
+ return;
+ }
+
+ //first request for this mesh
+ mLoadingMeshes[mesh_id].insert(vobj->getID());
+ }
+
+ if (gAssetStorage->hasLocalAsset(mesh_id, LLAssetType::AT_MESH))
+ { //already have asset, load desired LOD in background
+ mPendingMeshes.push_back(new LLMeshThread(mesh_id, vobj->getVolume()));
+ }
+ else
+ { //fetch asset and load when done
+ gAssetStorage->getAssetData(mesh_id, LLAssetType::AT_MESH,
+ getMeshAssetCallback, vobj->getVolume(), TRUE);
+ }
+
+ //do a quick search to see if we can't display something while we wait for this mesh to load
+ LLVolume* volume = vobj->getVolume();
+
+ if (volume)
+ {
+ LLVolumeParams params = volume->getParams();
+
+ LLVolumeLODGroup* group = LLPrimitive::getVolumeManager()->getGroup(params);
+
+ if (group)
+ {
+ //first see what the next lowest LOD available might be
+ for (S32 i = detail-1; i >= 0; --i)
+ {
+ LLVolume* lod = group->refLOD(i);
+ if (lod && lod->getNumVolumeFaces() > 0)
+ {
+ volume->copyVolumeFaces(lod);
+ group->derefLOD(lod);
+ return;
+ }
+
+ group->derefLOD(lod);
+ }
+
+ //no lower LOD is a available, is a higher lod available?
+ for (S32 i = detail+1; i < 4; ++i)
+ {
+ LLVolume* lod = group->refLOD(i);
+ if (lod && lod->getNumVolumeFaces() > 0)
+ {
+ volume->copyVolumeFaces(lod);
+ group->derefLOD(lod);
+ return;
+ }
+
+ group->derefLOD(lod);
+ }
+ }
+ }
+}
+
+//static
+void LLPipeline::getMeshAssetCallback(LLVFS *vfs,
+ const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status)
+{
+ gPipeline.mPendingMeshes.push_back(new LLMeshThread(asset_uuid, (LLVolume*) user_data));
+}
+
+
+LLPipeline::LLMeshThread::LLMeshThread(LLUUID mesh_id, LLVolume* target)
+: LLThread("mesh_loading_thread")
+{
+ mMeshID = mesh_id;
+ mVolume = NULL;
+ mDetail = target->getDetail();
+ mTargetVolume = target;
+}
+
+LLPipeline::LLMeshThread::~LLMeshThread()
+{
+
+}
+
+void LLPipeline::LLMeshThread::run()
+{
+ if (!gAssetStorage || LLApp::instance()->isQuitting())
+ {
+ return;
+ }
+
+ char* buffer = NULL;
+ S32 size = 0;
+
+ LLVFS* vfs = gAssetStorage->mVFS;
+
+ {
+ LLVFile file(vfs, mMeshID, LLAssetType::AT_MESH, LLVFile::READ);
+ file.waitForLock(VFSLOCK_READ);
+ size = file.getSize();
+
+ if (size == 0)
+ {
+ gPipeline.meshLoaded(this);
+ return;
+ }
+
+ buffer = new char[size];
+ file.read((U8*)&buffer[0], size);
+ }
+
+ {
+ std::string buffer_string(buffer, size);
+ std::istringstream buffer_stream(buffer_string);
+
+ {
+ LLVolumeParams volume_params;
+ volume_params.setType(LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE);
+ volume_params.setSculptID(mMeshID, LL_SCULPT_TYPE_MESH);
+ mVolume = new LLVolume(volume_params, mDetail);
+ mVolume->createVolumeFacesFromStream(buffer_stream);
+ }
+ }
+ delete[] buffer;
+
+ gPipeline.meshLoaded(this);
+}
+
+void LLPipeline::meshLoaded(LLPipeline::LLMeshThread* mesh_thread)
+{
+ LLMutexLock lock(mMeshMutex);
+ mLoadedMeshes.push_back(mesh_thread);
+}
+
+void LLPipeline::notifyLoadedMeshes()
+{ //called from main thread
+
+ U32 max_thread_count = llmax(gSavedSettings.getU32("MeshThreadCount"), (U32) 1);
+ while (mMeshThreadCount < max_thread_count && !mPendingMeshes.empty())
+ {
+ LLMeshThread* mesh_thread = mPendingMeshes.front();
+ mesh_thread->start();
+ ++mMeshThreadCount;
+ mPendingMeshes.pop_front();
+ }
+
+ LLMutexLock lock(mMeshMutex);
+ std::list<LLMeshThread*> stopping_threads;
+
+ for (std::list<LLMeshThread*>::iterator iter = mLoadedMeshes.begin(); iter != mLoadedMeshes.end(); ++iter)
+ { //for each mesh done loading
+ LLMeshThread* mesh = *iter;
+
+ if (!mesh->isStopped())
+ { //don't process a LLMeshThread until it's stopped
+ stopping_threads.push_back(mesh);
+ continue;
+ }
+
+ //get list of objects waiting to be notified this mesh is loaded
+ mesh_load_map::iterator obj_iter = mLoadingMeshes.find(mesh->mMeshID);
+
+ if (mesh->mVolume && obj_iter != mLoadingMeshes.end())
+ {
+ //make sure target volume is still valid
+ BOOL valid = FALSE;
+
+ for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+ {
+ LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
+
+ if (vobj)
+ {
+ if (vobj->getVolume() == mesh->mTargetVolume)
+ {
+ valid = TRUE;
+ }
+ }
+ }
+
+
+ if (valid)
+ {
+ mesh->mTargetVolume->copyVolumeFaces(mesh->mVolume);
+ for (std::set<LLUUID>::iterator vobj_iter = obj_iter->second.begin(); vobj_iter != obj_iter->second.end(); ++vobj_iter)
+ {
+ LLVOVolume* vobj = (LLVOVolume*) gObjectList.findObject(*vobj_iter);
+ if (vobj)
+ {
+ vobj->notifyMeshLoaded();
+ }
+ }
+ }
+
+ mLoadingMeshes.erase(mesh->mMeshID);
+ }
+
+ delete mesh;
+ --mMeshThreadCount;
+ }
+
+ mLoadedMeshes = stopping_threads;
+}
+
diff --git a/indra/newview/pipeline.h b/indra/newview/pipeline.h
index ce50a37405..3300f866e3 100644
--- a/indra/newview/pipeline.h
+++ b/indra/newview/pipeline.h
@@ -278,6 +278,10 @@ public:
LLCullResult::sg_list_t::iterator beginAlphaGroups();
LLCullResult::sg_list_t::iterator endAlphaGroups();
+
+ //mesh management functions
+ void loadMesh(LLVOVolume* volume, LLUUID mesh_id, S32 detail = 0);
+
void addTrianglesDrawn(S32 count);
BOOL hasRenderType(const U32 type) const { return (type && (mRenderTypeMask & (1<<type))) ? TRUE : FALSE; }
BOOL hasRenderDebugFeatureMask(const U32 mask) const { return (mRenderDebugFeatureMask & mask) ? TRUE : FALSE; }
@@ -672,6 +676,35 @@ public:
protected:
std::vector<LLFace*> mSelectedFaces;
+ typedef std::map<LLUUID, std::set<LLUUID> > mesh_load_map;
+ mesh_load_map mLoadingMeshes;
+
+ LLMutex* mMeshMutex;
+
+ class LLMeshThread : public LLThread
+ {
+ public:
+ LLPointer<LLVolume> mVolume;
+ LLVolume* mTargetVolume;
+ LLUUID mMeshID;
+ F32 mDetail;
+ LLMeshThread(LLUUID mesh_id, LLVolume* target);
+ ~LLMeshThread();
+ void run();
+ };
+
+ static void getMeshAssetCallback(LLVFS *vfs,
+ const LLUUID& asset_uuid,
+ LLAssetType::EType type,
+ void* user_data, S32 status, LLExtStat ext_status);
+
+ std::list<LLMeshThread*> mLoadedMeshes;
+ std::list<LLMeshThread*> mPendingMeshes;
+ U32 mMeshThreadCount;
+
+ void meshLoaded(LLMeshThread* mesh_thread);
+ void notifyLoadedMeshes();
+
LLPointer<LLViewerFetchedTexture> mFaceSelectImagep;
LLPointer<LLViewerTexture> mBloomImagep;
LLPointer<LLViewerTexture> mBloomImage2p;
diff --git a/indra/newview/skins/default/textures/textures.xml b/indra/newview/skins/default/textures/textures.xml
index fba8e0b06c..0b2effe90a 100644
--- a/indra/newview/skins/default/textures/textures.xml
+++ b/indra/newview/skins/default/textures/textures.xml
@@ -617,6 +617,8 @@
<texture name="icon_popular.tga" />
<texture name="icon_top_pick.tga" />
+ <texture name="inv_folder_mesh.tga"/>
+ <texture name="inv_item_mesh.tga"/>
<texture name="lag_status_critical.tga" />
<texture name="lag_status_good.tga" />
<texture name="lag_status_warning.tga" />
diff --git a/indra/newview/skins/default/xui/en/floater_about.xml b/indra/newview/skins/default/xui/en/floater_about.xml
index 2ff99dcf5a..056d08e6da 100644
--- a/indra/newview/skins/default/xui/en/floater_about.xml
+++ b/indra/newview/skins/default/xui/en/floater_about.xml
@@ -144,17 +144,20 @@ It is a rare mind indeed that can render the hitherto non-existent blindingly ob
word_wrap="true">
3Dconnexion SDK Copyright (C) 1992-2007 3Dconnexion
APR Copyright (C) 2000-2004 The Apache Software Foundation
+ Collada DOM Copyright 2005 Sony Computer Entertainment Inc.
cURL Copyright (C) 1996-2002, Daniel Stenberg, (daniel@haxx.se)
DBus/dbus-glib Copyright (C) 2002, 2003 CodeFactory AB / Copyright (C) 2003, 2004 Red Hat, Inc.
expat Copyright (C) 1998, 1999, 2000 Thai Open Source Software Center Ltd.
FreeType Copyright (C) 1996-2002, The FreeType Project (www.freetype.org).
GL Copyright (C) 1999-2004 Brian Paul.
+ GLOD Copyright (C) 2003-04 Jonathan Cohen, Nat Duca, Chris Niski, Johns Hopkins University and David Luebke, Brenden Schubert, University of Virginia.
google-perftools Copyright (c) 2005, Google Inc.
Havok.com(TM) Copyright (C) 1999-2001, Telekinesys Research Limited.
jpeg2000 Copyright (C) 2001, David Taubman, The University of New South Wales (UNSW)
jpeglib Copyright (C) 1991-1998, Thomas G. Lane.
ogg/vorbis Copyright (C) 2001, Xiphophorus
OpenSSL Copyright (C) 1998-2002 The OpenSSL Project.
+ PCRE Copyright (c) 1997-2008 University of Cambridge
Pth Copyright (C) 1999-2006 Ralf S. Engelschall &lt;rse@gnu.org&gt;
SDL Copyright (C) 1997, 1998, 1999, 2000, 2001, 2002 Sam Lantinga
SSLeay Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
diff --git a/indra/newview/skins/default/xui/en/floater_inventory.xml b/indra/newview/skins/default/xui/en/floater_inventory.xml
index 30639f955f..5720030af4 100644
--- a/indra/newview/skins/default/xui/en/floater_inventory.xml
+++ b/indra/newview/skins/default/xui/en/floater_inventory.xml
@@ -42,4 +42,25 @@
top="15"
width="467">
</panel>
+ <menu_item_call
+ label="Model (L$[COST])..."
+ layout="topleft"
+ name="Upload Model">
+ <menu_item_call.on_click
+ function="File.UploadModel"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Scene..."
+ layout="topleft"
+ name="Upload Scene">
+ <menu_item_call.on_click
+ function="File.UploadScene"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml
index c33d7cf31d..0348393bd3 100644
--- a/indra/newview/skins/default/xui/en/floater_tools.xml
+++ b/indra/newview/skins/default/xui/en/floater_tools.xml
@@ -1980,6 +1980,9 @@ even though the user gets a free copy.
label="Cylinder"
name="Cylinder"
value="Cylinder" />
+ <combo_box.item
+ label="Mesh"
+ value="Mesh" />
</combo_box>
</panel>
diff --git a/indra/newview/skins/default/xui/en/menu_viewer.xml b/indra/newview/skins/default/xui/en/menu_viewer.xml
index 1499095bcc..9edfc93be1 100644
--- a/indra/newview/skins/default/xui/en/menu_viewer.xml
+++ b/indra/newview/skins/default/xui/en/menu_viewer.xml
@@ -1,3698 +1,3698 @@
-<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
-<menu_bar
- bg_visible="false"
- follows="left|top|right"
- layout="topleft"
- name="Main Menu">
- <menu
- label="Me"
- layout="topleft"
- name="Me"
- tear_off="true">
- <menu_item_call
- label="Preferences"
- layout="topleft"
- name="Preferences"
- shortcut="control|P">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="preferences" />
- </menu_item_call>
- <menu_item_call
- label="My Dashboard"
- layout="topleft"
- name="Manage My Account">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="ManageMyAccount_url"
- parameter="WebLaunchJoinNow,http://secondlife.com/account/" />
- </menu_item_call>
- <menu_item_call
- label="Buy L$"
- layout="topleft"
- name="Buy and Sell L$">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="buy currency" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="My Profile"
- layout="topleft"
- name="Profile">
- <menu_item_call.on_click
- function="ShowAgentProfile"
- parameter="agent" />
- </menu_item_call>
- <menu_item_call
- label="My Appearance"
- layout="topleft"
- name="Appearance">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="appearance" />
- <menu_item_call.on_enable
- function="Edit.EnableCustomizeAvatar" />
- </menu_item_call>
- <menu_item_check
- label="My Inventory"
- layout="topleft"
- name="Inventory"
- shortcut="control|I">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="inventory" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="inventory" />
- </menu_item_check>
- <menu_item_call
- label="My Gestures"
- layout="topleft"
- name="Gestures"
- shortcut="control|G">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="gestures" />
- </menu_item_call>
- <menu
- label="My Status"
- layout="topleft"
- name="Status"
- tear_off="true">
- <menu_item_call
- label="Away"
- layout="topleft"
- name="Set Away">
- <menu_item_call.on_click
- function="World.SetAway" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft"/>
- <menu_item_call
- label="Busy"
- layout="topleft"
- name="Set Busy">
- <menu_item_call.on_click
- function="World.SetBusy"/>
- </menu_item_call>
- </menu>
- <menu_item_call
- label="Request Admin Status"
- layout="topleft"
- name="Request Admin Options"
- shortcut="control|alt|G"
- visible="false">
- <menu_item_call.on_click
- function="Advanced.RequestAdminStatus" />
- </menu_item_call>
- <menu_item_call
- label="Leave Admin Status"
- layout="topleft"
- name="Leave Admin Options"
- shortcut="control|alt|shift|G"
- visible="false">
- <menu_item_call.on_click
- function="Advanced.LeaveAdminStatus" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Quit [APP_NAME]"
- layout="topleft"
- name="Quit"
- shortcut="control|Q">
- <menu_item_call.on_click
- function="File.Quit" />
- </menu_item_call>
- </menu>
- <menu
- label="Communicate"
- layout="topleft"
- name="Communicate"
- tear_off="true">
- <menu_item_call
- label="My Friends"
- layout="topleft"
- name="My Friends"
- shortcut="control|shift|F">
- <menu_item_call.on_click
- function="SideTray.PanelPeopleTab"
- parameter="friends_panel" />
- </menu_item_call>
- <menu_item_call
- label="My Groups"
- layout="topleft"
- name="My Groups">
- <menu_item_call.on_click
- function="SideTray.PanelPeopleTab"
- parameter="groups_panel" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <!--menu_item_call
- label="Chat"
- layout="topleft"
- name="Chat">
- <menu_item_call.on_click
- function="World.Chat" />
- </menu_item_call-->
- <menu_item_check
- label="Nearby Chat"
- layout="topleft"
- name="Nearby Chat"
- shortcut="control|H">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="nearby_chat" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="nearby_chat" />
- </menu_item_check>
- <menu_item_call
- label="Nearby People"
- layout="topleft"
- name="Active Speakers"
- shortcut="control|shift|A">
- <menu_item_call.on_click
- function="SideTray.PanelPeopleTab"
- parameter="nearby_panel" />
- </menu_item_call>
- <menu_item_check
- label="Nearby Media"
- layout="topleft"
- name="Nearby Media"
- shortcut="control|alt|N">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="nearby_media" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="nearby_media" />
- </menu_item_check>
- <!--menu_item_check
- label="Block List"
- layout="topleft"
- name="Mute List">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="mute" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="mute" />
- </menu_item_check-->
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="(Legacy) Communicate"
- layout="topleft"
- name="Instant Message"
- shortcut="control|T">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="communicate" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="communicate" />
- </menu_item_check>
- <menu_item_call
- label="(Temp) Media Remote Ctrl"
- layout="topleft"
- name="Preferences"
- shortcut="control|alt|M">
- <menu_item_call.on_click
- function="Floater.Toggle"
- parameter="media_remote_ctrl" />
- </menu_item_call>
- </menu>
- <menu
- label="World"
- layout="topleft"
- name="World"
- tear_off="true">
- <menu_item_check
- label="Move"
- layout="topleft"
- name="Movement Controls">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="moveview" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="moveview" />
- </menu_item_check>
- <menu_item_check
- label="View"
- layout="topleft"
- name="Camera Controls">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="camera" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="camera" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="About Land"
- layout="topleft"
- name="About Land">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="about_land" />
- </menu_item_call>
- <menu_item_call
- label="Region/Estate"
- layout="topleft"
- name="Region/Estate">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="region_info" />
- </menu_item_call>
- <menu_item_call
- label="Buy Land"
- layout="topleft"
- name="Buy Land">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="buy land" />
- <menu_item_call.on_enable
- function="World.EnableBuyLand" />
- </menu_item_call>
- <menu_item_call
- label="My Land"
- layout="topleft"
- name="My Land">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="land_holdings" />
- </menu_item_call>
- <menu
- create_jump_keys="true"
- label="Show"
- layout="topleft"
- name="Land"
- tear_off="true">
- <menu_item_check
- label="Ban Lines"
- layout="topleft"
- name="Ban Lines">
- <menu_item_check.on_check
- control="ShowBanLines" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowBanLines" />
- </menu_item_check>
- <menu_item_check
- label="Beacons"
- layout="topleft"
- name="beacons"
- shortcut="control|alt|shift|N">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="beacons" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="beacons" />
- </menu_item_check>
- <menu_item_check
- label="Property Lines"
- layout="topleft"
- name="Property Lines"
- shortcut="control|alt|shift|P">
- <menu_item_check.on_check
- control="ShowPropertyLines" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowPropertyLines" />
- </menu_item_check>
- <menu_item_check
- label="Land Owners"
- layout="topleft"
- name="Land Owners">
- <menu_item_check.on_check
- control="ShowParcelOwners" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowParcelOwners" />
- </menu_item_check>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu
- label="Landmarks"
- layout="topleft"
- name="Landmarks"
- tear_off="true">
- <menu_item_call
- label="Create Landmark Here"
- layout="topleft"
- name="Create Landmark Here">
- <menu_item_call.on_click
- function="World.CreateLandmark" />
- <menu_item_call.on_enable
- function="World.EnableCreateLandmark" />
- </menu_item_call>
- <menu_item_call
- label="Set Home to Here"
- layout="topleft"
- name="Set Home to Here">
- <menu_item_call.on_click
- function="World.SetHomeLocation" />
- <menu_item_call.on_enable
- function="World.EnableSetHomeLocation" />
- </menu_item_call>
- <menu_item_call
- label="Teleport Home"
- layout="topleft"
- name="Teleport Home"
- shortcut="control|shift|H">
- <menu_item_call.on_click
- function="World.TeleportHome" />
- <menu_item_call.on_enable
- function="World.EnableTeleportHome" />
- </menu_item_call>
- </menu>
- <menu_item_check
- label="Mini-Map"
- layout="topleft"
- name="Mini-Map"
- shortcut="control|shift|M">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="mini_map" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="mini_map" />
- </menu_item_check>
- <menu_item_check
- label="World Map"
- layout="topleft"
- name="World Map"
- shortcut="control|M"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="world_map" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="world_map" />
- </menu_item_check>
- <!-- <menu_item_check
- label="Show Navigation Bar"
- layout="topleft"
- name="ShowNavbarNavigationPanel">
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowNavbarNavigationPanel" />
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowNavbarNavigationPanel" />
- </menu_item_check>
- <menu_item_check
- label="Show Favorites Bar"
- layout="topleft"
- name="ShowNavbarFavoritesPanel">
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowNavbarFavoritesPanel" />
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowNavbarFavoritesPanel" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />-->
- <menu_item_call
- label="Snapshot"
- layout="topleft"
- name="Take Snapshot"
- shortcut="control|shift|S">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="snapshot" />
- </menu_item_call>
- <menu
- create_jump_keys="true"
- label="Sun"
- layout="topleft"
- name="Environment Settings"
- tear_off="true">
- <menu_item_call
- label="Sunrise"
- layout="topleft"
- name="Sunrise">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="sunrise" />
- </menu_item_call>
- <menu_item_call
- label="Midday"
- layout="topleft"
- name="Noon"
- shortcut="control|shift|Y">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="noon" />
- </menu_item_call>
- <menu_item_call
- label="Sunset"
- layout="topleft"
- name="Sunset"
- shortcut="control|shift|N">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="sunset" />
- </menu_item_call>
- <menu_item_call
- label="Midnight"
- layout="topleft"
- name="Midnight">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="midnight" />
- </menu_item_call>
- <menu_item_call
- label="Use the Estate Time"
- layout="topleft"
- name="Revert to Region Default">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="default" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Environment Editor"
- layout="topleft"
- name="Environment Editor">
- <menu_item_call.on_click
- function="World.EnvSettings"
- parameter="editor" />
- </menu_item_call>
- </menu>
- </menu>
- <menu
- create_jump_keys="true"
- label="Build"
- layout="topleft"
- name="BuildTools"
- tear_off="true"
- visible="true">
- <menu_item_check
- label="Build"
- layout="topleft"
- name="Show Build Tools"
- shortcut="control|B">
- <menu_item_check.on_check
- function="Build.Active" />
- <menu_item_check.on_click
- function="Build.Toggle" />
- <menu_item_check.on_enable
- function="Build.Enabled" />
- </menu_item_check>
- <menu
- create_jump_keys="true"
- label="Select Build Tool"
- layout="topleft"
- name="Select Tool"
- tear_off="true">
- <menu_item_call
- label="Focus Tool"
- layout="topleft"
- name="Focus"
- shortcut="control|1">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="focus" />
- </menu_item_call>
- <menu_item_call
- label="Move Tool"
- layout="topleft"
- name="Move"
- shortcut="control|2">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="move" />
- </menu_item_call>
- <menu_item_call
- label="Edit Tool"
- layout="topleft"
- name="Edit"
- shortcut="control|3">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="edit" />
- </menu_item_call>
- <menu_item_call
- label="Create Tool"
- layout="topleft"
- name="Create"
- shortcut="control|4">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="create" />
- </menu_item_call>
- <menu_item_call
- label="Land Tool"
- layout="topleft"
- name="Land"
- shortcut="control|5">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="land" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Edit"
- layout="topleft"
- name="Edit"
- tear_off="true">
- <menu_item_call
- label="Undo"
- layout="topleft"
- name="Undo"
- shortcut="control|Z">
- <menu_item_call.on_click
- function="Edit.Undo" />
- <menu_item_call.on_enable
- function="Edit.EnableUndo" />
- </menu_item_call>
- <menu_item_call
- label="Redo"
- layout="topleft"
- name="Redo"
- shortcut="control|Y">
- <menu_item_call.on_click
- function="Edit.Redo" />
- <menu_item_call.on_enable
- function="Edit.EnableRedo" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Cut"
- layout="topleft"
- name="Cut"
- shortcut="control|X">
- <menu_item_call.on_click
- function="Edit.Cut" />
- <menu_item_call.on_enable
- function="Edit.EnableCut" />
- </menu_item_call>
- <menu_item_call
- label="Copy"
- layout="topleft"
- name="Copy"
- shortcut="control|C">
- <menu_item_call.on_click
- function="Edit.Copy" />
- <menu_item_call.on_enable
- function="Edit.EnableCopy" />
- </menu_item_call>
- <menu_item_call
- label="Paste"
- layout="topleft"
- name="Paste"
- shortcut="control|V">
- <menu_item_call.on_click
- function="Edit.Paste" />
- <menu_item_call.on_enable
- function="Edit.EnablePaste" />
- </menu_item_call>
- <menu_item_call
- label="Delete"
- layout="topleft"
- name="Delete"
- shortcut="Del">
- <menu_item_call.on_click
- function="Edit.Delete" />
- <menu_item_call.on_enable
- function="Edit.EnableDelete" />
- </menu_item_call>
- <menu_item_call
- label="Duplicate"
- layout="topleft"
- name="Duplicate"
- shortcut="control|D">
- <menu_item_call.on_click
- function="Edit.Duplicate" />
- <menu_item_call.on_enable
- function="Edit.EnableDuplicate" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Select All"
- layout="topleft"
- name="Select All"
- shortcut="control|A">
- <menu_item_call.on_click
- function="Edit.SelectAll" />
- <menu_item_call.on_enable
- function="Edit.EnableSelectAll" />
- </menu_item_call>
- <menu_item_call
- label="Deselect"
- layout="topleft"
- name="Deselect"
- shortcut="control|E">
- <menu_item_call.on_click
- function="Edit.Deselect" />
- <menu_item_call.on_enable
- function="Edit.EnableDeselect" />
- </menu_item_call>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Link"
- layout="topleft"
- name="Link"
- shortcut="control|L">
- <menu_item_call.on_click
- function="Tools.Link" />
- <menu_item_call.on_enable
- function="Tools.EnableLink" />
- </menu_item_call>
- <menu_item_call
- label="Unlink"
- layout="topleft"
- name="Unlink"
- shortcut="control|shift|L">
- <menu_item_call.on_click
- function="Tools.Unlink" />
- <menu_item_call.on_enable
- function="Tools.EnableUnlink" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Focus on Selection"
- layout="topleft"
- name="Focus on Selection"
- shortcut="H">
- <menu_item_call.on_click
- function="Tools.LookAtSelection"
- parameter="focus" />
- <menu_item_call.on_enable
- function="Tools.SomethingSelectedNoHUD" />
- </menu_item_call>
- <menu_item_call
- label="Zoom to Selection"
- layout="topleft"
- name="Zoom to Selection"
- shortcut="shift|H">
- <menu_item_call.on_click
- function="Tools.LookAtSelection"
- parameter="zoom" />
- <menu_item_call.on_enable
- function="Tools.SomethingSelectedNoHUD" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Object"
- layout="topleft"
- name="Object"
- tear_off="true">
- <menu_item_call
- label="Buy"
- layout="topleft"
- name="Menu Object Take"
- visible="true">
- <menu_item_call.on_click
- function="Tools.BuyOrTake" />
- <menu_item_call.on_enable
- function="Tools.EnableBuyOrTake"
- name="EnableBuyOrTake"
- parameter="Buy,Take" />
- </menu_item_call>
- <menu_item_call
- label="Take Copy"
- layout="topleft"
- name="Take Copy">
- <menu_item_call.on_click
- function="Tools.TakeCopy" />
- <menu_item_call.on_enable
- function="Tools.EnableTakeCopy" />
- </menu_item_call>
- <menu_item_call
- label="Save Back to My Inventory"
- layout="topleft"
- name="Save Object Back to My Inventory">
- <menu_item_call.on_click
- function="Tools.SaveToInventory" />
- <menu_item_call.on_enable
- function="Tools.EnableSaveToInventory" />
- </menu_item_call>
- <menu_item_call
- label="Save Back to Object Contents"
- layout="topleft"
- name="Save Object Back to Object Contents">
- <menu_item_call.on_click
- function="Tools.SaveToObjectInventory" />
- <menu_item_call.on_enable
- function="Tools.EnableSaveToObjectInventory" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Scripts"
- layout="topleft"
- name="Scripts"
- tear_off="true">
- <menu_item_call
- label="Recompile Scripts (Mono)"
- layout="topleft"
- name="Mono">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="compile mono" />
- <menu_item_call.on_enable
- function="EditableSelectedMono" />
- </menu_item_call>
- <menu_item_call
- label="Recompile Scripts (LSL)"
- layout="topleft"
- name="LSL">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="compile lsl" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- <menu_item_call
- label="Reset Scripts"
- layout="topleft"
- name="Reset Scripts">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="reset" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- <menu_item_call
- label="Set Scripts to Running"
- layout="topleft"
- name="Set Scripts to Running">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="start" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- <menu_item_call
- label="Set Scripts to Not Running"
- layout="topleft"
- name="Set Scripts to Not Running">
- <menu_item_call.on_click
- function="Tools.SelectedScriptAction"
- parameter="stop" />
- <menu_item_call.on_enable
- function="EditableSelected" />
- </menu_item_call>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Options"
- layout="topleft"
- name="Options"
- tear_off="true">
- <menu_item_check
- label="Edit Linked Parts"
- layout="topleft"
- name="Edit Linked Parts">
- <menu_item_check.on_check
- control="EditLinkedParts" />
- <menu_item_check.on_click
- function="Tools.EditLinkedParts"
- parameter="EditLinkedParts" />
- <menu_item_check.on_enable
- function="Tools.EnableToolNotPie" />
- </menu_item_check>
- <menu_item_call
- label="Set Default Upload Permissions"
- layout="topleft"
- name="perm prefs">
- <menu_item_call.on_click
- function="Floater.Toggle"
- parameter="perm_prefs" />
- <menu_item_check
- label="Show Advanced Permissions"
- layout="topleft"
- name="DebugPermissions">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugPermissions" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugPermissions" />
- </menu_item_check>
- </menu_item_call>
- <!--menu_item_call
- label="Show Script Warning/Error Window"
- layout="topleft"
- name="Show Script Warning/Error Window">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="script errors" />
- </menu_item_call-->
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Selection"
- layout="topleft"
- name="Selection"
- tear_off="true">
- <menu_item_check
- label="Select Only My Objects"
- layout="topleft"
- name="Select Only My Objects">
- <menu_item_check.on_check
- control="SelectOwnedOnly" />
- <menu_item_check.on_click
- function="Tools.SelectOnlyMyObjects"
- parameter="agents" />
- </menu_item_check>
- <menu_item_check
- label="Select Only Movable Objects"
- layout="topleft"
- name="Select Only Movable Objects">
- <menu_item_check.on_check
- control="SelectMovableOnly" />
- <menu_item_check.on_click
- function="Tools.SelectOnlyMovableObjects"
- parameter="movable" />
- </menu_item_check>
- <menu_item_check
- label="Select By Surrounding"
- layout="topleft"
- name="Select By Surrounding">
- <menu_item_check.on_check
- control="RectangleSelectInclusive" />
- <menu_item_check.on_click
- function="Tools.SelectBySurrounding" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Show"
- layout="topleft"
- name="Show"
- tear_off="true">
- <menu_item_check
- label="Show Hidden Selection"
- layout="topleft"
- name="Show Hidden Selection">
- <menu_item_check.on_check
- control="RenderHiddenSelections" />
- <menu_item_check.on_click
- function="Tools.ShowHiddenSelection" />
- </menu_item_check>
- <menu_item_check
- label="Show Light Radius for Selection"
- layout="topleft"
- name="Show Light Radius for Selection">
- <menu_item_check.on_check
- control="RenderLightRadius" />
- <menu_item_check.on_click
- function="Tools.ShowSelectionLightRadius" />
- </menu_item_check>
- <menu_item_check
- label="Show Selection Beam"
- layout="topleft"
- name="Show Selection Beam">
- <menu_item_check.on_check
- control="ShowSelectionBeam" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowSelectionBeam" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Grid"
- layout="topleft"
- name="Grid"
- tear_off="true">
- <menu_item_check
- label="Snap to Grid"
- layout="topleft"
- name="Snap to Grid"
- shortcut="G">
- <menu_item_check.on_check
- control="SnapEnabled" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="SnapEnabled" />
- <menu_item_check.on_enable
- function="Tools.EnableToolNotPie" />
- </menu_item_check>
- <menu_item_call
- label="Snap Object XY to Grid"
- layout="topleft"
- name="Snap Object XY to Grid"
- shortcut="shift|X">
- <menu_item_call.on_click
- function="Tools.SnapObjectXY" />
- <menu_item_call.on_enable
- function="Tools.EnableToolNotPie" />
- </menu_item_call>
- <menu_item_call
- label="Use Selection for Grid"
- layout="topleft"
- name="Use Selection for Grid"
- shortcut="shift|G">
- <menu_item_call.on_click
- function="Tools.UseSelectionForGrid" />
- <menu_item_call.on_enable
- function="SomethingSelected" />
- </menu_item_call>
- <menu_item_call
- label="Grid Options"
- layout="topleft"
- name="Grid Options"
- shortcut="control|shift|B">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="build_options" />
- <menu_item_call.on_enable
- function="Tools.EnableToolNotPie" />
- </menu_item_call>
- </menu>
- </menu>
- <menu
- create_jump_keys="true"
- label="Select Linked Parts"
- layout="topleft"
- name="Select Linked Parts"
- tear_off="true">
- <menu_item_call
- label="Select Next Part"
- layout="topleft"
- name="Select Next Part"
- shortcut="control|.">
- <menu_item_call.on_click
- function="Tools.SelectNextPart"
- parameter="next" />
- <menu_item_call.on_enable
- function="Tools.EnableSelectNextPart" />
- </menu_item_call>
- <menu_item_call
- label="Select Previous Part"
- layout="topleft"
- name="Select Previous Part"
- shortcut="control|,">
- <menu_item_call.on_click
- function="Tools.SelectNextPart"
- parameter="previous" />
- <menu_item_call.on_enable
- function="Tools.EnableSelectNextPart" />
- </menu_item_call>
- <menu_item_call
- label="Include Next Part"
- layout="topleft"
- name="Include Next Part"
- shortcut="control|shift|.">
- <menu_item_call.on_click
- function="Tools.SelectNextPart"
- parameter="includenext" />
- <menu_item_call.on_enable
- function="Tools.EnableSelectNextPart" />
- </menu_item_call>
- <menu_item_call
- label="Include Previous Part"
- layout="topleft"
- name="Include Previous Part"
- shortcut="control|shift|,">
- <menu_item_call.on_click
- function="Tools.SelectNextPart"
- parameter="includeprevious" />
- <menu_item_call.on_enable
- function="Tools.EnableSelectNextPart" />
- </menu_item_call>
- </menu>
- </menu>
- <menu
- label="Help"
- layout="topleft"
- name="Help"
- tear_off="true">
- <menu_item_call
- label="[SECOND_LIFE] Help"
- layout="topleft"
- name="Second Life Help"
- shortcut="F1">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="help f1" />
- </menu_item_call>
- <menu_item_call
- label="Tutorial"
- layout="topleft"
- name="Tutorial">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="hud" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Report Abuse"
- layout="topleft"
- name="Report Abuse">
- <menu_item_call.on_click
- function="ShowFloater"
- parameter="complaint reporter" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="About [APP_NAME]"
- layout="topleft"
- name="About Second Life">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="sl_about" />
- </menu_item_call>
- </menu>
- <menu
- label="Advanced"
- layout="topleft"
- name="Advanced"
- tear_off="true"
- visible="false">
- <menu_item_check
- label="Set Away After 30 Minutes"
- layout="topleft"
- name="Go Away/AFK When Idle">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="AllowIdleAFK" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="AllowIdleAFK" />
- </menu_item_check>
- <menu_item_call
- label="Stop Animating Me"
- layout="topleft"
- name="Stop Animating My Avatar">
- <menu_item_call.on_click
- function="Tools.StopAllAnimations" />
- </menu_item_call>
- <menu_item_call
- label="Rebake Textures"
- layout="topleft"
- name="Rebake Texture"
- shortcut="control|alt|R">
- <menu_item_call.on_click
- function="Advanced.RebakeTextures" />
- </menu_item_call>
- <menu_item_call
- label="Set UI Size to Default"
- layout="topleft"
- name="Set UI Size to Default">
- <menu_item_call.on_click
- function="View.DefaultUISize" />
- </menu_item_call>
- <menu_item_separator/>
- <menu_item_check
- label="Limit Select Distance"
- layout="topleft"
- name="Limit Select Distance">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="LimitSelectDistance" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="LimitSelectDistance" />
- </menu_item_check>
- <menu_item_check
- label="Disable Camera Constraints"
- layout="topleft"
- name="Disable Camera Distance">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DisableCameraConstraints" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DisableCameraConstraints" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="High-res Snapshot"
- layout="topleft"
- name="HighResSnapshot">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="HighResSnapshot" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="HighResSnapshot" />
- </menu_item_check>
- <menu_item_check
- label="Quiet Snapshots to Disk"
- layout="topleft"
- name="QuietSnapshotsToDisk">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="QuietSnapshotsToDisk" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="QuietSnapshotsToDisk" />
- </menu_item_check>
- <menu_item_check
- label="Compress Snapshots to Disk"
- layout="topleft"
- name="CompressSnapshotsToDisk">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="CompressSnapshotsToDisk" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="CompressSnapshotsToDisk" />
- </menu_item_check>
- <menu_item_call
- label="Save Texture As"
- layout="topleft"
- name="Save Texture As">
- <menu_item_call.on_click
- function="File.SaveTexture" />
- <menu_item_call.on_enable
- function="File.EnableSaveAs" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Performance Tools"
- layout="topleft"
- name="Performance Tools"
- tear_off="true">
- <menu_item_call
- label="Lag Meter"
- layout="topleft"
- name="Lag Meter">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="lagmeter" />
- </menu_item_call>
- <menu_item_check
- label="Statistics Bar"
- layout="topleft"
- name="Statistics Bar"
- shortcut="control|shift|1">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="stats" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="stats" />
- </menu_item_check>
- <menu_item_check
- label="Show Avatar Rendering Cost"
- layout="topleft"
- name="Avatar Rendering Cost">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="shame" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="shame" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Highlighting and Visibility"
- layout="topleft"
- name="Highlighting and Visibility"
- tear_off="true">
- <menu_item_check
- label="Cheesy Beacon"
- layout="topleft"
- name="Cheesy Beacon">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="CheesyBeacon" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="CheesyBeacon" />
- </menu_item_check>
- <menu_item_check
- label="Hide Particles"
- layout="topleft"
- name="Hide Particles"
- shortcut="control|alt|shift|=">
- <menu_item_check.on_check
- function="View.CheckRenderType"
- parameter="hideparticles" />
- <menu_item_check.on_click
- function="View.ToggleRenderType"
- parameter="hideparticles" />
- </menu_item_check>
- <menu_item_check
- label="Hide Selected"
- layout="topleft"
- name="Hide Selected">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="HideSelectedObjects" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="HideSelectedObjects" />
- </menu_item_check>
- <menu_item_check
- label="Highlight Transparent"
- layout="topleft"
- name="Highlight Transparent"
- shortcut="control|alt|T">
- <menu_item_check.on_check
- function="View.CheckHighlightTransparent" />
- <menu_item_check.on_click
- function="View.HighlightTransparent" />
- </menu_item_check>
- <menu_item_check
- label="Show HUD Attachments"
- layout="topleft"
- name="Show HUD Attachments"
- shortcut="alt|shift|H">
- <menu_item_check.on_check
- function="View.CheckHUDAttachments" />
- <menu_item_check.on_click
- function="View.ShowHUDAttachments" />
- </menu_item_check>
- <menu_item_check
- label="Show Mouselook Crosshairs"
- layout="topleft"
- name="ShowCrosshairs">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowCrosshairs" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowCrosshairs" />
- </menu_item_check>
- <!-- <menu
- create_jump_keys="true"
- label="Hover Tips"
- layout="topleft"
- name="Hover Tips"
- tear_off="true">
- <menu_item_check
- label="Show Tips"
- layout="topleft"
- name="Show Tips"
- shortcut="control|shift|T">
- <menu_item_check.on_check
- function="View.CheckShowHoverTips" />
- <menu_item_check.on_click
- function="View.ShowHoverTips" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />-->
- <menu_item_check
- label="Show Land Tooltips"
- layout="topleft"
- name="Land Tips">
- <menu_item_check.on_check
- control="ShowLandHoverTip" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowLandHoverTip" />
- <menu_item_check.on_enable
- function="View.CheckShowHoverTips" />
- </menu_item_check>
- <!-- <menu_item_check
- label="Show Tips On All Objects"
- layout="topleft"
- name="Tips On All Objects">
- <menu_item_check.on_check
- control="ShowAllObjectHoverTip" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowAllObjectHoverTip" />
- <menu_item_check.on_enable
- function="View.CheckShowHoverTips" />
- </menu_item_check>
- </menu>-->
-
- </menu>
-
- <menu
- create_jump_keys="true"
- label="Rendering Types"
- layout="topleft"
- name="Rendering Types"
- tear_off="true">
- <menu_item_check
- label="Simple"
- layout="topleft"
- name="Simple"
- shortcut="control|alt|shift|1">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="simple" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="simple" />
- </menu_item_check>
- <menu_item_check
- label="Alpha"
- layout="topleft"
- name="Alpha"
- shortcut="control|alt|shift|2">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="alpha" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="alpha" />
- </menu_item_check>
- <menu_item_check
- label="Tree"
- layout="topleft"
- name="Tree"
- shortcut="control|alt|shift|3">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="tree" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="tree" />
- </menu_item_check>
- <menu_item_check
- label="Avatars"
- layout="topleft"
- name="Character"
- shortcut="control|alt|shift|4">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="character" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="character" />
- </menu_item_check>
- <menu_item_check
- label="SurfacePath"
- layout="topleft"
- name="SurfacePath"
- shortcut="control|alt|shift|5">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="surfacePath" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="surfacePath" />
- </menu_item_check>
- <menu_item_check
- label="Sky"
- layout="topleft"
- name="Sky"
- shortcut="control|alt|shift|6">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="sky" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="sky" />
- </menu_item_check>
- <menu_item_check
- label="Water"
- layout="topleft"
- name="Water"
- shortcut="control|alt|shift|7">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="water" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="water" />
- </menu_item_check>
- <menu_item_check
- label="Ground"
- layout="topleft"
- name="Ground"
- shortcut="control|alt|shift|8">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="ground" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="ground" />
- </menu_item_check>
- <menu_item_check
- label="Volume"
- layout="topleft"
- name="Volume"
- shortcut="control|alt|shift|9">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="volume" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="volume" />
- </menu_item_check>
- <menu_item_check
- label="Grass"
- layout="topleft"
- name="Grass"
- shortcut="control|alt|shift|0">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="grass" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="grass" />
- </menu_item_check>
- <menu_item_check
- label="Clouds"
- layout="topleft"
- name="Clouds"
- shortcut="control|alt|shift|-">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="clouds" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="clouds" />
- </menu_item_check>
- <menu_item_check
- label="Particles"
- layout="topleft"
- name="Particles"
- shortcut="control|alt|shift|=">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="particles" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="particles" />
- </menu_item_check>
- <menu_item_check
- label="Bump"
- layout="topleft"
- name="Bump"
- shortcut="control|alt|shift|\">
- <menu_item_check.on_check
- function="Advanced.CheckRenderType"
- parameter="bump" />
- <menu_item_check.on_click
- function="Advanced.ToggleRenderType"
- parameter="bump" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Rendering Features"
- layout="topleft"
- name="Rendering Features"
- tear_off="true">
- <menu_item_check
- label="UI"
- layout="topleft"
- name="UI"
- shortcut="control|alt|F1">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="ui" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="ui" />
- </menu_item_check>
- <menu_item_check
- label="Selected"
- layout="topleft"
- name="Selected"
- shortcut="control|alt|F2">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="selected" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="selected" />
- </menu_item_check>
- <menu_item_check
- label="Highlighted"
- layout="topleft"
- name="Highlighted"
- shortcut="control|alt|F3">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="highlighted" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="highlighted" />
- </menu_item_check>
- <menu_item_check
- label="Dynamic Textures"
- layout="topleft"
- name="Dynamic Textures"
- shortcut="control|alt|F4">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="dynamic textures" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="dynamic textures" />
- </menu_item_check>
- <menu_item_check
- label="Foot Shadows"
- layout="topleft"
- name="Foot Shadows"
- shortcut="control|alt|F5">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="foot shadows" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="foot shadows" />
- </menu_item_check>
- <menu_item_check
- label="Fog"
- layout="topleft"
- name="Fog"
- shortcut="control|alt|F6">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="fog" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="fog" />
- </menu_item_check>
- <menu_item_check
- label="Test FRInfo"
- layout="topleft"
- name="Test FRInfo"
- shortcut="control|alt|F8">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="fr info" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="fr info" />
- </menu_item_check>
- <menu_item_check
- label="Flexible Objects"
- layout="topleft"
- name="Flexible Objects"
- shortcut="control|alt|F9">
- <menu_item_check.on_check
- function="Advanced.CheckFeature"
- parameter="flexible" />
- <menu_item_check.on_click
- function="Advanced.ToggleFeature"
- parameter="flexible" />
- </menu_item_check>
- </menu>
- <menu_item_check
- label="Run Multiple Threads"
- layout="topleft"
- name="Run Multiple Threads">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RunMultipleThreads" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RunMultipleThreads" />
- </menu_item_check>
- <menu_item_call
- label="Clear Group Cache"
- layout="topleft"
- name="ClearGroupCache">
- <menu_item_call.on_click
- function="Advanced.ClearGroupCache"
- parameter="ClearGroupCache" />
- </menu_item_call>
- <menu_item_check
- label="Mouse Smoothing"
- layout="topleft"
- name="Mouse Smoothing">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="MouseSmooth" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="MouseSmooth" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu
- label="Shortcuts"
- layout="topleft"
- name="Shortcuts"
- tear_off="true"
- visible="false">
- <menu_item_check
- label="Search"
- layout="topleft"
- name="Search"
- shortcut="control|F">
- <menu_item_check.on_check
- function="Floater.Visible"
- parameter="search" />
- <menu_item_check.on_click
- function="Floater.Toggle"
- parameter="search" />
- </menu_item_check>
- <menu_item_call
- enabled="false"
- label="Release Keys"
- layout="topleft"
- name="Release Keys">
- <menu_item_call.on_click
- function="Tools.ReleaseKeys"
- parameter="" />
- <menu_item_call.on_enable
- function="Tools.EnableReleaseKeys"
- parameter="" />
- </menu_item_call>
- <menu_item_call
- label="Set UI Size to Default"
- layout="topleft"
- name="Set UI Size to Default">
- <menu_item_call.on_click
- function="View.DefaultUISize" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="Always Run"
- layout="topleft"
- name="Always Run"
- shortcut="control|R">
- <menu_item_check.on_check
- function="World.CheckAlwaysRun" />
- <menu_item_check.on_click
- function="World.AlwaysRun" />
- </menu_item_check>
- <menu_item_check
- label="Fly"
- layout="topleft"
- name="Fly"
- shortcut="Home">
- <menu_item_check.on_click
- function="Agent.toggleFlying" />
- <menu_item_check.on_enable
- function="Agent.enableFlying" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Close Window"
- layout="topleft"
- name="Close Window"
- shortcut="control|W">
- <menu_item_call.on_click
- function="File.CloseWindow" />
- <menu_item_call.on_enable
- function="File.EnableCloseWindow" />
- </menu_item_call>
- <menu_item_call
- label="Close All Windows"
- layout="topleft"
- name="Close All Windows"
- shortcut="control|shift|W">
- <menu_item_call.on_click
- function="File.CloseAllWindows" />
- <menu_item_call.on_enable
- function="File.EnableCloseAllWindows" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Snapshot to Disk"
- layout="topleft"
- name="Snapshot to Disk"
- shortcut="control|`"
- use_mac_ctrl="true">
- <menu_item_call.on_click
- function="File.TakeSnapshotToDisk" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Mouselook"
- layout="topleft"
- name="Mouselook"
- shortcut="M">
- <menu_item_call.on_click
- function="View.Mouselook" />
- <menu_item_call.on_enable
- function="View.EnableMouselook" />
- </menu_item_call>
- <menu_item_check
- label="Joystick Flycam"
- layout="topleft"
- name="Joystick Flycam"
- shortcut="alt|shift|F">
- <menu_item_check.on_check
- function="View.CheckJoystickFlycam" />
- <menu_item_check.on_click
- function="View.JoystickFlycam" />
- <menu_item_check.on_enable
- function="View.EnableJoystickFlycam" />
- </menu_item_check>
- <menu_item_call
- label="Reset View"
- layout="topleft"
- name="Reset View"
- shortcut="Esc">
- <menu_item_call.on_click
- function="View.ResetView" />
- </menu_item_call>
- <menu_item_call
- label="Look at Last Chatter"
- layout="topleft"
- name="Look at Last Chatter"
- shortcut="control|\">
- <menu_item_call.on_click
- function="View.LookAtLastChatter" />
- <menu_item_call.on_enable
- function="View.EnableLastChatter" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Select Build Tool"
- layout="topleft"
- name="Select Tool"
- tear_off="true">
- <menu_item_call
- label="Focus Tool"
- layout="topleft"
- name="Focus"
- shortcut="control|1">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="focus" />
- </menu_item_call>
- <menu_item_call
- label="Move Tool"
- layout="topleft"
- name="Move"
- shortcut="control|2">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="move" />
- </menu_item_call>
- <menu_item_call
- label="Edit Tool"
- layout="topleft"
- name="Edit"
- shortcut="control|3">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="edit" />
- </menu_item_call>
- <menu_item_call
- label="Create Tool"
- layout="topleft"
- name="Create"
- shortcut="control|4">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="create" />
- </menu_item_call>
- <menu_item_call
- label="Land Tool"
- layout="topleft"
- name="Land"
- shortcut="control|5">
- <menu_item_call.on_click
- function="Tools.SelectTool"
- parameter="land" />
- </menu_item_call>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Zoom In"
- layout="topleft"
- name="Zoom In"
- shortcut="control|0">
- <menu_item_call.on_click
- function="View.ZoomIn" />
- </menu_item_call>
- <menu_item_call
- label="Zoom Default"
- layout="topleft"
- name="Zoom Default"
- shortcut="control|9">
- <menu_item_call.on_click
- function="View.ZoomDefault" />
- </menu_item_call>
- <menu_item_call
- label="Zoom Out"
- layout="topleft"
- name="Zoom Out"
- shortcut="control|8">
- <menu_item_call.on_click
- function="View.ZoomOut" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Toggle Fullscreen"
- layout="topleft"
- name="Toggle Fullscreen"
- >
- <!-- Note: shortcut="alt|Enter" was deleted from the preceding node-->
- <menu_item_call.on_click
- function="View.Fullscreen" />
- </menu_item_call>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Show Debug Settings"
- layout="topleft"
- name="Debug Settings">
- <menu_item_call.on_click
- function="Advanced.ShowDebugSettings"
- parameter="all" />
- </menu_item_call>
- <menu_item_check
- label="Show Develop Menu"
- layout="topleft"
- name="Debug Mode"
- shortcut="control|alt|Q">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="QAMode" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="QAMode" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Develop"
- layout="topleft"
- name="Develop"
- tear_off="true"
- visible="false">
- <menu
- create_jump_keys="true"
- label="Consoles"
- layout="topleft"
- name="Consoles"
- tear_off="true">
- <menu_item_check
- label="Texture Console"
- layout="topleft"
- name="Texture Console"
- shortcut="control|shift|3"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="texture" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="texture" />
- </menu_item_check>
- <menu_item_check
- label="Debug Console"
- layout="topleft"
- name="Debug Console"
- shortcut="control|shift|4"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="debug" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="debug" />
- </menu_item_check>
- <menu_item_call
- label="Notifications Console"
- layout="topleft"
- name="Notifications"
- shortcut="control|shift|5">
- <menu_item_call.on_click
- function="Floater.Toggle"
- parameter="notifications_console" />
- </menu_item_call>
- <menu_item_check
- label="Texture Size Console"
- layout="topleft"
- name="Texture Size"
- shortcut="control|shift|6">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="texture size" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="texture size" />
- </menu_item_check>
- <menu_item_check
- label="Texture Category Console"
- layout="topleft"
- name="Texture Category"
- shortcut="control|shift|7">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="texture category" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="texture category" />
- </menu_item_check>
- <menu_item_check
- label="Fast Timers"
- layout="topleft"
- name="Fast Timers"
- shortcut="control|shift|9"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="fast timers" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="fast timers" />
- </menu_item_check>
- <menu_item_check
- label="Memory"
- layout="topleft"
- name="Memory"
- shortcut="control|shift|0"
- use_mac_ctrl="true">
- <menu_item_check.on_check
- function="Advanced.CheckConsole"
- parameter="memory view" />
- <menu_item_check.on_click
- function="Advanced.ToggleConsole"
- parameter="memory view" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Region Info to Debug Console"
- layout="topleft"
- name="Region Info to Debug Console">
- <menu_item_call.on_click
- function="Advanced.DumpInfoToConsole"
- parameter="region" />
- </menu_item_call>
- <menu_item_call
- label="Group Info to Debug Console"
- layout="topleft"
- name="Group Info to Debug Console">
- <menu_item_call.on_click
- function="Advanced.DumpInfoToConsole"
- parameter="group" />
- </menu_item_call>
- <menu_item_call
- label="Capabilities Info to Debug Console"
- layout="topleft"
- name="Capabilities Info to Debug Console">
- <menu_item_call.on_click
- function="Advanced.DumpInfoToConsole"
- parameter="capabilities" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="Camera"
- layout="topleft"
- name="Camera">
- <menu_item_check.on_check
- function="Advanced.CheckHUDInfo"
- parameter="camera" />
- <menu_item_check.on_click
- function="Advanced.ToggleHUDInfo"
- parameter="camera" />
- </menu_item_check>
- <menu_item_check
- label="Wind"
- layout="topleft"
- name="Wind">
- <menu_item_check.on_check
- function="Advanced.CheckHUDInfo"
- parameter="wind" />
- <menu_item_check.on_click
- function="Advanced.ToggleHUDInfo"
- parameter="wind" />
- </menu_item_check>
- <menu_item_check
- label="FOV"
- layout="topleft"
- name="FOV">
- <menu_item_check.on_check
- function="Advanced.CheckHUDInfo"
- parameter="fov" />
- <menu_item_check.on_click
- function="Advanced.ToggleHUDInfo"
- parameter="fov" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Show Info"
- layout="topleft"
- name="Display Info"
- tear_off="true">
- <menu_item_check
- label="Show Time"
- layout="topleft"
- name="Show Time">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugShowTime" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugShowTime" />
- </menu_item_check>
- <menu_item_check
- label="Show Render Info"
- layout="topleft"
- name="Show Render Info">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugShowRenderInfo" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugShowRenderInfo" />
- </menu_item_check>
- <menu_item_check
- label="Show Matrices"
- layout="topleft"
- name="Show Matrices">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugShowRenderMatrices" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugShowRenderMatrices" />
- </menu_item_check>
- <menu_item_check
- label="Show Color Under Cursor"
- layout="topleft"
- name="Show Color Under Cursor">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugShowColor" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugShowColor" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="Show Updates to Objects"
- layout="topleft"
- name="Show Updates"
- shortcut="control|alt|shift|U">
- <menu_item_check.on_check
- function="Advanced.CheckShowObjectUpdates"
- parameter="ObjectUpdates" />
- <menu_item_check.on_click
- function="Advanced.ToggleShowObjectUpdates" />
- </menu_item_check>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu
- create_jump_keys="true"
- label="Force an Error"
- layout="topleft"
- name="Force Errors"
- tear_off="true">
- <menu_item_call
- label="Force Breakpoint"
- layout="topleft"
- name="Force Breakpoint"
- shortcut="control|alt|shift|B">
- <menu_item_call.on_click
- function="Advanced.ForceErrorBreakpoint" />
- </menu_item_call>
- <menu_item_call
- label="Force LLError And Crash"
- layout="topleft"
- name="Force LLError And Crash">
- <menu_item_call.on_click
- function="Advanced.ForceErrorLlerror" />
- </menu_item_call>
- <menu_item_call
- label="Force Bad Memory Access"
- layout="topleft"
- name="Force Bad Memory Access">
- <menu_item_call.on_click
- function="Advanced.ForceErrorBadMemoryAccess" />
- </menu_item_call>
- <menu_item_call
- label="Force Infinite Loop"
- layout="topleft"
- name="Force Infinite Loop">
- <menu_item_call.on_click
- function="Advanced.ForceErrorInfiniteLoop" />
- </menu_item_call>
- <menu_item_call
- label="Force Driver Crash"
- layout="topleft"
- name="Force Driver Carsh">
- <menu_item_call.on_click
- function="Advanced.ForceErrorDriverCrash" />
- </menu_item_call>
- <menu_item_call
- label="Force Software Exception"
- layout="topleft"
- name="Force Software Exception">
- <menu_item_call.on_click
- function="Advanced.ForceErrorSoftwareException" />
- </menu_item_call>
- <menu_item_call
- label="Force Disconnect Viewer"
- layout="topleft"
- name="Force Disconnect Viewer">
- <menu_item_call.on_click
- function="Advanced.ForceErrorDisconnectViewer" />
- </menu_item_call>
- <menu_item_call
- label="Simulate a Memory Leak..."
- layout="topleft"
- name="Memory Leaking Simulation">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="mem_leaking" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Render Tests"
- layout="topleft"
- name="Render Tests"
- tear_off="true">
- <menu_item_check
- label="Camera Offset"
- layout="topleft"
- name="Camera Offset">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="CameraOffset" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="CameraOffset" />
- </menu_item_check>
- <menu_item_check
- label="Randomize Framerate"
- layout="topleft"
- name="Randomize Framerate">
- <menu_item_check.on_check
- function="Advanced.CheckRandomizeFramerate"
- parameter="Randomize Framerate" />
- <menu_item_check.on_click
- function="Advanced.ToggleRandomizeFramerate" />
- </menu_item_check>
- <menu_item_check
- label="Periodic Slow Frame"
- layout="topleft"
- name="Periodic Slow Frame">
- <menu_item_check.on_check
- function="Advanced.CheckPeriodicSlowFrame"
- parameter="points" />
- <menu_item_check.on_click
- function="Advanced.TogglePeriodicSlowFrame"
- parameter="points" />
- </menu_item_check>
- <menu_item_check
- label="Frame Test"
- layout="topleft"
- name="Frame Test">
- <menu_item_check.on_check
- function="Advanced.CheckFrameTest"
- parameter="Frame Test" />
- <menu_item_check.on_click
- function="Advanced.ToggleFrameTest" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Render Metadata"
- layout="topleft"
- name="Render Metadata"
- tear_off="true">
- <menu_item_check
- label="Bounding Boxes"
- layout="topleft"
- name="Bounding Boxes">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="bboxes" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="bboxes" />
- </menu_item_check>
- <menu_item_check
- label="Octree"
- layout="topleft"
- name="Octree">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="octree" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="octree" />
- </menu_item_check>
- <menu_item_check
- label="Shadow Frusta"
- layout="topleft"
- name="Shadow Frusta">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="shadow frusta" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="shadow frusta" />
- </menu_item_check>
- <menu_item_check
- label="Occlusion"
- layout="topleft"
- name="Occlusion">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="occlusion" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="occlusion" />
- </menu_item_check>
- <menu_item_check
- label="Render Batches"
- layout="topleft"
- name="Render Batches">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="render batches" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="render batches" />
- </menu_item_check>
- <menu_item_check
- label="Texture Anim"
- layout="topleft"
- name="Texture Anim">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="texture anim" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="texture anim" />
- </menu_item_check>
- <menu_item_check
- label="Texture Priority"
- layout="topleft"
- name="Texture Priority">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="texture priority" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="texture priority" />
- </menu_item_check>
- <menu_item_check
- label="Texture Area"
- layout="topleft"
- name="Texture Area">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="texture area" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="texture area" />
- </menu_item_check>
- <menu_item_check
- label="Face Area"
- layout="topleft"
- name="Face Area">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="face area" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="face area" />
- </menu_item_check>
- <menu_item_check
- label="Lights"
- layout="topleft"
- name="Lights">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="lights" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="lights" />
- </menu_item_check>
- <menu_item_check
- label="Collision Skeleton"
- layout="topleft"
- name="Collision Skeleton">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="collision skeleton" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="collision skeleton" />
- </menu_item_check>
- <menu_item_check
- label="Raycast"
- layout="topleft"
- name="Raycast">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="raycast" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="raycast" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="Rendering"
- layout="topleft"
- name="Rendering"
- tear_off="true">
- <menu_item_check
- label="Axes"
- name="Axes">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowAxes" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowAxes" />
- </menu_item_check>
- <menu_item_check
- label="Tangent Basis"
- name="Tangent Basis">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowTangentBasis" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowTangentBasis" />
- </menu_item_check>
- <menu_item_call
- label="Selected Texture Info Basis"
- name="Selected Texture Info Basis"
- shortcut="control|alt|shift|T">
- <menu_item_call.on_click
- function="Advanced.SelectedTextureInfo" />
- </menu_item_call>
- <menu_item_check
- label="Wireframe"
- name="Wireframe"
- shortcut="control|shift|R">
- <menu_item_check.on_check
- function="Advanced.CheckWireframe"
- parameter="Wireframe" />
- <menu_item_check.on_click
- function="Advanced.ToggleWireframe" />
- </menu_item_check>
- <menu_item_check
- label="Object-Object Occlusion"
- name="Object-Object Occlusion"
- shortcut="control|shift|O">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="UseOcclusion" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="UseOcclusion" />
- <menu_item_check.on_enable
- function="Advanced.EnableObjectObjectOcclusion" />
- </menu_item_check>
- <menu_item_check
- label="Framebuffer Objects"
- name="Framebuffer Objects">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderUseFBO" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderUseFBO" />
- <menu_item_check.on_enable
- function="Advanced.EnableRenderFBO" />
- </menu_item_check>
- <menu_item_check
- label="Deferred Rendering"
- name="Deferred Rendering">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDeferred" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDeferred" />
- <menu_item_check.on_enable
- function="Advanced.EnableRenderDeferred" />
- </menu_item_check>
- <menu_item_check
- label="Global Illumintation"
- name="Global Illumination">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDeferredGI" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDeferredGI" />
- <menu_item_check.on_enable
- function="Advanced.EnableRenderDeferredGI" />
- </menu_item_check>
- <menu_item_separator />
- <menu_item_check
- label="Debug GL"
- name="Debug GL">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDebugGL" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDebugGL" />
- </menu_item_check>
- <menu_item_check
- label="Debug Pipeline"
- name="Debug Pipeline">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDebugGL" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDebugGL" />
- </menu_item_check>
- <menu_item_check
- label="Fast Alpha"
- name="Fast Alpha">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDebugGL" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDebugGL" />
- </menu_item_check>
- <menu_item_check
- label="Animation Textures"
- name="Animation Textures">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderDebugGL" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderDebugGL" />
- </menu_item_check>
- <menu_item_check
- label="Disable Textures"
- name="Disable Textures">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="TextureDisable" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="TextureDisable" />
- </menu_item_check>
- <menu_item_check
- label="Full Res Textures"
- layout="topleft"
- name="Rull Res Textures">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="TextureLoadFullRes" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="TextureLoadFullRes" />
- </menu_item_check>
- <menu_item_check
- label="Audit Textures"
- layout="topleft"
- name="Audit Textures">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="AuditTexture" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="AuditTexture" />
- </menu_item_check>
- <menu_item_check
- label="Texture Atlas"
- name="Texture Atlas">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="EnableTextureAtlas" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="EnableTextureAtlas" />
- </menu_item_check>
- <menu_item_check
- label="Render Attached Lights"
- name="Render Attached Lights">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderAttachedLights" />
- <menu_item_check.on_click
- function="Advanced.HandleAttchedLightParticles"
- parameter="RenderAttachedLights" />
- </menu_item_check>
- <menu_item_check
- label="Render Attached Particles"
- name="Render Attached Particles">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderAttachedParticles" />
- <menu_item_check.on_click
- function="Advanced.HandleAttchedLightParticles"
- parameter="RenderAttachedParticles" />
- </menu_item_check>
- <menu_item_check
- label="Hover Glow Objects"
- name="Hover Glow Objects">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="RenderHighlightEnable" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="RenderHighlightEnable" />
- </menu_item_check>
- </menu>
-
- <menu
- create_jump_keys="true"
- label="Network"
- layout="topleft"
- name="Network"
- tear_off="true">
- <menu_item_check
- label="Pause Agent"
- layout="topleft"
- name="AgentPause">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="AgentPause" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="AgentPause" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Enable Message Log"
- layout="topleft"
- name="Enable Message Log">
- <menu_item_call.on_click
- function="Advanced.EnableMessageLog" />
- </menu_item_call>
- <menu_item_call
- label="Disable Message Log"
- layout="topleft"
- name="Disable Message Log">
- <menu_item_call.on_click
- function="Advanced.DisableMessageLog" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="Velocity Interpolate Objects"
- layout="topleft"
- name="Velocity Interpolate Objects">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="VelocityInterpolate" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="VelocityInterpolate" />
- </menu_item_check>
- <menu_item_check
- label="Ping Interpolate Object Positions"
- layout="topleft"
- name="Ping Interpolate Object Positions">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="PingInterpolate" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="PingInterpolate" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Drop a Packet"
- layout="topleft"
- name="Drop a Packet"
- shortcut="control|alt|L">
- <menu_item_call.on_click
- function="Advanced.DropPacket" />
- </menu_item_call>
- </menu>
- <menu_item_call
- label="Dump Scripted Camera"
- layout="topleft"
- name="Dump Scripted Camera">
- <menu_item_call.on_click
- function="Advanced.DumpScriptedCamera" />
- </menu_item_call>
- <menu_item_call
- label="Bumps, Pushes &amp; Hits"
- layout="topleft"
- name="Bumps, Pushes &amp;amp; Hits">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="bumps" />
- </menu_item_call>
-
- <menu
- create_jump_keys="true"
- label="Recorder"
- layout="topleft"
- name="Recorder"
- tear_off="true">
- <menu_item_call
- label="Start Playback"
- layout="topleft"
- name="Start Playback">
- <menu_item_call.on_click
- function="Advanced.AgentPilot"
- parameter="start playback" />
- </menu_item_call>
- <menu_item_call
- label="Stop Playback"
- layout="topleft"
- name="Stop Playback">
- <menu_item_call.on_click
- function="Advanced.AgentPilot"
- parameter="stop playback" />
- </menu_item_call>
- <menu_item_check
- label="Loop Playback"
- layout="topleft"
- name="Loop Playback">
- <menu_item_check.on_check
- function="Advanced.CheckAgentPilotLoop"
- parameter="loopPlayback" />
- <menu_item_check.on_click
- function="Advanced.ToggleAgentPilotLoop" />
- </menu_item_check>
- <menu_item_call
- label="Start Record"
- layout="topleft"
- name="Start Record">
- <menu_item_call.on_click
- function="Advanced.AgentPilot"
- parameter="start record" />
- </menu_item_call>
- <menu_item_call
- label="Stop Record"
- layout="topleft"
- name="Stop Record">
- <menu_item_call.on_click
- function="Advanced.AgentPilot"
- parameter="stop record" />
- </menu_item_call>
- </menu>
-
- <menu
- create_jump_keys="true"
- label="World"
- layout="topleft"
- name="World"
- tear_off="true">
- <menu_item_check
- label="Sim Sun Override"
- layout="topleft"
- name="Sim Sun Override">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="SkyOverrideSimSunPosition" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="SkyOverrideSimSunPosition" />
- </menu_item_check>
- <menu_item_check
- label="Cheesy Beacon"
- layout="topleft"
- name="Cheesy Beacon">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="CheesyBeacon" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="CheesyBeacon" />
- </menu_item_check>
- <menu_item_check
- label="Fixed Weather"
- layout="topleft"
- name="Fixed Weather">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="FixedWeather" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="FixedWeather" />
- </menu_item_check>
- <menu_item_call
- label="Dump Region Object Cache"
- layout="topleft"
- name="Dump Region Object Cache">
- <menu_item_call.on_click
- function="Advanced.DumpRegionObjectCache" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="UI"
- layout="topleft"
- name="UI"
- tear_off="true">
- <!-- <menu_item_check
- label="New Bottom Bar"
- layout="topleft"
- name="New Bottom Bar">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="BottomPanelNew" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="BottomPanelNew" />
- </menu_item_check>-->
- <menu_item_call
- label="Web Browser Test"
- layout="topleft"
- name="Web Browser Test">
- <menu_item_call.on_click
- function="Advanced.WebBrowserTest"
- parameter="http://secondlife.com/app/search/slurls.html"/>
- </menu_item_call>
- <menu_item_call
- label="Dump SelectMgr"
- layout="topleft"
- name="Dump SelectMgr">
- <menu_item_call.on_click
- function="Advanced.DumpSelectMgr" />
- </menu_item_call>
- <menu_item_call
- label="Dump Inventory"
- layout="topleft"
- name="Dump Inventory">
- <menu_item_call.on_click
- function="Advanced.DumpInventory" />
- </menu_item_call>
- <menu_item_call
- label="Dump Timers"
- name="Dump Timers">
- <menu_item_call.on_click
- function="Advanced.DumpTimers" />
- </menu_item_call>
- <menu_item_call
- label="Dump Focus Holder"
- layout="topleft"
- name="Dump Focus Holder"
- shortcut="control|alt|F">
- <menu_item_call.on_click
- function="Advanced.DumpFocusHolder" />
- </menu_item_call>
- <menu_item_call
- label="Print Selected Object Info"
- layout="topleft"
- name="Print Selected Object Info"
- shortcut="control|shift|P">
- <menu_item_call.on_click
- function="Advanced.PrintSelectedObjectInfo" />
- </menu_item_call>
- <menu_item_call
- label="Print Agent Info"
- layout="topleft"
- name="Print Agent Info"
- shortcut="shift|P">
- <menu_item_call.on_click
- function="Advanced.PrintAgentInfo" />
- </menu_item_call>
- <menu_item_call
- label="Memory Stats"
- layout="topleft"
- name="Memory Stats"
- shortcut="control|alt|shift|M">
- <menu_item_call.on_click
- function="Advanced.PrintTextureMemoryStats" />
- </menu_item_call>
- <menu_item_check
- label="Double-ClickAuto-Pilot"
- layout="topleft"
- name="Double-ClickAuto-Pilot">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DoubleClickAutoPilot" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DoubleClickAutoPilot" />
- </menu_item_check>
-
- <menu_item_separator />
- <menu_item_check
- label="Debug SelectMgr"
- layout="topleft"
- name="Debug SelectMgr">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugSelectMgr" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugSelectMgr" />
- </menu_item_check>
- <menu_item_check
- label="Debug Clicks"
- layout="topleft"
- name="Debug Clicks">
- <menu_item_check.on_check
- function="Advanced.CheckDebugClicks"
- parameter="DebugClicks" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugClicks"
- parameter="DebugClicks" />
- </menu_item_check>
- <menu_item_check
- label="Debug Views"
- layout="topleft"
- name="Debug Views">
- <menu_item_check.on_check
- function="Advanced.CheckDebugViews" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugViews" />
- </menu_item_check>
- <menu_item_check
- label="Debug Name Tooltips"
- layout="topleft"
- name="Debug Name Tooltips">
- <menu_item_check.on_check
- function="Advanced.CheckXUINameTooltips"
- parameter="XUINameTooltips" />
- <menu_item_check.on_click
- function="Advanced.ToggleXUINameTooltips" />
- </menu_item_check>
- <menu_item_check
- label="Debug Mouse Events"
- layout="topleft"
- name="Debug Mouse Events">
- <menu_item_check.on_check
- function="Advanced.CheckDebugMouseEvents"
- parameter="MouseEvents" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugMouseEvents" />
- </menu_item_check>
- <menu_item_check
- label="Debug Keys"
- layout="topleft"
- name="Debug Keys">
- <menu_item_check.on_check
- function="Advanced.CheckDebugKeys"
- parameter="DebugKeys" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugKeys" />
- </menu_item_check>
- <menu_item_check
- label="Debug WindowProc"
- layout="topleft"
- name="Debug WindowProc">
- <menu_item_check.on_check
- function="Advanced.CheckDebugWindowProc"
- parameter="DebugWindowProc" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugWindowProc"
- parameter="DebugWindowProc" />
- </menu_item_check>
- </menu>
- <menu
- create_jump_keys="true"
- label="XUI"
- name="XUI"
- tear_off="true">
- <menu_item_call
- label="Reload Color Settings"
- layout="topleft"
- name="Reload Color Settings">
- <menu_item_call.on_click
- function="Advanced.ReloadColorSettings" />
- </menu_item_call>
- <menu_item_call
- label="Show Font Test"
- layout="topleft"
- name="Show Font Test">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="font_test" />
- </menu_item_call>
- <menu_item_call
- label="Load from XML..."
- layout="topleft"
- name="Load from XML">
- <menu_item_call.on_click
- function="Advanced.LoadUIFromXML" />
- </menu_item_call>
- <menu_item_call
- label="Save to XML..."
- layout="topleft"
- name="Save to XML">
- <menu_item_call.on_click
- function="Advanced.SaveUIToXML" />
- </menu_item_call>
- <menu_item_check
- label="Show XUI Names"
- layout="topleft"
- name="Show XUI Names">
- <menu_item_check.on_check
- function="Advanced.CheckXUINames"
- parameter="showUIname" />
- <menu_item_check.on_click
- function="Advanced.ToggleXUINames" />
- </menu_item_check>
- <menu_item_call
- label="Send Test IMs"
- layout="topleft"
- name="Send Test IMs">
- <menu_item_call.on_click
- function="Advanced.SendTestIMs" />
- </menu_item_call>
- <menu_item_call
- label="Test Inspectors"
- name="Test Inspectors"
- shortcut="control|shift|I">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="test_inspectors" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Avatar"
- layout="topleft"
- name="Character"
- tear_off="true">
- <menu
- create_jump_keys="true"
- label="Grab Baked Texture"
- layout="topleft"
- name="Grab Baked Texture"
- tear_off="true">
- <menu_item_call
- label="Iris"
- layout="topleft"
- name="Iris">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="iris" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture"
- parameter="iris" />
- </menu_item_call>
- <menu_item_call
- label="Head"
- layout="topleft"
- name="Head">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="head" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture"
- parameter="head" />
- </menu_item_call>
- <menu_item_call
- label="Upper Body"
- layout="topleft"
- name="Upper Body">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="upper" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture"
- parameter="upper" />
- </menu_item_call>
- <menu_item_call
- label="Lower Body"
- layout="topleft"
- name="Lower Body">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="lower" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture"
- parameter="lower" />
- </menu_item_call>
- <menu_item_call
- label="Skirt"
- layout="topleft"
- name="Skirt">
- <menu_item_call.on_click
- function="Advanced.GrabBakedTexture"
- parameter="skirt" />
- <menu_item_call.on_enable
- function="Advanced.EnableGrabBakedTexture"
- parameter="skirt" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Character Tests"
- layout="topleft"
- name="Character Tests"
- tear_off="true">
- <menu_item_call
- label="Appearance To XML"
- layout="topleft"
- name="Appearance To XML">
- <menu_item_call.on_click
- function="Advanced.AppearanceToXML" />
- </menu_item_call>
- <menu_item_call
- label="Toggle Character Geometry"
- layout="topleft"
- name="Toggle Character Geometry">
- <menu_item_call.on_click
- function="Advanced.ToggleCharacterGeometry" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Test Male"
- layout="topleft"
- name="Test Male">
- <menu_item_call.on_click
- function="Advanced.TestMale" />
- </menu_item_call>
- <menu_item_call
- label="Test Female"
- layout="topleft"
- name="Test Female">
- <menu_item_call.on_click
- function="Advanced.TestFemale" />
- </menu_item_call>
- <menu_item_call
- label="Toggle PG"
- layout="topleft"
- name="Toggle PG">
- <menu_item_call.on_click
- function="Advanced.TogglePG" />
- </menu_item_call>
- <menu_item_check
- label="Allow Select Avatar"
- layout="topleft"
- name="Allow Select Avatar">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="AllowSelectAvatar" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="AllowSelectAvatar" />
- </menu_item_check>
- </menu>
- <menu_item_call
- label="Force Params to Default"
- layout="topleft"
- name="Force Params to Default">
- <menu_item_call.on_click
- function="Advanced.ForceParamsToDefault" />
- </menu_item_call>
- <menu_item_check
- label="Animation Info"
- layout="topleft"
- name="Animation Info">
- <menu_item_check.on_check
- function="Advanced.CheckAnimationInfo"
- parameter="AnimationInfo" />
- <menu_item_check.on_click
- function="Advanced.ToggleAnimationInfo"
- parameter="" />
- </menu_item_check>
- <menu_item_check
- label="Slow Motion Animations"
- layout="topleft"
- name="Slow Motion Animations">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="SlowMotionAnimation" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="SlowMotionAnimation" />
- </menu_item_check>
- <menu_item_check
- label="Show Look At"
- layout="topleft"
- name="Show Look At">
- <menu_item_check.on_check
- function="Advanced.CheckShowLookAt"
- parameter="ShowLookAt" />
- <menu_item_check.on_click
- function="Advanced.ToggleShowLookAt" />
- </menu_item_check>
- <menu_item_check
- label="Show Point At"
- layout="topleft"
- name="Show Point At">
- <menu_item_check.on_check
- function="Advanced.CheckShowPointAt"
- parameter="ShowPointAt" />
- <menu_item_check.on_click
- function="Advanced.ToggleShowPointAt" />
- </menu_item_check>
- <menu_item_check
- label="Debug Joint Updates"
- layout="topleft"
- name="Debug Joint Updates">
- <menu_item_check.on_check
- function="Advanced.CheckDebugJointUpdates"
- parameter="DebugJointUpdates" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugJointUpdates" />
- </menu_item_check>
- <menu_item_check
- label="Disable LOD"
- layout="topleft"
- name="Disable LOD">
- <menu_item_check.on_check
- function="Advanced.CheckDisableLOD"
- parameter="DisableLOD" />
- <menu_item_check.on_click
- function="Advanced.ToggleDisableLOD" />
- </menu_item_check>
- <menu_item_check
- label="Debug Character Vis"
- layout="topleft"
- name="Debug Character Vis">
- <menu_item_check.on_check
- function="Advanced.CheckDebugCharacterVis"
- parameter="DebugCharacterVis" />
- <menu_item_check.on_click
- function="Advanced.ToggleDebugCharacterVis" />
- </menu_item_check>
- <menu_item_check
- label="Show Collision Skeleton"
- layout="topleft"
- name="Show Collision Skeleton">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="collision skeleton" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="collision skeleton" />
- </menu_item_check>
- <menu_item_check
- label="Display Agent Target"
- layout="topleft"
- name="Display Agent Target">
- <menu_item_check.on_check
- function="Advanced.CheckInfoDisplay"
- parameter="agent target" />
- <menu_item_check.on_click
- function="Advanced.ToggleInfoDisplay"
- parameter="agent target" />
- </menu_item_check>
-<!-- Appears not to exist anymore
- <menu_item_check
- label="Debug Rotation"
- layout="topleft"
- name="Debug Rotation">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="DebugAvatarRotation" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="DebugAvatarRotation" />
- </menu_item_check> -->
--->
- <menu_item_call
- label="Dump Attachments"
- layout="topleft"
- name="Dump Attachments">
- <menu_item_call.on_click
- function="Advanced.DumpAttachments" />
- </menu_item_call>
- <menu_item_call
- label="Debug Avatar Textures"
- layout="topleft"
- name="Debug Avatar Textures"
- shortcut="control|alt|shift|A">
- <menu_item_call.on_click
- function="Advanced.DebugAvatarTextures" />
- </menu_item_call>
- <menu_item_call
- label="Dump Local Textures"
- layout="topleft"
- name="Dump Local Textures"
- shortcut="alt|shift|M">
- <menu_item_call.on_click
- function="Advanced.DumpAvatarLocalTextures" />
- </menu_item_call>
- </menu>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Compress Images"
- layout="topleft"
- name="Compress Images">
- <menu_item_call.on_click
- function="Advanced.CompressImage" />
- </menu_item_call>
- <menu_item_check
- label="Output Debug Minidump"
- layout="topleft"
- name="Output Debug Minidump">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="SaveMinidump" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="SaveMinidump" />
- </menu_item_check>
- <menu_item_check
- label="Console Window on next Run"
- layout="topleft"
- name="Console Window">
- <menu_item_check.on_check
- function="CheckControl"
- parameter="ShowConsoleWindow" />
- <menu_item_check.on_click
- function="ToggleControl"
- parameter="ShowConsoleWindow" />
- </menu_item_check>
- <menu_item_separator
- layout="topleft" />
- <menu_item_check
- label="Show Admin Menu"
- layout="topleft"
- name="View Admin Options">
- <menu_item_check.on_check
- function="Advanced.CheckViewAdminOptions"
- parameter="ViewAdminOptions" />
- <menu_item_check.on_click
- function="Advanced.ToggleViewAdminOptions" />
- </menu_item_check>
- <menu_item_call
- label="Request Admin Status"
- layout="topleft"
- name="Request Admin Options"
- shortcut="control|alt|G">
- <menu_item_call.on_click
- function="Advanced.RequestAdminStatus" />
- </menu_item_call>
- <menu_item_call
- label="Leave Admin Status"
- layout="topleft"
- name="Leave Admin Options"
- shortcut="control|alt|shift|G">
- <menu_item_call.on_click
- function="Advanced.LeaveAdminStatus" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Admin"
- layout="topleft"
- name="Admin"
- tear_off="true"
- visible="false">
- <menu
- create_jump_keys="true"
- label="Object"
- layout="topleft"
- tear_off="true">
- <menu_item_call
- label="Take Copy"
- layout="topleft"
- name="Take Copy"
- shortcut="control|alt|shift|O">
- <menu_item_call.on_click
- function="Admin.ForceTakeCopy" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Force Owner To Me"
- layout="topleft"
- name="Force Owner To Me">
- <menu_item_call.on_click
- function="Admin.HandleObjectOwnerSelf" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Force Owner Permissive"
- layout="topleft"
- name="Force Owner Permissive">
- <menu_item_call.on_click
- function="Admin.HandleObjectOwnerPermissive" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Delete"
- layout="topleft"
- name="Delete"
- shortcut="control|alt|shift|Del">
- <menu_item_call.on_click
- function="Admin.HandleForceDelete" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Lock"
- layout="topleft"
- name="Lock"
- shortcut="control|alt|shift|L">
- <menu_item_call.on_click
- function="Admin.HandleObjectLock" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Get Assets IDs"
- layout="topleft"
- name="Get Assets IDs"
- shortcut="control|alt|shift|I">
- <menu_item_call.on_click
- function="Admin.HandleObjectAssetIDs" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Parcel"
- layout="topleft"
- name="Parcel"
- tear_off="true">
- <menu_item_call
- label="Owner To Me"
- layout="topleft"
- name="Owner To Me">
- <menu_item_call.on_click
- function="Admin.HandleForceParcelOwnerToMe" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Set to Linden Content"
- layout="topleft"
- name="Set to Linden Content"
- shortcut="control|alt|shift|C">
- <menu_item_call.on_click
- function="Admin.HandleForceParcelToContent" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Claim Public Land"
- layout="topleft"
- name="Claim Public Land">
- <menu_item_call.on_click
- function="Admin.HandleClaimPublicLand" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Region"
- layout="topleft"
- name="Region"
- tear_off="true">
- <menu_item_call
- label="Dump Temp Asset Data"
- layout="topleft"
- name="Dump Temp Asset Data">
- <menu_item_call.on_click
- function="Admin.HandleRegionDumpTempAssetData" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- <menu_item_call
- label="Save Region State"
- layout="topleft"
- name="Save Region State">
- <menu_item_call.on_click
- function="Admin.OnSaveState" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- </menu>
- <menu_item_call
- label="God Tools"
- layout="topleft"
- name="God Tools">
- <menu_item_call.on_click
- function="Floater.Show"
- parameter="god_tools" />
- <menu_item_call.on_enable
- function="IsGodCustomerService" />
- </menu_item_call>
- </menu>
- <menu
- create_jump_keys="true"
- label="Admin"
- layout="topleft"
- name="Deprecated"
- tear_off="true"
- visible="false">
- <menu
- create_jump_keys="true"
- label="Attach Object"
- layout="topleft"
- mouse_opaque="false"
- name="Attach Object"
- tear_off="true" />
- <menu
- create_jump_keys="true"
- label="Detach Object"
- layout="topleft"
- mouse_opaque="false"
- name="Detach Object"
- tear_off="true" />
- <menu
- create_jump_keys="true"
- label="Take Off Clothing"
- layout="topleft"
- mouse_opaque="false"
- name="Take Off Clothing"
- tear_off="true">
- <menu_item_call
- label="Shirt"
- layout="topleft"
- name="Shirt">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="shirt" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="shirt" />
- </menu_item_call>
- <menu_item_call
- label="Pants"
- layout="topleft"
- name="Pants">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="pants" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="pants" />
- </menu_item_call>
- <menu_item_call
- label="Shoes"
- layout="topleft"
- name="Shoes">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="shoes" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="shoes" />
- </menu_item_call>
- <menu_item_call
- label="Socks"
- layout="topleft"
- name="Socks">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="socks" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="socks" />
- </menu_item_call>
- <menu_item_call
- label="Jacket"
- layout="topleft"
- name="Jacket">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="jacket" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="jacket" />
- </menu_item_call>
- <menu_item_call
- label="Gloves"
- layout="topleft"
- name="Gloves">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="gloves" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="gloves" />
- </menu_item_call>
- <menu_item_call
- label="Undershirt"
- layout="topleft"
- name="Menu Undershirt">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="undershirt" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="undershirt" />
- </menu_item_call>
- <menu_item_call
- label="Underpants"
- layout="topleft"
- name="Menu Underpants">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="underpants" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="underpants" />
- </menu_item_call>
- <menu_item_call
- label="Skirt"
- layout="topleft"
- name="Skirt">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="skirt" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="skirt" />
- </menu_item_call>
- <menu_item_call
- label="Alpha"
- layout="topleft"
- name="Alpha">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="alpha" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="alpha" />
- </menu_item_call>
- <menu_item_call
- label="Tattoo"
- layout="topleft"
- name="Tattoo">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="tattoo" />
- <menu_item_call.on_enable
- function="Edit.EnableTakeOff"
- parameter="tattoo" />
- </menu_item_call>
- <menu_item_call
- label="All Clothes"
- layout="topleft"
- name="All Clothes">
- <menu_item_call.on_click
- function="Edit.TakeOff"
- parameter="all" />
- </menu_item_call>
- </menu>
- <menu_item_check
- label="Show Toolbar"
- layout="topleft"
- name="Show Toolbar">
- <menu_item_check.on_check
- function="FloaterVisible"
- parameter="toolbar" />
- <menu_item_check.on_click
- function="ShowFloater"
- parameter="toolbar" />
- </menu_item_check>
- <menu
- create_jump_keys="true"
- label="Help"
- layout="topleft"
- name="Help"
- tear_off="true">
- <menu_item_call
- label="Official Linden Blog"
- layout="topleft"
- name="Official Linden Blog">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="OfficialLindenBlog_url"
- parameter="WebLaunchSupportWiki,http://blog.secondlife.com/" />
- </menu_item_call>
- <menu_item_call
- label="Scripting Portal"
- layout="topleft"
- name="Scripting Portal">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="ScriptingPortal_url"
- parameter="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal" />
- </menu_item_call>
- <menu
- create_jump_keys="true"
- label="Bug Reporting"
- layout="topleft"
- name="Bug Reporting"
- tear_off="true">
- <menu_item_call
- label="Public Issue Tracker"
- layout="topleft"
- name="Public Issue Tracker">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="PublicIssueTracker_url"
- parameter="WebLaunchPublicIssue,http://jira.secondlife.com" />
- </menu_item_call>
- <menu_item_call
- label="Public Issue Tracker Help"
- layout="topleft"
- name="Publc Issue Tracker Help">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="PublicIssueTrackerHelp_url"
- parameter="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker" />
- </menu_item_call>
- <menu_item_separator
- layout="topleft" />
- <menu_item_call
- label="Bug Reporting 101"
- layout="topleft"
- name="Bug Reporing 101">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="BugReporting101_url"
- parameter="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101" />
- </menu_item_call>
- <menu_item_call
- label="Security Issues"
- layout="topleft"
- name="Security Issues">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="SecurityIssues_url"
- parameter="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues" />
- </menu_item_call>
- <menu_item_call
- label="QA Wiki"
- layout="topleft"
- name="QA Wiki">
- <menu_item_call.on_click
- function="PromptShowURL"
- name="QAWiki_url"
- parameter="WebLaunchQAWiki,http://wiki.secondlife.com/wiki/QA_Portal" />
- </menu_item_call>
- </menu>
- </menu>
- </menu>
-</menu_bar>
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<menu_bar
+ bg_visible="false"
+ follows="left|top|right"
+ layout="topleft"
+ name="Main Menu">
+ <menu
+ label="Me"
+ layout="topleft"
+ name="Me"
+ tear_off="true">
+ <menu_item_call
+ label="Preferences"
+ layout="topleft"
+ name="Preferences"
+ shortcut="control|P">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="preferences" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Dashboard"
+ layout="topleft"
+ name="Manage My Account">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="ManageMyAccount_url"
+ parameter="WebLaunchJoinNow,http://secondlife.com/account/" />
+ </menu_item_call>
+ <menu_item_call
+ label="Buy L$"
+ layout="topleft"
+ name="Buy and Sell L$">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="buy currency" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="My Profile"
+ layout="topleft"
+ name="Profile">
+ <menu_item_call.on_click
+ function="ShowAgentProfile"
+ parameter="agent" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Appearance"
+ layout="topleft"
+ name="Appearance">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="appearance" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCustomizeAvatar" />
+ </menu_item_call>
+ <menu_item_check
+ label="My Inventory"
+ layout="topleft"
+ name="Inventory"
+ shortcut="control|I">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="inventory" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="inventory" />
+ </menu_item_check>
+ <menu_item_call
+ label="My Gestures"
+ layout="topleft"
+ name="Gestures"
+ shortcut="control|G">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="gestures" />
+ </menu_item_call>
+ <menu
+ label="My Status"
+ layout="topleft"
+ name="Status"
+ tear_off="true">
+ <menu_item_call
+ label="Away"
+ layout="topleft"
+ name="Set Away">
+ <menu_item_call.on_click
+ function="World.SetAway" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft"/>
+ <menu_item_call
+ label="Busy"
+ layout="topleft"
+ name="Set Busy">
+ <menu_item_call.on_click
+ function="World.SetBusy"/>
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="Request Admin Status"
+ layout="topleft"
+ name="Request Admin Options"
+ shortcut="control|alt|G"
+ visible="false">
+ <menu_item_call.on_click
+ function="Advanced.RequestAdminStatus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Leave Admin Status"
+ layout="topleft"
+ name="Leave Admin Options"
+ shortcut="control|alt|shift|G"
+ visible="false">
+ <menu_item_call.on_click
+ function="Advanced.LeaveAdminStatus" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Quit [APP_NAME]"
+ layout="topleft"
+ name="Quit"
+ shortcut="control|Q">
+ <menu_item_call.on_click
+ function="File.Quit" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Communicate"
+ layout="topleft"
+ name="Communicate"
+ tear_off="true">
+ <menu_item_call
+ label="My Friends"
+ layout="topleft"
+ name="My Friends"
+ shortcut="control|shift|F">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="friends_panel" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Groups"
+ layout="topleft"
+ name="My Groups">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="groups_panel" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <!--menu_item_call
+ label="Chat"
+ layout="topleft"
+ name="Chat">
+ <menu_item_call.on_click
+ function="World.Chat" />
+ </menu_item_call-->
+ <menu_item_check
+ label="Nearby Chat"
+ layout="topleft"
+ name="Nearby Chat"
+ shortcut="control|H">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="nearby_chat" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="nearby_chat" />
+ </menu_item_check>
+ <menu_item_call
+ label="Nearby People"
+ layout="topleft"
+ name="Active Speakers"
+ shortcut="control|shift|A">
+ <menu_item_call.on_click
+ function="SideTray.PanelPeopleTab"
+ parameter="nearby_panel" />
+ </menu_item_call>
+ <menu_item_check
+ label="Nearby Media"
+ layout="topleft"
+ name="Nearby Media"
+ shortcut="control|alt|N">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="nearby_media" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="nearby_media" />
+ </menu_item_check>
+ <!--menu_item_check
+ label="Block List"
+ layout="topleft"
+ name="Mute List">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="mute" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="mute" />
+ </menu_item_check-->
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="(Legacy) Communicate"
+ layout="topleft"
+ name="Instant Message"
+ shortcut="control|T">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="communicate" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="communicate" />
+ </menu_item_check>
+ <menu_item_call
+ label="(Temp) Media Remote Ctrl"
+ layout="topleft"
+ name="Preferences"
+ shortcut="control|alt|M">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="media_remote_ctrl" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="World"
+ layout="topleft"
+ name="World"
+ tear_off="true">
+ <menu_item_check
+ label="Move"
+ layout="topleft"
+ name="Movement Controls">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="moveview" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="moveview" />
+ </menu_item_check>
+ <menu_item_check
+ label="View"
+ layout="topleft"
+ name="Camera Controls">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="camera" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="camera" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="About Land"
+ layout="topleft"
+ name="About Land">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="about_land" />
+ </menu_item_call>
+ <menu_item_call
+ label="Region/Estate"
+ layout="topleft"
+ name="Region/Estate">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="region_info" />
+ </menu_item_call>
+ <menu_item_call
+ label="Buy Land"
+ layout="topleft"
+ name="Buy Land">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="buy land" />
+ <menu_item_call.on_enable
+ function="World.EnableBuyLand" />
+ </menu_item_call>
+ <menu_item_call
+ label="My Land"
+ layout="topleft"
+ name="My Land">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="land_holdings" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Show"
+ layout="topleft"
+ name="Land"
+ tear_off="true">
+ <menu_item_check
+ label="Ban Lines"
+ layout="topleft"
+ name="Ban Lines">
+ <menu_item_check.on_check
+ control="ShowBanLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowBanLines" />
+ </menu_item_check>
+ <menu_item_check
+ label="Beacons"
+ layout="topleft"
+ name="beacons"
+ shortcut="control|alt|shift|N">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="beacons" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="beacons" />
+ </menu_item_check>
+ <menu_item_check
+ label="Property Lines"
+ layout="topleft"
+ name="Property Lines"
+ shortcut="control|alt|shift|P">
+ <menu_item_check.on_check
+ control="ShowPropertyLines" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowPropertyLines" />
+ </menu_item_check>
+ <menu_item_check
+ label="Land Owners"
+ layout="topleft"
+ name="Land Owners">
+ <menu_item_check.on_check
+ control="ShowParcelOwners" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowParcelOwners" />
+ </menu_item_check>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ label="Landmarks"
+ layout="topleft"
+ name="Landmarks"
+ tear_off="true">
+ <menu_item_call
+ label="Create Landmark Here"
+ layout="topleft"
+ name="Create Landmark Here">
+ <menu_item_call.on_click
+ function="World.CreateLandmark" />
+ <menu_item_call.on_enable
+ function="World.EnableCreateLandmark" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Home to Here"
+ layout="topleft"
+ name="Set Home to Here">
+ <menu_item_call.on_click
+ function="World.SetHomeLocation" />
+ <menu_item_call.on_enable
+ function="World.EnableSetHomeLocation" />
+ </menu_item_call>
+ <menu_item_call
+ label="Teleport Home"
+ layout="topleft"
+ name="Teleport Home"
+ shortcut="control|shift|H">
+ <menu_item_call.on_click
+ function="World.TeleportHome" />
+ <menu_item_call.on_enable
+ function="World.EnableTeleportHome" />
+ </menu_item_call>
+ </menu>
+ <menu_item_check
+ label="Mini-Map"
+ layout="topleft"
+ name="Mini-Map"
+ shortcut="control|shift|M">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="mini_map" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="mini_map" />
+ </menu_item_check>
+ <menu_item_check
+ label="World Map"
+ layout="topleft"
+ name="World Map"
+ shortcut="control|M"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="world_map" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="world_map" />
+ </menu_item_check>
+ <!-- <menu_item_check
+ label="Show Navigation Bar"
+ layout="topleft"
+ name="ShowNavbarNavigationPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarNavigationPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarNavigationPanel" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Favorites Bar"
+ layout="topleft"
+ name="ShowNavbarFavoritesPanel">
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowNavbarFavoritesPanel" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />-->
+ <menu_item_call
+ label="Snapshot"
+ layout="topleft"
+ name="Take Snapshot"
+ shortcut="control|shift|S">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="snapshot" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Sun"
+ layout="topleft"
+ name="Environment Settings"
+ tear_off="true">
+ <menu_item_call
+ label="Sunrise"
+ layout="topleft"
+ name="Sunrise">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="sunrise" />
+ </menu_item_call>
+ <menu_item_call
+ label="Midday"
+ layout="topleft"
+ name="Noon"
+ shortcut="control|shift|Y">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="noon" />
+ </menu_item_call>
+ <menu_item_call
+ label="Sunset"
+ layout="topleft"
+ name="Sunset"
+ shortcut="control|shift|N">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="sunset" />
+ </menu_item_call>
+ <menu_item_call
+ label="Midnight"
+ layout="topleft"
+ name="Midnight">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="midnight" />
+ </menu_item_call>
+ <menu_item_call
+ label="Use the Estate Time"
+ layout="topleft"
+ name="Revert to Region Default">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="default" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Environment Editor"
+ layout="topleft"
+ name="Environment Editor">
+ <menu_item_call.on_click
+ function="World.EnvSettings"
+ parameter="editor" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Build"
+ layout="topleft"
+ name="BuildTools"
+ tear_off="true"
+ visible="true">
+ <menu_item_check
+ label="Build"
+ layout="topleft"
+ name="Show Build Tools"
+ shortcut="control|B">
+ <menu_item_check.on_check
+ function="Build.Active" />
+ <menu_item_check.on_click
+ function="Build.Toggle" />
+ <menu_item_check.on_enable
+ function="Build.Enabled" />
+ </menu_item_check>
+ <menu
+ create_jump_keys="true"
+ label="Select Build Tool"
+ layout="topleft"
+ name="Select Tool"
+ tear_off="true">
+ <menu_item_call
+ label="Focus Tool"
+ layout="topleft"
+ name="Focus"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="focus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Move Tool"
+ layout="topleft"
+ name="Move"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="move" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Tool"
+ layout="topleft"
+ name="Edit"
+ shortcut="control|3">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Tool"
+ layout="topleft"
+ name="Create"
+ shortcut="control|4">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="create" />
+ </menu_item_call>
+ <menu_item_call
+ label="Land Tool"
+ layout="topleft"
+ name="Land"
+ shortcut="control|5">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="land" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Edit"
+ layout="topleft"
+ name="Edit"
+ tear_off="true">
+ <menu_item_call
+ label="Undo"
+ layout="topleft"
+ name="Undo"
+ shortcut="control|Z">
+ <menu_item_call.on_click
+ function="Edit.Undo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableUndo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Redo"
+ layout="topleft"
+ name="Redo"
+ shortcut="control|Y">
+ <menu_item_call.on_click
+ function="Edit.Redo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableRedo" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Cut"
+ layout="topleft"
+ name="Cut"
+ shortcut="control|X">
+ <menu_item_call.on_click
+ function="Edit.Cut" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCut" />
+ </menu_item_call>
+ <menu_item_call
+ label="Copy"
+ layout="topleft"
+ name="Copy"
+ shortcut="control|C">
+ <menu_item_call.on_click
+ function="Edit.Copy" />
+ <menu_item_call.on_enable
+ function="Edit.EnableCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Paste"
+ layout="topleft"
+ name="Paste"
+ shortcut="control|V">
+ <menu_item_call.on_click
+ function="Edit.Paste" />
+ <menu_item_call.on_enable
+ function="Edit.EnablePaste" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="Del">
+ <menu_item_call.on_click
+ function="Edit.Delete" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDelete" />
+ </menu_item_call>
+ <menu_item_call
+ label="Duplicate"
+ layout="topleft"
+ name="Duplicate"
+ shortcut="control|D">
+ <menu_item_call.on_click
+ function="Edit.Duplicate" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDuplicate" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Select All"
+ layout="topleft"
+ name="Select All"
+ shortcut="control|A">
+ <menu_item_call.on_click
+ function="Edit.SelectAll" />
+ <menu_item_call.on_enable
+ function="Edit.EnableSelectAll" />
+ </menu_item_call>
+ <menu_item_call
+ label="Deselect"
+ layout="topleft"
+ name="Deselect"
+ shortcut="control|E">
+ <menu_item_call.on_click
+ function="Edit.Deselect" />
+ <menu_item_call.on_enable
+ function="Edit.EnableDeselect" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Link"
+ layout="topleft"
+ name="Link"
+ shortcut="control|L">
+ <menu_item_call.on_click
+ function="Tools.Link" />
+ <menu_item_call.on_enable
+ function="Tools.EnableLink" />
+ </menu_item_call>
+ <menu_item_call
+ label="Unlink"
+ layout="topleft"
+ name="Unlink"
+ shortcut="control|shift|L">
+ <menu_item_call.on_click
+ function="Tools.Unlink" />
+ <menu_item_call.on_enable
+ function="Tools.EnableUnlink" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Focus on Selection"
+ layout="topleft"
+ name="Focus on Selection"
+ shortcut="H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="focus" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom to Selection"
+ layout="topleft"
+ name="Zoom to Selection"
+ shortcut="shift|H">
+ <menu_item_call.on_click
+ function="Tools.LookAtSelection"
+ parameter="zoom" />
+ <menu_item_call.on_enable
+ function="Tools.SomethingSelectedNoHUD" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Object"
+ layout="topleft"
+ name="Object"
+ tear_off="true">
+ <menu_item_call
+ label="Buy"
+ layout="topleft"
+ name="Menu Object Take"
+ visible="true">
+ <menu_item_call.on_click
+ function="Tools.BuyOrTake" />
+ <menu_item_call.on_enable
+ function="Tools.EnableBuyOrTake"
+ name="EnableBuyOrTake"
+ parameter="Buy,Take" />
+ </menu_item_call>
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="Take Copy">
+ <menu_item_call.on_click
+ function="Tools.TakeCopy" />
+ <menu_item_call.on_enable
+ function="Tools.EnableTakeCopy" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to My Inventory"
+ layout="topleft"
+ name="Save Object Back to My Inventory">
+ <menu_item_call.on_click
+ function="Tools.SaveToInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToInventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Back to Object Contents"
+ layout="topleft"
+ name="Save Object Back to Object Contents">
+ <menu_item_call.on_click
+ function="Tools.SaveToObjectInventory" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSaveToObjectInventory" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Scripts"
+ layout="topleft"
+ name="Scripts"
+ tear_off="true">
+ <menu_item_call
+ label="Recompile Scripts (Mono)"
+ layout="topleft"
+ name="Mono">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile mono" />
+ <menu_item_call.on_enable
+ function="EditableSelectedMono" />
+ </menu_item_call>
+ <menu_item_call
+ label="Recompile Scripts (LSL)"
+ layout="topleft"
+ name="LSL">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="compile lsl" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Reset Scripts"
+ layout="topleft"
+ name="Reset Scripts">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="reset" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Running"
+ layout="topleft"
+ name="Set Scripts to Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="start" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set Scripts to Not Running"
+ layout="topleft"
+ name="Set Scripts to Not Running">
+ <menu_item_call.on_click
+ function="Tools.SelectedScriptAction"
+ parameter="stop" />
+ <menu_item_call.on_enable
+ function="EditableSelected" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Options"
+ layout="topleft"
+ name="Options"
+ tear_off="true">
+ <menu_item_check
+ label="Edit Linked Parts"
+ layout="topleft"
+ name="Edit Linked Parts">
+ <menu_item_check.on_check
+ control="EditLinkedParts" />
+ <menu_item_check.on_click
+ function="Tools.EditLinkedParts"
+ parameter="EditLinkedParts" />
+ <menu_item_check.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_check>
+ <menu_item_call
+ label="Set Default Upload Permissions"
+ layout="topleft"
+ name="perm prefs">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="perm_prefs" />
+ <menu_item_check
+ label="Show Advanced Permissions"
+ layout="topleft"
+ name="DebugPermissions">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugPermissions" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugPermissions" />
+ </menu_item_check>
+ </menu_item_call>
+ <!--menu_item_call
+ label="Show Script Warning/Error Window"
+ layout="topleft"
+ name="Show Script Warning/Error Window">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="script errors" />
+ </menu_item_call-->
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Selection"
+ layout="topleft"
+ name="Selection"
+ tear_off="true">
+ <menu_item_check
+ label="Select Only My Objects"
+ layout="topleft"
+ name="Select Only My Objects">
+ <menu_item_check.on_check
+ control="SelectOwnedOnly" />
+ <menu_item_check.on_click
+ function="Tools.SelectOnlyMyObjects"
+ parameter="agents" />
+ </menu_item_check>
+ <menu_item_check
+ label="Select Only Movable Objects"
+ layout="topleft"
+ name="Select Only Movable Objects">
+ <menu_item_check.on_check
+ control="SelectMovableOnly" />
+ <menu_item_check.on_click
+ function="Tools.SelectOnlyMovableObjects"
+ parameter="movable" />
+ </menu_item_check>
+ <menu_item_check
+ label="Select By Surrounding"
+ layout="topleft"
+ name="Select By Surrounding">
+ <menu_item_check.on_check
+ control="RectangleSelectInclusive" />
+ <menu_item_check.on_click
+ function="Tools.SelectBySurrounding" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Show"
+ layout="topleft"
+ name="Show"
+ tear_off="true">
+ <menu_item_check
+ label="Show Hidden Selection"
+ layout="topleft"
+ name="Show Hidden Selection">
+ <menu_item_check.on_check
+ control="RenderHiddenSelections" />
+ <menu_item_check.on_click
+ function="Tools.ShowHiddenSelection" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Light Radius for Selection"
+ layout="topleft"
+ name="Show Light Radius for Selection">
+ <menu_item_check.on_check
+ control="RenderLightRadius" />
+ <menu_item_check.on_click
+ function="Tools.ShowSelectionLightRadius" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Selection Beam"
+ layout="topleft"
+ name="Show Selection Beam">
+ <menu_item_check.on_check
+ control="ShowSelectionBeam" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowSelectionBeam" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Grid"
+ layout="topleft"
+ name="Grid"
+ tear_off="true">
+ <menu_item_check
+ label="Snap to Grid"
+ layout="topleft"
+ name="Snap to Grid"
+ shortcut="G">
+ <menu_item_check.on_check
+ control="SnapEnabled" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SnapEnabled" />
+ <menu_item_check.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_check>
+ <menu_item_call
+ label="Snap Object XY to Grid"
+ layout="topleft"
+ name="Snap Object XY to Grid"
+ shortcut="shift|X">
+ <menu_item_call.on_click
+ function="Tools.SnapObjectXY" />
+ <menu_item_call.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_call>
+ <menu_item_call
+ label="Use Selection for Grid"
+ layout="topleft"
+ name="Use Selection for Grid"
+ shortcut="shift|G">
+ <menu_item_call.on_click
+ function="Tools.UseSelectionForGrid" />
+ <menu_item_call.on_enable
+ function="SomethingSelected" />
+ </menu_item_call>
+ <menu_item_call
+ label="Grid Options"
+ layout="topleft"
+ name="Grid Options"
+ shortcut="control|shift|B">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="build_options" />
+ <menu_item_call.on_enable
+ function="Tools.EnableToolNotPie" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Select Linked Parts"
+ layout="topleft"
+ name="Select Linked Parts"
+ tear_off="true">
+ <menu_item_call
+ label="Select Next Part"
+ layout="topleft"
+ name="Select Next Part"
+ shortcut="control|.">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="next" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Select Previous Part"
+ layout="topleft"
+ name="Select Previous Part"
+ shortcut="control|,">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="previous" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Include Next Part"
+ layout="topleft"
+ name="Include Next Part"
+ shortcut="control|shift|.">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="includenext" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ <menu_item_call
+ label="Include Previous Part"
+ layout="topleft"
+ name="Include Previous Part"
+ shortcut="control|shift|,">
+ <menu_item_call.on_click
+ function="Tools.SelectNextPart"
+ parameter="includeprevious" />
+ <menu_item_call.on_enable
+ function="Tools.EnableSelectNextPart" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ <menu
+ label="Help"
+ layout="topleft"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="[SECOND_LIFE] Help"
+ layout="topleft"
+ name="Second Life Help"
+ shortcut="F1">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="help f1" />
+ </menu_item_call>
+ <menu_item_call
+ label="Tutorial"
+ layout="topleft"
+ name="Tutorial">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="hud" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Report Abuse"
+ layout="topleft"
+ name="Report Abuse">
+ <menu_item_call.on_click
+ function="ShowFloater"
+ parameter="complaint reporter" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="About [APP_NAME]"
+ layout="topleft"
+ name="About Second Life">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="sl_about" />
+ </menu_item_call>
+ </menu>
+ <menu
+ label="Advanced"
+ layout="topleft"
+ name="Advanced"
+ tear_off="true"
+ visible="false">
+ <menu_item_check
+ label="Set Away After 30 Minutes"
+ layout="topleft"
+ name="Go Away/AFK When Idle">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AllowIdleAFK" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AllowIdleAFK" />
+ </menu_item_check>
+ <menu_item_call
+ label="Stop Animating Me"
+ layout="topleft"
+ name="Stop Animating My Avatar">
+ <menu_item_call.on_click
+ function="Tools.StopAllAnimations" />
+ </menu_item_call>
+ <menu_item_call
+ label="Rebake Textures"
+ layout="topleft"
+ name="Rebake Texture"
+ shortcut="control|alt|R">
+ <menu_item_call.on_click
+ function="Advanced.RebakeTextures" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set UI Size to Default"
+ layout="topleft"
+ name="Set UI Size to Default">
+ <menu_item_call.on_click
+ function="View.DefaultUISize" />
+ </menu_item_call>
+ <menu_item_separator/>
+ <menu_item_check
+ label="Limit Select Distance"
+ layout="topleft"
+ name="Limit Select Distance">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="LimitSelectDistance" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="LimitSelectDistance" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable Camera Constraints"
+ layout="topleft"
+ name="Disable Camera Distance">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DisableCameraConstraints" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DisableCameraConstraints" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="High-res Snapshot"
+ layout="topleft"
+ name="HighResSnapshot">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="HighResSnapshot" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="HighResSnapshot" />
+ </menu_item_check>
+ <menu_item_check
+ label="Quiet Snapshots to Disk"
+ layout="topleft"
+ name="QuietSnapshotsToDisk">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="QuietSnapshotsToDisk" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="QuietSnapshotsToDisk" />
+ </menu_item_check>
+ <menu_item_check
+ label="Compress Snapshots to Disk"
+ layout="topleft"
+ name="CompressSnapshotsToDisk">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CompressSnapshotsToDisk" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CompressSnapshotsToDisk" />
+ </menu_item_check>
+ <menu_item_call
+ label="Save Texture As"
+ layout="topleft"
+ name="Save Texture As">
+ <menu_item_call.on_click
+ function="File.SaveTexture" />
+ <menu_item_call.on_enable
+ function="File.EnableSaveAs" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Performance Tools"
+ layout="topleft"
+ name="Performance Tools"
+ tear_off="true">
+ <menu_item_call
+ label="Lag Meter"
+ layout="topleft"
+ name="Lag Meter">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="lagmeter" />
+ </menu_item_call>
+ <menu_item_check
+ label="Statistics Bar"
+ layout="topleft"
+ name="Statistics Bar"
+ shortcut="control|shift|1">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="stats" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="stats" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Avatar Rendering Cost"
+ layout="topleft"
+ name="Avatar Rendering Cost">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shame" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shame" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Highlighting and Visibility"
+ layout="topleft"
+ name="Highlighting and Visibility"
+ tear_off="true">
+ <menu_item_check
+ label="Cheesy Beacon"
+ layout="topleft"
+ name="Cheesy Beacon">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CheesyBeacon" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CheesyBeacon" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hide Particles"
+ layout="topleft"
+ name="Hide Particles"
+ shortcut="control|alt|shift|=">
+ <menu_item_check.on_check
+ function="View.CheckRenderType"
+ parameter="hideparticles" />
+ <menu_item_check.on_click
+ function="View.ToggleRenderType"
+ parameter="hideparticles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hide Selected"
+ layout="topleft"
+ name="Hide Selected">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="HideSelectedObjects" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="HideSelectedObjects" />
+ </menu_item_check>
+ <menu_item_check
+ label="Highlight Transparent"
+ layout="topleft"
+ name="Highlight Transparent"
+ shortcut="control|alt|T">
+ <menu_item_check.on_check
+ function="View.CheckHighlightTransparent" />
+ <menu_item_check.on_click
+ function="View.HighlightTransparent" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show HUD Attachments"
+ layout="topleft"
+ name="Show HUD Attachments"
+ shortcut="alt|shift|H">
+ <menu_item_check.on_check
+ function="View.CheckHUDAttachments" />
+ <menu_item_check.on_click
+ function="View.ShowHUDAttachments" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Mouselook Crosshairs"
+ layout="topleft"
+ name="ShowCrosshairs">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowCrosshairs" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowCrosshairs" />
+ </menu_item_check>
+ <!-- <menu
+ create_jump_keys="true"
+ label="Hover Tips"
+ layout="topleft"
+ name="Hover Tips"
+ tear_off="true">
+ <menu_item_check
+ label="Show Tips"
+ layout="topleft"
+ name="Show Tips"
+ shortcut="control|shift|T">
+ <menu_item_check.on_check
+ function="View.CheckShowHoverTips" />
+ <menu_item_check.on_click
+ function="View.ShowHoverTips" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />-->
+ <menu_item_check
+ label="Show Land Tooltips"
+ layout="topleft"
+ name="Land Tips">
+ <menu_item_check.on_check
+ control="ShowLandHoverTip" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowLandHoverTip" />
+ <menu_item_check.on_enable
+ function="View.CheckShowHoverTips" />
+ </menu_item_check>
+ <!-- <menu_item_check
+ label="Show Tips On All Objects"
+ layout="topleft"
+ name="Tips On All Objects">
+ <menu_item_check.on_check
+ control="ShowAllObjectHoverTip" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowAllObjectHoverTip" />
+ <menu_item_check.on_enable
+ function="View.CheckShowHoverTips" />
+ </menu_item_check>
+ </menu>-->
+
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="Rendering Types"
+ layout="topleft"
+ name="Rendering Types"
+ tear_off="true">
+ <menu_item_check
+ label="Simple"
+ layout="topleft"
+ name="Simple"
+ shortcut="control|alt|shift|1">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="simple" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="simple" />
+ </menu_item_check>
+ <menu_item_check
+ label="Alpha"
+ layout="topleft"
+ name="Alpha"
+ shortcut="control|alt|shift|2">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="alpha" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="alpha" />
+ </menu_item_check>
+ <menu_item_check
+ label="Tree"
+ layout="topleft"
+ name="Tree"
+ shortcut="control|alt|shift|3">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="tree" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="tree" />
+ </menu_item_check>
+ <menu_item_check
+ label="Avatars"
+ layout="topleft"
+ name="Character"
+ shortcut="control|alt|shift|4">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="character" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="character" />
+ </menu_item_check>
+ <menu_item_check
+ label="SurfacePath"
+ layout="topleft"
+ name="SurfacePath"
+ shortcut="control|alt|shift|5">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="surfacePath" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="surfacePath" />
+ </menu_item_check>
+ <menu_item_check
+ label="Sky"
+ layout="topleft"
+ name="Sky"
+ shortcut="control|alt|shift|6">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="sky" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="sky" />
+ </menu_item_check>
+ <menu_item_check
+ label="Water"
+ layout="topleft"
+ name="Water"
+ shortcut="control|alt|shift|7">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="water" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="water" />
+ </menu_item_check>
+ <menu_item_check
+ label="Ground"
+ layout="topleft"
+ name="Ground"
+ shortcut="control|alt|shift|8">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="ground" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="ground" />
+ </menu_item_check>
+ <menu_item_check
+ label="Volume"
+ layout="topleft"
+ name="Volume"
+ shortcut="control|alt|shift|9">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="volume" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="volume" />
+ </menu_item_check>
+ <menu_item_check
+ label="Grass"
+ layout="topleft"
+ name="Grass"
+ shortcut="control|alt|shift|0">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="grass" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="grass" />
+ </menu_item_check>
+ <menu_item_check
+ label="Clouds"
+ layout="topleft"
+ name="Clouds"
+ shortcut="control|alt|shift|-">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="clouds" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="clouds" />
+ </menu_item_check>
+ <menu_item_check
+ label="Particles"
+ layout="topleft"
+ name="Particles"
+ shortcut="control|alt|shift|=">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="particles" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="particles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Bump"
+ layout="topleft"
+ name="Bump"
+ shortcut="control|alt|shift|\">
+ <menu_item_check.on_check
+ function="Advanced.CheckRenderType"
+ parameter="bump" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRenderType"
+ parameter="bump" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Rendering Features"
+ layout="topleft"
+ name="Rendering Features"
+ tear_off="true">
+ <menu_item_check
+ label="UI"
+ layout="topleft"
+ name="UI"
+ shortcut="control|alt|F1">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="ui" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="ui" />
+ </menu_item_check>
+ <menu_item_check
+ label="Selected"
+ layout="topleft"
+ name="Selected"
+ shortcut="control|alt|F2">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="selected" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="selected" />
+ </menu_item_check>
+ <menu_item_check
+ label="Highlighted"
+ layout="topleft"
+ name="Highlighted"
+ shortcut="control|alt|F3">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="highlighted" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="highlighted" />
+ </menu_item_check>
+ <menu_item_check
+ label="Dynamic Textures"
+ layout="topleft"
+ name="Dynamic Textures"
+ shortcut="control|alt|F4">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="dynamic textures" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="dynamic textures" />
+ </menu_item_check>
+ <menu_item_check
+ label="Foot Shadows"
+ layout="topleft"
+ name="Foot Shadows"
+ shortcut="control|alt|F5">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="foot shadows" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="foot shadows" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fog"
+ layout="topleft"
+ name="Fog"
+ shortcut="control|alt|F6">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="fog" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="fog" />
+ </menu_item_check>
+ <menu_item_check
+ label="Test FRInfo"
+ layout="topleft"
+ name="Test FRInfo"
+ shortcut="control|alt|F8">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="fr info" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="fr info" />
+ </menu_item_check>
+ <menu_item_check
+ label="Flexible Objects"
+ layout="topleft"
+ name="Flexible Objects"
+ shortcut="control|alt|F9">
+ <menu_item_check.on_check
+ function="Advanced.CheckFeature"
+ parameter="flexible" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFeature"
+ parameter="flexible" />
+ </menu_item_check>
+ </menu>
+ <menu_item_check
+ label="Run Multiple Threads"
+ layout="topleft"
+ name="Run Multiple Threads">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RunMultipleThreads" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RunMultipleThreads" />
+ </menu_item_check>
+ <menu_item_call
+ label="Clear Group Cache"
+ layout="topleft"
+ name="ClearGroupCache">
+ <menu_item_call.on_click
+ function="Advanced.ClearGroupCache"
+ parameter="ClearGroupCache" />
+ </menu_item_call>
+ <menu_item_check
+ label="Mouse Smoothing"
+ layout="topleft"
+ name="Mouse Smoothing">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="MouseSmooth" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="MouseSmooth" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ label="Shortcuts"
+ layout="topleft"
+ name="Shortcuts"
+ tear_off="true"
+ visible="false">
+ <menu_item_check
+ label="Search"
+ layout="topleft"
+ name="Search"
+ shortcut="control|F">
+ <menu_item_check.on_check
+ function="Floater.Visible"
+ parameter="search" />
+ <menu_item_check.on_click
+ function="Floater.Toggle"
+ parameter="search" />
+ </menu_item_check>
+ <menu_item_call
+ enabled="false"
+ label="Release Keys"
+ layout="topleft"
+ name="Release Keys">
+ <menu_item_call.on_click
+ function="Tools.ReleaseKeys"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="Tools.EnableReleaseKeys"
+ parameter="" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set UI Size to Default"
+ layout="topleft"
+ name="Set UI Size to Default">
+ <menu_item_call.on_click
+ function="View.DefaultUISize" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Always Run"
+ layout="topleft"
+ name="Always Run"
+ shortcut="control|R">
+ <menu_item_check.on_check
+ function="World.CheckAlwaysRun" />
+ <menu_item_check.on_click
+ function="World.AlwaysRun" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fly"
+ layout="topleft"
+ name="Fly"
+ shortcut="Home">
+ <menu_item_check.on_click
+ function="Agent.toggleFlying" />
+ <menu_item_check.on_enable
+ function="Agent.enableFlying" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Close Window"
+ layout="topleft"
+ name="Close Window"
+ shortcut="control|W">
+ <menu_item_call.on_click
+ function="File.CloseWindow" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseWindow" />
+ </menu_item_call>
+ <menu_item_call
+ label="Close All Windows"
+ layout="topleft"
+ name="Close All Windows"
+ shortcut="control|shift|W">
+ <menu_item_call.on_click
+ function="File.CloseAllWindows" />
+ <menu_item_call.on_enable
+ function="File.EnableCloseAllWindows" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Snapshot to Disk"
+ layout="topleft"
+ name="Snapshot to Disk"
+ shortcut="control|`"
+ use_mac_ctrl="true">
+ <menu_item_call.on_click
+ function="File.TakeSnapshotToDisk" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Mouselook"
+ layout="topleft"
+ name="Mouselook"
+ shortcut="M">
+ <menu_item_call.on_click
+ function="View.Mouselook" />
+ <menu_item_call.on_enable
+ function="View.EnableMouselook" />
+ </menu_item_call>
+ <menu_item_check
+ label="Joystick Flycam"
+ layout="topleft"
+ name="Joystick Flycam"
+ shortcut="alt|shift|F">
+ <menu_item_check.on_check
+ function="View.CheckJoystickFlycam" />
+ <menu_item_check.on_click
+ function="View.JoystickFlycam" />
+ <menu_item_check.on_enable
+ function="View.EnableJoystickFlycam" />
+ </menu_item_check>
+ <menu_item_call
+ label="Reset View"
+ layout="topleft"
+ name="Reset View"
+ shortcut="Esc">
+ <menu_item_call.on_click
+ function="View.ResetView" />
+ </menu_item_call>
+ <menu_item_call
+ label="Look at Last Chatter"
+ layout="topleft"
+ name="Look at Last Chatter"
+ shortcut="control|\">
+ <menu_item_call.on_click
+ function="View.LookAtLastChatter" />
+ <menu_item_call.on_enable
+ function="View.EnableLastChatter" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Select Build Tool"
+ layout="topleft"
+ name="Select Tool"
+ tear_off="true">
+ <menu_item_call
+ label="Focus Tool"
+ layout="topleft"
+ name="Focus"
+ shortcut="control|1">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="focus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Move Tool"
+ layout="topleft"
+ name="Move"
+ shortcut="control|2">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="move" />
+ </menu_item_call>
+ <menu_item_call
+ label="Edit Tool"
+ layout="topleft"
+ name="Edit"
+ shortcut="control|3">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="edit" />
+ </menu_item_call>
+ <menu_item_call
+ label="Create Tool"
+ layout="topleft"
+ name="Create"
+ shortcut="control|4">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="create" />
+ </menu_item_call>
+ <menu_item_call
+ label="Land Tool"
+ layout="topleft"
+ name="Land"
+ shortcut="control|5">
+ <menu_item_call.on_click
+ function="Tools.SelectTool"
+ parameter="land" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Zoom In"
+ layout="topleft"
+ name="Zoom In"
+ shortcut="control|0">
+ <menu_item_call.on_click
+ function="View.ZoomIn" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Default"
+ layout="topleft"
+ name="Zoom Default"
+ shortcut="control|9">
+ <menu_item_call.on_click
+ function="View.ZoomDefault" />
+ </menu_item_call>
+ <menu_item_call
+ label="Zoom Out"
+ layout="topleft"
+ name="Zoom Out"
+ shortcut="control|8">
+ <menu_item_call.on_click
+ function="View.ZoomOut" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Toggle Fullscreen"
+ layout="topleft"
+ name="Toggle Fullscreen"
+ >
+ <!-- Note: shortcut="alt|Enter" was deleted from the preceding node-->
+ <menu_item_call.on_click
+ function="View.Fullscreen" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Show Debug Settings"
+ layout="topleft"
+ name="Debug Settings">
+ <menu_item_call.on_click
+ function="Advanced.ShowDebugSettings"
+ parameter="all" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show Develop Menu"
+ layout="topleft"
+ name="Debug Mode"
+ shortcut="control|alt|Q">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="QAMode" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="QAMode" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Develop"
+ layout="topleft"
+ name="Develop"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Consoles"
+ layout="topleft"
+ name="Consoles"
+ tear_off="true">
+ <menu_item_check
+ label="Texture Console"
+ layout="topleft"
+ name="Texture Console"
+ shortcut="control|shift|3"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Console"
+ layout="topleft"
+ name="Debug Console"
+ shortcut="control|shift|4"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="debug" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="debug" />
+ </menu_item_check>
+ <menu_item_call
+ label="Notifications Console"
+ layout="topleft"
+ name="Notifications"
+ shortcut="control|shift|5">
+ <menu_item_call.on_click
+ function="Floater.Toggle"
+ parameter="notifications_console" />
+ </menu_item_call>
+ <menu_item_check
+ label="Texture Size Console"
+ layout="topleft"
+ name="Texture Size"
+ shortcut="control|shift|6">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture size" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture size" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Category Console"
+ layout="topleft"
+ name="Texture Category"
+ shortcut="control|shift|7">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="texture category" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="texture category" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fast Timers"
+ layout="topleft"
+ name="Fast Timers"
+ shortcut="control|shift|9"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="fast timers" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="fast timers" />
+ </menu_item_check>
+ <menu_item_check
+ label="Memory"
+ layout="topleft"
+ name="Memory"
+ shortcut="control|shift|0"
+ use_mac_ctrl="true">
+ <menu_item_check.on_check
+ function="Advanced.CheckConsole"
+ parameter="memory view" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleConsole"
+ parameter="memory view" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Region Info to Debug Console"
+ layout="topleft"
+ name="Region Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="region" />
+ </menu_item_call>
+ <menu_item_call
+ label="Group Info to Debug Console"
+ layout="topleft"
+ name="Group Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="group" />
+ </menu_item_call>
+ <menu_item_call
+ label="Capabilities Info to Debug Console"
+ layout="topleft"
+ name="Capabilities Info to Debug Console">
+ <menu_item_call.on_click
+ function="Advanced.DumpInfoToConsole"
+ parameter="capabilities" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Camera"
+ layout="topleft"
+ name="Camera">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="camera" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="camera" />
+ </menu_item_check>
+ <menu_item_check
+ label="Wind"
+ layout="topleft"
+ name="Wind">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="wind" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="wind" />
+ </menu_item_check>
+ <menu_item_check
+ label="FOV"
+ layout="topleft"
+ name="FOV">
+ <menu_item_check.on_check
+ function="Advanced.CheckHUDInfo"
+ parameter="fov" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleHUDInfo"
+ parameter="fov" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Show Info"
+ layout="topleft"
+ name="Display Info"
+ tear_off="true">
+ <menu_item_check
+ label="Show Time"
+ layout="topleft"
+ name="Show Time">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowTime" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowTime" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Render Info"
+ layout="topleft"
+ name="Show Render Info">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowRenderInfo" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowRenderInfo" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Matrices"
+ layout="topleft"
+ name="Show Matrices">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowRenderMatrices" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowRenderMatrices" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Color Under Cursor"
+ layout="topleft"
+ name="Show Color Under Cursor">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugShowColor" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugShowColor" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Show Updates to Objects"
+ layout="topleft"
+ name="Show Updates"
+ shortcut="control|alt|shift|U">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowObjectUpdates"
+ parameter="ObjectUpdates" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowObjectUpdates" />
+ </menu_item_check>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu
+ create_jump_keys="true"
+ label="Force an Error"
+ layout="topleft"
+ name="Force Errors"
+ tear_off="true">
+ <menu_item_call
+ label="Force Breakpoint"
+ layout="topleft"
+ name="Force Breakpoint"
+ shortcut="control|alt|shift|B">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorBreakpoint" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force LLError And Crash"
+ layout="topleft"
+ name="Force LLError And Crash">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorLlerror" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Bad Memory Access"
+ layout="topleft"
+ name="Force Bad Memory Access">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorBadMemoryAccess" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Infinite Loop"
+ layout="topleft"
+ name="Force Infinite Loop">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorInfiniteLoop" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Driver Crash"
+ layout="topleft"
+ name="Force Driver Carsh">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorDriverCrash" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Software Exception"
+ layout="topleft"
+ name="Force Software Exception">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorSoftwareException" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Disconnect Viewer"
+ layout="topleft"
+ name="Force Disconnect Viewer">
+ <menu_item_call.on_click
+ function="Advanced.ForceErrorDisconnectViewer" />
+ </menu_item_call>
+ <menu_item_call
+ label="Simulate a Memory Leak..."
+ layout="topleft"
+ name="Memory Leaking Simulation">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="mem_leaking" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Render Tests"
+ layout="topleft"
+ name="Render Tests"
+ tear_off="true">
+ <menu_item_check
+ label="Camera Offset"
+ layout="topleft"
+ name="Camera Offset">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CameraOffset" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CameraOffset" />
+ </menu_item_check>
+ <menu_item_check
+ label="Randomize Framerate"
+ layout="topleft"
+ name="Randomize Framerate">
+ <menu_item_check.on_check
+ function="Advanced.CheckRandomizeFramerate"
+ parameter="Randomize Framerate" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleRandomizeFramerate" />
+ </menu_item_check>
+ <menu_item_check
+ label="Periodic Slow Frame"
+ layout="topleft"
+ name="Periodic Slow Frame">
+ <menu_item_check.on_check
+ function="Advanced.CheckPeriodicSlowFrame"
+ parameter="points" />
+ <menu_item_check.on_click
+ function="Advanced.TogglePeriodicSlowFrame"
+ parameter="points" />
+ </menu_item_check>
+ <menu_item_check
+ label="Frame Test"
+ layout="topleft"
+ name="Frame Test">
+ <menu_item_check.on_check
+ function="Advanced.CheckFrameTest"
+ parameter="Frame Test" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleFrameTest" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Render Metadata"
+ layout="topleft"
+ name="Render Metadata"
+ tear_off="true">
+ <menu_item_check
+ label="Bounding Boxes"
+ layout="topleft"
+ name="Bounding Boxes">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="bboxes" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="bboxes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Octree"
+ layout="topleft"
+ name="Octree">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="octree" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="octree" />
+ </menu_item_check>
+ <menu_item_check
+ label="Shadow Frusta"
+ layout="topleft"
+ name="Shadow Frusta">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="shadow frusta" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="shadow frusta" />
+ </menu_item_check>
+ <menu_item_check
+ label="Occlusion"
+ layout="topleft"
+ name="Occlusion">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="occlusion" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="occlusion" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Batches"
+ layout="topleft"
+ name="Render Batches">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="render batches" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="render batches" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Anim"
+ layout="topleft"
+ name="Texture Anim">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture anim" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture anim" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Priority"
+ layout="topleft"
+ name="Texture Priority">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture priority" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture priority" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Area"
+ layout="topleft"
+ name="Texture Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="texture area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="texture area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Face Area"
+ layout="topleft"
+ name="Face Area">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="face area" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="face area" />
+ </menu_item_check>
+ <menu_item_check
+ label="Lights"
+ layout="topleft"
+ name="Lights">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="lights" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="lights" />
+ </menu_item_check>
+ <menu_item_check
+ label="Collision Skeleton"
+ layout="topleft"
+ name="Collision Skeleton">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="collision skeleton" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="collision skeleton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Raycast"
+ layout="topleft"
+ name="Raycast">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="raycast" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="raycast" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Rendering"
+ layout="topleft"
+ name="Rendering"
+ tear_off="true">
+ <menu_item_check
+ label="Axes"
+ name="Axes">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowAxes" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowAxes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Tangent Basis"
+ name="Tangent Basis">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowTangentBasis" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowTangentBasis" />
+ </menu_item_check>
+ <menu_item_call
+ label="Selected Texture Info Basis"
+ name="Selected Texture Info Basis"
+ shortcut="control|alt|shift|T">
+ <menu_item_call.on_click
+ function="Advanced.SelectedTextureInfo" />
+ </menu_item_call>
+ <menu_item_check
+ label="Wireframe"
+ name="Wireframe"
+ shortcut="control|shift|R">
+ <menu_item_check.on_check
+ function="Advanced.CheckWireframe"
+ parameter="Wireframe" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleWireframe" />
+ </menu_item_check>
+ <menu_item_check
+ label="Object-Object Occlusion"
+ name="Object-Object Occlusion"
+ shortcut="control|shift|O">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="UseOcclusion" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="UseOcclusion" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableObjectObjectOcclusion" />
+ </menu_item_check>
+ <menu_item_check
+ label="Framebuffer Objects"
+ name="Framebuffer Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderUseFBO" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderFBO" />
+ </menu_item_check>
+ <menu_item_check
+ label="Deferred Rendering"
+ name="Deferred Rendering">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferred" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferred" />
+ </menu_item_check>
+ <menu_item_check
+ label="Global Illumintation"
+ name="Global Illumination">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDeferredGI" />
+ <menu_item_check.on_enable
+ function="Advanced.EnableRenderDeferredGI" />
+ </menu_item_check>
+ <menu_item_separator />
+ <menu_item_check
+ label="Debug GL"
+ name="Debug GL">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDebugGL" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDebugGL" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Pipeline"
+ name="Debug Pipeline">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDebugGL" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDebugGL" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fast Alpha"
+ name="Fast Alpha">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderFastAlpha" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderFastAlpha" />
+ </menu_item_check>
+ <menu_item_check
+ label="Animation Textures"
+ name="Animation Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderDebugGL" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderDebugGL" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable Textures"
+ name="Disable Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="TextureDisable" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="TextureDisable" />
+ </menu_item_check>
+ <menu_item_check
+ label="Full Res Textures"
+ layout="topleft"
+ name="Rull Res Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="TextureLoadFullRes" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="TextureLoadFullRes" />
+ </menu_item_check>
+ <menu_item_check
+ label="Audit Textures"
+ layout="topleft"
+ name="Audit Textures">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AuditTexture" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AuditTexture" />
+ </menu_item_check>
+ <menu_item_check
+ label="Texture Atlas"
+ name="Texture Atlas">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="EnableTextureAtlas" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="EnableTextureAtlas" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Attached Lights"
+ name="Render Attached Lights">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderAttachedLights" />
+ <menu_item_check.on_click
+ function="Advanced.HandleAttchedLightParticles"
+ parameter="RenderAttachedLights" />
+ </menu_item_check>
+ <menu_item_check
+ label="Render Attached Particles"
+ name="Render Attached Particles">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderAttachedParticles" />
+ <menu_item_check.on_click
+ function="Advanced.HandleAttchedLightParticles"
+ parameter="RenderAttachedParticles" />
+ </menu_item_check>
+ <menu_item_check
+ label="Hover Glow Objects"
+ name="Hover Glow Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="RenderHighlightEnable" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="RenderHighlightEnable" />
+ </menu_item_check>
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="Network"
+ layout="topleft"
+ name="Network"
+ tear_off="true">
+ <menu_item_check
+ label="Pause Agent"
+ layout="topleft"
+ name="AgentPause">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AgentPause" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AgentPause" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Enable Message Log"
+ layout="topleft"
+ name="Enable Message Log">
+ <menu_item_call.on_click
+ function="Advanced.EnableMessageLog" />
+ </menu_item_call>
+ <menu_item_call
+ label="Disable Message Log"
+ layout="topleft"
+ name="Disable Message Log">
+ <menu_item_call.on_click
+ function="Advanced.DisableMessageLog" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Velocity Interpolate Objects"
+ layout="topleft"
+ name="Velocity Interpolate Objects">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="VelocityInterpolate" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="VelocityInterpolate" />
+ </menu_item_check>
+ <menu_item_check
+ label="Ping Interpolate Object Positions"
+ layout="topleft"
+ name="Ping Interpolate Object Positions">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="PingInterpolate" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="PingInterpolate" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Drop a Packet"
+ layout="topleft"
+ name="Drop a Packet"
+ shortcut="control|alt|L">
+ <menu_item_call.on_click
+ function="Advanced.DropPacket" />
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="Dump Scripted Camera"
+ layout="topleft"
+ name="Dump Scripted Camera">
+ <menu_item_call.on_click
+ function="Advanced.DumpScriptedCamera" />
+ </menu_item_call>
+ <menu_item_call
+ label="Bumps, Pushes &amp; Hits"
+ layout="topleft"
+ name="Bumps, Pushes &amp;amp; Hits">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="bumps" />
+ </menu_item_call>
+
+ <menu
+ create_jump_keys="true"
+ label="Recorder"
+ layout="topleft"
+ name="Recorder"
+ tear_off="true">
+ <menu_item_call
+ label="Start Playback"
+ layout="topleft"
+ name="Start Playback">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="start playback" />
+ </menu_item_call>
+ <menu_item_call
+ label="Stop Playback"
+ layout="topleft"
+ name="Stop Playback">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="stop playback" />
+ </menu_item_call>
+ <menu_item_check
+ label="Loop Playback"
+ layout="topleft"
+ name="Loop Playback">
+ <menu_item_check.on_check
+ function="Advanced.CheckAgentPilotLoop"
+ parameter="loopPlayback" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleAgentPilotLoop" />
+ </menu_item_check>
+ <menu_item_call
+ label="Start Record"
+ layout="topleft"
+ name="Start Record">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="start record" />
+ </menu_item_call>
+ <menu_item_call
+ label="Stop Record"
+ layout="topleft"
+ name="Stop Record">
+ <menu_item_call.on_click
+ function="Advanced.AgentPilot"
+ parameter="stop record" />
+ </menu_item_call>
+ </menu>
+
+ <menu
+ create_jump_keys="true"
+ label="World"
+ layout="topleft"
+ name="World"
+ tear_off="true">
+ <menu_item_check
+ label="Sim Sun Override"
+ layout="topleft"
+ name="Sim Sun Override">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SkyOverrideSimSunPosition" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SkyOverrideSimSunPosition" />
+ </menu_item_check>
+ <menu_item_check
+ label="Cheesy Beacon"
+ layout="topleft"
+ name="Cheesy Beacon">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="CheesyBeacon" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="CheesyBeacon" />
+ </menu_item_check>
+ <menu_item_check
+ label="Fixed Weather"
+ layout="topleft"
+ name="Fixed Weather">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="FixedWeather" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="FixedWeather" />
+ </menu_item_check>
+ <menu_item_call
+ label="Dump Region Object Cache"
+ layout="topleft"
+ name="Dump Region Object Cache">
+ <menu_item_call.on_click
+ function="Advanced.DumpRegionObjectCache" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="UI"
+ layout="topleft"
+ name="UI"
+ tear_off="true">
+ <!-- <menu_item_check
+ label="New Bottom Bar"
+ layout="topleft"
+ name="New Bottom Bar">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="BottomPanelNew" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="BottomPanelNew" />
+ </menu_item_check>-->
+ <menu_item_call
+ label="Web Browser Test"
+ layout="topleft"
+ name="Web Browser Test">
+ <menu_item_call.on_click
+ function="Advanced.WebBrowserTest"
+ parameter="http://secondlife.com/app/search/slurls.html"/>
+ </menu_item_call>
+ <menu_item_call
+ label="Dump SelectMgr"
+ layout="topleft"
+ name="Dump SelectMgr">
+ <menu_item_call.on_click
+ function="Advanced.DumpSelectMgr" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Inventory"
+ layout="topleft"
+ name="Dump Inventory">
+ <menu_item_call.on_click
+ function="Advanced.DumpInventory" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Timers"
+ name="Dump Timers">
+ <menu_item_call.on_click
+ function="Advanced.DumpTimers" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Focus Holder"
+ layout="topleft"
+ name="Dump Focus Holder"
+ shortcut="control|alt|F">
+ <menu_item_call.on_click
+ function="Advanced.DumpFocusHolder" />
+ </menu_item_call>
+ <menu_item_call
+ label="Print Selected Object Info"
+ layout="topleft"
+ name="Print Selected Object Info"
+ shortcut="control|shift|P">
+ <menu_item_call.on_click
+ function="Advanced.PrintSelectedObjectInfo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Print Agent Info"
+ layout="topleft"
+ name="Print Agent Info"
+ shortcut="shift|P">
+ <menu_item_call.on_click
+ function="Advanced.PrintAgentInfo" />
+ </menu_item_call>
+ <menu_item_call
+ label="Memory Stats"
+ layout="topleft"
+ name="Memory Stats"
+ shortcut="control|alt|shift|M">
+ <menu_item_call.on_click
+ function="Advanced.PrintTextureMemoryStats" />
+ </menu_item_call>
+ <menu_item_check
+ label="Double-ClickAuto-Pilot"
+ layout="topleft"
+ name="Double-ClickAuto-Pilot">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DoubleClickAutoPilot" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DoubleClickAutoPilot" />
+ </menu_item_check>
+
+ <menu_item_separator />
+ <menu_item_check
+ label="Debug SelectMgr"
+ layout="topleft"
+ name="Debug SelectMgr">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugSelectMgr" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugSelectMgr" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Clicks"
+ layout="topleft"
+ name="Debug Clicks">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugClicks"
+ parameter="DebugClicks" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugClicks"
+ parameter="DebugClicks" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Views"
+ layout="topleft"
+ name="Debug Views">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugViews" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugViews" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Name Tooltips"
+ layout="topleft"
+ name="Debug Name Tooltips">
+ <menu_item_check.on_check
+ function="Advanced.CheckXUINameTooltips"
+ parameter="XUINameTooltips" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleXUINameTooltips" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Mouse Events"
+ layout="topleft"
+ name="Debug Mouse Events">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugMouseEvents"
+ parameter="MouseEvents" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugMouseEvents" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Keys"
+ layout="topleft"
+ name="Debug Keys">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugKeys"
+ parameter="DebugKeys" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugKeys" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug WindowProc"
+ layout="topleft"
+ name="Debug WindowProc">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugWindowProc"
+ parameter="DebugWindowProc" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugWindowProc"
+ parameter="DebugWindowProc" />
+ </menu_item_check>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="XUI"
+ name="XUI"
+ tear_off="true">
+ <menu_item_call
+ label="Reload Color Settings"
+ layout="topleft"
+ name="Reload Color Settings">
+ <menu_item_call.on_click
+ function="Advanced.ReloadColorSettings" />
+ </menu_item_call>
+ <menu_item_call
+ label="Show Font Test"
+ layout="topleft"
+ name="Show Font Test">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="font_test" />
+ </menu_item_call>
+ <menu_item_call
+ label="Load from XML..."
+ layout="topleft"
+ name="Load from XML">
+ <menu_item_call.on_click
+ function="Advanced.LoadUIFromXML" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save to XML..."
+ layout="topleft"
+ name="Save to XML">
+ <menu_item_call.on_click
+ function="Advanced.SaveUIToXML" />
+ </menu_item_call>
+ <menu_item_check
+ label="Show XUI Names"
+ layout="topleft"
+ name="Show XUI Names">
+ <menu_item_check.on_check
+ function="Advanced.CheckXUINames"
+ parameter="showUIname" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleXUINames" />
+ </menu_item_check>
+ <menu_item_call
+ label="Send Test IMs"
+ layout="topleft"
+ name="Send Test IMs">
+ <menu_item_call.on_click
+ function="Advanced.SendTestIMs" />
+ </menu_item_call>
+ <menu_item_call
+ label="Test Inspectors"
+ name="Test Inspectors"
+ shortcut="control|shift|I">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="test_inspectors" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Avatar"
+ layout="topleft"
+ name="Character"
+ tear_off="true">
+ <menu
+ create_jump_keys="true"
+ label="Grab Baked Texture"
+ layout="topleft"
+ name="Grab Baked Texture"
+ tear_off="true">
+ <menu_item_call
+ label="Iris"
+ layout="topleft"
+ name="Iris">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="iris" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="iris" />
+ </menu_item_call>
+ <menu_item_call
+ label="Head"
+ layout="topleft"
+ name="Head">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="head" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="head" />
+ </menu_item_call>
+ <menu_item_call
+ label="Upper Body"
+ layout="topleft"
+ name="Upper Body">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="upper" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="upper" />
+ </menu_item_call>
+ <menu_item_call
+ label="Lower Body"
+ layout="topleft"
+ name="Lower Body">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="lower" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="lower" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Advanced.GrabBakedTexture"
+ parameter="skirt" />
+ <menu_item_call.on_enable
+ function="Advanced.EnableGrabBakedTexture"
+ parameter="skirt" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Character Tests"
+ layout="topleft"
+ name="Character Tests"
+ tear_off="true">
+ <menu_item_call
+ label="Appearance To XML"
+ layout="topleft"
+ name="Appearance To XML">
+ <menu_item_call.on_click
+ function="Advanced.AppearanceToXML" />
+ </menu_item_call>
+ <menu_item_call
+ label="Toggle Character Geometry"
+ layout="topleft"
+ name="Toggle Character Geometry">
+ <menu_item_call.on_click
+ function="Advanced.ToggleCharacterGeometry" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Test Male"
+ layout="topleft"
+ name="Test Male">
+ <menu_item_call.on_click
+ function="Advanced.TestMale" />
+ </menu_item_call>
+ <menu_item_call
+ label="Test Female"
+ layout="topleft"
+ name="Test Female">
+ <menu_item_call.on_click
+ function="Advanced.TestFemale" />
+ </menu_item_call>
+ <menu_item_call
+ label="Toggle PG"
+ layout="topleft"
+ name="Toggle PG">
+ <menu_item_call.on_click
+ function="Advanced.TogglePG" />
+ </menu_item_call>
+ <menu_item_check
+ label="Allow Select Avatar"
+ layout="topleft"
+ name="Allow Select Avatar">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="AllowSelectAvatar" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="AllowSelectAvatar" />
+ </menu_item_check>
+ </menu>
+ <menu_item_call
+ label="Force Params to Default"
+ layout="topleft"
+ name="Force Params to Default">
+ <menu_item_call.on_click
+ function="Advanced.ForceParamsToDefault" />
+ </menu_item_call>
+ <menu_item_check
+ label="Animation Info"
+ layout="topleft"
+ name="Animation Info">
+ <menu_item_check.on_check
+ function="Advanced.CheckAnimationInfo"
+ parameter="AnimationInfo" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleAnimationInfo"
+ parameter="" />
+ </menu_item_check>
+ <menu_item_check
+ label="Slow Motion Animations"
+ layout="topleft"
+ name="Slow Motion Animations">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SlowMotionAnimation" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SlowMotionAnimation" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Look At"
+ layout="topleft"
+ name="Show Look At">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowLookAt"
+ parameter="ShowLookAt" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowLookAt" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Point At"
+ layout="topleft"
+ name="Show Point At">
+ <menu_item_check.on_check
+ function="Advanced.CheckShowPointAt"
+ parameter="ShowPointAt" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleShowPointAt" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Joint Updates"
+ layout="topleft"
+ name="Debug Joint Updates">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugJointUpdates"
+ parameter="DebugJointUpdates" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugJointUpdates" />
+ </menu_item_check>
+ <menu_item_check
+ label="Disable LOD"
+ layout="topleft"
+ name="Disable LOD">
+ <menu_item_check.on_check
+ function="Advanced.CheckDisableLOD"
+ parameter="DisableLOD" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDisableLOD" />
+ </menu_item_check>
+ <menu_item_check
+ label="Debug Character Vis"
+ layout="topleft"
+ name="Debug Character Vis">
+ <menu_item_check.on_check
+ function="Advanced.CheckDebugCharacterVis"
+ parameter="DebugCharacterVis" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleDebugCharacterVis" />
+ </menu_item_check>
+ <menu_item_check
+ label="Show Collision Skeleton"
+ layout="topleft"
+ name="Show Collision Skeleton">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="collision skeleton" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="collision skeleton" />
+ </menu_item_check>
+ <menu_item_check
+ label="Display Agent Target"
+ layout="topleft"
+ name="Display Agent Target">
+ <menu_item_check.on_check
+ function="Advanced.CheckInfoDisplay"
+ parameter="agent target" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleInfoDisplay"
+ parameter="agent target" />
+ </menu_item_check>
+<!-- Appears not to exist anymore
+ <menu_item_check
+ label="Debug Rotation"
+ layout="topleft"
+ name="Debug Rotation">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="DebugAvatarRotation" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="DebugAvatarRotation" />
+ </menu_item_check> -->
+-->
+ <menu_item_call
+ label="Dump Attachments"
+ layout="topleft"
+ name="Dump Attachments">
+ <menu_item_call.on_click
+ function="Advanced.DumpAttachments" />
+ </menu_item_call>
+ <menu_item_call
+ label="Debug Avatar Textures"
+ layout="topleft"
+ name="Debug Avatar Textures"
+ shortcut="control|alt|shift|A">
+ <menu_item_call.on_click
+ function="Advanced.DebugAvatarTextures" />
+ </menu_item_call>
+ <menu_item_call
+ label="Dump Local Textures"
+ layout="topleft"
+ name="Dump Local Textures"
+ shortcut="alt|shift|M">
+ <menu_item_call.on_click
+ function="Advanced.DumpAvatarLocalTextures" />
+ </menu_item_call>
+ </menu>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Compress Images"
+ layout="topleft"
+ name="Compress Images">
+ <menu_item_call.on_click
+ function="Advanced.CompressImage" />
+ </menu_item_call>
+ <menu_item_check
+ label="Output Debug Minidump"
+ layout="topleft"
+ name="Output Debug Minidump">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="SaveMinidump" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="SaveMinidump" />
+ </menu_item_check>
+ <menu_item_check
+ label="Console Window on next Run"
+ layout="topleft"
+ name="Console Window">
+ <menu_item_check.on_check
+ function="CheckControl"
+ parameter="ShowConsoleWindow" />
+ <menu_item_check.on_click
+ function="ToggleControl"
+ parameter="ShowConsoleWindow" />
+ </menu_item_check>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_check
+ label="Show Admin Menu"
+ layout="topleft"
+ name="View Admin Options">
+ <menu_item_check.on_check
+ function="Advanced.CheckViewAdminOptions"
+ parameter="ViewAdminOptions" />
+ <menu_item_check.on_click
+ function="Advanced.ToggleViewAdminOptions" />
+ </menu_item_check>
+ <menu_item_call
+ label="Request Admin Status"
+ layout="topleft"
+ name="Request Admin Options"
+ shortcut="control|alt|G">
+ <menu_item_call.on_click
+ function="Advanced.RequestAdminStatus" />
+ </menu_item_call>
+ <menu_item_call
+ label="Leave Admin Status"
+ layout="topleft"
+ name="Leave Admin Options"
+ shortcut="control|alt|shift|G">
+ <menu_item_call.on_click
+ function="Advanced.LeaveAdminStatus" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Admin"
+ layout="topleft"
+ name="Admin"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Object"
+ layout="topleft"
+ tear_off="true">
+ <menu_item_call
+ label="Take Copy"
+ layout="topleft"
+ name="Take Copy"
+ shortcut="control|alt|shift|O">
+ <menu_item_call.on_click
+ function="Admin.ForceTakeCopy" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Owner To Me"
+ layout="topleft"
+ name="Force Owner To Me">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectOwnerSelf" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Force Owner Permissive"
+ layout="topleft"
+ name="Force Owner Permissive">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectOwnerPermissive" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Delete"
+ layout="topleft"
+ name="Delete"
+ shortcut="control|alt|shift|Del">
+ <menu_item_call.on_click
+ function="Admin.HandleForceDelete" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Lock"
+ layout="topleft"
+ name="Lock"
+ shortcut="control|alt|shift|L">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectLock" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Get Assets IDs"
+ layout="topleft"
+ name="Get Assets IDs"
+ shortcut="control|alt|shift|I">
+ <menu_item_call.on_click
+ function="Admin.HandleObjectAssetIDs" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Parcel"
+ layout="topleft"
+ name="Parcel"
+ tear_off="true">
+ <menu_item_call
+ label="Owner To Me"
+ layout="topleft"
+ name="Owner To Me">
+ <menu_item_call.on_click
+ function="Admin.HandleForceParcelOwnerToMe" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Set to Linden Content"
+ layout="topleft"
+ name="Set to Linden Content"
+ shortcut="control|alt|shift|C">
+ <menu_item_call.on_click
+ function="Admin.HandleForceParcelToContent" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Claim Public Land"
+ layout="topleft"
+ name="Claim Public Land">
+ <menu_item_call.on_click
+ function="Admin.HandleClaimPublicLand" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Region"
+ layout="topleft"
+ name="Region"
+ tear_off="true">
+ <menu_item_call
+ label="Dump Temp Asset Data"
+ layout="topleft"
+ name="Dump Temp Asset Data">
+ <menu_item_call.on_click
+ function="Admin.HandleRegionDumpTempAssetData" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ <menu_item_call
+ label="Save Region State"
+ layout="topleft"
+ name="Save Region State">
+ <menu_item_call.on_click
+ function="Admin.OnSaveState" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu_item_call
+ label="God Tools"
+ layout="topleft"
+ name="God Tools">
+ <menu_item_call.on_click
+ function="Floater.Show"
+ parameter="god_tools" />
+ <menu_item_call.on_enable
+ function="IsGodCustomerService" />
+ </menu_item_call>
+ </menu>
+ <menu
+ create_jump_keys="true"
+ label="Admin"
+ layout="topleft"
+ name="Deprecated"
+ tear_off="true"
+ visible="false">
+ <menu
+ create_jump_keys="true"
+ label="Attach Object"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Attach Object"
+ tear_off="true" />
+ <menu
+ create_jump_keys="true"
+ label="Detach Object"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Detach Object"
+ tear_off="true" />
+ <menu
+ create_jump_keys="true"
+ label="Take Off Clothing"
+ layout="topleft"
+ mouse_opaque="false"
+ name="Take Off Clothing"
+ tear_off="true">
+ <menu_item_call
+ label="Shirt"
+ layout="topleft"
+ name="Shirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Pants"
+ layout="topleft"
+ name="Pants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="pants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="pants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Shoes"
+ layout="topleft"
+ name="Shoes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="shoes" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="shoes" />
+ </menu_item_call>
+ <menu_item_call
+ label="Socks"
+ layout="topleft"
+ name="Socks">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="socks" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="socks" />
+ </menu_item_call>
+ <menu_item_call
+ label="Jacket"
+ layout="topleft"
+ name="Jacket">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="jacket" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="jacket" />
+ </menu_item_call>
+ <menu_item_call
+ label="Gloves"
+ layout="topleft"
+ name="Gloves">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="gloves" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="gloves" />
+ </menu_item_call>
+ <menu_item_call
+ label="Undershirt"
+ layout="topleft"
+ name="Menu Undershirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="undershirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="undershirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Underpants"
+ layout="topleft"
+ name="Menu Underpants">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="underpants" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="underpants" />
+ </menu_item_call>
+ <menu_item_call
+ label="Skirt"
+ layout="topleft"
+ name="Skirt">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="skirt" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="skirt" />
+ </menu_item_call>
+ <menu_item_call
+ label="Alpha"
+ layout="topleft"
+ name="Alpha">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="alpha" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="alpha" />
+ </menu_item_call>
+ <menu_item_call
+ label="Tattoo"
+ layout="topleft"
+ name="Tattoo">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="tattoo" />
+ <menu_item_call.on_enable
+ function="Edit.EnableTakeOff"
+ parameter="tattoo" />
+ </menu_item_call>
+ <menu_item_call
+ label="All Clothes"
+ layout="topleft"
+ name="All Clothes">
+ <menu_item_call.on_click
+ function="Edit.TakeOff"
+ parameter="all" />
+ </menu_item_call>
+ </menu>
+ <menu_item_check
+ label="Show Toolbar"
+ layout="topleft"
+ name="Show Toolbar">
+ <menu_item_check.on_check
+ function="FloaterVisible"
+ parameter="toolbar" />
+ <menu_item_check.on_click
+ function="ShowFloater"
+ parameter="toolbar" />
+ </menu_item_check>
+ <menu
+ create_jump_keys="true"
+ label="Help"
+ layout="topleft"
+ name="Help"
+ tear_off="true">
+ <menu_item_call
+ label="Official Linden Blog"
+ layout="topleft"
+ name="Official Linden Blog">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="OfficialLindenBlog_url"
+ parameter="WebLaunchSupportWiki,http://blog.secondlife.com/" />
+ </menu_item_call>
+ <menu_item_call
+ label="Scripting Portal"
+ layout="topleft"
+ name="Scripting Portal">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="ScriptingPortal_url"
+ parameter="WebLaunchLSLWiki,http://wiki.secondlife.com/wiki/LSL_Portal" />
+ </menu_item_call>
+ <menu
+ create_jump_keys="true"
+ label="Bug Reporting"
+ layout="topleft"
+ name="Bug Reporting"
+ tear_off="true">
+ <menu_item_call
+ label="Public Issue Tracker"
+ layout="topleft"
+ name="Public Issue Tracker">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="PublicIssueTracker_url"
+ parameter="WebLaunchPublicIssue,http://jira.secondlife.com" />
+ </menu_item_call>
+ <menu_item_call
+ label="Public Issue Tracker Help"
+ layout="topleft"
+ name="Publc Issue Tracker Help">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="PublicIssueTrackerHelp_url"
+ parameter="WebLaunchPublicIssueHelp,http://wiki.secondlife.com/wiki/Issue_tracker" />
+ </menu_item_call>
+ <menu_item_separator
+ layout="topleft" />
+ <menu_item_call
+ label="Bug Reporting 101"
+ layout="topleft"
+ name="Bug Reporing 101">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="BugReporting101_url"
+ parameter="WebLaunchBugReport101,http://wiki.secondlife.com/wiki/Bug_Reporting_101" />
+ </menu_item_call>
+ <menu_item_call
+ label="Security Issues"
+ layout="topleft"
+ name="Security Issues">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="SecurityIssues_url"
+ parameter="WebLaunchSecurityIssues,http://wiki.secondlife.com/wiki/Security_issues" />
+ </menu_item_call>
+ <menu_item_call
+ label="QA Wiki"
+ layout="topleft"
+ name="QA Wiki">
+ <menu_item_call.on_click
+ function="PromptShowURL"
+ name="QAWiki_url"
+ parameter="WebLaunchQAWiki,http://wiki.secondlife.com/wiki/QA_Portal" />
+ </menu_item_call>
+ </menu>
+ </menu>
+ </menu>
+</menu_bar>
diff --git a/indra/newview/skins/default/xui/en/notifications.xml b/indra/newview/skins/default/xui/en/notifications.xml
index 989dc88851..227d0ae2cb 100644
--- a/indra/newview/skins/default/xui/en/notifications.xml
+++ b/indra/newview/skins/default/xui/en/notifications.xml
@@ -5699,7 +5699,7 @@ Attachment has been saved.
Unable to find the help topic for this element.
</notification>
- <notification
+ <notification
icon="alertmodal.tga"
name="ObjectMediaFailure"
type="alertmodal">
@@ -5710,6 +5710,29 @@ Server Error: Media update or get failed.
yestext="OK"/>
</notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="ConfirmClearTeleportHistory"
+ type="alertmodal">
+Are you sure you want to delete your teleport history?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="OK"/>
+ </notification>
+
+ <notification
+ icon="alertmodal.tga"
+ name="UploadCostConfirmation"
+ type="alertmodal">
+This upload will cost L$[PRICE], do you wish to continue with the upload?
+ <usetemplate
+ name="okcancelbuttons"
+ notext="Cancel"
+ yestext="Upload"/>
+ </notification>
+
<notification
icon="alertmodal.tga"
name="ConfirmClearTeleportHistory"
diff --git a/indra/newview/skins/default/xui/en/panel_main_inventory.xml b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
index fcee0ef953..d5887c46e8 100644
--- a/indra/newview/skins/default/xui/en/panel_main_inventory.xml
+++ b/indra/newview/skins/default/xui/en/panel_main_inventory.xml
@@ -16,7 +16,7 @@
<filter_editor
text_pad_left="12"
follows="left|top|right"
- font="SanSerif"
+ font="SanSerif"
height="20"
label="Filter"
layout="topleft"
@@ -61,7 +61,7 @@
height="30"
layout="bottomleft"
left="0"
- visible="true"
+ visible="true"
name="bottom_panel"
width="330">
<button
@@ -112,7 +112,7 @@
mouse_opaque="false"
name="Inventory Menu"
top="15"
- visible="true"
+ visible="true"
width="290">
<menu
height="101"
@@ -170,6 +170,26 @@
function="File.EnableUpload" />
</menu_item_call>
<menu_item_call
+ label="Model (L$[COST])..."
+ layout="topleft"
+ name="Upload Model">
+ <menu_item_call.on_click
+ function="File.UploadModel"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
+ label="Scene..."
+ layout="topleft"
+ name="Upload Scene">
+ <menu_item_call.on_click
+ function="File.UploadScene"
+ parameter="" />
+ <menu_item_call.on_enable
+ function="File.EnableUpload" />
+ </menu_item_call>
+ <menu_item_call
label="Bulk (L$[COST] per file)..."
layout="topleft"
name="Bulk Upload">
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index c850dce141..2fdc8337c8 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -1873,6 +1873,7 @@ this texture in your inventory
<string name="InvFolder favorite">Favorites</string>
<string name="InvFolder Current Outfit">Current Outfit</string>
<string name="InvFolder My Outfits">My Outfits</string>
+ <string name="InvFolder Meshes">Meshes</string>
<!-- are used for Friends and Friends/All folders in Inventory "Calling cards" folder. See EXT-694-->
<string name="InvFolder Friends">Friends</string>
diff --git a/indra/newview/viewer_manifest.py b/indra/newview/viewer_manifest.py
index b85d31d1ac..2ac759909b 100755
--- a/indra/newview/viewer_manifest.py
+++ b/indra/newview/viewer_manifest.py
@@ -268,8 +268,15 @@ class WindowsManifest(ViewerManifest):
# For using FMOD for sound... DJS
self.path("fmod.dll")
+
+ # For automatic level of detail generation in mesh importer
+ self.path("glod.dll")
+
+ # For reading collada files
+ self.path("libcollada14dom21.dll")
self.enable_no_crt_manifest_check()
+
# Media plugins - QuickTime
if self.prefix(src='../media_plugins/quicktime/%s' % self.args['configuration'], dst="llplugin"):
self.path("media_plugin_quicktime.dll")