/**
* @file llvisualparam.cpp
* @brief Implementation of LLPolyMesh class.
*
* $LicenseInfo:firstyear=2001&license=viewergpl$
*
* Copyright (c) 2001-2009, Linden Research, Inc.
*
* Second Life Viewer Source Code
* The source code in this file ("Source Code") is provided by Linden Lab
* to you under the terms of the GNU General Public License, version 2.0
* ("GPL"), unless you have obtained a separate licensing agreement
* ("Other License"), formally executed by you and Linden Lab. Terms of
* the GPL can be found in doc/GPL-license.txt in this distribution, or
* online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
*
* There are special exceptions to the terms and conditions of the GPL as
* it is applied to this Source Code. View the full text of the exception
* in the file doc/FLOSS-exception.txt in this software distribution, or
* online at
* http://secondlifegrid.net/programs/open_source/licensing/flossexception
*
* By copying, modifying or distributing this software, you acknowledge
* that you have read and understood your obligations described above,
* and agree to abide by those obligations.
*
* ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
* WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
* COMPLETENESS OR PERFORMANCE.
* $/LicenseInfo$
*/
//-----------------------------------------------------------------------------
// Header Files
//-----------------------------------------------------------------------------
#include "linden_common.h"
#include "llvisualparam.h"
//-----------------------------------------------------------------------------
// LLVisualParamInfo()
//-----------------------------------------------------------------------------
LLVisualParamInfo::LLVisualParamInfo()
: mID(-1),
mGroup(VISUAL_PARAM_GROUP_TWEAKABLE),
mMinWeight(0.f),
mMaxWeight(1.f),
mDefaultWeight(0.f),
mSex(SEX_BOTH)
{
}
//-----------------------------------------------------------------------------
// parseXml()
//-----------------------------------------------------------------------------
bool LLVisualParamInfo::parseXml(LLXmlTreeNode* node)
{
// attribute: id
static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
node->getFastAttributeS32(id_string, mID);
// attribute: group
U32 group = 0;
static LLStdStringHandle group_string = LLXmlTree::addAttributeString("group");
if (node->getFastAttributeU32(group_string, group))
{
if (group < NUM_VISUAL_PARAM_GROUPS)
{
mGroup = (EVisualParamGroup)group;
}
}
// attribute: value_min, value_max
static LLStdStringHandle value_min_string = LLXmlTree::addAttributeString("value_min");
static LLStdStringHandle value_max_string = LLXmlTree::addAttributeString("value_max");
node->getFastAttributeF32(value_min_string, mMinWeight);
node->getFastAttributeF32(value_max_string, mMaxWeight);
// attribute: value_default
F32 default_weight = 0;
static LLStdStringHandle value_default_string = LLXmlTree::addAttributeString("value_default");
if (node->getFastAttributeF32(value_default_string, default_weight))
{
mDefaultWeight = llclamp(default_weight, mMinWeight, mMaxWeight);
if (default_weight != mDefaultWeight)
{
llwarns << "value_default attribute is out of range in node "
<< mName << " " << default_weight << llendl;
}
}
// attribute: sex
std::string sex = "both";
static LLStdStringHandle sex_string = LLXmlTree::addAttributeString("sex");
node->getFastAttributeString(sex_string, sex); // optional
if (sex == "both")
{
mSex = SEX_BOTH;
}
else if (sex == "male")
{
mSex = SEX_MALE;
}
else if (sex == "female")
{
mSex = SEX_FEMALE;
}
else
{
llwarns << "Avatar file: has invalid sex attribute: " << sex
<< llendl;
return false;
}
// attribute: name
static LLStdStringHandle name_string = LLXmlTree::addAttributeString("name");
if (!node->getFastAttributeString(name_string, mName))
{
llwarns << "Avatar file: is missing name attribute" << llendl;
return false;
}
// attribute: label
static LLStdStringHandle label_string = LLXmlTree::addAttributeString("label");
if (!node->getFastAttributeString(label_string, mDisplayName))
{
mDisplayName = mName;
}
// JC - make sure the display name includes the capitalization in the XML file,
// not the lowercased version.
LLStringUtil::toLower(mName);
// attribute: label_min
static LLStdStringHandle label_min_string = LLXmlTree::addAttributeString("label_min");
if (!node->getFastAttributeString(label_min_string, mMinName))
{
mMinName = "Less";
}
// attribute: label_max
static LLStdStringHandle label_max_string = LLXmlTree::addAttributeString("label_max");
if (!node->getFastAttributeString(label_max_string, mMaxName))
{
mMaxName = "More";
}
return true;
}
//-----------------------------------------------------------------------------
// LLVisualParam()
//-----------------------------------------------------------------------------
LLVisualParam::LLVisualParam()
: mCurWeight(0.f),
mLastWeight(0.f),
mNext(NULL),
mTargetWeight(0.f),
mIsAnimating(false),
mIsDummy(false),
mID(-1),
mInfo(0),
mParamLocation(LOC_UNKNOWN)
{
}
LLVisualParam::LLVisualParam(const LLVisualParam& other)
: mCurWeight(other.mCurWeight),
mLastWeight(other.mLastWeight),
mNext(other.mNext),
mTargetWeight(other.mTargetWeight),
mIsAnimating(other.mIsAnimating),
mIsDummy(other.mIsDummy),
mID(other.mID),
mInfo(other.mInfo),
mParamLocation(other.mParamLocation)
{
}
//-----------------------------------------------------------------------------
// ~LLVisualParam()
//-----------------------------------------------------------------------------
LLVisualParam::~LLVisualParam()
{
if (mNext)
{
delete mNext;
mNext = NULL;
}
}
//=============================================================================
// This virtual functions should always be overridden, but is included here for
// use as templates
//=============================================================================
#if 0
//-----------------------------------------------------------------------------
// setInfo()
//-----------------------------------------------------------------------------
bool LLVisualParam::setInfo(LLVisualParamInfo* info)
{
llassert(mInfo == NULL);
if (info->mID < 0)
{
return false;
}
mInfo = info;
mID = info->mID;
setWeight(getDefaultWeight(), false);
return true;
}
#endif
//-----------------------------------------------------------------------------
// setWeight()
//-----------------------------------------------------------------------------
void LLVisualParam::setWeight(F32 weight, bool upload_bake)
{
if (mIsAnimating)
{
//RN: allow overshoot
mCurWeight = weight;
}
else if (mInfo)
{
mCurWeight = llclamp(weight, mInfo->mMinWeight, mInfo->mMaxWeight);
}
else
{
mCurWeight = weight;
}
if (mNext)
{
mNext->setWeight(weight, upload_bake);
}
}
//-----------------------------------------------------------------------------
// setAnimationTarget()
//-----------------------------------------------------------------------------
void LLVisualParam::setAnimationTarget(F32 target_value, bool upload_bake)
{
// don't animate dummy parameters
if (mIsDummy)
{
setWeight(target_value, upload_bake);
mTargetWeight = mCurWeight;
return;
}
if (mInfo)
{
if (isTweakable())
{
mTargetWeight = llclamp(target_value, mInfo->mMinWeight,
mInfo->mMaxWeight);
}
}
else
{
mTargetWeight = target_value;
}
mIsAnimating = true;
if (mNext)
{
mNext->setAnimationTarget(target_value, upload_bake);
}
}
//-----------------------------------------------------------------------------
// setNextParam()
//-----------------------------------------------------------------------------
void LLVisualParam::setNextParam(LLVisualParam* next)
{
// need to establish mNext before we start changing values on this, else
// initial value won't get mirrored (we can fix that, but better to forbid
// this pattern):
llassert(!mNext && getWeight() == getDefaultWeight());
mNext = next;
}
//-----------------------------------------------------------------------------
// animate()
//-----------------------------------------------------------------------------
void LLVisualParam::animate(F32 delta, bool upload_bake)
{
if (mIsAnimating)
{
F32 new_weight = (mTargetWeight - mCurWeight) * delta + mCurWeight;
setWeight(new_weight, upload_bake);
}
}
//-----------------------------------------------------------------------------
// stopAnimating()
//-----------------------------------------------------------------------------
void LLVisualParam::stopAnimating(bool upload_bake)
{
if (mIsAnimating && isTweakable())
{
mIsAnimating = false;
setWeight(mTargetWeight, upload_bake);
}
}
const std::string param_location_name(const EParamLocation& loc)
{
switch (loc)
{
case LOC_UNKNOWN: return "unknown";
case LOC_AV_SELF: return "self";
case LOC_AV_OTHER: return "other";
case LOC_WEARABLE: return "wearable";
default: return "error";
}
}
void LLVisualParam::setParamLocation(EParamLocation loc)
{
if (mParamLocation == LOC_UNKNOWN || loc == LOC_UNKNOWN)
{
mParamLocation = loc;
}
else if (mParamLocation != loc)
{
LL_DEBUGS("VisualParams") << "Param location is already "
<< mParamLocation << ", not slamming to "
<< loc << LL_ENDL;
}
}