00001
00032 #include "llviewerprecompiledheaders.h"
00033 #include "llviewerpartsource.h"
00034
00035 #include "llviewercontrol.h"
00036
00037 #include "llagent.h"
00038 #include "lldrawable.h"
00039 #include "llviewercamera.h"
00040 #include "llviewerimagelist.h"
00041 #include "llviewerobject.h"
00042 #include "llviewerobjectlist.h"
00043 #include "llvoavatar.h"
00044 #include "llworld.h"
00045 #include "pipeline.h"
00046
00047 LLViewerPartSource::LLViewerPartSource(const U32 type) :
00048 mType(type),
00049 mOwnerUUID(LLUUID::null),
00050 mPartFlags(0)
00051 {
00052 mLastUpdateTime = 0.f;
00053 mLastPartTime = 0.f;
00054 mIsDead = FALSE;
00055 mIsSuspended = FALSE;
00056 static U32 id_seed = 0;
00057 mID = ++id_seed;
00058
00059 mDelay = 0 ;
00060 }
00061
00062 void LLViewerPartSource::setDead()
00063 {
00064 mIsDead = TRUE;
00065 }
00066
00067
00068 void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt)
00069 {
00070 }
00071
00072 void LLViewerPartSource::update(const F32 dt)
00073 {
00074 llerrs << "Creating default part source!" << llendl;
00075 }
00076
00077 LLUUID LLViewerPartSource::getImageUUID() const
00078 {
00079 LLViewerImage* imagep = mImagep;
00080 if(imagep)
00081 {
00082 return imagep->getID();
00083 }
00084 return LLUUID::null;
00085 }
00086 void LLViewerPartSource::setStart()
00087 {
00088
00089
00090
00091 mDelay = 0 ;
00092 }
00093
00094 LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
00095 LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
00096 {
00097 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00098 llassert(source_objp);
00099 mSourceObjectp = source_objp;
00100 mPosAgent = mSourceObjectp->getPositionAgent();
00101 mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
00102 mImagep->bind();
00103 mImagep->setClamp(TRUE, TRUE);
00104 }
00105
00106
00107 void LLViewerPartSourceScript::setDead()
00108 {
00109 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00110 mIsDead = TRUE;
00111 mSourceObjectp = NULL;
00112 mTargetObjectp = NULL;
00113 }
00114
00115 void LLViewerPartSourceScript::update(const F32 dt)
00116 {
00117 if( mIsSuspended )
00118 return;
00119
00120 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00121 F32 old_update_time = mLastUpdateTime;
00122 mLastUpdateTime += dt;
00123
00124 F32 ref_rate_travelspeed = llmin(LLViewerPartSim::getInstance()->getRefRate(), 1.f);
00125
00126 F32 dt_update = mLastUpdateTime - mLastPartTime;
00127
00128
00129 if (!mSourceObjectp.isNull())
00130 {
00131 if (mSourceObjectp->isDead())
00132 {
00133 mSourceObjectp = NULL;
00134 }
00135 else if (mSourceObjectp->mDrawable.notNull())
00136 {
00137 mPosAgent = mSourceObjectp->getRenderPosition();
00138 }
00139 }
00140
00141 if (mTargetObjectp.isNull()
00142 && mPartSysData.mTargetUUID.notNull())
00143 {
00144
00145
00146
00147
00148 LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID);
00149 setTargetObject(target_objp);
00150 }
00151
00152 if (!mTargetObjectp.isNull())
00153 {
00154 if (mTargetObjectp->isDead())
00155 {
00156 mTargetObjectp = NULL;
00157 }
00158 else if (mTargetObjectp->mDrawable.notNull())
00159 {
00160 mTargetPosAgent = mTargetObjectp->getRenderPosition();
00161 }
00162 }
00163
00164 if (!mTargetObjectp)
00165 {
00166 mTargetPosAgent = mPosAgent;
00167 }
00168
00169 if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge))
00170 {
00171
00172 setDead();
00173 return;
00174 }
00175
00176
00177 if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
00178 {
00179 if (mSourceObjectp.notNull())
00180 {
00181 std::ostringstream ostr;
00182 ostr << mPartSysData;
00183 mSourceObjectp->setDebugText(ostr.str());
00184 }
00185 }
00186
00187 BOOL first_run = FALSE;
00188 if (old_update_time <= 0.f)
00189 {
00190 first_run = TRUE;
00191 }
00192
00193 F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate);
00194 dt_update = llmin(max_time, dt_update);
00195 while ((dt_update > mPartSysData.mBurstRate) || first_run)
00196 {
00197 first_run = FALSE;
00198
00199
00200
00201 F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
00202 if (angular_velocity_mag != 0.0f)
00203 {
00204 F32 av_angle = dt * angular_velocity_mag;
00205 LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
00206 mRotation *= dquat;
00207 }
00208 else
00209 {
00210
00211 mRotation.setQuat(0, 0, 0);
00212 }
00213
00214 if (LLViewerPartSim::getInstance()->aboveParticleLimit())
00215 {
00216
00217
00218 mLastPartTime = mLastUpdateTime;
00219 break;
00220
00221 }
00222
00223
00224
00225 F32 max_short_side =
00226 llmax(
00227 llmax(llmin(mPartSysData.mPartData.mStartScale[0],
00228 mPartSysData.mPartData.mStartScale[1]),
00229 llmin(mPartSysData.mPartData.mEndScale[0],
00230 mPartSysData.mPartData.mEndScale[1])),
00231 llmin((mPartSysData.mPartData.mStartScale[0]
00232 + mPartSysData.mPartData.mEndScale[0])/2,
00233 (mPartSysData.mPartData.mStartScale[1]
00234 + mPartSysData.mPartData.mEndScale[1])/2));
00235
00236 F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
00237
00238
00239 F32 max_dist = max_short_side * pixel_meter_ratio;
00240
00241 if (max_dist < 0.25f)
00242 {
00243
00244
00245
00246 mLastPartTime = mLastUpdateTime;
00247 break;
00248 }
00249
00250
00251 F32 dist = (mPosAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
00252
00253
00254
00255 F32 limited_rate=0.f;
00256 if (dist - max_dist > 0.f)
00257 {
00258 if((dist - max_dist) * ref_rate_travelspeed > mPartSysData.mPartData.mMaxAge - 0.2f )
00259 {
00260
00261 mLastPartTime = mLastUpdateTime;
00262 break;
00263 }
00264 limited_rate = ((dist - max_dist) * ref_rate_travelspeed) / mPartSysData.mPartData.mMaxAge;
00265 }
00266
00267 if(mDelay)
00268 {
00269 limited_rate = llmax(limited_rate, 0.01f * mDelay--) ;
00270 }
00271
00272 S32 i;
00273 for (i = 0; i < mPartSysData.mBurstPartCount; i++)
00274 {
00275 if (ll_frand() < llmax(1.0f - LLViewerPartSim::getInstance()->getBurstRate(), limited_rate))
00276 {
00277
00278 continue;
00279 }
00280
00281 LLPointer<LLViewerPart> part = new LLViewerPart();
00282
00283 part->init(this, mImagep, NULL);
00284 part->mFlags = mPartSysData.mPartData.mFlags;
00285 part->mMaxAge = mPartSysData.mPartData.mMaxAge;
00286 part->mStartColor = mPartSysData.mPartData.mStartColor;
00287 part->mEndColor = mPartSysData.mPartData.mEndColor;
00288 part->mColor = part->mStartColor;
00289
00290 part->mStartScale = mPartSysData.mPartData.mStartScale;
00291 part->mEndScale = mPartSysData.mPartData.mEndScale;
00292 part->mScale = part->mStartScale;
00293
00294 part->mAccel = mPartSysData.mPartAccel;
00295
00296 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
00297 {
00298 part->mPosAgent = mPosAgent;
00299 part->mVelocity.setVec(0.f, 0.f, 0.f);
00300 }
00301 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
00302 {
00303 part->mPosAgent = mPosAgent;
00304 LLVector3 part_dir_vector;
00305
00306 F32 mvs;
00307 do
00308 {
00309 part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
00310 part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
00311 part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
00312 mvs = part_dir_vector.magVecSquared();
00313 }
00314 while ((mvs > 1.f) || (mvs < 0.01f));
00315
00316 part_dir_vector.normVec();
00317 part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
00318 part->mVelocity = part_dir_vector;
00319 F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
00320 part->mVelocity *= speed;
00321 }
00322 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
00323 || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
00324 {
00325 part->mPosAgent = mPosAgent;
00326
00327
00328 LLVector3 part_dir_vector(0.0, 0.0, 1.0);
00329
00330
00331
00332
00333 F32 innerAngle = mPartSysData.mInnerAngle;
00334 F32 outerAngle = mPartSysData.mOuterAngle;
00335
00336
00337 F32 angle = innerAngle + ll_frand(outerAngle - innerAngle);
00338
00339 if (ll_frand() < 0.5)
00340 {
00341 angle = -angle;
00342 }
00343
00344 part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
00345
00346
00347 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
00348 {
00349 part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0);
00350 }
00351
00352
00353 if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
00354 {
00355
00356 part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
00357 }
00358
00359 if (mSourceObjectp)
00360 {
00361 part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
00362 }
00363
00364 part_dir_vector = part_dir_vector * mRotation;
00365
00366 part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
00367
00368 part->mVelocity = part_dir_vector;
00369
00370 F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
00371 part->mVelocity *= speed;
00372 }
00373 else
00374 {
00375 part->mPosAgent = mPosAgent;
00376 part->mVelocity.setVec(0.f, 0.f, 0.f);
00377
00378 }
00379
00380 if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK ||
00381 part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
00382 {
00383 mPartSysData.mBurstRadius = 0;
00384 }
00385
00386 LLViewerPartSim::getInstance()->addPart(part);
00387 }
00388
00389 mLastPartTime = mLastUpdateTime;
00390 dt_update -= mPartSysData.mBurstRate;
00391 }
00392 }
00393
00394
00395 LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num)
00396 {
00397 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00398 if (!pssp)
00399 {
00400 if (LLPartSysData::isNullPS(block_num))
00401 {
00402 return NULL;
00403 }
00404 LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
00405 if (!new_pssp->mPartSysData.unpackBlock(block_num))
00406 {
00407 return NULL;
00408 }
00409 if (new_pssp->mPartSysData.mTargetUUID.notNull())
00410 {
00411 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
00412 new_pssp->setTargetObject(target_objp);
00413 }
00414 return new_pssp;
00415 }
00416 else
00417 {
00418 if (LLPartSysData::isNullPS(block_num))
00419 {
00420 return NULL;
00421 }
00422
00423 if (!pssp->mPartSysData.unpackBlock(block_num))
00424 {
00425 return NULL;
00426 }
00427 if (pssp->mPartSysData.mTargetUUID.notNull())
00428 {
00429 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
00430 pssp->setTargetObject(target_objp);
00431 }
00432 return pssp;
00433 }
00434 }
00435
00436
00437 LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp)
00438 {
00439 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00440 if (!pssp)
00441 {
00442 LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
00443 if (!new_pssp->mPartSysData.unpack(dp))
00444 {
00445 return NULL;
00446 }
00447 if (new_pssp->mPartSysData.mTargetUUID.notNull())
00448 {
00449 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
00450 new_pssp->setTargetObject(target_objp);
00451 }
00452 return new_pssp;
00453 }
00454 else
00455 {
00456 if (!pssp->mPartSysData.unpack(dp))
00457 {
00458 return NULL;
00459 }
00460 if (pssp->mPartSysData.mTargetUUID.notNull())
00461 {
00462 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
00463 pssp->setTargetObject(target_objp);
00464 }
00465 return pssp;
00466 }
00467 }
00468
00469
00470
00471 LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters)
00472 {
00473 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00474
00475 LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
00476
00477 new_pssp->mPartSysData = particle_parameters;
00478
00479 if (new_pssp->mPartSysData.mTargetUUID.notNull())
00480 {
00481 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
00482 new_pssp->setTargetObject(target_objp);
00483 }
00484 return new_pssp;
00485 }
00486
00487
00488 void LLViewerPartSourceScript::setImage(LLViewerImage *imagep)
00489 {
00490 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00491 mImagep = imagep;
00492 }
00493
00494 void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
00495 {
00496 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00497 mTargetObjectp = objp;
00498 }
00499
00500
00501
00502
00503
00504 LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
00505 LLViewerPartSource(LL_PART_SOURCE_CHAT)
00506 {
00507 mPosAgent = pos;
00508 }
00509
00510 void LLViewerPartSourceSpiral::setDead()
00511 {
00512 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00513 mIsDead = TRUE;
00514 mSourceObjectp = NULL;
00515 }
00516
00517
00518 void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
00519 {
00520 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00521 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00522
00523 LLVector3 center_pos;
00524 LLPointer<LLViewerPartSource>& ps = part.mPartSourcep;
00525 LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get();
00526 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
00527 {
00528 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
00529 }
00530 else
00531 {
00532 part.mPosAgent = pss->mPosAgent;
00533 }
00534 F32 x = sin(F_TWO_PI*frac + part.mParameter);
00535 F32 y = cos(F_TWO_PI*frac + part.mParameter);
00536
00537 part.mPosAgent.mV[VX] += x;
00538 part.mPosAgent.mV[VY] += y;
00539 part.mPosAgent.mV[VZ] += -0.5f + frac;
00540 }
00541
00542
00543 void LLViewerPartSourceSpiral::update(const F32 dt)
00544 {
00545 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00546 if (!mImagep)
00547 {
00548 mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
00549 }
00550
00551 const F32 RATE = 0.025f;
00552
00553 mLastUpdateTime += dt;
00554
00555 F32 dt_update = mLastUpdateTime - mLastPartTime;
00556 F32 max_time = llmax(1.f, 10.f*RATE);
00557 dt_update = llmin(max_time, dt_update);
00558
00559 if (dt_update > RATE)
00560 {
00561 mLastPartTime = mLastUpdateTime;
00562 if (!LLViewerPartSim::getInstance()->shouldAddPart())
00563 {
00564
00565 return;
00566 }
00567
00568 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00569 {
00570 mPosAgent = mSourceObjectp->getRenderPosition();
00571 }
00572 LLPointer<LLViewerPart> part = new LLViewerPart();
00573 part->init(this, mImagep, updatePart);
00574 part->mStartColor = mColor;
00575 part->mEndColor = mColor;
00576 part->mEndColor.mV[3] = 0.f;
00577 part->mPosAgent = mPosAgent;
00578 part->mMaxAge = 1.f;
00579 part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
00580 part->mLastUpdateTime = 0.f;
00581 part->mScale.mV[0] = 0.25f;
00582 part->mScale.mV[1] = 0.25f;
00583 part->mParameter = ll_frand(F_TWO_PI);
00584
00585 LLViewerPartSim::getInstance()->addPart(part);
00586 }
00587 }
00588
00589 void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
00590 {
00591 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00592 mSourceObjectp = objp;
00593 }
00594
00595 void LLViewerPartSourceSpiral::setColor(const LLColor4 &color)
00596 {
00597 mColor = color;
00598 }
00599
00600
00601
00602
00603
00604 LLViewerPartSourceBeam::LLViewerPartSourceBeam() :
00605 LLViewerPartSource(LL_PART_SOURCE_BEAM)
00606 {
00607 }
00608
00609 LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
00610 {
00611 }
00612
00613 void LLViewerPartSourceBeam::setDead()
00614 {
00615 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00616 mIsDead = TRUE;
00617 mSourceObjectp = NULL;
00618 mTargetObjectp = NULL;
00619 }
00620
00621 void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
00622 {
00623 mColor = color;
00624 }
00625
00626
00627 void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
00628 {
00629 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00630 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00631
00632 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
00633 LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps;
00634 if (psb->mSourceObjectp.isNull())
00635 {
00636 part.mFlags = LLPartData::LL_PART_DEAD_MASK;
00637 return;
00638 }
00639
00640 LLVector3 source_pos_agent;
00641 LLVector3 target_pos_agent;
00642 if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull())
00643 {
00644 if (psb->mSourceObjectp->isAvatar())
00645 {
00646 LLViewerObject *objp = psb->mSourceObjectp;
00647 LLVOAvatar *avp = (LLVOAvatar *)objp;
00648 source_pos_agent = avp->mWristLeftp->getWorldPosition();
00649 }
00650 else
00651 {
00652 source_pos_agent = psb->mSourceObjectp->getRenderPosition();
00653 }
00654 }
00655 if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull())
00656 {
00657 target_pos_agent = psb->mTargetObjectp->getRenderPosition();
00658 }
00659
00660 part.mPosAgent = (1.f - frac) * source_pos_agent;
00661 if (psb->mTargetObjectp.isNull())
00662 {
00663 part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal));
00664 }
00665 else
00666 {
00667 part.mPosAgent += frac * target_pos_agent;
00668 }
00669 }
00670
00671
00672 void LLViewerPartSourceBeam::update(const F32 dt)
00673 {
00674 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00675 const F32 RATE = 0.025f;
00676
00677 mLastUpdateTime += dt;
00678
00679 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00680 {
00681 if (mSourceObjectp->isAvatar())
00682 {
00683 LLViewerObject *objp = mSourceObjectp;
00684 LLVOAvatar *avp = (LLVOAvatar *)objp;
00685 mPosAgent = avp->mWristLeftp->getWorldPosition();
00686 }
00687 else
00688 {
00689 mPosAgent = mSourceObjectp->getRenderPosition();
00690 }
00691 }
00692
00693 if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull())
00694 {
00695 mTargetPosAgent = mTargetObjectp->getRenderPosition();
00696 }
00697 else if (!mLKGTargetPosGlobal.isExactlyZero())
00698 {
00699 mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
00700 }
00701
00702 F32 dt_update = mLastUpdateTime - mLastPartTime;
00703 F32 max_time = llmax(1.f, 10.f*RATE);
00704 dt_update = llmin(max_time, dt_update);
00705
00706 if (dt_update > RATE)
00707 {
00708 mLastPartTime = mLastUpdateTime;
00709 if (!LLViewerPartSim::getInstance()->shouldAddPart())
00710 {
00711
00712 return;
00713 }
00714
00715 if (!mImagep)
00716 {
00717 mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
00718 }
00719
00720 LLPointer<LLViewerPart> part = new LLViewerPart();
00721 part->init(this, mImagep, NULL);
00722
00723 part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
00724 LLPartData::LL_PART_INTERP_SCALE_MASK |
00725 LLPartData::LL_PART_TARGET_POS_MASK |
00726 LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
00727 part->mMaxAge = 0.5f;
00728 part->mStartColor = mColor;
00729 part->mEndColor = part->mStartColor;
00730 part->mEndColor.mV[3] = 0.4f;
00731 part->mColor = part->mStartColor;
00732
00733 part->mStartScale = LLVector2(0.1f, 0.1f);
00734 part->mEndScale = LLVector2(0.1f, 0.1f);
00735 part->mScale = part->mStartScale;
00736
00737 part->mPosAgent = mPosAgent;
00738 part->mVelocity = mTargetPosAgent - mPosAgent;
00739
00740 LLViewerPartSim::getInstance()->addPart(part);
00741 }
00742 }
00743
00744 void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
00745 {
00746 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00747 mSourceObjectp = objp;
00748 }
00749
00750 void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
00751 {
00752 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00753 mTargetObjectp = objp;
00754 }
00755
00756
00757
00758
00759 LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
00760 LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
00761 {
00762 mPosAgent = pos;
00763 }
00764
00765 void LLViewerPartSourceChat::setDead()
00766 {
00767 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00768 mIsDead = TRUE;
00769 mSourceObjectp = NULL;
00770 }
00771
00772
00773 void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
00774 {
00775 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00776 F32 frac = part.mLastUpdateTime/part.mMaxAge;
00777
00778 LLVector3 center_pos;
00779 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
00780 LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps;
00781 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
00782 {
00783 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
00784 }
00785 else
00786 {
00787 part.mPosAgent = pss->mPosAgent;
00788 }
00789 F32 x = sin(F_TWO_PI*frac + part.mParameter);
00790 F32 y = cos(F_TWO_PI*frac + part.mParameter);
00791
00792 part.mPosAgent.mV[VX] += x;
00793 part.mPosAgent.mV[VY] += y;
00794 part.mPosAgent.mV[VZ] += -0.5f + frac;
00795 }
00796
00797
00798 void LLViewerPartSourceChat::update(const F32 dt)
00799 {
00800 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00801 if (!mImagep)
00802 {
00803 mImagep = gImageList.getImageFromFile("pixiesmall.j2c");
00804 }
00805
00806
00807 const F32 RATE = 0.025f;
00808
00809 mLastUpdateTime += dt;
00810
00811 if (mLastUpdateTime > 2.f)
00812 {
00813
00814 setDead();
00815 return;
00816 }
00817
00818 F32 dt_update = mLastUpdateTime - mLastPartTime;
00819
00820
00821 F32 max_time = llmax(1.f, 10.f*RATE);
00822 dt_update = llmin(max_time, dt_update);
00823
00824 if (dt_update > RATE)
00825 {
00826 mLastPartTime = mLastUpdateTime;
00827 if (!LLViewerPartSim::getInstance()->shouldAddPart())
00828 {
00829
00830 return;
00831 }
00832
00833 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
00834 {
00835 mPosAgent = mSourceObjectp->getRenderPosition();
00836 }
00837 LLPointer<LLViewerPart> part = new LLViewerPart();
00838 part->init(this, mImagep, updatePart);
00839 part->mStartColor = mColor;
00840 part->mEndColor = mColor;
00841 part->mEndColor.mV[3] = 0.f;
00842 part->mPosAgent = mPosAgent;
00843 part->mMaxAge = 1.f;
00844 part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
00845 part->mLastUpdateTime = 0.f;
00846 part->mScale.mV[0] = 0.25f;
00847 part->mScale.mV[1] = 0.25f;
00848 part->mParameter = ll_frand(F_TWO_PI);
00849
00850 LLViewerPartSim::getInstance()->addPart(part);
00851 }
00852 }
00853
00854 void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
00855 {
00856 LLMemType mt(LLMemType::MTYPE_PARTICLES);
00857 mSourceObjectp = objp;
00858 }
00859
00860 void LLViewerPartSourceChat::setColor(const LLColor4 &color)
00861 {
00862 mColor = color;
00863 }
00864
00865