summaryrefslogtreecommitdiff
path: root/indra/newview/llfloaterobjectweights.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llfloaterobjectweights.cpp')
-rw-r--r--indra/newview/llfloaterobjectweights.cpp228
1 files changed, 202 insertions, 26 deletions
diff --git a/indra/newview/llfloaterobjectweights.cpp b/indra/newview/llfloaterobjectweights.cpp
index bd8530abd7..cf89518c03 100644
--- a/indra/newview/llfloaterobjectweights.cpp
+++ b/indra/newview/llfloaterobjectweights.cpp
@@ -33,8 +33,10 @@
#include "lltextbox.h"
#include "llagent.h"
+#include "llcallbacklist.h"
#include "llviewerparcelmgr.h"
#include "llviewerregion.h"
+#include "llmeshrepository.h"
static const std::string lod_strings[4] =
{
@@ -74,6 +76,14 @@ bool LLCrossParcelFunctor::apply(LLViewerObject* obj)
LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
: LLFloater(key),
+ mWeightsDirty(false),
+ mSelectionDirty(true),
+ mSelectionMeshDirty(true),
+ mSelectionLastLOD(-1),
+ mSelectionLastTris(0),
+ mSelectionLastArea(0),
+ mLastActiveLODRequests(0),
+ mSelectionRefreshTime(0.),
mSelectedObjects(NULL),
mSelectedPrims(NULL),
mSelectedDownloadWeight(NULL),
@@ -88,6 +98,13 @@ LLFloaterObjectWeights::LLFloaterObjectWeights(const LLSD& key)
mTrianglesShown(nullptr),
mPixelArea(nullptr)
{
+ mSelectionConnection = LLSelectMgr::getInstance()->mUpdateSignal.connect(
+ [this]()
+ {
+ mSelectionDirty = true;
+ mSelectionMeshDirty = true; // assume that mesh data will arrive with a delay.
+ }
+ );
}
LLFloaterObjectWeights::~LLFloaterObjectWeights()
@@ -114,6 +131,11 @@ bool LLFloaterObjectWeights::postBuild()
mTrianglesShown = getChild<LLTextBox>("triangles_shown");
mPixelArea = getChild<LLTextBox>("pixel_area");
+ mHighLodTris = getChild<LLTextBox>("high_lod_tris");
+ mMediumLodTris = getChild<LLTextBox>("medium_lod_tris");
+ mLowLodTris = getChild<LLTextBox>("low_lod_tris");
+ mLowestLodTris = getChild<LLTextBox>("lowest_lod_tris");
+
return true;
}
@@ -122,6 +144,14 @@ void LLFloaterObjectWeights::onOpen(const LLSD& key)
{
refresh();
updateLandImpacts(LLViewerParcelMgr::getInstance()->getFloatingParcelSelection()->getParcel());
+
+ onIdleRefresh(this);
+ gIdleCallbacks.addFunction(onIdleRefresh, this);
+}
+
+void LLFloaterObjectWeights::onClose(bool app_quitting)
+{
+ gIdleCallbacks.deleteFunction(onIdleRefresh, this);
}
// virtual
@@ -131,8 +161,9 @@ void LLFloaterObjectWeights::onWeightsUpdate(const SelectionCost& selection_cost
mSelectedPhysicsWeight->setText(llformat("%.1f", selection_cost.mPhysicsCost));
mSelectedServerWeight->setText(llformat("%.1f", selection_cost.mSimulationCost));
- S32 render_cost = LLSelectMgr::getInstance()->getSelection()->getSelectedObjectRenderCost();
- mSelectedDisplayWeight->setText(llformat("%d", render_cost));
+ // onWeightsUpdate comes from a coroutine.
+ // Postpone LLSelectMgr operations as getSelectedObjectRenderCost is not coroutine-safe
+ mWeightsDirty = true;
toggleWeightsLoadingIndicators(false);
}
@@ -152,20 +183,13 @@ void LLFloaterObjectWeights::setErrorStatus(S32 status, const std::string& reaso
void LLFloaterObjectWeights::draw()
{
- // Normally it's a bad idea to set text and visibility inside draw
- // since it can cause rect updates go to different, already drawn elements,
- // but floater is very simple and these elements are supposed to be isolated
+ // This logic might be a bit too expensive for draw(),
+ // but this floater needs to react fast, even if it's
+ // detrimental to performance. Having callbacks like
+ // 'tris changed' in every selected object might be
+ // more impactful on performance.
LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
- if (selection->isEmpty())
- {
- const std::string text = getString("nothing_selected");
- mLodLevel->setText(text);
- mTrianglesShown->setText(text);
- mPixelArea->setText(text);
-
- toggleRenderLoadingIndicators(false);
- }
- else
+ if (!selection->isEmpty() && !mSelectionDirty)
{
S32 object_lod = -1;
bool multiple_lods = false;
@@ -192,27 +216,71 @@ void LLFloaterObjectWeights::draw()
}
}
- if (multiple_lods)
+ if (mSelectionLastTris != total_tris)
{
- mLodLevel->setText(getString("multiple_lods"));
- toggleRenderLoadingIndicators(false);
+ mSelectionDirty = true;
}
- else if (object_lod < 0)
+ else if (mSelectionLastArea != pixel_area)
{
- // nodes are waiting for data
- toggleRenderLoadingIndicators(true);
+ mSelectionDirty = true;
}
- else
+ else if (multiple_lods)
{
- mLodLevel->setText(getString(lod_strings[object_lod]));
- toggleRenderLoadingIndicators(false);
+ mSelectionDirty |= mSelectionLastLOD != -1;
+ }
+ else if (mSelectionLastLOD != object_lod)
+ {
+ mSelectionDirty = true;
}
- mTrianglesShown->setText(llformat("%d", total_tris));
- mPixelArea->setText(llformat("%ld", (S64)pixel_area)); // value capped at 10M
}
LLFloater::draw();
}
+void LLFloaterObjectWeights::onIdleRefresh(void* user_data)
+{
+ LLFloaterObjectWeights* self = (LLFloaterObjectWeights*)user_data;
+
+ F64 current_time = LLTimer::getTotalSeconds();
+ S32 current_lod_requests = LLMeshRepoThread::sActiveLODRequests.load();
+ // Can't look for a specific mesh (no callback mechanics and we
+ // need multiple ones), so just update periodically if something loads
+ self->mSelectionMeshDirty |= (self->mLastActiveLODRequests > current_lod_requests);
+ bool throttle_elapsed = (current_time - self->mSelectionRefreshTime) >= 2.0;
+
+ if (self->mLastActiveLODRequests < current_lod_requests)
+ {
+ // we are interested in finished downloads,
+ // so don't refresh if more requests are getting added.
+ self->mLastActiveLODRequests = current_lod_requests;
+ }
+
+ if (self->mSelectionDirty)
+ {
+ // Always refresh on selection changes
+ self->refreshDataFromSelection();
+ self->mSelectionDirty = false;
+ self->mSelectionRefreshTime = current_time;
+ // refreshDataFromSelection could have indirectly initiated more requests
+ self->mLastActiveLODRequests = LLMeshRepoThread::sActiveLODRequests.load();
+ }
+ else if (self->mSelectionMeshDirty && throttle_elapsed)
+ {
+ // LOD requests count changed or mesh needs lod data reload
+ self->refreshDataFromSelection();
+ self->mSelectionRefreshTime = current_time;
+ self->mSelectionMeshDirty = false;
+ // refreshDataFromSelection could have indirectly initiated more requests
+ self->mLastActiveLODRequests = LLMeshRepoThread::sActiveLODRequests.load();
+ }
+ else if (self->mWeightsDirty) // also done in refreshDataFromSelection
+ {
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ S32 render_cost = selection->getSelectedObjectRenderCost();
+ self->mSelectedDisplayWeight->setText(llformat("%d", render_cost));
+ self->mWeightsDirty = false;
+ }
+}
+
void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel)
{
if (!parcel || LLSelectMgr::getInstance()->getSelection()->isEmpty())
@@ -240,6 +308,101 @@ void LLFloaterObjectWeights::updateLandImpacts(const LLParcel* parcel)
}
}
+void LLFloaterObjectWeights::refreshDataFromSelection()
+{
+ LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection();
+ if (selection->isEmpty())
+ {
+ const std::string text = getString("nothing_selected");
+ mLodLevel->setText(text);
+ mTrianglesShown->setText(text);
+ mPixelArea->setText(text);
+
+ mHighLodTris->setText(text);
+ mMediumLodTris->setText(text);
+ mLowLodTris->setText(text);
+ mLowestLodTris->setText(text);
+
+ toggleRenderLoadingIndicators(false);
+ toggleLODLoadingIndicators(false);
+ }
+ else
+ {
+ S32 object_lod = -1;
+ bool multiple_lods = false;
+ S32 total_tris = 0;
+ F32 pixel_area = 0;
+ S32 high_tris = 0;
+ S32 medium_tris = 0;
+ S32 low_tris = 0;
+ S32 lowest_tris = 0;
+ for (LLObjectSelection::valid_root_iterator iter = selection->valid_root_begin();
+ iter != selection->valid_root_end(); ++iter)
+ {
+ LLViewerObject* object = (*iter)->getObject();
+ S32 lod = object->getLOD();
+ if (object_lod < 0)
+ {
+ object_lod = lod;
+ }
+ else if (object_lod != lod)
+ {
+ multiple_lods = true;
+ }
+
+ if (object->isRootEdit())
+ {
+ total_tris += object->recursiveGetTriangleCount();
+ pixel_area += object->getPixelArea();
+ object->recursiveGetLODTriangleCount(high_tris, medium_tris, low_tris, lowest_tris);
+ }
+ }
+
+ mSelectionLastTris = total_tris;
+ mSelectionLastArea = pixel_area;
+ if (multiple_lods)
+ {
+ mSelectionLastLOD = -1;
+ }
+ else
+ {
+ mSelectionLastLOD = object_lod;
+ }
+
+ if (multiple_lods)
+ {
+ mLodLevel->setText(getString("multiple_lods"));
+ toggleRenderLoadingIndicators(false);
+ toggleLODLoadingIndicators(false);
+ }
+ else if (object_lod < 0)
+ {
+ // nodes are waiting for data
+ toggleRenderLoadingIndicators(true);
+ toggleLODLoadingIndicators(true);
+ }
+ else
+ {
+ mLodLevel->setText(getString(lod_strings[object_lod]));
+ toggleRenderLoadingIndicators(false);
+ toggleLODLoadingIndicators(false);
+ }
+ mTrianglesShown->setText(llformat("%d", total_tris));
+ mPixelArea->setText(llformat("%ld", (S64)pixel_area)); // value capped at 10M
+ mHighLodTris->setText(llformat("%d", high_tris));
+ mMediumLodTris->setText(llformat("%d", medium_tris));
+ mLowLodTris->setText(llformat("%d", low_tris));
+ mLowestLodTris->setText(llformat("%d", lowest_tris));
+ }
+
+ if (mWeightsDirty)
+ {
+ S32 render_cost = selection->getSelectedObjectRenderCost();
+ mSelectedDisplayWeight->setText(llformat("%d", render_cost));
+ mWeightsDirty = false;
+ }
+}
+
void LLFloaterObjectWeights::refresh()
{
LLSelectMgr* sel_mgr = LLSelectMgr::getInstance();
@@ -341,6 +504,19 @@ void LLFloaterObjectWeights::toggleRenderLoadingIndicators(bool visible)
mPixelArea->setVisible(!visible);
}
+void LLFloaterObjectWeights::toggleLODLoadingIndicators(bool visible)
+{
+ childSetVisible("high_lod_tris_loading_indicator", visible);
+ childSetVisible("medium_lod_tris_loading_indicator", visible);
+ childSetVisible("low_lod_tris_loading_indicator", visible);
+ childSetVisible("lowest_lod_tris_loading_indicator", visible);
+
+ mHighLodTris->setVisible(!visible);
+ mMediumLodTris->setVisible(!visible);
+ mLowLodTris->setVisible(!visible);
+ mLowestLodTris->setVisible(!visible);
+}
+
void LLFloaterObjectWeights::updateIfNothingSelected()
{
const std::string text = getString("nothing_selected");