summaryrefslogtreecommitdiff
path: root/indra/llmessage/llpartdata.cpp
diff options
context:
space:
mode:
authorAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
committerAnsariel <ansariel.hiller@phoenixviewer.com>2024-05-22 19:04:52 +0200
commit1b67dd855c41f5a0cda7ec2a68d98071986ca703 (patch)
treeab243607f74f78200787bba5b9b88f07ef1b966f /indra/llmessage/llpartdata.cpp
parent6d6eabca44d08d5b97bfe3e941d2b9687c2246ea (diff)
parente1623bb276f83a43ce7a197e388720c05bdefe61 (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/llmessage/llpartdata.cpp')
-rw-r--r--indra/llmessage/llpartdata.cpp838
1 files changed, 419 insertions, 419 deletions
diff --git a/indra/llmessage/llpartdata.cpp b/indra/llmessage/llpartdata.cpp
index a4852cefba..afbc74b847 100644
--- a/indra/llmessage/llpartdata.cpp
+++ b/indra/llmessage/llpartdata.cpp
@@ -1,419 +1,419 @@
-/**
- * @file llpartdata.cpp
- * @brief Particle system data packing
- *
- * $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 "linden_common.h"
-
-#include "llpartdata.h"
-#include "message.h"
-
-#include "lldatapacker.h"
-#include "v4coloru.h"
-
-#include "llsdutil.h"
-#include "llsdutil_math.h"
-
-
-
-const S32 PS_PART_DATA_GLOW_SIZE = 2;
-const S32 PS_PART_DATA_BLEND_SIZE = 2;
-const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
-const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
-const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
- PS_LEGACY_PART_DATA_BLOCK_SIZE +
- PS_PART_DATA_BLEND_SIZE +
- PS_PART_DATA_GLOW_SIZE+
- 8; //two S32 size fields
-
-const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
-
-const F32 MAX_PART_SCALE = 4.f;
-
-bool LLPartData::hasGlow() const
-{
- return mStartGlow > 0.f || mEndGlow > 0.f;
-}
-
-bool LLPartData::hasBlendFunc() const
-{
- return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
-}
-
-S32 LLPartData::getSize() const
-{
- S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
- if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
- if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
-
- return size;
-}
-
-
-bool LLPartData::unpackLegacy(LLDataPacker &dp)
-{
- LLColor4U coloru;
-
- dp.unpackU32(mFlags, "pdflags");
- dp.unpackFixed(mMaxAge, "pdmaxage", false, 8, 8);
-
- dp.unpackColor4U(coloru, "pdstartcolor");
- mStartColor.setVec(coloru);
- dp.unpackColor4U(coloru, "pdendcolor");
- mEndColor.setVec(coloru);
- dp.unpackFixed(mStartScale.mV[0], "pdstartscalex", false, 3, 5);
- dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", false, 3, 5);
- dp.unpackFixed(mEndScale.mV[0], "pdendscalex", false, 3, 5);
- dp.unpackFixed(mEndScale.mV[1], "pdendscaley", false, 3, 5);
-
- mStartGlow = 0.f;
- mEndGlow = 0.f;
- mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
-
- return true;
-}
-
-bool LLPartData::unpack(LLDataPacker &dp)
-{
- S32 size = 0;
- dp.unpackS32(size, "partsize");
-
- unpackLegacy(dp);
- size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
-
- if (mFlags & LL_PART_DATA_GLOW)
- {
- if (size < PS_PART_DATA_GLOW_SIZE) return false;
-
- U8 tmp_glow = 0;
- dp.unpackU8(tmp_glow,"pdstartglow");
- mStartGlow = tmp_glow / 255.f;
- dp.unpackU8(tmp_glow,"pdendglow");
- mEndGlow = tmp_glow / 255.f;
-
- size -= PS_PART_DATA_GLOW_SIZE;
- }
- else
- {
- mStartGlow = 0.f;
- mEndGlow = 0.f;
- }
-
- if (mFlags & LL_PART_DATA_BLEND)
- {
- if (size < PS_PART_DATA_BLEND_SIZE) return false;
- dp.unpackU8(mBlendFuncSource,"pdblendsource");
- dp.unpackU8(mBlendFuncDest,"pdblenddest");
- size -= PS_PART_DATA_BLEND_SIZE;
- }
- else
- {
- mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
- }
-
- if (size > 0)
- { //leftover bytes, unrecognized parameters
- U8 feh = 0;
- while (size > 0)
- { //read remaining bytes in block
- dp.unpackU8(feh, "whippang");
- size--;
- }
-
- //this particle system won't display properly, better to not show anything
- return false;
- }
-
-
- return true;
-}
-
-void LLPartData::setFlags(const U32 flags)
-{
- mFlags = flags;
-}
-
-
-void LLPartData::setMaxAge(const F32 max_age)
-{
- mMaxAge = llclamp(max_age, 0.f, 30.f);
-}
-
-
-void LLPartData::setStartScale(const F32 xs, const F32 ys)
-{
- mStartScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
- mStartScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
-}
-
-
-void LLPartData::setEndScale(const F32 xs, const F32 ys)
-{
- mEndScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
- mEndScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
-}
-
-
-void LLPartData::setStartColor(const LLVector3 &rgb)
-{
- mStartColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
-}
-
-
-void LLPartData::setEndColor(const LLVector3 &rgb)
-{
- mEndColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
-}
-
-void LLPartData::setStartAlpha(const F32 alpha)
-{
- mStartColor.mV[3] = alpha;
-}
-void LLPartData::setEndAlpha(const F32 alpha)
-{
- mEndColor.mV[3] = alpha;
-}
-
-// static
-bool LLPartData::validBlendFunc(S32 func)
-{
- if (func >= 0
- && func < LL_PART_BF_COUNT
- && func != UNSUPPORTED_DEST_ALPHA
- && func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
- {
- return true;
- }
- return false;
-}
-
-LLPartSysData::LLPartSysData()
-{
- mCRC = 0;
- mFlags = 0;
-
- mPartData.mFlags = 0;
- mPartData.mStartColor = LLColor4(1.f, 1.f, 1.f, 1.f);
- mPartData.mEndColor = LLColor4(1.f, 1.f, 1.f, 1.f);
- mPartData.mStartScale = LLVector2(1.f, 1.f);
- mPartData.mEndScale = LLVector2(1.f, 1.f);
- mPartData.mMaxAge = 10.0;
- mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
- mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
- mPartData.mStartGlow = 0.f;
- mPartData.mEndGlow = 0.f;
-
- mMaxAge = 0.0;
- mStartAge = 0.0;
- mPattern = LL_PART_SRC_PATTERN_DROP; // Pattern for particle velocity
- mInnerAngle = 0.0; // Inner angle of PATTERN_ANGLE_*
- mOuterAngle = 0.0; // Outer angle of PATTERN_ANGLE_*
- mBurstRate = 0.1f; // How often to do a burst of particles
- mBurstPartCount = 1; // How many particles in a burst
- mBurstSpeedMin = 1.f; // Minimum particle velocity
- mBurstSpeedMax = 1.f; // Maximum particle velocity
- mBurstRadius = 0.f;
-
- mNumParticles = 0;
-}
-
-bool LLPartSysData::unpackSystem(LLDataPacker &dp)
-{
- dp.unpackU32(mCRC, "pscrc");
- dp.unpackU32(mFlags, "psflags");
- dp.unpackU8(mPattern, "pspattern");
- dp.unpackFixed(mMaxAge, "psmaxage", false, 8, 8);
- dp.unpackFixed(mStartAge, "psstartage", false, 8, 8);
- dp.unpackFixed(mInnerAngle, "psinnerangle", false, 3, 5);
- dp.unpackFixed(mOuterAngle, "psouterangle", false, 3, 5);
- dp.unpackFixed(mBurstRate, "psburstrate", false, 8, 8);
- mBurstRate = llmax(0.01f, mBurstRate);
- dp.unpackFixed(mBurstRadius, "psburstradius", false, 8, 8);
- dp.unpackFixed(mBurstSpeedMin, "psburstspeedmin", false, 8, 8);
- dp.unpackFixed(mBurstSpeedMax, "psburstspeedmax", false, 8, 8);
- dp.unpackU8(mBurstPartCount, "psburstpartcount");
-
- dp.unpackFixed(mAngularVelocity.mV[0], "psangvelx", true, 8, 7);
- dp.unpackFixed(mAngularVelocity.mV[1], "psangvely", true, 8, 7);
- dp.unpackFixed(mAngularVelocity.mV[2], "psangvelz", true, 8, 7);
-
- dp.unpackFixed(mPartAccel.mV[0], "psaccelx", true, 8, 7);
- dp.unpackFixed(mPartAccel.mV[1], "psaccely", true, 8, 7);
- dp.unpackFixed(mPartAccel.mV[2], "psaccelz", true, 8, 7);
-
- dp.unpackUUID(mPartImageID, "psuuid");
- dp.unpackUUID(mTargetUUID, "pstargetuuid");
- return true;
-}
-
-bool LLPartSysData::unpackLegacy(LLDataPacker &dp)
-{
- unpackSystem(dp);
- mPartData.unpackLegacy(dp);
-
- return true;
-}
-
-bool LLPartSysData::unpack(LLDataPacker &dp)
-{
- // syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
- S32 size = 0;
- dp.unpackS32(size, "syssize");
-
- if (size != PS_SYS_DATA_BLOCK_SIZE)
- { //unexpected size, this viewer doesn't know how to parse this particle system
-
- //skip to LLPartData block
- U8 feh = 0;
-
- for (U32 i = 0; i < size; ++i)
- {
- dp.unpackU8(feh, "whippang");
- }
-
- dp.unpackS32(size, "partsize");
- //skip LLPartData block
- for (U32 i = 0; i < size; ++i)
- {
- dp.unpackU8(feh, "whippang");
- }
- return false;
- }
-
- unpackSystem(dp);
-
- return mPartData.unpack(dp);
-}
-
-std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
-{
- s << "Flags: " << std::hex << data.mFlags;
- s << "Pattern: " << std::hex << (U32) data.mPattern << "\n";
- s << "Source Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
- s << "Particle Age: " << data.mPartData.mMaxAge << "\n";
- s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
- s << "Burst Rate: " << data.mBurstRate << "\n";
- s << "Burst Radius: " << data.mBurstRadius << "\n";
- s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
- s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
- s << "Angular Velocity: " << data.mAngularVelocity << "\n";
- s << "Accel: " << data.mPartAccel;
- return s;
-}
-
-bool LLPartSysData::isNullPS(const S32 block_num)
-{
- U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
- U32 crc;
-
- S32 size;
- // Check size of block
- size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
-
- if (!size)
- {
- return true;
- }
-
- if (size > PS_MAX_DATA_BLOCK_SIZE)
- {
- //size is too big, newer particle version unsupported
- return true;
- }
-
- gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
-
- LLDataPackerBinaryBuffer dp(ps_data_block, size);
- if (size > PS_LEGACY_DATA_BLOCK_SIZE)
- {
- // non legacy systems pack a size before the CRC
- S32 tmp = 0;
- dp.unpackS32(tmp, "syssize");
-
- if (tmp > PS_SYS_DATA_BLOCK_SIZE)
- { //unknown system data block size, don't know how to parse it, treat as NULL
- return true;
- }
- }
-
- dp.unpackU32(crc, "crc");
-
- if (crc == 0)
- {
- return true;
- }
- return false;
-}
-
-bool LLPartSysData::unpackBlock(const S32 block_num)
-{
- U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
-
- // Check size of block
- S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
-
- if (size > PS_MAX_DATA_BLOCK_SIZE)
- {
- // Larger packets are newer and unsupported
- return false;
- }
-
- // Get from message
- gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
-
- LLDataPackerBinaryBuffer dp(ps_data_block, size);
-
- if (size == PS_LEGACY_DATA_BLOCK_SIZE)
- {
- return unpackLegacy(dp);
- }
- else
- {
- return unpack(dp);
- }
-}
-
-bool LLPartSysData::isLegacyCompatible() const
-{
- return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
-}
-
-void LLPartSysData::clampSourceParticleRate()
-{
- F32 particle_rate = 0;
- particle_rate = mBurstPartCount/mBurstRate;
- if (particle_rate > 256.f)
- {
- mBurstPartCount = llfloor(((F32)mBurstPartCount)*(256.f/particle_rate));
- }
-}
-
-void LLPartSysData::setPartAccel(const LLVector3 &accel)
-{
- mPartAccel.mV[VX] = llclamp(accel.mV[VX], -100.f, 100.f);
- mPartAccel.mV[VY] = llclamp(accel.mV[VY], -100.f, 100.f);
- mPartAccel.mV[VZ] = llclamp(accel.mV[VZ], -100.f, 100.f);
-}
+/**
+ * @file llpartdata.cpp
+ * @brief Particle system data packing
+ *
+ * $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 "linden_common.h"
+
+#include "llpartdata.h"
+#include "message.h"
+
+#include "lldatapacker.h"
+#include "v4coloru.h"
+
+#include "llsdutil.h"
+#include "llsdutil_math.h"
+
+
+
+const S32 PS_PART_DATA_GLOW_SIZE = 2;
+const S32 PS_PART_DATA_BLEND_SIZE = 2;
+const S32 PS_LEGACY_PART_DATA_BLOCK_SIZE = 4 + 2 + 4 + 4 + 2 + 2; //18
+const S32 PS_SYS_DATA_BLOCK_SIZE = 68;
+const S32 PS_MAX_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE+
+ PS_LEGACY_PART_DATA_BLOCK_SIZE +
+ PS_PART_DATA_BLEND_SIZE +
+ PS_PART_DATA_GLOW_SIZE+
+ 8; //two S32 size fields
+
+const S32 PS_LEGACY_DATA_BLOCK_SIZE = PS_SYS_DATA_BLOCK_SIZE + PS_LEGACY_PART_DATA_BLOCK_SIZE;
+
+const F32 MAX_PART_SCALE = 4.f;
+
+bool LLPartData::hasGlow() const
+{
+ return mStartGlow > 0.f || mEndGlow > 0.f;
+}
+
+bool LLPartData::hasBlendFunc() const
+{
+ return mBlendFuncSource != LLPartData::LL_PART_BF_SOURCE_ALPHA || mBlendFuncDest != LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+}
+
+S32 LLPartData::getSize() const
+{
+ S32 size = PS_LEGACY_PART_DATA_BLOCK_SIZE;
+ if (hasGlow()) size += PS_PART_DATA_GLOW_SIZE;
+ if (hasBlendFunc()) size += PS_PART_DATA_BLEND_SIZE;
+
+ return size;
+}
+
+
+bool LLPartData::unpackLegacy(LLDataPacker &dp)
+{
+ LLColor4U coloru;
+
+ dp.unpackU32(mFlags, "pdflags");
+ dp.unpackFixed(mMaxAge, "pdmaxage", false, 8, 8);
+
+ dp.unpackColor4U(coloru, "pdstartcolor");
+ mStartColor.setVec(coloru);
+ dp.unpackColor4U(coloru, "pdendcolor");
+ mEndColor.setVec(coloru);
+ dp.unpackFixed(mStartScale.mV[0], "pdstartscalex", false, 3, 5);
+ dp.unpackFixed(mStartScale.mV[1], "pdstartscaley", false, 3, 5);
+ dp.unpackFixed(mEndScale.mV[0], "pdendscalex", false, 3, 5);
+ dp.unpackFixed(mEndScale.mV[1], "pdendscaley", false, 3, 5);
+
+ mStartGlow = 0.f;
+ mEndGlow = 0.f;
+ mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+
+ return true;
+}
+
+bool LLPartData::unpack(LLDataPacker &dp)
+{
+ S32 size = 0;
+ dp.unpackS32(size, "partsize");
+
+ unpackLegacy(dp);
+ size -= PS_LEGACY_PART_DATA_BLOCK_SIZE;
+
+ if (mFlags & LL_PART_DATA_GLOW)
+ {
+ if (size < PS_PART_DATA_GLOW_SIZE) return false;
+
+ U8 tmp_glow = 0;
+ dp.unpackU8(tmp_glow,"pdstartglow");
+ mStartGlow = tmp_glow / 255.f;
+ dp.unpackU8(tmp_glow,"pdendglow");
+ mEndGlow = tmp_glow / 255.f;
+
+ size -= PS_PART_DATA_GLOW_SIZE;
+ }
+ else
+ {
+ mStartGlow = 0.f;
+ mEndGlow = 0.f;
+ }
+
+ if (mFlags & LL_PART_DATA_BLEND)
+ {
+ if (size < PS_PART_DATA_BLEND_SIZE) return false;
+ dp.unpackU8(mBlendFuncSource,"pdblendsource");
+ dp.unpackU8(mBlendFuncDest,"pdblenddest");
+ size -= PS_PART_DATA_BLEND_SIZE;
+ }
+ else
+ {
+ mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+ }
+
+ if (size > 0)
+ { //leftover bytes, unrecognized parameters
+ U8 feh = 0;
+ while (size > 0)
+ { //read remaining bytes in block
+ dp.unpackU8(feh, "whippang");
+ size--;
+ }
+
+ //this particle system won't display properly, better to not show anything
+ return false;
+ }
+
+
+ return true;
+}
+
+void LLPartData::setFlags(const U32 flags)
+{
+ mFlags = flags;
+}
+
+
+void LLPartData::setMaxAge(const F32 max_age)
+{
+ mMaxAge = llclamp(max_age, 0.f, 30.f);
+}
+
+
+void LLPartData::setStartScale(const F32 xs, const F32 ys)
+{
+ mStartScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
+ mStartScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
+}
+
+
+void LLPartData::setEndScale(const F32 xs, const F32 ys)
+{
+ mEndScale.mV[VX] = llmin(xs, MAX_PART_SCALE);
+ mEndScale.mV[VY] = llmin(ys, MAX_PART_SCALE);
+}
+
+
+void LLPartData::setStartColor(const LLVector3 &rgb)
+{
+ mStartColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
+}
+
+
+void LLPartData::setEndColor(const LLVector3 &rgb)
+{
+ mEndColor.setVec(rgb.mV[0], rgb.mV[1], rgb.mV[2]);
+}
+
+void LLPartData::setStartAlpha(const F32 alpha)
+{
+ mStartColor.mV[3] = alpha;
+}
+void LLPartData::setEndAlpha(const F32 alpha)
+{
+ mEndColor.mV[3] = alpha;
+}
+
+// static
+bool LLPartData::validBlendFunc(S32 func)
+{
+ if (func >= 0
+ && func < LL_PART_BF_COUNT
+ && func != UNSUPPORTED_DEST_ALPHA
+ && func != UNSUPPORTED_ONE_MINUS_DEST_ALPHA)
+ {
+ return true;
+ }
+ return false;
+}
+
+LLPartSysData::LLPartSysData()
+{
+ mCRC = 0;
+ mFlags = 0;
+
+ mPartData.mFlags = 0;
+ mPartData.mStartColor = LLColor4(1.f, 1.f, 1.f, 1.f);
+ mPartData.mEndColor = LLColor4(1.f, 1.f, 1.f, 1.f);
+ mPartData.mStartScale = LLVector2(1.f, 1.f);
+ mPartData.mEndScale = LLVector2(1.f, 1.f);
+ mPartData.mMaxAge = 10.0;
+ mPartData.mBlendFuncSource = LLPartData::LL_PART_BF_SOURCE_ALPHA;
+ mPartData.mBlendFuncDest = LLPartData::LL_PART_BF_ONE_MINUS_SOURCE_ALPHA;
+ mPartData.mStartGlow = 0.f;
+ mPartData.mEndGlow = 0.f;
+
+ mMaxAge = 0.0;
+ mStartAge = 0.0;
+ mPattern = LL_PART_SRC_PATTERN_DROP; // Pattern for particle velocity
+ mInnerAngle = 0.0; // Inner angle of PATTERN_ANGLE_*
+ mOuterAngle = 0.0; // Outer angle of PATTERN_ANGLE_*
+ mBurstRate = 0.1f; // How often to do a burst of particles
+ mBurstPartCount = 1; // How many particles in a burst
+ mBurstSpeedMin = 1.f; // Minimum particle velocity
+ mBurstSpeedMax = 1.f; // Maximum particle velocity
+ mBurstRadius = 0.f;
+
+ mNumParticles = 0;
+}
+
+bool LLPartSysData::unpackSystem(LLDataPacker &dp)
+{
+ dp.unpackU32(mCRC, "pscrc");
+ dp.unpackU32(mFlags, "psflags");
+ dp.unpackU8(mPattern, "pspattern");
+ dp.unpackFixed(mMaxAge, "psmaxage", false, 8, 8);
+ dp.unpackFixed(mStartAge, "psstartage", false, 8, 8);
+ dp.unpackFixed(mInnerAngle, "psinnerangle", false, 3, 5);
+ dp.unpackFixed(mOuterAngle, "psouterangle", false, 3, 5);
+ dp.unpackFixed(mBurstRate, "psburstrate", false, 8, 8);
+ mBurstRate = llmax(0.01f, mBurstRate);
+ dp.unpackFixed(mBurstRadius, "psburstradius", false, 8, 8);
+ dp.unpackFixed(mBurstSpeedMin, "psburstspeedmin", false, 8, 8);
+ dp.unpackFixed(mBurstSpeedMax, "psburstspeedmax", false, 8, 8);
+ dp.unpackU8(mBurstPartCount, "psburstpartcount");
+
+ dp.unpackFixed(mAngularVelocity.mV[0], "psangvelx", true, 8, 7);
+ dp.unpackFixed(mAngularVelocity.mV[1], "psangvely", true, 8, 7);
+ dp.unpackFixed(mAngularVelocity.mV[2], "psangvelz", true, 8, 7);
+
+ dp.unpackFixed(mPartAccel.mV[0], "psaccelx", true, 8, 7);
+ dp.unpackFixed(mPartAccel.mV[1], "psaccely", true, 8, 7);
+ dp.unpackFixed(mPartAccel.mV[2], "psaccelz", true, 8, 7);
+
+ dp.unpackUUID(mPartImageID, "psuuid");
+ dp.unpackUUID(mTargetUUID, "pstargetuuid");
+ return true;
+}
+
+bool LLPartSysData::unpackLegacy(LLDataPacker &dp)
+{
+ unpackSystem(dp);
+ mPartData.unpackLegacy(dp);
+
+ return true;
+}
+
+bool LLPartSysData::unpack(LLDataPacker &dp)
+{
+ // syssize is currently unused. Adding now when modifying the 'version to make extensible in the future
+ S32 size = 0;
+ dp.unpackS32(size, "syssize");
+
+ if (size != PS_SYS_DATA_BLOCK_SIZE)
+ { //unexpected size, this viewer doesn't know how to parse this particle system
+
+ //skip to LLPartData block
+ U8 feh = 0;
+
+ for (U32 i = 0; i < size; ++i)
+ {
+ dp.unpackU8(feh, "whippang");
+ }
+
+ dp.unpackS32(size, "partsize");
+ //skip LLPartData block
+ for (U32 i = 0; i < size; ++i)
+ {
+ dp.unpackU8(feh, "whippang");
+ }
+ return false;
+ }
+
+ unpackSystem(dp);
+
+ return mPartData.unpack(dp);
+}
+
+std::ostream& operator<<(std::ostream& s, const LLPartSysData &data)
+{
+ s << "Flags: " << std::hex << data.mFlags;
+ s << "Pattern: " << std::hex << (U32) data.mPattern << "\n";
+ s << "Source Age: [" << data.mStartAge << ", " << data.mMaxAge << "]\n";
+ s << "Particle Age: " << data.mPartData.mMaxAge << "\n";
+ s << "Angle: [" << data.mInnerAngle << ", " << data.mOuterAngle << "]\n";
+ s << "Burst Rate: " << data.mBurstRate << "\n";
+ s << "Burst Radius: " << data.mBurstRadius << "\n";
+ s << "Burst Speed: [" << data.mBurstSpeedMin << ", " << data.mBurstSpeedMax << "]\n";
+ s << "Burst Part Count: " << std::hex << (U32) data.mBurstPartCount << "\n";
+ s << "Angular Velocity: " << data.mAngularVelocity << "\n";
+ s << "Accel: " << data.mPartAccel;
+ return s;
+}
+
+bool LLPartSysData::isNullPS(const S32 block_num)
+{
+ U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
+ U32 crc;
+
+ S32 size;
+ // Check size of block
+ size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
+
+ if (!size)
+ {
+ return true;
+ }
+
+ if (size > PS_MAX_DATA_BLOCK_SIZE)
+ {
+ //size is too big, newer particle version unsupported
+ return true;
+ }
+
+ gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
+
+ LLDataPackerBinaryBuffer dp(ps_data_block, size);
+ if (size > PS_LEGACY_DATA_BLOCK_SIZE)
+ {
+ // non legacy systems pack a size before the CRC
+ S32 tmp = 0;
+ dp.unpackS32(tmp, "syssize");
+
+ if (tmp > PS_SYS_DATA_BLOCK_SIZE)
+ { //unknown system data block size, don't know how to parse it, treat as NULL
+ return true;
+ }
+ }
+
+ dp.unpackU32(crc, "crc");
+
+ if (crc == 0)
+ {
+ return true;
+ }
+ return false;
+}
+
+bool LLPartSysData::unpackBlock(const S32 block_num)
+{
+ U8 ps_data_block[PS_MAX_DATA_BLOCK_SIZE];
+
+ // Check size of block
+ S32 size = gMessageSystem->getSize("ObjectData", block_num, "PSBlock");
+
+ if (size > PS_MAX_DATA_BLOCK_SIZE)
+ {
+ // Larger packets are newer and unsupported
+ return false;
+ }
+
+ // Get from message
+ gMessageSystem->getBinaryData("ObjectData", "PSBlock", ps_data_block, size, block_num, PS_MAX_DATA_BLOCK_SIZE);
+
+ LLDataPackerBinaryBuffer dp(ps_data_block, size);
+
+ if (size == PS_LEGACY_DATA_BLOCK_SIZE)
+ {
+ return unpackLegacy(dp);
+ }
+ else
+ {
+ return unpack(dp);
+ }
+}
+
+bool LLPartSysData::isLegacyCompatible() const
+{
+ return !mPartData.hasGlow() && !mPartData.hasBlendFunc();
+}
+
+void LLPartSysData::clampSourceParticleRate()
+{
+ F32 particle_rate = 0;
+ particle_rate = mBurstPartCount/mBurstRate;
+ if (particle_rate > 256.f)
+ {
+ mBurstPartCount = llfloor(((F32)mBurstPartCount)*(256.f/particle_rate));
+ }
+}
+
+void LLPartSysData::setPartAccel(const LLVector3 &accel)
+{
+ mPartAccel.mV[VX] = llclamp(accel.mV[VX], -100.f, 100.f);
+ mPartAccel.mV[VY] = llclamp(accel.mV[VY], -100.f, 100.f);
+ mPartAccel.mV[VZ] = llclamp(accel.mV[VZ], -100.f, 100.f);
+}