summaryrefslogtreecommitdiff
path: root/indra/newview/llhudicon.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'indra/newview/llhudicon.cpp')
-rw-r--r--indra/newview/llhudicon.cpp253
1 files changed, 253 insertions, 0 deletions
diff --git a/indra/newview/llhudicon.cpp b/indra/newview/llhudicon.cpp
new file mode 100644
index 0000000000..f2ab2dab11
--- /dev/null
+++ b/indra/newview/llhudicon.cpp
@@ -0,0 +1,253 @@
+/**
+ * @file llhudicon.cpp
+ * @brief LLHUDIcon class implementation
+ *
+ * Copyright (c) 2006-$CurrentYear$, Linden Research, Inc.
+ * $License$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llhudicon.h"
+
+#include "llgl.h"
+
+#include "llviewerobject.h"
+#include "lldrawable.h"
+#include "llviewercamera.h"
+#include "llviewerwindow.h"
+
+//-----------------------------------------------------------------------------
+// Local consts
+//-----------------------------------------------------------------------------
+const F32 ANIM_TIME = 0.4f;
+const F32 DIST_START_FADE = 15.f;
+const F32 DIST_END_FADE = 30.f;
+const F32 MAX_VISIBLE_TIME = 15.f;
+const F32 FADE_OUT_TIME = 1.f;
+
+//-----------------------------------------------------------------------------
+// Utility functions
+//-----------------------------------------------------------------------------
+static F32 calc_bouncy_animation(F32 x)
+{
+ return -(cosf(x * F_PI * 2.5f - F_PI_BY_TWO))*(0.4f + x * -0.1f) + x * 1.3f;
+}
+
+
+//-----------------------------------------------------------------------------
+// static declarations
+//-----------------------------------------------------------------------------
+LLHUDIcon::icon_instance_t LLHUDIcon::sIconInstances;
+
+LLHUDIcon::LLHUDIcon(const U8 type) :
+ LLHUDObject(type),
+ mImagep(NULL),
+ mPickID(0),
+ mScale(0.1f)
+{
+ sIconInstances.push_back(this);
+}
+
+LLHUDIcon::~LLHUDIcon()
+{
+ mImagep = NULL;
+}
+
+void LLHUDIcon::renderIcon(BOOL for_select)
+{
+ LLGLSUIDefault texture_state;
+ LLGLDepthTest gls_depth(GL_TRUE);
+ LLGLState no_texture(GL_TEXTURE_2D, for_select ? FALSE : TRUE);
+
+ if (mSourceObject.isNull() || mImagep.isNull())
+ {
+ markDead();
+ return;
+ }
+
+ LLVector3 obj_position = mSourceObject->getRenderPosition();
+
+ // put icon above object, and in front
+ // RN: don't use drawable radius, it's fricking HUGE
+ LLVector3 icon_relative_pos = (gCamera->getUpAxis() * ~mSourceObject->getRenderRotation());
+ icon_relative_pos.abs();
+
+ F32 distance_scale = llmin(mSourceObject->getScale().mV[VX] / icon_relative_pos.mV[VX],
+ mSourceObject->getScale().mV[VY] / icon_relative_pos.mV[VY],
+ mSourceObject->getScale().mV[VZ] / icon_relative_pos.mV[VZ]);
+ F32 up_distance = 0.5f * distance_scale;
+ LLVector3 icon_position = obj_position + (up_distance * gCamera->getUpAxis()) * 1.2f;
+
+ LLVector3 icon_to_cam = gCamera->getOrigin() - icon_position;
+ icon_to_cam.normVec();
+
+ icon_position += icon_to_cam * mSourceObject->mDrawable->getRadius() * 1.1f;
+
+ mDistance = dist_vec(icon_position, gCamera->getOrigin());
+
+ F32 alpha_factor = for_select ? 1.f : clamp_rescale(mDistance, DIST_START_FADE, DIST_END_FADE, 1.f, 0.f);
+
+ LLVector3 x_pixel_vec;
+ LLVector3 y_pixel_vec;
+
+ gCamera->getPixelVectors(icon_position, y_pixel_vec, x_pixel_vec);
+
+ F32 scale_factor = 1.f;
+ if (mAnimTimer.getElapsedTimeF32() < ANIM_TIME)
+ {
+ scale_factor = llmax(0.f, calc_bouncy_animation(mAnimTimer.getElapsedTimeF32() / ANIM_TIME));
+ }
+
+ F32 time_elapsed = mLifeTimer.getElapsedTimeF32();
+ if (time_elapsed > MAX_VISIBLE_TIME)
+ {
+ markDead();
+ return;
+ }
+
+ if (time_elapsed > MAX_VISIBLE_TIME - FADE_OUT_TIME)
+ {
+ alpha_factor *= clamp_rescale(time_elapsed, MAX_VISIBLE_TIME - FADE_OUT_TIME, MAX_VISIBLE_TIME, 1.f, 0.f);
+ }
+
+ F32 image_aspect = (F32)mImagep->mFullWidth / (F32)mImagep->mFullHeight;
+ LLVector3 x_scale = image_aspect * (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * x_pixel_vec;
+ LLVector3 y_scale = (F32)gViewerWindow->getWindowHeight() * mScale * scale_factor * y_pixel_vec;
+
+ LLVector3 lower_left = icon_position - (x_scale * 0.5f);
+ LLVector3 lower_right = icon_position + (x_scale * 0.5f);
+ LLVector3 upper_left = icon_position - (x_scale * 0.5f) + y_scale;
+ LLVector3 upper_right = icon_position + (x_scale * 0.5f) + y_scale;
+
+ if (for_select)
+ {
+ // set color to unique color id for picking
+ LLColor4U coloru((U8)(mPickID >> 16), (U8)(mPickID >> 8), (U8)mPickID);
+ glColor4ubv(coloru.mV);
+ }
+ else
+ {
+ LLColor4 icon_color = LLColor4::white;
+ icon_color.mV[VALPHA] = alpha_factor;
+ glColor4fv(icon_color.mV);
+ LLViewerImage::bindTexture(mImagep);
+ }
+
+ glBegin(GL_QUADS);
+ {
+ glTexCoord2f(0.f, 1.f);
+ glVertex3fv(upper_left.mV);
+ glTexCoord2f(0.f, 0.f);
+ glVertex3fv(lower_left.mV);
+ glTexCoord2f(1.f, 0.f);
+ glVertex3fv(lower_right.mV);
+ glTexCoord2f(1.f, 1.f);
+ glVertex3fv(upper_right.mV);
+ }
+ glEnd();
+}
+
+void LLHUDIcon::setImage(LLViewerImage* imagep)
+{
+ mImagep = imagep;
+ mImagep->setClamp(TRUE, TRUE);
+}
+
+void LLHUDIcon::setScale(F32 fraction_of_fov)
+{
+ mScale = fraction_of_fov;
+}
+
+void LLHUDIcon::markDead()
+{
+ if (mSourceObject)
+ {
+ mSourceObject->clearIcon();
+ }
+ LLHUDObject::markDead();
+}
+
+void LLHUDIcon::render()
+{
+ renderIcon(FALSE);
+}
+
+void LLHUDIcon::renderForSelect()
+{
+ renderIcon(TRUE);
+}
+
+
+//static
+S32 LLHUDIcon::generatePickIDs(S32 start_id, S32 step_size)
+{
+ S32 cur_id = start_id;
+ icon_instance_t::iterator icon_it;
+
+ for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
+ {
+ (*icon_it)->mPickID = cur_id;
+ cur_id += step_size;
+ }
+
+ return cur_id;
+}
+
+//static
+LLHUDIcon* LLHUDIcon::handlePick(S32 pick_id)
+{
+ icon_instance_t::iterator icon_it;
+
+ for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
+ {
+ if (pick_id == (*icon_it)->mPickID)
+ {
+ return *icon_it;
+ }
+ }
+
+ return NULL;
+}
+
+ //static
+void LLHUDIcon::updateAll()
+{
+ cleanupDeadIcons();
+}
+
+//static
+BOOL LLHUDIcon::iconsNearby()
+{
+ return !sIconInstances.empty();
+}
+
+//static
+void LLHUDIcon::cleanupDeadIcons()
+{
+ icon_instance_t::iterator icon_it;
+
+ icon_instance_t icons_to_erase;
+ for(icon_it = sIconInstances.begin(); icon_it != sIconInstances.end(); ++icon_it)
+ {
+ if ((*icon_it)->mDead)
+ {
+ icons_to_erase.push_back(*icon_it);
+ }
+ }
+
+ for(icon_it = icons_to_erase.begin(); icon_it != icons_to_erase.end(); ++icon_it)
+ {
+ icon_instance_t::iterator found_it = std::find(sIconInstances.begin(), sIconInstances.end(), *icon_it);
+ if (found_it != sIconInstances.end())
+ {
+ sIconInstances.erase(found_it);
+ }
+ }
+}
+
+//static
+S32 LLHUDIcon::getNumInstances()
+{
+ return (S32)sIconInstances.size();
+}