// only works for our specialized (AABB, position centered) bboxes BOOL bbox_overlap(LLBBox bbox1, LLBBox bbox2) { const F32 FUDGE = 0.001f; // because of SL precision/rounding LLVector3 delta = bbox1.getCenterAgent() - bbox2.getCenterAgent(); LLVector3 half_extent = (bbox1.getExtentLocal() + bbox2.getExtentLocal()) / 2.0; return ((fabs(delta.mV[VX]) < half_extent.mV[VX] - FUDGE) && (fabs(delta.mV[VY]) < half_extent.mV[VY] - FUDGE) && (fabs(delta.mV[VZ]) < half_extent.mV[VZ] - FUDGE)); }
// This function calculates the aspect ratio and the world aligned components of a selection bounding box. F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth) { // Convert the selection normal and an up vector to local coordinate space of the bbox LLVector3 local_normal = bbox.agentToLocalBasis(normal); LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f)); LLVector3 comp1(0.f,0.f,0.f); LLVector3 comp2(0.f,0.f,0.f); LLVector3 bbox_max = bbox.getExtentLocal(); F32 dot1 = 0.f; F32 dot2 = 0.f; lldebugs << "bounding box local size = " << bbox_max << ", local_normal = " << local_normal << llendl; // The largest component of the localized normal vector is the depth component // meaning that the other two are the legs of the rectangle. local_normal.abs(); // Using temporary variables for these makes the logic a bit more readable. bool XgtY = (local_normal.mV[VX] > local_normal.mV[VY]); bool XgtZ = (local_normal.mV[VX] > local_normal.mV[VZ]); bool YgtZ = (local_normal.mV[VY] > local_normal.mV[VZ]); if(XgtY && XgtZ) { lldebugs << "x component of normal is longest, using y and z" << llendl; comp1.mV[VY] = bbox_max.mV[VY]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VX]; } else if(!XgtY && YgtZ) { lldebugs << "y component of normal is longest, using x and z" << llendl; comp1.mV[VX] = bbox_max.mV[VX]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VY]; } else { lldebugs << "z component of normal is longest, using x and y" << llendl; comp1.mV[VX] = bbox_max.mV[VX]; comp2.mV[VY] = bbox_max.mV[VY]; *depth = bbox_max.mV[VZ]; } // The height is the vector closest to vertical in the bbox coordinate space (highest dot product value) dot1 = comp1 * z_vec; dot2 = comp2 * z_vec; if(fabs(dot1) > fabs(dot2)) { *height = comp1.length(); *width = comp2.length(); lldebugs << "comp1 = " << comp1 << ", height = " << *height << llendl; lldebugs << "comp2 = " << comp2 << ", width = " << *width << llendl; } else { *height = comp2.length(); *width = comp1.length(); lldebugs << "comp2 = " << comp2 << ", height = " << *height << llendl; lldebugs << "comp1 = " << comp1 << ", width = " << *width << llendl; } lldebugs << "returning " << (*width / *height) << llendl; // Return the aspect ratio. return *width / *height; }
// True if you selected an object. BOOL LLToolPie::pickLeftMouseDownCallback() { S32 x = mPick.mMousePt.mX; S32 y = mPick.mMousePt.mY; MASK mask = mPick.mKeyMask; if (mPick.mPickType == LLPickInfo::PICK_PARCEL_WALL) { LLParcel* parcel = LLViewerParcelMgr::getInstance()->getCollisionParcel(); if (parcel) { LLViewerParcelMgr::getInstance()->selectCollisionParcel(); if (parcel->getParcelFlag(PF_USE_PASS_LIST) && !LLViewerParcelMgr::getInstance()->isCollisionBanned()) { // if selling passes, just buy one void* deselect_when_done = (void*)TRUE; LLPanelLandGeneral::onClickBuyPass(deselect_when_done); } else { // not selling passes, get info LLFloaterReg::showInstance("about_land"); } } gFocusMgr.setKeyboardFocus(NULL); return LLTool::handleMouseDown(x, y, mask); } // didn't click in any UI object, so must have clicked in the world LLViewerObject *object = mPick.getObject(); LLViewerObject *parent = NULL; if (mPick.mPickType != LLPickInfo::PICK_LAND) { LLViewerParcelMgr::getInstance()->deselectLand(); } if (object) { parent = object->getRootEdit(); } if (handleMediaClick(mPick)) { return TRUE; } // If it's a left-click, and we have a special action, do it. if (useClickAction(mask, object, parent)) { mClickAction = 0; if (object && object->getClickAction()) { mClickAction = object->getClickAction(); } else if (parent && parent->getClickAction()) { mClickAction = parent->getClickAction(); } switch(mClickAction) { case CLICK_ACTION_TOUCH: // touch behavior down below... break; case CLICK_ACTION_SIT: { if (isAgentAvatarValid() && !gAgentAvatarp->isSitting()) // agent not already sitting { handle_object_sit_or_stand(); // put focus in world when sitting on an object gFocusMgr.setKeyboardFocus(NULL); return TRUE; } // else nothing (fall through to touch) } case CLICK_ACTION_PAY: if ((object && object->flagTakesMoney()) || (parent && parent->flagTakesMoney())) { // pay event goes to object actually clicked on mClickActionObject = object; mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); if (LLSelectMgr::getInstance()->selectGetAllValid()) { // call this right away, since we have all the info we need to continue the action selectionPropertiesReceived(); } return TRUE; } break; case CLICK_ACTION_BUY: mClickActionObject = parent; mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); if (LLSelectMgr::getInstance()->selectGetAllValid()) { // call this right away, since we have all the info we need to continue the action selectionPropertiesReceived(); } return TRUE; case CLICK_ACTION_OPEN: if (parent && parent->allowOpen()) { mClickActionObject = parent; mLeftClickSelection = LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE, TRUE); if (LLSelectMgr::getInstance()->selectGetAllValid()) { // call this right away, since we have all the info we need to continue the action selectionPropertiesReceived(); } } return TRUE; case CLICK_ACTION_PLAY: handle_click_action_play(); return TRUE; case CLICK_ACTION_OPEN_MEDIA: // mClickActionObject = object; handle_click_action_open_media(object); return TRUE; case CLICK_ACTION_ZOOM: { const F32 PADDING_FACTOR = 2.f; LLViewerObject* object = gObjectList.findObject(mPick.mObjectID); if (object) { gAgentCamera.setFocusOnAvatar(FALSE, ANIMATE); LLBBox bbox = object->getBoundingBoxAgent() ; F32 angle_of_view = llmax(0.1f, LLViewerCamera::getInstance()->getAspect() > 1.f ? LLViewerCamera::getInstance()->getView() * LLViewerCamera::getInstance()->getAspect() : LLViewerCamera::getInstance()->getView()); F32 distance = bbox.getExtentLocal().magVec() * PADDING_FACTOR / atan(angle_of_view); LLVector3 obj_to_cam = LLViewerCamera::getInstance()->getOrigin() - bbox.getCenterAgent(); obj_to_cam.normVec(); LLVector3d object_center_global = gAgent.getPosGlobalFromAgent(bbox.getCenterAgent()); gAgentCamera.setCameraPosAndFocusGlobal(object_center_global + LLVector3d(obj_to_cam * distance), object_center_global, mPick.mObjectID ); } } return TRUE; default: // nothing break; } } // put focus back "in world" gFocusMgr.setKeyboardFocus(NULL); BOOL touchable = (object && object->flagHandleTouch()) || (parent && parent->flagHandleTouch()); // Switch to grab tool if physical or triggerable if (object && !object->isAvatar() && ((object->usePhysics() || (parent && !parent->isAvatar() && parent->usePhysics())) || touchable) ) { gGrabTransientTool = this; LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolGrab::getInstance() ); return LLToolGrab::getInstance()->handleObjectHit( mPick ); } LLHUDIcon* last_hit_hud_icon = mPick.mHUDIcon; if (!object && last_hit_hud_icon && last_hit_hud_icon->getSourceObject()) { LLFloaterScriptDebug::show(last_hit_hud_icon->getSourceObject()->getID()); } // If left-click never selects or spawns a menu // Eat the event. if (!gSavedSettings.getBOOL("LeftClickShowMenu")) { // mouse already released if (!mGrabMouseButtonDown) { return TRUE; } while( object && object->isAttachment() && !object->flagHandleTouch()) { // don't pick avatar through hud attachment if (object->isHUDAttachment()) { break; } object = (LLViewerObject*)object->getParent(); } if (object && object == gAgentAvatarp) { // we left clicked on avatar, switch to focus mode LLToolMgr::getInstance()->setTransientTool(LLToolCamera::getInstance()); gViewerWindow->hideCursor(); LLToolCamera::getInstance()->setMouseCapture(TRUE); LLToolCamera::getInstance()->pickCallback(mPick); gAgentCamera.setFocusOnAvatar(TRUE, TRUE); return TRUE; } ////////// // // Could be first left-click on nothing // LLFirstUse::useLeftClickNoHit(); ///////// // Eat the event return LLTool::handleMouseDown(x, y, mask); } if (gAgent.leftButtonGrabbed()) { // if the left button is grabbed, don't put up the pie menu return LLTool::handleMouseDown(x, y, mask); } // Can't ignore children here. LLToolSelect::handleObjectSelection(mPick, FALSE, TRUE); // Spawn pie menu LLTool::handleRightMouseDown(x, y, mask); return TRUE; }
// This function calculates the aspect ratio and the world aligned components of a selection bounding box. F32 LLViewerMediaFocus::getBBoxAspectRatio(const LLBBox& bbox, const LLVector3& normal, F32* height, F32* width, F32* depth) { // Convert the selection normal and an up vector to local coordinate space of the bbox LLVector3 local_normal = bbox.agentToLocalBasis(normal); LLVector3 z_vec = bbox.agentToLocalBasis(LLVector3(0.0f, 0.0f, 1.0f)); LLVector3 comp1(0.f,0.f,0.f); LLVector3 comp2(0.f,0.f,0.f); LLVector3 bbox_max = bbox.getExtentLocal(); F32 dot1 = 0.f; F32 dot2 = 0.f; // The largest component of the localized normal vector is the depth component // meaning that the other two are the legs of the rectangle. local_normal.abs(); if(local_normal.mV[VX] > local_normal.mV[VY]) { if(local_normal.mV[VX] > local_normal.mV[VZ]) { // Use the y and z comps comp1.mV[VY] = bbox_max.mV[VY]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VX]; } else { // Use the x and y comps comp1.mV[VY] = bbox_max.mV[VY]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VZ]; } } else if(local_normal.mV[VY] > local_normal.mV[VZ]) { // Use the x and z comps comp1.mV[VX] = bbox_max.mV[VX]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VY]; } else { // Use the x and y comps comp1.mV[VY] = bbox_max.mV[VY]; comp2.mV[VZ] = bbox_max.mV[VZ]; *depth = bbox_max.mV[VX]; } // The height is the vector closest to vertical in the bbox coordinate space (highest dot product value) dot1 = comp1 * z_vec; dot2 = comp2 * z_vec; if(fabs(dot1) > fabs(dot2)) { *height = comp1.length(); *width = comp2.length(); } else { *height = comp2.length(); *width = comp1.length(); } // Return the aspect ratio. return *width / *height; }