lltoolplacer.cpp

Go to the documentation of this file.
00001 
00032 #include "llviewerprecompiledheaders.h"
00033 
00034 // self header
00035 #include "lltoolplacer.h"
00036 
00037 // linden library headers
00038 #include "llprimitive.h"
00039 
00040 // viewer headers
00041 #include "llbutton.h"
00042 #include "llviewercontrol.h"
00043 #include "llfirstuse.h"
00044 #include "llfloatertools.h"
00045 #include "llselectmgr.h"
00046 #include "llstatusbar.h"
00047 #include "lltoolcomp.h"
00048 #include "lltoolmgr.h"
00049 #include "llviewerobject.h"
00050 #include "llviewerregion.h"
00051 #include "llviewerwindow.h"
00052 #include "llworld.h"
00053 #include "llui.h"
00054 
00055 //Headers added for functions moved from viewer.cpp
00056 #include "llvograss.h"
00057 #include "llvotree.h"
00058 #include "llvolumemessage.h"
00059 #include "llhudmanager.h"
00060 #include "llagent.h"
00061 #include "audioengine.h"
00062 #include "llhudeffecttrail.h"
00063 #include "llviewerobjectlist.h"
00064 #include "llviewercamera.h"
00065 #include "llviewerstats.h"
00066 
00067 const LLVector3 DEFAULT_OBJECT_SCALE(0.5f, 0.5f, 0.5f);
00068 
00069 //static 
00070 LLPCode LLToolPlacer::sObjectType = LL_PCODE_CUBE;
00071 
00072 LLToolPlacer::LLToolPlacer()
00073 :       LLTool( "Create" )
00074 {
00075 }
00076 
00077 BOOL LLToolPlacer::raycastForNewObjPos( S32 x, S32 y, LLViewerObject** hit_obj, S32* hit_face, 
00078                                                          BOOL* b_hit_land, LLVector3* ray_start_region, LLVector3* ray_end_region, LLViewerRegion** region )
00079 {
00080         F32 max_dist_from_camera = gSavedSettings.getF32( "MaxSelectDistance" ) - 1.f;
00081 
00082         // Viewer-side pick to find the right sim to create the object on.  
00083         // First find the surface the object will be created on.
00084         gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE);
00085         
00086         // Note: use the frontmost non-flora version because (a) plants usually have lots of alpha and (b) pants' Havok
00087         // representations (if any) are NOT the same as their viewer representation.
00088         *hit_obj = gObjectList.findObject( gLastHitNonFloraObjectID );
00089         *hit_face = gLastHitNonFloraObjectFace;
00090         *b_hit_land = !(*hit_obj) && !gLastHitNonFloraPosGlobal.isExactlyZero();
00091         LLVector3d land_pos_global = gLastHitNonFloraPosGlobal;
00092 
00093         // Make sure there's a surface to place the new object on.
00094         BOOL bypass_sim_raycast = FALSE;
00095         LLVector3d      surface_pos_global;
00096         if (*b_hit_land)
00097         {
00098                 surface_pos_global = land_pos_global; 
00099                 bypass_sim_raycast = TRUE;
00100         }
00101         else 
00102         if (*hit_obj)
00103         {
00104                 surface_pos_global = (*hit_obj)->getPositionGlobal();
00105         }
00106         else
00107         {
00108                 return FALSE;
00109         }
00110 
00111         // Make sure the surface isn't too far away.
00112         LLVector3d ray_start_global = gAgent.getCameraPositionGlobal();
00113         F32 dist_to_surface_sq = (F32)((surface_pos_global - ray_start_global).magVecSquared());
00114         if( dist_to_surface_sq > (max_dist_from_camera * max_dist_from_camera) )
00115         {
00116                 return FALSE;
00117         }
00118 
00119         // Find the sim where the surface lives.
00120         LLViewerRegion *regionp = LLWorld::getInstance()->getRegionFromPosGlobal(surface_pos_global);
00121         if (!regionp)
00122         {
00123                 llwarns << "Trying to add object outside of all known regions!" << llendl;
00124                 return FALSE;
00125         }
00126 
00127         // Find the simulator-side ray that will be used to place the object accurately
00128         LLVector3d              mouse_direction;
00129         mouse_direction.setVec( gViewerWindow->mouseDirectionGlobal( x, y ) );
00130 
00131         *region = regionp;
00132         *ray_start_region =     regionp->getPosRegionFromGlobal( ray_start_global );
00133         F32 near_clip = LLViewerCamera::getInstance()->getNear() + 0.01f;  // Include an epsilon to avoid rounding issues.
00134         *ray_start_region += LLViewerCamera::getInstance()->getAtAxis() * near_clip;
00135 
00136         if( bypass_sim_raycast )
00137         {
00138                 // Hack to work around Havok's inability to ray cast onto height fields
00139                 *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global );  // ray end is the viewer's intersection point
00140         }
00141         else
00142         {
00143                 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.
00144                 *ray_end_region = regionp->getPosRegionFromGlobal( ray_end_global );
00145         }
00146 
00147         return TRUE;
00148 }
00149 
00150 
00151 BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics )
00152 {
00153         LLVector3 ray_start_region;
00154         LLVector3 ray_end_region;
00155         LLViewerRegion* regionp = NULL;
00156         BOOL b_hit_land = FALSE;
00157         S32 hit_face = -1;
00158         LLViewerObject* hit_obj = NULL;
00159         U8 state = 0;
00160         BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
00161         if( !success )
00162         {
00163                 return FALSE;
00164         }
00165 
00166         if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
00167         {
00168                 // Can't create objects on avatars or attachments
00169                 return FALSE;
00170         }
00171 
00172         if (NULL == regionp)
00173         {
00174                 llwarns << "regionp was NULL; aborting function." << llendl;
00175                 return FALSE;
00176         }
00177 
00178         if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX)
00179         {
00180                 LLFirstUse::useSandbox();
00181         }
00182 
00183         // Set params for new object based on its PCode.
00184         LLQuaternion    rotation;
00185         LLVector3               scale = DEFAULT_OBJECT_SCALE;
00186         U8                              material = LL_MCODE_WOOD;
00187         BOOL                    create_selected = FALSE;
00188         LLVolumeParams  volume_params;
00189         
00190         switch (pcode) 
00191         {
00192         case LL_PCODE_LEGACY_GRASS:
00193                 //  Randomize size of grass patch 
00194                 scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f),  1.f + ll_frand(2.f));
00195                 state = rand() % LLVOGrass::sMaxGrassSpecies;
00196                 break;
00197 
00198 
00199         case LL_PCODE_LEGACY_TREE:
00200         case LL_PCODE_TREE_NEW:
00201                 state = rand() % LLVOTree::sMaxTreeSpecies;
00202                 break;
00203 
00204         case LL_PCODE_SPHERE:
00205         case LL_PCODE_CONE:
00206         case LL_PCODE_CUBE:
00207         case LL_PCODE_CYLINDER:
00208         case LL_PCODE_TORUS:
00209         case LLViewerObject::LL_VO_SQUARE_TORUS:
00210         case LLViewerObject::LL_VO_TRIANGLE_TORUS:
00211         default:
00212                 create_selected = TRUE;
00213                 break;
00214         }
00215 
00216         // Play creation sound
00217         if (gAudiop)
00218         {
00219                 F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI");
00220                 gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume);
00221         }
00222 
00223         gMessageSystem->newMessageFast(_PREHASH_ObjectAdd);
00224         gMessageSystem->nextBlockFast(_PREHASH_AgentData);
00225         gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
00226         gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
00227         gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
00228         gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
00229         gMessageSystem->addU8Fast(_PREHASH_Material,    material);
00230 
00231         U32 flags = 0;          // not selected
00232         if (use_physics)
00233         {
00234                 flags |= FLAGS_USE_PHYSICS;
00235         }
00236         if (create_selected)
00237         {
00238                 flags |= FLAGS_CREATE_SELECTED;
00239         }
00240         gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags );
00241 
00242         LLPCode volume_pcode;   // ...PCODE_VOLUME, or the original on error
00243         switch (pcode)
00244         {
00245         case LL_PCODE_SPHERE:
00246                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
00247 
00248                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
00249                 volume_params.setBeginAndEndS( 0.f, 1.f );
00250                 volume_params.setBeginAndEndT( 0.f, 1.f );
00251                 volume_params.setRatio  ( 1, 1 );
00252                 volume_params.setShear  ( 0, 0 );
00253                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00254                 volume_pcode = LL_PCODE_VOLUME;
00255                 break;
00256 
00257         case LL_PCODE_TORUS:
00258                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
00259 
00260                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE );
00261                 volume_params.setBeginAndEndS( 0.f, 1.f );
00262                 volume_params.setBeginAndEndT( 0.f, 1.f );
00263                 volume_params.setRatio  ( 1.f, 0.25f ); // "top size"
00264                 volume_params.setShear  ( 0, 0 );
00265                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00266                 volume_pcode = LL_PCODE_VOLUME;
00267                 break;
00268 
00269         case LLViewerObject::LL_VO_SQUARE_TORUS:
00270                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
00271 
00272                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE );
00273                 volume_params.setBeginAndEndS( 0.f, 1.f );
00274                 volume_params.setBeginAndEndT( 0.f, 1.f );
00275                 volume_params.setRatio  ( 1.f, 0.25f ); // "top size"
00276                 volume_params.setShear  ( 0, 0 );
00277                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00278                 volume_pcode = LL_PCODE_VOLUME;
00279                 break;
00280 
00281         case LLViewerObject::LL_VO_TRIANGLE_TORUS:
00282                 rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis);
00283 
00284                 volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE );
00285                 volume_params.setBeginAndEndS( 0.f, 1.f );
00286                 volume_params.setBeginAndEndT( 0.f, 1.f );
00287                 volume_params.setRatio  ( 1.f, 0.25f ); // "top size"
00288                 volume_params.setShear  ( 0, 0 );
00289                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00290                 volume_pcode = LL_PCODE_VOLUME;
00291                 break;
00292 
00293         case LL_PCODE_SPHERE_HEMI:
00294                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE );
00295                 //volume_params.setBeginAndEndS( 0.5f, 1.f );
00296                 volume_params.setBeginAndEndT( 0.f, 0.5f );
00297                 volume_params.setRatio  ( 1, 1 );
00298                 volume_params.setShear  ( 0, 0 );
00299                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00300                 volume_pcode = LL_PCODE_VOLUME;
00301                 break;
00302 
00303         case LL_PCODE_CUBE:
00304                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
00305                 volume_params.setBeginAndEndS( 0.f, 1.f );
00306                 volume_params.setBeginAndEndT( 0.f, 1.f );
00307                 volume_params.setRatio  ( 1, 1 );
00308                 volume_params.setShear  ( 0, 0 );
00309                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00310                 volume_pcode = LL_PCODE_VOLUME;
00311                 break;
00312 
00313         case LL_PCODE_PRISM:
00314                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
00315                 volume_params.setBeginAndEndS( 0.f, 1.f );
00316                 volume_params.setBeginAndEndT( 0.f, 1.f );
00317                 volume_params.setRatio  ( 0, 1 );
00318                 volume_params.setShear  ( -0.5f, 0 );
00319                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00320                 volume_pcode = LL_PCODE_VOLUME;
00321                 break;
00322 
00323         case LL_PCODE_PYRAMID:
00324                 volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE );
00325                 volume_params.setBeginAndEndS( 0.f, 1.f );
00326                 volume_params.setBeginAndEndT( 0.f, 1.f );
00327                 volume_params.setRatio  ( 0, 0 );
00328                 volume_params.setShear  ( 0, 0 );
00329                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00330                 volume_pcode = LL_PCODE_VOLUME;
00331                 break;
00332 
00333         case LL_PCODE_TETRAHEDRON:
00334                 volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE );
00335                 volume_params.setBeginAndEndS( 0.f, 1.f );
00336                 volume_params.setBeginAndEndT( 0.f, 1.f );
00337                 volume_params.setRatio  ( 0, 0 );
00338                 volume_params.setShear  ( 0, 0 );
00339                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00340                 volume_pcode = LL_PCODE_VOLUME;
00341                 break;
00342 
00343         case LL_PCODE_CYLINDER:
00344                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
00345                 volume_params.setBeginAndEndS( 0.f, 1.f );
00346                 volume_params.setBeginAndEndT( 0.f, 1.f );
00347                 volume_params.setRatio  ( 1, 1 );
00348                 volume_params.setShear  ( 0, 0 );
00349                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00350                 volume_pcode = LL_PCODE_VOLUME;
00351                 break;
00352 
00353         case LL_PCODE_CYLINDER_HEMI:
00354                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
00355                 volume_params.setBeginAndEndS( 0.25f, 0.75f );
00356                 volume_params.setBeginAndEndT( 0.f, 1.f );
00357                 volume_params.setRatio  ( 1, 1 );
00358                 volume_params.setShear  ( 0, 0 );
00359                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00360                 volume_pcode = LL_PCODE_VOLUME;
00361                 break;
00362 
00363         case LL_PCODE_CONE:
00364                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
00365                 volume_params.setBeginAndEndS( 0.f, 1.f );
00366                 volume_params.setBeginAndEndT( 0.f, 1.f );
00367                 volume_params.setRatio  ( 0, 0 );
00368                 volume_params.setShear  ( 0, 0 );
00369                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00370                 volume_pcode = LL_PCODE_VOLUME;
00371                 break;
00372 
00373         case LL_PCODE_CONE_HEMI:
00374                 volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE );
00375                 volume_params.setBeginAndEndS( 0.25f, 0.75f );
00376                 volume_params.setBeginAndEndT( 0.f, 1.f );
00377                 volume_params.setRatio  ( 0, 0 );
00378                 volume_params.setShear  ( 0, 0 );
00379                 LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem);
00380                 volume_pcode = LL_PCODE_VOLUME;
00381                 break;
00382 
00383         default:
00384                 LLVolumeMessage::packVolumeParams(0, gMessageSystem);
00385                 volume_pcode = pcode;
00386                 break;
00387         }
00388         gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode);
00389 
00390         gMessageSystem->addVector3Fast(_PREHASH_Scale,                  scale );
00391         gMessageSystem->addQuatFast(_PREHASH_Rotation,                  rotation );
00392         gMessageSystem->addVector3Fast(_PREHASH_RayStart,               ray_start_region );
00393         gMessageSystem->addVector3Fast(_PREHASH_RayEnd,                 ray_end_region );
00394         gMessageSystem->addU8Fast(_PREHASH_BypassRaycast,               (U8)b_hit_land );
00395         gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE );
00396         gMessageSystem->addU8Fast(_PREHASH_State, state);
00397 
00398         // Limit raycast to a single object.  
00399         // Speeds up server raycast + avoid problems with server ray hitting objects
00400         // that were clipped by the near plane or culled on the viewer.
00401         LLUUID ray_target_id;
00402         if( hit_obj )
00403         {
00404                 ray_target_id = hit_obj->getID();
00405         }
00406         else
00407         {
00408                 ray_target_id.setNull();
00409         }
00410         gMessageSystem->addUUIDFast(_PREHASH_RayTargetID,                       ray_target_id );
00411         
00412         // Pack in name value pairs
00413         gMessageSystem->sendReliable(regionp->getHost());
00414 
00415         // Spawns a message, so must be after above send
00416         if (create_selected)
00417         {
00418                 LLSelectMgr::getInstance()->deselectAll();
00419                 gViewerWindow->getWindow()->incBusyCount();
00420         }
00421 
00422         // VEFFECT: AddObject
00423         LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE);
00424         effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject());
00425         effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region));
00426         effectp->setDuration(LL_HUD_DUR_SHORT);
00427         effectp->setColor(LLColor4U(gAgent.getEffectColor()));
00428 
00429         LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CREATE_COUNT);
00430 
00431         return TRUE;
00432 }
00433 
00434 // Used by the placer tool to add copies of the current selection.
00435 // Inspired by add_object().  JC
00436 BOOL LLToolPlacer::addDuplicate(S32 x, S32 y)
00437 {
00438         LLVector3 ray_start_region;
00439         LLVector3 ray_end_region;
00440         LLViewerRegion* regionp = NULL;
00441         BOOL b_hit_land = FALSE;
00442         S32 hit_face = -1;
00443         LLViewerObject* hit_obj = NULL;
00444         BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, &regionp );
00445         if( !success )
00446         {
00447                 make_ui_sound("UISndInvalidOp");
00448                 return FALSE;
00449         }
00450         if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
00451         {
00452                 // Can't create objects on avatars or attachments
00453                 make_ui_sound("UISndInvalidOp");
00454                 return FALSE;
00455         }
00456 
00457 
00458         // Limit raycast to a single object.  
00459         // Speeds up server raycast + avoid problems with server ray hitting objects
00460         // that were clipped by the near plane or culled on the viewer.
00461         LLUUID ray_target_id;
00462         if( hit_obj )
00463         {
00464                 ray_target_id = hit_obj->getID();
00465         }
00466         else
00467         {
00468                 ray_target_id.setNull();
00469         }
00470 
00471         LLSelectMgr::getInstance()->selectDuplicateOnRay(ray_start_region,
00472                                                                                 ray_end_region,
00473                                                                                 b_hit_land,                     // suppress raycast
00474                                                                                 FALSE,                          // intersection
00475                                                                                 ray_target_id,
00476                                                                                 gSavedSettings.getBOOL("CreateToolCopyCenters"),
00477                                                                                 gSavedSettings.getBOOL("CreateToolCopyRotates"),
00478                                                                                 FALSE);                         // select copy
00479 
00480         if (regionp
00481                 && (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX))
00482         {
00483                 LLFirstUse::useSandbox();
00484         }
00485 
00486         return TRUE;
00487 }
00488 
00489 
00490 BOOL LLToolPlacer::placeObject(S32 x, S32 y, MASK mask)
00491 {
00492         BOOL added = TRUE;
00493         
00494         if (gSavedSettings.getBOOL("CreateToolCopySelection"))
00495         {
00496                 added = addDuplicate(x, y);
00497         }
00498         else
00499         {
00500                 added = addObject( sObjectType, x, y, FALSE );
00501         }
00502 
00503         // ...and go back to the default tool
00504         if (added && !gSavedSettings.getBOOL("CreateToolKeepSelected"))
00505         {
00506                 LLToolMgr::getInstance()->getCurrentToolset()->selectTool( LLToolCompTranslate::getInstance() );
00507         }
00508 
00509         return added;
00510 }
00511 
00512 BOOL LLToolPlacer::handleHover(S32 x, S32 y, MASK mask)
00513 {
00514         lldebugst(LLERR_USER_INPUT) << "hover handled by LLToolPlacer" << llendl;               
00515         gViewerWindow->getWindow()->setCursor(UI_CURSOR_TOOLCREATE);
00516         return TRUE;
00517 }
00518 
00519 void LLToolPlacer::handleSelect()
00520 {
00521         gFloaterTools->setStatusText("place");
00522 }
00523 
00524 void LLToolPlacer::handleDeselect()
00525 {
00526 }
00527 
00529 // LLToolPlacerPanel
00530 
00531 // static
00532 LLPCode LLToolPlacerPanel::sCube                = LL_PCODE_CUBE;
00533 LLPCode LLToolPlacerPanel::sPrism               = LL_PCODE_PRISM;
00534 LLPCode LLToolPlacerPanel::sPyramid             = LL_PCODE_PYRAMID;
00535 LLPCode LLToolPlacerPanel::sTetrahedron = LL_PCODE_TETRAHEDRON;
00536 LLPCode LLToolPlacerPanel::sCylinder    = LL_PCODE_CYLINDER;
00537 LLPCode LLToolPlacerPanel::sCylinderHemi= LL_PCODE_CYLINDER_HEMI;
00538 LLPCode LLToolPlacerPanel::sCone                = LL_PCODE_CONE;
00539 LLPCode LLToolPlacerPanel::sConeHemi    = LL_PCODE_CONE_HEMI;
00540 LLPCode LLToolPlacerPanel::sTorus               = LL_PCODE_TORUS;
00541 LLPCode LLToolPlacerPanel::sSquareTorus = LLViewerObject::LL_VO_SQUARE_TORUS;
00542 LLPCode LLToolPlacerPanel::sTriangleTorus = LLViewerObject::LL_VO_TRIANGLE_TORUS;
00543 LLPCode LLToolPlacerPanel::sSphere              = LL_PCODE_SPHERE;
00544 LLPCode LLToolPlacerPanel::sSphereHemi  = LL_PCODE_SPHERE_HEMI;
00545 LLPCode LLToolPlacerPanel::sTree                = LL_PCODE_LEGACY_TREE;
00546 LLPCode LLToolPlacerPanel::sGrass               = LL_PCODE_LEGACY_GRASS;
00547 
00548 S32                     LLToolPlacerPanel::sButtonsAdded = 0;
00549 LLButton*       LLToolPlacerPanel::sButtons[ TOOL_PLACER_NUM_BUTTONS ];
00550 
00551 LLToolPlacerPanel::LLToolPlacerPanel(const std::string& name, const LLRect& rect)
00552         :
00553         LLPanel( name, rect )
00554 {
00555         /* DEPRECATED - JC
00556         addButton( "UIImgCubeUUID",                     "UIImgCubeSelectedUUID",                &LLToolPlacerPanel::sCube );
00557         addButton( "UIImgPrismUUID",            "UIImgPrismSelectedUUID",               &LLToolPlacerPanel::sPrism );
00558         addButton( "UIImgPyramidUUID",          "UIImgPyramidSelectedUUID",             &LLToolPlacerPanel::sPyramid );
00559         addButton( "UIImgTetrahedronUUID",      "UIImgTetrahedronSelectedUUID", &LLToolPlacerPanel::sTetrahedron );
00560         addButton( "UIImgCylinderUUID",         "UIImgCylinderSelectedUUID",    &LLToolPlacerPanel::sCylinder );
00561         addButton( "UIImgHalfCylinderUUID",     "UIImgHalfCylinderSelectedUUID",&LLToolPlacerPanel::sCylinderHemi );
00562         addButton( "UIImgConeUUID",                     "UIImgConeSelectedUUID",                &LLToolPlacerPanel::sCone );
00563         addButton( "UIImgHalfConeUUID",         "UIImgHalfConeSelectedUUID",    &LLToolPlacerPanel::sConeHemi );
00564         addButton( "UIImgSphereUUID",           "UIImgSphereSelectedUUID",              &LLToolPlacerPanel::sSphere );
00565         addButton( "UIImgHalfSphereUUID",       "UIImgHalfSphereSelectedUUID",  &LLToolPlacerPanel::sSphereHemi );
00566         addButton( "UIImgTreeUUID",                     "UIImgTreeSelectedUUID",                &LLToolPlacerPanel::sTree );
00567         addButton( "UIImgGrassUUID",            "UIImgGrassSelectedUUID",               &LLToolPlacerPanel::sGrass );
00568         addButton( "ObjectTorusImageID",        "ObjectTorusActiveImageID",             &LLToolPlacerPanel::sTorus );
00569         addButton( "ObjectTubeImageID",         "ObjectTubeActiveImageID",              &LLToolPlacerPanel::sSquareTorus );
00570         */
00571 }
00572 
00573 void LLToolPlacerPanel::addButton( const LLString& up_state, const LLString& down_state, LLPCode* pcode )
00574 {
00575         const S32 TOOL_SIZE = 32;
00576         const S32 HORIZ_SPACING = TOOL_SIZE + 5;
00577         const S32 VERT_SPACING = TOOL_SIZE + 5;
00578         const S32 VPAD = 10;
00579         const S32 HPAD = 7;
00580 
00581         S32 row = sButtonsAdded / 4;
00582         S32 column = sButtonsAdded % 4; 
00583 
00584         LLRect help_rect = gSavedSettings.getRect("ToolHelpRect");
00585 
00586         // Build the rectangle, recalling the origin is at lower left
00587         // and we want the icons to build down from the top.
00588         LLRect rect;
00589         rect.setLeftTopAndSize(
00590                 HPAD + (column * HORIZ_SPACING),
00591                 help_rect.mBottom - VPAD - (row * VERT_SPACING),
00592                 TOOL_SIZE,
00593                 TOOL_SIZE );
00594 
00595         LLButton* btn = new LLButton(
00596                 "ToolPlacerOptBtn",
00597                 rect,
00598                 up_state,
00599                 down_state,
00600                 "", &LLToolPlacerPanel::setObjectType,
00601                 pcode,
00602                 LLFontGL::sSansSerif);
00603         btn->setFollowsBottom();
00604         btn->setFollowsLeft();
00605         addChild(btn);
00606 
00607         sButtons[sButtonsAdded] = btn;
00608         sButtonsAdded++;
00609 }
00610 
00611 // static 
00612 void    LLToolPlacerPanel::setObjectType( void* data )
00613 {
00614         LLPCode pcode = *(LLPCode*) data;
00615         LLToolPlacer::setObjectType( pcode );
00616 }

Generated on Fri May 16 08:34:08 2008 for SecondLife by  doxygen 1.5.5