diff options
author | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
---|---|---|
committer | Ansariel <ansariel.hiller@phoenixviewer.com> | 2024-05-22 19:04:52 +0200 |
commit | 1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch) | |
tree | ab243607f74f78200787bba5b9b88f07ef1b966f /indra/newview/llviewerpartsource.cpp | |
parent | 6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff) | |
parent | e1623bb276f83a43ce7a197e388720c05bdefe61 (diff) |
Merge remote-tracking branch 'origin/main' into DRTVWR-600-maint-A
# Conflicts:
# autobuild.xml
# indra/cmake/CMakeLists.txt
# indra/cmake/GoogleMock.cmake
# indra/llaudio/llaudioengine_fmodstudio.cpp
# indra/llaudio/llaudioengine_fmodstudio.h
# indra/llaudio/lllistener_fmodstudio.cpp
# indra/llaudio/lllistener_fmodstudio.h
# indra/llaudio/llstreamingaudio_fmodstudio.cpp
# indra/llaudio/llstreamingaudio_fmodstudio.h
# indra/llcharacter/llmultigesture.cpp
# indra/llcharacter/llmultigesture.h
# indra/llimage/llimage.cpp
# indra/llimage/llimagepng.cpp
# indra/llimage/llimageworker.cpp
# indra/llimage/tests/llimageworker_test.cpp
# indra/llmessage/tests/llmockhttpclient.h
# indra/llprimitive/llgltfmaterial.h
# indra/llrender/llfontfreetype.cpp
# indra/llui/llcombobox.cpp
# indra/llui/llfolderview.cpp
# indra/llui/llfolderviewmodel.h
# indra/llui/lllineeditor.cpp
# indra/llui/lllineeditor.h
# indra/llui/lltextbase.cpp
# indra/llui/lltextbase.h
# indra/llui/lltexteditor.cpp
# indra/llui/lltextvalidate.cpp
# indra/llui/lltextvalidate.h
# indra/llui/lluictrl.h
# indra/llui/llview.cpp
# indra/llwindow/llwindowmacosx.cpp
# indra/newview/app_settings/settings.xml
# indra/newview/llappearancemgr.cpp
# indra/newview/llappearancemgr.h
# indra/newview/llavatarpropertiesprocessor.cpp
# indra/newview/llavatarpropertiesprocessor.h
# indra/newview/llbreadcrumbview.cpp
# indra/newview/llbreadcrumbview.h
# indra/newview/llbreastmotion.cpp
# indra/newview/llbreastmotion.h
# indra/newview/llconversationmodel.h
# indra/newview/lldensityctrl.cpp
# indra/newview/lldensityctrl.h
# indra/newview/llface.inl
# indra/newview/llfloatereditsky.cpp
# indra/newview/llfloatereditwater.cpp
# indra/newview/llfloateremojipicker.h
# indra/newview/llfloaterimsessiontab.cpp
# indra/newview/llfloaterprofiletexture.cpp
# indra/newview/llfloaterprofiletexture.h
# indra/newview/llgesturemgr.cpp
# indra/newview/llgesturemgr.h
# indra/newview/llimpanel.cpp
# indra/newview/llimpanel.h
# indra/newview/llinventorybridge.cpp
# indra/newview/llinventorybridge.h
# indra/newview/llinventoryclipboard.cpp
# indra/newview/llinventoryclipboard.h
# indra/newview/llinventoryfunctions.cpp
# indra/newview/llinventoryfunctions.h
# indra/newview/llinventorygallery.cpp
# indra/newview/lllistbrowser.cpp
# indra/newview/lllistbrowser.h
# indra/newview/llpanelobjectinventory.cpp
# indra/newview/llpanelprofile.cpp
# indra/newview/llpanelprofile.h
# indra/newview/llpreviewgesture.cpp
# indra/newview/llsavedsettingsglue.cpp
# indra/newview/llsavedsettingsglue.h
# indra/newview/lltooldraganddrop.cpp
# indra/newview/llurllineeditorctrl.cpp
# indra/newview/llvectorperfoptions.cpp
# indra/newview/llvectorperfoptions.h
# indra/newview/llviewerparceloverlay.cpp
# indra/newview/llviewertexlayer.cpp
# indra/newview/llviewertexturelist.cpp
# indra/newview/macmain.h
# indra/test/test.cpp
Diffstat (limited to 'indra/newview/llviewerpartsource.cpp')
-rw-r--r-- | indra/newview/llviewerpartsource.cpp | 1892 |
1 files changed, 946 insertions, 946 deletions
diff --git a/indra/newview/llviewerpartsource.cpp b/indra/newview/llviewerpartsource.cpp index aa62df176f..8664e93bc3 100644 --- a/indra/newview/llviewerpartsource.cpp +++ b/indra/newview/llviewerpartsource.cpp @@ -1,946 +1,946 @@ -/** - * @file llviewerpartsource.cpp - * @brief LLViewerPartSource class implementation - * - * $LicenseInfo:firstyear=2003&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" -#include "llviewerpartsource.h" - -#include "llviewercontrol.h" -#include "llrender.h" - -#include "llagent.h" -#include "lldrawable.h" -#include "llviewercamera.h" -#include "llviewertexturelist.h" -#include "llviewerobject.h" -#include "llviewerobjectlist.h" -#include "llvoavatar.h" -#include "llworld.h" -#include "pipeline.h" - - -static LLVOAvatar* find_avatar(const LLUUID& id) -{ - LLViewerObject *obj = gObjectList.findObject(id); - while (obj && obj->isAttachment()) - { - obj = (LLViewerObject *)obj->getParent(); - } - - if (obj && obj->isAvatar()) - { - return (LLVOAvatar*)obj; - } - else - { - return NULL; - } -} - -LLViewerPartSource::LLViewerPartSource(const U32 type) : - mType(type), - mOwnerUUID(LLUUID::null), - mPartFlags(0) -{ - mLastUpdateTime = 0.f; - mLastPartTime = 0.f; - mIsDead = false; - mIsSuspended = false; - static U32 id_seed = 0; - mID = ++id_seed; - - mLastPart = NULL; - - mDelay = 0 ; -} - -void LLViewerPartSource::setDead() -{ - mIsDead = true; -} - - -void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt) -{ -} - -void LLViewerPartSource::update(const F32 dt) -{ - LL_ERRS() << "Creating default part source!" << LL_ENDL; -} - -LLUUID LLViewerPartSource::getImageUUID() const -{ - LLViewerTexture* imagep = mImagep; - if(imagep) - { - return imagep->getID(); - } - return LLUUID::null; -} -void LLViewerPartSource::setStart() -{ - //cancel delaying to start a new added particle source, because some particle source just emits for a short time. - //however, canceling this might cause overall particle emmitting fluctuate for a while because the new added source jumps to - //the current particle emmitting settings instantly. -->bao - mDelay = 0 ; //99 -} - -LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) : - LLViewerPartSource(LL_PART_SOURCE_SCRIPT) -{ - llassert(source_objp); - mSourceObjectp = source_objp; - mPosAgent = mSourceObjectp->getPositionAgent(); - mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - - mImagep->setAddressMode(LLTexUnit::TAM_CLAMP); -} - - -void LLViewerPartSourceScript::setDead() -{ - mIsDead = true; - mSourceObjectp = NULL; - mTargetObjectp = NULL; -} - -void LLViewerPartSourceScript::update(const F32 dt) -{ - if( mIsSuspended ) - return; - - if (mOwnerAvatarp.isNull() && mOwnerUUID != LLUUID::null) - { - mOwnerAvatarp = find_avatar(mOwnerUUID); - } - if (mOwnerAvatarp.notNull() && LLVOAvatar::AOA_NORMAL != mOwnerAvatarp->getOverallAppearance()) - { - return; - } - - F32 old_update_time = mLastUpdateTime; - mLastUpdateTime += dt; - - F32 ref_rate_travelspeed = llmin(LLViewerPartSim::getInstance()->getRefRate(), 1.f); - - F32 dt_update = mLastUpdateTime - mLastPartTime; - - // Update this for objects which have the follow flag set... - if (!mSourceObjectp.isNull()) - { - if (mSourceObjectp->isDead()) - { - mSourceObjectp = NULL; - } - else if (mSourceObjectp->mDrawable.notNull()) - { - mPosAgent = mSourceObjectp->getRenderPosition(); - } - } - - if (mTargetObjectp.isNull() - && mPartSysData.mTargetUUID.notNull()) - { - // - // Hmm, missing object, let's see if we can find it... - // - - LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID); - setTargetObject(target_objp); - } - - if (!mTargetObjectp.isNull()) - { - if (mTargetObjectp->isDead()) - { - mTargetObjectp = NULL; - } - else if (mTargetObjectp->mDrawable.notNull()) - { - mTargetPosAgent = mTargetObjectp->getRenderPosition(); - } - } - - if (!mTargetObjectp) - { - mTargetPosAgent = mPosAgent; - } - - if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge)) - { - // Kill particle source because it has outlived its max age... - setDead(); - return; - } - - - if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES)) - { - if (mSourceObjectp.notNull()) - { - std::ostringstream ostr; - ostr << mPartSysData; - mSourceObjectp->setDebugText(ostr.str()); - } - } - - bool first_run = false; - if (old_update_time <= 0.f) - { - first_run = true; - } - - F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate); - dt_update = llmin(max_time, dt_update); - while ((dt_update > mPartSysData.mBurstRate) || first_run) - { - first_run = false; - - // Update the rotation of the particle source by the angular velocity - // First check to see if there is still an angular velocity. - F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec(); - if (angular_velocity_mag != 0.0f) - { - F32 av_angle = dt * angular_velocity_mag; - LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity); - mRotation *= dquat; - } - else - { - // No angular velocity. Reset our rotation. - mRotation.setQuat(0, 0, 0); - } - - if (LLViewerPartSim::getInstance()->aboveParticleLimit()) - { - // Don't bother doing any more updates if we're above the particle limit, - // just give up. - mLastPartTime = mLastUpdateTime; - break; - - } - - // find the greatest length that the shortest side of a system - // particle is expected to have - F32 max_short_side = - llmax( - llmax(llmin(mPartSysData.mPartData.mStartScale[0], - mPartSysData.mPartData.mStartScale[1]), - llmin(mPartSysData.mPartData.mEndScale[0], - mPartSysData.mPartData.mEndScale[1])), - llmin((mPartSysData.mPartData.mStartScale[0] - + mPartSysData.mPartData.mEndScale[0])/2, - (mPartSysData.mPartData.mStartScale[1] - + mPartSysData.mPartData.mEndScale[1])/2)); - - F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio(); - - // Maximum distance at which spawned particles will be viewable - F32 max_dist = max_short_side * pixel_meter_ratio; - - if (max_dist < 0.25f) - { - // < 1 pixel wide at a distance of >=25cm. Particles - // this tiny are useless and mostly spawned by buggy - // sources - mLastPartTime = mLastUpdateTime; - break; - } - - // Distance from camera - F32 dist = (mPosAgent - LLViewerCamera::getInstance()->getOrigin()).magVec(); - - // Particle size vs distance vs maxage throttling - - F32 limited_rate=0.f; - if (dist - max_dist > 0.f) - { - if((dist - max_dist) * ref_rate_travelspeed > mPartSysData.mPartData.mMaxAge - 0.2f ) - { - // You need to travel faster than 1 divided by reference rate m/s directly towards these particles to see them at least 0.2s - mLastPartTime = mLastUpdateTime; - break; - } - limited_rate = ((dist - max_dist) * ref_rate_travelspeed) / mPartSysData.mPartData.mMaxAge; - } - - if(mDelay) - { - limited_rate = llmax(limited_rate, 0.01f * mDelay--) ; - } - - S32 i; - for (i = 0; i < mPartSysData.mBurstPartCount; i++) - { - if (ll_frand() < llmax(1.0f - LLViewerPartSim::getInstance()->getBurstRate(), limited_rate)) - { - // Limit particle generation - continue; - } - - LLViewerPart* part = new LLViewerPart(); - - part->init(this, mImagep, NULL); - part->mFlags = mPartSysData.mPartData.mFlags; - if (!mSourceObjectp.isNull() && mSourceObjectp->isHUDAttachment()) - { - part->mFlags |= LLPartData::LL_PART_HUD; - } - - if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart) - { //set previous particle's parent to this particle to chain ribbon together - mLastPart->mParent = part; - part->mChild = mLastPart; - part->mAxis = LLVector3(0,0,1); - - if (mSourceObjectp.notNull()) - { - LLQuaternion rot = mSourceObjectp->getRenderRotation(); - part->mAxis *= rot; - } - } - - mLastPart = part; - - part->mMaxAge = mPartSysData.mPartData.mMaxAge; - part->mStartColor = mPartSysData.mPartData.mStartColor; - part->mEndColor = mPartSysData.mPartData.mEndColor; - part->mColor = part->mStartColor; - - part->mStartScale = mPartSysData.mPartData.mStartScale; - part->mEndScale = mPartSysData.mPartData.mEndScale; - part->mScale = part->mStartScale; - - part->mAccel = mPartSysData.mPartAccel; - - part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest; - part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource; - - part->mStartGlow = mPartSysData.mPartData.mStartGlow; - part->mEndGlow = mPartSysData.mPartData.mEndGlow; - part->mGlow = LLColor4U(0, 0, 0, (U8) ll_round(part->mStartGlow*255.f)); - - if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP) - { - part->mPosAgent = mPosAgent; - part->mVelocity.setVec(0.f, 0.f, 0.f); - } - else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE) - { - part->mPosAgent = mPosAgent; - LLVector3 part_dir_vector; - - F32 mvs; - do - { - part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f; - part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f; - part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f; - mvs = part_dir_vector.magVecSquared(); - } - while ((mvs > 1.f) || (mvs < 0.01f)); - - part_dir_vector.normVec(); - part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; - part->mVelocity = part_dir_vector; - F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); - part->mVelocity *= speed; - } - else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE - || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE) - { - part->mPosAgent = mPosAgent; - - // original implemenetation for part_dir_vector was just: - LLVector3 part_dir_vector(0.0, 0.0, 1.0); - // params from the script... - // outer = outer cone angle - // inner = inner cone angle - // between outer and inner there will be particles - F32 innerAngle = mPartSysData.mInnerAngle; - F32 outerAngle = mPartSysData.mOuterAngle; - - // generate a random angle within the given space... - F32 angle = innerAngle + ll_frand(outerAngle - innerAngle); - // split which side it will go on randomly... - if (ll_frand() < 0.5) - { - angle = -angle; - } - // Both patterns rotate around the x-axis first: - part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0); - - // If this is a cone pattern, rotate again to create the cone. - if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE) - { - part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0); - } - - // Only apply this rotation if using the deprecated angles. - if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE)) - { - // Deprecated... - part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0); - } - - if (mSourceObjectp) - { - part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation(); - } - - part_dir_vector = part_dir_vector * mRotation; - - part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector; - - part->mVelocity = part_dir_vector; - - F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin); - part->mVelocity *= speed; - } - else - { - part->mPosAgent = mPosAgent; - part->mVelocity.setVec(0.f, 0.f, 0.f); - //LL_WARNS() << "Unknown source pattern " << (S32)mPartSysData.mPattern << LL_ENDL; - } - - if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK || // SVC-193, VWR-717 - part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK) - { - mPartSysData.mBurstRadius = 0; - } - - LLViewerPartSim::getInstance()->addPart(part); - } - - mLastPartTime = mLastUpdateTime; - dt_update -= mPartSysData.mBurstRate; - } -} - -// static -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num) -{ - if (!pssp) - { - if (LLPartSysData::isNullPS(block_num)) - { - return NULL; - } - LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); - if (!new_pssp->mPartSysData.unpackBlock(block_num)) - { - return NULL; - } - if (new_pssp->mPartSysData.mTargetUUID.notNull()) - { - LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID); - new_pssp->setTargetObject(target_objp); - } - return new_pssp; - } - else - { - if (LLPartSysData::isNullPS(block_num)) - { - return NULL; - } - - F32 prev_max_age = pssp->mPartSysData.mMaxAge; - F32 prev_start_age = pssp->mPartSysData.mStartAge; - if (!pssp->mPartSysData.unpackBlock(block_num)) - { - return NULL; - } - else if (pssp->mPartSysData.mMaxAge - && (prev_max_age != pssp->mPartSysData.mMaxAge || prev_start_age != pssp->mPartSysData.mStartAge)) - { - // reusing existing pss, so reset time to allow particles to start again - pssp->mLastUpdateTime = 0.f; - pssp->mLastPartTime = 0.f; - } - - if (pssp->mPartSysData.mTargetUUID.notNull()) - { - LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); - pssp->setTargetObject(target_objp); - } - return pssp; - } -} - - -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy) -{ - if (!pssp) - { - LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); - if (legacy) - { - if (!new_pssp->mPartSysData.unpackLegacy(dp)) - { - return NULL; - } - } - else - { - if (!new_pssp->mPartSysData.unpack(dp)) - { - return NULL; - } - } - - if (new_pssp->mPartSysData.mTargetUUID.notNull()) - { - LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID); - new_pssp->setTargetObject(target_objp); - } - - return new_pssp; - } - else - { - if (legacy) - { - if (!pssp->mPartSysData.unpackLegacy(dp)) - { - return NULL; - } - } - else - { - if (!pssp->mPartSysData.unpack(dp)) - { - return NULL; - } - } - - if (pssp->mPartSysData.mTargetUUID.notNull()) - { - LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID); - pssp->setTargetObject(target_objp); - } - return pssp; - } -} - - -/* static */ -LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters) -{ - LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp); - - new_pssp->mPartSysData = particle_parameters; - - if (new_pssp->mPartSysData.mTargetUUID.notNull()) - { - LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID); - new_pssp->setTargetObject(target_objp); - } - return new_pssp; -} - - -void LLViewerPartSourceScript::setImage(LLViewerTexture *imagep) -{ - mImagep = imagep; -} - -void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp) -{ - mTargetObjectp = objp; -} - - - - - -LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) : - LLViewerPartSource(LL_PART_SOURCE_CHAT) -{ - mPosAgent = pos; -} - -void LLViewerPartSourceSpiral::setDead() -{ - mIsDead = true; - mSourceObjectp = NULL; -} - - -void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt) -{ - F32 frac = part.mLastUpdateTime/part.mMaxAge; - - LLVector3 center_pos; - LLPointer<LLViewerPartSource>& ps = part.mPartSourcep; - LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get(); - if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull()) - { - part.mPosAgent = pss->mSourceObjectp->getRenderPosition(); - } - else - { - part.mPosAgent = pss->mPosAgent; - } - F32 x = sin(F_TWO_PI*frac + part.mParameter); - F32 y = cos(F_TWO_PI*frac + part.mParameter); - - part.mPosAgent.mV[VX] += x; - part.mPosAgent.mV[VY] += y; - part.mPosAgent.mV[VZ] += -0.5f + frac; -} - - -void LLViewerPartSourceSpiral::update(const F32 dt) -{ - if (!mImagep) - { - mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - - const F32 RATE = 0.025f; - - mLastUpdateTime += dt; - - F32 dt_update = mLastUpdateTime - mLastPartTime; - F32 max_time = llmax(1.f, 10.f*RATE); - dt_update = llmin(max_time, dt_update); - - if (dt_update > RATE) - { - mLastPartTime = mLastUpdateTime; - if (!LLViewerPartSim::getInstance()->shouldAddPart()) - { - // Particle simulation says we have too many particles, skip all this - return; - } - - if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull()) - { - mPosAgent = mSourceObjectp->getRenderPosition(); - } - LLViewerPart* part = new LLViewerPart(); - part->init(this, mImagep, updatePart); - part->mStartColor = mColor; - part->mEndColor = mColor; - part->mEndColor.mV[3] = 0.f; - part->mPosAgent = mPosAgent; - part->mMaxAge = 1.f; - part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; - part->mLastUpdateTime = 0.f; - part->mScale.mV[0] = 0.25f; - part->mScale.mV[1] = 0.25f; - part->mParameter = ll_frand(F_TWO_PI); - part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; - part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; - part->mStartGlow = 0.f; - part->mEndGlow = 0.f; - part->mGlow = LLColor4U(0, 0, 0, 0); - - LLViewerPartSim::getInstance()->addPart(part); - } -} - -void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp) -{ - mSourceObjectp = objp; -} - -void LLViewerPartSourceSpiral::setColor(const LLColor4 &color) -{ - mColor = color; -} - - - - - -LLViewerPartSourceBeam::LLViewerPartSourceBeam() : - LLViewerPartSource(LL_PART_SOURCE_BEAM) -{ -} - -LLViewerPartSourceBeam::~LLViewerPartSourceBeam() -{ -} - -void LLViewerPartSourceBeam::setDead() -{ - mIsDead = true; - mSourceObjectp = NULL; - mTargetObjectp = NULL; -} - -void LLViewerPartSourceBeam::setColor(const LLColor4 &color) -{ - mColor = color; -} - - -void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt) -{ - F32 frac = part.mLastUpdateTime/part.mMaxAge; - - LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep; - LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps; - if (psb->mSourceObjectp.isNull()) - { - part.mFlags = LLPartData::LL_PART_DEAD_MASK; - return; - } - - LLVector3 source_pos_agent; - LLVector3 target_pos_agent; - if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull()) - { - if (psb->mSourceObjectp->isAvatar()) - { - LLViewerObject *objp = psb->mSourceObjectp; - LLVOAvatar *avp = (LLVOAvatar *)objp; - source_pos_agent = avp->mWristLeftp->getWorldPosition(); - } - else - { - source_pos_agent = psb->mSourceObjectp->getRenderPosition(); - } - } - if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull()) - { - target_pos_agent = psb->mTargetObjectp->getRenderPosition(); - } - - part.mPosAgent = (1.f - frac) * source_pos_agent; - if (psb->mTargetObjectp.isNull()) - { - part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal)); - } - else - { - part.mPosAgent += frac * target_pos_agent; - } -} - - -void LLViewerPartSourceBeam::update(const F32 dt) -{ - const F32 RATE = 0.025f; - - mLastUpdateTime += dt; - - if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull()) - { - if (mSourceObjectp->isAvatar()) - { - LLViewerObject *objp = mSourceObjectp; - LLVOAvatar *avp = (LLVOAvatar *)objp; - mPosAgent = avp->mWristLeftp->getWorldPosition(); - } - else - { - mPosAgent = mSourceObjectp->getRenderPosition(); - } - } - - if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull()) - { - mTargetPosAgent = mTargetObjectp->getRenderPosition(); - } - else if (!mLKGTargetPosGlobal.isExactlyZero()) - { - mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal); - } - - F32 dt_update = mLastUpdateTime - mLastPartTime; - F32 max_time = llmax(1.f, 10.f*RATE); - dt_update = llmin(max_time, dt_update); - - if (dt_update > RATE) - { - mLastPartTime = mLastUpdateTime; - if (!LLViewerPartSim::getInstance()->shouldAddPart()) - { - // Particle simulation says we have too many particles, skip all this - return; - } - - if (!mImagep) - { - mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - - LLViewerPart* part = new LLViewerPart(); - part->init(this, mImagep, updatePart); - - part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK | - LLPartData::LL_PART_INTERP_SCALE_MASK | - LLPartData::LL_PART_TARGET_POS_MASK | - LLPartData::LL_PART_FOLLOW_VELOCITY_MASK; - part->mMaxAge = 0.5f; - part->mStartColor = mColor; - part->mEndColor = part->mStartColor; - part->mEndColor.mV[3] = 0.4f; - part->mColor = part->mStartColor; - - part->mStartScale = LLVector2(0.1f, 0.1f); - part->mEndScale = LLVector2(0.1f, 0.1f); - part->mScale = part->mStartScale; - - part->mPosAgent = mPosAgent; - part->mVelocity = mTargetPosAgent - mPosAgent; - - part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; - part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; - part->mStartGlow = 0.f; - part->mEndGlow = 0.f; - part->mGlow = LLColor4U(0, 0, 0, 0); - - LLViewerPartSim::getInstance()->addPart(part); - } -} - -void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp) -{ - mSourceObjectp = objp; -} - -void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp) -{ - mTargetObjectp = objp; -} - - - - -LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) : - LLViewerPartSource(LL_PART_SOURCE_SPIRAL) -{ - mPosAgent = pos; -} - -void LLViewerPartSourceChat::setDead() -{ - mIsDead = true; - mSourceObjectp = NULL; -} - - -void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt) -{ - F32 frac = part.mLastUpdateTime/part.mMaxAge; - - LLVector3 center_pos; - LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep; - LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps; - if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull()) - { - part.mPosAgent = pss->mSourceObjectp->getRenderPosition(); - } - else - { - part.mPosAgent = pss->mPosAgent; - } - F32 x = sin(F_TWO_PI*frac + part.mParameter); - F32 y = cos(F_TWO_PI*frac + part.mParameter); - - part.mPosAgent.mV[VX] += x; - part.mPosAgent.mV[VY] += y; - part.mPosAgent.mV[VZ] += -0.5f + frac; -} - - -void LLViewerPartSourceChat::update(const F32 dt) -{ - if (!mImagep) - { - mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - - - const F32 RATE = 0.025f; - - mLastUpdateTime += dt; - - if (mLastUpdateTime > 2.f) - { - // Kill particle source because it has outlived its max age... - setDead(); - return; - } - - F32 dt_update = mLastUpdateTime - mLastPartTime; - - // Clamp us to generating at most one second's worth of particles on a frame. - F32 max_time = llmax(1.f, 10.f*RATE); - dt_update = llmin(max_time, dt_update); - - if (dt_update > RATE) - { - mLastPartTime = mLastUpdateTime; - if (!LLViewerPartSim::getInstance()->shouldAddPart()) - { - // Particle simulation says we have too many particles, skip all this - return; - } - - if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull()) - { - mPosAgent = mSourceObjectp->getRenderPosition(); - } - LLViewerPart* part = new LLViewerPart(); - part->init(this, mImagep, updatePart); - part->mStartColor = mColor; - part->mEndColor = mColor; - part->mEndColor.mV[3] = 0.f; - part->mPosAgent = mPosAgent; - part->mMaxAge = 1.f; - part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK; - part->mLastUpdateTime = 0.f; - part->mScale.mV[0] = 0.25f; - part->mScale.mV[1] = 0.25f; - part->mParameter = ll_frand(F_TWO_PI); - part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA; - part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA; - part->mStartGlow = 0.f; - part->mEndGlow = 0.f; - part->mGlow = LLColor4U(0, 0, 0, 0); - - - LLViewerPartSim::getInstance()->addPart(part); - } -} - -void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp) -{ - mSourceObjectp = objp; -} - -void LLViewerPartSourceChat::setColor(const LLColor4 &color) -{ - mColor = color; -} - - +/**
+ * @file llviewerpartsource.cpp
+ * @brief LLViewerPartSource class implementation
+ *
+ * $LicenseInfo:firstyear=2003&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+#include "llviewerpartsource.h"
+
+#include "llviewercontrol.h"
+#include "llrender.h"
+
+#include "llagent.h"
+#include "lldrawable.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerobject.h"
+#include "llviewerobjectlist.h"
+#include "llvoavatar.h"
+#include "llworld.h"
+#include "pipeline.h"
+
+
+static LLVOAvatar* find_avatar(const LLUUID& id)
+{
+ LLViewerObject *obj = gObjectList.findObject(id);
+ while (obj && obj->isAttachment())
+ {
+ obj = (LLViewerObject *)obj->getParent();
+ }
+
+ if (obj && obj->isAvatar())
+ {
+ return (LLVOAvatar*)obj;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+LLViewerPartSource::LLViewerPartSource(const U32 type) :
+ mType(type),
+ mOwnerUUID(LLUUID::null),
+ mPartFlags(0)
+{
+ mLastUpdateTime = 0.f;
+ mLastPartTime = 0.f;
+ mIsDead = false;
+ mIsSuspended = false;
+ static U32 id_seed = 0;
+ mID = ++id_seed;
+
+ mLastPart = NULL;
+
+ mDelay = 0 ;
+}
+
+void LLViewerPartSource::setDead()
+{
+ mIsDead = true;
+}
+
+
+void LLViewerPartSource::updatePart(LLViewerPart &part, const F32 dt)
+{
+}
+
+void LLViewerPartSource::update(const F32 dt)
+{
+ LL_ERRS() << "Creating default part source!" << LL_ENDL;
+}
+
+LLUUID LLViewerPartSource::getImageUUID() const
+{
+ LLViewerTexture* imagep = mImagep;
+ if(imagep)
+ {
+ return imagep->getID();
+ }
+ return LLUUID::null;
+}
+void LLViewerPartSource::setStart()
+{
+ //cancel delaying to start a new added particle source, because some particle source just emits for a short time.
+ //however, canceling this might cause overall particle emmitting fluctuate for a while because the new added source jumps to
+ //the current particle emmitting settings instantly. -->bao
+ mDelay = 0 ; //99
+}
+
+LLViewerPartSourceScript::LLViewerPartSourceScript(LLViewerObject *source_objp) :
+ LLViewerPartSource(LL_PART_SOURCE_SCRIPT)
+{
+ llassert(source_objp);
+ mSourceObjectp = source_objp;
+ mPosAgent = mSourceObjectp->getPositionAgent();
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+
+ mImagep->setAddressMode(LLTexUnit::TAM_CLAMP);
+}
+
+
+void LLViewerPartSourceScript::setDead()
+{
+ mIsDead = true;
+ mSourceObjectp = NULL;
+ mTargetObjectp = NULL;
+}
+
+void LLViewerPartSourceScript::update(const F32 dt)
+{
+ if( mIsSuspended )
+ return;
+
+ if (mOwnerAvatarp.isNull() && mOwnerUUID != LLUUID::null)
+ {
+ mOwnerAvatarp = find_avatar(mOwnerUUID);
+ }
+ if (mOwnerAvatarp.notNull() && LLVOAvatar::AOA_NORMAL != mOwnerAvatarp->getOverallAppearance())
+ {
+ return;
+ }
+
+ F32 old_update_time = mLastUpdateTime;
+ mLastUpdateTime += dt;
+
+ F32 ref_rate_travelspeed = llmin(LLViewerPartSim::getInstance()->getRefRate(), 1.f);
+
+ F32 dt_update = mLastUpdateTime - mLastPartTime;
+
+ // Update this for objects which have the follow flag set...
+ if (!mSourceObjectp.isNull())
+ {
+ if (mSourceObjectp->isDead())
+ {
+ mSourceObjectp = NULL;
+ }
+ else if (mSourceObjectp->mDrawable.notNull())
+ {
+ mPosAgent = mSourceObjectp->getRenderPosition();
+ }
+ }
+
+ if (mTargetObjectp.isNull()
+ && mPartSysData.mTargetUUID.notNull())
+ {
+ //
+ // Hmm, missing object, let's see if we can find it...
+ //
+
+ LLViewerObject *target_objp = gObjectList.findObject(mPartSysData.mTargetUUID);
+ setTargetObject(target_objp);
+ }
+
+ if (!mTargetObjectp.isNull())
+ {
+ if (mTargetObjectp->isDead())
+ {
+ mTargetObjectp = NULL;
+ }
+ else if (mTargetObjectp->mDrawable.notNull())
+ {
+ mTargetPosAgent = mTargetObjectp->getRenderPosition();
+ }
+ }
+
+ if (!mTargetObjectp)
+ {
+ mTargetPosAgent = mPosAgent;
+ }
+
+ if (mPartSysData.mMaxAge && ((mPartSysData.mStartAge + mLastUpdateTime + dt_update) > mPartSysData.mMaxAge))
+ {
+ // Kill particle source because it has outlived its max age...
+ setDead();
+ return;
+ }
+
+
+ if (gPipeline.hasRenderDebugMask(LLPipeline::RENDER_DEBUG_PARTICLES))
+ {
+ if (mSourceObjectp.notNull())
+ {
+ std::ostringstream ostr;
+ ostr << mPartSysData;
+ mSourceObjectp->setDebugText(ostr.str());
+ }
+ }
+
+ bool first_run = false;
+ if (old_update_time <= 0.f)
+ {
+ first_run = true;
+ }
+
+ F32 max_time = llmax(1.f, 10.f*mPartSysData.mBurstRate);
+ dt_update = llmin(max_time, dt_update);
+ while ((dt_update > mPartSysData.mBurstRate) || first_run)
+ {
+ first_run = false;
+
+ // Update the rotation of the particle source by the angular velocity
+ // First check to see if there is still an angular velocity.
+ F32 angular_velocity_mag = mPartSysData.mAngularVelocity.magVec();
+ if (angular_velocity_mag != 0.0f)
+ {
+ F32 av_angle = dt * angular_velocity_mag;
+ LLQuaternion dquat(av_angle, mPartSysData.mAngularVelocity);
+ mRotation *= dquat;
+ }
+ else
+ {
+ // No angular velocity. Reset our rotation.
+ mRotation.setQuat(0, 0, 0);
+ }
+
+ if (LLViewerPartSim::getInstance()->aboveParticleLimit())
+ {
+ // Don't bother doing any more updates if we're above the particle limit,
+ // just give up.
+ mLastPartTime = mLastUpdateTime;
+ break;
+
+ }
+
+ // find the greatest length that the shortest side of a system
+ // particle is expected to have
+ F32 max_short_side =
+ llmax(
+ llmax(llmin(mPartSysData.mPartData.mStartScale[0],
+ mPartSysData.mPartData.mStartScale[1]),
+ llmin(mPartSysData.mPartData.mEndScale[0],
+ mPartSysData.mPartData.mEndScale[1])),
+ llmin((mPartSysData.mPartData.mStartScale[0]
+ + mPartSysData.mPartData.mEndScale[0])/2,
+ (mPartSysData.mPartData.mStartScale[1]
+ + mPartSysData.mPartData.mEndScale[1])/2));
+
+ F32 pixel_meter_ratio = LLViewerCamera::getInstance()->getPixelMeterRatio();
+
+ // Maximum distance at which spawned particles will be viewable
+ F32 max_dist = max_short_side * pixel_meter_ratio;
+
+ if (max_dist < 0.25f)
+ {
+ // < 1 pixel wide at a distance of >=25cm. Particles
+ // this tiny are useless and mostly spawned by buggy
+ // sources
+ mLastPartTime = mLastUpdateTime;
+ break;
+ }
+
+ // Distance from camera
+ F32 dist = (mPosAgent - LLViewerCamera::getInstance()->getOrigin()).magVec();
+
+ // Particle size vs distance vs maxage throttling
+
+ F32 limited_rate=0.f;
+ if (dist - max_dist > 0.f)
+ {
+ if((dist - max_dist) * ref_rate_travelspeed > mPartSysData.mPartData.mMaxAge - 0.2f )
+ {
+ // You need to travel faster than 1 divided by reference rate m/s directly towards these particles to see them at least 0.2s
+ mLastPartTime = mLastUpdateTime;
+ break;
+ }
+ limited_rate = ((dist - max_dist) * ref_rate_travelspeed) / mPartSysData.mPartData.mMaxAge;
+ }
+
+ if(mDelay)
+ {
+ limited_rate = llmax(limited_rate, 0.01f * mDelay--) ;
+ }
+
+ S32 i;
+ for (i = 0; i < mPartSysData.mBurstPartCount; i++)
+ {
+ if (ll_frand() < llmax(1.0f - LLViewerPartSim::getInstance()->getBurstRate(), limited_rate))
+ {
+ // Limit particle generation
+ continue;
+ }
+
+ LLViewerPart* part = new LLViewerPart();
+
+ part->init(this, mImagep, NULL);
+ part->mFlags = mPartSysData.mPartData.mFlags;
+ if (!mSourceObjectp.isNull() && mSourceObjectp->isHUDAttachment())
+ {
+ part->mFlags |= LLPartData::LL_PART_HUD;
+ }
+
+ if (part->mFlags & LLPartData::LL_PART_RIBBON_MASK && mLastPart)
+ { //set previous particle's parent to this particle to chain ribbon together
+ mLastPart->mParent = part;
+ part->mChild = mLastPart;
+ part->mAxis = LLVector3(0,0,1);
+
+ if (mSourceObjectp.notNull())
+ {
+ LLQuaternion rot = mSourceObjectp->getRenderRotation();
+ part->mAxis *= rot;
+ }
+ }
+
+ mLastPart = part;
+
+ part->mMaxAge = mPartSysData.mPartData.mMaxAge;
+ part->mStartColor = mPartSysData.mPartData.mStartColor;
+ part->mEndColor = mPartSysData.mPartData.mEndColor;
+ part->mColor = part->mStartColor;
+
+ part->mStartScale = mPartSysData.mPartData.mStartScale;
+ part->mEndScale = mPartSysData.mPartData.mEndScale;
+ part->mScale = part->mStartScale;
+
+ part->mAccel = mPartSysData.mPartAccel;
+
+ part->mBlendFuncDest = mPartSysData.mPartData.mBlendFuncDest;
+ part->mBlendFuncSource = mPartSysData.mPartData.mBlendFuncSource;
+
+ part->mStartGlow = mPartSysData.mPartData.mStartGlow;
+ part->mEndGlow = mPartSysData.mPartData.mEndGlow;
+ part->mGlow = LLColor4U(0, 0, 0, (U8) ll_round(part->mStartGlow*255.f));
+
+ if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_DROP)
+ {
+ part->mPosAgent = mPosAgent;
+ part->mVelocity.setVec(0.f, 0.f, 0.f);
+ }
+ else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_EXPLODE)
+ {
+ part->mPosAgent = mPosAgent;
+ LLVector3 part_dir_vector;
+
+ F32 mvs;
+ do
+ {
+ part_dir_vector.mV[VX] = ll_frand(2.f) - 1.f;
+ part_dir_vector.mV[VY] = ll_frand(2.f) - 1.f;
+ part_dir_vector.mV[VZ] = ll_frand(2.f) - 1.f;
+ mvs = part_dir_vector.magVecSquared();
+ }
+ while ((mvs > 1.f) || (mvs < 0.01f));
+
+ part_dir_vector.normVec();
+ part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
+ part->mVelocity = part_dir_vector;
+ F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
+ part->mVelocity *= speed;
+ }
+ else if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE
+ || mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
+ {
+ part->mPosAgent = mPosAgent;
+
+ // original implemenetation for part_dir_vector was just:
+ LLVector3 part_dir_vector(0.0, 0.0, 1.0);
+ // params from the script...
+ // outer = outer cone angle
+ // inner = inner cone angle
+ // between outer and inner there will be particles
+ F32 innerAngle = mPartSysData.mInnerAngle;
+ F32 outerAngle = mPartSysData.mOuterAngle;
+
+ // generate a random angle within the given space...
+ F32 angle = innerAngle + ll_frand(outerAngle - innerAngle);
+ // split which side it will go on randomly...
+ if (ll_frand() < 0.5)
+ {
+ angle = -angle;
+ }
+ // Both patterns rotate around the x-axis first:
+ part_dir_vector.rotVec(angle, 1.0, 0.0, 0.0);
+
+ // If this is a cone pattern, rotate again to create the cone.
+ if (mPartSysData.mPattern & LLPartSysData::LL_PART_SRC_PATTERN_ANGLE_CONE)
+ {
+ part_dir_vector.rotVec(ll_frand(4*F_PI), 0.0, 0.0, 1.0);
+ }
+
+ // Only apply this rotation if using the deprecated angles.
+ if (! (mPartSysData.mFlags & LLPartSysData::LL_PART_USE_NEW_ANGLE))
+ {
+ // Deprecated...
+ part_dir_vector.rotVec(outerAngle, 1.0, 0.0, 0.0);
+ }
+
+ if (mSourceObjectp)
+ {
+ part_dir_vector = part_dir_vector * mSourceObjectp->getRenderRotation();
+ }
+
+ part_dir_vector = part_dir_vector * mRotation;
+
+ part->mPosAgent += mPartSysData.mBurstRadius*part_dir_vector;
+
+ part->mVelocity = part_dir_vector;
+
+ F32 speed = mPartSysData.mBurstSpeedMin + ll_frand(mPartSysData.mBurstSpeedMax - mPartSysData.mBurstSpeedMin);
+ part->mVelocity *= speed;
+ }
+ else
+ {
+ part->mPosAgent = mPosAgent;
+ part->mVelocity.setVec(0.f, 0.f, 0.f);
+ //LL_WARNS() << "Unknown source pattern " << (S32)mPartSysData.mPattern << LL_ENDL;
+ }
+
+ if (part->mFlags & LLPartData::LL_PART_FOLLOW_SRC_MASK || // SVC-193, VWR-717
+ part->mFlags & LLPartData::LL_PART_TARGET_LINEAR_MASK)
+ {
+ mPartSysData.mBurstRadius = 0;
+ }
+
+ LLViewerPartSim::getInstance()->addPart(part);
+ }
+
+ mLastPartTime = mLastUpdateTime;
+ dt_update -= mPartSysData.mBurstRate;
+ }
+}
+
+// static
+LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, const S32 block_num)
+{
+ if (!pssp)
+ {
+ if (LLPartSysData::isNullPS(block_num))
+ {
+ return NULL;
+ }
+ LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
+ if (!new_pssp->mPartSysData.unpackBlock(block_num))
+ {
+ return NULL;
+ }
+ if (new_pssp->mPartSysData.mTargetUUID.notNull())
+ {
+ LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
+ new_pssp->setTargetObject(target_objp);
+ }
+ return new_pssp;
+ }
+ else
+ {
+ if (LLPartSysData::isNullPS(block_num))
+ {
+ return NULL;
+ }
+
+ F32 prev_max_age = pssp->mPartSysData.mMaxAge;
+ F32 prev_start_age = pssp->mPartSysData.mStartAge;
+ if (!pssp->mPartSysData.unpackBlock(block_num))
+ {
+ return NULL;
+ }
+ else if (pssp->mPartSysData.mMaxAge
+ && (prev_max_age != pssp->mPartSysData.mMaxAge || prev_start_age != pssp->mPartSysData.mStartAge))
+ {
+ // reusing existing pss, so reset time to allow particles to start again
+ pssp->mLastUpdateTime = 0.f;
+ pssp->mLastPartTime = 0.f;
+ }
+
+ if (pssp->mPartSysData.mTargetUUID.notNull())
+ {
+ LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
+ pssp->setTargetObject(target_objp);
+ }
+ return pssp;
+ }
+}
+
+
+LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::unpackPSS(LLViewerObject *source_objp, LLPointer<LLViewerPartSourceScript> pssp, LLDataPacker &dp, bool legacy)
+{
+ if (!pssp)
+ {
+ LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
+ if (legacy)
+ {
+ if (!new_pssp->mPartSysData.unpackLegacy(dp))
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ if (!new_pssp->mPartSysData.unpack(dp))
+ {
+ return NULL;
+ }
+ }
+
+ if (new_pssp->mPartSysData.mTargetUUID.notNull())
+ {
+ LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
+ new_pssp->setTargetObject(target_objp);
+ }
+
+ return new_pssp;
+ }
+ else
+ {
+ if (legacy)
+ {
+ if (!pssp->mPartSysData.unpackLegacy(dp))
+ {
+ return NULL;
+ }
+ }
+ else
+ {
+ if (!pssp->mPartSysData.unpack(dp))
+ {
+ return NULL;
+ }
+ }
+
+ if (pssp->mPartSysData.mTargetUUID.notNull())
+ {
+ LLViewerObject *target_objp = gObjectList.findObject(pssp->mPartSysData.mTargetUUID);
+ pssp->setTargetObject(target_objp);
+ }
+ return pssp;
+ }
+}
+
+
+/* static */
+LLPointer<LLViewerPartSourceScript> LLViewerPartSourceScript::createPSS(LLViewerObject *source_objp, const LLPartSysData& particle_parameters)
+{
+ LLPointer<LLViewerPartSourceScript> new_pssp = new LLViewerPartSourceScript(source_objp);
+
+ new_pssp->mPartSysData = particle_parameters;
+
+ if (new_pssp->mPartSysData.mTargetUUID.notNull())
+ {
+ LLViewerObject *target_objp = gObjectList.findObject(new_pssp->mPartSysData.mTargetUUID);
+ new_pssp->setTargetObject(target_objp);
+ }
+ return new_pssp;
+}
+
+
+void LLViewerPartSourceScript::setImage(LLViewerTexture *imagep)
+{
+ mImagep = imagep;
+}
+
+void LLViewerPartSourceScript::setTargetObject(LLViewerObject *objp)
+{
+ mTargetObjectp = objp;
+}
+
+
+
+
+
+LLViewerPartSourceSpiral::LLViewerPartSourceSpiral(const LLVector3 &pos) :
+ LLViewerPartSource(LL_PART_SOURCE_CHAT)
+{
+ mPosAgent = pos;
+}
+
+void LLViewerPartSourceSpiral::setDead()
+{
+ mIsDead = true;
+ mSourceObjectp = NULL;
+}
+
+
+void LLViewerPartSourceSpiral::updatePart(LLViewerPart &part, const F32 dt)
+{
+ F32 frac = part.mLastUpdateTime/part.mMaxAge;
+
+ LLVector3 center_pos;
+ LLPointer<LLViewerPartSource>& ps = part.mPartSourcep;
+ LLViewerPartSourceSpiral *pss = (LLViewerPartSourceSpiral *)ps.get();
+ if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
+ {
+ part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
+ }
+ else
+ {
+ part.mPosAgent = pss->mPosAgent;
+ }
+ F32 x = sin(F_TWO_PI*frac + part.mParameter);
+ F32 y = cos(F_TWO_PI*frac + part.mParameter);
+
+ part.mPosAgent.mV[VX] += x;
+ part.mPosAgent.mV[VY] += y;
+ part.mPosAgent.mV[VZ] += -0.5f + frac;
+}
+
+
+void LLViewerPartSourceSpiral::update(const F32 dt)
+{
+ if (!mImagep)
+ {
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+ }
+
+ const F32 RATE = 0.025f;
+
+ mLastUpdateTime += dt;
+
+ F32 dt_update = mLastUpdateTime - mLastPartTime;
+ F32 max_time = llmax(1.f, 10.f*RATE);
+ dt_update = llmin(max_time, dt_update);
+
+ if (dt_update > RATE)
+ {
+ mLastPartTime = mLastUpdateTime;
+ if (!LLViewerPartSim::getInstance()->shouldAddPart())
+ {
+ // Particle simulation says we have too many particles, skip all this
+ return;
+ }
+
+ if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
+ {
+ mPosAgent = mSourceObjectp->getRenderPosition();
+ }
+ LLViewerPart* part = new LLViewerPart();
+ part->init(this, mImagep, updatePart);
+ part->mStartColor = mColor;
+ part->mEndColor = mColor;
+ part->mEndColor.mV[3] = 0.f;
+ part->mPosAgent = mPosAgent;
+ part->mMaxAge = 1.f;
+ part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
+ part->mLastUpdateTime = 0.f;
+ part->mScale.mV[0] = 0.25f;
+ part->mScale.mV[1] = 0.25f;
+ part->mParameter = ll_frand(F_TWO_PI);
+ part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
+ part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
+ part->mStartGlow = 0.f;
+ part->mEndGlow = 0.f;
+ part->mGlow = LLColor4U(0, 0, 0, 0);
+
+ LLViewerPartSim::getInstance()->addPart(part);
+ }
+}
+
+void LLViewerPartSourceSpiral::setSourceObject(LLViewerObject *objp)
+{
+ mSourceObjectp = objp;
+}
+
+void LLViewerPartSourceSpiral::setColor(const LLColor4 &color)
+{
+ mColor = color;
+}
+
+
+
+
+
+LLViewerPartSourceBeam::LLViewerPartSourceBeam() :
+ LLViewerPartSource(LL_PART_SOURCE_BEAM)
+{
+}
+
+LLViewerPartSourceBeam::~LLViewerPartSourceBeam()
+{
+}
+
+void LLViewerPartSourceBeam::setDead()
+{
+ mIsDead = true;
+ mSourceObjectp = NULL;
+ mTargetObjectp = NULL;
+}
+
+void LLViewerPartSourceBeam::setColor(const LLColor4 &color)
+{
+ mColor = color;
+}
+
+
+void LLViewerPartSourceBeam::updatePart(LLViewerPart &part, const F32 dt)
+{
+ F32 frac = part.mLastUpdateTime/part.mMaxAge;
+
+ LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
+ LLViewerPartSourceBeam *psb = (LLViewerPartSourceBeam *)ps;
+ if (psb->mSourceObjectp.isNull())
+ {
+ part.mFlags = LLPartData::LL_PART_DEAD_MASK;
+ return;
+ }
+
+ LLVector3 source_pos_agent;
+ LLVector3 target_pos_agent;
+ if (!psb->mSourceObjectp.isNull() && !psb->mSourceObjectp->mDrawable.isNull())
+ {
+ if (psb->mSourceObjectp->isAvatar())
+ {
+ LLViewerObject *objp = psb->mSourceObjectp;
+ LLVOAvatar *avp = (LLVOAvatar *)objp;
+ source_pos_agent = avp->mWristLeftp->getWorldPosition();
+ }
+ else
+ {
+ source_pos_agent = psb->mSourceObjectp->getRenderPosition();
+ }
+ }
+ if (!psb->mTargetObjectp.isNull() && !psb->mTargetObjectp->mDrawable.isNull())
+ {
+ target_pos_agent = psb->mTargetObjectp->getRenderPosition();
+ }
+
+ part.mPosAgent = (1.f - frac) * source_pos_agent;
+ if (psb->mTargetObjectp.isNull())
+ {
+ part.mPosAgent += frac * (gAgent.getPosAgentFromGlobal(psb->mLKGTargetPosGlobal));
+ }
+ else
+ {
+ part.mPosAgent += frac * target_pos_agent;
+ }
+}
+
+
+void LLViewerPartSourceBeam::update(const F32 dt)
+{
+ const F32 RATE = 0.025f;
+
+ mLastUpdateTime += dt;
+
+ if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
+ {
+ if (mSourceObjectp->isAvatar())
+ {
+ LLViewerObject *objp = mSourceObjectp;
+ LLVOAvatar *avp = (LLVOAvatar *)objp;
+ mPosAgent = avp->mWristLeftp->getWorldPosition();
+ }
+ else
+ {
+ mPosAgent = mSourceObjectp->getRenderPosition();
+ }
+ }
+
+ if (!mTargetObjectp.isNull() && !mTargetObjectp->mDrawable.isNull())
+ {
+ mTargetPosAgent = mTargetObjectp->getRenderPosition();
+ }
+ else if (!mLKGTargetPosGlobal.isExactlyZero())
+ {
+ mTargetPosAgent = gAgent.getPosAgentFromGlobal(mLKGTargetPosGlobal);
+ }
+
+ F32 dt_update = mLastUpdateTime - mLastPartTime;
+ F32 max_time = llmax(1.f, 10.f*RATE);
+ dt_update = llmin(max_time, dt_update);
+
+ if (dt_update > RATE)
+ {
+ mLastPartTime = mLastUpdateTime;
+ if (!LLViewerPartSim::getInstance()->shouldAddPart())
+ {
+ // Particle simulation says we have too many particles, skip all this
+ return;
+ }
+
+ if (!mImagep)
+ {
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+ }
+
+ LLViewerPart* part = new LLViewerPart();
+ part->init(this, mImagep, updatePart);
+
+ part->mFlags = LLPartData::LL_PART_INTERP_COLOR_MASK |
+ LLPartData::LL_PART_INTERP_SCALE_MASK |
+ LLPartData::LL_PART_TARGET_POS_MASK |
+ LLPartData::LL_PART_FOLLOW_VELOCITY_MASK;
+ part->mMaxAge = 0.5f;
+ part->mStartColor = mColor;
+ part->mEndColor = part->mStartColor;
+ part->mEndColor.mV[3] = 0.4f;
+ part->mColor = part->mStartColor;
+
+ part->mStartScale = LLVector2(0.1f, 0.1f);
+ part->mEndScale = LLVector2(0.1f, 0.1f);
+ part->mScale = part->mStartScale;
+
+ part->mPosAgent = mPosAgent;
+ part->mVelocity = mTargetPosAgent - mPosAgent;
+
+ part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
+ part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
+ part->mStartGlow = 0.f;
+ part->mEndGlow = 0.f;
+ part->mGlow = LLColor4U(0, 0, 0, 0);
+
+ LLViewerPartSim::getInstance()->addPart(part);
+ }
+}
+
+void LLViewerPartSourceBeam::setSourceObject(LLViewerObject* objp)
+{
+ mSourceObjectp = objp;
+}
+
+void LLViewerPartSourceBeam::setTargetObject(LLViewerObject* objp)
+{
+ mTargetObjectp = objp;
+}
+
+
+
+
+LLViewerPartSourceChat::LLViewerPartSourceChat(const LLVector3 &pos) :
+ LLViewerPartSource(LL_PART_SOURCE_SPIRAL)
+{
+ mPosAgent = pos;
+}
+
+void LLViewerPartSourceChat::setDead()
+{
+ mIsDead = true;
+ mSourceObjectp = NULL;
+}
+
+
+void LLViewerPartSourceChat::updatePart(LLViewerPart &part, const F32 dt)
+{
+ F32 frac = part.mLastUpdateTime/part.mMaxAge;
+
+ LLVector3 center_pos;
+ LLViewerPartSource *ps = (LLViewerPartSource*)part.mPartSourcep;
+ LLViewerPartSourceChat *pss = (LLViewerPartSourceChat *)ps;
+ if (!pss->mSourceObjectp.isNull() && !pss->mSourceObjectp->mDrawable.isNull())
+ {
+ part.mPosAgent = pss->mSourceObjectp->getRenderPosition();
+ }
+ else
+ {
+ part.mPosAgent = pss->mPosAgent;
+ }
+ F32 x = sin(F_TWO_PI*frac + part.mParameter);
+ F32 y = cos(F_TWO_PI*frac + part.mParameter);
+
+ part.mPosAgent.mV[VX] += x;
+ part.mPosAgent.mV[VY] += y;
+ part.mPosAgent.mV[VZ] += -0.5f + frac;
+}
+
+
+void LLViewerPartSourceChat::update(const F32 dt)
+{
+ if (!mImagep)
+ {
+ mImagep = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+ }
+
+
+ const F32 RATE = 0.025f;
+
+ mLastUpdateTime += dt;
+
+ if (mLastUpdateTime > 2.f)
+ {
+ // Kill particle source because it has outlived its max age...
+ setDead();
+ return;
+ }
+
+ F32 dt_update = mLastUpdateTime - mLastPartTime;
+
+ // Clamp us to generating at most one second's worth of particles on a frame.
+ F32 max_time = llmax(1.f, 10.f*RATE);
+ dt_update = llmin(max_time, dt_update);
+
+ if (dt_update > RATE)
+ {
+ mLastPartTime = mLastUpdateTime;
+ if (!LLViewerPartSim::getInstance()->shouldAddPart())
+ {
+ // Particle simulation says we have too many particles, skip all this
+ return;
+ }
+
+ if (!mSourceObjectp.isNull() && !mSourceObjectp->mDrawable.isNull())
+ {
+ mPosAgent = mSourceObjectp->getRenderPosition();
+ }
+ LLViewerPart* part = new LLViewerPart();
+ part->init(this, mImagep, updatePart);
+ part->mStartColor = mColor;
+ part->mEndColor = mColor;
+ part->mEndColor.mV[3] = 0.f;
+ part->mPosAgent = mPosAgent;
+ part->mMaxAge = 1.f;
+ part->mFlags = LLViewerPart::LL_PART_INTERP_COLOR_MASK;
+ part->mLastUpdateTime = 0.f;
+ part->mScale.mV[0] = 0.25f;
+ part->mScale.mV[1] = 0.25f;
+ part->mParameter = ll_frand(F_TWO_PI);
+ part->mBlendFuncDest = LLRender::BF_ONE_MINUS_SOURCE_ALPHA;
+ part->mBlendFuncSource = LLRender::BF_SOURCE_ALPHA;
+ part->mStartGlow = 0.f;
+ part->mEndGlow = 0.f;
+ part->mGlow = LLColor4U(0, 0, 0, 0);
+
+
+ LLViewerPartSim::getInstance()->addPart(part);
+ }
+}
+
+void LLViewerPartSourceChat::setSourceObject(LLViewerObject *objp)
+{
+ mSourceObjectp = objp;
+}
+
+void LLViewerPartSourceChat::setColor(const LLColor4 &color)
+{
+ mColor = color;
+}
+
+
|