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/llhudeffectpointat.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 'linden/indra/newview/llhudeffectpointat.cpp')
-rw-r--r-- | linden/indra/newview/llhudeffectpointat.cpp | 449 |
1 files changed, 449 insertions, 0 deletions
diff --git a/linden/indra/newview/llhudeffectpointat.cpp b/linden/indra/newview/llhudeffectpointat.cpp new file mode 100644 index 0000000..7644ff8 --- /dev/null +++ b/linden/indra/newview/llhudeffectpointat.cpp | |||
@@ -0,0 +1,449 @@ | |||
1 | /** | ||
2 | * @file llhudeffectpointat.cpp | ||
3 | * @brief LLHUDEffectPointAt class implementation | ||
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 "llhudeffectpointat.h" | ||
31 | |||
32 | #include "llgl.h" | ||
33 | |||
34 | #include "llagent.h" | ||
35 | #include "lldrawable.h" | ||
36 | #include "llviewerobjectlist.h" | ||
37 | #include "llvoavatar.h" | ||
38 | #include "message.h" | ||
39 | |||
40 | // packet layout | ||
41 | const S32 SOURCE_AVATAR = 0; | ||
42 | const S32 TARGET_OBJECT = 16; | ||
43 | const S32 TARGET_POS = 32; | ||
44 | const S32 POINTAT_TYPE = 56; | ||
45 | const S32 PKT_SIZE = 57; | ||
46 | |||
47 | // throttle | ||
48 | const F32 MAX_SENDS_PER_SEC = 4.f; | ||
49 | |||
50 | const F32 MIN_DELTAPOS_FOR_UPDATE = 0.05f; | ||
51 | |||
52 | // timeouts | ||
53 | // can't use actual F32_MAX, because we add this to the current frametime | ||
54 | const F32 MAX_TIMEOUT = F32_MAX / 4.f; | ||
55 | |||
56 | const F32 POINTAT_TIMEOUTS[POINTAT_NUM_TARGETS] = | ||
57 | { | ||
58 | MAX_TIMEOUT, //POINTAT_TARGET_NONE | ||
59 | MAX_TIMEOUT, //POINTAT_TARGET_SELECT | ||
60 | MAX_TIMEOUT, //POINTAT_TARGET_GRAB | ||
61 | 0.f, //POINTAT_TARGET_CLEAR | ||
62 | }; | ||
63 | |||
64 | const S32 POINTAT_PRIORITIES[POINTAT_NUM_TARGETS] = | ||
65 | { | ||
66 | 0, //POINTAT_TARGET_NONE | ||
67 | 1, //POINTAT_TARGET_SELECT | ||
68 | 2, //POINTAT_TARGET_GRAB | ||
69 | 3, //POINTAT_TARGET_CLEAR | ||
70 | }; | ||
71 | |||
72 | // statics | ||
73 | |||
74 | BOOL LLHUDEffectPointAt::sDebugPointAt; | ||
75 | |||
76 | |||
77 | //----------------------------------------------------------------------------- | ||
78 | // LLHUDEffectPointAt() | ||
79 | //----------------------------------------------------------------------------- | ||
80 | LLHUDEffectPointAt::LLHUDEffectPointAt(const U8 type) : | ||
81 | LLHUDEffect(type), | ||
82 | mKillTime(0.f), | ||
83 | mLastSendTime(0.f) | ||
84 | { | ||
85 | clearPointAtTarget(); | ||
86 | } | ||
87 | |||
88 | //----------------------------------------------------------------------------- | ||
89 | // ~LLHUDEffectPointAt() | ||
90 | //----------------------------------------------------------------------------- | ||
91 | LLHUDEffectPointAt::~LLHUDEffectPointAt() | ||
92 | { | ||
93 | } | ||
94 | |||
95 | //----------------------------------------------------------------------------- | ||
96 | // packData() | ||
97 | //----------------------------------------------------------------------------- | ||
98 | void LLHUDEffectPointAt::packData(LLMessageSystem *mesgsys) | ||
99 | { | ||
100 | // Pack the default data | ||
101 | LLHUDEffect::packData(mesgsys); | ||
102 | |||
103 | // Pack the type-specific data. Uses a fun packed binary format. Whee! | ||
104 | U8 packed_data[PKT_SIZE]; | ||
105 | memset(packed_data, 0, PKT_SIZE); | ||
106 | |||
107 | if (mSourceObject) | ||
108 | { | ||
109 | htonmemcpy(&(packed_data[SOURCE_AVATAR]), mSourceObject->mID.mData, MVT_LLUUID, 16); | ||
110 | } | ||
111 | else | ||
112 | { | ||
113 | htonmemcpy(&(packed_data[SOURCE_AVATAR]), LLUUID::null.mData, MVT_LLUUID, 16); | ||
114 | } | ||
115 | |||
116 | // pack both target object and position | ||
117 | // position interpreted as offset if target object is non-null | ||
118 | if (mTargetObject) | ||
119 | { | ||
120 | htonmemcpy(&(packed_data[TARGET_OBJECT]), mTargetObject->mID.mData, MVT_LLUUID, 16); | ||
121 | } | ||
122 | else | ||
123 | { | ||
124 | htonmemcpy(&(packed_data[TARGET_OBJECT]), LLUUID::null.mData, MVT_LLUUID, 16); | ||
125 | } | ||
126 | |||
127 | htonmemcpy(&(packed_data[TARGET_POS]), mTargetOffsetGlobal.mdV, MVT_LLVector3d, 24); | ||
128 | |||
129 | U8 pointAtTypePacked = (U8)mTargetType; | ||
130 | htonmemcpy(&(packed_data[POINTAT_TYPE]), &pointAtTypePacked, MVT_U8, 1); | ||
131 | |||
132 | mesgsys->addBinaryDataFast(_PREHASH_TypeData, packed_data, PKT_SIZE); | ||
133 | |||
134 | mLastSendTime = mTimer.getElapsedTimeF32(); | ||
135 | } | ||
136 | |||
137 | //----------------------------------------------------------------------------- | ||
138 | // unpackData() | ||
139 | //----------------------------------------------------------------------------- | ||
140 | void LLHUDEffectPointAt::unpackData(LLMessageSystem *mesgsys, S32 blocknum) | ||
141 | { | ||
142 | LLVector3d new_target; | ||
143 | U8 packed_data[PKT_SIZE]; | ||
144 | |||
145 | LLUUID dataId; | ||
146 | mesgsys->getUUIDFast(_PREHASH_Effect, _PREHASH_ID, dataId, blocknum); | ||
147 | |||
148 | // ignore messages from ourselves | ||
149 | if (!gAgent.mPointAt.isNull() && dataId == gAgent.mPointAt->getID()) | ||
150 | { | ||
151 | return; | ||
152 | } | ||
153 | |||
154 | LLHUDEffect::unpackData(mesgsys, blocknum); | ||
155 | LLUUID source_id; | ||
156 | LLUUID target_id; | ||
157 | S32 size = mesgsys->getSizeFast(_PREHASH_Effect, blocknum, _PREHASH_TypeData); | ||
158 | if (size != PKT_SIZE) | ||
159 | { | ||
160 | llwarns << "PointAt effect with bad size " << size << llendl; | ||
161 | return; | ||
162 | } | ||
163 | mesgsys->getBinaryDataFast(_PREHASH_Effect, _PREHASH_TypeData, packed_data, PKT_SIZE, blocknum); | ||
164 | |||
165 | htonmemcpy(source_id.mData, &(packed_data[SOURCE_AVATAR]), MVT_LLUUID, 16); | ||
166 | |||
167 | LLViewerObject *objp = gObjectList.findObject(source_id); | ||
168 | if (objp && objp->isAvatar()) | ||
169 | { | ||
170 | setSourceObject(objp); | ||
171 | } | ||
172 | else | ||
173 | { | ||
174 | //llwarns << "Could not find source avatar for pointat effect" << llendl; | ||
175 | return; | ||
176 | } | ||
177 | |||
178 | htonmemcpy(target_id.mData, &(packed_data[TARGET_OBJECT]), MVT_LLUUID, 16); | ||
179 | |||
180 | objp = gObjectList.findObject(target_id); | ||
181 | |||
182 | htonmemcpy(new_target.mdV, &(packed_data[TARGET_POS]), MVT_LLVector3d, 24); | ||
183 | |||
184 | if (objp) | ||
185 | { | ||
186 | setTargetObjectAndOffset(objp, new_target); | ||
187 | } | ||
188 | else if (target_id.isNull()) | ||
189 | { | ||
190 | setTargetPosGlobal(new_target); | ||
191 | } | ||
192 | |||
193 | U8 pointAtTypeUnpacked = 0; | ||
194 | htonmemcpy(&pointAtTypeUnpacked, &(packed_data[POINTAT_TYPE]), MVT_U8, 1); | ||
195 | mTargetType = (EPointAtType)pointAtTypeUnpacked; | ||
196 | |||
197 | // mKillTime = mTimer.getElapsedTimeF32() + mDuration; | ||
198 | update(); | ||
199 | } | ||
200 | |||
201 | //----------------------------------------------------------------------------- | ||
202 | // setTargetObjectAndOffset() | ||
203 | //----------------------------------------------------------------------------- | ||
204 | void LLHUDEffectPointAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset) | ||
205 | { | ||
206 | mTargetObject = objp; | ||
207 | mTargetOffsetGlobal = offset; | ||
208 | } | ||
209 | |||
210 | //----------------------------------------------------------------------------- | ||
211 | // setTargetPosGlobal() | ||
212 | //----------------------------------------------------------------------------- | ||
213 | void LLHUDEffectPointAt::setTargetPosGlobal(const LLVector3d &target_pos_global) | ||
214 | { | ||
215 | mTargetObject = NULL; | ||
216 | mTargetOffsetGlobal = target_pos_global; | ||
217 | } | ||
218 | |||
219 | //----------------------------------------------------------------------------- | ||
220 | // setPointAt() | ||
221 | // called by agent logic to set look at behavior locally, and propagate to sim | ||
222 | //----------------------------------------------------------------------------- | ||
223 | BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) | ||
224 | { | ||
225 | if (!mSourceObject) | ||
226 | { | ||
227 | return FALSE; | ||
228 | } | ||
229 | |||
230 | llassert(target_type < POINTAT_NUM_TARGETS); | ||
231 | |||
232 | // must be same or higher priority than existing effect | ||
233 | if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType]) | ||
234 | { | ||
235 | return FALSE; | ||
236 | } | ||
237 | |||
238 | F32 current_time = mTimer.getElapsedTimeF32(); | ||
239 | |||
240 | // type of pointat behavior or target object has changed | ||
241 | BOOL targetTypeChanged = (target_type != mTargetType) || | ||
242 | (object != mTargetObject); | ||
243 | |||
244 | BOOL targetPosChanged = (dist_vec(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE) && | ||
245 | ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)); | ||
246 | |||
247 | if (targetTypeChanged || targetPosChanged) | ||
248 | { | ||
249 | mLastSentOffsetGlobal = position; | ||
250 | setDuration(POINTAT_TIMEOUTS[target_type]); | ||
251 | setNeedsSendToSim(TRUE); | ||
252 | // llinfos << "Sending pointat data" << llendl; | ||
253 | } | ||
254 | |||
255 | if (target_type == POINTAT_TARGET_CLEAR) | ||
256 | { | ||
257 | clearPointAtTarget(); | ||
258 | } | ||
259 | else | ||
260 | { | ||
261 | mTargetType = target_type; | ||
262 | mTargetObject = object; | ||
263 | if (object) | ||
264 | { | ||
265 | mTargetOffsetGlobal.setVec(position); | ||
266 | } | ||
267 | else | ||
268 | { | ||
269 | mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); | ||
270 | } | ||
271 | |||
272 | mKillTime = mTimer.getElapsedTimeF32() + mDuration; | ||
273 | |||
274 | //set up requisite animation data | ||
275 | update(); | ||
276 | } | ||
277 | |||
278 | return TRUE; | ||
279 | } | ||
280 | |||
281 | //----------------------------------------------------------------------------- | ||
282 | // clearPointAtTarget() | ||
283 | //----------------------------------------------------------------------------- | ||
284 | void LLHUDEffectPointAt::clearPointAtTarget() | ||
285 | { | ||
286 | mTargetObject = NULL; | ||
287 | mTargetOffsetGlobal.clearVec(); | ||
288 | mTargetType = POINTAT_TARGET_NONE; | ||
289 | } | ||
290 | |||
291 | //----------------------------------------------------------------------------- | ||
292 | // markDead() | ||
293 | //----------------------------------------------------------------------------- | ||
294 | void LLHUDEffectPointAt::markDead() | ||
295 | { | ||
296 | if (!mSourceObject.isNull() && mSourceObject->isAvatar()) | ||
297 | { | ||
298 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint"); | ||
299 | } | ||
300 | |||
301 | clearPointAtTarget(); | ||
302 | LLHUDEffect::markDead(); | ||
303 | } | ||
304 | |||
305 | void LLHUDEffectPointAt::setSourceObject(LLViewerObject* objectp) | ||
306 | { | ||
307 | // restrict source objects to avatars | ||
308 | if (objectp && objectp->isAvatar()) | ||
309 | { | ||
310 | LLHUDEffect::setSourceObject(objectp); | ||
311 | } | ||
312 | } | ||
313 | |||
314 | //----------------------------------------------------------------------------- | ||
315 | // render() | ||
316 | //----------------------------------------------------------------------------- | ||
317 | void LLHUDEffectPointAt::render() | ||
318 | { | ||
319 | update(); | ||
320 | if (sDebugPointAt && mTargetType != POINTAT_TARGET_NONE) | ||
321 | { | ||
322 | LLGLSNoTexture gls_no_texture; | ||
323 | |||
324 | LLVector3 target = mTargetPos + mSourceObject->getRenderPosition(); | ||
325 | glPushMatrix(); | ||
326 | glTranslatef(target.mV[VX], target.mV[VY], target.mV[VZ]); | ||
327 | glScalef(0.3f, 0.3f, 0.3f); | ||
328 | glBegin(GL_LINES); | ||
329 | { | ||
330 | glColor3f(1.f, 0.f, 0.f); | ||
331 | glVertex3f(-1.f, 0.f, 0.f); | ||
332 | glVertex3f(1.f, 0.f, 0.f); | ||
333 | |||
334 | glVertex3f(0.f, -1.f, 0.f); | ||
335 | glVertex3f(0.f, 1.f, 0.f); | ||
336 | |||
337 | glVertex3f(0.f, 0.f, -1.f); | ||
338 | glVertex3f(0.f, 0.f, 1.f); | ||
339 | } glEnd(); | ||
340 | glPopMatrix(); | ||
341 | } | ||
342 | } | ||
343 | |||
344 | //----------------------------------------------------------------------------- | ||
345 | // update() | ||
346 | //----------------------------------------------------------------------------- | ||
347 | void LLHUDEffectPointAt::update() | ||
348 | { | ||
349 | // If the target object is dead, set the target object to NULL | ||
350 | if (!mTargetObject.isNull() && mTargetObject->isDead()) | ||
351 | { | ||
352 | clearPointAtTarget(); | ||
353 | } | ||
354 | |||
355 | if (mSourceObject.isNull() || mSourceObject->isDead()) | ||
356 | { | ||
357 | markDead(); | ||
358 | return; | ||
359 | } | ||
360 | |||
361 | F32 time = mTimer.getElapsedTimeF32(); | ||
362 | |||
363 | // clear out the effect if time is up | ||
364 | if (mKillTime != 0.f && time > mKillTime) | ||
365 | { | ||
366 | mTargetType = POINTAT_TARGET_NONE; | ||
367 | } | ||
368 | |||
369 | if (mSourceObject->isAvatar()) | ||
370 | { | ||
371 | if (mTargetType == POINTAT_TARGET_NONE) | ||
372 | { | ||
373 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->removeAnimationData("PointAtPoint"); | ||
374 | } | ||
375 | else | ||
376 | { | ||
377 | calcTargetPosition(); | ||
378 | |||
379 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->startMotion(ANIM_AGENT_EDITING); | ||
380 | } | ||
381 | } | ||
382 | } | ||
383 | |||
384 | //----------------------------------------------------------------------------- | ||
385 | // calcTargetPosition() | ||
386 | //----------------------------------------------------------------------------- | ||
387 | void LLHUDEffectPointAt::calcTargetPosition() | ||
388 | { | ||
389 | LLViewerObject *targetObject = (LLViewerObject *)mTargetObject; | ||
390 | LLVector3 local_offset; | ||
391 | |||
392 | if (targetObject) | ||
393 | { | ||
394 | local_offset.setVec(mTargetOffsetGlobal); | ||
395 | } | ||
396 | else | ||
397 | { | ||
398 | local_offset = gAgent.getPosAgentFromGlobal(mTargetOffsetGlobal); | ||
399 | } | ||
400 | |||
401 | if (targetObject && targetObject->mDrawable.notNull()) | ||
402 | { | ||
403 | LLQuaternion objRot; | ||
404 | if (targetObject->isAvatar()) | ||
405 | { | ||
406 | LLVOAvatar *avatarp = (LLVOAvatar *)targetObject; | ||
407 | mTargetPos = avatarp->mHeadp->getWorldPosition(); | ||
408 | objRot = avatarp->mPelvisp->getWorldRotation(); | ||
409 | } | ||
410 | else | ||
411 | { | ||
412 | if (targetObject->mDrawable->getGeneration() == -1) | ||
413 | { | ||
414 | mTargetPos = targetObject->getPositionAgent(); | ||
415 | objRot = targetObject->getWorldRotation(); | ||
416 | } | ||
417 | else | ||
418 | { | ||
419 | mTargetPos = targetObject->getRenderPosition(); | ||
420 | objRot = targetObject->getRenderRotation(); | ||
421 | } | ||
422 | } | ||
423 | |||
424 | mTargetPos += (local_offset * objRot); | ||
425 | } | ||
426 | else | ||
427 | { | ||
428 | mTargetPos = local_offset; | ||
429 | } | ||
430 | |||
431 | mTargetPos -= mSourceObject->getRenderPosition(); | ||
432 | |||
433 | if (mSourceObject->isAvatar()) | ||
434 | { | ||
435 | ((LLVOAvatar*)(LLViewerObject*)mSourceObject)->setAnimationData("PointAtPoint", (void *)&mTargetPos); | ||
436 | } | ||
437 | } | ||
438 | |||
439 | const LLVector3d LLHUDEffectPointAt::getPointAtPosGlobal() | ||
440 | { | ||
441 | LLVector3d global_pos; | ||
442 | global_pos.setVec(mTargetPos); | ||
443 | if (mSourceObject.notNull()) | ||
444 | { | ||
445 | global_pos += mSourceObject->getPositionGlobal(); | ||
446 | } | ||
447 | |||
448 | return global_pos; | ||
449 | } | ||