aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/lldriverparam.cpp
diff options
context:
space:
mode:
authorJacek Antonelli2008-08-15 23:44:46 -0500
committerJacek Antonelli2008-08-15 23:44:46 -0500
commit38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch)
treeadca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldriverparam.cpp
parentREADME.txt (diff)
downloadmeta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.zip
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.gz
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.bz2
meta-impy-38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4.tar.xz
Second Life viewer sources 1.13.2.12
Diffstat (limited to '')
-rw-r--r--linden/indra/newview/lldriverparam.cpp454
1 files changed, 454 insertions, 0 deletions
diff --git a/linden/indra/newview/lldriverparam.cpp b/linden/indra/newview/lldriverparam.cpp
new file mode 100644
index 0000000..3e0409e
--- /dev/null
+++ b/linden/indra/newview/lldriverparam.cpp
@@ -0,0 +1,454 @@
1/**
2 * @file lldriverparam.cpp
3 * @brief A visual parameter that drives (controls) other visual parameters.
4 *
5 * Copyright (c) 2002-2007, Linden Research, Inc.
6 *
7 * The source code in this file ("Source Code") is provided by Linden Lab
8 * to you under the terms of the GNU General Public License, version 2.0
9 * ("GPL"), unless you have obtained a separate licensing agreement
10 * ("Other License"), formally executed by you and Linden Lab. Terms of
11 * the GPL can be found in doc/GPL-license.txt in this distribution, or
12 * online at http://secondlife.com/developers/opensource/gplv2
13 *
14 * There are special exceptions to the terms and conditions of the GPL as
15 * it is applied to this Source Code. View the full text of the exception
16 * in the file doc/FLOSS-exception.txt in this software distribution, or
17 * online at http://secondlife.com/developers/opensource/flossexception
18 *
19 * By copying, modifying or distributing this software, you acknowledge
20 * that you have read and understood your obligations described above,
21 * and agree to abide by those obligations.
22 *
23 * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
24 * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
25 * COMPLETENESS OR PERFORMANCE.
26 */
27
28#include "llviewerprecompiledheaders.h"
29
30#include "lldriverparam.h"
31
32#include "llfasttimer.h"
33
34//-----------------------------------------------------------------------------
35// LLDriverParamInfo
36//-----------------------------------------------------------------------------
37
38LLDriverParamInfo::LLDriverParamInfo()
39{
40}
41
42BOOL LLDriverParamInfo::parseXml(LLXmlTreeNode* node)
43{
44 llassert( node->hasName( "param" ) && node->getChildByName( "param_driver" ) );
45
46 if( !LLViewerVisualParamInfo::parseXml( node ))
47 return FALSE;
48
49 LLXmlTreeNode* param_driver_node = node->getChildByName( "param_driver" );
50 if( !param_driver_node )
51 return FALSE;
52
53 for (LLXmlTreeNode* child = param_driver_node->getChildByName( "driven" );
54 child;
55 child = param_driver_node->getNextNamedChild())
56 {
57 S32 driven_id;
58 static LLStdStringHandle id_string = LLXmlTree::addAttributeString("id");
59 if( child->getFastAttributeS32( id_string, driven_id ) )
60 {
61 F32 min1 = mMinWeight;
62 F32 max1 = mMaxWeight;
63 F32 max2 = max1;
64 F32 min2 = max1;
65
66 // driven ________ //
67 // ^ /| |\ //
68 // | / | | \ //
69 // | / | | \ //
70 // | / | | \ //
71 // | / | | \ //
72 //-------|----|-------|----|-------> driver //
73 // | min1 max1 max2 min2
74
75 static LLStdStringHandle min1_string = LLXmlTree::addAttributeString("min1");
76 child->getFastAttributeF32( min1_string, min1 ); // optional
77 static LLStdStringHandle max1_string = LLXmlTree::addAttributeString("max1");
78 child->getFastAttributeF32( max1_string, max1 ); // optional
79 static LLStdStringHandle max2_string = LLXmlTree::addAttributeString("max2");
80 child->getFastAttributeF32( max2_string, max2 ); // optional
81 static LLStdStringHandle min2_string = LLXmlTree::addAttributeString("min2");
82 child->getFastAttributeF32( min2_string, min2 ); // optional
83
84 // Push these on the front of the deque, so that we can construct
85 // them in order later (faster)
86 mDrivenInfoList.push_front( LLDrivenEntryInfo( driven_id, min1, max1, max2, min2 ) );
87 }
88 else
89 {
90 llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
91 return FALSE;
92 }
93 }
94 return TRUE;
95}
96
97//-----------------------------------------------------------------------------
98// LLDriverParam
99//-----------------------------------------------------------------------------
100
101LLDriverParam::LLDriverParam(LLVOAvatar *avatarp)
102 : mCurrentDistortionParam( NULL ), mAvatarp(avatarp)
103{
104}
105
106LLDriverParam::~LLDriverParam()
107{
108}
109
110BOOL LLDriverParam::setInfo(LLDriverParamInfo *info)
111{
112 llassert(mInfo == NULL);
113 if (info->mID < 0)
114 return FALSE;
115 mInfo = info;
116 mID = info->mID;
117
118 setWeight(getDefaultWeight(), FALSE );
119
120 LLDriverParamInfo::entry_info_list_t::iterator iter;
121 mDriven.reserve(getInfo()->mDrivenInfoList.size());
122 for (iter = getInfo()->mDrivenInfoList.begin(); iter != getInfo()->mDrivenInfoList.end(); iter++)
123 {
124 LLDrivenEntryInfo *driven_info = &(*iter);
125 S32 driven_id = driven_info->mDrivenID;
126 LLViewerVisualParam* param = (LLViewerVisualParam*)mAvatarp->getVisualParam( driven_id );
127 if (param)
128 {
129 mDriven.push_back(LLDrivenEntry( param, driven_info ));
130 }
131 else
132 {
133 llerrs << "<driven> Unable to resolve driven parameter: " << driven_id << llendl;
134 mInfo = NULL;
135 return FALSE;
136 }
137 }
138
139 return TRUE;
140}
141
142#if 0 // obsolete
143BOOL LLDriverParam::parseData(LLXmlTreeNode* node)
144{
145 LLDriverParamInfo* info = new LLDriverParamInfo;
146
147 info->parseXml(node);
148 if (!setInfo(info))
149 {
150 delete info;
151 return FALSE;
152 }
153 return TRUE;
154}
155#endif
156
157void LLDriverParam::setWeight(F32 weight, BOOL set_by_user)
158{
159 F32 min_weight = getMinWeight();
160 F32 max_weight = getMaxWeight();
161 if (mIsAnimating)
162 {
163 // allow overshoot when animating
164 mCurWeight = weight;
165 }
166 else
167 {
168 mCurWeight = llclamp(weight, min_weight, max_weight);
169 }
170
171 // driven ________
172 // ^ /| |\ ^
173 // | / | | \ |
174 // | / | | \ |
175 // | / | | \ |
176 // | / | | \ |
177 //-------|----|-------|----|-------> driver
178 // | min1 max1 max2 min2
179
180 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
181 {
182 LLDrivenEntry* driven = &(*iter);
183 LLDrivenEntryInfo* info = driven->mInfo;
184
185 F32 driven_weight = 0.f;
186 F32 driven_min = driven->mParam->getMinWeight();
187 F32 driven_max = driven->mParam->getMaxWeight();
188
189 if (mIsAnimating)
190 {
191 // driven param doesn't interpolate (textures, for example)
192 if (!driven->mParam->getAnimating())
193 {
194 continue;
195 }
196 if( mCurWeight < info->mMin1 )
197 {
198 if (info->mMin1 == min_weight)
199 {
200 if (info->mMin1 == info->mMax1)
201 {
202 driven_weight = driven_max;
203 }
204 else
205 {
206 //up slope extrapolation
207 F32 t = (mCurWeight - info->mMin1) / (info->mMax1 - info->mMin1 );
208 driven_weight = driven_min + t * (driven_max - driven_min);
209 }
210 }
211 else
212 {
213 driven_weight = driven_min;
214 }
215
216 driven->mParam->setWeight( driven_weight, set_by_user );
217 continue;
218 }
219 else
220 if ( mCurWeight > info->mMin2 )
221 {
222 if (info->mMin2 == max_weight)
223 {
224 if (info->mMin2 == info->mMax2)
225 {
226 driven_weight = driven_max;
227 }
228 else
229 {
230 //down slope extrapolation
231 F32 t = (mCurWeight - info->mMax2) / (info->mMin2 - info->mMax2 );
232 driven_weight = driven_max + t * (driven_min - driven_max);
233 }
234 }
235 else
236 {
237 driven_weight = driven_min;
238 }
239
240 driven->mParam->setWeight( driven_weight, set_by_user );
241 continue;
242 }
243 }
244
245 driven_weight = getDrivenWeight(driven, mCurWeight);
246 driven->mParam->setWeight( driven_weight, set_by_user );
247 }
248}
249
250F32 LLDriverParam::getTotalDistortion()
251{
252 F32 sum = 0.f;
253 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
254 {
255 LLDrivenEntry* driven = &(*iter);
256 sum += driven->mParam->getTotalDistortion();
257 }
258
259 return sum;
260}
261
262const LLVector3 &LLDriverParam::getAvgDistortion()
263{
264 // It's not actually correct to take the average of averages, but it good enough here.
265 LLVector3 sum;
266 S32 count = 0;
267 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
268 {
269 LLDrivenEntry* driven = &(*iter);
270 sum += driven->mParam->getAvgDistortion();
271 count++;
272 }
273 sum /= (F32)count;
274
275 mDefaultVec = sum;
276 return mDefaultVec;
277}
278
279F32 LLDriverParam::getMaxDistortion()
280{
281 F32 max = 0.f;
282 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
283 {
284 LLDrivenEntry* driven = &(*iter);
285 F32 param_max = driven->mParam->getMaxDistortion();
286 if( param_max > max )
287 {
288 max = param_max;
289 }
290 }
291
292 return max;
293}
294
295
296LLVector3 LLDriverParam::getVertexDistortion(S32 index, LLPolyMesh *poly_mesh)
297{
298 LLVector3 sum;
299 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
300 {
301 LLDrivenEntry* driven = &(*iter);
302 sum += driven->mParam->getVertexDistortion( index, poly_mesh );
303 }
304 return sum;
305}
306
307const LLVector3* LLDriverParam::getFirstDistortion(U32 *index, LLPolyMesh **poly_mesh)
308{
309 mCurrentDistortionParam = NULL;
310 const LLVector3* v = NULL;
311 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
312 {
313 LLDrivenEntry* driven = &(*iter);
314 v = driven->mParam->getFirstDistortion( index, poly_mesh );
315 if( v )
316 {
317 mCurrentDistortionParam = driven->mParam;
318 break;
319 }
320 }
321
322 return v;
323};
324
325const LLVector3* LLDriverParam::getNextDistortion(U32 *index, LLPolyMesh **poly_mesh)
326{
327 llassert( mCurrentDistortionParam );
328 if( !mCurrentDistortionParam )
329 {
330 return NULL;
331 }
332
333 LLDrivenEntry* driven = NULL;
334 entry_list_t::iterator iter;
335
336 // Set mDriven iteration to the right point
337 for( iter = mDriven.begin(); iter != mDriven.end(); iter++ )
338 {
339 driven = &(*iter);
340 if( driven->mParam == mCurrentDistortionParam )
341 {
342 break;
343 }
344 }
345
346 // We're already in the middle of a param's distortions, so get the next one.
347 const LLVector3* v = driven->mParam->getNextDistortion( index, poly_mesh );
348 if( !v )
349 {
350 // This param is finished, so start the next param. It might not have any
351 // distortions, though, so we have to loop to find the next param that does.
352 for( iter++; iter != mDriven.end(); iter++ )
353 {
354 driven = &(*iter);
355 v = driven->mParam->getFirstDistortion( index, poly_mesh );
356 if( v )
357 {
358 mCurrentDistortionParam = driven->mParam;
359 break;
360 }
361 }
362 }
363
364 return v;
365};
366
367//-----------------------------------------------------------------------------
368// setAnimationTarget()
369//-----------------------------------------------------------------------------
370void LLDriverParam::setAnimationTarget( F32 target_value, BOOL set_by_user )
371{
372 LLVisualParam::setAnimationTarget(target_value, set_by_user);
373
374 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
375 {
376 LLDrivenEntry* driven = &(*iter);
377 F32 driven_weight = getDrivenWeight(driven, mTargetWeight);
378
379 // this isn't normally necessary, as driver params handle interpolation of their driven params
380 // but texture params need to know to assume their final value at beginning of interpolation
381 driven->mParam->setAnimationTarget(driven_weight, set_by_user);
382 }
383}
384
385//-----------------------------------------------------------------------------
386// stopAnimating()
387//-----------------------------------------------------------------------------
388void LLDriverParam::stopAnimating(BOOL set_by_user)
389{
390 LLVisualParam::stopAnimating(set_by_user);
391
392 for( entry_list_t::iterator iter = mDriven.begin(); iter != mDriven.end(); iter++ )
393 {
394 LLDrivenEntry* driven = &(*iter);
395 driven->mParam->setAnimating(FALSE);
396 }
397}
398
399//-----------------------------------------------------------------------------
400// getDrivenWeight()
401//-----------------------------------------------------------------------------
402F32 LLDriverParam::getDrivenWeight(const LLDrivenEntry* driven, F32 input_weight)
403{
404 F32 min_weight = getMinWeight();
405 F32 max_weight = getMaxWeight();
406 const LLDrivenEntryInfo* info = driven->mInfo;
407
408 F32 driven_weight = 0.f;
409 F32 driven_min = driven->mParam->getMinWeight();
410 F32 driven_max = driven->mParam->getMaxWeight();
411
412 if( input_weight <= info->mMin1 )
413 {
414 if( info->mMin1 == info->mMax1 &&
415 info->mMin1 <= min_weight)
416 {
417 driven_weight = driven_max;
418 }
419 else
420 {
421 driven_weight = driven_min;
422 }
423 }
424 else
425 if( input_weight <= info->mMax1 )
426 {
427 F32 t = (input_weight - info->mMin1) / (info->mMax1 - info->mMin1 );
428 driven_weight = driven_min + t * (driven_max - driven_min);
429 }
430 else
431 if( input_weight <= info->mMax2 )
432 {
433 driven_weight = driven_max;
434 }
435 else
436 if( input_weight <= info->mMin2 )
437 {
438 F32 t = (input_weight - info->mMax2) / (info->mMin2 - info->mMax2 );
439 driven_weight = driven_max + t * (driven_min - driven_max);
440 }
441 else
442 {
443 if (info->mMax2 >= max_weight)
444 {
445 driven_weight = driven_max;
446 }
447 else
448 {
449 driven_weight = driven_min;
450 }
451 }
452
453 return driven_weight;
454}