//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::update() { static const LLCachedControl<bool> show_look_at("AscentShowLookAt", false); // If the target object is dead, set the target object to NULL if (!mTargetObject.isNull() && mTargetObject->isDead()) { clearLookAtTarget(); } // if source avatar is null or dead, mark self as dead and return if (mSourceObject.isNull() || mSourceObject->isDead()) { markDead(); return; } // make sure the proper set of avatar attention are currently being used. LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; // for now the first cut will just switch on sex. future development could adjust // timeouts according to avatar age and/or other features. mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); F32 time = mTimer.getElapsedTimeF32(); // clear out the effect if time is up if (mKillTime != 0.f && time > mKillTime) { if (mTargetType != LOOKAT_TARGET_NONE) { clearLookAtTarget(); // look at timed out (only happens on own avatar), so tell everyone setNeedsSendToSim(TRUE); } } if (mTargetType != LOOKAT_TARGET_NONE) { if (calcTargetPosition()) { //LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); //if (!head_motion || head_motion->isStopped()) // singu: startMotion does basically the same as the above two lines... it starts it, unless it was already started. { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); } } } // Singu note: this displays extra information for look at targets. Due to the bug in llvoavatar.cpp // it was never displayed before and is not something users exect: turning it off for now #if 0 if (show_look_at) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); } #endif }
//----------------------------------------------------------------------------- // update() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::update() { LLHUDEffectLookAt::sDebugLookAt = gSavedSettings.getBOOL("PersistShowLookAt"); // If the target object is dead, set the target object to NULL if (!mTargetObject.isNull() && mTargetObject->isDead()) { clearLookAtTarget(); } // if source avatar is null or dead, mark self as dead and return if (mSourceObject.isNull() || mSourceObject->isDead()) { markDead(); return; } // make sure the proper set of avatar attention are currently being used. LLVOAvatar* source_avatar = (LLVOAvatar*)(LLViewerObject*)mSourceObject; // for now the first cut will just switch on sex. future development could adjust // timeouts according to avatar age and/or other features. mAttentions = (source_avatar->getSex() == SEX_MALE) ? &gBoyAttentions : &gGirlAttentions; //printf("updated to %s\n", (source_avatar->getSex() == SEX_MALE) ? "male" : "female"); F32 time = mTimer.getElapsedTimeF32(); // clear out the effect if time is up if (mKillTime != 0.f && time > mKillTime) { if (mTargetType != LOOKAT_TARGET_NONE) { clearLookAtTarget(); // look at timed out (only happens on own avatar), so tell everyone setNeedsSendToSim(TRUE); } } if (mTargetType != LOOKAT_TARGET_NONE) { if (calcTargetPosition()) { LLMotion* head_motion = ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->findMotion(ANIM_AGENT_HEAD_ROT); if (!head_motion || head_motion->isStopped()) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_HEAD_ROT); } } } if (sDebugLookAt) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->addDebugText((*mAttentions)[mTargetType].mName); } }
//----------------------------------------------------------------------------- // setLookAt() // called by agent logic to set look at behavior locally, and propagate to sim //----------------------------------------------------------------------------- BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) { if (!mSourceObject) { return FALSE; } if (target_type >= LOOKAT_NUM_TARGETS) { llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl; return FALSE; } // must be same or higher priority than existing effect if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) { return FALSE; } F32 current_time = mTimer.getElapsedTimeF32(); // type of lookat behavior or target object has changed BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); // lookat position has moved a certain amount and we haven't just sent an update lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); if (lookAtChanged) { mLastSentOffsetGlobal = position; F32 timeout = (*mAttentions)[target_type].mTimeout; setDuration(timeout); setNeedsSendToSim(TRUE); } if (target_type == LOOKAT_TARGET_CLEAR) { clearLookAtTarget(); } else { mTargetType = target_type; mTargetObject = object; if (object) { mTargetOffsetGlobal.setVec(position); } else { mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); } mKillTime = mTimer.getElapsedTimeF32() + mDuration; update(); } return TRUE; }
//----------------------------------------------------------------------------- // markDead() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::markDead() { if (mSourceObject.notNull()) { ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("LookAtPoint"); } mSourceObject = NULL; clearLookAtTarget(); LLHUDEffect::markDead(); }
//----------------------------------------------------------------------------- // LLHUDEffectLookAt() //----------------------------------------------------------------------------- LLHUDEffectLookAt::LLHUDEffectLookAt(const U8 type) : LLHUDEffect(type), mKillTime(0.f), mLastSendTime(0.f) { clearLookAtTarget(); // parse the default sets loadAttentions(); // initialize current attention set. switches when avatar sex changes. mAttentions = &gGirlAttentions; }
//----------------------------------------------------------------------------- // unpackData() //----------------------------------------------------------------------------- void LLHUDEffectLookAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum) { LLVector3d new_target; U8 packed_data[PKT_SIZE]; LLUUID dataId; mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum); if (!gAgentCamera.mLookAt.isNull() && dataId == gAgentCamera.mLookAt->getID()) { return; } LLHUDEffect::unpackData(mesgsys, blocknum); LLUUID source_id; LLUUID target_id; S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); if (size != PKT_SIZE) { llwarns << "LookAt effect with bad size " << size << llendl; return; } mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum); htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16); LLViewerObject *objp = gObjectList.findObject(source_id); if (objp && objp->isAvatar()) { setSourceObject(objp); } else { //llwarns << "Could not find source avatar for lookat effect" << llendl; return; } htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16); objp = gObjectList.findObject(target_id); htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24); if (objp) { setTargetObjectAndOffset(objp, new_target); } else if (target_id.isNull()) { setTargetPosGlobal(new_target); } else { //llwarns << "Could not find target object for lookat effect" << llendl; } U8 lookAtTypeUnpacked = 0; htonmemcpy(&lookAtTypeUnpacked, &(packed_data[LOOKAT_TYPE]), MVT_U8, 1); mTargetType = (ELookAtType)lookAtTypeUnpacked; if (mTargetType == LOOKAT_TARGET_NONE) { clearLookAtTarget(); } }