00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llhudeffectpointat.h"
00035
00036 #include "llgl.h"
00037
00038 #include "llagent.h"
00039 #include "lldrawable.h"
00040 #include "llviewerobjectlist.h"
00041 #include "llvoavatar.h"
00042 #include "message.h"
00043
00044
00045 const S32 SOURCE_AVATAR = 0;
00046 const S32 TARGET_OBJECT = 16;
00047 const S32 TARGET_POS = 32;
00048 const S32 POINTAT_TYPE = 56;
00049 const S32 PKT_SIZE = 57;
00050
00051
00052 const F32 MAX_SENDS_PER_SEC = 4.f;
00053
00054 const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f;
00055
00056
00057
00058 const F32 MAX_TIMEOUT = F32_MAX / 4.f;
00059
00060 const F32 POINTAT_TIMEOUTS[POINTAT_NUM_TARGETS] =
00061 {
00062 MAX_TIMEOUT,
00063 MAX_TIMEOUT,
00064 MAX_TIMEOUT,
00065 0.f,
00066 };
00067
00068 const S32 POINTAT_PRIORITIES[POINTAT_NUM_TARGETS] =
00069 {
00070 0,
00071 1,
00072 2,
00073 3,
00074 };
00075
00076
00077
00078 BOOL LLHUDEffectPointAt::sDebugPointAt;
00079
00080
00081
00082
00083
00084 LLHUDEffectPointAt::LLHUDEffectPointAt(const U8 type) :
00085 LLHUDEffect(type),
00086 mKillTime(0.f),
00087 mLastSendTime(0.f)
00088 {
00089 clearPointAtTarget();
00090 }
00091
00092
00093
00094
00095 LLHUDEffectPointAt::~LLHUDEffectPointAt()
00096 {
00097 }
00098
00099
00100
00101
00102 void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys)
00103 {
00104
00105 LLHUDEffect::packData(mesgsys);
00106
00107
00108 U8 packed_data[PKT_SIZE];
00109 memset(packed_data, 0, PKT_SIZE);
00110
00111 if (mSourceObject)
00112 {
00113 htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16);
00114 }
00115 else
00116 {
00117 htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16);
00118 }
00119
00120
00121
00122 if (mTargetObject)
00123 {
00124 htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16);
00125 }
00126 else
00127 {
00128 htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16);
00129 }
00130
00131 htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24);
00132
00133 U8 pointAtTypePacked = (U8)mTargetType;
00134 htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1);
00135
00136 mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE);
00137
00138 mLastSendTime = mTimer.getElapsedTimeF32();
00139 }
00140
00141
00142
00143
00144 void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum)
00145 {
00146 LLVector3d new_target;
00147 U8 packed_data[PKT_SIZE];
00148
00149 LLUUID dataId;
00150 mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum);
00151
00152
00153 if (!gAgent.mPointAt.isNull() && dataId == gAgent.mPointAt->getID())
00154 {
00155 return;
00156 }
00157
00158 LLHUDEffect::unpackData(mesgsys, blocknum);
00159 LLUUID source_id;
00160 LLUUID target_id;
00161 S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData);
00162 if (size != PKT_SIZE)
00163 {
00164 llwarns << "PointAt effect with bad size " << size << llendl;
00165 return;
00166 }
00167 mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum);
00168
00169 htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16);
00170
00171 LLViewerObject *objp = gObjectList.findObject(source_id);
00172 if (objp && objp->isAvatar())
00173 {
00174 setSourceObject(objp);
00175 }
00176 else
00177 {
00178
00179 return;
00180 }
00181
00182 htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16);
00183
00184 objp = gObjectList.findObject(target_id);
00185
00186 htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24);
00187
00188 if (objp)
00189 {
00190 setTargetObjectAndOffset(objp, new_target);
00191 }
00192 else if (target_id.isNull())
00193 {
00194 setTargetPosGlobal(new_target);
00195 }
00196
00197 U8 pointAtTypeUnpacked = 0;
00198 htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1);
00199 mTargetType = (EPointAtType)pointAtTypeUnpacked;
00200
00201
00202 update();
00203 }
00204
00205
00206
00207
00208 void LLHUDEffectPointAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset)
00209 {
00210 mTargetObject = objp;
00211 mTargetOffsetGlobal = offset;
00212 }
00213
00214
00215
00216
00217 void LLHUDEffectPointAt::setTargetPosGlobal(const LLVector3d &target_pos_global)
00218 {
00219 mTargetObject = NULL;
00220 mTargetOffsetGlobal = target_pos_global;
00221 }
00222
00223
00224
00225
00226
00227 BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position)
00228 {
00229 if (!mSourceObject)
00230 {
00231 return FALSE;
00232 }
00233
00234 llassert(target_type < POINTAT_NUM_TARGETS);
00235
00236
00237 if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType])
00238 {
00239 return FALSE;
00240 }
00241
00242 F32 current_time = mTimer.getElapsedTimeF32();
00243
00244
00245 BOOL targetTypeChanged = (target_type != mTargetType) ||
00246 (object != mTargetObject);
00247
00248 BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) &&
00249 ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC));
00250
00251 if (targetTypeChanged || targetPosChanged)
00252 {
00253 mLastSentOffsetGlobal = position;
00254 setDuration(POINTAT_TIMEOUTS[target_type]);
00255 setNeedsSendToSim(TRUE);
00256
00257 }
00258
00259 if (target_type == POINTAT_TARGET_CLEAR)
00260 {
00261 clearPointAtTarget();
00262 }
00263 else
00264 {
00265 mTargetType = target_type;
00266 mTargetObject = object;
00267 if (object)
00268 {
00269 mTargetOffsetGlobal.setVec(position);
00270 }
00271 else
00272 {
00273 mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position);
00274 }
00275
00276 mKillTime = mTimer.getElapsedTimeF32() + mDuration;
00277
00278
00279 update();
00280 }
00281
00282 return TRUE;
00283 }
00284
00285
00286
00287
00288 void LLHUDEffectPointAt::clearPointAtTarget()
00289 {
00290 mTargetObject = NULL;
00291 mTargetOffsetGlobal.clearVec();
00292 mTargetType = POINTAT_TARGET_NONE;
00293 }
00294
00295
00296
00297
00298 void LLHUDEffectPointAt::markDead()
00299 {
00300 if (!mSourceObject.isNull() && mSourceObject->isAvatar())
00301 {
00302 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
00303 }
00304
00305 clearPointAtTarget();
00306 LLHUDEffect::markDead();
00307 }
00308
00309 void LLHUDEffectPointAt::setSourceObject(LLViewerObject* objectp)
00310 {
00311
00312 if (objectp && objectp->isAvatar())
00313 {
00314 LLHUDEffect::setSourceObject(objectp);
00315 }
00316 }
00317
00318
00319
00320
00321 void LLHUDEffectPointAt::render()
00322 {
00323 update();
00324 if (sDebugPointAt && mTargetType != POINTAT_TARGET_NONE)
00325 {
00326 LLGLSNoTexture gls_no_texture;
00327
00328 LLVector3 target = mTargetPos + mSourceObject->getRenderPosition();
00329 glPushMatrix();
00330 glTranslatef(target.mV[VX], target.mV[VY], target.mV[VZ]);
00331 glScalef(0.3f, 0.3f, 0.3f);
00332 glBegin(GL_LINES);
00333 {
00334 glColor3f(1.f, 0.f, 0.f);
00335 glVertex3f(-1.f, 0.f, 0.f);
00336 glVertex3f(1.f, 0.f, 0.f);
00337
00338 glVertex3f(0.f, -1.f, 0.f);
00339 glVertex3f(0.f, 1.f, 0.f);
00340
00341 glVertex3f(0.f, 0.f, -1.f);
00342 glVertex3f(0.f, 0.f, 1.f);
00343 } glEnd();
00344 glPopMatrix();
00345 }
00346 }
00347
00348
00349
00350
00351 void LLHUDEffectPointAt::update()
00352 {
00353
00354 if (!mTargetObject.isNull() && mTargetObject->isDead())
00355 {
00356 clearPointAtTarget();
00357 }
00358
00359 if (mSourceObject.isNull() || mSourceObject->isDead())
00360 {
00361 markDead();
00362 return;
00363 }
00364
00365 F32 time = mTimer.getElapsedTimeF32();
00366
00367
00368 if (mKillTime != 0.f && time > mKillTime)
00369 {
00370 mTargetType = POINTAT_TARGET_NONE;
00371 }
00372
00373 if (mSourceObject->isAvatar())
00374 {
00375 if (mTargetType == POINTAT_TARGET_NONE)
00376 {
00377 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint");
00378 }
00379 else
00380 {
00381 calcTargetPosition();
00382
00383 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_EDITING);
00384 }
00385 }
00386 }
00387
00388
00389
00390
00391 void LLHUDEffectPointAt::calcTargetPosition()
00392 {
00393 LLViewerObject *targetObject = (LLViewerObject *)mTargetObject;
00394 LLVector3 local_offset;
00395
00396 if (targetObject)
00397 {
00398 local_offset.setVec(mTargetOffsetGlobal);
00399 }
00400 else
00401 {
00402 local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal);
00403 }
00404
00405 if (targetObject && targetObject->mDrawable.notNull())
00406 {
00407 LLQuaternion objRot;
00408 if (targetObject->isAvatar())
00409 {
00410 LLVOAvatar *avatarp = (LLVOAvatar *)targetObject;
00411 mTargetPos = avatarp->mHeadp->getWorldPosition();
00412 objRot = avatarp->mPelvisp->getWorldRotation();
00413 }
00414 else
00415 {
00416 if (targetObject->mDrawable->getGeneration() == -1)
00417 {
00418 mTargetPos = targetObject->getPositionAgent();
00419 objRot = targetObject->getWorldRotation();
00420 }
00421 else
00422 {
00423 mTargetPos = targetObject->getRenderPosition();
00424 objRot = targetObject->getRenderRotation();
00425 }
00426 }
00427
00428 mTargetPos += (local_offset * objRot);
00429 }
00430 else
00431 {
00432 mTargetPos = local_offset;
00433 }
00434
00435 mTargetPos -= mSourceObject->getRenderPosition();
00436
00437 if (mSourceObject->isAvatar())
00438 {
00439 ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("PointAtPoint", (void *)&mTargetPos);
00440 }
00441 }
00442
00443 const LLVector3d LLHUDEffectPointAt::getPointAtPosGlobal()
00444 {
00445 LLVector3d global_pos;
00446 global_pos.setVec(mTargetPos);
00447 if (mSourceObject.notNull())
00448 {
00449 global_pos += mSourceObject->getPositionGlobal();
00450 }
00451
00452 return global_pos;
00453 }