00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "lldriverparam.h"
00035
00036 #include "llfasttimer.h"
00037
00038
00039
00040
00041
00042 LLDriverParamInfo::LLDriverParamInfo()
00043 {
00044 }
00045
00046 BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node)
00047 {
00048 llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) );
00049
00050 if( !LLViewerVisualParamInfo::parseXml( node ))
00051 return FALSE;
00052
00053 LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" );
00054 if( !param_driver_node )
00055 return FALSE;
00056
00057 for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" );
00058 child;
00059 child = param_driver_node->getNextNamedChild())
00060 {
00061 S32 driven_id;
00062 static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
00063 if( child->getFastAttributeS32( id_string, driven_id ) )
00064 {
00065 F32 min1 = mMinWeight;
00066 F32 max1 = mMaxWeight;
00067 F32 max2 = max1;
00068 F32 min2 = max1;
00069
00070
00071
00072
00073
00074
00075
00076
00077
00078
00079 static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1");
00080 child->getFastAttributeF32( min1_string, min1 );
00081 static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1");
00082 child->getFastAttributeF32( max1_string, max1 );
00083 static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2");
00084 child->getFastAttributeF32( max2_string, max2 );
00085 static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2");
00086 child->getFastAttributeF32( min2_string, min2 );
00087
00088
00089
00090 mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) );
00091 }
00092 else
00093 {
00094 llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
00095 return FALSE;
00096 }
00097 }
00098 return TRUE;
00099 }
00100
00101
00102
00103
00104
00105 LLDriverParam::LLDriverParam(LLVOAvatar *avatarp)
00106 : mCurrentDistortionParam( NULL ), mAvatarp(avatarp)
00107 {
00108 }
00109
00110 LLDriverParam::~LLDriverParam()
00111 {
00112 }
00113
00114 BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
00115 {
00116 llassert(mInfo == NULL);
00117 if (info->mID < 0)
00118 return FALSE;
00119 mInfo = info;
00120 mID = info->mID;
00121
00122 setWeight(getDefaultWeight(), FALSE );
00123
00124 LLDriverParamInfo::entry_info_list_t::iterator iter;
00125 mDriven.reserve(getInfo()->mDrivenInfoList.size());
00126 for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); iter++)
00127 {
00128 LLDrivenEntryInfo *driven_info = &(*iter);
00129 S32 driven_id = driven_info->mDrivenID;
00130 LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarp->getVisualParam( driven_id );
00131 if (param)
00132 {
00133 mDriven.push_back(LLDrivenEntry( param, driven_info ));
00134 }
00135 else
00136 {
00137 llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
00138 mInfo = NULL;
00139 return FALSE;
00140 }
00141 }
00142
00143 return TRUE;
00144 }
00145
00146 #if 0 // obsolete
00147 BOOL LLDriverParam::parseData(LLXmlTreeNode* node)
00148 {
00149 LLDriverParamInfo* info = new LLDriverParamInfo;
00150
00151 info->parseXml(node);
00152 if (!setInfo(info))
00153 {
00154 delete info;
00155 return FALSE;
00156 }
00157 return TRUE;
00158 }
00159 #endif
00160
00161 void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
00162 {
00163 F32 min_weight = getMinWeight();
00164 F32 max_weight = getMaxWeight();
00165 if (mIsAnimating)
00166 {
00167
00168 mCurWeight = weight;
00169 }
00170 else
00171 {
00172 mCurWeight = llclamp(weight, min_weight, max_weight);
00173 }
00174
00175
00176
00177
00178
00179
00180
00181
00182
00183
00184 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00185 {
00186 LLDrivenEntry* driven = &(*iter);
00187 LLDrivenEntryInfo* info = driven->mInfo;
00188
00189 F32 driven_weight = 0.f;
00190 F32 driven_min = driven->mParam->getMinWeight();
00191 F32 driven_max = driven->mParam->getMaxWeight();
00192
00193 if (mIsAnimating)
00194 {
00195
00196 if (!driven->mParam->getAnimating())
00197 {
00198 continue;
00199 }
00200 if( mCurWeight < info->mMin1 )
00201 {
00202 if (info->mMin1 == min_weight)
00203 {
00204 if (info->mMin1 == info->mMax1)
00205 {
00206 driven_weight = driven_max;
00207 }
00208 else
00209 {
00210
00211 F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 );
00212 driven_weight = driven_min + t * (driven_max - driven_min);
00213 }
00214 }
00215 else
00216 {
00217 driven_weight = driven_min;
00218 }
00219
00220 driven->mParam->setWeight( driven_weight, set_by_user );
00221 continue;
00222 }
00223 else
00224 if ( mCurWeight > info->mMin2 )
00225 {
00226 if (info->mMin2 == max_weight)
00227 {
00228 if (info->mMin2 == info->mMax2)
00229 {
00230 driven_weight = driven_max;
00231 }
00232 else
00233 {
00234
00235 F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 );
00236 driven_weight = driven_max + t * (driven_min - driven_max);
00237 }
00238 }
00239 else
00240 {
00241 driven_weight = driven_min;
00242 }
00243
00244 driven->mParam->setWeight( driven_weight, set_by_user );
00245 continue;
00246 }
00247 }
00248
00249 driven_weight = getDrivenWeight(driven, mCurWeight);
00250 driven->mParam->setWeight( driven_weight, set_by_user );
00251 }
00252 }
00253
00254 F32 LLDriverParam::getTotalDistortion()
00255 {
00256 F32 sum = 0.f;
00257 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00258 {
00259 LLDrivenEntry* driven = &(*iter);
00260 sum += driven->mParam->getTotalDistortion();
00261 }
00262
00263 return sum;
00264 }
00265
00266 const LLVector3 &LLDriverParam::getAvgDistortion()
00267 {
00268
00269 LLVector3 sum;
00270 S32 count = 0;
00271 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00272 {
00273 LLDrivenEntry* driven = &(*iter);
00274 sum += driven->mParam->getAvgDistortion();
00275 count++;
00276 }
00277 sum /= (F32)count;
00278
00279 mDefaultVec = sum;
00280 return mDefaultVec;
00281 }
00282
00283 F32 LLDriverParam::getMaxDistortion()
00284 {
00285 F32 max = 0.f;
00286 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00287 {
00288 LLDrivenEntry* driven = &(*iter);
00289 F32 param_max = driven->mParam->getMaxDistortion();
00290 if( param_max > max )
00291 {
00292 max = param_max;
00293 }
00294 }
00295
00296 return max;
00297 }
00298
00299
00300 LLVector3 LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh)
00301 {
00302 LLVector3 sum;
00303 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00304 {
00305 LLDrivenEntry* driven = &(*iter);
00306 sum += driven->mParam->getVertexDistortion( index, poly_mesh );
00307 }
00308 return sum;
00309 }
00310
00311 const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
00312 {
00313 mCurrentDistortionParam = NULL;
00314 const LLVector3* v = NULL;
00315 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00316 {
00317 LLDrivenEntry* driven = &(*iter);
00318 v = driven->mParam->getFirstDistortion( index, poly_mesh );
00319 if( v )
00320 {
00321 mCurrentDistortionParam = driven->mParam;
00322 break;
00323 }
00324 }
00325
00326 return v;
00327 };
00328
00329 const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
00330 {
00331 llassert( mCurrentDistortionParam );
00332 if( !mCurrentDistortionParam )
00333 {
00334 return NULL;
00335 }
00336
00337 LLDrivenEntry* driven = NULL;
00338 entry_list_t::iterator iter;
00339
00340
00341 for( iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00342 {
00343 driven = &(*iter);
00344 if( driven->mParam == mCurrentDistortionParam )
00345 {
00346 break;
00347 }
00348 }
00349
00350
00351 const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh );
00352 if( (!v) && (iter != mDriven.end()) )
00353 {
00354
00355
00356 for( iter++; iter != mDriven.end(); iter++ )
00357 {
00358 driven = &(*iter);
00359 v = driven->mParam->getFirstDistortion( index, poly_mesh );
00360 if( v )
00361 {
00362 mCurrentDistortionParam = driven->mParam;
00363 break;
00364 }
00365 }
00366 }
00367
00368 return v;
00369 };
00370
00371
00372
00373
00374 void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user )
00375 {
00376 LLVisualParam::setAnimationTarget(target_value, set_by_user);
00377
00378 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00379 {
00380 LLDrivenEntry* driven = &(*iter);
00381 F32 driven_weight = getDrivenWeight(driven, mTargetWeight);
00382
00383
00384
00385 driven->mParam->setAnimationTarget(driven_weight, set_by_user);
00386 }
00387 }
00388
00389
00390
00391
00392 void LLDriverParam::stopAnimating(BOOL set_by_user)
00393 {
00394 LLVisualParam::stopAnimating(set_by_user);
00395
00396 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
00397 {
00398 LLDrivenEntry* driven = &(*iter);
00399 driven->mParam->setAnimating(FALSE);
00400 }
00401 }
00402
00403
00404
00405
00406 F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight)
00407 {
00408 F32 min_weight = getMinWeight();
00409 F32 max_weight = getMaxWeight();
00410 const LLDrivenEntryInfo* info = driven->mInfo;
00411
00412 F32 driven_weight = 0.f;
00413 F32 driven_min = driven->mParam->getMinWeight();
00414 F32 driven_max = driven->mParam->getMaxWeight();
00415
00416 if( input_weight <= info->mMin1 )
00417 {
00418 if( info->mMin1 == info->mMax1 &&
00419 info->mMin1 <= min_weight)
00420 {
00421 driven_weight = driven_max;
00422 }
00423 else
00424 {
00425 driven_weight = driven_min;
00426 }
00427 }
00428 else
00429 if( input_weight <= info->mMax1 )
00430 {
00431 F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 );
00432 driven_weight = driven_min + t * (driven_max - driven_min);
00433 }
00434 else
00435 if( input_weight <= info->mMax2 )
00436 {
00437 driven_weight = driven_max;
00438 }
00439 else
00440 if( input_weight <= info->mMin2 )
00441 {
00442 F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 );
00443 driven_weight = driven_max + t * (driven_min - driven_max);
00444 }
00445 else
00446 {
00447 if (info->mMax2 >= max_weight)
00448 {
00449 driven_weight = driven_max;
00450 }
00451 else
00452 {
00453 driven_weight = driven_min;
00454 }
00455 }
00456
00457 return driven_weight;
00458 }