diff options
Diffstat (limited to 'indra/newview/llvoavatar.cpp')
-rw-r--r-- | indra/newview/llvoavatar.cpp | 1237 |
1 files changed, 873 insertions, 364 deletions
diff --git a/indra/newview/llvoavatar.cpp b/indra/newview/llvoavatar.cpp index 3b51d07f96..f69b9b3861 100644 --- a/indra/newview/llvoavatar.cpp +++ b/indra/newview/llvoavatar.cpp @@ -38,6 +38,7 @@ #include "raytrace.h" #include "llagent.h" // Get state values from here +#include "llagentbenefits.h" #include "llagentcamera.h" #include "llagentwearables.h" #include "llanimationstates.h" @@ -197,6 +198,8 @@ const F32 NAMETAG_VERT_OFFSET_WEIGHT = 0.17f; const U32 LLVOAvatar::VISUAL_COMPLEXITY_UNKNOWN = 0; const F64 HUD_OVERSIZED_TEXTURE_DATA_SIZE = 1024 * 1024; +const F32 MAX_TEXTURE_WAIT_TIME_SEC = 60; + enum ERenderName { RENDER_NAME_NEVER, @@ -204,6 +207,8 @@ enum ERenderName RENDER_NAME_FADE }; +#define JELLYDOLLS_SHOULD_IMPOSTOR + //----------------------------------------------------------------------------- // Callback data //----------------------------------------------------------------------------- @@ -570,9 +575,9 @@ private: //----------------------------------------------------------------------------- // Static Data //----------------------------------------------------------------------------- -LLAvatarAppearanceDictionary *LLVOAvatar::sAvatarDictionary = NULL; S32 LLVOAvatar::sFreezeCounter = 0; -U32 LLVOAvatar::sMaxNonImpostors = 12; // overridden based on graphics setting +U32 LLVOAvatar::sMaxNonImpostors = 12; // Set from RenderAvatarMaxNonImpostors +bool LLVOAvatar::sLimitNonImpostors = false; // True unless RenderAvatarMaxNonImpostors is 0 (unlimited) F32 LLVOAvatar::sRenderDistance = 256.f; S32 LLVOAvatar::sNumVisibleAvatars = 0; S32 LLVOAvatar::sNumLODChangesThisFrame = 0; @@ -599,7 +604,6 @@ BOOL LLVOAvatar::sShowFootPlane = FALSE; BOOL LLVOAvatar::sVisibleInFirstPerson = FALSE; F32 LLVOAvatar::sLODFactor = 1.f; F32 LLVOAvatar::sPhysicsLODFactor = 1.f; -bool LLVOAvatar::sUseImpostors = false; // overwridden by RenderAvatarMaxNonImpostors BOOL LLVOAvatar::sJointDebug = FALSE; F32 LLVOAvatar::sUnbakedTime = 0.f; F32 LLVOAvatar::sUnbakedUpdateTime = 0.f; @@ -632,6 +636,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mMeshValid(FALSE), mVisible(FALSE), mLastImpostorUpdateFrameTime(0.f), + mLastImpostorUpdateReason(0), mWindFreq(0.f), mRipplePhase( 0.f ), mBelowWater(FALSE), @@ -654,6 +659,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mNeedsSkin(FALSE), mLastSkinTime(0.f), mUpdatePeriod(1), + mOverallAppearance(AOA_INVISIBLE), mVisualComplexityStale(true), mVisuallyMuteSetting(AV_RENDER_NORMALLY), mMutedAVColor(LLColor4::white /* used for "uninitialize" */), @@ -663,6 +669,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, mFullyLoadedInitialized(FALSE), mVisualComplexity(VISUAL_COMPLEXITY_UNKNOWN), mLoadedCallbacksPaused(FALSE), + mLoadedCallbackTextures(0), mRenderUnloadedAvatar(LLCachedControl<bool>(gSavedSettings, "RenderUnloadedAvatar", false)), mLastRezzedStatus(-1), mIsEditingAppearance(FALSE), @@ -697,6 +704,7 @@ LLVOAvatar::LLVOAvatar(const LLUUID& id, setAnimationData("Speed", &mSpeed); mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 0; mNeedsAnimUpdate = TRUE; mNeedsExtentUpdate = true; @@ -752,8 +760,8 @@ std::string LLVOAvatar::avString() const } else { - std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); - return " Avatar '" + getFullname() + "' " + viz_string + " "; + std::string viz_string = LLVOAvatar::rezStatusToString(getRezzedStatus()); + return " Avatar '" + getFullname() + "' " + viz_string + " "; } } @@ -883,8 +891,9 @@ BOOL LLVOAvatar::hasGray() const S32 LLVOAvatar::getRezzedStatus() const { if (getIsCloud()) return 0; - if (isFullyTextured() && allBakedTexturesCompletelyDownloaded()) return 3; - if (isFullyTextured()) return 2; + bool textured = isFullyTextured(); + if (textured && allBakedTexturesCompletelyDownloaded()) return 3; + if (textured) return 2; llassert(hasGray()); return 1; // gray } @@ -1020,15 +1029,15 @@ void LLVOAvatar::dumpBakedStatus() { LL_CONT << " Unbaked ("; - for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator iter = LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); ++iter) { const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = iter->second; const ETextureIndex index = baked_dict->mTextureIndex; if (!inst->isTextureDefined(index)) { - LL_CONT << " " << (LLAvatarAppearanceDictionary::getInstance()->getTexture(index) ? LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mName : ""); + LL_CONT << " " << (LLAvatarAppearance::getDictionary()->getTexture(index) ? LLAvatarAppearance::getDictionary()->getTexture(index)->mName : ""); } } LL_CONT << " ) " << inst->getUnbakedPixelAreaRank(); @@ -1071,6 +1080,7 @@ void LLVOAvatar::resetImpostors() LLVOAvatar* avatar = (LLVOAvatar*) *iter; avatar->mImpostor.release(); avatar->mNeedsImpostorUpdate = TRUE; + avatar->mLastImpostorUpdateReason = 1; } } @@ -1114,6 +1124,7 @@ void LLVOAvatar::initClass() LLJoint::setDebugJointNames(gSavedSettings.getString("DebugAvatarJoints")); LLControlAvatar::sRegionChangedSlot = gAgent.addRegionChangedCallback(&LLControlAvatar::onRegionChanged); + } @@ -1314,72 +1325,84 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) LL_RECORD_BLOCK_TIME(FTM_AVATAR_EXTENT_UPDATE); S32 box_detail = gSavedSettings.getS32("AvatarBoundingBoxComplexity"); + if (getOverallAppearance() != AOA_NORMAL) + { + if (isControlAvatar()) + { + // Animated objects don't show system avatar but do need to include rigged meshes in their bounding box. + box_detail = 3; + } + else + { + // Jellydolled avatars ignore attachments, etc, use only system avatar. + box_detail = 1; + } + } // FIXME the update_min_max function used below assumes there is a // known starting point, but in general there isn't. Ideally the // box update logic should be modified to handle the no-point-yet // case. For most models, starting with the pelvis is safe though. LLVector3 zero_pos; - LLVector4a pos; + LLVector4a pos; if (dist_vec(zero_pos, mPelvisp->getWorldPosition())<0.001) { // Don't use pelvis until av initialized - pos.load3(getRenderPosition().mV); + pos.load3(getRenderPosition().mV); } else { pos.load3(mPelvisp->getWorldPosition().mV); } - newMin = pos; - newMax = pos; + newMin = pos; + newMax = pos; - //stretch bounding box by joint positions. Doing this for - //control avs, where the polymeshes aren't maintained or - //displayed, can give inaccurate boxes due to joints stuck at (0,0,0). - if ((box_detail>=1) && !isControlAvatar()) + if (box_detail>=1 && !isControlAvatar()) { - for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) - { - LLPolyMesh* mesh = i->second; - for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.size(); joint_num++) - { - LLVector4a trans; - trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV); - update_min_max(newMin, newMax, trans); - } - } - + //stretch bounding box by joint positions. Doing this for + //control avs, where the polymeshes aren't maintained or + //displayed, can give inaccurate boxes due to joints stuck at (0,0,0). + for (polymesh_map_t::iterator i = mPolyMeshes.begin(); i != mPolyMeshes.end(); ++i) + { + LLPolyMesh* mesh = i->second; + for (S32 joint_num = 0; joint_num < mesh->mJointRenderData.size(); joint_num++) + { + LLVector4a trans; + trans.load3( mesh->mJointRenderData[joint_num]->mWorldMatrix->getTranslation().mV); + update_min_max(newMin, newMax, trans); + } + } } - // Pad bounding box for starting joint, plus polymesh if - // applicable. Subsequent calcs should be accurate enough to not - // need padding. - LLVector4a padding(0.25); - newMin.sub(padding); - newMax.add(padding); + // Pad bounding box for starting joint, plus polymesh if + // applicable. Subsequent calcs should be accurate enough to not + // need padding. + LLVector4a padding(0.25); + newMin.sub(padding); + newMax.add(padding); - //stretch bounding box by static attachments + //stretch bounding box by static attachments if (box_detail >= 2) { float max_attachment_span = get_default_max_prim_scale() * 5.0f; - - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) - { - LLViewerJointAttachment* attachment = iter->second; + + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) + { + LLViewerJointAttachment* attachment = iter->second; - if (attachment->getValid()) - { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) - { + if (attachment->getValid()) + { + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) + { // Don't we need to look at children of attached_object as well? - const LLViewerObject* attached_object = attachment_iter->get(); - if (attached_object && !attached_object->isHUDAttachment()) - { + const LLViewerObject* attached_object = attachment_iter->get(); + if (attached_object && !attached_object->isHUDAttachment()) + { const LLVOVolume *vol = dynamic_cast<const LLVOVolume*>(attached_object); if (vol && vol->isAnimatedObject()) { @@ -1401,39 +1424,39 @@ void LLVOAvatar::calculateSpatialExtents(LLVector4a& newMin, LLVector4a& newMax) { continue; } - LLDrawable* drawable = attached_object->mDrawable; - if (drawable && !drawable->isState(LLDrawable::RIGGED)) - { - LLSpatialBridge* bridge = drawable->getSpatialBridge(); - if (bridge) - { - const LLVector4a* ext = bridge->getSpatialExtents(); - LLVector4a distance; - distance.setSub(ext[1], ext[0]); - LLVector4a max_span(max_attachment_span); - - S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; - - // Only add the prim to spatial extents calculations if it isn't a megaprim. - // max_attachment_span calculated at the start of the function - // (currently 5 times our max prim size) - if (lt == 0x7) - { - update_min_max(newMin,newMax,ext[0]); - update_min_max(newMin,newMax,ext[1]); - } - } - } - } - } - } - } + LLDrawable* drawable = attached_object->mDrawable; + if (drawable && !drawable->isState(LLDrawable::RIGGED)) + { + LLSpatialBridge* bridge = drawable->getSpatialBridge(); + if (bridge) + { + const LLVector4a* ext = bridge->getSpatialExtents(); + LLVector4a distance; + distance.setSub(ext[1], ext[0]); + LLVector4a max_span(max_attachment_span); + + S32 lt = distance.lessThan(max_span).getGatheredBits() & 0x7; + + // Only add the prim to spatial extents calculations if it isn't a megaprim. + // max_attachment_span calculated at the start of the function + // (currently 5 times our max prim size) + if (lt == 0x7) + { + update_min_max(newMin,newMax,ext[0]); + update_min_max(newMin,newMax,ext[1]); + } + } + } + } + } + } + } } // Stretch bounding box by rigged mesh joint boxes if (box_detail>=3) { - updateRiggingInfo(); + updateRiggingInfo(); for (S32 joint_num = 0; joint_num < LL_CHARACTER_MAX_ANIMATED_JOINTS; joint_num++) { LLJoint *joint = getJoint(joint_num); @@ -1573,13 +1596,16 @@ void LLVOAvatar::renderCollisionVolumes() } } -void LLVOAvatar::renderBones() +void LLVOAvatar::renderBones(const std::string &selected_joint) { LLGLEnable blend(GL_BLEND); avatar_joint_list_t::iterator iter = mSkeleton.begin(); - avatar_joint_list_t::iterator end = mSkeleton.end(); + avatar_joint_list_t::iterator end = mSkeleton.end(); + // For selected joints + static LLVector3 SELECTED_COLOR_OCCLUDED(1.0f, 1.0f, 0.0f); + static LLVector3 SELECTED_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); // For bones with position overrides defined static LLVector3 OVERRIDE_COLOR_OCCLUDED(1.0f, 0.0f, 0.0f); static LLVector3 OVERRIDE_COLOR_VISIBLE(0.5f, 0.5f, 0.5f); @@ -1606,7 +1632,18 @@ void LLVOAvatar::renderBones() LLVector3 pos; LLUUID mesh_id; - if (jointp->hasAttachmentPosOverride(pos,mesh_id)) + F32 sphere_scale = SPHERE_SCALEF; + + // We are in render, so it is preferable to implement selection + // in a different way, but since this is for debug/preview, this + // is low priority + if (jointp->getName() == selected_joint) + { + sphere_scale *= 16; + occ_color = SELECTED_COLOR_OCCLUDED; + visible_color = SELECTED_COLOR_VISIBLE; + } + else if (jointp->hasAttachmentPosOverride(pos,mesh_id)) { occ_color = OVERRIDE_COLOR_OCCLUDED; visible_color = OVERRIDE_COLOR_VISIBLE; @@ -1627,7 +1664,6 @@ void LLVOAvatar::renderBones() LLVector3 begin_pos(0,0,0); LLVector3 end_pos(jointp->getEnd()); - F32 sphere_scale = SPHERE_SCALEF; gGL.pushMatrix(); gGL.multMatrix( &jointp->getXform()->getWorldMatrix().mMatrix[0][0] ); @@ -2006,6 +2042,38 @@ void LLVOAvatar::resetVisualParams() } } +void LLVOAvatar::applyDefaultParams() +{ + // These are params from avs with newly created copies of shape, + // skin, hair, eyes, plus gender set as noted. Run arche_tool.py + // to get params from some other xml appearance dump. + std::map<S32, U8> male_params = { + {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,255}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} + }; + std::map<S32, U8> female_params = { + {1,33}, {2,61}, {4,85}, {5,23}, {6,58}, {7,127}, {8,63}, {10,85}, {11,63}, {12,42}, {13,0}, {14,85}, {15,63}, {16,36}, {17,85}, {18,95}, {19,153}, {20,63}, {21,34}, {22,0}, {23,63}, {24,109}, {25,88}, {27,132}, {31,63}, {33,136}, {34,81}, {35,85}, {36,103}, {37,136}, {38,127}, {80,0}, {93,203}, {98,0}, {99,0}, {105,127}, {108,0}, {110,0}, {111,127}, {112,0}, {113,0}, {114,127}, {115,0}, {116,0}, {117,0}, {119,127}, {130,114}, {131,127}, {132,99}, {133,63}, {134,127}, {135,140}, {136,127}, {137,127}, {140,0}, {141,0}, {142,0}, {143,191}, {150,0}, {155,104}, {157,0}, {162,0}, {163,0}, {165,0}, {166,0}, {167,0}, {168,0}, {169,0}, {177,0}, {181,145}, {182,216}, {183,133}, {184,0}, {185,127}, {192,0}, {193,127}, {196,170}, {198,0}, {503,0}, {505,127}, {506,127}, {507,109}, {508,85}, {513,127}, {514,127}, {515,63}, {517,85}, {518,42}, {603,100}, {604,216}, {605,214}, {606,204}, {607,204}, {608,204}, {609,51}, {616,25}, {617,89}, {619,76}, {624,204}, {625,0}, {629,127}, {637,0}, {638,0}, {646,144}, {647,85}, {649,127}, {650,132}, {652,127}, {653,85}, {654,0}, {656,127}, {659,127}, {662,127}, {663,127}, {664,127}, {665,127}, {674,59}, {675,127}, {676,85}, {678,127}, {682,127}, {683,106}, {684,47}, {685,79}, {690,127}, {692,127}, {693,204}, {700,63}, {701,0}, {702,0}, {703,0}, {704,0}, {705,127}, {706,127}, {707,0}, {708,0}, {709,0}, {710,0}, {711,127}, {712,0}, {713,159}, {714,0}, {715,0}, {750,178}, {752,127}, {753,36}, {754,85}, {755,131}, {756,127}, {757,127}, {758,127}, {759,153}, {760,95}, {762,0}, {763,140}, {764,74}, {765,27}, {769,127}, {773,127}, {775,0}, {779,214}, {780,204}, {781,198}, {785,0}, {789,0}, {795,63}, {796,30}, {799,127}, {800,226}, {801,255}, {802,198}, {803,255}, {804,255}, {805,255}, {806,255}, {807,255}, {808,255}, {812,255}, {813,255}, {814,255}, {815,204}, {816,0}, {817,255}, {818,255}, {819,255}, {820,255}, {821,255}, {822,255}, {823,255}, {824,255}, {825,255}, {826,255}, {827,255}, {828,0}, {829,255}, {830,255}, {834,255}, {835,255}, {836,255}, {840,0}, {841,127}, {842,127}, {844,255}, {848,25}, {858,100}, {859,255}, {860,255}, {861,255}, {862,255}, {863,84}, {868,0}, {869,0}, {877,0}, {879,51}, {880,132}, {921,255}, {922,255}, {923,255}, {10000,0}, {10001,0}, {10002,25}, {10003,0}, {10004,25}, {10005,23}, {10006,51}, {10007,0}, {10008,25}, {10009,23}, {10010,51}, {10011,0}, {10012,0}, {10013,25}, {10014,0}, {10015,25}, {10016,23}, {10017,51}, {10018,0}, {10019,0}, {10020,25}, {10021,0}, {10022,25}, {10023,23}, {10024,51}, {10025,0}, {10026,25}, {10027,23}, {10028,51}, {10029,0}, {10030,25}, {10031,23}, {10032,51}, {11000,1}, {11001,127} + }; + std::map<S32, U8> *params = NULL; + if (getSex() == SEX_MALE) + params = &male_params; + else + params = &female_params; + + for( auto it = params->begin(); it != params->end(); ++it) + { + LLVisualParam* param = getVisualParam(it->first); + if( !param ) + { + // invalid id + break; + } + + U8 value = it->second; + F32 newWeight = U8_to_F32(value, param->getMinWeight(), param->getMaxWeight()); + param->setWeight(newWeight); + } +} + //----------------------------------------------------------------------------- // resetSkeleton() //----------------------------------------------------------------------------- @@ -2045,8 +2113,10 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) LL_ERRS() << "Error resetting skeleton" << LL_ENDL; } - // Reset attachment points (buildSkeleton only does bones and CVs) - bool ignore_hud_joints = true; + // Reset attachment points + // BuildSkeleton only does bones and CVs but we still need to reinit huds + // since huds can be animated. + bool ignore_hud_joints = !isSelf(); initAttachmentPoints(ignore_hud_joints); // Fix up collision volumes @@ -2066,15 +2136,30 @@ void LLVOAvatar::resetSkeleton(bool reset_animations) } // Reset tweakable params to preserved state - if (mLastProcessedAppearance) - { - bool slam_params = true; - applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); - } + if (getOverallAppearance() == AOA_NORMAL) + { + if (mLastProcessedAppearance) + { + bool slam_params = true; + applyParsedAppearanceMessage(*mLastProcessedAppearance, slam_params); + } + } + else + { + // Stripped down approximation of + // applyParsedAppearanceMessage, but with alternative default + // (jellydoll) params + setCompositeUpdatesEnabled( FALSE ); + gPipeline.markGLRebuild(this); + applyDefaultParams(); + setCompositeUpdatesEnabled( TRUE ); + updateMeshTextures(); + updateMeshVisibility(); + } updateVisualParams(); // Restore attachment pos overrides - updateAttachmentOverrides(); + updateAttachmentOverrides(); // Animations if (reset_animations) @@ -2407,6 +2492,7 @@ S32 LLVOAvatar::setTETexture(const U8 te, const LLUUID& uuid) } static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE("Avatar Update"); +static LLTrace::BlockTimerStatHandle FTM_AVATAR_UPDATE_COMPLEXITY("Avatar Update Complexity"); static LLTrace::BlockTimerStatHandle FTM_JOINT_UPDATE("Update Joints"); //------------------------------------------------------------------------ @@ -2449,14 +2535,13 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) return; } - if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR)) + if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR)) && !(gSavedSettings.getBOOL("DisableAllRenderTypes")) && !isSelf()) { return; } // Update should be happening max once per frame. - const S32 upd_freq = 4; // force update every upd_freq frames. if ((mLastAnimExtents[0]==LLVector3())|| (mLastAnimExtents[1])==LLVector3()) { @@ -2464,6 +2549,7 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) } else { + const S32 upd_freq = 4; // force update every upd_freq frames. mNeedsExtentUpdate = ((LLDrawable::getCurrentFrame()+mID.mData[0])%upd_freq==0); } @@ -2548,8 +2634,41 @@ void LLVOAvatar::idleUpdate(LLAgent &agent, const F64 &time) } idleUpdateNameTag( mLastRootPos ); + + // Complexity has stale mechanics, but updates still can be very rapid + // so spread avatar complexity calculations over frames to lesen load from + // rapid updates and to make sure all avatars are not calculated at once. + S32 compl_upd_freq = 20; + if (isControlAvatar()) + { + // animeshes do not (or won't) have impostors nor change outfis, + // no need for high frequency + compl_upd_freq = 100; + } + else if (mLastRezzedStatus <= 0) //cloud or init + { + compl_upd_freq = 60; + } + else if (isSelf()) + { + compl_upd_freq = 5; + } + else if (mLastRezzedStatus == 1) //'grey', not fully loaded + { + compl_upd_freq = 40; + } + else if (isInMuteList()) //cheap, buffers value from search + { + compl_upd_freq = 100; + } + + if ((LLFrameTimer::getFrameCount() + mID.mData[0]) % compl_upd_freq == 0) + { + LL_RECORD_BLOCK_TIME(FTM_AVATAR_UPDATE_COMPLEXITY); idleUpdateRenderComplexity(); } + idleUpdateDebugInfo(); +} void LLVOAvatar::idleUpdateVoiceVisualizer(bool voice_enabled) { @@ -2675,7 +2794,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) BOOL visible = isVisible() || mNeedsAnimUpdate; // update attachments positions - if (detailed_update || !sUseImpostors) + if (detailed_update) { LL_RECORD_BLOCK_TIME(FTM_ATTACHMENT_UPDATE); for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); @@ -2735,6 +2854,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (angle_diff > F_PI/512.f*distance*mUpdatePeriod) { mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 2; } } @@ -2746,6 +2866,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (dist_diff/mImpostorDistance > 0.1f) { mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 3; } else { @@ -2758,6 +2879,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (diff.getLength3().getF32() > 0.05f) { mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 4; } else { @@ -2765,6 +2887,7 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (diff.getLength3().getF32() > 0.05f) { mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 5; } } } @@ -2773,13 +2896,13 @@ void LLVOAvatar::idleUpdateMisc(bool detailed_update) if (mDrawable.notNull()) { - mDrawable->movePartition(); + mDrawable->movePartition(); - //force a move if sitting on an active object - if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) - { - gPipeline.markMoved(mDrawable, TRUE); - } + //force a move if sitting on an active object + if (getParent() && ((LLViewerObject*) getParent())->mDrawable->isActive()) + { + gPipeline.markMoved(mDrawable, TRUE); + } } } @@ -2859,7 +2982,10 @@ F32 LLVOAvatar::calcMorphAmount() void LLVOAvatar::idleUpdateLipSync(bool voice_enabled) { // Use the Lipsync_Ooh and Lipsync_Aah morphs for lip sync - if ( voice_enabled && (LLVoiceClient::getInstance()->lipSyncEnabled()) && LLVoiceClient::getInstance()->getIsSpeaking( mID ) ) + if ( voice_enabled + && mLastRezzedStatus > 0 // no point updating lip-sync for clouds + && (LLVoiceClient::getInstance()->lipSyncEnabled()) + && LLVoiceClient::getInstance()->getIsSpeaking( mID ) ) { F32 ooh_morph_amount = 0.0f; F32 aah_morph_amount = 0.0f; @@ -2953,7 +3079,7 @@ void LLVOAvatar::idleUpdateLoadingEffect() void LLVOAvatar::idleUpdateWindEffect() { // update wind effect - if ((LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) + if ((LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) >= LLDrawPoolAvatar::SHADER_LEVEL_CLOTH)) { F32 hover_strength = 0.f; F32 time_delta = mRippleTimer.getElapsedTimeF32() - mRippleTimeLast; @@ -3207,7 +3333,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) std::string title_str = title->getString(); LLStringFn::replace_ascii_controlchars(title_str,LL_UNKNOWN_CHAR); addNameTagLine(title_str, name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + LLFontGL::getFontSansSerifSmall(), true); } static LLUICachedControl<bool> show_display_names("NameTagShowDisplayNames", true); @@ -3227,7 +3353,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) if (show_display_names) { addNameTagLine(av_name.getDisplayName(), name_tag_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerif()); + LLFontGL::getFontSansSerif(), true); } // Suppress SLID display if display name matches exactly (ugh) if (show_usernames && !av_name.isDisplayNameDefault()) @@ -3235,14 +3361,14 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) // *HACK: Desaturate the color LLColor4 username_color = name_tag_color * 0.83f; addNameTagLine(av_name.getUserName(), username_color, LLFontGL::NORMAL, - LLFontGL::getFontSansSerifSmall()); + LLFontGL::getFontSansSerifSmall(), true); } } else { const LLFontGL* font = LLFontGL::getFontSansSerif(); std::string full_name = LLCacheName::buildFullName( firstname->getString(), lastname->getString() ); - addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font); + addNameTagLine(full_name, name_tag_color, LLFontGL::NORMAL, font, true); } mNameAway = is_away; @@ -3334,7 +3460,7 @@ void LLVOAvatar::idleUpdateNameTagText(BOOL new_name) } } -void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font) +void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, S32 style, const LLFontGL* font, const bool use_ellipses) { llassert(mNameText); if (mVisibleChat) @@ -3343,7 +3469,7 @@ void LLVOAvatar::addNameTagLine(const std::string& line, const LLColor4& color, } else { - mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font); + mNameText->addLine(line, color, (LLFontGL::StyleFlags)style, font, use_ellipses); } mNameIsSet |= !line.empty(); } @@ -3505,14 +3631,19 @@ bool LLVOAvatar::isVisuallyMuted() muted = false; } else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) - { // Always want to see this AV as an impostor + { +#ifdef JELLYDOLLS_SHOULD_IMPOSTOR muted = true; + // Always want to see this AV as an impostor +#else + muted = false; +#endif } else if (isInMuteList()) { muted = true; } - else + else { muted = isTooComplex(); } @@ -3521,7 +3652,7 @@ bool LLVOAvatar::isVisuallyMuted() return muted; } -bool LLVOAvatar::isInMuteList() +bool LLVOAvatar::isInMuteList() const { bool muted = false; F64 now = LLFrameTimer::getTotalSeconds(); @@ -3583,9 +3714,14 @@ void LLVOAvatar::updateAppearanceMessageDebugText() if (hover_offset[2] != 0.0) { debug_line += llformat(" hov_z: %.3f", hover_offset[2]); - debug_line += llformat(" %s", (isSitting() ? "S" : "T")); + debug_line += llformat(" %s", (isSitting() ? "S" : "T")); debug_line += llformat("%s", (isMotionActive(ANIM_AGENT_SIT_GROUND_CONSTRAINED) ? "G" : "-")); } + if (mInAir) + { + debug_line += " A"; + + } LLVector3 ankle_right_pos_agent = mFootRightp->getWorldPosition(); LLVector3 normal; @@ -3598,9 +3734,38 @@ void LLVOAvatar::updateAppearanceMessageDebugText() LLVector3 pelvis_pos = mPelvisp->getPosition(); debug_line += llformat(" rp %.3f pp %.3f", root_pos[2], pelvis_pos[2]); - S32 is_visible = (S32) isVisible(); - S32 is_m_visible = (S32) mVisible; - debug_line += llformat(" v %d/%d", is_visible, is_m_visible); + const LLVector3& scale = getScale(); + debug_line += llformat(" scale-z %.3f", scale[2]); + S32 is_visible = (S32) isVisible(); + S32 is_m_visible = (S32) mVisible; + debug_line += llformat(" v %d/%d", is_visible, is_m_visible); + + AvatarOverallAppearance aoa = getOverallAppearance(); + if (aoa == AOA_NORMAL) + { + debug_line += " N"; + } + else if (aoa == AOA_JELLYDOLL) + { + debug_line += " J"; + } + else + { + debug_line += " I"; + } + + if (mMeshValid) + { + debug_line += "m"; + } + else + { + debug_line += "-"; + } + if (isImpostor()) + { + debug_line += " Imp" + llformat("%d[%d]:%.1f", mUpdatePeriod, mLastImpostorUpdateReason, ((F32)(gFrameTimeSeconds-mLastImpostorUpdateFrameTime))); + } addDebugText(debug_line); } @@ -3642,13 +3807,13 @@ LLViewerInventoryItem* recursiveGetObjectInventoryItem(LLViewerObject *vobj, LLU void LLVOAvatar::updateAnimationDebugText() { - for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); - iter != mMotionController.getActiveMotions().end(); ++iter) + for (LLMotionController::motion_list_t::iterator iter = mMotionController.getActiveMotions().begin(); + iter != mMotionController.getActiveMotions().end(); ++iter) + { + LLMotion* motionp = *iter; + if (motionp->getMinPixelArea() < getPixelArea()) { - LLMotion* motionp = *iter; - if (motionp->getMinPixelArea() < getPixelArea()) - { - std::string output; + std::string output; std::string motion_name = motionp->getName(); if (motion_name.empty()) { @@ -3665,73 +3830,74 @@ void LLVOAvatar::updateAnimationDebugText() } } if (motion_name.empty()) + { + std::string name; + if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf()) { - std::string name; - if (gAgent.isGodlikeWithoutAdminMenuFakery() || isSelf()) + name = motionp->getID().asString(); + LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin(); + for (; anim_it != mAnimationSources.end(); ++anim_it) { - name = motionp->getID().asString(); - LLVOAvatar::AnimSourceIterator anim_it = mAnimationSources.begin(); - for (; anim_it != mAnimationSources.end(); ++anim_it) + if (anim_it->second == motionp->getID()) { - if (anim_it->second == motionp->getID()) + LLViewerObject* object = gObjectList.findObject(anim_it->first); + if (!object) + { + break; + } + if (object->isAvatar()) { - LLViewerObject* object = gObjectList.findObject(anim_it->first); - if (!object) + if (mMotionController.mIsSelf) { - break; + // Searching inventory by asset id is really long + // so just mark as inventory + // Also item is likely to be named by LLPreviewAnim + name += "(inventory)"; } - if (object->isAvatar()) + } + else + { + LLViewerInventoryItem* item = NULL; + if (!object->isInventoryDirty()) { - if (mMotionController.mIsSelf) - { - // Searching inventory by asset id is really long - // so just mark as inventory - // Also item is likely to be named by LLPreviewAnim - name += "(inventory)"; - } + item = object->getInventoryItemByAsset(motionp->getID()); + } + if (item) + { + name = item->getName(); + } + else if (object->isAttachment()) + { + name += "(att:" + getAttachmentItemName() + ")"; } else { - LLViewerInventoryItem* item = NULL; - if (!object->isInventoryDirty()) - { - item = object->getInventoryItemByAsset(motionp->getID()); - } - if (item) - { - name = item->getName(); - } - else if (object->isAttachment()) - { - name += "(" + getAttachmentItemName() + ")"; - } - else - { - // in-world object, name or content unknown - name += "(in-world)"; - } + // in-world object, name or content unknown + name += "(in-world)"; } - break; } + break; } } - else - { - name = LLUUID::null.asString(); - } - output = llformat("%s - %d", - name.c_str(), - (U32)motionp->getPriority()); } else { - output = llformat("%s - %d", - motion_name.c_str(), - (U32)motionp->getPriority()); + name = LLUUID::null.asString(); } - addDebugText(output); + motion_name = name; + } + std::string motion_tag = ""; + if (mPlayingAnimations.find(motionp->getID()) != mPlayingAnimations.end()) + { + motion_tag = "*"; } + output = llformat("%s%s - %d", + motion_name.c_str(), + motion_tag.c_str(), + (U32)motionp->getPriority()); + addDebugText(output); } + } } void LLVOAvatar::updateDebugText() @@ -3860,7 +4026,14 @@ void LLVOAvatar::updateFootstepSounds() // computeUpdatePeriod() // Factored out from updateCharacter() // Set new value for mUpdatePeriod based on distance and various other factors. -//------------------------------------------------------------------------ +// +// Note 10-2020: it turns out that none of these update period +// calculations have been having any effect, because +// mNeedsImpostorUpdate was not being set in updateCharacter(). So +// it's really open to question whether we want to enable time based updates, and if +// so, at what rate. Leaving the rates as given would lead to +// drastically more frequent impostor updates than we've been doing all these years. +// ------------------------------------------------------------------------ void LLVOAvatar::computeUpdatePeriod() { bool visually_muted = isVisuallyMuted(); @@ -3868,7 +4041,7 @@ void LLVOAvatar::computeUpdatePeriod() && isVisible() && (!isSelf() || visually_muted) && !isUIAvatar() - && sUseImpostors + && (sLimitNonImpostors || visually_muted) && !mNeedsAnimUpdate && !sFreezeCounter) { @@ -3876,11 +4049,14 @@ void LLVOAvatar::computeUpdatePeriod() LLVector4a size; size.setSub(ext[1],ext[0]); F32 mag = size.getLength3().getF32()*0.5f; + + const S32 UPDATE_RATE_SLOW = 64; + const S32 UPDATE_RATE_MED = 48; + const S32 UPDATE_RATE_FAST = 32; - F32 impostor_area = 256.f*512.f*(8.125f - LLVOAvatar::sLODFactor*8.f); if (visually_muted) - { // visually muted avatars update at 16 hz - mUpdatePeriod = 16; + { // visually muted avatars update at lowest rate + mUpdatePeriod = UPDATE_RATE_SLOW; } else if (! shouldImpostor() || mDrawable->mDistanceWRTCamera < 1.f + mag) @@ -3889,29 +4065,29 @@ void LLVOAvatar::computeUpdatePeriod() // impostor camera near clip plane mUpdatePeriod = 1; } - else if ( shouldImpostor(4) ) + else if ( shouldImpostor(4.0) ) { //background avatars are REALLY slow updating impostors - mUpdatePeriod = 16; + mUpdatePeriod = UPDATE_RATE_SLOW; } - else if ( shouldImpostor(3) ) - { //back 25% of max visible avatars are slow updating impostors - mUpdatePeriod = 8; + else if (mLastRezzedStatus <= 0) + { + // Don't update cloud avatars too often + mUpdatePeriod = UPDATE_RATE_SLOW; } - else if (mImpostorPixelArea <= impostor_area) - { // stuff in between gets an update period based on pixel area - mUpdatePeriod = llclamp((S32) sqrtf(impostor_area*4.f/mImpostorPixelArea), 2, 8); + else if ( shouldImpostor(3.0) ) + { //back 25% of max visible avatars are slow updating impostors + mUpdatePeriod = UPDATE_RATE_MED; } - else + else { //nearby avatars, update the impostors more frequently. - mUpdatePeriod = 4; + mUpdatePeriod = UPDATE_RATE_FAST; } } else { mUpdatePeriod = 1; } - } //------------------------------------------------------------------------ @@ -4182,7 +4358,33 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w if (!isSitting() && !was_sit_ground_constrained) { root_pos += LLVector3d(getHoverOffset()); - } + if (getOverallAppearance() == AOA_JELLYDOLL) + { + F32 offz = -0.5 * (getScale()[VZ] - mBodySize.mV[VZ]); + root_pos[2] += offz; + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() + // << " frame " << LLFrameTimer::getFrameCount() + // << " root adjust offz " << offz + // << " scalez " << getScale()[VZ] + // << " bsz " << mBodySize.mV[VZ] + // << LL_ENDL; + // } + } + } + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() << " aoa " << (S32) getOverallAppearance() + // << " frame " << LLFrameTimer::getFrameCount() + // << " scalez " << getScale()[VZ] + // << " bsz " << mBodySize.mV[VZ] + // << " root pos " << root_pos[2] + // << " curr rootz " << mRoot->getPosition()[2] + // << " pp-z " << mPelvisp->getPosition()[2] + // << " renderpos " << getRenderPosition() + // << LL_ENDL; + // } LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this); if (cav) @@ -4193,6 +4395,14 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w else { LLVector3 newPosition = gAgent.getPosAgentFromGlobal(root_pos); + // if (!isSelf() && !isControlAvatar()) + // { + // LL_DEBUGS("Avatar") << "av " << getFullname() + // << " frame " << LLFrameTimer::getFrameCount() + // << " newPosition " << newPosition + // << " renderpos " << getRenderPosition() + // << LL_ENDL; + // } if (newPosition != mRoot->getXform()->getWorldPosition()) { mRoot->touch(); @@ -4223,6 +4433,37 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w } //------------------------------------------------------------------------ +// LLVOAvatar::computeNeedsUpdate() +// +// Most of the logic here is to figure out when to periodically update impostors. +// Non-impostors have mUpdatePeriod == 1 and will need update every frame. +//------------------------------------------------------------------------ +bool LLVOAvatar::computeNeedsUpdate() +{ + const F32 MAX_IMPOSTOR_INTERVAL = 4.0f; + computeUpdatePeriod(); + + bool needs_update_by_frame_count = ((LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0); + + bool needs_update_by_max_time = ((gFrameTimeSeconds-mLastImpostorUpdateFrameTime)> MAX_IMPOSTOR_INTERVAL); + bool needs_update = needs_update_by_frame_count || needs_update_by_max_time; + + if (needs_update && !isSelf()) + { + if (needs_update_by_max_time) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 11; + } + else + { + //mNeedsImpostorUpdate = TRUE; + //mLastImpostorUpdateReason = 10; + } + } + return needs_update; +} + // updateCharacter() // // This is called for all avatars, so there are 4 possible situations: @@ -4245,7 +4486,7 @@ void LLVOAvatar::updateRootPositionAndRotation(LLAgent& agent, F32 speed, bool w // simulator. // //------------------------------------------------------------------------ -BOOL LLVOAvatar::updateCharacter(LLAgent &agent) +bool LLVOAvatar::updateCharacter(LLAgent &agent) { updateDebugText(); @@ -4257,6 +4498,7 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) BOOL visible = isVisible(); bool is_control_avatar = isControlAvatar(); // capture state to simplify tracing bool is_attachment = false; + if (is_control_avatar) { LLControlAvatar *cav = dynamic_cast<LLControlAvatar*>(this); @@ -4276,24 +4518,30 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) //-------------------------------------------------------------------- // The rest should only be done occasionally for far away avatars. - // Set mUpdatePeriod and visible based on distance and other criteria. + // Set mUpdatePeriod and visible based on distance and other criteria, + // and flag for impostor update if needed. //-------------------------------------------------------------------- - computeUpdatePeriod(); - visible = (LLDrawable::getCurrentFrame()+mID.mData[0])%mUpdatePeriod == 0 ? TRUE : FALSE; - + bool needs_update = computeNeedsUpdate(); + //-------------------------------------------------------------------- - // Early out if not visible and not self + // Early out if does not need update and not self // don't early out for your own avatar, as we rely on your animations playing reliably // for example, the "turn around" animation when entering customize avatar needs to trigger // even when your avatar is offscreen //-------------------------------------------------------------------- - if (!visible && !isSelf()) + if (!needs_update && !isSelf()) { updateMotions(LLCharacter::HIDDEN_UPDATE); return FALSE; } //-------------------------------------------------------------------- + // Handle transitions between regular rendering, jellydoll, or invisible. + // Can trigger skeleton reset or animation changes + //-------------------------------------------------------------------- + updateOverallAppearance(); + + //-------------------------------------------------------------------- // change animation time quanta based on avatar render load //-------------------------------------------------------------------- // SL-763 the time step quantization does not currently work. @@ -4336,12 +4584,17 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) mSpeed = speed; // update animations - if (mSpecialRenderMode == 1) // Animation Preview + if (!visible) + { + updateMotions(LLCharacter::HIDDEN_UPDATE); + } + else if (mSpecialRenderMode == 1) // Animation Preview { updateMotions(LLCharacter::FORCE_UPDATE); } else { + // Might be better to do HIDDEN_UPDATE if cloud updateMotions(LLCharacter::NORMAL_UPDATE); } @@ -4369,10 +4622,13 @@ BOOL LLVOAvatar::updateCharacter(LLAgent &agent) // Update child joints as needed. mRoot->updateWorldMatrixChildren(); - // System avatar mesh vertices need to be reskinned. - mNeedsSkin = TRUE; + if (visible) + { + // System avatar mesh vertices need to be reskinned. + mNeedsSkin = TRUE; + } - return TRUE; + return visible; } //----------------------------------------------------------------------------- @@ -4655,7 +4911,7 @@ U32 LLVOAvatar::renderSkinned() } } - if (LLViewerShaderMgr::instance()->getVertexShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) + if (LLViewerShaderMgr::instance()->getShaderLevel(LLViewerShaderMgr::SHADER_AVATAR) <= 0) { if (mNeedsSkin) { @@ -4804,19 +5060,29 @@ U32 LLVOAvatar::renderSkinned() BOOL first_pass = TRUE; if (!LLDrawPoolAvatar::sSkipOpaque) { + if (isUIAvatar() && mIsDummy) + { + LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); + if (hair_mesh) + { + num_indices += hair_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); + } + first_pass = FALSE; + } if (!isSelf() || gAgent.needsRenderHead() || LLPipeline::sShadowRender) { - if (isTextureVisible(TEX_HEAD_BAKED) || isUIAvatar()) + + if (isTextureVisible(TEX_HEAD_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* head_mesh = getViewerJoint(MESH_ID_HEAD); if (head_mesh) { - num_indices += head_mesh->render(mAdjustedPixelArea, TRUE, mIsDummy); + num_indices += head_mesh->render(mAdjustedPixelArea, first_pass, mIsDummy); } first_pass = FALSE; } } - if (isTextureVisible(TEX_UPPER_BAKED) || isUIAvatar()) + if (isTextureVisible(TEX_UPPER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* upper_mesh = getViewerJoint(MESH_ID_UPPER_BODY); if (upper_mesh) @@ -4826,7 +5092,7 @@ U32 LLVOAvatar::renderSkinned() first_pass = FALSE; } - if (isTextureVisible(TEX_LOWER_BAKED) || isUIAvatar()) + if (isTextureVisible(TEX_LOWER_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* lower_mesh = getViewerJoint(MESH_ID_LOWER_BODY); if (lower_mesh) @@ -4883,7 +5149,7 @@ U32 LLVOAvatar::renderTransparent(BOOL first_pass) } first_pass = FALSE; } - if (isTextureVisible(TEX_HAIR_BAKED)) + if (isTextureVisible(TEX_HAIR_BAKED) && (getOverallAppearance() != AOA_JELLYDOLL)) { LLViewerJoint* hair_mesh = getViewerJoint(MESH_ID_HAIR); if (hair_mesh) @@ -4931,7 +5197,7 @@ U32 LLVOAvatar::renderRigid() gGL.setAlphaRejectSettings(LLRender::CF_GREATER, 0.5f); } - if (isTextureVisible(TEX_EYES_BAKED) || isUIAvatar()) + if (isTextureVisible(TEX_EYES_BAKED) || (getOverallAppearance() == AOA_JELLYDOLL && !isControlAvatar()) || isUIAvatar()) { LLViewerJoint* eyeball_left = getViewerJoint(MESH_ID_EYEBALL_LEFT); LLViewerJoint* eyeball_right = getViewerJoint(MESH_ID_EYEBALL_RIGHT); @@ -5109,7 +5375,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set<LLUUID>& ids) const { for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); LLViewerFetchedTexture *imagep = NULL; @@ -5118,7 +5384,7 @@ void LLVOAvatar::collectLocalTextureUUIDs(std::set<LLUUID>& ids) const imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); if (texture_dict && texture_dict->mIsLocalTexture) { ids.insert(imagep->getID()); @@ -5252,7 +5518,7 @@ void LLVOAvatar::updateTextures() mHasGrey = FALSE; // debug for (U32 texture_index = 0; texture_index < getNumTEs(); texture_index++) { - LLWearableType::EType wearable_type = LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)texture_index); + LLWearableType::EType wearable_type = LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)texture_index); U32 num_wearables = gAgentWearables.getWearableCount(wearable_type); const LLTextureEntry *te = getTE(texture_index); @@ -5275,7 +5541,7 @@ void LLVOAvatar::updateTextures() imagep = LLViewerTextureManager::staticCastToFetchedTexture(getImage(texture_index, wearable_index), TRUE); if (imagep) { - const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)texture_index); + const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)texture_index); const EBakedTextureIndex baked_index = texture_dict ? texture_dict->mBakedTextureIndex : EBakedTextureIndex::BAKED_NUM_INDICES; if (texture_dict && texture_dict->mIsLocalTexture) { @@ -5318,12 +5584,28 @@ void LLVOAvatar::checkTextureLoading() } if(mLoadedCallbacksPaused == pause) { + if (!pause && mFirstFullyVisible && mLoadedCallbackTextures < mCallbackTextureList.size()) + { + // We still need to update 'loaded' textures count to decide on 'cloud' visibility + // Alternatively this can be done on TextureLoaded callbacks, but is harder to properly track + mLoadedCallbackTextures = 0; + for (LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); + iter != mCallbackTextureList.end(); ++iter) + { + LLViewerFetchedTexture* tex = gTextureList.findImage(*iter); + if (tex && (tex->getDiscardLevel() >= 0 || tex->isMissingAsset())) + { + mLoadedCallbackTextures++; + } + } + } return ; } if(mCallbackTextureList.empty()) //when is self or no callbacks. Note: this list for self is always empty. { mLoadedCallbacksPaused = pause ; + mLoadedCallbackTextures = 0; return ; //nothing to check. } @@ -5331,7 +5613,9 @@ void LLVOAvatar::checkTextureLoading() { return ; //have not been invisible for enough time. } - + + mLoadedCallbackTextures = pause ? mCallbackTextureList.size() : 0; + for(LLLoadedCallbackEntry::source_callback_list_t::iterator iter = mCallbackTextureList.begin(); iter != mCallbackTextureList.end(); ++iter) { @@ -5352,9 +5636,15 @@ void LLVOAvatar::checkTextureLoading() tex->unpauseLoadedCallbacks(&mCallbackTextureList) ; tex->addTextureStats(START_AREA); //jump start the fetching again + + // technically shouldn't need to account for missing, but callback might not have happened yet + if (tex->getDiscardLevel() >= 0 || tex->isMissingAsset()) + { + mLoadedCallbackTextures++; // consider it loaded (we have at least some data) + } } - } - } + } + } if(!pause) { @@ -5426,7 +5716,7 @@ const std::string LLVOAvatar::getImageURL(const U8 te, const LLUUID &uuid) return url; } - const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearanceDictionary::getInstance()->getTexture((ETextureIndex)te); + const LLAvatarAppearanceDictionary::TextureEntry* texture_entry = LLAvatarAppearance::getDictionary()->getTexture((ETextureIndex)te); if (texture_entry != NULL) { url = appearance_service_url + "texture/" + getID().asString() + "/" + texture_entry->mDefaultImageName + "/" + uuid.asString(); @@ -5536,8 +5826,8 @@ void LLVOAvatar::processAnimationStateChanges() stopMotion(ANIM_AGENT_TARGET); if (mEnableDefaultMotions) { - startMotion(ANIM_AGENT_BODY_NOISE); - } + startMotion(ANIM_AGENT_BODY_NOISE); + } } // clear all current animations @@ -5557,23 +5847,32 @@ void LLVOAvatar::processAnimationStateChanges() ++anim_it; } + // if jellydolled, shelve all playing animations + if (getOverallAppearance() != AOA_NORMAL) + { + mPlayingAnimations.clear(); + } + // start up all new anims - for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();) + if (getOverallAppearance() == AOA_NORMAL) { - AnimIterator found_anim = mPlayingAnimations.find(anim_it->first); - - // signaled but not playing, or different sequence id, start motion - if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second) + for (anim_it = mSignaledAnimations.begin(); anim_it != mSignaledAnimations.end();) { - if (processSingleAnimationStateChange(anim_it->first, TRUE)) + AnimIterator found_anim = mPlayingAnimations.find(anim_it->first); + + // signaled but not playing, or different sequence id, start motion + if (found_anim == mPlayingAnimations.end() || found_anim->second != anim_it->second) { - mPlayingAnimations[anim_it->first] = anim_it->second; - ++anim_it; - continue; + if (processSingleAnimationStateChange(anim_it->first, TRUE)) + { + mPlayingAnimations[anim_it->first] = anim_it->second; + ++anim_it; + continue; + } } - } - ++anim_it; + ++anim_it; + } } // clear source information for animations which have been stopped @@ -6136,6 +6435,11 @@ void LLVOAvatar::addAttachmentOverridesForObject(LLViewerObject *vo, std::set<LL } LLScopedContextString str("addAttachmentOverridesForObject " + getFullname()); + + if (getOverallAppearance() != AOA_NORMAL) + { + return; + } LL_DEBUGS("AnimatedObjects") << "adding" << LL_ENDL; dumpStack("AnimatedObjectsStack"); @@ -6576,7 +6880,7 @@ void LLVOAvatar::initAttachmentPoints(bool ignore_hud_joints) LLAvatarXmlInfo::LLAvatarAttachmentInfo *info = *iter; if (info->mIsHUDAttachment && (!isSelf() || ignore_hud_joints)) { - //don't process hud joint for other avatars, or when doing a skeleton reset. + //don't process hud joint for other avatars. continue; } @@ -6794,13 +7098,13 @@ LLDrawable *LLVOAvatar::createDrawable(LLPipeline *pipeline) pipeline->allocDrawable(this); mDrawable->setLit(FALSE); - LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*) gPipeline.getPool(LLDrawPool::POOL_AVATAR); + LLDrawPoolAvatar *poolp = (LLDrawPoolAvatar*)gPipeline.getPool(mIsControlAvatar ? LLDrawPool::POOL_CONTROL_AV : LLDrawPool::POOL_AVATAR); // Only a single face (one per avatar) //this face will be splitted into several if its vertex buffer is too long. mDrawable->setState(LLDrawable::ACTIVE); mDrawable->addFace(poolp, NULL); - mDrawable->setRenderType(LLPipeline::RENDER_TYPE_AVATAR); + mDrawable->setRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR); mNumInitFaces = mDrawable->getNumFaces() ; @@ -6825,7 +7129,7 @@ static LLTrace::BlockTimerStatHandle FTM_UPDATE_AVATAR("Update Avatar"); BOOL LLVOAvatar::updateGeometry(LLDrawable *drawable) { LL_RECORD_BLOCK_TIME(FTM_UPDATE_AVATAR); - if (!(gPipeline.hasRenderType(LLPipeline::RENDER_TYPE_AVATAR))) + if (!(gPipeline.hasRenderType(mIsControlAvatar ? LLPipeline::RENDER_TYPE_CONTROL_AV : LLPipeline::RENDER_TYPE_AVATAR))) { return TRUE; } @@ -7061,20 +7365,7 @@ U32 LLVOAvatar::getNumAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAttachments() const { - const S32 MAX_AGENT_ATTACHMENTS = 38; - - S32 max_attach = MAX_AGENT_ATTACHMENTS; - - if (gAgent.getRegion()) - { - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (features.has("MaxAgentAttachments")) - { - max_attach = features["MaxAgentAttachments"].asInteger(); - } - } - return max_attach; + return LLAgentBenefitsMgr::current().getAttachmentLimit(); } //----------------------------------------------------------------------------- @@ -7108,24 +7399,7 @@ U32 LLVOAvatar::getNumAnimatedObjectAttachments() const //----------------------------------------------------------------------------- S32 LLVOAvatar::getMaxAnimatedObjectAttachments() const { - S32 max_attach = 0; - if (gSavedSettings.getBOOL("AnimatedObjectsIgnoreLimits")) - { - max_attach = getMaxAttachments(); - } - else - { - if (gAgent.getRegion()) - { - LLSD features; - gAgent.getRegion()->getSimulatorFeatures(features); - if (features.has("AnimatedObjects")) - { - max_attach = features["AnimatedObjects"]["MaxAgentAnimatedObjectAttachments"].asInteger(); - } - } - } - return max_attach; + return LLAgentBenefitsMgr::current().getAnimatedObjectLimit(); } //----------------------------------------------------------------------------- @@ -7363,7 +7637,8 @@ void LLVOAvatar::sitOnObject(LLViewerObject *sit_object) mRoot->updateWorldMatrixChildren(); stopMotion(ANIM_AGENT_BODY_NOISE); - + + gAgentCamera.setInitSitRot(gAgent.getFrameAgent().getQuaternion()); } //----------------------------------------------------------------------------- @@ -7490,8 +7765,8 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const break; // Do nothing } - for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - tex_iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator tex_iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + tex_iter != LLAvatarAppearance::getDictionary()->getTextures().end(); ++tex_iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = tex_iter->second; @@ -7504,7 +7779,7 @@ BOOL LLVOAvatar::isWearingWearableType(LLWearableType::EType type) const if (texture_dict->mIsUsedByBakedTexture) { const EBakedTextureIndex baked_index = texture_dict->mBakedTextureIndex; - return isTextureDefined(LLAvatarAppearanceDictionary::getInstance()->getBakedTexture(baked_index)->mTextureIndex); + return isTextureDefined(LLAvatarAppearance::getDictionary()->getBakedTexture(baked_index)->mTextureIndex); } return FALSE; } @@ -7584,9 +7859,15 @@ void LLVOAvatar::onGlobalColorChanged(const LLTexGlobalColor* global_color) } // virtual +// Do rigged mesh attachments display with this av? bool LLVOAvatar::shouldRenderRigged() const { - return true; + if (getOverallAppearance() == AOA_NORMAL) + { + return true; + } + // TBD - render for AOA_JELLYDOLL? + return false; } // FIXME: We have an mVisible member, set in updateVisibility(), but this @@ -7618,14 +7899,13 @@ bool LLVOAvatar::getIsCloud() const ); } -void LLVOAvatar::updateRezzedStatusTimers() +void LLVOAvatar::updateRezzedStatusTimers(S32 rez_status) { // State machine for rezzed status. Statuses are -1 on startup, 0 // = cloud, 1 = gray, 2 = downloading, 3 = full. // Purpose is to collect time data for each it takes avatar to reach // various loading landmarks: gray, textured (partial), textured fully. - S32 rez_status = getRezzedStatus(); if (rez_status != mLastRezzedStatus) { LL_DEBUGS("Avatar") << avString() << "rez state change: " << mLastRezzedStatus << " -> " << rez_status << LL_ENDL; @@ -7795,8 +8075,21 @@ void LLVOAvatar::logMetricsTimerRecord(const std::string& phase_name, F32 elapse // returns true if the value has changed. BOOL LLVOAvatar::updateIsFullyLoaded() { - const bool loading = getIsCloud(); - updateRezzedStatusTimers(); + S32 rez_status = getRezzedStatus(); + bool loading = getIsCloud(); + if (mFirstFullyVisible && !mIsControlAvatar) + { + loading = ((rez_status < 2) + // Wait at least 60s for unfinished textures to finish on first load, + // don't wait forever, it might fail. Even if it will eventually load by + // itself and update mLoadedCallbackTextures (or fail and clean the list), + // avatars are more time-sensitive than textures and can't wait that long. + || (mLoadedCallbackTextures < mCallbackTextureList.size() && mLastTexCallbackAddedTime.getElapsedTimeF32() < MAX_TEXTURE_WAIT_TIME_SEC) + || !mPendingAttachment.empty() + || (rez_status < 3 && !isFullyBaked()) + ); + } + updateRezzedStatusTimers(rez_status); updateRuthTimer(loading); return processFullyLoadedChange(loading); } @@ -7832,13 +8125,22 @@ void LLVOAvatar::updateRuthTimer(bool loading) BOOL LLVOAvatar::processFullyLoadedChange(bool loading) { - // we wait a little bit before giving the all clear, - // to let textures settle down - const F32 PAUSE = 1.f; + // We wait a little bit before giving the 'all clear', to let things to + // settle down (models to snap into place, textures to get first packets) + const F32 LOADED_DELAY = 1.f; + const F32 FIRST_USE_DELAY = 3.f; + if (loading) mFullyLoadedTimer.reset(); - - mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > PAUSE); + + if (mFirstFullyVisible) + { + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > FIRST_USE_DELAY); + } + else + { + mFullyLoaded = (mFullyLoadedTimer.getElapsedTimeF32() > LOADED_DELAY); + } if (!mPreviousFullyLoaded && !loading && mFullyLoaded) { @@ -7846,12 +8148,14 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) } // did our loading state "change" from last call? - // runway - why are we updating every 30 calls even if nothing has changed? + // FIXME runway - why are we updating every 30 calls even if nothing has changed? + // This causes updateLOD() to run every 30 frames, among other things. const S32 UPDATE_RATE = 30; BOOL changed = ((mFullyLoaded != mPreviousFullyLoaded) || // if the value is different from the previous call (!mFullyLoadedInitialized) || // if we've never been called before (mFullyLoadedFrameCounter % UPDATE_RATE == 0)); // every now and then issue a change + BOOL fully_loaded_changed = (mFullyLoaded != mPreviousFullyLoaded); mPreviousFullyLoaded = mFullyLoaded; mFullyLoadedInitialized = TRUE; @@ -7862,7 +8166,13 @@ BOOL LLVOAvatar::processFullyLoadedChange(bool loading) // to know about outfit switching LLAvatarRenderNotifier::getInstance()->updateNotificationState(); } - + + if (fully_loaded_changed && !isSelf() && mFullyLoaded && isImpostor()) + { + // Fix for jellydoll initially invisible + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 6; + } return changed; } @@ -7934,47 +8244,25 @@ void LLVOAvatar::updateMeshVisibility() bool bake_flag[BAKED_NUM_INDICES]; memset(bake_flag, 0, BAKED_NUM_INDICES*sizeof(bool)); - for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); - iter != mAttachmentPoints.end(); - ++iter) + if (getOverallAppearance() == AOA_NORMAL) { - LLViewerJointAttachment* attachment = iter->second; - if (attachment) + for (attachment_map_t::iterator iter = mAttachmentPoints.begin(); + iter != mAttachmentPoints.end(); + ++iter) { - for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); - attachment_iter != attachment->mAttachedObjects.end(); - ++attachment_iter) + LLViewerJointAttachment* attachment = iter->second; + if (attachment) { - LLViewerObject *objectp = attachment_iter->get(); - if (objectp) - { - for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++) - { - LLTextureEntry* tex_entry = objectp->getTE(face_index); - bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); - bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); - bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); - bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); - bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); - bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); - bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); - bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); - bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); - bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); - bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); - } - } - - LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); - for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); - iter1 != child_list.end(); ++iter1) + for (LLViewerJointAttachment::attachedobjs_vec_t::iterator attachment_iter = attachment->mAttachedObjects.begin(); + attachment_iter != attachment->mAttachedObjects.end(); + ++attachment_iter) { - LLViewerObject* objectchild = *iter1; - if (objectchild) + LLViewerObject *objectp = attachment_iter->get(); + if (objectp) { - for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++) + for (int face_index = 0; face_index < objectp->getNumTEs(); face_index++) { - LLTextureEntry* tex_entry = objectchild->getTE(face_index); + LLTextureEntry* tex_entry = objectp->getTE(face_index); bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); @@ -7988,6 +8276,31 @@ void LLVOAvatar::updateMeshVisibility() bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); } } + + LLViewerObject::const_child_list_t& child_list = objectp->getChildren(); + for (LLViewerObject::child_list_t::const_iterator iter1 = child_list.begin(); + iter1 != child_list.end(); ++iter1) + { + LLViewerObject* objectchild = *iter1; + if (objectchild) + { + for (int face_index = 0; face_index < objectchild->getNumTEs(); face_index++) + { + LLTextureEntry* tex_entry = objectchild->getTE(face_index); + bake_flag[BAKED_HEAD] |= (tex_entry->getID() == IMG_USE_BAKED_HEAD); + bake_flag[BAKED_EYES] |= (tex_entry->getID() == IMG_USE_BAKED_EYES); + bake_flag[BAKED_HAIR] |= (tex_entry->getID() == IMG_USE_BAKED_HAIR); + bake_flag[BAKED_LOWER] |= (tex_entry->getID() == IMG_USE_BAKED_LOWER); + bake_flag[BAKED_UPPER] |= (tex_entry->getID() == IMG_USE_BAKED_UPPER); + bake_flag[BAKED_SKIRT] |= (tex_entry->getID() == IMG_USE_BAKED_SKIRT); + bake_flag[BAKED_LEFT_ARM] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTARM); + bake_flag[BAKED_LEFT_LEG] |= (tex_entry->getID() == IMG_USE_BAKED_LEFTLEG); + bake_flag[BAKED_AUX1] |= (tex_entry->getID() == IMG_USE_BAKED_AUX1); + bake_flag[BAKED_AUX2] |= (tex_entry->getID() == IMG_USE_BAKED_AUX2); + bake_flag[BAKED_AUX3] |= (tex_entry->getID() == IMG_USE_BAKED_AUX3); + } + } + } } } } @@ -8128,6 +8441,7 @@ void LLVOAvatar::updateMeshTextures() LLViewerTexLayerSet* layerset = getTexLayerSet(i); if (use_lkg_baked_layer[i] && !isUsingLocalAppearance() ) { + // use last known good layer (no new one) LLViewerFetchedTexture* baked_img = LLViewerTextureManager::getFetchedTexture(mBakedTextureDatas[i].mLastTextureID); mBakedTextureDatas[i].mIsUsed = TRUE; @@ -8146,6 +8460,7 @@ void LLVOAvatar::updateMeshTextures() } else if (!isUsingLocalAppearance() && is_layer_baked[i]) { + // use new layer LLViewerFetchedTexture* baked_img = LLViewerTextureManager::staticCastToFetchedTexture( getImage( mBakedTextureDatas[i].mTextureIndex, 0 ), TRUE) ; @@ -8165,10 +8480,15 @@ void LLVOAvatar::updateMeshTextures() ((i == BAKED_HEAD) || (i == BAKED_UPPER) || (i == BAKED_LOWER)) ) { baked_img->setLoadedCallback(onBakedTextureMasksLoaded, MORPH_MASK_REQUESTED_DISCARD, TRUE, TRUE, new LLTextureMaskData( mID ), - src_callback_list, paused); + src_callback_list, paused); } baked_img->setLoadedCallback(onBakedTextureLoaded, SWITCH_TO_BAKED_DISCARD, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); + if (baked_img->getDiscardLevel() < 0 && !paused) + { + // mLoadedCallbackTextures will be updated by checkTextureLoading() below + mLastTexCallbackAddedTime.reset(); + } // this could add paused texture callbacks mLoadedCallbacksPaused |= paused; @@ -8222,8 +8542,8 @@ void LLVOAvatar::updateMeshTextures() for (LLAvatarAppearanceDictionary::BakedTextures::const_iterator baked_iter = - LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().begin(); - baked_iter != LLAvatarAppearanceDictionary::getInstance()->getBakedTextures().end(); + LLAvatarAppearance::getDictionary()->getBakedTextures().begin(); + baked_iter != LLAvatarAppearance::getDictionary()->getBakedTextures().end(); ++baked_iter) { const EBakedTextureIndex baked_index = baked_iter->first; @@ -8401,7 +8721,7 @@ void LLVOAvatar::releaseComponentTextures() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { - const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + const LLAvatarAppearanceDictionary::BakedEntry * bakedDicEntry = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); // skip if this is a skirt and av is not wearing one, or if we don't have a baked texture UUID if (!isTextureDefined(bakedDicEntry->mTextureIndex) && ( (baked_index != BAKED_SKIRT) || isWearingWearableType(LLWearableType::WT_SKIRT) )) @@ -8420,8 +8740,8 @@ void LLVOAvatar::releaseComponentTextures() void LLVOAvatar::dumpAvatarTEs( const std::string& context ) const { LL_DEBUGS("Avatar") << avString() << (isSelf() ? "Self: " : "Other: ") << context << LL_ENDL; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); ++iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; @@ -8562,13 +8882,16 @@ void LLVOAvatar::onFirstTEMessageReceived() LL_DEBUGS("Avatar") << avString() << "layer_baked, setting onInitialBakedTextureLoaded as callback" << LL_ENDL; image->setLoadedCallback( onInitialBakedTextureLoaded, MAX_DISCARD_LEVEL, FALSE, FALSE, new LLUUID( mID ), src_callback_list, paused ); - + if (image->getDiscardLevel() < 0 && !paused) + { + mLastTexCallbackAddedTime.reset(); + } // this could add paused texture callbacks mLoadedCallbacksPaused |= paused; } } - mMeshTexturesDirty = TRUE; + mMeshTexturesDirty = TRUE; gPipeline.markGLRebuild(this); } } @@ -8908,7 +9231,11 @@ void LLVOAvatar::processAvatarAppearance( LLMessageSystem* mesgsys ) mLastProcessedAppearance = contents; bool slam_params = false; - applyParsedAppearanceMessage(*contents, slam_params); + applyParsedAppearanceMessage(*contents, slam_params); + if (getOverallAppearance() != AOA_NORMAL) + { + resetSkeleton(false); + } } void LLVOAvatar::applyParsedAppearanceMessage(LLAppearanceMessageContents& contents, bool slam_params) @@ -9167,8 +9494,8 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture self->mBakedTextureDatas[BAKED_HEAD].mTexLayerSet->applyMorphMask(aux_src->getData(), aux_src->getWidth(), aux_src->getHeight(), 1); maskData->mLastDiscardLevel = discard_level; */ BOOL found_texture_id = false; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); ++iter) { @@ -9215,8 +9542,6 @@ void LLVOAvatar::onBakedTextureMasksLoaded( BOOL success, LLViewerFetchedTexture // static void LLVOAvatar::onInitialBakedTextureLoaded( BOOL success, LLViewerFetchedTexture *src_vi, LLImageRaw* src, LLImageRaw* aux_src, S32 discard_level, BOOL final, void* userdata ) { - - LLUUID *avatar_idp = (LLUUID *)userdata; LLVOAvatar *selfp = (LLVOAvatar *)gObjectList.findObject(*avatar_idp); @@ -9301,7 +9626,7 @@ void LLVOAvatar::useBakedTexture( const LLUUID& id ) } const LLAvatarAppearanceDictionary::BakedEntry *baked_dict = - LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)i); + LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)i); for (texture_vec_t::const_iterator local_tex_iter = baked_dict->mLocalTextures.begin(); local_tex_iter != baked_dict->mLocalTextures.end(); ++local_tex_iter) @@ -9436,7 +9761,7 @@ void LLVOAvatar::dumpArchetypeXML(const std::string& prefix, bool group_by_weara for (U8 te = 0; te < TEX_NUM_INDICES; te++) { - if (LLAvatarAppearanceDictionary::getTEWearableType((ETextureIndex)te) == type) + if (LLAvatarAppearance::getDictionary()->getTEWearableType((ETextureIndex)te) == type) { // MULTIPLE_WEARABLES: extend to multiple wearables? LLViewerTexture* te_image = getImage((ETextureIndex)te, 0); @@ -9803,7 +10128,7 @@ BOOL LLVOAvatar::updateLOD() return FALSE; } - if (isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry()) + if (!LLPipeline::sImpostorRender && isImpostor() && 0 != mDrawable->getNumFaces() && mDrawable->getFace(0)->hasGeometry()) { return TRUE; } @@ -9981,7 +10306,7 @@ void LLVOAvatar::onActiveOverrideMeshesChanged() U32 LLVOAvatar::getPartitionType() const { // Avatars merely exist as drawables in the bridge partition - return LLViewerRegion::PARTITION_BRIDGE; + return mIsControlAvatar ? LLViewerRegion::PARTITION_CONTROL_AV : LLViewerRegion::PARTITION_AVATAR; } //static @@ -9994,10 +10319,10 @@ void LLVOAvatar::updateImpostors() iter != instances_copy.end(); ++iter) { LLVOAvatar* avatar = (LLVOAvatar*) *iter; - if (!avatar->isDead() && avatar->isVisible() - && ( - (avatar->isImpostor() || LLVOAvatar::AV_DO_NOT_RENDER == avatar->getVisualMuteSettings()) && avatar->needsImpostorUpdate()) - ) + if (!avatar->isDead() + && avatar->isVisible() + && avatar->isImpostor() + && avatar->needsImpostorUpdate()) { avatar->calcMutedAVColor(); gPipeline.generateImpostor(avatar); @@ -10010,12 +10335,20 @@ void LLVOAvatar::updateImpostors() // virtual BOOL LLVOAvatar::isImpostor() { - return sUseImpostors && (isVisuallyMuted() || (mUpdatePeriod >= IMPOSTOR_PERIOD)) ? TRUE : FALSE; + return isVisuallyMuted() || (sLimitNonImpostors && (mUpdatePeriod > 1)); } -BOOL LLVOAvatar::shouldImpostor(const U32 rank_factor) const +BOOL LLVOAvatar::shouldImpostor(const F32 rank_factor) { - return (!isSelf() && sUseImpostors && mVisibilityRank > (sMaxNonImpostors * rank_factor)); + if (isSelf()) + { + return false; + } + if (isVisuallyMuted()) + { + return true; + } + return sLimitNonImpostors && (mVisibilityRank > sMaxNonImpostors * rank_factor); } BOOL LLVOAvatar::needsImpostorUpdate() const @@ -10058,16 +10391,16 @@ void LLVOAvatar::getImpostorValues(LLVector4a* extents, LLVector3& angle, F32& d } // static -const U32 LLVOAvatar::IMPOSTORS_OFF = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors +const U32 LLVOAvatar::NON_IMPOSTORS_MAX_SLIDER = 66; /* Must equal the maximum allowed the RenderAvatarMaxNonImpostors * slider in panel_preferences_graphics1.xml */ // static void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue) { U32 oldmax = sMaxNonImpostors; - bool oldflg = sUseImpostors; + bool oldflg = sLimitNonImpostors; - if (IMPOSTORS_OFF <= newMaxNonImpostorsValue) + if (NON_IMPOSTORS_MAX_SLIDER <= newMaxNonImpostorsValue) { sMaxNonImpostors = 0; } @@ -10075,13 +10408,13 @@ void LLVOAvatar::updateImpostorRendering(U32 newMaxNonImpostorsValue) { sMaxNonImpostors = newMaxNonImpostorsValue; } - // the sUseImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0) - sUseImpostors = (0 != sMaxNonImpostors); - if ( oldflg != sUseImpostors ) + // the sLimitNonImpostors flag depends on whether or not sMaxNonImpostors is set to the no-limit value (0) + sLimitNonImpostors = (0 != sMaxNonImpostors); + if ( oldflg != sLimitNonImpostors ) { LL_DEBUGS("AvatarRender") << "was " << (oldflg ? "use" : "don't use" ) << " impostors (max " << oldmax << "); " - << "now " << (sUseImpostors ? "use" : "don't use" ) << " impostors (max " << sMaxNonImpostors << "); " + << "now " << (sLimitNonImpostors ? "use" : "don't use" ) << " impostors (max " << sMaxNonImpostors << "); " << LL_ENDL; } } @@ -10102,7 +10435,10 @@ void LLVOAvatar::idleUpdateRenderComplexity() // Render Complexity calculateUpdateRenderComplexity(); // Update mVisualComplexity if needed +} +void LLVOAvatar::idleUpdateDebugInfo() +{ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_AVATAR_DRAW_INFO)) { std::string info_line; @@ -10335,7 +10671,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() // Diagnostic list of all textures on our avatar static std::set<LLUUID> all_textures; - if (mVisualComplexityStale) + if (mVisualComplexityStale) { U32 cost = VISUAL_COMPLEXITY_UNKNOWN; LLVOVolume::texture_cost_t textures; @@ -10344,7 +10680,7 @@ void LLVOAvatar::calculateUpdateRenderComplexity() for (U8 baked_index = 0; baked_index < BAKED_NUM_INDICES; baked_index++) { const LLAvatarAppearanceDictionary::BakedEntry *baked_dict - = LLAvatarAppearanceDictionary::getInstance()->getBakedTexture((EBakedTextureIndex)baked_index); + = LLAvatarAppearance::getDictionary()->getBakedTexture((EBakedTextureIndex)baked_index); ETextureIndex tex_index = baked_dict->mTextureIndex; if ((tex_index != TEX_SKIRT_BAKED) || (isWearingWearableType(LLWearableType::WT_SKIRT))) { @@ -10409,8 +10745,8 @@ void LLVOAvatar::calculateUpdateRenderComplexity() } // print any avatar textures we didn't already know about - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); ++iter) { const LLAvatarAppearanceDictionary::TextureEntry *texture_dict = iter->second; @@ -10463,10 +10799,178 @@ void LLVOAvatar::setVisualMuteSettings(VisualMuteSettings set) { mVisuallyMuteSetting = set; mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 7; LLRenderMuteList::getInstance()->saveVisualMuteSetting(getID(), S32(set)); } + +void LLVOAvatar::setOverallAppearanceNormal() +{ + if (isControlAvatar()) + return; + + LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); + resetSkeleton(false); + getJoint("mPelvis")->setPosition(pelvis_pos); + + for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) + { + bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); + LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; + if (!is_playing) + { + // Anim was not requested for this av by sim, but may be playing locally + stopMotion(*it); + } + } + mJellyAnims.clear(); + + processAnimationStateChanges(); +} + +void LLVOAvatar::setOverallAppearanceJellyDoll() +{ + if (isControlAvatar()) + return; + + // stop current animations + { + for ( LLVOAvatar::AnimIterator anim_it= mPlayingAnimations.begin(); + anim_it != mPlayingAnimations.end(); + ++anim_it) + { + { + stopMotion(anim_it->first, TRUE); + } + } + } + processAnimationStateChanges(); + + // Start any needed anims for jellydoll + updateOverallAppearanceAnimations(); + + LLVector3 pelvis_pos = getJoint("mPelvis")->getPosition(); + resetSkeleton(false); + getJoint("mPelvis")->setPosition(pelvis_pos); + +} + +void LLVOAvatar::setOverallAppearanceInvisible() +{ +} + +void LLVOAvatar::updateOverallAppearance() +{ + AvatarOverallAppearance new_overall = getOverallAppearance(); + if (new_overall != mOverallAppearance) + { + switch (new_overall) + { + case AOA_NORMAL: + setOverallAppearanceNormal(); + break; + case AOA_JELLYDOLL: + setOverallAppearanceJellyDoll(); + break; + case AOA_INVISIBLE: + setOverallAppearanceInvisible(); + break; + } + mOverallAppearance = new_overall; + if (!isSelf()) + { + mNeedsImpostorUpdate = TRUE; + mLastImpostorUpdateReason = 8; + } + updateMeshVisibility(); + } + + // This needs to be done even if overall appearance has not + // changed, since sit/stand status can be different. + updateOverallAppearanceAnimations(); +} + +void LLVOAvatar::updateOverallAppearanceAnimations() +{ + if (isControlAvatar()) + return; + + if (getOverallAppearance() == AOA_JELLYDOLL) + { + LLUUID motion_id; + if (isSitting() && getParent()) // sitting on object + { + motion_id = ANIM_AGENT_SIT_FEMALE; + } + else if (isSitting()) // sitting on ground + { + motion_id = ANIM_AGENT_SIT_GROUND_CONSTRAINED; + } + else // standing + { + motion_id = ANIM_AGENT_STAND; + } + if (mJellyAnims.find(motion_id) == mJellyAnims.end()) + { + for (auto it = mJellyAnims.begin(); it != mJellyAnims.end(); ++it) + { + bool is_playing = (mPlayingAnimations.find(*it) != mPlayingAnimations.end()); + LL_DEBUGS("Avatar") << "jelly anim " << *it << " " << is_playing << LL_ENDL; + if (!is_playing) + { + // Anim was not requested for this av by sim, but may be playing locally + stopMotion(*it, TRUE); + } + } + mJellyAnims.clear(); + + startMotion(motion_id); + mJellyAnims.insert(motion_id); + + processAnimationStateChanges(); + } + } +} + +// Based on isVisuallyMuted(), but has 3 possible results. +LLVOAvatar::AvatarOverallAppearance LLVOAvatar::getOverallAppearance() const +{ + AvatarOverallAppearance result = AOA_NORMAL; + + // Priority order (highest priority first) + // * own avatar is always drawn normally + // * if on the "always draw normally" list, draw them normally + // * if on the "always visually mute" list, show as jellydoll + // * if explicitly muted (blocked), show as invisible + // * check against the render cost and attachment limits - if too complex, show as jellydoll + if (isSelf()) + { + result = AOA_NORMAL; + } + else // !isSelf() + { + if (isInMuteList()) + { + result = AOA_INVISIBLE; + } + else if (mVisuallyMuteSetting == AV_ALWAYS_RENDER) + { + result = AOA_NORMAL; + } + else if (mVisuallyMuteSetting == AV_DO_NOT_RENDER) + { // Always want to see this AV as an impostor + result = AOA_JELLYDOLL; + } + else if (isTooComplex()) + { + result = AOA_JELLYDOLL; + } + } + + return result; +} + void LLVOAvatar::calcMutedAVColor() { LLColor4 new_color(mMutedAVColor); @@ -10476,8 +10980,8 @@ void LLVOAvatar::calcMutedAVColor() if (getVisualMuteSettings() == AV_DO_NOT_RENDER) { // explicitly not-rendered avatars are light grey - new_color = LLColor4::grey3; - change_msg = " not rendered: color is grey3"; + new_color = LLColor4::grey4; + change_msg = " not rendered: color is grey4"; } else if (LLMuteList::getInstance()->isMuted(av_id)) // the user blocked them { @@ -10490,26 +10994,31 @@ void LLVOAvatar::calcMutedAVColor() new_color = LLColor4::white; change_msg = " simple imposter "; } +#ifdef COLORIZE_JELLYDOLLS else if ( mMutedAVColor == LLColor4::white || mMutedAVColor == LLColor4::grey3 || mMutedAVColor == LLColor4::grey4 ) - { + { // select a color based on the first byte of the agents uuid so any muted agent is always the same color F32 color_value = (F32) (av_id.mData[0]); - F32 spectrum = (color_value / 256.0); // spectrum is between 0 and 1.f + F32 spectrum = (color_value / 256.0); // spectrum is between 0 and 1.f - // Array of colors. These are arranged so only one RGB color changes between each step, + // Array of colors. These are arranged so only one RGB color changes between each step, // and it loops back to red so there is an even distribution. It is not a heat map - const S32 NUM_SPECTRUM_COLORS = 7; + const S32 NUM_SPECTRUM_COLORS = 7; static LLColor4 * spectrum_color[NUM_SPECTRUM_COLORS] = { &LLColor4::red, &LLColor4::magenta, &LLColor4::blue, &LLColor4::cyan, &LLColor4::green, &LLColor4::yellow, &LLColor4::red }; - - spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1); // Scale to range of number of colors - S32 spectrum_index_1 = floor(spectrum); // Desired color will be after this index - S32 spectrum_index_2 = spectrum_index_1 + 1; // and before this index (inclusive) + + spectrum = spectrum * (NUM_SPECTRUM_COLORS - 1); // Scale to range of number of colors + S32 spectrum_index_1 = floor(spectrum); // Desired color will be after this index + S32 spectrum_index_2 = spectrum_index_1 + 1; // and before this index (inclusive) F32 fractBetween = spectrum - (F32)(spectrum_index_1); // distance between the two indexes (0-1) - - new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); - new_color.normalize(); - new_color *= 0.28f; // Tone it down + new_color = lerp(*spectrum_color[spectrum_index_1], *spectrum_color[spectrum_index_2], fractBetween); + new_color.normalize(); + new_color *= 0.28f; // Tone it down + } +#endif + else + { + new_color = LLColor4::grey4; change_msg = " over limit color "; } @@ -10525,7 +11034,7 @@ BOOL LLVOAvatar::isIndexLocalTexture(ETextureIndex index) { return (index < 0 || index >= TEX_NUM_INDICES) ? false - : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsLocalTexture; + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsLocalTexture; } // static @@ -10533,15 +11042,15 @@ BOOL LLVOAvatar::isIndexBakedTexture(ETextureIndex index) { return (index < 0 || index >= TEX_NUM_INDICES) ? false - : LLAvatarAppearanceDictionary::getInstance()->getTexture(index)->mIsBakedTexture; + : LLAvatarAppearance::getDictionary()->getTexture(index)->mIsBakedTexture; } const std::string LLVOAvatar::getBakedStatusForPrintout() const { std::string line; - for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearanceDictionary::getInstance()->getTextures().begin(); - iter != LLAvatarAppearanceDictionary::getInstance()->getTextures().end(); + for (LLAvatarAppearanceDictionary::Textures::const_iterator iter = LLAvatarAppearance::getDictionary()->getTextures().begin(); + iter != LLAvatarAppearance::getDictionary()->getTextures().end(); ++iter) { const ETextureIndex index = iter->first; |