diff options
Diffstat (limited to 'indra/newview/llfloaterobjectweights.cpp')
| -rw-r--r-- | indra/newview/llfloaterobjectweights.cpp | 228 |
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"); |
