00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034
00035 #include "lltoolplacer.h"
00036
00037
00038 #include "llprimitive.h"
00039
00040
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
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
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
00083
00084 gViewerWindow->hitObjectOrLandGlobalImmediate(x, y, NULL, FALSE);
00085
00086
00087
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
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
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
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
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;
00134 *ray_start_region += LLViewerCamera::getInstance()->getAtAxis() * near_clip;
00135
00136 if( bypass_sim_raycast )
00137 {
00138
00139 *ray_end_region = regionp->getPosRegionFromGlobal( surface_pos_global );
00140 }
00141 else
00142 {
00143 LLVector3d ray_end_global = ray_start_global + (1.f + max_dist_from_camera) * mouse_direction;
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, ®ionp );
00161 if( !success )
00162 {
00163 return FALSE;
00164 }
00165
00166 if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) )
00167 {
00168
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
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
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
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;
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;
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 );
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 );
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 );
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
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
00399
00400
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
00413 gMessageSystem->sendReliable(regionp->getHost());
00414
00415
00416 if (create_selected)
00417 {
00418 LLSelectMgr::getInstance()->deselectAll();
00419 gViewerWindow->getWindow()->incBusyCount();
00420 }
00421
00422
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
00435
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, ®ionp );
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
00453 make_ui_sound("UISndInvalidOp");
00454 return FALSE;
00455 }
00456
00457
00458
00459
00460
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,
00474 FALSE,
00475 ray_target_id,
00476 gSavedSettings.getBOOL("CreateToolCopyCenters"),
00477 gSavedSettings.getBOOL("CreateToolCopyRotates"),
00478 FALSE);
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
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
00530
00531
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
00556
00557
00558
00559
00560
00561
00562
00563
00564
00565
00566
00567
00568
00569
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
00587
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
00612 void LLToolPlacerPanel::setObjectType( void* data )
00613 {
00614 LLPCode pcode = *(LLPCode*) data;
00615 LLToolPlacer::setObjectType( pcode );
00616 }