Files
SingularityViewer/indra/llcharacter/llmultigesture.cpp
2019-03-21 22:01:13 -04:00

435 lines
10 KiB
C++

/**
* @file llmultigesture.cpp
* @brief Gestures that are asset-based and can have multiple steps.
*
* $LicenseInfo:firstyear=2004&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 <algorithm>
#include "stdio.h"
#include "llmultigesture.h"
#include "llerror.h"
#include "lldatapacker.h"
#include "llstl.h"
constexpr S32 GESTURE_VERSION = 2;
//---------------------------------------------------------------------------
// LLMultiGesture
//---------------------------------------------------------------------------
LLMultiGesture::LLMultiGesture()
: mKey(),
mMask(),
mName(),
mTrigger(),
mReplaceText(),
mSteps(),
mPlaying(false),
mLocal(false),
mCurrentStep(0),
mDoneCallback(nullptr)
{
reset();
}
LLMultiGesture::~LLMultiGesture()
{
std::for_each(mSteps.begin(), mSteps.end(), DeletePointer());
}
void LLMultiGesture::reset()
{
mPlaying = false;
mLocal = false;
mCurrentStep = 0;
mWaitTimer.reset();
mWaitingTimer = false;
mWaitingAnimations = false;
mWaitingAtEnd = false;
mRequestedAnimIDs.clear();
mPlayingAnimIDs.clear();
}
S32 LLMultiGesture::getMaxSerialSize() const
{
S32 max_size = 0;
// ascii format, being very conservative about possible
// label lengths.
max_size += 64; // version S32
max_size += 64; // key U8
max_size += 64; // mask U32
max_size += 256; // trigger string
max_size += 256; // replace string
max_size += 64; // step count S32
for (const auto& step : mSteps)
{
max_size += 64; // type S32
max_size += step->getMaxSerialSize();
}
/* binary format
max_size += sizeof(S32); // version
max_size += sizeof(mKey);
max_size += sizeof(mMask);
max_size += mTrigger.length() + 1; // for null
max_size += sizeof(S32); // step count
for (const auto& step : mSteps)
{
max_size += sizeof(S32); // type
max_size += step->getMaxSerialSize();
}
*/
return max_size;
}
bool LLMultiGesture::serialize(LLDataPacker& dp) const
{
dp.packS32(GESTURE_VERSION, "version");
dp.packU8(mKey, "key");
dp.packU32(mMask, "mask");
dp.packString(mTrigger, "trigger");
dp.packString(mReplaceText, "replace");
S32 count = (S32)mSteps.size();
dp.packS32(count, "step_count");
for (const auto& step : mSteps)
{
dp.packS32(step->getType(), "step_type");
if (!step->serialize(dp))
{
return false;
}
}
return true;
}
bool LLMultiGesture::deserialize(LLDataPacker& dp)
{
S32 version;
dp.unpackS32(version, "version");
if (version != GESTURE_VERSION)
{
LL_WARNS() << "Bad LLMultiGesture version " << version
<< " should be " << GESTURE_VERSION
<< LL_ENDL;
return false;
}
dp.unpackU8(mKey, "key");
dp.unpackU32(mMask, "mask");
dp.unpackString(mTrigger, "trigger");
dp.unpackString(mReplaceText, "replace");
S32 count;
dp.unpackS32(count, "step_count");
if (count < 0)
{
LL_WARNS() << "Bad LLMultiGesture step count " << count << LL_ENDL;
return false;
}
std::unique_ptr<LLGestureStep> step;
for (S32 i = 0; i < count; ++i)
{
S32 type;
dp.unpackS32(type, "step_type");
switch((EStepType)type)
{
case STEP_ANIMATION: step.reset(new LLGestureStepAnimation); break;
case STEP_SOUND: step.reset(new LLGestureStepSound); break;
case STEP_CHAT: step.reset(new LLGestureStepChat); break;
case STEP_WAIT: step.reset(new LLGestureStepWait); break;
default:
{
LL_WARNS() << "Bad LLMultiGesture step type " << type << LL_ENDL;
return false;
}
}
if (!step->deserialize(dp)) return false;
mSteps.push_back(step.release());
}
return true;
}
void LLMultiGesture::dump()
{
LL_INFOS() << "key " << S32(mKey) << " mask " << U32(mMask)
<< " trigger " << mTrigger
<< " replace " << mReplaceText
<< LL_ENDL;
for (const auto& step : mSteps)
{
step->dump();
}
}
//---------------------------------------------------------------------------
// LLGestureStepAnimation
//---------------------------------------------------------------------------
LLGestureStepAnimation::LLGestureStepAnimation()
: LLGestureStep(),
mAnimName("None"),
mAnimAssetID(),
mFlags(0x0)
{ }
LLGestureStepAnimation::~LLGestureStepAnimation()
{ }
S32 LLGestureStepAnimation::getMaxSerialSize() const
{
S32 max_size = 0;
// ascii
max_size += 256; // anim name
max_size += 64; // anim asset id
max_size += 64; // flags
/* binary
max_size += mAnimName.length() + 1;
max_size += sizeof(mAnimAssetID);
max_size += sizeof(mFlags);
*/
return max_size;
}
bool LLGestureStepAnimation::serialize(LLDataPacker& dp) const
{
dp.packString(mAnimName, "anim_name");
dp.packUUID(mAnimAssetID, "asset_id");
dp.packU32(mFlags, "flags");
return true;
}
bool LLGestureStepAnimation::deserialize(LLDataPacker& dp)
{
dp.unpackString(mAnimName, "anim_name");
// Apparently an earlier version of the gesture code added \r to the end
// of the animation names. Get rid of it. JC
if (!mAnimName.empty() && mAnimName.back() == '\r')
{
// chop the last character
mAnimName.resize(mAnimName.length() - 1);
}
dp.unpackUUID(mAnimAssetID, "asset_id");
dp.unpackU32(mFlags, "flags");
return true;
}
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepAnimation::getLabel() const
{
/* std::string label;
if (mFlags & ANIM_FLAG_STOP)
label = "Stop Animation: ";
else
label = "Start Animation: ";
label += mAnimName;*/
return {mFlags & ANIM_FLAG_STOP ? "AnimFlagStop" : "AnimFlagStart", mAnimName};
}
void LLGestureStepAnimation::dump()
{
LL_INFOS() << "step animation " << mAnimName
<< " id " << mAnimAssetID
<< " flags " << mFlags
<< LL_ENDL;
}
//---------------------------------------------------------------------------
// LLGestureStepSound
//---------------------------------------------------------------------------
LLGestureStepSound::LLGestureStepSound()
: LLGestureStep(),
mSoundName("None"),
mSoundAssetID(),
mFlags(0x0)
{ }
LLGestureStepSound::~LLGestureStepSound()
{ }
S32 LLGestureStepSound::getMaxSerialSize() const
{
S32 max_size = 0;
max_size += 256; // sound name
max_size += 64; // sound asset id
max_size += 64; // flags
/* binary
max_size += mSoundName.length() + 1;
max_size += sizeof(mSoundAssetID);
max_size += sizeof(mFlags);
*/
return max_size;
}
bool LLGestureStepSound::serialize(LLDataPacker& dp) const
{
dp.packString(mSoundName, "sound_name");
dp.packUUID(mSoundAssetID, "asset_id");
dp.packU32(mFlags, "flags");
return true;
}
bool LLGestureStepSound::deserialize(LLDataPacker& dp)
{
dp.unpackString(mSoundName, "sound_name");
dp.unpackUUID(mSoundAssetID, "asset_id");
dp.unpackU32(mFlags, "flags");
return true;
}
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepSound::getLabel() const
{
// std::string label("Sound: ");
// label += mSoundName;
return {"Sound", mSoundName};
}
void LLGestureStepSound::dump()
{
LL_INFOS() << "step sound " << mSoundName
<< " id " << mSoundAssetID
<< " flags " << mFlags
<< LL_ENDL;
}
//---------------------------------------------------------------------------
// LLGestureStepChat
//---------------------------------------------------------------------------
LLGestureStepChat::LLGestureStepChat()
: LLGestureStep(),
mChatText(),
mFlags(0x0)
{ }
LLGestureStepChat::~LLGestureStepChat()
{ }
S32 LLGestureStepChat::getMaxSerialSize() const
{
S32 max_size = 0;
max_size += 256; // chat text
max_size += 64; // flags
/* binary
max_size += mChatText.length() + 1;
max_size += sizeof(mFlags);
*/
return max_size;
}
bool LLGestureStepChat::serialize(LLDataPacker& dp) const
{
dp.packString(mChatText, "chat_text");
dp.packU32(mFlags, "flags");
return true;
}
bool LLGestureStepChat::deserialize(LLDataPacker& dp)
{
dp.unpackString(mChatText, "chat_text");
dp.unpackU32(mFlags, "flags");
return true;
}
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepChat::getLabel() const
{
return {"Chat", mChatText};
}
void LLGestureStepChat::dump()
{
LL_INFOS() << "step chat " << mChatText
<< " flags " << mFlags
<< LL_ENDL;
}
//---------------------------------------------------------------------------
// LLGestureStepWait
//---------------------------------------------------------------------------
LLGestureStepWait::LLGestureStepWait()
: LLGestureStep(),
mWaitSeconds(0.f),
mFlags(0x0)
{ }
LLGestureStepWait::~LLGestureStepWait()
{ }
S32 LLGestureStepWait::getMaxSerialSize() const
{
S32 max_size = 0;
max_size += 64; // wait seconds
max_size += 64; // flags
/* binary
max_size += sizeof(mWaitSeconds);
max_size += sizeof(mFlags);
*/
return max_size;
}
bool LLGestureStepWait::serialize(LLDataPacker& dp) const
{
dp.packF32(mWaitSeconds, "wait_seconds");
dp.packU32(mFlags, "flags");
return true;
}
bool LLGestureStepWait::deserialize(LLDataPacker& dp)
{
dp.unpackF32(mWaitSeconds, "wait_seconds");
dp.unpackU32(mFlags, "flags");
return true;
}
// *NOTE: result is translated in LLPreviewGesture::getLabel()
std::vector<std::string> LLGestureStepWait::getLabel() const
{
return {"Wait",
mFlags & WAIT_FLAG_TIME ? llformat("%.1f seconds", mWaitSeconds)
: mFlags & WAIT_FLAG_ALL_ANIM ? "until animations are done"
: LLStringUtil::null};
}
void LLGestureStepWait::dump()
{
LL_INFOS() << "step wait " << mWaitSeconds
<< " flags " << mFlags
<< LL_ENDL;
}