PageRenderTime 43ms CodeModel.GetById 10ms app.highlight 28ms RepoModel.GetById 2ms app.codeStats 0ms

/indra/newview/llviewerjointattachment.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 449 lines | 338 code | 42 blank | 69 comment | 69 complexity | b7ba1faacc865a974da5040b691c7dba MD5 | raw file
  1/** 
  2 * @file llviewerjointattachment.cpp
  3 * @brief Implementation of LLViewerJointAttachment class
  4 *
  5 * $LicenseInfo:firstyear=2002&license=viewerlgpl$
  6 * Second Life Viewer Source Code
  7 * Copyright (C) 2010, Linden Research, Inc.
  8 * 
  9 * This library is free software; you can redistribute it and/or
 10 * modify it under the terms of the GNU Lesser General Public
 11 * License as published by the Free Software Foundation;
 12 * version 2.1 of the License only.
 13 * 
 14 * This library is distributed in the hope that it will be useful,
 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 17 * Lesser General Public License for more details.
 18 * 
 19 * You should have received a copy of the GNU Lesser General Public
 20 * License along with this library; if not, write to the Free Software
 21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 22 * 
 23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
 24 * $/LicenseInfo$
 25 */
 26
 27#include "llviewerprecompiledheaders.h"
 28
 29#include "llviewerjointattachment.h"
 30
 31#include "llagentconstants.h"
 32#include "llviewercontrol.h"
 33#include "lldrawable.h"
 34#include "llgl.h"
 35#include "llhudtext.h"
 36#include "llrender.h"
 37#include "llvoavatarself.h"
 38#include "llvolume.h"
 39#include "pipeline.h"
 40#include "llspatialpartition.h"
 41#include "llinventorymodel.h"
 42#include "llviewerobjectlist.h"
 43#include "llface.h"
 44#include "llvoavatar.h"
 45
 46#include "llglheaders.h"
 47
 48extern LLPipeline gPipeline;
 49
 50//-----------------------------------------------------------------------------
 51// LLViewerJointAttachment()
 52//-----------------------------------------------------------------------------
 53LLViewerJointAttachment::LLViewerJointAttachment() :
 54	mVisibleInFirst(FALSE),
 55	mGroup(0),
 56	mIsHUDAttachment(FALSE),
 57	mPieSlice(-1)
 58{
 59	mValid = FALSE;
 60	mUpdateXform = FALSE;
 61	mAttachedObjects.clear();
 62}
 63
 64//-----------------------------------------------------------------------------
 65// ~LLViewerJointAttachment()
 66//-----------------------------------------------------------------------------
 67LLViewerJointAttachment::~LLViewerJointAttachment()
 68{
 69}
 70
 71//-----------------------------------------------------------------------------
 72// isTransparent()
 73//-----------------------------------------------------------------------------
 74BOOL LLViewerJointAttachment::isTransparent()
 75{
 76	return FALSE;
 77}
 78
 79//-----------------------------------------------------------------------------
 80// drawShape()
 81//-----------------------------------------------------------------------------
 82U32 LLViewerJointAttachment::drawShape( F32 pixelArea, BOOL first_pass, BOOL is_dummy )
 83{
 84	if (LLVOAvatar::sShowAttachmentPoints)
 85	{
 86		LLGLDisable cull_face(GL_CULL_FACE);
 87		
 88		gGL.color4f(1.f, 1.f, 1.f, 1.f);
 89		gGL.begin(LLRender::QUADS);
 90		{
 91			gGL.vertex3f(-0.1f, 0.1f, 0.f);
 92			gGL.vertex3f(-0.1f, -0.1f, 0.f);
 93			gGL.vertex3f(0.1f, -0.1f, 0.f);
 94			gGL.vertex3f(0.1f, 0.1f, 0.f);
 95		}gGL.end();
 96	}
 97	return 0;
 98}
 99
100void LLViewerJointAttachment::setupDrawable(LLViewerObject *object)
101{
102	if (!object->mDrawable)
103		return;
104	if (object->mDrawable->isActive())
105	{
106		object->mDrawable->makeStatic(FALSE);
107	}
108
109	object->mDrawable->mXform.setParent(getXform()); // LLViewerJointAttachment::lazyAttach
110	object->mDrawable->makeActive();
111	LLVector3 current_pos = object->getRenderPosition();
112	LLQuaternion current_rot = object->getRenderRotation();
113	LLQuaternion attachment_pt_inv_rot = ~(getWorldRotation());
114
115	current_pos -= getWorldPosition();
116	current_pos.rotVec(attachment_pt_inv_rot);
117
118	current_rot = current_rot * attachment_pt_inv_rot;
119
120	object->mDrawable->mXform.setPosition(current_pos);
121	object->mDrawable->mXform.setRotation(current_rot);
122	gPipeline.markMoved(object->mDrawable);
123	gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD
124	object->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
125	
126	if(mIsHUDAttachment)
127	{
128		for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)
129		{
130			object->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER);
131		}
132	}
133
134	LLViewerObject::const_child_list_t& child_list = object->getChildren();
135	for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
136		 iter != child_list.end(); ++iter)
137	{
138		LLViewerObject* childp = *iter;
139		if (childp && childp->mDrawable.notNull())
140		{
141			childp->mDrawable->setState(LLDrawable::USE_BACKLIGHT);
142			gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD
143			gPipeline.markMoved(childp->mDrawable);
144
145			if(mIsHUDAttachment)
146			{
147				for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++)
148				{
149					childp->mDrawable->getFace(face_num)->setState(LLFace::HUD_RENDER);
150				}
151			}
152		}
153	}
154}
155
156//-----------------------------------------------------------------------------
157// addObject()
158//-----------------------------------------------------------------------------
159BOOL LLViewerJointAttachment::addObject(LLViewerObject* object)
160{
161	object->extractAttachmentItemID();
162
163	// Same object reattached
164	if (isObjectAttached(object))
165	{
166		llinfos << "(same object re-attached)" << llendl;
167		removeObject(object);
168		// Pass through anyway to let setupDrawable()
169		// re-connect object to the joint correctly
170	}
171	
172	// Two instances of the same inventory item attached --
173	// Request detach, and kill the object in the meantime.
174	if (getAttachedObject(object->getAttachmentItemID()))
175	{
176		llinfos << "(same object re-attached)" << llendl;
177		object->markDead();
178
179		// If this happens to be attached to self, then detach.
180		LLVOAvatarSelf::detachAttachmentIntoInventory(object->getAttachmentItemID());
181		return FALSE;
182	}
183
184	mAttachedObjects.push_back(object);
185	setupDrawable(object);
186	
187	if (mIsHUDAttachment)
188	{
189		if (object->mText.notNull())
190		{
191			object->mText->setOnHUDAttachment(TRUE);
192		}
193		LLViewerObject::const_child_list_t& child_list = object->getChildren();
194		for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
195			 iter != child_list.end(); ++iter)
196		{
197			LLViewerObject* childp = *iter;
198			if (childp && childp->mText.notNull())
199			{
200				childp->mText->setOnHUDAttachment(TRUE);
201			}
202		}
203	}
204	calcLOD();
205	mUpdateXform = TRUE;
206	
207	return TRUE;
208}
209
210//-----------------------------------------------------------------------------
211// removeObject()
212//-----------------------------------------------------------------------------
213void LLViewerJointAttachment::removeObject(LLViewerObject *object)
214{
215	attachedobjs_vec_t::iterator iter;
216	for (iter = mAttachedObjects.begin();
217		 iter != mAttachedObjects.end();
218		 ++iter)
219	{
220		LLViewerObject *attached_object = (*iter);
221		if (attached_object == object)
222		{
223			break;
224		}
225	}
226	if (iter == mAttachedObjects.end())
227	{
228		llwarns << "Could not find object to detach" << llendl;
229		return;
230	}
231
232	// force object visibile
233	setAttachmentVisibility(TRUE);
234
235	mAttachedObjects.erase(iter);
236	if (object->mDrawable.notNull())
237	{
238		//if object is active, make it static
239		if(object->mDrawable->isActive())
240		{
241			object->mDrawable->makeStatic(FALSE);
242		}
243
244		LLVector3 cur_position = object->getRenderPosition();
245		LLQuaternion cur_rotation = object->getRenderRotation();
246
247		object->mDrawable->mXform.setPosition(cur_position);
248		object->mDrawable->mXform.setRotation(cur_rotation);
249		gPipeline.markMoved(object->mDrawable, TRUE);
250		gPipeline.markTextured(object->mDrawable); // face may need to change draw pool to/from POOL_HUD
251		object->mDrawable->clearState(LLDrawable::USE_BACKLIGHT);
252
253		if (mIsHUDAttachment)
254		{
255			for (S32 face_num = 0; face_num < object->mDrawable->getNumFaces(); face_num++)
256			{
257				object->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER);
258			}
259		}
260	}
261
262	LLViewerObject::const_child_list_t& child_list = object->getChildren();
263	for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
264		 iter != child_list.end(); ++iter)
265	{
266		LLViewerObject* childp = *iter;
267		if (childp && childp->mDrawable.notNull())
268		{
269			childp->mDrawable->clearState(LLDrawable::USE_BACKLIGHT);
270			gPipeline.markTextured(childp->mDrawable); // face may need to change draw pool to/from POOL_HUD
271			if (mIsHUDAttachment)
272			{
273				for (S32 face_num = 0; face_num < childp->mDrawable->getNumFaces(); face_num++)
274				{
275					childp->mDrawable->getFace(face_num)->clearState(LLFace::HUD_RENDER);
276				}
277			}
278		}
279	} 
280
281	if (mIsHUDAttachment)
282	{
283		if (object->mText.notNull())
284		{
285			object->mText->setOnHUDAttachment(FALSE);
286		}
287		LLViewerObject::const_child_list_t& child_list = object->getChildren();
288		for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
289			 iter != child_list.end(); ++iter)
290		{
291			LLViewerObject* childp = *iter;
292			if (childp->mText.notNull())
293			{
294				childp->mText->setOnHUDAttachment(FALSE);
295			}
296		}
297	}
298	if (mAttachedObjects.size() == 0)
299	{
300		mUpdateXform = FALSE;
301	}
302	object->setAttachmentItemID(LLUUID::null);
303}
304
305//-----------------------------------------------------------------------------
306// setAttachmentVisibility()
307//-----------------------------------------------------------------------------
308void LLViewerJointAttachment::setAttachmentVisibility(BOOL visible)
309{
310	for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
311		 iter != mAttachedObjects.end();
312		 ++iter)
313	{
314		LLViewerObject *attached_obj = (*iter);
315		if (!attached_obj || attached_obj->mDrawable.isNull() || 
316			!(attached_obj->mDrawable->getSpatialBridge()))
317			continue;
318		
319		if (visible)
320		{
321			// Hack to make attachments not visible by disabling their type mask!
322			// This will break if you can ever attach non-volumes! - djs 02/14/03
323			attached_obj->mDrawable->getSpatialBridge()->mDrawableType = 
324				attached_obj->isHUDAttachment() ? LLPipeline::RENDER_TYPE_HUD : LLPipeline::RENDER_TYPE_VOLUME;
325		}
326		else
327		{
328			attached_obj->mDrawable->getSpatialBridge()->mDrawableType = 0;
329		}
330	}
331}
332
333//-----------------------------------------------------------------------------
334// setOriginalPosition()
335//-----------------------------------------------------------------------------
336void LLViewerJointAttachment::setOriginalPosition(LLVector3& position)
337{
338	mOriginalPos = position;
339	setPosition(position);
340}
341
342//-----------------------------------------------------------------------------
343// clampObjectPosition()
344//-----------------------------------------------------------------------------
345void LLViewerJointAttachment::clampObjectPosition()
346{
347	for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
348		 iter != mAttachedObjects.end();
349		 ++iter)
350	{
351		if (LLViewerObject *attached_object = (*iter))
352		{
353			// *NOTE: object can drift when hitting maximum radius
354			LLVector3 attachmentPos = attached_object->getPosition();
355			F32 dist = attachmentPos.normVec();
356			dist = llmin(dist, MAX_ATTACHMENT_DIST);
357			attachmentPos *= dist;
358			attached_object->setPosition(attachmentPos);
359		}
360	}
361}
362
363//-----------------------------------------------------------------------------
364// calcLOD()
365//-----------------------------------------------------------------------------
366void LLViewerJointAttachment::calcLOD()
367{
368	F32 maxarea = 0;
369	for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
370		 iter != mAttachedObjects.end();
371		 ++iter)
372	{
373		if (LLViewerObject *attached_object = (*iter))
374		{
375			maxarea = llmax(maxarea,attached_object->getMaxScale() * attached_object->getMidScale());
376			LLViewerObject::const_child_list_t& child_list = attached_object->getChildren();
377			for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin();
378				 iter != child_list.end(); ++iter)
379			{
380				LLViewerObject* childp = *iter;
381				F32 area = childp->getMaxScale() * childp->getMidScale();
382				maxarea = llmax(maxarea, area);
383			}
384		}
385	}
386	maxarea = llclamp(maxarea, .01f*.01f, 1.f);
387	F32 avatar_area = (4.f * 4.f); // pixels for an avatar sized attachment
388	F32 min_pixel_area = avatar_area / maxarea;
389	setLOD(min_pixel_area);
390}
391
392//-----------------------------------------------------------------------------
393// updateLOD()
394//-----------------------------------------------------------------------------
395BOOL LLViewerJointAttachment::updateLOD(F32 pixel_area, BOOL activate)
396{
397	BOOL res = FALSE;
398	if (!mValid)
399	{
400		setValid(TRUE, TRUE);
401		res = TRUE;
402	}
403	return res;
404}
405
406BOOL LLViewerJointAttachment::isObjectAttached(const LLViewerObject *viewer_object) const
407{
408	for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
409		 iter != mAttachedObjects.end();
410		 ++iter)
411	{
412		const LLViewerObject* attached_object = (*iter);
413		if (attached_object == viewer_object)
414		{
415			return TRUE;
416		}
417	}
418	return FALSE;
419}
420
421const LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id) const
422{
423	for (attachedobjs_vec_t::const_iterator iter = mAttachedObjects.begin();
424		 iter != mAttachedObjects.end();
425		 ++iter)
426	{
427		const LLViewerObject* attached_object = (*iter);
428		if (attached_object->getAttachmentItemID() == object_id)
429		{
430			return attached_object;
431		}
432	}
433	return NULL;
434}
435
436LLViewerObject *LLViewerJointAttachment::getAttachedObject(const LLUUID &object_id)
437{
438	for (attachedobjs_vec_t::iterator iter = mAttachedObjects.begin();
439		 iter != mAttachedObjects.end();
440		 ++iter)
441	{
442		LLViewerObject* attached_object = (*iter);
443		if (attached_object->getAttachmentItemID() == object_id)
444		{
445			return attached_object;
446		}
447	}
448	return NULL;
449}