summaryrefslogtreecommitdiff
path: root/indra/newview
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview')
-rw-r--r--indra/newview/llfloaterobjectweights.cpp161
-rw-r--r--indra/newview/llfloaterobjectweights.h22
-rw-r--r--indra/newview/llviewerobject.cpp14
-rw-r--r--indra/newview/llviewerobject.h4
-rw-r--r--indra/newview/llviewerparceloverlay.cpp59
-rw-r--r--indra/newview/llviewerparceloverlay.h1
-rw-r--r--indra/newview/llviewerregion.cpp5
-rw-r--r--indra/newview/llviewerregion.h1
-rw-r--r--indra/newview/skins/default/xui/en/floater_object_weights.xml38
9 files changed, 293 insertions, 12 deletions
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
index 93aa8dcf08..d39a93991f 100644
--- a/indra/newview/llfloaterobjectweights.cpp
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -27,8 +27,43 @@
#include "llfloaterobjectweights.h"
+#include "llparcel.h"
+
+#include "llfloaterreg.h"
#include "lltextbox.h"
+#include "llselectmgr.h"
+#include "llviewerparcelmgr.h"
+#include "llviewerregion.h"
+
+struct LLCrossParcelFunctor : public LLSelectedObjectFunctor
+{
+ /*virtual*/ bool apply(LLViewerObject* obj)
+ {
+ return obj->crossesParcelBounds();
+ }
+};
+
+/**
+ * Class LLLandImpactsObserver
+ *
+ * An observer class to monitor parcel selection and update
+ * the land impacts data from a parcel containing the selected object.
+ */
+class LLLandImpactsObserver : public LLParcelObserver
+{
+public:
+ virtual void changed()
+ {
+ LLFloaterObjectWeights* object_weights_floater = LLFloaterReg::getTypedInstance<LLFloaterObjectWeights>("object_weights");
+ if(object_weights_floater)
+ {
+ object_weights_floater->updateLandImpacts();
+ }
+ }
+};
+
+
LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
: LLFloater(key),
mSelectedObjects(NULL),
@@ -40,12 +75,22 @@ LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
mSelectedOnLand(NULL),
mRezzedOnLand(NULL),
mRemainingCapacity(NULL),
- mTotalCapacity(NULL)
+ mTotalCapacity(NULL),
+ mLandImpactsObserver(NULL)
{
+ mLandImpactsObserver = new LLLandImpactsObserver();
+ LLViewerParcelMgr::getInstance()->addObserver(mLandImpactsObserver);
}
LLFloaterObjectWeights::~LLFloaterObjectWeights()
{
+ mObjectSelection = NULL;
+ mParcelSelection = NULL;
+
+ mSelectMgrConnection.disconnect();
+
+ LLViewerParcelMgr::getInstance()->removeObserver(mLandImpactsObserver);
+ delete mLandImpactsObserver;
}
// virtual
@@ -59,10 +104,10 @@ BOOL LLFloaterObjectWeights::postBuild()
mSelectedServerWeight = getChild<LLTextBox>("server");
mSelectedDisplayWeight = getChild<LLTextBox>("display");
- mSelectedOnLand = getChild<LLTextBox>("used_download_weight");
- mRezzedOnLand = getChild<LLTextBox>("used_download_weight");
- mRemainingCapacity = getChild<LLTextBox>("used_download_weight");
- mTotalCapacity = getChild<LLTextBox>("used_download_weight");
+ mSelectedOnLand = getChild<LLTextBox>("selected");
+ mRezzedOnLand = getChild<LLTextBox>("rezzed_on_land");
+ mRemainingCapacity = getChild<LLTextBox>("remaining_capacity");
+ mTotalCapacity = getChild<LLTextBox>("total_capacity");
return TRUE;
}
@@ -70,15 +115,111 @@ BOOL LLFloaterObjectWeights::postBuild()
// virtual
void LLFloaterObjectWeights::onOpen(const LLSD& key)
{
- updateIfNothingSelected();
+ mSelectMgrConnection = LLSelectMgr::instance().mUpdateSignal.connect(boost::bind(&LLFloaterObjectWeights::refresh, this));
+
+ mObjectSelection = LLSelectMgr::getInstance()->getEditSelection();
+ mParcelSelection = LLViewerParcelMgr::getInstance()->getFloatingParcelSelection();
+
+ refresh();
+}
+
+// virtual
+void LLFloaterObjectWeights::onClose(bool app_quitting)
+{
+ mSelectMgrConnection.disconnect();
+
+ mObjectSelection = NULL;
+ mParcelSelection = NULL;
}
-void LLFloaterObjectWeights::toggleLoadingIndicators(bool visible)
+void LLFloaterObjectWeights::updateLandImpacts()
+{
+ LLParcel *parcel = mParcelSelection->getParcel();
+ if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ updateIfNothingSelected();
+ }
+ else
+ {
+ S32 selected_prims = parcel->getSelectedPrimCount();
+ S32 rezzed_prims = parcel->getSimWidePrimCount();
+ S32 total_capacity = parcel->getSimWideMaxPrimCapacity();
+
+ mSelectedOnLand->setText(llformat("%d", selected_prims));
+ mRezzedOnLand->setText(llformat("%d", rezzed_prims));
+ mRemainingCapacity->setText(llformat("%d", total_capacity - rezzed_prims));
+ mTotalCapacity->setText(llformat("%d", total_capacity));
+
+ toggleLandImpactsLoadingIndicators(false);
+ }
+}
+
+void LLFloaterObjectWeights::refresh()
+{
+ if (LLSelectMgr::getInstance()->getSelection()->isEmpty())
+ {
+ updateIfNothingSelected();
+ }
+ else
+ {
+ S32 prim_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ S32 link_count = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount();
+
+ mSelectedObjects->setText(llformat("%d", link_count));
+ mSelectedPrims->setText(llformat("%d", prim_count));
+
+ LLCrossParcelFunctor func;
+ if (LLSelectMgr::getInstance()->getSelection()->applyToRootObjects(&func, true))
+ {
+ // Some of the selected objects cross parcel bounds.
+ // We don't display land impacts in this case.
+ const std::string text = getString("nothing_selected");
+
+ mSelectedOnLand->setText(text);
+ mRezzedOnLand->setText(text);
+ mRemainingCapacity->setText(text);
+ mTotalCapacity->setText(text);
+
+ toggleLandImpactsLoadingIndicators(false);
+ }
+ else
+ {
+ LLViewerObject* selected_object = mObjectSelection->getFirstObject();
+ if (selected_object)
+ {
+ // Select a parcel at the currently selected object's position.
+ LLViewerParcelMgr::getInstance()->selectParcelAt(selected_object->getPositionGlobal());
+
+ toggleLandImpactsLoadingIndicators(true);
+ }
+ }
+ }
+}
+
+void LLFloaterObjectWeights::toggleWeightsLoadingIndicators(bool visible)
{
childSetVisible("download_loading_indicator", visible);
childSetVisible("physics_loading_indicator", visible);
childSetVisible("server_loading_indicator", visible);
childSetVisible("display_loading_indicator", visible);
+
+ mSelectedDownloadWeight->setVisible(!visible);
+ mSelectedPhysicsWeight->setVisible(!visible);
+ mSelectedServerWeight->setVisible(!visible);
+ mSelectedDisplayWeight->setVisible(!visible);
+}
+
+void LLFloaterObjectWeights::toggleLandImpactsLoadingIndicators(bool visible)
+{
+ childSetVisible("selected_loading_indicator", visible);
+ childSetVisible("rezzed_on_land_loading_indicator", visible);
+ childSetVisible("remaining_capacity_loading_indicator", visible);
+ childSetVisible("total_capacity_loading_indicator", visible);
+
+ mSelectedOnLand->setVisible(!visible);
+ mRezzedOnLand->setVisible(!visible);
+ mRemainingCapacity->setVisible(!visible);
+ mTotalCapacity->setVisible(!visible);
}
void LLFloaterObjectWeights::updateIfNothingSelected()
@@ -94,6 +235,10 @@ void LLFloaterObjectWeights::updateIfNothingSelected()
mSelectedDisplayWeight->setText(text);
mSelectedOnLand->setText(text);
+ mRezzedOnLand->setText(text);
+ mRemainingCapacity->setText(text);
+ mTotalCapacity->setText(text);
- toggleLoadingIndicators(false);
+ toggleWeightsLoadingIndicators(false);
+ toggleLandImpactsLoadingIndicators(false);
}
diff --git a/indra/newview/llfloaterobjectweights.h b/indra/newview/llfloaterobjectweights.h
index 10e35ad7a7..82743a8aa7 100644
--- a/indra/newview/llfloaterobjectweights.h
+++ b/indra/newview/llfloaterobjectweights.h
@@ -29,6 +29,9 @@
#include "llfloater.h"
+class LLLandImpactsObserver;
+class LLObjectSelection;
+class LLParcelSelection;
class LLTextBox;
class LLFloaterObjectWeights : public LLFloater
@@ -36,15 +39,25 @@ class LLFloaterObjectWeights : public LLFloater
public:
LOG_CLASS(LLFloaterObjectWeights);
+ typedef LLSafeHandle<LLObjectSelection> LLObjectSelectionHandle;
+ typedef LLSafeHandle<LLParcelSelection> LLParcelSelectionHandle;
+
LLFloaterObjectWeights(const LLSD& key);
~LLFloaterObjectWeights();
/*virtual*/ BOOL postBuild();
/*virtual*/ void onOpen(const LLSD& key);
+ /*virtual*/ void onClose(bool app_quitting);
+
+ void updateLandImpacts();
private:
- void toggleLoadingIndicators(bool visible);
+ void refresh();
+
+ void toggleWeightsLoadingIndicators(bool visible);
+ void toggleLandImpactsLoadingIndicators(bool visible);
+
void updateIfNothingSelected();
LLTextBox *mSelectedObjects;
@@ -59,6 +72,13 @@ private:
LLTextBox *mRezzedOnLand;
LLTextBox *mRemainingCapacity;
LLTextBox *mTotalCapacity;
+
+ LLLandImpactsObserver *mLandImpactsObserver;
+
+ LLObjectSelectionHandle mObjectSelection;
+ LLParcelSelectionHandle mParcelSelection;
+
+ boost::signals2::connection mSelectMgrConnection;
};
#endif //LL_LLFLOATEROBJECTWEIGHTS_H
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index af2ceee0b7..f5946dfbff 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -627,6 +627,20 @@ void LLViewerObject::constructAndAddReturnable( std::vector<PotentialReturnableO
}
}
+bool LLViewerObject::crossesParcelBounds()
+{
+ std::vector<LLBBox> boxes;
+ boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+ }
+
+ return mRegionp && mRegionp->objectsCrossParcel(boxes);
+}
+
BOOL LLViewerObject::setParent(LLViewerObject* parent)
{
if(mParent != parent)
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index cf2975b3b0..c035534761 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -242,6 +242,10 @@ public:
void buildReturnablesForChildrenVO( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion );
void constructAndAddReturnable( std::vector<PotentialReturnableObject>& returnables, LLViewerObject* pChild, LLViewerRegion* pTargetRegion );
+ // This method returns true if the object crosses
+ // any parcel bounds in the region.
+ bool crossesParcelBounds();
+
/*
// This method will scan through this object, and then query the
// selection manager to see if the local agent probably has the
diff --git a/indra/newview/llviewerparceloverlay.cpp b/indra/newview/llviewerparceloverlay.cpp
index eff16b6a6e..e619b89f9b 100644
--- a/indra/newview/llviewerparceloverlay.cpp
+++ b/indra/newview/llviewerparceloverlay.cpp
@@ -201,6 +201,65 @@ bool LLViewerParcelOverlay::encroachesOnUnowned(const std::vector<LLBBox>& boxes
return false;
}
+bool LLViewerParcelOverlay::encroachesOnNearbyParcel(const std::vector<LLBBox>& boxes) const
+{
+ // boxes are expected to already be axis aligned
+ for (U32 i = 0; i < boxes.size(); ++i)
+ {
+ LLVector3 min = boxes[i].getMinAgent();
+ LLVector3 max = boxes[i].getMaxAgent();
+
+ // If an object crosses region borders it crosses a parcel
+ if ( min.mV[VX] < 0
+ || min.mV[VY] < 0
+ || max.mV[VX] > REGION_WIDTH_METERS
+ || max.mV[VY] > REGION_WIDTH_METERS)
+ {
+ return true;
+ }
+
+ S32 left = S32(llclamp((min.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 right = S32(llclamp((max.mV[VX] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 bottom = S32(llclamp((min.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+ S32 top = S32(llclamp((max.mV[VY] / PARCEL_GRID_STEP_METERS), 0.f, REGION_WIDTH_METERS - 1));
+
+ const S32 GRIDS_PER_EDGE = mParcelGridsPerEdge;
+
+ for (S32 row = bottom; row <= top; row++)
+ {
+ for (S32 col = left; col <= right; col++)
+ {
+ // This is not the rightmost column
+ if (col < GRIDS_PER_EDGE-1)
+ {
+ U8 east_overlay = mOwnership[row*GRIDS_PER_EDGE+col+1];
+ // If the column to the east of the current one marks
+ // the other parcel's west edge and the box extends
+ // to the west it crosses the parcel border.
+ if ((east_overlay & PARCEL_WEST_LINE) && col < right)
+ {
+ return true;
+ }
+ }
+
+ // This is not the topmost column
+ if (row < GRIDS_PER_EDGE-1)
+ {
+ U8 north_overlay = mOwnership[(row+1)*GRIDS_PER_EDGE+col];
+ // If the row to the north of the current one marks
+ // the other parcel's south edge and the box extends
+ // to the south it crosses the parcel border.
+ if ((north_overlay & PARCEL_SOUTH_LINE) && row < top)
+ {
+ return true;
+ }
+ }
+ }
+ }
+ }
+ return false;
+}
+
BOOL LLViewerParcelOverlay::isSoundLocal(const LLVector3& pos) const
{
S32 row = S32(pos.mV[VY] / PARCEL_GRID_STEP_METERS);
diff --git a/indra/newview/llviewerparceloverlay.h b/indra/newview/llviewerparceloverlay.h
index 3c6794e7d0..7445d5bf1d 100644
--- a/indra/newview/llviewerparceloverlay.h
+++ b/indra/newview/llviewerparceloverlay.h
@@ -61,6 +61,7 @@ public:
// bounding boxes which isn't perfect, but is close
bool encroachesOwned(const std::vector<LLBBox>& boxes) const;
bool encroachesOnUnowned(const std::vector<LLBBox>& boxes) const;
+ bool encroachesOnNearbyParcel(const std::vector<LLBBox>& boxes) const;
BOOL isSoundLocal(const LLVector3& pos) const;
diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp
index ce73164dd2..822127c0b3 100644
--- a/indra/newview/llviewerregion.cpp
+++ b/indra/newview/llviewerregion.cpp
@@ -1779,6 +1779,11 @@ bool LLViewerRegion::childrenObjectReturnable( const std::vector<LLBBox>& boxes
return result;
}
+bool LLViewerRegion::objectsCrossParcel(const std::vector<LLBBox>& boxes) const
+{
+ return mParcelOverlay && mParcelOverlay->encroachesOnNearbyParcel(boxes);
+}
+
void LLViewerRegion::getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions )
{
mImpl->mLandp->getNeighboringRegions( uniqueRegions );
diff --git a/indra/newview/llviewerregion.h b/indra/newview/llviewerregion.h
index b3c19ea58d..c86c30b93c 100644
--- a/indra/newview/llviewerregion.h
+++ b/indra/newview/llviewerregion.h
@@ -322,6 +322,7 @@ public:
bool objectIsReturnable(const LLVector3& pos, const std::vector<LLBBox>& boxes) const;
bool childrenObjectReturnable( const std::vector<LLBBox>& boxes ) const;
+ bool objectsCrossParcel(const std::vector<LLBBox>& boxes) const;
void getNeighboringRegions( std::vector<LLViewerRegion*>& uniqueRegions );
diff --git a/indra/newview/skins/default/xui/en/floater_object_weights.xml b/indra/newview/skins/default/xui/en/floater_object_weights.xml
index f377386679..a73db3af32 100644
--- a/indra/newview/skins/default/xui/en/floater_object_weights.xml
+++ b/indra/newview/skins/default/xui/en/floater_object_weights.xml
@@ -222,6 +222,14 @@
top_pad="3"
value="--"
width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="selected_loading_indicator"
+ top_delta="0"
+ width="16" />
<text
follows="left|top"
height="16"
@@ -241,6 +249,14 @@
top_pad="3"
value="--"
width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="rezzed_on_land_loading_indicator"
+ top_delta="0"
+ width="16" />
<text
follows="left|top"
height="16"
@@ -260,12 +276,20 @@
top_pad="3"
value="--"
width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="remaining_capacity_loading_indicator"
+ top_delta="0"
+ width="16" />
<text
follows="left|top"
height="16"
layout="topleft"
left_pad="10"
- name="remaining_capacity"
+ name="remaining_capacity_label"
top_delta="0"
value="Remaining capacity"
width="130" />
@@ -279,12 +303,20 @@
top_pad="3"
value="--"
width="40" />
+ <loading_indicator
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="34"
+ name="total_capacity_loading_indicator"
+ top_delta="0"
+ width="16" />
<text
follows="left|top"
height="16"
layout="topleft"
left_pad="10"
- name="total_capacity"
+ name="total_capacity_label"
top_delta="0"
value="Total capacity"
width="130" />
@@ -303,7 +335,7 @@
height="16"
layout="topleft"
left="10"
- name="total_capacity"
+ name="help_SLURL"
top_pad="10"
value="[secondlife:///www.secondlife.com What is all this?...]"
width="180" />