diff options
author | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
---|---|---|
committer | Jacek Antonelli | 2008-08-15 23:44:46 -0500 |
commit | 38d6d37f2d982fa959e9e8a4a3f7e1ccfad7b5d4 (patch) | |
tree | adca584755d22ca041a2dbfc35d4eca01f70b32c /linden/indra/newview/lldriverparam.cpp | |
parent | README.txt (diff) | |
download | meta-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.cpp | 454 |
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 | |||
38 | LLDriverParamInfo::LLDriverParamInfo() | ||
39 | { | ||
40 | } | ||
41 | |||
42 | BOOL 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 | |||
101 | LLDriverParam::LLDriverParam(LLVOAvatar *avatarp) | ||
102 | : mCurrentDistortionParam( NULL ), mAvatarp(avatarp) | ||
103 | { | ||
104 | } | ||
105 | |||
106 | LLDriverParam::~LLDriverParam() | ||
107 | { | ||
108 | } | ||
109 | |||
110 | BOOL 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 | ||
143 | BOOL 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 | |||
157 | void 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 | |||
250 | F32 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 | |||
262 | const 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 | |||
279 | F32 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 | |||
296 | LLVector3 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 | |||
307 | const 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 | |||
325 | const 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 | //----------------------------------------------------------------------------- | ||
370 | void 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 | //----------------------------------------------------------------------------- | ||
388 | void 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 | //----------------------------------------------------------------------------- | ||
402 | F32 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 | } | ||