123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220 |
- /**
- * @file llmaniprotate.cpp
- * @brief LLManipRotate class implementation
- *
- * $LicenseInfo:firstyear=2002&license=viewergpl$
- *
- * Copyright (c) 2002-2009, Linden Research, Inc.
- *
- * Second Life Viewer Source Code
- * The source code in this file ("Source Code") is provided by Linden Lab
- * to you under the terms of the GNU General Public License, version 2.0
- * ("GPL"), unless you have obtained a separate licensing agreement
- * ("Other License"), formally executed by you and Linden Lab. Terms of
- * the GPL can be found in doc/GPL-license.txt in this distribution, or
- * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
- *
- * There are special exceptions to the terms and conditions of the GPL as
- * it is applied to this Source Code. View the full text of the exception
- * in the file doc/FLOSS-exception.txt in this software distribution, or
- * online at
- * http://secondlifegrid.net/programs/open_source/licensing/flossexception
- *
- * By copying, modifying or distributing this software, you acknowledge
- * that you have read and understood your obligations described above,
- * and agree to abide by those obligations.
- *
- * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
- * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
- * COMPLETENESS OR PERFORMANCE.
- * $/LicenseInfo$
- */
- #include "llviewerprecompiledheaders.h"
- #include "llmaniprotate.h"
- #include "llbutton.h"
- #include "llgl.h"
- #include "llprimitive.h"
- #include "llrender.h"
- #include "llagent.h"
- #include "lldrawable.h"
- #include "llhoverview.h"
- #include "llfloatertools.h"
- #include "llpipeline.h"
- #include "llselectmgr.h"
- #include "llstatusbar.h"
- #include "llviewercamera.h"
- #include "llviewercontrol.h"
- #include "llviewerdisplay.h" // For hud_render_text()
- #include "llviewerobject.h"
- #include "llviewershadermgr.h"
- #include "llviewerwindow.h"
- #include "llvoavatarself.h"
- #include "llworld.h"
- constexpr F32 RADIUS_PIXELS = 100.f; // Size in screen space
- constexpr F32 SQ_RADIUS = RADIUS_PIXELS * RADIUS_PIXELS;
- constexpr F32 WIDTH_PIXELS = 8;
- constexpr S32 CIRCLE_STEPS = 100;
- constexpr F32 MAX_MANIP_SELECT_DISTANCE = 100.f;
- constexpr F32 SNAP_ANGLE_INCREMENT = 5.625f;
- constexpr F32 SNAP_ANGLE_DETENTE = SNAP_ANGLE_INCREMENT;
- constexpr F32 SNAP_GUIDE_RADIUS_1 = 2.8f;
- constexpr F32 SNAP_GUIDE_RADIUS_2 = 2.4f;
- constexpr F32 SNAP_GUIDE_RADIUS_3 = 2.2f;
- constexpr F32 SNAP_GUIDE_RADIUS_4 = 2.1f;
- constexpr F32 SNAP_GUIDE_RADIUS_5 = 2.05f;
- constexpr F32 SNAP_GUIDE_INNER_RADIUS = 2.f;
- constexpr F32 SELECTED_MANIPULATOR_SCALE = 1.05f;
- constexpr F32 MANIPULATOR_SCALE_HALF_LIFE = 0.07f;
- // gcc accepts constexpr here, but not clang...
- static const F32 AXIS_ONTO_CAM_TOLERANCE = cosf(80.f * DEG_TO_RAD);
- LLManipRotate::LLManipRotate(LLToolComposite* composite)
- : LLManip(std::string("Rotate"), composite),
- mRotationCenter(),
- mCenterScreen(),
- mRotation(),
- mMouseDown(),
- mMouseCur(),
- mRadiusMeters(0.f),
- mCenterToCam(),
- mCenterToCamNorm(),
- mCenterToCamMag(0.f),
- mCenterToProfilePlane(),
- mCenterToProfilePlaneMag(0.f),
- mSmoothRotate(false),
- mCamEdgeOn(false),
- mManipulatorScales(1.f, 1.f, 1.f, 1.f)
- {
- }
- // static
- bool LLManipRotate::getSnapEnabled()
- {
- static LLCachedControl<bool> snap_enabled(gSavedSettings, "SnapEnabled");
- return snap_enabled;
- }
- void LLManipRotate::handleSelect()
- {
- // *FIX: put this in mouseDown ?
- gSelectMgr.saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- if (gFloaterToolsp)
- {
- gFloaterToolsp->setStatusText("rotate");
- }
- LLManip::handleSelect();
- }
- void LLManipRotate::render()
- {
- LLGLSUIDefault gls_ui;
- gGL.getTexUnit(0)->bind(LLViewerFetchedTexture::sWhiteImagep);
- LLGLDepthTest gls_depth(GL_TRUE);
- LLGLEnable gl_blend(GL_BLEND);
- // You can rotate if you can move
- LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(true);
- if (!first_object)
- {
- return;
- }
- if (!updateVisiblity())
- {
- return;
- }
- gGL.matrixMode(LLRender::MM_MODELVIEW);
- gGL.pushMatrix();
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- F32 zoom = gAgent.mHUDCurZoom;
- gGL.scalef(zoom, zoom, zoom);
- }
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- LLColor4 highlight_outside(1.f, 1.f, 0.f, 1.f);
- LLColor4 highlight_inside(0.7f, 0.7f, 0.f, 0.5f);
- F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS;
- gGL.pushMatrix();
- {
- // are we in the middle of a constrained drag?
- if (mManipPart >= LL_ROT_X && mManipPart <= LL_ROT_Z)
- {
- renderSnapGuides();
- }
- else
- {
- gDebugProgram.bind();
- LLGLEnable cull_face(GL_CULL_FACE);
- LLGLDepthTest gls_depth(GL_FALSE);
- gGL.pushMatrix();
- {
- // Draw "sphere" (intersection of sphere with tangent cone that
- // has apex at camera)
- gGL.translatef(mCenterToProfilePlane.mV[VX],
- mCenterToProfilePlane.mV[VY],
- mCenterToProfilePlane.mV[VZ]);
- gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);
- // Inverse change of basis vectors
- LLVector3 forward = mCenterToCamNorm;
- LLVector3 left = gAgent.getUpAxis() % forward;
- left.normalize();
- LLVector3 up = forward % left;
- LLVector4 a(-forward);
- a.mV[3] = 0;
- LLVector4 b(up);
- b.mV[3] = 0;
- LLVector4 c(left);
- c.mV[3] = 0;
- LLMatrix4 mat;
- mat.initRows(a, b, c, LLVector4(0.f, 0.f, 0.f, 1.f));
- LLMatrix4a mata;
- mata.loadu(mat.getF32ptr());
- gGL.multMatrix(mata);
- static const LLMatrix4a rot = gl_gen_rot(-90, 0.f, 1.f, 0.f);
- gGL.rotatef(rot);
- LLColor4 color;
- if (mManipPart == LL_ROT_ROLL || mHighlightedPart == LL_ROT_ROLL)
- {
- color.set(0.8f, 0.8f, 0.8f, 0.8f);
- gGL.scalef(mManipulatorScales.mV[VW],
- mManipulatorScales.mV[VW],
- mManipulatorScales.mV[VW]);
- }
- else
- {
- color.set(0.7f, 0.7f, 0.7f, 0.6f);
- }
- gGL.diffuseColor4fv(color.mV);
- gl_washer_2d(mRadiusMeters + width_meters, mRadiusMeters,
- CIRCLE_STEPS, color, color);
- if (mManipPart == LL_NO_PART)
- {
- gGL.color4f(0.7f, 0.7f, 0.7f, 0.3f);
- gGL.diffuseColor4f(0.7f, 0.7f, 0.7f, 0.3f);
- gl_circle_2d(0, 0, mRadiusMeters, CIRCLE_STEPS, true);
- }
- gGL.flush();
- }
- gGL.popMatrix();
- gUIProgram.bind();
- }
- gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);
- LLQuaternion rot;
- F32 angle_radians, x, y, z;
- LLVector3 grid_origin;
- LLVector3 grid_scale;
- LLQuaternion grid_rotation;
- gSelectMgr.getGrid(grid_origin, grid_rotation, grid_scale);
- grid_rotation.getAngleAxis(&angle_radians, &x, &y, &z);
- gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
- gDebugProgram.bind();
- F32 critical_damp =
- LLCriticalDamp::getInterpolant(MANIPULATOR_SCALE_HALF_LIFE);
- if (mManipPart == LL_ROT_Z)
- {
- static const LLVector4 rot_z_axis(1.f, 1.f,
- SELECTED_MANIPULATOR_SCALE, 1.f);
- mManipulatorScales = lerp(mManipulatorScales, rot_z_axis,
- critical_damp);
- gGL.pushMatrix();
- {
- // Selected part
- gGL.scalef(mManipulatorScales.mV[VZ],
- mManipulatorScales.mV[VZ],
- mManipulatorScales.mV[VZ]);
- renderActiveRing(mRadiusMeters, width_meters,
- LLColor4(0.f, 0.f, 1.f, 1.f),
- LLColor4(0.f, 0.f, 1.f, 0.3f));
- }
- gGL.popMatrix();
- }
- else if (mManipPart == LL_ROT_Y)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f),
- critical_damp);
- gGL.pushMatrix();
- {
- static const LLMatrix4a rot = gl_gen_rot(90.f, 1.f, 0.f, 0.f);
- gGL.rotatef(rot);
- gGL.scalef(mManipulatorScales.mV[VY],
- mManipulatorScales.mV[VY],
- mManipulatorScales.mV[VY]);
- renderActiveRing(mRadiusMeters, width_meters,
- LLColor4(0.f, 1.f, 0.f, 1.f),
- LLColor4(0.f, 1.f, 0.f, 0.3f));
- }
- gGL.popMatrix();
- }
- else if (mManipPart == LL_ROT_X)
- {
- mManipulatorScales = lerp(mManipulatorScales,
- LLVector4(SELECTED_MANIPULATOR_SCALE,
- 1.f, 1.f, 1.f),
- critical_damp);
- gGL.pushMatrix();
- {
- static const LLMatrix4a rot = gl_gen_rot(90.f, 0.f, 1.f, 0.f);
- gGL.rotatef(rot);
- gGL.scalef(mManipulatorScales.mV[VX],
- mManipulatorScales.mV[VX],
- mManipulatorScales.mV[VX]);
- renderActiveRing(mRadiusMeters, width_meters,
- LLColor4(1.f, 0.f, 0.f, 1.f),
- LLColor4(1.f, 0.f, 0.f, 0.3f));
- }
- gGL.popMatrix();
- }
- else if (mManipPart == LL_ROT_ROLL)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE),
- critical_damp);
- }
- else if (mManipPart == LL_NO_PART)
- {
- if (mHighlightedPart == LL_NO_PART)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, 1.f, 1.f, 1.f),
- critical_damp);
- }
- LLGLEnable cull_face(GL_CULL_FACE);
- LLGLEnable clip_plane0(GL_CLIP_PLANE0);
- LLGLDepthTest gls_depth(GL_FALSE);
- // First pass: centers. Second pass: sides.
- for (S32 i = 0; i < 2; i++)
- {
- gGL.pushMatrix();
- {
- if (mHighlightedPart == LL_ROT_Z)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, 1.f, SELECTED_MANIPULATOR_SCALE, 1.f),
- critical_damp);
- gGL.scalef(mManipulatorScales.mV[VZ],
- mManipulatorScales.mV[VZ],
- mManipulatorScales.mV[VZ]);
- // Hovering over part
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(0.f, 0.f, 1.f, 1.f),
- LLColor4(0.f, 0.f, 1.f, 0.5f),
- CIRCLE_STEPS, i);
- }
- else
- {
- // Default
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(0.f, 0.f, 0.8f, 0.8f),
- LLColor4(0.f, 0.f, 0.8f, 0.4f),
- CIRCLE_STEPS, i);
- }
- }
- gGL.popMatrix();
- gGL.pushMatrix();
- {
- static const LLMatrix4a rot =
- gl_gen_rot(90.f, 1.f, 0.f, 0.f);
- gGL.rotatef(rot);
- if (mHighlightedPart == LL_ROT_Y)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, SELECTED_MANIPULATOR_SCALE, 1.f, 1.f),
- critical_damp);
- gGL.scalef(mManipulatorScales.mV[VY],
- mManipulatorScales.mV[VY],
- mManipulatorScales.mV[VY]);
- // Hovering over part
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(0.f, 1.f, 0.f, 1.f),
- LLColor4(0.f, 1.f, 0.f, 0.5f),
- CIRCLE_STEPS, i);
- }
- else
- {
- // Default
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(0.f, 0.8f, 0.f, 0.8f),
- LLColor4(0.f, 0.8f, 0.f, 0.4f),
- CIRCLE_STEPS, i);
- }
- }
- gGL.popMatrix();
- gGL.pushMatrix();
- {
- static const LLMatrix4a rot =
- gl_gen_rot(90.f, 0.f, 1.f, 0.f);
- gGL.rotatef(rot);
- if (mHighlightedPart == LL_ROT_X)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(SELECTED_MANIPULATOR_SCALE, 1.f, 1.f, 1.f),
- critical_damp);
- gGL.scalef(mManipulatorScales.mV[VX],
- mManipulatorScales.mV[VX],
- mManipulatorScales.mV[VX]);
- // Hovering over part
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(1.f, 0.f, 0.f, 1.f),
- LLColor4(1.f, 0.f, 0.f, 0.5f),
- CIRCLE_STEPS, i);
- }
- else
- {
- // Default
- gl_ring(mRadiusMeters, width_meters,
- LLColor4(0.8f, 0.f, 0.f, 0.8f),
- LLColor4(0.8f, 0.f, 0.f, 0.4f),
- CIRCLE_STEPS, i);
- }
- }
- gGL.popMatrix();
- if (mHighlightedPart == LL_ROT_ROLL)
- {
- mManipulatorScales =
- lerp(mManipulatorScales,
- LLVector4(1.f, 1.f, 1.f, SELECTED_MANIPULATOR_SCALE),
- critical_damp);
- }
- }
- }
- gUIProgram.bind();
- }
- gGL.popMatrix();
- gGL.popMatrix();
- LLVector3 euler_angles;
- LLQuaternion object_rot = first_object->getRotationEdit();
- object_rot.getEulerAngles(&(euler_angles.mV[VX]), &(euler_angles.mV[VY]),
- &(euler_angles.mV[VZ]));
- euler_angles *= RAD_TO_DEG;
- euler_angles.mV[VX] = ll_round(fmodf(euler_angles.mV[VX] + 360.f, 360.f),
- 0.05f);
- euler_angles.mV[VY] = ll_round(fmodf(euler_angles.mV[VY] + 360.f, 360.f),
- 0.05f);
- euler_angles.mV[VZ] = ll_round(fmodf(euler_angles.mV[VZ] + 360.f, 360.f),
- 0.05f);
- renderXYZ(euler_angles);
- }
- bool LLManipRotate::handleMouseDown(S32 x, S32 y, MASK mask)
- {
- bool handled = false;
- LLViewerObject* first_object =
- mObjectSelection->getFirstMoveableObject(true);
- if (first_object)
- {
- if (mHighlightedPart != LL_NO_PART)
- {
- handled = handleMouseDownOnPart(x, y, mask);
- }
- }
- return handled;
- }
- // Assumes that one of the parts of the manipulator was hit.
- bool LLManipRotate::handleMouseDownOnPart(S32 x, S32 y, MASK mask)
- {
- if (!canAffectSelection())
- {
- return false;
- }
- highlightManipulators(x, y);
- S32 hit_part = mHighlightedPart;
- // We just started a drag, so save initial object positions
- gSelectMgr.saveSelectedObjectTransform(SELECT_ACTION_TYPE_ROTATE);
- // Save selection center
- mRotationCenter = gAgent.getPosGlobalFromAgent(getPivotPoint());
- mManipPart = (EManipPart)hit_part;
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- if (mManipPart == LL_ROT_GENERAL)
- {
- mMouseDown = intersectMouseWithSphere(x, y, center, mRadiusMeters);
- }
- else
- {
- // Project onto the plane of the ring
- LLVector3 axis = getConstraintAxis();
- F32 axis_onto_cam = fabsf(axis * mCenterToCamNorm);
- if (axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE)
- {
- LLVector3 up_from_axis = mCenterToCamNorm % axis;
- up_from_axis.normalize();
- LLVector3 cur_intersection;
- getMousePointOnPlaneAgent(cur_intersection, x, y, center,
- mCenterToCam);
- cur_intersection -= center;
- mMouseDown = projected_vec(cur_intersection, up_from_axis);
- F32 mouse_depth = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
- F32 mouse_dist_sqrd = mMouseDown.lengthSquared();
- if (mouse_dist_sqrd > 0.0001f)
- {
- mouse_depth = sqrtf(mouse_depth * mouse_depth -
- mouse_dist_sqrd);
- }
- LLVector3 projected_center_to_cam = mCenterToCamNorm -
- projected_vec(mCenterToCamNorm,
- axis);
- mMouseDown += mouse_depth * projected_center_to_cam;
- }
- else
- {
- mMouseDown = findNearestPointOnRing(x, y, center, axis) - center;
- mMouseDown.normalize();
- }
- }
- mMouseCur = mMouseDown;
- // Route future Mouse messages here preemptively (release on mouse up).
- setMouseCapture(true);
- gSelectMgr.enableSilhouette(false);
- mHelpTextTimer.reset();
- ++sNumTimesHelpTextShown;
- return true;
- }
- LLVector3 LLManipRotate::findNearestPointOnRing(S32 x, S32 y,
- const LLVector3& center,
- const LLVector3& axis)
- {
- // Project the delta onto the ring and rescale it by the radius so that it
- // is _on_ the ring.
- LLVector3 proj_onto_ring;
- getMousePointOnPlaneAgent(proj_onto_ring, x, y, center, axis);
- proj_onto_ring -= center;
- proj_onto_ring.normalize();
- return center + proj_onto_ring * mRadiusMeters;
- }
- bool LLManipRotate::handleMouseUp(S32 x, S32 y, MASK mask)
- {
- // first, perform normal processing in case this was a quick-click
- handleHover(x, y, mask);
- if (hasMouseCapture())
- {
- for (LLObjectSelection::iterator iter = mObjectSelection->begin(),
- end = mObjectSelection->end();
- iter != end; ++iter)
- {
- LLSelectNode* nodep = *iter;
- LLViewerObject* object = nodep->getObject();
- if (!object)
- {
- llwarns << "NULL selected object !" << llendl;
- continue;
- }
- LLViewerObject* root_object = object->getRootEdit();
- // have permission to move and object is root of selection or
- // individually selected
- if (object->permMove() && !object->isPermanentEnforced() &&
- (!root_object || !root_object->isPermanentEnforced()) &&
- (object->isRootEdit() || nodep->mIndividualSelection))
- {
- object->mUnselectedChildrenPositions.clear() ;
- }
- }
- mManipPart = LL_NO_PART;
- // Might have missed last update due to timing.
- gSelectMgr.sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
- gSelectMgr.enableSilhouette(true);
- #if 0
- gAgent.setObjectTracking(gSavedSettings.getBool("TrackFocusObject"));
- #endif
- gSelectMgr.updateSelectionCenter();
- gSelectMgr.saveSelectedObjectTransform(SELECT_ACTION_TYPE_PICK);
- }
- return LLManip::handleMouseUp(x, y, mask);
- }
- bool LLManipRotate::handleHover(S32 x, S32 y, MASK mask)
- {
- if (hasMouseCapture())
- {
- if (mObjectSelection->isEmpty())
- {
- // Somehow the object got deselected while we were dragging it.
- setMouseCapture(false);
- }
- else
- {
- drag(x, y);
- }
- LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (active)"
- << LL_ENDL;
- }
- else
- {
- highlightManipulators(x, y);
- LL_DEBUGS("UserInput") << "hover handled by LLManipRotate (inactive)"
- << LL_ENDL;
- }
- gViewerWindowp->setCursor(UI_CURSOR_TOOLROTATE);
- return true;
- }
- LLVector3 LLManipRotate::projectToSphere(F32 x, F32 y, bool* on_sphere)
- {
- F32 z = 0.f;
- F32 dist_squared = x*x + y*y;
- *on_sphere = dist_squared <= SQ_RADIUS;
- if (*on_sphere)
- {
- z = sqrtf(SQ_RADIUS - dist_squared);
- }
- return LLVector3(x, y, z);
- }
- // Freeform rotation
- void LLManipRotate::drag(S32 x, S32 y)
- {
- if (!updateVisiblity())
- {
- return;
- }
- if (mManipPart == LL_ROT_GENERAL)
- {
- mRotation = dragUnconstrained(x, y);
- }
- else
- {
- mRotation = dragConstrained(x, y);
- }
- bool gltf_mode = false;
- bool damped = mSmoothRotate;
- mSmoothRotate = false;
- for (LLObjectSelection::iterator iter = mObjectSelection->begin(),
- end = mObjectSelection->end();
- iter != end; ++iter)
- {
- LLSelectNode* nodep = *iter;
- LLViewerObject* object = nodep->getObject();
- if (!object)
- {
- llwarns << "NULL selected object !" << llendl;
- continue;
- }
- LLViewerObject* root_object = object->getRootEdit();
- // Have permission to move and object is root of selection or
- // individually selected
- if (object->permMove() && !object->isPermanentEnforced() &&
- (!root_object || !root_object->isPermanentEnforced()) &&
- (object->isRootEdit() || nodep->mIndividualSelection))
- {
- if (nodep->mSelectedGLTFNode != -1)
- {
- // Manipulating a GLTF node
- gltf_mode = true;
- LLQuaternion new_rot = nodep->mSavedRotation * mRotation;
- object->setGLTFNodeRotationAgent(nodep->mSelectedGLTFNode,
- new_rot);
- }
- if (gltf_mode)
- {
- continue;
- }
- if (!object->isRootEdit())
- {
- // Child objects should not update if parent is selected
- LLViewerObject* editable_root =
- (LLViewerObject*)object->getParent();
- if (editable_root->isSelected())
- {
- // we will be moved properly by our parent, so skip
- continue;
- }
- }
- LLQuaternion new_rot = nodep->mSavedRotation * mRotation;
- std::vector<LLVector3>& child_positions =
- object->mUnselectedChildrenPositions ;
- std::vector<LLQuaternion> child_rotations;
- if (object->isRootEdit() && nodep->mIndividualSelection)
- {
- object->saveUnselectedChildrenRotation(child_rotations) ;
- object->saveUnselectedChildrenPosition(child_positions) ;
- }
- if (object->getParent() && object->mDrawable.notNull())
- {
- LLQuaternion invParentRotation =
- object->mDrawable->mXform.getParent()->getWorldRotation();
- invParentRotation.transpose();
- object->setRotation(new_rot * invParentRotation, damped);
- rebuild(object);
- }
- else
- {
- object->setRotation(new_rot, damped);
- rebuild(object);
- }
- // For individually selected roots, we need to counter-rotate all
- // the children
- if (object->isRootEdit() && nodep->mIndividualSelection)
- {
- // RN: must do non-damped updates on these objects so relative
- // rotation appears constant instead of having two competing
- // slerps making the child objects appear to "wobble"
- object->resetChildrenRotationAndPosition(child_rotations,
- child_positions);
- }
- }
- }
- if (!gltf_mode)
- {
- // Update positions
- for (LLObjectSelection::iterator iter = mObjectSelection->begin(),
- end = mObjectSelection->end();
- iter != end; ++iter)
- {
- LLSelectNode* nodep = *iter;
- if (nodep->mSelectedGLTFNode != -1)
- {
- continue;
- }
- LLViewerObject* object = nodep->getObject();
- if (!object)
- {
- llwarns << "NULL selected object !" << llendl;
- continue;
- }
- LLViewerObject* root_object = object->getRootEdit();
- // To avoid cumulative position changes we calculate the objects
- // new position using its saved position
- if (object->permMove() && !object->isPermanentEnforced() &&
- (!root_object || !root_object->isPermanentEnforced()))
- {
- LLVector3 center =
- gAgent.getPosAgentFromGlobal(mRotationCenter);
- LLVector3 old_position;
- LLVector3 new_position;
- if (object->isAttachment() && object->mDrawable.notNull())
- {
- // Need to work in drawable space to handle selected items
- // from multiple attachments (which have no shared frame of
- // reference other than their render positions).
- LLXform* parent_xform = object->mDrawable->getXform()->getParent();
- new_position = nodep->mSavedPositionLocal *
- parent_xform->getWorldRotation() +
- parent_xform->getWorldPosition();
- old_position = object->getPosition() *
- parent_xform->getWorldRotation() +
- //object->getRenderPosition();
- parent_xform->getWorldPosition();
- }
- else
- {
- new_position =
- gAgent.getPosAgentFromGlobal(nodep->mSavedPositionGlobal);
- old_position = object->getPositionAgent();
- }
- // New relative rotated position
- new_position = (new_position - center) * mRotation;
- new_position += center;
- if (object->isRootEdit() && !object->isAttachment())
- {
- LLVector3d new_pos_global =
- gAgent.getPosGlobalFromAgent(new_position);
- new_pos_global =
- gWorld.clipToVisibleRegions(nodep->mSavedPositionGlobal,
- new_pos_global);
- new_position =
- gAgent.getPosAgentFromGlobal(new_pos_global);
- }
- // For individually selected child objects
- if (!object->isRootEdit() && nodep->mIndividualSelection)
- {
- LLViewerObject* parentp =
- (LLViewerObject*)object->getParent();
- if (!parentp->isSelected())
- {
- if (object->isAttachment() &&
- object->mDrawable.notNull())
- {
- // Find position relative to render position of
- // parent
- object->setPositionLocal((new_position -
- parentp->getRenderPosition()) *
- ~parentp->getRenderRotation());
- rebuild(object);
- }
- else
- {
- object->setPositionParent((new_position -
- parentp->getPositionAgent()) *
- ~parentp->getRotationRegion());
- rebuild(object);
- }
- }
- }
- else if (object->isRootEdit())
- {
- if (object->isAttachment() && object->mDrawable.notNull())
- {
- LLXform* parent_xform =
- object->mDrawable->getXform()->getParent();
- object->setPositionLocal((new_position -
- parent_xform->getWorldPosition()) *
- ~parent_xform->getWorldRotation());
- rebuild(object);
- }
- else
- {
- object->setPositionAgent(new_position);
- rebuild(object);
- }
- }
- // For individually selected roots, we need to counter-
- //translate all unselected children
- if (object->isRootEdit() && nodep->mIndividualSelection)
- {
- // Only offset by parent's translation as we have already
- // countered parent's rotation
- rebuild(object);
- object->resetChildrenPosition(old_position - new_position);
- }
- }
- }
- }
- // Store changes to override updates
- for (LLObjectSelection::iterator
- iter = gSelectMgr.getSelection()->begin(),
- end = gSelectMgr.getSelection()->end();
- iter != end; ++iter)
- {
- LLSelectNode* nodep = *iter;
- LLViewerObject* object = nodep->getObject();
- if (!object)
- {
- llwarns << "NULL selected object !" << llendl;
- continue;
- }
- LLViewerObject* root_object = object->getRootEdit();
- if (!object->isAvatar() && object->permModify() &&
- object->permMove() && !object->isPermanentEnforced() &&
- (!root_object || !root_object->isPermanentEnforced()))
- {
- nodep->mLastRotation = object->getRotation();
- nodep->mLastPositionLocal = object->getPosition();
- }
- }
- gSelectMgr.updateSelectionCenter();
- // RN: just clear focus so camera doesn't follow spurious object updates
- gAgent.clearFocusObject();
- dialog_refresh_all();
- }
- void LLManipRotate::renderActiveRing(F32 radius, F32 width,
- const LLColor4& front_color,
- const LLColor4& back_color)
- {
- LLGLEnable cull_face(GL_CULL_FACE);
- gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, false);
- gl_ring(radius, width, back_color, back_color * 0.5f, CIRCLE_STEPS, true);
- {
- LLGLDepthTest gls_depth(GL_FALSE);
- gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS,
- false);
- gl_ring(radius, width, front_color, front_color * 0.5f, CIRCLE_STEPS,
- true);
- }
- }
- void LLManipRotate::renderSnapGuides()
- {
- if (!getSnapEnabled())
- {
- return;
- }
- LLVector3 grid_origin;
- LLVector3 grid_scale;
- LLQuaternion grid_rotation;
- gSelectMgr.getGrid(grid_origin, grid_rotation, grid_scale, true);
- LLVector3 constraint_axis = getConstraintAxis();
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- LLVector3 cam_at_axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_at_axis.set(1.f, 0.f, 0.f);
- }
- else
- {
- cam_at_axis = center - gAgent.getCameraPositionAgent();
- cam_at_axis.normalize();
- }
- LLVector3 world_snap_axis;
- LLVector3 test_axis = constraint_axis;
- bool constrain_to_ref_object = false;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT &&
- isAgentAvatarValid())
- {
- test_axis = test_axis * ~grid_rotation;
- }
- else if (gSelectMgr.getGridMode() == GRID_MODE_REF_OBJECT)
- {
- test_axis = test_axis * ~grid_rotation;
- constrain_to_ref_object = true;
- }
- test_axis.abs();
- // Find closest global/reference axis to local constraint axis;
- if (test_axis.mV[VX] > test_axis.mV[VY] &&
- test_axis.mV[VX] > test_axis.mV[VZ])
- {
- world_snap_axis = LLVector3::y_axis;
- }
- else if (test_axis.mV[VY] > test_axis.mV[VZ])
- {
- world_snap_axis = LLVector3::z_axis;
- }
- else
- {
- world_snap_axis = LLVector3::x_axis;
- }
- LLVector3 projected_snap_axis = world_snap_axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT &&
- isAgentAvatarValid())
- {
- projected_snap_axis = projected_snap_axis * grid_rotation;
- }
- else if (constrain_to_ref_object)
- {
- projected_snap_axis = projected_snap_axis * grid_rotation;
- }
- // Project world snap axis onto constraint plane
- projected_snap_axis -= projected_vec(projected_snap_axis, constraint_axis);
- projected_snap_axis.normalize();
- S32 num_rings = mCamEdgeOn ? 2 : 1;
- for (S32 ring_num = 0; ring_num < num_rings; ring_num++)
- {
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- if (mCamEdgeOn)
- {
- // Draw two opposing rings
- if (ring_num == 0)
- {
- center += constraint_axis * mRadiusMeters * 0.5f;
- }
- else
- {
- center -= constraint_axis * mRadiusMeters * 0.5f;
- }
- }
- LLGLDepthTest gls_depth(GL_FALSE);
- for (S32 pass = 0; pass < 3; ++pass)
- {
- // Render snap guide ring
- gGL.pushMatrix();
- LLQuaternion snap_guide_rot;
- F32 angle_radians, x, y, z;
- snap_guide_rot.shortestArc(LLVector3::z_axis, getConstraintAxis());
- snap_guide_rot.getAngleAxis(&angle_radians, &x, &y, &z);
- gGL.translatef(center.mV[VX], center.mV[VY], center.mV[VZ]);
- gGL.rotatef(angle_radians * RAD_TO_DEG, x, y, z);
- LLColor4 line_color = setupSnapGuideRenderPass(pass);
- gGL.color4fv(line_color.mV);
- if (mCamEdgeOn)
- {
- // render an arc
- LLVector3 edge_normal = cam_at_axis % constraint_axis;
- edge_normal.normalize();
- LLVector3 x_axis_snap = LLVector3::x_axis * snap_guide_rot;
- LLVector3 y_axis_snap = LLVector3::y_axis * snap_guide_rot;
- F32 end_angle = atan2f(y_axis_snap * edge_normal, x_axis_snap *
- edge_normal);
- F32 start_angle = end_angle - F_PI;
- gl_arc_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS,
- CIRCLE_STEPS, false, start_angle, end_angle);
- }
- else
- {
- gl_circle_2d(0.f, 0.f, mRadiusMeters * SNAP_GUIDE_INNER_RADIUS,
- CIRCLE_STEPS, false);
- }
- gGL.popMatrix();
- // *TODO: translate
- static const std::string up_str("Up");
- static const std::string dwn_str("Down");
- static const std::string bck_str("Back");
- static const std::string fwd_str("Forward");
- static const std::string lft_str("Left");
- static const std::string rgt_str("Right");
- static const std::string nth_str("North");
- static const std::string sth_str("South");
- static const std::string wst_str("West");
- static const std::string est_str("East");
- bool is_attachment = mObjectSelection->isAttachment();
- const std::string& dir1_str = is_attachment ? fwd_str : est_str;
- const std::string& dir2_str = is_attachment ? lft_str : nth_str;
- const std::string& dir3_str = is_attachment ? rgt_str : sth_str;
- const std::string& dir4_str = is_attachment ? bck_str : wst_str;
- for (S32 i = 0; i < 64; i++)
- {
- bool render_text = true;
- F32 deg = 5.625f * (F32)i;
- LLVector3 inner_point;
- LLVector3 outer_point;
- LLVector3 text_point;
- LLQuaternion rot(deg * DEG_TO_RAD, constraint_axis);
- gGL.begin(LLRender::LINES);
- {
- inner_point = (projected_snap_axis * mRadiusMeters *
- SNAP_GUIDE_INNER_RADIUS * rot) + center;
- F32 tick_length = 0.f;
- if (i % 16 == 0)
- {
- tick_length = mRadiusMeters *
- (SNAP_GUIDE_RADIUS_1 - SNAP_GUIDE_INNER_RADIUS);
- }
- else if (i % 8 == 0)
- {
- tick_length = mRadiusMeters *
- (SNAP_GUIDE_RADIUS_2 - SNAP_GUIDE_INNER_RADIUS);
- }
- else if (i % 4 == 0)
- {
- tick_length = mRadiusMeters *
- (SNAP_GUIDE_RADIUS_3 - SNAP_GUIDE_INNER_RADIUS);
- }
- else if (i % 2 == 0)
- {
- tick_length = mRadiusMeters *
- (SNAP_GUIDE_RADIUS_4 - SNAP_GUIDE_INNER_RADIUS);
- }
- else
- {
- tick_length = mRadiusMeters *
- (SNAP_GUIDE_RADIUS_5 - SNAP_GUIDE_INNER_RADIUS);
- }
- if (mCamEdgeOn)
- {
- // don't draw ticks that are on back side of circle
- F32 dot = cam_at_axis * (projected_snap_axis * rot);
- if (dot > 0.f)
- {
- outer_point = inner_point;
- render_text = false;
- }
- else
- {
- if (ring_num == 0)
- {
- outer_point = inner_point +
- (constraint_axis * tick_length) *
- rot;
- }
- else
- {
- outer_point = inner_point -
- (constraint_axis * tick_length) *
- rot;
- }
- }
- }
- else
- {
- outer_point = inner_point +
- (projected_snap_axis * tick_length) *
- rot;
- }
- text_point = outer_point +
- (projected_snap_axis * mRadiusMeters * 0.1f) *
- rot;
- gGL.vertex3fv(inner_point.mV);
- gGL.vertex3fv(outer_point.mV);
- }
- gGL.end();
- // RN: text rendering does own shadow pass, so only render once
- if (pass == 1 && render_text && i % 16 == 0)
- {
- if (world_snap_axis.mV[VX])
- {
- if (i == 0)
- {
- renderTickText(text_point, dir1_str);
- }
- else if (i == 16)
- {
- if (constraint_axis.mV[VZ] > 0.f)
- {
- renderTickText(text_point, dir2_str);
- }
- else
- {
- renderTickText(text_point, dir3_str);
- }
- }
- else if (i == 32)
- {
- renderTickText(text_point, dir4_str);
- }
- else if (constraint_axis.mV[VZ] > 0.f)
- {
- renderTickText(text_point, dir3_str);
- }
- else
- {
- renderTickText(text_point, dir2_str);
- }
- }
- else if (world_snap_axis.mV[VY])
- {
- if (i == 0)
- {
- renderTickText(text_point, dir2_str);
- }
- else if (i == 16)
- {
- if (constraint_axis.mV[VX] > 0.f)
- {
- renderTickText(text_point, up_str);
- }
- else
- {
- renderTickText(text_point, dwn_str);
- }
- }
- else if (i == 32)
- {
- renderTickText(text_point, dir3_str);
- }
- else if (constraint_axis.mV[VX] > 0.f)
- {
- renderTickText(text_point, dwn_str);
- }
- else
- {
- renderTickText(text_point, up_str);
- }
- }
- else if (world_snap_axis.mV[VZ])
- {
- if (i == 0)
- {
- renderTickText(text_point, up_str);
- }
- else if (i == 16)
- {
- if (constraint_axis.mV[VY] > 0.f)
- {
- renderTickText(text_point, dir1_str);
- }
- else
- {
- renderTickText(text_point, dir4_str);
- }
- }
- else if (i == 32)
- {
- renderTickText(text_point, dwn_str);
- }
- else if (constraint_axis.mV[VY] > 0.f)
- {
- renderTickText(text_point, dir4_str);
- }
- else
- {
- renderTickText(text_point, dir1_str);
- }
- }
- }
- gGL.color4fv(line_color.mV);
- }
- // Now render projected object axis
- if (mInSnapRegime)
- {
- LLVector3 object_axis;
- getObjectAxisClosestToMouse(object_axis);
- // Project onto constraint plane
- LLSelectNode* first_node = mObjectSelection->getFirstMoveableNode(true);
- object_axis = object_axis * first_node->getObject()->getRenderRotation();
- object_axis = object_axis - (object_axis * getConstraintAxis()) * getConstraintAxis();
- object_axis.normalize();
- object_axis = object_axis * SNAP_GUIDE_INNER_RADIUS * mRadiusMeters + center;
- LLVector3 line_start = center;
- gGL.begin(LLRender::LINES);
- {
- gGL.vertex3fv(line_start.mV);
- gGL.vertex3fv(object_axis.mV);
- }
- gGL.end();
- // Draw snap guide arrow
- gGL.begin(LLRender::TRIANGLES);
- {
- LLVector3 arrow_dir;
- LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis();
- arrow_span.normalize();
- arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start;
- arrow_dir.normalize();
- if (ring_num == 1)
- {
- arrow_dir *= -1.f;
- }
- gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV);
- gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV);
- gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV);
- }
- gGL.end();
- {
- LLGLDepthTest gls_depth(GL_TRUE);
- gGL.begin(LLRender::LINES);
- {
- gGL.vertex3fv(line_start.mV);
- gGL.vertex3fv(object_axis.mV);
- }
- gGL.end();
- // Draw snap guide arrow
- gGL.begin(LLRender::TRIANGLES);
- {
- LLVector3 arrow_dir;
- LLVector3 arrow_span = (object_axis - line_start) % getConstraintAxis();
- arrow_span.normalize();
- arrow_dir = mCamEdgeOn ? getConstraintAxis() : object_axis - line_start;
- arrow_dir.normalize();
- if (ring_num == 1)
- {
- arrow_dir *= -1.f;
- }
- gGL.vertex3fv((object_axis + arrow_dir * mRadiusMeters * 0.1f).mV);
- gGL.vertex3fv((object_axis + arrow_span * mRadiusMeters * 0.1f).mV);
- gGL.vertex3fv((object_axis - arrow_span * mRadiusMeters * 0.1f).mV);
- }
- gGL.end();
- }
- }
- }
- }
- // Render help text
- if (mObjectSelection->getSelectType() != SELECT_TYPE_HUD)
- {
- if (mHelpTextTimer.getElapsedTimeF32() <
- sHelpTextVisibleTime + sHelpTextFadeTime &&
- sNumTimesHelpTextShown < sMaxTimesShowHelpText)
- {
- LLVector3 sel_center = gSelectMgr.getSavedBBoxOfSelection().getCenterAgent();
- LLVector3 offset_dir = gViewerCamera.getUpAxis();
- static LLCachedControl<F32> grid_alpha(gSavedSettings,
- "GridOpacity");
- LLVector3 help_text_pos = sel_center + mRadiusMeters * 3.f * offset_dir;
- LLColor4 help_text_color = LLColor4::white;
- help_text_color.mV[VALPHA] =
- clamp_rescale(mHelpTextTimer.getElapsedTimeF32(),
- sHelpTextVisibleTime,
- sHelpTextVisibleTime + sHelpTextFadeTime,
- grid_alpha, 0.f);
- const LLFontGL* big_fontp = LLFontGL::getFontSansSerif();
- static LLWString text1 =
- utf8str_to_wstring("Move mouse cursor over ruler");
- static F32 text1_width = -0.5f *
- big_fontp->getWidthF32(text1.c_str());
- hud_render_text(text1, help_text_pos, *big_fontp, LLFontGL::NORMAL,
- text1_width, 3.f, help_text_color, false);
- static LLWString text2 = utf8str_to_wstring("to snap to grid");
- static F32 text2_width = -0.5f *
- big_fontp->getWidthF32(text2.c_str());
- help_text_pos -= offset_dir * mRadiusMeters * 0.4f;
- hud_render_text(text2, help_text_pos, *big_fontp, LLFontGL::NORMAL,
- text2_width, 3.f, help_text_color, false);
- }
- }
- }
- // Returns true if center of sphere is visible. Also sets a bunch of member
- // variables that are used later (e.g. mCenterToCam)
- bool LLManipRotate::updateVisiblity()
- {
- // We do not want to recalculate the center of the selection during a drag.
- // Due to packet delays, sometimes half the objects in the selection have
- // their new position and half have their old one. This creates subtle
- // errors in the computed center position for that frame. Unfortunately,
- // these errors accumulate. The result is objects seem to "fly apart"
- // during rotations. JC - 03.26.2002
- if (!hasMouseCapture())
- {
- mRotationCenter = gAgent.getPosGlobalFromAgent(getPivotPoint());
- }
- bool visible = false;
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- F32 zoom = gAgent.mHUDCurZoom;
- mCenterToCam = LLVector3(-1.f / zoom, 0.f, 0.f);
- mCenterToCamNorm = mCenterToCam;
- mCenterToCamMag = mCenterToCamNorm.normalize();
- mRadiusMeters = RADIUS_PIXELS / (F32)gViewerCamera.getViewHeightInPixels();
- mRadiusMeters /= zoom;
- mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters / mCenterToCamMag;
- mCenterToProfilePlane = -mCenterToProfilePlaneMag * mCenterToCamNorm;
- mCenterScreen.set((S32)((0.5f - mRotationCenter.mdV[VY]) /
- zoom * gViewerWindowp->getWindowWidth()),
- (S32)((mRotationCenter.mdV[VZ] + 0.5f) /
- zoom * gViewerWindowp->getWindowHeight()));
- visible = true;
- }
- else
- {
- visible = gViewerCamera.projectPosAgentToScreen(center, mCenterScreen);
- if (visible)
- {
- mCenterToCam = gAgent.getCameraPositionAgent() - center;
- mCenterToCamNorm = mCenterToCam;
- mCenterToCamMag = mCenterToCamNorm.normalize();
- LLVector3 cameraAtAxis = gViewerCamera.getAtAxis();
- cameraAtAxis.normalize();
- F32 z_dist = -1.f * (mCenterToCam * cameraAtAxis);
- // Do not drag manip if object too far away
- static LLCachedControl<bool> limit_select_distance(gSavedSettings,
- "LimitSelectDistance");
- static LLCachedControl<F32> max_select_distance(gSavedSettings,
- "MaxSelectDistance");
- if (limit_select_distance &&
- dist_vec(gAgent.getPositionAgent(),
- center) > max_select_distance)
- {
- visible = false;
- }
- if (mCenterToCamMag > 0.001f)
- {
- F32 fraction_of_fov = RADIUS_PIXELS /
- (F32)gViewerCamera.getViewHeightInPixels();
- F32 apparent_angle = fraction_of_fov * gViewerCamera.getView();
- mRadiusMeters = z_dist * tanf(apparent_angle);
- mCenterToProfilePlaneMag = mRadiusMeters * mRadiusMeters /
- mCenterToCamMag;
- mCenterToProfilePlane = -mCenterToProfilePlaneMag *
- mCenterToCamNorm;
- }
- else
- {
- visible = false;
- }
- }
- }
- mCamEdgeOn = false;
- F32 axis_onto_cam =
- mManipPart >= LL_ROT_X ? fabsf(getConstraintAxis() * mCenterToCamNorm)
- : 0.f;
- if (axis_onto_cam < AXIS_ONTO_CAM_TOLERANCE)
- {
- mCamEdgeOn = true;
- }
- return visible;
- }
- LLQuaternion LLManipRotate::dragUnconstrained(S32 x, S32 y)
- {
- LLVector3 cam = gAgent.getCameraPositionAgent();
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- mMouseCur = intersectMouseWithSphere(x, y, center, mRadiusMeters);
- F32 delta_x = (F32)(mCenterScreen.mX - x);
- F32 delta_y = (F32)(mCenterScreen.mY - y);
- F32 dist_from_sphere_center = sqrtf(delta_x * delta_x + delta_y * delta_y);
- LLVector3 axis = mMouseDown % mMouseCur;
- F32 angle = atan2f(sqrtf(axis * axis), mMouseDown * mMouseCur);
- axis.normalize();
- LLQuaternion sphere_rot(angle, axis);
- if (is_approx_zero(1.f - mMouseDown * mMouseCur))
- {
- return LLQuaternion::DEFAULT;
- }
- else if (dist_from_sphere_center < RADIUS_PIXELS)
- {
- return sphere_rot;
- }
- else
- {
- LLVector3 intersection;
- getMousePointOnPlaneAgent(intersection, x, y,
- center + mCenterToProfilePlane,
- mCenterToCamNorm);
- // Amount dragging in sphere from center to periphery would rotate
- // object
- F32 in_sphere_angle = F_PI_BY_TWO;
- F32 dist_to_tangent_point = mRadiusMeters;
- if (!is_approx_zero(mCenterToProfilePlaneMag))
- {
- dist_to_tangent_point = sqrtf(mRadiusMeters * mRadiusMeters -
- mCenterToProfilePlaneMag *
- mCenterToProfilePlaneMag);
- in_sphere_angle = atan2f(dist_to_tangent_point,
- mCenterToProfilePlaneMag);
- }
- LLVector3 profile_center_to_intersection =
- intersection - (center + mCenterToProfilePlane);
- F32 dist_to_intersection = profile_center_to_intersection.normalize();
- F32 angle = (-1.f + dist_to_intersection / dist_to_tangent_point) *
- in_sphere_angle;
- LLVector3 axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- axis = LLVector3(-1.f, 0.f, 0.f) % profile_center_to_intersection;
- }
- else
- {
- axis = (cam - center) % profile_center_to_intersection;
- axis.normalize();
- }
- return sphere_rot * LLQuaternion(angle, axis);
- }
- }
- LLVector3 LLManipRotate::getConstraintAxis()
- {
- LLVector3 axis;
- if (LL_ROT_ROLL == mManipPart)
- {
- axis = mCenterToCamNorm;
- }
- else
- {
- S32 axis_dir = mManipPart - LL_ROT_X;
- if (axis_dir >= 0 && axis_dir < 3)
- {
- axis.mV[axis_dir] = 1.f;
- }
- else
- {
- llwarns << "Got bogus hit part " << mManipPart << llendl;
- llassert(false);
- axis.mV[0] = 1.f;
- }
- LLVector3 grid_origin;
- LLVector3 grid_scale;
- LLQuaternion grid_rotation;
- gSelectMgr.getGrid(grid_origin, grid_rotation, grid_scale);
- LLSelectNode* first_node =
- mObjectSelection->getFirstMoveableNode(true);
- if (first_node)
- {
- // *FIX: get agent local attachment grid working
- // Put rotation into frame of first selected root object
- axis = axis * grid_rotation;
- }
- }
- return axis;
- }
- LLQuaternion LLManipRotate::dragConstrained(S32 x, S32 y)
- {
- LLSelectNode* first_object_node =
- mObjectSelection->getFirstMoveableNode(true);
- LLVector3 constraint_axis = getConstraintAxis();
- LLVector3 center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- F32 angle = 0.f;
- // build snap axes
- LLVector3 grid_origin;
- LLVector3 grid_scale;
- LLQuaternion grid_rotation;
- gSelectMgr.getGrid(grid_origin, grid_rotation, grid_scale);
- LLVector3 axis1;
- LLVector3 axis2;
- LLVector3 test_axis = constraint_axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT &&
- isAgentAvatarValid())
- {
- test_axis = test_axis * ~grid_rotation;
- }
- else if (gSelectMgr.getGridMode() == GRID_MODE_REF_OBJECT)
- {
- test_axis = test_axis * ~grid_rotation;
- }
- test_axis.abs();
- // Find closest global axis to constraint axis;
- if (test_axis.mV[VX] > test_axis.mV[VY] && test_axis.mV[VX] > test_axis.mV[VZ])
- {
- axis1 = LLVector3::y_axis;
- }
- else if (test_axis.mV[VY] > test_axis.mV[VZ])
- {
- axis1 = LLVector3::z_axis;
- }
- else
- {
- axis1 = LLVector3::x_axis;
- }
- if (mObjectSelection->getSelectType() == SELECT_TYPE_ATTACHMENT &&
- isAgentAvatarValid())
- {
- axis1 = axis1 * grid_rotation;
- }
- else if (gSelectMgr.getGridMode() == GRID_MODE_REF_OBJECT)
- {
- axis1 = axis1 * grid_rotation;
- }
- // Project axis onto constraint plane
- axis1 -= (axis1 * constraint_axis) * constraint_axis;
- axis1.normalize();
- // Calculate third and final axis
- axis2 = constraint_axis % axis1;
- const F32 snap_radius = SNAP_GUIDE_INNER_RADIUS * mRadiusMeters;
- if (mCamEdgeOn)
- {
- // We are looking at the ring edge-on.
- LLVector3 snap_plane_center = center +
- (constraint_axis * mRadiusMeters * 0.5f);
- LLVector3 cam_to_snap_plane;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_to_snap_plane.set(1.f, 0.f, 0.f);
- }
- else
- {
- cam_to_snap_plane = snap_plane_center -
- gAgent.getCameraPositionAgent();
- cam_to_snap_plane.normalize();
- }
- LLVector3 projected_mouse;
- bool hit = getMousePointOnPlaneAgent(projected_mouse, x, y,
- snap_plane_center,
- constraint_axis);
- projected_mouse -= snap_plane_center;
- if (getSnapEnabled())
- {
- S32 snap_plane = 0;
- F32 dot = cam_to_snap_plane * constraint_axis;
- if (fabsf(dot) < 0.01f)
- {
- // Looking at ring edge on, project onto view plane and check
- // if mouse is past ring
- getMousePointOnPlaneAgent(projected_mouse, x, y,
- snap_plane_center,
- cam_to_snap_plane);
- projected_mouse -= snap_plane_center;
- dot = projected_mouse * constraint_axis;
- if (projected_mouse * constraint_axis > 0)
- {
- snap_plane = 1;
- }
- projected_mouse -= dot * constraint_axis;
- }
- else if (dot > 0.f)
- {
- // Look for mouse position outside and in front of snap circle
- if (hit && projected_mouse * cam_to_snap_plane < 0.f &&
- projected_mouse.length() > snap_radius)
- {
- snap_plane = 1;
- }
- }
- // Look for mouse position inside or in back of snap circle
- else if (!hit || projected_mouse * cam_to_snap_plane > 0.f ||
- projected_mouse.length() < snap_radius)
- {
- snap_plane = 1;
- }
- if (snap_plane == 0)
- {
- // Try other plane
- snap_plane_center = center -
- constraint_axis * mRadiusMeters * 0.5f;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_to_snap_plane.set(1.f, 0.f, 0.f);
- }
- else
- {
- cam_to_snap_plane = snap_plane_center -
- gAgent.getCameraPositionAgent();
- cam_to_snap_plane.normalize();
- }
- hit = getMousePointOnPlaneAgent(projected_mouse, x, y,
- snap_plane_center,
- constraint_axis);
- projected_mouse -= snap_plane_center;
- dot = cam_to_snap_plane * constraint_axis;
- if (fabsf(dot) < 0.01f)
- {
- // Looking at ring edge on, project onto view plane and
- // check if mouse is past ring
- getMousePointOnPlaneAgent(projected_mouse, x, y,
- snap_plane_center,
- cam_to_snap_plane);
- projected_mouse -= snap_plane_center;
- dot = projected_mouse * constraint_axis;
- if (projected_mouse * constraint_axis < 0)
- {
- snap_plane = 2;
- }
- projected_mouse -= dot * constraint_axis;
- }
- else if (dot < 0.f)
- {
- // Look for mouse position outside and in front of snap
- // circle
- if (hit && projected_mouse * cam_to_snap_plane < 0.f &&
- projected_mouse.length() > snap_radius)
- {
- snap_plane = 2;
- }
- }
- // Look for mouse position inside or in back of snap circle
- else if (!hit || projected_mouse * cam_to_snap_plane > 0.f ||
- projected_mouse.length() < snap_radius)
- {
- snap_plane = 2;
- }
- }
- if (snap_plane > 0)
- {
- LLVector3 cam_at_axis;
- if (mObjectSelection->getSelectType() == SELECT_TYPE_HUD)
- {
- cam_at_axis.set(1.f, 0.f, 0.f);
- }
- else
- {
- cam_at_axis = snap_plane_center -
- gAgent.getCameraPositionAgent();
- cam_at_axis.normalize();
- }
- // First, project mouse onto screen plane at point tangent to
- // rotation radius.
- getMousePointOnPlaneAgent(projected_mouse, x, y,
- snap_plane_center, cam_at_axis);
- // Project that point onto rotation plane
- projected_mouse -= snap_plane_center;
- projected_mouse -= projected_vec(projected_mouse,
- constraint_axis);
- F32 mouse_lateral_dist = llmin(snap_radius,
- projected_mouse.length());
- F32 mouse_depth = snap_radius;
- if (fabsf(mouse_lateral_dist) > 0.01f)
- {
- mouse_depth = sqrtf(snap_radius * snap_radius -
- mouse_lateral_dist * mouse_lateral_dist);
- }
- LLVector3 projected_camera_at = cam_at_axis -
- projected_vec(cam_at_axis,
- constraint_axis);
- projected_mouse -= mouse_depth * projected_camera_at;
- if (!mInSnapRegime)
- {
- mSmoothRotate = true;
- }
- mInSnapRegime = true;
- // 0 to 360 deg
- F32 mouse_angle = fmodf(atan2f(projected_mouse * axis1,
- projected_mouse * axis2) *
- RAD_TO_DEG + 360.f, 360.f);
- F32 relative_mouse_angle = fmodf(mouse_angle + SNAP_ANGLE_DETENTE / 2,
- SNAP_ANGLE_INCREMENT);
- LLVector3 object_axis;
- getObjectAxisClosestToMouse(object_axis);
- object_axis = object_axis * first_object_node->mSavedRotation;
- // Project onto constraint plane
- object_axis = object_axis -
- object_axis * getConstraintAxis() * getConstraintAxis();
- object_axis.normalize();
- if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
- {
- F32 quantized_mouse_angle = mouse_angle - relative_mouse_angle +
- SNAP_ANGLE_DETENTE * 0.5f;
- angle = quantized_mouse_angle * DEG_TO_RAD -
- atan2f(object_axis * axis1, object_axis * axis2);
- }
- else
- {
- angle = mouse_angle * DEG_TO_RAD -
- atan2f(object_axis * axis1, object_axis * axis2);
- }
- return LLQuaternion(-angle, constraint_axis);
- }
- else
- {
- if (mInSnapRegime)
- {
- mSmoothRotate = true;
- }
- mInSnapRegime = false;
- }
- }
- else
- {
- if (mInSnapRegime)
- {
- mSmoothRotate = true;
- }
- mInSnapRegime = false;
- }
- if (!mInSnapRegime)
- {
- LLVector3 up_from_axis = mCenterToCamNorm % constraint_axis;
- up_from_axis.normalize();
- LLVector3 cur_intersection;
- getMousePointOnPlaneAgent(cur_intersection, x, y, center,
- mCenterToCam);
- cur_intersection -= center;
- mMouseCur = projected_vec(cur_intersection, up_from_axis);
- F32 mouse_depth = snap_radius;
- F32 mouse_dist_sqrd = mMouseCur.lengthSquared();
- if (mouse_dist_sqrd > 0.0001f)
- {
- mouse_depth = sqrtf(snap_radius * snap_radius -
- mouse_dist_sqrd);
- }
- LLVector3 projected_center_to_cam = mCenterToCamNorm -
- projected_vec(mCenterToCamNorm,
- constraint_axis);
- mMouseCur += mouse_depth * projected_center_to_cam;
- F32 dist = cur_intersection * up_from_axis - mMouseDown * up_from_axis;
- angle = dist / snap_radius * -F_PI_BY_TWO;
- }
- }
- else
- {
- LLVector3 projected_mouse;
- getMousePointOnPlaneAgent(projected_mouse, x, y, center, constraint_axis);
- projected_mouse -= center;
- mMouseCur = projected_mouse;
- mMouseCur.normalize();
- if (!first_object_node)
- {
- return LLQuaternion::DEFAULT;
- }
- if (getSnapEnabled() && projected_mouse.length() > snap_radius)
- {
- if (!mInSnapRegime)
- {
- mSmoothRotate = true;
- }
- mInSnapRegime = true;
- // 0 to 360 deg
- F32 mouse_angle = fmodf(atan2f(projected_mouse * axis1,
- projected_mouse * axis2) *
- RAD_TO_DEG + 360.f, 360.f);
- F32 relative_mouse_angle = fmodf(mouse_angle + SNAP_ANGLE_DETENTE / 2,
- SNAP_ANGLE_INCREMENT);
- //fmodf(ll_round(mouse_angle * RAD_TO_DEG, 7.5f) + 360.f, 360.f);
- LLVector3 object_axis;
- getObjectAxisClosestToMouse(object_axis);
- object_axis = object_axis * first_object_node->mSavedRotation;
- // project onto constraint plane
- object_axis = object_axis - object_axis * getConstraintAxis() *
- getConstraintAxis();
- object_axis.normalize();
- if (relative_mouse_angle < SNAP_ANGLE_DETENTE)
- {
- F32 quantized_mouse_angle = mouse_angle - relative_mouse_angle +
- SNAP_ANGLE_DETENTE * 0.5f;
- angle = quantized_mouse_angle * DEG_TO_RAD -
- atan2f(object_axis * axis1, object_axis * axis2);
- }
- else
- {
- angle = mouse_angle * DEG_TO_RAD -
- atan2f(object_axis * axis1, object_axis * axis2);
- }
- return LLQuaternion(-angle, constraint_axis);
- }
- else
- {
- if (mInSnapRegime)
- {
- mSmoothRotate = true;
- }
- mInSnapRegime = false;
- }
- LLVector3 axis = mMouseDown % mMouseCur;
- angle = atan2f(sqrtf(axis * axis), mMouseCur * mMouseDown);
- F32 dir = axis * constraint_axis; // cross product
- if (dir < 0.f)
- {
- angle *= -1.f;
- }
- }
- static LLCachedControl<F32> rotation_step(gSavedSettings, "RotationStep");
- F32 step_size = DEG_TO_RAD * rotation_step;
- angle -= fmod(angle, step_size);
- return LLQuaternion(angle, constraint_axis);
- }
- LLVector3 LLManipRotate::intersectMouseWithSphere(S32 x, S32 y,
- const LLVector3& sphere_center,
- F32 sphere_radius)
- {
- LLVector3 ray_pt;
- LLVector3 ray_dir;
- mouseToRay(x, y, &ray_pt, &ray_dir);
- return intersectRayWithSphere(ray_pt, ray_dir, sphere_center, sphere_radius);
- }
- LLVector3 LLManipRotate::intersectRayWithSphere(const LLVector3& ray_pt,
- const LLVector3& ray_dir,
- const LLVector3& sphere_center,
- F32 sphere_radius)
- {
- LLVector3 ray_pt_to_center = sphere_center - ray_pt;
- F32 center_distance = ray_pt_to_center.normalize();
- F32 dot = ray_dir * ray_pt_to_center;
- if (dot == 0.f)
- {
- return LLVector3::zero;
- }
- // Point which ray hits plane centered on sphere origin, facing ray origin
- LLVector3 intersection_sphere_plane =
- ray_pt + ray_dir * center_distance / dot;
- // Vector from sphere origin to the point, normalized to sphere radius
- LLVector3 sphere_center_to_intersection =
- (intersection_sphere_plane - sphere_center) / sphere_radius;
- LLVector3 result;
- F32 dist_squared = sphere_center_to_intersection.lengthSquared();
- if (dist_squared > 1.f)
- {
- result = sphere_center_to_intersection;
- result.normalize();
- }
- else
- {
- result = sphere_center_to_intersection -
- ray_dir * sqrtf(1.f - dist_squared);
- }
- return result;
- }
- // Utility function. Should probably be moved to another class.
- //static
- void LLManipRotate::mouseToRay(S32 x, S32 y, LLVector3* ray_pt,
- LLVector3* ray_dir)
- {
- if (gSelectMgr.getSelection()->getSelectType() == SELECT_TYPE_HUD)
- {
- F32 zoom = gAgent.mHUDCurZoom;
- F32 mouse_x = ((F32)x / gViewerWindowp->getWindowWidth() - 0.5f) / zoom;
- F32 mouse_y = ((F32)y / gViewerWindowp->getWindowHeight() - 0.5f) / zoom;
- *ray_pt = LLVector3(-1.f, -mouse_x, mouse_y);
- *ray_dir = LLVector3(1.f, 0.f, 0.f);
- }
- else
- {
- *ray_pt = gAgent.getCameraPositionAgent();
- gViewerCamera.projectScreenToPosAgent(x, y, ray_dir);
- *ray_dir -= *ray_pt;
- ray_dir->normalize();
- }
- }
- void LLManipRotate::highlightManipulators(S32 x, S32 y)
- {
- mHighlightedPart = LL_NO_PART;
- //LLBBox bbox = gSelectMgr.getBBoxOfSelection();
- LLViewerObject* first_object = mObjectSelection->getFirstMoveableObject(true);
- if (!first_object)
- {
- return;
- }
- LLVector3 rotation_center = gAgent.getPosAgentFromGlobal(mRotationCenter);
- LLVector3 mouse_dir_x;
- LLVector3 mouse_dir_y;
- LLVector3 mouse_dir_z;
- LLVector3 intersection_roll;
- LLVector3 grid_origin;
- LLVector3 grid_scale;
- LLQuaternion grid_rotation;
- gSelectMgr.getGrid(grid_origin, grid_rotation, grid_scale);
- LLVector3 rot_x_axis = LLVector3::x_axis * grid_rotation;
- LLVector3 rot_y_axis = LLVector3::y_axis * grid_rotation;
- LLVector3 rot_z_axis = LLVector3::z_axis * grid_rotation;
- F32 proj_rot_x_axis = fabsf(rot_x_axis * mCenterToCamNorm);
- F32 proj_rot_y_axis = fabsf(rot_y_axis * mCenterToCamNorm);
- F32 proj_rot_z_axis = fabsf(rot_z_axis * mCenterToCamNorm);
- F32 min_select_distance = 0.f;
- F32 cur_select_distance = 0.f;
- // test x
- getMousePointOnPlaneAgent(mouse_dir_x, x, y, rotation_center, rot_x_axis);
- mouse_dir_x -= rotation_center;
- // push intersection point out when working at obtuse angle to make ring
- // easier to hit
- mouse_dir_x *= 1.f + (1.f - fabsf(rot_x_axis * mCenterToCamNorm)) * 0.1f;
- // test y
- getMousePointOnPlaneAgent(mouse_dir_y, x, y, rotation_center, rot_y_axis);
- mouse_dir_y -= rotation_center;
- mouse_dir_y *= 1.f + (1.f - fabsf(rot_y_axis * mCenterToCamNorm)) * 0.1f;
- // test z
- getMousePointOnPlaneAgent(mouse_dir_z, x, y, rotation_center, rot_z_axis);
- mouse_dir_z -= rotation_center;
- mouse_dir_z *= 1.f + (1.f - fabsf(rot_z_axis * mCenterToCamNorm)) * 0.1f;
- // test roll
- getMousePointOnPlaneAgent(intersection_roll, x, y, rotation_center,
- mCenterToCamNorm);
- intersection_roll -= rotation_center;
- F32 dist_x = mouse_dir_x.normalize();
- F32 dist_y = mouse_dir_y.normalize();
- F32 dist_z = mouse_dir_z.normalize();
- F32 distance_threshold = MAX_MANIP_SELECT_DISTANCE * mRadiusMeters /
- gViewerWindowp->getWindowHeight();
- if (fabsf(dist_x - mRadiusMeters) * llmax(0.05f, proj_rot_x_axis) <
- distance_threshold)
- {
- // selected x
- cur_select_distance = dist_x * mouse_dir_x * mCenterToCamNorm;
- if (cur_select_distance >= -0.05f &&
- (min_select_distance == 0.f ||
- cur_select_distance > min_select_distance))
- {
- min_select_distance = cur_select_distance;
- mHighlightedPart = LL_ROT_X;
- }
- }
- if (fabsf(dist_y - mRadiusMeters) * llmax(0.05f, proj_rot_y_axis) <
- distance_threshold)
- {
- // selected y
- cur_select_distance = dist_y * mouse_dir_y * mCenterToCamNorm;
- if (cur_select_distance >= -0.05f &&
- (min_select_distance == 0.f ||
- cur_select_distance > min_select_distance))
- {
- min_select_distance = cur_select_distance;
- mHighlightedPart = LL_ROT_Y;
- }
- }
- if (fabsf(dist_z - mRadiusMeters) * llmax(0.05f, proj_rot_z_axis) <
- distance_threshold)
- {
- // selected z
- cur_select_distance = dist_z * mouse_dir_z * mCenterToCamNorm;
- if (cur_select_distance >= -0.05f &&
- (min_select_distance == 0.f ||
- cur_select_distance > min_select_distance))
- {
- min_select_distance = cur_select_distance;
- mHighlightedPart = LL_ROT_Z;
- }
- }
- // Test for edge-on intersections
- if (proj_rot_x_axis < 0.05f)
- {
- if ((proj_rot_y_axis > 0.05f && dist_y < mRadiusMeters &&
- dist_y * fabsf(mouse_dir_y * rot_x_axis) < distance_threshold) ||
- (proj_rot_z_axis > 0.05f && dist_z < mRadiusMeters &&
- dist_z * fabsf(mouse_dir_z * rot_x_axis) < distance_threshold))
- {
- mHighlightedPart = LL_ROT_X;
- }
- }
- if (proj_rot_y_axis < 0.05f)
- {
- if ((proj_rot_x_axis > 0.05f && dist_x < mRadiusMeters &&
- dist_x * fabsf(mouse_dir_x * rot_y_axis) < distance_threshold) ||
- (proj_rot_z_axis > 0.05f && dist_z < mRadiusMeters &&
- dist_z * fabsf(mouse_dir_z * rot_y_axis) < distance_threshold))
- {
- mHighlightedPart = LL_ROT_Y;
- }
- }
- if (proj_rot_z_axis < 0.05f)
- {
- if ((proj_rot_x_axis > 0.05f && dist_x < mRadiusMeters &&
- dist_x * fabsf(mouse_dir_x * rot_z_axis) < distance_threshold) ||
- (proj_rot_y_axis > 0.05f && dist_y < mRadiusMeters &&
- dist_y * fabsf(mouse_dir_y * rot_z_axis) < distance_threshold))
- {
- mHighlightedPart = LL_ROT_Z;
- }
- }
- // Test for roll
- if (mHighlightedPart == LL_NO_PART)
- {
- F32 roll_distance = intersection_roll.length();
- F32 width_meters = WIDTH_PIXELS * mRadiusMeters / RADIUS_PIXELS;
- // use larger distance threshold for roll as it is checked only if
- // something else wasn't highlighted
- if (fabsf(roll_distance - mRadiusMeters - width_meters * 2.f) <
- distance_threshold * 2.f)
- {
- mHighlightedPart = LL_ROT_ROLL;
- }
- else if (roll_distance < mRadiusMeters)
- {
- mHighlightedPart = LL_ROT_GENERAL;
- }
- }
- }
- S32 LLManipRotate::getObjectAxisClosestToMouse(LLVector3& object_axis)
- {
- LLSelectNode* first_object_node =
- mObjectSelection->getFirstMoveableNode(true);
- if (!first_object_node)
- {
- object_axis.clear();
- return -1;
- }
- LLQuaternion obj_rotation = first_object_node->mSavedRotation;
- LLVector3 mouse_down_object = mMouseDown * ~obj_rotation;
- LLVector3 mouse_down_abs = mouse_down_object;
- mouse_down_abs.abs();
- S32 axis_index = 0;
- if (mouse_down_abs.mV[VX] > mouse_down_abs.mV[VY] &&
- mouse_down_abs.mV[VX] > mouse_down_abs.mV[VZ])
- {
- if (mouse_down_object.mV[VX] > 0.f)
- {
- object_axis = LLVector3::x_axis;
- }
- else
- {
- object_axis = LLVector3::x_axis_neg;
- }
- axis_index = VX;
- }
- else if (mouse_down_abs.mV[VY] > mouse_down_abs.mV[VZ])
- {
- if (mouse_down_object.mV[VY] > 0.f)
- {
- object_axis = LLVector3::y_axis;
- }
- else
- {
- object_axis = LLVector3::y_axis_neg;
- }
- axis_index = VY;
- }
- else
- {
- if (mouse_down_object.mV[VZ] > 0.f)
- {
- object_axis = LLVector3::z_axis;
- }
- else
- {
- object_axis = LLVector3::z_axis_neg;
- }
- axis_index = VZ;
- }
- return axis_index;
- }
- //virtual
- bool LLManipRotate::canAffectSelection()
- {
- bool can_rotate = mObjectSelection->getObjectCount() != 0;
- if (can_rotate)
- {
- struct f final : public LLSelectedObjectFunctor
- {
- bool apply(LLViewerObject* objectp) override
- {
- static LLCachedControl<bool> edit_linked_parts(gSavedSettings,
- "EditLinkedParts");
- if (!objectp)
- {
- llwarns << "NULL object passed to functor !" << llendl;
- return false;
- }
- LLViewerObject* root_object = objectp->getRootEdit();
- return objectp->permMove() &&
- !objectp->isPermanentEnforced() &&
- (!root_object || !root_object->isPermanentEnforced()) &&
- (objectp->permModify() || !edit_linked_parts);
- }
- } func;
- can_rotate = mObjectSelection->applyToObjects(&func);
- }
- return can_rotate;
- }
|