From 99a9258d5217565d9c4e4753a5697857b6b339b7 Mon Sep 17 00:00:00 2001 From: Rider Linden Date: Wed, 25 Sep 2024 18:03:57 -0700 Subject: Issue #2687: Honor flag sent by server indicating server side autopilot is engaged. When flag is set allow sever to update local avatar rotation. --- indra/newview/llviewerobject.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 86440fca48..b87b17e3cf 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2325,6 +2325,12 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, // Set the rotation of the object followed by adjusting for the accumulated angular velocity (llSetTargetOmega) setRotation(new_rot * mAngularVelocityRot); + if ((mFlags & FLAGS_SERVER_AUTOPILOT) && asAvatar() && asAvatar()->isSelf()) + { + gAgent.resetAxes(); + gAgent.rotate(new_rot); + gAgentCamera.resetView(); + } setChanged(ROTATED | SILHOUETTE); } -- cgit v1.3 From 4214ab8e79809412fdec626fa5f914723e6d4704 Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Thu, 12 Dec 2024 23:32:34 +0200 Subject: #3280 Fix crashes at gFloaterTools Likely specific to headless client --- indra/newview/llagent.cpp | 5 ++++- indra/newview/llgiveinventory.cpp | 12 ++++++++++-- indra/newview/llpanelprimmediacontrols.cpp | 2 +- indra/newview/llselectmgr.cpp | 5 ++++- indra/newview/lltoolbrush.cpp | 5 ++++- indra/newview/lltooldraganddrop.cpp | 23 +++++++++++++++-------- indra/newview/lltoolplacer.cpp | 5 ++++- indra/newview/lltoolselectland.cpp | 5 ++++- indra/newview/llviewermenu.cpp | 6 +++++- indra/newview/llviewerobject.cpp | 12 ++++++------ indra/newview/pipeline.cpp | 2 +- 11 files changed, 58 insertions(+), 24 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llagent.cpp b/indra/newview/llagent.cpp index 8756baa04a..a076594e0a 100644 --- a/indra/newview/llagent.cpp +++ b/indra/newview/llagent.cpp @@ -2501,7 +2501,10 @@ void LLAgent::endAnimationUpdateUI() gAgentAvatarp->updateAttachmentVisibility(gAgentCamera.getCameraMode()); } - gFloaterTools->dirty(); + if (gFloaterTools) + { + gFloaterTools->dirty(); + } // Don't let this be called more than once if the camera // mode hasn't changed. --JC diff --git a/indra/newview/llgiveinventory.cpp b/indra/newview/llgiveinventory.cpp index 1259b65ebe..57dd203f2f 100644 --- a/indra/newview/llgiveinventory.cpp +++ b/indra/newview/llgiveinventory.cpp @@ -414,7 +414,11 @@ void LLGiveInventory::commitGiveInventoryItem(const LLUUID& to_agent, effectp->setTargetObject(gObjectList.findObject(to_agent)); effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - gFloaterTools->dirty(); + + if (gFloaterTools) + { + gFloaterTools->dirty(); + } LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); @@ -572,7 +576,11 @@ bool LLGiveInventory::commitGiveInventoryCategory(const LLUUID& to_agent, effectp->setTargetObject(gObjectList.findObject(to_agent)); effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - gFloaterTools->dirty(); + + if (gFloaterTools) + { + gFloaterTools->dirty(); + } LLMuteList::getInstance()->autoRemove(to_agent, LLMuteList::AR_INVENTORY); diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp index b8c12ce0b9..b00b9d1ad1 100644 --- a/indra/newview/llpanelprimmediacontrols.cpp +++ b/indra/newview/llpanelprimmediacontrols.cpp @@ -294,7 +294,7 @@ void LLPanelPrimMediaControls::updateShape() LLViewerMediaImpl* media_impl = getTargetMediaImpl(); LLViewerObject* objectp = getTargetObject(); - if(!media_impl || gFloaterTools->getVisible()) + if(!media_impl || (gFloaterTools && gFloaterTools->getVisible())) { setVisible(false); return; diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index fceb25b3d3..1d4bfb0ed9 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -7253,7 +7253,10 @@ void dialog_refresh_all() // *TODO: Eliminate all calls into outside classes below, make those // objects register with the update signal. - gFloaterTools->dirty(); + if (gFloaterTools) + { + gFloaterTools->dirty(); + } gMenuObject->needsArrange(); diff --git a/indra/newview/lltoolbrush.cpp b/indra/newview/lltoolbrush.cpp index 2fe81df4fb..cf7b123fa7 100644 --- a/indra/newview/lltoolbrush.cpp +++ b/indra/newview/lltoolbrush.cpp @@ -447,7 +447,10 @@ void LLToolBrushLand::handleSelect() { gEditMenuHandler = this; - gFloaterTools->setStatusText("modifyland"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("modifyland"); + } // if (!mBrushSelected) { mBrushSelected = true; diff --git a/indra/newview/lltooldraganddrop.cpp b/indra/newview/lltooldraganddrop.cpp index 4efa289141..75adb722f3 100644 --- a/indra/newview/lltooldraganddrop.cpp +++ b/indra/newview/lltooldraganddrop.cpp @@ -1253,6 +1253,7 @@ void LLToolDragAndDrop::dropMaterial(LLViewerObject* hit_obj, // If user dropped a material onto face it implies // applying texture now without cancel, save to selection if (nodep + && gFloaterTools && gFloaterTools->getVisible() && nodep->mSavedGLTFMaterialIds.size() > hit_face) { @@ -1429,10 +1430,10 @@ void LLToolDragAndDrop::dropTexture(LLViewerObject* hit_obj, // If user dropped a texture onto face it implies // applying texture now without cancel, save to selection - LLPanelFace* panel_face = gFloaterTools->getPanelFace(); + LLPanelFace* panel_face = gFloaterTools ? gFloaterTools->getPanelFace() : nullptr; if (nodep - && gFloaterTools->getVisible() && panel_face + && gFloaterTools->getVisible() && panel_face->getTextureDropChannel() == 0 /*texture*/ && nodep->mSavedTextures.size() > hit_face) { @@ -1488,8 +1489,8 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, if (allow_adding_to_override) { LLGLTFMaterial::TextureInfo drop_channel = LLGLTFMaterial::GLTF_TEXTURE_INFO_BASE_COLOR; - LLPanelFace* panel_face = gFloaterTools->getPanelFace(); - if (gFloaterTools->getVisible() && panel_face) + LLPanelFace* panel_face = gFloaterTools ? gFloaterTools->getPanelFace() : nullptr; + if (panel_face && gFloaterTools->getVisible()) { drop_channel = panel_face->getPBRDropChannel(); } @@ -1514,9 +1515,9 @@ void LLToolDragAndDrop::dropTextureOneFace(LLViewerObject* hit_obj, LLTextureEntry* tep = hit_obj->getTE(hit_face); - LLPanelFace* panel_face = gFloaterTools->getPanelFace(); + LLPanelFace* panel_face = gFloaterTools ? gFloaterTools->getPanelFace() : nullptr; - if (gFloaterTools->getVisible() && panel_face) + if (panel_face && gFloaterTools->getVisible()) { tex_channel = (tex_channel > -1) ? tex_channel : panel_face->getTextureDropChannel(); switch (tex_channel) @@ -1611,7 +1612,10 @@ void LLToolDragAndDrop::dropScript(LLViewerObject* hit_obj, } } hit_obj->saveScript(new_script, active, true); - gFloaterTools->dirty(); + if (gFloaterTools) + { + gFloaterTools->dirty(); + } // VEFFECT: SetScript LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, true); @@ -1844,7 +1848,10 @@ void LLToolDragAndDrop::dropInventory(LLViewerObject* hit_obj, effectp->setTargetObject(hit_obj); effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); - gFloaterTools->dirty(); + if (gFloaterTools) + { + gFloaterTools->dirty(); + } } // accessor that looks at permissions, copyability, and names of diff --git a/indra/newview/lltoolplacer.cpp b/indra/newview/lltoolplacer.cpp index b15bb5efd5..0d141d7545 100644 --- a/indra/newview/lltoolplacer.cpp +++ b/indra/newview/lltoolplacer.cpp @@ -527,7 +527,10 @@ bool LLToolPlacer::handleHover(S32 x, S32 y, MASK mask) void LLToolPlacer::handleSelect() { - gFloaterTools->setStatusText("place"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("place"); + } } void LLToolPlacer::handleDeselect() diff --git a/indra/newview/lltoolselectland.cpp b/indra/newview/lltoolselectland.cpp index 88553c7557..331581fd88 100644 --- a/indra/newview/lltoolselectland.cpp +++ b/indra/newview/lltoolselectland.cpp @@ -207,7 +207,10 @@ void LLToolSelectLand::render() void LLToolSelectLand::handleSelect() { - gFloaterTools->setStatusText("selectland"); + if (gFloaterTools) + { + gFloaterTools->setStatusText("selectland"); + } } diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index 6281ac1f9e..1c9a892a4f 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -3177,7 +3177,11 @@ void handle_object_edit() LLFloaterReg::showInstance("build"); LLToolMgr::getInstance()->setCurrentToolset(gBasicToolset); - gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); + + if (gFloaterTools) + { + gFloaterTools->setEditTool( LLToolCompTranslate::getInstance() ); + } LLViewerJoystick::getInstance()->moveObjects(true); LLViewerJoystick::getInstance()->setNeedsReset(true); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 86440fca48..74d795ea25 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1290,7 +1290,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, #endif //clear cost and linkset cost setObjectCostStale(); - if (isSelected()) + if (isSelected() && gFloaterTools) { gFloaterTools->dirty(); } @@ -1729,7 +1729,7 @@ U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, #endif setObjectCostStale(); - if (isSelected()) + if (isSelected() && gFloaterTools) { gFloaterTools->dirty(); } @@ -3747,7 +3747,7 @@ void LLViewerObject::setObjectCost(F32 cost) mObjectCost = cost; mCostStale = false; - if (isSelected()) + if (isSelected() && gFloaterTools) { gFloaterTools->dirty(); } @@ -3767,7 +3767,7 @@ void LLViewerObject::setLinksetCost(F32 cost) iter++; } - if (needs_refresh) + if (needs_refresh && gFloaterTools) { gFloaterTools->dirty(); } @@ -3778,7 +3778,7 @@ void LLViewerObject::setPhysicsCost(F32 cost) mPhysicsCost = cost; mCostStale = false; - if (isSelected()) + if (isSelected() && gFloaterTools) { gFloaterTools->dirty(); } @@ -3789,7 +3789,7 @@ void LLViewerObject::setLinksetPhysicsCost(F32 cost) mLinksetPhysicsCost = cost; mCostStale = false; - if (isSelected()) + if (isSelected() && gFloaterTools) { gFloaterTools->dirty(); } diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 5f096a5356..6c5fd855fd 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -7208,7 +7208,7 @@ void LLPipeline::tonemap(LLRenderTarget* src, LLRenderTarget* dst) LLSettingsSky::ptr_t psky = LLEnvironment::instance().getCurrentSky(); - bool no_post = gSnapshotNoPost || psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f || (buildNoPost && gFloaterTools->isAvailable()); + bool no_post = gSnapshotNoPost || psky->getReflectionProbeAmbiance(should_auto_adjust) == 0.f || (buildNoPost && gFloaterTools && gFloaterTools->isAvailable()); LLGLSLShader& shader = no_post ? gNoPostTonemapProgram : gDeferredPostTonemapProgram; shader.bind(); -- cgit v1.3 From 6fd4f13c477705a71c3ad24955872d734a6c3dd6 Mon Sep 17 00:00:00 2001 From: Salad Dais Date: Thu, 30 May 2024 16:29:58 +0000 Subject: Add support for RequestTaskInventory capability The viewer now prefers to load inventory via the capability rather than over the deprecated Xfer system, though both are still supported. # Conflicts: # indra/newview/llviewerobject.h --- indra/newview/llviewerobject.cpp | 146 +++++++++++++++++++++++++++++++++++++-- indra/newview/llviewerobject.h | 2 + indra/newview/llviewerregion.cpp | 1 + 3 files changed, 145 insertions(+), 4 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 86440fca48..2eeb0640cc 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -2917,6 +2917,17 @@ void LLViewerObject::fetchInventoryFromServer() delete mInventory; mInventory = NULL; + // This will get reset by doInventoryCallback or processTaskInv + mInvRequestState = INVENTORY_REQUEST_PENDING; + + if (mRegionp && !mRegionp->getCapability("RequestTaskInventory").empty()) + { + LLCoros::instance().launch("LLViewerObject::fetchInventoryFromCapCoro()", + boost::bind(&LLViewerObject::fetchInventoryFromCapCoro, mID)); + } + else + { + LL_WARNS() << "Using old task inventory path!" << LL_ENDL; // Results in processTaskInv LLMessageSystem* msg = gMessageSystem; msg->newMessageFast(_PREHASH_RequestTaskInventory); @@ -2926,15 +2937,13 @@ void LLViewerObject::fetchInventoryFromServer() msg->nextBlockFast(_PREHASH_InventoryData); msg->addU32Fast(_PREHASH_LocalID, mLocalID); msg->sendReliable(mRegionp->getHost()); - - // This will get reset by doInventoryCallback or processTaskInv - mInvRequestState = INVENTORY_REQUEST_PENDING; + } } } void LLViewerObject::fetchInventoryDelayed(const F64 &time_seconds) { - // unless already waiting, drop previous request and shedule an update + // unless already waiting, drop previous request and schedule an update if (mInvRequestState != INVENTORY_REQUEST_WAIT) { if (mInvRequestXFerId != 0) @@ -2965,6 +2974,80 @@ void LLViewerObject::fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 } } +//static +void LLViewerObject::fetchInventoryFromCapCoro(const LLUUID task_inv) +{ + LLViewerObject *obj = gObjectList.findObject(task_inv); + if (obj) + { + LLCore::HttpRequest::policy_t httpPolicy(LLCore::HttpRequest::DEFAULT_POLICY_ID); + LLCoreHttpUtil::HttpCoroutineAdapter::ptr_t + httpAdapter(new LLCoreHttpUtil::HttpCoroutineAdapter("TaskInventoryRequest", httpPolicy)); + LLCore::HttpRequest::ptr_t httpRequest(new LLCore::HttpRequest); + std::string url = obj->mRegionp->getCapability("RequestTaskInventory") + "?task_id=" + obj->mID.asString(); + // If we already have a copy of the inventory then add it so the server won't re-send something we already have. + // We expect this case to crop up in the case of failed inventory mutations, but it might happen otherwise as well. + if (obj->mInventorySerialNum && obj->mInventory) + url += "&inventory_serial=" + std::to_string(obj->mInventorySerialNum); + + obj->mInvRequestState = INVENTORY_XFER; + LLSD result = httpAdapter->getAndSuspend(httpRequest, url); + + LLSD httpResults = result[LLCoreHttpUtil::HttpCoroutineAdapter::HTTP_RESULTS]; + LLCore::HttpStatus status = LLCoreHttpUtil::HttpCoroutineAdapter::getStatusFromLLSD(httpResults); + + // Object may have gone away while we were suspended, double-check that it still exists + obj = gObjectList.findObject(task_inv); + if (!obj) + { + LL_WARNS() << "Object " << task_inv << " went away while fetching inventory, dropping result" << LL_ENDL; + return; + } + + bool potentially_stale = false; + if (status) + { + // Dealing with inventory serials is kind of funky. They're monotonically increasing and 16 bits, + // so we expect them to overflow, but we can use inv serial < expected serial as a signal that we may + // have mutated the task inventory since we kicked off the request, and those mutations may have not + // been taken into account yet. Of course, those mutations may have actually failed which would result + // in the inv serial never increasing. + // + // When we detect this case, set the expected inv serial to the inventory serial we actually received + // and kick off a re-request after a slight delay. + S16 serial = (S16)result["inventory_serial"].asInteger(); + potentially_stale = serial < obj->mExpectedInventorySerialNum; + LL_INFOS() << "Inventory loaded for " << task_inv << LL_ENDL; + obj->mInventorySerialNum = serial; + obj->mExpectedInventorySerialNum = serial; + obj->loadTaskInvLLSD(result); + } + else if (status.getType() == 304) + { + LL_INFOS() << "Inventory wasn't changed on server!" << LL_ENDL; + obj->mInvRequestState = INVENTORY_REQUEST_STOPPED; + // Even though it wasn't necessary to send a response, we still may have mutated + // the inventory since we kicked off the request, check for that case. + potentially_stale = obj->mInventorySerialNum < obj->mExpectedInventorySerialNum; + // Set this to what we already have so that we don't re-request a second time. + obj->mExpectedInventorySerialNum = obj->mInventorySerialNum; + } + else + { + // Not sure that there's anything sensible we can do to recover here, retrying in a loop would be bad. + LL_WARNS() << "Error status while requesting task inventory: " << status.toString() << LL_ENDL; + obj->mInvRequestState = INVENTORY_REQUEST_STOPPED; + } + + if (potentially_stale) + { + // Stale? I guess we can use what we got for now, but we'll have to re-request + LL_WARNS() << "Stale inv_serial? Re-requesting." << LL_ENDL; + obj->fetchInventoryDelayed(INVENTORY_UPDATE_WAIT_TIME_OUTDATED); + } + } +} + LLControlAvatar *LLViewerObject::getControlAvatar() { return getRootEdit()->mControlAvatar.get(); @@ -3140,6 +3223,20 @@ void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) S16 serial = 0; msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, serial); + if (object->mRegionp && !object->mRegionp->getCapability("RequestTaskInventory").empty()) + { + // It seems that simulator may ask us to re-download the task inventory if an update to the inventory + // happened out-of-band while we had the object selected (like if a script is saved.) + // + // If we're meant to use the HTTP capability, ignore the contents of the UDP message and fetch the + // inventory via the CAP so that we don't flow down the UDP inventory request path unconditionally here. + // We shouldn't need to wait, as any updates should already be ready to fetch by this point. + LL_INFOS() << "Handling unsolicited ReplyTaskInventory for " << task_id << LL_ENDL; + object->mExpectedInventorySerialNum = serial; + object->fetchInventoryFromServer(); + return; + } + if (serial == object->mInventorySerialNum && serial < object->mExpectedInventorySerialNum) { @@ -3347,6 +3444,47 @@ bool LLViewerObject::loadTaskInvFile(const std::string& filename) return true; } +void LLViewerObject::loadTaskInvLLSD(const LLSD& inv_result) +{ + if (inv_result.has("contents")) + { + if(mInventory) + { + mInventory->clear(); // will deref and delete it + } + else + { + mInventory = new LLInventoryObject::object_list_t; + } + + // Synthesize the "Contents" category, the viewer expects it, but it isn't sent. + LLPointer inv = new LLInventoryObject(mID, LLUUID::null, LLAssetType::AT_CATEGORY, "Contents"); + mInventory->push_front(inv); + + const LLSD& inventory = inv_result["contents"]; + for (const auto& inv_entry : llsd::inArray(inventory)) + { + if (inv_entry.has("item_id")) + { + LLPointer inv = new LLViewerInventoryItem; + inv->unpackMessage(inv_entry); + mInventory->push_front(inv); + } + else + { + LL_WARNS_ONCE() << "Unknown inventory entry while reading from inventory file. Entry: '" + << inv_entry << "'" << LL_ENDL; + } + } + } + else + { + LL_WARNS() << "unable to load task inventory: " << inv_result << LL_ENDL; + return; + } + doInventoryCallback(); +} + void LLViewerObject::doInventoryCallback() { for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 119b07b1f5..63458e60ea 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -688,6 +688,7 @@ private: // forms task inventory request after some time passed, marks request as pending void fetchInventoryDelayed(const F64 &time_seconds); static void fetchInventoryDelayedCoro(const LLUUID task_inv, const F64 time_seconds); + static void fetchInventoryFromCapCoro(const LLUUID task_inv); public: // @@ -826,6 +827,7 @@ protected: static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); bool loadTaskInvFile(const std::string& filename); + void loadTaskInvLLSD(const LLSD &inv_result); void doInventoryCallback(); bool isOnMap(); diff --git a/indra/newview/llviewerregion.cpp b/indra/newview/llviewerregion.cpp index c21aeb1d57..697433148b 100755 --- a/indra/newview/llviewerregion.cpp +++ b/indra/newview/llviewerregion.cpp @@ -3239,6 +3239,7 @@ void LLViewerRegionImpl::buildCapabilityNames(LLSD& capabilityNames) capabilityNames.append("FetchInventory2"); capabilityNames.append("FetchInventoryDescendents2"); capabilityNames.append("IncrementCOFVersion"); + capabilityNames.append("RequestTaskInventory"); AISAPI::getCapNames(capabilityNames); capabilityNames.append("InterestList"); -- cgit v1.3 From dee3257ffd9735f0cdaec643743b9dd8cd1920b3 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Thu, 20 Mar 2025 15:15:42 +0200 Subject: #1964 fix for reflection probe doesn't update position when the linkset is moved by the script --- indra/newview/llviewerobject.cpp | 12 ++++++++++++ 1 file changed, 12 insertions(+) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 030dfeaa6f..3d88cc5f39 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4820,6 +4820,18 @@ void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, bool damped) else { setPositionRegion(pos_parent, damped); + + // #1964 mark reflection probe in the linkset to update position after moving via script + for (LLViewerObject* child : mChildList) + { + if (child && child->isReflectionProbe()) + { + if (LLDrawable* drawablep = child->mDrawable) + { + gPipeline.markMoved(drawablep); + } + } + } } } -- cgit v1.3 From 6b88a2bec27e24debb4eb4fe986850f36f8689a9 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 24 Mar 2025 18:05:06 +0200 Subject: #3780 disable water exclusion if user applies PBR or Media --- indra/newview/llpanelface.cpp | 5 +---- indra/newview/llselectmgr.cpp | 11 ++++++++++- indra/newview/llselectmgr.h | 1 + indra/newview/llviewerobject.cpp | 25 +++++++++++++++++++++++++ indra/newview/llviewerobject.h | 2 ++ 5 files changed, 39 insertions(+), 5 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llpanelface.cpp b/indra/newview/llpanelface.cpp index c4f118fed8..b7d9df6ea6 100644 --- a/indra/newview/llpanelface.cpp +++ b/indra/newview/llpanelface.cpp @@ -3075,10 +3075,7 @@ void LLPanelFace::onCommitHideWater() } else { - // reset texture to default plywood - LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); - // reset texture repeats, that might be altered by invisiprim script from wiki - LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); + LLSelectMgr::getInstance()->clearWaterExclusion(); } } diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp index b307de787c..cc88d31aee 100644 --- a/indra/newview/llselectmgr.cpp +++ b/indra/newview/llselectmgr.cpp @@ -1995,7 +1995,7 @@ bool LLSelectMgr::selectionSetGLTFMaterial(const LLUUID& mat_id) asset_id = BLANK_MATERIAL_ASSET_ID; } } - + objectp->clearTEWaterExclusion(te); // Blank out most override data on the object and send to server objectp->setRenderMaterialID(te, asset_id); @@ -2477,6 +2477,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data) } else { // Add/update media + object->clearTEWaterExclusion(te); object->setTEMediaFlags(te, mMediaFlags); LLVOVolume *vo = dynamic_cast(object); llassert(NULL != vo); @@ -7724,6 +7725,14 @@ void LLSelectMgr::setAgentHUDZoom(F32 target_zoom, F32 current_zoom) gAgentCamera.mHUDCurZoom = current_zoom; } +void LLSelectMgr::clearWaterExclusion() +{ + // reset texture to default plywood + LLSelectMgr::getInstance()->selectionSetImage(DEFAULT_OBJECT_TEXTURE); + // reset texture repeats, that might be altered by invisiprim script from wiki + LLSelectMgr::getInstance()->selectionTexScaleAutofit(2.f); +} + ///////////////////////////////////////////////////////////////////////////// // Object selection iterator helpers ///////////////////////////////////////////////////////////////////////////// diff --git a/indra/newview/llselectmgr.h b/indra/newview/llselectmgr.h index b70ec3dbea..0dbdc133e3 100644 --- a/indra/newview/llselectmgr.h +++ b/indra/newview/llselectmgr.h @@ -836,6 +836,7 @@ public: void getAgentHUDZoom(F32 &target_zoom, F32 ¤t_zoom) const; void updatePointAt(); + void clearWaterExclusion(); // Internal list maintenance functions. TODO: Make these private! void remove(std::vector& objects); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 3d88cc5f39..c5e81dd179 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7682,6 +7682,31 @@ void LLViewerObject::setGLTFAsset(const LLUUID& id) updateVolume(volume_params); } +void LLViewerObject::clearTEWaterExclusion(const U8 te) +{ + if (permModify()) + { + LLViewerTexture* image = getTEImage(te); + if (image && (IMG_ALPHA_GRAD == image->getID())) + { + // reset texture to default plywood + setTEImage(te, LLViewerTextureManager::getFetchedTexture(DEFAULT_OBJECT_TEXTURE, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)); + + // reset texture repeats, that might be altered by invisiprim script from wiki + U32 s_axis, t_axis; + if (!LLPrimitive::getTESTAxes(te, &s_axis, &t_axis)) + { + return; + } + F32 DEFAULT_REPEATS = 2.f; + F32 new_s = getScale().mV[s_axis] * DEFAULT_REPEATS; + F32 new_t = getScale().mV[t_axis] * DEFAULT_REPEATS; + + setTEScale(te, new_s, new_t); + sendTEUpdate(); + } + } +} class ObjectPhysicsProperties : public LLHTTPNode { diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 63458e60ea..2b52ea2076 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -405,6 +405,8 @@ public: LLViewerTexture *getTENormalMap(const U8 te) const; LLViewerTexture *getTESpecularMap(const U8 te) const; + void clearTEWaterExclusion(const U8 te); + bool isImageAlphaBlended(const U8 te) const; void fitFaceTexture(const U8 face); -- cgit v1.3 From 778a69c6e1783ea6c9c7ac3102990646ff2e38da Mon Sep 17 00:00:00 2001 From: Andrey Kleshchev Date: Wed, 30 Apr 2025 19:24:51 +0300 Subject: #4005 Crash at LLVOVolume::isMesh Doesn't make much sense, if param is in use it is supposed to be set, but bugsplat says sculpt_params is null --- indra/newview/llpanelobject.cpp | 24 +++++++++++++----------- indra/newview/llviewerobject.cpp | 7 +++++-- indra/newview/llvovolume.cpp | 33 +++++++++++++++++++++------------ 3 files changed, 39 insertions(+), 25 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 0a3a2e753a..23e6a9fbcf 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -2267,19 +2267,21 @@ void LLPanelObject::onCopyParams() if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) { LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (get_can_copy_texture(texture_id)) - { - LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; - mClipboardParams["sculpt"]["id"] = texture_id; - } - else + if (sculpt_params) { - mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; - } + LLUUID texture_id = sculpt_params->getSculptTexture(); + if (get_can_copy_texture(texture_id)) + { + LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; + mClipboardParams["sculpt"]["id"] = texture_id; + } + else + { + mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE; + } - mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); + } } } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 8d90187e91..9e77b40a45 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -4184,8 +4184,11 @@ void LLViewerObject::boostTexturePriority(bool boost_children /* = true */) if (isSculpted() && !isMesh()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + if (sculpt_params) + { + LLUUID sculpt_id = sculpt_params->getSculptTexture(); + LLViewerTextureManager::getFetchedTexture(sculpt_id, FTT_DEFAULT, true, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLGLTexture::BOOST_SELECTED); + } } if (boost_children) diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp index b434ec9377..29ada883e6 100644 --- a/indra/newview/llvovolume.cpp +++ b/indra/newview/llvovolume.cpp @@ -352,8 +352,11 @@ U32 LLVOVolume::processUpdateMessage(LLMessageSystem *mesgsys, if (isSculpted()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - sculpt_id = sculpt_params->getSculptTexture(); - sculpt_type = sculpt_params->getSculptType(); + if (sculpt_params) + { + sculpt_id = sculpt_params->getSculptTexture(); + sculpt_type = sculpt_params->getSculptType(); + } LL_DEBUGS("ObjectUpdate") << "uuid " << mID << " set sculpt_id " << sculpt_id << LL_ENDL; } @@ -1188,12 +1191,15 @@ void LLVOVolume::updateSculptTexture() if (isSculpted() && !isMesh()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID id = sculpt_params->getSculptTexture(); - if (id.notNull()) + if (sculpt_params) { - mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_SCULPTED, LLViewerTexture::LOD_TEXTURE); - mSculptTexture->forceToSaveRawImage(0, F32_MAX); - mSculptTexture->setKnownDrawSize(256, 256); + LLUUID id = sculpt_params->getSculptTexture(); + if (id.notNull()) + { + mSculptTexture = LLViewerTextureManager::getFetchedTexture(id, FTT_DEFAULT, true, LLGLTexture::BOOST_SCULPTED, LLViewerTexture::LOD_TEXTURE); + mSculptTexture->forceToSaveRawImage(0, F32_MAX); + mSculptTexture->setKnownDrawSize(256, 256); + } } mSkinInfoUnavaliable = false; @@ -3580,12 +3586,15 @@ bool LLVOVolume::isMesh() const if (isSculpted()) { LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - U8 sculpt_type = sculpt_params->getSculptType(); - - if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) - // mesh is a mesh + if (sculpt_params) { - return true; + U8 sculpt_type = sculpt_params->getSculptType(); + + if ((sculpt_type & LL_SCULPT_TYPE_MASK) == LL_SCULPT_TYPE_MESH) + // mesh is a mesh + { + return true; + } } } -- cgit v1.3 From d7bd769129100332791569cbffa07f54d2fca991 Mon Sep 17 00:00:00 2001 From: Maxim Nikolenko Date: Mon, 22 Sep 2025 15:46:04 +0300 Subject: #4715 disable ZoomIn an object item when the region is not connected to the current region --- indra/llui/lltextbase.cpp | 20 ++++++++++++++++++ indra/llui/lltextbase.h | 3 +++ indra/newview/llchathistory.cpp | 9 ++++++-- indra/newview/llviewermenu.cpp | 2 +- indra/newview/llviewerobject.cpp | 45 ++++++++++++++++++++++++++++++++++++++++ indra/newview/llviewerobject.h | 3 +++ 6 files changed, 79 insertions(+), 3 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/llui/lltextbase.cpp b/indra/llui/lltextbase.cpp index 3fe0df1848..69729fa421 100644 --- a/indra/llui/lltextbase.cpp +++ b/indra/llui/lltextbase.cpp @@ -185,6 +185,7 @@ LLTextBase::LLTextBase(const LLTextBase::Params &p) mURLClickSignal(NULL), mIsFriendSignal(NULL), mIsObjectBlockedSignal(NULL), + mIsObjectReachableSignal(NULL), mMaxTextByteLength( p.max_text_length ), mFont(p.font), mFontShadow(p.font_shadow), @@ -290,6 +291,7 @@ LLTextBase::~LLTextBase() delete mURLClickSignal; delete mIsFriendSignal; delete mIsObjectBlockedSignal; + delete mIsObjectReachableSignal; } void LLTextBase::initFromParams(const LLTextBase::Params& p) @@ -2281,6 +2283,15 @@ void LLTextBase::createUrlContextMenu(S32 x, S32 y, const std::string &in_url) unblockButton->setVisible(is_blocked); } } + + if (mIsObjectReachableSignal) + { + bool is_reachable = *(*mIsObjectReachableSignal)(LLUUID(LLUrlAction::getObjectId(url))); + if (LLView* zoom_btn = menu->getChild("zoom_in")) + { + zoom_btn->setEnabled(is_reachable); + } + } menu->show(x, y); LLMenuGL::showPopup(this, menu, x, y); } @@ -3387,6 +3398,15 @@ boost::signals2::connection LLTextBase::setIsObjectBlockedCallback(const is_bloc return mIsObjectBlockedSignal->connect(cb); } +boost::signals2::connection LLTextBase::setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb) +{ + if (!mIsObjectReachableSignal) + { + mIsObjectReachableSignal = new is_obj_reachable_signal_t(); + } + return mIsObjectReachableSignal->connect(cb); +} + // // LLTextSegment // diff --git a/indra/llui/lltextbase.h b/indra/llui/lltextbase.h index 8ca653acb9..07cd9a1ee5 100644 --- a/indra/llui/lltextbase.h +++ b/indra/llui/lltextbase.h @@ -325,6 +325,7 @@ public: typedef boost::signals2::signal is_friend_signal_t; typedef boost::signals2::signal is_blocked_signal_t; + typedef boost::signals2::signal is_obj_reachable_signal_t; struct LineSpacingParams : public LLInitParam::ChoiceBlock { @@ -535,6 +536,7 @@ public: boost::signals2::connection setURLClickedCallback(const commit_signal_t::slot_type& cb); boost::signals2::connection setIsFriendCallback(const is_friend_signal_t::slot_type& cb); boost::signals2::connection setIsObjectBlockedCallback(const is_blocked_signal_t::slot_type& cb); + boost::signals2::connection setIsObjectReachableCallback(const is_obj_reachable_signal_t::slot_type& cb); void setWordWrap(bool wrap); LLScrollContainer* getScrollContainer() const { return mScroller; } @@ -783,6 +785,7 @@ protected: // Used to check if user with given ID is avatar's friend is_friend_signal_t* mIsFriendSignal; is_blocked_signal_t* mIsObjectBlockedSignal; + is_obj_reachable_signal_t* mIsObjectReachableSignal; LLUIString mLabel; // text label that is visible when no user text provided }; diff --git a/indra/newview/llchathistory.cpp b/indra/newview/llchathistory.cpp index 2facc43811..c1af09ebc7 100644 --- a/indra/newview/llchathistory.cpp +++ b/indra/newview/llchathistory.cpp @@ -215,7 +215,8 @@ public: LLUUID obj_id = mObjectData["object_id"]; if (obj_id.notNull()) { - return nullptr != gObjectList.findObject(mAvatarID); + LLViewerObject* object = gObjectList.findObject(obj_id); + return object && object->isReachable(); } return false; } @@ -1118,7 +1119,11 @@ LLChatHistory::LLChatHistory(const LLChatHistory::Params& p) mEditor = LLUICtrlFactory::create(editor_params, this); mEditor->setIsFriendCallback(LLAvatarActions::isFriend); mEditor->setIsObjectBlockedCallback(boost::bind(&LLMuteList::isMuted, LLMuteList::getInstance(), _1, _2, 0)); - + mEditor->setIsObjectReachableCallback([](const LLUUID& obj_id) + { + LLViewerObject* object = gObjectList.findObject(obj_id); + return object && object->isReachable(); + }); } LLSD LLChatHistory::getValue() const diff --git a/indra/newview/llviewermenu.cpp b/indra/newview/llviewermenu.cpp index f7688b762f..34a3745222 100644 --- a/indra/newview/llviewermenu.cpp +++ b/indra/newview/llviewermenu.cpp @@ -6516,7 +6516,7 @@ bool handle_zoom_to_object(const LLUUID& object_id) LLViewerObject* object = gObjectList.findObject(object_id); - if (object) + if (object && object->isReachable()) { gAgentCamera.setFocusOnAvatar(false, ANIMATE); diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index 9e77b40a45..ce93e6f371 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7717,6 +7717,51 @@ void LLViewerObject::clearTEWaterExclusion(const U8 te) } } +bool LLViewerObject::isReachable() +{ + LLViewerRegion* agent_region = gAgent.getRegion(); + LLViewerRegion* object_region = getRegion(); + + if (!agent_region || !object_region) + { + return false; + } + if (agent_region == object_region) + { + return true; + } + + std::unordered_set visited; + std::queue pending; + visited.insert(agent_region); + pending.push(agent_region); + + while (!pending.empty()) + { + LLViewerRegion* current = pending.front(); + pending.pop(); + + std::vector neighbors; + current->getNeighboringRegions(neighbors); + + for (LLViewerRegion* neighbor : neighbors) + { + if (!neighbor) continue; + + if (neighbor == object_region) + { + return true; + } + // region's neighbors were not checked + if (visited.insert(neighbor).second) + { + pending.push(neighbor); + } + } + } + return false; +} + class ObjectPhysicsProperties : public LLHTTPNode { public: diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 2b52ea2076..66ed3b8dfa 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -249,6 +249,9 @@ public: // Accessor functions LLViewerRegion* getRegion() const { return mRegionp; } + // Check if object is reachable from agent region by traversing loaded neighboring regions + bool isReachable(); + bool isSelected() const { return mUserSelected; } // Check whole linkset bool isAnySelected() const; -- cgit v1.3 From 69d7c0f7efa648b0016baa98ccbe584cb91203ff Mon Sep 17 00:00:00 2001 From: Cosmic Linden Date: Mon, 11 Nov 2024 10:45:47 -0800 Subject: secondlife/viewer#2570: Fix baked texture shared between avatars when in PBR material --- indra/newview/llfetchedgltfmaterial.cpp | 8 ++++ indra/newview/llfetchedgltfmaterial.h | 1 + indra/newview/llviewerobject.cpp | 85 ++++++++++++++++++++------------- indra/newview/llviewerobject.h | 1 + 4 files changed, 62 insertions(+), 33 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/llfetchedgltfmaterial.cpp b/indra/newview/llfetchedgltfmaterial.cpp index 558fc92018..a05f725673 100644 --- a/indra/newview/llfetchedgltfmaterial.cpp +++ b/indra/newview/llfetchedgltfmaterial.cpp @@ -222,6 +222,14 @@ void LLFetchedGLTFMaterial::updateTextureTracking() } } +void LLFetchedGLTFMaterial::clearFetchedTextures() +{ + mBaseColorTexture = nullptr; + mNormalTexture = nullptr; + mMetallicRoughnessTexture = nullptr; + mEmissiveTexture = nullptr; +} + void LLFetchedGLTFMaterial::materialBegin() { llassert(!mFetching); diff --git a/indra/newview/llfetchedgltfmaterial.h b/indra/newview/llfetchedgltfmaterial.h index 4a33b9f05f..074e3fef41 100644 --- a/indra/newview/llfetchedgltfmaterial.h +++ b/indra/newview/llfetchedgltfmaterial.h @@ -67,6 +67,7 @@ public: LLPointer mNormalTexture; LLPointer mMetallicRoughnessTexture; LLPointer mEmissiveTexture; + void clearFetchedTextures(); std::set mTextureEntires; diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index ce93e6f371..ed4856df11 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -5090,11 +5090,10 @@ void LLViewerObject::setNumTEs(const U8 num_tes) if (base_material && override_material) { tep->setGLTFMaterialOverride(new LLGLTFMaterial(*override_material)); - - LLGLTFMaterial* render_material = new LLFetchedGLTFMaterial(); - *render_material = *base_material; - render_material->applyOverride(*override_material); - tep->setGLTFRenderMaterial(render_material); + } + if (base_material) + { + initRenderMaterial(i); } } } @@ -5270,6 +5269,9 @@ void LLViewerObject::updateTEMaterialTextures(U8 te) }); } getTE(te)->setGLTFMaterial(mat); + initRenderMaterial(te); + mat = (LLFetchedGLTFMaterial*) getTE(te)->getGLTFRenderMaterial(); + llassert(mat == nullptr || dynamic_cast(getTE(te)->getGLTFRenderMaterial()) != nullptr); } else if (mat_id.isNull() && mat != nullptr) { @@ -5659,6 +5661,42 @@ S32 LLViewerObject::setTEMaterialParams(const U8 te, const LLMaterialPtr pMateri return retval; } +// Set render material if there are overrides or if the base material is has a +// baked texture. Otherwise, set it to null. +// If you are setting the material override and not sending an update message, +// you should probably call this function. +S32 LLViewerObject::initRenderMaterial(U8 te) +{ + LL_PROFILE_ZONE_SCOPED; + + LLTextureEntry* tep = getTE(te); + if (!tep) { return 0; } + const LLFetchedGLTFMaterial* base_material = static_cast(tep->getGLTFMaterial()); + llassert(base_material); + if (!base_material) { return 0; } + const LLGLTFMaterial* override_material = tep->getGLTFMaterialOverride(); + LLFetchedGLTFMaterial* render_material = nullptr; + bool need_render_material = override_material; + if (!need_render_material) + { + for (const LLUUID& texture_id : base_material->mTextureId) + { + if (LLAvatarAppearanceDefines::LLAvatarAppearanceDictionary::isBakedImageId(texture_id)) + { + need_render_material = true; + break; + } + } + } + if (need_render_material) + { + render_material = new LLFetchedGLTFMaterial(*base_material); + if (override_material) { render_material->applyOverride(*override_material); } + render_material->clearFetchedTextures(); + } + return tep->setGLTFRenderMaterial(render_material); +} + S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_mat) { LL_PROFILE_ZONE_SCOPED; @@ -5692,22 +5730,13 @@ S32 LLViewerObject::setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* override_ma if (retval) { + retval = initRenderMaterial(te) | retval; if (override_mat) { - LLFetchedGLTFMaterial* render_mat = new LLFetchedGLTFMaterial(*src_mat); - render_mat->applyOverride(*override_mat); - tep->setGLTFRenderMaterial(render_mat); - retval = TEM_CHANGE_TEXTURE; - for (LLGLTFMaterial::local_tex_map_t::value_type &val : override_mat->mTrackingIdToLocalTexture) { LLLocalBitmapMgr::getInstance()->associateGLTFMaterial(val.first, override_mat); } - - } - else if (tep->setGLTFRenderMaterial(nullptr)) - { - retval = TEM_CHANGE_TEXTURE; } } @@ -7577,25 +7606,15 @@ void LLViewerObject::setRenderMaterialID(S32 te_in, const LLUUID& id, bool updat // the overrides have not changed due to being only texture // transforms. Re-apply the overrides to the render material here, // if present. - const LLGLTFMaterial* override_material = tep->getGLTFMaterialOverride(); - if (override_material) + // Also, sometimes, the material has baked textures, which requires + // a copy unique to this object. + // Currently, we do not deduplicate render materials. + new_material->onMaterialComplete([obj_id = getID(), te]() { - new_material->onMaterialComplete([obj_id = getID(), te]() - { - LLViewerObject* obj = gObjectList.findObject(obj_id); - if (!obj) { return; } - LLTextureEntry* tep = obj->getTE(te); - if (!tep) { return; } - const LLGLTFMaterial* new_material = tep->getGLTFMaterial(); - if (!new_material) { return; } - const LLGLTFMaterial* override_material = tep->getGLTFMaterialOverride(); - if (!override_material) { return; } - LLGLTFMaterial* render_material = new LLFetchedGLTFMaterial(); - *render_material = *new_material; - render_material->applyOverride(*override_material); - tep->setGLTFRenderMaterial(render_material); - }); - } + LLViewerObject* obj = gObjectList.findObject(obj_id); + if (!obj) { return; } + obj->initRenderMaterial(te); + }); } } diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index 66ed3b8dfa..a9c2db60e4 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -392,6 +392,7 @@ public: /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); /*virtual*/ S32 setTEMaterialID(const U8 te, const LLMaterialID& pMaterialID); /*virtual*/ S32 setTEMaterialParams(const U8 te, const LLMaterialPtr pMaterialParams); + S32 initRenderMaterial(const U8 te); virtual S32 setTEGLTFMaterialOverride(U8 te, LLGLTFMaterial* mat); // Used by Materials update functions to properly kick off rebuilds -- cgit v1.3 From 4b78edbd1cd62b34f0b3f2b98ab4398437c6bc4d Mon Sep 17 00:00:00 2001 From: Hecklezz Date: Thu, 13 Nov 2025 15:55:28 +1000 Subject: Follow-up null checks on mVObjp to prevent crashes Signed-off-by: Hecklezz --- indra/newview/lldrawable.cpp | 5 +++++ indra/newview/llface.h | 2 +- indra/newview/llviewerobject.cpp | 2 +- indra/newview/llvograss.cpp | 2 +- indra/newview/pipeline.cpp | 4 ++-- 5 files changed, 10 insertions(+), 5 deletions(-) (limited to 'indra/newview/llviewerobject.cpp') diff --git a/indra/newview/lldrawable.cpp b/indra/newview/lldrawable.cpp index 6f8fb34fb3..322ee90541 100644 --- a/indra/newview/lldrawable.cpp +++ b/indra/newview/lldrawable.cpp @@ -954,6 +954,11 @@ void LLDrawable::updateTexture() return; } + if (!mVObjp) + { + return; + } + if (getNumFaces() != mVObjp->getNumTEs()) { //drawable is transitioning its face count return; diff --git a/indra/newview/llface.h b/indra/newview/llface.h index 65637fbf85..db18f6643e 100644 --- a/indra/newview/llface.h +++ b/indra/newview/llface.h @@ -127,7 +127,7 @@ public: void setIndexInTex(U32 ch, S32 index) { llassert(ch < LLRender::NUM_TEXTURE_CHANNELS); mIndexInTex[ch] = index; } void setWorldMatrix(const LLMatrix4& mat); - const LLTextureEntry* getTextureEntry() const { return mVObjp->getTE(mTEOffset); } + const LLTextureEntry* getTextureEntry() const { return mVObjp ? mVObjp->getTE(mTEOffset) : nullptr; } LLFacePool* getPool() const { return mDrawPoolp; } U32 getPoolType() const { return mPoolType; } diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index ed4856df11..59bcad9a26 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -7235,7 +7235,7 @@ void LLAlphaObject::getBlendFunc(S32 face, LLRender::eBlendFactor& src, LLRender void LLStaticViewerObject::updateDrawable(bool force_damped) { // Force an immediate rebuild on any update - if (mDrawable.notNull()) + if (mDrawable.notNull() && mDrawable->getVObj()) { mDrawable->updateXform(true); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); diff --git a/indra/newview/llvograss.cpp b/indra/newview/llvograss.cpp index fdd39a0e30..86d08b8658 100644 --- a/indra/newview/llvograss.cpp +++ b/indra/newview/llvograss.cpp @@ -736,7 +736,7 @@ void LLGrassPartition::getGeometry(LLSpatialGroup* group) void LLVOGrass::updateDrawable(bool force_damped) { // Force an immediate rebuild on any update - if (mDrawable.notNull()) + if (mDrawable.notNull() && mDrawable->getVObj()) { mDrawable->updateXform(true); gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL); diff --git a/indra/newview/pipeline.cpp b/indra/newview/pipeline.cpp index 7f30baa66c..0aa6ffb335 100644 --- a/indra/newview/pipeline.cpp +++ b/indra/newview/pipeline.cpp @@ -2955,7 +2955,7 @@ void LLPipeline::markMoved(LLDrawable *drawablep, bool damped_motion) void LLPipeline::markShift(LLDrawable *drawablep) { - if (!drawablep || drawablep->isDead()) + if (!drawablep || drawablep->isDead() || !drawablep->getVObj()) { return; } @@ -2989,7 +2989,7 @@ void LLPipeline::shiftObjects(const LLVector3 &offset) iter != mShiftList.end(); iter++) { LLDrawable *drawablep = *iter; - if (drawablep->isDead()) + if (drawablep->isDead() || !drawablep->getVObj()) { continue; } -- cgit v1.3