From 03282e3618da2280184b2363f86d45783e22329b Mon Sep 17 00:00:00 2001
From: Rye Mutt <rye@alchemyviewer.org>
Date: Thu, 12 Mar 2020 03:34:16 -0400
Subject: [PATCH] War on dynamic_cast<LLVOVolume> edition!

---
 indra/newview/llcontrolavatar.cpp          |  2 +-
 indra/newview/llfloatertools.cpp           |  4 +-
 indra/newview/llpanelprimmediacontrols.cpp | 15 ++++---
 indra/newview/llselectmgr.cpp              |  6 +--
 indra/newview/llspatialpartition.cpp       |  6 +--
 indra/newview/llviewermessage.cpp          |  2 +-
 indra/newview/llviewerobject.cpp           | 13 +++++-
 indra/newview/llviewerobject.h             |  2 +
 indra/newview/llviewerwindow.cpp           |  3 +-
 indra/newview/llvoavatar.cpp               | 46 +++++++++++-----------
 indra/newview/llvovolume.cpp               | 15 ++++---
 indra/newview/llvovolume.h                 |  1 +
 12 files changed, 68 insertions(+), 47 deletions(-)

diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp
index f57c4495afa..1f4abdd8edd 100644
--- a/indra/newview/llcontrolavatar.cpp
+++ b/indra/newview/llcontrolavatar.cpp
@@ -501,7 +501,7 @@ void LLControlAvatar::getAnimatedVolumes(std::vector<LLVOVolume*>& volumes)
 		 iter != child_list.end(); ++iter)
 	{
 		LLViewerObject* childp = *iter;
-        LLVOVolume *child_volp = dynamic_cast<LLVOVolume*>(childp);
+        LLVOVolume *child_volp = childp ? childp->asVolume() : nullptr;
         if (child_volp && child_volp->isAnimatedObject())
         {
             volumes.push_back(child_volp);
diff --git a/indra/newview/llfloatertools.cpp b/indra/newview/llfloatertools.cpp
index 0429749e11d..96acc5b4249 100644
--- a/indra/newview/llfloatertools.cpp
+++ b/indra/newview/llfloatertools.cpp
@@ -1251,8 +1251,8 @@ void LLFloaterTools::getMediaState()
 		for ( ; iter != end; ++iter)
 		{
 			LLSelectNode* node = *iter;
-			LLVOVolume* object = dynamic_cast<LLVOVolume*>(node->getObject());
-			if (NULL != object)
+			LLVOVolume* object = node ? node->getObject()->asVolume() : nullptr;
+			if (nullptr != object)
 			{
 				if (!object->permModify())
 				{
diff --git a/indra/newview/llpanelprimmediacontrols.cpp b/indra/newview/llpanelprimmediacontrols.cpp
index 6e61584d33f..32fb33f734c 100644
--- a/indra/newview/llpanelprimmediacontrols.cpp
+++ b/indra/newview/llpanelprimmediacontrols.cpp
@@ -319,11 +319,12 @@ void LLPanelPrimMediaControls::updateShape()
 		bool hasPermsControl = true;
 		bool mini_controls = false;
 		LLMediaEntry *media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
-		if (media_data && NULL != dynamic_cast<LLVOVolume*>(objectp))
+        LLVOVolume *vol = objectp ? objectp->asVolume() : nullptr;
+		if (media_data && vol)
 		{
 			// Don't show the media controls if we do not have permissions
-			enabled = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
-			hasPermsControl = dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+			enabled = vol->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
+			hasPermsControl = vol->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL);
 			mini_controls = (LLMediaEntry::MINI == media_data->getControls());
 		}
 		const bool is_hud = objectp->isHUDAttachment();
@@ -805,12 +806,16 @@ void LLPanelPrimMediaControls::draw()
 	// draw control background UI image
 	
 	LLViewerObject* objectp = getTargetObject();
-	LLMediaEntry *media_data(0);
+	LLMediaEntry *media_data = nullptr;
+	LLVOVolume* volumep = nullptr;
 
 	if( objectp )
+	{
 		media_data = objectp->getTE(mTargetObjectFace)->getMediaData();
+		volumep = objectp->asVolume();
+	}
 
-	if( !dynamic_cast<LLVOVolume*>(objectp) || !media_data || dynamic_cast<LLVOVolume*>(objectp)->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL) )
+	if( !volumep || !media_data || volumep->hasMediaPermission(media_data, LLVOVolume::MEDIA_PERM_CONTROL) )
 		mBackgroundImage->draw( controls_bg_area, UI_VERTEX_COLOR % alpha);
 
 	// draw volume slider background UI image
diff --git a/indra/newview/llselectmgr.cpp b/indra/newview/llselectmgr.cpp
index f93a81fb569..dce448cd53d 100644
--- a/indra/newview/llselectmgr.cpp
+++ b/indra/newview/llselectmgr.cpp
@@ -2088,7 +2088,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data)
 					else {
 						// Add/update media
 						object->setTEMediaFlags(te, mMediaFlags);
-						LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+						LLVOVolume *vo = object->asVolume();
 						llassert(NULL != vo);
 						if (NULL != vo) 
 						{
@@ -2114,7 +2114,7 @@ void LLSelectMgr::selectionSetMedia(U8 media_type, const LLSD &media_data)
 			if (object->permModify())
 			{
 				object->sendTEUpdate();
-				LLVOVolume *vo = dynamic_cast<LLVOVolume*>(object);
+				LLVOVolume *vo = object->asVolume();
 				llassert(NULL != vo);
 				// It's okay to skip this object if hasMedia() is false...
 				// the sendTEUpdate() above would remove all media data if it were
@@ -7537,7 +7537,7 @@ S32 LLObjectSelection::getSelectedObjectRenderCost()
 						 ++child_iter)
 				   {
 					   LLViewerObject* child_obj = *child_iter;
-					   LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+					   LLVOVolume *child = child_obj ? child_obj->asVolume() : nullptr;
 					   if (child)
 					   {
 						   cost += child->getRenderCost(textures);
diff --git a/indra/newview/llspatialpartition.cpp b/indra/newview/llspatialpartition.cpp
index d651761f4af..1917a5a3e4f 100644
--- a/indra/newview/llspatialpartition.cpp
+++ b/indra/newview/llspatialpartition.cpp
@@ -2033,7 +2033,7 @@ void renderComplexityDisplay(LLDrawable* drawablep)
 		return;
 	}
 
-	LLVOVolume *voVol = dynamic_cast<LLVOVolume*>(vobj);
+	LLVOVolume *voVol = vobj->asVolume();;
 
 	if (!voVol)
 	{
@@ -2052,8 +2052,8 @@ void renderComplexityDisplay(LLDrawable* drawablep)
 	LLViewerObject::const_child_list_t children = voVol->getChildren();
 	for (LLViewerObject::const_child_list_t::const_iterator iter = children.begin(); iter != children.end(); ++iter)
 	{
-		const LLViewerObject *child = *iter;
-		const LLVOVolume *child_volume = dynamic_cast<const LLVOVolume*>(child);
+		LLViewerObject *child = *iter;
+		LLVOVolume* child_volume = child ? child->asVolume() : nullptr;
 		if (child_volume)
 		{
 			cost += child_volume->getRenderCost(textures);
diff --git a/indra/newview/llviewermessage.cpp b/indra/newview/llviewermessage.cpp
index f86d7b131b0..194fc5a9a76 100644
--- a/indra/newview/llviewermessage.cpp
+++ b/indra/newview/llviewermessage.cpp
@@ -4428,7 +4428,7 @@ void process_object_animation(LLMessageSystem *mesgsys, void **user_data)
         return;
     }
     
-	LLVOVolume *volp = dynamic_cast<LLVOVolume*>(objp);
+	LLVOVolume *volp = objp->asVolume();
     if (!volp)
     {
 		LL_DEBUGS("AnimatedObjectsNotify") << "Received animation state for non-volume object " << uuid << LL_ENDL;
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp
index f1108f9ca5a..336261eb4f0 100644
--- a/indra/newview/llviewerobject.cpp
+++ b/indra/newview/llviewerobject.cpp
@@ -3151,7 +3151,7 @@ void LLViewerObject::linkControlAvatar()
 {
     if (!getControlAvatar() && isRootEdit())
     {
-        LLVOVolume *volp = dynamic_cast<LLVOVolume*>(this);
+        LLVOVolume *volp = asVolume();
         if (!volp)
         {
             LL_WARNS() << "called with null or non-volume object" << LL_ENDL;
@@ -3972,7 +3972,9 @@ F32 LLViewerObject::recursiveGetScaledSurfaceArea() const
                  ++child_iter)
             {
                 LLViewerObject* child_obj = *child_iter;
-                LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+				if(!child_obj) continue;
+
+                LLVOVolume *child = child_obj->asVolume();
                 if (child && child->getVolume())
                 {
                     const LLVector3& scale = child->getScale();
@@ -5692,11 +5694,18 @@ bool LLViewerObject::isOwnerInMuteList(LLUUID id)
 	return muted;
 }
 
+// virtual 
 LLVOAvatar* LLViewerObject::asAvatar()
 {
 	return NULL;
 }
 
+// virtual 
+LLVOVolume* LLViewerObject::asVolume()
+{
+	return nullptr;
+}
+
 // If this object is directly or indirectly parented by an avatar,
 // return it.  Normally getAvatar() is the correct function to call;
 // it will give the avatar used for skinning.  The exception is with
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h
index 809ad995d32..1ded01ee292 100644
--- a/indra/newview/llviewerobject.h
+++ b/indra/newview/llviewerobject.h
@@ -61,6 +61,7 @@ class LLPipeline;
 class LLTextureEntry;
 class LLVOAvatar;
 class LLVOInventoryListener;
+class LLVOVolume;
 class LLViewerInventoryItem;
 class LLViewerObject;
 class LLViewerObjectMedia;
@@ -138,6 +139,7 @@ class LLViewerObject
 	BOOL isParticleSource() const;
 
 	virtual LLVOAvatar* asAvatar();
+	virtual LLVOVolume* asVolume();
 
 	LLVOAvatar* getAvatarAncestor();
 
diff --git a/indra/newview/llviewerwindow.cpp b/indra/newview/llviewerwindow.cpp
index 81ddbcd220e..ff2723b5fe0 100644
--- a/indra/newview/llviewerwindow.cpp
+++ b/indra/newview/llviewerwindow.cpp
@@ -1192,7 +1192,8 @@ LLWindowCallbacks::DragNDropResult LLViewerWindow::handleDragNDrop( LLWindow *wi
 
 					LL_DEBUGS() << "Object: picked at " << pos.mX << ", " << pos.mY << " - face = " << object_face << " - URL = " << url << LL_ENDL;
 
-					LLVOVolume *obj = dynamic_cast<LLVOVolume*>(static_cast<LLViewerObject*>(pick_info.getObject()));
+					LLViewerObject* vobjp = static_cast<LLViewerObject*>(pick_info.getObject());
+					LLVOVolume *obj = vobjp ? vobjp->asVolume() : nullptr;
 				
 					if (obj && !obj->getRegion()->getCapability("ObjectMedia").empty())
 					{
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp
index f20b082d8c7..126e8de893b 100644
--- a/indra/newview/llvoavatar.cpp
+++ b/indra/newview/llvoavatar.cpp
@@ -1382,15 +1382,15 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
 				 ++attachment_iter)
 			{
                     // Don't we need to look at children of attached_object as well?
-                const LLViewerObject* attached_object = attachment_iter->get();
+                LLViewerObject* attached_object = attachment_iter->get();
 				if (attached_object && !attached_object->isHUDAttachment())
 				{
-                        const LLVOVolume *vol = dynamic_cast<const LLVOVolume*>(attached_object);
+                        const LLVOVolume *vol = attached_object->asVolume();
                         if (vol && vol->isAnimatedObject())
                         {
                             // Animated objects already have a bounding box in their control av, use that. 
                             // Could lag by a frame if there's no guarantee on order of processing for avatars.
-                            LLControlAvatar *cav = vol->getControlAvatar();
+                            const LLControlAvatar *cav = vol->getControlAvatar();
                             if (cav)
                             {
                                 LLVector4a cav_min;
@@ -1409,7 +1409,7 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax)
 					LLDrawable* drawable = attached_object->mDrawable;
 					if (drawable && !drawable->isState(LLDrawable::RIGGED))
 					{
-						LLSpatialBridge* bridge = drawable->getSpatialBridge();
+						const LLSpatialBridge* bridge = drawable->getSpatialBridge();
 						if (bridge)
 						{
 							const LLVector4a* ext = bridge->getSpatialExtents();
@@ -6235,7 +6235,7 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL
         }
 	}
 
-	LLVOVolume *vobj = dynamic_cast<LLVOVolume*>(vo);
+	LLVOVolume *vobj = vo->asVolume();
 	bool pelvisGotSet = false;
 
 	if (!vobj)
@@ -7632,12 +7632,12 @@ void LLVOAvatar::rebuildAttachments()
 	{
 		for (LLViewerObject* pAttachObj : kvpAttachPt.second->mAttachedObjects)
 		{
-			if (LLVOVolume* pAttachVol = (pAttachObj->isMesh()) ? dynamic_cast<LLVOVolume*>(pAttachObj) : nullptr)
+			if (LLVOVolume* pAttachVol = (pAttachObj->isMesh()) ? pAttachObj->asVolume() : nullptr)
 			{
 				pAttachVol->forceLOD(3);
 				for (LLViewerObject* pChildObj : pAttachObj->getChildren())
 				{
-					if (LLVOVolume* pChildVol = (pChildObj->isMesh()) ? dynamic_cast<LLVOVolume*>(pChildObj) : nullptr)
+					if (LLVOVolume* pChildVol = (pChildObj->isMesh()) ? pChildObj->asVolume() : nullptr)
 						pAttachVol->forceLOD(3);
 				}
 			}
@@ -9978,11 +9978,12 @@ void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes)
 		LLViewerJointAttachment* attachment = iter->second;
 		LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_end = attachment->mAttachedObjects.end();
 		
-		for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attach_iter = attachment->mAttachedObjects.begin();
-			 attach_iter != attach_end; ++attach_iter)
+		for (LLViewerObject* attached_object : attachment->mAttachedObjects)
 		{
-			LLViewerObject* attached_object =  attach_iter->get();
-            LLVOVolume *volume = dynamic_cast<LLVOVolume*>(attached_object);
+			if (!attached_object)
+				continue;
+
+            LLVOVolume *volume = attached_object->asVolume();
             if (volume)
             {
                 volumes.push_back(volume);
@@ -9995,11 +9996,12 @@ void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes)
                 }
             }
             LLViewerObject::const_child_list_t& children = attached_object->getChildren();
-            for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
-                 it != children.end(); ++it)
+            for (LLViewerObject* childp : children)
             {
-                LLViewerObject *childp = *it;
-                LLVOVolume *volume = dynamic_cast<LLVOVolume*>(childp);
+				if (!childp) 
+					continue;
+
+                LLVOVolume *volume = childp->asVolume();
                 if (volume)
                 {
                     volumes.push_back(volume);
@@ -10016,11 +10018,9 @@ void LLVOAvatar::getAssociatedVolumes(std::vector<LLVOVolume*>& volumes)
         {
             volumes.push_back(volp);
             LLViewerObject::const_child_list_t& children = volp->getChildren();
-            for (LLViewerObject::const_child_list_t::const_iterator it = children.begin();
-                 it != children.end(); ++it)
+            for (LLViewerObject* childp : children)
             {
-                LLViewerObject *childp = *it;
-                LLVOVolume *volume = dynamic_cast<LLVOVolume*>(childp);
+                LLVOVolume *volume = childp ? childp->asVolume() : nullptr;
                 if (volume)
                 {
                     volumes.push_back(volume);
@@ -10345,7 +10345,7 @@ void LLVOAvatar::accountRenderComplexityForObject(
 								  ++child_iter)
 							{
 								LLViewerObject* child_obj = *child_iter;
-								LLVOVolume *child = dynamic_cast<LLVOVolume*>( child_obj );
+								LLVOVolume *child = child_obj ? child_obj->asVolume() : nullptr;
 								if (child)
 								{
 									attachment_children_cost += child->getRenderCost(textures);
@@ -10396,11 +10396,9 @@ void LLVOAvatar::accountRenderComplexityForObject(
                         hud_object_complexity.objectsCount++;
 
                         LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
-                        for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
-                            iter != child_list.end(); ++iter)
+                        for (LLViewerObject* childp : child_list)
                         {
-                            LLViewerObject* childp = *iter;
-                            const LLVOVolume* chld_volume = dynamic_cast<LLVOVolume*>(childp);
+                            const LLVOVolume* chld_volume = childp ? childp->asVolume() : nullptr;
                             if (chld_volume)
                             {
                                 // get cost and individual textures
diff --git a/indra/newview/llvovolume.cpp b/indra/newview/llvovolume.cpp
index a78c248c33e..c30d74f62fa 100644
--- a/indra/newview/llvovolume.cpp
+++ b/indra/newview/llvovolume.cpp
@@ -267,6 +267,11 @@ LLVOVolume::~LLVOVolume()
 	}
 }
 
+LLVOVolume* LLVOVolume::asVolume()
+{
+	return this;
+}
+
 void LLVOVolume::markDead()
 {
 	if (!mDead)
@@ -1324,7 +1329,7 @@ std::string get_debug_object_lod_text(LLVOVolume *rootp)
          iter != child_list.end(); ++iter)
     {
         LLViewerObject *childp = *iter;
-        LLVOVolume *volp = dynamic_cast<LLVOVolume*>(childp);
+        LLVOVolume *volp = childp ? childp->asVolume() : nullptr;
         if (volp)
         {
             lod_string += llformat("%d",volp->getLOD());
@@ -3674,8 +3679,6 @@ bool LLVOVolume::isAnimatedObject() const
 // virtual
 void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_parent)
 {
-    LLVOVolume *old_volp = dynamic_cast<LLVOVolume*>(old_parent);
-
     if (new_parent && !new_parent->isAvatar())
     {
         if (mControlAvatar.notNull())
@@ -3687,7 +3690,9 @@ void LLVOVolume::onReparent(LLViewerObject *old_parent, LLViewerObject *new_pare
             av->markForDeath();
         }
     }
-    if (old_volp && old_volp->isAnimatedObject())
+
+	LLVOVolume *old_volp = old_parent ? old_parent->asVolume() : nullptr;
+	if (old_volp && old_volp->isAnimatedObject())
     {
         if (old_volp->getControlAvatar())
         {
@@ -5442,7 +5447,7 @@ void LLVolumeGeometryManager::rebuildGeom(LLSpatialGroup* group)
 	if (bridge)
 	{
         vobj = bridge->mDrawable->getVObj();
-        vol_obj = dynamic_cast<LLVOVolume*>(vobj);
+        vol_obj = vobj ? vobj->asVolume() : nullptr;
 	}
     if (vol_obj)
     {
diff --git a/indra/newview/llvovolume.h b/indra/newview/llvovolume.h
index d9f40de9449..e42a0081628 100644
--- a/indra/newview/llvovolume.h
+++ b/indra/newview/llvovolume.h
@@ -115,6 +115,7 @@ class LLVOVolume : public LLViewerObject
 
 public:
 						LLVOVolume(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp);
+				LLVOVolume* asVolume();
 	/*virtual*/ void markDead();		// Override (and call through to parent) to clean up media references
 
 	/*virtual*/ LLDrawable* createDrawable(LLPipeline *pipeline);
-- 
GitLab