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