Exemplo n.º 1
0
// 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 = ll_round((F32) left * LLUI::getScaleFactor().mV[VX]);
    right = ll_round((F32) right * LLUI::getScaleFactor().mV[VX]);
    top = ll_round((F32) top * LLUI::getScaleFactor().mV[VY]);
    bottom = ll_round((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);
    }
    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
    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();
}