summaryrefslogtreecommitdiff
path: root/indra
diff options
context:
space:
mode:
authorgabriel lee <gabriel@lindenlab.com>2009-12-19 02:02:38 +0000
committergabriel lee <gabriel@lindenlab.com>2009-12-19 02:02:38 +0000
commit75a4c5a6dd0cdaf9755bf40821d23c45296181d4 (patch)
tree18c897f956ecf0588c3b342bdde1f8c0a6c7daad /indra
parent06019288c181ad986e854969214a5c6ec3ba69b2 (diff)
parente148eebff38acd2c552971c4f24bea79d477dcec (diff)
added script limits floater
reviewed by mani
Diffstat (limited to 'indra')
-rw-r--r--indra/newview/CMakeLists.txt4
-rw-r--r--indra/newview/llfloaterland.cpp22
-rw-r--r--indra/newview/llfloaterland.h7
-rw-r--r--indra/newview/llfloaterscriptlimits.cpp1061
-rw-r--r--indra/newview/llfloaterscriptlimits.h259
-rw-r--r--indra/newview/llfloatertopobjects.cpp5
-rw-r--r--indra/newview/llviewerfloaterreg.cpp2
-rw-r--r--indra/newview/llviewerregion.cpp3
-rw-r--r--indra/newview/skins/default/xui/en/floater_about_land.xml12
-rw-r--r--indra/newview/skins/default/xui/en/floater_customize.xml10
-rw-r--r--indra/newview/skins/default/xui/en/floater_script_limits.xml20
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml62
-rw-r--r--indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml122
-rw-r--r--indra/newview/skins/default/xui/en/strings.xml53
14 files changed, 1636 insertions, 6 deletions
diff --git a/indra/newview/CMakeLists.txt b/indra/newview/CMakeLists.txt
index 8953682fae..9f7b782320 100644
--- a/indra/newview/CMakeLists.txt
+++ b/indra/newview/CMakeLists.txt
@@ -200,6 +200,7 @@ set(viewer_SOURCE_FILES
llfloaterregioninfo.cpp
llfloaterreporter.cpp
llfloaterscriptdebug.cpp
+ llfloaterscriptlimits.cpp
llfloatersearch.cpp
llfloatersellland.cpp
llfloatersettingsdebug.cpp
@@ -696,7 +697,7 @@ set(viewer_HEADER_FILES
llfloatermediasettings.h
llfloatermemleak.h
llfloaternamedesc.h
- llfloaternearbymedia.h
+ llfloaternearbymedia.h
llfloaternotificationsconsole.h
llfloateropenobject.h
llfloaterparcel.h
@@ -709,6 +710,7 @@ set(viewer_HEADER_FILES
llfloaterregioninfo.h
llfloaterreporter.h
llfloaterscriptdebug.h
+ llfloaterscriptlimits.h
llfloatersearch.h
llfloatersellland.h
llfloatersettingsdebug.h
diff --git a/indra/newview/llfloaterland.cpp b/indra/newview/llfloaterland.cpp
index 81322abbf7..02884575b0 100644
--- a/indra/newview/llfloaterland.cpp
+++ b/indra/newview/llfloaterland.cpp
@@ -52,6 +52,7 @@
#include "llfloateravatarpicker.h"
#include "llfloaterauction.h"
#include "llfloatergroups.h"
+#include "llfloaterscriptlimits.h"
#include "llavataractions.h"
#include "lllineeditor.h"
#include "llnamelistctrl.h"
@@ -148,6 +149,10 @@ void send_parcel_select_objects(S32 parcel_local_id, U32 return_type,
msg->sendReliable(region->getHost());
}
+LLParcel* LLFloaterLand::getCurrentSelectedParcel()
+{
+ return mParcel->getParcel();
+};
//static
LLPanelLandObjects* LLFloaterLand::getCurrentPanelLandObjects()
@@ -421,6 +426,9 @@ BOOL LLPanelLandGeneral::postBuild()
mBtnBuyLand = getChild<LLButton>("Buy Land...");
mBtnBuyLand->setClickedCallback(onClickBuyLand, (void*)&BUY_PERSONAL_LAND);
+ mBtnScriptLimits = getChild<LLButton>("Scripts...");
+ mBtnScriptLimits->setClickedCallback(onClickScriptLimits, this);
+
mBtnBuyGroupLand = getChild<LLButton>("Buy For Group...");
mBtnBuyGroupLand->setClickedCallback(onClickBuyLand, (void*)&BUY_GROUP_LAND);
@@ -508,6 +516,7 @@ void LLPanelLandGeneral::refresh()
mTextDwell->setText(LLStringUtil::null);
mBtnBuyLand->setEnabled(FALSE);
+ mBtnScriptLimits->setEnabled(FALSE);
mBtnBuyGroupLand->setEnabled(FALSE);
mBtnReleaseLand->setEnabled(FALSE);
mBtnReclaimLand->setEnabled(FALSE);
@@ -715,6 +724,8 @@ void LLPanelLandGeneral::refresh()
mBtnBuyLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
+ mBtnScriptLimits->setEnabled(true);
+// LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, false));
mBtnBuyGroupLand->setEnabled(
LLViewerParcelMgr::getInstance()->canAgentBuyParcel(parcel, true));
@@ -854,6 +865,17 @@ void LLPanelLandGeneral::onClickBuyLand(void* data)
LLViewerParcelMgr::getInstance()->startBuyLand(*for_group);
}
+// static
+void LLPanelLandGeneral::onClickScriptLimits(void* data)
+{
+ LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
+ LLParcel* parcel = panelp->mParcel->getParcel();
+ if(parcel != NULL)
+ {
+ LLFloaterReg::showInstance("script_limits");
+ }
+}
+
BOOL LLPanelLandGeneral::enableDeedToGroup(void* data)
{
LLPanelLandGeneral* panelp = (LLPanelLandGeneral*)data;
diff --git a/indra/newview/llfloaterland.h b/indra/newview/llfloaterland.h
index f7fb978c2a..eb47fbe15b 100644
--- a/indra/newview/llfloaterland.h
+++ b/indra/newview/llfloaterland.h
@@ -70,6 +70,7 @@ class LLPanelLandAccess;
class LLPanelLandBan;
class LLPanelLandRenters;
class LLPanelLandCovenant;
+class LLParcel;
class LLFloaterLand
: public LLFloater
@@ -80,7 +81,9 @@ public:
static LLPanelLandObjects* getCurrentPanelLandObjects();
static LLPanelLandCovenant* getCurrentPanelLandCovenant();
-
+
+ LLParcel* getCurrentSelectedParcel();
+
virtual void onOpen(const LLSD& key);
virtual BOOL postBuild();
@@ -146,6 +149,7 @@ public:
static BOOL enableDeedToGroup(void*);
static void onClickDeed(void*);
static void onClickBuyLand(void* data);
+ static void onClickScriptLimits(void* data);
static void onClickRelease(void*);
static void onClickReclaim(void*);
static void onClickBuyPass(void* deselect_when_done);
@@ -215,6 +219,7 @@ protected:
LLTextBox* mTextDwell;
LLButton* mBtnBuyLand;
+ LLButton* mBtnScriptLimits;
LLButton* mBtnBuyGroupLand;
// these buttons share the same location, but
diff --git a/indra/newview/llfloaterscriptlimits.cpp b/indra/newview/llfloaterscriptlimits.cpp
new file mode 100644
index 0000000000..3042fbc6ec
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.cpp
@@ -0,0 +1,1061 @@
+/**
+ * @file llfloaterscriptlimits.cpp
+ * @author Gabriel Lee
+ * @brief Implementation of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llfloaterscriptlimits.h"
+
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+#include "message.h"
+
+#include "llagent.h"
+#include "llfloateravatarpicker.h"
+#include "llfloaterland.h"
+#include "llfloaterreg.h"
+#include "llregionhandle.h"
+#include "llscrolllistctrl.h"
+#include "llscrolllistitem.h"
+#include "llparcel.h"
+#include "lltabcontainer.h"
+#include "lltracker.h"
+#include "lltrans.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+
+///----------------------------------------------------------------------------
+/// LLFloaterScriptLimits
+///----------------------------------------------------------------------------
+
+// due to server side bugs the full summary display is not possible
+// until they are fixed this define creates a simple version of the
+// summary which only shows available & correct information
+#define USE_SIMPLE_SUMMARY
+
+LLFloaterScriptLimits::LLFloaterScriptLimits(const LLSD& seed)
+ : LLFloater(seed)
+{
+}
+
+BOOL LLFloaterScriptLimits::postBuild()
+{
+ // a little cheap and cheerful - if there's an about land panel open default to showing parcel info,
+ // otherwise default to showing attachments (avatar appearance)
+ bool selectParcelPanel = false;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(instance)
+ {
+ if(instance->isShown())
+ {
+ selectParcelPanel = true;
+ }
+ }
+
+ mTab = getChild<LLTabContainer>("scriptlimits_panels");
+
+ // contruct the panels
+ LLPanelScriptLimitsRegionMemory* panel_memory;
+ panel_memory = new LLPanelScriptLimitsRegionMemory;
+ mInfoPanels.push_back(panel_memory);
+
+ LLUICtrlFactory::getInstance()->buildPanel(panel_memory, "panel_script_limits_region_memory.xml");
+ mTab->addTabPanel(panel_memory);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = new LLPanelScriptLimitsRegionURLs;
+ mInfoPanels.push_back(panel_urls);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_urls, "panel_script_limits_region_urls.xml");
+ mTab->addTabPanel(panel_urls);
+
+ LLPanelScriptLimitsAttachment* panel_attachments = new LLPanelScriptLimitsAttachment;
+ mInfoPanels.push_back(panel_attachments);
+ LLUICtrlFactory::getInstance()->buildPanel(panel_attachments, "panel_script_limits_my_avatar.xml");
+ mTab->addTabPanel(panel_attachments);
+
+ if(selectParcelPanel)
+ {
+ mTab->selectTab(0);
+ }
+ else
+ {
+ mTab->selectTab(2);
+ }
+
+ return TRUE;
+}
+
+LLFloaterScriptLimits::~LLFloaterScriptLimits()
+{
+}
+
+// public
+void LLFloaterScriptLimits::refresh()
+{
+ for(info_panels_t::iterator iter = mInfoPanels.begin();
+ iter != mInfoPanels.end(); ++iter)
+ {
+ (*iter)->refresh();
+ }
+}
+
+
+///----------------------------------------------------------------------------
+// Base class for panels
+///----------------------------------------------------------------------------
+
+LLPanelScriptLimitsInfo::LLPanelScriptLimitsInfo()
+ : LLPanel()
+{
+}
+
+
+// virtual
+BOOL LLPanelScriptLimitsInfo::postBuild()
+{
+ refresh();
+ return TRUE;
+}
+
+// virtual
+void LLPanelScriptLimitsInfo::updateChild(LLUICtrl* child_ctr)
+{
+}
+
+///----------------------------------------------------------------------------
+// Responders
+///----------------------------------------------------------------------------
+
+void fetchScriptLimitsRegionInfoResponder::result(const LLSD& content)
+{
+ // at this point we have an llsd which should contain ether one or two urls to the services we want.
+ // first we look for the details service:
+ if(content.has("ScriptResourceDetails"))
+ {
+ LLHTTPClient::get(content["ScriptResourceDetails"], new fetchScriptLimitsRegionDetailsResponder(mInfo));
+ }
+ else
+ {
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+
+// temp - only show info if we get details - there's nothing to show if not until the sim gets fixed
+#ifdef USE_SIMPLE_SUMMARY
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ std::string msg = LLTrans::getString("ScriptLimitsRequestDontOwnParcel");
+ panel_memory->childSetValue("loading_text", LLSD(msg));
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->childSetValue("loading_text", LLSD(msg));
+
+ // intentional early out as we dont want the resource summary if we are using the "simple summary"
+ // and the details are missing
+ return;
+#endif
+ }
+ }
+
+ // then the summary service:
+ if(content.has("ScriptResourceSummary"))
+ {
+ LLHTTPClient::get(content["ScriptResourceSummary"], new fetchScriptLimitsRegionSummaryResponder(mInfo));
+ }
+}
+
+void fetchScriptLimitsRegionInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionSummaryResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionSummary(content);
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionSummary(content);
+ }
+}
+
+void fetchScriptLimitsRegionSummaryResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsRegionDetailsResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->setRegionDetails(content);
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->setRegionDetails(content);
+ }
+}
+
+void fetchScriptLimitsRegionDetailsResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::result(const LLSD& content)
+{
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+
+ if(!instance)
+ {
+ llinfos << "Failed to get llfloaterscriptlimits instance" << llendl;
+ }
+ else
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel->setAttachmentDetails(content);
+ }
+}
+
+void fetchScriptLimitsAttachmentInfoResponder::error(U32 status, const std::string& reason)
+{
+ llinfos << "Error from responder " << reason << llendl;
+}
+
+///----------------------------------------------------------------------------
+// Memory Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsRegionMemory::getLandScriptResources()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("LandResources");
+ if (!url.empty())
+ {
+ body["parcel_id"] = mParcelId;
+
+ LLSD info;
+ info["parcel_id"] = mParcelId;
+ LLHTTPClient::post(url, body, new fetchScriptLimitsRegionInfoResponder(info));
+
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::processParcelInfo(const LLParcelData& parcel_data)
+{
+ mParcelId = parcel_data.parcel_id;
+
+ if(!getLandScriptResources())
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setParcelID(const LLUUID& parcel_id)
+{
+ if (!parcel_id.isNull())
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->addObserver(parcel_id, this);
+ LLRemoteParcelInfoProcessor::getInstance()->sendParcelInfoRequest(parcel_id);
+ }
+ else
+ {
+ std::string msg_error = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_error));
+ }
+}
+
+// virtual
+void LLPanelScriptLimitsRegionMemory::setErrorStatus(U32 status, const std::string& reason)
+{
+ llerrs << "Can't handle remote parcel request."<< " Http Status: "<< status << ". Reason : "<< reason<<llendl;
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["memory"].asInteger() / 1024;
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = "";
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ mObjectListIDs.push_back(task_id);
+ total_objects++;
+ }
+ }
+
+ mParcelMemoryUsed =total_size;
+ mGotParcelMemoryUsed = TRUE;
+ populateParcelMemoryText();
+}
+
+void LLPanelScriptLimitsRegionMemory::populateParcelMemoryText()
+{
+ if(mGotParcelMemoryUsed && mGotParcelMemoryMax)
+ {
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsedSimple", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#else
+ S32 parcel_memory_available = mParcelMemoryMax - mParcelMemoryUsed;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ args_parcel_memory["[COUNT]"] = llformat ("%d", mParcelMemoryUsed);
+ args_parcel_memory["[MAX]"] = llformat ("%d", mParcelMemoryMax);
+ args_parcel_memory["[AVAILABLE]"] = llformat ("%d", parcel_memory_available);
+ std::string msg_parcel_memory = LLTrans::getString("ScriptLimitsMemoryUsed", args_parcel_memory);
+ childSetValue("memory_used", LLSD(msg_parcel_memory));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelMemoryMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary doesn't contain memory info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("memory"))
+ {
+ mParcelMemoryUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelMemoryUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelMemoryText();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+
+ return StartRequestChain();
+}
+
+BOOL LLPanelScriptLimitsRegionMemory::StartRequestChain()
+{
+ LLUUID region_id;
+
+ LLFloaterLand* instance = LLFloaterReg::getTypedInstance<LLFloaterLand>("about_land");
+ if(!instance)
+ {
+ //this isnt really an error...
+// llinfos << "Failed to get about land instance" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(std::string("")));
+ //might have to do parent post build here
+ //if not logic below could use early outs
+ return FALSE;
+ }
+
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+
+ LLParcel* parcel = instance->getCurrentSelectedParcel();
+ LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
+
+ LLUUID current_region_id = gAgent.getRegion()->getRegionID();
+
+ if ((region) && (parcel))
+ {
+ LLVector3 parcel_center = parcel->getCenterpoint();
+
+ region_id = region->getRegionID();
+
+ if(region_id != current_region_id)
+ {
+ std::string msg_wrong_region = LLTrans::getString("ScriptLimitsRequestWrongRegion");
+ childSetValue("loading_text", LLSD(msg_wrong_region));
+ panel_urls->childSetValue("loading_text", LLSD(msg_wrong_region));
+ return FALSE;
+ }
+
+ LLVector3d pos_global = region->getCenterGlobal();
+
+ LLSD body;
+ std::string url = region->getCapability("RemoteParcelRequest");
+ if (!url.empty())
+ {
+ body["location"] = ll_sd_from_vector3(parcel_center);
+ if (!region_id.isNull())
+ {
+ body["region_id"] = region_id;
+ }
+ if (!pos_global.isExactlyZero())
+ {
+ U64 region_handle = to_region_handle(pos_global);
+ body["region_handle"] = ll_sd_from_U64(region_handle);
+ }
+ LLHTTPClient::post(url, body, new LLRemoteParcelRequestResponder(getObserverHandle()));
+ }
+ else
+ {
+ llwarns << "Can't get parcel info for script information request" << region_id
+ << ". Region: " << region->getName()
+ << " does not support RemoteParcelRequest" << llendl;
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+ }
+ else
+ {
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ panel_urls->childSetValue("loading_text", LLSD(msg_waiting));
+ }
+
+ return LLPanelScriptLimitsInfo::postBuild();
+}
+
+void LLPanelScriptLimitsRegionMemory::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelMemoryUsed = FALSE;
+ mGotParcelMemoryMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_memory;
+ std::string msg_empty_string("");
+ childSetValue("memory_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListIDs.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickRefresh(void* userdata)
+{
+ llinfos << "LLPanelRegionGeneralInfo::onClickRefresh" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+void LLPanelScriptLimitsRegionMemory::showBeacon()
+{
+/* LLScrollListCtrl* list = getChild<LLScrollListCtrl>("scripts_list");
+ if (!list) return;
+
+ LLScrollListItem* first_selected = list->getFirstSelected();
+ if (!first_selected) return;
+
+ std::string name = first_selected->getColumn(1)->getValue().asString();
+ std::string pos_string = first_selected->getColumn(3)->getValue().asString();
+
+ llinfos << ">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>" <<llendl;
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+
+ F32 x, y, z;
+ S32 matched = sscanf(pos_string.c_str(), "<%g,%g,%g>", &x, &y, &z);
+ if (matched != 3) return;
+
+ LLVector3 pos_agent(x, y, z);
+ LLVector3d pos_global = gAgent.getPosGlobalFromAgent(pos_agent);
+ llinfos << "name = " << name << " pos = " << pos_string << llendl;
+ std::string tooltip("");
+ LLTracker::trackLocation(pos_global, name, tooltip, LLTracker::LOCATION_ITEM);*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickHighlight(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickHighlight" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+void LLPanelScriptLimitsRegionMemory::returnObjects()
+{
+/* llinfos << "started" << llendl;
+ LLMessageSystem *msg = gMessageSystem;
+
+ LLViewerRegion* region = gAgent.getRegion();
+ if (!region) return;
+
+ llinfos << "got region" << llendl;
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+ if (!list || list->getItemCount() == 0) return;
+
+ llinfos << "got list" << llendl;
+ std::vector<LLUUID>::iterator id_itor;
+
+ bool start_message = true;
+
+ for (id_itor = mObjectListIDs.begin(); id_itor != mObjectListIDs.end(); ++id_itor)
+ {
+ LLUUID task_id = *id_itor;
+ llinfos << task_id << llendl;
+ if (!list->isSelected(task_id))
+ {
+ llinfos << "not selected" << llendl;
+ // Selected only
+ continue;
+ }
+ llinfos << "selected" << llendl;
+ if (start_message)
+ {
+ msg->newMessageFast(_PREHASH_ParcelReturnObjects);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID,gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ParcelData);
+ msg->addS32Fast(_PREHASH_LocalID, -1); // Whole region
+ msg->addS32Fast(_PREHASH_ReturnType, RT_LIST);
+ start_message = false;
+ llinfos << "start message" << llendl;
+ }
+
+ msg->nextBlockFast(_PREHASH_TaskIDs);
+ msg->addUUIDFast(_PREHASH_TaskID, task_id);
+ llinfos << "added id" << llendl;
+
+ if (msg->isSendFullFast(_PREHASH_TaskIDs))
+ {
+ msg->sendReliable(region->getHost());
+ start_message = true;
+ llinfos << "sent 1" << llendl;
+ }
+ }
+
+ if (!start_message)
+ {
+ msg->sendReliable(region->getHost());
+ llinfos << "sent 2" << llendl;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionMemory::onClickReturn(void* userdata)
+{
+/* llinfos << "LLPanelRegionGeneralInfo::onClickReturn" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// URLs Panel
+///----------------------------------------------------------------------------
+
+void LLPanelScriptLimitsRegionURLs::setRegionDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+
+ S32 number_parcels = content["parcels"].size();
+
+ LLStringUtil::format_map_t args_parcels;
+ args_parcels["[PARCELS]"] = llformat ("%d", number_parcels);
+ std::string msg_parcels = LLTrans::getString("ScriptLimitsParcelsOwned", args_parcels);
+ childSetValue("parcels_listed", LLSD(msg_parcels));
+
+ S32 total_objects = 0;
+ S32 total_size = 0;
+
+ for(S32 i = 0; i < number_parcels; i++)
+ {
+ std::string parcel_name = content["parcels"][i]["name"].asString();
+ llinfos << parcel_name << llendl;
+
+ S32 number_objects = content["parcels"][i]["objects"].size();
+ for(S32 j = 0; j < number_objects; j++)
+ {
+ if(content["parcels"][i]["objects"][j]["resources"].has("urls"))
+ {
+ S32 size = content["parcels"][i]["objects"][j]["resources"]["urls"].asInteger();
+ total_size += size;
+
+ std::string name_buf = content["parcels"][i]["objects"][j]["name"].asString();
+ LLUUID task_id = content["parcels"][i]["objects"][j]["id"].asUUID();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "urls";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+ element["columns"][1]["column"] = "name";
+ element["columns"][1]["value"] = name_buf;
+ element["columns"][1]["font"] = "SANSSERIF";
+ element["columns"][2]["column"] = "owner";
+ element["columns"][2]["value"] = "";
+ element["columns"][2]["font"] = "SANSSERIF";
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = parcel_name;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ mObjectListIDs.push_back(task_id);
+ total_objects++;
+ }
+ }
+ }
+
+ mParcelURLsUsed =total_size;
+ mGotParcelURLsUsed = TRUE;
+ populateParcelURLsText();
+}
+
+void LLPanelScriptLimitsRegionURLs::populateParcelURLsText()
+{
+ if(mGotParcelURLsUsed && mGotParcelURLsMax)
+ {
+
+#ifdef USE_SIMPLE_SUMMARY
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsedSimple", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#else
+ S32 parcel_urls_available = mParcelURLsMax - mParcelURLsUsed;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ args_parcel_urls["[COUNT]"] = llformat ("%d", mParcelURLsUsed);
+ args_parcel_urls["[MAX]"] = llformat ("%d", mParcelURLsMax);
+ args_parcel_urls["[AVAILABLE]"] = llformat ("%d", parcel_urls_available);
+ std::string msg_parcel_urls = LLTrans::getString("ScriptLimitsURLsUsed", args_parcel_urls);
+ childSetValue("urls_used", LLSD(msg_parcel_urls));
+#endif
+
+ childSetValue("loading_text", LLSD(std::string("")));
+
+ }
+}
+
+void LLPanelScriptLimitsRegionURLs::setRegionSummary(LLSD content)
+{
+ if(content["summary"]["available"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][0]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else if(content["summary"]["available"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsMax = content["summary"]["available"][1]["amount"].asInteger();
+ mGotParcelURLsMax = TRUE;
+ }
+ else
+ {
+ llinfos << "summary contains no url info" << llendl;
+ return;
+ }
+/*
+ currently this is broken on the server, so we get this value from the details section
+ and update via populateParcelMemoryText() when both sets of information have been returned
+
+ when the sim is fixed this should be used instead:
+ if(content["summary"]["used"][0]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][0]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else if(content["summary"]["used"][1]["type"].asString() == std::string("urls"))
+ {
+ mParcelURLsUsed = content["summary"]["used"][1]["amount"].asInteger();
+ mGotParcelURLsUsed = TRUE;
+ }
+ else
+ {
+ //ERROR!!!
+ return;
+ }*/
+
+ populateParcelURLsText();
+}
+
+BOOL LLPanelScriptLimitsRegionURLs::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+ childSetAction("highlight_btn", onClickHighlight, this);
+ childSetAction("return_btn", onClickReturn, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return FALSE;
+}
+
+void LLPanelScriptLimitsRegionURLs::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ mGotParcelURLsUsed = FALSE;
+ mGotParcelURLsMax = FALSE;
+
+ LLStringUtil::format_map_t args_parcel_urls;
+ std::string msg_empty_string("");
+ childSetValue("urls_used", LLSD(msg_empty_string));
+ childSetValue("parcels_listed", LLSD(msg_empty_string));
+
+ mObjectListIDs.clear();
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel_memory = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the memory panel to re-request all the info
+ panel_memory->clearList();
+
+ LLPanelScriptLimitsRegionURLs* panel_urls = (LLPanelScriptLimitsRegionURLs*)tab->getChild<LLPanel>("script_limits_region_urls_panel");
+ // but the urls panel to clear itself
+ panel_urls->clearList();
+
+ panel_memory->StartRequestChain();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickHighlight(void* userdata)
+{
+/* llinfos << "Highlight clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the beacon function from the memory panel
+ panel->showBeacon();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+// static
+void LLPanelScriptLimitsRegionURLs::onClickReturn(void* userdata)
+{
+/* llinfos << "Return clicked" << llendl;
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsRegionMemory* panel = (LLPanelScriptLimitsRegionMemory*)tab->getChild<LLPanel>("script_limits_region_memory_panel");
+ // use the return function from the memory panel
+ panel->returnObjects();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after highlight button clicked" << llendl;
+// std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestError");
+// panel->childSetValue("loading_text", LLSD(msg_waiting));
+ return;
+ }*/
+}
+
+///----------------------------------------------------------------------------
+// Attachment Panel
+///----------------------------------------------------------------------------
+
+BOOL LLPanelScriptLimitsAttachment::requestAttachmentDetails()
+{
+ LLSD body;
+ std::string url = gAgent.getRegion()->getCapability("AttachmentResources");
+ if (!url.empty())
+ {
+ LLHTTPClient::get(url, body, new fetchScriptLimitsAttachmentInfoResponder());
+ return TRUE;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLPanelScriptLimitsAttachment::setAttachmentDetails(LLSD content)
+{
+ LLScrollListCtrl *list = getChild<LLScrollListCtrl>("scripts_list");
+ S32 number_attachments = content["attachments"].size();
+
+ for(int i = 0; i < number_attachments; i++)
+ {
+ std::string humanReadableLocation = "";
+ if(content["attachments"][i].has("location"))
+ {
+ std::string actualLocation = content["attachments"][i]["location"];
+ humanReadableLocation = LLTrans::getString(actualLocation.c_str());
+ }
+
+ S32 number_objects = content["attachments"][i]["objects"].size();
+ for(int j = 0; j < number_objects; j++)
+ {
+ LLUUID task_id = content["attachments"][i]["objects"][j]["id"].asUUID();
+ S32 size = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("memory"))
+ {
+ size = content["attachments"][i]["objects"][j]["resources"]["memory"].asInteger();
+ }
+ S32 urls = 0;
+ if(content["attachments"][i]["objects"][j]["resources"].has("urls"))
+ {
+ urls = content["attachments"][i]["objects"][j]["resources"]["urls"].asInteger();
+ }
+ std::string name = content["attachments"][i]["objects"][j]["name"].asString();
+
+ LLSD element;
+
+ element["id"] = task_id;
+ element["columns"][0]["column"] = "size";
+ element["columns"][0]["value"] = llformat("%d", size);
+ element["columns"][0]["font"] = "SANSSERIF";
+
+ element["columns"][1]["column"] = "urls";
+ element["columns"][1]["value"] = llformat("%d", urls);
+ element["columns"][1]["font"] = "SANSSERIF";
+
+ element["columns"][2]["column"] = "name";
+ element["columns"][2]["value"] = name;
+ element["columns"][2]["font"] = "SANSSERIF";
+
+ element["columns"][3]["column"] = "location";
+ element["columns"][3]["value"] = humanReadableLocation;
+ element["columns"][3]["font"] = "SANSSERIF";
+
+ list->addElement(element);
+ }
+ }
+
+ childSetValue("loading_text", LLSD(std::string("")));
+}
+
+BOOL LLPanelScriptLimitsAttachment::postBuild()
+{
+ childSetAction("refresh_list_btn", onClickRefresh, this);
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+ return requestAttachmentDetails();
+}
+
+void LLPanelScriptLimitsAttachment::clearList()
+{
+ LLCtrlListInterface *list = childGetListInterface("scripts_list");
+
+ if (list)
+ {
+ list->operateOnAll(LLCtrlListInterface::OP_DELETE);
+ }
+
+ std::string msg_waiting = LLTrans::getString("ScriptLimitsRequestWaiting");
+ childSetValue("loading_text", LLSD(msg_waiting));
+}
+
+// static
+void LLPanelScriptLimitsAttachment::onClickRefresh(void* userdata)
+{
+ llinfos << "Refresh clicked" << llendl;
+
+ LLFloaterScriptLimits* instance = LLFloaterReg::getTypedInstance<LLFloaterScriptLimits>("script_limits");
+ if(instance)
+ {
+ LLTabContainer* tab = instance->getChild<LLTabContainer>("scriptlimits_panels");
+ LLPanelScriptLimitsAttachment* panel_attachments = (LLPanelScriptLimitsAttachment*)tab->getChild<LLPanel>("script_limits_my_avatar_panel");
+ panel_attachments->clearList();
+ panel_attachments->requestAttachmentDetails();
+ return;
+ }
+ else
+ {
+ llwarns << "could not find LLPanelScriptLimitsRegionMemory instance after refresh button clicked" << llendl;
+ return;
+ }
+}
diff --git a/indra/newview/llfloaterscriptlimits.h b/indra/newview/llfloaterscriptlimits.h
new file mode 100644
index 0000000000..88239136e3
--- /dev/null
+++ b/indra/newview/llfloaterscriptlimits.h
@@ -0,0 +1,259 @@
+/**
+ * @file llfloaterscriptlimits.h
+ * @author Gabriel Lee
+ * @brief Declaration of the region info and controls floater and panels.
+ *
+ * $LicenseInfo:firstyear=2004&license=viewergpl$
+ *
+ * Copyright (c) 2004-2009, Linden Research, Inc.
+ *
+ * Second Life Viewer Source Code
+ * The source code in this file ("Source Code") is provided by Linden Lab
+ * to you under the terms of the GNU General Public License, version 2.0
+ * ("GPL"), unless you have obtained a separate licensing agreement
+ * ("Other License"), formally executed by you and Linden Lab. Terms of
+ * the GPL can be found in doc/GPL-license.txt in this distribution, or
+ * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
+ *
+ * There are special exceptions to the terms and conditions of the GPL as
+ * it is applied to this Source Code. View the full text of the exception
+ * in the file doc/FLOSS-exception.txt in this software distribution, or
+ * online at
+ * http://secondlifegrid.net/programs/open_source/licensing/flossexception
+ *
+ * By copying, modifying or distributing this software, you acknowledge
+ * that you have read and understood your obligations described above,
+ * and agree to abide by those obligations.
+ *
+ * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
+ * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
+ * COMPLETENESS OR PERFORMANCE.
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLFLOATERSCRIPTLIMITS_H
+#define LL_LLFLOATERSCRIPTLIMITS_H
+
+#include <vector>
+#include "llfloater.h"
+#include "llhost.h"
+#include "llpanel.h"
+#include "llremoteparcelrequest.h"
+
+class LLPanelScriptLimitsInfo;
+class LLTabContainer;
+
+class LLPanelScriptLimitsRegionMemory;
+
+class LLFloaterScriptLimits : public LLFloater
+{
+ friend class LLFloaterReg;
+public:
+
+ /*virtual*/ BOOL postBuild();
+
+ // from LLPanel
+ virtual void refresh();
+
+private:
+
+ LLFloaterScriptLimits(const LLSD& seed);
+ ~LLFloaterScriptLimits();
+
+protected:
+
+ LLTabContainer* mTab;
+ typedef std::vector<LLPanelScriptLimitsInfo*> info_panels_t;
+ info_panels_t mInfoPanels;
+};
+
+
+// Base class for all script limits information panels.
+class LLPanelScriptLimitsInfo : public LLPanel
+{
+public:
+ LLPanelScriptLimitsInfo();
+
+ virtual BOOL postBuild();
+ virtual void updateChild(LLUICtrl* child_ctrl);
+
+protected:
+ void initCtrl(const std::string& name);
+
+ typedef std::vector<std::string> strings_t;
+
+ LLHost mHost;
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Responders
+/////////////////////////////////////////////////////////////////////////////
+
+class fetchScriptLimitsRegionInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionInfoResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionSummaryResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionSummaryResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsRegionDetailsResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsRegionDetailsResponder(const LLSD& info) : mInfo(info) {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+ LLSD mInfo;
+};
+
+class fetchScriptLimitsAttachmentInfoResponder: public LLHTTPClient::Responder
+{
+ public:
+ fetchScriptLimitsAttachmentInfoResponder() {};
+
+ void result(const LLSD& content);
+ void error(U32 status, const std::string& reason);
+ public:
+ protected:
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Memory panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionMemory : public LLPanelScriptLimitsInfo, LLRemoteParcelInfoObserver
+{
+
+public:
+ LLPanelScriptLimitsRegionMemory()
+ : LLPanelScriptLimitsInfo(), LLRemoteParcelInfoObserver(), mParcelId(LLUUID()), mGotParcelMemoryUsed(FALSE), mGotParcelMemoryMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionMemory()
+ {
+ LLRemoteParcelInfoProcessor::getInstance()->removeObserver(mParcelId, this);
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ BOOL StartRequestChain();
+
+ void populateParcelMemoryText();
+ BOOL getLandScriptResources();
+ void clearList();
+ void showBeacon();
+ void returnObjects();
+
+private:
+
+ LLUUID mParcelId;
+ BOOL mGotParcelMemoryUsed;
+ BOOL mGotParcelMemoryMax;
+ S32 mParcelMemoryMax;
+ S32 mParcelMemoryUsed;
+
+ std::vector<LLUUID> mObjectListIDs;
+
+protected:
+
+// LLRemoteParcelInfoObserver interface:
+/*virtual*/ void processParcelInfo(const LLParcelData& parcel_data);
+/*virtual*/ void setParcelID(const LLUUID& parcel_id);
+/*virtual*/ void setErrorStatus(U32 status, const std::string& reason);
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// URLs panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsRegionURLs : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsRegionURLs()
+ : LLPanelScriptLimitsInfo(), mParcelId(LLUUID()), mGotParcelURLsUsed(FALSE), mGotParcelURLsMax(FALSE) {};
+ ~LLPanelScriptLimitsRegionURLs()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setRegionDetails(LLSD content);
+ void setRegionSummary(LLSD content);
+
+ void populateParcelURLsText();
+ void clearList();
+
+private:
+
+ LLUUID mParcelId;
+ BOOL mGotParcelURLsUsed;
+ BOOL mGotParcelURLsMax;
+ S32 mParcelURLsMax;
+ S32 mParcelURLsUsed;
+
+ std::vector<LLUUID> mObjectListIDs;
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+ static void onClickHighlight(void* userdata);
+ static void onClickReturn(void* userdata);
+};
+
+/////////////////////////////////////////////////////////////////////////////
+// Attachment panel
+/////////////////////////////////////////////////////////////////////////////
+
+class LLPanelScriptLimitsAttachment : public LLPanelScriptLimitsInfo
+{
+
+public:
+ LLPanelScriptLimitsAttachment()
+ : LLPanelScriptLimitsInfo() {};
+ ~LLPanelScriptLimitsAttachment()
+ {
+ };
+
+ // LLPanel
+ virtual BOOL postBuild();
+
+ void setAttachmentDetails(LLSD content);
+
+ BOOL requestAttachmentDetails();
+ void clearList();
+
+private:
+
+protected:
+
+ static void onClickRefresh(void* userdata);
+};
+
+#endif
diff --git a/indra/newview/llfloatertopobjects.cpp b/indra/newview/llfloatertopobjects.cpp
index 86992d6a31..c930e99bad 100644
--- a/indra/newview/llfloatertopobjects.cpp
+++ b/indra/newview/llfloatertopobjects.cpp
@@ -162,7 +162,7 @@ void LLFloaterTopObjects::handleReply(LLMessageSystem *msg, void** data)
msg->getU32Fast(_PREHASH_RequestData, _PREHASH_ReportType, mCurrentMode);
LLScrollListCtrl *list = getChild<LLScrollListCtrl>("objects_list");
-
+
S32 block_count = msg->getNumberOfBlocks("ReportData");
for (S32 block = 0; block < block_count; ++block)
{
@@ -432,7 +432,6 @@ void LLFloaterTopObjects::onRefresh()
filter = mFilter;
clearList();
-
LLMessageSystem *msg = gMessageSystem;
msg->newMessageFast(_PREHASH_LandStatRequest);
msg->nextBlockFast(_PREHASH_AgentData);
@@ -465,7 +464,7 @@ void LLFloaterTopObjects::onGetByOwnerName()
}
void LLFloaterTopObjects::showBeacon()
-{
+{
LLScrollListCtrl* list = getChild<LLScrollListCtrl>("objects_list");
if (!list) return;
diff --git a/indra/newview/llviewerfloaterreg.cpp b/indra/newview/llviewerfloaterreg.cpp
index 35c9a1d367..00db11a767 100644
--- a/indra/newview/llviewerfloaterreg.cpp
+++ b/indra/newview/llviewerfloaterreg.cpp
@@ -94,6 +94,7 @@
#include "llfloaterregioninfo.h"
#include "llfloaterreporter.h"
#include "llfloaterscriptdebug.h"
+#include "llfloaterscriptlimits.h"
#include "llfloatersellland.h"
#include "llfloatersettingsdebug.h"
#include "llfloatersnapshot.h"
@@ -241,6 +242,7 @@ void LLViewerFloaterReg::registerFloaters()
LLFloaterReg::add("script_debug", "floater_script_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebug>);
LLFloaterReg::add("script_debug_output", "floater_script_debug_panel.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptDebugOutput>);
LLFloaterReg::add("script_floater", "floater_script.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLScriptFloater>);
+ LLFloaterReg::add("script_limits", "floater_script_limits.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterScriptLimits>);
LLFloaterReg::add("sell_land", "floater_sell_land.xml", &LLFloaterSellLand::buildFloater);
LLFloaterReg::add("settings_debug", "floater_settings_debug.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloaterSettingsDebug>);
LLFloaterReg::add("stats", "floater_stats.xml", (LLFloaterBuildFunc)&LLFloaterReg::build<LLFloater>);
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index d1c9840a97..77d2d493bd 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1421,6 +1421,8 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
setCapability("Seed", url);
LLSD capabilityNames = LLSD::emptyArray();
+
+ capabilityNames.append("AttachmentResources");
capabilityNames.append("ChatSessionRequest");
capabilityNames.append("CopyInventoryFromNotecard");
capabilityNames.append("DispatchRegionInfo");
@@ -1434,6 +1436,7 @@ void LLViewerRegion::setSeedCapability(const std::string& url)
capabilityNames.append("GetTexture");
capabilityNames.append("GroupProposalBallot");
capabilityNames.append("HomeLocation");
+ capabilityNames.append("LandResources");
capabilityNames.append("MapLayer");
capabilityNames.append("MapLayerGod");
capabilityNames.append("NewFileAgentInventory");
diff --git a/indra/newview/skins/default/xui/en/floater_about_land.xml b/indra/newview/skins/default/xui/en/floater_about_land.xml
index 81e6503407..a581190d18 100644
--- a/indra/newview/skins/default/xui/en/floater_about_land.xml
+++ b/indra/newview/skins/default/xui/en/floater_about_land.xml
@@ -274,7 +274,7 @@
<button
enabled="false"
follows="left|top"
- height="23S"
+ height="23"
label="Deed"
layout="topleft"
left_pad="2"
@@ -472,6 +472,16 @@
top="328"
width="100" />
<button
+ enabled="true"
+ follows="left|top"
+ height="23"
+ label="Script Info"
+ layout="topleft"
+ left="10"
+ name="Scripts..."
+ top="352"
+ width="100" />
+ <button
enabled="false"
follows="left|top"
height="23"
diff --git a/indra/newview/skins/default/xui/en/floater_customize.xml b/indra/newview/skins/default/xui/en/floater_customize.xml
index 153a9c2c45..ffdb59d44c 100644
--- a/indra/newview/skins/default/xui/en/floater_customize.xml
+++ b/indra/newview/skins/default/xui/en/floater_customize.xml
@@ -3381,6 +3381,16 @@ scratch and wear it.
</scroll_container>
<button
bottom="598"
+ follows="right|left"
+ height="20"
+ label="Script Info"
+ label_selected="Script Info"
+ layout="topleft"
+ name="script_info"
+ left="2"
+ width="98" />
+ <button
+ bottom="598"
follows="right|bottom"
height="23"
label="Make Outfit"
diff --git a/indra/newview/skins/default/xui/en/floater_script_limits.xml b/indra/newview/skins/default/xui/en/floater_script_limits.xml
new file mode 100644
index 0000000000..98c44ad1b3
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/floater_script_limits.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ height="570"
+ help_topic="scriptlimits"
+ layout="topleft"
+ name="scriptlimits"
+ save_rect="true"
+ title="SCRIPT INFORMATION"
+ width="480">
+ <tab_container
+ bottom="555"
+ follows="left|right|top|bottom"
+ layout="topleft"
+ left="1"
+ name="scriptlimits_panels"
+ right="-1"
+ tab_position="top"
+ top="20" />
+</floater>
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
new file mode 100644
index 0000000000..d98f690339
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_my_avatar.xml
@@ -0,0 +1,62 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="MY AVATAR"
+ layout="topleft"
+ left="0"
+ name="script_limits_my_avatar_panel"
+ top="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top="10"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="500"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="17"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="URLs"
+ name="urls"
+ width="50" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="140" />
+ <scroll_list.columns
+ label="Location"
+ name="location"
+ width="130" />
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
new file mode 100644
index 0000000000..0fa3c1cf2e
--- /dev/null
+++ b/indra/newview/skins/default/xui/en/panel_script_limits_region_memory.xml
@@ -0,0 +1,122 @@
+<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<panel
+ border="true"
+ follows="top|left"
+ height="570"
+ label="REGION MEMORY"
+ layout="topleft"
+ name="script_limits_region_memory_panel"
+ top="0"
+ left="0"
+ width="480">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ name="script_memory"
+ top_pad="24"
+ text_color="White"
+ width="480">
+ Parcel Script Memory
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="parcels_listed"
+ top_delta="18"
+ visible="true"
+ width="480">
+ Parcels Owned:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="30"
+ name="memory_used"
+ top_delta="18"
+ width="480">
+ Memory used:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="loading_text"
+ top_delta="32"
+ text_color="EmphasisColor"
+ width="480">
+ Loading...
+ </text>
+ <scroll_list
+ draw_heading="true"
+ follows="all"
+ height="409"
+ layout="topleft"
+ left_delta="0"
+ multi_select="true"
+ name="scripts_list"
+ top_delta="16"
+ width="460">
+ <scroll_list.columns
+ label="Size (kb)"
+ name="size"
+ width="70" />
+ <scroll_list.columns
+ label="Object Name"
+ name="name"
+ width="100" />
+ <scroll_list.columns
+ label="Object Owner"
+ name="owner"
+ width="100" />
+ <scroll_list.columns
+ label="Parcel / Location"
+ name="location"
+ width="130" />
+<!-- <scroll_list.commit_callback
+ function="TopObjects.CommitObjectsList" />-->
+ </scroll_list>
+ <button
+ follows="bottom|left"
+ height="19"
+ label="Refresh List"
+ layout="bottomleft"
+ left_pad="5"
+ name="refresh_list_btn"
+ top="34"
+ left="10"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Highlight"
+ layout="bottomright"
+ left="370"
+ name="highlight_btn"
+ top="34"
+ width="100" />
+ <button
+ follows="bottom|right"
+ height="19"
+ visible="false"
+ label="Return"
+ layout="bottomright"
+ name="return_btn"
+ top="34"
+ left_delta="-105"
+ width="100" />
+</panel>
diff --git a/indra/newview/skins/default/xui/en/strings.xml b/indra/newview/skins/default/xui/en/strings.xml
index ec4723bd55..7438a36ed0 100644
--- a/indra/newview/skins/default/xui/en/strings.xml
+++ b/indra/newview/skins/default/xui/en/strings.xml
@@ -2041,6 +2041,59 @@ this texture in your inventory
<string name="RegionInfoAllowedResidents">Allowed residents: ([ALLOWEDAGENTS], max [MAXACCESS])</string>
<string name="RegionInfoAllowedGroups">Allowed groups: ([ALLOWEDGROUPS], max [MAXACCESS])</string>
+ <!-- script limits floater -->
+ <string name="ScriptLimitsParcelScriptMemory">Parcel Script Memory</string>
+ <string name="ScriptLimitsParcelsOwned">Parcels Listed: [PARCELS]</string>
+ <string name="ScriptLimitsMemoryUsed">Memory used: [COUNT] kb out of [MAX] kb; [AVAILABLE] kb available</string>
+ <string name="ScriptLimitsMemoryUsedSimple">Memory used: [COUNT] kb</string>
+ <string name="ScriptLimitsParcelScriptURLs">Parcel Script URLs</string>
+ <string name="ScriptLimitsURLsUsed">URLs used: [COUNT] out of [MAX]; [AVAILABLE] available</string>
+ <string name="ScriptLimitsURLsUsedSimple">URLs used: [COUNT]</string>
+ <string name="ScriptLimitsRequestError">Error requesting information</string>
+ <string name="ScriptLimitsRequestWrongRegion">Error: script information is only available in your current region</string>
+ <string name="ScriptLimitsRequestWaiting">Retrieving information...</string>
+ <string name="ScriptLimitsRequestDontOwnParcel">You do not have permission to examine this parcel</string>
+
+ <string name="SITTING_ON">Sitting On</string>
+ <string name="ATTACH_CHEST">Chest</string>
+ <string name="ATTACH_HEAD">Head</string>
+ <string name="ATTACH_LSHOULDER">Left Shoulder</string>
+ <string name="ATTACH_RSHOULDER">Right Shoulder</string>
+ <string name="ATTACH_LHAND">Left Hand</string>
+ <string name="ATTACH_RHAND">Right Hand</string>
+ <string name="ATTACH_LFOOT">Left Foot</string>
+ <string name="ATTACH_RFOOT">Right Foot</string>
+ <string name="ATTACH_BACK">Back</string>
+ <string name="ATTACH_PELVIS">Pelvis</string>
+ <string name="ATTACH_MOUTH">Mouth</string>
+ <string name="ATTACH_CHIN">Chin</string>
+ <string name="ATTACH_LEAR">Left Ear</string>
+ <string name="ATTACH_REAR">Right Ear</string>
+ <string name="ATTACH_LEYE">Left Eye</string>
+ <string name="ATTACH_REYE">Right Eye</string>
+ <string name="ATTACH_NOSE">Nose</string>
+ <string name="ATTACH_RUARM">Right Upper Arm</string>
+ <string name="ATTACH_RLARM">Right Lower Arm</string>
+ <string name="ATTACH_LUARM">Left Upper Arm</string>
+ <string name="ATTACH_LLARM">Left Lower Arm</string>
+ <string name="ATTACH_RHIP">Right Hip</string>
+ <string name="ATTACH_RULEG">Right Upper Leg</string>
+ <string name="ATTACH_RLLEG">Right Lower Leg</string>
+ <string name="ATTACH_LHIP">Left Hip</string>
+ <string name="ATTACH_LULEG">Left Upper Leg</string>
+ <string name="ATTACH_LLLEG">Left Lower Leg</string>
+ <string name="ATTACH_BELLY">Belly</string>
+ <string name="ATTACH_RPEC">Right Pec</string>
+ <string name="ATTACH_LPEC">Left Pec</string>
+ <string name="ATTACH_HUD_CENTER_2"><HUD Center 2/string>
+ <string name="ATTACH_HUD_TOP_RIGHT">HUD Top Right</string>
+ <string name="ATTACH_HUD_TOP_CENTER">HUD Top Center</string>
+ <string name="ATTACH_HUD_TOP_LEFT">HUD Top Left</string>
+ <string name="ATTACH_HUD_CENTER_1">HUD Center 1</string>
+ <string name="ATTACH_HUD_BOTTOM_LEFT">HUD Bottom Left</string>
+ <string name="ATTACH_HUD_BOTTOM">HUD Bottom</string>
+ <string name="ATTACH_HUD_BOTTOM_RIGHT">HUD Bottom Right</string>
+
<!-- script editor -->
<string name="CursorPos">Line [LINE], Column [COLUMN]</string>