aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llviewerpartsource.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/llviewerpartsource.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to 'linden/indra/newview/llviewerpartsource.cpp')
-rw-r--r--linden/indra/newview/llviewerpartsource.cpp738
1 files changed, 738 insertions, 0 deletions
diff --git a/linden/indra/newview/llviewerpartsource.cpp b/linden/indra/newview/llviewerpartsource.cpp
new file mode 100644
index 0000000..ceb6761
--- /dev/null
+++ b/linden/indra/newview/llviewerpartsource.cpp
@@ -0,0 +1,738 @@
1/**
2 * @file llviewerpartsource.cpp
3 * @brief LLViewerPartSource class implementation
4 *
5 * Copyright (c) 2003-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29#include "llviewerpartsource.h"
30
31#include "llviewercontrol.h"
32
33#include "llagent.h"
34#include "lldrawable.h"
35#include "llviewerimagelist.h"
36#include "llviewerobject.h"
37#include "llviewerobjectlist.h"
38#include "llvoavatar.h"
39#include "llworld.h"
40
41LLViewerPartSource::LLViewerPartSource(const U32 type) :
42 mType(type),
43 mOwnerUUID(LLUUID::null)
44{
45 mLastUpdateTime = 0.f;
46 mLastPartTime = 0.f;
47 mIsDead = FALSE;
48}
49
50void LLViewerPartSource::setDead()
51{
52 mIsDead = TRUE;
53}
54
55
56void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt)
57{
58}
59
60void LLViewerPartSource::update(const F32 dt)
61{
62 llerrs << "Creating default part source!" << llendl;
63}
64
65
66
67LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
68 LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
69{
70 llassert(source_objp);
71 mSourceObjectp = source_objp;
72 mPosAgent = mSourceObjectp->getPositionAgent();
73 LLUUID id;
74 id.set( gViewerArt.getString("pixiesmall.tga") );
75 mImagep = gImageList.getImage(id);
76 mImagep->bind();
77 mImagep->setClamp(TRUE, TRUE);
78}
79
80
81void LLViewerPartSourceScript::setDead()
82{
83 mIsDead = TRUE;
84 mSourceObjectp = NULL;
85 mTargetObjectp = NULL;
86}
87
88
89
90void LLViewerPartSourceScript::update(const F32 dt)
91{
92 F32 old_update_time = mLastUpdateTime;
93 mLastUpdateTime += dt;
94
95 F32 dt_update = mLastUpdateTime - mLastPartTime;
96
97 // Update this for objects which have the follow flag set...
98 if (!mSourceObjectp.isNull())
99 {
100 if (mSourceObjectp->isDead())
101 {
102 mSourceObjectp = NULL;
103 }
104 else if (mSourceObjectp->mDrawable.notNull())
105 {
106 mPosAgent = mSourceObjectp->getRenderPosition();
107 }
108 }
109
110 if (mTargetObjectp.isNull()
111 && mPartSysData.mTargetUUID.notNull())
112 {
113 //
114 // Hmm, missing object, let's see if we can find it...
115 //
116
117 LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID);
118 setTargetObject(target_objp);
119 }
120
121 if (!mTargetObjectp.isNull())
122 {
123 if (mTargetObjectp->isDead())
124 {
125 mTargetObjectp = NULL;
126 }
127 else if (mTargetObjectp->mDrawable.notNull())
128 {
129 mTargetPosAgent = mTargetObjectp->getRenderPosition();
130 }
131 }
132
133 if (!mTargetObjectp)
134 {
135 mTargetPosAgent = mPosAgent;
136 }
137
138 if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge))
139 {
140 // Kill particle source because it has outlived its max age...
141 setDead();
142 return;
143 }
144
145 BOOL first_run = FALSE;
146 if (old_update_time <= 0.f)
147 {
148 first_run = TRUE;
149 }
150
151 F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate);
152 dt_update = llmin(max_time, dt_update);
153 while ((dt_update > mPartSysData.mBurstRate) || first_run)
154 {
155 first_run = FALSE;
156 LLViewerPart part;
157
158 part.init(this, mImagep, NULL);
159 part.mFlags = mPartSysData.mPartData.mFlags;
160 part.mMaxAge = mPartSysData.mPartData.mMaxAge;
161 part.mStartColor = mPartSysData.mPartData.mStartColor;
162 part.mEndColor = mPartSysData.mPartData.mEndColor;
163 part.mColor = part.mStartColor;
164
165 part.mStartScale = mPartSysData.mPartData.mStartScale;
166 part.mEndScale = mPartSysData.mPartData.mEndScale;
167 part.mScale = part.mStartScale;
168
169 part.mAccel = mPartSysData.mPartAccel;
170
171 // Update the rotation of the particle source by the angular velocity
172 // First check to see if there is still an angular velocity.
173 F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
174 if (angular_velocity_mag != 0.0f)
175 {
176 F32 av_angle = dt * angular_velocity_mag;
177 LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
178 mRotation *= dquat;
179 }
180 else
181 {
182 // No angular velocity. Reset our rotation.
183 mRotation.setQuat(0, 0, 0);
184 }
185
186 if (gWorldPointer->mPartSim.aboveParticleLimit())
187 {
188 // Don't bother doing any more updates if we're above the particle limit,
189 // just give up.
190 mLastPartTime = mLastUpdateTime;
191 break;
192 }
193
194 S32 i;
195 for (i = 0; i < mPartSysData.mBurstPartCount; i++)
196 {
197 if (!gWorldPointer->mPartSim.shouldAddPart())
198 {
199 // Particle simulation says we have too many particles, skip all this
200 continue;
201 }
202
203 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
204 {
205 part.mPosAgent = mPosAgent;
206 part.mVelocity.setVec(0.f, 0.f, 0.f);
207 }
208 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
209 {
210 part.mPosAgent = mPosAgent;
211 LLVector3 part_dir_vector;
212
213 F32 mvs;
214 do
215 {
216 part_dir_vector.mV[VX] = frand(2.f) - 1.f;
217 part_dir_vector.mV[VY] = frand(2.f) - 1.f;
218 part_dir_vector.mV[VZ] = frand(2.f) - 1.f;
219 mvs = part_dir_vector.magVecSquared();
220 }
221 while ((mvs > 1.f) || (mvs < 0.01f));
222
223 part_dir_vector.normVec();
224 part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
225 part.mVelocity = part_dir_vector;
226 F32 speed = mPartSysData.mBurstSpeedMin + frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
227 part.mVelocity *= speed;
228 }
229 else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
230 || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
231 {
232 part.mPosAgent = mPosAgent;
233
234 // original implemenetation for part_dir_vector was just:
235 LLVector3 part_dir_vector(0.0, 0.0, 1.0);
236
237 // params from the script...
238 // outer = outer cone angle
239 // inner = inner cone angle
240 // between outer and inner there will be particles
241 F32 innerAngle = mPartSysData.mInnerAngle;
242 F32 outerAngle = mPartSysData.mOuterAngle;
243
244 // generate a random angle within the given space...
245 F32 angle = innerAngle + frand(outerAngle - innerAngle);
246
247 // split which side it will go on randomly...
248 if (frand(1.0) < 0.5)
249 {
250 angle = -angle;
251 }
252
253 // Both patterns rotate around the x-axis first:
254 part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
255
256 // If this is a cone pattern, rotate again to create the cone.
257 if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
258 {
259 part_dir_vector.rotVec(frand(4*F_PI), 0.0, 0.0, 1.0);
260 }
261
262 // Only apply this rotation if using the deprecated angles.
263 if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
264 {
265 // Deprecated...
266 part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
267 }
268
269 if (mSourceObjectp)
270 {
271 part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
272 }
273 part_dir_vector = part_dir_vector * mRotation;
274
275 part.mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
276
277 part.mVelocity = part_dir_vector;
278
279 F32 speed = mPartSysData.mBurstSpeedMin + frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
280 part.mVelocity *= speed;
281 }
282 else
283 {
284 part.mPosAgent = mPosAgent;
285 part.mVelocity.setVec(0.f, 0.f, 0.f);
286 //llwarns << "Unknown source pattern " << (S32)mPartSysData.mPattern << llendl;
287 }
288
289 gWorldPointer->mPartSim.addPart(part);
290 }
291
292 mLastPartTime = mLastUpdateTime;
293 dt_update -= mPartSysData.mBurstRate;
294 }
295}
296
297// static
298LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, const S32 block_num)
299{
300 if (!pssp)
301 {
302 if (LLPartSysData::isNullPS(block_num))
303 {
304 return NULL;
305 }
306 LLViewerPartSourceScript *new_pssp = new LLViewerPartSourceScript(source_objp);
307 if (!new_pssp->mPartSysData.unpackBlock(block_num))
308 {
309 return NULL;
310 }
311 if (new_pssp->mPartSysData.mTargetUUID.notNull())
312 {
313 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
314 new_pssp->setTargetObject(target_objp);
315 }
316 return new_pssp;
317 }
318 else
319 {
320 if (LLPartSysData::isNullPS(block_num))
321 {
322 return NULL;
323 }
324
325 if (!pssp->mPartSysData.unpackBlock(block_num))
326 {
327 return NULL;
328 }
329 if (pssp->mPartSysData.mTargetUUID.notNull())
330 {
331 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
332 pssp->setTargetObject(target_objp);
333 }
334 return pssp;
335 }
336}
337
338
339LLViewerPartSourceScript *LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLViewerPartSourceScript *pssp, LLDataPacker &dp)
340{
341 if (!pssp)
342 {
343 LLViewerPartSourceScript *new_pssp = new LLViewerPartSourceScript(source_objp);
344 if (!new_pssp->mPartSysData.unpack(dp))
345 {
346 return NULL;
347 }
348 if (new_pssp->mPartSysData.mTargetUUID.notNull())
349 {
350 LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
351 new_pssp->setTargetObject(target_objp);
352 }
353 return new_pssp;
354 }
355 else
356 {
357 if (!pssp->mPartSysData.unpack(dp))
358 {
359 return NULL;
360 }
361 if (pssp->mPartSysData.mTargetUUID.notNull())
362 {
363 LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
364 pssp->setTargetObject(target_objp);
365 }
366 return pssp;
367 }
368}
369
370void LLViewerPartSourceScript::setImage(LLViewerImage *imagep)
371{
372 mImagep = imagep;
373}
374
375void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
376{
377 mTargetObjectp = objp;
378}
379
380
381
382
383
384LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
385 LLViewerPartSource(LL_PART_SOURCE_CHAT)
386{
387 mPosAgent = pos;
388}
389
390void LLViewerPartSourceSpiral::setDead()
391{
392 mIsDead = TRUE;
393 mSourceObjectp = NULL;
394}
395
396
397void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
398{
399 F32 frac = part.mLastUpdateTime/part.mMaxAge;
400
401 LLVector3 center_pos;
402 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
403 LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps;
404 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
405 {
406 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
407 }
408 else
409 {
410 part.mPosAgent = pss->mPosAgent;
411 }
412 F32 x = sin(F_TWO_PI*frac + part.mParameter);
413 F32 y = cos(F_TWO_PI*frac + part.mParameter);
414
415 part.mPosAgent.mV[VX] += x;
416 part.mPosAgent.mV[VY] += y;
417 part.mPosAgent.mV[VZ] += -0.5f + frac;
418}
419
420
421void LLViewerPartSourceSpiral::update(const F32 dt)
422{
423 if (!mImagep)
424 {
425 LLUUID id;
426 id.set( gViewerArt.getString("pixiesmall.tga") );
427 mImagep = gImageList.getImage(id);
428 }
429
430 const F32 RATE = 0.025f;
431
432 mLastUpdateTime += dt;
433
434 F32 dt_update = mLastUpdateTime - mLastPartTime;
435 F32 max_time = llmax(1.f, 10.f*RATE);
436 dt_update = llmin(max_time, dt_update);
437
438 if (dt_update > RATE)
439 {
440 mLastPartTime = mLastUpdateTime;
441 if (!gWorldPointer->mPartSim.shouldAddPart())
442 {
443 // Particle simulation says we have too many particles, skip all this
444 return;
445 }
446
447 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
448 {
449 mPosAgent = mSourceObjectp->getRenderPosition();
450 }
451 LLViewerPart part;
452 part.init(this, mImagep, updatePart);
453 part.mStartColor = mColor;
454 part.mEndColor = mColor;
455 part.mEndColor.mV[3] = 0.f;
456 part.mPosAgent = mPosAgent;
457 part.mMaxAge = 1.f;
458 part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
459 part.mLastUpdateTime = 0.f;
460 part.mScale.mV[0] = 0.25f;
461 part.mScale.mV[1] = 0.25f;
462 part.mParameter = frand(F_TWO_PI);
463
464 gWorldPointer->mPartSim.addPart(part);
465 }
466}
467
468void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
469{
470 mSourceObjectp = objp;
471}
472
473void LLViewerPartSourceSpiral::setColor(const LLColor4 &color)
474{
475 mColor = color;
476}
477
478
479
480
481
482LLViewerPartSourceBeam::LLViewerPartSourceBeam() :
483 LLViewerPartSource(LL_PART_SOURCE_BEAM)
484{
485}
486
487LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
488{
489}
490
491void LLViewerPartSourceBeam::setDead()
492{
493 mIsDead = TRUE;
494 mSourceObjectp = NULL;
495 mTargetObjectp = NULL;
496}
497
498void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
499{
500 mColor = color;
501}
502
503
504void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
505{
506 F32 frac = part.mLastUpdateTime/part.mMaxAge;
507
508 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
509 LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps;
510 if (psb->mSourceObjectp.isNull())
511 {
512 part.mFlags = LLPartData::LL_PART_DEAD_MASK;
513 return;
514 }
515
516 LLVector3 source_pos_agent;
517 LLVector3 target_pos_agent;
518 if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull())
519 {
520 if (psb->mSourceObjectp->isAvatar())
521 {
522 LLViewerObject *objp = psb->mSourceObjectp;
523 LLVOAvatar *avp = (LLVOAvatar *)objp;
524 source_pos_agent = avp->mWristLeftp->getWorldPosition();
525 }
526 else
527 {
528 source_pos_agent = psb->mSourceObjectp->getRenderPosition();
529 }
530 }
531 if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull())
532 {
533 target_pos_agent = psb->mTargetObjectp->getRenderPosition();
534 }
535
536 part.mPosAgent = (1.f - frac) * source_pos_agent;
537 if (psb->mTargetObjectp.isNull())
538 {
539 part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal));
540 }
541 else
542 {
543 part.mPosAgent += frac * target_pos_agent;
544 }
545}
546
547
548void LLViewerPartSourceBeam::update(const F32 dt)
549{
550
551 const F32 RATE = 0.025f;
552
553 mLastUpdateTime += dt;
554
555 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
556 {
557 if (mSourceObjectp->isAvatar())
558 {
559 LLViewerObject *objp = mSourceObjectp;
560 LLVOAvatar *avp = (LLVOAvatar *)objp;
561 mPosAgent = avp->mWristLeftp->getWorldPosition();
562 }
563 else
564 {
565 mPosAgent = mSourceObjectp->getRenderPosition();
566 }
567 }
568
569 if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull())
570 {
571 mTargetPosAgent = mTargetObjectp->getRenderPosition();
572 }
573 else if (!mLKGTargetPosGlobal.isExactlyZero())
574 {
575 mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
576 }
577
578 F32 dt_update = mLastUpdateTime - mLastPartTime;
579 F32 max_time = llmax(1.f, 10.f*RATE);
580 dt_update = llmin(max_time, dt_update);
581
582 if (dt_update > RATE)
583 {
584 mLastPartTime = mLastUpdateTime;
585 if (!gWorldPointer->mPartSim.shouldAddPart())
586 {
587 // Particle simulation says we have too many particles, skip all this
588 return;
589 }
590
591 if (!mImagep)
592 {
593 LLUUID id;
594 id.set( gViewerArt.getString("pixiesmall.tga") );
595 mImagep = gImageList.getImage(id);
596 }
597
598 LLViewerPart part;
599 part.init(this, mImagep, NULL);
600
601 part.mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
602 LLPartData::LL_PART_INTERP_SCALE_MASK |
603 LLPartData::LL_PART_TARGET_POS_MASK |
604 LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
605 part.mMaxAge = 0.5f;
606 part.mStartColor = mColor;
607 part.mEndColor = part.mStartColor;
608 part.mEndColor.mV[3] = 0.4f;
609 part.mColor = part.mStartColor;
610
611 part.mStartScale = LLVector2(0.1f, 0.1f);
612 part.mEndScale = LLVector2(0.1f, 0.1f);
613 part.mScale = part.mStartScale;
614
615 part.mPosAgent = mPosAgent;
616 part.mVelocity = mTargetPosAgent - mPosAgent;
617
618 gWorldPointer->mPartSim.addPart(part);
619 }
620}
621
622void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
623{
624 mSourceObjectp = objp;
625}
626
627void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
628{
629 mTargetObjectp = objp;
630}
631
632
633
634
635LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
636 LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
637{
638 mPosAgent = pos;
639}
640
641void LLViewerPartSourceChat::setDead()
642{
643 mIsDead = TRUE;
644 mSourceObjectp = NULL;
645}
646
647
648void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
649{
650 F32 frac = part.mLastUpdateTime/part.mMaxAge;
651
652 LLVector3 center_pos;
653 LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
654 LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps;
655 if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
656 {
657 part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
658 }
659 else
660 {
661 part.mPosAgent = pss->mPosAgent;
662 }
663 F32 x = sin(F_TWO_PI*frac + part.mParameter);
664 F32 y = cos(F_TWO_PI*frac + part.mParameter);
665
666 part.mPosAgent.mV[VX] += x;
667 part.mPosAgent.mV[VY] += y;
668 part.mPosAgent.mV[VZ] += -0.5f + frac;
669}
670
671
672void LLViewerPartSourceChat::update(const F32 dt)
673{
674 if (!mImagep)
675 {
676 LLUUID id;
677 id.set( gViewerArt.getString("pixiesmall.tga") );
678 mImagep = gImageList.getImage(id);
679 }
680
681
682 const F32 RATE = 0.025f;
683
684 mLastUpdateTime += dt;
685
686 if (mLastUpdateTime > 2.f)
687 {
688 // Kill particle source because it has outlived its max age...
689 setDead();
690 return;
691 }
692
693 F32 dt_update = mLastUpdateTime - mLastPartTime;
694
695 // Clamp us to generating at most one second's worth of particles on a frame.
696 F32 max_time = llmax(1.f, 10.f*RATE);
697 dt_update = llmin(max_time, dt_update);
698
699 if (dt_update > RATE)
700 {
701 mLastPartTime = mLastUpdateTime;
702 if (!gWorldPointer->mPartSim.shouldAddPart())
703 {
704 // Particle simulation says we have too many particles, skip all this
705 return;
706 }
707
708 if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
709 {
710 mPosAgent = mSourceObjectp->getRenderPosition();
711 }
712 LLViewerPart part;
713 part.init(this, mImagep, updatePart);
714 part.mStartColor = mColor;
715 part.mEndColor = mColor;
716 part.mEndColor.mV[3] = 0.f;
717 part.mPosAgent = mPosAgent;
718 part.mMaxAge = 1.f;
719 part.mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
720 part.mLastUpdateTime = 0.f;
721 part.mScale.mV[0] = 0.25f;
722 part.mScale.mV[1] = 0.25f;
723 part.mParameter = frand(F_TWO_PI);
724
725 gWorldPointer->mPartSim.addPart(part);
726 }
727}
728
729void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
730{
731 mSourceObjectp = objp;
732}
733
734void LLViewerPartSourceChat::setColor(const LLColor4 &color)
735{
736 mColor = color;
737}
738