aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/linden/indra/newview/llhudeffectpointat.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/llhudeffectpointat.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 'linden/indra/newview/llhudeffectpointat.cpp')
-rw-r--r--linden/indra/newview/llhudeffectpointat.cpp449
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
41const S32 SOURCE_AVATAR = 0;
42const S32 TARGET_OBJECT = 16;
43const S32 TARGET_POS = 32;
44const S32 POINTAT_TYPE = 56;
45const S32 PKT_SIZE = 57;
46
47// throttle
48const F32 MAX_SENDS_PER_SEC = 4.f;
49
50const 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
54const F32 MAX_TIMEOUT = F32_MAX / 4.f;
55
56const 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
64const 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
74BOOL LLHUDEffectPointAt::sDebugPointAt;
75
76
77//-----------------------------------------------------------------------------
78// LLHUDEffectPointAt()
79//-----------------------------------------------------------------------------
80LLHUDEffectPointAt::LLHUDEffectPointAt(const U8 type) :
81 LLHUDEffect(type),
82 mKillTime(0.f),
83 mLastSendTime(0.f)
84{
85 clearPointAtTarget();
86}
87
88//-----------------------------------------------------------------------------
89// ~LLHUDEffectPointAt()
90//-----------------------------------------------------------------------------
91LLHUDEffectPointAt::~LLHUDEffectPointAt()
92{
93}
94
95//-----------------------------------------------------------------------------
96// packData()
97//-----------------------------------------------------------------------------
98void 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//-----------------------------------------------------------------------------
140void 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//-----------------------------------------------------------------------------
204void LLHUDEffectPointAt::setTargetObjectAndOffset(LLViewerObject *objp, LLVector3d offset)
205{
206 mTargetObject = objp;
207 mTargetOffsetGlobal = offset;
208}
209
210//-----------------------------------------------------------------------------
211// setTargetPosGlobal()
212//-----------------------------------------------------------------------------
213void 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//-----------------------------------------------------------------------------
223BOOL 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//-----------------------------------------------------------------------------
284void LLHUDEffectPointAt::clearPointAtTarget()
285{
286 mTargetObject = NULL;
287 mTargetOffsetGlobal.clearVec();
288 mTargetType = POINTAT_TARGET_NONE;
289}
290
291//-----------------------------------------------------------------------------
292// markDead()
293//-----------------------------------------------------------------------------
294void 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
305void 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//-----------------------------------------------------------------------------
317void 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//-----------------------------------------------------------------------------
347void 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//-----------------------------------------------------------------------------
387void 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
439const 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}