BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) { LLVector3 ray_start_region; LLVector3 ray_end_region; LLViewerRegion* regionp = NULL; BOOL b_hit_land = FALSE; S32 hit_face = -1; LLViewerObject* hit_obj = NULL; U8 state = 0; BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp ); if( !success ) { return FALSE; } if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) ) { // Can't create objects on avatars or attachments return FALSE; } if (NULL == regionp) { llwarns << "regionp was NULL; aborting function." << llendl; return FALSE; } if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX) { LLFirstUse::useSandbox(); } // Set params for new object based on its PCode. LLQuaternion rotation; LLVector3 scale = DEFAULT_OBJECT_SCALE; U8 material = LL_MCODE_WOOD; BOOL create_selected = FALSE; LLVolumeParams volume_params; switch (pcode) { case LL_PCODE_LEGACY_GRASS: // Randomize size of grass patch scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f)); state = rand() % LLVOGrass::sMaxGrassSpecies; break; case LL_PCODE_LEGACY_TREE: case LL_PCODE_TREE_NEW: state = rand() % LLVOTree::sMaxTreeSpecies; break; case LL_PCODE_SPHERE: case LL_PCODE_CONE: case LL_PCODE_CUBE: case LL_PCODE_CYLINDER: case LL_PCODE_TORUS: case LLViewerObject::LL_VO_SQUARE_TORUS: case LLViewerObject::LL_VO_TRIANGLE_TORUS: default: create_selected = TRUE; break; } // Play creation sound if (gAudiop) { F32 volume = gSavedSettings.getBOOL("MuteUI") ? 0.f : gSavedSettings.getF32("AudioLevelUI"); gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), volume); } gMessageSystem->newMessageFast(_PREHASH_ObjectAdd); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU8Fast(_PREHASH_Material, material); U32 flags = 0; // not selected if (use_physics) { flags |= FLAGS_USE_PHYSICS; } if (create_selected) { flags |= FLAGS_CREATE_SELECTED; } gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags ); LLPCode volume_pcode; // ...PCODE_VOLUME, or the original on error switch (pcode) { case LL_PCODE_SPHERE: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LLViewerObject::LL_VO_SQUARE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LLViewerObject::LL_VO_TRIANGLE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_SPHERE_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); //volume_params.setBeginAndEndS( 0.5f, 1.f ); volume_params.setBeginAndEndT( 0.f, 0.5f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CUBE: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_PRISM: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 1 ); volume_params.setShear ( -0.5f, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_PYRAMID: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_TETRAHEDRON: volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CYLINDER: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CYLINDER_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.25f, 0.75f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CONE: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CONE_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.25f, 0.75f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; default: LLVolumeMessage::packVolumeParams(0, gMessageSystem); volume_pcode = pcode; break; } gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode); gMessageSystem->addVector3Fast(_PREHASH_Scale, scale ); gMessageSystem->addQuatFast(_PREHASH_Rotation, rotation ); gMessageSystem->addVector3Fast(_PREHASH_RayStart, ray_start_region ); gMessageSystem->addVector3Fast(_PREHASH_RayEnd, ray_end_region ); gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, (U8)b_hit_land ); gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE ); gMessageSystem->addU8Fast(_PREHASH_State, state); // Limit raycast to a single object. // Speeds up server raycast + avoid problems with server ray hitting objects // that were clipped by the near plane or culled on the viewer. LLUUID ray_target_id; if( hit_obj ) { ray_target_id = hit_obj->getID(); } else { ray_target_id.setNull(); } gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, ray_target_id ); // Pack in name value pairs gMessageSystem->sendReliable(regionp->getHost()); // Spawns a message, so must be after above send if (create_selected) { gSelectMgr->deselectAll(); gViewerWindow->getWindow()->incBusyCount(); } // VEFFECT: AddObject LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)gHUDManager->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject()); effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region)); effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); gViewerStats->incStat(LLViewerStats::ST_CREATE_COUNT); return TRUE; }
// static void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) { llassert(msg); if (!msg) return; //const S32 SIM_NAME_BUF = 256; U64 region_flags; U8 sim_access; U8 agent_limit; std::string sim_name; U32 estate_id; U32 parent_estate_id; F32 water_height; F32 billable_factor; F32 object_bonus_factor; F32 terrain_raise_limit; F32 terrain_lower_limit; S32 price_per_meter; S32 redirect_grid_x; S32 redirect_grid_y; LLUUID cache_id; LLHost host = msg->getSender(); msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, sim_name); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess, sim_access); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents, agent_limit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); if (msg->has(_PREHASH_RegionInfo3)) { msg->getU64Fast(_PREHASH_RegionInfo3, _PREHASH_RegionFlagsExtended, region_flags); } else { U32 flags = 0; msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, flags); region_flags = flags; } if (host != gAgent.getRegionHost()) { // Update is for a different region than the one we're in. // Just check for a waterheight change. LLWorld::getInstance()->waterHeightRegionInfo(sim_name, water_height); return; } msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, price_per_meter); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridX, redirect_grid_x); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridY, redirect_grid_y); // push values to the current LLViewerRegion LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { regionp->setRegionNameAndZone(sim_name); regionp->setRegionFlags(region_flags); regionp->setSimAccess(sim_access); regionp->setWaterHeight(water_height); regionp->setBillableFactor(billable_factor); } LLFloaterGodTools* god_tools = LLFloaterReg::getTypedInstance<LLFloaterGodTools>("god_tools"); if (!god_tools) return; // push values to god tools, if available if ( gAgent.isGodlike() && LLFloaterReg::instanceVisible("god_tools") && god_tools->mPanelRegionTools && god_tools->mPanelObjectTools) { LLPanelRegionTools* rtool = god_tools->mPanelRegionTools; god_tools->mCurrentHost = host; // store locally rtool->setSimName(sim_name); rtool->setEstateID(estate_id); rtool->setParentEstateID(parent_estate_id); rtool->setCheckFlags(region_flags); rtool->setBillableFactor(billable_factor); rtool->setPricePerMeter(price_per_meter); rtool->setRedirectGridX(redirect_grid_x); rtool->setRedirectGridY(redirect_grid_y); rtool->enableAllWidgets(); LLPanelObjectTools *otool = god_tools->mPanelObjectTools; otool->setCheckFlags(region_flags); otool->enableAllWidgets(); LLViewerRegion *regionp = gAgent.getRegion(); if ( !regionp ) { // -1 implies non-existent rtool->setGridPosX(-1); rtool->setGridPosY(-1); } else { //compute the grid position of the region LLVector3d global_pos = regionp->getPosGlobalFromRegion(LLVector3::zero); S32 grid_pos_x = (S32) (global_pos.mdV[VX] / 256.0f); S32 grid_pos_y = (S32) (global_pos.mdV[VY] / 256.0f); rtool->setGridPosX(grid_pos_x); rtool->setGridPosY(grid_pos_y); } } }
// static void LLFloaterGodTools::processRegionInfo(LLMessageSystem* msg) { LLHost host = msg->getSender(); if (host != gAgent.getRegionHost()) { // update is for a different region than the one we're in return; } //const S32 SIM_NAME_BUF = 256; U32 region_flags; U8 sim_access; U8 agent_limit; char sim_name[MAX_STRING]; /*Flawfinder: ignore*/ U32 estate_id; U32 parent_estate_id; F32 water_height; F32 billable_factor; F32 object_bonus_factor; F32 terrain_raise_limit; F32 terrain_lower_limit; S32 price_per_meter; S32 redirect_grid_x; S32 redirect_grid_y; LLUUID cache_id; msg->getStringFast(_PREHASH_RegionInfo, _PREHASH_SimName, MAX_STRING, sim_name); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_EstateID, estate_id); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_ParentEstateID, parent_estate_id); msg->getU32Fast(_PREHASH_RegionInfo, _PREHASH_RegionFlags, region_flags); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_SimAccess, sim_access); msg->getU8Fast(_PREHASH_RegionInfo, _PREHASH_MaxAgents, agent_limit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_ObjectBonusFactor, object_bonus_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_BillableFactor, billable_factor); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_WaterHeight, water_height); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainRaiseLimit, terrain_raise_limit); msg->getF32Fast(_PREHASH_RegionInfo, _PREHASH_TerrainLowerLimit, terrain_lower_limit); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_PricePerMeter, price_per_meter); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridX, redirect_grid_x); msg->getS32Fast(_PREHASH_RegionInfo, _PREHASH_RedirectGridY, redirect_grid_y); // push values to the current LLViewerRegion LLViewerRegion *regionp = gAgent.getRegion(); if (regionp) { regionp->setRegionNameAndZone(sim_name); regionp->setRegionFlags(region_flags); regionp->setSimAccess(sim_access); regionp->setWaterHeight(water_height); regionp->setBillableFactor(billable_factor); } // push values to god tools, if available if (sGodTools && sGodTools->mPanelRegionTools && sGodTools->mPanelObjectTools && msg && gAgent.isGodlike()) { LLPanelRegionTools* rtool = sGodTools->mPanelRegionTools; sGodTools->mCurrentHost = host; // store locally rtool->setSimName(sim_name); rtool->setEstateID(estate_id); rtool->setParentEstateID(parent_estate_id); rtool->setCheckFlags(region_flags); rtool->setBillableFactor(billable_factor); rtool->setPricePerMeter(price_per_meter); rtool->setRedirectGridX(redirect_grid_x); rtool->setRedirectGridY(redirect_grid_y); rtool->enableAllWidgets(); LLPanelObjectTools *otool = sGodTools->mPanelObjectTools; otool->setCheckFlags(region_flags); otool->enableAllWidgets(); LLViewerRegion *regionp = gAgent.getRegion(); if ( !regionp ) { // -1 implies non-existent rtool->setGridPosX(-1); rtool->setGridPosY(-1); } else { //compute the grid position of the region LLVector3d global_pos = regionp->getPosGlobalFromRegion(LLVector3::zero); S32 grid_pos_x = (S32) (global_pos.mdV[VX] / 256.0f); S32 grid_pos_y = (S32) (global_pos.mdV[VY] / 256.0f); rtool->setGridPosX(grid_pos_x); rtool->setGridPosY(grid_pos_y); } } }
LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) { if (positionRegionValidGlobal(end_pos)) { return end_pos; } LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); if (!regionp) { return start_pos; } LLVector3d delta_pos = end_pos - start_pos; LLVector3d delta_pos_abs; delta_pos_abs.setVec(delta_pos); delta_pos_abs.abs(); LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); F64 clip_factor = 1.0; F32 region_width = regionp->getWidth(); if (region_coord.mV[VX] < 0.f) { if (region_coord.mV[VY] < region_coord.mV[VX]) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else { // clip along x - clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); } } else if (region_coord.mV[VX] > region_width) { if (region_coord.mV[VY] > region_coord.mV[VX]) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } else { //clip along x + clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; } } else if (region_coord.mV[VY] < 0.f) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else if (region_coord.mV[VY] > region_width) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } // clamp to within region dimensions LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); final_region_pos.mdV[VX] = llclamp(final_region_pos.mdV[VX], 0.0, (F64)(region_width - F_ALMOST_ZERO)); final_region_pos.mdV[VY] = llclamp(final_region_pos.mdV[VY], 0.0, (F64)(region_width - F_ALMOST_ZERO)); final_region_pos.mdV[VZ] = llclamp(final_region_pos.mdV[VZ], 0.0, (F64)(LLWorld::getInstance()->getRegionMaxHeight() - F_ALMOST_ZERO)); return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); }
LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) { if (positionRegionValidGlobal(end_pos)) { return end_pos; } LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); if (!regionp) { return start_pos; } LLVector3d delta_pos = end_pos - start_pos; LLVector3d delta_pos_abs; delta_pos_abs.setVec(delta_pos); delta_pos_abs.abs(); LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); F64 clip_factor = 1.0; F32 region_width = regionp->getWidth(); if (region_coord.mV[VX] < 0.f) { if (region_coord.mV[VY] < region_coord.mV[VX]) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else { // clip along x - clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); } } else if (region_coord.mV[VX] > region_width) { if (region_coord.mV[VY] > region_coord.mV[VX]) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } else { //clip along x + clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; } } else if (region_coord.mV[VY] < 0.f) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else if (region_coord.mV[VY] > region_width) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } // clamp to < 256 to stay in sim LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); final_region_pos.clamp(0.0, 255.999); return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); }
BOOL LLToolPlacer::addObject( LLPCode pcode, S32 x, S32 y, U8 use_physics ) { LLVector3 ray_start_region; LLVector3 ray_end_region; LLViewerRegion* regionp = NULL; BOOL b_hit_land = FALSE; S32 hit_face = -1; LLViewerObject* hit_obj = NULL; U8 state = 0; BOOL success = raycastForNewObjPos( x, y, &hit_obj, &hit_face, &b_hit_land, &ray_start_region, &ray_end_region, ®ionp ); if( !success ) { return FALSE; } if( hit_obj && (hit_obj->isAvatar() || hit_obj->isAttachment()) ) { // Can't create objects on avatars or attachments return FALSE; } if (NULL == regionp) { llwarns << "regionp was NULL; aborting function." << llendl; return FALSE; } if (regionp->getRegionFlags() & REGION_FLAGS_SANDBOX) { LLFirstUse::useSandbox(); } // Set params for new object based on its PCode. LLQuaternion rotation; LLVector3 scale = LLVector3( gSavedSettings.getF32("EmeraldBuildPrefs_Xsize"), gSavedSettings.getF32("EmeraldBuildPrefs_Ysize"), gSavedSettings.getF32("EmeraldBuildPrefs_Zsize")); U8 material = LL_MCODE_WOOD; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Stone") material = LL_MCODE_STONE; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Metal") material = LL_MCODE_METAL; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Wood") material = LL_MCODE_WOOD; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Flesh") material = LL_MCODE_FLESH; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Rubber") material = LL_MCODE_RUBBER; if(gSavedSettings.getString("EmeraldBuildPrefs_Material")== "Plastic") material = LL_MCODE_PLASTIC; BOOL create_selected = FALSE; LLVolumeParams volume_params; switch (pcode) { case LL_PCODE_LEGACY_GRASS: // Randomize size of grass patch scale.setVec(10.f + ll_frand(20.f), 10.f + ll_frand(20.f), 1.f + ll_frand(2.f)); state = rand() % LLVOGrass::sMaxGrassSpecies; break; case LL_PCODE_LEGACY_TREE: case LL_PCODE_TREE_NEW: state = rand() % LLVOTree::sMaxTreeSpecies; break; case LL_PCODE_SPHERE: case LL_PCODE_CONE: case LL_PCODE_CUBE: case LL_PCODE_CYLINDER: case LL_PCODE_TORUS: case LLViewerObject::LL_VO_SQUARE_TORUS: case LLViewerObject::LL_VO_TRIANGLE_TORUS: default: create_selected = TRUE; break; } // Play creation sound if (gAudiop) { gAudiop->triggerSound( LLUUID(gSavedSettings.getString("UISndObjectCreate")), gAgent.getID(), 1.0f, LLAudioEngine::AUDIO_TYPE_UI); } gMessageSystem->newMessageFast(_PREHASH_ObjectAdd); gMessageSystem->nextBlockFast(_PREHASH_AgentData); gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); //MOYMOD 2009-05, If avatar is in land group/land owner group, // it rezzes it with it to prevent autoreturn/whatever if(gSavedSettings.getBOOL("mm_alwaysRezWithLandGroup")){ LLParcel *parcel = LLViewerParcelMgr::getInstance()->getAgentParcel(); if(gAgent.isInGroup(parcel->getGroupID())){ gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getGroupID()); }else if(gAgent.isInGroup(parcel->getOwnerID())){ gMessageSystem->addUUIDFast(_PREHASH_GroupID, parcel->getOwnerID()); }else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); }else gMessageSystem->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); gMessageSystem->nextBlockFast(_PREHASH_ObjectData); gMessageSystem->addU8Fast(_PREHASH_Material, material); U32 flags = 0; // not selected if (use_physics || gSavedSettings.getBOOL("EmeraldBuildPrefs_Physical")) { flags |= FLAGS_USE_PHYSICS; } //if (create_selected) // [RLVa:KB] - Checked: 2009-07-04 (RLVa-1.0.0b) | Added: RLVa-1.0.0b if ( (create_selected) && (!gRlvHandler.hasBehaviour(RLV_BHVR_EDIT)) ) // [/RLVa:KB] { flags |= FLAGS_CREATE_SELECTED; } gMessageSystem->addU32Fast(_PREHASH_AddFlags, flags ); LLPCode volume_pcode; // ...PCODE_VOLUME, or the original on error switch (pcode) { case LL_PCODE_SPHERE: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LLViewerObject::LL_VO_SQUARE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LLViewerObject::LL_VO_TRIANGLE_TORUS: rotation.setQuat(90.f * DEG_TO_RAD, LLVector3::y_axis); volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_CIRCLE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1.f, 0.25f ); // "top size" volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_SPHERE_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE_HALF, LL_PCODE_PATH_CIRCLE ); //volume_params.setBeginAndEndS( 0.5f, 1.f ); volume_params.setBeginAndEndT( 0.f, 0.5f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CUBE: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_PRISM: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 1 ); volume_params.setShear ( -0.5f, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_PYRAMID: volume_params.setType( LL_PCODE_PROFILE_SQUARE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_TETRAHEDRON: volume_params.setType( LL_PCODE_PROFILE_EQUALTRI, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CYLINDER: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CYLINDER_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.25f, 0.75f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 1, 1 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CONE: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.f, 1.f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; case LL_PCODE_CONE_HEMI: volume_params.setType( LL_PCODE_PROFILE_CIRCLE, LL_PCODE_PATH_LINE ); volume_params.setBeginAndEndS( 0.25f, 0.75f ); volume_params.setBeginAndEndT( 0.f, 1.f ); volume_params.setRatio ( 0, 0 ); volume_params.setShear ( 0, 0 ); LLVolumeMessage::packVolumeParams(&volume_params, gMessageSystem); volume_pcode = LL_PCODE_VOLUME; break; default: LLVolumeMessage::packVolumeParams(0, gMessageSystem); volume_pcode = pcode; break; } gMessageSystem->addU8Fast(_PREHASH_PCode, volume_pcode); gMessageSystem->addVector3Fast(_PREHASH_Scale, scale ); gMessageSystem->addQuatFast(_PREHASH_Rotation, rotation ); gMessageSystem->addVector3Fast(_PREHASH_RayStart, ray_start_region ); gMessageSystem->addVector3Fast(_PREHASH_RayEnd, ray_end_region ); gMessageSystem->addU8Fast(_PREHASH_BypassRaycast, (U8)b_hit_land ); gMessageSystem->addU8Fast(_PREHASH_RayEndIsIntersection, (U8)FALSE ); gMessageSystem->addU8Fast(_PREHASH_State, state); // Limit raycast to a single object. // Speeds up server raycast + avoid problems with server ray hitting objects // that were clipped by the near plane or culled on the viewer. LLUUID ray_target_id; if( hit_obj ) { ray_target_id = hit_obj->getID(); } else { ray_target_id.setNull(); } gMessageSystem->addUUIDFast(_PREHASH_RayTargetID, ray_target_id ); // Pack in name value pairs gMessageSystem->sendReliable(regionp->getHost()); //lgg set flag to set texture here gImportTracker.expectRez(); // Spawns a message, so must be after above send if (create_selected) { LLSelectMgr::getInstance()->deselectAll(); gViewerWindow->getWindow()->incBusyCount(); } // VEFFECT: AddObject LLHUDEffectSpiral *effectp = (LLHUDEffectSpiral *)LLHUDManager::getInstance()->createViewerEffect(LLHUDObject::LL_HUD_EFFECT_BEAM, TRUE); effectp->setSourceObject((LLViewerObject*)gAgent.getAvatarObject()); effectp->setPositionGlobal(regionp->getPosGlobalFromRegion(ray_end_region)); effectp->setDuration(LL_HUD_DUR_SHORT); effectp->setColor(LLColor4U(gAgent.getEffectColor())); LLViewerStats::getInstance()->incStat(LLViewerStats::ST_CREATE_COUNT); return TRUE; }
LLVector3d LLWorld::clipToVisibleRegions(const LLVector3d &start_pos, const LLVector3d &end_pos) { if (positionRegionValidGlobal(end_pos)) { return end_pos; } LLViewerRegion* regionp = getRegionFromPosGlobal(start_pos); if (!regionp) { return start_pos; } LLVector3d delta_pos = end_pos - start_pos; LLVector3d delta_pos_abs; delta_pos_abs.setVec(delta_pos); delta_pos_abs.abs(); LLVector3 region_coord = regionp->getPosRegionFromGlobal(end_pos); F64 clip_factor = 1.0; F32 region_width = regionp->getWidth(); if (region_coord.mV[VX] < 0.f) { if (region_coord.mV[VY] < region_coord.mV[VX]) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else { // clip along x - clip_factor = -(region_coord.mV[VX] / delta_pos_abs.mdV[VX]); } } else if (region_coord.mV[VX] > region_width) { if (region_coord.mV[VY] > region_coord.mV[VX]) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } else { //clip along x + clip_factor = (region_coord.mV[VX] - region_width) / delta_pos_abs.mdV[VX]; } } else if (region_coord.mV[VY] < 0.f) { // clip along y - clip_factor = -(region_coord.mV[VY] / delta_pos_abs.mdV[VY]); } else if (region_coord.mV[VY] > region_width) { // clip along y + clip_factor = (region_coord.mV[VY] - region_width) / delta_pos_abs.mdV[VY]; } // clamp to < 256 to stay in sim LLVector3d final_region_pos = LLVector3d(region_coord) - (delta_pos * clip_factor); // clamp x, y to [0,256[ and z to [0,REGION_HEIGHT_METERS] (the clamp function cannot be used here) if (final_region_pos.mdV[VX] < 0) final_region_pos.mdV[VX] = 0.0; if (final_region_pos.mdV[VY] < 0) final_region_pos.mdV[VY] = 0.0; if (final_region_pos.mdV[VZ] < 0) final_region_pos.mdV[VZ] = 0.0; if (final_region_pos.mdV[VX] > 255.999) final_region_pos.mdV[VX] = 255.999; if (final_region_pos.mdV[VY] > 255.999) final_region_pos.mdV[VY] = 255.999; if (final_region_pos.mdV[VZ] > REGION_HEIGHT_METERS) final_region_pos.mdV[VZ] = REGION_HEIGHT_METERS; //final_region_pos.clamp(0.0, 255.999); return regionp->getPosGlobalFromRegion(LLVector3(final_region_pos)); }