void LLLocalSpeakerMgr::updateSpeakerList() { // pull speakers from voice channel LLSpeakerMgr::updateSpeakerList(); if (gDisconnected)//the world is cleared. { return ; } // pick up non-voice speakers in chat range uuid_vec_t avatar_ids; std::vector<LLVector3d> positions; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgent.getPositionGlobal(), CHAT_NORMAL_RADIUS); for(U32 i=0; i<avatar_ids.size(); i++) { setSpeaker(avatar_ids[i]); } // check if text only speakers have moved out of chat range for (speaker_map_t::iterator speaker_it = mSpeakers.begin(); speaker_it != mSpeakers.end(); ++speaker_it) { LLUUID speaker_id = speaker_it->first; LLSpeaker* speakerp = speaker_it->second; if (speakerp->mStatus == LLSpeaker::STATUS_TEXT_ONLY) { LLVOAvatar* avatarp = (LLVOAvatar*)gObjectList.findObject(speaker_id); if (!avatarp || dist_vec_squared(avatarp->getPositionAgent(), gAgent.getPositionAgent()) > CHAT_NORMAL_RADIUS_SQUARED) { setSpeakerNotInChannel(speakerp); } } } }
//----------------------------------------------------------------------------- // setLookAt() // called by agent logic to set look at behavior locally, and propagate to sim //----------------------------------------------------------------------------- BOOL LLHUDEffectLookAt::setLookAt(ELookAtType target_type, LLViewerObject *object, LLVector3 position) { if (!mSourceObject) { return FALSE; } if (target_type >= LOOKAT_NUM_TARGETS) { llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl; return FALSE; } // must be same or higher priority than existing effect if ((*mAttentions)[target_type].mPriority < (*mAttentions)[mTargetType].mPriority) { return FALSE; } F32 current_time = mTimer.getElapsedTimeF32(); // type of lookat behavior or target object has changed BOOL lookAtChanged = (target_type != mTargetType) || (object != mTargetObject); // lookat position has moved a certain amount and we haven't just sent an update lookAtChanged = lookAtChanged || ((dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC))); if (lookAtChanged) { mLastSentOffsetGlobal = position; F32 timeout = (*mAttentions)[target_type].mTimeout; setDuration(timeout); setNeedsSendToSim(TRUE); } if (target_type == LOOKAT_TARGET_CLEAR) { clearLookAtTarget(); } else { mTargetType = target_type; mTargetObject = object; if (object) { mTargetOffsetGlobal.setVec(position); } else { mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); } mKillTime = mTimer.getElapsedTimeF32() + mDuration; update(); } return TRUE; }
BOOL LLToolGrab::handleHover(S32 x, S32 y, MASK mask) { if (!gViewerWindow->getLeftMouseDown()) { gViewerWindow->setCursor(UI_CURSOR_TOOLGRAB); setMouseCapture(FALSE); return TRUE; } // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Added: RLVa-0.2.0f // Don't allow dragging beyond 1.5m under @fartouch=n LLViewerObject* pObj; if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (GRAB_INACTIVE != mMode) && (hasMouseCapture()) && ((pObj = mGrabPick.getObject()) != NULL) && (!pObj->isDead()) && (!pObj->isHUDAttachment()) && (dist_vec_squared(gAgent.getPositionAgent(), pObj->getPositionRegion() + mGrabPick.mObjectOffset) > 1.5f * 1.5f) ) { if (gGrabTransientTool) { // Prevent the grab tool from popping up as soon as we kill the drag operation gBasicToolset->selectTool(gGrabTransientTool); gGrabTransientTool = NULL; } setMouseCapture(FALSE); } // [/RLVa:KB] // Do the right hover based on mode switch( mMode ) { case GRAB_ACTIVE_CENTER: handleHoverActive( x, y, mask ); // cursor hidden break; case GRAB_NONPHYSICAL: handleHoverNonPhysical(x, y, mask); break; case GRAB_INACTIVE: handleHoverInactive( x, y, mask ); // cursor set here break; case GRAB_NOOBJECT: case GRAB_LOCKED: handleHoverFailed( x, y, mask ); break; } mLastMouseX = x; mLastMouseY = y; return TRUE; }
void v4math_object::test<19>() { F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; F32 val1,val2; LLVector4 vec4(x1,y1,z1),vec4a(x2,y2,z2); val1 = dist_vec(vec4,vec4a); val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec4,vec4a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("dist_vec_squared: Fail ",val2, val1); }
void v3math_object::test<31>() { F32 x1 =-2.3f, y1 = 2.f,z1 = 1.2f, x2 = 1.3f, y2 = 1.f, z2 = 1.f; F32 val1,val2; LLVector3 vec3(x1,y1,z1),vec3a(x2,y2,z2); val1 = dist_vec(vec3,vec3a); val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("1:dist_vec: Fail ",val2, val1); val1 = dist_vec_squared(vec3,vec3a); val2 =((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2) + (z1 - z2)* (z1 -z2)); ensure_equals("2:dist_vec_squared: Fail ",val2, val1); val1 = dist_vec_squared2D(vec3, vec3a); val2 =(x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); ensure_equals("3:dist_vec_squared2D: Fail ",val2, val1); }
void v2math_object::test<21>() { F32 x1 =1.f, y1 = 2.f, x2 = -.32f, y2 = .2234f; F32 val1, val2; LLVector2 vec2(x1, y1),vec3(x2, y2); val1 = dist_vec_squared2D(vec2, vec3); val2 = (x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2); ensure_equals("dist_vec_squared2D values are not equal",val2, val1); val1 = dist_vec_squared(vec2, vec3); ensure_equals("dist_vec_squared values are not equal",val2, val1); val1 = dist_vec(vec2, vec3); val2 = fsqrtf((x1 - x2)*(x1 - x2) + (y1 - y2)* (y1 - y2)); ensure_equals("dist_vec values are not equal",val2, val1); }
void LLToolFace::pickCallback(const LLPickInfo& pick_info) { LLViewerObject* hit_obj = pick_info.getObject(); if (hit_obj) { S32 hit_face = pick_info.mObjectFace; if (hit_obj->isAvatar()) { // ...clicked on an avatar, so don't do anything return; } // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f if ( (rlv_handler_t::isEnabled()) && ( (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) || ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!hit_obj->isAttachment()) || (!hit_obj->permYouOwner())) && (dist_vec_squared(gAgent.getPositionAgent(), hit_obj->getPositionRegion() + pick_info.mObjectOffset) > 1.5f * 1.5f) ))) { return; } // [/RLVa:KB] // ...clicked on a world object, try to pick the appropriate face if (pick_info.mKeyMask & MASK_SHIFT) { // If object not selected, need to inform sim if ( !hit_obj->isSelected() ) { // object wasn't selected so add the object and face LLSelectMgr::getInstance()->selectObjectOnly(hit_obj, hit_face); } else if (!LLSelectMgr::getInstance()->getSelection()->contains(hit_obj, hit_face) ) { // object is selected, but not this face, so add it. LLSelectMgr::getInstance()->addAsIndividual(hit_obj, hit_face); } else { // object is selected, as is this face, so remove the face. LLSelectMgr::getInstance()->remove(hit_obj, hit_face); // BUG: If you remove the last face, the simulator won't know about it. } } else { // clicked without modifiers, select only // this face LLSelectMgr::getInstance()->deselectAll(); LLSelectMgr::getInstance()->selectObjectOnly(hit_obj, hit_face); } } else { if (!(pick_info.mKeyMask == MASK_SHIFT)) { LLSelectMgr::getInstance()->deselectAll(); } } }
// Returns true if you got at least one object void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) { // [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Modified: RLVa-1.3.0c // Block rectangle selection if: // - prevented from editing and no exceptions are set (see below for the case where exceptions are set) // - prevented from interacting at all if ( (rlv_handler_t::isEnabled()) && ( ((gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) && (!gRlvHandler.hasException(RLV_BHVR_EDIT))) || (gRlvHandler.hasBehaviour(RLV_BHVR_INTERACT)) ) ) { return; } // [/RLVa:KB] LLVector3 av_pos = gAgent.getPositionAgent(); F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance"); select_dist_squared = select_dist_squared * select_dist_squared; BOOL deselect = (mask == MASK_CONTROL); S32 left = llmin(x, mDragStartX); S32 right = llmax(x, mDragStartX); S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); left = llround((F32) left * LLUI::getScaleFactor().mV[VX]); right = llround((F32) right * LLUI::getScaleFactor().mV[VX]); top = llround((F32) top * LLUI::getScaleFactor().mV[VY]); bottom = llround((F32) bottom * LLUI::getScaleFactor().mV[VY]); F32 old_far_plane = LLViewerCamera::getInstance()->getFar(); F32 old_near_plane = LLViewerCamera::getInstance()->getNear(); S32 width = right - left + 1; S32 height = top - bottom + 1; BOOL grow_selection = FALSE; BOOL shrink_selection = FALSE; if (height > mDragLastHeight || width > mDragLastWidth) { grow_selection = TRUE; } if (height < mDragLastHeight || width < mDragLastWidth) { shrink_selection = TRUE; } if (!grow_selection && !shrink_selection) { // nothing to do return; } mDragLastHeight = height; mDragLastWidth = width; S32 center_x = (left + right) / 2; S32 center_y = (top + bottom) / 2; // save drawing mode gGL.matrixMode(LLRender::MM_PROJECTION); gGL.pushMatrix(); BOOL limit_select_distance = gSavedSettings.getBOOL("LimitSelectDistance"); if (limit_select_distance) { // ...select distance from control LLVector3 relative_av_pos = av_pos; relative_av_pos -= LLViewerCamera::getInstance()->getOrigin(); F32 new_far = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() + gSavedSettings.getF32("MaxSelectDistance"); F32 new_near = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() - gSavedSettings.getF32("MaxSelectDistance"); new_near = llmax(new_near, 0.1f); LLViewerCamera::getInstance()->setFar(new_far); LLViewerCamera::getInstance()->setNear(new_near); } // [RLVa:KB] - Checked: 2010-04-11 (RLVa-1.2.0e) | Modified: RLVa-1.0.0g if (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) { // We'll allow drag selection under fartouch, but only within the fartouch range // (just copy/paste the code above us to make that work, thank you Lindens!) LLVector3 relative_av_pos = av_pos; relative_av_pos -= LLViewerCamera::getInstance()->getOrigin(); F32 new_far = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() + 1.5f; F32 new_near = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() - 1.5f; new_near = llmax(new_near, 0.1f); LLViewerCamera::getInstance()->setFar(new_far); LLViewerCamera::getInstance()->setNear(new_near); // Usurp these two limit_select_distance = TRUE; select_dist_squared = 1.5f * 1.5f; } // [/RLVa:KB] LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, center_x-width/2, center_y-height/2, width, height, limit_select_distance); if (shrink_selection) { struct f : public LLSelectedObjectFunctor { virtual bool apply(LLViewerObject* vobjp) { LLDrawable* drawable = vobjp->mDrawable; if (!drawable || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment()) { return true; } S32 result = LLViewerCamera::getInstance()->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); switch (result) { case 0: LLSelectMgr::getInstance()->unhighlightObjectOnly(vobjp); break; case 1: // check vertices if (!LLViewerCamera::getInstance()->areVertsVisible(vobjp, LLSelectMgr::sRectSelectInclusive)) { LLSelectMgr::getInstance()->unhighlightObjectOnly(vobjp); } break; default: break; } return true; } } func; LLSelectMgr::getInstance()->getHighlightedObjects()->applyToObjects(&func); } if (grow_selection) { std::vector<LLDrawable*> potentials; for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { part->cull(*LLViewerCamera::getInstance(), &potentials, TRUE); } } } for (std::vector<LLDrawable*>::iterator iter = potentials.begin(); iter != potentials.end(); iter++) { LLDrawable* drawable = *iter; LLViewerObject* vobjp = drawable->getVObj(); if (!drawable || !vobjp || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment() || (deselect && !vobjp->isSelected())) { continue; } if (limit_select_distance && dist_vec_squared(drawable->getWorldPosition(), av_pos) > select_dist_squared) { continue; } // [RLVa:KB] - Checked: 2010-11-29 (RLVa-1.3.0c) | Added: RLVa-1.3.0c if ( (rlv_handler_t::isEnabled()) && (!gRlvHandler.canEdit(vobjp)) ) { continue; } // [/RLVa:KB] S32 result = LLViewerCamera::getInstance()->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); if (result) { switch (result) { case 1: // check vertices if (LLViewerCamera::getInstance()->areVertsVisible(vobjp, LLSelectMgr::sRectSelectInclusive)) { LLSelectMgr::getInstance()->highlightObjectOnly(vobjp); } break; case 2: LLSelectMgr::getInstance()->highlightObjectOnly(vobjp); break; default: break; } } } } // restore drawing mode gGL.matrixMode(LLRender::MM_PROJECTION); gGL.popMatrix(); gGL.matrixMode(LLRender::MM_MODELVIEW); // restore camera LLViewerCamera::getInstance()->setFar(old_far_plane); LLViewerCamera::getInstance()->setNear(old_near_plane); gViewerWindow->setup3DRender(); }
BOOL LLToolGrab::handleObjectHit(const LLPickInfo& info) { mGrabPick = info; LLViewerObject* objectp = mGrabPick.getObject(); if (gDebugClicks) { llinfos << "LLToolGrab handleObjectHit " << info.mMousePt.mX << "," << info.mMousePt.mY << llendl; } if (NULL == objectp) // unexpected { llwarns << "objectp was NULL; returning FALSE" << llendl; return FALSE; } //if (objectp->isAvatar()) // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f if ( (objectp->isAvatar()) || ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && ((!objectp->isAttachment()) || (!objectp->permYouOwner())) && (dist_vec_squared(gAgent.getPositionAgent(), mGrabPick.mIntersection) > 1.5f * 1.5f) ) ) // [/RLVa:KB] { if (gGrabTransientTool) { gBasicToolset->selectTool( gGrabTransientTool ); gGrabTransientTool = NULL; } return TRUE; } setMouseCapture( TRUE ); // Grabs always start from the root // objectp = (LLViewerObject *)objectp->getRoot(); LLViewerObject* parent = objectp->getRootEdit(); BOOL script_touch = (objectp->flagHandleTouch()) || (parent && parent->flagHandleTouch()); // Clicks on scripted or physical objects are temporary grabs, so // not "Build mode" mHideBuildHighlight = script_touch || objectp->usePhysics(); if (!objectp->usePhysics()) { // In mouselook, we shouldn't be able to grab non-physical, // non-touchable objects. If it has a touch handler, we // do grab it (so llDetectedGrab works), but movement is // blocked on the server side. JC if (gAgent.cameraMouselook() && !script_touch) { mMode = GRAB_LOCKED; gViewerWindow->hideCursor(); gViewerWindow->moveCursorToCenter(); } else { mMode = GRAB_NONPHYSICAL; } // Don't bail out here, go on and grab so buttons can get // their "touched" event. } else if( !objectp->permMove() ) { // if mouse is over a physical object without move permission, show feedback if user tries to move it. mMode = GRAB_LOCKED; // Don't bail out here, go on and grab so buttons can get // their "touched" event. } else { // if mouse is over a physical object with move permission, // select it and enter "grab" mode (hiding cursor, etc.) mMode = GRAB_ACTIVE_CENTER; gViewerWindow->hideCursor(); gViewerWindow->moveCursorToCenter(); } // Always send "touched" message mLastMouseX = gViewerWindow->getCurrentMouseX(); mLastMouseY = gViewerWindow->getCurrentMouseY(); mAccumDeltaX = 0; mAccumDeltaY = 0; mHasMoved = FALSE; mOutsideSlop = FALSE; mVerticalDragging = (info.mKeyMask == MASK_VERTICAL) || gGrabBtnVertical; startGrab(); if ((info.mKeyMask == MASK_SPIN) || gGrabBtnSpin) { startSpin(); } LLSelectMgr::getInstance()->updateSelectionCenter(); // update selection beam // update point at LLViewerObject *edit_object = info.getObject(); if (edit_object && info.mPickType != LLPickInfo::PICK_FLORA) { LLVector3 local_edit_point = gAgent.getPosAgentFromGlobal(info.mPosGlobal); local_edit_point -= edit_object->getPositionAgent(); local_edit_point = local_edit_point * ~edit_object->getRenderRotation(); gAgent.setPointAt(POINTAT_TARGET_GRAB, edit_object, local_edit_point ); gAgent.setLookAt(LOOKAT_TARGET_SELECT, edit_object, local_edit_point ); } // on transient grabs (clicks on world objects), kill the grab immediately if (!gViewerWindow->getLeftMouseDown() && gGrabTransientTool && (mMode == GRAB_NONPHYSICAL || mMode == GRAB_LOCKED)) { gBasicToolset->selectTool( gGrabTransientTool ); gGrabTransientTool = NULL; } return TRUE; }
// static LLObjectSelectionHandle LLToolSelect::handleObjectSelection(const LLPickInfo& pick, BOOL ignore_group, BOOL temp_select, BOOL select_root) { LLViewerObject* object = pick.getObject(); if (select_root) { object = object->getRootEdit(); } // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f if (rlv_handler_t::isEnabled()) { if (gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) { if (!temp_select) { return LLSelectMgr::getInstance()->getSelection(); } else { // Temporary selection, but if the build floater is open then it'll be permanent so get rid of the floater if (gFloaterTools->getVisible()) { // Copy/paste from toggle_build_mode() gAgent.resetView(false); gFloaterTools->close(); gViewerWindow->showCursor(); } } } if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (object) && ((!object->isAttachment()) || (!object->permYouOwner())) && (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion()) > 1.5f * 1.5f) ) { // NOTE-RLVa: see behaviour notes for a rather lengthy explanation of why we're doing things this way //if (dist_vec_squared(gAgent.getPositionAgent(), object->getPositionRegion() + pick.mObjectOffset) > 1.5f * 1.5f) if (dist_vec_squared(gAgent.getPositionAgent(), pick.mIntersection) > 1.5f * 1.5f) { if ( (gFloaterTools->getVisible()) && (pick.mKeyMask != MASK_SHIFT) && (pick.mKeyMask != MASK_CONTROL) ) LLSelectMgr::getInstance()->deselectAll(); return LLSelectMgr::getInstance()->getSelection(); } else if (gFloaterTools->getVisible()) { // Copy/paste from toggle_build_mode() gAgent.resetView(false); gFloaterTools->close(); gViewerWindow->showCursor(); } } } // [/RLVa:KB] BOOL select_owned = gSavedSettings.getBOOL("SelectOwnedOnly"); BOOL select_movable = gSavedSettings.getBOOL("SelectMovableOnly"); BOOL select_region = gSavedSettings.getBOOL("SelectThisRegionOnly"); // *NOTE: These settings must be cleaned up at bottom of function. if (temp_select || gAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", FALSE); gSavedSettings.setBOOL("SelectMovableOnly", FALSE); gSavedSettings.setBOOL("SelectThisRegionOnly", TRUE); LLSelectMgr::getInstance()->setForceSelection(TRUE); } BOOL extend_select = (pick.mKeyMask == MASK_SHIFT) || (pick.mKeyMask == MASK_CONTROL); // If no object, check for icon, then just deselect if (!object) { LLHUDIcon* last_hit_hud_icon = pick.mHUDIcon; if (last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) { LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); } else if (!extend_select) { LLSelectMgr::getInstance()->deselectAll(); } } else { BOOL already_selected = object->isSelected(); if ( extend_select ) { if ( already_selected ) { if ( ignore_group ) { LLSelectMgr::getInstance()->deselectObjectOnly(object); } else { LLSelectMgr::getInstance()->deselectObjectAndFamily(object, TRUE, TRUE); } } else { if ( ignore_group ) { LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); } else { LLSelectMgr::getInstance()->selectObjectAndFamily(object); } } } else { // Save the current zoom values because deselect resets them. F32 target_zoom; F32 current_zoom; LLSelectMgr::getInstance()->getAgentHUDZoom(target_zoom, current_zoom); // JC - Change behavior to make it easier to select children // of linked sets. 9/3/2002 if( !already_selected || ignore_group) { // ...lose current selection in favor of just this object LLSelectMgr::getInstance()->deselectAll(); } if ( ignore_group ) { LLSelectMgr::getInstance()->selectObjectOnly(object, SELECT_ALL_TES); } else { LLSelectMgr::getInstance()->selectObjectAndFamily(object); } // restore the zoom to the previously stored values. LLSelectMgr::getInstance()->setAgentHUDZoom(target_zoom, current_zoom); } if (!gAgent.getFocusOnAvatar() && // if camera not glued to avatar LLVOAvatar::findAvatarFromAttachment(object) != gAgent.getAvatarObject() && // and it's not one of your attachments object != gAgent.getAvatarObject()) // and it's not you { // have avatar turn to face the selected object(s) LLVector3d selection_center = LLSelectMgr::getInstance()->getSelectionCenterGlobal(); selection_center = selection_center - gAgent.getPositionGlobal(); LLVector3 selection_dir; selection_dir.setVec(selection_center); selection_dir.mV[VZ] = 0.f; selection_dir.normVec(); if (!object->isAvatar() && gAgent.getAtAxis() * selection_dir < 0.6f) { LLQuaternion target_rot; target_rot.shortestArc(LLVector3::x_axis, selection_dir); gAgent.startAutoPilotGlobal(gAgent.getPositionGlobal(), "", &target_rot, NULL, NULL, 1.f, SELECTION_ROTATION_TRESHOLD); } } if (temp_select) { if (!already_selected) { LLViewerObject* root_object = (LLViewerObject*)object->getRootEdit(); LLObjectSelectionHandle selection = LLSelectMgr::getInstance()->getSelection(); // this is just a temporary selection LLSelectNode* select_node = selection->findNode(root_object); if (select_node) { select_node->setTransient(TRUE); } LLViewerObject::const_child_list_t& child_list = root_object->getChildren(); for (LLViewerObject::child_list_t::const_iterator iter = child_list.begin(); iter != child_list.end(); iter++) { LLViewerObject* child = *iter; select_node = selection->findNode(child); if (select_node) { select_node->setTransient(TRUE); } } } } //if(temp_select) } //if(!object) // Cleanup temp select settings above. if (temp_select || gAllowSelectAvatar) { gSavedSettings.setBOOL("SelectOwnedOnly", select_owned); gSavedSettings.setBOOL("SelectMovableOnly", select_movable); gSavedSettings.setBOOL("SelectThisRegionOnly", select_region); LLSelectMgr::getInstance()->setForceSelection(FALSE); } return LLSelectMgr::getInstance()->getSelection(); }
//----------------------------------------------------------------------------- // LLBVHLoader::optimize() //----------------------------------------------------------------------------- void LLBVHLoader::optimize() { //RN: assumes motion blend, which is the default now if (!mLoop && mEaseIn + mEaseOut > mDuration && mDuration != 0.f) { F32 factor = mDuration / (mEaseIn + mEaseOut); mEaseIn *= factor; mEaseOut *= factor; } JointVector::iterator ji; for (ji = mJoints.begin(); ji != mJoints.end(); ++ji) { Joint *joint = *ji; BOOL pos_changed = FALSE; BOOL rot_changed = FALSE; if ( ! joint->mIgnore ) { joint->mNumPosKeys = 0; joint->mNumRotKeys = 0; LLQuaternion::Order order = bvhStringToOrder( joint->mOrder ); KeyVector::iterator first_key = joint->mKeys.begin(); // no keys? if (first_key == joint->mKeys.end()) { joint->mIgnore = TRUE; continue; } LLVector3 first_frame_pos(first_key->mPos); LLQuaternion first_frame_rot = mayaQ( first_key->mRot[0], first_key->mRot[1], first_key->mRot[2], order); // skip first key KeyVector::iterator ki = joint->mKeys.begin(); if (joint->mKeys.size() == 1) { // *FIX: use single frame to move pelvis // if only one keyframe force output for this joint rot_changed = TRUE; } else { // if more than one keyframe, use first frame as reference and skip to second first_key->mIgnorePos = TRUE; first_key->mIgnoreRot = TRUE; ++ki; } KeyVector::iterator ki_prev = ki; KeyVector::iterator ki_last_good_pos = ki; KeyVector::iterator ki_last_good_rot = ki; S32 numPosFramesConsidered = 2; S32 numRotFramesConsidered = 2; F32 rot_threshold = ROTATION_KEYFRAME_THRESHOLD / llmax((F32)joint->mChildTreeMaxDepth * 0.33f, 1.f); double diff_max = 0; KeyVector::iterator ki_max = ki; for (; ki != joint->mKeys.end(); ++ki) { if (ki_prev == ki_last_good_pos) { joint->mNumPosKeys++; if (dist_vec_squared(LLVector3(ki_prev->mPos), first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } } else { //check position for noticeable effect LLVector3 test_pos(ki_prev->mPos); LLVector3 last_good_pos(ki_last_good_pos->mPos); LLVector3 current_pos(ki->mPos); LLVector3 interp_pos = lerp(current_pos, last_good_pos, 1.f / (F32)numPosFramesConsidered); if (dist_vec_squared(current_pos, first_frame_pos) > POSITION_MOTION_THRESHOLD_SQUARED) { pos_changed = TRUE; } if (dist_vec_squared(interp_pos, test_pos) < POSITION_KEYFRAME_THRESHOLD_SQUARED) { ki_prev->mIgnorePos = TRUE; numPosFramesConsidered++; } else { numPosFramesConsidered = 2; ki_last_good_pos = ki_prev; joint->mNumPosKeys++; } } if (ki_prev == ki_last_good_rot) { joint->mNumRotKeys++; LLQuaternion test_rot = mayaQ( ki_prev->mRot[0], ki_prev->mRot[1], ki_prev->mRot[2], order); F32 x_delta = dist_vec(LLVector3::x_axis * first_frame_rot, LLVector3::x_axis * test_rot); F32 y_delta = dist_vec(LLVector3::y_axis * first_frame_rot, LLVector3::y_axis * test_rot); F32 rot_test = x_delta + y_delta; if (rot_test > ROTATION_MOTION_THRESHOLD) { rot_changed = TRUE; } } else { //check rotation for noticeable effect LLQuaternion test_rot = mayaQ( ki_prev->mRot[0], ki_prev->mRot[1], ki_prev->mRot[2], order); LLQuaternion last_good_rot = mayaQ( ki_last_good_rot->mRot[0], ki_last_good_rot->mRot[1], ki_last_good_rot->mRot[2], order); LLQuaternion current_rot = mayaQ( ki->mRot[0], ki->mRot[1], ki->mRot[2], order); LLQuaternion interp_rot = lerp(1.f / (F32)numRotFramesConsidered, current_rot, last_good_rot); F32 x_delta; F32 y_delta; F32 rot_test; // Test if the rotation has changed significantly since the very first frame. If false // for all frames, then we'll just throw out this joint's rotation entirely. x_delta = dist_vec(LLVector3::x_axis * first_frame_rot, LLVector3::x_axis * test_rot); y_delta = dist_vec(LLVector3::y_axis * first_frame_rot, LLVector3::y_axis * test_rot); rot_test = x_delta + y_delta; if (rot_test > ROTATION_MOTION_THRESHOLD) { rot_changed = TRUE; } x_delta = dist_vec(LLVector3::x_axis * interp_rot, LLVector3::x_axis * test_rot); y_delta = dist_vec(LLVector3::y_axis * interp_rot, LLVector3::y_axis * test_rot); rot_test = x_delta + y_delta; // Draw a line between the last good keyframe and current. Test the distance between the last frame (current-1, i.e. ki_prev) // and the line. If it's greater than some threshold, then it represents a significant frame and we want to include it. if (rot_test >= rot_threshold || (ki+1 == joint->mKeys.end() && numRotFramesConsidered > 2)) { // Add the current test keyframe (which is technically the previous key, i.e. ki_prev). numRotFramesConsidered = 2; ki_last_good_rot = ki_prev; joint->mNumRotKeys++; // Add another keyframe between the last good keyframe and current, at whatever point was the most "significant" (i.e. // had the largest deviation from the earlier tests). Note that a more robust approach would be test all intermediate // keyframes against the line between the last good keyframe and current, but we're settling for this other method // because it's significantly faster. if (diff_max > 0) { if (ki_max->mIgnoreRot == TRUE) { ki_max->mIgnoreRot = FALSE; joint->mNumRotKeys++; } diff_max = 0; } } else { // This keyframe isn't significant enough, throw it away. ki_prev->mIgnoreRot = TRUE; numRotFramesConsidered++; // Store away the keyframe that has the largest deviation from the interpolated line, for insertion later. if (rot_test > diff_max) { diff_max = rot_test; ki_max = ki; } } } ki_prev = ki; } } // don't output joints with no motion if (!(pos_changed || rot_changed)) { //LL_INFOS() << "Ignoring joint " << joint->mName << LL_ENDL; joint->mIgnore = TRUE; } } }
// Returns "distance" between target destination and resulting xfrom F32 LLDrawable::updateXform(BOOL undamped) { BOOL damped = !undamped; // Position LLVector3 old_pos(mXform.getPosition()); LLVector3 target_pos; if (mXform.isRoot()) { // get root position in your agent's region target_pos = mVObjp->getPositionAgent(); } else { // parent-relative position target_pos = mVObjp->getPosition(); } // Rotation LLQuaternion old_rot(mXform.getRotation()); LLQuaternion target_rot = mVObjp->getRotation(); //scaling LLVector3 target_scale = mVObjp->getScale(); LLVector3 old_scale = mCurrentScale; // Damping F32 dist_squared = 0.f; F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera); if (damped && isVisible()) { F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); // FIXME: This can be negative! It is be possible for some rots to 'cancel out' pos or size changes. dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); dist_squared += dist_vec_squared(new_scale, target_scale); if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) && (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)) { // interpolate target_pos = new_pos; target_rot = new_rot; target_scale = new_scale; } else if (mVObjp->getAngularVelocity().isExactlyZero()) { // snap to final position (only if no target omega is applied) dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } } } else { // The following fixes MAINT-1742 but breaks vehicles similar to MAINT-2275 // dist_squared = dist_vec_squared(old_pos, target_pos); // The following fixes MAINT-2247 but causes MAINT-2275 //dist_squared += (1.f - dot(old_rot, target_rot)) * 10.f; //dist_squared += dist_vec_squared(old_scale, target_scale); } LLVector3 vec = mCurrentScale-target_scale; if (vec*vec > MIN_INTERPOLATE_DISTANCE_SQUARED) { //scale change requires immediate rebuild mCurrentScale = target_scale; gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!isRoot() && (!mVObjp->getAngularVelocity().isExactlyZero() || dist_squared > 0.f)) { //child prim moving relative to parent, tag as needing to be rendered atomically and rebuild dist_squared = 1.f; //keep this object on the move list if (!isState(LLDrawable::ANIMATED_CHILD)) { setState(LLDrawable::ANIMATED_CHILD); gPipeline.markRebuild(this, LLDrawable::REBUILD_ALL, TRUE); mVObjp->dirtySpatialGroup(); } } else if (!isRoot() && ((dist_vec_squared(old_pos, target_pos) > 0.f) || (1.f - dot(old_rot, target_rot)) > 0.f)) { //fix for BUG-840, MAINT-2275, MAINT-1742, MAINT-2247 gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!getVOVolume() && !isAvatar()) { movePartition(); } // Update mXform.setPosition(target_pos); mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); } return dist_squared; }
// Returns "distance" between target destination and resulting xfrom F32 LLDrawable::updateXform(BOOL undamped) { BOOL damped = !undamped; // Position LLVector3 old_pos(mXform.getPosition()); LLVector3 target_pos; if (mXform.isRoot()) { // get root position in your agent's region target_pos = mVObjp->getPositionAgent(); } else { // parent-relative position target_pos = mVObjp->getPosition(); } // Rotation LLQuaternion old_rot(mXform.getRotation()); LLQuaternion target_rot = mVObjp->getRotation(); //scaling LLVector3 target_scale = mVObjp->getScale(); LLVector3 old_scale = mCurrentScale; LLVector3 dest_scale = target_scale; // Damping F32 dist_squared = 0.f; F32 camdist2 = (mDistanceWRTCamera * mDistanceWRTCamera); if (damped && isVisible()) { F32 lerp_amt = llclamp(LLCriticalDamp::getInterpolant(OBJECT_DAMPING_TIME_CONSTANT), 0.f, 1.f); LLVector3 new_pos = lerp(old_pos, target_pos, lerp_amt); dist_squared = dist_vec_squared(new_pos, target_pos); LLQuaternion new_rot = nlerp(lerp_amt, old_rot, target_rot); dist_squared += (1.f - dot(new_rot, target_rot)) * 10.f; LLVector3 new_scale = lerp(old_scale, target_scale, lerp_amt); dist_squared += dist_vec_squared(new_scale, target_scale); if ((dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED * camdist2) && (dist_squared <= MAX_INTERPOLATE_DISTANCE_SQUARED)) { // interpolate target_pos = new_pos; target_rot = new_rot; target_scale = new_scale; } else { // snap to final position dist_squared = 0.0f; if (getVOVolume() && !isRoot()) { //child prim snapping to some position, needs a rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } } } if ((mCurrentScale != target_scale) || (!isRoot() && (dist_squared >= MIN_INTERPOLATE_DISTANCE_SQUARED || !mVObjp->getAngularVelocity().isExactlyZero() || target_pos != mXform.getPosition() || target_rot != mXform.getRotation()))) { //child prim moving or scale change requires immediate rebuild gPipeline.markRebuild(this, LLDrawable::REBUILD_POSITION, TRUE); } else if (!getVOVolume() && !isAvatar()) { movePartition(); } // Update mXform.setPosition(target_pos); mXform.setRotation(target_rot); mXform.setScale(LLVector3(1,1,1)); //no scale in drawable transforms (IT'S A RULE!) mXform.updateMatrix(); mCurrentScale = target_scale; if (mSpatialBridge) { gPipeline.markMoved(mSpatialBridge, FALSE); } return dist_squared; }
BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face, BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region ) { F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f; // Viewer-side pick to find the right sim to create the object on. // First find the surface the object will be created on. LLPickInfo pick = gViewerWindow->pickImmediate(x, y, FALSE); // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok // representations (if any) are NOT the same as their viewer representation. if (pick.mPickType == LLPickInfo::PICK_FLORA) { *hit_obj = NULL; *hit_face = -1; } else { *hit_obj = pick.getObject(); *hit_face = pick.mObjectFace; } *b_hit_land = !(*hit_obj) && !pick.mPosGlobal.isExactlyZero(); LLVector3d land_pos_global = pick.mPosGlobal; // Make sure there's a surface to place the new object on. BOOL bypass_sim_raycast = FALSE; LLVector3d surface_pos_global; if (*b_hit_land) { surface_pos_global = land_pos_global; bypass_sim_raycast = TRUE; } else if (*hit_obj) { surface_pos_global = (*hit_obj)->getPositionGlobal(); } else { return FALSE; } // Make sure the surface isn't too far away. LLVector3d ray_start_global = gAgentCamera.getCameraPositionGlobal(); F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared()); if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) ) { return FALSE; } // [RLVa:KB] - Checked: 2009-07-10 (RLVa-1.0.0g) | Modified: RLVa-0.2.0f // NOTE: don't use surface_pos_global since for prims it will be the center of the prim while we need center + offset if ( (gRlvHandler.hasBehaviour(RLV_BHVR_FARTOUCH)) && (dist_vec_squared(gAgent.getPositionGlobal(), pick.mPosGlobal) > 1.5f * 1.5f) ) { return FALSE; } // [/RLVa:KB] // Find the sim where the surface lives. LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global); if (!regionp) { llwarns << "Trying to add object outside of all known regions!" << llendl; return FALSE; } // Find the simulator-side ray that will be used to place the object accurately LLVector3d mouse_direction; mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) ); *region = regionp; *ray_start_region = regionp->getPosRegionFromGlobal( ray_start_global ); F32 near_clip = LLViewerCamera::getInstance()->getNear() + 0.01f; // Include an epsilon to avoid rounding issues. *ray_start_region += LLViewerCamera::getInstance()->getAtAxis() * near_clip; if( bypass_sim_raycast ) { // Hack to work around Havok's inability to ray cast onto height fields *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global ); // ray end is the viewer's intersection point } else { LLVector3d ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction; // add an epsilon to the sim version of the ray to avoid rounding problems. *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global ); } return TRUE; }
//----------------------------------------------------------------------------- // setPointAt() // called by agent logic to set look at behavior locally, and propagate to sim //----------------------------------------------------------------------------- BOOL LLHUDEffectPointAt::setPointAt(EPointAtType target_type, LLViewerObject *object, LLVector3 position) { if (!mSourceObject) { return FALSE; } if (target_type >= POINTAT_NUM_TARGETS) { llwarns << "Bad target_type " << (int)target_type << " - ignoring." << llendl; return FALSE; } // must be same or higher priority than existing effect if (POINTAT_PRIORITIES[target_type] < POINTAT_PRIORITIES[mTargetType]) { return FALSE; } F32 current_time = mTimer.getElapsedTimeF32(); // type of pointat behavior or target object has changed BOOL targetTypeChanged = (target_type != mTargetType) || (object != mTargetObject); BOOL targetPosChanged = (dist_vec_squared(position, mLastSentOffsetGlobal) > MIN_DELTAPOS_FOR_UPDATE_SQUARED) && ((current_time - mLastSendTime) > (1.f / MAX_SENDS_PER_SEC)); if (targetTypeChanged || targetPosChanged) { mLastSentOffsetGlobal = position; setDuration(POINTAT_TIMEOUTS[target_type]); setNeedsSendToSim(TRUE); // llinfos << "Sending pointat data" << llendl; } if (target_type == POINTAT_TARGET_CLEAR) { clearPointAtTarget(); } else { mTargetType = target_type; mTargetObject = object; if (object) { mTargetOffsetGlobal.setVec(position); } else { mTargetOffsetGlobal = gAgent.getPosGlobalFromAgent(position); } mKillTime = mTimer.getElapsedTimeF32() + mDuration; //set up requisite animation data update(); } return TRUE; }
// Returns true if you got at least one object void LLToolSelectRect::handleRectangleSelection(S32 x, S32 y, MASK mask) { LLVector3 av_pos = gAgent.getPositionAgent(); F32 select_dist_squared = gSavedSettings.getF32("MaxSelectDistance"); select_dist_squared = select_dist_squared * select_dist_squared; BOOL deselect = (mask == MASK_CONTROL); S32 left = llmin(x, mDragStartX); S32 right = llmax(x, mDragStartX); S32 top = llmax(y, mDragStartY); S32 bottom =llmin(y, mDragStartY); left = llround((F32) left * LLUI::sGLScaleFactor.mV[VX]); right = llround((F32) right * LLUI::sGLScaleFactor.mV[VX]); top = llround((F32) top * LLUI::sGLScaleFactor.mV[VY]); bottom = llround((F32) bottom * LLUI::sGLScaleFactor.mV[VY]); F32 old_far_plane = LLViewerCamera::getInstance()->getFar(); F32 old_near_plane = LLViewerCamera::getInstance()->getNear(); S32 width = right - left + 1; S32 height = top - bottom + 1; BOOL grow_selection = FALSE; BOOL shrink_selection = FALSE; if (height > mDragLastHeight || width > mDragLastWidth) { grow_selection = TRUE; } if (height < mDragLastHeight || width < mDragLastWidth) { shrink_selection = TRUE; } if (!grow_selection && !shrink_selection) { // nothing to do return; } mDragLastHeight = height; mDragLastWidth = width; S32 center_x = (left + right) / 2; S32 center_y = (top + bottom) / 2; // save drawing mode glMatrixMode(GL_PROJECTION); gGL.pushMatrix(); BOOL limit_select_distance = gSavedSettings.getBOOL("LimitSelectDistance"); if (limit_select_distance) { // ...select distance from control LLVector3 relative_av_pos = av_pos; relative_av_pos -= LLViewerCamera::getInstance()->getOrigin(); F32 new_far = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() + gSavedSettings.getF32("MaxSelectDistance"); F32 new_near = relative_av_pos * LLViewerCamera::getInstance()->getAtAxis() - gSavedSettings.getF32("MaxSelectDistance"); new_near = llmax(new_near, 0.1f); LLViewerCamera::getInstance()->setFar(new_far); LLViewerCamera::getInstance()->setNear(new_near); } LLViewerCamera::getInstance()->setPerspective(FOR_SELECTION, center_x-width/2, center_y-height/2, width, height, limit_select_distance); if (shrink_selection) { struct f : public LLSelectedObjectFunctor { virtual bool apply(LLViewerObject* vobjp) { LLDrawable* drawable = vobjp->mDrawable; if (!drawable || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment()) { return true; } S32 result = LLViewerCamera::getInstance()->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); switch (result) { case 0: LLSelectMgr::getInstance()->unhighlightObjectOnly(vobjp); break; case 1: // check vertices if (!LLViewerCamera::getInstance()->areVertsVisible(vobjp, LLSelectMgr::sRectSelectInclusive)) { LLSelectMgr::getInstance()->unhighlightObjectOnly(vobjp); } break; default: break; } return true; } } func; LLSelectMgr::getInstance()->getHighlightedObjects()->applyToObjects(&func); } if (grow_selection) { std::vector<LLDrawable*> potentials; for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* region = *iter; for (U32 i = 0; i < LLViewerRegion::NUM_PARTITIONS; i++) { LLSpatialPartition* part = region->getSpatialPartition(i); if (part) { part->cull(*LLViewerCamera::getInstance(), &potentials, TRUE); } } } for (std::vector<LLDrawable*>::iterator iter = potentials.begin(); iter != potentials.end(); iter++) { LLDrawable* drawable = *iter; LLViewerObject* vobjp = drawable->getVObj(); if (!drawable || !vobjp || vobjp->getPCode() != LL_PCODE_VOLUME || vobjp->isAttachment() || (deselect && !vobjp->isSelected())) { continue; } if (limit_select_distance && dist_vec_squared(drawable->getWorldPosition(), av_pos) > select_dist_squared) { continue; } S32 result = LLViewerCamera::getInstance()->sphereInFrustum(drawable->getPositionAgent(), drawable->getRadius()); if (result) { switch (result) { case 1: // check vertices if (LLViewerCamera::getInstance()->areVertsVisible(vobjp, LLSelectMgr::sRectSelectInclusive)) { LLSelectMgr::getInstance()->highlightObjectOnly(vobjp); } break; case 2: LLSelectMgr::getInstance()->highlightObjectOnly(vobjp); break; default: break; } } } } // restore drawing mode glMatrixMode(GL_PROJECTION); gGL.popMatrix(); glMatrixMode(GL_MODELVIEW); // restore camera LLViewerCamera::getInstance()->setFar(old_far_plane); LLViewerCamera::getInstance()->setNear(old_near_plane); gViewerWindow->setup3DRender(); }
//static void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color) { if(chat.mMuted) { r_color= LLUIColorTable::instance().getColor("LtGray"); } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: r_color = LLUIColorTable::instance().getColor("SystemChatColor"); break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull() || SYSTEM_FROM == chat.mFromName) { r_color = LLUIColorTable::instance().getColor("SystemChatColor"); } else { if(gAgentID == chat.mFromID) { r_color = LLUIColorTable::instance().getColor("UserChatColor"); } else { r_color = LLUIColorTable::instance().getColor("AgentChatColor"); } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { r_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); } else if ( chat.mChatType == CHAT_TYPE_DIRECT ) { r_color = LLUIColorTable::instance().getColor("DirectChatColor"); } else { r_color = LLUIColorTable::instance().getColor("ObjectChatColor"); } break; default: r_color.setToWhite(); } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); F32 dist_near_chat = gAgent.getNearChatRadius(); if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color.mV[VALPHA] = 0.8f; } } } }
void LLWorld::getAvatars(std::vector<LLUUID>* avatar_ids, std::vector<LLVector3d>* positions, const LLVector3d& relative_to, F32 radius) const { F32 radius_squared = radius * radius; if(avatar_ids != NULL) { avatar_ids->clear(); } if(positions != NULL) { positions->clear(); } // get the list of avatars from the character list first, so distances are correct // when agent is above 1020m and other avatars are nearby for (std::vector<LLCharacter*>::iterator iter = LLCharacter::sInstances.begin(); iter != LLCharacter::sInstances.end(); ++iter) { LLVOAvatar* pVOAvatar = (LLVOAvatar*) *iter; if (!pVOAvatar->isDead() && !pVOAvatar->isSelf() && !pVOAvatar->mIsDummy) { LLUUID uuid = pVOAvatar->getID(); if(!uuid.isNull()) { LLVector3d pos_global = pVOAvatar->getPositionGlobal(); if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { if(positions != NULL) { positions->push_back(pos_global); } if(avatar_ids !=NULL) { avatar_ids->push_back(uuid); } } } } } // region avatars added for situations where radius is greater than RenderFarClip for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* regionp = *iter; const LLVector3d& origin_global = regionp->getOriginGlobal(); S32 count = regionp->mMapAvatars.count(); for (S32 i = 0; i < count; i++) { LLVector3d pos_global = unpackLocalToGlobalPosition(regionp->mMapAvatars.get(i), origin_global); if(dist_vec_squared(pos_global, relative_to) <= radius_squared) { LLUUID uuid = regionp->mMapAvatarIDs.get(i); // if this avatar doesn't already exist in the list, add it if(uuid.notNull() && avatar_ids != NULL && std::find(avatar_ids->begin(), avatar_ids->end(), uuid) == avatar_ids->end()) { if(positions != NULL) { positions->push_back(pos_global); } avatar_ids->push_back(uuid); } } } } }
LLColor4 get_text_color(const LLChat& chat) { LLColor4 text_color; if(chat.mMuted) { text_color.setVec(0.8f, 0.8f, 0.8f, 1.f); } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: text_color = LLUIColorTable::instance().getColor("SystemChatColor"); break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull()) { text_color = LLUIColorTable::instance().getColor("SystemChatColor"); } else { if(gAgent.getID() == chat.mFromID) { text_color = LLUIColorTable::instance().getColor("UserChatColor"); } else { text_color = LLUIColorTable::instance().getColor("AgentChatColor"); } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { text_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { text_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); } else { text_color = LLUIColorTable::instance().getColor("ObjectChatColor"); } break; default: text_color.setToWhite(); } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); F32 dist_near_chat = gAgent.getNearChatRadius(); if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat text_color.mV[VALPHA] = 0.8f; } } } return text_color; }
void LLNetMap::draw() { static LLFrameTimer map_timer; static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white); static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white); //static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white); static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white); static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white); if (mObjectImagep.isNull()) { createObjectImage(); } static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); if (auto_center) { mCurPan = lerp(mCurPan, mTargetPan, LLSmoothInterpolation::getInterpolant(0.1f)); } // Prepare a scissor region F32 rotation = 0; gGL.pushMatrix(); gGL.pushUIMatrix(); LLVector3 offset = gGL.getUITranslation(); LLVector3 scale = gGL.getUIScale(); gGL.loadIdentity(); gGL.loadUIIdentity(); gGL.scalef(scale.mV[0], scale.mV[1], scale.mV[2]); gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); { LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.matrixMode(LLRender::MM_MODELVIEW); // Draw background rectangle LLColor4 background_color = mBackgroundColor.get(); gGL.color4fv( background_color.mV ); gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0); } // region 0,0 is in the middle S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPan.mV[VX]); S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPan.mV[VY]); gGL.pushMatrix(); gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f); static LLUICachedControl<bool> rotate_map("MiniMapRotate", true); if( rotate_map ) { // rotate subsequent draws to agent rotation rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ); gGL.rotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f); } // figure out where agent is S32 region_width = ll_round(LLWorld::getInstance()->getRegionWidthInMeters()); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* regionp = *iter; // Find x and y position relative to camera's center. LLVector3 origin_agent = regionp->getOriginAgent(); LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent(); F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale; F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale; // background region rectangle F32 bottom = relative_y; F32 left = relative_x; F32 top = bottom + mScale ; F32 right = left + mScale ; if (regionp == gAgent.getRegion()) { gGL.color4f(1.f, 1.f, 1.f, 1.f); } else { gGL.color4f(0.8f, 0.8f, 0.8f, 1.f); } if (!regionp->isAlive()) { gGL.color4f(1.f, 0.5f, 0.5f, 1.f); } // Draw using texture. gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture()); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); gGL.end(); // Draw water gGL.setAlphaRejectSettings(LLRender::CF_GREATER, ABOVE_WATERLINE_ALPHA / 255.f); { if (regionp->getLand().getWaterTexture()) { gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture()); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); gGL.end(); } } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } // Redraw object layer periodically if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f)) { mUpdateNow = false; // Locate the centre of the object layer, accounting for panning LLVector3 new_center = globalPosToView(gAgentCamera.getCameraPositionGlobal()); new_center.mV[VX] -= mCurPan.mV[VX]; new_center.mV[VY] -= mCurPan.mV[VY]; new_center.mV[VZ] = 0.f; mObjectImageCenterGlobal = viewPosToGlobal(llfloor(new_center.mV[VX]), llfloor(new_center.mV[VY])); // Create the base texture. U8 *default_texture = mObjectRawImagep->getData(); memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() ); // Draw objects gObjectList.renderObjectsForMap(*this); mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight()); map_timer.reset(); } LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal); LLVector3 camera_position = gAgentCamera.getCameraPositionAgent(); map_center_agent -= camera_position; map_center_agent.mV[VX] *= mScale/region_width; map_center_agent.mV[VY] *= mScale/region_width; gGL.getTexUnit(0)->bind(mObjectImagep); F32 image_half_width = 0.5f*mObjectMapPixels; F32 image_half_height = 0.5f*mObjectMapPixels; gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]); gGL.end(); gGL.popMatrix(); // Mouse pointer in local coordinates S32 local_mouse_x; S32 local_mouse_y; //localMouse(&local_mouse_x, &local_mouse_y); LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mClosestAgentToCursor.setNull(); F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE); LLVector3 pos_map; uuid_vec_t avatar_ids; std::vector<LLVector3d> positions; bool unknown_relative_z; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal()); // Draw avatars for (U32 i = 0; i < avatar_ids.size(); i++) { LLUUID uuid = avatar_ids[i]; // Skip self, we'll draw it later if (uuid == gAgent.getID()) continue; pos_map = globalPosToView(positions[i]); bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z && camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z; LLWorldMapView::drawAvatar( pos_map.mV[VX], pos_map.mV[VY], color, pos_map.mV[VZ], mDotRadius, unknown_relative_z); if(uuid.notNull()) { bool selected = false; uuid_vec_t::iterator sel_iter = gmSelected.begin(); for (; sel_iter != gmSelected.end(); sel_iter++) { if(*sel_iter == uuid) { selected = true; break; } } if(selected) { if( (pos_map.mV[VX] < 0) || (pos_map.mV[VY] < 0) || (pos_map.mV[VX] >= getRect().getWidth()) || (pos_map.mV[VY] >= getRect().getHeight()) ) { S32 x = ll_round( pos_map.mV[VX] ); S32 y = ll_round( pos_map.mV[VY] ); LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); } else { LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f); } } } F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { closest_dist_squared = dist_to_cursor_squared; mClosestAgentToCursor = uuid; } } // Draw dot for autopilot target if (gAgent.getAutoPilot()) { drawTracking( gAgent.getAutoPilotTargetGlobal(), map_track_color ); } else { LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); if ( LLTracker::TRACKING_AVATAR == tracking_status ) { drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color ); } else if ( LLTracker::TRACKING_LANDMARK == tracking_status || LLTracker::TRACKING_LOCATION == tracking_status ) { drawTracking( LLTracker::getTrackedPositionGlobal(), map_track_color ); } } // Draw dot for self avatar position LLVector3d pos_global = gAgent.getPositionGlobal(); pos_map = globalPosToView(pos_global); S32 dot_width = ll_round(mDotRadius * 2.f); LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage; if (you) { you->draw(ll_round(pos_map.mV[VX] - mDotRadius), ll_round(pos_map.mV[VY] - mDotRadius), dot_width, dot_width); F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { mClosestAgentToCursor = gAgent.getID(); } } // Draw frustum F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters(); F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); F32 far_clip_pixels = far_clip_meters * meters_to_pixels; F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); F32 half_width_pixels = half_width_meters * meters_to_pixels; F32 ctr_x = (F32)center_sw_left; F32 ctr_y = (F32)center_sw_bottom; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); if( rotate_map ) { gGL.color4fv((map_frustum_color()).mV); gGL.begin( LLRender::TRIANGLES ); gGL.vertex2f( ctr_x, ctr_y ); gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels ); gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels ); gGL.end(); } else { gGL.color4fv((map_frustum_rotating_color()).mV); // If we don't rotate the map, we have to rotate the frustum. gGL.pushMatrix(); gGL.translatef( ctr_x, ctr_y, 0 ); gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); gGL.begin( LLRender::TRIANGLES ); gGL.vertex2f( 0, 0 ); gGL.vertex2f( -half_width_pixels, far_clip_pixels ); gGL.vertex2f( half_width_pixels, far_clip_pixels ); gGL.end(); gGL.popMatrix(); } } gGL.popMatrix(); gGL.popUIMatrix(); LLUICtrl::draw(); }
// This function selects an ideal viewing distance based on the focused object, pick normal, and padding value void LLViewerMediaFocus::setCameraZoom(LLViewerObject* object, LLVector3 normal, F32 padding_factor, bool zoom_in_only) { if (object) { gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); LLBBox bbox = object->getBoundingBoxAgent(); LLVector3d center = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); F32 height; F32 width; F32 depth; F32 angle_of_view; F32 distance; // We need the aspect ratio, and the 3 components of the bbox as height, width, and depth. F32 aspect_ratio = getBBoxAspectRatio(bbox, normal, &height, &width, &depth); F32 camera_aspect = LLViewerCamera::getInstance()->getAspect(); lldebugs << "normal = " << normal << ", aspect_ratio = " << aspect_ratio << ", camera_aspect = " << camera_aspect << llendl; // We will normally use the side of the volume aligned with the short side of the screen (i.e. the height for // a screen in a landscape aspect ratio), however there is an edge case where the aspect ratio of the object is // more extreme than the screen. In this case we invert the logic, using the longer component of both the object // and the screen. bool invert = (camera_aspect > 1.0f && aspect_ratio > camera_aspect) || (camera_aspect < 1.0f && aspect_ratio < camera_aspect); // To calculate the optimum viewing distance we will need the angle of the shorter side of the view rectangle. // In portrait mode this is the width, and in landscape it is the height. // We then calculate the distance based on the corresponding side of the object bbox (width for portrait, height for landscape) // We will add half the depth of the bounding box, as the distance projection uses the center point of the bbox. if(camera_aspect < 1.0f || invert) { angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect()); distance = width * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); lldebugs << "using width (" << width << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl; } else { angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getView()); distance = height * 0.5 * padding_factor / tan(angle_of_view * 0.5f ); lldebugs << "using height (" << height << "), angle_of_view = " << angle_of_view << ", distance = " << distance << llendl; } distance += depth * 0.5; // Finally animate the camera to this new position and focal point LLVector3d camera_pos, target_pos; // The target lookat position is the center of the selection (in global coords) target_pos = center; // Target look-from (camera) position is "distance" away from the target along the normal LLVector3d pickNormal = LLVector3d(normal); pickNormal.normalize(); camera_pos = target_pos + pickNormal * distance; if (pickNormal == LLVector3d::z_axis || pickNormal == LLVector3d::z_axis_neg) { // If the normal points directly up, the camera will "flip" around. // We try to avoid this by adjusting the target camera position a // smidge towards current camera position // *NOTE: this solution is not perfect. All it attempts to solve is the // "looking down" problem where the camera flips around when it animates // to that position. You still are not guaranteed to be looking at the // media in the correct orientation. What this solution does is it will // put the camera into position keeping as best it can the current // orientation with respect to the face. In other words, if before zoom // the media appears "upside down" from the camera, after zooming it will // still be upside down, but at least it will not flip. LLVector3d cur_camera_pos = LLVector3d(gAgentCamera.getCameraPositionGlobal()); LLVector3d delta = (cur_camera_pos - camera_pos); F64 len = delta.length(); delta.normalize(); // Move 1% of the distance towards original camera location camera_pos += 0.01 * len * delta; } // If we are not allowing zooming out and the old camera position is closer to // the center then the new intended camera position, don't move camera and return if (zoom_in_only && (dist_vec_squared(gAgentCamera.getCameraPositionGlobal(), target_pos) < dist_vec_squared(camera_pos, target_pos))) { return; } gAgentCamera.setCameraPosAndFocusGlobal(camera_pos, target_pos, object->getID() ); } else { // If we have no object, focus back on the avatar. gAgentCamera.setFocusOnAvatar(TRUE, ANIMATE); } }
//static void LLViewerChat::getChatColor(const LLChat& chat, std::string& r_color_name, F32& r_color_alpha) { if(chat.mMuted) { r_color_name = "LtGray"; } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: r_color_name = "SystemChatColor"; break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull()) { r_color_name = "SystemChatColor"; } else { if(gAgentID == chat.mFromID) { r_color_name = "UserChatColor"; } else { r_color_name = "AgentChatColor"; } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { r_color_name = "ScriptErrorColor"; } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { r_color_name = "llOwnerSayChatColor"; } else if ( chat.mChatType == CHAT_TYPE_DIRECT ) { r_color_name = "DirectChatColor"; } else if ( chat.mChatType == CHAT_TYPE_IM ) { r_color_name = "ObjectIMColor"; } else { r_color_name = "ObjectChatColor"; } break; default: r_color_name = "White"; } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); F32 dist_near_chat = LLWorld::getInstance()->getSayDistance(); if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color_alpha = 0.8f; } else { r_color_alpha = 1.0f; } } } }
void LLNetMap::draw() { // Ansariel: Synchronize netmap scale throughout instances if (mScale != sScale) { setScale(sScale); } static LLFrameTimer map_timer; static LLUIColor map_avatar_color = LLUIColorTable::instance().getColor("MapAvatarColor", LLColor4::white); static LLUIColor map_avatar_friend_color = LLUIColorTable::instance().getColor("MapAvatarFriendColor", LLColor4::white); static LLUIColor map_avatar_linden_color = LLUIColorTable::instance().getColor("MapAvatarLindenColor", LLColor4::blue); static LLUIColor map_avatar_muted_color = LLUIColorTable::instance().getColor("MapAvatarMutedColor", LLColor4::grey3); static LLUIColor map_track_color = LLUIColorTable::instance().getColor("MapTrackColor", LLColor4::white); static LLUIColor map_track_disabled_color = LLUIColorTable::instance().getColor("MapTrackDisabledColor", LLColor4::white); static LLUIColor map_frustum_color = LLUIColorTable::instance().getColor("MapFrustumColor", LLColor4::white); static LLUIColor map_frustum_rotating_color = LLUIColorTable::instance().getColor("MapFrustumRotatingColor", LLColor4::white); static LLUIColor map_chat_ring_color = LLUIColorTable::instance().getColor("MapChatRingColor", LLColor4::yellow); static LLUIColor map_shout_ring_color = LLUIColorTable::instance().getColor("MapShoutRingColor", LLColor4::red); if (mObjectImagep.isNull()) { createObjectImage(); } static LLUICachedControl<bool> auto_center("MiniMapAutoCenter", true); if (auto_center) { mCurPan = lerp(mCurPan, mTargetPan, LLCriticalDamp::getInterpolant(0.1f)); } // Prepare a scissor region F32 rotation = 0; gGL.pushMatrix(); gGL.pushUIMatrix(); LLVector3 offset = gGL.getUITranslation(); LLVector3 scale = gGL.getUIScale(); gGL.loadIdentity(); gGL.loadUIIdentity(); gGL.scalef(scale.mV[0], scale.mV[1], scale.mV[2]); gGL.translatef(offset.mV[0], offset.mV[1], offset.mV[2]); { LLLocalClipRect clip(getLocalRect()); { gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); gGL.matrixMode(LLRender::MM_MODELVIEW); // Draw background rectangle LLColor4 background_color = mBackgroundColor.get(); gGL.color4fv( background_color.mV ); gl_rect_2d(0, getRect().getHeight(), getRect().getWidth(), 0); } // region 0,0 is in the middle S32 center_sw_left = getRect().getWidth() / 2 + llfloor(mCurPan.mV[VX]); S32 center_sw_bottom = getRect().getHeight() / 2 + llfloor(mCurPan.mV[VY]); gGL.pushMatrix(); gGL.translatef( (F32) center_sw_left, (F32) center_sw_bottom, 0.f); static LLUICachedControl<bool> rotate_map("MiniMapRotate", true); if( rotate_map ) { // rotate subsequent draws to agent rotation rotation = atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ); gGL.rotatef( rotation * RAD_TO_DEG, 0.f, 0.f, 1.f); } // figure out where agent is S32 region_width = llround(LLWorld::getInstance()->getRegionWidthInMeters()); for (LLWorld::region_list_t::const_iterator iter = LLWorld::getInstance()->getRegionList().begin(); iter != LLWorld::getInstance()->getRegionList().end(); ++iter) { LLViewerRegion* regionp = *iter; // Find x and y position relative to camera's center. LLVector3 origin_agent = regionp->getOriginAgent(); LLVector3 rel_region_pos = origin_agent - gAgentCamera.getCameraPositionAgent(); F32 relative_x = (rel_region_pos.mV[0] / region_width) * mScale; F32 relative_y = (rel_region_pos.mV[1] / region_width) * mScale; // background region rectangle F32 bottom = relative_y; F32 left = relative_x; F32 top = bottom + mScale ; F32 right = left + mScale ; if (regionp == gAgent.getRegion()) { gGL.color4f(1.f, 1.f, 1.f, 1.f); } else { gGL.color4f(0.8f, 0.8f, 0.8f, 1.f); } if (!regionp->isAlive()) { gGL.color4f(1.f, 0.5f, 0.5f, 1.f); } // Draw using texture. gGL.getTexUnit(0)->bind(regionp->getLand().getSTexture()); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); gGL.end(); // Draw water gGL.setAlphaRejectSettings(LLRender::CF_GREATER, ABOVE_WATERLINE_ALPHA / 255.f); { if (regionp->getLand().getWaterTexture()) { gGL.getTexUnit(0)->bind(regionp->getLand().getWaterTexture()); gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(left, top); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(left, bottom); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(right, bottom); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(right, top); gGL.end(); } } gGL.setAlphaRejectSettings(LLRender::CF_DEFAULT); } // Redraw object layer periodically if (mUpdateNow || (map_timer.getElapsedTimeF32() > 0.5f)) { mUpdateNow = false; // Locate the centre of the object layer, accounting for panning LLVector3 new_center = globalPosToView(gAgentCamera.getCameraPositionGlobal()); new_center.mV[VX] -= mCurPan.mV[VX]; new_center.mV[VY] -= mCurPan.mV[VY]; new_center.mV[VZ] = 0.f; mObjectImageCenterGlobal = viewPosToGlobal(llfloor(new_center.mV[VX]), llfloor(new_center.mV[VY])); // Create the base texture. U8 *default_texture = mObjectRawImagep->getData(); memset( default_texture, 0, mObjectImagep->getWidth() * mObjectImagep->getHeight() * mObjectImagep->getComponents() ); // Draw objects gObjectList.renderObjectsForMap(*this); mObjectImagep->setSubImage(mObjectRawImagep, 0, 0, mObjectImagep->getWidth(), mObjectImagep->getHeight()); map_timer.reset(); } LLVector3 map_center_agent = gAgent.getPosAgentFromGlobal(mObjectImageCenterGlobal); LLVector3 camera_position = gAgentCamera.getCameraPositionAgent(); map_center_agent -= camera_position; map_center_agent.mV[VX] *= mScale/region_width; map_center_agent.mV[VY] *= mScale/region_width; gGL.getTexUnit(0)->bind(mObjectImagep); F32 image_half_width = 0.5f*mObjectMapPixels; F32 image_half_height = 0.5f*mObjectMapPixels; gGL.begin(LLRender::QUADS); gGL.texCoord2f(0.f, 1.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, image_half_height + map_center_agent.mV[VY]); gGL.texCoord2f(0.f, 0.f); gGL.vertex2f(map_center_agent.mV[VX] - image_half_width, map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 0.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], map_center_agent.mV[VY] - image_half_height); gGL.texCoord2f(1.f, 1.f); gGL.vertex2f(image_half_width + map_center_agent.mV[VX], image_half_height + map_center_agent.mV[VY]); gGL.end(); gGL.popMatrix(); // Mouse pointer in local coordinates S32 local_mouse_x; S32 local_mouse_y; //localMouse(&local_mouse_x, &local_mouse_y); LLUI::getMousePositionLocal(this, &local_mouse_x, &local_mouse_y); mClosestAgentToCursor.setNull(); F32 closest_dist_squared = F32_MAX; // value will be overridden in the loop F32 min_pick_dist_squared = (mDotRadius * MIN_PICK_SCALE) * (mDotRadius * MIN_PICK_SCALE); LLVector3 pos_map; uuid_vec_t avatar_ids; std::vector<LLVector3d> positions; bool unknown_relative_z; LLWorld::getInstance()->getAvatars(&avatar_ids, &positions, gAgentCamera.getCameraPositionGlobal()); // Draw avatars for (U32 i = 0; i < avatar_ids.size(); i++) { pos_map = globalPosToView(positions[i]); LLUUID uuid = avatar_ids[i]; bool show_as_friend = (LLAvatarTracker::instance().getBuddyInfo(uuid) != NULL); LLColor4 color = show_as_friend ? map_avatar_friend_color : map_avatar_color; // <FS:Ansariel> Check for unknown Z-offset => AVATAR_UNKNOWN_Z_OFFSET //unknown_relative_z = positions[i].mdV[VZ] == COARSEUPDATE_MAX_Z && // camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z; unknown_relative_z = false; if (positions[i].mdV[VZ] == AVATAR_UNKNOWN_Z_OFFSET) { if (camera_position.mV[VZ] >= COARSEUPDATE_MAX_Z) { // No exact data and cam >=1020 => we don't know if // other avatar is above or below us => unknown unknown_relative_z = true; } else { // No exact data but cam is below 1020 => other avatar // is definitely above us => bump Z-offset to F32_MAX // so we get the up chevron pos_map.mV[VZ] = F32_MAX; } } // </FS:Ansariel> // Colorize muted avatars and Lindens std::string fullName; LLMuteList* muteListInstance = LLMuteList::getInstance(); if (muteListInstance->isMuted(uuid)) color = map_avatar_muted_color; else if (gCacheName->getFullName(uuid, fullName) && muteListInstance->isLinden(fullName)) color = map_avatar_linden_color; // Mark Avatars with special colors - Ansariel if (LLNetMap::sAvatarMarksMap.find(uuid) != LLNetMap::sAvatarMarksMap.end()) { color = LLNetMap::sAvatarMarksMap[uuid]; } //color based on contact sets prefs if(LGGContactSets::getInstance()->hasFriendColorThatShouldShow(uuid,FALSE,FALSE,FALSE,TRUE)) { color = LGGContactSets::getInstance()->getFriendColor(uuid); } // [RLVa:KB] - Checked: 2010-04-19 (RLVa-1.2.0f) | Modified: RLVa-1.2.0f | FS-Specific LLWorldMapView::drawAvatar( pos_map.mV[VX], pos_map.mV[VY], ((!gRlvHandler.hasBehaviour(RLV_BHVR_SHOWNAMES)) ? color : map_avatar_color.get()), pos_map.mV[VZ], mDotRadius, unknown_relative_z); // [/RLVa:KB] // LLWorldMapView::drawAvatar( // pos_map.mV[VX], pos_map.mV[VY], // color, // pos_map.mV[VZ], mDotRadius, // unknown_relative_z); if(uuid.notNull()) { bool selected = false; uuid_vec_t::iterator sel_iter = gmSelected.begin(); for (; sel_iter != gmSelected.end(); sel_iter++) { if(*sel_iter == uuid) { selected = true; break; } } if(selected) { if( (pos_map.mV[VX] < 0) || (pos_map.mV[VY] < 0) || (pos_map.mV[VX] >= getRect().getWidth()) || (pos_map.mV[VY] >= getRect().getHeight()) ) { S32 x = llround( pos_map.mV[VX] ); S32 y = llround( pos_map.mV[VY] ); LLWorldMapView::drawTrackingCircle( getRect(), x, y, color, 1, 10); } else { LLWorldMapView::drawTrackingDot(pos_map.mV[VX],pos_map.mV[VY],color,0.f); } } } F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { closest_dist_squared = dist_to_cursor_squared; mClosestAgentToCursor = uuid; mClosestAgentPosition = positions[i]; } } // Draw dot for autopilot target if (gAgent.getAutoPilot()) { drawTracking( gAgent.getAutoPilotTargetGlobal(), map_track_color ); } else { LLTracker::ETrackingStatus tracking_status = LLTracker::getTrackingStatus(); if ( LLTracker::TRACKING_AVATAR == tracking_status ) { drawTracking( LLAvatarTracker::instance().getGlobalPos(), map_track_color ); } else if ( LLTracker::TRACKING_LANDMARK == tracking_status || LLTracker::TRACKING_LOCATION == tracking_status ) { drawTracking( LLTracker::getTrackedPositionGlobal(), map_track_color ); } } // Draw dot for self avatar position LLVector3d pos_global = gAgent.getPositionGlobal(); pos_map = globalPosToView(pos_global); S32 dot_width = llround(mDotRadius * 2.f); LLUIImagePtr you = LLWorldMapView::sAvatarYouLargeImage; if (you) { you->draw(llround(pos_map.mV[VX] - mDotRadius), llround(pos_map.mV[VY] - mDotRadius), dot_width, dot_width); F32 dist_to_cursor_squared = dist_vec_squared(LLVector2(pos_map.mV[VX], pos_map.mV[VY]), LLVector2(local_mouse_x,local_mouse_y)); if(dist_to_cursor_squared < min_pick_dist_squared && dist_to_cursor_squared < closest_dist_squared) { mClosestAgentToCursor = gAgent.getID(); mClosestAgentPosition = pos_global; } // Draw chat range ring(s) static LLUICachedControl<bool> chat_ring("MiniMapChatRing", true); if(chat_ring) { drawRing(LLWorld::getInstance()->getSayDistance(), pos_map, map_chat_ring_color); drawRing(LLWorld::getInstance()->getShoutDistance(), pos_map, map_shout_ring_color); } } // Draw frustum F32 meters_to_pixels = mScale/ LLWorld::getInstance()->getRegionWidthInMeters(); F32 horiz_fov = LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect(); F32 far_clip_meters = LLViewerCamera::getInstance()->getFar(); F32 far_clip_pixels = far_clip_meters * meters_to_pixels; F32 half_width_meters = far_clip_meters * tan( horiz_fov / 2 ); F32 half_width_pixels = half_width_meters * meters_to_pixels; F32 ctr_x = (F32)center_sw_left; F32 ctr_y = (F32)center_sw_bottom; gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE); if( rotate_map ) { gGL.color4fv((map_frustum_color()).mV); gGL.begin( LLRender::TRIANGLES ); gGL.vertex2f( ctr_x, ctr_y ); gGL.vertex2f( ctr_x - half_width_pixels, ctr_y + far_clip_pixels ); gGL.vertex2f( ctr_x + half_width_pixels, ctr_y + far_clip_pixels ); gGL.end(); } else { gGL.color4fv((map_frustum_rotating_color()).mV); // If we don't rotate the map, we have to rotate the frustum. gGL.pushMatrix(); gGL.translatef( ctr_x, ctr_y, 0 ); gGL.rotatef( atan2( LLViewerCamera::getInstance()->getAtAxis().mV[VX], LLViewerCamera::getInstance()->getAtAxis().mV[VY] ) * RAD_TO_DEG, 0.f, 0.f, -1.f); gGL.begin( LLRender::TRIANGLES ); gGL.vertex2f( 0, 0 ); gGL.vertex2f( -half_width_pixels, far_clip_pixels ); gGL.vertex2f( half_width_pixels, far_clip_pixels ); gGL.end(); gGL.popMatrix(); } } gGL.popMatrix(); gGL.popUIMatrix(); LLUICtrl::draw(); }
//static void LLViewerChat::getChatColor(const LLChat& chat, LLColor4& r_color, bool is_local) { if(chat.mMuted) { r_color= LLUIColorTable::instance().getColor("LtGray"); } else { switch(chat.mSourceType) { case CHAT_SOURCE_SYSTEM: r_color = LLUIColorTable::instance().getColor("SystemChatColor"); break; case CHAT_SOURCE_AGENT: if (chat.mFromID.isNull() || SYSTEM_FROM == chat.mFromName) { r_color = LLUIColorTable::instance().getColor("SystemChatColor"); } else { if(gAgentID == chat.mFromID) { r_color = LLUIColorTable::instance().getColor("UserChatColor"); } else { r_color = LLUIColorTable::instance().getColor("AgentChatColor"); } //color based on contact sets prefs if(LGGContactSets::getInstance()->hasFriendColorThatShouldShow(chat.mFromID,TRUE)) { r_color = LGGContactSets::getInstance()->getFriendColor(chat.mFromID); } } break; case CHAT_SOURCE_OBJECT: if (chat.mChatType == CHAT_TYPE_DEBUG_MSG) { r_color = LLUIColorTable::instance().getColor("ScriptErrorColor"); } else if ( chat.mChatType == CHAT_TYPE_OWNER ) { r_color = LLUIColorTable::instance().getColor("llOwnerSayChatColor"); } else if ( chat.mChatType == CHAT_TYPE_DIRECT ) { r_color = LLUIColorTable::instance().getColor("DirectChatColor"); } else if ( chat.mChatType == CHAT_TYPE_IM ) { r_color = LLUIColorTable::instance().getColor("ObjectIMColor"); } else { r_color = LLUIColorTable::instance().getColor("ObjectChatColor"); } break; default: r_color.setToWhite(); } //Keyword alerts -KC if ((gAgentID != chat.mFromID || chat.mFromName == SYSTEM_FROM) && FSKeywords::getInstance()->chatContainsKeyword(chat, is_local)) { std::string msg = chat.mFromName; std::string prefix = chat.mText.substr(0, 4); if(prefix == "/me " || prefix == "/me'") { msg = msg + chat.mText.substr(3); } else { msg = msg + ": " + chat.mText; } #if LL_WINDOWS gGrowlManager->notify("Keyword Alert", msg, "Keyword Alert"); #endif static LLCachedControl<bool> sFSKeywordChangeColor(gSavedPerAccountSettings, "FSKeywordChangeColor"); if (sFSKeywordChangeColor) { static LLCachedControl<LLColor4> sFSKeywordColor(gSavedPerAccountSettings, "FSKeywordColor"); r_color = sFSKeywordColor; } } if (!chat.mPosAgent.isExactlyZero()) { LLVector3 pos_agent = gAgent.getPositionAgent(); F32 distance_squared = dist_vec_squared(pos_agent, chat.mPosAgent); F32 dist_near_chat = LLWorld::getInstance()->getSayDistance(); if (distance_squared > dist_near_chat * dist_near_chat) { // diminish far-off chat r_color.mV[VALPHA] = 0.8f; } } } }