From 60d3dd98a44230c21803c1606552ee098ed9fa7c Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 21 Feb 2024 21:05:14 +0100 Subject: Convert remaining BOOL to bool --- indra/newview/llcontrolavatar.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'indra/newview/llcontrolavatar.cpp') diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 7def9c045f..873c683b38 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -51,7 +51,7 @@ LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewer mScaleConstraintFixup(1.0), mRegionChanged(false) { - mIsDummy = TRUE; + mIsDummy = true; mIsControlAvatar = true; mEnableDefaultMotions = false; } @@ -295,7 +295,7 @@ void LLControlAvatar::updateVolumeGeom() return; if (mRootVolp->mDrawable->isActive()) { - mRootVolp->mDrawable->makeStatic(FALSE); + mRootVolp->mDrawable->makeStatic(false); } mRootVolp->mDrawable->makeActive(); gPipeline.markMoved(mRootVolp->mDrawable); @@ -615,9 +615,9 @@ void LLControlAvatar::updateAnimations() // virtual LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, S32 face, - BOOL pick_transparent, - BOOL pick_rigged, - BOOL pick_unselectable, + bool pick_transparent, + bool pick_rigged, + bool pick_unselectable, S32* face_hit, LLVector4a* intersection, LLVector2* tex_coord, @@ -694,7 +694,7 @@ bool LLControlAvatar::shouldRenderRigged() const } // virtual -BOOL LLControlAvatar::isImpostor() +bool LLControlAvatar::isImpostor() { // Attached animated objects should match state of their attached av. LLVOAvatar *attached_av = getAttachedAvatar(); -- cgit v1.2.3 From e2e37cced861b98de8c1a7c9c0d3a50d2d90e433 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Wed, 22 May 2024 21:25:21 +0200 Subject: Fix line endlings --- indra/newview/llcontrolavatar.cpp | 1438 ++++++++++++++++++------------------- 1 file changed, 719 insertions(+), 719 deletions(-) (limited to 'indra/newview/llcontrolavatar.cpp') diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index 909e0f9e95..bb853a3ddc 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -1,719 +1,719 @@ -/** - * @file llcontrolavatar.cpp - * @brief Implementation for special dummy avatar used to drive rigged meshes. - * - * $LicenseInfo:firstyear=2017&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2017, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llcontrolavatar.h" -#include "llagent.h" // Get state values from here -#include "llviewerobjectlist.h" -#include "pipeline.h" -#include "llanimationstates.h" -#include "llviewercontrol.h" -#include "llmeshrepository.h" -#include "llviewerregion.h" -#include "llskinningutil.h" - -const F32 LLControlAvatar::MAX_LEGAL_OFFSET = 3.0f; -const F32 LLControlAvatar::MAX_LEGAL_SIZE = 64.0f; - -//static -boost::signals2::connection LLControlAvatar::sRegionChangedSlot; - -LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : - LLVOAvatar(id, pcode, regionp), - mPlaying(false), - mGlobalScale(1.0f), - mMarkedForDeath(false), - mRootVolp(NULL), - mControlAVBridge(NULL), - mScaleConstraintFixup(1.0), - mRegionChanged(false) -{ - mIsDummy = true; - mIsControlAvatar = true; - mEnableDefaultMotions = false; -} - -// virtual -LLControlAvatar::~LLControlAvatar() -{ - // Should already have been unlinked before destruction - llassert(!mRootVolp); -} - -// virtual -void LLControlAvatar::initInstance() -{ - // Potential optimizations here: avoid creating system - // avatar mesh content since it's not used. For now we just clean some - // things up after the fact in releaseMeshData(). - LLVOAvatar::initInstance(); - - createDrawable(&gPipeline); - updateJointLODs(); - updateGeometry(mDrawable); - hideSkirt(); - - mInitFlags |= 1<<4; -} - -const LLVOAvatar *LLControlAvatar::getAttachedAvatar() const -{ - if (mRootVolp && mRootVolp->isAttachment()) - { - return mRootVolp->getAvatarAncestor(); - } - return NULL; -} - -LLVOAvatar *LLControlAvatar::getAttachedAvatar() -{ - if (mRootVolp && mRootVolp->isAttachment()) - { - return mRootVolp->getAvatarAncestor(); - } - return NULL; -} - -void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const -{ - F32 max_legal_offset = MAX_LEGAL_OFFSET; - if (gSavedSettings.getControl("AnimatedObjectsMaxLegalOffset")) - { - max_legal_offset = gSavedSettings.getF32("AnimatedObjectsMaxLegalOffset"); - } - max_legal_offset = llmax(max_legal_offset,0.f); - - F32 max_legal_size = MAX_LEGAL_SIZE; - if (gSavedSettings.getControl("AnimatedObjectsMaxLegalSize")) - { - max_legal_size = gSavedSettings.getF32("AnimatedObjectsMaxLegalSize"); - } - max_legal_size = llmax(max_legal_size, 1.f); - - new_pos_fixup = LLVector3(); - new_scale_fixup = 1.0f; - LLVector3 vol_pos = mRootVolp->getRenderPosition(); - - // Fix up position if needed to prevent visual encroachment - if (box_valid_and_non_zero(getLastAnimExtents())) // wait for state to settle down - { - // The goal here is to ensure that the extent of the avatar's - // bounding box does not wander too far from the - // official position of the corresponding volume. We - // do this by tracking the distance and applying a - // correction to the control avatar position if - // needed. - const LLVector3 *extents = getLastAnimExtents(); - LLVector3 unshift_extents[2]; - unshift_extents[0] = extents[0] - mPositionConstraintFixup; - unshift_extents[1] = extents[1] - mPositionConstraintFixup; - LLVector3 box_dims = extents[1]-extents[0]; - F32 box_size = llmax(box_dims[0],box_dims[1],box_dims[2]); - - if (!mRootVolp->isAttachment()) - { - LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents); - F32 offset_dist = pos_box_offset.length(); - if (offset_dist > MAX_LEGAL_OFFSET && offset_dist > 0.f) - { - F32 target_dist = (offset_dist - MAX_LEGAL_OFFSET); - new_pos_fixup = (target_dist/offset_dist)*pos_box_offset; - } - if (new_pos_fixup != mPositionConstraintFixup) - { - LL_DEBUGS("ConstraintFix") << getFullname() << " pos fix, offset_dist " << offset_dist << " pos fixup " - << new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL; - LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL; - LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL; - LL_DEBUGS("ConstraintFix") << "unshift_extents " << unshift_extents[0] << " " << unshift_extents[1] << LL_ENDL; - - } - } - if (box_size/mScaleConstraintFixup > MAX_LEGAL_SIZE) - { - new_scale_fixup = mScaleConstraintFixup* MAX_LEGAL_SIZE /box_size; - LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup " - << mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE - << " -> new scale " << new_scale_fixup << LL_ENDL; - } - } -} - -void LLControlAvatar::matchVolumeTransform() -{ - if (mRootVolp) - { - LLVector3 new_pos_fixup; - F32 new_scale_fixup; - if (mRegionChanged) - { - new_scale_fixup = mScaleConstraintFixup; - new_pos_fixup = mPositionConstraintFixup; - mRegionChanged = false; - } - else - { - getNewConstraintFixups(new_pos_fixup, new_scale_fixup); - } - mPositionConstraintFixup = new_pos_fixup; - mScaleConstraintFixup = new_scale_fixup; - - if (mRootVolp->isAttachment()) - { - LLVOAvatar *attached_av = getAttachedAvatar(); - if (attached_av) - { - LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp); - if (getRegion() && !isDead()) - { - setPositionAgent(mRootVolp->getRenderPosition()); - } - attach->updateWorldPRSParent(); - LLVector3 joint_pos = attach->getWorldPosition(); - LLQuaternion joint_rot = attach->getWorldRotation(); - LLVector3 obj_pos = mRootVolp->mDrawable->getPosition(); - LLQuaternion obj_rot = mRootVolp->mDrawable->getRotation(); - obj_pos.rotVec(joint_rot); - mRoot->setWorldPosition(obj_pos + joint_pos); - mRoot->setWorldRotation(obj_rot * joint_rot); - setRotation(mRoot->getRotation()); - - setGlobalScale(mScaleConstraintFixup); - } - else - { - LL_WARNS_ONCE() << "can't find attached av!" << LL_ENDL; - } - } - else - { - LLVector3 vol_pos = mRootVolp->getRenderPosition(); - - // FIXME: Currently if you're doing something like playing an - // animation that moves the pelvis (on an avatar or - // animated object), the name tag and debug text will be - // left behind. Ideally setPosition() would follow the - // skeleton around in a smarter way, so name tags, - // complexity info and such line up better. Should defer - // this until avatars also get fixed. - - LLQuaternion obj_rot; - if (mRootVolp->mDrawable) - { - obj_rot = mRootVolp->mDrawable->getRotation(); - } - else - { - obj_rot = mRootVolp->getRotation(); - } - - LLMatrix3 bind_mat; - - LLQuaternion bind_rot; -#define MATCH_BIND_SHAPE -#ifdef MATCH_BIND_SHAPE - // MAINT-8671 - based on a patch from Beq Janus - const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo(); - if (skin_info) - { - LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL; - bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(skin_info->mBindShapeMatrix)); - } -#endif - setRotation(bind_rot*obj_rot); - mRoot->setWorldRotation(bind_rot*obj_rot); - if (getRegion() && !isDead()) - { - setPositionAgent(vol_pos); - } - mRoot->setPosition(vol_pos + mPositionConstraintFixup); - - setGlobalScale(mScaleConstraintFixup); - } - } -} - -void LLControlAvatar::setGlobalScale(F32 scale) -{ - if (scale <= 0.0) - { - LL_WARNS() << "invalid global scale " << scale << LL_ENDL; - return; - } - if (scale != mGlobalScale) - { - F32 adjust_scale = scale/mGlobalScale; - LL_INFOS() << "scale " << scale << " adjustment " << adjust_scale << LL_ENDL; - // should we be scaling from the pelvis or the root? - recursiveScaleJoint(mPelvisp,adjust_scale); - mGlobalScale = scale; - } -} - -void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor) -{ - joint->setScale(factor * joint->getScale()); - - for (LLJoint::joints_t::iterator iter = joint->mChildren.begin(); - iter != joint->mChildren.end(); ++iter) - { - LLJoint* child = *iter; - recursiveScaleJoint(child, factor); - } -} - -// Based on LLViewerJointAttachment::setupDrawable(), without the attaching part. -void LLControlAvatar::updateVolumeGeom() -{ - if (!mRootVolp->mDrawable) - return; - if (mRootVolp->mDrawable->isActive()) - { - mRootVolp->mDrawable->makeStatic(false); - } - mRootVolp->mDrawable->makeActive(); - gPipeline.markMoved(mRootVolp->mDrawable); - gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD - - LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* childp = *iter; - if (childp && childp->mDrawable.notNull()) - { - gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD - gPipeline.markMoved(childp->mDrawable); - } - } - - gPipeline.markRebuild(mRootVolp->mDrawable, LLDrawable::REBUILD_ALL); - mRootVolp->markForUpdate(); - - // Note that attachment overrides aren't needed here, have already - // been applied at the time the mControlAvatar was created, in - // llvovolume.cpp. - - matchVolumeTransform(); - - // Initial exploration of allowing scaling skeleton to match root - // prim bounding box. If enabled, would probably be controlled by - // an additional checkbox and default to off. Not enabled for - // initial release. - - // What should the scale be? What we really want is the ratio - // between the scale at which the object was originally designed - // and rigged, and the scale to which it has been subsequently - // modified - for example, if the object has been scaled down by a - // factor of 2 then we should use 0.5 as the global scale. But we - // don't have the original scale stored anywhere, just the current - // scale. Possibilities - 1) remember the original scale - // somewhere, 2) add another field to let the user specify the - // global scale, 3) approximate the original scale by looking at - // the proportions of the skeleton after joint positions have - // been applied - - //LLVector3 obj_scale = obj->getScale(); - //F32 obj_scale_z = llmax(obj_scale[2],0.1f); - //setGlobalScale(obj_scale_z/2.0f); // roughly fit avatar height range (2m) into object height -} - -LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj) -{ - LLControlAvatar *cav = (LLControlAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), CO_FLAG_CONTROL_AVATAR); - - if (cav) - { - cav->mRootVolp = obj; - - // Sync up position/rotation with object - cav->matchVolumeTransform(); - } - - return cav; -} - -void LLControlAvatar::markForDeath() -{ - mMarkedForDeath = true; - // object unlinked cav and might be dead already - // might need to clean mControlAVBridge here as well - mRootVolp = NULL; -} - -void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time) -{ - if (mMarkedForDeath) - { - markDead(); - mMarkedForDeath = false; - } - else - { - LLVOAvatar::idleUpdate(agent,time); - } -} - -void LLControlAvatar::markDead() -{ - mRootVolp = NULL; - super::markDead(); - mControlAVBridge = NULL; -} - -bool LLControlAvatar::computeNeedsUpdate() -{ - computeUpdatePeriod(); - - // Animesh attachments are a special case. Should have the same update cadence as their attached parent avatar. - LLVOAvatar *attached_av = getAttachedAvatar(); - if (attached_av) - { - // Have to run computeNeedsUpdate() for attached av in - // case it hasn't run updateCharacter() already this - // frame. Note this means that the attached av will - // run computeNeedsUpdate() multiple times per frame - // if it has animesh attachments. Results will be - // consistent except for the corner case of exceeding - // MAX_IMPOSTOR_INTERVAL in one call but not another, - // which should be rare. - attached_av->computeNeedsUpdate(); - mNeedsImpostorUpdate = attached_av->mNeedsImpostorUpdate; - if (mNeedsImpostorUpdate) - { - mLastImpostorUpdateReason = 12; - } - return mNeedsImpostorUpdate; - } - return LLVOAvatar::computeNeedsUpdate(); -} - -bool LLControlAvatar::updateCharacter(LLAgent &agent) -{ - return LLVOAvatar::updateCharacter(agent); -} - -//virtual -void LLControlAvatar::updateDebugText() -{ - if (gSavedSettings.getBOOL("DebugAnimatedObjects")) - { - S32 total_linkset_count = 0; - if (mRootVolp) - { - total_linkset_count = 1 + mRootVolp->getChildren().size(); - } - std::vector volumes; - getAnimatedVolumes(volumes); - S32 animated_volume_count = volumes.size(); - std::string active_string; - std::string type_string; - std::string lod_string; - std::string animated_object_flag_string; - S32 total_tris = 0; - S32 total_verts = 0; - F32 est_tris = 0.f; - F32 est_streaming_tris = 0.f; - F32 streaming_cost = 0.f; - std::string cam_dist_string = ""; - S32 cam_dist_count = 0; - F32 lod_radius = mRootVolp ? mRootVolp->mLODRadius : 0.f; - - for (std::vector::iterator it = volumes.begin(); - it != volumes.end(); ++it) - { - LLVOVolume *volp = *it; - S32 verts = 0; - total_tris += volp->getTriangleCount(&verts); - total_verts += verts; - est_tris += volp->getEstTrianglesMax(); - est_streaming_tris += volp->getEstTrianglesStreamingCost(); - streaming_cost += volp->getStreamingCost(); - lod_string += llformat("%d",volp->getLOD()); - if (volp && volp->mDrawable) - { - bool is_animated_flag = volp->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; - if (is_animated_flag) - { - animated_object_flag_string += "1"; - } - else - { - animated_object_flag_string += "0"; - } - if (volp->mDrawable->isActive()) - { - active_string += "A"; - } - else - { - active_string += "S"; - } - if (volp->isRiggedMesh()) - { - // Rigged/animatable mesh - type_string += "R"; - lod_radius = volp->mLODRadius; - } - else if (volp->isMesh()) - { - // Static mesh - type_string += "M"; - } - else - { - // Any other prim - type_string += "P"; - } - if (cam_dist_count < 4) - { - cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + "/" + - LLStringOps::getReadableNumber(volp->mLODAdjustedDistance) + " "; - cam_dist_count++; - } - } - else - { - active_string += "-"; - type_string += "-"; - } - } - addDebugText(llformat("CAV obj %d anim %d active %s impost %d upprd %d strcst %f", - total_linkset_count, animated_volume_count, - active_string.c_str(), (S32) isImpostor(), getUpdatePeriod(), streaming_cost)); - addDebugText(llformat("types %s lods %s", type_string.c_str(), lod_string.c_str())); - addDebugText(llformat("flags %s", animated_object_flag_string.c_str())); - addDebugText(llformat("tris %d (est %.1f, streaming %.1f), verts %d", total_tris, est_tris, est_streaming_tris, total_verts)); - addDebugText(llformat("pxarea %s rank %d", LLStringOps::getReadableNumber(getPixelArea()).c_str(), getVisibilityRank())); - addDebugText(llformat("lod_radius %s dists %s", LLStringOps::getReadableNumber(lod_radius).c_str(),cam_dist_string.c_str())); - if (mPositionConstraintFixup.length() > 0.0f || mScaleConstraintFixup != 1.0f) - { - addDebugText(llformat("pos fix (%.1f %.1f %.1f) scale %f", - mPositionConstraintFixup[0], - mPositionConstraintFixup[1], - mPositionConstraintFixup[2], - mScaleConstraintFixup)); - } - -#if 0 - std::string region_name = "no region"; - if (mRootVolp->getRegion()) - { - region_name = mRootVolp->getRegion()->getName(); - } - std::string skel_region_name = "skel no region"; - if (getRegion()) - { - skel_region_name = getRegion()->getName(); - } - addDebugText(llformat("region %x %s skel %x %s", - mRootVolp->getRegion(), region_name.c_str(), - getRegion(), skel_region_name.c_str())); -#endif - - } - LLVOAvatar::updateDebugText(); -} - -void LLControlAvatar::getAnimatedVolumes(std::vector& volumes) -{ - if (!mRootVolp) - { - return; - } - - volumes.push_back(mRootVolp); - - LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); - for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); - iter != child_list.end(); ++iter) - { - LLViewerObject* childp = *iter; - LLVOVolume *child_volp = dynamic_cast(childp); - if (child_volp && child_volp->isAnimatedObject()) - { - volumes.push_back(child_volp); - } - } -} - -// This is called after an associated object receives an animation -// message. Combine the signaled animations for all associated objects -// and process any resulting state changes. -void LLControlAvatar::updateAnimations() -{ - if (!mRootVolp) - { - LL_WARNS_ONCE("AnimatedObjectsNotify") << "No root vol" << LL_ENDL; - return; - } - - std::vector volumes; - getAnimatedVolumes(volumes); - - // Rebuild mSignaledAnimations from the associated volumes. - std::map anims; - for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) - { - LLVOVolume *volp = *vol_it; - //LL_INFOS("AnimatedObjects") << "updating anim for vol " << volp->getID() << " root " << mRootVolp->getID() << LL_ENDL; - signaled_animation_map_t& signaled_animations = LLObjectSignaledAnimationMap::instance().getMap()[volp->getID()]; - for (std::map::iterator anim_it = signaled_animations.begin(); - anim_it != signaled_animations.end(); - ++anim_it) - { - std::map::iterator found_anim_it = anims.find(anim_it->first); - if (found_anim_it != anims.end()) - { - // Animation already present, use the larger sequence id - anims[anim_it->first] = llmax(found_anim_it->second, anim_it->second); - } - else - { - // Animation not already present, use this sequence id. - anims[anim_it->first] = anim_it->second; - } - LL_DEBUGS("AnimatedObjectsNotify") << "found anim for vol " << volp->getID() << " anim " << anim_it->first << " root " << mRootVolp->getID() << LL_ENDL; - } - } - if (!mPlaying) - { - mPlaying = true; - //if (!mRootVolp->isAnySelected()) - { - updateVolumeGeom(); - mRootVolp->recursiveMarkForUpdate(); - } - } - - mSignaledAnimations = anims; - processAnimationStateChanges(); -} - -// virtual -LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, - S32 face, - bool pick_transparent, - bool pick_rigged, - bool pick_unselectable, - S32* face_hit, - LLVector4a* intersection, - LLVector2* tex_coord, - LLVector4a* normal, - LLVector4a* tangent) -{ - if (!mRootVolp) - { - return NULL; - } - - LLViewerObject* hit = NULL; - - if (lineSegmentBoundingBox(start, end)) - { - LLVector4a local_end = end; - LLVector4a local_intersection; - if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) - { - local_end = local_intersection; - if (intersection) - { - *intersection = local_intersection; - } - hit = mRootVolp; - } - else - { - std::vector volumes; - getAnimatedVolumes(volumes); - - for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) - { - LLVOVolume *volp = *vol_it; - if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) - { - local_end = local_intersection; - if (intersection) - { - *intersection = local_intersection; - } - hit = volp; - break; - } - } - } - } - - return hit; -} - -// virtual -std::string LLControlAvatar::getFullname() const -{ - if (mRootVolp) - { - return "AO_" + mRootVolp->getID().getString(); - } - else - { - return "AO_no_root_vol"; - } -} - -// virtual -bool LLControlAvatar::shouldRenderRigged() const -{ - const LLVOAvatar *attached_av = getAttachedAvatar(); - if (attached_av) - { - return attached_av->shouldRenderRigged(); - } - return true; -} - -// virtual -bool LLControlAvatar::isImpostor() -{ - // Attached animated objects should match state of their attached av. - LLVOAvatar *attached_av = getAttachedAvatar(); - if (attached_av) - { - return attached_av->isImpostor(); - } - return LLVOAvatar::isImpostor(); -} - -//static -void LLControlAvatar::onRegionChanged() -{ - std::vector::iterator it = LLCharacter::sInstances.begin(); - for ( ; it != LLCharacter::sInstances.end(); ++it) - { - LLControlAvatar* cav = dynamic_cast(*it); - if (!cav) continue; - cav->mRegionChanged = true; - } -} +/** + * @file llcontrolavatar.cpp + * @brief Implementation for special dummy avatar used to drive rigged meshes. + * + * $LicenseInfo:firstyear=2017&license=viewerlgpl$ + * Second Life Viewer Source Code + * Copyright (C) 2017, Linden Research, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; + * version 2.1 of the License only. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA + * $/LicenseInfo$ + */ + +#include "llviewerprecompiledheaders.h" +#include "llcontrolavatar.h" +#include "llagent.h" // Get state values from here +#include "llviewerobjectlist.h" +#include "pipeline.h" +#include "llanimationstates.h" +#include "llviewercontrol.h" +#include "llmeshrepository.h" +#include "llviewerregion.h" +#include "llskinningutil.h" + +const F32 LLControlAvatar::MAX_LEGAL_OFFSET = 3.0f; +const F32 LLControlAvatar::MAX_LEGAL_SIZE = 64.0f; + +//static +boost::signals2::connection LLControlAvatar::sRegionChangedSlot; + +LLControlAvatar::LLControlAvatar(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp) : + LLVOAvatar(id, pcode, regionp), + mPlaying(false), + mGlobalScale(1.0f), + mMarkedForDeath(false), + mRootVolp(NULL), + mControlAVBridge(NULL), + mScaleConstraintFixup(1.0), + mRegionChanged(false) +{ + mIsDummy = true; + mIsControlAvatar = true; + mEnableDefaultMotions = false; +} + +// virtual +LLControlAvatar::~LLControlAvatar() +{ + // Should already have been unlinked before destruction + llassert(!mRootVolp); +} + +// virtual +void LLControlAvatar::initInstance() +{ + // Potential optimizations here: avoid creating system + // avatar mesh content since it's not used. For now we just clean some + // things up after the fact in releaseMeshData(). + LLVOAvatar::initInstance(); + + createDrawable(&gPipeline); + updateJointLODs(); + updateGeometry(mDrawable); + hideSkirt(); + + mInitFlags |= 1<<4; +} + +const LLVOAvatar *LLControlAvatar::getAttachedAvatar() const +{ + if (mRootVolp && mRootVolp->isAttachment()) + { + return mRootVolp->getAvatarAncestor(); + } + return NULL; +} + +LLVOAvatar *LLControlAvatar::getAttachedAvatar() +{ + if (mRootVolp && mRootVolp->isAttachment()) + { + return mRootVolp->getAvatarAncestor(); + } + return NULL; +} + +void LLControlAvatar::getNewConstraintFixups(LLVector3& new_pos_fixup, F32& new_scale_fixup) const +{ + F32 max_legal_offset = MAX_LEGAL_OFFSET; + if (gSavedSettings.getControl("AnimatedObjectsMaxLegalOffset")) + { + max_legal_offset = gSavedSettings.getF32("AnimatedObjectsMaxLegalOffset"); + } + max_legal_offset = llmax(max_legal_offset,0.f); + + F32 max_legal_size = MAX_LEGAL_SIZE; + if (gSavedSettings.getControl("AnimatedObjectsMaxLegalSize")) + { + max_legal_size = gSavedSettings.getF32("AnimatedObjectsMaxLegalSize"); + } + max_legal_size = llmax(max_legal_size, 1.f); + + new_pos_fixup = LLVector3(); + new_scale_fixup = 1.0f; + LLVector3 vol_pos = mRootVolp->getRenderPosition(); + + // Fix up position if needed to prevent visual encroachment + if (box_valid_and_non_zero(getLastAnimExtents())) // wait for state to settle down + { + // The goal here is to ensure that the extent of the avatar's + // bounding box does not wander too far from the + // official position of the corresponding volume. We + // do this by tracking the distance and applying a + // correction to the control avatar position if + // needed. + const LLVector3 *extents = getLastAnimExtents(); + LLVector3 unshift_extents[2]; + unshift_extents[0] = extents[0] - mPositionConstraintFixup; + unshift_extents[1] = extents[1] - mPositionConstraintFixup; + LLVector3 box_dims = extents[1]-extents[0]; + F32 box_size = llmax(box_dims[0],box_dims[1],box_dims[2]); + + if (!mRootVolp->isAttachment()) + { + LLVector3 pos_box_offset = point_to_box_offset(vol_pos, unshift_extents); + F32 offset_dist = pos_box_offset.length(); + if (offset_dist > MAX_LEGAL_OFFSET && offset_dist > 0.f) + { + F32 target_dist = (offset_dist - MAX_LEGAL_OFFSET); + new_pos_fixup = (target_dist/offset_dist)*pos_box_offset; + } + if (new_pos_fixup != mPositionConstraintFixup) + { + LL_DEBUGS("ConstraintFix") << getFullname() << " pos fix, offset_dist " << offset_dist << " pos fixup " + << new_pos_fixup << " was " << mPositionConstraintFixup << LL_ENDL; + LL_DEBUGS("ConstraintFix") << "vol_pos " << vol_pos << LL_ENDL; + LL_DEBUGS("ConstraintFix") << "extents " << extents[0] << " " << extents[1] << LL_ENDL; + LL_DEBUGS("ConstraintFix") << "unshift_extents " << unshift_extents[0] << " " << unshift_extents[1] << LL_ENDL; + + } + } + if (box_size/mScaleConstraintFixup > MAX_LEGAL_SIZE) + { + new_scale_fixup = mScaleConstraintFixup* MAX_LEGAL_SIZE /box_size; + LL_DEBUGS("ConstraintFix") << getFullname() << " scale fix, box_size " << box_size << " fixup " + << mScaleConstraintFixup << " max legal " << MAX_LEGAL_SIZE + << " -> new scale " << new_scale_fixup << LL_ENDL; + } + } +} + +void LLControlAvatar::matchVolumeTransform() +{ + if (mRootVolp) + { + LLVector3 new_pos_fixup; + F32 new_scale_fixup; + if (mRegionChanged) + { + new_scale_fixup = mScaleConstraintFixup; + new_pos_fixup = mPositionConstraintFixup; + mRegionChanged = false; + } + else + { + getNewConstraintFixups(new_pos_fixup, new_scale_fixup); + } + mPositionConstraintFixup = new_pos_fixup; + mScaleConstraintFixup = new_scale_fixup; + + if (mRootVolp->isAttachment()) + { + LLVOAvatar *attached_av = getAttachedAvatar(); + if (attached_av) + { + LLViewerJointAttachment *attach = attached_av->getTargetAttachmentPoint(mRootVolp); + if (getRegion() && !isDead()) + { + setPositionAgent(mRootVolp->getRenderPosition()); + } + attach->updateWorldPRSParent(); + LLVector3 joint_pos = attach->getWorldPosition(); + LLQuaternion joint_rot = attach->getWorldRotation(); + LLVector3 obj_pos = mRootVolp->mDrawable->getPosition(); + LLQuaternion obj_rot = mRootVolp->mDrawable->getRotation(); + obj_pos.rotVec(joint_rot); + mRoot->setWorldPosition(obj_pos + joint_pos); + mRoot->setWorldRotation(obj_rot * joint_rot); + setRotation(mRoot->getRotation()); + + setGlobalScale(mScaleConstraintFixup); + } + else + { + LL_WARNS_ONCE() << "can't find attached av!" << LL_ENDL; + } + } + else + { + LLVector3 vol_pos = mRootVolp->getRenderPosition(); + + // FIXME: Currently if you're doing something like playing an + // animation that moves the pelvis (on an avatar or + // animated object), the name tag and debug text will be + // left behind. Ideally setPosition() would follow the + // skeleton around in a smarter way, so name tags, + // complexity info and such line up better. Should defer + // this until avatars also get fixed. + + LLQuaternion obj_rot; + if (mRootVolp->mDrawable) + { + obj_rot = mRootVolp->mDrawable->getRotation(); + } + else + { + obj_rot = mRootVolp->getRotation(); + } + + LLMatrix3 bind_mat; + + LLQuaternion bind_rot; +#define MATCH_BIND_SHAPE +#ifdef MATCH_BIND_SHAPE + // MAINT-8671 - based on a patch from Beq Janus + const LLMeshSkinInfo* skin_info = mRootVolp->getSkinInfo(); + if (skin_info) + { + LL_DEBUGS("BindShape") << getFullname() << " bind shape " << skin_info->mBindShapeMatrix << LL_ENDL; + bind_rot = LLSkinningUtil::getUnscaledQuaternion(LLMatrix4(skin_info->mBindShapeMatrix)); + } +#endif + setRotation(bind_rot*obj_rot); + mRoot->setWorldRotation(bind_rot*obj_rot); + if (getRegion() && !isDead()) + { + setPositionAgent(vol_pos); + } + mRoot->setPosition(vol_pos + mPositionConstraintFixup); + + setGlobalScale(mScaleConstraintFixup); + } + } +} + +void LLControlAvatar::setGlobalScale(F32 scale) +{ + if (scale <= 0.0) + { + LL_WARNS() << "invalid global scale " << scale << LL_ENDL; + return; + } + if (scale != mGlobalScale) + { + F32 adjust_scale = scale/mGlobalScale; + LL_INFOS() << "scale " << scale << " adjustment " << adjust_scale << LL_ENDL; + // should we be scaling from the pelvis or the root? + recursiveScaleJoint(mPelvisp,adjust_scale); + mGlobalScale = scale; + } +} + +void LLControlAvatar::recursiveScaleJoint(LLJoint* joint, F32 factor) +{ + joint->setScale(factor * joint->getScale()); + + for (LLJoint::joints_t::iterator iter = joint->mChildren.begin(); + iter != joint->mChildren.end(); ++iter) + { + LLJoint* child = *iter; + recursiveScaleJoint(child, factor); + } +} + +// Based on LLViewerJointAttachment::setupDrawable(), without the attaching part. +void LLControlAvatar::updateVolumeGeom() +{ + if (!mRootVolp->mDrawable) + return; + if (mRootVolp->mDrawable->isActive()) + { + mRootVolp->mDrawable->makeStatic(false); + } + mRootVolp->mDrawable->makeActive(); + gPipeline.markMoved(mRootVolp->mDrawable); + gPipeline.markTextured(mRootVolp->mDrawable); // face may need to change draw pool to/from POOL_HUD + + LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* childp = *iter; + if (childp && childp->mDrawable.notNull()) + { + gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD + gPipeline.markMoved(childp->mDrawable); + } + } + + gPipeline.markRebuild(mRootVolp->mDrawable, LLDrawable::REBUILD_ALL); + mRootVolp->markForUpdate(); + + // Note that attachment overrides aren't needed here, have already + // been applied at the time the mControlAvatar was created, in + // llvovolume.cpp. + + matchVolumeTransform(); + + // Initial exploration of allowing scaling skeleton to match root + // prim bounding box. If enabled, would probably be controlled by + // an additional checkbox and default to off. Not enabled for + // initial release. + + // What should the scale be? What we really want is the ratio + // between the scale at which the object was originally designed + // and rigged, and the scale to which it has been subsequently + // modified - for example, if the object has been scaled down by a + // factor of 2 then we should use 0.5 as the global scale. But we + // don't have the original scale stored anywhere, just the current + // scale. Possibilities - 1) remember the original scale + // somewhere, 2) add another field to let the user specify the + // global scale, 3) approximate the original scale by looking at + // the proportions of the skeleton after joint positions have + // been applied + + //LLVector3 obj_scale = obj->getScale(); + //F32 obj_scale_z = llmax(obj_scale[2],0.1f); + //setGlobalScale(obj_scale_z/2.0f); // roughly fit avatar height range (2m) into object height +} + +LLControlAvatar *LLControlAvatar::createControlAvatar(LLVOVolume *obj) +{ + LLControlAvatar *cav = (LLControlAvatar*)gObjectList.createObjectViewer(LL_PCODE_LEGACY_AVATAR, gAgent.getRegion(), CO_FLAG_CONTROL_AVATAR); + + if (cav) + { + cav->mRootVolp = obj; + + // Sync up position/rotation with object + cav->matchVolumeTransform(); + } + + return cav; +} + +void LLControlAvatar::markForDeath() +{ + mMarkedForDeath = true; + // object unlinked cav and might be dead already + // might need to clean mControlAVBridge here as well + mRootVolp = NULL; +} + +void LLControlAvatar::idleUpdate(LLAgent &agent, const F64 &time) +{ + if (mMarkedForDeath) + { + markDead(); + mMarkedForDeath = false; + } + else + { + LLVOAvatar::idleUpdate(agent,time); + } +} + +void LLControlAvatar::markDead() +{ + mRootVolp = NULL; + super::markDead(); + mControlAVBridge = NULL; +} + +bool LLControlAvatar::computeNeedsUpdate() +{ + computeUpdatePeriod(); + + // Animesh attachments are a special case. Should have the same update cadence as their attached parent avatar. + LLVOAvatar *attached_av = getAttachedAvatar(); + if (attached_av) + { + // Have to run computeNeedsUpdate() for attached av in + // case it hasn't run updateCharacter() already this + // frame. Note this means that the attached av will + // run computeNeedsUpdate() multiple times per frame + // if it has animesh attachments. Results will be + // consistent except for the corner case of exceeding + // MAX_IMPOSTOR_INTERVAL in one call but not another, + // which should be rare. + attached_av->computeNeedsUpdate(); + mNeedsImpostorUpdate = attached_av->mNeedsImpostorUpdate; + if (mNeedsImpostorUpdate) + { + mLastImpostorUpdateReason = 12; + } + return mNeedsImpostorUpdate; + } + return LLVOAvatar::computeNeedsUpdate(); +} + +bool LLControlAvatar::updateCharacter(LLAgent &agent) +{ + return LLVOAvatar::updateCharacter(agent); +} + +//virtual +void LLControlAvatar::updateDebugText() +{ + if (gSavedSettings.getBOOL("DebugAnimatedObjects")) + { + S32 total_linkset_count = 0; + if (mRootVolp) + { + total_linkset_count = 1 + mRootVolp->getChildren().size(); + } + std::vector volumes; + getAnimatedVolumes(volumes); + S32 animated_volume_count = volumes.size(); + std::string active_string; + std::string type_string; + std::string lod_string; + std::string animated_object_flag_string; + S32 total_tris = 0; + S32 total_verts = 0; + F32 est_tris = 0.f; + F32 est_streaming_tris = 0.f; + F32 streaming_cost = 0.f; + std::string cam_dist_string = ""; + S32 cam_dist_count = 0; + F32 lod_radius = mRootVolp ? mRootVolp->mLODRadius : 0.f; + + for (std::vector::iterator it = volumes.begin(); + it != volumes.end(); ++it) + { + LLVOVolume *volp = *it; + S32 verts = 0; + total_tris += volp->getTriangleCount(&verts); + total_verts += verts; + est_tris += volp->getEstTrianglesMax(); + est_streaming_tris += volp->getEstTrianglesStreamingCost(); + streaming_cost += volp->getStreamingCost(); + lod_string += llformat("%d",volp->getLOD()); + if (volp && volp->mDrawable) + { + bool is_animated_flag = volp->getExtendedMeshFlags() & LLExtendedMeshParams::ANIMATED_MESH_ENABLED_FLAG; + if (is_animated_flag) + { + animated_object_flag_string += "1"; + } + else + { + animated_object_flag_string += "0"; + } + if (volp->mDrawable->isActive()) + { + active_string += "A"; + } + else + { + active_string += "S"; + } + if (volp->isRiggedMesh()) + { + // Rigged/animatable mesh + type_string += "R"; + lod_radius = volp->mLODRadius; + } + else if (volp->isMesh()) + { + // Static mesh + type_string += "M"; + } + else + { + // Any other prim + type_string += "P"; + } + if (cam_dist_count < 4) + { + cam_dist_string += LLStringOps::getReadableNumber(volp->mLODDistance) + "/" + + LLStringOps::getReadableNumber(volp->mLODAdjustedDistance) + " "; + cam_dist_count++; + } + } + else + { + active_string += "-"; + type_string += "-"; + } + } + addDebugText(llformat("CAV obj %d anim %d active %s impost %d upprd %d strcst %f", + total_linkset_count, animated_volume_count, + active_string.c_str(), (S32) isImpostor(), getUpdatePeriod(), streaming_cost)); + addDebugText(llformat("types %s lods %s", type_string.c_str(), lod_string.c_str())); + addDebugText(llformat("flags %s", animated_object_flag_string.c_str())); + addDebugText(llformat("tris %d (est %.1f, streaming %.1f), verts %d", total_tris, est_tris, est_streaming_tris, total_verts)); + addDebugText(llformat("pxarea %s rank %d", LLStringOps::getReadableNumber(getPixelArea()).c_str(), getVisibilityRank())); + addDebugText(llformat("lod_radius %s dists %s", LLStringOps::getReadableNumber(lod_radius).c_str(),cam_dist_string.c_str())); + if (mPositionConstraintFixup.length() > 0.0f || mScaleConstraintFixup != 1.0f) + { + addDebugText(llformat("pos fix (%.1f %.1f %.1f) scale %f", + mPositionConstraintFixup[0], + mPositionConstraintFixup[1], + mPositionConstraintFixup[2], + mScaleConstraintFixup)); + } + +#if 0 + std::string region_name = "no region"; + if (mRootVolp->getRegion()) + { + region_name = mRootVolp->getRegion()->getName(); + } + std::string skel_region_name = "skel no region"; + if (getRegion()) + { + skel_region_name = getRegion()->getName(); + } + addDebugText(llformat("region %x %s skel %x %s", + mRootVolp->getRegion(), region_name.c_str(), + getRegion(), skel_region_name.c_str())); +#endif + + } + LLVOAvatar::updateDebugText(); +} + +void LLControlAvatar::getAnimatedVolumes(std::vector& volumes) +{ + if (!mRootVolp) + { + return; + } + + volumes.push_back(mRootVolp); + + LLViewerObject::const_child_list_t& child_list = mRootVolp->getChildren(); + for (LLViewerObject::const_child_list_t::const_iterator iter = child_list.begin(); + iter != child_list.end(); ++iter) + { + LLViewerObject* childp = *iter; + LLVOVolume *child_volp = dynamic_cast(childp); + if (child_volp && child_volp->isAnimatedObject()) + { + volumes.push_back(child_volp); + } + } +} + +// This is called after an associated object receives an animation +// message. Combine the signaled animations for all associated objects +// and process any resulting state changes. +void LLControlAvatar::updateAnimations() +{ + if (!mRootVolp) + { + LL_WARNS_ONCE("AnimatedObjectsNotify") << "No root vol" << LL_ENDL; + return; + } + + std::vector volumes; + getAnimatedVolumes(volumes); + + // Rebuild mSignaledAnimations from the associated volumes. + std::map anims; + for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) + { + LLVOVolume *volp = *vol_it; + //LL_INFOS("AnimatedObjects") << "updating anim for vol " << volp->getID() << " root " << mRootVolp->getID() << LL_ENDL; + signaled_animation_map_t& signaled_animations = LLObjectSignaledAnimationMap::instance().getMap()[volp->getID()]; + for (std::map::iterator anim_it = signaled_animations.begin(); + anim_it != signaled_animations.end(); + ++anim_it) + { + std::map::iterator found_anim_it = anims.find(anim_it->first); + if (found_anim_it != anims.end()) + { + // Animation already present, use the larger sequence id + anims[anim_it->first] = llmax(found_anim_it->second, anim_it->second); + } + else + { + // Animation not already present, use this sequence id. + anims[anim_it->first] = anim_it->second; + } + LL_DEBUGS("AnimatedObjectsNotify") << "found anim for vol " << volp->getID() << " anim " << anim_it->first << " root " << mRootVolp->getID() << LL_ENDL; + } + } + if (!mPlaying) + { + mPlaying = true; + //if (!mRootVolp->isAnySelected()) + { + updateVolumeGeom(); + mRootVolp->recursiveMarkForUpdate(); + } + } + + mSignaledAnimations = anims; + processAnimationStateChanges(); +} + +// virtual +LLViewerObject* LLControlAvatar::lineSegmentIntersectRiggedAttachments(const LLVector4a& start, const LLVector4a& end, + S32 face, + bool pick_transparent, + bool pick_rigged, + bool pick_unselectable, + S32* face_hit, + LLVector4a* intersection, + LLVector2* tex_coord, + LLVector4a* normal, + LLVector4a* tangent) +{ + if (!mRootVolp) + { + return NULL; + } + + LLViewerObject* hit = NULL; + + if (lineSegmentBoundingBox(start, end)) + { + LLVector4a local_end = end; + LLVector4a local_intersection; + if (mRootVolp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) + { + local_end = local_intersection; + if (intersection) + { + *intersection = local_intersection; + } + hit = mRootVolp; + } + else + { + std::vector volumes; + getAnimatedVolumes(volumes); + + for (std::vector::iterator vol_it = volumes.begin(); vol_it != volumes.end(); ++vol_it) + { + LLVOVolume *volp = *vol_it; + if (mRootVolp != volp && volp->lineSegmentIntersect(start, local_end, face, pick_transparent, pick_rigged, pick_unselectable, face_hit, &local_intersection, tex_coord, normal, tangent)) + { + local_end = local_intersection; + if (intersection) + { + *intersection = local_intersection; + } + hit = volp; + break; + } + } + } + } + + return hit; +} + +// virtual +std::string LLControlAvatar::getFullname() const +{ + if (mRootVolp) + { + return "AO_" + mRootVolp->getID().getString(); + } + else + { + return "AO_no_root_vol"; + } +} + +// virtual +bool LLControlAvatar::shouldRenderRigged() const +{ + const LLVOAvatar *attached_av = getAttachedAvatar(); + if (attached_av) + { + return attached_av->shouldRenderRigged(); + } + return true; +} + +// virtual +bool LLControlAvatar::isImpostor() +{ + // Attached animated objects should match state of their attached av. + LLVOAvatar *attached_av = getAttachedAvatar(); + if (attached_av) + { + return attached_av->isImpostor(); + } + return LLVOAvatar::isImpostor(); +} + +//static +void LLControlAvatar::onRegionChanged() +{ + std::vector::iterator it = LLCharacter::sInstances.begin(); + for ( ; it != LLCharacter::sInstances.end(); ++it) + { + LLControlAvatar* cav = dynamic_cast(*it); + if (!cav) continue; + cav->mRegionChanged = true; + } +} -- cgit v1.2.3 From b42f9d836b4c0f7fbd4bdae1734021e2a09fdbe8 Mon Sep 17 00:00:00 2001 From: Ansariel Date: Sat, 1 Jun 2024 15:49:26 +0200 Subject: Re-enable a lot of compiler warnings for MSVC and address the C4267 "possible loss of precision" warnings --- indra/newview/llcontrolavatar.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'indra/newview/llcontrolavatar.cpp') diff --git a/indra/newview/llcontrolavatar.cpp b/indra/newview/llcontrolavatar.cpp index bb853a3ddc..716333b217 100644 --- a/indra/newview/llcontrolavatar.cpp +++ b/indra/newview/llcontrolavatar.cpp @@ -424,11 +424,11 @@ void LLControlAvatar::updateDebugText() S32 total_linkset_count = 0; if (mRootVolp) { - total_linkset_count = 1 + mRootVolp->getChildren().size(); + total_linkset_count = 1 + static_cast(mRootVolp->getChildren().size()); } std::vector volumes; getAnimatedVolumes(volumes); - S32 animated_volume_count = volumes.size(); + S32 animated_volume_count = static_cast(volumes.size()); std::string active_string; std::string type_string; std::string lod_string; -- cgit v1.2.3