diff options
Diffstat (limited to 'indra/newview')
-rw-r--r-- | indra/newview/llpanelobject.cpp | 3998 | ||||
-rw-r--r-- | indra/newview/llviewerobject.cpp | 11424 | ||||
-rw-r--r-- | indra/newview/llviewerobject.h | 1650 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_preview.xml | 1094 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_model_wizard.xml | 2078 | ||||
-rw-r--r-- | indra/newview/skins/default/xui/en/floater_tools.xml | 6388 |
6 files changed, 13316 insertions, 13316 deletions
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index 34a92cd0ac..74f48907d2 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1,1999 +1,1999 @@ -/** - * @file llpanelobject.cpp - * @brief Object editing (position, scale, etc.) in the tools floater - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -// file include -#include "llpanelobject.h" - -// linden library includes -#include "lleconomy.h" -#include "llerror.h" -#include "llfontgl.h" -#include "llpermissionsflags.h" -#include "llstring.h" -#include "llvolume.h" -#include "m3math.h" - -// project includes -#include "llagent.h" -#include "llbutton.h" -#include "llcheckboxctrl.h" -#include "llcolorswatch.h" -#include "llcombobox.h" -#include "llfocusmgr.h" -#include "llmanipscale.h" -#include "llpreviewscript.h" -#include "llresmgr.h" -#include "llselectmgr.h" -#include "llspinctrl.h" -#include "lltexturectrl.h" -#include "lltextbox.h" -#include "lltool.h" -#include "lltoolcomp.h" -#include "lltoolmgr.h" -#include "llui.h" -#include "llviewerobject.h" -#include "llviewerregion.h" -#include "llviewerwindow.h" -#include "llvovolume.h" -#include "llworld.h" -#include "pipeline.h" -#include "llviewercontrol.h" -#include "lluictrlfactory.h" -//#include "llfirstuse.h" - -#include "lldrawpool.h" - -// -// Constants -// -enum { - MI_BOX, - MI_CYLINDER, - MI_PRISM, - MI_SPHERE, - MI_TORUS, - MI_TUBE, - MI_RING, - MI_SCULPT, - MI_NONE, - MI_VOLUME_COUNT -}; - -enum { - MI_HOLE_SAME, - MI_HOLE_CIRCLE, - MI_HOLE_SQUARE, - MI_HOLE_TRIANGLE, - MI_HOLE_COUNT -}; - -//static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright"); - -BOOL LLPanelObject::postBuild() -{ - setMouseOpaque(FALSE); - - //-------------------------------------------------------- - // Top - //-------------------------------------------------------- - - // Lock checkbox - mCheckLock = getChild<LLCheckBoxCtrl>("checkbox locked"); - childSetCommitCallback("checkbox locked",onCommitLock,this); - - // Physical checkbox - mCheckPhysics = getChild<LLCheckBoxCtrl>("Physical Checkbox Ctrl"); - childSetCommitCallback("Physical Checkbox Ctrl",onCommitPhysics,this); - - // Temporary checkbox - mCheckTemporary = getChild<LLCheckBoxCtrl>("Temporary Checkbox Ctrl"); - childSetCommitCallback("Temporary Checkbox Ctrl",onCommitTemporary,this); - - // Phantom checkbox - mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl"); - childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this); - - - // Position - mLabelPosition = getChild<LLTextBox>("label position"); - mCtrlPosX = getChild<LLSpinCtrl>("Pos X"); - childSetCommitCallback("Pos X",onCommitPosition,this); - mCtrlPosY = getChild<LLSpinCtrl>("Pos Y"); - childSetCommitCallback("Pos Y",onCommitPosition,this); - mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z"); - childSetCommitCallback("Pos Z",onCommitPosition,this); - - // Scale - mLabelSize = getChild<LLTextBox>("label size"); - mCtrlScaleX = getChild<LLSpinCtrl>("Scale X"); - childSetCommitCallback("Scale X",onCommitScale,this); - - // Scale Y - mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y"); - childSetCommitCallback("Scale Y",onCommitScale,this); - - // Scale Z - mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z"); - childSetCommitCallback("Scale Z",onCommitScale,this); - - // Rotation - mLabelRotation = getChild<LLTextBox>("label rotation"); - mCtrlRotX = getChild<LLSpinCtrl>("Rot X"); - childSetCommitCallback("Rot X",onCommitRotation,this); - mCtrlRotY = getChild<LLSpinCtrl>("Rot Y"); - childSetCommitCallback("Rot Y",onCommitRotation,this); - mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z"); - childSetCommitCallback("Rot Z",onCommitRotation,this); - - //-------------------------------------------------------- - - // Base Type - mComboBaseType = getChild<LLComboBox>("comboBaseType"); - childSetCommitCallback("comboBaseType",onCommitParametric,this); - - // Cut - mLabelCut = getChild<LLTextBox>("text cut"); - mSpinCutBegin = getChild<LLSpinCtrl>("cut begin"); - childSetCommitCallback("cut begin",onCommitParametric,this); - mSpinCutBegin->setValidateBeforeCommit( precommitValidate ); - mSpinCutEnd = getChild<LLSpinCtrl>("cut end"); - childSetCommitCallback("cut end",onCommitParametric,this); - mSpinCutEnd->setValidateBeforeCommit( &precommitValidate ); - - // Hollow / Skew - mLabelHollow = getChild<LLTextBox>("text hollow"); - mLabelSkew = getChild<LLTextBox>("text skew"); - mSpinHollow = getChild<LLSpinCtrl>("Scale 1"); - childSetCommitCallback("Scale 1",onCommitParametric,this); - mSpinHollow->setValidateBeforeCommit( &precommitValidate ); - mSpinSkew = getChild<LLSpinCtrl>("Skew"); - childSetCommitCallback("Skew",onCommitParametric,this); - mSpinSkew->setValidateBeforeCommit( &precommitValidate ); - mLabelHoleType = getChild<LLTextBox>("Hollow Shape"); - - // Hole Type - mComboHoleType = getChild<LLComboBox>("hole"); - childSetCommitCallback("hole",onCommitParametric,this); - - // Twist - mLabelTwist = getChild<LLTextBox>("text twist"); - mSpinTwistBegin = getChild<LLSpinCtrl>("Twist Begin"); - childSetCommitCallback("Twist Begin",onCommitParametric,this); - mSpinTwistBegin->setValidateBeforeCommit( precommitValidate ); - mSpinTwist = getChild<LLSpinCtrl>("Twist End"); - childSetCommitCallback("Twist End",onCommitParametric,this); - mSpinTwist->setValidateBeforeCommit( &precommitValidate ); - - // Scale - mSpinScaleX = getChild<LLSpinCtrl>("Taper Scale X"); - childSetCommitCallback("Taper Scale X",onCommitParametric,this); - mSpinScaleX->setValidateBeforeCommit( &precommitValidate ); - mSpinScaleY = getChild<LLSpinCtrl>("Taper Scale Y"); - childSetCommitCallback("Taper Scale Y",onCommitParametric,this); - mSpinScaleY->setValidateBeforeCommit( &precommitValidate ); - - // Shear - mLabelShear = getChild<LLTextBox>("text topshear"); - mSpinShearX = getChild<LLSpinCtrl>("Shear X"); - childSetCommitCallback("Shear X",onCommitParametric,this); - mSpinShearX->setValidateBeforeCommit( &precommitValidate ); - mSpinShearY = getChild<LLSpinCtrl>("Shear Y"); - childSetCommitCallback("Shear Y",onCommitParametric,this); - mSpinShearY->setValidateBeforeCommit( &precommitValidate ); - - // Path / Profile - mCtrlPathBegin = getChild<LLSpinCtrl>("Path Limit Begin"); - childSetCommitCallback("Path Limit Begin",onCommitParametric,this); - mCtrlPathBegin->setValidateBeforeCommit( &precommitValidate ); - mCtrlPathEnd = getChild<LLSpinCtrl>("Path Limit End"); - childSetCommitCallback("Path Limit End",onCommitParametric,this); - mCtrlPathEnd->setValidateBeforeCommit( &precommitValidate ); - - // Taper - mLabelTaper = getChild<LLTextBox>("text taper2"); - mSpinTaperX = getChild<LLSpinCtrl>("Taper X"); - childSetCommitCallback("Taper X",onCommitParametric,this); - mSpinTaperX->setValidateBeforeCommit( precommitValidate ); - mSpinTaperY = getChild<LLSpinCtrl>("Taper Y"); - childSetCommitCallback("Taper Y",onCommitParametric,this); - mSpinTaperY->setValidateBeforeCommit( precommitValidate ); - - // Radius Offset / Revolutions - mLabelRadiusOffset = getChild<LLTextBox>("text radius delta"); - mLabelRevolutions = getChild<LLTextBox>("text revolutions"); - mSpinRadiusOffset = getChild<LLSpinCtrl>("Radius Offset"); - childSetCommitCallback("Radius Offset",onCommitParametric,this); - mSpinRadiusOffset->setValidateBeforeCommit( &precommitValidate ); - mSpinRevolutions = getChild<LLSpinCtrl>("Revolutions"); - childSetCommitCallback("Revolutions",onCommitParametric,this); - mSpinRevolutions->setValidateBeforeCommit( &precommitValidate ); - - // Sculpt - mCtrlSculptTexture = getChild<LLTextureCtrl>("sculpt texture control"); - if (mCtrlSculptTexture) - { - mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE)); - mCtrlSculptTexture->setCommitCallback( boost::bind(&LLPanelObject::onCommitSculpt, this, _2 )); - mCtrlSculptTexture->setOnCancelCallback( boost::bind(&LLPanelObject::onCancelSculpt, this, _2 )); - mCtrlSculptTexture->setOnSelectCallback( boost::bind(&LLPanelObject::onSelectSculpt, this, _2 )); - mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 )); - // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode - mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER); - // Allow any texture to be used during non-immediate mode. - mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE); - LLAggregatePermissions texture_perms; - if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms)) - { - BOOL can_copy = - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL; - BOOL can_transfer = - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY || - texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL; - mCtrlSculptTexture->setCanApplyImmediately(can_copy && can_transfer); - } - else - { - mCtrlSculptTexture->setCanApplyImmediately(FALSE); - } - } - - mLabelSculptType = getChild<LLTextBox>("label sculpt type"); - mCtrlSculptType = getChild<LLComboBox>("sculpt type control"); - childSetCommitCallback("sculpt type control", onCommitSculptType, this); - mCtrlSculptMirror = getChild<LLCheckBoxCtrl>("sculpt mirror control"); - childSetCommitCallback("sculpt mirror control", onCommitSculptType, this); - mCtrlSculptInvert = getChild<LLCheckBoxCtrl>("sculpt invert control"); - childSetCommitCallback("sculpt invert control", onCommitSculptType, this); - - // Start with everyone disabled - clearCtrls(); - - return TRUE; -} - -LLPanelObject::LLPanelObject() -: LLPanel(), - mIsPhysical(FALSE), - mIsTemporary(FALSE), - mIsPhantom(FALSE), - mCastShadows(TRUE), - mSelectedType(MI_BOX), - mSculptTextureRevert(LLUUID::null), - mSculptTypeRevert(0) -{ -} - - -LLPanelObject::~LLPanelObject() -{ - // Children all cleaned up by default view destructor. -} - -void LLPanelObject::getState( ) -{ - LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject(); - LLViewerObject* root_objectp = objectp; - if(!objectp) - { - objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject(); - // *FIX: shouldn't we just keep the child? - if (objectp) - { - LLViewerObject* parentp = objectp->getRootEdit(); - - if (parentp) - { - root_objectp = parentp; - } - else - { - root_objectp = objectp; - } - } - } - - LLVOVolume *volobjp = NULL; - if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME)) - { - volobjp = (LLVOVolume *)objectp; - } - - if( !objectp ) - { - //forfeit focus - if (gFocusMgr.childHasKeyboardFocus(this)) - { - gFocusMgr.setKeyboardFocus(NULL); - } - - // Disable all text input fields - clearCtrls(); - return; - } - - // can move or rotate only linked group with move permissions, or sub-object with move and modify perms - BOOL enable_move = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts")); - BOOL enable_scale = objectp->permMove() && objectp->permModify(); - BOOL enable_rotate = objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts")); - - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) - && (selected_count == 1); - - if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1) - { - enable_move = FALSE; - enable_scale = FALSE; - enable_rotate = FALSE; - } - - LLVector3 vec; - if (enable_move) - { - vec = objectp->getPositionEdit(); - mCtrlPosX->set( vec.mV[VX] ); - mCtrlPosY->set( vec.mV[VY] ); - mCtrlPosZ->set( vec.mV[VZ] ); - } - else - { - mCtrlPosX->clear(); - mCtrlPosY->clear(); - mCtrlPosZ->clear(); - } - - - mLabelPosition->setEnabled( enable_move ); - mCtrlPosX->setEnabled(enable_move); - mCtrlPosY->setEnabled(enable_move); - mCtrlPosZ->setEnabled(enable_move); - - if (enable_scale) - { - vec = objectp->getScale(); - mCtrlScaleX->set( vec.mV[VX] ); - mCtrlScaleY->set( vec.mV[VY] ); - mCtrlScaleZ->set( vec.mV[VZ] ); - } - else - { - mCtrlScaleX->clear(); - mCtrlScaleY->clear(); - mCtrlScaleZ->clear(); - } - - mLabelSize->setEnabled( enable_scale ); - mCtrlScaleX->setEnabled( enable_scale ); - mCtrlScaleY->setEnabled( enable_scale ); - mCtrlScaleZ->setEnabled( enable_scale ); - - LLQuaternion object_rot = objectp->getRotationEdit(); - object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ])); - mCurEulerDegrees *= RAD_TO_DEG; - mCurEulerDegrees.mV[VX] = fmod(llround(mCurEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f); - mCurEulerDegrees.mV[VY] = fmod(llround(mCurEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f); - mCurEulerDegrees.mV[VZ] = fmod(llround(mCurEulerDegrees.mV[VZ], OBJECT_ROTATION_PRECISION) + 360.f, 360.f); - - if (enable_rotate) - { - mCtrlRotX->set( mCurEulerDegrees.mV[VX] ); - mCtrlRotY->set( mCurEulerDegrees.mV[VY] ); - mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] ); - } - else - { - mCtrlRotX->clear(); - mCtrlRotY->clear(); - mCtrlRotZ->clear(); - } - - mLabelRotation->setEnabled( enable_rotate ); - mCtrlRotX->setEnabled( enable_rotate ); - mCtrlRotY->setEnabled( enable_rotate ); - mCtrlRotZ->setEnabled( enable_rotate ); - - BOOL owners_identical; - LLUUID owner_id; - std::string owner_name; - owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name); - - // BUG? Check for all objects being editable? - S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount(); - BOOL editable = root_objectp->permModify(); - - // Select Single Message - getChildView("select_single")->setVisible( FALSE); - getChildView("edit_object")->setVisible( FALSE); - if (!editable || single_volume || selected_count <= 1) - { - getChildView("edit_object")->setVisible( TRUE); - getChildView("edit_object")->setEnabled(TRUE); - } - else - { - getChildView("select_single")->setVisible( TRUE); - getChildView("select_single")->setEnabled(TRUE); - } - // Lock checkbox - only modifiable if you own the object. - BOOL self_owned = (gAgent.getID() == owner_id); - mCheckLock->setEnabled( roots_selected > 0 && self_owned ); - - // More lock and debit checkbox - get the values - BOOL valid; - U32 owner_mask_on; - U32 owner_mask_off; - valid = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, &owner_mask_on, &owner_mask_off); - - if(valid) - { - if(owner_mask_on & PERM_MOVE) - { - // owner can move, so not locked - mCheckLock->set(FALSE); - mCheckLock->setTentative(FALSE); - } - else if(owner_mask_off & PERM_MOVE) - { - // owner can't move, so locked - mCheckLock->set(TRUE); - mCheckLock->setTentative(FALSE); - } - else - { - // some locked, some not locked - mCheckLock->set(FALSE); - mCheckLock->setTentative(TRUE); - } - } - - BOOL is_flexible = volobjp && volobjp->isFlexible(); - - // Physics checkbox - mIsPhysical = root_objectp->usePhysics(); - mCheckPhysics->set( mIsPhysical ); - mCheckPhysics->setEnabled( roots_selected>0 - && (editable || gAgent.isGodlike()) - && !is_flexible); - - mIsTemporary = root_objectp->flagTemporaryOnRez(); - mCheckTemporary->set( mIsTemporary ); - mCheckTemporary->setEnabled( roots_selected>0 && editable ); - - mIsPhantom = root_objectp->flagPhantom(); - mCheckPhantom->set( mIsPhantom ); - mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible ); - - -#if 0 // 1.9.2 - mCastShadows = root_objectp->flagCastShadows(); - mCheckCastShadows->set( mCastShadows ); - mCheckCastShadows->setEnabled( roots_selected==1 && editable ); -#endif - - //---------------------------------------------------------------------------- - - S32 selected_item = MI_BOX; - S32 selected_hole = MI_HOLE_SAME; - BOOL enabled = FALSE; - BOOL hole_enabled = FALSE; - F32 scale_x=1.f, scale_y=1.f; - BOOL isMesh = FALSE; - - if( !objectp || !objectp->getVolume() || !editable || !single_volume) - { - // Clear out all geometry fields. - mComboBaseType->clear(); - mSpinHollow->clear(); - mSpinCutBegin->clear(); - mSpinCutEnd->clear(); - mCtrlPathBegin->clear(); - mCtrlPathEnd->clear(); - mSpinScaleX->clear(); - mSpinScaleY->clear(); - mSpinTwist->clear(); - mSpinTwistBegin->clear(); - mComboHoleType->clear(); - mSpinShearX->clear(); - mSpinShearY->clear(); - mSpinTaperX->clear(); - mSpinTaperY->clear(); - mSpinRadiusOffset->clear(); - mSpinRevolutions->clear(); - mSpinSkew->clear(); - - mSelectedType = MI_NONE; - } - else - { - // Only allowed to change these parameters for objects - // that you have permissions on AND are not attachments. - enabled = root_objectp->permModify(); - - // Volume type - const LLVolumeParams &volume_params = objectp->getVolume()->getParams(); - U8 path = volume_params.getPathParams().getCurveType(); - U8 profile_and_hole = volume_params.getProfileParams().getCurveType(); - U8 profile = profile_and_hole & LL_PCODE_PROFILE_MASK; - U8 hole = profile_and_hole & LL_PCODE_HOLE_MASK; - - // Scale goes first so we can differentiate between a sphere and a torus, - // which have the same profile and path types. - - // Scale - scale_x = volume_params.getRatioX(); - scale_y = volume_params.getRatioY(); - - BOOL linear_path = (path == LL_PCODE_PATH_LINE) || (path == LL_PCODE_PATH_FLEXIBLE); - if ( linear_path && profile == LL_PCODE_PROFILE_CIRCLE ) - { - selected_item = MI_CYLINDER; - } - else if ( linear_path && profile == LL_PCODE_PROFILE_SQUARE ) - { - selected_item = MI_BOX; - } - else if ( linear_path && profile == LL_PCODE_PROFILE_ISOTRI ) - { - selected_item = MI_PRISM; - } - else if ( linear_path && profile == LL_PCODE_PROFILE_EQUALTRI ) - { - selected_item = MI_PRISM; - } - else if ( linear_path && profile == LL_PCODE_PROFILE_RIGHTTRI ) - { - selected_item = MI_PRISM; - } - else if (path == LL_PCODE_PATH_FLEXIBLE) // shouldn't happen - { - selected_item = MI_CYLINDER; // reasonable default - } - else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y > 0.75f) - { - selected_item = MI_SPHERE; - } - else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y <= 0.75f) - { - selected_item = MI_TORUS; - } - else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE_HALF) - { - selected_item = MI_SPHERE; - } - else if ( path == LL_PCODE_PATH_CIRCLE2 && profile == LL_PCODE_PROFILE_CIRCLE ) - { - // Spirals aren't supported. Make it into a sphere. JC - selected_item = MI_SPHERE; - } - else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_EQUALTRI ) - { - selected_item = MI_RING; - } - else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_SQUARE && scale_y <= 0.75f) - { - selected_item = MI_TUBE; - } - else - { - llinfos << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << llendl; - selected_item = MI_BOX; - } - - - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - selected_item = MI_SCULPT; - //LLFirstUse::useSculptedPrim(); - } - - - mComboBaseType ->setCurrentByIndex( selected_item ); - mSelectedType = selected_item; - - // Grab S path - F32 begin_s = volume_params.getBeginS(); - F32 end_s = volume_params.getEndS(); - - // Compute cut and advanced cut from S and T - F32 begin_t = volume_params.getBeginT(); - F32 end_t = volume_params.getEndT(); - - // Hollowness - F32 hollow = volume_params.getHollow(); - mSpinHollow->set( 100.f * hollow ); - - // All hollow objects allow a shape to be selected. - if (hollow > 0.f) - { - switch (hole) - { - case LL_PCODE_HOLE_CIRCLE: - selected_hole = MI_HOLE_CIRCLE; - break; - case LL_PCODE_HOLE_SQUARE: - selected_hole = MI_HOLE_SQUARE; - break; - case LL_PCODE_HOLE_TRIANGLE: - selected_hole = MI_HOLE_TRIANGLE; - break; - case LL_PCODE_HOLE_SAME: - default: - selected_hole = MI_HOLE_SAME; - break; - } - mComboHoleType->setCurrentByIndex( selected_hole ); - hole_enabled = enabled; - } - else - { - mComboHoleType->setCurrentByIndex( MI_HOLE_SAME ); - hole_enabled = FALSE; - } - - // Cut interpretation varies based on base object type - F32 cut_begin, cut_end, adv_cut_begin, adv_cut_end; - - if ( selected_item == MI_SPHERE || selected_item == MI_TORUS || - selected_item == MI_TUBE || selected_item == MI_RING ) - { - cut_begin = begin_t; - cut_end = end_t; - adv_cut_begin = begin_s; - adv_cut_end = end_s; - } - else - { - cut_begin = begin_s; - cut_end = end_s; - adv_cut_begin = begin_t; - adv_cut_end = end_t; - } - - mSpinCutBegin ->set( cut_begin ); - mSpinCutEnd ->set( cut_end ); - mCtrlPathBegin ->set( adv_cut_begin ); - mCtrlPathEnd ->set( adv_cut_end ); - - // Twist - F32 twist = volume_params.getTwist(); - F32 twist_begin = volume_params.getTwistBegin(); - // Check the path type for conversion. - if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE) - { - twist *= OBJECT_TWIST_LINEAR_MAX; - twist_begin *= OBJECT_TWIST_LINEAR_MAX; - } - else - { - twist *= OBJECT_TWIST_MAX; - twist_begin *= OBJECT_TWIST_MAX; - } - - mSpinTwist ->set( twist ); - mSpinTwistBegin ->set( twist_begin ); - - // Shear - F32 shear_x = volume_params.getShearX(); - F32 shear_y = volume_params.getShearY(); - mSpinShearX->set( shear_x ); - mSpinShearY->set( shear_y ); - - // Taper - F32 taper_x = volume_params.getTaperX(); - F32 taper_y = volume_params.getTaperY(); - mSpinTaperX->set( taper_x ); - mSpinTaperY->set( taper_y ); - - // Radius offset. - F32 radius_offset = volume_params.getRadiusOffset(); - // Limit radius offset, based on taper and hole size y. - F32 radius_mag = fabs(radius_offset); - F32 hole_y_mag = fabs(scale_y); - F32 taper_y_mag = fabs(taper_y); - // Check to see if the taper effects us. - if ( (radius_offset > 0.f && taper_y < 0.f) || - (radius_offset < 0.f && taper_y > 0.f) ) - { - // The taper does not help increase the radius offset range. - taper_y_mag = 0.f; - } - F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); - // Enforce the maximum magnitude. - if (radius_mag > max_radius_mag) - { - // Check radius offset sign. - if (radius_offset < 0.f) - { - radius_offset = -max_radius_mag; - } - else - { - radius_offset = max_radius_mag; - } - } - mSpinRadiusOffset->set( radius_offset); - - // Revolutions - F32 revolutions = volume_params.getRevolutions(); - mSpinRevolutions->set( revolutions ); - - // Skew - F32 skew = volume_params.getSkew(); - // Limit skew, based on revolutions hole size x. - F32 skew_mag= fabs(skew); - F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); - // Discontinuity; A revolution of 1 allows skews below 0.5. - if ( fabs(revolutions - 1.0f) < 0.001) - min_skew_mag = 0.0f; - - // Clip skew. - if (skew_mag < min_skew_mag) - { - // Check skew sign. - if (skew < 0.0f) - { - skew = -min_skew_mag; - } - else - { - skew = min_skew_mag; - } - } - mSpinSkew->set( skew ); - } - - // Compute control visibility, label names, and twist range. - // Start with defaults. - BOOL cut_visible = TRUE; - BOOL hollow_visible = TRUE; - BOOL top_size_x_visible = TRUE; - BOOL top_size_y_visible = TRUE; - BOOL top_shear_x_visible = TRUE; - BOOL top_shear_y_visible = TRUE; - BOOL twist_visible = TRUE; - BOOL advanced_cut_visible = FALSE; - BOOL taper_visible = FALSE; - BOOL skew_visible = FALSE; - BOOL radius_offset_visible = FALSE; - BOOL revolutions_visible = FALSE; - BOOL sculpt_texture_visible = FALSE; - F32 twist_min = OBJECT_TWIST_LINEAR_MIN; - F32 twist_max = OBJECT_TWIST_LINEAR_MAX; - F32 twist_inc = OBJECT_TWIST_LINEAR_INC; - - BOOL advanced_is_dimple = FALSE; - BOOL advanced_is_slice = FALSE; - BOOL size_is_hole = FALSE; - - // Tune based on overall volume type - switch (selected_item) - { - case MI_SPHERE: - top_size_x_visible = FALSE; - top_size_y_visible = FALSE; - top_shear_x_visible = FALSE; - top_shear_y_visible = FALSE; - //twist_visible = FALSE; - advanced_cut_visible = TRUE; - advanced_is_dimple = TRUE; - twist_min = OBJECT_TWIST_MIN; - twist_max = OBJECT_TWIST_MAX; - twist_inc = OBJECT_TWIST_INC; - break; - - case MI_TORUS: - case MI_TUBE: - case MI_RING: - //top_size_x_visible = FALSE; - //top_size_y_visible = FALSE; - size_is_hole = TRUE; - skew_visible = TRUE; - advanced_cut_visible = TRUE; - taper_visible = TRUE; - radius_offset_visible = TRUE; - revolutions_visible = TRUE; - twist_min = OBJECT_TWIST_MIN; - twist_max = OBJECT_TWIST_MAX; - twist_inc = OBJECT_TWIST_INC; - - break; - - case MI_SCULPT: - cut_visible = FALSE; - hollow_visible = FALSE; - twist_visible = FALSE; - top_size_x_visible = FALSE; - top_size_y_visible = FALSE; - top_shear_x_visible = FALSE; - top_shear_y_visible = FALSE; - skew_visible = FALSE; - advanced_cut_visible = FALSE; - taper_visible = FALSE; - radius_offset_visible = FALSE; - revolutions_visible = FALSE; - sculpt_texture_visible = TRUE; - - break; - - case MI_BOX: - advanced_cut_visible = TRUE; - advanced_is_slice = TRUE; - break; - - case MI_CYLINDER: - advanced_cut_visible = TRUE; - advanced_is_slice = TRUE; - break; - - case MI_PRISM: - advanced_cut_visible = TRUE; - advanced_is_slice = TRUE; - break; - - default: - break; - } - - // Check if we need to change top size/hole size params. - switch (selected_item) - { - case MI_SPHERE: - case MI_TORUS: - case MI_TUBE: - case MI_RING: - mSpinScaleX->set( scale_x ); - mSpinScaleY->set( scale_y ); - mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE); - mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X); - mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE); - mSpinScaleY->setMaxValue(OBJECT_MAX_HOLE_SIZE_Y); - break; - default: - if (editable) - { - mSpinScaleX->set( 1.f - scale_x ); - mSpinScaleY->set( 1.f - scale_y ); - mSpinScaleX->setMinValue(-1.f); - mSpinScaleX->setMaxValue(1.f); - mSpinScaleY->setMinValue(-1.f); - mSpinScaleY->setMaxValue(1.f); - } - break; - } - - // Check if we need to limit the hollow based on the hole type. - if ( selected_hole == MI_HOLE_SQUARE && - ( selected_item == MI_CYLINDER || selected_item == MI_TORUS || - selected_item == MI_PRISM || selected_item == MI_RING || - selected_item == MI_SPHERE ) ) - { - mSpinHollow->setMinValue(0.f); - mSpinHollow->setMaxValue(70.f); - } - else - { - mSpinHollow->setMinValue(0.f); - mSpinHollow->setMaxValue(95.f); - } - - // Update field enablement - mComboBaseType ->setEnabled( enabled ); - - mLabelCut ->setEnabled( enabled ); - mSpinCutBegin ->setEnabled( enabled ); - mSpinCutEnd ->setEnabled( enabled ); - - mLabelHollow ->setEnabled( enabled ); - mSpinHollow ->setEnabled( enabled ); - mLabelHoleType ->setEnabled( hole_enabled ); - mComboHoleType ->setEnabled( hole_enabled ); - - mLabelTwist ->setEnabled( enabled ); - mSpinTwist ->setEnabled( enabled ); - mSpinTwistBegin ->setEnabled( enabled ); - - mLabelSkew ->setEnabled( enabled ); - mSpinSkew ->setEnabled( enabled ); - - getChildView("scale_hole")->setVisible( FALSE); - getChildView("scale_taper")->setVisible( FALSE); - if (top_size_x_visible || top_size_y_visible) - { - if (size_is_hole) - { - getChildView("scale_hole")->setVisible( TRUE); - getChildView("scale_hole")->setEnabled(enabled); - } - else - { - getChildView("scale_taper")->setVisible( TRUE); - getChildView("scale_taper")->setEnabled(enabled); - } - } - - mSpinScaleX ->setEnabled( enabled ); - mSpinScaleY ->setEnabled( enabled ); - - mLabelShear ->setEnabled( enabled ); - mSpinShearX ->setEnabled( enabled ); - mSpinShearY ->setEnabled( enabled ); - - getChildView("advanced_cut")->setVisible( FALSE); - getChildView("advanced_dimple")->setVisible( FALSE); - getChildView("advanced_slice")->setVisible( FALSE); - - if (advanced_cut_visible) - { - if (advanced_is_dimple) - { - getChildView("advanced_dimple")->setVisible( TRUE); - getChildView("advanced_dimple")->setEnabled(enabled); - } - - else if (advanced_is_slice) - { - getChildView("advanced_slice")->setVisible( TRUE); - getChildView("advanced_slice")->setEnabled(enabled); - } - else - { - getChildView("advanced_cut")->setVisible( TRUE); - getChildView("advanced_cut")->setEnabled(enabled); - } - } - - mCtrlPathBegin ->setEnabled( enabled ); - mCtrlPathEnd ->setEnabled( enabled ); - - mLabelTaper ->setEnabled( enabled ); - mSpinTaperX ->setEnabled( enabled ); - mSpinTaperY ->setEnabled( enabled ); - - mLabelRadiusOffset->setEnabled( enabled ); - mSpinRadiusOffset ->setEnabled( enabled ); - - mLabelRevolutions->setEnabled( enabled ); - mSpinRevolutions ->setEnabled( enabled ); - - // Update field visibility - mLabelCut ->setVisible( cut_visible ); - mSpinCutBegin ->setVisible( cut_visible ); - mSpinCutEnd ->setVisible( cut_visible ); - - mLabelHollow ->setVisible( hollow_visible ); - mSpinHollow ->setVisible( hollow_visible ); - mLabelHoleType ->setVisible( hollow_visible ); - mComboHoleType ->setVisible( hollow_visible ); - - mLabelTwist ->setVisible( twist_visible ); - mSpinTwist ->setVisible( twist_visible ); - mSpinTwistBegin ->setVisible( twist_visible ); - mSpinTwist ->setMinValue( twist_min ); - mSpinTwist ->setMaxValue( twist_max ); - mSpinTwist ->setIncrement( twist_inc ); - mSpinTwistBegin ->setMinValue( twist_min ); - mSpinTwistBegin ->setMaxValue( twist_max ); - mSpinTwistBegin ->setIncrement( twist_inc ); - - mSpinScaleX ->setVisible( top_size_x_visible ); - mSpinScaleY ->setVisible( top_size_y_visible ); - - mLabelSkew ->setVisible( skew_visible ); - mSpinSkew ->setVisible( skew_visible ); - - mLabelShear ->setVisible( top_shear_x_visible || top_shear_y_visible ); - mSpinShearX ->setVisible( top_shear_x_visible ); - mSpinShearY ->setVisible( top_shear_y_visible ); - - mCtrlPathBegin ->setVisible( advanced_cut_visible ); - mCtrlPathEnd ->setVisible( advanced_cut_visible ); - - mLabelTaper ->setVisible( taper_visible ); - mSpinTaperX ->setVisible( taper_visible ); - mSpinTaperY ->setVisible( taper_visible ); - - mLabelRadiusOffset->setVisible( radius_offset_visible ); - mSpinRadiusOffset ->setVisible( radius_offset_visible ); - - mLabelRevolutions->setVisible( revolutions_visible ); - mSpinRevolutions ->setVisible( revolutions_visible ); - - mCtrlSculptTexture->setVisible(sculpt_texture_visible); - mLabelSculptType->setVisible(sculpt_texture_visible); - mCtrlSculptType->setVisible(sculpt_texture_visible); - - - // sculpt texture - if (selected_item == MI_SCULPT) - { - - - LLUUID id; - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - - - if (sculpt_params) // if we have a legal sculpt param block for this object: - { - if (mObject != objectp) // we've just selected a new object, so save for undo - { - mSculptTextureRevert = sculpt_params->getSculptTexture(); - mSculptTypeRevert = sculpt_params->getSculptType(); - } - - U8 sculpt_type = sculpt_params->getSculptType(); - U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK; - BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT; - BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR; - isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH); - - LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); - if(mTextureCtrl) - { - mTextureCtrl->setTentative(FALSE); - mTextureCtrl->setEnabled(editable && !isMesh); - if (editable) - mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture()); - else - mTextureCtrl->setImageAssetID(LLUUID::null); - } - - mComboBaseType->setEnabled(!isMesh); - - if (mCtrlSculptType) - { - mCtrlSculptType->setCurrentByIndex(sculpt_stitching); - mCtrlSculptType->setEnabled(editable && !isMesh); - } - - if (mCtrlSculptMirror) - { - mCtrlSculptMirror->set(sculpt_mirror); - mCtrlSculptMirror->setEnabled(editable && !isMesh); - } - - if (mCtrlSculptInvert) - { - mCtrlSculptInvert->set(sculpt_invert); - mCtrlSculptInvert->setEnabled(editable); - } - - if (mLabelSculptType) - { - mLabelSculptType->setEnabled(TRUE); - } - - } - } - else - { - mSculptTextureRevert = LLUUID::null; - } - - mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh); - mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh); - - //---------------------------------------------------------------------------- - - mObject = objectp; - mRootObject = root_objectp; -} - -// static -bool LLPanelObject::precommitValidate( const LLSD& data ) -{ - // TODO: Richard will fill this in later. - return TRUE; // FALSE means that validation failed and new value should not be commited. -} - -void LLPanelObject::sendIsPhysical() -{ - BOOL value = mCheckPhysics->get(); - if( mIsPhysical != value ) - { - LLSelectMgr::getInstance()->selectionUpdatePhysics(value); - mIsPhysical = value; - - llinfos << "update physics sent" << llendl; - } - else - { - llinfos << "update physics not changed" << llendl; - } -} - -void LLPanelObject::sendIsTemporary() -{ - BOOL value = mCheckTemporary->get(); - if( mIsTemporary != value ) - { - LLSelectMgr::getInstance()->selectionUpdateTemporary(value); - mIsTemporary = value; - - llinfos << "update temporary sent" << llendl; - } - else - { - llinfos << "update temporary not changed" << llendl; - } -} - - -void LLPanelObject::sendIsPhantom() -{ - BOOL value = mCheckPhantom->get(); - if( mIsPhantom != value ) - { - LLSelectMgr::getInstance()->selectionUpdatePhantom(value); - mIsPhantom = value; - - llinfos << "update phantom sent" << llendl; - } - else - { - llinfos << "update phantom not changed" << llendl; - } -} - -void LLPanelObject::sendCastShadows() -{ - BOOL value = mCheckCastShadows->get(); - if( mCastShadows != value ) - { - LLSelectMgr::getInstance()->selectionUpdateCastShadows(value); - mCastShadows = value; - - llinfos << "update cast shadows sent" << llendl; - } - else - { - llinfos << "update cast shadows not changed" << llendl; - } -} - -// static -void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - - if (self->mObject.isNull()) - { - return; - } - - if (self->mObject->getPCode() != LL_PCODE_VOLUME) - { - // Don't allow modification of non-volume objects. - return; - } - - LLVolume *volume = self->mObject->getVolume(); - if (!volume) - { - return; - } - - LLVolumeParams volume_params; - self->getVolumeParams(volume_params); - - - - // set sculpting - S32 selected_type = self->mComboBaseType->getCurrentIndex(); - - if (selected_type == MI_SCULPT) - { - self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, TRUE, TRUE); - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) - volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType()); - } - else - { - LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) - self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE); - } - - // Update the volume, if necessary. - self->mObject->updateVolume(volume_params); - - - // This was added to make sure thate when changes are made, the UI - // adjusts to present valid options. - // *FIX: only some changes, ie, hollow or primitive type changes, - // require a refresh. - self->refresh(); - -} - -void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params) -{ - // Figure out what type of volume to make - S32 was_selected_type = mSelectedType; - S32 selected_type = mComboBaseType->getCurrentIndex(); - U8 profile; - U8 path; - switch ( selected_type ) - { - case MI_CYLINDER: - profile = LL_PCODE_PROFILE_CIRCLE; - path = LL_PCODE_PATH_LINE; - break; - - case MI_BOX: - profile = LL_PCODE_PROFILE_SQUARE; - path = LL_PCODE_PATH_LINE; - break; - - case MI_PRISM: - profile = LL_PCODE_PROFILE_EQUALTRI; - path = LL_PCODE_PATH_LINE; - break; - - case MI_SPHERE: - profile = LL_PCODE_PROFILE_CIRCLE_HALF; - path = LL_PCODE_PATH_CIRCLE; - break; - - case MI_TORUS: - profile = LL_PCODE_PROFILE_CIRCLE; - path = LL_PCODE_PATH_CIRCLE; - break; - - case MI_TUBE: - profile = LL_PCODE_PROFILE_SQUARE; - path = LL_PCODE_PATH_CIRCLE; - break; - - case MI_RING: - profile = LL_PCODE_PROFILE_EQUALTRI; - path = LL_PCODE_PATH_CIRCLE; - break; - - case MI_SCULPT: - profile = LL_PCODE_PROFILE_CIRCLE; - path = LL_PCODE_PATH_CIRCLE; - break; - - default: - llwarns << "Unknown base type " << selected_type - << " in getVolumeParams()" << llendl; - // assume a box - selected_type = MI_BOX; - profile = LL_PCODE_PROFILE_SQUARE; - path = LL_PCODE_PATH_LINE; - break; - } - - - if (path == LL_PCODE_PATH_LINE) - { - LLVOVolume *volobjp = (LLVOVolume *)(LLViewerObject*)(mObject); - if (volobjp->isFlexible()) - { - path = LL_PCODE_PATH_FLEXIBLE; - } - } - - S32 selected_hole = mComboHoleType->getCurrentIndex(); - U8 hole; - switch (selected_hole) - { - case MI_HOLE_CIRCLE: - hole = LL_PCODE_HOLE_CIRCLE; - break; - case MI_HOLE_SQUARE: - hole = LL_PCODE_HOLE_SQUARE; - break; - case MI_HOLE_TRIANGLE: - hole = LL_PCODE_HOLE_TRIANGLE; - break; - case MI_HOLE_SAME: - default: - hole = LL_PCODE_HOLE_SAME; - break; - } - - volume_params.setType(profile | hole, path); - mSelectedType = selected_type; - - // Compute cut start/end - F32 cut_begin = mSpinCutBegin->get(); - F32 cut_end = mSpinCutEnd->get(); - - // Make sure at least OBJECT_CUT_INC of the object survives - if (cut_begin > cut_end - OBJECT_MIN_CUT_INC) - { - cut_begin = cut_end - OBJECT_MIN_CUT_INC; - mSpinCutBegin->set(cut_begin); - } - - F32 adv_cut_begin = mCtrlPathBegin->get(); - F32 adv_cut_end = mCtrlPathEnd->get(); - - // Make sure at least OBJECT_CUT_INC of the object survives - if (adv_cut_begin > adv_cut_end - OBJECT_MIN_CUT_INC) - { - adv_cut_begin = adv_cut_end - OBJECT_MIN_CUT_INC; - mCtrlPathBegin->set(adv_cut_begin); - } - - F32 begin_s, end_s; - F32 begin_t, end_t; - - if (selected_type == MI_SPHERE || selected_type == MI_TORUS || - selected_type == MI_TUBE || selected_type == MI_RING) - { - begin_s = adv_cut_begin; - end_s = adv_cut_end; - - begin_t = cut_begin; - end_t = cut_end; - } - else - { - begin_s = cut_begin; - end_s = cut_end; - - begin_t = adv_cut_begin; - end_t = adv_cut_end; - } - - volume_params.setBeginAndEndS(begin_s, end_s); - volume_params.setBeginAndEndT(begin_t, end_t); - - // Hollowness - F32 hollow = mSpinHollow->get() / 100.f; - - if ( selected_hole == MI_HOLE_SQUARE && - ( selected_type == MI_CYLINDER || selected_type == MI_TORUS || - selected_type == MI_PRISM || selected_type == MI_RING || - selected_type == MI_SPHERE ) ) - { - if (hollow > 0.7f) hollow = 0.7f; - } - - volume_params.setHollow( hollow ); - - // Twist Begin,End - F32 twist_begin = mSpinTwistBegin->get(); - F32 twist = mSpinTwist->get(); - // Check the path type for twist conversion. - if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE) - { - twist_begin /= OBJECT_TWIST_LINEAR_MAX; - twist /= OBJECT_TWIST_LINEAR_MAX; - } - else - { - twist_begin /= OBJECT_TWIST_MAX; - twist /= OBJECT_TWIST_MAX; - } - - volume_params.setTwistBegin(twist_begin); - volume_params.setTwist(twist); - - // Scale X,Y - F32 scale_x = mSpinScaleX->get(); - F32 scale_y = mSpinScaleY->get(); - if ( was_selected_type == MI_BOX || was_selected_type == MI_CYLINDER || was_selected_type == MI_PRISM) - { - scale_x = 1.f - scale_x; - scale_y = 1.f - scale_y; - } - - // Skew - F32 skew = mSpinSkew->get(); - - // Taper X,Y - F32 taper_x = mSpinTaperX->get(); - F32 taper_y = mSpinTaperY->get(); - - // Radius offset - F32 radius_offset = mSpinRadiusOffset->get(); - - // Revolutions - F32 revolutions = mSpinRevolutions->get(); - - if ( selected_type == MI_SPHERE ) - { - // Snap values to valid sphere parameters. - scale_x = 1.0f; - scale_y = 1.0f; - skew = 0.0f; - taper_x = 0.0f; - taper_y = 0.0f; - radius_offset = 0.0f; - revolutions = 1.0f; - } - else if ( selected_type == MI_TORUS || selected_type == MI_TUBE || - selected_type == MI_RING ) - { - scale_x = llclamp( - scale_x, - OBJECT_MIN_HOLE_SIZE, - OBJECT_MAX_HOLE_SIZE_X); - scale_y = llclamp( - scale_y, - OBJECT_MIN_HOLE_SIZE, - OBJECT_MAX_HOLE_SIZE_Y); - - // Limit radius offset, based on taper and hole size y. - F32 radius_mag = fabs(radius_offset); - F32 hole_y_mag = fabs(scale_y); - F32 taper_y_mag = fabs(taper_y); - // Check to see if the taper effects us. - if ( (radius_offset > 0.f && taper_y < 0.f) || - (radius_offset < 0.f && taper_y > 0.f) ) - { - // The taper does not help increase the radius offset range. - taper_y_mag = 0.f; - } - F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag); - // Enforce the maximum magnitude. - if (radius_mag > max_radius_mag) - { - // Check radius offset sign. - if (radius_offset < 0.f) - { - radius_offset = -max_radius_mag; - } - else - { - radius_offset = max_radius_mag; - } - } - - // Check the skew value against the revolutions. - F32 skew_mag= fabs(skew); - F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f); - // Discontinuity; A revolution of 1 allows skews below 0.5. - if ( fabs(revolutions - 1.0f) < 0.001) - min_skew_mag = 0.0f; - - // Clip skew. - if (skew_mag < min_skew_mag) - { - // Check skew sign. - if (skew < 0.0f) - { - skew = -min_skew_mag; - } - else - { - skew = min_skew_mag; - } - } - } - - volume_params.setRatio( scale_x, scale_y ); - volume_params.setSkew(skew); - volume_params.setTaper( taper_x, taper_y ); - volume_params.setRadiusOffset(radius_offset); - volume_params.setRevolutions(revolutions); - - // Shear X,Y - F32 shear_x = mSpinShearX->get(); - F32 shear_y = mSpinShearY->get(); - volume_params.setShear( shear_x, shear_y ); - - if (selected_type == MI_SCULPT) - { - volume_params.setSculptID(LLUUID::null, 0); - volume_params.setBeginAndEndT (0, 1); - volume_params.setBeginAndEndS (0, 1); - volume_params.setHollow (0); - volume_params.setTwistBegin (0); - volume_params.setTwistEnd (0); - volume_params.setRatio (1, 0.5); - volume_params.setShear (0, 0); - volume_params.setTaper (0, 0); - volume_params.setRevolutions (1); - volume_params.setRadiusOffset (0); - volume_params.setSkew (0); - } - -} - -// BUG: Make work with multiple objects -void LLPanelObject::sendRotation(BOOL btn_down) -{ - if (mObject.isNull()) return; - - LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); - new_rot.mV[VX] = llround(new_rot.mV[VX], OBJECT_ROTATION_PRECISION); - new_rot.mV[VY] = llround(new_rot.mV[VY], OBJECT_ROTATION_PRECISION); - new_rot.mV[VZ] = llround(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION); - - // Note: must compare before conversion to radians - LLVector3 delta = new_rot - mCurEulerDegrees; - - if (delta.magVec() >= 0.0005f) - { - mCurEulerDegrees = new_rot; - new_rot *= DEG_TO_RAD; - - LLQuaternion rotation; - rotation.setQuat(new_rot.mV[VX], new_rot.mV[VY], new_rot.mV[VZ]); - - if (mRootObject != mObject) - { - rotation = rotation * ~mRootObject->getRotationRegion(); - } - std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ; - std::vector<LLQuaternion> child_rotations; - if (mObject->isRootEdit()) - { - mObject->saveUnselectedChildrenRotation(child_rotations) ; - mObject->saveUnselectedChildrenPosition(child_positions) ; - } - - mObject->setRotation(rotation); - LLManip::rebuild(mObject) ; - - // for individually selected roots, we need to counterrotate all the children - if (mObject->isRootEdit()) - { - mObject->resetChildrenRotationAndPosition(child_rotations, child_positions) ; - } - - if(!btn_down) - { - child_positions.clear() ; - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION); - } - } -} - - -// BUG: Make work with multiple objects -void LLPanelObject::sendScale(BOOL btn_down) -{ - if (mObject.isNull()) return; - - LLVector3 newscale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); - - LLVector3 delta = newscale - mObject->getScale(); - if (delta.magVec() >= 0.0005f) - { - // scale changed by more than 1/2 millimeter - - // check to see if we aren't scaling the textures - // (in which case the tex coord's need to be recomputed) - BOOL dont_stretch_textures = !LLManipScale::getStretchTextures(); - if (dont_stretch_textures) - { - LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_SCALE); - } - - mObject->setScale(newscale, TRUE); - - if(!btn_down) - { - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE | UPD_POSITION); - } - - LLSelectMgr::getInstance()->adjustTexturesByScale(TRUE, !dont_stretch_textures); -// llinfos << "scale sent" << llendl; - } - else - { -// llinfos << "scale not changed" << llendl; - } -} - - -void LLPanelObject::sendPosition(BOOL btn_down) -{ - if (mObject.isNull()) return; - - LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); - LLViewerRegion* regionp = mObject->getRegion(); - - // Clamp the Z height - const F32 height = newpos.mV[VZ]; - const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal()); - const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight(); - - if (!mObject->isAttachment()) - { - if ( height < min_height) - { - newpos.mV[VZ] = min_height; - mCtrlPosZ->set( min_height ); - } - else if ( height > max_height ) - { - newpos.mV[VZ] = max_height; - mCtrlPosZ->set( max_height ); - } - - // Grass is always drawn on the ground, so clamp its position to the ground - if (mObject->getPCode() == LL_PCODE_LEGACY_GRASS) - { - mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f); - } - } - - // Make sure new position is in a valid region, so the object - // won't get dumped by the simulator. - LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos); - - if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) ) - { - // send only if the position is changed, that is, the delta vector is not zero - LLVector3d old_pos_global = mObject->getPositionGlobal(); - LLVector3d delta = new_pos_global - old_pos_global; - // moved more than 1/2 millimeter - if (delta.magVec() >= 0.0005f) - { - if (mRootObject != mObject) - { - newpos = newpos - mRootObject->getPositionRegion(); - newpos = newpos * ~mRootObject->getRotationRegion(); - mObject->setPositionParent(newpos); - } - else - { - mObject->setPositionEdit(newpos); - } - - LLManip::rebuild(mObject) ; - - // for individually selected roots, we need to counter-translate all unselected children - if (mObject->isRootEdit()) - { - // only offset by parent's translation - mObject->resetChildrenPosition(LLVector3(-delta), TRUE) ; - } - - if(!btn_down) - { - LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION); - } - - LLSelectMgr::getInstance()->updateSelectionCenter(); - } - } - else - { - // move failed, so we update the UI with the correct values - LLVector3 vec = mRootObject->getPositionRegion(); - mCtrlPosX->set(vec.mV[VX]); - mCtrlPosY->set(vec.mV[VY]); - mCtrlPosZ->set(vec.mV[VZ]); - } -} - -void LLPanelObject::sendSculpt() -{ - if (mObject.isNull()) - return; - - LLSculptParams sculpt_params; - - if (mCtrlSculptTexture) - sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID()); - - U8 sculpt_type = 0; - - if (mCtrlSculptType) - sculpt_type |= mCtrlSculptType->getCurrentIndex(); - - bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH; - - if (mCtrlSculptMirror) - { - mCtrlSculptMirror->setEnabled(enabled ? TRUE : FALSE); - } - if (mCtrlSculptInvert) - { - mCtrlSculptInvert->setEnabled(enabled ? TRUE : FALSE); - } - - if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get())) - sculpt_type |= LL_SCULPT_FLAG_MIRROR; - - if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get())) - sculpt_type |= LL_SCULPT_FLAG_INVERT; - - sculpt_params.setSculptType(sculpt_type); - mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE); -} - -void LLPanelObject::refresh() -{ - getState(); - if (mObject.notNull() && mObject->isDead()) - { - mObject = NULL; - } - - if (mRootObject.notNull() && mRootObject->isDead()) - { - mRootObject = NULL; - } - - bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") && - gAgent.getRegion() && - !gAgent.getRegion()->getCapability("GetMesh").empty(); - - F32 max_scale = get_default_max_prim_scale(LLPickInfo::isFlora(mObject)); - - getChild<LLSpinCtrl>("Scale X")->setMaxValue(max_scale); - getChild<LLSpinCtrl>("Scale Y")->setMaxValue(max_scale); - getChild<LLSpinCtrl>("Scale Z")->setMaxValue(max_scale); - - BOOL found = mCtrlSculptType->itemExists("Mesh"); - if (enable_mesh && !found) - { - mCtrlSculptType->add("Mesh"); - } - else if (!enable_mesh && found) - { - mCtrlSculptType->remove("Mesh"); - } -} - - -void LLPanelObject::draw() -{ - const LLColor4 white( 1.0f, 1.0f, 1.0f, 1); - const LLColor4 red( 1.0f, 0.25f, 0.f, 1); - const LLColor4 green( 0.f, 1.0f, 0.f, 1); - const LLColor4 blue( 0.f, 0.5f, 1.0f, 1); - - // Tune the colors of the labels - LLTool* tool = LLToolMgr::getInstance()->getCurrentTool(); - - if (tool == LLToolCompTranslate::getInstance()) - { - mCtrlPosX ->setLabelColor(red); - mCtrlPosY ->setLabelColor(green); - mCtrlPosZ ->setLabelColor(blue); - - mCtrlScaleX ->setLabelColor(white); - mCtrlScaleY ->setLabelColor(white); - mCtrlScaleZ ->setLabelColor(white); - - mCtrlRotX ->setLabelColor(white); - mCtrlRotY ->setLabelColor(white); - mCtrlRotZ ->setLabelColor(white); - } - else if ( tool == LLToolCompScale::getInstance() ) - { - mCtrlPosX ->setLabelColor(white); - mCtrlPosY ->setLabelColor(white); - mCtrlPosZ ->setLabelColor(white); - - mCtrlScaleX ->setLabelColor(red); - mCtrlScaleY ->setLabelColor(green); - mCtrlScaleZ ->setLabelColor(blue); - - mCtrlRotX ->setLabelColor(white); - mCtrlRotY ->setLabelColor(white); - mCtrlRotZ ->setLabelColor(white); - } - else if ( tool == LLToolCompRotate::getInstance() ) - { - mCtrlPosX ->setLabelColor(white); - mCtrlPosY ->setLabelColor(white); - mCtrlPosZ ->setLabelColor(white); - - mCtrlScaleX ->setLabelColor(white); - mCtrlScaleY ->setLabelColor(white); - mCtrlScaleZ ->setLabelColor(white); - - mCtrlRotX ->setLabelColor(red); - mCtrlRotY ->setLabelColor(green); - mCtrlRotZ ->setLabelColor(blue); - } - else - { - mCtrlPosX ->setLabelColor(white); - mCtrlPosY ->setLabelColor(white); - mCtrlPosZ ->setLabelColor(white); - - mCtrlScaleX ->setLabelColor(white); - mCtrlScaleY ->setLabelColor(white); - mCtrlScaleZ ->setLabelColor(white); - - mCtrlRotX ->setLabelColor(white); - mCtrlRotY ->setLabelColor(white); - mCtrlRotZ ->setLabelColor(white); - } - - LLPanel::draw(); -} - -// virtual -void LLPanelObject::clearCtrls() -{ - LLPanel::clearCtrls(); - - mCheckLock ->set(FALSE); - mCheckLock ->setEnabled( FALSE ); - mCheckPhysics ->set(FALSE); - mCheckPhysics ->setEnabled( FALSE ); - mCheckTemporary ->set(FALSE); - mCheckTemporary ->setEnabled( FALSE ); - mCheckPhantom ->set(FALSE); - mCheckPhantom ->setEnabled( FALSE ); - -#if 0 // 1.9.2 - mCheckCastShadows->set(FALSE); - mCheckCastShadows->setEnabled( FALSE ); -#endif - // Disable text labels - mLabelPosition ->setEnabled( FALSE ); - mLabelSize ->setEnabled( FALSE ); - mLabelRotation ->setEnabled( FALSE ); - mLabelCut ->setEnabled( FALSE ); - mLabelHollow ->setEnabled( FALSE ); - mLabelHoleType ->setEnabled( FALSE ); - mLabelTwist ->setEnabled( FALSE ); - mLabelSkew ->setEnabled( FALSE ); - mLabelShear ->setEnabled( FALSE ); - mLabelTaper ->setEnabled( FALSE ); - mLabelRadiusOffset->setEnabled( FALSE ); - mLabelRevolutions->setEnabled( FALSE ); - - getChildView("select_single")->setVisible( FALSE); - getChildView("edit_object")->setVisible( TRUE); - getChildView("edit_object")->setEnabled(FALSE); - - getChildView("scale_hole")->setEnabled(FALSE); - getChildView("scale_taper")->setEnabled(FALSE); - getChildView("advanced_cut")->setEnabled(FALSE); - getChildView("advanced_dimple")->setEnabled(FALSE); - getChildView("advanced_slice")->setVisible( FALSE); -} - -// -// Static functions -// - -// static -void LLPanelObject::onCommitLock(LLUICtrl *ctrl, void *data) -{ - // Checkbox will have toggled itself - LLPanelObject *self = (LLPanelObject *)data; - - if(self->mRootObject.isNull()) return; - - BOOL new_state = self->mCheckLock->get(); - - LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY); -} - -// static -void LLPanelObject::onCommitPosition( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ; - self->sendPosition(btn_down); -} - -// static -void LLPanelObject::onCommitScale( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ; - self->sendScale(btn_down); -} - -// static -void LLPanelObject::onCommitRotation( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ; - self->sendRotation(btn_down); -} - -// static -void LLPanelObject::onCommitPhysics( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - self->sendIsPhysical(); -} - -// static -void LLPanelObject::onCommitTemporary( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - self->sendIsTemporary(); -} - -// static -void LLPanelObject::onCommitPhantom( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - self->sendIsPhantom(); -} - -// static -void LLPanelObject::onCommitCastShadows( LLUICtrl* ctrl, void* userdata ) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - self->sendCastShadows(); -} - - -void LLPanelObject::onSelectSculpt(const LLSD& data) -{ - LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); - - if (mTextureCtrl) - { - mSculptTextureRevert = mTextureCtrl->getImageAssetID(); - } - - sendSculpt(); -} - - -void LLPanelObject::onCommitSculpt( const LLSD& data ) -{ - sendSculpt(); -} - -BOOL LLPanelObject::onDropSculpt(LLInventoryItem* item) -{ - LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); - - if (mTextureCtrl) - { - LLUUID asset = item->getAssetUUID(); - - mTextureCtrl->setImageAssetID(asset); - mSculptTextureRevert = asset; - } - - return TRUE; -} - - -void LLPanelObject::onCancelSculpt(const LLSD& data) -{ - LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control"); - if(!mTextureCtrl) - return; - - mTextureCtrl->setImageAssetID(mSculptTextureRevert); - - sendSculpt(); -} - -// static -void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - - self->sendSculpt(); -} +/**
+ * @file llpanelobject.cpp
+ * @brief Object editing (position, scale, etc.) in the tools floater
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+// file include
+#include "llpanelobject.h"
+
+// linden library includes
+#include "lleconomy.h"
+#include "llerror.h"
+#include "llfontgl.h"
+#include "llpermissionsflags.h"
+#include "llstring.h"
+#include "llvolume.h"
+#include "m3math.h"
+
+// project includes
+#include "llagent.h"
+#include "llbutton.h"
+#include "llcheckboxctrl.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
+#include "llfocusmgr.h"
+#include "llmanipscale.h"
+#include "llpreviewscript.h"
+#include "llresmgr.h"
+#include "llselectmgr.h"
+#include "llspinctrl.h"
+#include "lltexturectrl.h"
+#include "lltextbox.h"
+#include "lltool.h"
+#include "lltoolcomp.h"
+#include "lltoolmgr.h"
+#include "llui.h"
+#include "llviewerobject.h"
+#include "llviewerregion.h"
+#include "llviewerwindow.h"
+#include "llvovolume.h"
+#include "llworld.h"
+#include "pipeline.h"
+#include "llviewercontrol.h"
+#include "lluictrlfactory.h"
+//#include "llfirstuse.h"
+
+#include "lldrawpool.h"
+
+//
+// Constants
+//
+enum {
+ MI_BOX,
+ MI_CYLINDER,
+ MI_PRISM,
+ MI_SPHERE,
+ MI_TORUS,
+ MI_TUBE,
+ MI_RING,
+ MI_SCULPT,
+ MI_NONE,
+ MI_VOLUME_COUNT
+};
+
+enum {
+ MI_HOLE_SAME,
+ MI_HOLE_CIRCLE,
+ MI_HOLE_SQUARE,
+ MI_HOLE_TRIANGLE,
+ MI_HOLE_COUNT
+};
+
+//static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright");
+
+BOOL LLPanelObject::postBuild()
+{
+ setMouseOpaque(FALSE);
+
+ //--------------------------------------------------------
+ // Top
+ //--------------------------------------------------------
+
+ // Lock checkbox
+ mCheckLock = getChild<LLCheckBoxCtrl>("checkbox locked");
+ childSetCommitCallback("checkbox locked",onCommitLock,this);
+
+ // Physical checkbox
+ mCheckPhysics = getChild<LLCheckBoxCtrl>("Physical Checkbox Ctrl");
+ childSetCommitCallback("Physical Checkbox Ctrl",onCommitPhysics,this);
+
+ // Temporary checkbox
+ mCheckTemporary = getChild<LLCheckBoxCtrl>("Temporary Checkbox Ctrl");
+ childSetCommitCallback("Temporary Checkbox Ctrl",onCommitTemporary,this);
+
+ // Phantom checkbox
+ mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl");
+ childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this);
+
+
+ // Position
+ mLabelPosition = getChild<LLTextBox>("label position");
+ mCtrlPosX = getChild<LLSpinCtrl>("Pos X");
+ childSetCommitCallback("Pos X",onCommitPosition,this);
+ mCtrlPosY = getChild<LLSpinCtrl>("Pos Y");
+ childSetCommitCallback("Pos Y",onCommitPosition,this);
+ mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z");
+ childSetCommitCallback("Pos Z",onCommitPosition,this);
+
+ // Scale
+ mLabelSize = getChild<LLTextBox>("label size");
+ mCtrlScaleX = getChild<LLSpinCtrl>("Scale X");
+ childSetCommitCallback("Scale X",onCommitScale,this);
+
+ // Scale Y
+ mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y");
+ childSetCommitCallback("Scale Y",onCommitScale,this);
+
+ // Scale Z
+ mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z");
+ childSetCommitCallback("Scale Z",onCommitScale,this);
+
+ // Rotation
+ mLabelRotation = getChild<LLTextBox>("label rotation");
+ mCtrlRotX = getChild<LLSpinCtrl>("Rot X");
+ childSetCommitCallback("Rot X",onCommitRotation,this);
+ mCtrlRotY = getChild<LLSpinCtrl>("Rot Y");
+ childSetCommitCallback("Rot Y",onCommitRotation,this);
+ mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z");
+ childSetCommitCallback("Rot Z",onCommitRotation,this);
+
+ //--------------------------------------------------------
+
+ // Base Type
+ mComboBaseType = getChild<LLComboBox>("comboBaseType");
+ childSetCommitCallback("comboBaseType",onCommitParametric,this);
+
+ // Cut
+ mLabelCut = getChild<LLTextBox>("text cut");
+ mSpinCutBegin = getChild<LLSpinCtrl>("cut begin");
+ childSetCommitCallback("cut begin",onCommitParametric,this);
+ mSpinCutBegin->setValidateBeforeCommit( precommitValidate );
+ mSpinCutEnd = getChild<LLSpinCtrl>("cut end");
+ childSetCommitCallback("cut end",onCommitParametric,this);
+ mSpinCutEnd->setValidateBeforeCommit( &precommitValidate );
+
+ // Hollow / Skew
+ mLabelHollow = getChild<LLTextBox>("text hollow");
+ mLabelSkew = getChild<LLTextBox>("text skew");
+ mSpinHollow = getChild<LLSpinCtrl>("Scale 1");
+ childSetCommitCallback("Scale 1",onCommitParametric,this);
+ mSpinHollow->setValidateBeforeCommit( &precommitValidate );
+ mSpinSkew = getChild<LLSpinCtrl>("Skew");
+ childSetCommitCallback("Skew",onCommitParametric,this);
+ mSpinSkew->setValidateBeforeCommit( &precommitValidate );
+ mLabelHoleType = getChild<LLTextBox>("Hollow Shape");
+
+ // Hole Type
+ mComboHoleType = getChild<LLComboBox>("hole");
+ childSetCommitCallback("hole",onCommitParametric,this);
+
+ // Twist
+ mLabelTwist = getChild<LLTextBox>("text twist");
+ mSpinTwistBegin = getChild<LLSpinCtrl>("Twist Begin");
+ childSetCommitCallback("Twist Begin",onCommitParametric,this);
+ mSpinTwistBegin->setValidateBeforeCommit( precommitValidate );
+ mSpinTwist = getChild<LLSpinCtrl>("Twist End");
+ childSetCommitCallback("Twist End",onCommitParametric,this);
+ mSpinTwist->setValidateBeforeCommit( &precommitValidate );
+
+ // Scale
+ mSpinScaleX = getChild<LLSpinCtrl>("Taper Scale X");
+ childSetCommitCallback("Taper Scale X",onCommitParametric,this);
+ mSpinScaleX->setValidateBeforeCommit( &precommitValidate );
+ mSpinScaleY = getChild<LLSpinCtrl>("Taper Scale Y");
+ childSetCommitCallback("Taper Scale Y",onCommitParametric,this);
+ mSpinScaleY->setValidateBeforeCommit( &precommitValidate );
+
+ // Shear
+ mLabelShear = getChild<LLTextBox>("text topshear");
+ mSpinShearX = getChild<LLSpinCtrl>("Shear X");
+ childSetCommitCallback("Shear X",onCommitParametric,this);
+ mSpinShearX->setValidateBeforeCommit( &precommitValidate );
+ mSpinShearY = getChild<LLSpinCtrl>("Shear Y");
+ childSetCommitCallback("Shear Y",onCommitParametric,this);
+ mSpinShearY->setValidateBeforeCommit( &precommitValidate );
+
+ // Path / Profile
+ mCtrlPathBegin = getChild<LLSpinCtrl>("Path Limit Begin");
+ childSetCommitCallback("Path Limit Begin",onCommitParametric,this);
+ mCtrlPathBegin->setValidateBeforeCommit( &precommitValidate );
+ mCtrlPathEnd = getChild<LLSpinCtrl>("Path Limit End");
+ childSetCommitCallback("Path Limit End",onCommitParametric,this);
+ mCtrlPathEnd->setValidateBeforeCommit( &precommitValidate );
+
+ // Taper
+ mLabelTaper = getChild<LLTextBox>("text taper2");
+ mSpinTaperX = getChild<LLSpinCtrl>("Taper X");
+ childSetCommitCallback("Taper X",onCommitParametric,this);
+ mSpinTaperX->setValidateBeforeCommit( precommitValidate );
+ mSpinTaperY = getChild<LLSpinCtrl>("Taper Y");
+ childSetCommitCallback("Taper Y",onCommitParametric,this);
+ mSpinTaperY->setValidateBeforeCommit( precommitValidate );
+
+ // Radius Offset / Revolutions
+ mLabelRadiusOffset = getChild<LLTextBox>("text radius delta");
+ mLabelRevolutions = getChild<LLTextBox>("text revolutions");
+ mSpinRadiusOffset = getChild<LLSpinCtrl>("Radius Offset");
+ childSetCommitCallback("Radius Offset",onCommitParametric,this);
+ mSpinRadiusOffset->setValidateBeforeCommit( &precommitValidate );
+ mSpinRevolutions = getChild<LLSpinCtrl>("Revolutions");
+ childSetCommitCallback("Revolutions",onCommitParametric,this);
+ mSpinRevolutions->setValidateBeforeCommit( &precommitValidate );
+
+ // Sculpt
+ mCtrlSculptTexture = getChild<LLTextureCtrl>("sculpt texture control");
+ if (mCtrlSculptTexture)
+ {
+ mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE));
+ mCtrlSculptTexture->setCommitCallback( boost::bind(&LLPanelObject::onCommitSculpt, this, _2 ));
+ mCtrlSculptTexture->setOnCancelCallback( boost::bind(&LLPanelObject::onCancelSculpt, this, _2 ));
+ mCtrlSculptTexture->setOnSelectCallback( boost::bind(&LLPanelObject::onSelectSculpt, this, _2 ));
+ mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 ));
+ // Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
+ mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ // Allow any texture to be used during non-immediate mode.
+ mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE);
+ LLAggregatePermissions texture_perms;
+ if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms))
+ {
+ BOOL can_copy =
+ texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY ||
+ texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL;
+ BOOL can_transfer =
+ texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY ||
+ texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL;
+ mCtrlSculptTexture->setCanApplyImmediately(can_copy && can_transfer);
+ }
+ else
+ {
+ mCtrlSculptTexture->setCanApplyImmediately(FALSE);
+ }
+ }
+
+ mLabelSculptType = getChild<LLTextBox>("label sculpt type");
+ mCtrlSculptType = getChild<LLComboBox>("sculpt type control");
+ childSetCommitCallback("sculpt type control", onCommitSculptType, this);
+ mCtrlSculptMirror = getChild<LLCheckBoxCtrl>("sculpt mirror control");
+ childSetCommitCallback("sculpt mirror control", onCommitSculptType, this);
+ mCtrlSculptInvert = getChild<LLCheckBoxCtrl>("sculpt invert control");
+ childSetCommitCallback("sculpt invert control", onCommitSculptType, this);
+
+ // Start with everyone disabled
+ clearCtrls();
+
+ return TRUE;
+}
+
+LLPanelObject::LLPanelObject()
+: LLPanel(),
+ mIsPhysical(FALSE),
+ mIsTemporary(FALSE),
+ mIsPhantom(FALSE),
+ mCastShadows(TRUE),
+ mSelectedType(MI_BOX),
+ mSculptTextureRevert(LLUUID::null),
+ mSculptTypeRevert(0)
+{
+}
+
+
+LLPanelObject::~LLPanelObject()
+{
+ // Children all cleaned up by default view destructor.
+}
+
+void LLPanelObject::getState( )
+{
+ LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
+ LLViewerObject* root_objectp = objectp;
+ if(!objectp)
+ {
+ objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
+ // *FIX: shouldn't we just keep the child?
+ if (objectp)
+ {
+ LLViewerObject* parentp = objectp->getRootEdit();
+
+ if (parentp)
+ {
+ root_objectp = parentp;
+ }
+ else
+ {
+ root_objectp = objectp;
+ }
+ }
+ }
+
+ LLVOVolume *volobjp = NULL;
+ if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
+ {
+ volobjp = (LLVOVolume *)objectp;
+ }
+
+ if( !objectp )
+ {
+ //forfeit focus
+ if (gFocusMgr.childHasKeyboardFocus(this))
+ {
+ gFocusMgr.setKeyboardFocus(NULL);
+ }
+
+ // Disable all text input fields
+ clearCtrls();
+ return;
+ }
+
+ // can move or rotate only linked group with move permissions, or sub-object with move and modify perms
+ BOOL enable_move = objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
+ BOOL enable_scale = objectp->permMove() && objectp->permModify();
+ BOOL enable_rotate = objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts"));
+
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ))
+ && (selected_count == 1);
+
+ if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1)
+ {
+ enable_move = FALSE;
+ enable_scale = FALSE;
+ enable_rotate = FALSE;
+ }
+
+ LLVector3 vec;
+ if (enable_move)
+ {
+ vec = objectp->getPositionEdit();
+ mCtrlPosX->set( vec.mV[VX] );
+ mCtrlPosY->set( vec.mV[VY] );
+ mCtrlPosZ->set( vec.mV[VZ] );
+ }
+ else
+ {
+ mCtrlPosX->clear();
+ mCtrlPosY->clear();
+ mCtrlPosZ->clear();
+ }
+
+
+ mLabelPosition->setEnabled( enable_move );
+ mCtrlPosX->setEnabled(enable_move);
+ mCtrlPosY->setEnabled(enable_move);
+ mCtrlPosZ->setEnabled(enable_move);
+
+ if (enable_scale)
+ {
+ vec = objectp->getScale();
+ mCtrlScaleX->set( vec.mV[VX] );
+ mCtrlScaleY->set( vec.mV[VY] );
+ mCtrlScaleZ->set( vec.mV[VZ] );
+ }
+ else
+ {
+ mCtrlScaleX->clear();
+ mCtrlScaleY->clear();
+ mCtrlScaleZ->clear();
+ }
+
+ mLabelSize->setEnabled( enable_scale );
+ mCtrlScaleX->setEnabled( enable_scale );
+ mCtrlScaleY->setEnabled( enable_scale );
+ mCtrlScaleZ->setEnabled( enable_scale );
+
+ LLQuaternion object_rot = objectp->getRotationEdit();
+ object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ]));
+ mCurEulerDegrees *= RAD_TO_DEG;
+ mCurEulerDegrees.mV[VX] = fmod(llround(mCurEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mCurEulerDegrees.mV[VY] = fmod(llround(mCurEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mCurEulerDegrees.mV[VZ] = fmod(llround(mCurEulerDegrees.mV[VZ], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+
+ if (enable_rotate)
+ {
+ mCtrlRotX->set( mCurEulerDegrees.mV[VX] );
+ mCtrlRotY->set( mCurEulerDegrees.mV[VY] );
+ mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] );
+ }
+ else
+ {
+ mCtrlRotX->clear();
+ mCtrlRotY->clear();
+ mCtrlRotZ->clear();
+ }
+
+ mLabelRotation->setEnabled( enable_rotate );
+ mCtrlRotX->setEnabled( enable_rotate );
+ mCtrlRotY->setEnabled( enable_rotate );
+ mCtrlRotZ->setEnabled( enable_rotate );
+
+ BOOL owners_identical;
+ LLUUID owner_id;
+ std::string owner_name;
+ owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
+
+ // BUG? Check for all objects being editable?
+ S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount();
+ BOOL editable = root_objectp->permModify();
+
+ // Select Single Message
+ getChildView("select_single")->setVisible( FALSE);
+ getChildView("edit_object")->setVisible( FALSE);
+ if (!editable || single_volume || selected_count <= 1)
+ {
+ getChildView("edit_object")->setVisible( TRUE);
+ getChildView("edit_object")->setEnabled(TRUE);
+ }
+ else
+ {
+ getChildView("select_single")->setVisible( TRUE);
+ getChildView("select_single")->setEnabled(TRUE);
+ }
+ // Lock checkbox - only modifiable if you own the object.
+ BOOL self_owned = (gAgent.getID() == owner_id);
+ mCheckLock->setEnabled( roots_selected > 0 && self_owned );
+
+ // More lock and debit checkbox - get the values
+ BOOL valid;
+ U32 owner_mask_on;
+ U32 owner_mask_off;
+ valid = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, &owner_mask_on, &owner_mask_off);
+
+ if(valid)
+ {
+ if(owner_mask_on & PERM_MOVE)
+ {
+ // owner can move, so not locked
+ mCheckLock->set(FALSE);
+ mCheckLock->setTentative(FALSE);
+ }
+ else if(owner_mask_off & PERM_MOVE)
+ {
+ // owner can't move, so locked
+ mCheckLock->set(TRUE);
+ mCheckLock->setTentative(FALSE);
+ }
+ else
+ {
+ // some locked, some not locked
+ mCheckLock->set(FALSE);
+ mCheckLock->setTentative(TRUE);
+ }
+ }
+
+ BOOL is_flexible = volobjp && volobjp->isFlexible();
+
+ // Physics checkbox
+ mIsPhysical = root_objectp->usePhysics();
+ mCheckPhysics->set( mIsPhysical );
+ mCheckPhysics->setEnabled( roots_selected>0
+ && (editable || gAgent.isGodlike())
+ && !is_flexible);
+
+ mIsTemporary = root_objectp->flagTemporaryOnRez();
+ mCheckTemporary->set( mIsTemporary );
+ mCheckTemporary->setEnabled( roots_selected>0 && editable );
+
+ mIsPhantom = root_objectp->flagPhantom();
+ mCheckPhantom->set( mIsPhantom );
+ mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible );
+
+
+#if 0 // 1.9.2
+ mCastShadows = root_objectp->flagCastShadows();
+ mCheckCastShadows->set( mCastShadows );
+ mCheckCastShadows->setEnabled( roots_selected==1 && editable );
+#endif
+
+ //----------------------------------------------------------------------------
+
+ S32 selected_item = MI_BOX;
+ S32 selected_hole = MI_HOLE_SAME;
+ BOOL enabled = FALSE;
+ BOOL hole_enabled = FALSE;
+ F32 scale_x=1.f, scale_y=1.f;
+ BOOL isMesh = FALSE;
+
+ if( !objectp || !objectp->getVolume() || !editable || !single_volume)
+ {
+ // Clear out all geometry fields.
+ mComboBaseType->clear();
+ mSpinHollow->clear();
+ mSpinCutBegin->clear();
+ mSpinCutEnd->clear();
+ mCtrlPathBegin->clear();
+ mCtrlPathEnd->clear();
+ mSpinScaleX->clear();
+ mSpinScaleY->clear();
+ mSpinTwist->clear();
+ mSpinTwistBegin->clear();
+ mComboHoleType->clear();
+ mSpinShearX->clear();
+ mSpinShearY->clear();
+ mSpinTaperX->clear();
+ mSpinTaperY->clear();
+ mSpinRadiusOffset->clear();
+ mSpinRevolutions->clear();
+ mSpinSkew->clear();
+
+ mSelectedType = MI_NONE;
+ }
+ else
+ {
+ // Only allowed to change these parameters for objects
+ // that you have permissions on AND are not attachments.
+ enabled = root_objectp->permModify();
+
+ // Volume type
+ const LLVolumeParams &volume_params = objectp->getVolume()->getParams();
+ U8 path = volume_params.getPathParams().getCurveType();
+ U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
+ U8 profile = profile_and_hole & LL_PCODE_PROFILE_MASK;
+ U8 hole = profile_and_hole & LL_PCODE_HOLE_MASK;
+
+ // Scale goes first so we can differentiate between a sphere and a torus,
+ // which have the same profile and path types.
+
+ // Scale
+ scale_x = volume_params.getRatioX();
+ scale_y = volume_params.getRatioY();
+
+ BOOL linear_path = (path == LL_PCODE_PATH_LINE) || (path == LL_PCODE_PATH_FLEXIBLE);
+ if ( linear_path && profile == LL_PCODE_PROFILE_CIRCLE )
+ {
+ selected_item = MI_CYLINDER;
+ }
+ else if ( linear_path && profile == LL_PCODE_PROFILE_SQUARE )
+ {
+ selected_item = MI_BOX;
+ }
+ else if ( linear_path && profile == LL_PCODE_PROFILE_ISOTRI )
+ {
+ selected_item = MI_PRISM;
+ }
+ else if ( linear_path && profile == LL_PCODE_PROFILE_EQUALTRI )
+ {
+ selected_item = MI_PRISM;
+ }
+ else if ( linear_path && profile == LL_PCODE_PROFILE_RIGHTTRI )
+ {
+ selected_item = MI_PRISM;
+ }
+ else if (path == LL_PCODE_PATH_FLEXIBLE) // shouldn't happen
+ {
+ selected_item = MI_CYLINDER; // reasonable default
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y > 0.75f)
+ {
+ selected_item = MI_SPHERE;
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y <= 0.75f)
+ {
+ selected_item = MI_TORUS;
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE_HALF)
+ {
+ selected_item = MI_SPHERE;
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE2 && profile == LL_PCODE_PROFILE_CIRCLE )
+ {
+ // Spirals aren't supported. Make it into a sphere. JC
+ selected_item = MI_SPHERE;
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_EQUALTRI )
+ {
+ selected_item = MI_RING;
+ }
+ else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_SQUARE && scale_y <= 0.75f)
+ {
+ selected_item = MI_TUBE;
+ }
+ else
+ {
+ llinfos << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << llendl;
+ selected_item = MI_BOX;
+ }
+
+
+ if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
+ {
+ selected_item = MI_SCULPT;
+ //LLFirstUse::useSculptedPrim();
+ }
+
+
+ mComboBaseType ->setCurrentByIndex( selected_item );
+ mSelectedType = selected_item;
+
+ // Grab S path
+ F32 begin_s = volume_params.getBeginS();
+ F32 end_s = volume_params.getEndS();
+
+ // Compute cut and advanced cut from S and T
+ F32 begin_t = volume_params.getBeginT();
+ F32 end_t = volume_params.getEndT();
+
+ // Hollowness
+ F32 hollow = volume_params.getHollow();
+ mSpinHollow->set( 100.f * hollow );
+
+ // All hollow objects allow a shape to be selected.
+ if (hollow > 0.f)
+ {
+ switch (hole)
+ {
+ case LL_PCODE_HOLE_CIRCLE:
+ selected_hole = MI_HOLE_CIRCLE;
+ break;
+ case LL_PCODE_HOLE_SQUARE:
+ selected_hole = MI_HOLE_SQUARE;
+ break;
+ case LL_PCODE_HOLE_TRIANGLE:
+ selected_hole = MI_HOLE_TRIANGLE;
+ break;
+ case LL_PCODE_HOLE_SAME:
+ default:
+ selected_hole = MI_HOLE_SAME;
+ break;
+ }
+ mComboHoleType->setCurrentByIndex( selected_hole );
+ hole_enabled = enabled;
+ }
+ else
+ {
+ mComboHoleType->setCurrentByIndex( MI_HOLE_SAME );
+ hole_enabled = FALSE;
+ }
+
+ // Cut interpretation varies based on base object type
+ F32 cut_begin, cut_end, adv_cut_begin, adv_cut_end;
+
+ if ( selected_item == MI_SPHERE || selected_item == MI_TORUS ||
+ selected_item == MI_TUBE || selected_item == MI_RING )
+ {
+ cut_begin = begin_t;
+ cut_end = end_t;
+ adv_cut_begin = begin_s;
+ adv_cut_end = end_s;
+ }
+ else
+ {
+ cut_begin = begin_s;
+ cut_end = end_s;
+ adv_cut_begin = begin_t;
+ adv_cut_end = end_t;
+ }
+
+ mSpinCutBegin ->set( cut_begin );
+ mSpinCutEnd ->set( cut_end );
+ mCtrlPathBegin ->set( adv_cut_begin );
+ mCtrlPathEnd ->set( adv_cut_end );
+
+ // Twist
+ F32 twist = volume_params.getTwist();
+ F32 twist_begin = volume_params.getTwistBegin();
+ // Check the path type for conversion.
+ if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
+ {
+ twist *= OBJECT_TWIST_LINEAR_MAX;
+ twist_begin *= OBJECT_TWIST_LINEAR_MAX;
+ }
+ else
+ {
+ twist *= OBJECT_TWIST_MAX;
+ twist_begin *= OBJECT_TWIST_MAX;
+ }
+
+ mSpinTwist ->set( twist );
+ mSpinTwistBegin ->set( twist_begin );
+
+ // Shear
+ F32 shear_x = volume_params.getShearX();
+ F32 shear_y = volume_params.getShearY();
+ mSpinShearX->set( shear_x );
+ mSpinShearY->set( shear_y );
+
+ // Taper
+ F32 taper_x = volume_params.getTaperX();
+ F32 taper_y = volume_params.getTaperY();
+ mSpinTaperX->set( taper_x );
+ mSpinTaperY->set( taper_y );
+
+ // Radius offset.
+ F32 radius_offset = volume_params.getRadiusOffset();
+ // Limit radius offset, based on taper and hole size y.
+ F32 radius_mag = fabs(radius_offset);
+ F32 hole_y_mag = fabs(scale_y);
+ F32 taper_y_mag = fabs(taper_y);
+ // Check to see if the taper effects us.
+ if ( (radius_offset > 0.f && taper_y < 0.f) ||
+ (radius_offset < 0.f && taper_y > 0.f) )
+ {
+ // The taper does not help increase the radius offset range.
+ taper_y_mag = 0.f;
+ }
+ F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag);
+ // Enforce the maximum magnitude.
+ if (radius_mag > max_radius_mag)
+ {
+ // Check radius offset sign.
+ if (radius_offset < 0.f)
+ {
+ radius_offset = -max_radius_mag;
+ }
+ else
+ {
+ radius_offset = max_radius_mag;
+ }
+ }
+ mSpinRadiusOffset->set( radius_offset);
+
+ // Revolutions
+ F32 revolutions = volume_params.getRevolutions();
+ mSpinRevolutions->set( revolutions );
+
+ // Skew
+ F32 skew = volume_params.getSkew();
+ // Limit skew, based on revolutions hole size x.
+ F32 skew_mag= fabs(skew);
+ F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f);
+ // Discontinuity; A revolution of 1 allows skews below 0.5.
+ if ( fabs(revolutions - 1.0f) < 0.001)
+ min_skew_mag = 0.0f;
+
+ // Clip skew.
+ if (skew_mag < min_skew_mag)
+ {
+ // Check skew sign.
+ if (skew < 0.0f)
+ {
+ skew = -min_skew_mag;
+ }
+ else
+ {
+ skew = min_skew_mag;
+ }
+ }
+ mSpinSkew->set( skew );
+ }
+
+ // Compute control visibility, label names, and twist range.
+ // Start with defaults.
+ BOOL cut_visible = TRUE;
+ BOOL hollow_visible = TRUE;
+ BOOL top_size_x_visible = TRUE;
+ BOOL top_size_y_visible = TRUE;
+ BOOL top_shear_x_visible = TRUE;
+ BOOL top_shear_y_visible = TRUE;
+ BOOL twist_visible = TRUE;
+ BOOL advanced_cut_visible = FALSE;
+ BOOL taper_visible = FALSE;
+ BOOL skew_visible = FALSE;
+ BOOL radius_offset_visible = FALSE;
+ BOOL revolutions_visible = FALSE;
+ BOOL sculpt_texture_visible = FALSE;
+ F32 twist_min = OBJECT_TWIST_LINEAR_MIN;
+ F32 twist_max = OBJECT_TWIST_LINEAR_MAX;
+ F32 twist_inc = OBJECT_TWIST_LINEAR_INC;
+
+ BOOL advanced_is_dimple = FALSE;
+ BOOL advanced_is_slice = FALSE;
+ BOOL size_is_hole = FALSE;
+
+ // Tune based on overall volume type
+ switch (selected_item)
+ {
+ case MI_SPHERE:
+ top_size_x_visible = FALSE;
+ top_size_y_visible = FALSE;
+ top_shear_x_visible = FALSE;
+ top_shear_y_visible = FALSE;
+ //twist_visible = FALSE;
+ advanced_cut_visible = TRUE;
+ advanced_is_dimple = TRUE;
+ twist_min = OBJECT_TWIST_MIN;
+ twist_max = OBJECT_TWIST_MAX;
+ twist_inc = OBJECT_TWIST_INC;
+ break;
+
+ case MI_TORUS:
+ case MI_TUBE:
+ case MI_RING:
+ //top_size_x_visible = FALSE;
+ //top_size_y_visible = FALSE;
+ size_is_hole = TRUE;
+ skew_visible = TRUE;
+ advanced_cut_visible = TRUE;
+ taper_visible = TRUE;
+ radius_offset_visible = TRUE;
+ revolutions_visible = TRUE;
+ twist_min = OBJECT_TWIST_MIN;
+ twist_max = OBJECT_TWIST_MAX;
+ twist_inc = OBJECT_TWIST_INC;
+
+ break;
+
+ case MI_SCULPT:
+ cut_visible = FALSE;
+ hollow_visible = FALSE;
+ twist_visible = FALSE;
+ top_size_x_visible = FALSE;
+ top_size_y_visible = FALSE;
+ top_shear_x_visible = FALSE;
+ top_shear_y_visible = FALSE;
+ skew_visible = FALSE;
+ advanced_cut_visible = FALSE;
+ taper_visible = FALSE;
+ radius_offset_visible = FALSE;
+ revolutions_visible = FALSE;
+ sculpt_texture_visible = TRUE;
+
+ break;
+
+ case MI_BOX:
+ advanced_cut_visible = TRUE;
+ advanced_is_slice = TRUE;
+ break;
+
+ case MI_CYLINDER:
+ advanced_cut_visible = TRUE;
+ advanced_is_slice = TRUE;
+ break;
+
+ case MI_PRISM:
+ advanced_cut_visible = TRUE;
+ advanced_is_slice = TRUE;
+ break;
+
+ default:
+ break;
+ }
+
+ // Check if we need to change top size/hole size params.
+ switch (selected_item)
+ {
+ case MI_SPHERE:
+ case MI_TORUS:
+ case MI_TUBE:
+ case MI_RING:
+ mSpinScaleX->set( scale_x );
+ mSpinScaleY->set( scale_y );
+ mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);
+ mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);
+ mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE);
+ mSpinScaleY->setMaxValue(OBJECT_MAX_HOLE_SIZE_Y);
+ break;
+ default:
+ if (editable)
+ {
+ mSpinScaleX->set( 1.f - scale_x );
+ mSpinScaleY->set( 1.f - scale_y );
+ mSpinScaleX->setMinValue(-1.f);
+ mSpinScaleX->setMaxValue(1.f);
+ mSpinScaleY->setMinValue(-1.f);
+ mSpinScaleY->setMaxValue(1.f);
+ }
+ break;
+ }
+
+ // Check if we need to limit the hollow based on the hole type.
+ if ( selected_hole == MI_HOLE_SQUARE &&
+ ( selected_item == MI_CYLINDER || selected_item == MI_TORUS ||
+ selected_item == MI_PRISM || selected_item == MI_RING ||
+ selected_item == MI_SPHERE ) )
+ {
+ mSpinHollow->setMinValue(0.f);
+ mSpinHollow->setMaxValue(70.f);
+ }
+ else
+ {
+ mSpinHollow->setMinValue(0.f);
+ mSpinHollow->setMaxValue(95.f);
+ }
+
+ // Update field enablement
+ mComboBaseType ->setEnabled( enabled );
+
+ mLabelCut ->setEnabled( enabled );
+ mSpinCutBegin ->setEnabled( enabled );
+ mSpinCutEnd ->setEnabled( enabled );
+
+ mLabelHollow ->setEnabled( enabled );
+ mSpinHollow ->setEnabled( enabled );
+ mLabelHoleType ->setEnabled( hole_enabled );
+ mComboHoleType ->setEnabled( hole_enabled );
+
+ mLabelTwist ->setEnabled( enabled );
+ mSpinTwist ->setEnabled( enabled );
+ mSpinTwistBegin ->setEnabled( enabled );
+
+ mLabelSkew ->setEnabled( enabled );
+ mSpinSkew ->setEnabled( enabled );
+
+ getChildView("scale_hole")->setVisible( FALSE);
+ getChildView("scale_taper")->setVisible( FALSE);
+ if (top_size_x_visible || top_size_y_visible)
+ {
+ if (size_is_hole)
+ {
+ getChildView("scale_hole")->setVisible( TRUE);
+ getChildView("scale_hole")->setEnabled(enabled);
+ }
+ else
+ {
+ getChildView("scale_taper")->setVisible( TRUE);
+ getChildView("scale_taper")->setEnabled(enabled);
+ }
+ }
+
+ mSpinScaleX ->setEnabled( enabled );
+ mSpinScaleY ->setEnabled( enabled );
+
+ mLabelShear ->setEnabled( enabled );
+ mSpinShearX ->setEnabled( enabled );
+ mSpinShearY ->setEnabled( enabled );
+
+ getChildView("advanced_cut")->setVisible( FALSE);
+ getChildView("advanced_dimple")->setVisible( FALSE);
+ getChildView("advanced_slice")->setVisible( FALSE);
+
+ if (advanced_cut_visible)
+ {
+ if (advanced_is_dimple)
+ {
+ getChildView("advanced_dimple")->setVisible( TRUE);
+ getChildView("advanced_dimple")->setEnabled(enabled);
+ }
+
+ else if (advanced_is_slice)
+ {
+ getChildView("advanced_slice")->setVisible( TRUE);
+ getChildView("advanced_slice")->setEnabled(enabled);
+ }
+ else
+ {
+ getChildView("advanced_cut")->setVisible( TRUE);
+ getChildView("advanced_cut")->setEnabled(enabled);
+ }
+ }
+
+ mCtrlPathBegin ->setEnabled( enabled );
+ mCtrlPathEnd ->setEnabled( enabled );
+
+ mLabelTaper ->setEnabled( enabled );
+ mSpinTaperX ->setEnabled( enabled );
+ mSpinTaperY ->setEnabled( enabled );
+
+ mLabelRadiusOffset->setEnabled( enabled );
+ mSpinRadiusOffset ->setEnabled( enabled );
+
+ mLabelRevolutions->setEnabled( enabled );
+ mSpinRevolutions ->setEnabled( enabled );
+
+ // Update field visibility
+ mLabelCut ->setVisible( cut_visible );
+ mSpinCutBegin ->setVisible( cut_visible );
+ mSpinCutEnd ->setVisible( cut_visible );
+
+ mLabelHollow ->setVisible( hollow_visible );
+ mSpinHollow ->setVisible( hollow_visible );
+ mLabelHoleType ->setVisible( hollow_visible );
+ mComboHoleType ->setVisible( hollow_visible );
+
+ mLabelTwist ->setVisible( twist_visible );
+ mSpinTwist ->setVisible( twist_visible );
+ mSpinTwistBegin ->setVisible( twist_visible );
+ mSpinTwist ->setMinValue( twist_min );
+ mSpinTwist ->setMaxValue( twist_max );
+ mSpinTwist ->setIncrement( twist_inc );
+ mSpinTwistBegin ->setMinValue( twist_min );
+ mSpinTwistBegin ->setMaxValue( twist_max );
+ mSpinTwistBegin ->setIncrement( twist_inc );
+
+ mSpinScaleX ->setVisible( top_size_x_visible );
+ mSpinScaleY ->setVisible( top_size_y_visible );
+
+ mLabelSkew ->setVisible( skew_visible );
+ mSpinSkew ->setVisible( skew_visible );
+
+ mLabelShear ->setVisible( top_shear_x_visible || top_shear_y_visible );
+ mSpinShearX ->setVisible( top_shear_x_visible );
+ mSpinShearY ->setVisible( top_shear_y_visible );
+
+ mCtrlPathBegin ->setVisible( advanced_cut_visible );
+ mCtrlPathEnd ->setVisible( advanced_cut_visible );
+
+ mLabelTaper ->setVisible( taper_visible );
+ mSpinTaperX ->setVisible( taper_visible );
+ mSpinTaperY ->setVisible( taper_visible );
+
+ mLabelRadiusOffset->setVisible( radius_offset_visible );
+ mSpinRadiusOffset ->setVisible( radius_offset_visible );
+
+ mLabelRevolutions->setVisible( revolutions_visible );
+ mSpinRevolutions ->setVisible( revolutions_visible );
+
+ mCtrlSculptTexture->setVisible(sculpt_texture_visible);
+ mLabelSculptType->setVisible(sculpt_texture_visible);
+ mCtrlSculptType->setVisible(sculpt_texture_visible);
+
+
+ // sculpt texture
+ if (selected_item == MI_SCULPT)
+ {
+
+
+ LLUUID id;
+ LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+
+
+ if (sculpt_params) // if we have a legal sculpt param block for this object:
+ {
+ if (mObject != objectp) // we've just selected a new object, so save for undo
+ {
+ mSculptTextureRevert = sculpt_params->getSculptTexture();
+ mSculptTypeRevert = sculpt_params->getSculptType();
+ }
+
+ U8 sculpt_type = sculpt_params->getSculptType();
+ U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
+ BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
+ BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
+ isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
+
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
+ if(mTextureCtrl)
+ {
+ mTextureCtrl->setTentative(FALSE);
+ mTextureCtrl->setEnabled(editable && !isMesh);
+ if (editable)
+ mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture());
+ else
+ mTextureCtrl->setImageAssetID(LLUUID::null);
+ }
+
+ mComboBaseType->setEnabled(!isMesh);
+
+ if (mCtrlSculptType)
+ {
+ mCtrlSculptType->setCurrentByIndex(sculpt_stitching);
+ mCtrlSculptType->setEnabled(editable && !isMesh);
+ }
+
+ if (mCtrlSculptMirror)
+ {
+ mCtrlSculptMirror->set(sculpt_mirror);
+ mCtrlSculptMirror->setEnabled(editable && !isMesh);
+ }
+
+ if (mCtrlSculptInvert)
+ {
+ mCtrlSculptInvert->set(sculpt_invert);
+ mCtrlSculptInvert->setEnabled(editable);
+ }
+
+ if (mLabelSculptType)
+ {
+ mLabelSculptType->setEnabled(TRUE);
+ }
+
+ }
+ }
+ else
+ {
+ mSculptTextureRevert = LLUUID::null;
+ }
+
+ mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh);
+ mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh);
+
+ //----------------------------------------------------------------------------
+
+ mObject = objectp;
+ mRootObject = root_objectp;
+}
+
+// static
+bool LLPanelObject::precommitValidate( const LLSD& data )
+{
+ // TODO: Richard will fill this in later.
+ return TRUE; // FALSE means that validation failed and new value should not be commited.
+}
+
+void LLPanelObject::sendIsPhysical()
+{
+ BOOL value = mCheckPhysics->get();
+ if( mIsPhysical != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdatePhysics(value);
+ mIsPhysical = value;
+
+ llinfos << "update physics sent" << llendl;
+ }
+ else
+ {
+ llinfos << "update physics not changed" << llendl;
+ }
+}
+
+void LLPanelObject::sendIsTemporary()
+{
+ BOOL value = mCheckTemporary->get();
+ if( mIsTemporary != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdateTemporary(value);
+ mIsTemporary = value;
+
+ llinfos << "update temporary sent" << llendl;
+ }
+ else
+ {
+ llinfos << "update temporary not changed" << llendl;
+ }
+}
+
+
+void LLPanelObject::sendIsPhantom()
+{
+ BOOL value = mCheckPhantom->get();
+ if( mIsPhantom != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdatePhantom(value);
+ mIsPhantom = value;
+
+ llinfos << "update phantom sent" << llendl;
+ }
+ else
+ {
+ llinfos << "update phantom not changed" << llendl;
+ }
+}
+
+void LLPanelObject::sendCastShadows()
+{
+ BOOL value = mCheckCastShadows->get();
+ if( mCastShadows != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdateCastShadows(value);
+ mCastShadows = value;
+
+ llinfos << "update cast shadows sent" << llendl;
+ }
+ else
+ {
+ llinfos << "update cast shadows not changed" << llendl;
+ }
+}
+
+// static
+void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+
+ if (self->mObject.isNull())
+ {
+ return;
+ }
+
+ if (self->mObject->getPCode() != LL_PCODE_VOLUME)
+ {
+ // Don't allow modification of non-volume objects.
+ return;
+ }
+
+ LLVolume *volume = self->mObject->getVolume();
+ if (!volume)
+ {
+ return;
+ }
+
+ LLVolumeParams volume_params;
+ self->getVolumeParams(volume_params);
+
+
+
+ // set sculpting
+ S32 selected_type = self->mComboBaseType->getCurrentIndex();
+
+ if (selected_type == MI_SCULPT)
+ {
+ self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, TRUE, TRUE);
+ LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ if (sculpt_params)
+ volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType());
+ }
+ else
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ if (sculpt_params)
+ self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE);
+ }
+
+ // Update the volume, if necessary.
+ self->mObject->updateVolume(volume_params);
+
+
+ // This was added to make sure thate when changes are made, the UI
+ // adjusts to present valid options.
+ // *FIX: only some changes, ie, hollow or primitive type changes,
+ // require a refresh.
+ self->refresh();
+
+}
+
+void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params)
+{
+ // Figure out what type of volume to make
+ S32 was_selected_type = mSelectedType;
+ S32 selected_type = mComboBaseType->getCurrentIndex();
+ U8 profile;
+ U8 path;
+ switch ( selected_type )
+ {
+ case MI_CYLINDER:
+ profile = LL_PCODE_PROFILE_CIRCLE;
+ path = LL_PCODE_PATH_LINE;
+ break;
+
+ case MI_BOX:
+ profile = LL_PCODE_PROFILE_SQUARE;
+ path = LL_PCODE_PATH_LINE;
+ break;
+
+ case MI_PRISM:
+ profile = LL_PCODE_PROFILE_EQUALTRI;
+ path = LL_PCODE_PATH_LINE;
+ break;
+
+ case MI_SPHERE:
+ profile = LL_PCODE_PROFILE_CIRCLE_HALF;
+ path = LL_PCODE_PATH_CIRCLE;
+ break;
+
+ case MI_TORUS:
+ profile = LL_PCODE_PROFILE_CIRCLE;
+ path = LL_PCODE_PATH_CIRCLE;
+ break;
+
+ case MI_TUBE:
+ profile = LL_PCODE_PROFILE_SQUARE;
+ path = LL_PCODE_PATH_CIRCLE;
+ break;
+
+ case MI_RING:
+ profile = LL_PCODE_PROFILE_EQUALTRI;
+ path = LL_PCODE_PATH_CIRCLE;
+ break;
+
+ case MI_SCULPT:
+ profile = LL_PCODE_PROFILE_CIRCLE;
+ path = LL_PCODE_PATH_CIRCLE;
+ break;
+
+ default:
+ llwarns << "Unknown base type " << selected_type
+ << " in getVolumeParams()" << llendl;
+ // assume a box
+ selected_type = MI_BOX;
+ profile = LL_PCODE_PROFILE_SQUARE;
+ path = LL_PCODE_PATH_LINE;
+ break;
+ }
+
+
+ if (path == LL_PCODE_PATH_LINE)
+ {
+ LLVOVolume *volobjp = (LLVOVolume *)(LLViewerObject*)(mObject);
+ if (volobjp->isFlexible())
+ {
+ path = LL_PCODE_PATH_FLEXIBLE;
+ }
+ }
+
+ S32 selected_hole = mComboHoleType->getCurrentIndex();
+ U8 hole;
+ switch (selected_hole)
+ {
+ case MI_HOLE_CIRCLE:
+ hole = LL_PCODE_HOLE_CIRCLE;
+ break;
+ case MI_HOLE_SQUARE:
+ hole = LL_PCODE_HOLE_SQUARE;
+ break;
+ case MI_HOLE_TRIANGLE:
+ hole = LL_PCODE_HOLE_TRIANGLE;
+ break;
+ case MI_HOLE_SAME:
+ default:
+ hole = LL_PCODE_HOLE_SAME;
+ break;
+ }
+
+ volume_params.setType(profile | hole, path);
+ mSelectedType = selected_type;
+
+ // Compute cut start/end
+ F32 cut_begin = mSpinCutBegin->get();
+ F32 cut_end = mSpinCutEnd->get();
+
+ // Make sure at least OBJECT_CUT_INC of the object survives
+ if (cut_begin > cut_end - OBJECT_MIN_CUT_INC)
+ {
+ cut_begin = cut_end - OBJECT_MIN_CUT_INC;
+ mSpinCutBegin->set(cut_begin);
+ }
+
+ F32 adv_cut_begin = mCtrlPathBegin->get();
+ F32 adv_cut_end = mCtrlPathEnd->get();
+
+ // Make sure at least OBJECT_CUT_INC of the object survives
+ if (adv_cut_begin > adv_cut_end - OBJECT_MIN_CUT_INC)
+ {
+ adv_cut_begin = adv_cut_end - OBJECT_MIN_CUT_INC;
+ mCtrlPathBegin->set(adv_cut_begin);
+ }
+
+ F32 begin_s, end_s;
+ F32 begin_t, end_t;
+
+ if (selected_type == MI_SPHERE || selected_type == MI_TORUS ||
+ selected_type == MI_TUBE || selected_type == MI_RING)
+ {
+ begin_s = adv_cut_begin;
+ end_s = adv_cut_end;
+
+ begin_t = cut_begin;
+ end_t = cut_end;
+ }
+ else
+ {
+ begin_s = cut_begin;
+ end_s = cut_end;
+
+ begin_t = adv_cut_begin;
+ end_t = adv_cut_end;
+ }
+
+ volume_params.setBeginAndEndS(begin_s, end_s);
+ volume_params.setBeginAndEndT(begin_t, end_t);
+
+ // Hollowness
+ F32 hollow = mSpinHollow->get() / 100.f;
+
+ if ( selected_hole == MI_HOLE_SQUARE &&
+ ( selected_type == MI_CYLINDER || selected_type == MI_TORUS ||
+ selected_type == MI_PRISM || selected_type == MI_RING ||
+ selected_type == MI_SPHERE ) )
+ {
+ if (hollow > 0.7f) hollow = 0.7f;
+ }
+
+ volume_params.setHollow( hollow );
+
+ // Twist Begin,End
+ F32 twist_begin = mSpinTwistBegin->get();
+ F32 twist = mSpinTwist->get();
+ // Check the path type for twist conversion.
+ if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
+ {
+ twist_begin /= OBJECT_TWIST_LINEAR_MAX;
+ twist /= OBJECT_TWIST_LINEAR_MAX;
+ }
+ else
+ {
+ twist_begin /= OBJECT_TWIST_MAX;
+ twist /= OBJECT_TWIST_MAX;
+ }
+
+ volume_params.setTwistBegin(twist_begin);
+ volume_params.setTwist(twist);
+
+ // Scale X,Y
+ F32 scale_x = mSpinScaleX->get();
+ F32 scale_y = mSpinScaleY->get();
+ if ( was_selected_type == MI_BOX || was_selected_type == MI_CYLINDER || was_selected_type == MI_PRISM)
+ {
+ scale_x = 1.f - scale_x;
+ scale_y = 1.f - scale_y;
+ }
+
+ // Skew
+ F32 skew = mSpinSkew->get();
+
+ // Taper X,Y
+ F32 taper_x = mSpinTaperX->get();
+ F32 taper_y = mSpinTaperY->get();
+
+ // Radius offset
+ F32 radius_offset = mSpinRadiusOffset->get();
+
+ // Revolutions
+ F32 revolutions = mSpinRevolutions->get();
+
+ if ( selected_type == MI_SPHERE )
+ {
+ // Snap values to valid sphere parameters.
+ scale_x = 1.0f;
+ scale_y = 1.0f;
+ skew = 0.0f;
+ taper_x = 0.0f;
+ taper_y = 0.0f;
+ radius_offset = 0.0f;
+ revolutions = 1.0f;
+ }
+ else if ( selected_type == MI_TORUS || selected_type == MI_TUBE ||
+ selected_type == MI_RING )
+ {
+ scale_x = llclamp(
+ scale_x,
+ OBJECT_MIN_HOLE_SIZE,
+ OBJECT_MAX_HOLE_SIZE_X);
+ scale_y = llclamp(
+ scale_y,
+ OBJECT_MIN_HOLE_SIZE,
+ OBJECT_MAX_HOLE_SIZE_Y);
+
+ // Limit radius offset, based on taper and hole size y.
+ F32 radius_mag = fabs(radius_offset);
+ F32 hole_y_mag = fabs(scale_y);
+ F32 taper_y_mag = fabs(taper_y);
+ // Check to see if the taper effects us.
+ if ( (radius_offset > 0.f && taper_y < 0.f) ||
+ (radius_offset < 0.f && taper_y > 0.f) )
+ {
+ // The taper does not help increase the radius offset range.
+ taper_y_mag = 0.f;
+ }
+ F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag);
+ // Enforce the maximum magnitude.
+ if (radius_mag > max_radius_mag)
+ {
+ // Check radius offset sign.
+ if (radius_offset < 0.f)
+ {
+ radius_offset = -max_radius_mag;
+ }
+ else
+ {
+ radius_offset = max_radius_mag;
+ }
+ }
+
+ // Check the skew value against the revolutions.
+ F32 skew_mag= fabs(skew);
+ F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f);
+ // Discontinuity; A revolution of 1 allows skews below 0.5.
+ if ( fabs(revolutions - 1.0f) < 0.001)
+ min_skew_mag = 0.0f;
+
+ // Clip skew.
+ if (skew_mag < min_skew_mag)
+ {
+ // Check skew sign.
+ if (skew < 0.0f)
+ {
+ skew = -min_skew_mag;
+ }
+ else
+ {
+ skew = min_skew_mag;
+ }
+ }
+ }
+
+ volume_params.setRatio( scale_x, scale_y );
+ volume_params.setSkew(skew);
+ volume_params.setTaper( taper_x, taper_y );
+ volume_params.setRadiusOffset(radius_offset);
+ volume_params.setRevolutions(revolutions);
+
+ // Shear X,Y
+ F32 shear_x = mSpinShearX->get();
+ F32 shear_y = mSpinShearY->get();
+ volume_params.setShear( shear_x, shear_y );
+
+ if (selected_type == MI_SCULPT)
+ {
+ volume_params.setSculptID(LLUUID::null, 0);
+ volume_params.setBeginAndEndT (0, 1);
+ volume_params.setBeginAndEndS (0, 1);
+ volume_params.setHollow (0);
+ volume_params.setTwistBegin (0);
+ volume_params.setTwistEnd (0);
+ volume_params.setRatio (1, 0.5);
+ volume_params.setShear (0, 0);
+ volume_params.setTaper (0, 0);
+ volume_params.setRevolutions (1);
+ volume_params.setRadiusOffset (0);
+ volume_params.setSkew (0);
+ }
+
+}
+
+// BUG: Make work with multiple objects
+void LLPanelObject::sendRotation(BOOL btn_down)
+{
+ if (mObject.isNull()) return;
+
+ LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
+ new_rot.mV[VX] = llround(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VY] = llround(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VZ] = llround(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION);
+
+ // Note: must compare before conversion to radians
+ LLVector3 delta = new_rot - mCurEulerDegrees;
+
+ if (delta.magVec() >= 0.0005f)
+ {
+ mCurEulerDegrees = new_rot;
+ new_rot *= DEG_TO_RAD;
+
+ LLQuaternion rotation;
+ rotation.setQuat(new_rot.mV[VX], new_rot.mV[VY], new_rot.mV[VZ]);
+
+ if (mRootObject != mObject)
+ {
+ rotation = rotation * ~mRootObject->getRotationRegion();
+ }
+ std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ;
+ std::vector<LLQuaternion> child_rotations;
+ if (mObject->isRootEdit())
+ {
+ mObject->saveUnselectedChildrenRotation(child_rotations) ;
+ mObject->saveUnselectedChildrenPosition(child_positions) ;
+ }
+
+ mObject->setRotation(rotation);
+ LLManip::rebuild(mObject) ;
+
+ // for individually selected roots, we need to counterrotate all the children
+ if (mObject->isRootEdit())
+ {
+ mObject->resetChildrenRotationAndPosition(child_rotations, child_positions) ;
+ }
+
+ if(!btn_down)
+ {
+ child_positions.clear() ;
+ LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
+ }
+ }
+}
+
+
+// BUG: Make work with multiple objects
+void LLPanelObject::sendScale(BOOL btn_down)
+{
+ if (mObject.isNull()) return;
+
+ LLVector3 newscale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
+
+ LLVector3 delta = newscale - mObject->getScale();
+ if (delta.magVec() >= 0.0005f)
+ {
+ // scale changed by more than 1/2 millimeter
+
+ // check to see if we aren't scaling the textures
+ // (in which case the tex coord's need to be recomputed)
+ BOOL dont_stretch_textures = !LLManipScale::getStretchTextures();
+ if (dont_stretch_textures)
+ {
+ LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_SCALE);
+ }
+
+ mObject->setScale(newscale, TRUE);
+
+ if(!btn_down)
+ {
+ LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE | UPD_POSITION);
+ }
+
+ LLSelectMgr::getInstance()->adjustTexturesByScale(TRUE, !dont_stretch_textures);
+// llinfos << "scale sent" << llendl;
+ }
+ else
+ {
+// llinfos << "scale not changed" << llendl;
+ }
+}
+
+
+void LLPanelObject::sendPosition(BOOL btn_down)
+{
+ if (mObject.isNull()) return;
+
+ LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
+ LLViewerRegion* regionp = mObject->getRegion();
+
+ // Clamp the Z height
+ const F32 height = newpos.mV[VZ];
+ const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal());
+ const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight();
+
+ if (!mObject->isAttachment())
+ {
+ if ( height < min_height)
+ {
+ newpos.mV[VZ] = min_height;
+ mCtrlPosZ->set( min_height );
+ }
+ else if ( height > max_height )
+ {
+ newpos.mV[VZ] = max_height;
+ mCtrlPosZ->set( max_height );
+ }
+
+ // Grass is always drawn on the ground, so clamp its position to the ground
+ if (mObject->getPCode() == LL_PCODE_LEGACY_GRASS)
+ {
+ mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f);
+ }
+ }
+
+ // Make sure new position is in a valid region, so the object
+ // won't get dumped by the simulator.
+ LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos);
+
+ if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) )
+ {
+ // send only if the position is changed, that is, the delta vector is not zero
+ LLVector3d old_pos_global = mObject->getPositionGlobal();
+ LLVector3d delta = new_pos_global - old_pos_global;
+ // moved more than 1/2 millimeter
+ if (delta.magVec() >= 0.0005f)
+ {
+ if (mRootObject != mObject)
+ {
+ newpos = newpos - mRootObject->getPositionRegion();
+ newpos = newpos * ~mRootObject->getRotationRegion();
+ mObject->setPositionParent(newpos);
+ }
+ else
+ {
+ mObject->setPositionEdit(newpos);
+ }
+
+ LLManip::rebuild(mObject) ;
+
+ // for individually selected roots, we need to counter-translate all unselected children
+ if (mObject->isRootEdit())
+ {
+ // only offset by parent's translation
+ mObject->resetChildrenPosition(LLVector3(-delta), TRUE) ;
+ }
+
+ if(!btn_down)
+ {
+ LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
+ }
+
+ LLSelectMgr::getInstance()->updateSelectionCenter();
+ }
+ }
+ else
+ {
+ // move failed, so we update the UI with the correct values
+ LLVector3 vec = mRootObject->getPositionRegion();
+ mCtrlPosX->set(vec.mV[VX]);
+ mCtrlPosY->set(vec.mV[VY]);
+ mCtrlPosZ->set(vec.mV[VZ]);
+ }
+}
+
+void LLPanelObject::sendSculpt()
+{
+ if (mObject.isNull())
+ return;
+
+ LLSculptParams sculpt_params;
+
+ if (mCtrlSculptTexture)
+ sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID());
+
+ U8 sculpt_type = 0;
+
+ if (mCtrlSculptType)
+ sculpt_type |= mCtrlSculptType->getCurrentIndex();
+
+ bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
+
+ if (mCtrlSculptMirror)
+ {
+ mCtrlSculptMirror->setEnabled(enabled ? TRUE : FALSE);
+ }
+ if (mCtrlSculptInvert)
+ {
+ mCtrlSculptInvert->setEnabled(enabled ? TRUE : FALSE);
+ }
+
+ if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get()))
+ sculpt_type |= LL_SCULPT_FLAG_MIRROR;
+
+ if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get()))
+ sculpt_type |= LL_SCULPT_FLAG_INVERT;
+
+ sculpt_params.setSculptType(sculpt_type);
+ mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, TRUE);
+}
+
+void LLPanelObject::refresh()
+{
+ getState();
+ if (mObject.notNull() && mObject->isDead())
+ {
+ mObject = NULL;
+ }
+
+ if (mRootObject.notNull() && mRootObject->isDead())
+ {
+ mRootObject = NULL;
+ }
+
+ bool enable_mesh = gSavedSettings.getBOOL("MeshEnabled") &&
+ gAgent.getRegion() &&
+ !gAgent.getRegion()->getCapability("GetMesh").empty();
+
+ F32 max_scale = get_default_max_prim_scale(LLPickInfo::isFlora(mObject));
+
+ getChild<LLSpinCtrl>("Scale X")->setMaxValue(max_scale);
+ getChild<LLSpinCtrl>("Scale Y")->setMaxValue(max_scale);
+ getChild<LLSpinCtrl>("Scale Z")->setMaxValue(max_scale);
+
+ BOOL found = mCtrlSculptType->itemExists("Mesh");
+ if (enable_mesh && !found)
+ {
+ mCtrlSculptType->add("Mesh");
+ }
+ else if (!enable_mesh && found)
+ {
+ mCtrlSculptType->remove("Mesh");
+ }
+}
+
+
+void LLPanelObject::draw()
+{
+ const LLColor4 white( 1.0f, 1.0f, 1.0f, 1);
+ const LLColor4 red( 1.0f, 0.25f, 0.f, 1);
+ const LLColor4 green( 0.f, 1.0f, 0.f, 1);
+ const LLColor4 blue( 0.f, 0.5f, 1.0f, 1);
+
+ // Tune the colors of the labels
+ LLTool* tool = LLToolMgr::getInstance()->getCurrentTool();
+
+ if (tool == LLToolCompTranslate::getInstance())
+ {
+ mCtrlPosX ->setLabelColor(red);
+ mCtrlPosY ->setLabelColor(green);
+ mCtrlPosZ ->setLabelColor(blue);
+
+ mCtrlScaleX ->setLabelColor(white);
+ mCtrlScaleY ->setLabelColor(white);
+ mCtrlScaleZ ->setLabelColor(white);
+
+ mCtrlRotX ->setLabelColor(white);
+ mCtrlRotY ->setLabelColor(white);
+ mCtrlRotZ ->setLabelColor(white);
+ }
+ else if ( tool == LLToolCompScale::getInstance() )
+ {
+ mCtrlPosX ->setLabelColor(white);
+ mCtrlPosY ->setLabelColor(white);
+ mCtrlPosZ ->setLabelColor(white);
+
+ mCtrlScaleX ->setLabelColor(red);
+ mCtrlScaleY ->setLabelColor(green);
+ mCtrlScaleZ ->setLabelColor(blue);
+
+ mCtrlRotX ->setLabelColor(white);
+ mCtrlRotY ->setLabelColor(white);
+ mCtrlRotZ ->setLabelColor(white);
+ }
+ else if ( tool == LLToolCompRotate::getInstance() )
+ {
+ mCtrlPosX ->setLabelColor(white);
+ mCtrlPosY ->setLabelColor(white);
+ mCtrlPosZ ->setLabelColor(white);
+
+ mCtrlScaleX ->setLabelColor(white);
+ mCtrlScaleY ->setLabelColor(white);
+ mCtrlScaleZ ->setLabelColor(white);
+
+ mCtrlRotX ->setLabelColor(red);
+ mCtrlRotY ->setLabelColor(green);
+ mCtrlRotZ ->setLabelColor(blue);
+ }
+ else
+ {
+ mCtrlPosX ->setLabelColor(white);
+ mCtrlPosY ->setLabelColor(white);
+ mCtrlPosZ ->setLabelColor(white);
+
+ mCtrlScaleX ->setLabelColor(white);
+ mCtrlScaleY ->setLabelColor(white);
+ mCtrlScaleZ ->setLabelColor(white);
+
+ mCtrlRotX ->setLabelColor(white);
+ mCtrlRotY ->setLabelColor(white);
+ mCtrlRotZ ->setLabelColor(white);
+ }
+
+ LLPanel::draw();
+}
+
+// virtual
+void LLPanelObject::clearCtrls()
+{
+ LLPanel::clearCtrls();
+
+ mCheckLock ->set(FALSE);
+ mCheckLock ->setEnabled( FALSE );
+ mCheckPhysics ->set(FALSE);
+ mCheckPhysics ->setEnabled( FALSE );
+ mCheckTemporary ->set(FALSE);
+ mCheckTemporary ->setEnabled( FALSE );
+ mCheckPhantom ->set(FALSE);
+ mCheckPhantom ->setEnabled( FALSE );
+
+#if 0 // 1.9.2
+ mCheckCastShadows->set(FALSE);
+ mCheckCastShadows->setEnabled( FALSE );
+#endif
+ // Disable text labels
+ mLabelPosition ->setEnabled( FALSE );
+ mLabelSize ->setEnabled( FALSE );
+ mLabelRotation ->setEnabled( FALSE );
+ mLabelCut ->setEnabled( FALSE );
+ mLabelHollow ->setEnabled( FALSE );
+ mLabelHoleType ->setEnabled( FALSE );
+ mLabelTwist ->setEnabled( FALSE );
+ mLabelSkew ->setEnabled( FALSE );
+ mLabelShear ->setEnabled( FALSE );
+ mLabelTaper ->setEnabled( FALSE );
+ mLabelRadiusOffset->setEnabled( FALSE );
+ mLabelRevolutions->setEnabled( FALSE );
+
+ getChildView("select_single")->setVisible( FALSE);
+ getChildView("edit_object")->setVisible( TRUE);
+ getChildView("edit_object")->setEnabled(FALSE);
+
+ getChildView("scale_hole")->setEnabled(FALSE);
+ getChildView("scale_taper")->setEnabled(FALSE);
+ getChildView("advanced_cut")->setEnabled(FALSE);
+ getChildView("advanced_dimple")->setEnabled(FALSE);
+ getChildView("advanced_slice")->setVisible( FALSE);
+}
+
+//
+// Static functions
+//
+
+// static
+void LLPanelObject::onCommitLock(LLUICtrl *ctrl, void *data)
+{
+ // Checkbox will have toggled itself
+ LLPanelObject *self = (LLPanelObject *)data;
+
+ if(self->mRootObject.isNull()) return;
+
+ BOOL new_state = self->mCheckLock->get();
+
+ LLSelectMgr::getInstance()->selectionSetObjectPermissions(PERM_OWNER, !new_state, PERM_MOVE | PERM_MODIFY);
+}
+
+// static
+void LLPanelObject::onCommitPosition( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ;
+ self->sendPosition(btn_down);
+}
+
+// static
+void LLPanelObject::onCommitScale( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ;
+ self->sendScale(btn_down);
+}
+
+// static
+void LLPanelObject::onCommitRotation( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ BOOL btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown() ;
+ self->sendRotation(btn_down);
+}
+
+// static
+void LLPanelObject::onCommitPhysics( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ self->sendIsPhysical();
+}
+
+// static
+void LLPanelObject::onCommitTemporary( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ self->sendIsTemporary();
+}
+
+// static
+void LLPanelObject::onCommitPhantom( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ self->sendIsPhantom();
+}
+
+// static
+void LLPanelObject::onCommitCastShadows( LLUICtrl* ctrl, void* userdata )
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+ self->sendCastShadows();
+}
+
+
+void LLPanelObject::onSelectSculpt(const LLSD& data)
+{
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
+
+ if (mTextureCtrl)
+ {
+ mSculptTextureRevert = mTextureCtrl->getImageAssetID();
+ }
+
+ sendSculpt();
+}
+
+
+void LLPanelObject::onCommitSculpt( const LLSD& data )
+{
+ sendSculpt();
+}
+
+BOOL LLPanelObject::onDropSculpt(LLInventoryItem* item)
+{
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
+
+ if (mTextureCtrl)
+ {
+ LLUUID asset = item->getAssetUUID();
+
+ mTextureCtrl->setImageAssetID(asset);
+ mSculptTextureRevert = asset;
+ }
+
+ return TRUE;
+}
+
+
+void LLPanelObject::onCancelSculpt(const LLSD& data)
+{
+ LLTextureCtrl* mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
+ if(!mTextureCtrl)
+ return;
+
+ mTextureCtrl->setImageAssetID(mSculptTextureRevert);
+
+ sendSculpt();
+}
+
+// static
+void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata)
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+
+ self->sendSculpt();
+}
diff --git a/indra/newview/llviewerobject.cpp b/indra/newview/llviewerobject.cpp index e7878d8adf..929f3ad188 100644 --- a/indra/newview/llviewerobject.cpp +++ b/indra/newview/llviewerobject.cpp @@ -1,5712 +1,5712 @@ -/** - * @file llviewerobject.cpp - * @brief Base class for viewer objects - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#include "llviewerprecompiledheaders.h" - -#include "llviewerobject.h" - -#include "llaudioengine.h" -#include "imageids.h" -#include "indra_constants.h" -#include "llmath.h" -#include "llflexibleobject.h" -#include "llviewercontrol.h" -#include "lldatapacker.h" -#include "llfasttimer.h" -#include "llfloaterreg.h" -#include "llfontgl.h" -#include "llframetimer.h" -#include "llinventory.h" -#include "llinventorydefines.h" -#include "llmaterialtable.h" -#include "llmutelist.h" -#include "llnamevalue.h" -#include "llprimitive.h" -#include "llquantize.h" -#include "llregionhandle.h" -#include "llsdserialize.h" -#include "lltree_common.h" -#include "llxfermanager.h" -#include "message.h" -#include "object_flags.h" -#include "timing.h" - -#include "llaudiosourcevo.h" -#include "llagent.h" -#include "llagentcamera.h" -#include "llbbox.h" -#include "llbox.h" -#include "llcylinder.h" -#include "lldrawable.h" -#include "llface.h" -#include "llfloaterproperties.h" -#include "llfloatertools.h" -#include "llfollowcam.h" -#include "llhudtext.h" -#include "llselectmgr.h" -#include "llrendersphere.h" -#include "lltooldraganddrop.h" -#include "llviewercamera.h" -#include "llviewertexturelist.h" -#include "llviewerinventory.h" -#include "llviewerobjectlist.h" -#include "llviewerparceloverlay.h" -#include "llviewerpartsource.h" -#include "llviewerregion.h" -#include "llviewerstats.h" -#include "llviewertextureanim.h" -#include "llviewerwindow.h" // For getSpinAxis -#include "llvoavatar.h" -#include "llvoavatarself.h" -#include "llvoclouds.h" -#include "llvograss.h" -#include "llvoground.h" -#include "llvolume.h" -#include "llvolumemessage.h" -#include "llvopartgroup.h" -#include "llvosky.h" -#include "llvosurfacepatch.h" -#include "llvotextbubble.h" -#include "llvotree.h" -#include "llvovolume.h" -#include "llvowater.h" -#include "llworld.h" -#include "llui.h" -#include "pipeline.h" -#include "llviewernetwork.h" -#include "llvowlsky.h" -#include "llmanip.h" -#include "lltrans.h" -#include "llsdutil.h" -#include "llmediaentry.h" -#include "llaccountingquota.h" - -//#define DEBUG_UPDATE_TYPE - -BOOL LLViewerObject::sVelocityInterpolate = TRUE; -BOOL LLViewerObject::sPingInterpolate = TRUE; - -U32 LLViewerObject::sNumZombieObjects = 0; -S32 LLViewerObject::sNumObjects = 0; -BOOL LLViewerObject::sMapDebug = TRUE; -LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK -LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit -S32 LLViewerObject::sAxisArrowLength(50); -BOOL LLViewerObject::sPulseEnabled(FALSE); -BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE - -// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime -F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion -F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction - - -static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object"); - -// static -LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) -{ - LLViewerObject *res = NULL; - LLFastTimer t1(FTM_CREATE_OBJECT); - - switch (pcode) - { - case LL_PCODE_VOLUME: - res = new LLVOVolume(id, pcode, regionp); break; - case LL_PCODE_LEGACY_AVATAR: - { - if (id == gAgentID) - { - if (!gAgentAvatarp) - { - gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp); - } - else - { - gAgentAvatarp->updateRegion(regionp); - } - res = gAgentAvatarp; - } - else - { - res = new LLVOAvatar(id, pcode, regionp); - } - static_cast<LLVOAvatar*>(res)->initInstance(); - break; - } - case LL_PCODE_LEGACY_GRASS: - res = new LLVOGrass(id, pcode, regionp); break; - case LL_PCODE_LEGACY_PART_SYS: -// llwarns << "Creating old part sys!" << llendl; -// res = new LLVOPart(id, pcode, regionp); break; - res = NULL; break; - case LL_PCODE_LEGACY_TREE: - res = new LLVOTree(id, pcode, regionp); break; - case LL_PCODE_TREE_NEW: -// llwarns << "Creating new tree!" << llendl; -// res = new LLVOTree(id, pcode, regionp); break; - res = NULL; break; - case LL_PCODE_LEGACY_TEXT_BUBBLE: - res = new LLVOTextBubble(id, pcode, regionp); break; - case LL_VO_CLOUDS: - res = new LLVOClouds(id, pcode, regionp); break; - case LL_VO_SURFACE_PATCH: - res = new LLVOSurfacePatch(id, pcode, regionp); break; - case LL_VO_SKY: - res = new LLVOSky(id, pcode, regionp); break; - case LL_VO_VOID_WATER: - res = new LLVOVoidWater(id, pcode, regionp); break; - case LL_VO_WATER: - res = new LLVOWater(id, pcode, regionp); break; - case LL_VO_GROUND: - res = new LLVOGround(id, pcode, regionp); break; - case LL_VO_PART_GROUP: - res = new LLVOPartGroup(id, pcode, regionp); break; - case LL_VO_HUD_PART_GROUP: - res = new LLVOHUDPartGroup(id, pcode, regionp); break; - case LL_VO_WL_SKY: - res = new LLVOWLSky(id, pcode, regionp); break; - default: - llwarns << "Unknown object pcode " << (S32)pcode << llendl; - res = NULL; break; - } - return res; -} - -LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global) -: LLPrimitive(), - mChildList(), - mID(id), - mLocalID(0), - mTotalCRC(0), - mTEImages(NULL), - mGLName(0), - mbCanSelect(TRUE), - mFlags(0), - mPhysicsShapeType(0), - mPhysicsGravity(0), - mPhysicsFriction(0), - mPhysicsDensity(0), - mPhysicsRestitution(0), - mDrawable(), - mCreateSelected(FALSE), - mRenderMedia(FALSE), - mBestUpdatePrecision(0), - mText(), - mLastInterpUpdateSecs(0.f), - mLastMessageUpdateSecs(0.f), - mLatestRecvPacketID(0), - mData(NULL), - mAudioSourcep(NULL), - mAudioGain(1.f), - mAppAngle(0.f), - mPixelArea(1024.f), - mInventory(NULL), - mInventorySerialNum(0), - mRegionp( regionp ), - mInventoryPending(FALSE), - mInventoryDirty(FALSE), - mDead(FALSE), - mOrphaned(FALSE), - mUserSelected(FALSE), - mOnActiveList(FALSE), - mOnMap(FALSE), - mStatic(FALSE), - mNumFaces(0), - mTimeDilation(1.f), - mRotTime(0.f), - mJointInfo(NULL), - mState(0), - mMedia(NULL), - mClickAction(0), - mObjectCost(0), - mLinksetCost(0), - mPhysicsCost(0), - mLinksetPhysicsCost(0.f), - mCostStale(true), - mPhysicsShapeUnknown(true), - mAttachmentItemID(LLUUID::null), - mLastUpdateType(OUT_UNKNOWN), - mLastUpdateCached(FALSE) -{ - if (!is_global) - { - llassert(mRegionp); - } - - LLPrimitive::init_primitive(pcode); - - // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time - mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); - - mPositionRegion = LLVector3(0.f, 0.f, 0.f); - - if (!is_global && mRegionp) - { - mPositionAgent = mRegionp->getOriginAgent(); - } - - LLViewerObject::sNumObjects++; -} - -LLViewerObject::~LLViewerObject() -{ - deleteTEImages(); - - if(mInventory) - { - mInventory->clear(); // will deref and delete entries - delete mInventory; - mInventory = NULL; - } - - if (mJointInfo) - { - delete mJointInfo; - mJointInfo = NULL; - } - - if (mPartSourcep) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - - // Delete memory associated with extra parameters. - std::map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if(iter->second != NULL) - { - delete iter->second->data; - delete iter->second; - } - } - mExtraParameterList.clear(); - - for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; - mNameValuePairs.clear(); - - delete[] mData; - mData = NULL; - - delete mMedia; - mMedia = NULL; - - sNumObjects--; - sNumZombieObjects--; - llassert(mChildList.size() == 0); - - clearInventoryListeners(); -} - -void LLViewerObject::deleteTEImages() -{ - delete[] mTEImages; - mTEImages = NULL; -} - -void LLViewerObject::markDead() -{ - if (!mDead) - { - //llinfos << "Marking self " << mLocalID << " as dead." << llendl; - - // Root object of this hierarchy unlinks itself. - if (getParent()) - { - ((LLViewerObject *)getParent())->removeChild(this); - // go ahead and delete any jointinfo's that we find - delete mJointInfo; - mJointInfo = NULL; - } - - // Mark itself as dead - mDead = TRUE; - gObjectList.cleanupReferences(this); - - LLViewerObject *childp; - while (mChildList.size() > 0) - { - childp = mChildList.back(); - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - //llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl; - childp->setParent(NULL); // LLViewerObject::markDead 1 - childp->markDead(); - } - else - { - // make sure avatar is no longer parented, - // so we can properly set it's position - childp->setDrawableParent(NULL); - ((LLVOAvatar*)childp)->getOffObject(); - childp->setParent(NULL); // LLViewerObject::markDead 2 - } - mChildList.pop_back(); - } - - if (mDrawable.notNull()) - { - // Drawables are reference counted, mark as dead, then nuke the pointer. - mDrawable->markDead(); - mDrawable = NULL; - } - - if (mText) - { - mText->markDead(); - mText = NULL; - } - - if (mIcon) - { - mIcon->markDead(); - mIcon = NULL; - } - - if (mPartSourcep) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - - if (mAudioSourcep) - { - // Do some cleanup - if (gAudiop) - { - gAudiop->cleanupAudioSource(mAudioSourcep); - } - mAudioSourcep = NULL; - } - - if (flagAnimSource()) - { - if (isAgentAvatarValid()) - { - // stop motions associated with this object - gAgentAvatarp->stopMotionFromSource(mID); - } - } - - if (flagCameraSource()) - { - LLFollowCamMgr::removeFollowCamParams(mID); - } - - sNumZombieObjects++; - } -} - -void LLViewerObject::dump() const -{ - llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl; - llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl; - llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl; - - llinfos << "Parent: " << getParent() << llendl; - llinfos << "ID: " << mID << llendl; - llinfos << "LocalID: " << mLocalID << llendl; - llinfos << "PositionRegion: " << getPositionRegion() << llendl; - llinfos << "PositionAgent: " << getPositionAgent() << llendl; - llinfos << "PositionGlobal: " << getPositionGlobal() << llendl; - llinfos << "Velocity: " << getVelocity() << llendl; - if (mDrawable.notNull() && mDrawable->getNumFaces()) - { - LLFacePool *poolp = mDrawable->getFace(0)->getPool(); - if (poolp) - { - llinfos << "Pool: " << poolp << llendl; - llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl; - } - } - //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl; - //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl; - /* - llinfos << "Velocity: " << getVelocity() << llendl; - llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl; - llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl; - llinfos << "AppAngle: " << mAppAngle << llendl; - llinfos << "PixelArea: " << mPixelArea << llendl; - - char buffer[1000]; - char *key; - for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() ) - { - mNameValuePairs[key]->printNameValue(buffer); - llinfos << buffer << llendl; - } - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - llinfos << " child " << child->getID() << llendl; - } - */ -} - -void LLViewerObject::printNameValuePairs() const -{ - for (name_value_map_t::const_iterator iter = mNameValuePairs.begin(); - iter != mNameValuePairs.end(); iter++) - { - LLNameValue* nv = iter->second; - llinfos << nv->printNameValue() << llendl; - } -} - -void LLViewerObject::initVOClasses() -{ - // Initialized shared class stuff first. - LLVOAvatar::initClass(); - LLVOTree::initClass(); - llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl; - LLVOGrass::initClass(); - LLVOWater::initClass(); - LLVOVolume::initClass(); -} - -void LLViewerObject::cleanupVOClasses() -{ - LLVOGrass::cleanupClass(); - LLVOWater::cleanupClass(); - LLVOTree::cleanupClass(); - LLVOAvatar::cleanupClass(); - LLVOVolume::cleanupClass(); -} - -// Replaces all name value pairs with data from \n delimited list -// Does not update server -void LLViewerObject::setNameValueList(const std::string& name_value_list) -{ - // Clear out the old - for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ; - mNameValuePairs.clear(); - - // Bring in the new - std::string::size_type length = name_value_list.length(); - std::string::size_type start = 0; - while (start < length) - { - std::string::size_type end = name_value_list.find_first_of("\n", start); - if (end == std::string::npos) end = length; - if (end > start) - { - std::string tok = name_value_list.substr(start, end - start); - addNVPair(tok); - } - start = end+1; - } -} - - -// This method returns true if the object is over land owned by the -// agent. -bool LLViewerObject::isReturnable() -{ - if (isAttachment()) - { - return false; - } - std::vector<LLBBox> boxes; - boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned()); - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned()); - } - - return mRegionp - && mRegionp->objectIsReturnable(getPositionRegion(), boxes); -} - -BOOL LLViewerObject::setParent(LLViewerObject* parent) -{ - if(mParent != parent) - { - LLViewerObject* old_parent = (LLViewerObject*)mParent ; - BOOL ret = LLPrimitive::setParent(parent); - if(ret && old_parent && parent) - { - old_parent->removeChild(this) ; - } - return ret ; - } - - return FALSE ; -} - -void LLViewerObject::addChild(LLViewerObject *childp) -{ - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - if (*i == childp) - { //already has child - return; - } - } - - if (!isAvatar()) - { - // propagate selection properties - childp->mbCanSelect = mbCanSelect; - } - - if(childp->setParent(this)) - { - mChildList.push_back(childp); - } -} - -void LLViewerObject::removeChild(LLViewerObject *childp) -{ - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - if (*i == childp) - { - if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar()) - { - gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME); - } - - mChildList.erase(i); - - if(childp->getParent() == this) - { - childp->setParent(NULL); - } - break; - } - } - - if (childp->isSelected()) - { - LLSelectMgr::getInstance()->deselectObjectAndFamily(childp); - BOOL add_to_end = TRUE; - LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end); - } -} - -void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects) -{ - objects.push_back(this); - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - if (!child->isAvatar()) - { - child->addThisAndAllChildren(objects); - } - } -} - -void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects) -{ - objects.push_back(this); - // don't add any attachments when temporarily selecting avatar - if (isAvatar()) - { - return; - } - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - if ( (!child->isAvatar()) && (!child->isJointChild())) - { - child->addThisAndNonJointChildren(objects); - } - } -} - -BOOL LLViewerObject::isChild(LLViewerObject *childp) const -{ - for (child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* testchild = *iter; - if (testchild == childp) - return TRUE; - } - return FALSE; -} - - -// returns TRUE if at least one avatar is sitting on this object -BOOL LLViewerObject::isSeat() const -{ - for (child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - if (child->isAvatar()) - { - return TRUE; - } - } - return FALSE; - -} - -BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp) -{ - if (mDrawable.isNull()) - { - return FALSE; - } - - BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL); - if(!ret) - { - return FALSE ; - } - LLDrawable* old_parent = mDrawable->mParent; - mDrawable->mParent = parentp; - - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE); - if( (old_parent != parentp && old_parent) - || (parentp && parentp->isActive())) - { - // *TODO we should not be relying on setDrawable parent to call markMoved - gPipeline.markMoved(mDrawable, FALSE); - } - else if (!mDrawable->isAvatar()) - { - mDrawable->updateXform(TRUE); - /*if (!mDrawable->getSpatialGroup()) - { - mDrawable->movePartition(); - }*/ - } - - return ret; -} - -// Show or hide particles, icon and HUD -void LLViewerObject::hideExtraDisplayItems( BOOL hidden ) -{ - if( mPartSourcep.notNull() ) - { - LLViewerPartSourceScript *partSourceScript = mPartSourcep.get(); - partSourceScript->setSuspended( hidden ); - } - - if( mText.notNull() ) - { - LLHUDText *hudText = mText.get(); - hudText->setHidden( hidden ); - } - - if( mIcon.notNull() ) - { - LLHUDIcon *hudIcon = mIcon.get(); - hudIcon->setHidden( hidden ); - } -} - -U32 LLViewerObject::checkMediaURL(const std::string &media_url) -{ - U32 retval = (U32)0x0; - if (!mMedia && !media_url.empty()) - { - retval |= MEDIA_URL_ADDED; - mMedia = new LLViewerObjectMedia; - mMedia->mMediaURL = media_url; - mMedia->mMediaType = LLViewerObject::MEDIA_SET; - mMedia->mPassedWhitelist = FALSE; - } - else if (mMedia) - { - if (media_url.empty()) - { - retval |= MEDIA_URL_REMOVED; - delete mMedia; - mMedia = NULL; - } - else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test. - { - /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() && - LLTextureEntry::getVersionFromMediaVersionString(media_url) == - LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1)) - */ - { - // If the media URL is different and WE were not the one who - // changed it, mark dirty. - retval |= MEDIA_URL_UPDATED; - } - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - } - } - return retval; -} - -U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - U32 retval = 0x0; - - // Coordinates of objects on simulators are region-local. - U64 region_handle; - mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle); - - { - LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle); - if(regionp != mRegionp && regionp && mRegionp)//region cross - { - //this is the redundant position and region update, but it is necessary in case the viewer misses the following - //position and region update messages from sim. - //this redundant update should not cause any problems. - LLVector3 delta_pos = mRegionp->getOriginAgent() - regionp->getOriginAgent(); - setPositionParent(getPosition() + delta_pos); //update to the new region position immediately. - setRegion(regionp) ; //change the region. - } - else - { - mRegionp = regionp ; - } - } - - if (!mRegionp) - { - U32 x, y; - from_region_handle(region_handle, &x, &y); - - llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl; - return retval; - } - - U16 time_dilation16; - mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16); - F32 time_dilation = ((F32) time_dilation16) / 65535.f; - mTimeDilation = time_dilation; - mRegionp->setTimeDilation(time_dilation); - - // this will be used to determine if we've really changed position - // Use getPosition, not getPositionRegion, since this is what we're comparing directly against. - LLVector3 test_pos_parent = getPosition(); - - U8 data[60+16]; // This needs to match the largest size below. -#ifdef LL_BIG_ENDIAN - U16 valswizzle[4]; -#endif - U16 *val; - const F32 size = LLWorld::getInstance()->getRegionWidthInMeters(); - const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight(); - const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight(); - S32 length; - S32 count; - S32 this_update_precision = 32; // in bits - - // Temporaries, because we need to compare w/ previous to set dirty flags... - LLVector3 new_pos_parent; - LLVector3 new_vel; - LLVector3 new_acc; - LLVector3 new_angv; - LLVector3 old_angv = getAngularVelocity(); - LLQuaternion new_rot; - LLVector3 new_scale = getScale(); - - U32 parent_id = 0; - U8 material = 0; - U8 click_action = 0; - U32 crc = 0; - - bool old_special_hover_cursor = specialHoverCursor(); - - LLViewerObject *cur_parentp = (LLViewerObject *)getParent(); - - if (cur_parentp) - { - parent_id = cur_parentp->mLocalID; - } - - if (!dp) - { - switch(update_type) - { - case OUT_FULL: - { -#ifdef DEBUG_UPDATE_TYPE - llinfos << "Full:" << getID() << llendl; -#endif - //clear cost and linkset cost - mCostStale = true; - if (isSelected()) - { - gFloaterTools->dirty(); - } - - LLUUID audio_uuid; - LLUUID owner_id; // only valid if audio_uuid or particle system is not null - F32 gain; - U8 sound_flags; - - mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num); - mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num); - mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num ); - // HACK: Owner id only valid if non-null sound id or particle system - mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num ); - mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Material, material, block_num ); - mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num); - mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num ); - length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num); - - mTotalCRC = crc; - - // Owner ID used for sound muting or particle system muting - setAttachedSound(audio_uuid, owner_id, gain, sound_flags); - - U8 old_material = getMaterial(); - if (old_material != material) - { - setMaterial(material); - if (mDrawable.notNull()) - { - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - setClickAction(click_action); - - count = 0; - LLVector4 collision_plane; - - switch(length) - { - case (60 + 16): - // pull out collision normal for avatar - htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 60: - this_update_precision = 32; - // this is a terse update - // pos - htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // vel - htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // acc - htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // theta - { - LLVector3 vec; - htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - new_rot.unpackFromVector3(vec); - } - count += sizeof(LLVector3); - // omega - htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); -#if LL_DARWIN - if (length == 76) - { - setAngularVelocity(LLVector3::zero); - } -#endif - break; - case(32 + 16): - // pull out collision normal for avatar - htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 32: - this_update_precision = 16; - test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - - // This is a terse 16 update, so treat data as an array of U16's. -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setVelocity(LLVector3(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size))); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size))); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*4; - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - new_angv.setVec(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); - break; - - case 16: - this_update_precision = 8; - test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - // this is a terse 8 update - new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); - - setVelocity(U8_to_F32(data[3], -size, size), - U8_to_F32(data[4], -size, size), - U8_to_F32(data[5], -size, size) ); - - setAcceleration(U8_to_F32(data[6], -size, size), - U8_to_F32(data[7], -size, size), - U8_to_F32(data[8], -size, size) ); - - new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); - new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); - new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); - new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); - - new_angv.setVec(U8_to_F32(data[13], -size, size), - U8_to_F32(data[14], -size, size), - U8_to_F32(data[15], -size, size) ); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); - break; - } - - //////////////////////////////////////////////////// - // - // Here we handle data specific to the full message. - // - - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // clear all but local flags - mFlags &= FLAGS_LOCAL; - mFlags |= flags; - - U8 state; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mState = state; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - - // Set all name value pairs - S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue); - if (nv_size > 0) - { - std::string name_value_list; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num); - setNameValueList(name_value_list); - } - - // Clear out any existing generic data - if (mData) - { - delete [] mData; - } - - // Check for appended generic data - S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data); - if (data_size <= 0) - { - mData = NULL; - } - else - { - // ...has generic data - mData = new U8[data_size]; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num); - } - - S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text); - if (text_size > 1) - { - // Setup object text - if (!mText) - { - mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mText->setFont(LLFontGL::getFontSansSerif()); - mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); - mText->setMaxLines(-1); - mText->setSourceObject(this); - mText->setOnHUDAttachment(isHUDAttachment()); - } - - std::string temp_string; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num ); - - LLColor4U coloru; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num); - - // alpha was flipped so that it zero encoded better - coloru.mV[3] = 255 - coloru.mV[3]; - mText->setColor(LLColor4(coloru)); - mText->setString(temp_string); - - if (mDrawable.notNull()) - { - setChanged(MOVED | SILHOUETTE); - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - else if (mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - - std::string media_url; - mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num); - retval |= checkMediaURL(media_url); - - // - // Unpack particle system data - // - unpackParticleSource(block_num, owner_id); - - // Mark all extra parameters not used - std::map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - iter->second->in_use = FALSE; - } - - // Unpack extra parameters - S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams); - if (size > 0) - { - U8 *buffer = new U8[size]; - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num); - LLDataPackerBinaryBuffer dp(buffer, size); - - U8 num_parameters; - dp.unpackU8(num_parameters, "num_params"); - U8 param_block[MAX_OBJECT_PARAMS_SIZE]; - for (U8 param=0; param<num_parameters; ++param) - { - U16 param_type; - S32 param_size; - dp.unpackU16(param_type, "param_type"); - dp.unpackBinaryData(param_block, param_size, "param_data"); - //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl; - LLDataPackerBinaryBuffer dp2(param_block, param_size); - unpackParameterEntry(param_type, &dp2); - } - delete[] buffer; - } - - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if (!iter->second->in_use) - { - // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, FALSE, false); - } - } - - U8 joint_type = 0; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num); - if (joint_type) - { - // create new joint info - if (!mJointInfo) - { - mJointInfo = new LLVOJointInfo; - } - mJointInfo->mJointType = (EHavokJointType) joint_type; - mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num); - mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num); - } - else if (mJointInfo) - { - // this joint info is no longer needed - delete mJointInfo; - mJointInfo = NULL; - } - - break; - } - - case OUT_TERSE_IMPROVED: - { -#ifdef DEBUG_UPDATE_TYPE - llinfos << "TI:" << getID() << llendl; -#endif - length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData); - mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num); - count = 0; - LLVector4 collision_plane; - - switch(length) - { - case(60 + 16): - // pull out collision normal for avatar - htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 60: - // this is a terse 32 update - // pos - this_update_precision = 32; - htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // vel - htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // acc - htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - count += sizeof(LLVector3); - // theta - { - LLVector3 vec; - htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - new_rot.unpackFromVector3(vec); - } - count += sizeof(LLVector3); - // omega - htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3)); - if (new_angv.isExactlyZero()) - { - // reset rotation time - resetRot(); - } - setAngularVelocity(new_angv); -#if LL_DARWIN - if (length == 76) - { - setAngularVelocity(LLVector3::zero); - } -#endif - break; - case(32 + 16): - // pull out collision normal for avatar - htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4)); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - count += sizeof(LLVector4); - // fall through - case 32: - // this is a terse 16 update - this_update_precision = 16; - test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setVelocity(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*3; - setAcceleration(U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - count += sizeof(U16)*4; - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f); - -#ifdef LL_BIG_ENDIAN - htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6); - val = valswizzle; -#else - val = (U16 *) &data[count]; -#endif - setAngularVelocity( U16_to_F32(val[VX], -size, size), - U16_to_F32(val[VY], -size, size), - U16_to_F32(val[VZ], -size, size)); - break; - - case 16: - // this is a terse 8 update - this_update_precision = 8; - test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT); - new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size); - new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT); - - setVelocity(U8_to_F32(data[3], -size, size), - U8_to_F32(data[4], -size, size), - U8_to_F32(data[5], -size, size) ); - - setAcceleration(U8_to_F32(data[6], -size, size), - U8_to_F32(data[7], -size, size), - U8_to_F32(data[8], -size, size) ); - - new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f); - new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f); - new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f); - new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f); - - setAngularVelocity( U8_to_F32(data[13], -size, size), - U8_to_F32(data[14], -size, size), - U8_to_F32(data[15], -size, size) ); - break; - } - - U8 state; - mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num ); - mState = state; - break; - } - - default: - break; - - } - } - else - { - // handle the compressed case - LLUUID sound_uuid; - LLUUID owner_id; - F32 gain = 0; - U8 sound_flags = 0; - F32 cutoff = 0; - - U16 val[4]; - - U8 state; - - dp->unpackU8(state, "State"); - mState = state; - - switch(update_type) - { - case OUT_TERSE_IMPROVED: - { -#ifdef DEBUG_UPDATE_TYPE - llinfos << "CompTI:" << getID() << llendl; -#endif - U8 value; - dp->unpackU8(value, "agent"); - if (value) - { - LLVector4 collision_plane; - dp->unpackVector4(collision_plane, "Plane"); - ((LLVOAvatar*)this)->setFootPlane(collision_plane); - } - test_pos_parent = getPosition(); - dp->unpackVector3(new_pos_parent, "Pos"); - dp->unpackU16(val[VX], "VelX"); - dp->unpackU16(val[VY], "VelY"); - dp->unpackU16(val[VZ], "VelZ"); - setVelocity(U16_to_F32(val[VX], -128.f, 128.f), - U16_to_F32(val[VY], -128.f, 128.f), - U16_to_F32(val[VZ], -128.f, 128.f)); - dp->unpackU16(val[VX], "AccX"); - dp->unpackU16(val[VY], "AccY"); - dp->unpackU16(val[VZ], "AccZ"); - setAcceleration(U16_to_F32(val[VX], -64.f, 64.f), - U16_to_F32(val[VY], -64.f, 64.f), - U16_to_F32(val[VZ], -64.f, 64.f)); - - dp->unpackU16(val[VX], "ThetaX"); - dp->unpackU16(val[VY], "ThetaY"); - dp->unpackU16(val[VZ], "ThetaZ"); - dp->unpackU16(val[VS], "ThetaS"); - new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f); - new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f); - new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f); - new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f); - dp->unpackU16(val[VX], "AccX"); - dp->unpackU16(val[VY], "AccY"); - dp->unpackU16(val[VZ], "AccZ"); - setAngularVelocity( U16_to_F32(val[VX], -64.f, 64.f), - U16_to_F32(val[VY], -64.f, 64.f), - U16_to_F32(val[VZ], -64.f, 64.f)); - } - break; - case OUT_FULL_COMPRESSED: - case OUT_FULL_CACHED: - { -#ifdef DEBUG_UPDATE_TYPE - llinfos << "CompFull:" << getID() << llendl; -#endif - mCostStale = true; - - if (isSelected()) - { - gFloaterTools->dirty(); - } - - dp->unpackU32(crc, "CRC"); - mTotalCRC = crc; - dp->unpackU8(material, "Material"); - U8 old_material = getMaterial(); - if (old_material != material) - { - setMaterial(material); - if (mDrawable.notNull()) - { - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - dp->unpackU8(click_action, "ClickAction"); - setClickAction(click_action); - dp->unpackVector3(new_scale, "Scale"); - dp->unpackVector3(new_pos_parent, "Pos"); - LLVector3 vec; - dp->unpackVector3(vec, "Rot"); - new_rot.unpackFromVector3(vec); - setAcceleration(LLVector3::zero); - - U32 value; - dp->unpackU32(value, "SpecialCode"); - dp->setPassFlags(value); - dp->unpackUUID(owner_id, "Owner"); - - if (value & 0x80) - { - dp->unpackVector3(vec, "Omega"); - setAngularVelocity(vec); - } - - if (value & 0x20) - { - dp->unpackU32(parent_id, "ParentID"); - } - else - { - parent_id = 0; - } - - S32 sp_size; - U32 size; - if (value & 0x2) - { - sp_size = 1; - delete [] mData; - mData = new U8[1]; - dp->unpackU8(((U8*)mData)[0], "TreeData"); - } - else if (value & 0x1) - { - dp->unpackU32(size, "ScratchPadSize"); - delete [] mData; - mData = new U8[size]; - dp->unpackBinaryData((U8 *)mData, sp_size, "PartData"); - } - else - { - mData = NULL; - } - - // Setup object text - if (!mText && (value & 0x4)) - { - mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mText->setFont(LLFontGL::getFontSansSerif()); - mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); - mText->setMaxLines(-1); // Set to match current agni behavior. - mText->setSourceObject(this); - mText->setOnHUDAttachment(isHUDAttachment()); - } - - if (value & 0x4) - { - std::string temp_string; - dp->unpackString(temp_string, "Text"); - LLColor4U coloru; - dp->unpackBinaryDataFixed(coloru.mV, 4, "Color"); - coloru.mV[3] = 255 - coloru.mV[3]; - mText->setColor(LLColor4(coloru)); - mText->setString(temp_string); - - setChanged(TEXTURE); - } - else if(mText.notNull()) - { - mText->markDead(); - mText = NULL; - } - - std::string media_url; - if (value & 0x200) - { - dp->unpackString(media_url, "MediaURL"); - } - retval |= checkMediaURL(media_url); - - // - // Unpack particle system data - // - if (value & 0x8) - { - unpackParticleSource(*dp, owner_id); - } - else - { - deleteParticleSource(); - } - - // Mark all extra parameters not used - std::map<U16, ExtraParameter*>::iterator iter; - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - iter->second->in_use = FALSE; - } - - // Unpack extra params - U8 num_parameters; - dp->unpackU8(num_parameters, "num_params"); - U8 param_block[MAX_OBJECT_PARAMS_SIZE]; - for (U8 param=0; param<num_parameters; ++param) - { - U16 param_type; - S32 param_size; - dp->unpackU16(param_type, "param_type"); - dp->unpackBinaryData(param_block, param_size, "param_data"); - //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl; - LLDataPackerBinaryBuffer dp2(param_block, param_size); - unpackParameterEntry(param_type, &dp2); - } - - for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter) - { - if (!iter->second->in_use) - { - // Send an update message in case it was formerly in use - parameterChanged(iter->first, iter->second->data, FALSE, false); - } - } - - if (value & 0x10) - { - dp->unpackUUID(sound_uuid, "SoundUUID"); - dp->unpackF32(gain, "SoundGain"); - dp->unpackU8(sound_flags, "SoundFlags"); - dp->unpackF32(cutoff, "SoundRadius"); - } - - if (value & 0x100) - { - std::string name_value_list; - dp->unpackString(name_value_list, "NV"); - - setNameValueList(name_value_list); - } - - mTotalCRC = crc; - - setAttachedSound(sound_uuid, owner_id, gain, sound_flags); - - // only get these flags on updates from sim, not cached ones - // Preload these five flags for every object. - // Finer shades require the object to be selected, and the selection manager - // stores the extended permission info. - U32 flags; - mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num); - // keep local flags and overwrite remote-controlled flags - mFlags = (mFlags & FLAGS_LOCAL) | flags; - - // ...new objects that should come in selected need to be added to the selected list - mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0); - } - break; - - default: - break; - } - } - - // - // Fix object parenting. - // - BOOL b_changed_status = FALSE; - - if (OUT_TERSE_IMPROVED != update_type) - { - // We only need to update parenting on full updates, terse updates - // don't send parenting information. - if (!cur_parentp) - { - if (parent_id == 0) - { - // No parent now, no parent in message -> do nothing - } - else - { - // No parent now, new parent in message -> attach to that parent if possible - LLUUID parent_uuid; - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - mesgsys->getSenderIP(), - mesgsys->getSenderPort()); - - LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid); - - // - // Check to see if we have the corresponding viewer object for the parent. - // - if (sent_parentp && sent_parentp->getParent() == this) - { - // Try to recover if we attempt to attach a parent to its child - llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << llendl; - this->removeChild(sent_parentp); - sent_parentp->setDrawableParent(NULL); - } - - if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead()) - { - // - // We have a viewer object for the parent, and it's not dead. - // Do the actual reparenting here. - // - - // new parent is valid - b_changed_status = TRUE; - // ...no current parent, so don't try to remove child - if (mDrawable.notNull()) - { - if (mDrawable->isDead() || !mDrawable->getVObj()) - { - llwarns << "Drawable is dead or no VObj!" << llendl; - sent_parentp->addChild(this); - } - else - { - if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1 - { - // Bad, we got a cycle somehow. - // Kill both the parent and the child, and - // set cache misses for both of them. - llwarns << "Attempting to recover from parenting cycle!" << llendl; - llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl; - llwarns << "Adding to cache miss list" << llendl; - setParent(NULL); - sent_parentp->setParent(NULL); - getRegion()->addCacheMissFull(getLocalID()); - getRegion()->addCacheMissFull(sent_parentp->getLocalID()); - gObjectList.killObject(sent_parentp); - gObjectList.killObject(this); - return retval; - } - sent_parentp->addChild(this); - // make sure this object gets a non-damped update - if (sent_parentp->mDrawable.notNull()) - { - gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped - } - } - } - else - { - sent_parentp->addChild(this); - } - - // Show particles, icon and HUD - hideExtraDisplayItems( FALSE ); - - setChanged(MOVED | SILHOUETTE); - } - else - { - // - // No corresponding viewer object for the parent, put the various - // pieces on the orphan list. - // - - //parent_id - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); - - gObjectList.orphanize(this, parent_id, ip, port); - - // Hide particles, icon and HUD - hideExtraDisplayItems( TRUE ); - } - } - } - else - { - // BUG: this is a bad assumption once border crossing is alowed - if ( (parent_id == cur_parentp->mLocalID) - &&(update_type == OUT_TERSE_IMPROVED)) - { - // Parent now, same parent in message -> do nothing - - // Debugging for suspected problems with local ids. - //LLUUID parent_uuid; - //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() ); - //if (parent_uuid != cur_parentp->getID() ) - //{ - // llerrs << "Local ID match but UUID mismatch of viewer object" << llendl; - //} - } - else - { - // Parented now, different parent in message - LLViewerObject *sent_parentp; - if (parent_id == 0) - { - // - // This object is no longer parented, we sent in a zero parent ID. - // - sent_parentp = NULL; - } - else - { - LLUUID parent_uuid; - LLViewerObjectList::getUUIDFromLocal(parent_uuid, - parent_id, - gMessageSystem->getSenderIP(), - gMessageSystem->getSenderPort()); - sent_parentp = gObjectList.findObject(parent_uuid); - - if (isAvatar()) - { - // This logic is meant to handle the case where a sitting avatar has reached a new sim - // ahead of the object she was sitting on (which is common as objects are transfered through - // a slower route than agents)... - // In this case, the local id for the object will not be valid, since the viewer has not received - // a full update for the object from that sim yet, so we assume that the agent is still sitting - // where she was originally. --RN - if (!sent_parentp) - { - sent_parentp = cur_parentp; - } - } - else if (!sent_parentp) - { - // - // Switching parents, but we don't know the new parent. - // - U32 ip = mesgsys->getSenderIP(); - U32 port = mesgsys->getSenderPort(); - - // We're an orphan, flag things appropriately. - gObjectList.orphanize(this, parent_id, ip, port); - } - } - - // Reattach if possible. - if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this) - { - // New parent is valid, detach and reattach - b_changed_status = TRUE; - if (mDrawable.notNull()) - { - if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2 - { - // Bad, we got a cycle somehow. - // Kill both the parent and the child, and - // set cache misses for both of them. - llwarns << "Attempting to recover from parenting cycle!" << llendl; - llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl; - llwarns << "Adding to cache miss list" << llendl; - setParent(NULL); - sent_parentp->setParent(NULL); - getRegion()->addCacheMissFull(getLocalID()); - getRegion()->addCacheMissFull(sent_parentp->getLocalID()); - gObjectList.killObject(sent_parentp); - gObjectList.killObject(this); - return retval; - } - // make sure this object gets a non-damped update - } - cur_parentp->removeChild(this); - sent_parentp->addChild(this); - setChanged(MOVED | SILHOUETTE); - sent_parentp->setChanged(MOVED | SILHOUETTE); - if (sent_parentp->mDrawable.notNull()) - { - gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped - } - } - else if (!sent_parentp) - { - bool remove_parent = true; - // No new parent, or the parent that we sent doesn't exist on the viewer. - LLViewerObject *parentp = (LLViewerObject *)getParent(); - if (parentp) - { - if (parentp->getRegion() != getRegion()) - { - // This is probably an object flying across a region boundary, the - // object probably ISN'T being reparented, but just got an object - // update out of order (child update before parent). - //llinfos << "Don't reparent object handoffs!" << llendl; - remove_parent = false; - } - } - - if (remove_parent) - { - b_changed_status = TRUE; - if (mDrawable.notNull()) - { - // clear parent to removeChild can put the drawable on the damped list - setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3 - } - - cur_parentp->removeChild(this); - - if (mJointInfo && !parent_id) - { - // since this object is no longer parent-relative - // we make sure we delete any joint info - delete mJointInfo; - mJointInfo = NULL; - } - - setChanged(MOVED | SILHOUETTE); - - if (mDrawable.notNull()) - { - // make sure this object gets a non-damped update - gPipeline.markMoved(mDrawable, FALSE); // undamped - } - } - } - } - } - } - - new_rot.normQuat(); - - if (sPingInterpolate) - { - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender()); - if (cdp) - { - F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped); - LLVector3 diff = getVelocity() * ping_delay; - new_pos_parent += diff; - } - else - { - llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl; - } - } - - ////////////////////////// - // - // Set the generic change flags... - // - // - - // WTF? If we're going to skip this message, why are we - // doing all the parenting, etc above? - U32 packet_id = mesgsys->getCurrentRecvPacketID(); - if (packet_id < mLatestRecvPacketID && - mLatestRecvPacketID - packet_id < 65536) - { - //skip application of this message, it's old - return retval; - } - - mLatestRecvPacketID = packet_id; - - // Set the change flags for scale - if (new_scale != getScale()) - { - setChanged(SCALED | SILHOUETTE); - setScale(new_scale); // Must follow setting permYouOwner() - } - - // first, let's see if the new position is actually a change - - //static S32 counter = 0; - - F32 vel_mag_sq = getVelocity().magVecSquared(); - F32 accel_mag_sq = getAcceleration().magVecSquared(); - - if ( ((b_changed_status)||(test_pos_parent != new_pos_parent)) - ||( (!isSelected()) - &&( (vel_mag_sq != 0.f) - ||(accel_mag_sq != 0.f) - ||(this_update_precision > mBestUpdatePrecision)))) - { - mBestUpdatePrecision = this_update_precision; - - LLVector3 diff = new_pos_parent - test_pos_parent ; - F32 mag_sqr = diff.magVecSquared() ; - if(llfinite(mag_sqr)) - { - setPositionParent(new_pos_parent); - } - else - { - llwarns << "Can not move the object/avatar to an infinite location!" << llendl ; - - retval |= INVALID_UPDATE ; - } - - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - - // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps - if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) ) - { - LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() ); - } - } - - if (new_rot != mLastRot - || new_angv != old_angv) - { - if (new_rot != mLastRot) - { - mLastRot = new_rot; - setRotation(new_rot); - } - - setChanged(ROTATED | SILHOUETTE); - - resetRot(); - } - - - if ( gShowObjectUpdates ) - { - if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf())) - && mRegionp) - { - LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp); - LLVOTextBubble* bubble = (LLVOTextBubble*) object; - - if (update_type == OUT_TERSE_IMPROVED) - { - bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f); - } - else - { - bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f); - } - object->setPositionGlobal(getPositionGlobal()); - gPipeline.addObject(object); - } - } - - if ((0.0f == vel_mag_sq) && - (0.0f == accel_mag_sq) && - (0.0f == getAngularVelocity().magVecSquared())) - { - mStatic = TRUE; // This object doesn't move! - } - else - { - mStatic = FALSE; - } - -// BUG: This code leads to problems during group rotate and any scale operation. -// Small discepencies between the simulator and viewer representations cause the -// selection center to creep, leading to objects moving around the wrong center. -// -// Removing this, however, means that if someone else drags an object you have -// selected, your selection center and dialog boxes will be wrong. It also means -// that higher precision information on selected objects will be ignored. -// -// I believe the group rotation problem is fixed. JNC 1.21.2002 -// - // Additionally, if any child is selected, need to update the dialogs and selection - // center. - BOOL needs_refresh = mUserSelected; - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - needs_refresh = needs_refresh || child->mUserSelected; - } - - if (needs_refresh) - { - LLSelectMgr::getInstance()->updateSelectionCenter(); - dialog_refresh_all(); - } - - - // Mark update time as approx. now, with the ping delay. - // Ping delay is off because it's not set for velocity interpolation, causing - // much jumping and hopping around... - -// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay(); - mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds(); - mLastMessageUpdateSecs = mLastInterpUpdateSecs; - if (mDrawable.notNull()) - { - // Don't clear invisibility flag on update if still orphaned! - if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned) - { -// lldebugs << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << llendl; - mDrawable->setState(LLDrawable::CLEAR_INVISIBLE); - } - } - - // Update special hover cursor status - bool special_hover_cursor = specialHoverCursor(); - if (old_special_hover_cursor != special_hover_cursor - && mDrawable.notNull()) - { - mDrawable->updateSpecialHoverCursor(special_hover_cursor); - } - - return retval; -} - -BOOL LLViewerObject::isActive() const -{ - return TRUE; -} - - - -BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time) -{ - static LLFastTimer::DeclareTimer ftm("Viewer Object"); - LLFastTimer t(ftm); - - if (mDead) - { - // It's dead. Don't update it. - return TRUE; - } - - // CRO - don't velocity interp linked objects! - // Leviathan - but DO velocity interp joints - if (!mStatic && sVelocityInterpolate && !isSelected()) - { - // calculate dt from last update - F32 dt_raw = (F32)(time - mLastInterpUpdateSecs); - F32 dt = mTimeDilation * dt_raw; - - if (!mJointInfo) - { - applyAngularVelocity(dt); - } - - LLViewerObject *parentp = (LLViewerObject *) getParent(); - if (mJointInfo) - { - if (parentp) - { - // do parent-relative stuff - LLVector3 ang_vel = getAngularVelocity(); - F32 omega = ang_vel.magVecSquared(); - F32 angle = 0.0f; - LLQuaternion dQ; - if (omega > 0.00001f) - { - omega = sqrt(omega); - angle = omega * dt; - dQ.setQuat(angle, ang_vel); - } - LLVector3 pos = getPosition(); - - if (HJT_HINGE == mJointInfo->mJointType) - { - // hinge = uniform circular motion - LLVector3 parent_pivot = getVelocity(); - LLVector3 parent_axis = getAcceleration(); - - angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis - dQ.setQuat(angle, mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis - LLVector3 pivot_offset = pos - mJointInfo->mPivot; // pos in pivot-frame - pivot_offset = pivot_offset * dQ; // new rotated pivot-frame pos - pos = mJointInfo->mPivot + pivot_offset; // parent-frame - LLViewerObject::setPosition(pos); - LLQuaternion Q_PC = getRotation(); - setRotation(Q_PC * dQ); - mLastInterpUpdateSecs = time; - } - else if (HJT_POINT == mJointInfo->mJointType) - // || HJT_LPOINT == mJointInfo->mJointType) - { - // point-to-point = spin about axis and uniform circular motion - // of axis about the pivot point - // - // NOTE: this interpolation scheme is not quite good enough to - // reduce the bandwidth -- needs a gravitational correction. - // Similarly for hinges with axes that deviate from vertical. - - LLQuaternion Q_PC = getRotation(); - Q_PC = Q_PC * dQ; - setRotation(Q_PC); - - LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor; // AxisOrAnchor = anchor - pos = mJointInfo->mPivot + pivot_to_child * Q_PC; - LLViewerObject::setPosition(pos); - mLastInterpUpdateSecs = time; - } - /* else if (HJT_WHEEL == mJointInfo->mJointInfo) - { - // wheel = uniform rotation about axis, with linear - // velocity interpolation (if any) - LLVector3 parent_axis = getAcceleration(); // HACK -- accel stores the parent-axis (parent-frame) - - LLQuaternion Q_PC = getRotation(); - - angle = dt * (parent_axis * ang_vel); - dQ.setQuat(angle, parent_axis); - - Q_PC = Q_PC * dQ; - setRotation(Q_PC); - - pos = getPosition() + dt * getVelocity(); - LLViewerObject::setPosition(pos); - mLastInterpUpdateSecs = time; - }*/ - } - } - else if (isAttachment()) - { - mLastInterpUpdateSecs = time; - return TRUE; - } - else - { // Move object based on it's velocity and rotation - interpolateLinearMotion(time, dt); - } - } - - updateDrawable(FALSE); - - return TRUE; -} - - -// Move an object due to idle-time viewer side updates by iterpolating motion -void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt) -{ - // linear motion - // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object - // updates represents the average velocity of the last timestep, rather than the final velocity. - // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically - // - // *TODO: should also wrap linear accel/velocity in check - // to see if object is selected, instead of explicitly - // zeroing it out - - F64 time_since_last_update = time - mLastMessageUpdateSecs; - if (time_since_last_update <= 0.0 || dt <= 0.f) - { - return; - } - - LLVector3 accel = getAcceleration(); - LLVector3 vel = getVelocity(); - - if (sMaxUpdateInterpolationTime <= 0.0) - { // Old code path ... unbounded, simple interpolation - if (!(accel.isExactlyZero() && vel.isExactlyZero())) - { - LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - - // region local - setPositionRegion(pos + getPositionRegion()); - setVelocity(vel + accel*dt); - - // for objects that are spinning but not translating, make sure to flag them as having moved - setChanged(MOVED | SILHOUETTE); - } - } - else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving - { // Object is moving, and hasn't been too long since we got an update from the server - - // Calculate predicted position and velocity - LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt; - LLVector3 new_v = accel * dt; - - if (time_since_last_update > sPhaseOutUpdateInterpolationTime && - sPhaseOutUpdateInterpolationTime > 0.0) - { // Haven't seen a viewer update in a while, check to see if the ciruit is still active - if (mRegionp) - { // The simulator will NOT send updates if the object continues normally on the path - // predicted by the velocity and the acceleration (often gravity) sent to the viewer - // So check to see if the circuit is blocked, which means the sim is likely in a long lag - LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() ); - if (cdp) - { - // Find out how many seconds since last packet arrived on the circuit - F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime(); - - if (!cdp->isAlive() || // Circuit is dead or blocked - cdp->isBlocked() || // or doesn't seem to be getting any packets - (time_since_last_packet > sPhaseOutUpdateInterpolationTime)) - { - // Start to reduce motion interpolation since we haven't seen a server update in a while - F64 time_since_last_interpolation = time - mLastInterpUpdateSecs; - F64 phase_out = 1.0; - if (time_since_last_update > sMaxUpdateInterpolationTime) - { // Past the time limit, so stop the object - phase_out = 0.0; - //llinfos << "Motion phase out to zero" << llendl; - - // Kill angular motion as well. Note - not adding this due to paranoia - // about stopping rotation for llTargetOmega objects and not having it restart - // setAngularVelocity(LLVector3::zero); - } - else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime) - { // Last update was already phased out a bit - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / - (sMaxUpdateInterpolationTime - time_since_last_interpolation); - //llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl; - } - else - { // Phase out from full value - phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) / - (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime); - //llinfos << "Starting motion phase out of " << (F32) phase_out << llendl; - } - phase_out = llclamp(phase_out, 0.0, 1.0); - - new_pos = new_pos * ((F32) phase_out); - new_v = new_v * ((F32) phase_out); - } - } - } - } - - new_pos = new_pos + getPositionRegion(); - new_v = new_v + vel; - - - // Clamp interpolated position to minimum underground and maximum region height - LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); - F32 min_height; - if (isAvatar()) - { // Make a better guess about AVs not going underground - min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global); - min_height += (0.5f * getScale().mV[VZ]); - } - else - { // This will put the object underground, but we can't tell if it will stop - // at ground level or not - min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global); - } - - new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]); - new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]); - - // Check to see if it's going off the region - LLVector3 temp(new_pos); - if (temp.clamp(0.f, mRegionp->getWidth())) - { // Going off this region, so see if we might end up on another region - LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); - new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above - - // Clip the positions to known regions - LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global); - if (clip_pos_global != new_pos_global) - { // Was clipped, so this means we hit a edge where there is no region to enter - - //llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global) - // << " from " << new_pos << llendl; - new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global); - - // Stop motion and get server update for bouncing on the edge - new_v.clear(); - setAcceleration(LLVector3::zero); - } - else - { // Let predicted movement cross into another region - //llinfos << "Predicting region crossing to " << new_pos << llendl; - } - } - - // Set new position and velocity - setPositionRegion(new_pos); - setVelocity(new_v); - - // for objects that are spinning but not translating, make sure to flag them as having moved - setChanged(MOVED | SILHOUETTE); - } - - // Update the last time we did anything - mLastInterpUpdateSecs = time; -} - - - -BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - delete [] mData; - - if (datap) - { - mData = new U8[data_size]; - if (!mData) - { - return FALSE; - } - memcpy(mData, datap, data_size); /* Flawfinder: ignore */ - } - return TRUE; -} - -// delete an item in the inventory, but don't tell the server. This is -// used internally by remove, update, and savescript. -// This will only delete the first item with an item_id in the list -void LLViewerObject::deleteInventoryItem(const LLUUID& item_id) -{ - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it ) - { - if((*it)->getUUID() == item_id) - { - // This is safe only because we return immediatly. - mInventory->erase(it); // will deref and delete it - return; - } - } - doInventoryCallback(); - } -} - -void LLViewerObject::doUpdateInventory( - LLPointer<LLViewerInventoryItem>& item, - U8 key, - bool is_new) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - LLViewerInventoryItem* old_item = NULL; - if(TASK_INVENTORY_ITEM_KEY == key) - { - old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID()); - } - else if(TASK_INVENTORY_ASSET_KEY == key) - { - old_item = getInventoryItemByAsset(item->getAssetUUID()); - } - LLUUID item_id; - LLUUID new_owner; - LLUUID new_group; - BOOL group_owned = FALSE; - if(old_item) - { - item_id = old_item->getUUID(); - new_owner = old_item->getPermissions().getOwner(); - new_group = old_item->getPermissions().getGroup(); - group_owned = old_item->getPermissions().isGroupOwned(); - old_item = NULL; - } - else - { - item_id = item->getUUID(); - } - if(!is_new && mInventory) - { - // Attempt to update the local inventory. If we can get the - // object perm, we have perfect visibility, so we want the - // serial number to match. Otherwise, take our best guess and - // make sure that the serial number does not match. - deleteInventoryItem(item_id); - LLPermissions perm(item->getPermissions()); - LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this); - bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true; - if(obj_perm) - { - perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic); - } - else - { - if(group_owned) - { - perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); - } - else if(!new_owner.isNull()) - { - // The object used to be in inventory, so we can - // assume the owner and group will match what they are - // there. - perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic); - } - // *FIX: can make an even better guess by using the mPermGroup flags - else if(permYouOwner()) - { - // best guess. - perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic); - --mInventorySerialNum; - } - else - { - // dummy it up. - perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic); - --mInventorySerialNum; - } - } - LLViewerInventoryItem* oldItem = item; - LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem); - new_item->setPermissions(perm); - mInventory->push_front(new_item); - doInventoryCallback(); - ++mInventorySerialNum; - } -} - -// save a script, which involves removing the old one, and rezzing -// in the new one. This method should be called with the asset id -// of the new and old script AFTER the bytecode has been saved. -void LLViewerObject::saveScript( - const LLViewerInventoryItem* item, - BOOL active, - bool is_new) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - /* - * XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the - * interaction with doUpdateInventory() called below. - */ - lldebugs << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << llendl; - LLPointer<LLViewerInventoryItem> task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), item->getFlags(), - item->getCreationDate()); - task_item->setTransactionID(item->getTransactionID()); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RezScript); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID()); - msg->nextBlockFast(_PREHASH_UpdateBlock); - msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID)); - U8 enabled = active; - msg->addBOOLFast(_PREHASH_Enabled, enabled); - msg->nextBlockFast(_PREHASH_InventoryBlock); - task_item->packMessage(msg); - msg->sendReliable(mRegionp->getHost()); - - // do the internal logic - doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new); -} - -void LLViewerObject::moveInventory(const LLUUID& folder_id, - const LLUUID& item_id) -{ - lldebugs << "LLViewerObject::moveInventory " << item_id << llendl; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_MoveTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->addUUIDFast(_PREHASH_FolderID, folder_id); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addUUIDFast(_PREHASH_ItemID, item_id); - msg->sendReliable(mRegionp->getHost()); - - LLInventoryObject* inv_obj = getInventoryObject(item_id); - if(inv_obj) - { - LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj; - if(!item->getPermissions().allowCopyBy(gAgent.getID())) - { - deleteInventoryItem(item_id); - ++mInventorySerialNum; - } - } -} - -void LLViewerObject::dirtyInventory() -{ - // If there aren't any LLVOInventoryListeners, we won't be - // able to update our mInventory when it comes back from the - // simulator, so we should not clear the inventory either. - if(mInventory && !mInventoryCallbacks.empty()) - { - mInventory->clear(); // will deref and delete entries - delete mInventory; - mInventory = NULL; - mInventoryDirty = TRUE; - } -} - -void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo; - info->mListener = listener; - info->mInventoryData = user_data; - mInventoryCallbacks.push_front(info); -} - -void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener) -{ - if (listener == NULL) - return; - for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); - iter != mInventoryCallbacks.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLInventoryCallbackInfo* info = *curiter; - if (info->mListener == listener) - { - delete info; - mInventoryCallbacks.erase(curiter); - break; - } - } -} - -void LLViewerObject::clearInventoryListeners() -{ - for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer()); - mInventoryCallbacks.clear(); -} - -void LLViewerObject::requestInventory() -{ - mInventoryDirty = FALSE; - if(mInventory) - { - //mInventory->clear() // will deref and delete it - //delete mInventory; - //mInventory = NULL; - doInventoryCallback(); - } - // throw away duplicate requests - else - { - fetchInventoryFromServer(); - } -} - -void LLViewerObject::fetchInventoryFromServer() -{ - if (!mInventoryPending) - { - delete mInventory; - mInventory = NULL; - mInventoryDirty = FALSE; - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RequestTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->sendReliable(mRegionp->getHost()); - - // this will get reset by dirtyInventory or doInventoryCallback - mInventoryPending = TRUE; - } -} - -struct LLFilenameAndTask -{ - LLUUID mTaskID; - std::string mFilename; -#ifdef _DEBUG - static S32 sCount; - LLFilenameAndTask() - { - ++sCount; - lldebugs << "Constructing LLFilenameAndTask: " << sCount << llendl; - } - ~LLFilenameAndTask() - { - --sCount; - lldebugs << "Destroying LLFilenameAndTask: " << sCount << llendl; - } -private: - LLFilenameAndTask(const LLFilenameAndTask& rhs); - const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const; -#endif -}; - -#ifdef _DEBUG -S32 LLFilenameAndTask::sCount = 0; -#endif - -// static -void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - LLUUID task_id; - msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id); - LLViewerObject* object = gObjectList.findObject(task_id); - if(!object) - { - llwarns << "LLViewerObject::processTaskInv object " - << task_id << " does not exist." << llendl; - return; - } - - msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum); - LLFilenameAndTask* ft = new LLFilenameAndTask; - ft->mTaskID = task_id; - - std::string unclean_filename; - msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename); - ft->mFilename = LLDir::getScrubbedFileName(unclean_filename); - - if(ft->mFilename.empty()) - { - lldebugs << "Task has no inventory" << llendl; - // mock up some inventory to make a drop target. - if(object->mInventory) - { - object->mInventory->clear(); // will deref and delete it - } - else - { - object->mInventory = new LLInventoryObject::object_list_t(); - } - LLPointer<LLInventoryObject> obj; - obj = new LLInventoryObject(object->mID, LLUUID::null, - LLAssetType::AT_CATEGORY, - LLTrans::getString("ViewerObjectContents").c_str()); - object->mInventory->push_front(obj); - object->doInventoryCallback(); - delete ft; - return; - } - gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename), - ft->mFilename, LL_PATH_CACHE, - object->mRegionp->getHost(), - TRUE, - &LLViewerObject::processTaskInvFile, - (void**)ft, - LLXferManager::HIGH_PRIORITY); -} - -void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status) -{ - LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data; - LLViewerObject* object = NULL; - if(ft && (0 == error_code) && - (object = gObjectList.findObject(ft->mTaskID))) - { - object->loadTaskInvFile(ft->mFilename); - } - else - { - // This Occurs When to requests were made, and the first one - // has already handled it. - lldebugs << "Problem loading task inventory. Return code: " - << error_code << llendl; - } - delete ft; -} - -void LLViewerObject::loadTaskInvFile(const std::string& filename) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename); - llifstream ifs(filename_and_local_path); - if(ifs.good()) - { - char buffer[MAX_STRING]; /* Flawfinder: ignore */ - // *NOTE: This buffer size is hard coded into scanf() below. - char keyword[MAX_STRING]; /* Flawfinder: ignore */ - if(mInventory) - { - mInventory->clear(); // will deref and delete it - } - else - { - mInventory = new LLInventoryObject::object_list_t; - } - while(ifs.good()) - { - ifs.getline(buffer, MAX_STRING); - sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */ - if(0 == strcmp("inv_item", keyword)) - { - LLPointer<LLInventoryObject> inv = new LLViewerInventoryItem; - inv->importLegacyStream(ifs); - mInventory->push_front(inv); - } - else if(0 == strcmp("inv_object", keyword)) - { - LLPointer<LLInventoryObject> inv = new LLInventoryObject; - inv->importLegacyStream(ifs); - inv->rename(LLTrans::getString("ViewerObjectContents").c_str()); - mInventory->push_front(inv); - } - else - { - llwarns << "Unknown token in inventory file '" - << keyword << "'" << llendl; - } - } - ifs.close(); - LLFile::remove(filename_and_local_path); - } - else - { - llwarns << "unable to load task inventory: " << filename_and_local_path - << llendl; - } - doInventoryCallback(); -} - -void LLViewerObject::doInventoryCallback() -{ - for (callback_list_t::iterator iter = mInventoryCallbacks.begin(); - iter != mInventoryCallbacks.end(); ) - { - callback_list_t::iterator curiter = iter++; - LLInventoryCallbackInfo* info = *curiter; - if (info->mListener != NULL) - { - info->mListener->inventoryChanged(this, - mInventory, - mInventorySerialNum, - info->mInventoryData); - } - else - { - llinfos << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << llendl; - delete info; - mInventoryCallbacks.erase(curiter); - } - } - mInventoryPending = FALSE; -} - -void LLViewerObject::removeInventory(const LLUUID& item_id) -{ - // close any associated floater properties - LLFloaterReg::hideInstance("properties", item_id); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_RemoveTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_InventoryData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addUUIDFast(_PREHASH_ItemID, item_id); - msg->sendReliable(mRegionp->getHost()); - deleteInventoryItem(item_id); - ++mInventorySerialNum; -} - -void LLViewerObject::updateInventory( - LLViewerInventoryItem* item, - U8 key, - bool is_new) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - // This slices the object into what we're concerned about on the - // viewer. The simulator will take the permissions and transfer - // ownership. - LLPointer<LLViewerInventoryItem> task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), - item->getFlags(), - item->getCreationDate()); - task_item->setTransactionID(item->getTransactionID()); - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_UpdateTaskInventory); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID()); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_UpdateData); - msg->addU32Fast(_PREHASH_LocalID, mLocalID); - msg->addU8Fast(_PREHASH_Key, key); - msg->nextBlockFast(_PREHASH_InventoryData); - task_item->packMessage(msg); - msg->sendReliable(mRegionp->getHost()); - - // do the internal logic - doUpdateInventory(task_item, key, is_new); -} - -void LLViewerObject::updateInventoryLocal(LLInventoryItem* item, U8 key) -{ - LLPointer<LLViewerInventoryItem> task_item = - new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(), - item->getAssetUUID(), item->getType(), - item->getInventoryType(), - item->getName(), item->getDescription(), - item->getSaleInfo(), item->getFlags(), - item->getCreationDate()); - - // do the internal logic - const bool is_new = false; - doUpdateInventory(task_item, key, is_new); -} - -LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id) -{ - LLInventoryObject* rv = NULL; - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for ( ; it != end; ++it) - { - if((*it)->getUUID() == item_id) - { - rv = *it; - break; - } - } - } - return rv; -} - -void LLViewerObject::getInventoryContents(LLInventoryObject::object_list_t& objects) -{ - if(mInventory) - { - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it) - { - if ((*it)->getType() != LLAssetType::AT_CATEGORY) - { - objects.push_back(*it); - } - } - } -} - -LLInventoryObject* LLViewerObject::getInventoryRoot() -{ - if (!mInventory || !mInventory->size()) - { - return NULL; - } - return mInventory->back(); -} - -LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id) -{ - if (mInventoryDirty) - llwarns << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << llendl; - - LLViewerInventoryItem* rv = NULL; - if(mInventory) - { - LLViewerInventoryItem* item = NULL; - - LLInventoryObject::object_list_t::iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::iterator end = mInventory->end(); - for( ; it != end; ++it) - { - LLInventoryObject* obj = *it; - if(obj->getType() != LLAssetType::AT_CATEGORY) - { - // *FIX: gank-ass down cast! - item = (LLViewerInventoryItem*)obj; - if(item->getAssetUUID() == asset_id) - { - rv = item; - break; - } - } - } - } - return rv; -} - -void LLViewerObject::updateViewerInventoryAsset( - const LLViewerInventoryItem* item, - const LLUUID& new_asset) -{ - LLPointer<LLViewerInventoryItem> task_item = - new LLViewerInventoryItem(item); - task_item->setAssetUUID(new_asset); - - // do the internal logic - doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false); -} - -void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent) -{ - if (getVolume()) - { //volumes calculate pixel area and angle per face - return; - } - - LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent(); - LLVector3 pos_agent = getRenderPosition(); - - F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX]; - F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY]; - F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ]; - - F32 max_scale = getMaxScale(); - F32 mid_scale = getMidScale(); - F32 min_scale = getMinScale(); - - // IW: estimate - when close to large objects, computing range based on distance from center is no good - // to try to get a min distance from face, subtract min_scale/2 from the range. - // This means we'll load too much detail sometimes, but that's better than not enough - // I don't think there's a better way to do this without calculating distance per-poly - F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2; - - LLViewerCamera* camera = LLViewerCamera::getInstance(); - if (range < 0.001f || isHUDAttachment()) // range == zero - { - mAppAngle = 180.f; - mPixelArea = (F32)camera->getScreenPixelArea(); - } - else - { - mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG; - - F32 pixels_per_meter = camera->getPixelMeterRatio() / range; - - mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale); - if (mPixelArea > camera->getScreenPixelArea()) - { - mAppAngle = 180.f; - mPixelArea = (F32)camera->getScreenPixelArea(); - } - } -} - -BOOL LLViewerObject::updateLOD() -{ - return FALSE; -} - -BOOL LLViewerObject::updateGeometry(LLDrawable *drawable) -{ - return TRUE; -} - -void LLViewerObject::updateGL() -{ - -} - -void LLViewerObject::updateFaceSize(S32 idx) -{ - -} - -LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline) -{ - return NULL; -} - -void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped) -{ - LLPrimitive::setScale(scale); - if (mDrawable.notNull()) - { - //encompass completely sheared objects by taking - //the most extreme point possible (<1,1,0.5>) - mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec()); - updateDrawable(damped); - } - - if( (LL_PCODE_VOLUME == getPCode()) && !isDead() ) - { - if (permYouOwner() || (scale.magVecSquared() > (7.5f * 7.5f)) ) - { - if (!mOnMap) - { - llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle())); - - gObjectList.addToMap(this); - mOnMap = TRUE; - } - } - else - { - if (mOnMap) - { - gObjectList.removeFromMap(this); - mOnMap = FALSE; - } - } - } -} - -void LLViewerObject::setObjectCost(F32 cost) -{ - mObjectCost = cost; - mCostStale = false; - - if (isSelected()) - { - gFloaterTools->dirty(); - } -} - -void LLViewerObject::setLinksetCost(F32 cost) -{ - mLinksetCost = cost; - mCostStale = false; - - if (isSelected()) - { - gFloaterTools->dirty(); - } -} - -void LLViewerObject::setPhysicsCost(F32 cost) -{ - mPhysicsCost = cost; - mCostStale = false; - - if (isSelected()) - { - gFloaterTools->dirty(); - } -} - -void LLViewerObject::setLinksetPhysicsCost(F32 cost) -{ - mLinksetPhysicsCost = cost; - mCostStale = false; - - if (isSelected()) - { - gFloaterTools->dirty(); - } -} - - -F32 LLViewerObject::getObjectCost() -{ - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mObjectCost; -} - -F32 LLViewerObject::getLinksetCost() -{ - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mLinksetCost; -} - -F32 LLViewerObject::getPhysicsCost() -{ - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mPhysicsCost; -} - -F32 LLViewerObject::getLinksetPhysicsCost() -{ - if (mCostStale) - { - gObjectList.updateObjectCost(this); - } - - return mLinksetPhysicsCost; -} - -F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes) -{ - return 0.f; -} - -U32 LLViewerObject::getTriangleCount() -{ - return 0; -} - -U32 LLViewerObject::getHighLODTriangleCount() -{ - return 0; -} - -void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax) -{ - LLVector4a center; - center.load3(getRenderPosition().mV); - LLVector4a size; - size.load3(getScale().mV); - newMin.setSub(center, size); - newMax.setAdd(center, size); - - mDrawable->setPositionGroup(center); -} - -F32 LLViewerObject::getBinRadius() -{ - if (mDrawable.notNull()) - { - const LLVector4a* ext = mDrawable->getSpatialExtents(); - LLVector4a diff; - diff.setSub(ext[1], ext[0]); - return diff.getLength3().getF32(); - } - - return getScale().magVec(); -} - -F32 LLViewerObject::getMaxScale() const -{ - return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]); -} - -F32 LLViewerObject::getMinScale() const -{ - return llmin(getScale().mV[0],getScale().mV[1],getScale().mV[2]); -} - -F32 LLViewerObject::getMidScale() const -{ - if (getScale().mV[VX] < getScale().mV[VY]) - { - if (getScale().mV[VY] < getScale().mV[VZ]) - { - return getScale().mV[VY]; - } - else if (getScale().mV[VX] < getScale().mV[VZ]) - { - return getScale().mV[VZ]; - } - else - { - return getScale().mV[VX]; - } - } - else if (getScale().mV[VX] < getScale().mV[VZ]) - { - return getScale().mV[VX]; - } - else if (getScale().mV[VY] < getScale().mV[VZ]) - { - return getScale().mV[VZ]; - } - else - { - return getScale().mV[VY]; - } -} - - -void LLViewerObject::updateTextures() -{ -} - -void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */) -{ - if (isDead()) - { - return; - } - - S32 i; - S32 tex_count = getNumTEs(); - for (i = 0; i < tex_count; i++) - { - getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); - } - - if (isSculpted() && !isMesh()) - { - LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT); - LLUUID sculpt_id = sculpt_params->getSculptTexture(); - LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED); - } - - if (boost_children) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->boostTexturePriority(); - } - } -} - - -void LLViewerObject::setLineWidthForWindowSize(S32 window_width) -{ - if (window_width < 700) - { - LLUI::setLineWidth(2.0f); - } - else if (window_width < 1100) - { - LLUI::setLineWidth(3.0f); - } - else if (window_width < 2000) - { - LLUI::setLineWidth(4.0f); - } - else - { - // _damn_, what a nice monitor! - LLUI::setLineWidth(5.0f); - } -} - -void LLViewerObject::increaseArrowLength() -{ -/* ??? - if (mAxisArrowLength == 50) - { - mAxisArrowLength = 100; - } - else - { - mAxisArrowLength = 150; - } -*/ -} - - -void LLViewerObject::decreaseArrowLength() -{ -/* ??? - if (mAxisArrowLength == 150) - { - mAxisArrowLength = 100; - } - else - { - mAxisArrowLength = 50; - } -*/ -} - -// Culled from newsim LLTask::addNVPair -void LLViewerObject::addNVPair(const std::string& data) -{ - // cout << "LLViewerObject::addNVPair() with ---" << data << "---" << endl; - LLNameValue *nv = new LLNameValue(data.c_str()); - -// char splat[MAX_STRING]; -// temp->printNameValue(splat); -// llinfos << "addNVPair " << splat << llendl; - - name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName); - if (iter != mNameValuePairs.end()) - { - LLNameValue* foundnv = iter->second; - if (foundnv->mClass != NVC_READ_ONLY) - { - delete foundnv; - mNameValuePairs.erase(iter); - } - else - { - delete nv; -// llinfos << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << llendl; - return; - } - } - mNameValuePairs[nv->mName] = nv; -} - -BOOL LLViewerObject::removeNVPair(const std::string& name) -{ - char* canonical_name = gNVNameTable.addString(name); - - lldebugs << "LLViewerObject::removeNVPair(): " << name << llendl; - - name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name); - if (iter != mNameValuePairs.end()) - { - if( mRegionp ) - { - LLNameValue* nv = iter->second; -/* - std::string buffer = nv->printNameValue(); - gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair); - gMessageSystem->nextBlockFast(_PREHASH_TaskData); - gMessageSystem->addUUIDFast(_PREHASH_ID, mID); - - gMessageSystem->nextBlockFast(_PREHASH_NameValueData); - gMessageSystem->addStringFast(_PREHASH_NVPair, buffer); - - gMessageSystem->sendReliable( mRegionp->getHost() ); -*/ - // Remove the NV pair from the local list. - delete nv; - mNameValuePairs.erase(iter); - return TRUE; - } - else - { - lldebugs << "removeNVPair - No region for object" << llendl; - } - } - return FALSE; -} - - -LLNameValue *LLViewerObject::getNVPair(const std::string& name) const -{ - char *canonical_name; - - canonical_name = gNVNameTable.addString(name); - - // If you access a map with a name that isn't in it, it will add the name and a null pointer. - // So first check if the data is in the map. - name_value_map_t::const_iterator iter = mNameValuePairs.find(canonical_name); - if (iter != mNameValuePairs.end()) - { - return iter->second; - } - else - { - return NULL; - } -} - -void LLViewerObject::updatePositionCaches() const -{ - if(mRegionp) - { - if (!isRoot()) - { - mPositionRegion = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } - else - { - mPositionRegion = getPosition(); - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } - } -} - -const LLVector3d LLViewerObject::getPositionGlobal() const -{ - if(mRegionp) - { - LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion()); - - if (isAttachment()) - { - position_global = gAgent.getPosGlobalFromAgent(getRenderPosition()); - } - return position_global; - } - else - { - LLVector3d position_global(getPosition()); - return position_global; - } -} - -const LLVector3 &LLViewerObject::getPositionAgent() const -{ - if (mRegionp) - { - if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent())) - { - // Don't return cached position if you have a parent, recalc (until all dirtying is done correctly. - LLVector3 position_region; - position_region = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation(); - mPositionAgent = mRegionp->getPosAgentFromRegion(position_region); - } - else - { - mPositionAgent = mRegionp->getPosAgentFromRegion(getPosition()); - } - } - return mPositionAgent; -} - -const LLVector3 &LLViewerObject::getPositionRegion() const -{ - if (!isRoot()) - { - LLViewerObject *parent = (LLViewerObject *)getParent(); - mPositionRegion = parent->getPositionRegion() + (getPosition() * parent->getRotation()); - } - else - { - mPositionRegion = getPosition(); - } - - return mPositionRegion; -} - -const LLVector3 LLViewerObject::getPositionEdit() const -{ - if (isRootEdit()) - { - return getPosition(); - } - else - { - LLViewerObject *parent = (LLViewerObject *)getParent(); - LLVector3 position_edit = parent->getPositionEdit() + getPosition() * parent->getRotationEdit(); - return position_edit; - } -} - -const LLVector3 LLViewerObject::getRenderPosition() const -{ - if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) - { - LLVOAvatar* avatar = getAvatar(); - if (avatar) - { - return avatar->getPositionAgent(); - } - } - - if (mDrawable.isNull() || mDrawable->getGeneration() < 0) - { - return getPositionAgent(); - } - else - { - return mDrawable->getPositionAgent(); - } -} - -const LLVector3 LLViewerObject::getPivotPositionAgent() const -{ - return getRenderPosition(); -} - -const LLQuaternion LLViewerObject::getRenderRotation() const -{ - LLQuaternion ret; - if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED)) - { - return ret; - } - - if (mDrawable.isNull() || mDrawable->isStatic()) - { - ret = getRotationEdit(); - } - else - { - if (!mDrawable->isRoot()) - { - ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix()); - } - else - { - ret = LLQuaternion(mDrawable->getWorldMatrix()); - } - } - - return ret; -} - -const LLMatrix4 LLViewerObject::getRenderMatrix() const -{ - return mDrawable->getWorldMatrix(); -} - -const LLQuaternion LLViewerObject::getRotationRegion() const -{ - LLQuaternion global_rotation = getRotation(); - if (!((LLXform *)this)->isRoot()) - { - global_rotation = global_rotation * getParent()->getRotation(); - } - return global_rotation; -} - -const LLQuaternion LLViewerObject::getRotationEdit() const -{ - LLQuaternion global_rotation = getRotation(); - if (!((LLXform *)this)->isRootEdit()) - { - global_rotation = global_rotation * getParent()->getRotation(); - } - return global_rotation; -} - -void LLViewerObject::setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped ) -{ - if (isAttachment()) - { - LLVector3 new_pos = mRegionp->getPosRegionFromGlobal(pos_global); - if (isRootEdit()) - { - new_pos -= mDrawable->mXform.getParent()->getWorldPosition(); - LLQuaternion world_rotation = mDrawable->mXform.getParent()->getWorldRotation(); - new_pos = new_pos * ~world_rotation; - } - else - { - LLViewerObject* parentp = (LLViewerObject*)getParent(); - new_pos -= parentp->getPositionAgent(); - new_pos = new_pos * ~parentp->getRotationRegion(); - } - LLViewerObject::setPosition(new_pos); - - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - } - else - { - if( isRoot() ) - { - setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); - } - else - { - // the relative position with the parent is not constant - LLViewerObject* parent = (LLViewerObject *)getParent(); - //RN: this assumes we are only calling this function from the edit tools - gPipeline.updateMoveNormalAsync(parent->mDrawable); - - LLVector3 pos_local = mRegionp->getPosRegionFromGlobal(pos_global) - parent->getPositionRegion(); - pos_local = pos_local * ~parent->getRotationRegion(); - LLViewerObject::setPosition( pos_local ); - } - } - //RN: assumes we always want to snap the object when calling this function - gPipeline.updateMoveNormalAsync(mDrawable); -} - -void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped) -{ - if (getPosition() != pos) - { - setChanged(TRANSLATED | SILHOUETTE); - } - - LLXform::setPosition(pos); - updateDrawable(damped); - if (isRoot()) - { - // position caches need to be up to date on root objects - updatePositionCaches(); - } -} - -void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped) -{ - if (isAttachment()) - { - if (isRootEdit()) - { - LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); - newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); - - LLQuaternion invWorldRotation = mDrawable->mXform.getParent()->getWorldRotation(); - invWorldRotation.transQuat(); - - newPos = newPos * invWorldRotation; - LLViewerObject::setPosition(newPos); - } - else - { - // assumes parent is root editable (root of attachment) - LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global); - newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition(); - LLVector3 delta_pos = newPos - getPosition(); - - LLQuaternion invRotation = mDrawable->getRotation(); - invRotation.transQuat(); - - delta_pos = delta_pos * invRotation; - - // *FIX: is this right? Shouldn't we be calling the - // LLViewerObject version of setPosition? - LLVector3 old_pos = mDrawable->mXform.getParent()->getPosition(); - mDrawable->mXform.getParent()->setPosition(old_pos + delta_pos); - setChanged(TRANSLATED | SILHOUETTE); - } - if (mParent && ((LLViewerObject*)mParent)->isAvatar()) - { - // we have changed the position of an attachment, so we need to clamp it - LLVOAvatar *avatar = (LLVOAvatar*)mParent; - - avatar->clampAttachmentPositions(); - } - } - else - { - if (isRoot()) - { - setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global)); - } - else - { - // the relative position with the parent is constant, but the parent's position needs to be changed - LLVector3d position_offset; - position_offset.setVec(getPosition()*getParent()->getRotation()); - LLVector3d new_pos_global = pos_global - position_offset; - ((LLViewerObject *)getParent())->setPositionGlobal(new_pos_global); - } - } - updateDrawable(damped); -} - - -void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped) -{ - // Set position relative to parent, if no parent, relative to region - if (!isRoot()) - { - LLViewerObject::setPosition(pos_parent, damped); - //updateDrawable(damped); - } - else - { - setPositionRegion(pos_parent, damped); - } -} - -void LLViewerObject::setPositionRegion(const LLVector3 &pos_region, BOOL damped) -{ - if (!isRootEdit()) - { - LLViewerObject* parent = (LLViewerObject*) getParent(); - LLViewerObject::setPosition((pos_region-parent->getPositionRegion())*~parent->getRotationRegion()); - } - else - { - LLViewerObject::setPosition(pos_region); - mPositionRegion = pos_region; - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } -} - -void LLViewerObject::setPositionAgent(const LLVector3 &pos_agent, BOOL damped) -{ - LLVector3 pos_region = getRegion()->getPosRegionFromAgent(pos_agent); - setPositionRegion(pos_region, damped); -} - -// identical to setPositionRegion() except it checks for child-joints -// and doesn't also move the joint-parent -// TODO -- implement similar intelligence for joint-parents toward -// their joint-children -void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped) -{ - if (!isRootEdit()) - { - // the relative position with the parent is constant, but the parent's position needs to be changed - LLVector3 position_offset = getPosition() * getParent()->getRotation(); - - ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset); - updateDrawable(damped); - } - else if (isJointChild()) - { - // compute new parent-relative position - LLViewerObject *parent = (LLViewerObject *) getParent(); - LLQuaternion inv_parent_rot = parent->getRotation(); - inv_parent_rot.transQuat(); - LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot; - LLViewerObject::setPosition(pos_parent, damped); - } - else - { - LLViewerObject::setPosition(pos_edit, damped); - mPositionRegion = pos_edit; - mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion); - } -} - - -LLViewerObject* LLViewerObject::getRootEdit() const -{ - const LLViewerObject* root = this; - while (root->mParent - && !(root->mJointInfo - || ((LLViewerObject*)root->mParent)->isAvatar()) ) - { - root = (LLViewerObject*)root->mParent; - } - return (LLViewerObject*)root; -} - - -BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, const LLVector3& end, - S32 face, - BOOL pick_transparent, - S32* face_hit, - LLVector3* intersection, - LLVector2* tex_coord, - LLVector3* normal, - LLVector3* bi_normal) -{ - return false; -} - -BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector3& start, const LLVector3& end) -{ - if (mDrawable.isNull() || mDrawable->isDead()) - { - return FALSE; - } - - const LLVector4a* ext = mDrawable->getSpatialExtents(); - - //VECTORIZE THIS - LLVector4a center; - center.setAdd(ext[1], ext[0]); - center.mul(0.5f); - LLVector4a size; - size.setSub(ext[1], ext[0]); - size.mul(0.5f); - - LLVector4a starta, enda; - starta.load3(start.mV); - enda.load3(end.mV); - - return LLLineSegmentBoxIntersect(starta, enda, center, size); -} - -U8 LLViewerObject::getMediaType() const -{ - if (mMedia) - { - return mMedia->mMediaType; - } - else - { - return LLViewerObject::MEDIA_NONE; - } -} - -void LLViewerObject::setMediaType(U8 media_type) -{ - if (!mMedia) - { - // TODO what if we don't have a media pointer? - } - else if (mMedia->mMediaType != media_type) - { - mMedia->mMediaType = media_type; - - // TODO: update materials with new image - } -} - -std::string LLViewerObject::getMediaURL() const -{ - if (mMedia) - { - return mMedia->mMediaURL; - } - else - { - return std::string(); - } -} - -void LLViewerObject::setMediaURL(const std::string& media_url) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - if (!mMedia) - { - mMedia = new LLViewerObjectMedia; - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - - // TODO: update materials with new image - } - else if (mMedia->mMediaURL != media_url) - { - mMedia->mMediaURL = media_url; - mMedia->mPassedWhitelist = FALSE; - - // TODO: update materials with new image - } -} - -BOOL LLViewerObject::getMediaPassedWhitelist() const -{ - if (mMedia) - { - return mMedia->mPassedWhitelist; - } - else - { - return FALSE; - } -} - -void LLViewerObject::setMediaPassedWhitelist(BOOL passed) -{ - if (mMedia) - { - mMedia->mPassedWhitelist = passed; - } -} - -BOOL LLViewerObject::setMaterial(const U8 material) -{ - BOOL res = LLPrimitive::setMaterial(material); - if (res) - { - setChanged(TEXTURE); - } - return res; -} - -void LLViewerObject::setNumTEs(const U8 num_tes) -{ - LLMemType mt(LLMemType::MTYPE_OBJECT); - - U32 i; - if (num_tes != getNumTEs()) - { - if (num_tes) - { - LLPointer<LLViewerTexture> *new_images; - new_images = new LLPointer<LLViewerTexture>[num_tes]; - for (i = 0; i < num_tes; i++) - { - if (i < getNumTEs()) - { - new_images[i] = mTEImages[i]; - } - else if (getNumTEs()) - { - new_images[i] = mTEImages[getNumTEs()-1]; - } - else - { - new_images[i] = NULL; - } - } - - deleteTEImages(); - - mTEImages = new_images; - } - else - { - deleteTEImages(); - } - LLPrimitive::setNumTEs(num_tes); - setChanged(TEXTURE); - - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } -} - -void LLViewerObject::sendMaterialUpdate() const -{ - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessageFast(_PREHASH_ObjectMaterial); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - gMessageSystem->addU8Fast(_PREHASH_Material, getMaterial() ); - gMessageSystem->sendReliable( regionp->getHost() ); - -} - -// formerly send_object_rotation -void LLViewerObject::sendRotationUpdate() const -{ - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessageFast(_PREHASH_ObjectRotation); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID); - gMessageSystem->addQuatFast(_PREHASH_Rotation, getRotationEdit()); - //llinfos << "Sent rotation " << getRotationEdit() << llendl; - gMessageSystem->sendReliable( regionp->getHost() ); -} - -/* Obsolete, we use MultipleObjectUpdate instead -//// formerly send_object_position_global -//void LLViewerObject::sendPositionUpdate() const -//{ -// gMessageSystem->newMessageFast(_PREHASH_ObjectPosition); -// gMessageSystem->nextBlockFast(_PREHASH_AgentData); -// gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); -// gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); -// gMessageSystem->nextBlockFast(_PREHASH_ObjectData); -// gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); -// gMessageSystem->addVector3Fast(_PREHASH_Position, getPositionRegion()); -// LLViewerRegion* regionp = getRegion(); -// gMessageSystem->sendReliable(regionp->getHost()); -//} -*/ - -//formerly send_object_shape(LLViewerObject *object) -void LLViewerObject::sendShapeUpdate() -{ - gMessageSystem->newMessageFast(_PREHASH_ObjectShape); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->nextBlockFast(_PREHASH_ObjectData); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - - LLVolumeMessage::packVolumeParams(&getVolume()->getParams(), gMessageSystem); - - LLViewerRegion *regionp = getRegion(); - gMessageSystem->sendReliable( regionp->getHost() ); -} - - -void LLViewerObject::sendTEUpdate() const -{ - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ObjectImage); - - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - if (mMedia) - { - msg->addString("MediaURL", mMedia->mMediaURL); - } - else - { - msg->addString("MediaURL", NULL); - } - - // TODO send media type - - packTEMessage(msg); - - LLViewerRegion *regionp = getRegion(); - msg->sendReliable( regionp->getHost() ); -} - -void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry) -{ - LLPrimitive::setTE(te, texture_entry); -// This doesn't work, don't get any textures. -// if (mDrawable.notNull() && mDrawable->isVisible()) -// { - const LLUUID& image_id = getTE(te)->getID(); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE); -// } -} - -void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep) -{ - if (mTEImages[te] != imagep) - { - mTEImages[te] = imagep; - LLPrimitive::setTETexture(te, imagep->getID()); - setChanged(TEXTURE); - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } -} - - -S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host) -{ - S32 retval = 0; - if (uuid != getTE(te)->getID() || - uuid == LLUUID::null) - { - retval = LLPrimitive::setTETexture(te, uuid); - mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host); - setChanged(TEXTURE); - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; -} - - -void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image) -{ - if(index < 0 || index >= getNumTEs()) - { - return ; - } - mTEImages[index] = new_image ; -} - -S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid) -{ - // Invalid host == get from the agent's sim - return setTETextureCore(te, uuid, LLHost::invalid); -} - - -S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color) -{ - return setTEColor(te, LLColor4(color)); -} - -S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (color != tep->getColor()) - { - retval = LLPrimitive::setTEColor(te, color); - if (mDrawable.notNull() && retval) - { - // These should only happen on updates which are not the initial update. - dirtyMesh(); - } - } - return retval; -} - -S32 LLViewerObject::setTEBumpmap(const U8 te, const U8 bump) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (bump != tep->getBumpmap()) - { - retval = LLPrimitive::setTEBumpmap(te, bump); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE); - } - } - return retval; -} - -S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (texgen != tep->getTexGen()) - { - retval = LLPrimitive::setTETexGen(te, texgen); - setChanged(TEXTURE); - } - return retval; -} - -S32 LLViewerObject::setTEMediaTexGen(const U8 te, const U8 media) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (media != tep->getMediaTexGen()) - { - retval = LLPrimitive::setTEMediaTexGen(te, media); - setChanged(TEXTURE); - } - return retval; -} - -S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (shiny != tep->getShiny()) - { - retval = LLPrimitive::setTEShiny(te, shiny); - setChanged(TEXTURE); - } - return retval; -} - -S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (fullbright != tep->getFullbright()) - { - retval = LLPrimitive::setTEFullbright(te, fullbright); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; -} - - -S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags) -{ - // this might need work for media type - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (media_flags != tep->getMediaFlags()) - { - retval = LLPrimitive::setTEMediaFlags(te, media_flags); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE); - gPipeline.markTextured(mDrawable); - // JC - probably only need this if changes texture coords - //gPipeline.markRebuild(mDrawable); - } - } - return retval; -} - -S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow) -{ - S32 retval = 0; - const LLTextureEntry *tep = getTE(te); - if (!tep) - { - llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl; - } - else if (glow != tep->getGlow()) - { - retval = LLPrimitive::setTEGlow(te, glow); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markTextured(mDrawable); - } - } - return retval; -} - - -S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t) -{ - S32 retval = 0; - retval = LLPrimitive::setTEScale(te, s, t); - setChanged(TEXTURE); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - return retval; -} - -S32 LLViewerObject::setTEScaleS(const U8 te, const F32 s) -{ - S32 retval = LLPrimitive::setTEScaleS(te, s); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - - return retval; -} - -S32 LLViewerObject::setTEScaleT(const U8 te, const F32 t) -{ - S32 retval = LLPrimitive::setTEScaleT(te, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - - return retval; -} - -S32 LLViewerObject::setTEOffset(const U8 te, const F32 s, const F32 t) -{ - S32 retval = LLPrimitive::setTEOffset(te, s, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - return retval; -} - -S32 LLViewerObject::setTEOffsetS(const U8 te, const F32 s) -{ - S32 retval = LLPrimitive::setTEOffsetS(te, s); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - - return retval; -} - -S32 LLViewerObject::setTEOffsetT(const U8 te, const F32 t) -{ - S32 retval = LLPrimitive::setTEOffsetT(te, t); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - - return retval; -} - -S32 LLViewerObject::setTERotation(const U8 te, const F32 r) -{ - S32 retval = LLPrimitive::setTERotation(te, r); - if (mDrawable.notNull() && retval) - { - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD); - } - return retval; -} - - -LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const -{ -// llassert(mTEImages); - - if (face < getNumTEs()) - { - LLViewerTexture* image = mTEImages[face]; - if (image) - { - return image; - } - else - { - return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep); - } - } - - llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl; - - return NULL; -} - - -void LLViewerObject::fitFaceTexture(const U8 face) -{ - llinfos << "fitFaceTexture not implemented" << llendl; -} - - -LLBBox LLViewerObject::getBoundingBoxAgent() const -{ - LLVector3 position_agent; - LLQuaternion rot; - LLViewerObject* avatar_parent = NULL; - LLViewerObject* root_edit = (LLViewerObject*)getRootEdit(); - if (root_edit) - { - avatar_parent = (LLViewerObject*)root_edit->getParent(); - } - - if (avatar_parent && avatar_parent->isAvatar() && - root_edit && root_edit->mDrawable.notNull() && root_edit->mDrawable->getXform()->getParent()) - { - LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent(); - position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition(); - rot = getRotationEdit() * parent_xform->getWorldRotation(); - } - else - { - position_agent = getPositionAgent(); - rot = getRotationRegion(); - } - - return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f ); -} - -U32 LLViewerObject::getNumVertices() const -{ - U32 num_vertices = 0; - if (mDrawable.notNull()) - { - S32 i, num_faces; - num_faces = mDrawable->getNumFaces(); - for (i = 0; i < num_faces; i++) - { - num_vertices += mDrawable->getFace(i)->getGeomCount(); - } - } - return num_vertices; -} - -U32 LLViewerObject::getNumIndices() const -{ - U32 num_indices = 0; - if (mDrawable.notNull()) - { - S32 i, num_faces; - num_faces = mDrawable->getNumFaces(); - for (i = 0; i < num_faces; i++) - { - num_indices += mDrawable->getFace(i)->getIndicesCount(); - } - } - return num_indices; -} - -// Find the number of instances of this object's inventory that are of the given type -S32 LLViewerObject::countInventoryContents(LLAssetType::EType type) -{ - S32 count = 0; - if( mInventory ) - { - LLInventoryObject::object_list_t::const_iterator it = mInventory->begin(); - LLInventoryObject::object_list_t::const_iterator end = mInventory->end(); - for( ; it != end ; ++it ) - { - if( (*it)->getType() == type ) - { - ++count; - } - } - } - return count; -} - - -void LLViewerObject::setCanSelect(BOOL canSelect) -{ - mbCanSelect = canSelect; - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->mbCanSelect = canSelect; - } -} - -void LLViewerObject::setDebugText(const std::string &utf8text) -{ - if (utf8text.empty() && !mText) - { - return; - } - - if (!mText) - { - mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT); - mText->setFont(LLFontGL::getFontSansSerif()); - mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP); - mText->setMaxLines(-1); - mText->setSourceObject(this); - mText->setOnHUDAttachment(isHUDAttachment()); - } - mText->setColor(LLColor4::white); - mText->setString(utf8text); - mText->setZCompare(FALSE); - mText->setDoFade(FALSE); - updateText(); -} - -void LLViewerObject::setIcon(LLViewerTexture* icon_image) -{ - if (!mIcon) - { - mIcon = (LLHUDIcon *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_ICON); - mIcon->setSourceObject(this); - mIcon->setImage(icon_image); - // *TODO: make this user configurable - mIcon->setScale(0.03f); - } - else - { - mIcon->restartLifeTimer(); - } -} - -void LLViewerObject::clearIcon() -{ - if (mIcon) - { - mIcon = NULL; - } -} - -LLViewerObject* LLViewerObject::getSubParent() -{ - if (isJointChild()) - { - return this; - } - return (LLViewerObject*) getParent(); -} - -const LLViewerObject* LLViewerObject::getSubParent() const -{ - if (isJointChild()) - { - return this; - } - return (const LLViewerObject*) getParent(); -} - -BOOL LLViewerObject::isOnMap() -{ - return mOnMap; -} - - -void LLViewerObject::updateText() -{ - if (!isDead()) - { - if (mText.notNull()) - { - LLVector3 up_offset(0,0,0); - up_offset.mV[2] = getScale().mV[VZ]*0.6f; - - if (mDrawable.notNull()) - { - mText->setPositionAgent(getRenderPosition() + up_offset); - } - else - { - mText->setPositionAgent(getPositionAgent() + up_offset); - } - } - } -} - -LLVOAvatar* LLViewerObject::asAvatar() -{ - return NULL; -} - -BOOL LLViewerObject::isParticleSource() const -{ - return !mPartSourcep.isNull() && !mPartSourcep->isDead(); -} - -void LLViewerObject::setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id) -{ - if (mPartSourcep) - { - deleteParticleSource(); - } - - LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::createPSS(this, particle_parameters); - mPartSourcep = pss; - - if (mPartSourcep) - { - mPartSourcep->setOwnerUUID(owner_id); - - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.tga"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } - LLViewerPartSim::getInstance()->addPartSource(pss); -} - -void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& owner_id) -{ - if (!mPartSourcep.isNull() && mPartSourcep->isDead()) - { - mPartSourcep = NULL; - } - if (mPartSourcep) - { - // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, block_num)) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - } - else - { - LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num); - //If the owner is muted, don't create the system - if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; - - // We need to be able to deal with a particle source that hasn't changed, but still got an update! - if (pss) - { -// llinfos << "Making particle system with owner " << owner_id << llendl; - pss->setOwnerUUID(owner_id); - mPartSourcep = pss; - LLViewerPartSim::getInstance()->addPartSource(pss); - } - } - if (mPartSourcep) - { - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } -} - -void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id) -{ - if (!mPartSourcep.isNull() && mPartSourcep->isDead()) - { - mPartSourcep = NULL; - } - if (mPartSourcep) - { - // If we've got one already, just update the existing source (or remove it) - if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp)) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } - } - else - { - LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp); - //If the owner is muted, don't create the system - if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return; - // We need to be able to deal with a particle source that hasn't changed, but still got an update! - if (pss) - { -// llinfos << "Making particle system with owner " << owner_id << llendl; - pss->setOwnerUUID(owner_id); - mPartSourcep = pss; - LLViewerPartSim::getInstance()->addPartSource(pss); - } - } - if (mPartSourcep) - { - if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID) - { - LLViewerTexture* image; - if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null) - { - image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c"); - } - else - { - image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID); - } - mPartSourcep->setImage(image); - } - } -} - -void LLViewerObject::deleteParticleSource() -{ - if (mPartSourcep.notNull()) - { - mPartSourcep->setDead(); - mPartSourcep = NULL; - } -} - -// virtual -void LLViewerObject::updateDrawable(BOOL force_damped) -{ - if (mDrawable.notNull() && - !mDrawable->isState(LLDrawable::ON_MOVE_LIST) && - isChanged(MOVED)) - { - BOOL damped_motion = - !isChanged(SHIFTED) && // not shifted between regions this frame and... - ( force_damped || // ...forced into damped motion by application logic or... - ( !isSelected() && // ...not selected and... - ( mDrawable->isRoot() || // ... is root or ... - (getParent() && !((LLViewerObject*)getParent())->isSelected())// ... parent is not selected and ... - ) && - getPCode() == LL_PCODE_VOLUME && // ...is a volume object and... - getVelocity().isExactlyZero() && // ...is not moving physically and... - mDrawable->getGeneration() != -1 // ...was not created this frame. - ) - ); - gPipeline.markMoved(mDrawable, damped_motion); - } - clearChanged(SHIFTED); -} - -// virtual, overridden by LLVOVolume -F32 LLViewerObject::getVObjRadius() const -{ - return mDrawable.notNull() ? mDrawable->getRadius() : 0.f; -} - -void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags) -{ - if (!gAudiop) - { - return; - } - - if (audio_uuid.isNull()) - { - if (!mAudioSourcep) - { - return; - } - if (mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads()) - { - // We don't clear the sound if it's a loop, it'll go away on its own. - // At least, this appears to be how the scripts work. - // The attached sound ID is set to NULL to avoid it playing back when the - // object rezzes in on non-looping sounds. - //llinfos << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << llendl; - gAudiop->cleanupAudioSource(mAudioSourcep); - mAudioSourcep = NULL; - } - else if (flags & LL_SOUND_FLAG_STOP) - { - // Just shut off the sound - mAudioSourcep->play(LLUUID::null); - } - return; - } - if (flags & LL_SOUND_FLAG_LOOP - && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData() - && mAudioSourcep->getCurrentData()->getID() == audio_uuid) - { - //llinfos << "Already playing this sound on a loop, ignoring" << llendl; - return; - } - - // don't clean up before previous sound is done. Solves: SL-33486 - if ( mAudioSourcep && mAudioSourcep->isDone() ) - { - gAudiop->cleanupAudioSource(mAudioSourcep); - mAudioSourcep = NULL; - } - - if (mAudioSourcep && mAudioSourcep->isMuted() && - mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid) - { - //llinfos << "Already having this sound as muted sound, ignoring" << llendl; - return; - } - - getAudioSource(owner_id); - - if (mAudioSourcep) - { - BOOL queue = flags & LL_SOUND_FLAG_QUEUE; - mAudioGain = gain; - mAudioSourcep->setGain(gain); - mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP); - mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER); - mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE); - mAudioSourcep->setQueueSounds(queue); - if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG - { - mAudioSourcep->play(LLUUID::null); - } - - // Play this sound if region maturity permits - if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) ) - { - //llinfos << "Playing attached sound " << audio_uuid << llendl; - mAudioSourcep->play(audio_uuid); - } - } -} - -LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id) -{ - if (!mAudioSourcep) - { - // Arbitrary low gain for a sound that's not playing. - // This is used for sound preloads, for example. - LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this); - - mAudioSourcep = asvop; - if(gAudiop) gAudiop->addAudioSource(asvop); - } - - return mAudioSourcep; -} - -void LLViewerObject::adjustAudioGain(const F32 gain) -{ - if (!gAudiop) - { - return; - } - if (mAudioSourcep) - { - mAudioGain = gain; - mAudioSourcep->setGain(mAudioGain); - } -} - -//---------------------------------------------------------------------------- - -bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp) -{ - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param) - { - param->data->unpack(*dp); - param->in_use = TRUE; - parameterChanged(param_type, param->data, TRUE, false); - return true; - } - else - { - return false; - } -} - -LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type) -{ - LLNetworkData* new_block = NULL; - switch (param_type) - { - case LLNetworkData::PARAMS_FLEXIBLE: - { - new_block = new LLFlexibleObjectData(); - break; - } - case LLNetworkData::PARAMS_LIGHT: - { - new_block = new LLLightParams(); - break; - } - case LLNetworkData::PARAMS_SCULPT: - { - new_block = new LLSculptParams(); - break; - } - case LLNetworkData::PARAMS_LIGHT_IMAGE: - { - new_block = new LLLightImageParams(); - break; - } - default: - { - llinfos << "Unknown param type." << llendl; - break; - } - }; - - if (new_block) - { - ExtraParameter* new_entry = new ExtraParameter; - new_entry->data = new_block; - new_entry->in_use = false; // not in use yet - mExtraParameterList[param_type] = new_entry; - return new_entry; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const -{ - std::map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type); - if (itor != mExtraParameterList.end()) - { - return itor->second; - } - return NULL; -} - -LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type) -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (!param) - { - param = createNewParameterEntry(param_type); - } - return param; -} - -LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->data; - } - else - { - return NULL; - } -} - -BOOL LLViewerObject::getParameterEntryInUse(U16 param_type) const -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - return param->in_use; - } - else - { - return FALSE; - } -} - -bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin) -{ - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param) - { - if (param->in_use && new_value == *(param->data)) - { - return false; - } - param->in_use = true; - param->data->copy(new_value); - parameterChanged(param_type, param->data, TRUE, local_origin); - return true; - } - else - { - return false; - } -} - -// Assumed to be called locally -// If in_use is TRUE, will crate a new extra parameter if none exists. -// Should always return true. -bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin) -{ - ExtraParameter* param = getExtraParameterEntryCreate(param_type); - if (param && param->in_use != in_use) - { - param->in_use = in_use; - parameterChanged(param_type, param->data, in_use, local_origin); - return true; - } - return false; -} - -void LLViewerObject::parameterChanged(U16 param_type, bool local_origin) -{ - ExtraParameter* param = getExtraParameterEntry(param_type); - if (param) - { - parameterChanged(param_type, param->data, param->in_use, local_origin); - } -} - -void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin) -{ - if (local_origin) - { - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - - // Change happened on the viewer. Send the change up - U8 tmp[MAX_OBJECT_PARAMS_SIZE]; - LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE); - if (data->pack(dpb)) - { - U32 datasize = (U32)dpb.getCurrentSize(); - - LLMessageSystem* msg = gMessageSystem; - msg->newMessageFast(_PREHASH_ObjectExtraParams); - msg->nextBlockFast(_PREHASH_AgentData); - msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - msg->nextBlockFast(_PREHASH_ObjectData); - msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID ); - - msg->addU16Fast(_PREHASH_ParamType, param_type); - msg->addBOOLFast(_PREHASH_ParamInUse, in_use); - - msg->addU32Fast(_PREHASH_ParamSize, datasize); - msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize); - - msg->sendReliable( regionp->getHost() ); - } - else - { - llwarns << "Failed to send object extra parameters: " << param_type << llendl; - } - } -} - -void LLViewerObject::setDrawableState(U32 state, BOOL recursive) -{ - if (mDrawable) - { - mDrawable->setState(state); - } - if (recursive) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->setDrawableState(state, recursive); - } - } -} - -void LLViewerObject::clearDrawableState(U32 state, BOOL recursive) -{ - if (mDrawable) - { - mDrawable->clearState(state); - } - if (recursive) - { - for (child_list_t::iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* child = *iter; - child->clearDrawableState(state, recursive); - } - } -} - -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! -// RN: these functions assume a 2-level hierarchy -//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! - -// Owned by anyone? -BOOL LLViewerObject::permAnyOwner() const -{ - if (isRootEdit()) - { - return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0); - } - else - { - return ((LLViewerObject*)getParent())->permAnyOwner(); - } -} -// Owned by this viewer? -BOOL LLViewerObject::permYouOwner() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permYouOwner(); - } -} - -// Owned by a group? -BOOL LLViewerObject::permGroupOwner() const -{ - if (isRootEdit()) - { - return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0); - } - else - { - return ((LLViewerObject*)getParent())->permGroupOwner(); - } -} - -// Can the owner edit -BOOL LLViewerObject::permOwnerModify() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permOwnerModify(); - } -} - -// Can edit -BOOL LLViewerObject::permModify() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_MODIFY) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permModify(); - } -} - -// Can copy -BOOL LLViewerObject::permCopy() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_COPY) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permCopy(); - } -} - -// Can move -BOOL LLViewerObject::permMove() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_MOVE) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permMove(); - } -} - -// Can be transferred -BOOL LLViewerObject::permTransfer() const -{ - if (isRootEdit()) - { -#ifdef HACKED_GODLIKE_VIEWER - return TRUE; -#else -# ifdef TOGGLE_HACKED_GODLIKE_VIEWER - if (!LLGridManager::getInstance()->isInProductionGrid() - && (gAgent.getGodLevel() >= GOD_MAINTENANCE)) - { - return TRUE; - } -# endif - return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0); -#endif - } - else - { - return ((LLViewerObject*)getParent())->permTransfer(); - } -} - -// Can only open objects that you own, or that someone has -// given you modify rights to. JC -BOOL LLViewerObject::allowOpen() const -{ - return !flagInventoryEmpty() && (permYouOwner() || permModify()); -} - -LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo() -{ - if (mListener) - { - mListener->clearVOInventoryListener(); - } -} - -void LLViewerObject::updateVolume(const LLVolumeParams& volume_params) -{ - if (setVolume(volume_params, 1)) // *FIX: magic number, ack! - { - // Transmit the update to the simulator - sendShapeUpdate(); - markForUpdate(TRUE); - } -} - -void LLViewerObject::markForUpdate(BOOL priority) -{ - if (mDrawable.notNull()) - { - gPipeline.markTextured(mDrawable); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, priority); - } -} - -bool LLViewerObject::getIncludeInSearch() const -{ - return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0); -} - -void LLViewerObject::setIncludeInSearch(bool include_in_search) -{ - if (include_in_search) - { - mFlags |= FLAGS_INCLUDE_IN_SEARCH; - } - else - { - mFlags &= ~FLAGS_INCLUDE_IN_SEARCH; - } -} - -void LLViewerObject::setRegion(LLViewerRegion *regionp) -{ - if (!regionp) - { - llwarns << "viewer object set region to NULL" << llendl; - } - - mLatestRecvPacketID = 0; - mRegionp = regionp; - - for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i) - { - LLViewerObject* child = *i; - child->setRegion(regionp); - } - - setChanged(MOVED | SILHOUETTE); - updateDrawable(FALSE); -} - -// virtual -void LLViewerObject::updateRegion(LLViewerRegion *regionp) -{ -// if (regionp) -// { -// F64 now = LLFrameTimer::getElapsedSeconds(); -// llinfos << "Updating to region " << regionp->getName() -// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0) -// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0) -// << llendl; -// } -} - - -bool LLViewerObject::specialHoverCursor() const -{ - return (mFlags & FLAGS_USE_PHYSICS) - || (mFlags & FLAGS_HANDLE_TOUCH) - || (mClickAction != 0); -} - -void LLViewerObject::updateFlags(BOOL physics_changed) -{ - LLViewerRegion* regionp = getRegion(); - if(!regionp) return; - gMessageSystem->newMessage("ObjectFlagUpdate"); - gMessageSystem->nextBlockFast(_PREHASH_AgentData); - gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() ); - gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID()); - gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() ); - gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, usePhysics() ); - gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() ); - gMessageSystem->addBOOL("IsPhantom", flagPhantom() ); - gMessageSystem->addBOOL("CastsShadows", flagCastShadows() ); - if (physics_changed) - { - gMessageSystem->nextBlock("ExtraPhysics"); - gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() ); - gMessageSystem->addF32("Density", getPhysicsDensity() ); - gMessageSystem->addF32("Friction", getPhysicsFriction() ); - gMessageSystem->addF32("Restitution", getPhysicsRestitution() ); - gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() ); - } - gMessageSystem->sendReliable( regionp->getHost() ); -} - -BOOL LLViewerObject::setFlags(U32 flags, BOOL state) -{ - BOOL setit = FALSE; - if (state) - { - if ((mFlags & flags) != flags) - { - mFlags |= flags; - setit = TRUE; - } - } - else - { - if ((mFlags & flags) != 0) - { - mFlags &= ~flags; - setit = TRUE; - } - } - - // BUG: Sometimes viewer physics and simulator physics get - // out of sync. To fix this, always send update to simulator. -// if (setit) - { - updateFlags(); - } - return setit; -} - -void LLViewerObject::setPhysicsShapeType(U8 type) -{ - mPhysicsShapeUnknown = false; - mPhysicsShapeType = type; - mCostStale = true; -} - -void LLViewerObject::setPhysicsGravity(F32 gravity) -{ - mPhysicsGravity = gravity; -} - -void LLViewerObject::setPhysicsFriction(F32 friction) -{ - mPhysicsFriction = friction; -} - -void LLViewerObject::setPhysicsDensity(F32 density) -{ - mPhysicsDensity = density; -} - -void LLViewerObject::setPhysicsRestitution(F32 restitution) -{ - mPhysicsRestitution = restitution; -} - -U8 LLViewerObject::getPhysicsShapeType() const -{ - if (mPhysicsShapeUnknown) - { - mPhysicsShapeUnknown = false; - gObjectList.updatePhysicsFlags(this); - } - - return mPhysicsShapeType; -} - -void LLViewerObject::applyAngularVelocity(F32 dt) -{ - //do target omega here - mRotTime += dt; - LLVector3 ang_vel = getAngularVelocity(); - F32 omega = ang_vel.magVecSquared(); - F32 angle = 0.0f; - LLQuaternion dQ; - if (omega > 0.00001f) - { - omega = sqrt(omega); - angle = omega * dt; - - ang_vel *= 1.f/omega; - - dQ.setQuat(angle, ang_vel); - - setRotation(getRotation()*dQ); - setChanged(MOVED | SILHOUETTE); - } -} - -void LLViewerObject::resetRot() -{ - mRotTime = 0.0f; -} - -U32 LLViewerObject::getPartitionType() const -{ - return LLViewerRegion::PARTITION_NONE; -} - -void LLViewerObject::dirtySpatialGroup(BOOL priority) const -{ - if (mDrawable) - { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->dirtyGeom(); - gPipeline.markRebuild(group, priority); - } - } -} - -void LLViewerObject::dirtyMesh() -{ - if (mDrawable) - { - LLSpatialGroup* group = mDrawable->getSpatialGroup(); - if (group) - { - group->dirtyMesh(); - } - } -} - -F32 LLAlphaObject::getPartSize(S32 idx) -{ - return 0.f; -} - -// virtual -void LLStaticViewerObject::updateDrawable(BOOL force_damped) -{ - // Force an immediate rebuild on any update - if (mDrawable.notNull()) - { - mDrawable->updateXform(TRUE); - gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE); - } - clearChanged(SHIFTED); -} - -void LLViewerObject::saveUnselectedChildrenPosition(std::vector<LLVector3>& positions) -{ - if(mChildList.empty() || !positions.empty()) - { - return ; - } - - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - positions.push_back(childp->getPositionEdit()); - } - } - - return ; -} - -void LLViewerObject::saveUnselectedChildrenRotation(std::vector<LLQuaternion>& rotations) -{ - if(mChildList.empty()) - { - return ; - } - - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - rotations.push_back(childp->getRotationEdit()); - } - } - - return ; -} - -//counter-rotation -void LLViewerObject::resetChildrenRotationAndPosition(const std::vector<LLQuaternion>& rotations, - const std::vector<LLVector3>& positions) -{ - if(mChildList.empty()) - { - return ; - } - - S32 index = 0 ; - LLQuaternion inv_rotation = ~getRotationEdit() ; - LLVector3 offset = getPositionEdit() ; - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - childp->setRotation(rotations[index] * inv_rotation); - childp->setPosition((positions[index] - offset) * inv_rotation); - LLManip::rebuild(childp); - } - else //avatar - { - LLVector3 reset_pos = (positions[index] - offset) * inv_rotation ; - LLQuaternion reset_rot = rotations[index] * inv_rotation ; - - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); - ((LLVOAvatar*)childp)->mDrawable->mXform.setRotation(reset_rot) ; - - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE); - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setRotation(reset_rot, TRUE) ; - - LLManip::rebuild(childp); - } - index++; - } - } - - return ; -} - -//counter-translation -void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplified) -{ - if(mChildList.empty()) - { - return ; - } - - LLVector3 child_offset; - if(simplified) //translation only, rotation matrix does not change - { - child_offset = offset * ~getRotation(); - } - else //rotation matrix might change too. - { - if (isAttachment() && mDrawable.notNull()) - { - LLXform* attachment_point_xform = mDrawable->getXform()->getParent(); - LLQuaternion parent_rotation = getRotation() * attachment_point_xform->getWorldRotation(); - child_offset = offset * ~parent_rotation; - } - else - { - child_offset = offset * ~getRenderRotation(); - } - } - - for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin(); - iter != mChildList.end(); iter++) - { - LLViewerObject* childp = *iter; - if (!childp->isSelected() && childp->mDrawable.notNull()) - { - if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR) - { - childp->setPosition(childp->getPosition() + child_offset); - LLManip::rebuild(childp); - } - else //avatar - { - LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ; - - ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos); - ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos); - - LLManip::rebuild(childp); - } - } - } - - return ; -} - -const LLUUID &LLViewerObject::getAttachmentItemID() const -{ - return mAttachmentItemID; -} - -void LLViewerObject::setAttachmentItemID(const LLUUID &id) -{ - mAttachmentItemID = id; -} - -EObjectUpdateType LLViewerObject::getLastUpdateType() const -{ - return mLastUpdateType; -} - -void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type) -{ - mLastUpdateType = last_update_type; -} - -BOOL LLViewerObject::getLastUpdateCached() const -{ - return mLastUpdateCached; -} - -void LLViewerObject::setLastUpdateCached(BOOL last_update_cached) -{ - mLastUpdateCached = last_update_cached; -} - -const LLUUID &LLViewerObject::extractAttachmentItemID() -{ - LLUUID item_id = LLUUID::null; - LLNameValue* item_id_nv = getNVPair("AttachItemID"); - if( item_id_nv ) - { - const char* s = item_id_nv->getString(); - if( s ) - { - item_id.set(s); - } - } - setAttachmentItemID(item_id); - return getAttachmentItemID(); -} - -//virtual -LLVOAvatar* LLViewerObject::getAvatar() const -{ - if (isAttachment()) - { - LLViewerObject* vobj = (LLViewerObject*) getParent(); - - while (vobj && !vobj->asAvatar()) - { - vobj = (LLViewerObject*) vobj->getParent(); - } - - return (LLVOAvatar*) vobj; - } - - return NULL; -} - - -class ObjectPhysicsProperties : public LLHTTPNode -{ -public: - virtual void post( - ResponsePtr responder, - const LLSD& context, - const LLSD& input) const - { - LLSD object_data = input["body"]["ObjectData"]; - S32 num_entries = object_data.size(); - - for ( S32 i = 0; i < num_entries; i++ ) - { - LLSD& curr_object_data = object_data[i]; - U32 local_id = curr_object_data["LocalID"].asInteger(); - - // Iterate through nodes at end, since it can be on both the regular AND hover list - struct f : public LLSelectedNodeFunctor - { - U32 mID; - f(const U32& id) : mID(id) {} - virtual bool apply(LLSelectNode* node) - { - return (node->getObject() && node->getObject()->mLocalID == mID ); - } - } func(local_id); - - LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func); - - if (node) - { - // The LLSD message builder doesn't know how to handle U8, so we need to send as S8 and cast - U8 type = (U8)curr_object_data["PhysicsShapeType"].asInteger(); - F32 density = (F32)curr_object_data["Density"].asReal(); - F32 friction = (F32)curr_object_data["Friction"].asReal(); - F32 restitution = (F32)curr_object_data["Restitution"].asReal(); - F32 gravity = (F32)curr_object_data["GravityMultiplier"].asReal(); - - node->getObject()->setPhysicsShapeType(type); - node->getObject()->setPhysicsGravity(gravity); - node->getObject()->setPhysicsFriction(friction); - node->getObject()->setPhysicsDensity(density); - node->getObject()->setPhysicsRestitution(restitution); - } - } - - dialog_refresh_all(); - }; -}; - -LLHTTPRegistration<ObjectPhysicsProperties> - gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties"); - - -void LLViewerObject::updateQuota( const SelectionQuota& quota ) -{ - //update quotas - mSelectionQuota = quota; -} +/**
+ * @file llviewerobject.cpp
+ * @brief Base class for viewer objects
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#include "llviewerprecompiledheaders.h"
+
+#include "llviewerobject.h"
+
+#include "llaudioengine.h"
+#include "imageids.h"
+#include "indra_constants.h"
+#include "llmath.h"
+#include "llflexibleobject.h"
+#include "llviewercontrol.h"
+#include "lldatapacker.h"
+#include "llfasttimer.h"
+#include "llfloaterreg.h"
+#include "llfontgl.h"
+#include "llframetimer.h"
+#include "llinventory.h"
+#include "llinventorydefines.h"
+#include "llmaterialtable.h"
+#include "llmutelist.h"
+#include "llnamevalue.h"
+#include "llprimitive.h"
+#include "llquantize.h"
+#include "llregionhandle.h"
+#include "llsdserialize.h"
+#include "lltree_common.h"
+#include "llxfermanager.h"
+#include "message.h"
+#include "object_flags.h"
+#include "timing.h"
+
+#include "llaudiosourcevo.h"
+#include "llagent.h"
+#include "llagentcamera.h"
+#include "llbbox.h"
+#include "llbox.h"
+#include "llcylinder.h"
+#include "lldrawable.h"
+#include "llface.h"
+#include "llfloaterproperties.h"
+#include "llfloatertools.h"
+#include "llfollowcam.h"
+#include "llhudtext.h"
+#include "llselectmgr.h"
+#include "llrendersphere.h"
+#include "lltooldraganddrop.h"
+#include "llviewercamera.h"
+#include "llviewertexturelist.h"
+#include "llviewerinventory.h"
+#include "llviewerobjectlist.h"
+#include "llviewerparceloverlay.h"
+#include "llviewerpartsource.h"
+#include "llviewerregion.h"
+#include "llviewerstats.h"
+#include "llviewertextureanim.h"
+#include "llviewerwindow.h" // For getSpinAxis
+#include "llvoavatar.h"
+#include "llvoavatarself.h"
+#include "llvoclouds.h"
+#include "llvograss.h"
+#include "llvoground.h"
+#include "llvolume.h"
+#include "llvolumemessage.h"
+#include "llvopartgroup.h"
+#include "llvosky.h"
+#include "llvosurfacepatch.h"
+#include "llvotextbubble.h"
+#include "llvotree.h"
+#include "llvovolume.h"
+#include "llvowater.h"
+#include "llworld.h"
+#include "llui.h"
+#include "pipeline.h"
+#include "llviewernetwork.h"
+#include "llvowlsky.h"
+#include "llmanip.h"
+#include "lltrans.h"
+#include "llsdutil.h"
+#include "llmediaentry.h"
+#include "llaccountingquota.h"
+
+//#define DEBUG_UPDATE_TYPE
+
+BOOL LLViewerObject::sVelocityInterpolate = TRUE;
+BOOL LLViewerObject::sPingInterpolate = TRUE;
+
+U32 LLViewerObject::sNumZombieObjects = 0;
+S32 LLViewerObject::sNumObjects = 0;
+BOOL LLViewerObject::sMapDebug = TRUE;
+LLColor4 LLViewerObject::sEditSelectColor( 1.0f, 1.f, 0.f, 0.3f); // Edit OK
+LLColor4 LLViewerObject::sNoEditSelectColor( 1.0f, 0.f, 0.f, 0.3f); // Can't edit
+S32 LLViewerObject::sAxisArrowLength(50);
+BOOL LLViewerObject::sPulseEnabled(FALSE);
+BOOL LLViewerObject::sUseSharedDrawables(FALSE); // TRUE
+
+// sMaxUpdateInterpolationTime must be greater than sPhaseOutUpdateInterpolationTime
+F64 LLViewerObject::sMaxUpdateInterpolationTime = 3.0; // For motion interpolation: after X seconds with no updates, don't predict object motion
+F64 LLViewerObject::sPhaseOutUpdateInterpolationTime = 2.0; // For motion interpolation: after Y seconds with no updates, taper off motion prediction
+
+
+static LLFastTimer::DeclareTimer FTM_CREATE_OBJECT("Create Object");
+
+// static
+LLViewerObject *LLViewerObject::createObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
+{
+ LLViewerObject *res = NULL;
+ LLFastTimer t1(FTM_CREATE_OBJECT);
+
+ switch (pcode)
+ {
+ case LL_PCODE_VOLUME:
+ res = new LLVOVolume(id, pcode, regionp); break;
+ case LL_PCODE_LEGACY_AVATAR:
+ {
+ if (id == gAgentID)
+ {
+ if (!gAgentAvatarp)
+ {
+ gAgentAvatarp = new LLVOAvatarSelf(id, pcode, regionp);
+ }
+ else
+ {
+ gAgentAvatarp->updateRegion(regionp);
+ }
+ res = gAgentAvatarp;
+ }
+ else
+ {
+ res = new LLVOAvatar(id, pcode, regionp);
+ }
+ static_cast<LLVOAvatar*>(res)->initInstance();
+ break;
+ }
+ case LL_PCODE_LEGACY_GRASS:
+ res = new LLVOGrass(id, pcode, regionp); break;
+ case LL_PCODE_LEGACY_PART_SYS:
+// llwarns << "Creating old part sys!" << llendl;
+// res = new LLVOPart(id, pcode, regionp); break;
+ res = NULL; break;
+ case LL_PCODE_LEGACY_TREE:
+ res = new LLVOTree(id, pcode, regionp); break;
+ case LL_PCODE_TREE_NEW:
+// llwarns << "Creating new tree!" << llendl;
+// res = new LLVOTree(id, pcode, regionp); break;
+ res = NULL; break;
+ case LL_PCODE_LEGACY_TEXT_BUBBLE:
+ res = new LLVOTextBubble(id, pcode, regionp); break;
+ case LL_VO_CLOUDS:
+ res = new LLVOClouds(id, pcode, regionp); break;
+ case LL_VO_SURFACE_PATCH:
+ res = new LLVOSurfacePatch(id, pcode, regionp); break;
+ case LL_VO_SKY:
+ res = new LLVOSky(id, pcode, regionp); break;
+ case LL_VO_VOID_WATER:
+ res = new LLVOVoidWater(id, pcode, regionp); break;
+ case LL_VO_WATER:
+ res = new LLVOWater(id, pcode, regionp); break;
+ case LL_VO_GROUND:
+ res = new LLVOGround(id, pcode, regionp); break;
+ case LL_VO_PART_GROUP:
+ res = new LLVOPartGroup(id, pcode, regionp); break;
+ case LL_VO_HUD_PART_GROUP:
+ res = new LLVOHUDPartGroup(id, pcode, regionp); break;
+ case LL_VO_WL_SKY:
+ res = new LLVOWLSky(id, pcode, regionp); break;
+ default:
+ llwarns << "Unknown object pcode " << (S32)pcode << llendl;
+ res = NULL; break;
+ }
+ return res;
+}
+
+LLViewerObject::LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global)
+: LLPrimitive(),
+ mChildList(),
+ mID(id),
+ mLocalID(0),
+ mTotalCRC(0),
+ mTEImages(NULL),
+ mGLName(0),
+ mbCanSelect(TRUE),
+ mFlags(0),
+ mPhysicsShapeType(0),
+ mPhysicsGravity(0),
+ mPhysicsFriction(0),
+ mPhysicsDensity(0),
+ mPhysicsRestitution(0),
+ mDrawable(),
+ mCreateSelected(FALSE),
+ mRenderMedia(FALSE),
+ mBestUpdatePrecision(0),
+ mText(),
+ mLastInterpUpdateSecs(0.f),
+ mLastMessageUpdateSecs(0.f),
+ mLatestRecvPacketID(0),
+ mData(NULL),
+ mAudioSourcep(NULL),
+ mAudioGain(1.f),
+ mAppAngle(0.f),
+ mPixelArea(1024.f),
+ mInventory(NULL),
+ mInventorySerialNum(0),
+ mRegionp( regionp ),
+ mInventoryPending(FALSE),
+ mInventoryDirty(FALSE),
+ mDead(FALSE),
+ mOrphaned(FALSE),
+ mUserSelected(FALSE),
+ mOnActiveList(FALSE),
+ mOnMap(FALSE),
+ mStatic(FALSE),
+ mNumFaces(0),
+ mTimeDilation(1.f),
+ mRotTime(0.f),
+ mJointInfo(NULL),
+ mState(0),
+ mMedia(NULL),
+ mClickAction(0),
+ mObjectCost(0),
+ mLinksetCost(0),
+ mPhysicsCost(0),
+ mLinksetPhysicsCost(0.f),
+ mCostStale(true),
+ mPhysicsShapeUnknown(true),
+ mAttachmentItemID(LLUUID::null),
+ mLastUpdateType(OUT_UNKNOWN),
+ mLastUpdateCached(FALSE)
+{
+ if (!is_global)
+ {
+ llassert(mRegionp);
+ }
+
+ LLPrimitive::init_primitive(pcode);
+
+ // CP: added 12/2/2005 - this was being initialised to 0, not the current frame time
+ mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
+
+ mPositionRegion = LLVector3(0.f, 0.f, 0.f);
+
+ if (!is_global && mRegionp)
+ {
+ mPositionAgent = mRegionp->getOriginAgent();
+ }
+
+ LLViewerObject::sNumObjects++;
+}
+
+LLViewerObject::~LLViewerObject()
+{
+ deleteTEImages();
+
+ if(mInventory)
+ {
+ mInventory->clear(); // will deref and delete entries
+ delete mInventory;
+ mInventory = NULL;
+ }
+
+ if (mJointInfo)
+ {
+ delete mJointInfo;
+ mJointInfo = NULL;
+ }
+
+ if (mPartSourcep)
+ {
+ mPartSourcep->setDead();
+ mPartSourcep = NULL;
+ }
+
+ // Delete memory associated with extra parameters.
+ std::map<U16, ExtraParameter*>::iterator iter;
+ for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ {
+ if(iter->second != NULL)
+ {
+ delete iter->second->data;
+ delete iter->second;
+ }
+ }
+ mExtraParameterList.clear();
+
+ for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
+ mNameValuePairs.clear();
+
+ delete[] mData;
+ mData = NULL;
+
+ delete mMedia;
+ mMedia = NULL;
+
+ sNumObjects--;
+ sNumZombieObjects--;
+ llassert(mChildList.size() == 0);
+
+ clearInventoryListeners();
+}
+
+void LLViewerObject::deleteTEImages()
+{
+ delete[] mTEImages;
+ mTEImages = NULL;
+}
+
+void LLViewerObject::markDead()
+{
+ if (!mDead)
+ {
+ //llinfos << "Marking self " << mLocalID << " as dead." << llendl;
+
+ // Root object of this hierarchy unlinks itself.
+ if (getParent())
+ {
+ ((LLViewerObject *)getParent())->removeChild(this);
+ // go ahead and delete any jointinfo's that we find
+ delete mJointInfo;
+ mJointInfo = NULL;
+ }
+
+ // Mark itself as dead
+ mDead = TRUE;
+ gObjectList.cleanupReferences(this);
+
+ LLViewerObject *childp;
+ while (mChildList.size() > 0)
+ {
+ childp = mChildList.back();
+ if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
+ {
+ //llinfos << "Marking child " << childp->getLocalID() << " as dead." << llendl;
+ childp->setParent(NULL); // LLViewerObject::markDead 1
+ childp->markDead();
+ }
+ else
+ {
+ // make sure avatar is no longer parented,
+ // so we can properly set it's position
+ childp->setDrawableParent(NULL);
+ ((LLVOAvatar*)childp)->getOffObject();
+ childp->setParent(NULL); // LLViewerObject::markDead 2
+ }
+ mChildList.pop_back();
+ }
+
+ if (mDrawable.notNull())
+ {
+ // Drawables are reference counted, mark as dead, then nuke the pointer.
+ mDrawable->markDead();
+ mDrawable = NULL;
+ }
+
+ if (mText)
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+
+ if (mIcon)
+ {
+ mIcon->markDead();
+ mIcon = NULL;
+ }
+
+ if (mPartSourcep)
+ {
+ mPartSourcep->setDead();
+ mPartSourcep = NULL;
+ }
+
+ if (mAudioSourcep)
+ {
+ // Do some cleanup
+ if (gAudiop)
+ {
+ gAudiop->cleanupAudioSource(mAudioSourcep);
+ }
+ mAudioSourcep = NULL;
+ }
+
+ if (flagAnimSource())
+ {
+ if (isAgentAvatarValid())
+ {
+ // stop motions associated with this object
+ gAgentAvatarp->stopMotionFromSource(mID);
+ }
+ }
+
+ if (flagCameraSource())
+ {
+ LLFollowCamMgr::removeFollowCamParams(mID);
+ }
+
+ sNumZombieObjects++;
+ }
+}
+
+void LLViewerObject::dump() const
+{
+ llinfos << "Type: " << pCodeToString(mPrimitiveCode) << llendl;
+ llinfos << "Drawable: " << (LLDrawable *)mDrawable << llendl;
+ llinfos << "Update Age: " << LLFrameTimer::getElapsedSeconds() - mLastMessageUpdateSecs << llendl;
+
+ llinfos << "Parent: " << getParent() << llendl;
+ llinfos << "ID: " << mID << llendl;
+ llinfos << "LocalID: " << mLocalID << llendl;
+ llinfos << "PositionRegion: " << getPositionRegion() << llendl;
+ llinfos << "PositionAgent: " << getPositionAgent() << llendl;
+ llinfos << "PositionGlobal: " << getPositionGlobal() << llendl;
+ llinfos << "Velocity: " << getVelocity() << llendl;
+ if (mDrawable.notNull() && mDrawable->getNumFaces())
+ {
+ LLFacePool *poolp = mDrawable->getFace(0)->getPool();
+ if (poolp)
+ {
+ llinfos << "Pool: " << poolp << llendl;
+ llinfos << "Pool reference count: " << poolp->mReferences.size() << llendl;
+ }
+ }
+ //llinfos << "BoxTree Min: " << mDrawable->getBox()->getMin() << llendl;
+ //llinfos << "BoxTree Max: " << mDrawable->getBox()->getMin() << llendl;
+ /*
+ llinfos << "Velocity: " << getVelocity() << llendl;
+ llinfos << "AnyOwner: " << permAnyOwner() << " YouOwner: " << permYouOwner() << " Edit: " << mPermEdit << llendl;
+ llinfos << "UsePhysics: " << usePhysics() << " CanSelect " << mbCanSelect << " UserSelected " << mUserSelected << llendl;
+ llinfos << "AppAngle: " << mAppAngle << llendl;
+ llinfos << "PixelArea: " << mPixelArea << llendl;
+
+ char buffer[1000];
+ char *key;
+ for (key = mNameValuePairs.getFirstKey(); key; key = mNameValuePairs.getNextKey() )
+ {
+ mNameValuePairs[key]->printNameValue(buffer);
+ llinfos << buffer << llendl;
+ }
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ llinfos << " child " << child->getID() << llendl;
+ }
+ */
+}
+
+void LLViewerObject::printNameValuePairs() const
+{
+ for (name_value_map_t::const_iterator iter = mNameValuePairs.begin();
+ iter != mNameValuePairs.end(); iter++)
+ {
+ LLNameValue* nv = iter->second;
+ llinfos << nv->printNameValue() << llendl;
+ }
+}
+
+void LLViewerObject::initVOClasses()
+{
+ // Initialized shared class stuff first.
+ LLVOAvatar::initClass();
+ LLVOTree::initClass();
+ llinfos << "Viewer Object size: " << sizeof(LLViewerObject) << llendl;
+ LLVOGrass::initClass();
+ LLVOWater::initClass();
+ LLVOVolume::initClass();
+}
+
+void LLViewerObject::cleanupVOClasses()
+{
+ LLVOGrass::cleanupClass();
+ LLVOWater::cleanupClass();
+ LLVOTree::cleanupClass();
+ LLVOAvatar::cleanupClass();
+ LLVOVolume::cleanupClass();
+}
+
+// Replaces all name value pairs with data from \n delimited list
+// Does not update server
+void LLViewerObject::setNameValueList(const std::string& name_value_list)
+{
+ // Clear out the old
+ for_each(mNameValuePairs.begin(), mNameValuePairs.end(), DeletePairedPointer()) ;
+ mNameValuePairs.clear();
+
+ // Bring in the new
+ std::string::size_type length = name_value_list.length();
+ std::string::size_type start = 0;
+ while (start < length)
+ {
+ std::string::size_type end = name_value_list.find_first_of("\n", start);
+ if (end == std::string::npos) end = length;
+ if (end > start)
+ {
+ std::string tok = name_value_list.substr(start, end - start);
+ addNVPair(tok);
+ }
+ start = end+1;
+ }
+}
+
+
+// This method returns true if the object is over land owned by the
+// agent.
+bool LLViewerObject::isReturnable()
+{
+ if (isAttachment())
+ {
+ return false;
+ }
+ std::vector<LLBBox> boxes;
+ boxes.push_back(LLBBox(getPositionRegion(), getRotationRegion(), getScale() * -0.5f, getScale() * 0.5f).getAxisAligned());
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ boxes.push_back(LLBBox(child->getPositionRegion(), child->getRotationRegion(), child->getScale() * -0.5f, child->getScale() * 0.5f).getAxisAligned());
+ }
+
+ return mRegionp
+ && mRegionp->objectIsReturnable(getPositionRegion(), boxes);
+}
+
+BOOL LLViewerObject::setParent(LLViewerObject* parent)
+{
+ if(mParent != parent)
+ {
+ LLViewerObject* old_parent = (LLViewerObject*)mParent ;
+ BOOL ret = LLPrimitive::setParent(parent);
+ if(ret && old_parent && parent)
+ {
+ old_parent->removeChild(this) ;
+ }
+ return ret ;
+ }
+
+ return FALSE ;
+}
+
+void LLViewerObject::addChild(LLViewerObject *childp)
+{
+ for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
+ {
+ if (*i == childp)
+ { //already has child
+ return;
+ }
+ }
+
+ if (!isAvatar())
+ {
+ // propagate selection properties
+ childp->mbCanSelect = mbCanSelect;
+ }
+
+ if(childp->setParent(this))
+ {
+ mChildList.push_back(childp);
+ }
+}
+
+void LLViewerObject::removeChild(LLViewerObject *childp)
+{
+ for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
+ {
+ if (*i == childp)
+ {
+ if (!childp->isAvatar() && mDrawable.notNull() && mDrawable->isActive() && childp->mDrawable.notNull() && !isAvatar())
+ {
+ gPipeline.markRebuild(childp->mDrawable, LLDrawable::REBUILD_VOLUME);
+ }
+
+ mChildList.erase(i);
+
+ if(childp->getParent() == this)
+ {
+ childp->setParent(NULL);
+ }
+ break;
+ }
+ }
+
+ if (childp->isSelected())
+ {
+ LLSelectMgr::getInstance()->deselectObjectAndFamily(childp);
+ BOOL add_to_end = TRUE;
+ LLSelectMgr::getInstance()->selectObjectAndFamily(childp, add_to_end);
+ }
+}
+
+void LLViewerObject::addThisAndAllChildren(std::vector<LLViewerObject*>& objects)
+{
+ objects.push_back(this);
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ if (!child->isAvatar())
+ {
+ child->addThisAndAllChildren(objects);
+ }
+ }
+}
+
+void LLViewerObject::addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects)
+{
+ objects.push_back(this);
+ // don't add any attachments when temporarily selecting avatar
+ if (isAvatar())
+ {
+ return;
+ }
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ if ( (!child->isAvatar()) && (!child->isJointChild()))
+ {
+ child->addThisAndNonJointChildren(objects);
+ }
+ }
+}
+
+BOOL LLViewerObject::isChild(LLViewerObject *childp) const
+{
+ for (child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* testchild = *iter;
+ if (testchild == childp)
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+// returns TRUE if at least one avatar is sitting on this object
+BOOL LLViewerObject::isSeat() const
+{
+ for (child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ if (child->isAvatar())
+ {
+ return TRUE;
+ }
+ }
+ return FALSE;
+
+}
+
+BOOL LLViewerObject::setDrawableParent(LLDrawable* parentp)
+{
+ if (mDrawable.isNull())
+ {
+ return FALSE;
+ }
+
+ BOOL ret = mDrawable->mXform.setParent(parentp ? &parentp->mXform : NULL);
+ if(!ret)
+ {
+ return FALSE ;
+ }
+ LLDrawable* old_parent = mDrawable->mParent;
+ mDrawable->mParent = parentp;
+
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_VOLUME, TRUE);
+ if( (old_parent != parentp && old_parent)
+ || (parentp && parentp->isActive()))
+ {
+ // *TODO we should not be relying on setDrawable parent to call markMoved
+ gPipeline.markMoved(mDrawable, FALSE);
+ }
+ else if (!mDrawable->isAvatar())
+ {
+ mDrawable->updateXform(TRUE);
+ /*if (!mDrawable->getSpatialGroup())
+ {
+ mDrawable->movePartition();
+ }*/
+ }
+
+ return ret;
+}
+
+// Show or hide particles, icon and HUD
+void LLViewerObject::hideExtraDisplayItems( BOOL hidden )
+{
+ if( mPartSourcep.notNull() )
+ {
+ LLViewerPartSourceScript *partSourceScript = mPartSourcep.get();
+ partSourceScript->setSuspended( hidden );
+ }
+
+ if( mText.notNull() )
+ {
+ LLHUDText *hudText = mText.get();
+ hudText->setHidden( hidden );
+ }
+
+ if( mIcon.notNull() )
+ {
+ LLHUDIcon *hudIcon = mIcon.get();
+ hudIcon->setHidden( hidden );
+ }
+}
+
+U32 LLViewerObject::checkMediaURL(const std::string &media_url)
+{
+ U32 retval = (U32)0x0;
+ if (!mMedia && !media_url.empty())
+ {
+ retval |= MEDIA_URL_ADDED;
+ mMedia = new LLViewerObjectMedia;
+ mMedia->mMediaURL = media_url;
+ mMedia->mMediaType = LLViewerObject::MEDIA_SET;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ else if (mMedia)
+ {
+ if (media_url.empty())
+ {
+ retval |= MEDIA_URL_REMOVED;
+ delete mMedia;
+ mMedia = NULL;
+ }
+ else if (mMedia->mMediaURL != media_url) // <-- This is an optimization. If they are equal don't bother with below's test.
+ {
+ /*if (! (LLTextureEntry::getAgentIDFromMediaVersionString(media_url) == gAgent.getID() &&
+ LLTextureEntry::getVersionFromMediaVersionString(media_url) ==
+ LLTextureEntry::getVersionFromMediaVersionString(mMedia->mMediaURL) + 1))
+ */
+ {
+ // If the media URL is different and WE were not the one who
+ // changed it, mark dirty.
+ retval |= MEDIA_URL_UPDATED;
+ }
+ mMedia->mMediaURL = media_url;
+ mMedia->mPassedWhitelist = FALSE;
+ }
+ }
+ return retval;
+}
+
+U32 LLViewerObject::processUpdateMessage(LLMessageSystem *mesgsys,
+ void **user_data,
+ U32 block_num,
+ const EObjectUpdateType update_type,
+ LLDataPacker *dp)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+ U32 retval = 0x0;
+
+ // Coordinates of objects on simulators are region-local.
+ U64 region_handle;
+ mesgsys->getU64Fast(_PREHASH_RegionData, _PREHASH_RegionHandle, region_handle);
+
+ {
+ LLViewerRegion* regionp = LLWorld::getInstance()->getRegionFromHandle(region_handle);
+ if(regionp != mRegionp && regionp && mRegionp)//region cross
+ {
+ //this is the redundant position and region update, but it is necessary in case the viewer misses the following
+ //position and region update messages from sim.
+ //this redundant update should not cause any problems.
+ LLVector3 delta_pos = mRegionp->getOriginAgent() - regionp->getOriginAgent();
+ setPositionParent(getPosition() + delta_pos); //update to the new region position immediately.
+ setRegion(regionp) ; //change the region.
+ }
+ else
+ {
+ mRegionp = regionp ;
+ }
+ }
+
+ if (!mRegionp)
+ {
+ U32 x, y;
+ from_region_handle(region_handle, &x, &y);
+
+ llerrs << "Object has invalid region " << x << ":" << y << "!" << llendl;
+ return retval;
+ }
+
+ U16 time_dilation16;
+ mesgsys->getU16Fast(_PREHASH_RegionData, _PREHASH_TimeDilation, time_dilation16);
+ F32 time_dilation = ((F32) time_dilation16) / 65535.f;
+ mTimeDilation = time_dilation;
+ mRegionp->setTimeDilation(time_dilation);
+
+ // this will be used to determine if we've really changed position
+ // Use getPosition, not getPositionRegion, since this is what we're comparing directly against.
+ LLVector3 test_pos_parent = getPosition();
+
+ U8 data[60+16]; // This needs to match the largest size below.
+#ifdef LL_BIG_ENDIAN
+ U16 valswizzle[4];
+#endif
+ U16 *val;
+ const F32 size = LLWorld::getInstance()->getRegionWidthInMeters();
+ const F32 MAX_HEIGHT = LLWorld::getInstance()->getRegionMaxHeight();
+ const F32 MIN_HEIGHT = LLWorld::getInstance()->getRegionMinHeight();
+ S32 length;
+ S32 count;
+ S32 this_update_precision = 32; // in bits
+
+ // Temporaries, because we need to compare w/ previous to set dirty flags...
+ LLVector3 new_pos_parent;
+ LLVector3 new_vel;
+ LLVector3 new_acc;
+ LLVector3 new_angv;
+ LLVector3 old_angv = getAngularVelocity();
+ LLQuaternion new_rot;
+ LLVector3 new_scale = getScale();
+
+ U32 parent_id = 0;
+ U8 material = 0;
+ U8 click_action = 0;
+ U32 crc = 0;
+
+ bool old_special_hover_cursor = specialHoverCursor();
+
+ LLViewerObject *cur_parentp = (LLViewerObject *)getParent();
+
+ if (cur_parentp)
+ {
+ parent_id = cur_parentp->mLocalID;
+ }
+
+ if (!dp)
+ {
+ switch(update_type)
+ {
+ case OUT_FULL:
+ {
+#ifdef DEBUG_UPDATE_TYPE
+ llinfos << "Full:" << getID() << llendl;
+#endif
+ //clear cost and linkset cost
+ mCostStale = true;
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+
+ LLUUID audio_uuid;
+ LLUUID owner_id; // only valid if audio_uuid or particle system is not null
+ F32 gain;
+ U8 sound_flags;
+
+ mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_CRC, crc, block_num);
+ mesgsys->getU32Fast( _PREHASH_ObjectData, _PREHASH_ParentID, parent_id, block_num);
+ mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_Sound, audio_uuid, block_num );
+ // HACK: Owner id only valid if non-null sound id or particle system
+ mesgsys->getUUIDFast(_PREHASH_ObjectData, _PREHASH_OwnerID, owner_id, block_num );
+ mesgsys->getF32Fast( _PREHASH_ObjectData, _PREHASH_Gain, gain, block_num );
+ mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Flags, sound_flags, block_num );
+ mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_Material, material, block_num );
+ mesgsys->getU8Fast( _PREHASH_ObjectData, _PREHASH_ClickAction, click_action, block_num);
+ mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_Scale, new_scale, block_num );
+ length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
+
+ mTotalCRC = crc;
+
+ // Owner ID used for sound muting or particle system muting
+ setAttachedSound(audio_uuid, owner_id, gain, sound_flags);
+
+ U8 old_material = getMaterial();
+ if (old_material != material)
+ {
+ setMaterial(material);
+ if (mDrawable.notNull())
+ {
+ gPipeline.markMoved(mDrawable, FALSE); // undamped
+ }
+ }
+ setClickAction(click_action);
+
+ count = 0;
+ LLVector4 collision_plane;
+
+ switch(length)
+ {
+ case (60 + 16):
+ // pull out collision normal for avatar
+ htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ ((LLVOAvatar*)this)->setFootPlane(collision_plane);
+ count += sizeof(LLVector4);
+ // fall through
+ case 60:
+ this_update_precision = 32;
+ // this is a terse update
+ // pos
+ htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // vel
+ htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // acc
+ htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // theta
+ {
+ LLVector3 vec;
+ htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ new_rot.unpackFromVector3(vec);
+ }
+ count += sizeof(LLVector3);
+ // omega
+ htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ if (new_angv.isExactlyZero())
+ {
+ // reset rotation time
+ resetRot();
+ }
+ setAngularVelocity(new_angv);
+#if LL_DARWIN
+ if (length == 76)
+ {
+ setAngularVelocity(LLVector3::zero);
+ }
+#endif
+ break;
+ case(32 + 16):
+ // pull out collision normal for avatar
+ htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ ((LLVOAvatar*)this)->setFootPlane(collision_plane);
+ count += sizeof(LLVector4);
+ // fall through
+ case 32:
+ this_update_precision = 16;
+ test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
+
+ // This is a terse 16 update, so treat data as an array of U16's.
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ setVelocity(LLVector3(U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size)));
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ setAcceleration(LLVector3(U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size)));
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 4);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*4;
+ new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
+ new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
+ new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
+ new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ new_angv.setVec(U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size));
+ if (new_angv.isExactlyZero())
+ {
+ // reset rotation time
+ resetRot();
+ }
+ setAngularVelocity(new_angv);
+ break;
+
+ case 16:
+ this_update_precision = 8;
+ test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
+ // this is a terse 8 update
+ new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
+
+ setVelocity(U8_to_F32(data[3], -size, size),
+ U8_to_F32(data[4], -size, size),
+ U8_to_F32(data[5], -size, size) );
+
+ setAcceleration(U8_to_F32(data[6], -size, size),
+ U8_to_F32(data[7], -size, size),
+ U8_to_F32(data[8], -size, size) );
+
+ new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
+ new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
+ new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
+ new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
+
+ new_angv.setVec(U8_to_F32(data[13], -size, size),
+ U8_to_F32(data[14], -size, size),
+ U8_to_F32(data[15], -size, size) );
+ if (new_angv.isExactlyZero())
+ {
+ // reset rotation time
+ resetRot();
+ }
+ setAngularVelocity(new_angv);
+ break;
+ }
+
+ ////////////////////////////////////////////////////
+ //
+ // Here we handle data specific to the full message.
+ //
+
+ U32 flags;
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
+ // clear all but local flags
+ mFlags &= FLAGS_LOCAL;
+ mFlags |= flags;
+
+ U8 state;
+ mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
+ mState = state;
+
+ // ...new objects that should come in selected need to be added to the selected list
+ mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
+
+ // Set all name value pairs
+ S32 nv_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_NameValue);
+ if (nv_size > 0)
+ {
+ std::string name_value_list;
+ mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_NameValue, name_value_list, block_num);
+ setNameValueList(name_value_list);
+ }
+
+ // Clear out any existing generic data
+ if (mData)
+ {
+ delete [] mData;
+ }
+
+ // Check for appended generic data
+ S32 data_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Data);
+ if (data_size <= 0)
+ {
+ mData = NULL;
+ }
+ else
+ {
+ // ...has generic data
+ mData = new U8[data_size];
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_Data, mData, data_size, block_num);
+ }
+
+ S32 text_size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_Text);
+ if (text_size > 1)
+ {
+ // Setup object text
+ if (!mText)
+ {
+ mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
+ mText->setFont(LLFontGL::getFontSansSerif());
+ mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+ mText->setMaxLines(-1);
+ mText->setSourceObject(this);
+ mText->setOnHUDAttachment(isHUDAttachment());
+ }
+
+ std::string temp_string;
+ mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_Text, temp_string, block_num );
+
+ LLColor4U coloru;
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_TextColor, coloru.mV, 4, block_num);
+
+ // alpha was flipped so that it zero encoded better
+ coloru.mV[3] = 255 - coloru.mV[3];
+ mText->setColor(LLColor4(coloru));
+ mText->setString(temp_string);
+
+ if (mDrawable.notNull())
+ {
+ setChanged(MOVED | SILHOUETTE);
+ gPipeline.markMoved(mDrawable, FALSE); // undamped
+ }
+ }
+ else if (mText.notNull())
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+
+ std::string media_url;
+ mesgsys->getStringFast(_PREHASH_ObjectData, _PREHASH_MediaURL, media_url, block_num);
+ retval |= checkMediaURL(media_url);
+
+ //
+ // Unpack particle system data
+ //
+ unpackParticleSource(block_num, owner_id);
+
+ // Mark all extra parameters not used
+ std::map<U16, ExtraParameter*>::iterator iter;
+ for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ {
+ iter->second->in_use = FALSE;
+ }
+
+ // Unpack extra parameters
+ S32 size = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ExtraParams);
+ if (size > 0)
+ {
+ U8 *buffer = new U8[size];
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ExtraParams, buffer, size, block_num);
+ LLDataPackerBinaryBuffer dp(buffer, size);
+
+ U8 num_parameters;
+ dp.unpackU8(num_parameters, "num_params");
+ U8 param_block[MAX_OBJECT_PARAMS_SIZE];
+ for (U8 param=0; param<num_parameters; ++param)
+ {
+ U16 param_type;
+ S32 param_size;
+ dp.unpackU16(param_type, "param_type");
+ dp.unpackBinaryData(param_block, param_size, "param_data");
+ //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
+ LLDataPackerBinaryBuffer dp2(param_block, param_size);
+ unpackParameterEntry(param_type, &dp2);
+ }
+ delete[] buffer;
+ }
+
+ for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ {
+ if (!iter->second->in_use)
+ {
+ // Send an update message in case it was formerly in use
+ parameterChanged(iter->first, iter->second->data, FALSE, false);
+ }
+ }
+
+ U8 joint_type = 0;
+ mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_JointType, joint_type, block_num);
+ if (joint_type)
+ {
+ // create new joint info
+ if (!mJointInfo)
+ {
+ mJointInfo = new LLVOJointInfo;
+ }
+ mJointInfo->mJointType = (EHavokJointType) joint_type;
+ mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointPivot, mJointInfo->mPivot, block_num);
+ mesgsys->getVector3Fast(_PREHASH_ObjectData, _PREHASH_JointAxisOrAnchor, mJointInfo->mAxisOrAnchor, block_num);
+ }
+ else if (mJointInfo)
+ {
+ // this joint info is no longer needed
+ delete mJointInfo;
+ mJointInfo = NULL;
+ }
+
+ break;
+ }
+
+ case OUT_TERSE_IMPROVED:
+ {
+#ifdef DEBUG_UPDATE_TYPE
+ llinfos << "TI:" << getID() << llendl;
+#endif
+ length = mesgsys->getSizeFast(_PREHASH_ObjectData, block_num, _PREHASH_ObjectData);
+ mesgsys->getBinaryDataFast(_PREHASH_ObjectData, _PREHASH_ObjectData, data, length, block_num);
+ count = 0;
+ LLVector4 collision_plane;
+
+ switch(length)
+ {
+ case(60 + 16):
+ // pull out collision normal for avatar
+ htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ ((LLVOAvatar*)this)->setFootPlane(collision_plane);
+ count += sizeof(LLVector4);
+ // fall through
+ case 60:
+ // this is a terse 32 update
+ // pos
+ this_update_precision = 32;
+ htonmemcpy(new_pos_parent.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // vel
+ htonmemcpy((void*)getVelocity().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // acc
+ htonmemcpy((void*)getAcceleration().mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ count += sizeof(LLVector3);
+ // theta
+ {
+ LLVector3 vec;
+ htonmemcpy(vec.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ new_rot.unpackFromVector3(vec);
+ }
+ count += sizeof(LLVector3);
+ // omega
+ htonmemcpy((void*)new_angv.mV, &data[count], MVT_LLVector3, sizeof(LLVector3));
+ if (new_angv.isExactlyZero())
+ {
+ // reset rotation time
+ resetRot();
+ }
+ setAngularVelocity(new_angv);
+#if LL_DARWIN
+ if (length == 76)
+ {
+ setAngularVelocity(LLVector3::zero);
+ }
+#endif
+ break;
+ case(32 + 16):
+ // pull out collision normal for avatar
+ htonmemcpy(collision_plane.mV, &data[count], MVT_LLVector4, sizeof(LLVector4));
+ ((LLVOAvatar*)this)->setFootPlane(collision_plane);
+ count += sizeof(LLVector4);
+ // fall through
+ case 32:
+ // this is a terse 16 update
+ this_update_precision = 16;
+ test_pos_parent.quantize16(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ new_pos_parent.mV[VX] = U16_to_F32(val[VX], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VY] = U16_to_F32(val[VY], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VZ] = U16_to_F32(val[VZ], MIN_HEIGHT, MAX_HEIGHT);
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ setVelocity(U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size));
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*3;
+ setAcceleration(U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size));
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Quat, 8);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ count += sizeof(U16)*4;
+ new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
+ new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
+ new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
+ new_rot.mQ[VW] = U16_to_F32(val[VW], -1.f, 1.f);
+
+#ifdef LL_BIG_ENDIAN
+ htonmemcpy(valswizzle, &data[count], MVT_U16Vec3, 6);
+ val = valswizzle;
+#else
+ val = (U16 *) &data[count];
+#endif
+ setAngularVelocity( U16_to_F32(val[VX], -size, size),
+ U16_to_F32(val[VY], -size, size),
+ U16_to_F32(val[VZ], -size, size));
+ break;
+
+ case 16:
+ // this is a terse 8 update
+ this_update_precision = 8;
+ test_pos_parent.quantize8(-0.5f*size, 1.5f*size, MIN_HEIGHT, MAX_HEIGHT);
+ new_pos_parent.mV[VX] = U8_to_F32(data[0], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VY] = U8_to_F32(data[1], -0.5f*size, 1.5f*size);
+ new_pos_parent.mV[VZ] = U8_to_F32(data[2], MIN_HEIGHT, MAX_HEIGHT);
+
+ setVelocity(U8_to_F32(data[3], -size, size),
+ U8_to_F32(data[4], -size, size),
+ U8_to_F32(data[5], -size, size) );
+
+ setAcceleration(U8_to_F32(data[6], -size, size),
+ U8_to_F32(data[7], -size, size),
+ U8_to_F32(data[8], -size, size) );
+
+ new_rot.mQ[VX] = U8_to_F32(data[9], -1.f, 1.f);
+ new_rot.mQ[VY] = U8_to_F32(data[10], -1.f, 1.f);
+ new_rot.mQ[VZ] = U8_to_F32(data[11], -1.f, 1.f);
+ new_rot.mQ[VW] = U8_to_F32(data[12], -1.f, 1.f);
+
+ setAngularVelocity( U8_to_F32(data[13], -size, size),
+ U8_to_F32(data[14], -size, size),
+ U8_to_F32(data[15], -size, size) );
+ break;
+ }
+
+ U8 state;
+ mesgsys->getU8Fast(_PREHASH_ObjectData, _PREHASH_State, state, block_num );
+ mState = state;
+ break;
+ }
+
+ default:
+ break;
+
+ }
+ }
+ else
+ {
+ // handle the compressed case
+ LLUUID sound_uuid;
+ LLUUID owner_id;
+ F32 gain = 0;
+ U8 sound_flags = 0;
+ F32 cutoff = 0;
+
+ U16 val[4];
+
+ U8 state;
+
+ dp->unpackU8(state, "State");
+ mState = state;
+
+ switch(update_type)
+ {
+ case OUT_TERSE_IMPROVED:
+ {
+#ifdef DEBUG_UPDATE_TYPE
+ llinfos << "CompTI:" << getID() << llendl;
+#endif
+ U8 value;
+ dp->unpackU8(value, "agent");
+ if (value)
+ {
+ LLVector4 collision_plane;
+ dp->unpackVector4(collision_plane, "Plane");
+ ((LLVOAvatar*)this)->setFootPlane(collision_plane);
+ }
+ test_pos_parent = getPosition();
+ dp->unpackVector3(new_pos_parent, "Pos");
+ dp->unpackU16(val[VX], "VelX");
+ dp->unpackU16(val[VY], "VelY");
+ dp->unpackU16(val[VZ], "VelZ");
+ setVelocity(U16_to_F32(val[VX], -128.f, 128.f),
+ U16_to_F32(val[VY], -128.f, 128.f),
+ U16_to_F32(val[VZ], -128.f, 128.f));
+ dp->unpackU16(val[VX], "AccX");
+ dp->unpackU16(val[VY], "AccY");
+ dp->unpackU16(val[VZ], "AccZ");
+ setAcceleration(U16_to_F32(val[VX], -64.f, 64.f),
+ U16_to_F32(val[VY], -64.f, 64.f),
+ U16_to_F32(val[VZ], -64.f, 64.f));
+
+ dp->unpackU16(val[VX], "ThetaX");
+ dp->unpackU16(val[VY], "ThetaY");
+ dp->unpackU16(val[VZ], "ThetaZ");
+ dp->unpackU16(val[VS], "ThetaS");
+ new_rot.mQ[VX] = U16_to_F32(val[VX], -1.f, 1.f);
+ new_rot.mQ[VY] = U16_to_F32(val[VY], -1.f, 1.f);
+ new_rot.mQ[VZ] = U16_to_F32(val[VZ], -1.f, 1.f);
+ new_rot.mQ[VS] = U16_to_F32(val[VS], -1.f, 1.f);
+ dp->unpackU16(val[VX], "AccX");
+ dp->unpackU16(val[VY], "AccY");
+ dp->unpackU16(val[VZ], "AccZ");
+ setAngularVelocity( U16_to_F32(val[VX], -64.f, 64.f),
+ U16_to_F32(val[VY], -64.f, 64.f),
+ U16_to_F32(val[VZ], -64.f, 64.f));
+ }
+ break;
+ case OUT_FULL_COMPRESSED:
+ case OUT_FULL_CACHED:
+ {
+#ifdef DEBUG_UPDATE_TYPE
+ llinfos << "CompFull:" << getID() << llendl;
+#endif
+ mCostStale = true;
+
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+
+ dp->unpackU32(crc, "CRC");
+ mTotalCRC = crc;
+ dp->unpackU8(material, "Material");
+ U8 old_material = getMaterial();
+ if (old_material != material)
+ {
+ setMaterial(material);
+ if (mDrawable.notNull())
+ {
+ gPipeline.markMoved(mDrawable, FALSE); // undamped
+ }
+ }
+ dp->unpackU8(click_action, "ClickAction");
+ setClickAction(click_action);
+ dp->unpackVector3(new_scale, "Scale");
+ dp->unpackVector3(new_pos_parent, "Pos");
+ LLVector3 vec;
+ dp->unpackVector3(vec, "Rot");
+ new_rot.unpackFromVector3(vec);
+ setAcceleration(LLVector3::zero);
+
+ U32 value;
+ dp->unpackU32(value, "SpecialCode");
+ dp->setPassFlags(value);
+ dp->unpackUUID(owner_id, "Owner");
+
+ if (value & 0x80)
+ {
+ dp->unpackVector3(vec, "Omega");
+ setAngularVelocity(vec);
+ }
+
+ if (value & 0x20)
+ {
+ dp->unpackU32(parent_id, "ParentID");
+ }
+ else
+ {
+ parent_id = 0;
+ }
+
+ S32 sp_size;
+ U32 size;
+ if (value & 0x2)
+ {
+ sp_size = 1;
+ delete [] mData;
+ mData = new U8[1];
+ dp->unpackU8(((U8*)mData)[0], "TreeData");
+ }
+ else if (value & 0x1)
+ {
+ dp->unpackU32(size, "ScratchPadSize");
+ delete [] mData;
+ mData = new U8[size];
+ dp->unpackBinaryData((U8 *)mData, sp_size, "PartData");
+ }
+ else
+ {
+ mData = NULL;
+ }
+
+ // Setup object text
+ if (!mText && (value & 0x4))
+ {
+ mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
+ mText->setFont(LLFontGL::getFontSansSerif());
+ mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+ mText->setMaxLines(-1); // Set to match current agni behavior.
+ mText->setSourceObject(this);
+ mText->setOnHUDAttachment(isHUDAttachment());
+ }
+
+ if (value & 0x4)
+ {
+ std::string temp_string;
+ dp->unpackString(temp_string, "Text");
+ LLColor4U coloru;
+ dp->unpackBinaryDataFixed(coloru.mV, 4, "Color");
+ coloru.mV[3] = 255 - coloru.mV[3];
+ mText->setColor(LLColor4(coloru));
+ mText->setString(temp_string);
+
+ setChanged(TEXTURE);
+ }
+ else if(mText.notNull())
+ {
+ mText->markDead();
+ mText = NULL;
+ }
+
+ std::string media_url;
+ if (value & 0x200)
+ {
+ dp->unpackString(media_url, "MediaURL");
+ }
+ retval |= checkMediaURL(media_url);
+
+ //
+ // Unpack particle system data
+ //
+ if (value & 0x8)
+ {
+ unpackParticleSource(*dp, owner_id);
+ }
+ else
+ {
+ deleteParticleSource();
+ }
+
+ // Mark all extra parameters not used
+ std::map<U16, ExtraParameter*>::iterator iter;
+ for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ {
+ iter->second->in_use = FALSE;
+ }
+
+ // Unpack extra params
+ U8 num_parameters;
+ dp->unpackU8(num_parameters, "num_params");
+ U8 param_block[MAX_OBJECT_PARAMS_SIZE];
+ for (U8 param=0; param<num_parameters; ++param)
+ {
+ U16 param_type;
+ S32 param_size;
+ dp->unpackU16(param_type, "param_type");
+ dp->unpackBinaryData(param_block, param_size, "param_data");
+ //llinfos << "Param type: " << param_type << ", Size: " << param_size << llendl;
+ LLDataPackerBinaryBuffer dp2(param_block, param_size);
+ unpackParameterEntry(param_type, &dp2);
+ }
+
+ for (iter = mExtraParameterList.begin(); iter != mExtraParameterList.end(); ++iter)
+ {
+ if (!iter->second->in_use)
+ {
+ // Send an update message in case it was formerly in use
+ parameterChanged(iter->first, iter->second->data, FALSE, false);
+ }
+ }
+
+ if (value & 0x10)
+ {
+ dp->unpackUUID(sound_uuid, "SoundUUID");
+ dp->unpackF32(gain, "SoundGain");
+ dp->unpackU8(sound_flags, "SoundFlags");
+ dp->unpackF32(cutoff, "SoundRadius");
+ }
+
+ if (value & 0x100)
+ {
+ std::string name_value_list;
+ dp->unpackString(name_value_list, "NV");
+
+ setNameValueList(name_value_list);
+ }
+
+ mTotalCRC = crc;
+
+ setAttachedSound(sound_uuid, owner_id, gain, sound_flags);
+
+ // only get these flags on updates from sim, not cached ones
+ // Preload these five flags for every object.
+ // Finer shades require the object to be selected, and the selection manager
+ // stores the extended permission info.
+ U32 flags;
+ mesgsys->getU32Fast(_PREHASH_ObjectData, _PREHASH_UpdateFlags, flags, block_num);
+ // keep local flags and overwrite remote-controlled flags
+ mFlags = (mFlags & FLAGS_LOCAL) | flags;
+
+ // ...new objects that should come in selected need to be added to the selected list
+ mCreateSelected = ((flags & FLAGS_CREATE_SELECTED) != 0);
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ //
+ // Fix object parenting.
+ //
+ BOOL b_changed_status = FALSE;
+
+ if (OUT_TERSE_IMPROVED != update_type)
+ {
+ // We only need to update parenting on full updates, terse updates
+ // don't send parenting information.
+ if (!cur_parentp)
+ {
+ if (parent_id == 0)
+ {
+ // No parent now, no parent in message -> do nothing
+ }
+ else
+ {
+ // No parent now, new parent in message -> attach to that parent if possible
+ LLUUID parent_uuid;
+ LLViewerObjectList::getUUIDFromLocal(parent_uuid,
+ parent_id,
+ mesgsys->getSenderIP(),
+ mesgsys->getSenderPort());
+
+ LLViewerObject *sent_parentp = gObjectList.findObject(parent_uuid);
+
+ //
+ // Check to see if we have the corresponding viewer object for the parent.
+ //
+ if (sent_parentp && sent_parentp->getParent() == this)
+ {
+ // Try to recover if we attempt to attach a parent to its child
+ llwarns << "Attempt to attach a parent to it's child: " << this->getID() << " to " << sent_parentp->getID() << llendl;
+ this->removeChild(sent_parentp);
+ sent_parentp->setDrawableParent(NULL);
+ }
+
+ if (sent_parentp && (sent_parentp != this) && !sent_parentp->isDead())
+ {
+ //
+ // We have a viewer object for the parent, and it's not dead.
+ // Do the actual reparenting here.
+ //
+
+ // new parent is valid
+ b_changed_status = TRUE;
+ // ...no current parent, so don't try to remove child
+ if (mDrawable.notNull())
+ {
+ if (mDrawable->isDead() || !mDrawable->getVObj())
+ {
+ llwarns << "Drawable is dead or no VObj!" << llendl;
+ sent_parentp->addChild(this);
+ }
+ else
+ {
+ if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 1
+ {
+ // Bad, we got a cycle somehow.
+ // Kill both the parent and the child, and
+ // set cache misses for both of them.
+ llwarns << "Attempting to recover from parenting cycle!" << llendl;
+ llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
+ llwarns << "Adding to cache miss list" << llendl;
+ setParent(NULL);
+ sent_parentp->setParent(NULL);
+ getRegion()->addCacheMissFull(getLocalID());
+ getRegion()->addCacheMissFull(sent_parentp->getLocalID());
+ gObjectList.killObject(sent_parentp);
+ gObjectList.killObject(this);
+ return retval;
+ }
+ sent_parentp->addChild(this);
+ // make sure this object gets a non-damped update
+ if (sent_parentp->mDrawable.notNull())
+ {
+ gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
+ }
+ }
+ }
+ else
+ {
+ sent_parentp->addChild(this);
+ }
+
+ // Show particles, icon and HUD
+ hideExtraDisplayItems( FALSE );
+
+ setChanged(MOVED | SILHOUETTE);
+ }
+ else
+ {
+ //
+ // No corresponding viewer object for the parent, put the various
+ // pieces on the orphan list.
+ //
+
+ //parent_id
+ U32 ip = mesgsys->getSenderIP();
+ U32 port = mesgsys->getSenderPort();
+
+ gObjectList.orphanize(this, parent_id, ip, port);
+
+ // Hide particles, icon and HUD
+ hideExtraDisplayItems( TRUE );
+ }
+ }
+ }
+ else
+ {
+ // BUG: this is a bad assumption once border crossing is alowed
+ if ( (parent_id == cur_parentp->mLocalID)
+ &&(update_type == OUT_TERSE_IMPROVED))
+ {
+ // Parent now, same parent in message -> do nothing
+
+ // Debugging for suspected problems with local ids.
+ //LLUUID parent_uuid;
+ //LLViewerObjectList::getUUIDFromLocal(parent_uuid, parent_id, mesgsys->getSenderIP(), mesgsys->getSenderPort() );
+ //if (parent_uuid != cur_parentp->getID() )
+ //{
+ // llerrs << "Local ID match but UUID mismatch of viewer object" << llendl;
+ //}
+ }
+ else
+ {
+ // Parented now, different parent in message
+ LLViewerObject *sent_parentp;
+ if (parent_id == 0)
+ {
+ //
+ // This object is no longer parented, we sent in a zero parent ID.
+ //
+ sent_parentp = NULL;
+ }
+ else
+ {
+ LLUUID parent_uuid;
+ LLViewerObjectList::getUUIDFromLocal(parent_uuid,
+ parent_id,
+ gMessageSystem->getSenderIP(),
+ gMessageSystem->getSenderPort());
+ sent_parentp = gObjectList.findObject(parent_uuid);
+
+ if (isAvatar())
+ {
+ // This logic is meant to handle the case where a sitting avatar has reached a new sim
+ // ahead of the object she was sitting on (which is common as objects are transfered through
+ // a slower route than agents)...
+ // In this case, the local id for the object will not be valid, since the viewer has not received
+ // a full update for the object from that sim yet, so we assume that the agent is still sitting
+ // where she was originally. --RN
+ if (!sent_parentp)
+ {
+ sent_parentp = cur_parentp;
+ }
+ }
+ else if (!sent_parentp)
+ {
+ //
+ // Switching parents, but we don't know the new parent.
+ //
+ U32 ip = mesgsys->getSenderIP();
+ U32 port = mesgsys->getSenderPort();
+
+ // We're an orphan, flag things appropriately.
+ gObjectList.orphanize(this, parent_id, ip, port);
+ }
+ }
+
+ // Reattach if possible.
+ if (sent_parentp && sent_parentp != cur_parentp && sent_parentp != this)
+ {
+ // New parent is valid, detach and reattach
+ b_changed_status = TRUE;
+ if (mDrawable.notNull())
+ {
+ if (!setDrawableParent(sent_parentp->mDrawable)) // LLViewerObject::processUpdateMessage 2
+ {
+ // Bad, we got a cycle somehow.
+ // Kill both the parent and the child, and
+ // set cache misses for both of them.
+ llwarns << "Attempting to recover from parenting cycle!" << llendl;
+ llwarns << "Killing " << sent_parentp->getID() << " and " << getID() << llendl;
+ llwarns << "Adding to cache miss list" << llendl;
+ setParent(NULL);
+ sent_parentp->setParent(NULL);
+ getRegion()->addCacheMissFull(getLocalID());
+ getRegion()->addCacheMissFull(sent_parentp->getLocalID());
+ gObjectList.killObject(sent_parentp);
+ gObjectList.killObject(this);
+ return retval;
+ }
+ // make sure this object gets a non-damped update
+ }
+ cur_parentp->removeChild(this);
+ sent_parentp->addChild(this);
+ setChanged(MOVED | SILHOUETTE);
+ sent_parentp->setChanged(MOVED | SILHOUETTE);
+ if (sent_parentp->mDrawable.notNull())
+ {
+ gPipeline.markMoved(sent_parentp->mDrawable, FALSE); // undamped
+ }
+ }
+ else if (!sent_parentp)
+ {
+ bool remove_parent = true;
+ // No new parent, or the parent that we sent doesn't exist on the viewer.
+ LLViewerObject *parentp = (LLViewerObject *)getParent();
+ if (parentp)
+ {
+ if (parentp->getRegion() != getRegion())
+ {
+ // This is probably an object flying across a region boundary, the
+ // object probably ISN'T being reparented, but just got an object
+ // update out of order (child update before parent).
+ //llinfos << "Don't reparent object handoffs!" << llendl;
+ remove_parent = false;
+ }
+ }
+
+ if (remove_parent)
+ {
+ b_changed_status = TRUE;
+ if (mDrawable.notNull())
+ {
+ // clear parent to removeChild can put the drawable on the damped list
+ setDrawableParent(NULL); // LLViewerObject::processUpdateMessage 3
+ }
+
+ cur_parentp->removeChild(this);
+
+ if (mJointInfo && !parent_id)
+ {
+ // since this object is no longer parent-relative
+ // we make sure we delete any joint info
+ delete mJointInfo;
+ mJointInfo = NULL;
+ }
+
+ setChanged(MOVED | SILHOUETTE);
+
+ if (mDrawable.notNull())
+ {
+ // make sure this object gets a non-damped update
+ gPipeline.markMoved(mDrawable, FALSE); // undamped
+ }
+ }
+ }
+ }
+ }
+ }
+
+ new_rot.normQuat();
+
+ if (sPingInterpolate)
+ {
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit(mesgsys->getSender());
+ if (cdp)
+ {
+ F32 ping_delay = 0.5f * mTimeDilation * ( ((F32)cdp->getPingDelay()) * 0.001f + gFrameDTClamped);
+ LLVector3 diff = getVelocity() * ping_delay;
+ new_pos_parent += diff;
+ }
+ else
+ {
+ llwarns << "findCircuit() returned NULL; skipping interpolation" << llendl;
+ }
+ }
+
+ //////////////////////////
+ //
+ // Set the generic change flags...
+ //
+ //
+
+ // WTF? If we're going to skip this message, why are we
+ // doing all the parenting, etc above?
+ U32 packet_id = mesgsys->getCurrentRecvPacketID();
+ if (packet_id < mLatestRecvPacketID &&
+ mLatestRecvPacketID - packet_id < 65536)
+ {
+ //skip application of this message, it's old
+ return retval;
+ }
+
+ mLatestRecvPacketID = packet_id;
+
+ // Set the change flags for scale
+ if (new_scale != getScale())
+ {
+ setChanged(SCALED | SILHOUETTE);
+ setScale(new_scale); // Must follow setting permYouOwner()
+ }
+
+ // first, let's see if the new position is actually a change
+
+ //static S32 counter = 0;
+
+ F32 vel_mag_sq = getVelocity().magVecSquared();
+ F32 accel_mag_sq = getAcceleration().magVecSquared();
+
+ if ( ((b_changed_status)||(test_pos_parent != new_pos_parent))
+ ||( (!isSelected())
+ &&( (vel_mag_sq != 0.f)
+ ||(accel_mag_sq != 0.f)
+ ||(this_update_precision > mBestUpdatePrecision))))
+ {
+ mBestUpdatePrecision = this_update_precision;
+
+ LLVector3 diff = new_pos_parent - test_pos_parent ;
+ F32 mag_sqr = diff.magVecSquared() ;
+ if(llfinite(mag_sqr))
+ {
+ setPositionParent(new_pos_parent);
+ }
+ else
+ {
+ llwarns << "Can not move the object/avatar to an infinite location!" << llendl ;
+
+ retval |= INVALID_UPDATE ;
+ }
+
+ if (mParent && ((LLViewerObject*)mParent)->isAvatar())
+ {
+ // we have changed the position of an attachment, so we need to clamp it
+ LLVOAvatar *avatar = (LLVOAvatar*)mParent;
+
+ avatar->clampAttachmentPositions();
+ }
+
+ // If we're snapping the position by more than 0.5m, update LLViewerStats::mAgentPositionSnaps
+ if ( asAvatar() && asAvatar()->isSelf() && (mag_sqr > 0.25f) )
+ {
+ LLViewerStats::getInstance()->mAgentPositionSnaps.push( diff.length() );
+ }
+ }
+
+ if (new_rot != mLastRot
+ || new_angv != old_angv)
+ {
+ if (new_rot != mLastRot)
+ {
+ mLastRot = new_rot;
+ setRotation(new_rot);
+ }
+
+ setChanged(ROTATED | SILHOUETTE);
+
+ resetRot();
+ }
+
+
+ if ( gShowObjectUpdates )
+ {
+ if (!((mPrimitiveCode == LL_PCODE_LEGACY_AVATAR) && (((LLVOAvatar *) this)->isSelf()))
+ && mRegionp)
+ {
+ LLViewerObject* object = gObjectList.createObjectViewer(LL_PCODE_LEGACY_TEXT_BUBBLE, mRegionp);
+ LLVOTextBubble* bubble = (LLVOTextBubble*) object;
+
+ if (update_type == OUT_TERSE_IMPROVED)
+ {
+ bubble->mColor.setVec(0.f, 0.f, 1.f, 1.f);
+ }
+ else
+ {
+ bubble->mColor.setVec(1.f, 0.f, 0.f, 1.f);
+ }
+ object->setPositionGlobal(getPositionGlobal());
+ gPipeline.addObject(object);
+ }
+ }
+
+ if ((0.0f == vel_mag_sq) &&
+ (0.0f == accel_mag_sq) &&
+ (0.0f == getAngularVelocity().magVecSquared()))
+ {
+ mStatic = TRUE; // This object doesn't move!
+ }
+ else
+ {
+ mStatic = FALSE;
+ }
+
+// BUG: This code leads to problems during group rotate and any scale operation.
+// Small discepencies between the simulator and viewer representations cause the
+// selection center to creep, leading to objects moving around the wrong center.
+//
+// Removing this, however, means that if someone else drags an object you have
+// selected, your selection center and dialog boxes will be wrong. It also means
+// that higher precision information on selected objects will be ignored.
+//
+// I believe the group rotation problem is fixed. JNC 1.21.2002
+//
+ // Additionally, if any child is selected, need to update the dialogs and selection
+ // center.
+ BOOL needs_refresh = mUserSelected;
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ needs_refresh = needs_refresh || child->mUserSelected;
+ }
+
+ if (needs_refresh)
+ {
+ LLSelectMgr::getInstance()->updateSelectionCenter();
+ dialog_refresh_all();
+ }
+
+
+ // Mark update time as approx. now, with the ping delay.
+ // Ping delay is off because it's not set for velocity interpolation, causing
+ // much jumping and hopping around...
+
+// U32 ping_delay = mesgsys->mCircuitInfo.getPingDelay();
+ mLastInterpUpdateSecs = LLFrameTimer::getElapsedSeconds();
+ mLastMessageUpdateSecs = mLastInterpUpdateSecs;
+ if (mDrawable.notNull())
+ {
+ // Don't clear invisibility flag on update if still orphaned!
+ if (mDrawable->isState(LLDrawable::FORCE_INVISIBLE) && !mOrphaned)
+ {
+// lldebugs << "Clearing force invisible: " << mID << ":" << getPCodeString() << ":" << getPositionAgent() << llendl;
+ mDrawable->setState(LLDrawable::CLEAR_INVISIBLE);
+ }
+ }
+
+ // Update special hover cursor status
+ bool special_hover_cursor = specialHoverCursor();
+ if (old_special_hover_cursor != special_hover_cursor
+ && mDrawable.notNull())
+ {
+ mDrawable->updateSpecialHoverCursor(special_hover_cursor);
+ }
+
+ return retval;
+}
+
+BOOL LLViewerObject::isActive() const
+{
+ return TRUE;
+}
+
+
+
+BOOL LLViewerObject::idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time)
+{
+ static LLFastTimer::DeclareTimer ftm("Viewer Object");
+ LLFastTimer t(ftm);
+
+ if (mDead)
+ {
+ // It's dead. Don't update it.
+ return TRUE;
+ }
+
+ // CRO - don't velocity interp linked objects!
+ // Leviathan - but DO velocity interp joints
+ if (!mStatic && sVelocityInterpolate && !isSelected())
+ {
+ // calculate dt from last update
+ F32 dt_raw = (F32)(time - mLastInterpUpdateSecs);
+ F32 dt = mTimeDilation * dt_raw;
+
+ if (!mJointInfo)
+ {
+ applyAngularVelocity(dt);
+ }
+
+ LLViewerObject *parentp = (LLViewerObject *) getParent();
+ if (mJointInfo)
+ {
+ if (parentp)
+ {
+ // do parent-relative stuff
+ LLVector3 ang_vel = getAngularVelocity();
+ F32 omega = ang_vel.magVecSquared();
+ F32 angle = 0.0f;
+ LLQuaternion dQ;
+ if (omega > 0.00001f)
+ {
+ omega = sqrt(omega);
+ angle = omega * dt;
+ dQ.setQuat(angle, ang_vel);
+ }
+ LLVector3 pos = getPosition();
+
+ if (HJT_HINGE == mJointInfo->mJointType)
+ {
+ // hinge = uniform circular motion
+ LLVector3 parent_pivot = getVelocity();
+ LLVector3 parent_axis = getAcceleration();
+
+ angle = dt * (ang_vel * mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
+ dQ.setQuat(angle, mJointInfo->mAxisOrAnchor); // AxisOrAnchor = axis
+ LLVector3 pivot_offset = pos - mJointInfo->mPivot; // pos in pivot-frame
+ pivot_offset = pivot_offset * dQ; // new rotated pivot-frame pos
+ pos = mJointInfo->mPivot + pivot_offset; // parent-frame
+ LLViewerObject::setPosition(pos);
+ LLQuaternion Q_PC = getRotation();
+ setRotation(Q_PC * dQ);
+ mLastInterpUpdateSecs = time;
+ }
+ else if (HJT_POINT == mJointInfo->mJointType)
+ // || HJT_LPOINT == mJointInfo->mJointType)
+ {
+ // point-to-point = spin about axis and uniform circular motion
+ // of axis about the pivot point
+ //
+ // NOTE: this interpolation scheme is not quite good enough to
+ // reduce the bandwidth -- needs a gravitational correction.
+ // Similarly for hinges with axes that deviate from vertical.
+
+ LLQuaternion Q_PC = getRotation();
+ Q_PC = Q_PC * dQ;
+ setRotation(Q_PC);
+
+ LLVector3 pivot_to_child = - mJointInfo->mAxisOrAnchor; // AxisOrAnchor = anchor
+ pos = mJointInfo->mPivot + pivot_to_child * Q_PC;
+ LLViewerObject::setPosition(pos);
+ mLastInterpUpdateSecs = time;
+ }
+ /* else if (HJT_WHEEL == mJointInfo->mJointInfo)
+ {
+ // wheel = uniform rotation about axis, with linear
+ // velocity interpolation (if any)
+ LLVector3 parent_axis = getAcceleration(); // HACK -- accel stores the parent-axis (parent-frame)
+
+ LLQuaternion Q_PC = getRotation();
+
+ angle = dt * (parent_axis * ang_vel);
+ dQ.setQuat(angle, parent_axis);
+
+ Q_PC = Q_PC * dQ;
+ setRotation(Q_PC);
+
+ pos = getPosition() + dt * getVelocity();
+ LLViewerObject::setPosition(pos);
+ mLastInterpUpdateSecs = time;
+ }*/
+ }
+ }
+ else if (isAttachment())
+ {
+ mLastInterpUpdateSecs = time;
+ return TRUE;
+ }
+ else
+ { // Move object based on it's velocity and rotation
+ interpolateLinearMotion(time, dt);
+ }
+ }
+
+ updateDrawable(FALSE);
+
+ return TRUE;
+}
+
+
+// Move an object due to idle-time viewer side updates by iterpolating motion
+void LLViewerObject::interpolateLinearMotion(const F64 & time, const F32 & dt)
+{
+ // linear motion
+ // PHYSICS_TIMESTEP is used below to correct for the fact that the velocity in object
+ // updates represents the average velocity of the last timestep, rather than the final velocity.
+ // the time dilation above should guarantee that dt is never less than PHYSICS_TIMESTEP, theoretically
+ //
+ // *TODO: should also wrap linear accel/velocity in check
+ // to see if object is selected, instead of explicitly
+ // zeroing it out
+
+ F64 time_since_last_update = time - mLastMessageUpdateSecs;
+ if (time_since_last_update <= 0.0 || dt <= 0.f)
+ {
+ return;
+ }
+
+ LLVector3 accel = getAcceleration();
+ LLVector3 vel = getVelocity();
+
+ if (sMaxUpdateInterpolationTime <= 0.0)
+ { // Old code path ... unbounded, simple interpolation
+ if (!(accel.isExactlyZero() && vel.isExactlyZero()))
+ {
+ LLVector3 pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
+
+ // region local
+ setPositionRegion(pos + getPositionRegion());
+ setVelocity(vel + accel*dt);
+
+ // for objects that are spinning but not translating, make sure to flag them as having moved
+ setChanged(MOVED | SILHOUETTE);
+ }
+ }
+ else if (!accel.isExactlyZero() || !vel.isExactlyZero()) // object is moving
+ { // Object is moving, and hasn't been too long since we got an update from the server
+
+ // Calculate predicted position and velocity
+ LLVector3 new_pos = (vel + (0.5f * (dt-PHYSICS_TIMESTEP)) * accel) * dt;
+ LLVector3 new_v = accel * dt;
+
+ if (time_since_last_update > sPhaseOutUpdateInterpolationTime &&
+ sPhaseOutUpdateInterpolationTime > 0.0)
+ { // Haven't seen a viewer update in a while, check to see if the ciruit is still active
+ if (mRegionp)
+ { // The simulator will NOT send updates if the object continues normally on the path
+ // predicted by the velocity and the acceleration (often gravity) sent to the viewer
+ // So check to see if the circuit is blocked, which means the sim is likely in a long lag
+ LLCircuitData *cdp = gMessageSystem->mCircuitInfo.findCircuit( mRegionp->getHost() );
+ if (cdp)
+ {
+ // Find out how many seconds since last packet arrived on the circuit
+ F64 time_since_last_packet = LLMessageSystem::getMessageTimeSeconds() - cdp->getLastPacketInTime();
+
+ if (!cdp->isAlive() || // Circuit is dead or blocked
+ cdp->isBlocked() || // or doesn't seem to be getting any packets
+ (time_since_last_packet > sPhaseOutUpdateInterpolationTime))
+ {
+ // Start to reduce motion interpolation since we haven't seen a server update in a while
+ F64 time_since_last_interpolation = time - mLastInterpUpdateSecs;
+ F64 phase_out = 1.0;
+ if (time_since_last_update > sMaxUpdateInterpolationTime)
+ { // Past the time limit, so stop the object
+ phase_out = 0.0;
+ //llinfos << "Motion phase out to zero" << llendl;
+
+ // Kill angular motion as well. Note - not adding this due to paranoia
+ // about stopping rotation for llTargetOmega objects and not having it restart
+ // setAngularVelocity(LLVector3::zero);
+ }
+ else if (mLastInterpUpdateSecs - mLastMessageUpdateSecs > sPhaseOutUpdateInterpolationTime)
+ { // Last update was already phased out a bit
+ phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
+ (sMaxUpdateInterpolationTime - time_since_last_interpolation);
+ //llinfos << "Continuing motion phase out of " << (F32) phase_out << llendl;
+ }
+ else
+ { // Phase out from full value
+ phase_out = (sMaxUpdateInterpolationTime - time_since_last_update) /
+ (sMaxUpdateInterpolationTime - sPhaseOutUpdateInterpolationTime);
+ //llinfos << "Starting motion phase out of " << (F32) phase_out << llendl;
+ }
+ phase_out = llclamp(phase_out, 0.0, 1.0);
+
+ new_pos = new_pos * ((F32) phase_out);
+ new_v = new_v * ((F32) phase_out);
+ }
+ }
+ }
+ }
+
+ new_pos = new_pos + getPositionRegion();
+ new_v = new_v + vel;
+
+
+ // Clamp interpolated position to minimum underground and maximum region height
+ LLVector3d new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos);
+ F32 min_height;
+ if (isAvatar())
+ { // Make a better guess about AVs not going underground
+ min_height = LLWorld::getInstance()->resolveLandHeightGlobal(new_pos_global);
+ min_height += (0.5f * getScale().mV[VZ]);
+ }
+ else
+ { // This will put the object underground, but we can't tell if it will stop
+ // at ground level or not
+ min_height = LLWorld::getInstance()->getMinAllowedZ(this, new_pos_global);
+ }
+
+ new_pos.mV[VZ] = llmax(min_height, new_pos.mV[VZ]);
+ new_pos.mV[VZ] = llmin(LLWorld::getInstance()->getRegionMaxHeight(), new_pos.mV[VZ]);
+
+ // Check to see if it's going off the region
+ LLVector3 temp(new_pos);
+ if (temp.clamp(0.f, mRegionp->getWidth()))
+ { // Going off this region, so see if we might end up on another region
+ LLVector3d old_pos_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());
+ new_pos_global = mRegionp->getPosGlobalFromRegion(new_pos); // Re-fetch in case it got clipped above
+
+ // Clip the positions to known regions
+ LLVector3d clip_pos_global = LLWorld::getInstance()->clipToVisibleRegions(old_pos_global, new_pos_global);
+ if (clip_pos_global != new_pos_global)
+ { // Was clipped, so this means we hit a edge where there is no region to enter
+
+ //llinfos << "Hit empty region edge, clipped predicted position to " << mRegionp->getPosRegionFromGlobal(clip_pos_global)
+ // << " from " << new_pos << llendl;
+ new_pos = mRegionp->getPosRegionFromGlobal(clip_pos_global);
+
+ // Stop motion and get server update for bouncing on the edge
+ new_v.clear();
+ setAcceleration(LLVector3::zero);
+ }
+ else
+ { // Let predicted movement cross into another region
+ //llinfos << "Predicting region crossing to " << new_pos << llendl;
+ }
+ }
+
+ // Set new position and velocity
+ setPositionRegion(new_pos);
+ setVelocity(new_v);
+
+ // for objects that are spinning but not translating, make sure to flag them as having moved
+ setChanged(MOVED | SILHOUETTE);
+ }
+
+ // Update the last time we did anything
+ mLastInterpUpdateSecs = time;
+}
+
+
+
+BOOL LLViewerObject::setData(const U8 *datap, const U32 data_size)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ delete [] mData;
+
+ if (datap)
+ {
+ mData = new U8[data_size];
+ if (!mData)
+ {
+ return FALSE;
+ }
+ memcpy(mData, datap, data_size); /* Flawfinder: ignore */
+ }
+ return TRUE;
+}
+
+// delete an item in the inventory, but don't tell the server. This is
+// used internally by remove, update, and savescript.
+// This will only delete the first item with an item_id in the list
+void LLViewerObject::deleteInventoryItem(const LLUUID& item_id)
+{
+ if(mInventory)
+ {
+ LLInventoryObject::object_list_t::iterator it = mInventory->begin();
+ LLInventoryObject::object_list_t::iterator end = mInventory->end();
+ for( ; it != end; ++it )
+ {
+ if((*it)->getUUID() == item_id)
+ {
+ // This is safe only because we return immediatly.
+ mInventory->erase(it); // will deref and delete it
+ return;
+ }
+ }
+ doInventoryCallback();
+ }
+}
+
+void LLViewerObject::doUpdateInventory(
+ LLPointer<LLViewerInventoryItem>& item,
+ U8 key,
+ bool is_new)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ LLViewerInventoryItem* old_item = NULL;
+ if(TASK_INVENTORY_ITEM_KEY == key)
+ {
+ old_item = (LLViewerInventoryItem*)getInventoryObject(item->getUUID());
+ }
+ else if(TASK_INVENTORY_ASSET_KEY == key)
+ {
+ old_item = getInventoryItemByAsset(item->getAssetUUID());
+ }
+ LLUUID item_id;
+ LLUUID new_owner;
+ LLUUID new_group;
+ BOOL group_owned = FALSE;
+ if(old_item)
+ {
+ item_id = old_item->getUUID();
+ new_owner = old_item->getPermissions().getOwner();
+ new_group = old_item->getPermissions().getGroup();
+ group_owned = old_item->getPermissions().isGroupOwned();
+ old_item = NULL;
+ }
+ else
+ {
+ item_id = item->getUUID();
+ }
+ if(!is_new && mInventory)
+ {
+ // Attempt to update the local inventory. If we can get the
+ // object perm, we have perfect visibility, so we want the
+ // serial number to match. Otherwise, take our best guess and
+ // make sure that the serial number does not match.
+ deleteInventoryItem(item_id);
+ LLPermissions perm(item->getPermissions());
+ LLPermissions* obj_perm = LLSelectMgr::getInstance()->findObjectPermissions(this);
+ bool is_atomic = ((S32)LLAssetType::AT_OBJECT == item->getType()) ? false : true;
+ if(obj_perm)
+ {
+ perm.setOwnerAndGroup(LLUUID::null, obj_perm->getOwner(), obj_perm->getGroup(), is_atomic);
+ }
+ else
+ {
+ if(group_owned)
+ {
+ perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
+ }
+ else if(!new_owner.isNull())
+ {
+ // The object used to be in inventory, so we can
+ // assume the owner and group will match what they are
+ // there.
+ perm.setOwnerAndGroup(LLUUID::null, new_owner, new_group, is_atomic);
+ }
+ // *FIX: can make an even better guess by using the mPermGroup flags
+ else if(permYouOwner())
+ {
+ // best guess.
+ perm.setOwnerAndGroup(LLUUID::null, gAgent.getID(), item->getPermissions().getGroup(), is_atomic);
+ --mInventorySerialNum;
+ }
+ else
+ {
+ // dummy it up.
+ perm.setOwnerAndGroup(LLUUID::null, LLUUID::null, LLUUID::null, is_atomic);
+ --mInventorySerialNum;
+ }
+ }
+ LLViewerInventoryItem* oldItem = item;
+ LLViewerInventoryItem* new_item = new LLViewerInventoryItem(oldItem);
+ new_item->setPermissions(perm);
+ mInventory->push_front(new_item);
+ doInventoryCallback();
+ ++mInventorySerialNum;
+ }
+}
+
+// save a script, which involves removing the old one, and rezzing
+// in the new one. This method should be called with the asset id
+// of the new and old script AFTER the bytecode has been saved.
+void LLViewerObject::saveScript(
+ const LLViewerInventoryItem* item,
+ BOOL active,
+ bool is_new)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ /*
+ * XXXPAM Investigate not making this copy. Seems unecessary, but I'm unsure about the
+ * interaction with doUpdateInventory() called below.
+ */
+ lldebugs << "LLViewerObject::saveScript() " << item->getUUID() << " " << item->getAssetUUID() << llendl;
+ LLPointer<LLViewerInventoryItem> task_item =
+ new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
+ item->getAssetUUID(), item->getType(),
+ item->getInventoryType(),
+ item->getName(), item->getDescription(),
+ item->getSaleInfo(), item->getFlags(),
+ item->getCreationDate());
+ task_item->setTransactionID(item->getTransactionID());
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RezScript);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_GroupID, gAgent.getGroupID());
+ msg->nextBlockFast(_PREHASH_UpdateBlock);
+ msg->addU32Fast(_PREHASH_ObjectLocalID, (mLocalID));
+ U8 enabled = active;
+ msg->addBOOLFast(_PREHASH_Enabled, enabled);
+ msg->nextBlockFast(_PREHASH_InventoryBlock);
+ task_item->packMessage(msg);
+ msg->sendReliable(mRegionp->getHost());
+
+ // do the internal logic
+ doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, is_new);
+}
+
+void LLViewerObject::moveInventory(const LLUUID& folder_id,
+ const LLUUID& item_id)
+{
+ lldebugs << "LLViewerObject::moveInventory " << item_id << llendl;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_MoveTaskInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->addUUIDFast(_PREHASH_FolderID, folder_id);
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addU32Fast(_PREHASH_LocalID, mLocalID);
+ msg->addUUIDFast(_PREHASH_ItemID, item_id);
+ msg->sendReliable(mRegionp->getHost());
+
+ LLInventoryObject* inv_obj = getInventoryObject(item_id);
+ if(inv_obj)
+ {
+ LLViewerInventoryItem* item = (LLViewerInventoryItem*)inv_obj;
+ if(!item->getPermissions().allowCopyBy(gAgent.getID()))
+ {
+ deleteInventoryItem(item_id);
+ ++mInventorySerialNum;
+ }
+ }
+}
+
+void LLViewerObject::dirtyInventory()
+{
+ // If there aren't any LLVOInventoryListeners, we won't be
+ // able to update our mInventory when it comes back from the
+ // simulator, so we should not clear the inventory either.
+ if(mInventory && !mInventoryCallbacks.empty())
+ {
+ mInventory->clear(); // will deref and delete entries
+ delete mInventory;
+ mInventory = NULL;
+ mInventoryDirty = TRUE;
+ }
+}
+
+void LLViewerObject::registerInventoryListener(LLVOInventoryListener* listener, void* user_data)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ LLInventoryCallbackInfo* info = new LLInventoryCallbackInfo;
+ info->mListener = listener;
+ info->mInventoryData = user_data;
+ mInventoryCallbacks.push_front(info);
+}
+
+void LLViewerObject::removeInventoryListener(LLVOInventoryListener* listener)
+{
+ if (listener == NULL)
+ return;
+ for (callback_list_t::iterator iter = mInventoryCallbacks.begin();
+ iter != mInventoryCallbacks.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ LLInventoryCallbackInfo* info = *curiter;
+ if (info->mListener == listener)
+ {
+ delete info;
+ mInventoryCallbacks.erase(curiter);
+ break;
+ }
+ }
+}
+
+void LLViewerObject::clearInventoryListeners()
+{
+ for_each(mInventoryCallbacks.begin(), mInventoryCallbacks.end(), DeletePointer());
+ mInventoryCallbacks.clear();
+}
+
+void LLViewerObject::requestInventory()
+{
+ mInventoryDirty = FALSE;
+ if(mInventory)
+ {
+ //mInventory->clear() // will deref and delete it
+ //delete mInventory;
+ //mInventory = NULL;
+ doInventoryCallback();
+ }
+ // throw away duplicate requests
+ else
+ {
+ fetchInventoryFromServer();
+ }
+}
+
+void LLViewerObject::fetchInventoryFromServer()
+{
+ if (!mInventoryPending)
+ {
+ delete mInventory;
+ mInventory = NULL;
+ mInventoryDirty = FALSE;
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RequestTaskInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addU32Fast(_PREHASH_LocalID, mLocalID);
+ msg->sendReliable(mRegionp->getHost());
+
+ // this will get reset by dirtyInventory or doInventoryCallback
+ mInventoryPending = TRUE;
+ }
+}
+
+struct LLFilenameAndTask
+{
+ LLUUID mTaskID;
+ std::string mFilename;
+#ifdef _DEBUG
+ static S32 sCount;
+ LLFilenameAndTask()
+ {
+ ++sCount;
+ lldebugs << "Constructing LLFilenameAndTask: " << sCount << llendl;
+ }
+ ~LLFilenameAndTask()
+ {
+ --sCount;
+ lldebugs << "Destroying LLFilenameAndTask: " << sCount << llendl;
+ }
+private:
+ LLFilenameAndTask(const LLFilenameAndTask& rhs);
+ const LLFilenameAndTask& operator=(const LLFilenameAndTask& rhs) const;
+#endif
+};
+
+#ifdef _DEBUG
+S32 LLFilenameAndTask::sCount = 0;
+#endif
+
+// static
+void LLViewerObject::processTaskInv(LLMessageSystem* msg, void** user_data)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ LLUUID task_id;
+ msg->getUUIDFast(_PREHASH_InventoryData, _PREHASH_TaskID, task_id);
+ LLViewerObject* object = gObjectList.findObject(task_id);
+ if(!object)
+ {
+ llwarns << "LLViewerObject::processTaskInv object "
+ << task_id << " does not exist." << llendl;
+ return;
+ }
+
+ msg->getS16Fast(_PREHASH_InventoryData, _PREHASH_Serial, object->mInventorySerialNum);
+ LLFilenameAndTask* ft = new LLFilenameAndTask;
+ ft->mTaskID = task_id;
+
+ std::string unclean_filename;
+ msg->getStringFast(_PREHASH_InventoryData, _PREHASH_Filename, unclean_filename);
+ ft->mFilename = LLDir::getScrubbedFileName(unclean_filename);
+
+ if(ft->mFilename.empty())
+ {
+ lldebugs << "Task has no inventory" << llendl;
+ // mock up some inventory to make a drop target.
+ if(object->mInventory)
+ {
+ object->mInventory->clear(); // will deref and delete it
+ }
+ else
+ {
+ object->mInventory = new LLInventoryObject::object_list_t();
+ }
+ LLPointer<LLInventoryObject> obj;
+ obj = new LLInventoryObject(object->mID, LLUUID::null,
+ LLAssetType::AT_CATEGORY,
+ LLTrans::getString("ViewerObjectContents").c_str());
+ object->mInventory->push_front(obj);
+ object->doInventoryCallback();
+ delete ft;
+ return;
+ }
+ gXferManager->requestFile(gDirUtilp->getExpandedFilename(LL_PATH_CACHE, ft->mFilename),
+ ft->mFilename, LL_PATH_CACHE,
+ object->mRegionp->getHost(),
+ TRUE,
+ &LLViewerObject::processTaskInvFile,
+ (void**)ft,
+ LLXferManager::HIGH_PRIORITY);
+}
+
+void LLViewerObject::processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status)
+{
+ LLFilenameAndTask* ft = (LLFilenameAndTask*)user_data;
+ LLViewerObject* object = NULL;
+ if(ft && (0 == error_code) &&
+ (object = gObjectList.findObject(ft->mTaskID)))
+ {
+ object->loadTaskInvFile(ft->mFilename);
+ }
+ else
+ {
+ // This Occurs When to requests were made, and the first one
+ // has already handled it.
+ lldebugs << "Problem loading task inventory. Return code: "
+ << error_code << llendl;
+ }
+ delete ft;
+}
+
+void LLViewerObject::loadTaskInvFile(const std::string& filename)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ std::string filename_and_local_path = gDirUtilp->getExpandedFilename(LL_PATH_CACHE, filename);
+ llifstream ifs(filename_and_local_path);
+ if(ifs.good())
+ {
+ char buffer[MAX_STRING]; /* Flawfinder: ignore */
+ // *NOTE: This buffer size is hard coded into scanf() below.
+ char keyword[MAX_STRING]; /* Flawfinder: ignore */
+ if(mInventory)
+ {
+ mInventory->clear(); // will deref and delete it
+ }
+ else
+ {
+ mInventory = new LLInventoryObject::object_list_t;
+ }
+ while(ifs.good())
+ {
+ ifs.getline(buffer, MAX_STRING);
+ sscanf(buffer, " %254s", keyword); /* Flawfinder: ignore */
+ if(0 == strcmp("inv_item", keyword))
+ {
+ LLPointer<LLInventoryObject> inv = new LLViewerInventoryItem;
+ inv->importLegacyStream(ifs);
+ mInventory->push_front(inv);
+ }
+ else if(0 == strcmp("inv_object", keyword))
+ {
+ LLPointer<LLInventoryObject> inv = new LLInventoryObject;
+ inv->importLegacyStream(ifs);
+ inv->rename(LLTrans::getString("ViewerObjectContents").c_str());
+ mInventory->push_front(inv);
+ }
+ else
+ {
+ llwarns << "Unknown token in inventory file '"
+ << keyword << "'" << llendl;
+ }
+ }
+ ifs.close();
+ LLFile::remove(filename_and_local_path);
+ }
+ else
+ {
+ llwarns << "unable to load task inventory: " << filename_and_local_path
+ << llendl;
+ }
+ doInventoryCallback();
+}
+
+void LLViewerObject::doInventoryCallback()
+{
+ for (callback_list_t::iterator iter = mInventoryCallbacks.begin();
+ iter != mInventoryCallbacks.end(); )
+ {
+ callback_list_t::iterator curiter = iter++;
+ LLInventoryCallbackInfo* info = *curiter;
+ if (info->mListener != NULL)
+ {
+ info->mListener->inventoryChanged(this,
+ mInventory,
+ mInventorySerialNum,
+ info->mInventoryData);
+ }
+ else
+ {
+ llinfos << "LLViewerObject::doInventoryCallback() deleting bad listener entry." << llendl;
+ delete info;
+ mInventoryCallbacks.erase(curiter);
+ }
+ }
+ mInventoryPending = FALSE;
+}
+
+void LLViewerObject::removeInventory(const LLUUID& item_id)
+{
+ // close any associated floater properties
+ LLFloaterReg::hideInstance("properties", item_id);
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_RemoveTaskInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ msg->addU32Fast(_PREHASH_LocalID, mLocalID);
+ msg->addUUIDFast(_PREHASH_ItemID, item_id);
+ msg->sendReliable(mRegionp->getHost());
+ deleteInventoryItem(item_id);
+ ++mInventorySerialNum;
+}
+
+void LLViewerObject::updateInventory(
+ LLViewerInventoryItem* item,
+ U8 key,
+ bool is_new)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ // This slices the object into what we're concerned about on the
+ // viewer. The simulator will take the permissions and transfer
+ // ownership.
+ LLPointer<LLViewerInventoryItem> task_item =
+ new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
+ item->getAssetUUID(), item->getType(),
+ item->getInventoryType(),
+ item->getName(), item->getDescription(),
+ item->getSaleInfo(),
+ item->getFlags(),
+ item->getCreationDate());
+ task_item->setTransactionID(item->getTransactionID());
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_UpdateTaskInventory);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_UpdateData);
+ msg->addU32Fast(_PREHASH_LocalID, mLocalID);
+ msg->addU8Fast(_PREHASH_Key, key);
+ msg->nextBlockFast(_PREHASH_InventoryData);
+ task_item->packMessage(msg);
+ msg->sendReliable(mRegionp->getHost());
+
+ // do the internal logic
+ doUpdateInventory(task_item, key, is_new);
+}
+
+void LLViewerObject::updateInventoryLocal(LLInventoryItem* item, U8 key)
+{
+ LLPointer<LLViewerInventoryItem> task_item =
+ new LLViewerInventoryItem(item->getUUID(), mID, item->getPermissions(),
+ item->getAssetUUID(), item->getType(),
+ item->getInventoryType(),
+ item->getName(), item->getDescription(),
+ item->getSaleInfo(), item->getFlags(),
+ item->getCreationDate());
+
+ // do the internal logic
+ const bool is_new = false;
+ doUpdateInventory(task_item, key, is_new);
+}
+
+LLInventoryObject* LLViewerObject::getInventoryObject(const LLUUID& item_id)
+{
+ LLInventoryObject* rv = NULL;
+ if(mInventory)
+ {
+ LLInventoryObject::object_list_t::iterator it = mInventory->begin();
+ LLInventoryObject::object_list_t::iterator end = mInventory->end();
+ for ( ; it != end; ++it)
+ {
+ if((*it)->getUUID() == item_id)
+ {
+ rv = *it;
+ break;
+ }
+ }
+ }
+ return rv;
+}
+
+void LLViewerObject::getInventoryContents(LLInventoryObject::object_list_t& objects)
+{
+ if(mInventory)
+ {
+ LLInventoryObject::object_list_t::iterator it = mInventory->begin();
+ LLInventoryObject::object_list_t::iterator end = mInventory->end();
+ for( ; it != end; ++it)
+ {
+ if ((*it)->getType() != LLAssetType::AT_CATEGORY)
+ {
+ objects.push_back(*it);
+ }
+ }
+ }
+}
+
+LLInventoryObject* LLViewerObject::getInventoryRoot()
+{
+ if (!mInventory || !mInventory->size())
+ {
+ return NULL;
+ }
+ return mInventory->back();
+}
+
+LLViewerInventoryItem* LLViewerObject::getInventoryItemByAsset(const LLUUID& asset_id)
+{
+ if (mInventoryDirty)
+ llwarns << "Peforming inventory lookup for object " << mID << " that has dirty inventory!" << llendl;
+
+ LLViewerInventoryItem* rv = NULL;
+ if(mInventory)
+ {
+ LLViewerInventoryItem* item = NULL;
+
+ LLInventoryObject::object_list_t::iterator it = mInventory->begin();
+ LLInventoryObject::object_list_t::iterator end = mInventory->end();
+ for( ; it != end; ++it)
+ {
+ LLInventoryObject* obj = *it;
+ if(obj->getType() != LLAssetType::AT_CATEGORY)
+ {
+ // *FIX: gank-ass down cast!
+ item = (LLViewerInventoryItem*)obj;
+ if(item->getAssetUUID() == asset_id)
+ {
+ rv = item;
+ break;
+ }
+ }
+ }
+ }
+ return rv;
+}
+
+void LLViewerObject::updateViewerInventoryAsset(
+ const LLViewerInventoryItem* item,
+ const LLUUID& new_asset)
+{
+ LLPointer<LLViewerInventoryItem> task_item =
+ new LLViewerInventoryItem(item);
+ task_item->setAssetUUID(new_asset);
+
+ // do the internal logic
+ doUpdateInventory(task_item, TASK_INVENTORY_ITEM_KEY, false);
+}
+
+void LLViewerObject::setPixelAreaAndAngle(LLAgent &agent)
+{
+ if (getVolume())
+ { //volumes calculate pixel area and angle per face
+ return;
+ }
+
+ LLVector3 viewer_pos_agent = gAgentCamera.getCameraPositionAgent();
+ LLVector3 pos_agent = getRenderPosition();
+
+ F32 dx = viewer_pos_agent.mV[VX] - pos_agent.mV[VX];
+ F32 dy = viewer_pos_agent.mV[VY] - pos_agent.mV[VY];
+ F32 dz = viewer_pos_agent.mV[VZ] - pos_agent.mV[VZ];
+
+ F32 max_scale = getMaxScale();
+ F32 mid_scale = getMidScale();
+ F32 min_scale = getMinScale();
+
+ // IW: estimate - when close to large objects, computing range based on distance from center is no good
+ // to try to get a min distance from face, subtract min_scale/2 from the range.
+ // This means we'll load too much detail sometimes, but that's better than not enough
+ // I don't think there's a better way to do this without calculating distance per-poly
+ F32 range = sqrt(dx*dx + dy*dy + dz*dz) - min_scale/2;
+
+ LLViewerCamera* camera = LLViewerCamera::getInstance();
+ if (range < 0.001f || isHUDAttachment()) // range == zero
+ {
+ mAppAngle = 180.f;
+ mPixelArea = (F32)camera->getScreenPixelArea();
+ }
+ else
+ {
+ mAppAngle = (F32) atan2( max_scale, range) * RAD_TO_DEG;
+
+ F32 pixels_per_meter = camera->getPixelMeterRatio() / range;
+
+ mPixelArea = (pixels_per_meter * max_scale) * (pixels_per_meter * mid_scale);
+ if (mPixelArea > camera->getScreenPixelArea())
+ {
+ mAppAngle = 180.f;
+ mPixelArea = (F32)camera->getScreenPixelArea();
+ }
+ }
+}
+
+BOOL LLViewerObject::updateLOD()
+{
+ return FALSE;
+}
+
+BOOL LLViewerObject::updateGeometry(LLDrawable *drawable)
+{
+ return TRUE;
+}
+
+void LLViewerObject::updateGL()
+{
+
+}
+
+void LLViewerObject::updateFaceSize(S32 idx)
+{
+
+}
+
+LLDrawable* LLViewerObject::createDrawable(LLPipeline *pipeline)
+{
+ return NULL;
+}
+
+void LLViewerObject::setScale(const LLVector3 &scale, BOOL damped)
+{
+ LLPrimitive::setScale(scale);
+ if (mDrawable.notNull())
+ {
+ //encompass completely sheared objects by taking
+ //the most extreme point possible (<1,1,0.5>)
+ mDrawable->setRadius(LLVector3(1,1,0.5f).scaleVec(scale).magVec());
+ updateDrawable(damped);
+ }
+
+ if( (LL_PCODE_VOLUME == getPCode()) && !isDead() )
+ {
+ if (permYouOwner() || (scale.magVecSquared() > (7.5f * 7.5f)) )
+ {
+ if (!mOnMap)
+ {
+ llassert_always(LLWorld::getInstance()->getRegionFromHandle(getRegion()->getHandle()));
+
+ gObjectList.addToMap(this);
+ mOnMap = TRUE;
+ }
+ }
+ else
+ {
+ if (mOnMap)
+ {
+ gObjectList.removeFromMap(this);
+ mOnMap = FALSE;
+ }
+ }
+ }
+}
+
+void LLViewerObject::setObjectCost(F32 cost)
+{
+ mObjectCost = cost;
+ mCostStale = false;
+
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+}
+
+void LLViewerObject::setLinksetCost(F32 cost)
+{
+ mLinksetCost = cost;
+ mCostStale = false;
+
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+}
+
+void LLViewerObject::setPhysicsCost(F32 cost)
+{
+ mPhysicsCost = cost;
+ mCostStale = false;
+
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+}
+
+void LLViewerObject::setLinksetPhysicsCost(F32 cost)
+{
+ mLinksetPhysicsCost = cost;
+ mCostStale = false;
+
+ if (isSelected())
+ {
+ gFloaterTools->dirty();
+ }
+}
+
+
+F32 LLViewerObject::getObjectCost()
+{
+ if (mCostStale)
+ {
+ gObjectList.updateObjectCost(this);
+ }
+
+ return mObjectCost;
+}
+
+F32 LLViewerObject::getLinksetCost()
+{
+ if (mCostStale)
+ {
+ gObjectList.updateObjectCost(this);
+ }
+
+ return mLinksetCost;
+}
+
+F32 LLViewerObject::getPhysicsCost()
+{
+ if (mCostStale)
+ {
+ gObjectList.updateObjectCost(this);
+ }
+
+ return mPhysicsCost;
+}
+
+F32 LLViewerObject::getLinksetPhysicsCost()
+{
+ if (mCostStale)
+ {
+ gObjectList.updateObjectCost(this);
+ }
+
+ return mLinksetPhysicsCost;
+}
+
+F32 LLViewerObject::getStreamingCost(S32* bytes, S32* visible_bytes)
+{
+ return 0.f;
+}
+
+U32 LLViewerObject::getTriangleCount()
+{
+ return 0;
+}
+
+U32 LLViewerObject::getHighLODTriangleCount()
+{
+ return 0;
+}
+
+void LLViewerObject::updateSpatialExtents(LLVector4a& newMin, LLVector4a &newMax)
+{
+ LLVector4a center;
+ center.load3(getRenderPosition().mV);
+ LLVector4a size;
+ size.load3(getScale().mV);
+ newMin.setSub(center, size);
+ newMax.setAdd(center, size);
+
+ mDrawable->setPositionGroup(center);
+}
+
+F32 LLViewerObject::getBinRadius()
+{
+ if (mDrawable.notNull())
+ {
+ const LLVector4a* ext = mDrawable->getSpatialExtents();
+ LLVector4a diff;
+ diff.setSub(ext[1], ext[0]);
+ return diff.getLength3().getF32();
+ }
+
+ return getScale().magVec();
+}
+
+F32 LLViewerObject::getMaxScale() const
+{
+ return llmax(getScale().mV[VX],getScale().mV[VY], getScale().mV[VZ]);
+}
+
+F32 LLViewerObject::getMinScale() const
+{
+ return llmin(getScale().mV[0],getScale().mV[1],getScale().mV[2]);
+}
+
+F32 LLViewerObject::getMidScale() const
+{
+ if (getScale().mV[VX] < getScale().mV[VY])
+ {
+ if (getScale().mV[VY] < getScale().mV[VZ])
+ {
+ return getScale().mV[VY];
+ }
+ else if (getScale().mV[VX] < getScale().mV[VZ])
+ {
+ return getScale().mV[VZ];
+ }
+ else
+ {
+ return getScale().mV[VX];
+ }
+ }
+ else if (getScale().mV[VX] < getScale().mV[VZ])
+ {
+ return getScale().mV[VX];
+ }
+ else if (getScale().mV[VY] < getScale().mV[VZ])
+ {
+ return getScale().mV[VZ];
+ }
+ else
+ {
+ return getScale().mV[VY];
+ }
+}
+
+
+void LLViewerObject::updateTextures()
+{
+}
+
+void LLViewerObject::boostTexturePriority(BOOL boost_children /* = TRUE */)
+{
+ if (isDead())
+ {
+ return;
+ }
+
+ S32 i;
+ S32 tex_count = getNumTEs();
+ for (i = 0; i < tex_count; i++)
+ {
+ getTEImage(i)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
+ }
+
+ if (isSculpted() && !isMesh())
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ LLUUID sculpt_id = sculpt_params->getSculptTexture();
+ LLViewerTextureManager::getFetchedTexture(sculpt_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE)->setBoostLevel(LLViewerTexture::BOOST_SELECTED);
+ }
+
+ if (boost_children)
+ {
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ child->boostTexturePriority();
+ }
+ }
+}
+
+
+void LLViewerObject::setLineWidthForWindowSize(S32 window_width)
+{
+ if (window_width < 700)
+ {
+ LLUI::setLineWidth(2.0f);
+ }
+ else if (window_width < 1100)
+ {
+ LLUI::setLineWidth(3.0f);
+ }
+ else if (window_width < 2000)
+ {
+ LLUI::setLineWidth(4.0f);
+ }
+ else
+ {
+ // _damn_, what a nice monitor!
+ LLUI::setLineWidth(5.0f);
+ }
+}
+
+void LLViewerObject::increaseArrowLength()
+{
+/* ???
+ if (mAxisArrowLength == 50)
+ {
+ mAxisArrowLength = 100;
+ }
+ else
+ {
+ mAxisArrowLength = 150;
+ }
+*/
+}
+
+
+void LLViewerObject::decreaseArrowLength()
+{
+/* ???
+ if (mAxisArrowLength == 150)
+ {
+ mAxisArrowLength = 100;
+ }
+ else
+ {
+ mAxisArrowLength = 50;
+ }
+*/
+}
+
+// Culled from newsim LLTask::addNVPair
+void LLViewerObject::addNVPair(const std::string& data)
+{
+ // cout << "LLViewerObject::addNVPair() with ---" << data << "---" << endl;
+ LLNameValue *nv = new LLNameValue(data.c_str());
+
+// char splat[MAX_STRING];
+// temp->printNameValue(splat);
+// llinfos << "addNVPair " << splat << llendl;
+
+ name_value_map_t::iterator iter = mNameValuePairs.find(nv->mName);
+ if (iter != mNameValuePairs.end())
+ {
+ LLNameValue* foundnv = iter->second;
+ if (foundnv->mClass != NVC_READ_ONLY)
+ {
+ delete foundnv;
+ mNameValuePairs.erase(iter);
+ }
+ else
+ {
+ delete nv;
+// llinfos << "Trying to write to Read Only NVPair " << temp->mName << " in addNVPair()" << llendl;
+ return;
+ }
+ }
+ mNameValuePairs[nv->mName] = nv;
+}
+
+BOOL LLViewerObject::removeNVPair(const std::string& name)
+{
+ char* canonical_name = gNVNameTable.addString(name);
+
+ lldebugs << "LLViewerObject::removeNVPair(): " << name << llendl;
+
+ name_value_map_t::iterator iter = mNameValuePairs.find(canonical_name);
+ if (iter != mNameValuePairs.end())
+ {
+ if( mRegionp )
+ {
+ LLNameValue* nv = iter->second;
+/*
+ std::string buffer = nv->printNameValue();
+ gMessageSystem->newMessageFast(_PREHASH_RemoveNameValuePair);
+ gMessageSystem->nextBlockFast(_PREHASH_TaskData);
+ gMessageSystem->addUUIDFast(_PREHASH_ID, mID);
+
+ gMessageSystem->nextBlockFast(_PREHASH_NameValueData);
+ gMessageSystem->addStringFast(_PREHASH_NVPair, buffer);
+
+ gMessageSystem->sendReliable( mRegionp->getHost() );
+*/
+ // Remove the NV pair from the local list.
+ delete nv;
+ mNameValuePairs.erase(iter);
+ return TRUE;
+ }
+ else
+ {
+ lldebugs << "removeNVPair - No region for object" << llendl;
+ }
+ }
+ return FALSE;
+}
+
+
+LLNameValue *LLViewerObject::getNVPair(const std::string& name) const
+{
+ char *canonical_name;
+
+ canonical_name = gNVNameTable.addString(name);
+
+ // If you access a map with a name that isn't in it, it will add the name and a null pointer.
+ // So first check if the data is in the map.
+ name_value_map_t::const_iterator iter = mNameValuePairs.find(canonical_name);
+ if (iter != mNameValuePairs.end())
+ {
+ return iter->second;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+void LLViewerObject::updatePositionCaches() const
+{
+ if(mRegionp)
+ {
+ if (!isRoot())
+ {
+ mPositionRegion = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation();
+ mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
+ }
+ else
+ {
+ mPositionRegion = getPosition();
+ mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
+ }
+ }
+}
+
+const LLVector3d LLViewerObject::getPositionGlobal() const
+{
+ if(mRegionp)
+ {
+ LLVector3d position_global = mRegionp->getPosGlobalFromRegion(getPositionRegion());
+
+ if (isAttachment())
+ {
+ position_global = gAgent.getPosGlobalFromAgent(getRenderPosition());
+ }
+ return position_global;
+ }
+ else
+ {
+ LLVector3d position_global(getPosition());
+ return position_global;
+ }
+}
+
+const LLVector3 &LLViewerObject::getPositionAgent() const
+{
+ if (mRegionp)
+ {
+ if (mDrawable.notNull() && (!mDrawable->isRoot() && getParent()))
+ {
+ // Don't return cached position if you have a parent, recalc (until all dirtying is done correctly.
+ LLVector3 position_region;
+ position_region = ((LLViewerObject *)getParent())->getPositionRegion() + getPosition() * getParent()->getRotation();
+ mPositionAgent = mRegionp->getPosAgentFromRegion(position_region);
+ }
+ else
+ {
+ mPositionAgent = mRegionp->getPosAgentFromRegion(getPosition());
+ }
+ }
+ return mPositionAgent;
+}
+
+const LLVector3 &LLViewerObject::getPositionRegion() const
+{
+ if (!isRoot())
+ {
+ LLViewerObject *parent = (LLViewerObject *)getParent();
+ mPositionRegion = parent->getPositionRegion() + (getPosition() * parent->getRotation());
+ }
+ else
+ {
+ mPositionRegion = getPosition();
+ }
+
+ return mPositionRegion;
+}
+
+const LLVector3 LLViewerObject::getPositionEdit() const
+{
+ if (isRootEdit())
+ {
+ return getPosition();
+ }
+ else
+ {
+ LLViewerObject *parent = (LLViewerObject *)getParent();
+ LLVector3 position_edit = parent->getPositionEdit() + getPosition() * parent->getRotationEdit();
+ return position_edit;
+ }
+}
+
+const LLVector3 LLViewerObject::getRenderPosition() const
+{
+ if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED))
+ {
+ LLVOAvatar* avatar = getAvatar();
+ if (avatar)
+ {
+ return avatar->getPositionAgent();
+ }
+ }
+
+ if (mDrawable.isNull() || mDrawable->getGeneration() < 0)
+ {
+ return getPositionAgent();
+ }
+ else
+ {
+ return mDrawable->getPositionAgent();
+ }
+}
+
+const LLVector3 LLViewerObject::getPivotPositionAgent() const
+{
+ return getRenderPosition();
+}
+
+const LLQuaternion LLViewerObject::getRenderRotation() const
+{
+ LLQuaternion ret;
+ if (mDrawable.notNull() && mDrawable->isState(LLDrawable::RIGGED))
+ {
+ return ret;
+ }
+
+ if (mDrawable.isNull() || mDrawable->isStatic())
+ {
+ ret = getRotationEdit();
+ }
+ else
+ {
+ if (!mDrawable->isRoot())
+ {
+ ret = getRotation() * LLQuaternion(mDrawable->getParent()->getWorldMatrix());
+ }
+ else
+ {
+ ret = LLQuaternion(mDrawable->getWorldMatrix());
+ }
+ }
+
+ return ret;
+}
+
+const LLMatrix4 LLViewerObject::getRenderMatrix() const
+{
+ return mDrawable->getWorldMatrix();
+}
+
+const LLQuaternion LLViewerObject::getRotationRegion() const
+{
+ LLQuaternion global_rotation = getRotation();
+ if (!((LLXform *)this)->isRoot())
+ {
+ global_rotation = global_rotation * getParent()->getRotation();
+ }
+ return global_rotation;
+}
+
+const LLQuaternion LLViewerObject::getRotationEdit() const
+{
+ LLQuaternion global_rotation = getRotation();
+ if (!((LLXform *)this)->isRootEdit())
+ {
+ global_rotation = global_rotation * getParent()->getRotation();
+ }
+ return global_rotation;
+}
+
+void LLViewerObject::setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped )
+{
+ if (isAttachment())
+ {
+ LLVector3 new_pos = mRegionp->getPosRegionFromGlobal(pos_global);
+ if (isRootEdit())
+ {
+ new_pos -= mDrawable->mXform.getParent()->getWorldPosition();
+ LLQuaternion world_rotation = mDrawable->mXform.getParent()->getWorldRotation();
+ new_pos = new_pos * ~world_rotation;
+ }
+ else
+ {
+ LLViewerObject* parentp = (LLViewerObject*)getParent();
+ new_pos -= parentp->getPositionAgent();
+ new_pos = new_pos * ~parentp->getRotationRegion();
+ }
+ LLViewerObject::setPosition(new_pos);
+
+ if (mParent && ((LLViewerObject*)mParent)->isAvatar())
+ {
+ // we have changed the position of an attachment, so we need to clamp it
+ LLVOAvatar *avatar = (LLVOAvatar*)mParent;
+
+ avatar->clampAttachmentPositions();
+ }
+ }
+ else
+ {
+ if( isRoot() )
+ {
+ setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global));
+ }
+ else
+ {
+ // the relative position with the parent is not constant
+ LLViewerObject* parent = (LLViewerObject *)getParent();
+ //RN: this assumes we are only calling this function from the edit tools
+ gPipeline.updateMoveNormalAsync(parent->mDrawable);
+
+ LLVector3 pos_local = mRegionp->getPosRegionFromGlobal(pos_global) - parent->getPositionRegion();
+ pos_local = pos_local * ~parent->getRotationRegion();
+ LLViewerObject::setPosition( pos_local );
+ }
+ }
+ //RN: assumes we always want to snap the object when calling this function
+ gPipeline.updateMoveNormalAsync(mDrawable);
+}
+
+void LLViewerObject::setPosition(const LLVector3 &pos, BOOL damped)
+{
+ if (getPosition() != pos)
+ {
+ setChanged(TRANSLATED | SILHOUETTE);
+ }
+
+ LLXform::setPosition(pos);
+ updateDrawable(damped);
+ if (isRoot())
+ {
+ // position caches need to be up to date on root objects
+ updatePositionCaches();
+ }
+}
+
+void LLViewerObject::setPositionGlobal(const LLVector3d &pos_global, BOOL damped)
+{
+ if (isAttachment())
+ {
+ if (isRootEdit())
+ {
+ LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global);
+ newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition();
+
+ LLQuaternion invWorldRotation = mDrawable->mXform.getParent()->getWorldRotation();
+ invWorldRotation.transQuat();
+
+ newPos = newPos * invWorldRotation;
+ LLViewerObject::setPosition(newPos);
+ }
+ else
+ {
+ // assumes parent is root editable (root of attachment)
+ LLVector3 newPos = mRegionp->getPosRegionFromGlobal(pos_global);
+ newPos = newPos - mDrawable->mXform.getParent()->getWorldPosition();
+ LLVector3 delta_pos = newPos - getPosition();
+
+ LLQuaternion invRotation = mDrawable->getRotation();
+ invRotation.transQuat();
+
+ delta_pos = delta_pos * invRotation;
+
+ // *FIX: is this right? Shouldn't we be calling the
+ // LLViewerObject version of setPosition?
+ LLVector3 old_pos = mDrawable->mXform.getParent()->getPosition();
+ mDrawable->mXform.getParent()->setPosition(old_pos + delta_pos);
+ setChanged(TRANSLATED | SILHOUETTE);
+ }
+ if (mParent && ((LLViewerObject*)mParent)->isAvatar())
+ {
+ // we have changed the position of an attachment, so we need to clamp it
+ LLVOAvatar *avatar = (LLVOAvatar*)mParent;
+
+ avatar->clampAttachmentPositions();
+ }
+ }
+ else
+ {
+ if (isRoot())
+ {
+ setPositionRegion(mRegionp->getPosRegionFromGlobal(pos_global));
+ }
+ else
+ {
+ // the relative position with the parent is constant, but the parent's position needs to be changed
+ LLVector3d position_offset;
+ position_offset.setVec(getPosition()*getParent()->getRotation());
+ LLVector3d new_pos_global = pos_global - position_offset;
+ ((LLViewerObject *)getParent())->setPositionGlobal(new_pos_global);
+ }
+ }
+ updateDrawable(damped);
+}
+
+
+void LLViewerObject::setPositionParent(const LLVector3 &pos_parent, BOOL damped)
+{
+ // Set position relative to parent, if no parent, relative to region
+ if (!isRoot())
+ {
+ LLViewerObject::setPosition(pos_parent, damped);
+ //updateDrawable(damped);
+ }
+ else
+ {
+ setPositionRegion(pos_parent, damped);
+ }
+}
+
+void LLViewerObject::setPositionRegion(const LLVector3 &pos_region, BOOL damped)
+{
+ if (!isRootEdit())
+ {
+ LLViewerObject* parent = (LLViewerObject*) getParent();
+ LLViewerObject::setPosition((pos_region-parent->getPositionRegion())*~parent->getRotationRegion());
+ }
+ else
+ {
+ LLViewerObject::setPosition(pos_region);
+ mPositionRegion = pos_region;
+ mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
+ }
+}
+
+void LLViewerObject::setPositionAgent(const LLVector3 &pos_agent, BOOL damped)
+{
+ LLVector3 pos_region = getRegion()->getPosRegionFromAgent(pos_agent);
+ setPositionRegion(pos_region, damped);
+}
+
+// identical to setPositionRegion() except it checks for child-joints
+// and doesn't also move the joint-parent
+// TODO -- implement similar intelligence for joint-parents toward
+// their joint-children
+void LLViewerObject::setPositionEdit(const LLVector3 &pos_edit, BOOL damped)
+{
+ if (!isRootEdit())
+ {
+ // the relative position with the parent is constant, but the parent's position needs to be changed
+ LLVector3 position_offset = getPosition() * getParent()->getRotation();
+
+ ((LLViewerObject *)getParent())->setPositionEdit(pos_edit - position_offset);
+ updateDrawable(damped);
+ }
+ else if (isJointChild())
+ {
+ // compute new parent-relative position
+ LLViewerObject *parent = (LLViewerObject *) getParent();
+ LLQuaternion inv_parent_rot = parent->getRotation();
+ inv_parent_rot.transQuat();
+ LLVector3 pos_parent = (pos_edit - parent->getPositionRegion()) * inv_parent_rot;
+ LLViewerObject::setPosition(pos_parent, damped);
+ }
+ else
+ {
+ LLViewerObject::setPosition(pos_edit, damped);
+ mPositionRegion = pos_edit;
+ mPositionAgent = mRegionp->getPosAgentFromRegion(mPositionRegion);
+ }
+}
+
+
+LLViewerObject* LLViewerObject::getRootEdit() const
+{
+ const LLViewerObject* root = this;
+ while (root->mParent
+ && !(root->mJointInfo
+ || ((LLViewerObject*)root->mParent)->isAvatar()) )
+ {
+ root = (LLViewerObject*)root->mParent;
+ }
+ return (LLViewerObject*)root;
+}
+
+
+BOOL LLViewerObject::lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ S32 face,
+ BOOL pick_transparent,
+ S32* face_hit,
+ LLVector3* intersection,
+ LLVector2* tex_coord,
+ LLVector3* normal,
+ LLVector3* bi_normal)
+{
+ return false;
+}
+
+BOOL LLViewerObject::lineSegmentBoundingBox(const LLVector3& start, const LLVector3& end)
+{
+ if (mDrawable.isNull() || mDrawable->isDead())
+ {
+ return FALSE;
+ }
+
+ const LLVector4a* ext = mDrawable->getSpatialExtents();
+
+ //VECTORIZE THIS
+ LLVector4a center;
+ center.setAdd(ext[1], ext[0]);
+ center.mul(0.5f);
+ LLVector4a size;
+ size.setSub(ext[1], ext[0]);
+ size.mul(0.5f);
+
+ LLVector4a starta, enda;
+ starta.load3(start.mV);
+ enda.load3(end.mV);
+
+ return LLLineSegmentBoxIntersect(starta, enda, center, size);
+}
+
+U8 LLViewerObject::getMediaType() const
+{
+ if (mMedia)
+ {
+ return mMedia->mMediaType;
+ }
+ else
+ {
+ return LLViewerObject::MEDIA_NONE;
+ }
+}
+
+void LLViewerObject::setMediaType(U8 media_type)
+{
+ if (!mMedia)
+ {
+ // TODO what if we don't have a media pointer?
+ }
+ else if (mMedia->mMediaType != media_type)
+ {
+ mMedia->mMediaType = media_type;
+
+ // TODO: update materials with new image
+ }
+}
+
+std::string LLViewerObject::getMediaURL() const
+{
+ if (mMedia)
+ {
+ return mMedia->mMediaURL;
+ }
+ else
+ {
+ return std::string();
+ }
+}
+
+void LLViewerObject::setMediaURL(const std::string& media_url)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ if (!mMedia)
+ {
+ mMedia = new LLViewerObjectMedia;
+ mMedia->mMediaURL = media_url;
+ mMedia->mPassedWhitelist = FALSE;
+
+ // TODO: update materials with new image
+ }
+ else if (mMedia->mMediaURL != media_url)
+ {
+ mMedia->mMediaURL = media_url;
+ mMedia->mPassedWhitelist = FALSE;
+
+ // TODO: update materials with new image
+ }
+}
+
+BOOL LLViewerObject::getMediaPassedWhitelist() const
+{
+ if (mMedia)
+ {
+ return mMedia->mPassedWhitelist;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+void LLViewerObject::setMediaPassedWhitelist(BOOL passed)
+{
+ if (mMedia)
+ {
+ mMedia->mPassedWhitelist = passed;
+ }
+}
+
+BOOL LLViewerObject::setMaterial(const U8 material)
+{
+ BOOL res = LLPrimitive::setMaterial(material);
+ if (res)
+ {
+ setChanged(TEXTURE);
+ }
+ return res;
+}
+
+void LLViewerObject::setNumTEs(const U8 num_tes)
+{
+ LLMemType mt(LLMemType::MTYPE_OBJECT);
+
+ U32 i;
+ if (num_tes != getNumTEs())
+ {
+ if (num_tes)
+ {
+ LLPointer<LLViewerTexture> *new_images;
+ new_images = new LLPointer<LLViewerTexture>[num_tes];
+ for (i = 0; i < num_tes; i++)
+ {
+ if (i < getNumTEs())
+ {
+ new_images[i] = mTEImages[i];
+ }
+ else if (getNumTEs())
+ {
+ new_images[i] = mTEImages[getNumTEs()-1];
+ }
+ else
+ {
+ new_images[i] = NULL;
+ }
+ }
+
+ deleteTEImages();
+
+ mTEImages = new_images;
+ }
+ else
+ {
+ deleteTEImages();
+ }
+ LLPrimitive::setNumTEs(num_tes);
+ setChanged(TEXTURE);
+
+ if (mDrawable.notNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+}
+
+void LLViewerObject::sendMaterialUpdate() const
+{
+ LLViewerRegion* regionp = getRegion();
+ if(!regionp) return;
+ gMessageSystem->newMessageFast(_PREHASH_ObjectMaterial);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
+ gMessageSystem->addU8Fast(_PREHASH_Material, getMaterial() );
+ gMessageSystem->sendReliable( regionp->getHost() );
+
+}
+
+// formerly send_object_rotation
+void LLViewerObject::sendRotationUpdate() const
+{
+ LLViewerRegion* regionp = getRegion();
+ if(!regionp) return;
+ gMessageSystem->newMessageFast(_PREHASH_ObjectRotation);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID);
+ gMessageSystem->addQuatFast(_PREHASH_Rotation, getRotationEdit());
+ //llinfos << "Sent rotation " << getRotationEdit() << llendl;
+ gMessageSystem->sendReliable( regionp->getHost() );
+}
+
+/* Obsolete, we use MultipleObjectUpdate instead
+//// formerly send_object_position_global
+//void LLViewerObject::sendPositionUpdate() const
+//{
+// gMessageSystem->newMessageFast(_PREHASH_ObjectPosition);
+// gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+// gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+// gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+// gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+// gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
+// gMessageSystem->addVector3Fast(_PREHASH_Position, getPositionRegion());
+// LLViewerRegion* regionp = getRegion();
+// gMessageSystem->sendReliable(regionp->getHost());
+//}
+*/
+
+//formerly send_object_shape(LLViewerObject *object)
+void LLViewerObject::sendShapeUpdate()
+{
+ gMessageSystem->newMessageFast(_PREHASH_ObjectShape);
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->nextBlockFast(_PREHASH_ObjectData);
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
+
+ LLVolumeMessage::packVolumeParams(&getVolume()->getParams(), gMessageSystem);
+
+ LLViewerRegion *regionp = getRegion();
+ gMessageSystem->sendReliable( regionp->getHost() );
+}
+
+
+void LLViewerObject::sendTEUpdate() const
+{
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ObjectImage);
+
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
+ if (mMedia)
+ {
+ msg->addString("MediaURL", mMedia->mMediaURL);
+ }
+ else
+ {
+ msg->addString("MediaURL", NULL);
+ }
+
+ // TODO send media type
+
+ packTEMessage(msg);
+
+ LLViewerRegion *regionp = getRegion();
+ msg->sendReliable( regionp->getHost() );
+}
+
+void LLViewerObject::setTE(const U8 te, const LLTextureEntry &texture_entry)
+{
+ LLPrimitive::setTE(te, texture_entry);
+// This doesn't work, don't get any textures.
+// if (mDrawable.notNull() && mDrawable->isVisible())
+// {
+ const LLUUID& image_id = getTE(te)->getID();
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(image_id, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
+// }
+}
+
+void LLViewerObject::setTEImage(const U8 te, LLViewerTexture *imagep)
+{
+ if (mTEImages[te] != imagep)
+ {
+ mTEImages[te] = imagep;
+ LLPrimitive::setTETexture(te, imagep->getID());
+ setChanged(TEXTURE);
+ if (mDrawable.notNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+}
+
+
+S32 LLViewerObject::setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host)
+{
+ S32 retval = 0;
+ if (uuid != getTE(te)->getID() ||
+ uuid == LLUUID::null)
+ {
+ retval = LLPrimitive::setTETexture(te, uuid);
+ mTEImages[te] = LLViewerTextureManager::getFetchedTexture(uuid, TRUE, LLViewerTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE, 0, 0, host);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+ return retval;
+}
+
+
+void LLViewerObject::changeTEImage(S32 index, LLViewerTexture* new_image)
+{
+ if(index < 0 || index >= getNumTEs())
+ {
+ return ;
+ }
+ mTEImages[index] = new_image ;
+}
+
+S32 LLViewerObject::setTETexture(const U8 te, const LLUUID& uuid)
+{
+ // Invalid host == get from the agent's sim
+ return setTETextureCore(te, uuid, LLHost::invalid);
+}
+
+
+S32 LLViewerObject::setTEColor(const U8 te, const LLColor3& color)
+{
+ return setTEColor(te, LLColor4(color));
+}
+
+S32 LLViewerObject::setTEColor(const U8 te, const LLColor4& color)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (color != tep->getColor())
+ {
+ retval = LLPrimitive::setTEColor(te, color);
+ if (mDrawable.notNull() && retval)
+ {
+ // These should only happen on updates which are not the initial update.
+ dirtyMesh();
+ }
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEBumpmap(const U8 te, const U8 bump)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (bump != tep->getBumpmap())
+ {
+ retval = LLPrimitive::setTEBumpmap(te, bump);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markTextured(mDrawable);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, TRUE);
+ }
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTETexGen(const U8 te, const U8 texgen)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (texgen != tep->getTexGen())
+ {
+ retval = LLPrimitive::setTETexGen(te, texgen);
+ setChanged(TEXTURE);
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEMediaTexGen(const U8 te, const U8 media)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (media != tep->getMediaTexGen())
+ {
+ retval = LLPrimitive::setTEMediaTexGen(te, media);
+ setChanged(TEXTURE);
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEShiny(const U8 te, const U8 shiny)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (shiny != tep->getShiny())
+ {
+ retval = LLPrimitive::setTEShiny(te, shiny);
+ setChanged(TEXTURE);
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEFullbright(const U8 te, const U8 fullbright)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (fullbright != tep->getFullbright())
+ {
+ retval = LLPrimitive::setTEFullbright(te, fullbright);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+ return retval;
+}
+
+
+S32 LLViewerObject::setTEMediaFlags(const U8 te, const U8 media_flags)
+{
+ // this might need work for media type
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (media_flags != tep->getMediaFlags())
+ {
+ retval = LLPrimitive::setTEMediaFlags(te, media_flags);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD, TRUE);
+ gPipeline.markTextured(mDrawable);
+ // JC - probably only need this if changes texture coords
+ //gPipeline.markRebuild(mDrawable);
+ }
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEGlow(const U8 te, const F32 glow)
+{
+ S32 retval = 0;
+ const LLTextureEntry *tep = getTE(te);
+ if (!tep)
+ {
+ llwarns << "No texture entry for te " << (S32)te << ", object " << mID << llendl;
+ }
+ else if (glow != tep->getGlow())
+ {
+ retval = LLPrimitive::setTEGlow(te, glow);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markTextured(mDrawable);
+ }
+ }
+ return retval;
+}
+
+
+S32 LLViewerObject::setTEScale(const U8 te, const F32 s, const F32 t)
+{
+ S32 retval = 0;
+ retval = LLPrimitive::setTEScale(te, s, t);
+ setChanged(TEXTURE);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEScaleS(const U8 te, const F32 s)
+{
+ S32 retval = LLPrimitive::setTEScaleS(te, s);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+
+ return retval;
+}
+
+S32 LLViewerObject::setTEScaleT(const U8 te, const F32 t)
+{
+ S32 retval = LLPrimitive::setTEScaleT(te, t);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+
+ return retval;
+}
+
+S32 LLViewerObject::setTEOffset(const U8 te, const F32 s, const F32 t)
+{
+ S32 retval = LLPrimitive::setTEOffset(te, s, t);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+ return retval;
+}
+
+S32 LLViewerObject::setTEOffsetS(const U8 te, const F32 s)
+{
+ S32 retval = LLPrimitive::setTEOffsetS(te, s);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+
+ return retval;
+}
+
+S32 LLViewerObject::setTEOffsetT(const U8 te, const F32 t)
+{
+ S32 retval = LLPrimitive::setTEOffsetT(te, t);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+
+ return retval;
+}
+
+S32 LLViewerObject::setTERotation(const U8 te, const F32 r)
+{
+ S32 retval = LLPrimitive::setTERotation(te, r);
+ if (mDrawable.notNull() && retval)
+ {
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_TCOORD);
+ }
+ return retval;
+}
+
+
+LLViewerTexture *LLViewerObject::getTEImage(const U8 face) const
+{
+// llassert(mTEImages);
+
+ if (face < getNumTEs())
+ {
+ LLViewerTexture* image = mTEImages[face];
+ if (image)
+ {
+ return image;
+ }
+ else
+ {
+ return (LLViewerTexture*)(LLViewerFetchedTexture::sDefaultImagep);
+ }
+ }
+
+ llerrs << llformat("Requested Image from invalid face: %d/%d",face,getNumTEs()) << llendl;
+
+ return NULL;
+}
+
+
+void LLViewerObject::fitFaceTexture(const U8 face)
+{
+ llinfos << "fitFaceTexture not implemented" << llendl;
+}
+
+
+LLBBox LLViewerObject::getBoundingBoxAgent() const
+{
+ LLVector3 position_agent;
+ LLQuaternion rot;
+ LLViewerObject* avatar_parent = NULL;
+ LLViewerObject* root_edit = (LLViewerObject*)getRootEdit();
+ if (root_edit)
+ {
+ avatar_parent = (LLViewerObject*)root_edit->getParent();
+ }
+
+ if (avatar_parent && avatar_parent->isAvatar() &&
+ root_edit && root_edit->mDrawable.notNull() && root_edit->mDrawable->getXform()->getParent())
+ {
+ LLXform* parent_xform = root_edit->mDrawable->getXform()->getParent();
+ position_agent = (getPositionEdit() * parent_xform->getWorldRotation()) + parent_xform->getWorldPosition();
+ rot = getRotationEdit() * parent_xform->getWorldRotation();
+ }
+ else
+ {
+ position_agent = getPositionAgent();
+ rot = getRotationRegion();
+ }
+
+ return LLBBox( position_agent, rot, getScale() * -0.5f, getScale() * 0.5f );
+}
+
+U32 LLViewerObject::getNumVertices() const
+{
+ U32 num_vertices = 0;
+ if (mDrawable.notNull())
+ {
+ S32 i, num_faces;
+ num_faces = mDrawable->getNumFaces();
+ for (i = 0; i < num_faces; i++)
+ {
+ num_vertices += mDrawable->getFace(i)->getGeomCount();
+ }
+ }
+ return num_vertices;
+}
+
+U32 LLViewerObject::getNumIndices() const
+{
+ U32 num_indices = 0;
+ if (mDrawable.notNull())
+ {
+ S32 i, num_faces;
+ num_faces = mDrawable->getNumFaces();
+ for (i = 0; i < num_faces; i++)
+ {
+ num_indices += mDrawable->getFace(i)->getIndicesCount();
+ }
+ }
+ return num_indices;
+}
+
+// Find the number of instances of this object's inventory that are of the given type
+S32 LLViewerObject::countInventoryContents(LLAssetType::EType type)
+{
+ S32 count = 0;
+ if( mInventory )
+ {
+ LLInventoryObject::object_list_t::const_iterator it = mInventory->begin();
+ LLInventoryObject::object_list_t::const_iterator end = mInventory->end();
+ for( ; it != end ; ++it )
+ {
+ if( (*it)->getType() == type )
+ {
+ ++count;
+ }
+ }
+ }
+ return count;
+}
+
+
+void LLViewerObject::setCanSelect(BOOL canSelect)
+{
+ mbCanSelect = canSelect;
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ child->mbCanSelect = canSelect;
+ }
+}
+
+void LLViewerObject::setDebugText(const std::string &utf8text)
+{
+ if (utf8text.empty() && !mText)
+ {
+ return;
+ }
+
+ if (!mText)
+ {
+ mText = (LLHUDText *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_TEXT);
+ mText->setFont(LLFontGL::getFontSansSerif());
+ mText->setVertAlignment(LLHUDText::ALIGN_VERT_TOP);
+ mText->setMaxLines(-1);
+ mText->setSourceObject(this);
+ mText->setOnHUDAttachment(isHUDAttachment());
+ }
+ mText->setColor(LLColor4::white);
+ mText->setString(utf8text);
+ mText->setZCompare(FALSE);
+ mText->setDoFade(FALSE);
+ updateText();
+}
+
+void LLViewerObject::setIcon(LLViewerTexture* icon_image)
+{
+ if (!mIcon)
+ {
+ mIcon = (LLHUDIcon *)LLHUDObject::addHUDObject(LLHUDObject::LL_HUD_ICON);
+ mIcon->setSourceObject(this);
+ mIcon->setImage(icon_image);
+ // *TODO: make this user configurable
+ mIcon->setScale(0.03f);
+ }
+ else
+ {
+ mIcon->restartLifeTimer();
+ }
+}
+
+void LLViewerObject::clearIcon()
+{
+ if (mIcon)
+ {
+ mIcon = NULL;
+ }
+}
+
+LLViewerObject* LLViewerObject::getSubParent()
+{
+ if (isJointChild())
+ {
+ return this;
+ }
+ return (LLViewerObject*) getParent();
+}
+
+const LLViewerObject* LLViewerObject::getSubParent() const
+{
+ if (isJointChild())
+ {
+ return this;
+ }
+ return (const LLViewerObject*) getParent();
+}
+
+BOOL LLViewerObject::isOnMap()
+{
+ return mOnMap;
+}
+
+
+void LLViewerObject::updateText()
+{
+ if (!isDead())
+ {
+ if (mText.notNull())
+ {
+ LLVector3 up_offset(0,0,0);
+ up_offset.mV[2] = getScale().mV[VZ]*0.6f;
+
+ if (mDrawable.notNull())
+ {
+ mText->setPositionAgent(getRenderPosition() + up_offset);
+ }
+ else
+ {
+ mText->setPositionAgent(getPositionAgent() + up_offset);
+ }
+ }
+ }
+}
+
+LLVOAvatar* LLViewerObject::asAvatar()
+{
+ return NULL;
+}
+
+BOOL LLViewerObject::isParticleSource() const
+{
+ return !mPartSourcep.isNull() && !mPartSourcep->isDead();
+}
+
+void LLViewerObject::setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id)
+{
+ if (mPartSourcep)
+ {
+ deleteParticleSource();
+ }
+
+ LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::createPSS(this, particle_parameters);
+ mPartSourcep = pss;
+
+ if (mPartSourcep)
+ {
+ mPartSourcep->setOwnerUUID(owner_id);
+
+ if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
+ {
+ LLViewerTexture* image;
+ if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
+ {
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.tga");
+ }
+ else
+ {
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
+ }
+ mPartSourcep->setImage(image);
+ }
+ }
+ LLViewerPartSim::getInstance()->addPartSource(pss);
+}
+
+void LLViewerObject::unpackParticleSource(const S32 block_num, const LLUUID& owner_id)
+{
+ if (!mPartSourcep.isNull() && mPartSourcep->isDead())
+ {
+ mPartSourcep = NULL;
+ }
+ if (mPartSourcep)
+ {
+ // If we've got one already, just update the existing source (or remove it)
+ if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, block_num))
+ {
+ mPartSourcep->setDead();
+ mPartSourcep = NULL;
+ }
+ }
+ else
+ {
+ LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, block_num);
+ //If the owner is muted, don't create the system
+ if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;
+
+ // We need to be able to deal with a particle source that hasn't changed, but still got an update!
+ if (pss)
+ {
+// llinfos << "Making particle system with owner " << owner_id << llendl;
+ pss->setOwnerUUID(owner_id);
+ mPartSourcep = pss;
+ LLViewerPartSim::getInstance()->addPartSource(pss);
+ }
+ }
+ if (mPartSourcep)
+ {
+ if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
+ {
+ LLViewerTexture* image;
+ if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
+ {
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+ }
+ else
+ {
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
+ }
+ mPartSourcep->setImage(image);
+ }
+ }
+}
+
+void LLViewerObject::unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id)
+{
+ if (!mPartSourcep.isNull() && mPartSourcep->isDead())
+ {
+ mPartSourcep = NULL;
+ }
+ if (mPartSourcep)
+ {
+ // If we've got one already, just update the existing source (or remove it)
+ if (!LLViewerPartSourceScript::unpackPSS(this, mPartSourcep, dp))
+ {
+ mPartSourcep->setDead();
+ mPartSourcep = NULL;
+ }
+ }
+ else
+ {
+ LLPointer<LLViewerPartSourceScript> pss = LLViewerPartSourceScript::unpackPSS(this, NULL, dp);
+ //If the owner is muted, don't create the system
+ if(LLMuteList::getInstance()->isMuted(owner_id, LLMute::flagParticles)) return;
+ // We need to be able to deal with a particle source that hasn't changed, but still got an update!
+ if (pss)
+ {
+// llinfos << "Making particle system with owner " << owner_id << llendl;
+ pss->setOwnerUUID(owner_id);
+ mPartSourcep = pss;
+ LLViewerPartSim::getInstance()->addPartSource(pss);
+ }
+ }
+ if (mPartSourcep)
+ {
+ if (mPartSourcep->getImage()->getID() != mPartSourcep->mPartSysData.mPartImageID)
+ {
+ LLViewerTexture* image;
+ if (mPartSourcep->mPartSysData.mPartImageID == LLUUID::null)
+ {
+ image = LLViewerTextureManager::getFetchedTextureFromFile("pixiesmall.j2c");
+ }
+ else
+ {
+ image = LLViewerTextureManager::getFetchedTexture(mPartSourcep->mPartSysData.mPartImageID);
+ }
+ mPartSourcep->setImage(image);
+ }
+ }
+}
+
+void LLViewerObject::deleteParticleSource()
+{
+ if (mPartSourcep.notNull())
+ {
+ mPartSourcep->setDead();
+ mPartSourcep = NULL;
+ }
+}
+
+// virtual
+void LLViewerObject::updateDrawable(BOOL force_damped)
+{
+ if (mDrawable.notNull() &&
+ !mDrawable->isState(LLDrawable::ON_MOVE_LIST) &&
+ isChanged(MOVED))
+ {
+ BOOL damped_motion =
+ !isChanged(SHIFTED) && // not shifted between regions this frame and...
+ ( force_damped || // ...forced into damped motion by application logic or...
+ ( !isSelected() && // ...not selected and...
+ ( mDrawable->isRoot() || // ... is root or ...
+ (getParent() && !((LLViewerObject*)getParent())->isSelected())// ... parent is not selected and ...
+ ) &&
+ getPCode() == LL_PCODE_VOLUME && // ...is a volume object and...
+ getVelocity().isExactlyZero() && // ...is not moving physically and...
+ mDrawable->getGeneration() != -1 // ...was not created this frame.
+ )
+ );
+ gPipeline.markMoved(mDrawable, damped_motion);
+ }
+ clearChanged(SHIFTED);
+}
+
+// virtual, overridden by LLVOVolume
+F32 LLViewerObject::getVObjRadius() const
+{
+ return mDrawable.notNull() ? mDrawable->getRadius() : 0.f;
+}
+
+void LLViewerObject::setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags)
+{
+ if (!gAudiop)
+ {
+ return;
+ }
+
+ if (audio_uuid.isNull())
+ {
+ if (!mAudioSourcep)
+ {
+ return;
+ }
+ if (mAudioSourcep->isLoop() && !mAudioSourcep->hasPendingPreloads())
+ {
+ // We don't clear the sound if it's a loop, it'll go away on its own.
+ // At least, this appears to be how the scripts work.
+ // The attached sound ID is set to NULL to avoid it playing back when the
+ // object rezzes in on non-looping sounds.
+ //llinfos << "Clearing attached sound " << mAudioSourcep->getCurrentData()->getID() << llendl;
+ gAudiop->cleanupAudioSource(mAudioSourcep);
+ mAudioSourcep = NULL;
+ }
+ else if (flags & LL_SOUND_FLAG_STOP)
+ {
+ // Just shut off the sound
+ mAudioSourcep->play(LLUUID::null);
+ }
+ return;
+ }
+ if (flags & LL_SOUND_FLAG_LOOP
+ && mAudioSourcep && mAudioSourcep->isLoop() && mAudioSourcep->getCurrentData()
+ && mAudioSourcep->getCurrentData()->getID() == audio_uuid)
+ {
+ //llinfos << "Already playing this sound on a loop, ignoring" << llendl;
+ return;
+ }
+
+ // don't clean up before previous sound is done. Solves: SL-33486
+ if ( mAudioSourcep && mAudioSourcep->isDone() )
+ {
+ gAudiop->cleanupAudioSource(mAudioSourcep);
+ mAudioSourcep = NULL;
+ }
+
+ if (mAudioSourcep && mAudioSourcep->isMuted() &&
+ mAudioSourcep->getCurrentData() && mAudioSourcep->getCurrentData()->getID() == audio_uuid)
+ {
+ //llinfos << "Already having this sound as muted sound, ignoring" << llendl;
+ return;
+ }
+
+ getAudioSource(owner_id);
+
+ if (mAudioSourcep)
+ {
+ BOOL queue = flags & LL_SOUND_FLAG_QUEUE;
+ mAudioGain = gain;
+ mAudioSourcep->setGain(gain);
+ mAudioSourcep->setLoop(flags & LL_SOUND_FLAG_LOOP);
+ mAudioSourcep->setSyncMaster(flags & LL_SOUND_FLAG_SYNC_MASTER);
+ mAudioSourcep->setSyncSlave(flags & LL_SOUND_FLAG_SYNC_SLAVE);
+ mAudioSourcep->setQueueSounds(queue);
+ if(!queue) // stop any current sound first to avoid "farts of doom" (SL-1541) -MG
+ {
+ mAudioSourcep->play(LLUUID::null);
+ }
+
+ // Play this sound if region maturity permits
+ if( gAgent.canAccessMaturityAtGlobal(this->getPositionGlobal()) )
+ {
+ //llinfos << "Playing attached sound " << audio_uuid << llendl;
+ mAudioSourcep->play(audio_uuid);
+ }
+ }
+}
+
+LLAudioSource *LLViewerObject::getAudioSource(const LLUUID& owner_id)
+{
+ if (!mAudioSourcep)
+ {
+ // Arbitrary low gain for a sound that's not playing.
+ // This is used for sound preloads, for example.
+ LLAudioSourceVO *asvop = new LLAudioSourceVO(mID, owner_id, 0.01f, this);
+
+ mAudioSourcep = asvop;
+ if(gAudiop) gAudiop->addAudioSource(asvop);
+ }
+
+ return mAudioSourcep;
+}
+
+void LLViewerObject::adjustAudioGain(const F32 gain)
+{
+ if (!gAudiop)
+ {
+ return;
+ }
+ if (mAudioSourcep)
+ {
+ mAudioGain = gain;
+ mAudioSourcep->setGain(mAudioGain);
+ }
+}
+
+//----------------------------------------------------------------------------
+
+bool LLViewerObject::unpackParameterEntry(U16 param_type, LLDataPacker *dp)
+{
+ ExtraParameter* param = getExtraParameterEntryCreate(param_type);
+ if (param)
+ {
+ param->data->unpack(*dp);
+ param->in_use = TRUE;
+ parameterChanged(param_type, param->data, TRUE, false);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+LLViewerObject::ExtraParameter* LLViewerObject::createNewParameterEntry(U16 param_type)
+{
+ LLNetworkData* new_block = NULL;
+ switch (param_type)
+ {
+ case LLNetworkData::PARAMS_FLEXIBLE:
+ {
+ new_block = new LLFlexibleObjectData();
+ break;
+ }
+ case LLNetworkData::PARAMS_LIGHT:
+ {
+ new_block = new LLLightParams();
+ break;
+ }
+ case LLNetworkData::PARAMS_SCULPT:
+ {
+ new_block = new LLSculptParams();
+ break;
+ }
+ case LLNetworkData::PARAMS_LIGHT_IMAGE:
+ {
+ new_block = new LLLightImageParams();
+ break;
+ }
+ default:
+ {
+ llinfos << "Unknown param type." << llendl;
+ break;
+ }
+ };
+
+ if (new_block)
+ {
+ ExtraParameter* new_entry = new ExtraParameter;
+ new_entry->data = new_block;
+ new_entry->in_use = false; // not in use yet
+ mExtraParameterList[param_type] = new_entry;
+ return new_entry;
+ }
+ return NULL;
+}
+
+LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntry(U16 param_type) const
+{
+ std::map<U16, ExtraParameter*>::const_iterator itor = mExtraParameterList.find(param_type);
+ if (itor != mExtraParameterList.end())
+ {
+ return itor->second;
+ }
+ return NULL;
+}
+
+LLViewerObject::ExtraParameter* LLViewerObject::getExtraParameterEntryCreate(U16 param_type)
+{
+ ExtraParameter* param = getExtraParameterEntry(param_type);
+ if (!param)
+ {
+ param = createNewParameterEntry(param_type);
+ }
+ return param;
+}
+
+LLNetworkData* LLViewerObject::getParameterEntry(U16 param_type) const
+{
+ ExtraParameter* param = getExtraParameterEntry(param_type);
+ if (param)
+ {
+ return param->data;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+BOOL LLViewerObject::getParameterEntryInUse(U16 param_type) const
+{
+ ExtraParameter* param = getExtraParameterEntry(param_type);
+ if (param)
+ {
+ return param->in_use;
+ }
+ else
+ {
+ return FALSE;
+ }
+}
+
+bool LLViewerObject::setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin)
+{
+ ExtraParameter* param = getExtraParameterEntryCreate(param_type);
+ if (param)
+ {
+ if (param->in_use && new_value == *(param->data))
+ {
+ return false;
+ }
+ param->in_use = true;
+ param->data->copy(new_value);
+ parameterChanged(param_type, param->data, TRUE, local_origin);
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+// Assumed to be called locally
+// If in_use is TRUE, will crate a new extra parameter if none exists.
+// Should always return true.
+bool LLViewerObject::setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin)
+{
+ ExtraParameter* param = getExtraParameterEntryCreate(param_type);
+ if (param && param->in_use != in_use)
+ {
+ param->in_use = in_use;
+ parameterChanged(param_type, param->data, in_use, local_origin);
+ return true;
+ }
+ return false;
+}
+
+void LLViewerObject::parameterChanged(U16 param_type, bool local_origin)
+{
+ ExtraParameter* param = getExtraParameterEntry(param_type);
+ if (param)
+ {
+ parameterChanged(param_type, param->data, param->in_use, local_origin);
+ }
+}
+
+void LLViewerObject::parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin)
+{
+ if (local_origin)
+ {
+ LLViewerRegion* regionp = getRegion();
+ if(!regionp) return;
+
+ // Change happened on the viewer. Send the change up
+ U8 tmp[MAX_OBJECT_PARAMS_SIZE];
+ LLDataPackerBinaryBuffer dpb(tmp, MAX_OBJECT_PARAMS_SIZE);
+ if (data->pack(dpb))
+ {
+ U32 datasize = (U32)dpb.getCurrentSize();
+
+ LLMessageSystem* msg = gMessageSystem;
+ msg->newMessageFast(_PREHASH_ObjectExtraParams);
+ msg->nextBlockFast(_PREHASH_AgentData);
+ msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ msg->nextBlockFast(_PREHASH_ObjectData);
+ msg->addU32Fast(_PREHASH_ObjectLocalID, mLocalID );
+
+ msg->addU16Fast(_PREHASH_ParamType, param_type);
+ msg->addBOOLFast(_PREHASH_ParamInUse, in_use);
+
+ msg->addU32Fast(_PREHASH_ParamSize, datasize);
+ msg->addBinaryDataFast(_PREHASH_ParamData, tmp, datasize);
+
+ msg->sendReliable( regionp->getHost() );
+ }
+ else
+ {
+ llwarns << "Failed to send object extra parameters: " << param_type << llendl;
+ }
+ }
+}
+
+void LLViewerObject::setDrawableState(U32 state, BOOL recursive)
+{
+ if (mDrawable)
+ {
+ mDrawable->setState(state);
+ }
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ child->setDrawableState(state, recursive);
+ }
+ }
+}
+
+void LLViewerObject::clearDrawableState(U32 state, BOOL recursive)
+{
+ if (mDrawable)
+ {
+ mDrawable->clearState(state);
+ }
+ if (recursive)
+ {
+ for (child_list_t::iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* child = *iter;
+ child->clearDrawableState(state, recursive);
+ }
+ }
+}
+
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+// RN: these functions assume a 2-level hierarchy
+//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
+
+// Owned by anyone?
+BOOL LLViewerObject::permAnyOwner() const
+{
+ if (isRootEdit())
+ {
+ return ((mFlags & FLAGS_OBJECT_ANY_OWNER) != 0);
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permAnyOwner();
+ }
+}
+// Owned by this viewer?
+BOOL LLViewerObject::permYouOwner() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_YOU_OWNER) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permYouOwner();
+ }
+}
+
+// Owned by a group?
+BOOL LLViewerObject::permGroupOwner() const
+{
+ if (isRootEdit())
+ {
+ return ((mFlags & FLAGS_OBJECT_GROUP_OWNED) != 0);
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permGroupOwner();
+ }
+}
+
+// Can the owner edit
+BOOL LLViewerObject::permOwnerModify() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_OWNER_MODIFY) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permOwnerModify();
+ }
+}
+
+// Can edit
+BOOL LLViewerObject::permModify() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_MODIFY) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permModify();
+ }
+}
+
+// Can copy
+BOOL LLViewerObject::permCopy() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_COPY) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permCopy();
+ }
+}
+
+// Can move
+BOOL LLViewerObject::permMove() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_MOVE) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permMove();
+ }
+}
+
+// Can be transferred
+BOOL LLViewerObject::permTransfer() const
+{
+ if (isRootEdit())
+ {
+#ifdef HACKED_GODLIKE_VIEWER
+ return TRUE;
+#else
+# ifdef TOGGLE_HACKED_GODLIKE_VIEWER
+ if (!LLGridManager::getInstance()->isInProductionGrid()
+ && (gAgent.getGodLevel() >= GOD_MAINTENANCE))
+ {
+ return TRUE;
+ }
+# endif
+ return ((mFlags & FLAGS_OBJECT_TRANSFER) != 0);
+#endif
+ }
+ else
+ {
+ return ((LLViewerObject*)getParent())->permTransfer();
+ }
+}
+
+// Can only open objects that you own, or that someone has
+// given you modify rights to. JC
+BOOL LLViewerObject::allowOpen() const
+{
+ return !flagInventoryEmpty() && (permYouOwner() || permModify());
+}
+
+LLViewerObject::LLInventoryCallbackInfo::~LLInventoryCallbackInfo()
+{
+ if (mListener)
+ {
+ mListener->clearVOInventoryListener();
+ }
+}
+
+void LLViewerObject::updateVolume(const LLVolumeParams& volume_params)
+{
+ if (setVolume(volume_params, 1)) // *FIX: magic number, ack!
+ {
+ // Transmit the update to the simulator
+ sendShapeUpdate();
+ markForUpdate(TRUE);
+ }
+}
+
+void LLViewerObject::markForUpdate(BOOL priority)
+{
+ if (mDrawable.notNull())
+ {
+ gPipeline.markTextured(mDrawable);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_GEOMETRY, priority);
+ }
+}
+
+bool LLViewerObject::getIncludeInSearch() const
+{
+ return ((mFlags & FLAGS_INCLUDE_IN_SEARCH) != 0);
+}
+
+void LLViewerObject::setIncludeInSearch(bool include_in_search)
+{
+ if (include_in_search)
+ {
+ mFlags |= FLAGS_INCLUDE_IN_SEARCH;
+ }
+ else
+ {
+ mFlags &= ~FLAGS_INCLUDE_IN_SEARCH;
+ }
+}
+
+void LLViewerObject::setRegion(LLViewerRegion *regionp)
+{
+ if (!regionp)
+ {
+ llwarns << "viewer object set region to NULL" << llendl;
+ }
+
+ mLatestRecvPacketID = 0;
+ mRegionp = regionp;
+
+ for (child_list_t::iterator i = mChildList.begin(); i != mChildList.end(); ++i)
+ {
+ LLViewerObject* child = *i;
+ child->setRegion(regionp);
+ }
+
+ setChanged(MOVED | SILHOUETTE);
+ updateDrawable(FALSE);
+}
+
+// virtual
+void LLViewerObject::updateRegion(LLViewerRegion *regionp)
+{
+// if (regionp)
+// {
+// F64 now = LLFrameTimer::getElapsedSeconds();
+// llinfos << "Updating to region " << regionp->getName()
+// << ", ms since last update message: " << (F32)((now - mLastMessageUpdateSecs) * 1000.0)
+// << ", ms since last interpolation: " << (F32)((now - mLastInterpUpdateSecs) * 1000.0)
+// << llendl;
+// }
+}
+
+
+bool LLViewerObject::specialHoverCursor() const
+{
+ return (mFlags & FLAGS_USE_PHYSICS)
+ || (mFlags & FLAGS_HANDLE_TOUCH)
+ || (mClickAction != 0);
+}
+
+void LLViewerObject::updateFlags(BOOL physics_changed)
+{
+ LLViewerRegion* regionp = getRegion();
+ if(!regionp) return;
+ gMessageSystem->newMessage("ObjectFlagUpdate");
+ gMessageSystem->nextBlockFast(_PREHASH_AgentData);
+ gMessageSystem->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
+ gMessageSystem->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
+ gMessageSystem->addU32Fast(_PREHASH_ObjectLocalID, getLocalID() );
+ gMessageSystem->addBOOLFast(_PREHASH_UsePhysics, usePhysics() );
+ gMessageSystem->addBOOL("IsTemporary", flagTemporaryOnRez() );
+ gMessageSystem->addBOOL("IsPhantom", flagPhantom() );
+ gMessageSystem->addBOOL("CastsShadows", flagCastShadows() );
+ if (physics_changed)
+ {
+ gMessageSystem->nextBlock("ExtraPhysics");
+ gMessageSystem->addU8("PhysicsShapeType", getPhysicsShapeType() );
+ gMessageSystem->addF32("Density", getPhysicsDensity() );
+ gMessageSystem->addF32("Friction", getPhysicsFriction() );
+ gMessageSystem->addF32("Restitution", getPhysicsRestitution() );
+ gMessageSystem->addF32("GravityMultiplier", getPhysicsGravity() );
+ }
+ gMessageSystem->sendReliable( regionp->getHost() );
+}
+
+BOOL LLViewerObject::setFlags(U32 flags, BOOL state)
+{
+ BOOL setit = FALSE;
+ if (state)
+ {
+ if ((mFlags & flags) != flags)
+ {
+ mFlags |= flags;
+ setit = TRUE;
+ }
+ }
+ else
+ {
+ if ((mFlags & flags) != 0)
+ {
+ mFlags &= ~flags;
+ setit = TRUE;
+ }
+ }
+
+ // BUG: Sometimes viewer physics and simulator physics get
+ // out of sync. To fix this, always send update to simulator.
+// if (setit)
+ {
+ updateFlags();
+ }
+ return setit;
+}
+
+void LLViewerObject::setPhysicsShapeType(U8 type)
+{
+ mPhysicsShapeUnknown = false;
+ mPhysicsShapeType = type;
+ mCostStale = true;
+}
+
+void LLViewerObject::setPhysicsGravity(F32 gravity)
+{
+ mPhysicsGravity = gravity;
+}
+
+void LLViewerObject::setPhysicsFriction(F32 friction)
+{
+ mPhysicsFriction = friction;
+}
+
+void LLViewerObject::setPhysicsDensity(F32 density)
+{
+ mPhysicsDensity = density;
+}
+
+void LLViewerObject::setPhysicsRestitution(F32 restitution)
+{
+ mPhysicsRestitution = restitution;
+}
+
+U8 LLViewerObject::getPhysicsShapeType() const
+{
+ if (mPhysicsShapeUnknown)
+ {
+ mPhysicsShapeUnknown = false;
+ gObjectList.updatePhysicsFlags(this);
+ }
+
+ return mPhysicsShapeType;
+}
+
+void LLViewerObject::applyAngularVelocity(F32 dt)
+{
+ //do target omega here
+ mRotTime += dt;
+ LLVector3 ang_vel = getAngularVelocity();
+ F32 omega = ang_vel.magVecSquared();
+ F32 angle = 0.0f;
+ LLQuaternion dQ;
+ if (omega > 0.00001f)
+ {
+ omega = sqrt(omega);
+ angle = omega * dt;
+
+ ang_vel *= 1.f/omega;
+
+ dQ.setQuat(angle, ang_vel);
+
+ setRotation(getRotation()*dQ);
+ setChanged(MOVED | SILHOUETTE);
+ }
+}
+
+void LLViewerObject::resetRot()
+{
+ mRotTime = 0.0f;
+}
+
+U32 LLViewerObject::getPartitionType() const
+{
+ return LLViewerRegion::PARTITION_NONE;
+}
+
+void LLViewerObject::dirtySpatialGroup(BOOL priority) const
+{
+ if (mDrawable)
+ {
+ LLSpatialGroup* group = mDrawable->getSpatialGroup();
+ if (group)
+ {
+ group->dirtyGeom();
+ gPipeline.markRebuild(group, priority);
+ }
+ }
+}
+
+void LLViewerObject::dirtyMesh()
+{
+ if (mDrawable)
+ {
+ LLSpatialGroup* group = mDrawable->getSpatialGroup();
+ if (group)
+ {
+ group->dirtyMesh();
+ }
+ }
+}
+
+F32 LLAlphaObject::getPartSize(S32 idx)
+{
+ return 0.f;
+}
+
+// virtual
+void LLStaticViewerObject::updateDrawable(BOOL force_damped)
+{
+ // Force an immediate rebuild on any update
+ if (mDrawable.notNull())
+ {
+ mDrawable->updateXform(TRUE);
+ gPipeline.markRebuild(mDrawable, LLDrawable::REBUILD_ALL, TRUE);
+ }
+ clearChanged(SHIFTED);
+}
+
+void LLViewerObject::saveUnselectedChildrenPosition(std::vector<LLVector3>& positions)
+{
+ if(mChildList.empty() || !positions.empty())
+ {
+ return ;
+ }
+
+ for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* childp = *iter;
+ if (!childp->isSelected() && childp->mDrawable.notNull())
+ {
+ positions.push_back(childp->getPositionEdit());
+ }
+ }
+
+ return ;
+}
+
+void LLViewerObject::saveUnselectedChildrenRotation(std::vector<LLQuaternion>& rotations)
+{
+ if(mChildList.empty())
+ {
+ return ;
+ }
+
+ for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* childp = *iter;
+ if (!childp->isSelected() && childp->mDrawable.notNull())
+ {
+ rotations.push_back(childp->getRotationEdit());
+ }
+ }
+
+ return ;
+}
+
+//counter-rotation
+void LLViewerObject::resetChildrenRotationAndPosition(const std::vector<LLQuaternion>& rotations,
+ const std::vector<LLVector3>& positions)
+{
+ if(mChildList.empty())
+ {
+ return ;
+ }
+
+ S32 index = 0 ;
+ LLQuaternion inv_rotation = ~getRotationEdit() ;
+ LLVector3 offset = getPositionEdit() ;
+ for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* childp = *iter;
+ if (!childp->isSelected() && childp->mDrawable.notNull())
+ {
+ if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
+ {
+ childp->setRotation(rotations[index] * inv_rotation);
+ childp->setPosition((positions[index] - offset) * inv_rotation);
+ LLManip::rebuild(childp);
+ }
+ else //avatar
+ {
+ LLVector3 reset_pos = (positions[index] - offset) * inv_rotation ;
+ LLQuaternion reset_rot = rotations[index] * inv_rotation ;
+
+ ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos);
+ ((LLVOAvatar*)childp)->mDrawable->mXform.setRotation(reset_rot) ;
+
+ ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos, TRUE);
+ ((LLVOAvatar*)childp)->mDrawable->getVObj()->setRotation(reset_rot, TRUE) ;
+
+ LLManip::rebuild(childp);
+ }
+ index++;
+ }
+ }
+
+ return ;
+}
+
+//counter-translation
+void LLViewerObject::resetChildrenPosition(const LLVector3& offset, BOOL simplified)
+{
+ if(mChildList.empty())
+ {
+ return ;
+ }
+
+ LLVector3 child_offset;
+ if(simplified) //translation only, rotation matrix does not change
+ {
+ child_offset = offset * ~getRotation();
+ }
+ else //rotation matrix might change too.
+ {
+ if (isAttachment() && mDrawable.notNull())
+ {
+ LLXform* attachment_point_xform = mDrawable->getXform()->getParent();
+ LLQuaternion parent_rotation = getRotation() * attachment_point_xform->getWorldRotation();
+ child_offset = offset * ~parent_rotation;
+ }
+ else
+ {
+ child_offset = offset * ~getRenderRotation();
+ }
+ }
+
+ for (LLViewerObject::child_list_t::const_iterator iter = mChildList.begin();
+ iter != mChildList.end(); iter++)
+ {
+ LLViewerObject* childp = *iter;
+ if (!childp->isSelected() && childp->mDrawable.notNull())
+ {
+ if (childp->getPCode() != LL_PCODE_LEGACY_AVATAR)
+ {
+ childp->setPosition(childp->getPosition() + child_offset);
+ LLManip::rebuild(childp);
+ }
+ else //avatar
+ {
+ LLVector3 reset_pos = ((LLVOAvatar*)childp)->mDrawable->mXform.getPosition() + child_offset ;
+
+ ((LLVOAvatar*)childp)->mDrawable->mXform.setPosition(reset_pos);
+ ((LLVOAvatar*)childp)->mDrawable->getVObj()->setPosition(reset_pos);
+
+ LLManip::rebuild(childp);
+ }
+ }
+ }
+
+ return ;
+}
+
+const LLUUID &LLViewerObject::getAttachmentItemID() const
+{
+ return mAttachmentItemID;
+}
+
+void LLViewerObject::setAttachmentItemID(const LLUUID &id)
+{
+ mAttachmentItemID = id;
+}
+
+EObjectUpdateType LLViewerObject::getLastUpdateType() const
+{
+ return mLastUpdateType;
+}
+
+void LLViewerObject::setLastUpdateType(EObjectUpdateType last_update_type)
+{
+ mLastUpdateType = last_update_type;
+}
+
+BOOL LLViewerObject::getLastUpdateCached() const
+{
+ return mLastUpdateCached;
+}
+
+void LLViewerObject::setLastUpdateCached(BOOL last_update_cached)
+{
+ mLastUpdateCached = last_update_cached;
+}
+
+const LLUUID &LLViewerObject::extractAttachmentItemID()
+{
+ LLUUID item_id = LLUUID::null;
+ LLNameValue* item_id_nv = getNVPair("AttachItemID");
+ if( item_id_nv )
+ {
+ const char* s = item_id_nv->getString();
+ if( s )
+ {
+ item_id.set(s);
+ }
+ }
+ setAttachmentItemID(item_id);
+ return getAttachmentItemID();
+}
+
+//virtual
+LLVOAvatar* LLViewerObject::getAvatar() const
+{
+ if (isAttachment())
+ {
+ LLViewerObject* vobj = (LLViewerObject*) getParent();
+
+ while (vobj && !vobj->asAvatar())
+ {
+ vobj = (LLViewerObject*) vobj->getParent();
+ }
+
+ return (LLVOAvatar*) vobj;
+ }
+
+ return NULL;
+}
+
+
+class ObjectPhysicsProperties : public LLHTTPNode
+{
+public:
+ virtual void post(
+ ResponsePtr responder,
+ const LLSD& context,
+ const LLSD& input) const
+ {
+ LLSD object_data = input["body"]["ObjectData"];
+ S32 num_entries = object_data.size();
+
+ for ( S32 i = 0; i < num_entries; i++ )
+ {
+ LLSD& curr_object_data = object_data[i];
+ U32 local_id = curr_object_data["LocalID"].asInteger();
+
+ // Iterate through nodes at end, since it can be on both the regular AND hover list
+ struct f : public LLSelectedNodeFunctor
+ {
+ U32 mID;
+ f(const U32& id) : mID(id) {}
+ virtual bool apply(LLSelectNode* node)
+ {
+ return (node->getObject() && node->getObject()->mLocalID == mID );
+ }
+ } func(local_id);
+
+ LLSelectNode* node = LLSelectMgr::getInstance()->getSelection()->getFirstNode(&func);
+
+ if (node)
+ {
+ // The LLSD message builder doesn't know how to handle U8, so we need to send as S8 and cast
+ U8 type = (U8)curr_object_data["PhysicsShapeType"].asInteger();
+ F32 density = (F32)curr_object_data["Density"].asReal();
+ F32 friction = (F32)curr_object_data["Friction"].asReal();
+ F32 restitution = (F32)curr_object_data["Restitution"].asReal();
+ F32 gravity = (F32)curr_object_data["GravityMultiplier"].asReal();
+
+ node->getObject()->setPhysicsShapeType(type);
+ node->getObject()->setPhysicsGravity(gravity);
+ node->getObject()->setPhysicsFriction(friction);
+ node->getObject()->setPhysicsDensity(density);
+ node->getObject()->setPhysicsRestitution(restitution);
+ }
+ }
+
+ dialog_refresh_all();
+ };
+};
+
+LLHTTPRegistration<ObjectPhysicsProperties>
+ gHTTPRegistrationObjectPhysicsProperties("/message/ObjectPhysicsProperties");
+
+
+void LLViewerObject::updateQuota( const SelectionQuota& quota )
+{
+ //update quotas
+ mSelectionQuota = quota;
+}
diff --git a/indra/newview/llviewerobject.h b/indra/newview/llviewerobject.h index a0ad52df6b..1335c5c319 100644 --- a/indra/newview/llviewerobject.h +++ b/indra/newview/llviewerobject.h @@ -1,825 +1,825 @@ -/** - * @file llviewerobject.h - * @brief Description of LLViewerObject class, which is the base class for most objects in the viewer. - * - * $LicenseInfo:firstyear=2001&license=viewerlgpl$ - * Second Life Viewer Source Code - * Copyright (C) 2010, Linden Research, Inc. - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; - * version 2.1 of the License only. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA - * - * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA - * $/LicenseInfo$ - */ - -#ifndef LL_LLVIEWEROBJECT_H -#define LL_LLVIEWEROBJECT_H - -#include <map> - -#include "llassetstorage.h" -#include "lldarrayptr.h" -#include "llhudicon.h" -#include "llinventory.h" -#include "llrefcount.h" -#include "llmemtype.h" -#include "llprimitive.h" -#include "lluuid.h" -#include "llvoinventorylistener.h" -#include "object_flags.h" -#include "llquaternion.h" -#include "v3dmath.h" -#include "v3math.h" -#include "llvertexbuffer.h" -#include "llaccountingquota.h" - -class LLAgent; // TODO: Get rid of this. -class LLAudioSource; -class LLAudioSourceVO; -class LLBBox; -class LLDataPacker; -class LLColor4; -class LLFrameTimer; -class LLDrawable; -class LLHost; -class LLHUDText; -class LLWorld; -class LLNameValue; -class LLNetMap; -class LLMessageSystem; -class LLPartSysData; -class LLPrimitive; -class LLPipeline; -class LLTextureEntry; -class LLViewerTexture; -class LLViewerInventoryItem; -class LLViewerObject; -class LLViewerPartSourceScript; -class LLViewerRegion; -class LLViewerObjectMedia; -class LLVOInventoryListener; -class LLVOAvatar; - -typedef enum e_object_update_type -{ - OUT_FULL, - OUT_TERSE_IMPROVED, - OUT_FULL_COMPRESSED, - OUT_FULL_CACHED, - OUT_UNKNOWN, -} EObjectUpdateType; - - -// callback typedef for inventory -typedef void (*inventory_callback)(LLViewerObject*, - LLInventoryObject::object_list_t*, - S32 serial_num, - void*); - -// a small struct for keeping track of joints -struct LLVOJointInfo -{ - EHavokJointType mJointType; - LLVector3 mPivot; // parent-frame - // whether the below an axis or anchor (and thus its frame) - // depends on the joint type: - // HINGE ==> axis=parent-frame - // P2P ==> anchor=child-frame - LLVector3 mAxisOrAnchor; -}; - -// for exporting textured materials from SL -struct LLMaterialExportInfo -{ -public: - LLMaterialExportInfo(S32 mat_index, S32 texture_index, LLColor4 color) : - mMaterialIndex(mat_index), mTextureIndex(texture_index), mColor(color) {}; - - S32 mMaterialIndex; - S32 mTextureIndex; - LLColor4 mColor; -}; - -//============================================================================ - -class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate -{ -protected: - ~LLViewerObject(); // use unref() - - // TomY: Provide for a list of extra parameter structures, mapped by structure name - struct ExtraParameter - { - BOOL in_use; - LLNetworkData *data; - }; - std::map<U16, ExtraParameter*> mExtraParameterList; - -public: - typedef std::list<LLPointer<LLViewerObject> > child_list_t; - typedef std::list<LLPointer<LLViewerObject> > vobj_list_t; - - typedef const child_list_t const_child_list_t; - - LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE); - MEM_TYPE_NEW(LLMemType::MTYPE_OBJECT); - - virtual void markDead(); // Mark this object as dead, and clean up its references - BOOL isDead() const {return mDead;} - BOOL isOrphaned() const { return mOrphaned; } - BOOL isParticleSource() const; - - virtual LLVOAvatar* asAvatar(); - - static void initVOClasses(); - static void cleanupVOClasses(); - - void addNVPair(const std::string& data); - BOOL removeNVPair(const std::string& name); - LLNameValue* getNVPair(const std::string& name) const; // null if no name value pair by that name - - // Object create and update functions - virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time); - - // Types of media we can associate - enum { MEDIA_NONE = 0, MEDIA_SET = 1 }; - - // Return codes for processUpdateMessage - enum { - MEDIA_URL_REMOVED = 0x1, - MEDIA_URL_ADDED = 0x2, - MEDIA_URL_UPDATED = 0x4, - MEDIA_FLAGS_CHANGED = 0x8, - INVALID_UPDATE = 0x80000000 - }; - - virtual U32 processUpdateMessage(LLMessageSystem *mesgsys, - void **user_data, - U32 block_num, - const EObjectUpdateType update_type, - LLDataPacker *dp); - - - virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate. - BOOL onActiveList() const {return mOnActiveList;} - void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; } - - virtual BOOL isAttachment() const { return FALSE; } - virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment - virtual BOOL isHUDAttachment() const { return FALSE; } - virtual void updateRadius() {}; - virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius() - - BOOL isJointChild() const { return mJointInfo ? TRUE : FALSE; } - EHavokJointType getJointType() const { return mJointInfo ? mJointInfo->mJointType : HJT_INVALID; } - // for jointed and other parent-relative hacks - LLViewerObject* getSubParent(); - const LLViewerObject* getSubParent() const; - - // Object visiblility and GPW functions - virtual void setPixelAreaAndAngle(LLAgent &agent); // Override to generate accurate apparent angle and area - - virtual U32 getNumVertices() const; - virtual U32 getNumIndices() const; - S32 getNumFaces() const { return mNumFaces; } - - // Graphical stuff for objects - maybe broken out into render class later? - virtual void updateTextures(); - virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object - - virtual LLDrawable* createDrawable(LLPipeline *pipeline); - virtual BOOL updateGeometry(LLDrawable *drawable); - virtual void updateGL(); - virtual void updateFaceSize(S32 idx); - virtual BOOL updateLOD(); - virtual BOOL setDrawableParent(LLDrawable* parentp); - F32 getRotTime() { return mRotTime; } - void resetRot(); - void applyAngularVelocity(F32 dt); - - void setLineWidthForWindowSize(S32 window_width); - - static void increaseArrowLength(); // makes axis arrows for selections longer - static void decreaseArrowLength(); // makes axis arrows for selections shorter - - // Accessor functions - LLViewerRegion* getRegion() const { return mRegionp; } - - BOOL isSelected() const { return mUserSelected; } - virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;} - - const LLUUID &getID() const { return mID; } - U32 getLocalID() const { return mLocalID; } - U32 getCRC() const { return mTotalCRC; } - - virtual BOOL isFlexible() const { return FALSE; } - virtual BOOL isSculpted() const { return FALSE; } - virtual BOOL isMesh() const { return FALSE; } - virtual BOOL hasLightTexture() const { return FALSE; } - - // This method returns true if the object is over land owned by - // the agent, one of its groups, or it encroaches and - // anti-encroachment is enabled - bool isReturnable(); - - /* - // This method will scan through this object, and then query the - // selection manager to see if the local agent probably has the - // ability to modify the object. Since this calls into the - // selection manager, you should avoid calling this method from - // there. - BOOL isProbablyModifiable() const; - */ - - virtual BOOL setParent(LLViewerObject* parent); - virtual void addChild(LLViewerObject *childp); - virtual void removeChild(LLViewerObject *childp); - const_child_list_t& getChildren() const { return mChildList; } - S32 numChildren() const { return mChildList.size(); } - void addThisAndAllChildren(std::vector<LLViewerObject*>& objects); - void addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects); - BOOL isChild(LLViewerObject *childp) const; - BOOL isSeat() const; - - - //detect if given line segment (in agent space) intersects with this viewer object. - //returns TRUE if intersection detected and returns information about intersection - virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end, - S32 face = -1, // which face to check, -1 = ALL_SIDES - BOOL pick_transparent = FALSE, - S32* face_hit = NULL, // which face was hit - LLVector3* intersection = NULL, // return the intersection point - LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point - LLVector3* normal = NULL, // return the surface normal at the intersection point - LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point - ); - - virtual BOOL lineSegmentBoundingBox(const LLVector3& start, const LLVector3& end); - - virtual const LLVector3d getPositionGlobal() const; - virtual const LLVector3 &getPositionRegion() const; - virtual const LLVector3 getPositionEdit() const; - virtual const LLVector3 &getPositionAgent() const; - virtual const LLVector3 getRenderPosition() const; - - virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not - - LLViewerObject* getRootEdit() const; - - const LLQuaternion getRotationRegion() const; - const LLQuaternion getRotationEdit() const; - const LLQuaternion getRenderRotation() const; - virtual const LLMatrix4 getRenderMatrix() const; - - void setPosition(const LLVector3 &pos, BOOL damped = FALSE); - void setPositionGlobal(const LLVector3d &position, BOOL damped = FALSE); - void setPositionRegion(const LLVector3 &position, BOOL damped = FALSE); - void setPositionEdit(const LLVector3 &position, BOOL damped = FALSE); - void setPositionAgent(const LLVector3 &pos_agent, BOOL damped = FALSE); - void setPositionParent(const LLVector3 &pos_parent, BOOL damped = FALSE); - void setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped = FALSE ); - - virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const { return xform->getWorldMatrix(); } - - inline void setRotation(const F32 x, const F32 y, const F32 z, BOOL damped = FALSE); - inline void setRotation(const LLQuaternion& quat, BOOL damped = FALSE); - void sendRotationUpdate() const; - - /*virtual*/ void setNumTEs(const U8 num_tes); - /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry); - /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid); - S32 setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color); - /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color); - /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t); - /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s); - /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t); - /*virtual*/ S32 setTEOffset(const U8 te, const F32 s, const F32 t); - /*virtual*/ S32 setTEOffsetS(const U8 te, const F32 s); - /*virtual*/ S32 setTEOffsetT(const U8 te, const F32 t); - /*virtual*/ S32 setTERotation(const U8 te, const F32 r); - /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump ); - /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen ); - /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics - /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny ); - /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright ); - /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags ); - /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow); - /*virtual*/ BOOL setMaterial(const U8 material); - virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive - void changeTEImage(S32 index, LLViewerTexture* new_image) ; - LLViewerTexture *getTEImage(const U8 te) const; - - void fitFaceTexture(const U8 face); - void sendTEUpdate() const; // Sends packed representation of all texture entry information - - virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE); - - virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL); - virtual U32 getTriangleCount(); - virtual U32 getHighLODTriangleCount(); - - void setObjectCost(F32 cost); - F32 getObjectCost(); - - void setLinksetCost(F32 cost); - F32 getLinksetCost(); - - void setPhysicsCost(F32 cost); - F32 getPhysicsCost(); - - void setLinksetPhysicsCost(F32 cost); - F32 getLinksetPhysicsCost(); - - void sendShapeUpdate(); - - U8 getState() { return mState; } - - F32 getAppAngle() const { return mAppAngle; } - F32 getPixelArea() const { return mPixelArea; } - void setPixelArea(F32 area) { mPixelArea = area; } - F32 getMaxScale() const; - F32 getMidScale() const; - F32 getMinScale() const; - - // Owner id is this object's owner - void setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags); - void adjustAudioGain(const F32 gain); - void clearAttachedSound() { mAudioSourcep = NULL; } - - // Create if necessary - LLAudioSource *getAudioSource(const LLUUID& owner_id); - bool isAudioSource() {return mAudioSourcep != NULL;} - - U8 getMediaType() const; - void setMediaType(U8 media_type); - - std::string getMediaURL() const; - void setMediaURL(const std::string& media_url); - - BOOL getMediaPassedWhitelist() const; - void setMediaPassedWhitelist(BOOL passed); - - void sendMaterialUpdate() const; - - void setCanSelect(BOOL canSelect); - - void setDebugText(const std::string &utf8text); - void setIcon(LLViewerTexture* icon_image); - void clearIcon(); - - void markForUpdate(BOOL priority); - void updateVolume(const LLVolumeParams& volume_params); - virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max); - virtual F32 getBinRadius(); - - LLBBox getBoundingBoxAgent() const; - - void updatePositionCaches() const; // Update the global and region position caches from the object (and parent's) xform. - void updateText(); // update text label position - virtual void updateDrawable(BOOL force_damped); // force updates on static objects - - void setDrawableState(U32 state, BOOL recursive = TRUE); - void clearDrawableState(U32 state, BOOL recursive = TRUE); - - // Called when the drawable shifts - virtual void onShift(const LLVector4a &shift_vector) { } - - ////////////////////////////////////// - // - // Inventory methods - // - - // This function is called when someone is interested in a viewer - // object's inventory. The callback is called as soon as the - // viewer object has the inventory stored locally. - void registerInventoryListener(LLVOInventoryListener* listener, void* user_data); - void removeInventoryListener(LLVOInventoryListener* listener); - BOOL isInventoryPending() { return mInventoryPending; } - void clearInventoryListeners(); - void requestInventory(); - void fetchInventoryFromServer(); - static void processTaskInv(LLMessageSystem* msg, void** user_data); - void removeInventory(const LLUUID& item_id); - - // The updateInventory() call potentially calls into the selection - // manager, so do no call updateInventory() from the selection - // manager until we have better iterators. - void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new); - void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging. - LLInventoryObject* getInventoryObject(const LLUUID& item_id); - void getInventoryContents(LLInventoryObject::object_list_t& objects); - LLInventoryObject* getInventoryRoot(); - LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id); - S16 getInventorySerial() const { return mInventorySerialNum; } - - // These functions does viewer-side only object inventory modifications - void updateViewerInventoryAsset( - const LLViewerInventoryItem* item, - const LLUUID& new_asset); - - // This function will make sure that we refresh the inventory. - void dirtyInventory(); - BOOL isInventoryDirty() { return mInventoryDirty; } - - // save a script, which involves removing the old one, and rezzing - // in the new one. This method should be called with the asset id - // of the new and old script AFTER the bytecode has been saved. - void saveScript(const LLViewerInventoryItem* item, BOOL active, bool is_new); - - // move an inventory item out of the task and into agent - // inventory. This operation is based on messaging. No permissions - // checks are made on the viewer - the server will double check. - void moveInventory(const LLUUID& agent_folder, const LLUUID& item_id); - - // Find the number of instances of this object's inventory that are of the given type - S32 countInventoryContents( LLAssetType::EType type ); - - BOOL permAnyOwner() const; - BOOL permYouOwner() const; - BOOL permGroupOwner() const; - BOOL permOwnerModify() const; - BOOL permModify() const; - BOOL permCopy() const; - BOOL permMove() const; - BOOL permTransfer() const; - inline BOOL usePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); } - inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); } - inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); } - inline BOOL flagTakesMoney() const { return ((mFlags & FLAGS_TAKES_MONEY) != 0); } - inline BOOL flagPhantom() const { return ((mFlags & FLAGS_PHANTOM) != 0); } - inline BOOL flagInventoryEmpty() const { return ((mFlags & FLAGS_INVENTORY_EMPTY) != 0); } - inline BOOL flagCastShadows() const { return ((mFlags & FLAGS_CAST_SHADOWS) != 0); } - inline BOOL flagAllowInventoryAdd() const { return ((mFlags & FLAGS_ALLOW_INVENTORY_DROP) != 0); } - inline BOOL flagTemporary() const { return ((mFlags & FLAGS_TEMPORARY) != 0); } - inline BOOL flagTemporaryOnRez() const { return ((mFlags & FLAGS_TEMPORARY_ON_REZ) != 0); } - inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); } - inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); } - inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); } - inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); } - - U8 getPhysicsShapeType() const; - inline F32 getPhysicsGravity() const { return mPhysicsGravity; } - inline F32 getPhysicsFriction() const { return mPhysicsFriction; } - inline F32 getPhysicsDensity() const { return mPhysicsDensity; } - inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; } - - bool getIncludeInSearch() const; - void setIncludeInSearch(bool include_in_search); - - // Does "open" object menu item apply? - BOOL allowOpen() const; - - void setClickAction(U8 action) { mClickAction = action; } - U8 getClickAction() const { return mClickAction; } - bool specialHoverCursor() const; // does it have a special hover cursor? - - void setRegion(LLViewerRegion *regionp); - virtual void updateRegion(LLViewerRegion *regionp); - - void updateFlags(BOOL physics_changed = FALSE); - BOOL setFlags(U32 flag, BOOL state); - void setPhysicsShapeType(U8 type); - void setPhysicsGravity(F32 gravity); - void setPhysicsFriction(F32 friction); - void setPhysicsDensity(F32 density); - void setPhysicsRestitution(F32 restitution); - - virtual void dump() const; - static U32 getNumZombieObjects() { return sNumZombieObjects; } - - void printNameValuePairs() const; - - virtual S32 getLOD() const { return 3; } - virtual U32 getPartitionType() const; - virtual void dirtySpatialGroup(BOOL priority = FALSE) const; - virtual void dirtyMesh(); - - virtual LLNetworkData* getParameterEntry(U16 param_type) const; - virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin); - virtual BOOL getParameterEntryInUse(U16 param_type) const; - virtual bool setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin); - // Called when a parameter is changed - virtual void parameterChanged(U16 param_type, bool local_origin); - virtual void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin); - - friend class LLViewerObjectList; - friend class LLViewerMediaList; - -public: - //counter-translation - void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ; - //counter-rotation - void resetChildrenRotationAndPosition(const std::vector<LLQuaternion>& rotations, - const std::vector<LLVector3>& positions) ; - void saveUnselectedChildrenRotation(std::vector<LLQuaternion>& rotations) ; - void saveUnselectedChildrenPosition(std::vector<LLVector3>& positions) ; - std::vector<LLVector3> mUnselectedChildrenPositions ; - -private: - ExtraParameter* createNewParameterEntry(U16 param_type); - ExtraParameter* getExtraParameterEntry(U16 param_type) const; - ExtraParameter* getExtraParameterEntryCreate(U16 param_type); - bool unpackParameterEntry(U16 param_type, LLDataPacker *dp); - - // This function checks to see if the given media URL has changed its version - // and the update wasn't due to this agent's last action. - U32 checkMediaURL(const std::string &media_url); - - // Motion prediction between updates - void interpolateLinearMotion(const F64 & time, const F32 & dt); - -public: - // - // Viewer-side only types - use the LL_PCODE_APP mask. - // - typedef enum e_vo_types - { - LL_VO_CLOUDS = LL_PCODE_APP | 0x20, - LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30, - LL_VO_WL_SKY = LL_PCODE_APP | 0x40, - LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50, - LL_VO_SKY = LL_PCODE_APP | 0x60, - LL_VO_VOID_WATER = LL_PCODE_APP | 0x70, - LL_VO_WATER = LL_PCODE_APP | 0x80, - LL_VO_GROUND = LL_PCODE_APP | 0x90, - LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0, - LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0, - LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0, - } EVOType; - - typedef enum e_physics_shape_types - { - PHYSICS_SHAPE_PRIM = 0, - PHYSICS_SHAPE_NONE, - PHYSICS_SHAPE_CONVEX_HULL, - } EPhysicsShapeType; - - LLUUID mID; - - // unique within region, not unique across regions - // Local ID = 0 is not used - U32 mLocalID; - - // Last total CRC received from sim, used for caching - U32 mTotalCRC; - - LLPointer<LLViewerTexture> *mTEImages; - - // Selection, picking and rendering variables - U32 mGLName; // GL "name" used by selection code - BOOL mbCanSelect; // true if user can select this object by clicking - - // Grabbed from UPDATE_FLAGS - U32 mFlags; - - // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties - U8 mPhysicsShapeType; - F32 mPhysicsGravity; - F32 mPhysicsFriction; - F32 mPhysicsDensity; - F32 mPhysicsRestitution; - - - // Pipeline classes - LLPointer<LLDrawable> mDrawable; - - // Band-aid to select object after all creation initialization is done - BOOL mCreateSelected; - - // Replace textures with web pages on this object while drawing - BOOL mRenderMedia; - - // In bits - S32 mBestUpdatePrecision; - - // TODO: Make all this stuff private. JC - LLPointer<LLHUDText> mText; - LLPointer<LLHUDIcon> mIcon; - - static BOOL sUseSharedDrawables; - -protected: - // delete an item in the inventory, but don't tell the - // server. This is used internally by remove, update, and - // savescript. - void deleteInventoryItem(const LLUUID& item_id); - - // do the update/caching logic. called by saveScript and - // updateInventory. - void doUpdateInventory(LLPointer<LLViewerInventoryItem>& item, U8 key, bool is_new); - - - static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp); - - BOOL setData(const U8 *datap, const U32 data_size); - - // Hide or show HUD, icon and particles - void hideExtraDisplayItems( BOOL hidden ); - - ////////////////////////// - // - // inventory functionality - // - - static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status); - void loadTaskInvFile(const std::string& filename); - void doInventoryCallback(); - - BOOL isOnMap(); - - void unpackParticleSource(const S32 block_num, const LLUUID& owner_id); - void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id); - void deleteParticleSource(); - void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id); - -public: - void updateQuota( const SelectionQuota& quota ); - const SelectionQuota& getQuota( void ) { return mSelectionQuota; } - -private: - void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string - void deleteTEImages(); // correctly deletes list of images - -protected: - typedef std::map<char *, LLNameValue *> name_value_map_t; - name_value_map_t mNameValuePairs; // Any name-value pairs stored by script - - child_list_t mChildList; - - F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation - F64 mLastMessageUpdateSecs; // Last update from a message from the simulator - TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator - - // extra data sent from the sim...currently only used for tree species info - U8* mData; - - LLPointer<LLViewerPartSourceScript> mPartSourcep; // Particle source associated with this object. - LLAudioSourceVO* mAudioSourcep; - F32 mAudioGain; - - F32 mAppAngle; // Apparent visual arc in degrees - F32 mPixelArea; // Apparent area in pixels - - // This is the object's inventory from the viewer's perspective. - LLInventoryObject::object_list_t* mInventory; - class LLInventoryCallbackInfo - { - public: - ~LLInventoryCallbackInfo(); - LLVOInventoryListener* mListener; - void* mInventoryData; - }; - typedef std::list<LLInventoryCallbackInfo*> callback_list_t; - callback_list_t mInventoryCallbacks; - S16 mInventorySerialNum; - - LLViewerRegion *mRegionp; // Region that this object belongs to. - BOOL mInventoryPending; - BOOL mInventoryDirty; - BOOL mDead; - BOOL mOrphaned; // This is an orphaned child - BOOL mUserSelected; // Cached user select information - BOOL mOnActiveList; - BOOL mOnMap; // On the map. - BOOL mStatic; // Object doesn't move. - S32 mNumFaces; - - F32 mTimeDilation; // Time dilation sent with the object. - F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega) - LLQuaternion mLastRot; // last rotation received from the simulator - - LLVOJointInfo* mJointInfo; - U8 mState; // legacy - LLViewerObjectMedia* mMedia; // NULL if no media associated - U8 mClickAction; - F32 mObjectCost; //resource cost of this object or -1 if unknown - F32 mLinksetCost; - F32 mPhysicsCost; - F32 mLinksetPhysicsCost; - - SelectionQuota mSelectionQuota; - - bool mCostStale; - mutable bool mPhysicsShapeUnknown; - - static U32 sNumZombieObjects; // Objects which are dead, but not deleted - - static BOOL sMapDebug; // Map render mode - static LLColor4 sEditSelectColor; - static LLColor4 sNoEditSelectColor; - static F32 sCurrentPulse; - static BOOL sPulseEnabled; - - static S32 sAxisArrowLength; - - // These two caches are only correct for non-parented objects right now! - mutable LLVector3 mPositionRegion; - mutable LLVector3 mPositionAgent; - - static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; } - static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; } - - static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; } - static void setPingInterpolate(BOOL value) { sPingInterpolate = value; } - -private: - static S32 sNumObjects; - - static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation - static F64 sMaxUpdateInterpolationTime; // For motion interpolation - - static BOOL sVelocityInterpolate; - static BOOL sPingInterpolate; - - //-------------------------------------------------------------------- - // For objects that are attachments - //-------------------------------------------------------------------- -public: - const LLUUID &getAttachmentItemID() const; - void setAttachmentItemID(const LLUUID &id); - const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object - EObjectUpdateType getLastUpdateType() const; - void setLastUpdateType(EObjectUpdateType last_update_type); - BOOL getLastUpdateCached() const; - void setLastUpdateCached(BOOL last_update_cached); - -private: - LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory. - EObjectUpdateType mLastUpdateType; - BOOL mLastUpdateCached; -}; - -/////////////////// -// -// Inlines -// -// - -inline void LLViewerObject::setRotation(const LLQuaternion& quat, BOOL damped) -{ - LLPrimitive::setRotation(quat); - setChanged(ROTATED | SILHOUETTE); - updateDrawable(damped); -} - -inline void LLViewerObject::setRotation(const F32 x, const F32 y, const F32 z, BOOL damped) -{ - LLPrimitive::setRotation(x, y, z); - setChanged(ROTATED | SILHOUETTE); - updateDrawable(damped); -} - -class LLViewerObjectMedia -{ -public: - LLViewerObjectMedia() : mMediaURL(), mPassedWhitelist(FALSE), mMediaType(0) { } - - std::string mMediaURL; // for web pages on surfaces, one per prim - BOOL mPassedWhitelist; // user has OK'd display - U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc. -}; - -// subclass of viewer object that can be added to particle partitions -class LLAlphaObject : public LLViewerObject -{ -public: - LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp) - : LLViewerObject(id,pcode,regionp) - { mDepth = 0.f; } - - virtual F32 getPartSize(S32 idx); - virtual void getGeometry(S32 idx, - LLStrider<LLVector3>& verticesp, - LLStrider<LLVector3>& normalsp, - LLStrider<LLVector2>& texcoordsp, - LLStrider<LLColor4U>& colorsp, - LLStrider<U16>& indicesp) = 0; - - F32 mDepth; -}; - -class LLStaticViewerObject : public LLViewerObject -{ -public: - LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE) - : LLViewerObject(id,pcode,regionp, is_global) - { } - - virtual void updateDrawable(BOOL force_damped); -}; - - -#endif +/**
+ * @file llviewerobject.h
+ * @brief Description of LLViewerObject class, which is the base class for most objects in the viewer.
+ *
+ * $LicenseInfo:firstyear=2001&license=viewerlgpl$
+ * Second Life Viewer Source Code
+ * Copyright (C) 2010, Linden Research, Inc.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation;
+ * version 2.1 of the License only.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
+ *
+ * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
+ * $/LicenseInfo$
+ */
+
+#ifndef LL_LLVIEWEROBJECT_H
+#define LL_LLVIEWEROBJECT_H
+
+#include <map>
+
+#include "llassetstorage.h"
+#include "lldarrayptr.h"
+#include "llhudicon.h"
+#include "llinventory.h"
+#include "llrefcount.h"
+#include "llmemtype.h"
+#include "llprimitive.h"
+#include "lluuid.h"
+#include "llvoinventorylistener.h"
+#include "object_flags.h"
+#include "llquaternion.h"
+#include "v3dmath.h"
+#include "v3math.h"
+#include "llvertexbuffer.h"
+#include "llaccountingquota.h"
+
+class LLAgent; // TODO: Get rid of this.
+class LLAudioSource;
+class LLAudioSourceVO;
+class LLBBox;
+class LLDataPacker;
+class LLColor4;
+class LLFrameTimer;
+class LLDrawable;
+class LLHost;
+class LLHUDText;
+class LLWorld;
+class LLNameValue;
+class LLNetMap;
+class LLMessageSystem;
+class LLPartSysData;
+class LLPrimitive;
+class LLPipeline;
+class LLTextureEntry;
+class LLViewerTexture;
+class LLViewerInventoryItem;
+class LLViewerObject;
+class LLViewerPartSourceScript;
+class LLViewerRegion;
+class LLViewerObjectMedia;
+class LLVOInventoryListener;
+class LLVOAvatar;
+
+typedef enum e_object_update_type
+{
+ OUT_FULL,
+ OUT_TERSE_IMPROVED,
+ OUT_FULL_COMPRESSED,
+ OUT_FULL_CACHED,
+ OUT_UNKNOWN,
+} EObjectUpdateType;
+
+
+// callback typedef for inventory
+typedef void (*inventory_callback)(LLViewerObject*,
+ LLInventoryObject::object_list_t*,
+ S32 serial_num,
+ void*);
+
+// a small struct for keeping track of joints
+struct LLVOJointInfo
+{
+ EHavokJointType mJointType;
+ LLVector3 mPivot; // parent-frame
+ // whether the below an axis or anchor (and thus its frame)
+ // depends on the joint type:
+ // HINGE ==> axis=parent-frame
+ // P2P ==> anchor=child-frame
+ LLVector3 mAxisOrAnchor;
+};
+
+// for exporting textured materials from SL
+struct LLMaterialExportInfo
+{
+public:
+ LLMaterialExportInfo(S32 mat_index, S32 texture_index, LLColor4 color) :
+ mMaterialIndex(mat_index), mTextureIndex(texture_index), mColor(color) {};
+
+ S32 mMaterialIndex;
+ S32 mTextureIndex;
+ LLColor4 mColor;
+};
+
+//============================================================================
+
+class LLViewerObject : public LLPrimitive, public LLRefCount, public LLGLUpdate
+{
+protected:
+ ~LLViewerObject(); // use unref()
+
+ // TomY: Provide for a list of extra parameter structures, mapped by structure name
+ struct ExtraParameter
+ {
+ BOOL in_use;
+ LLNetworkData *data;
+ };
+ std::map<U16, ExtraParameter*> mExtraParameterList;
+
+public:
+ typedef std::list<LLPointer<LLViewerObject> > child_list_t;
+ typedef std::list<LLPointer<LLViewerObject> > vobj_list_t;
+
+ typedef const child_list_t const_child_list_t;
+
+ LLViewerObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp, BOOL is_global = FALSE);
+ MEM_TYPE_NEW(LLMemType::MTYPE_OBJECT);
+
+ virtual void markDead(); // Mark this object as dead, and clean up its references
+ BOOL isDead() const {return mDead;}
+ BOOL isOrphaned() const { return mOrphaned; }
+ BOOL isParticleSource() const;
+
+ virtual LLVOAvatar* asAvatar();
+
+ static void initVOClasses();
+ static void cleanupVOClasses();
+
+ void addNVPair(const std::string& data);
+ BOOL removeNVPair(const std::string& name);
+ LLNameValue* getNVPair(const std::string& name) const; // null if no name value pair by that name
+
+ // Object create and update functions
+ virtual BOOL idleUpdate(LLAgent &agent, LLWorld &world, const F64 &time);
+
+ // Types of media we can associate
+ enum { MEDIA_NONE = 0, MEDIA_SET = 1 };
+
+ // Return codes for processUpdateMessage
+ enum {
+ MEDIA_URL_REMOVED = 0x1,
+ MEDIA_URL_ADDED = 0x2,
+ MEDIA_URL_UPDATED = 0x4,
+ MEDIA_FLAGS_CHANGED = 0x8,
+ INVALID_UPDATE = 0x80000000
+ };
+
+ virtual U32 processUpdateMessage(LLMessageSystem *mesgsys,
+ void **user_data,
+ U32 block_num,
+ const EObjectUpdateType update_type,
+ LLDataPacker *dp);
+
+
+ virtual BOOL isActive() const; // Whether this object needs to do an idleUpdate.
+ BOOL onActiveList() const {return mOnActiveList;}
+ void setOnActiveList(BOOL on_active) { mOnActiveList = on_active; }
+
+ virtual BOOL isAttachment() const { return FALSE; }
+ virtual LLVOAvatar* getAvatar() const; //get the avatar this object is attached to, or NULL if object is not an attachment
+ virtual BOOL isHUDAttachment() const { return FALSE; }
+ virtual void updateRadius() {};
+ virtual F32 getVObjRadius() const; // default implemenation is mDrawable->getRadius()
+
+ BOOL isJointChild() const { return mJointInfo ? TRUE : FALSE; }
+ EHavokJointType getJointType() const { return mJointInfo ? mJointInfo->mJointType : HJT_INVALID; }
+ // for jointed and other parent-relative hacks
+ LLViewerObject* getSubParent();
+ const LLViewerObject* getSubParent() const;
+
+ // Object visiblility and GPW functions
+ virtual void setPixelAreaAndAngle(LLAgent &agent); // Override to generate accurate apparent angle and area
+
+ virtual U32 getNumVertices() const;
+ virtual U32 getNumIndices() const;
+ S32 getNumFaces() const { return mNumFaces; }
+
+ // Graphical stuff for objects - maybe broken out into render class later?
+ virtual void updateTextures();
+ virtual void boostTexturePriority(BOOL boost_children = TRUE); // When you just want to boost priority of this object
+
+ virtual LLDrawable* createDrawable(LLPipeline *pipeline);
+ virtual BOOL updateGeometry(LLDrawable *drawable);
+ virtual void updateGL();
+ virtual void updateFaceSize(S32 idx);
+ virtual BOOL updateLOD();
+ virtual BOOL setDrawableParent(LLDrawable* parentp);
+ F32 getRotTime() { return mRotTime; }
+ void resetRot();
+ void applyAngularVelocity(F32 dt);
+
+ void setLineWidthForWindowSize(S32 window_width);
+
+ static void increaseArrowLength(); // makes axis arrows for selections longer
+ static void decreaseArrowLength(); // makes axis arrows for selections shorter
+
+ // Accessor functions
+ LLViewerRegion* getRegion() const { return mRegionp; }
+
+ BOOL isSelected() const { return mUserSelected; }
+ virtual void setSelected(BOOL sel) { mUserSelected = sel; mRotTime = 0.f;}
+
+ const LLUUID &getID() const { return mID; }
+ U32 getLocalID() const { return mLocalID; }
+ U32 getCRC() const { return mTotalCRC; }
+
+ virtual BOOL isFlexible() const { return FALSE; }
+ virtual BOOL isSculpted() const { return FALSE; }
+ virtual BOOL isMesh() const { return FALSE; }
+ virtual BOOL hasLightTexture() const { return FALSE; }
+
+ // This method returns true if the object is over land owned by
+ // the agent, one of its groups, or it encroaches and
+ // anti-encroachment is enabled
+ bool isReturnable();
+
+ /*
+ // This method will scan through this object, and then query the
+ // selection manager to see if the local agent probably has the
+ // ability to modify the object. Since this calls into the
+ // selection manager, you should avoid calling this method from
+ // there.
+ BOOL isProbablyModifiable() const;
+ */
+
+ virtual BOOL setParent(LLViewerObject* parent);
+ virtual void addChild(LLViewerObject *childp);
+ virtual void removeChild(LLViewerObject *childp);
+ const_child_list_t& getChildren() const { return mChildList; }
+ S32 numChildren() const { return mChildList.size(); }
+ void addThisAndAllChildren(std::vector<LLViewerObject*>& objects);
+ void addThisAndNonJointChildren(std::vector<LLViewerObject*>& objects);
+ BOOL isChild(LLViewerObject *childp) const;
+ BOOL isSeat() const;
+
+
+ //detect if given line segment (in agent space) intersects with this viewer object.
+ //returns TRUE if intersection detected and returns information about intersection
+ virtual BOOL lineSegmentIntersect(const LLVector3& start, const LLVector3& end,
+ S32 face = -1, // which face to check, -1 = ALL_SIDES
+ BOOL pick_transparent = FALSE,
+ S32* face_hit = NULL, // which face was hit
+ LLVector3* intersection = NULL, // return the intersection point
+ LLVector2* tex_coord = NULL, // return the texture coordinates of the intersection point
+ LLVector3* normal = NULL, // return the surface normal at the intersection point
+ LLVector3* bi_normal = NULL // return the surface bi-normal at the intersection point
+ );
+
+ virtual BOOL lineSegmentBoundingBox(const LLVector3& start, const LLVector3& end);
+
+ virtual const LLVector3d getPositionGlobal() const;
+ virtual const LLVector3 &getPositionRegion() const;
+ virtual const LLVector3 getPositionEdit() const;
+ virtual const LLVector3 &getPositionAgent() const;
+ virtual const LLVector3 getRenderPosition() const;
+
+ virtual const LLVector3 getPivotPositionAgent() const; // Usually = to getPositionAgent, unless like flex objects it's not
+
+ LLViewerObject* getRootEdit() const;
+
+ const LLQuaternion getRotationRegion() const;
+ const LLQuaternion getRotationEdit() const;
+ const LLQuaternion getRenderRotation() const;
+ virtual const LLMatrix4 getRenderMatrix() const;
+
+ void setPosition(const LLVector3 &pos, BOOL damped = FALSE);
+ void setPositionGlobal(const LLVector3d &position, BOOL damped = FALSE);
+ void setPositionRegion(const LLVector3 &position, BOOL damped = FALSE);
+ void setPositionEdit(const LLVector3 &position, BOOL damped = FALSE);
+ void setPositionAgent(const LLVector3 &pos_agent, BOOL damped = FALSE);
+ void setPositionParent(const LLVector3 &pos_parent, BOOL damped = FALSE);
+ void setPositionAbsoluteGlobal( const LLVector3d &pos_global, BOOL damped = FALSE );
+
+ virtual const LLMatrix4& getWorldMatrix(LLXformMatrix* xform) const { return xform->getWorldMatrix(); }
+
+ inline void setRotation(const F32 x, const F32 y, const F32 z, BOOL damped = FALSE);
+ inline void setRotation(const LLQuaternion& quat, BOOL damped = FALSE);
+ void sendRotationUpdate() const;
+
+ /*virtual*/ void setNumTEs(const U8 num_tes);
+ /*virtual*/ void setTE(const U8 te, const LLTextureEntry &texture_entry);
+ /*virtual*/ S32 setTETexture(const U8 te, const LLUUID &uuid);
+ S32 setTETextureCore(const U8 te, const LLUUID& uuid, LLHost host);
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor3 &color);
+ /*virtual*/ S32 setTEColor(const U8 te, const LLColor4 &color);
+ /*virtual*/ S32 setTEScale(const U8 te, const F32 s, const F32 t);
+ /*virtual*/ S32 setTEScaleS(const U8 te, const F32 s);
+ /*virtual*/ S32 setTEScaleT(const U8 te, const F32 t);
+ /*virtual*/ S32 setTEOffset(const U8 te, const F32 s, const F32 t);
+ /*virtual*/ S32 setTEOffsetS(const U8 te, const F32 s);
+ /*virtual*/ S32 setTEOffsetT(const U8 te, const F32 t);
+ /*virtual*/ S32 setTERotation(const U8 te, const F32 r);
+ /*virtual*/ S32 setTEBumpmap(const U8 te, const U8 bump );
+ /*virtual*/ S32 setTETexGen(const U8 te, const U8 texgen );
+ /*virtual*/ S32 setTEMediaTexGen(const U8 te, const U8 media ); // *FIXME: this confusingly acts upon a superset of setTETexGen's flags without absorbing its semantics
+ /*virtual*/ S32 setTEShiny(const U8 te, const U8 shiny );
+ /*virtual*/ S32 setTEFullbright(const U8 te, const U8 fullbright );
+ /*virtual*/ S32 setTEMediaFlags(const U8 te, const U8 media_flags );
+ /*virtual*/ S32 setTEGlow(const U8 te, const F32 glow);
+ /*virtual*/ BOOL setMaterial(const U8 material);
+ virtual void setTEImage(const U8 te, LLViewerTexture *imagep); // Not derived from LLPrimitive
+ void changeTEImage(S32 index, LLViewerTexture* new_image) ;
+ LLViewerTexture *getTEImage(const U8 te) const;
+
+ void fitFaceTexture(const U8 face);
+ void sendTEUpdate() const; // Sends packed representation of all texture entry information
+
+ virtual void setScale(const LLVector3 &scale, BOOL damped = FALSE);
+
+ virtual F32 getStreamingCost(S32* bytes = NULL, S32* visible_bytes = NULL);
+ virtual U32 getTriangleCount();
+ virtual U32 getHighLODTriangleCount();
+
+ void setObjectCost(F32 cost);
+ F32 getObjectCost();
+
+ void setLinksetCost(F32 cost);
+ F32 getLinksetCost();
+
+ void setPhysicsCost(F32 cost);
+ F32 getPhysicsCost();
+
+ void setLinksetPhysicsCost(F32 cost);
+ F32 getLinksetPhysicsCost();
+
+ void sendShapeUpdate();
+
+ U8 getState() { return mState; }
+
+ F32 getAppAngle() const { return mAppAngle; }
+ F32 getPixelArea() const { return mPixelArea; }
+ void setPixelArea(F32 area) { mPixelArea = area; }
+ F32 getMaxScale() const;
+ F32 getMidScale() const;
+ F32 getMinScale() const;
+
+ // Owner id is this object's owner
+ void setAttachedSound(const LLUUID &audio_uuid, const LLUUID& owner_id, const F32 gain, const U8 flags);
+ void adjustAudioGain(const F32 gain);
+ void clearAttachedSound() { mAudioSourcep = NULL; }
+
+ // Create if necessary
+ LLAudioSource *getAudioSource(const LLUUID& owner_id);
+ bool isAudioSource() {return mAudioSourcep != NULL;}
+
+ U8 getMediaType() const;
+ void setMediaType(U8 media_type);
+
+ std::string getMediaURL() const;
+ void setMediaURL(const std::string& media_url);
+
+ BOOL getMediaPassedWhitelist() const;
+ void setMediaPassedWhitelist(BOOL passed);
+
+ void sendMaterialUpdate() const;
+
+ void setCanSelect(BOOL canSelect);
+
+ void setDebugText(const std::string &utf8text);
+ void setIcon(LLViewerTexture* icon_image);
+ void clearIcon();
+
+ void markForUpdate(BOOL priority);
+ void updateVolume(const LLVolumeParams& volume_params);
+ virtual void updateSpatialExtents(LLVector4a& min, LLVector4a& max);
+ virtual F32 getBinRadius();
+
+ LLBBox getBoundingBoxAgent() const;
+
+ void updatePositionCaches() const; // Update the global and region position caches from the object (and parent's) xform.
+ void updateText(); // update text label position
+ virtual void updateDrawable(BOOL force_damped); // force updates on static objects
+
+ void setDrawableState(U32 state, BOOL recursive = TRUE);
+ void clearDrawableState(U32 state, BOOL recursive = TRUE);
+
+ // Called when the drawable shifts
+ virtual void onShift(const LLVector4a &shift_vector) { }
+
+ //////////////////////////////////////
+ //
+ // Inventory methods
+ //
+
+ // This function is called when someone is interested in a viewer
+ // object's inventory. The callback is called as soon as the
+ // viewer object has the inventory stored locally.
+ void registerInventoryListener(LLVOInventoryListener* listener, void* user_data);
+ void removeInventoryListener(LLVOInventoryListener* listener);
+ BOOL isInventoryPending() { return mInventoryPending; }
+ void clearInventoryListeners();
+ void requestInventory();
+ void fetchInventoryFromServer();
+ static void processTaskInv(LLMessageSystem* msg, void** user_data);
+ void removeInventory(const LLUUID& item_id);
+
+ // The updateInventory() call potentially calls into the selection
+ // manager, so do no call updateInventory() from the selection
+ // manager until we have better iterators.
+ void updateInventory(LLViewerInventoryItem* item, U8 key, bool is_new);
+ void updateInventoryLocal(LLInventoryItem* item, U8 key); // Update without messaging.
+ LLInventoryObject* getInventoryObject(const LLUUID& item_id);
+ void getInventoryContents(LLInventoryObject::object_list_t& objects);
+ LLInventoryObject* getInventoryRoot();
+ LLViewerInventoryItem* getInventoryItemByAsset(const LLUUID& asset_id);
+ S16 getInventorySerial() const { return mInventorySerialNum; }
+
+ // These functions does viewer-side only object inventory modifications
+ void updateViewerInventoryAsset(
+ const LLViewerInventoryItem* item,
+ const LLUUID& new_asset);
+
+ // This function will make sure that we refresh the inventory.
+ void dirtyInventory();
+ BOOL isInventoryDirty() { return mInventoryDirty; }
+
+ // save a script, which involves removing the old one, and rezzing
+ // in the new one. This method should be called with the asset id
+ // of the new and old script AFTER the bytecode has been saved.
+ void saveScript(const LLViewerInventoryItem* item, BOOL active, bool is_new);
+
+ // move an inventory item out of the task and into agent
+ // inventory. This operation is based on messaging. No permissions
+ // checks are made on the viewer - the server will double check.
+ void moveInventory(const LLUUID& agent_folder, const LLUUID& item_id);
+
+ // Find the number of instances of this object's inventory that are of the given type
+ S32 countInventoryContents( LLAssetType::EType type );
+
+ BOOL permAnyOwner() const;
+ BOOL permYouOwner() const;
+ BOOL permGroupOwner() const;
+ BOOL permOwnerModify() const;
+ BOOL permModify() const;
+ BOOL permCopy() const;
+ BOOL permMove() const;
+ BOOL permTransfer() const;
+ inline BOOL usePhysics() const { return ((mFlags & FLAGS_USE_PHYSICS) != 0); }
+ inline BOOL flagScripted() const { return ((mFlags & FLAGS_SCRIPTED) != 0); }
+ inline BOOL flagHandleTouch() const { return ((mFlags & FLAGS_HANDLE_TOUCH) != 0); }
+ inline BOOL flagTakesMoney() const { return ((mFlags & FLAGS_TAKES_MONEY) != 0); }
+ inline BOOL flagPhantom() const { return ((mFlags & FLAGS_PHANTOM) != 0); }
+ inline BOOL flagInventoryEmpty() const { return ((mFlags & FLAGS_INVENTORY_EMPTY) != 0); }
+ inline BOOL flagCastShadows() const { return ((mFlags & FLAGS_CAST_SHADOWS) != 0); }
+ inline BOOL flagAllowInventoryAdd() const { return ((mFlags & FLAGS_ALLOW_INVENTORY_DROP) != 0); }
+ inline BOOL flagTemporary() const { return ((mFlags & FLAGS_TEMPORARY) != 0); }
+ inline BOOL flagTemporaryOnRez() const { return ((mFlags & FLAGS_TEMPORARY_ON_REZ) != 0); }
+ inline BOOL flagAnimSource() const { return ((mFlags & FLAGS_ANIM_SOURCE) != 0); }
+ inline BOOL flagCameraSource() const { return ((mFlags & FLAGS_CAMERA_SOURCE) != 0); }
+ inline BOOL flagCameraDecoupled() const { return ((mFlags & FLAGS_CAMERA_DECOUPLED) != 0); }
+ inline BOOL flagObjectMove() const { return ((mFlags & FLAGS_OBJECT_MOVE) != 0); }
+
+ U8 getPhysicsShapeType() const;
+ inline F32 getPhysicsGravity() const { return mPhysicsGravity; }
+ inline F32 getPhysicsFriction() const { return mPhysicsFriction; }
+ inline F32 getPhysicsDensity() const { return mPhysicsDensity; }
+ inline F32 getPhysicsRestitution() const { return mPhysicsRestitution; }
+
+ bool getIncludeInSearch() const;
+ void setIncludeInSearch(bool include_in_search);
+
+ // Does "open" object menu item apply?
+ BOOL allowOpen() const;
+
+ void setClickAction(U8 action) { mClickAction = action; }
+ U8 getClickAction() const { return mClickAction; }
+ bool specialHoverCursor() const; // does it have a special hover cursor?
+
+ void setRegion(LLViewerRegion *regionp);
+ virtual void updateRegion(LLViewerRegion *regionp);
+
+ void updateFlags(BOOL physics_changed = FALSE);
+ BOOL setFlags(U32 flag, BOOL state);
+ void setPhysicsShapeType(U8 type);
+ void setPhysicsGravity(F32 gravity);
+ void setPhysicsFriction(F32 friction);
+ void setPhysicsDensity(F32 density);
+ void setPhysicsRestitution(F32 restitution);
+
+ virtual void dump() const;
+ static U32 getNumZombieObjects() { return sNumZombieObjects; }
+
+ void printNameValuePairs() const;
+
+ virtual S32 getLOD() const { return 3; }
+ virtual U32 getPartitionType() const;
+ virtual void dirtySpatialGroup(BOOL priority = FALSE) const;
+ virtual void dirtyMesh();
+
+ virtual LLNetworkData* getParameterEntry(U16 param_type) const;
+ virtual bool setParameterEntry(U16 param_type, const LLNetworkData& new_value, bool local_origin);
+ virtual BOOL getParameterEntryInUse(U16 param_type) const;
+ virtual bool setParameterEntryInUse(U16 param_type, BOOL in_use, bool local_origin);
+ // Called when a parameter is changed
+ virtual void parameterChanged(U16 param_type, bool local_origin);
+ virtual void parameterChanged(U16 param_type, LLNetworkData* data, BOOL in_use, bool local_origin);
+
+ friend class LLViewerObjectList;
+ friend class LLViewerMediaList;
+
+public:
+ //counter-translation
+ void resetChildrenPosition(const LLVector3& offset, BOOL simplified = FALSE) ;
+ //counter-rotation
+ void resetChildrenRotationAndPosition(const std::vector<LLQuaternion>& rotations,
+ const std::vector<LLVector3>& positions) ;
+ void saveUnselectedChildrenRotation(std::vector<LLQuaternion>& rotations) ;
+ void saveUnselectedChildrenPosition(std::vector<LLVector3>& positions) ;
+ std::vector<LLVector3> mUnselectedChildrenPositions ;
+
+private:
+ ExtraParameter* createNewParameterEntry(U16 param_type);
+ ExtraParameter* getExtraParameterEntry(U16 param_type) const;
+ ExtraParameter* getExtraParameterEntryCreate(U16 param_type);
+ bool unpackParameterEntry(U16 param_type, LLDataPacker *dp);
+
+ // This function checks to see if the given media URL has changed its version
+ // and the update wasn't due to this agent's last action.
+ U32 checkMediaURL(const std::string &media_url);
+
+ // Motion prediction between updates
+ void interpolateLinearMotion(const F64 & time, const F32 & dt);
+
+public:
+ //
+ // Viewer-side only types - use the LL_PCODE_APP mask.
+ //
+ typedef enum e_vo_types
+ {
+ LL_VO_CLOUDS = LL_PCODE_APP | 0x20,
+ LL_VO_SURFACE_PATCH = LL_PCODE_APP | 0x30,
+ LL_VO_WL_SKY = LL_PCODE_APP | 0x40,
+ LL_VO_SQUARE_TORUS = LL_PCODE_APP | 0x50,
+ LL_VO_SKY = LL_PCODE_APP | 0x60,
+ LL_VO_VOID_WATER = LL_PCODE_APP | 0x70,
+ LL_VO_WATER = LL_PCODE_APP | 0x80,
+ LL_VO_GROUND = LL_PCODE_APP | 0x90,
+ LL_VO_PART_GROUP = LL_PCODE_APP | 0xa0,
+ LL_VO_TRIANGLE_TORUS = LL_PCODE_APP | 0xb0,
+ LL_VO_HUD_PART_GROUP = LL_PCODE_APP | 0xc0,
+ } EVOType;
+
+ typedef enum e_physics_shape_types
+ {
+ PHYSICS_SHAPE_PRIM = 0,
+ PHYSICS_SHAPE_NONE,
+ PHYSICS_SHAPE_CONVEX_HULL,
+ } EPhysicsShapeType;
+
+ LLUUID mID;
+
+ // unique within region, not unique across regions
+ // Local ID = 0 is not used
+ U32 mLocalID;
+
+ // Last total CRC received from sim, used for caching
+ U32 mTotalCRC;
+
+ LLPointer<LLViewerTexture> *mTEImages;
+
+ // Selection, picking and rendering variables
+ U32 mGLName; // GL "name" used by selection code
+ BOOL mbCanSelect; // true if user can select this object by clicking
+
+ // Grabbed from UPDATE_FLAGS
+ U32 mFlags;
+
+ // Sent to sim in UPDATE_FLAGS, received in ObjectPhysicsProperties
+ U8 mPhysicsShapeType;
+ F32 mPhysicsGravity;
+ F32 mPhysicsFriction;
+ F32 mPhysicsDensity;
+ F32 mPhysicsRestitution;
+
+
+ // Pipeline classes
+ LLPointer<LLDrawable> mDrawable;
+
+ // Band-aid to select object after all creation initialization is done
+ BOOL mCreateSelected;
+
+ // Replace textures with web pages on this object while drawing
+ BOOL mRenderMedia;
+
+ // In bits
+ S32 mBestUpdatePrecision;
+
+ // TODO: Make all this stuff private. JC
+ LLPointer<LLHUDText> mText;
+ LLPointer<LLHUDIcon> mIcon;
+
+ static BOOL sUseSharedDrawables;
+
+protected:
+ // delete an item in the inventory, but don't tell the
+ // server. This is used internally by remove, update, and
+ // savescript.
+ void deleteInventoryItem(const LLUUID& item_id);
+
+ // do the update/caching logic. called by saveScript and
+ // updateInventory.
+ void doUpdateInventory(LLPointer<LLViewerInventoryItem>& item, U8 key, bool is_new);
+
+
+ static LLViewerObject *createObject(const LLUUID &id, LLPCode pcode, LLViewerRegion *regionp);
+
+ BOOL setData(const U8 *datap, const U32 data_size);
+
+ // Hide or show HUD, icon and particles
+ void hideExtraDisplayItems( BOOL hidden );
+
+ //////////////////////////
+ //
+ // inventory functionality
+ //
+
+ static void processTaskInvFile(void** user_data, S32 error_code, LLExtStat ext_status);
+ void loadTaskInvFile(const std::string& filename);
+ void doInventoryCallback();
+
+ BOOL isOnMap();
+
+ void unpackParticleSource(const S32 block_num, const LLUUID& owner_id);
+ void unpackParticleSource(LLDataPacker &dp, const LLUUID& owner_id);
+ void deleteParticleSource();
+ void setParticleSource(const LLPartSysData& particle_parameters, const LLUUID& owner_id);
+
+public:
+ void updateQuota( const SelectionQuota& quota );
+ const SelectionQuota& getQuota( void ) { return mSelectionQuota; }
+
+private:
+ void setNameValueList(const std::string& list); // clears nv pairs and then individually adds \n separated NV pairs from \0 terminated string
+ void deleteTEImages(); // correctly deletes list of images
+
+protected:
+ typedef std::map<char *, LLNameValue *> name_value_map_t;
+ name_value_map_t mNameValuePairs; // Any name-value pairs stored by script
+
+ child_list_t mChildList;
+
+ F64 mLastInterpUpdateSecs; // Last update for purposes of interpolation
+ F64 mLastMessageUpdateSecs; // Last update from a message from the simulator
+ TPACKETID mLatestRecvPacketID; // Latest time stamp on message from simulator
+
+ // extra data sent from the sim...currently only used for tree species info
+ U8* mData;
+
+ LLPointer<LLViewerPartSourceScript> mPartSourcep; // Particle source associated with this object.
+ LLAudioSourceVO* mAudioSourcep;
+ F32 mAudioGain;
+
+ F32 mAppAngle; // Apparent visual arc in degrees
+ F32 mPixelArea; // Apparent area in pixels
+
+ // This is the object's inventory from the viewer's perspective.
+ LLInventoryObject::object_list_t* mInventory;
+ class LLInventoryCallbackInfo
+ {
+ public:
+ ~LLInventoryCallbackInfo();
+ LLVOInventoryListener* mListener;
+ void* mInventoryData;
+ };
+ typedef std::list<LLInventoryCallbackInfo*> callback_list_t;
+ callback_list_t mInventoryCallbacks;
+ S16 mInventorySerialNum;
+
+ LLViewerRegion *mRegionp; // Region that this object belongs to.
+ BOOL mInventoryPending;
+ BOOL mInventoryDirty;
+ BOOL mDead;
+ BOOL mOrphaned; // This is an orphaned child
+ BOOL mUserSelected; // Cached user select information
+ BOOL mOnActiveList;
+ BOOL mOnMap; // On the map.
+ BOOL mStatic; // Object doesn't move.
+ S32 mNumFaces;
+
+ F32 mTimeDilation; // Time dilation sent with the object.
+ F32 mRotTime; // Amount (in seconds) that object has rotated according to angular velocity (llSetTargetOmega)
+ LLQuaternion mLastRot; // last rotation received from the simulator
+
+ LLVOJointInfo* mJointInfo;
+ U8 mState; // legacy
+ LLViewerObjectMedia* mMedia; // NULL if no media associated
+ U8 mClickAction;
+ F32 mObjectCost; //resource cost of this object or -1 if unknown
+ F32 mLinksetCost;
+ F32 mPhysicsCost;
+ F32 mLinksetPhysicsCost;
+
+ SelectionQuota mSelectionQuota;
+
+ bool mCostStale;
+ mutable bool mPhysicsShapeUnknown;
+
+ static U32 sNumZombieObjects; // Objects which are dead, but not deleted
+
+ static BOOL sMapDebug; // Map render mode
+ static LLColor4 sEditSelectColor;
+ static LLColor4 sNoEditSelectColor;
+ static F32 sCurrentPulse;
+ static BOOL sPulseEnabled;
+
+ static S32 sAxisArrowLength;
+
+ // These two caches are only correct for non-parented objects right now!
+ mutable LLVector3 mPositionRegion;
+ mutable LLVector3 mPositionAgent;
+
+ static void setPhaseOutUpdateInterpolationTime(F32 value) { sPhaseOutUpdateInterpolationTime = (F64) value; }
+ static void setMaxUpdateInterpolationTime(F32 value) { sMaxUpdateInterpolationTime = (F64) value; }
+
+ static void setVelocityInterpolate(BOOL value) { sVelocityInterpolate = value; }
+ static void setPingInterpolate(BOOL value) { sPingInterpolate = value; }
+
+private:
+ static S32 sNumObjects;
+
+ static F64 sPhaseOutUpdateInterpolationTime; // For motion interpolation
+ static F64 sMaxUpdateInterpolationTime; // For motion interpolation
+
+ static BOOL sVelocityInterpolate;
+ static BOOL sPingInterpolate;
+
+ //--------------------------------------------------------------------
+ // For objects that are attachments
+ //--------------------------------------------------------------------
+public:
+ const LLUUID &getAttachmentItemID() const;
+ void setAttachmentItemID(const LLUUID &id);
+ const LLUUID &extractAttachmentItemID(); // find&set the inventory item ID of the attached object
+ EObjectUpdateType getLastUpdateType() const;
+ void setLastUpdateType(EObjectUpdateType last_update_type);
+ BOOL getLastUpdateCached() const;
+ void setLastUpdateCached(BOOL last_update_cached);
+
+private:
+ LLUUID mAttachmentItemID; // ItemID of the associated object is in user inventory.
+ EObjectUpdateType mLastUpdateType;
+ BOOL mLastUpdateCached;
+};
+
+///////////////////
+//
+// Inlines
+//
+//
+
+inline void LLViewerObject::setRotation(const LLQuaternion& quat, BOOL damped)
+{
+ LLPrimitive::setRotation(quat);
+ setChanged(ROTATED | SILHOUETTE);
+ updateDrawable(damped);
+}
+
+inline void LLViewerObject::setRotation(const F32 x, const F32 y, const F32 z, BOOL damped)
+{
+ LLPrimitive::setRotation(x, y, z);
+ setChanged(ROTATED | SILHOUETTE);
+ updateDrawable(damped);
+}
+
+class LLViewerObjectMedia
+{
+public:
+ LLViewerObjectMedia() : mMediaURL(), mPassedWhitelist(FALSE), mMediaType(0) { }
+
+ std::string mMediaURL; // for web pages on surfaces, one per prim
+ BOOL mPassedWhitelist; // user has OK'd display
+ U8 mMediaType; // see LLTextureEntry::WEB_PAGE, etc.
+};
+
+// subclass of viewer object that can be added to particle partitions
+class LLAlphaObject : public LLViewerObject
+{
+public:
+ LLAlphaObject(const LLUUID &id, const LLPCode pcode, LLViewerRegion *regionp)
+ : LLViewerObject(id,pcode,regionp)
+ { mDepth = 0.f; }
+
+ virtual F32 getPartSize(S32 idx);
+ virtual void getGeometry(S32 idx,
+ LLStrider<LLVector3>& verticesp,
+ LLStrider<LLVector3>& normalsp,
+ LLStrider<LLVector2>& texcoordsp,
+ LLStrider<LLColor4U>& colorsp,
+ LLStrider<U16>& indicesp) = 0;
+
+ F32 mDepth;
+};
+
+class LLStaticViewerObject : public LLViewerObject
+{
+public:
+ LLStaticViewerObject(const LLUUID& id, const LLPCode pcode, LLViewerRegion* regionp, BOOL is_global = FALSE)
+ : LLViewerObject(id,pcode,regionp, is_global)
+ { }
+
+ virtual void updateDrawable(BOOL force_damped);
+};
+
+
+#endif
diff --git a/indra/newview/skins/default/xui/en/floater_model_preview.xml b/indra/newview/skins/default/xui/en/floater_model_preview.xml index dce55dae12..a24306456a 100644 --- a/indra/newview/skins/default/xui/en/floater_model_preview.xml +++ b/indra/newview/skins/default/xui/en/floater_model_preview.xml @@ -1,547 +1,547 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater can_close="true" can_drag_on_left="false" can_minimize="false" - can_resize="true" height="550" min_height="550" min_width="620" - name="Model Preview" title="Upload Model" width="620"> - - <string name="status_idle">Idle</string> - <string name="status_reading_file">Loading...</string> - <string name="status_generating_meshes">Generating Meshes...</string> - <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string> - <string name="high">High</string> - <string name="medium">Medium</string> - <string name="low">Low</string> - <string name="lowest">Lowest</string> - <string name="mesh_status_good">Ship it!</string> - <string name="mesh_status_na">N/A</string> - <string name="mesh_status_none">None</string> - <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string> - <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string> - <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> - <string name="mesh_status_missing_lod">Missing required level of detail.</string> - <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" --> - <string name="decomposing">Analyzing...</string> - <string name="simplifying">Simplifying...</string> - - - <text left="15" bottom="25" follows="top|left" height="15" name="name_label"> - Name: - </text> - <line_editor bottom_delta="20" follows="top|left|right" height="19" max_length_bytes="64" - name="description_form" prevalidate_callback="ascii" width="290" /> - - <text bottom_delta="20" left="15" follows="left|top" height="15" name="lod_label"> - Preview: - </text> - <combo_box bottom_delta="20" follows="left|top" height="18" - name="preview_lod_combo" width="240" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - Level of Detail: High - </combo_item> - <combo_item name="medium"> - Level of Detail: Medium - </combo_item> - <combo_item name="low"> - Level of Detail: Low - </combo_item> - <combo_item name="lowest"> - Level of Detail: Lowest - </combo_item> - </combo_box> - - <menu_button follows="top|left" - image_hover_unselected="Toolbar_Left_Over" - image_overlay="OptionsMenu_Off" - image_selected="Toolbar_Left_Selected" - image_unselected="Toolbar_Left_Off" - layout="topleft" - left_pad="5" - name="options_gear_btn" - width="31" - height="25"/> - <!-- Placeholder panel for 3D preview render --> - <panel - name="preview_panel" - left="15" - bevel_style="none" - border_style="line" - border="true" - width="290" - height="290" - follows="all"/> - - <text bottom_delta="25" left="25" width="100" follows="bottom|left">Upload Details</text> - <panel top_pad="5" border="true" left="15" width="290" height="70" follows="bottom|left" - bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> - <text left="25" follows="bottom|left" width="140" height="15" name="streaming cost"> - Resource Cost: [COST] - </text> - <text left="25" top_pad="5" width="140" follows="bottom|left" height="15" name="physics cost"> - Physics Cost: [COST] - </text> - <text left="25" top_pad="5" follows="bottom|left" height="15" name="upload fee"> - Upload Fee: N/A - </text> - </panel> - - <text left="10" bottom="540" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text> - - - <button bottom="540" left="300" follows="bottom|right" height="20" label="Defaults" - width="80" name="reset_btn" tool_tip="Reset to defaults"/> - <button bottom="540" left="430" follows="bottom|right" height="20" label="Upload" - width="80" name="ok_btn" tool_tip="Upload to simulator"/> - <button left_pad="10" follows="right|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/> - - <tab_container - follows="right|top|bottom" - top="15" - left="310" - height="470" - width="300" - name="import_tab" - border="true" - tab_position="top"> - - <!-- LOD PANEL --> - <panel - border="true" - label="Level of Detail" - name="lod_panel"> - - <text left="10" width="240" bottom="20" height="15" follows="left|top" name="lod_table_header"> - Select Level of Detail: - </text> - - <text valign="center" halign="center" bg_visible="true" bottom_delta="16" left="75" width="65" height="18" follows="left|top" value="Triangles"/> - <text valign="center" halign="center" bg_visible="true" left_pad="0" width="65" height="18" follows="left|top" value="Vertices"/> - <text valign="center" halign="center" left_pad="0" width="65" bg_visible="true" height="18" follows="left|top" value="Status"/> - - <text valign="center" halign="center" bg_visible="true" name="high_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="High"/> - <text valign="center" halign="center" bg_visible="true" name="high_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="high_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="high_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> - <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_high" left_delta="20" top_delta="0" /> - - <text valign="center" halign="center" bg_visible="true" name="medium_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Medium"/> - <text valign="center" halign="center" bg_visible="true" name="medium_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="medium_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="medium_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> - <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_medium" left_delta="20" top_delta="0" /> - - <text valign="center" halign="center" bg_visible="true" name="low_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Low"/> - <text valign="center" halign="center" bg_visible="true" name="low_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="low_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="low_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> - <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_low" left_delta="20" top_delta="0" /> - - <text valign="center" halign="center" bg_visible="true" name="lowest_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Lowest"/> - <text valign="center" halign="center" bg_visible="true" name="lowest_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="lowest_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/> - <text valign="center" halign="center" bg_visible="true" name="lowest_status" left_pad="0" width="65" height="18" follows="left|top" value=""/> - <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_lowest" left_delta="20" top_delta="0" /> - - <text left="10" width="240" height="15" top_pad="15" follows="left|top" name="lod_table_footer"> - Level of Detail: [DETAIL] - </text> - - <icon height="16" width="16" left="20" follows="left|top" name="lod_status_message_icon"/> - <text left_pad="5" width="200" height="28" follows="left|top" top_pad="-15" wrap="true" name="lod_status_message_text"/> - - <text top_pad="-3" left="10" height="15" follows="left|top"> - Mesh - </text> - - <radio_group follows="top|left" height="210" left="30" name="lod_file_or_limit" width="240" value="lod_from_file"> - <radio_item bottom="195" label="Load from file" name="lod_from_file"/> - <radio_item bottom="150" label="Auto generate" name="lod_auto_generate"/> - <radio_item bottom="0" label="None" name="lod_none"/> - </radio_group> - - <line_editor follows="left|top" bottom_delta="-170" width="140" left="45" value="" name="lod_file" height="20"/> - <button bottom_delta="3" name="lod_browse" label="Browse..." left_pad="5" follows="left|top" width="70" height="25"/> - - <combo_box follows="top|left" name="lod_mode" top_pad="22" width="100" left="45" height="20"> - <combo_item name="triangle_limit"> - Triangle Limit - </combo_item> - <combo_item name="error_threshold"> - Error Threshold - </combo_item> - </combo_box> - <spinner follows="top|left" name="lod_triangle_limit" increment="10" left_pad="5" height="20" width="100" decimal_digits="0" enabled="true"/> - <spinner left_delta="0" bottom_delta="0" increment="0.01" follows="top|left" name="lod_error_threshold" min_val="0" max_val="100" height="20" width="100" decimal_digits="3" visible="false" enabled="true"/> - - <text follows="top|left" name="build_operator_text" left="45" top_pad="10" width="100" height="15"> - Build Operator: - </text> - <text follows="top|left" name="queue_mode_text" left_pad="5" width="100" height="15"> - Queue Mode: - </text> - <combo_box follows="top|left" name="build_operator" top_pad="5" left="45" width="100" height="20"> - <combo_item name="edge_collapse"> - Edge Collapse - </combo_item> - <combo_item name="half_edge_collapse"> - Half Edge Collapse - </combo_item> - </combo_box> - - <combo_box follows="top|left" name="queue_mode" left_pad="5" width="100" height="20"> - <combo_item name="greedy"> - Greedy - </combo_item> - <combo_item name="lazy"> - Lazy - </combo_item> - <combo_item name="independent"> - Independent - </combo_item> - </combo_box> - - <text top_pad="10" name="border_mode_text" left="45" follows="left|top" width="100" height="15"> - Border Mode: - </text> - - <text left_pad="5" name="share_tolderance_text" follows="left|top" width="100" height="15"> - Share Tolerance: - </text> - - <combo_box follows="left|top" left="45" height="20" name="border_mode" width="100"> - <combo_item name="border_unlock"> - Unlock - </combo_item> - <combo_item name="border_lock"> - Lock - </combo_item> - </combo_box> - <spinner follows="left|top" name="share_tolerance" left_pad="5" width="100" decimal_digits="5" initial_value="0.00001" height="20"/> - - <text left="10" top_pad="35" follows="top|left" width="240" height="15"> - Generate Normals - </text> - <text left="35" top_pad="5" follows="top|left" width="100" height="15" name="crease_label"> - Crease Angle: - </text> - <spinner follows="top|left" left_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/> - </panel> - - <!-- PANEL --> - <panel - border="true" - label="Physics" - name="physics_panel"> - - <!-- PHYSICS GEOMETRY--> - <panel - follows="top|left" - name="physics geometry" - left="0" - top="0" - width="300" - height="65" - visible="true" - border="true" - bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> - - <radio_group follows="top|left" top="10" width="240" height="40" name="physics_load_radio" value="physics_load_from_file"> - <radio_item bottom="0" name="physics_load_from_file" label="File:"/> - <radio_item bottom="23" name="physics_use_lod" label="Use Level of Detail:"/> - </radio_group> - - <combo_box left="180" top="10" follows="left|top" height="18" - name="physics_lod_combo" width="110" tool_tip="LOD to use for physics shape"> - <combo_item name="physics_lowest"> - Lowest - </combo_item> - <combo_item name="physics_low"> - Low - </combo_item> - <combo_item name="physics_medium"> - Medium - </combo_item> - <combo_item name="physics_high"> - High - </combo_item> - </combo_box> - - <line_editor follows="left|top" top_pad="5" width="140" left="60" value="" name="physics_file" height="20"/> - <button left_pad="10" name="physics_browse" label="Browse..." follows="left|top" width="70" height="20"/> - - <!-- - <check_box name="physics_optimize" follows="left|top" width="130" left="10" top_pad="5" height="20" label="Optimize"/> - <check_box name="physics_use_hull" follows="left|top" width="130" left_pad="5" height="20" label="Use Convex Hull"/> - --> - </panel> - - - <!-- PHYSICS ANALYSIS--> - <panel - follows="top|left" - name="physics analysis" - top_pad="0" - left="0" - width="300" - height="130" - visible="true" - border="true" - bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> - - <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig"> - Step 1: Analysis - </text> - - <text top_pad="5" width="50" follows="top|left" height="15"> - Method: - </text> - <combo_box name="Method" follows="top|left" left_pad="5" bottom_delta="2" height="20" width="80"/> - <text left="160" bottom_delta="-2" width="50" follows="top|left" height="15"> - Quality: - </text> - <combo_box name="Decompose Quality" bottom_delta="2" follows="top|left" left_pad="5" height="20" width="80"/> - - <slider name="Smooth" left="10" width="280" follows="top|left" top_pad="10" height="20" label="Smooth:"/> - - <check_box name="Close Holes (Slow)" follows="top|left" top_pad="10" height="15" label="Close Holes (slow)"/> - - <button left="200" bottom_delta="0" width="90" follows="top|left" label="Analyze" name="Decompose" height="20"/> - <button left="200" bottom_delta="0" width="90" follows="top|left" label="Cancel" name="decompose_cancel" visble="false" height="20"/> - </panel> - - - <!-- PHYSICS SIMPLIFICATION --> - <panel - follows="top|left" - name="physics simplification" - left="0" - top_pad="0" - width="300" - height="150" - visible="true" - border="true" - bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> - - <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig"> - Step 2: Simplification - </text> - - <text left="10" top_pad="5" height="15" width="140" follows="top|left"> - Method: - </text> - - <combo_box left_pad="5" height="20" width="120" follows="top|left" name="Simplify Method"/> - - <slider left="10" name="Combine Quality" label="Passes:" label_width="120" width="270" follows="top|left" top_pad="10" height="20"/> - <slider name="Detail Scale" label="Detail Scale:" label_width="120" width="270" follows="top|left" top_pad="10" height="20"/> - <slider name="Retain%" label="Retain:" label_width="120" width="270" follows="top|left" bottom_delta="0" left_delta="0" visible="false" height="20"/> - <button left="190" width="90" follows="top|left" label="Simplify" name="Simplify" height="20"/> - <button left="190" bottom_delta="0" width="90" follows="top|left" label="Cancel" name="simplify_cancel" height="20"/> - - </panel> - - <!-- INFO PANEL --> - <panel - left="0" - top_pad="0" - width="300" - height="100" - follows="left|top" - name="physics info" - visible="true" - border="true" - bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3"> - - <slider name="physics_explode" follows="top|left" top="10" left="10" label="Preview Spread:" min_val="0.0" max_val="3.0" height="20" width="280"/> - - <text follows="top|left" name="physics_triangles" top_pad="10" height="15" left="10"> - Triangles: [TRIANGLES] - </text> - <text follows="top|left" name="physics_points" top_pad="5" height="15"> - Vertices: [POINTS] - </text> - <text follows="top|left" name="physics_hulls" top_pad="5" height="15"> - Hulls: [HULLS] - </text> - - - </panel> - </panel> - - <!-- MODIFIERS PANEL --> - <panel - border="true" - label="Modifiers" - name="modifiers_panel"> - <text left="10" width="90" bottom="30" follows="top|left" height="15"> - Scale: - </text> - <text left_pad="5" width="140" follows="top|left" height="15"> - Dimensions: - </text> - - <spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> - - <text left_pad="20" height="15" name="import_dimensions" follows="top|left"> - [X] x [Y] x [Z] m - </text> - - <text left="10" top_pad="20" follows="top|left" height="15"> - Include: - </text> - - <check_box top_pad="5" name="upload_textures" height="15" follows="top|left" label="Textures"/> - <check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/> - <check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/> - - <text left="10" top_pad="4" width="90" bottom="30" follows="top|left" height="15"> - Pelvis Z Offset: - </text> - - <spinner left="10" top_pad="4" height="20" follows="top|left" width="80" value="0.0" min_val="-3.00" max_val="3.0" name="pelvis_offset"/> - - </panel> - </tab_container> - - <!-- - <button bottom_delta="0" left="10" width="120" name="auto fill" label="Generate LOD" tool_tip="Automatically generate levels of detail"/> - <button bottom_delta="0" left="140" width="120" name="smooth normals" label="Generate Normals" tool_tip="Regenerate normals based on mesh shape"/> - <button bottom_delta="0" left="260" width="120" name="consolidate" label="Consolidate" tool_tip="Combine similar submeshes (reduces number of submeshes)"/> - <button bottom_delta="30" left="260" width="120" name="scrub materials" label="Scrub Materials" tool_tip="Remove all material information (clear textures, set all colors to white)."/> - - <spinner bottom_delta="0" left="140" width="120" height="16" initial_value="75" label_width="60" name="edge threshold" decimal_digits="0" min_val="0" max_val="180" increment="5" label="Hard Angle" tool_tip="Maximum angle that will be smoothed between triangles when using Generate Normals"/> - - <text bottom_delta="30" follows="top|left" height="15" left="10" name="high_lod_label"> - High LOD: - </text> - <combo_box bottom_delta="0" left="97" follows="left|top" height="18" - name="high detail combo" width="100" tool_tip="Specify mesh for this level of detail"> - <combo_item name="high none" value="none"> - None - </combo_item> - <combo_item name="high choose file" value="file"> - Choose File... - </combo_item> - <combo_item name="high triangle limit" value="limit"> - Triangle Limit - </combo_item> - </combo_box> - <spinner bottom_delta="-5" left="200" width="120" name="high limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/> - <text bottom_delta="25" follows="top|left" height="15" left="10" name="high info" width="300"> - [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes. - [MESSAGE] - </text> - - <text bottom_delta="35" follows="top|left" height="15" left="10" name="medium_lod_label"> - Medium LOD: - </text> - <combo_box bottom_delta="0" left="97" follows="left|top" height="18" - name="medium detail combo" width="100" tool_tip="Specify mesh for this level of detail"> - <combo_item name="medium none" value="none"> - None - </combo_item> - <combo_item name="medium choose file" value="file"> - Choose File... - </combo_item> - <combo_item name="medium triangle limit" value="limit"> - Triangle Limit - </combo_item> - </combo_box> - <spinner bottom_delta="-5" left="200" width="120" name="medium limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/> - <text bottom_delta="25" follows="top|left" height="15" left="10" name="medium info" width="300"> - [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes. - [MESSAGE] - </text> - - <text bottom_delta="35" follows="top|left" height="15" left="10" name="low_lod_label"> - Low LOD: - </text> - <combo_box bottom_delta="0" left="97" follows="left|top" height="18" - name="low detail combo" width="100" tool_tip="Specify mesh for this level of detail"> - <combo_item name="low none" value="none"> - None - </combo_item> - <combo_item name="low choose file" value="file"> - Choose File... - </combo_item> - <combo_item name="low triangle limit" value="limit"> - Triangle Limit - </combo_item> - </combo_box> - <spinner bottom_delta="-5" left="200" width="120" name="low limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/> - <text bottom_delta="25" follows="top|left" height="15" left="10" name="low info" width="300"> - [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes - [MESSAGE] - </text> - - <text bottom_delta="35" follows="top|left" height="15" left="10" name="lowest_lod_label"> - Lowest LOD: - </text> - <combo_box bottom_delta="0" left="97" follows="left|top" height="18" - name="lowest detail combo" width="100" tool_tip="Specify mesh for this level of detail"> - <combo_item name="lowest none" value="none"> - None - </combo_item> - <combo_item name="lowest choose file" value="file"> - Choose File... - </combo_item> - <combo_item name="lowest triangle limit" value="limit"> - Triangle Limit - </combo_item> - </combo_box> - <spinner bottom_delta="-5" left="200" width="120" name="lowest limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/> - <text bottom_delta="25" follows="top|left" height="15" left="10" name="lowest info" width="300"> - [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes - [MESSAGE] - </text> - - <text bottom_delta="35" follows="top|left" height="15" left="10" name="physics_lod_label"> - Physical Shape: - </text> - <combo_box bottom_delta="0" left="97" follows="left|top" height="18" - name="physics detail combo" width="100"> - <combo_item name="physics none" value="none"> - None - </combo_item> - <combo_item name="physics choose file" value="file"> - Choose File... - </combo_item> - <combo_item name="physics triangle limit" value="limit"> - Triangle Limit... - </combo_item> - </combo_box> - <spinner bottom_delta="-5" left="200" width="90" name="physics limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/> - <button bottom_delta="0" left="290" width="30" follows="left|top" height="20" label=">>" - name="decompose_btn" tool_tip="Create convex decomposition."/> - <text bottom_delta="25" follows="top|left" height="15" left="10" name="physics info" width="300"> - [TRIANGLES] Triangles, [HULLS] Hulls, [POINTS] Points - </text> - - <text bottom_delta="25" follows="top|left" height="15" left="10" name="include label" width="300"> - Include: - </text> - - <check_box bottom_delta="20" follow="bottom|left" height="20" label="Textures" - left="15" width="125" name="upload_textures" tool_tip="Upload associated textures "/> - - <check_box bottom_delta="20" follow="bottom|left" height="20" label="Skin Weights" - left="15" width="125" name="upload_skin" tool_tip="Upload vertex skin weighting information."/> - - <check_box bottom_delta="20" follow="bottom|left" height="20" label="Joint Positions" - left="15" width="125" name="upload_joints" tool_tip="Upload joint position information (will override avatar joint positions when mesh is worn)."/> - - - <button bottom_delta="25" follows="bottom|left" height="20" label="Upload" - left="15" name="ok_btn" width="125" tool_tip="Upload to simulator"/> - - <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="description_label" text_color="1 0.82 0.46 1"> - (No charge for upload during First Look) - </text> - <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="upload_message"> - [MESSAGE] - </text> - - <spinner bottom_delta="20" label="Scale" left="15" width="120" name="debug scale" decimal_digits="3" increment="0.1" min_val="0" max_val="64" initial_value="1" tool_tip="Multiplier for incoming object scale. If incoming dimensions are very small or very large, modify this value to get dimensions into an acceptable range."/> - <text bottom_delta="30" left="15" width="280" follows="top|left" height="15" name="dimensions"> - Model Dimensions: [X]m x [Y]m x [Z]m - </text> - --> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater can_close="true" can_drag_on_left="false" can_minimize="false"
+ can_resize="true" height="550" min_height="550" min_width="620"
+ name="Model Preview" title="Upload Model" width="620">
+
+ <string name="status_idle">Idle</string>
+ <string name="status_reading_file">Loading...</string>
+ <string name="status_generating_meshes">Generating Meshes...</string>
+ <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
+ <string name="high">High</string>
+ <string name="medium">Medium</string>
+ <string name="low">Low</string>
+ <string name="lowest">Lowest</string>
+ <string name="mesh_status_good">Ship it!</string>
+ <string name="mesh_status_na">N/A</string>
+ <string name="mesh_status_none">None</string>
+ <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string>
+ <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string>
+ <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string>
+ <string name="mesh_status_missing_lod">Missing required level of detail.</string>
+ <string name="layer_all">All</string> <!-- Text to display in physics layer combo box for "all layers" -->
+ <string name="decomposing">Analyzing...</string>
+ <string name="simplifying">Simplifying...</string>
+
+
+ <text left="15" bottom="25" follows="top|left" height="15" name="name_label">
+ Name:
+ </text>
+ <line_editor bottom_delta="20" follows="top|left|right" height="19" max_length_bytes="64"
+ name="description_form" prevalidate_callback="ascii" width="290" />
+
+ <text bottom_delta="20" left="15" follows="left|top" height="15" name="lod_label">
+ Preview:
+ </text>
+ <combo_box bottom_delta="20" follows="left|top" height="18"
+ name="preview_lod_combo" width="240" tool_tip="LOD to view in preview render">
+ <combo_item name="high">
+ Level of Detail: High
+ </combo_item>
+ <combo_item name="medium">
+ Level of Detail: Medium
+ </combo_item>
+ <combo_item name="low">
+ Level of Detail: Low
+ </combo_item>
+ <combo_item name="lowest">
+ Level of Detail: Lowest
+ </combo_item>
+ </combo_box>
+
+ <menu_button follows="top|left"
+ image_hover_unselected="Toolbar_Left_Over"
+ image_overlay="OptionsMenu_Off"
+ image_selected="Toolbar_Left_Selected"
+ image_unselected="Toolbar_Left_Off"
+ layout="topleft"
+ left_pad="5"
+ name="options_gear_btn"
+ width="31"
+ height="25"/>
+ <!-- Placeholder panel for 3D preview render -->
+ <panel
+ name="preview_panel"
+ left="15"
+ bevel_style="none"
+ border_style="line"
+ border="true"
+ width="290"
+ height="290"
+ follows="all"/>
+
+ <text bottom_delta="25" left="25" width="100" follows="bottom|left">Upload Details</text>
+ <panel top_pad="5" border="true" left="15" width="290" height="70" follows="bottom|left"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+ <text left="25" follows="bottom|left" width="140" height="15" name="streaming cost">
+ Resource Cost: [COST]
+ </text>
+ <text left="25" top_pad="5" width="140" follows="bottom|left" height="15" name="physics cost">
+ Physics Cost: [COST]
+ </text>
+ <text left="25" top_pad="5" follows="bottom|left" height="15" name="upload fee">
+ Upload Fee: N/A
+ </text>
+ </panel>
+
+ <text left="10" bottom="540" width="290" height="15" follows="bottom|left|right" name="status">[STATUS]</text>
+
+
+ <button bottom="540" left="300" follows="bottom|right" height="20" label="Defaults"
+ width="80" name="reset_btn" tool_tip="Reset to defaults"/>
+ <button bottom="540" left="430" follows="bottom|right" height="20" label="Upload"
+ width="80" name="ok_btn" tool_tip="Upload to simulator"/>
+ <button left_pad="10" follows="right|bottom" height="20" width="80" label="Cancel" name="cancel_btn"/>
+
+ <tab_container
+ follows="right|top|bottom"
+ top="15"
+ left="310"
+ height="470"
+ width="300"
+ name="import_tab"
+ border="true"
+ tab_position="top">
+
+ <!-- LOD PANEL -->
+ <panel
+ border="true"
+ label="Level of Detail"
+ name="lod_panel">
+
+ <text left="10" width="240" bottom="20" height="15" follows="left|top" name="lod_table_header">
+ Select Level of Detail:
+ </text>
+
+ <text valign="center" halign="center" bg_visible="true" bottom_delta="16" left="75" width="65" height="18" follows="left|top" value="Triangles"/>
+ <text valign="center" halign="center" bg_visible="true" left_pad="0" width="65" height="18" follows="left|top" value="Vertices"/>
+ <text valign="center" halign="center" left_pad="0" width="65" bg_visible="true" height="18" follows="left|top" value="Status"/>
+
+ <text valign="center" halign="center" bg_visible="true" name="high_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="High"/>
+ <text valign="center" halign="center" bg_visible="true" name="high_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="high_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="high_status" left_pad="0" width="65" height="18" follows="left|top" value=""/>
+ <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_high" left_delta="20" top_delta="0" />
+
+ <text valign="center" halign="center" bg_visible="true" name="medium_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Medium"/>
+ <text valign="center" halign="center" bg_visible="true" name="medium_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="medium_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="medium_status" left_pad="0" width="65" height="18" follows="left|top" value=""/>
+ <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_medium" left_delta="20" top_delta="0" />
+
+ <text valign="center" halign="center" bg_visible="true" name="low_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Low"/>
+ <text valign="center" halign="center" bg_visible="true" name="low_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="low_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="low_status" left_pad="0" width="65" height="18" follows="left|top" value=""/>
+ <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_low" left_delta="20" top_delta="0" />
+
+ <text valign="center" halign="center" bg_visible="true" name="lowest_label" left="10" top_pad="0" width="65" height="18" follows="left|top" value="Lowest"/>
+ <text valign="center" halign="center" bg_visible="true" name="lowest_triangles" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="lowest_vertices" left_pad="0" width="65" height="18" follows="left|top" value="0"/>
+ <text valign="center" halign="center" bg_visible="true" name="lowest_status" left_pad="0" width="65" height="18" follows="left|top" value=""/>
+ <icon height="16" width="16" image_name="lag_status_critical.tga" mouse_opaque="true" name="status_icon_lowest" left_delta="20" top_delta="0" />
+
+ <text left="10" width="240" height="15" top_pad="15" follows="left|top" name="lod_table_footer">
+ Level of Detail: [DETAIL]
+ </text>
+
+ <icon height="16" width="16" left="20" follows="left|top" name="lod_status_message_icon"/>
+ <text left_pad="5" width="200" height="28" follows="left|top" top_pad="-15" wrap="true" name="lod_status_message_text"/>
+
+ <text top_pad="-3" left="10" height="15" follows="left|top">
+ Mesh
+ </text>
+
+ <radio_group follows="top|left" height="210" left="30" name="lod_file_or_limit" width="240" value="lod_from_file">
+ <radio_item bottom="195" label="Load from file" name="lod_from_file"/>
+ <radio_item bottom="150" label="Auto generate" name="lod_auto_generate"/>
+ <radio_item bottom="0" label="None" name="lod_none"/>
+ </radio_group>
+
+ <line_editor follows="left|top" bottom_delta="-170" width="140" left="45" value="" name="lod_file" height="20"/>
+ <button bottom_delta="3" name="lod_browse" label="Browse..." left_pad="5" follows="left|top" width="70" height="25"/>
+
+ <combo_box follows="top|left" name="lod_mode" top_pad="22" width="100" left="45" height="20">
+ <combo_item name="triangle_limit">
+ Triangle Limit
+ </combo_item>
+ <combo_item name="error_threshold">
+ Error Threshold
+ </combo_item>
+ </combo_box>
+ <spinner follows="top|left" name="lod_triangle_limit" increment="10" left_pad="5" height="20" width="100" decimal_digits="0" enabled="true"/>
+ <spinner left_delta="0" bottom_delta="0" increment="0.01" follows="top|left" name="lod_error_threshold" min_val="0" max_val="100" height="20" width="100" decimal_digits="3" visible="false" enabled="true"/>
+
+ <text follows="top|left" name="build_operator_text" left="45" top_pad="10" width="100" height="15">
+ Build Operator:
+ </text>
+ <text follows="top|left" name="queue_mode_text" left_pad="5" width="100" height="15">
+ Queue Mode:
+ </text>
+ <combo_box follows="top|left" name="build_operator" top_pad="5" left="45" width="100" height="20">
+ <combo_item name="edge_collapse">
+ Edge Collapse
+ </combo_item>
+ <combo_item name="half_edge_collapse">
+ Half Edge Collapse
+ </combo_item>
+ </combo_box>
+
+ <combo_box follows="top|left" name="queue_mode" left_pad="5" width="100" height="20">
+ <combo_item name="greedy">
+ Greedy
+ </combo_item>
+ <combo_item name="lazy">
+ Lazy
+ </combo_item>
+ <combo_item name="independent">
+ Independent
+ </combo_item>
+ </combo_box>
+
+ <text top_pad="10" name="border_mode_text" left="45" follows="left|top" width="100" height="15">
+ Border Mode:
+ </text>
+
+ <text left_pad="5" name="share_tolderance_text" follows="left|top" width="100" height="15">
+ Share Tolerance:
+ </text>
+
+ <combo_box follows="left|top" left="45" height="20" name="border_mode" width="100">
+ <combo_item name="border_unlock">
+ Unlock
+ </combo_item>
+ <combo_item name="border_lock">
+ Lock
+ </combo_item>
+ </combo_box>
+ <spinner follows="left|top" name="share_tolerance" left_pad="5" width="100" decimal_digits="5" initial_value="0.00001" height="20"/>
+
+ <text left="10" top_pad="35" follows="top|left" width="240" height="15">
+ Generate Normals
+ </text>
+ <text left="35" top_pad="5" follows="top|left" width="100" height="15" name="crease_label">
+ Crease Angle:
+ </text>
+ <spinner follows="top|left" left_pad="5" min_val="0" max_val="180" value="75" width="60" height="20" name="crease_angle"/>
+ </panel>
+
+ <!-- PANEL -->
+ <panel
+ border="true"
+ label="Physics"
+ name="physics_panel">
+
+ <!-- PHYSICS GEOMETRY-->
+ <panel
+ follows="top|left"
+ name="physics geometry"
+ left="0"
+ top="0"
+ width="300"
+ height="65"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
+ <radio_group follows="top|left" top="10" width="240" height="40" name="physics_load_radio" value="physics_load_from_file">
+ <radio_item bottom="0" name="physics_load_from_file" label="File:"/>
+ <radio_item bottom="23" name="physics_use_lod" label="Use Level of Detail:"/>
+ </radio_group>
+
+ <combo_box left="180" top="10" follows="left|top" height="18"
+ name="physics_lod_combo" width="110" tool_tip="LOD to use for physics shape">
+ <combo_item name="physics_lowest">
+ Lowest
+ </combo_item>
+ <combo_item name="physics_low">
+ Low
+ </combo_item>
+ <combo_item name="physics_medium">
+ Medium
+ </combo_item>
+ <combo_item name="physics_high">
+ High
+ </combo_item>
+ </combo_box>
+
+ <line_editor follows="left|top" top_pad="5" width="140" left="60" value="" name="physics_file" height="20"/>
+ <button left_pad="10" name="physics_browse" label="Browse..." follows="left|top" width="70" height="20"/>
+
+ <!--
+ <check_box name="physics_optimize" follows="left|top" width="130" left="10" top_pad="5" height="20" label="Optimize"/>
+ <check_box name="physics_use_hull" follows="left|top" width="130" left_pad="5" height="20" label="Use Convex Hull"/>
+ -->
+ </panel>
+
+
+ <!-- PHYSICS ANALYSIS-->
+ <panel
+ follows="top|left"
+ name="physics analysis"
+ top_pad="0"
+ left="0"
+ width="300"
+ height="130"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
+ <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig">
+ Step 1: Analysis
+ </text>
+
+ <text top_pad="5" width="50" follows="top|left" height="15">
+ Method:
+ </text>
+ <combo_box name="Method" follows="top|left" left_pad="5" bottom_delta="2" height="20" width="80"/>
+ <text left="160" bottom_delta="-2" width="50" follows="top|left" height="15">
+ Quality:
+ </text>
+ <combo_box name="Decompose Quality" bottom_delta="2" follows="top|left" left_pad="5" height="20" width="80"/>
+
+ <slider name="Smooth" left="10" width="280" follows="top|left" top_pad="10" height="20" label="Smooth:"/>
+
+ <check_box name="Close Holes (Slow)" follows="top|left" top_pad="10" height="15" label="Close Holes (slow)"/>
+
+ <button left="200" bottom_delta="0" width="90" follows="top|left" label="Analyze" name="Decompose" height="20"/>
+ <button left="200" bottom_delta="0" width="90" follows="top|left" label="Cancel" name="decompose_cancel" visble="false" height="20"/>
+ </panel>
+
+
+ <!-- PHYSICS SIMPLIFICATION -->
+ <panel
+ follows="top|left"
+ name="physics simplification"
+ left="0"
+ top_pad="0"
+ width="300"
+ height="150"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
+ <text follows="left|top" bottom="40" height="30" left="10" font="SansSerifBig">
+ Step 2: Simplification
+ </text>
+
+ <text left="10" top_pad="5" height="15" width="140" follows="top|left">
+ Method:
+ </text>
+
+ <combo_box left_pad="5" height="20" width="120" follows="top|left" name="Simplify Method"/>
+
+ <slider left="10" name="Combine Quality" label="Passes:" label_width="120" width="270" follows="top|left" top_pad="10" height="20"/>
+ <slider name="Detail Scale" label="Detail Scale:" label_width="120" width="270" follows="top|left" top_pad="10" height="20"/>
+ <slider name="Retain%" label="Retain:" label_width="120" width="270" follows="top|left" bottom_delta="0" left_delta="0" visible="false" height="20"/>
+ <button left="190" width="90" follows="top|left" label="Simplify" name="Simplify" height="20"/>
+ <button left="190" bottom_delta="0" width="90" follows="top|left" label="Cancel" name="simplify_cancel" height="20"/>
+
+ </panel>
+
+ <!-- INFO PANEL -->
+ <panel
+ left="0"
+ top_pad="0"
+ width="300"
+ height="100"
+ follows="left|top"
+ name="physics info"
+ visible="true"
+ border="true"
+ bevel_style="none" bg_alpha_color="0 0 0 0" bg_opaque_color="0 0 0 0.3">
+
+ <slider name="physics_explode" follows="top|left" top="10" left="10" label="Preview Spread:" min_val="0.0" max_val="3.0" height="20" width="280"/>
+
+ <text follows="top|left" name="physics_triangles" top_pad="10" height="15" left="10">
+ Triangles: [TRIANGLES]
+ </text>
+ <text follows="top|left" name="physics_points" top_pad="5" height="15">
+ Vertices: [POINTS]
+ </text>
+ <text follows="top|left" name="physics_hulls" top_pad="5" height="15">
+ Hulls: [HULLS]
+ </text>
+
+
+ </panel>
+ </panel>
+
+ <!-- MODIFIERS PANEL -->
+ <panel
+ border="true"
+ label="Modifiers"
+ name="modifiers_panel">
+ <text left="10" width="90" bottom="30" follows="top|left" height="15">
+ Scale:
+ </text>
+ <text left_pad="5" width="140" follows="top|left" height="15">
+ Dimensions:
+ </text>
+
+ <spinner left="10" height="20" follows="top|left" width="80" top_pad="5" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/>
+
+ <text left_pad="20" height="15" name="import_dimensions" follows="top|left">
+ [X] x [Y] x [Z] m
+ </text>
+
+ <text left="10" top_pad="20" follows="top|left" height="15">
+ Include:
+ </text>
+
+ <check_box top_pad="5" name="upload_textures" height="15" follows="top|left" label="Textures"/>
+ <check_box top_pad="5" name="upload_skin" height="15" follows="top|left" label="Skin weight"/>
+ <check_box top_pad="5" left="20" name="upload_joints" height="15" follows="top|left" label="Joint positions"/>
+
+ <text left="10" top_pad="4" width="90" bottom="30" follows="top|left" height="15">
+ Pelvis Z Offset:
+ </text>
+
+ <spinner left="10" top_pad="4" height="20" follows="top|left" width="80" value="0.0" min_val="-3.00" max_val="3.0" name="pelvis_offset"/>
+
+ </panel>
+ </tab_container>
+
+ <!--
+ <button bottom_delta="0" left="10" width="120" name="auto fill" label="Generate LOD" tool_tip="Automatically generate levels of detail"/>
+ <button bottom_delta="0" left="140" width="120" name="smooth normals" label="Generate Normals" tool_tip="Regenerate normals based on mesh shape"/>
+ <button bottom_delta="0" left="260" width="120" name="consolidate" label="Consolidate" tool_tip="Combine similar submeshes (reduces number of submeshes)"/>
+ <button bottom_delta="30" left="260" width="120" name="scrub materials" label="Scrub Materials" tool_tip="Remove all material information (clear textures, set all colors to white)."/>
+
+ <spinner bottom_delta="0" left="140" width="120" height="16" initial_value="75" label_width="60" name="edge threshold" decimal_digits="0" min_val="0" max_val="180" increment="5" label="Hard Angle" tool_tip="Maximum angle that will be smoothed between triangles when using Generate Normals"/>
+
+ <text bottom_delta="30" follows="top|left" height="15" left="10" name="high_lod_label">
+ High LOD:
+ </text>
+ <combo_box bottom_delta="0" left="97" follows="left|top" height="18"
+ name="high detail combo" width="100" tool_tip="Specify mesh for this level of detail">
+ <combo_item name="high none" value="none">
+ None
+ </combo_item>
+ <combo_item name="high choose file" value="file">
+ Choose File...
+ </combo_item>
+ <combo_item name="high triangle limit" value="limit">
+ Triangle Limit
+ </combo_item>
+ </combo_box>
+ <spinner bottom_delta="-5" left="200" width="120" name="high limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/>
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="high info" width="300">
+ [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes.
+ [MESSAGE]
+ </text>
+
+ <text bottom_delta="35" follows="top|left" height="15" left="10" name="medium_lod_label">
+ Medium LOD:
+ </text>
+ <combo_box bottom_delta="0" left="97" follows="left|top" height="18"
+ name="medium detail combo" width="100" tool_tip="Specify mesh for this level of detail">
+ <combo_item name="medium none" value="none">
+ None
+ </combo_item>
+ <combo_item name="medium choose file" value="file">
+ Choose File...
+ </combo_item>
+ <combo_item name="medium triangle limit" value="limit">
+ Triangle Limit
+ </combo_item>
+ </combo_box>
+ <spinner bottom_delta="-5" left="200" width="120" name="medium limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/>
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="medium info" width="300">
+ [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes.
+ [MESSAGE]
+ </text>
+
+ <text bottom_delta="35" follows="top|left" height="15" left="10" name="low_lod_label">
+ Low LOD:
+ </text>
+ <combo_box bottom_delta="0" left="97" follows="left|top" height="18"
+ name="low detail combo" width="100" tool_tip="Specify mesh for this level of detail">
+ <combo_item name="low none" value="none">
+ None
+ </combo_item>
+ <combo_item name="low choose file" value="file">
+ Choose File...
+ </combo_item>
+ <combo_item name="low triangle limit" value="limit">
+ Triangle Limit
+ </combo_item>
+ </combo_box>
+ <spinner bottom_delta="-5" left="200" width="120" name="low limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/>
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="low info" width="300">
+ [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes
+ [MESSAGE]
+ </text>
+
+ <text bottom_delta="35" follows="top|left" height="15" left="10" name="lowest_lod_label">
+ Lowest LOD:
+ </text>
+ <combo_box bottom_delta="0" left="97" follows="left|top" height="18"
+ name="lowest detail combo" width="100" tool_tip="Specify mesh for this level of detail">
+ <combo_item name="lowest none" value="none">
+ None
+ </combo_item>
+ <combo_item name="lowest choose file" value="file">
+ Choose File...
+ </combo_item>
+ <combo_item name="lowest triangle limit" value="limit">
+ Triangle Limit
+ </combo_item>
+ </combo_box>
+ <spinner bottom_delta="-5" left="200" width="120" name="lowest limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/>
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="lowest info" width="300">
+ [TRIANGLES] Triangles, [VERTICES] Vertices, [SUBMESHES] Submeshes
+ [MESSAGE]
+ </text>
+
+ <text bottom_delta="35" follows="top|left" height="15" left="10" name="physics_lod_label">
+ Physical Shape:
+ </text>
+ <combo_box bottom_delta="0" left="97" follows="left|top" height="18"
+ name="physics detail combo" width="100">
+ <combo_item name="physics none" value="none">
+ None
+ </combo_item>
+ <combo_item name="physics choose file" value="file">
+ Choose File...
+ </combo_item>
+ <combo_item name="physics triangle limit" value="limit">
+ Triangle Limit...
+ </combo_item>
+ </combo_box>
+ <spinner bottom_delta="-5" left="200" width="90" name="physics limit" decimal_digits="0" increment="1" min_val="0" max_val="100" tool_tip="Triangle budget for this LOD"/>
+ <button bottom_delta="0" left="290" width="30" follows="left|top" height="20" label=">>"
+ name="decompose_btn" tool_tip="Create convex decomposition."/>
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="physics info" width="300">
+ [TRIANGLES] Triangles, [HULLS] Hulls, [POINTS] Points
+ </text>
+
+ <text bottom_delta="25" follows="top|left" height="15" left="10" name="include label" width="300">
+ Include:
+ </text>
+
+ <check_box bottom_delta="20" follow="bottom|left" height="20" label="Textures"
+ left="15" width="125" name="upload_textures" tool_tip="Upload associated textures "/>
+
+ <check_box bottom_delta="20" follow="bottom|left" height="20" label="Skin Weights"
+ left="15" width="125" name="upload_skin" tool_tip="Upload vertex skin weighting information."/>
+
+ <check_box bottom_delta="20" follow="bottom|left" height="20" label="Joint Positions"
+ left="15" width="125" name="upload_joints" tool_tip="Upload joint position information (will override avatar joint positions when mesh is worn)."/>
+
+
+ <button bottom_delta="25" follows="bottom|left" height="20" label="Upload"
+ left="15" name="ok_btn" width="125" tool_tip="Upload to simulator"/>
+
+ <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="description_label" text_color="1 0.82 0.46 1">
+ (No charge for upload during First Look)
+ </text>
+ <text bottom_delta="20" left="15" width="280" follows="top|left" height="15" name="upload_message">
+ [MESSAGE]
+ </text>
+
+ <spinner bottom_delta="20" label="Scale" left="15" width="120" name="debug scale" decimal_digits="3" increment="0.1" min_val="0" max_val="64" initial_value="1" tool_tip="Multiplier for incoming object scale. If incoming dimensions are very small or very large, modify this value to get dimensions into an acceptable range."/>
+ <text bottom_delta="30" left="15" width="280" follows="top|left" height="15" name="dimensions">
+ Model Dimensions: [X]m x [Y]m x [Z]m
+ </text>
+ -->
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_model_wizard.xml b/indra/newview/skins/default/xui/en/floater_model_wizard.xml index 47b2e5fd79..6c0fffa60e 100644 --- a/indra/newview/skins/default/xui/en/floater_model_wizard.xml +++ b/indra/newview/skins/default/xui/en/floater_model_wizard.xml @@ -1,1039 +1,1039 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - layout="topleft" - name="Model Wizard" - help_topic="model_wizard" - bg_opaque_image_overlay="0.5 0.5 0.5 1" - height="480" - save_rect="true" - title="UPLOAD MODEL WIZARD" - width="535"> - <button - top="32" - tab_stop="false" - left="410" - height="32" - name="upload_btn" - enabled="false" - label="5. Upload" - border="false" - image_unselected="BreadCrumbBtn_Right_Off" - image_selected="BreadCrumbBtn_Right_Press" - image_hover_unselected="BreadCrumbBtn_Right_Over" - image_disabled="BreadCrumbBtn_Right_Disabled" - image_disabled_selected="BreadCrumbBtn_Right_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Upload"/> - </button> - <button - top="32" - left="310" - height="32" - tab_stop="false" - name="review_btn" - label="4. Review" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Review"/> - </button> - <button - top="32" - left="210" - height="32" - name="physics2_btn" - label="3. Physics" - tab_stop="false" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Physics2"/> - </button> - <button - top="32" - left="210" - height="32" - name="physics_btn" - label="3. Physics" - tab_stop="false" - enabled="false" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Physics"/> - </button> - <button - top="32" - left="115" - name="optimize_btn" - label="2. Optimize" - tab_stop="false" - height="32" - border="false" - image_unselected="BreadCrumbBtn_Middle_Off" - image_selected="BreadCrumbBtn_Middle_Press" - image_hover_unselected="BreadCrumbBtn_Middle_Over" - image_disabled="BreadCrumbBtn_Middle_Disabled" - image_disabled_selected="BreadCrumbBtn_Middle_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Optimize"/> - </button> - <button - top="32" - left="15" - name="choose_file_btn" - tab_stop="false" - enabled="false" - label="1. Choose File" - height="32" - image_unselected="BreadCrumbBtn_Left_Off" - image_selected="BreadCrumbBtn_Left_Press" - image_hover_unselected="BreadCrumbBtn_Left_Over" - image_disabled="BreadCrumbBtn_Left_Disabled" - image_disabled_selected="BreadCrumbBtn_Left_Disabled" - width="110"> - <button.commit_callback - function="Wizard.Choose"/> - </button> - <panel - height="388" - top_pad="0" - name="choose_file_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - width="505" - name="header_panel" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - top="3" - name="header_text" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Upload Model - </text> - </panel> - <text - top_pad="14" - width="460" - height="20" - name="description" - font="SansSerifSmall" - layout="topleft" - word_wrap="true" - left_delta="5"> - This wizard will help you import mesh models to Second Life. First specify a file containing the model you wish to import. Second Life supports COLLADA (.dae) files. - </text> - <panel - top_delta="40" - left="15" - height="270" - width="505" - name="content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - type="string" - length="1" - text_color="White" - follows="left|top" - top="10" - height="10" - layout="topleft" - left_delta="10" - name="Cache location" - width="300"> - Filename: - </text> - <line_editor - border_style="line" - border_thickness="1" - follows="left|top" - font="SansSerifSmall" - height="20" - layout="topleft" - left_delta="0" - max_length="4096" - name="lod_file" - top_pad="5" - width="220" /> - <button - follows="left|top" - height="23" - label="Browse..." - label_selected="Browse..." - layout="topleft" - left_pad="5" - name="browse" - top_delta="-1" - width="85"> - </button> - <text - top_delta="-15" - width="200" - height="15" - font="SansSerifSmall" - layout="topleft" - text_color="White" - left_pad="19"> - Model Preview: - </text> - <!-- Placeholder panel for 3D preview render --> - <panel - left_delta="0" - top_pad="0" - name="preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border="true" - height="150" - follows="all" - width="150"> - </panel> - <text - top_pad="10" - width="130" - height="14" - left="340" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X: Y: Z: - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_dividers" - left_delta="41"> - | | - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left="356"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left="403"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left="450"/> - <text - top="100" - width="320" - height="15" - left="10" - text_color="White" - word_wrap="true"> - Note: - </text> - <text - top_pad="0" - width="320" - height="40" - left="10" - word_wrap="true"> -Advanced users familiar with 3d content creation tools may prefer to use the [secondlife:///app/floater/upload_model Advanced Mesh Import Window] . - </text> - </panel> - </panel> - - - <panel - height="388" - top_delta="0" - name="optimize_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Optimize - </text> - </panel> - <text - top_pad="14" - width="460" - height="20" - font="SansSerifSmall" - layout="topleft" - name="description" - word_wrap="true" - left_delta="5"> - This wizard has optimized your model to improve performance. You may adjust the results of the optimization process bellow or click Next to continue. - </text> - <panel - top_delta="40" - visible="false" - left="15" - height="270" - width="505" - name="content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text - top="20" - width="300" - height="12" - font="SansSerifBold" - left="112">Generating Level of Detail</text> - <progress_bar - name="optimize_progress_bar" - image_fill="model_wizard\progress_light.png" - color_bg="1 1 1 1" - color_bar="1 1 1 0.96" - follows="left|right|top" - width="260" - height="16" - image_bar="model_wizard\progress_bar_bg.png" - top_pad="14" - left="110"/> - <icon - top_pad="10" - left_delta="0" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="high_detail_text" - width="200" - height="14">Generate Level of Detail: High</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="medium_detail_text" - width="200" - height="14">Generate Level of Detail: Medium</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="low_detail_text" - width="200" - height="14">Generate Level of Detail: Low</text> - <icon - top_pad="10" - left_delta="-18" - width="13" - height="12" - image_name="model_wizard\check_mark.png"/> - <text - top_delta="0" - left_delta="18" - name="lowest_detail_text" - width="200" - height="14">Generate Level of Detail: Lowest</text> - </panel> - <panel - top_delta="0" - left_delta="0" - height="270" - width="505" - name="content2" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> - Model Preview: - </text> - <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22" - name="preview_lod_combo2" width="90" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <panel - left="10" - top_pad="5" - name="preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="185" - follows="all" - width="185"> - </panel> - <text top="45" left="214" text_color="White" font="SansSerifSmallBold" halign="center" width="110" height="30" wrap="true">Higher Performance</text> - <text top="75" left="204" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text> - <text top="45" left="378" text_color="White" font="SansSerifSmallBold" halign="center" width="90" height="30" wrap="true">Higher Accuracy</text> - <text top="75" left="364" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text> - - <slider - follows="left|top" - height="20" - increment="1" - layout="topleft" - left="204" - max_val="3" - initial_value="2" - min_val="0" - name="accuracy_slider" - show_text="false" - top="130" - width="290" /> - <text - font="SansSerifSmall" - top_pad="0" - width="300" - left_delta="6" - height="4">' - </text> - - - <icon - top_pad="14" - left_delta="0" - width="280" - height="2" - image_name="model_wizard\divider_line.png"/> - - <text top_delta="20" width="200" text_color="White" left_delta="50" name="streaming cost" height="20">Resource Cost: [COST]</text> - <text - top_pad="15" - width="130" - height="14" - left="10" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X: Y: Z: - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_dividers" - left_delta="41"> - | | - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left_delta="-25"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left_delta="46"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left_delta="46"/> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="physics_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="header_text" - top="3" - height="10" - font="SansSerifBig" - text_color="White" - layout="topleft"> - Physics - </text> - </panel> - <text - top_pad="10" - width="474" - height="50" - font="SansSerifSmall" - layout="topleft" - name="description" - word_wrap="true" - left_delta="5"> - The wizard will create a physical shape, which determines how the object interacts with other objects and avatars. Set the slider to the detail level most appropriate for how your object will be used: - </text> - <panel - top_delta="44" - left="15" - height="270" - width="505" - name="content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="15" left="20" text_color="White" font="SansSerifSmallBold" width="110" height="30" wrap="true" halign="center">Higher Performance</text> - <text top="45" left="10" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text> - <text top="15" left="372" text_color="White" font="SansSerifSmallBold" width="90" height="30" wrap="true" halign="center">Higher Accuracy</text> - <text top="45" left="360" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text> - - <slider - follows="left|top" - height="22" - increment=".1" - layout="topleft" - left="20" - max_val="1" - initial_value="0.5" - min_val="0" - name="physics_slider" - show_text="false" - top="90" - width="440" /> - <text - font="SansSerifSmall" - top_pad="0" - width="500" - left_delta="6" - height="4">' ' ' ' ' ' ' ' ' ' '</text> - <text top_pad="10" width="110" halign="center" word_wrap="true" left="25" height="40">Recommended for solid objects</text> - <text top_delta="0" width="110" halign="center" word_wrap="true" left="190" height="40">Recommended for buildings</text> - <text top_delta="0" width="110" halign="center" word_wrap="true" left="350" height="40">Recommended for vehicles</text> - - - <icon - top_pad="5" - left="15" - width="470" - height="2" - image_name="model_wizard\divider_line.png"/> - - <text top_delta="30" width="180" text_color="White" left="160" name="streaming cost" height="20">Resource Cost: [COST]</text> - - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="physics2_panel" - visible="true" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="header_text" - text_color="White" - top="3" - height="10" - font="SansSerifBig" - layout="topleft"> - Physics - </text> - </panel> - <text - top_pad="14" - width="475" - height="50" - font="SansSerifSmall" - layout="topleft" - name="description" - word_wrap="true" - left_delta="5"> - Preview the physics shape below then click Next to continue. To modify the physics shape, click the Back button. - </text> - <panel - top_delta="40" - left="15" - height="270" - width="505" - name="content" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true"> - <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> - Model Preview: - </text> - <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22" - name="preview_lod_combo3" width="90" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <panel - left="10" - top_pad="10" - name="preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="190" - follows="all" - width="190"> - </panel> - <text - top_pad="8" - width="130" - height="14" - left="10" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X: Y: Z: - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_dividers" - left_delta="41"> - | | - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left_delta="-25"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left_delta="46"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left_delta="46"/> - <text top="60" width="180" text_color="White" left="225" name="streaming cost" height="20">Resource Cost: [COST]</text> - </panel> - </panel> - - <panel - height="388" - top_delta="0" - name="review_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="header_text" - text_color="White" - top="3" - height="10" - font="SansSerifBig" - layout="topleft"> - Review - </text> - </panel> - <text - top_pad="14" - width="470" - height="24" - font="SansSerifSmall" - layout="topleft" - name="description" - word_wrap="true" - left_delta="5"> - Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload. - </text> - <icon - top_pad="10" - left="20" - width="495" - height="2" - image_name="model_wizard\divider_line.png"/> - <panel - top_pad="5" - left="15" - height="270" - width="505" - name="content"> - <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label"> - Model Preview: - </text> - <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22" - name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render"> - <combo_item name="high"> - High - </combo_item> - <combo_item name="medium"> - Medium - </combo_item> - <combo_item name="low"> - Low - </combo_item> - <combo_item name="lowest"> - Lowest - </combo_item> - </combo_box> - <panel - left="10" - top_pad="10" - name="preview_panel" - bevel_style="none" - highlight_light_color="0.09 0.09 0.09 1" - border_style="line" - border="true" - height="190" - follows="all" - width="190"> - </panel> - <text - top_pad="8" - width="130" - height="14" - left="10" - text_color="White" - word_wrap="true"> - Dimensions (meters): - </text> - <text - top_pad="0" - width="160" - height="15" - font="SansSerifSmallBold" - text_color="White" - name="dimensions" - left_delta="0"> - X: Y: Z: - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_dividers" - left_delta="41"> - | | - </text> - <text - top_delta="0" - width="160" - height="15" - name="dimension_x" - left_delta="-25"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_y" - left_delta="46"/> - <text - top_delta="0" - width="160" - height="15" - name="dimension_z" - left_delta="46"/> - </panel> - <text - width="300" - height="12" - top="125" - name="streaming cost" - left="230" - font="SansSerifSmallBold" - text_color="White">Resource Cost: [COST]</text> - <text - width="285" - height="30" - top_pad="0" - left_delta="0" - word_wrap="true" - font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text> - <text - width="300" - height="12" - name="physics cost" - top_pad="10" - left_delta="0" - font="SansSerifSmallBold" - text_color="White">Physics Cost: [COST]</text> - <text - width="285" - height="30" - top_pad="0" - left_delta="0" - word_wrap="true" - font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text> - <text - width="200" - height="12" - top_pad="10" - left_delta="0" - font="SansSerifSmallBold" - text_color="White">Upload Fee:</text> - <text - width="285" - height="26" - top_pad="0" - left_delta="0" - word_wrap="true" - font="SansSerifItalic">This is the amount the upload will cost.</text> - <check_box - height="16" - layout="topleft" - left_delta="0" - name="confirm_checkbox" - top_pad="15" - width="16" /> - <text - height="100" - width="240" - word_wrap="true" - left_delta="25" - top_delta="0">I confirm that I have the appropriate rights to the material contained in this model. [secondlife:///app/floater/learn_more Learn more]</text> - </panel> - - - - - <panel - height="388" - top_delta="0" - name="upload_panel" - visible="false" - width="535" - left="0"> - <panel - height="22" - top_pad="15" - name="header_panel" - width="505" - bg_opaque_color="DkGray2" - background_visible="true" - background_opaque="true" - left="15"> - <text - width="200" - left="10" - name="header_text" - top="3" - text_color="White" - height="10" - font="SansSerifBig" - layout="topleft"> - Upload Complete! - </text> - </panel> - <text - top_pad="14" - width="474" - height="20" - font="SansSerifSmall" - layout="topleft" - name="description" - word_wrap="true" - left_delta="5"> - Congratulations! Your model has been sucessfully uploaded. You will find the model in the Objects folder in your inventory. - </text> - <icon - top_pad="15" - left_delta="0" - width="495" - height="2" - image_name="model_wizard\divider_line.png"/> - </panel> - - - - <button - top="440" - right="-245" - width="90" - height="22" - name="back" - label="<< Back" /> - <button - top_delta="0" - right="-150" - width="90" - height="22" - name="next" - label="Next >> " /> - <button - top_delta="0" - right="-150" - width="90" - height="22" - visible="false" - name="upload" - tool_tip="Upload to simulator" - label="Upload" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="cancel" - label="Cancel" /> - <button - top_delta="0" - right="-15" - width="90" - height="22" - name="close" - visible="false" - label="Close" /> - <spinner visible="false" left="10" height="20" follows="top|left" width="80" top_pad="-50" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/> - - <string name="status_idle">Idle</string> - <string name="status_reading_file">Loading...</string> - <string name="status_generating_meshes">Generating Meshes...</string> - <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string> - <string name="high">High</string> - <string name="medium">Medium</string> - <string name="low">Low</string> - <string name="lowest">Lowest</string> - <string name="mesh_status_good">Ship it!</string> - <string name="mesh_status_na">N/A</string> - <string name="mesh_status_none">None</string> - <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string> - <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string> - <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string> - <string name="mesh_status_missing_lod">Missing required level of detail.</string> - <string name="layer_all">All</string> - <!-- Text to display in physics layer combo box for "all layers" --> - -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ layout="topleft"
+ name="Model Wizard"
+ help_topic="model_wizard"
+ bg_opaque_image_overlay="0.5 0.5 0.5 1"
+ height="480"
+ save_rect="true"
+ title="UPLOAD MODEL WIZARD"
+ width="535">
+ <button
+ top="32"
+ tab_stop="false"
+ left="410"
+ height="32"
+ name="upload_btn"
+ enabled="false"
+ label="5. Upload"
+ border="false"
+ image_unselected="BreadCrumbBtn_Right_Off"
+ image_selected="BreadCrumbBtn_Right_Press"
+ image_hover_unselected="BreadCrumbBtn_Right_Over"
+ image_disabled="BreadCrumbBtn_Right_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Right_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Upload"/>
+ </button>
+ <button
+ top="32"
+ left="310"
+ height="32"
+ tab_stop="false"
+ name="review_btn"
+ label="4. Review"
+ enabled="false"
+ border="false"
+ image_unselected="BreadCrumbBtn_Middle_Off"
+ image_selected="BreadCrumbBtn_Middle_Press"
+ image_hover_unselected="BreadCrumbBtn_Middle_Over"
+ image_disabled="BreadCrumbBtn_Middle_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Middle_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Review"/>
+ </button>
+ <button
+ top="32"
+ left="210"
+ height="32"
+ name="physics2_btn"
+ label="3. Physics"
+ tab_stop="false"
+ enabled="false"
+ border="false"
+ image_unselected="BreadCrumbBtn_Middle_Off"
+ image_selected="BreadCrumbBtn_Middle_Press"
+ image_hover_unselected="BreadCrumbBtn_Middle_Over"
+ image_disabled="BreadCrumbBtn_Middle_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Middle_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Physics2"/>
+ </button>
+ <button
+ top="32"
+ left="210"
+ height="32"
+ name="physics_btn"
+ label="3. Physics"
+ tab_stop="false"
+ enabled="false"
+ border="false"
+ image_unselected="BreadCrumbBtn_Middle_Off"
+ image_selected="BreadCrumbBtn_Middle_Press"
+ image_hover_unselected="BreadCrumbBtn_Middle_Over"
+ image_disabled="BreadCrumbBtn_Middle_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Middle_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Physics"/>
+ </button>
+ <button
+ top="32"
+ left="115"
+ name="optimize_btn"
+ label="2. Optimize"
+ tab_stop="false"
+ height="32"
+ border="false"
+ image_unselected="BreadCrumbBtn_Middle_Off"
+ image_selected="BreadCrumbBtn_Middle_Press"
+ image_hover_unselected="BreadCrumbBtn_Middle_Over"
+ image_disabled="BreadCrumbBtn_Middle_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Middle_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Optimize"/>
+ </button>
+ <button
+ top="32"
+ left="15"
+ name="choose_file_btn"
+ tab_stop="false"
+ enabled="false"
+ label="1. Choose File"
+ height="32"
+ image_unselected="BreadCrumbBtn_Left_Off"
+ image_selected="BreadCrumbBtn_Left_Press"
+ image_hover_unselected="BreadCrumbBtn_Left_Over"
+ image_disabled="BreadCrumbBtn_Left_Disabled"
+ image_disabled_selected="BreadCrumbBtn_Left_Disabled"
+ width="110">
+ <button.commit_callback
+ function="Wizard.Choose"/>
+ </button>
+ <panel
+ height="388"
+ top_pad="0"
+ name="choose_file_panel"
+ visible="false"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ width="505"
+ name="header_panel"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ top="3"
+ name="header_text"
+ text_color="White"
+ height="10"
+ font="SansSerifBig"
+ layout="topleft">
+ Upload Model
+ </text>
+ </panel>
+ <text
+ top_pad="14"
+ width="460"
+ height="20"
+ name="description"
+ font="SansSerifSmall"
+ layout="topleft"
+ word_wrap="true"
+ left_delta="5">
+ This wizard will help you import mesh models to Second Life. First specify a file containing the model you wish to import. Second Life supports COLLADA (.dae) files.
+ </text>
+ <panel
+ top_delta="40"
+ left="15"
+ height="270"
+ width="505"
+ name="content"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true">
+ <text
+ type="string"
+ length="1"
+ text_color="White"
+ follows="left|top"
+ top="10"
+ height="10"
+ layout="topleft"
+ left_delta="10"
+ name="Cache location"
+ width="300">
+ Filename:
+ </text>
+ <line_editor
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ font="SansSerifSmall"
+ height="20"
+ layout="topleft"
+ left_delta="0"
+ max_length="4096"
+ name="lod_file"
+ top_pad="5"
+ width="220" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Browse..."
+ label_selected="Browse..."
+ layout="topleft"
+ left_pad="5"
+ name="browse"
+ top_delta="-1"
+ width="85">
+ </button>
+ <text
+ top_delta="-15"
+ width="200"
+ height="15"
+ font="SansSerifSmall"
+ layout="topleft"
+ text_color="White"
+ left_pad="19">
+ Model Preview:
+ </text>
+ <!-- Placeholder panel for 3D preview render -->
+ <panel
+ left_delta="0"
+ top_pad="0"
+ name="preview_panel"
+ bevel_style="none"
+ highlight_light_color="0.09 0.09 0.09 1"
+ border="true"
+ height="150"
+ follows="all"
+ width="150">
+ </panel>
+ <text
+ top_pad="10"
+ width="130"
+ height="14"
+ left="340"
+ text_color="White"
+ word_wrap="true">
+ Dimensions (meters):
+ </text>
+ <text
+ top_pad="0"
+ width="160"
+ height="15"
+ font="SansSerifSmallBold"
+ text_color="White"
+ name="dimensions"
+ left_delta="0">
+ X: Y: Z:
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_dividers"
+ left_delta="41">
+ | |
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_x"
+ left="356"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_y"
+ left="403"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_z"
+ left="450"/>
+ <text
+ top="100"
+ width="320"
+ height="15"
+ left="10"
+ text_color="White"
+ word_wrap="true">
+ Note:
+ </text>
+ <text
+ top_pad="0"
+ width="320"
+ height="40"
+ left="10"
+ word_wrap="true">
+Advanced users familiar with 3d content creation tools may prefer to use the [secondlife:///app/floater/upload_model Advanced Mesh Import Window] .
+ </text>
+ </panel>
+ </panel>
+
+
+ <panel
+ height="388"
+ top_delta="0"
+ name="optimize_panel"
+ visible="false"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ name="header_panel"
+ width="505"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ name="header_text"
+ top="3"
+ text_color="White"
+ height="10"
+ font="SansSerifBig"
+ layout="topleft">
+ Optimize
+ </text>
+ </panel>
+ <text
+ top_pad="14"
+ width="460"
+ height="20"
+ font="SansSerifSmall"
+ layout="topleft"
+ name="description"
+ word_wrap="true"
+ left_delta="5">
+ This wizard has optimized your model to improve performance. You may adjust the results of the optimization process bellow or click Next to continue.
+ </text>
+ <panel
+ top_delta="40"
+ visible="false"
+ left="15"
+ height="270"
+ width="505"
+ name="content"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true">
+ <text
+ top="20"
+ width="300"
+ height="12"
+ font="SansSerifBold"
+ left="112">Generating Level of Detail</text>
+ <progress_bar
+ name="optimize_progress_bar"
+ image_fill="model_wizard\progress_light.png"
+ color_bg="1 1 1 1"
+ color_bar="1 1 1 0.96"
+ follows="left|right|top"
+ width="260"
+ height="16"
+ image_bar="model_wizard\progress_bar_bg.png"
+ top_pad="14"
+ left="110"/>
+ <icon
+ top_pad="10"
+ left_delta="0"
+ width="13"
+ height="12"
+ image_name="model_wizard\check_mark.png"/>
+ <text
+ top_delta="0"
+ left_delta="18"
+ name="high_detail_text"
+ width="200"
+ height="14">Generate Level of Detail: High</text>
+ <icon
+ top_pad="10"
+ left_delta="-18"
+ width="13"
+ height="12"
+ image_name="model_wizard\check_mark.png"/>
+ <text
+ top_delta="0"
+ left_delta="18"
+ name="medium_detail_text"
+ width="200"
+ height="14">Generate Level of Detail: Medium</text>
+ <icon
+ top_pad="10"
+ left_delta="-18"
+ width="13"
+ height="12"
+ image_name="model_wizard\check_mark.png"/>
+ <text
+ top_delta="0"
+ left_delta="18"
+ name="low_detail_text"
+ width="200"
+ height="14">Generate Level of Detail: Low</text>
+ <icon
+ top_pad="10"
+ left_delta="-18"
+ width="13"
+ height="12"
+ image_name="model_wizard\check_mark.png"/>
+ <text
+ top_delta="0"
+ left_delta="18"
+ name="lowest_detail_text"
+ width="200"
+ height="14">Generate Level of Detail: Lowest</text>
+ </panel>
+ <panel
+ top_delta="0"
+ left_delta="0"
+ height="270"
+ width="505"
+ name="content2"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true">
+ <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label">
+ Model Preview:
+ </text>
+ <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22"
+ name="preview_lod_combo2" width="90" tool_tip="LOD to view in preview render">
+ <combo_item name="high">
+ High
+ </combo_item>
+ <combo_item name="medium">
+ Medium
+ </combo_item>
+ <combo_item name="low">
+ Low
+ </combo_item>
+ <combo_item name="lowest">
+ Lowest
+ </combo_item>
+ </combo_box>
+ <panel
+ left="10"
+ top_pad="5"
+ name="preview_panel"
+ bevel_style="none"
+ highlight_light_color="0.09 0.09 0.09 1"
+ border_style="line"
+ border="true"
+ height="185"
+ follows="all"
+ width="185">
+ </panel>
+ <text top="45" left="214" text_color="White" font="SansSerifSmallBold" halign="center" width="110" height="30" wrap="true">Higher Performance</text>
+ <text top="75" left="204" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
+ <text top="45" left="378" text_color="White" font="SansSerifSmallBold" halign="center" width="90" height="30" wrap="true">Higher Accuracy</text>
+ <text top="75" left="364" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
+
+ <slider
+ follows="left|top"
+ height="20"
+ increment="1"
+ layout="topleft"
+ left="204"
+ max_val="3"
+ initial_value="2"
+ min_val="0"
+ name="accuracy_slider"
+ show_text="false"
+ top="130"
+ width="290" />
+ <text
+ font="SansSerifSmall"
+ top_pad="0"
+ width="300"
+ left_delta="6"
+ height="4">'
+ </text>
+
+
+ <icon
+ top_pad="14"
+ left_delta="0"
+ width="280"
+ height="2"
+ image_name="model_wizard\divider_line.png"/>
+
+ <text top_delta="20" width="200" text_color="White" left_delta="50" name="streaming cost" height="20">Resource Cost: [COST]</text>
+ <text
+ top_pad="15"
+ width="130"
+ height="14"
+ left="10"
+ text_color="White"
+ word_wrap="true">
+ Dimensions (meters):
+ </text>
+ <text
+ top_pad="0"
+ width="160"
+ height="15"
+ font="SansSerifSmallBold"
+ text_color="White"
+ name="dimensions"
+ left_delta="0">
+ X: Y: Z:
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_dividers"
+ left_delta="41">
+ | |
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_x"
+ left_delta="-25"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_y"
+ left_delta="46"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_z"
+ left_delta="46"/>
+ </panel>
+ </panel>
+
+ <panel
+ height="388"
+ top_delta="0"
+ name="physics_panel"
+ visible="false"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ name="header_panel"
+ width="505"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ name="header_text"
+ top="3"
+ height="10"
+ font="SansSerifBig"
+ text_color="White"
+ layout="topleft">
+ Physics
+ </text>
+ </panel>
+ <text
+ top_pad="10"
+ width="474"
+ height="50"
+ font="SansSerifSmall"
+ layout="topleft"
+ name="description"
+ word_wrap="true"
+ left_delta="5">
+ The wizard will create a physical shape, which determines how the object interacts with other objects and avatars. Set the slider to the detail level most appropriate for how your object will be used:
+ </text>
+ <panel
+ top_delta="44"
+ left="15"
+ height="270"
+ width="505"
+ name="content"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true">
+ <text top="15" left="20" text_color="White" font="SansSerifSmallBold" width="110" height="30" wrap="true" halign="center">Higher Performance</text>
+ <text top="45" left="10" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">Faster rendering but less detailed; lowers Resource (prim) cost.</text>
+ <text top="15" left="372" text_color="White" font="SansSerifSmallBold" width="90" height="30" wrap="true" halign="center">Higher Accuracy</text>
+ <text top="45" left="360" halign="center" width="130" word_wrap="true" font="SansSerifSmall" height="80">More detailed model but slower; increases Resource (prim) cost.</text>
+
+ <slider
+ follows="left|top"
+ height="22"
+ increment=".1"
+ layout="topleft"
+ left="20"
+ max_val="1"
+ initial_value="0.5"
+ min_val="0"
+ name="physics_slider"
+ show_text="false"
+ top="90"
+ width="440" />
+ <text
+ font="SansSerifSmall"
+ top_pad="0"
+ width="500"
+ left_delta="6"
+ height="4">' ' ' ' ' ' ' ' ' ' '</text>
+ <text top_pad="10" width="110" halign="center" word_wrap="true" left="25" height="40">Recommended for solid objects</text>
+ <text top_delta="0" width="110" halign="center" word_wrap="true" left="190" height="40">Recommended for buildings</text>
+ <text top_delta="0" width="110" halign="center" word_wrap="true" left="350" height="40">Recommended for vehicles</text>
+
+
+ <icon
+ top_pad="5"
+ left="15"
+ width="470"
+ height="2"
+ image_name="model_wizard\divider_line.png"/>
+
+ <text top_delta="30" width="180" text_color="White" left="160" name="streaming cost" height="20">Resource Cost: [COST]</text>
+
+ </panel>
+ </panel>
+
+ <panel
+ height="388"
+ top_delta="0"
+ name="physics2_panel"
+ visible="true"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ name="header_panel"
+ width="505"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ name="header_text"
+ text_color="White"
+ top="3"
+ height="10"
+ font="SansSerifBig"
+ layout="topleft">
+ Physics
+ </text>
+ </panel>
+ <text
+ top_pad="14"
+ width="475"
+ height="50"
+ font="SansSerifSmall"
+ layout="topleft"
+ name="description"
+ word_wrap="true"
+ left_delta="5">
+ Preview the physics shape below then click Next to continue. To modify the physics shape, click the Back button.
+ </text>
+ <panel
+ top_delta="40"
+ left="15"
+ height="270"
+ width="505"
+ name="content"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true">
+ <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label">
+ Model Preview:
+ </text>
+ <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22"
+ name="preview_lod_combo3" width="90" tool_tip="LOD to view in preview render">
+ <combo_item name="high">
+ High
+ </combo_item>
+ <combo_item name="medium">
+ Medium
+ </combo_item>
+ <combo_item name="low">
+ Low
+ </combo_item>
+ <combo_item name="lowest">
+ Lowest
+ </combo_item>
+ </combo_box>
+ <panel
+ left="10"
+ top_pad="10"
+ name="preview_panel"
+ bevel_style="none"
+ highlight_light_color="0.09 0.09 0.09 1"
+ border_style="line"
+ border="true"
+ height="190"
+ follows="all"
+ width="190">
+ </panel>
+ <text
+ top_pad="8"
+ width="130"
+ height="14"
+ left="10"
+ text_color="White"
+ word_wrap="true">
+ Dimensions (meters):
+ </text>
+ <text
+ top_pad="0"
+ width="160"
+ height="15"
+ font="SansSerifSmallBold"
+ text_color="White"
+ name="dimensions"
+ left_delta="0">
+ X: Y: Z:
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_dividers"
+ left_delta="41">
+ | |
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_x"
+ left_delta="-25"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_y"
+ left_delta="46"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_z"
+ left_delta="46"/>
+ <text top="60" width="180" text_color="White" left="225" name="streaming cost" height="20">Resource Cost: [COST]</text>
+ </panel>
+ </panel>
+
+ <panel
+ height="388"
+ top_delta="0"
+ name="review_panel"
+ visible="false"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ name="header_panel"
+ width="505"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ name="header_text"
+ text_color="White"
+ top="3"
+ height="10"
+ font="SansSerifBig"
+ layout="topleft">
+ Review
+ </text>
+ </panel>
+ <text
+ top_pad="14"
+ width="470"
+ height="24"
+ font="SansSerifSmall"
+ layout="topleft"
+ name="description"
+ word_wrap="true"
+ left_delta="5">
+ Review the details below then click. Upload to upload your model. Your L$ balance will be charged when you click Upload.
+ </text>
+ <icon
+ top_pad="10"
+ left="20"
+ width="495"
+ height="2"
+ image_name="model_wizard\divider_line.png"/>
+ <panel
+ top_pad="5"
+ left="15"
+ height="270"
+ width="505"
+ name="content">
+ <text top="10" left="10" width="85" text_color="White" follows="left|top" height="15" name="lod_label">
+ Model Preview:
+ </text>
+ <combo_box left_pad="5" top_delta="-5" follows="left|top" list_position="below" height="22"
+ name="preview_lod_combo" width="90" tool_tip="LOD to view in preview render">
+ <combo_item name="high">
+ High
+ </combo_item>
+ <combo_item name="medium">
+ Medium
+ </combo_item>
+ <combo_item name="low">
+ Low
+ </combo_item>
+ <combo_item name="lowest">
+ Lowest
+ </combo_item>
+ </combo_box>
+ <panel
+ left="10"
+ top_pad="10"
+ name="preview_panel"
+ bevel_style="none"
+ highlight_light_color="0.09 0.09 0.09 1"
+ border_style="line"
+ border="true"
+ height="190"
+ follows="all"
+ width="190">
+ </panel>
+ <text
+ top_pad="8"
+ width="130"
+ height="14"
+ left="10"
+ text_color="White"
+ word_wrap="true">
+ Dimensions (meters):
+ </text>
+ <text
+ top_pad="0"
+ width="160"
+ height="15"
+ font="SansSerifSmallBold"
+ text_color="White"
+ name="dimensions"
+ left_delta="0">
+ X: Y: Z:
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_dividers"
+ left_delta="41">
+ | |
+ </text>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_x"
+ left_delta="-25"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_y"
+ left_delta="46"/>
+ <text
+ top_delta="0"
+ width="160"
+ height="15"
+ name="dimension_z"
+ left_delta="46"/>
+ </panel>
+ <text
+ width="300"
+ height="12"
+ top="125"
+ name="streaming cost"
+ left="230"
+ font="SansSerifSmallBold"
+ text_color="White">Resource Cost: [COST]</text>
+ <text
+ width="285"
+ height="30"
+ top_pad="0"
+ left_delta="0"
+ word_wrap="true"
+ font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text>
+ <text
+ width="300"
+ height="12"
+ name="physics cost"
+ top_pad="10"
+ left_delta="0"
+ font="SansSerifSmallBold"
+ text_color="White">Physics Cost: [COST]</text>
+ <text
+ width="285"
+ height="30"
+ top_pad="0"
+ left_delta="0"
+ word_wrap="true"
+ font="SansSerifItalic">This is the cost to your Region's prim/object limit, at default scale</text>
+ <text
+ width="200"
+ height="12"
+ top_pad="10"
+ left_delta="0"
+ font="SansSerifSmallBold"
+ text_color="White">Upload Fee:</text>
+ <text
+ width="285"
+ height="26"
+ top_pad="0"
+ left_delta="0"
+ word_wrap="true"
+ font="SansSerifItalic">This is the amount the upload will cost.</text>
+ <check_box
+ height="16"
+ layout="topleft"
+ left_delta="0"
+ name="confirm_checkbox"
+ top_pad="15"
+ width="16" />
+ <text
+ height="100"
+ width="240"
+ word_wrap="true"
+ left_delta="25"
+ top_delta="0">I confirm that I have the appropriate rights to the material contained in this model. [secondlife:///app/floater/learn_more Learn more]</text>
+ </panel>
+
+
+
+
+ <panel
+ height="388"
+ top_delta="0"
+ name="upload_panel"
+ visible="false"
+ width="535"
+ left="0">
+ <panel
+ height="22"
+ top_pad="15"
+ name="header_panel"
+ width="505"
+ bg_opaque_color="DkGray2"
+ background_visible="true"
+ background_opaque="true"
+ left="15">
+ <text
+ width="200"
+ left="10"
+ name="header_text"
+ top="3"
+ text_color="White"
+ height="10"
+ font="SansSerifBig"
+ layout="topleft">
+ Upload Complete!
+ </text>
+ </panel>
+ <text
+ top_pad="14"
+ width="474"
+ height="20"
+ font="SansSerifSmall"
+ layout="topleft"
+ name="description"
+ word_wrap="true"
+ left_delta="5">
+ Congratulations! Your model has been sucessfully uploaded. You will find the model in the Objects folder in your inventory.
+ </text>
+ <icon
+ top_pad="15"
+ left_delta="0"
+ width="495"
+ height="2"
+ image_name="model_wizard\divider_line.png"/>
+ </panel>
+
+
+
+ <button
+ top="440"
+ right="-245"
+ width="90"
+ height="22"
+ name="back"
+ label="<< Back" />
+ <button
+ top_delta="0"
+ right="-150"
+ width="90"
+ height="22"
+ name="next"
+ label="Next >> " />
+ <button
+ top_delta="0"
+ right="-150"
+ width="90"
+ height="22"
+ visible="false"
+ name="upload"
+ tool_tip="Upload to simulator"
+ label="Upload" />
+ <button
+ top_delta="0"
+ right="-15"
+ width="90"
+ height="22"
+ name="cancel"
+ label="Cancel" />
+ <button
+ top_delta="0"
+ right="-15"
+ width="90"
+ height="22"
+ name="close"
+ visible="false"
+ label="Close" />
+ <spinner visible="false" left="10" height="20" follows="top|left" width="80" top_pad="-50" value="1.0" min_val="0.01" max_val="64.0" name="import_scale"/>
+
+ <string name="status_idle">Idle</string>
+ <string name="status_reading_file">Loading...</string>
+ <string name="status_generating_meshes">Generating Meshes...</string>
+ <string name="status_vertex_number_overflow">Error: Vertex number is more than 65534, aborted!</string>
+ <string name="high">High</string>
+ <string name="medium">Medium</string>
+ <string name="low">Low</string>
+ <string name="lowest">Lowest</string>
+ <string name="mesh_status_good">Ship it!</string>
+ <string name="mesh_status_na">N/A</string>
+ <string name="mesh_status_none">None</string>
+ <string name="mesh_status_submesh_mismatch">Levels of detail have a different number of textureable faces.</string>
+ <string name="mesh_status_mesh_mismatch">Levels of detail have a different number of mesh instances.</string>
+ <string name="mesh_status_too_many_vertices">Level of detail has too many vertices.</string>
+ <string name="mesh_status_missing_lod">Missing required level of detail.</string>
+ <string name="layer_all">All</string>
+ <!-- Text to display in physics layer combo box for "all layers" -->
+
+</floater>
diff --git a/indra/newview/skins/default/xui/en/floater_tools.xml b/indra/newview/skins/default/xui/en/floater_tools.xml index 40bf7bfed7..e342b441ac 100644 --- a/indra/newview/skins/default/xui/en/floater_tools.xml +++ b/indra/newview/skins/default/xui/en/floater_tools.xml @@ -1,3194 +1,3194 @@ -<?xml version="1.0" encoding="utf-8" standalone="yes" ?> -<floater - legacy_header_height="18" - follows="left|top|right" - height="580" - layout="topleft" - bg_opaque_image="Window_NoTitle_Foreground" - bg_alpha_image="Window_NoTitle_Background" - name="toolbox floater" - help_topic="toolbox_floater" - save_rect="true" - short_title="BUILD TOOLS" - single_instance="true" - save_visibility="true" - sound_flags="0" - width="295"> - <floater.string - name="status_rotate"> - Drag colored bands to rotate object - </floater.string> - <floater.string - name="status_scale"> - Click and drag to stretch selected side - </floater.string> - <floater.string - name="status_move"> - Drag to move, shift-drag to copy - </floater.string> - <floater.string - name="status_modifyland"> - Click and hold to modify land - </floater.string> - <floater.string - name="status_camera"> - Click and drag to move camera - </floater.string> - <floater.string - name="status_grab"> - Drag to move, Ctrl to lift, Ctrl+Shift to rotate - </floater.string> - <floater.string - name="status_place"> - Click inworld to build - </floater.string> - <floater.string - name="status_selectland"> - Click and drag to select land - </floater.string> - <floater.string - name="grid_screen_text"> - Screen - </floater.string> - <floater.string - name="grid_local_text"> - Local - </floater.string> - <floater.string - name="grid_world_text"> - World - </floater.string> - <floater.string - name="grid_reference_text"> - Reference - </floater.string> - <floater.string - name="grid_attachment_text"> - Attachment - </floater.string> - <button - follows="left|top" - height="25" - image_bottom_pad="1" - image_overlay="Tool_Zoom" - image_selected="PushButton_Selected_Press" - layout="topleft" - left="10" - name="button focus" - tool_tip="Focus" - width="35"> - <button.commit_callback - function="BuildTool.setTool" - parameter="Focus" /> - </button> - <button - follows="left|top" - height="25" - image_bottom_pad="1" - image_overlay="Tool_Grab" - image_selected="PushButton_Selected_Press" - layout="topleft" - left_pad="10" - name="button move" - tool_tip="Move" - width="35"> - <button.commit_callback - function="BuildTool.setTool" - parameter="Move" /> - </button> - <button - follows="left|top" - height="25" - image_bottom_pad="1" - image_overlay="Tool_Face" - image_selected="PushButton_Selected_Press" - layout="topleft" - left_pad="10" - name="button edit" - tool_tip="Edit" - width="35"> - <button.commit_callback - function="BuildTool.setTool" - parameter="Edit" /> - </button> - <button - follows="left|top" - height="25" - image_bottom_pad="1" - image_overlay="Tool_Create" - image_selected="PushButton_Selected_Press" - layout="topleft" - left_pad="10" - name="button create" - tool_tip="Create" - width="35"> - <button.commit_callback - function="BuildTool.setTool" - parameter="Create" /> - </button> - <button - follows="left|top" - height="25" - image_bottom_pad="1" - image_overlay="Tool_Dozer" - image_selected="PushButton_Selected_Press" - layout="topleft" - left_pad="10" - name="button land" - tool_tip="Land" - width="35"> - <button.commit_callback - function="BuildTool.setTool" - parameter="Land" /> - </button> - <text - height="30" - word_wrap="true" - use_ellipses="true" - type="string" - text_color="LabelSelectedDisabledColor" - length="1" - follows="left|top" - layout="topleft" - left="8" - name="text status" - top_pad="3" - width="285"> - Drag to move, shift-drag to copy - </text> - <radio_group - layout="topleft" - left="10" - height="70" - top="59" - name="focus_radio_group"> - <radio_item - top_pad="6" - label="Zoom" - layout="topleft" - name="radio zoom" /> - <radio_item - top_pad="6" - label="Orbit (Ctrl)" - layout="topleft" - name="radio orbit" /> - <radio_item - top_pad="6" - label="Pan (Ctrl+Shift)" - layout="topleft" - name="radio pan" /> - <radio_group.commit_callback - function="BuildTool.commitRadioFocus"/> - </radio_group> - <slider_bar - follows="left|top" - height="14" - increment="0.01" - initial_value="0.125" - layout="topleft" - max_val="0.5" - top_delta="-2" - left_delta="100" - name="slider zoom" - width="134"> - <slider_bar.commit_callback - function="BuildTool.commitZoom"/> - </slider_bar> - <radio_group - left="10" - height="70" - top="59" - layout="topleft" - name="move_radio_group"> - <radio_item - top_pad="6" - label="Move" - layout="topleft" - name="radio move" /> - <radio_item - top_pad="6" - label="Lift (Ctrl)" - layout="topleft" - name="radio lift" /> - <radio_item - top_pad="6" - label="Spin (Ctrl+Shift)" - layout="topleft" - name="radio spin" /> - <radio_group.commit_callback - function="BuildTool.commitRadioMove"/> - </radio_group> - <radio_group - follows="left|top" - left="5" - top="59" - height="70" - layout="topleft" - name="edit_radio_group"> - <radio_item - label="Move" - layout="topleft" - name="radio position" /> - <radio_item - top_pad="6" - label="Rotate (Ctrl)" - layout="topleft" - name="radio rotate" /> - <radio_item - top_pad="6" - label="Stretch (Ctrl+Shift)" - layout="topleft" - name="radio stretch" /> - <radio_item - top_pad="6" - label="Select Face" - layout="topleft" - name="radio select face" /> - <radio_group.commit_callback - function="BuildTool.commitRadioEdit"/> - </radio_group> - <check_box - left="5" - follows="left|top" - height="28" - control_name="EditLinkedParts" - label="Edit linked" - layout="topleft" - name="checkbox edit linked parts" - top_pad="-10"> - <check_box.commit_callback - function="BuildTool.selectComponent"/> - </check_box> - - <button - follows="left|top" - height="23" - label="Link" - top_pad="2" - layout="topleft" - left="5" - name="link_btn" - width="50"> - <button.commit_callback - function="BuildTool.LinkObjects"/> - </button> - <button - follows="left|top" - height="23" - label="Unlink" - layout="topleft" - left_pad="2" - name="unlink_btn" - width="50"> - <button.commit_callback - function="BuildTool.UnlinkObjects"/> - </button> - <text - text_color="LtGray_50" - follows="top|left" - halign="left" - left_pad="3" - name="RenderingCost" - tool_tip="Shows the rendering cost calculated for this object" - top_delta="11" - type="string" - width="100"> - þ: [COUNT] - </text> - <check_box - control_name="ScaleUniform" - height="19" - label="" - layout="topleft" - left="143" - name="checkbox uniform" - top="50" - width="20" /> - <text - height="19" - label="Stretch Both Sides" - left_delta="20" - name="checkbox uniform label" - top_delta="2" - width="120" - layout="topleft" - follows="top|left" - wrap="true"> - Stretch Both Sides - </text> - <check_box - control_name="ScaleStretchTextures" - height="19" - initial_value="true" - label="Stretch Textures" - layout="topleft" - left="143" - name="checkbox stretch textures" - top_pad="-6" - follows="left|top" - width="134" /> - <check_box - control_name="SnapEnabled" - height="18" - initial_value="true" - label="Snap to grid" - layout="topleft" - top_pad="0" - name="checkbox snap to grid" - width="134" /> - <combo_box - height="23" - layout="topleft" - follows="left|top" - name="combobox grid mode" - tool_tip="Choose the type of grid ruler for positioning the object" - top_pad="0" - width="108"> - <combo_box.item - label="World grid" - name="World" - value="World" /> - <combo_box.item - label="Local grid" - name="Local" - value="Local" /> - <combo_box.item - label="Reference grid" - name="Reference" - value="Reference" /> - <combo_box.commit_callback - function="BuildTool.gridMode"/> - </combo_box> - <button - left_pad="0" - image_selected="ForwardArrow_Press" - image_unselected="ForwardArrow_Off" - layout="topleft" - follows="top|left" - name="Options..." - tool_tip="See more grid options" - top_pad="-22" - right="-10" - width="18" - height="23" > - <button.commit_callback - function="BuildTool.gridOptions"/> - </button> - <button - follows="left|top" - height="20" - image_disabled="Object_Cube" - image_disabled_selected="Object_Cube" - image_selected="Object_Cube_Selected" - image_unselected="Object_Cube" - layout="topleft" - left="10" - name="ToolCube" - tool_tip="Cube" - top="51" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Prism" - image_disabled_selected="Object_Prism" - image_selected="Object_Prism_Selected" - image_unselected="Object_Prism" - layout="topleft" - left_delta="29" - name="ToolPrism" - tool_tip="Prism" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Pyramid" - image_disabled_selected="Object_Pyramid" - image_selected="Object_Pyramid_Selected" - image_unselected="Object_Pyramid" - layout="topleft" - left_delta="29" - name="ToolPyramid" - tool_tip="Pyramid" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Tetrahedron" - image_disabled_selected="Object_Tetrahedron" - image_selected="Object_Tetrahedron_Selected" - image_unselected="Object_Tetrahedron" - layout="topleft" - left_delta="29" - name="ToolTetrahedron" - tool_tip="Tetrahedron" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Cylinder" - image_disabled_selected="Object_Cylinder" - image_selected="Object_Cylinder_Selected" - image_unselected="Object_Cylinder" - layout="topleft" - left_delta="29" - name="ToolCylinder" - tool_tip="Cylinder" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Hemi_Cylinder" - image_disabled_selected="Object_Hemi_Cylinder" - image_selected="Object_Hemi_Cylinder_Selected" - image_unselected="Object_Hemi_Cylinder" - layout="topleft" - left_delta="29" - name="ToolHemiCylinder" - tool_tip="Hemicylinder" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Cone" - image_disabled_selected="Object_Cone" - image_selected="Object_Cone_Selected" - image_unselected="Object_Cone" - layout="topleft" - left_delta="29" - name="ToolCone" - tool_tip="Cone" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Hemi_Cone" - image_disabled_selected="Object_Hemi_Cone" - image_selected="Object_Hemi_Cone_Selected" - image_unselected="Object_Hemi_Cone" - layout="topleft" - left_delta="29" - name="ToolHemiCone" - tool_tip="Hemicone" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Sphere" - image_disabled_selected="Object_Sphere" - image_selected="Object_Sphere_Selected" - image_unselected="Object_Sphere" - layout="topleft" - left_delta="29" - name="ToolSphere" - tool_tip="Sphere" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Hemi_Sphere" - image_disabled_selected="Object_Hemi_Sphere" - image_selected="Object_Hemi_Sphere_Selected" - image_unselected="Object_Hemi_Sphere" - layout="topleft" - left_delta="29" - name="ToolHemiSphere" - tool_tip="Hemisphere" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Torus" - image_disabled_selected="Object_Torus" - image_selected="Object_Torus_Selected" - image_unselected="Object_Torus" - layout="topleft" - left="10" - name="ToolTorus" - tool_tip="Torus" - top="77" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Tube" - image_disabled_selected="Object_Tube" - image_selected="Object_Tube_Selected" - image_unselected="Object_Tube" - layout="topleft" - left_delta="29" - name="ToolTube" - tool_tip="Tube" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Ring" - image_disabled_selected="Object_Ring" - image_selected="Object_Ring_Selected" - image_unselected="Object_Ring" - layout="topleft" - left_delta="29" - name="ToolRing" - tool_tip="Ring" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Tree" - image_disabled_selected="Object_Tree" - image_selected="Object_Tree_Selected" - image_unselected="Object_Tree" - layout="topleft" - left_delta="29" - name="ToolTree" - tool_tip="Tree" - top_delta="0" - width="20" /> - <button - follows="left|top" - height="20" - image_disabled="Object_Grass" - image_disabled_selected="Object_Grass" - image_selected="Object_Grass_Selected" - image_unselected="Object_Grass" - image_overlay_color="Red" - layout="topleft" - left_delta="29" - name="ToolGrass" - tool_tip="Grass" - top_delta="0" - width="20" /> - <check_box - control_name="CreateToolKeepSelected" - height="19" - label="Keep Tool selected" - layout="topleft" - left="4" - name="checkbox sticky" - top="101" - width="128" /> - <check_box - control_name="CreateToolCopySelection" - height="19" - label="Copy selection" - layout="topleft" - left_delta="0" - name="checkbox copy selection" - top_delta="15" - width="134" /> - <check_box - control_name="CreateToolCopyCenters" - height="19" - initial_value="true" - label="Center Copy" - layout="topleft" - left_delta="18" - name="checkbox copy centers" - top="132" - width="134" /> - <check_box - control_name="CreateToolCopyRotates" - height="19" - label="Rotate Copy" - layout="topleft" - left_delta="0" - name="checkbox copy rotates" - top_delta="16" - width="134" /> - <radio_group - height="105" - layout="topleft" - left="4" - name="land_radio_group" - top="54" - width="114"> - <radio_item - height="19" - label="Select Land" - layout="topleft" - left="0" - name="radio select land" - top="-106" - width="134" /> - <radio_item - height="19" - label="Flatten" - layout="topleft" - left_delta="0" - name="radio flatten" - top_delta="15" - width="114" /> - <radio_item - height="19" - label="Raise" - layout="topleft" - left_delta="0" - name="radio raise" - top_delta="15" - width="114" /> - <radio_item - height="19" - label="Lower" - layout="topleft" - left_delta="0" - name="radio lower" - top_delta="15" - width="114" /> - <radio_item - height="19" - label="Smooth" - layout="topleft" - left_delta="0" - name="radio smooth" - top_delta="15" - width="114" /> - <radio_item - height="19" - label="Roughen" - layout="topleft" - left_delta="0" - name="radio noise" - top_delta="15" - width="114" /> - <radio_item - height="19" - label="Revert" - layout="topleft" - left_delta="0" - name="radio revert" - top_delta="15" - width="114" /> - <radio_group.commit_callback - function="BuildTool.commitRadioLand"/> - </radio_group> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - left="135" - name="Bulldozer:" - top="57" - width="100"> - Bulldozer: - </text> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - name="Dozer Size:" - left="135" - top_pad="5" - width="50"> - Size - </text> - <slider_bar - control_name ="LandBrushSize" - follows="left|top" - height="19" - initial_value="2.0" - layout="topleft" - max_val="11" - min_val="1" - left_pad="0" - name="slider brush size" - top_delta="-3" - width="80" /> - <text - type="string" - length="1" - follows="left|top" - height="12" - layout="topleft" - name="Strength:" - left="135" - top_pad="5" - width="50"> - Strength - </text> - <slider_bar - follows="left|top" - height="19" - left_pad="0" - initial_value="0.00" - layout="topleft" - max_val="2" - min_val="-1" - name="slider force" - top_delta="-3" - width="80" > - <slider_bar.commit_callback - function="BuildTool.LandBrushForce"/> - </slider_bar> - <button - follows="left|top" - height="23" - label="Apply" - label_selected="Apply" - top_pad="5" - layout="topleft" - left="135" - name="button apply to selection" - tool_tip="Modify selected land" - width="82"> - <button.commit_callback - function="BuildTool.applyToSelection"/> - </button> - <text - text_color="LtGray_50" - type="string" - length="1" - height="10" - follows="left|top" - halign="right" - layout="topleft" - right="-10" - name="obj_count" - top_pad="5" - width="143"> - Objects: [COUNT] - </text> - <text - text_color="LtGray_50" - type="string" - length="1" - height="10" - follows="left|top" - halign="right" - layout="topleft" - right="-10" - name="prim_count" - width="143"> - Prims: [COUNT] - </text> - <text - text_color="LtGray_50" - type="string" - length="1" - height="10" - follows="left|top" - halign="right" - layout="topleft" - right="-120" - name="linked_set_count" - top="144" - width="80"> - Linked Sets: [COUNT] - </text> - <text - text_color="LtGray_50" - type="string" - length="1" - height="10" - follows="left|top" - halign="right" - layout="topleft" - top_delta="0" - right="-8" - name="linked_set_cost" - tool_tip="Cost of currently selected linked sets as [prims],[physics complexity]" - width="80"> - Cost: [COST] / [PHYSICS] - </text> - <text - text_color="LtGray_50" - type="string" - length="1" - follows="left|top" - halign="right" - layout="topleft" - top_pad="5" - right="-120" - name="object_count" - width="80"> - Objects: [COUNT] - </text> - <text - text_color="LtGray_50" - type="string" - length="1" - follows="left|top" - halign="right" - layout="topleft" - top_delta="0" - right="-8" - name="object_cost" - tool_tip="Cost of currently selected objects as [prims] / [physics complexity]" - width="80"> - Cost: [COST] / [PHYSICS] - </text> - <!-- <text --> - <!-- text_color="LtGray_50" --> - <!-- type="string" --> - <!-- length="1" --> - <!-- height="10" --> - <!-- follows="left|top" --> - <!-- halign="right" --> - <!-- layout="topleft" --> - <!-- right="-10" --> - <!-- name="obj_count" --> - <!-- top_pad="5" --> - <!-- width="143"> --> - <!-- Objects: [COUNT] --> - <!-- </text> --> - <!-- <text --> - <!-- text_color="LtGray_50" --> - <!-- type="string" --> - <!-- length="1" --> - <!-- follows="left|top" --> - <!-- halign="right" --> - <!-- layout="topleft" --> - <!-- right="-10" --> - <!-- name="prim_count" --> - <!-- width="143"> --> - <!-- Prims: [COUNT] --> - <!-- </text> --> - <tab_container - follows="left|top" - height="410" - halign="center" - left="0" - name="Object Info Tabs" - tab_max_width="100" - tab_min_width="40" - tab_position="top" - tab_height="25" - top="173" - width="295"> - -<panel - border="false" - follows="all" - label="General" - layout="topleft" - mouse_opaque="false" - help_topic="toolbox_general_tab" - name="General" - top="16" - width="295"> - <panel.string - name="text deed continued"> - Deed - </panel.string> - <panel.string - name="text deed"> - Deed - </panel.string> - <panel.string - name="text modify info 1"> - You can modify this object - </panel.string> - <panel.string - name="text modify info 2"> - You can modify these objects - </panel.string> - <panel.string - name="text modify info 3"> - You can't modify this object - </panel.string> - <panel.string - name="text modify info 4"> - You can't modify these objects - </panel.string> - <panel.string - name="text modify warning"> - You must select entire object to set permissions - </panel.string> - <panel.string - name="Cost Default"> - Price: L$ - </panel.string> - <panel.string - name="Cost Total"> - Total Price: L$ - </panel.string> - <panel.string - name="Cost Per Unit"> - Price Per: L$ - </panel.string> - <panel.string - name="Cost Mixed"> - Mixed Price - </panel.string> - <panel.string - name="Sale Mixed"> - Mixed Sale - </panel.string> - <text - follows="left|top" - height="10" - left="10" - name="Name:" - top="5" - width="90"> - Name: - </text> - <line_editor - follows="left|top|right" - height="19" - left_pad="0" - max_length_bytes="63" - name="Object Name" - select_on_focus="true" - top_delta="0" - width="170" /> - <text - follows="left|top" - height="10" - left="10" - name="Description:" - top_pad="3" - width="90"> - Description: - </text> - <line_editor - follows="left|top|right" - height="19" - left_pad="0" - max_length_bytes="127" - name="Object Description" - select_on_focus="true" - top_delta="0" - width="170" /> - <text - type="string" - left="10" - length="1" - follows="left|top" - height="19" - layout="topleft" - name="Creator:" - top_pad="7" - width="90"> - Creator: - </text> - <!-- *NOTE: Intentionally wide for long names --> - <text - type="string" - length="1" - follows="left|top" - left_pad="0" - height="20" - layout="topleft" - name="Creator Name" - top_delta="0" - translate="false" - width="190" - word_wrap="true" - use_ellipses="true"> - TestString PleaseIgnore (please.ignore) - </text> - <text - type="string" - length="1" - left="10" - follows="left|top" - height="19" - layout="topleft" - name="Owner:" - top_pad="13" - width="90"> - Owner: - </text> - <!-- *NOTE: Intentionally wide for long names --> - <text - type="string" - length="1" - follows="left|top" - height="20" - layout="topleft" - name="Owner Name" - left_pad="0" - top_delta="0" - translate="false" - width="190" - word_wrap="true" - use_ellipses="true"> - TestString PleaseIgnore (please.ignore) - </text> - <text - type="string" - length="1" - follows="left|top" - layout="topleft" - left="10" - height="18" - name="Group:" - top_pad="17" - width="75"> - Group: - </text> - <name_box - follows="left|top" - height="18" - initial_value="Loading..." - layout="topleft" - left_pad="23" - name="Group Name Proxy" - width="142" /> - <button - follows="top|left" - height="23" - image_overlay="Edit_Wrench" - layout="topleft" - left_pad="13" - name="button set group" - tab_stop="false" - tool_tip="Choose a group to share this object's permissions" - width="23" /> - <check_box - height="19" - follows="left|top" - label="Share" - layout="topleft" - name="checkbox share with group" - tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions." - top_pad="10" - left="100" - width="87" /> - <button - follows="top|left" - height="23" - label="Deed" - label_selected="Deed" - layout="topleft" - name="button deed" - left_pad="19" - tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer." - width="80" /> - <text - type="string" - length="1" - follows="left|top" - height="16" - layout="topleft" - top_pad="10" - left="10" - name="label click action" - width="118"> - Click to: - </text> - <combo_box - follows="left|top" - height="23" - layout="topleft" - name="clickaction" - width="148" - left_pad="10"> - <combo_box.item - label="Touch (default)" - name="Touch/grab(default)" - value="Touch" /> - <combo_box.item - label="Sit on object" - name="Sitonobject" - value="Sit" /> - <combo_box.item - label="Buy object" - name="Buyobject" - value="Buy" /> - <combo_box.item - label="Pay object" - name="Payobject" - value="Pay" /> - <combo_box.item - label="Open" - name="Open" - value="Open" /> - <combo_box.item - label="Zoom" - name="Zoom" - value="Zoom" /> - </combo_box> - <check_box - height="23" - label="For Sale:" - layout="topleft" - name="checkbox for sale" - left="7" - width="100" /> -<!-- NEW SALE TYPE COMBO BOX --> - <combo_box - left_pad="10" - layout="topleft" - follows="left|top" - allow_text_entry="false" - height="23" - initial_value="2" - max_chars="20" - mouse_opaque="true" - name="sale type" - width="168"> - <combo_box.item - name="Copy" - label="Copy" - value="2" /> - <combo_box.item - name="Contents" - label="Contents" - value="3" /> - <combo_box.item - name="Original" - label="Original" - value="1" /> - </combo_box> -<!-- NEW PRICE SPINNER -Objects are allowed to be for sale for L$0 to invoke buy UI behavior -even though the user gets a free copy. ---> - <spinner - follows="left|top" - decimal_digits="0" - increment="1" - top_pad="8" - left="118" - control_name="Edit Cost" - name="Edit Cost" - label="Price: L$" - label_width="65" - width="165" - min_val="0" - height="20" - max_val="999999999" /> - <check_box - height="15" - width="110" - top_pad="5" - label="Show in search" - layout="topleft" - left="100" - name="search_check" - tool_tip="Let people see this object in search results" /> - <panel - border="false" - follows="left|top" - layout="topleft" - mouse_opaque="false" - background_visible="true" - bg_alpha_color="DkGray" - name="perms_build" - left="0" - top_pad="4" - height="105" - width="290"> - <text - type="string" - length="1" - left="10" - top_pad="9" - text_color="EmphasisColor" - height="16" - follows="left|top|right" - layout="topleft" - name="perm_modify" - width="264"> - You can modify this object - </text> - <text - type="string" - follows="left|top" - name="Anyone can:" - width="250" - left="10"> - Anyone: - </text> - <check_box - height="19" - label="Move" - layout="topleft" - name="checkbox allow everyone move" - left="10" - width="85" /> - <check_box - height="19" - label="Copy" - layout="topleft" - left_pad="0" - name="checkbox allow everyone copy" - width="90" /> - <text - type="string" - follows="left|top" - height="19" - name="Next owner can:" - width="250" - left="10"> - Next owner: - </text> - <check_box - follows="left|top|right" - label="Modify" - layout="topleft" - left="10" - name="checkbox next owner can modify" - width="85" /> - <check_box - follows="left|top|right" - height="19" - label="Copy" - layout="topleft" - left_pad="0" - name="checkbox next owner can copy" - width="80" /> - <check_box - follows="left|top|right" - height="19" - label="Transfer" - layout="topleft" - name="checkbox next owner can transfer" - left_pad="0" - top_delta="0" - tool_tip="Next owner can give away or resell this object" - width="100" /> -<!-- *NOTE: These "B/O/G/E/N/F fields may overlap "perm_modify" above, - but that's OK, this is used only for debugging. --> - <text - type="string" - text_color="EmphasisColor" - length="1" - top="9" - follows="left|top" - layout="topleft" - left="230" - name="B:" - height="10" - width="80"> - B: - </text> - <text - type="string" - text_color="White" - length="1" - follows="left|top" - layout="topleft" - left_delta="0" - top_pad="2" - name="O:" - height="10" - width="80"> - O: - </text> - <text - type="string" - text_color="EmphasisColor" - length="1" - follows="left|top" - layout="topleft" - left_delta="0" - top_pad="2" - name="G:" - height="10" - width="80"> - G: - </text> - <text - type="string" - text_color="White" - length="1" - follows="left|top" - left_delta="0" - top_pad="2" - layout="topleft" - name="E:" - height="10" - width="80"> - E: - </text> - <text - type="string" - text_color="EmphasisColor" - length="1" - follows="left|top" - layout="topleft" - left_delta="0" - top_pad="2" - name="N:" - height="10" - width="80"> - N: - </text> - <text - type="string" - text_color="White" - length="1" - follows="left|top" - layout="topleft" - left_delta="0" - top_pad="2" - name="F:" - height="10" - width="80"> - F: - </text> - </panel> - </panel> - <!-- Object tab --> - <panel - border="false" - follows="all" - height="567" - label="Object" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="toolbox_object_tab" - name="Object" - top="16" - width="295"> - <check_box - height="19" - label="Locked" - layout="topleft" - name="checkbox locked" - tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits." - top_pad="5" - left="10" - width="123" /> - <check_box - height="19" - label="Physical" - layout="topleft" - name="Physical Checkbox Ctrl" - tool_tip="Allows object to be pushed and affected by gravity" - top_pad="0" - width="123" /> - <check_box - height="19" - label="Temporary" - layout="topleft" - name="Temporary Checkbox Ctrl" - tool_tip="Causes object to be deleted 1 minute after creation" - top_pad="0" - width="123" /> - <check_box - height="19" - label="Phantom" - layout="topleft" - name="Phantom Checkbox Ctrl" - tool_tip="Causes object to not collide with other objects or avatars" - top_pad="0" - width="123" /> - - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - name="label position" - top_pad="10" - width="121"> - Position (meters) - </text> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - max_val="512" - min_val="-256" - name="Pos X" - text_enabled_color="1 0 0.3 .7" - top_pad="5" - width="87" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_delta="0" - max_val="512" - min_val="-256" - name="Pos Y" - text_enabled_color="EmphasisColor" - top_pad="3" - width="87" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Z" - label_width="10" - layout="topleft" - left_delta="0" - max_val="4096" - name="Pos Z" - text_enabled_color="0 0.8 1 .65" - top_pad="3" - width="87" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="label size" - top_pad="6" - width="121"> - Size (meters) - </text> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - max_val="64" - min_val="0.01" - name="Scale X" - text_enabled_color="1 1 1 1" - top_pad="5" - width="87" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_delta="0" - max_val="64" - min_val="0.01" - name="Scale Y" - text_enabled_color="1 1 1 1" - top_pad="3" - width="87" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Z" - label_width="10" - layout="topleft" - left_delta="0" - max_val="64" - min_val="0.01" - name="Scale Z" - text_enabled_color="1 1 1 1" - top_pad="3" - width="87" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="label rotation" - top_pad="10" - width="121"> - Rotation (degrees) - </text> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="1" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - max_val="9999" - min_val="-9999" - name="Rot X" - text_enabled_color="1 1 1 1" - top_pad="5" - width="87" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="1" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_delta="0" - max_val="9999" - min_val="-9999" - name="Rot Y" - text_enabled_color="1 1 1 1" - top_pad="3" - width="87" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="1" - initial_value="0" - label="Z" - label_width="10" - layout="topleft" - left_delta="0" - max_val="9999" - min_val="-9999" - name="Rot Z" - text_enabled_color="1 1 1 1" - top_pad="3" - width="87" /> - <!-- <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="label basetype" - top="5" - width="150"> - Prim Type - </text>--> - <combo_box - height="19" - layout="topleft" - name="comboBaseType" - top="6" - left="125" - width="150"> - <combo_box.item - label="Box" - name="Box" - value="Box" /> - <combo_box.item - label="Cylinder" - name="Cylinder" - value="Cylinder" /> - <combo_box.item - label="Prism" - name="Prism" - value="Prism" /> - <combo_box.item - label="Sphere" - name="Sphere" - value="Sphere" /> - <combo_box.item - label="Torus" - name="Torus" - value="Torus" /> - <combo_box.item - label="Tube" - name="Tube" - value="Tube" /> - <combo_box.item - label="Ring" - name="Ring" - value="Ring" /> - <combo_box.item - label="Sculpted" - name="Sculpted" - value="Sculpted" /> - </combo_box> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="text cut" - top_pad="5" - width="150"> - Path Cut (begin/end) - </text> - <spinner - follows="left|top" - height="16" - increment="0.025" - initial_value="0" - label="B" - label_width="10" - layout="topleft" - left_delta="0" - max_val="0.98" - name="cut begin" - top_pad="4" - width="68" /> - <spinner - follows="left|top" - height="16" - increment="0.025" - initial_value="1" - label="E" - label_width="10" - layout="topleft" - left_pad="10" - min_val="0.02" - name="cut end" - top_delta="0" - width="68" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="text hollow" - top_pad="6" - width="68"> - Hollow - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_pad="10" - name="text skew" - width="63"> - Skew - </text> - <spinner - decimal_digits="1" - follows="left|top" - height="19" - increment="5" - initial_value="0" - layout="topleft" - left="125" - max_val="95" - name="Scale 1" - top_pad="4" - width="68" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - layout="topleft" - left_pad="10" - max_val="0.95" - min_val="-0.95" - name="Skew" - top_delta="0" - width="68" /> - <text - type="string" - length="1" - follows="left|top" - height="15" - layout="topleft" - left="125" - name="Hollow Shape" - top_pad="4" - width="150"> - Hollow Shape - </text> - <combo_box - height="23" - layout="topleft" - left_delta="0" - name="hole" - top_pad="-2" - width="150"> - <combo_box.item - label="Default" - name="Default" - value="Default" /> - <combo_box.item - label="Circle" - name="Circle" - value="Circle" /> - <combo_box.item - label="Square" - name="Square" - value="Square" /> - <combo_box.item - label="Triangle" - name="Triangle" - value="Triangle" /> - </combo_box> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="text twist" - top_pad="5" - width="150"> - Twist (begin/end) - </text> - <spinner - decimal_digits="0" - follows="left|top" - height="19" - increment="9" - initial_value="0" - label="B" - label_width="10" - layout="topleft" - left_delta="0" - max_val="180" - min_val="-180" - name="Twist Begin" - top_pad="4" - width="68" /> - <spinner - decimal_digits="0" - follows="left|top" - height="19" - increment="9" - initial_value="0" - label="E" - label_width="10" - layout="topleft" - left_pad="10" - max_val="180" - min_val="-180" - name="Twist End" - top_delta="0" - width="68" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="scale_taper" - top_pad="3" - width="150"> - Taper - </text> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="scale_hole" - top_delta="0" - width="150"> - Hole Size - </text> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - min_val="-1" - name="Taper Scale X" - top_pad="4" - width="68" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_pad="10" - min_val="-1" - name="Taper Scale Y" - top_delta="0" - width="68" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="text topshear" - top_pad="3" - width="141"> - Top Shear - </text> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - max_val="0.5" - min_val="-0.5" - name="Shear X" - top_pad="4" - width="68" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_pad="10" - max_val="0.5" - min_val="-0.5" - name="Shear Y" - top_delta="0" - width="68" /> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="advanced_cut" - top_pad="3" - width="150"> - Profile Cut (begin/end) - </text> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="advanced_dimple" - top_delta="0" - width="150"> - Dimple (begin/end) - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="advanced_slice" - top_delta="0" - width="150"> - Slice (begin/end) - </text> - <spinner - follows="left|top" - height="19" - increment="0.02" - initial_value="0" - label="B" - label_width="10" - layout="topleft" - left_delta="0" - max_val="0.98" - name="Path Limit Begin" - top_pad="3" - width="68" /> - <spinner - follows="left|top" - height="19" - increment="0.02" - initial_value="1" - label="E" - label_width="10" - layout="topleft" - left_pad="10" - min_val="0.02" - name="Path Limit End" - top_delta="0" - width="68" /> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="text taper2" - top_pad="3" - width="150"> - Taper - </text> - <spinner - visible="false" - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="X" - label_width="10" - layout="topleft" - left_delta="0" - min_val="-1" - name="Taper X" - top_pad="3" - width="68" /> - <spinner - visible="false" - decimal_digits="2" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - label="Y" - label_width="10" - layout="topleft" - left_pad="10" - min_val="-1" - name="Taper Y" - top_delta="0" - width="68" /> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="125" - name="text radius delta" - top_pad="2" - width="78"> - Radius - </text> - <text - visible="false" - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="78" - name="text revolutions" - width="68"> - Revolutions - </text> - <spinner - visible="false" - follows="left|top" - height="19" - increment="0.05" - initial_value="0" - layout="topleft" - left="125" - min_val="-1" - name="Radius Offset" - top_pad="4" - width="68" /> - <spinner - visible="false" - decimal_digits="2" - follows="left|top" - height="19" - initial_value="1" - layout="topleft" - left_pad="10" - max_val="4" - min_val="1" - name="Revolutions" - top_delta="0" - width="68" /> - <texture_picker - can_apply_immediately="true" - default_image_name="Default" - follows="left|top" - height="141" - label="Sculpt Texture" - layout="topleft" - left="125" - name="sculpt texture control" - tool_tip="Click to choose a picture" - top="70" - visible="false" - width="145" /> - <check_box - height="19" - label="Mirror" - layout="topleft" - left_delta="0" - name="sculpt mirror control" - tool_tip="Flips sculpted prim along the X axis" - top_pad="8" - visible="false" - width="130" /> - <check_box - height="19" - label="Inside-out" - layout="topleft" - left_delta="0" - name="sculpt invert control" - tool_tip="Inverts the sculpted prims normals, making it appear inside-out" - top_pad="4" - visible="false" - width="121" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="label sculpt type" - top_pad="10" - visible="false" - width="130"> - Stitching type - </text> - <combo_box - height="19" - layout="topleft" - left_delta="0" - name="sculpt type control" - top_pad="4" - visible="false" - width="150"> - <combo_box.item - label="(none)" - name="None" - value="None" /> - <combo_box.item - label="Sphere" - name="Sphere" - value="Sphere" /> - <combo_box.item - label="Torus" - name="Torus" - value="Torus" /> - <combo_box.item - label="Plane" - name="Plane" - value="Plane" /> - <combo_box.item - label="Cylinder" - name="Cylinder" - value="Cylinder" /> - <combo_box.item - label="Mesh" - name="Mesh" - value="Mesh" /> - </combo_box> - </panel> - <panel - border="false" - follows="all" - height="367" - label="Features" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="toolbox_features_tab" - name="Features" - top_delta="0" - width="295"> - <panel.string name="None">None</panel.string> - <panel.string name="Prim">Prim</panel.string> - <panel.string name="Convex Hull">Convex Hull</panel.string> - <text - type="string" - length="1" - follows="left|top" - height="20" - layout="topleft" - left="10" - name="select_single" - top="5" - width="252" - word_wrap="true"> - Select only one primitive to edit features. - </text> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="edit_object" - top="5" - width="252"> - Edit object features: - </text> - <check_box - height="19" - label="Flexible Path" - layout="topleft" - left="10" - name="Flexible1D Checkbox Ctrl" - tool_tip="Allows object to flex about the Z axis (Client-side only)" - top_pad="20" - width="121" /> - <spinner - follows="left|top" - height="19" - increment="1" - initial_value="2" - label="Softness" - label_width="70" - layout="topleft" - left_delta="0" - max_val="3" - name="FlexNumSections" - top_pad="10" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.5" - initial_value="0.3" - label="Gravity" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - min_val="-10" - name="FlexGravity" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.5" - initial_value="2" - label="Drag" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - name="FlexFriction" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.5" - initial_value="0" - label="Wind" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - name="FlexWind" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.5" - initial_value="1" - label="Tension" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - name="FlexTension" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Force X" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - min_val="-10" - name="FlexForceX" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Force Y" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - min_val="-10" - name="FlexForceY" - top_pad="4" - width="128" /> - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Force Z" - label_width="70" - layout="topleft" - left_delta="0" - max_val="10" - min_val="-10" - name="FlexForceZ" - top_pad="4" - width="128" /> - - <check_box - height="16" - label="Light" - layout="topleft" - left="10" - name="Light Checkbox Ctrl" - tool_tip="Causes object to emit light" - top_pad="15" - width="60" /> - <color_swatch - can_apply_immediately="true" - color="0.5 0.5 0.5 1" - border.border_thickness="0" - follows="left|top" - height="50" - layout="topleft" - left_pad="10" - top_pad="-17" - name="colorswatch" - tool_tip="Click to open color picker" - width="40" /> - <texture_picker - allow_no_texture="true" - top_delta="0" - can_apply_immediately="true" - default_image_name="Default" - follows="left|top" - height="48" - label="" - left_delta="57" - mouse_opaque="true" - name="light texture control" - tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)" - width="32" /> - <spinner - follows="left|top" - height="19" - initial_value="0.5" - label="Intensity" - label_width="70" - layout="topleft" - left="10" - name="Light Intensity" - top_pad="3" - width="128" /> - <spinner bottom_delta="0" - decimal_digits="3" - follows="left|top" - height="16" - increment="0.1" - initial_value="0.5" - label="FOV" - label_width="55" - left="144" - max_val="3" - min_val="0" - mouse_opaque="true" - name="Light FOV" - width="120" /> - <spinner follows="left|top" - height="19" - initial_value="5" - label="Radius" - label_width="70" - layout="topleft" - left="10" - max_val="20" - name="Light Radius" - top_pad="3" - width="128" /> - <spinner bottom_delta="0" - decimal_digits="3" - follows="left|top" - height="16" - increment="0.5" - initial_value="0.5" - label="Focus" - label_width="55" - left="144" - max_val="20" - min_val="-20" - mouse_opaque="true" - name="Light Focus" - width="120" /> - <spinner follows="left|top" - height="19" - increment="0.25" - initial_value="1" - label="Falloff" - label_width="70" - layout="topleft" - left="10" - max_val="2" - name="Light Falloff" - top_pad="3" - width="128" /> - <spinner bottom_delta="0" - decimal_digits="3" - follows="left|top" - height="16" - increment="0.05" - initial_value="1" - label="Ambiance" - label_width="55" - left="144" - max_val="1" - min_val="0" - mouse_opaque="true" - name="Light Ambiance" - width="120" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - name="label physicsshapetype" - top="38" - width="121"> - Physics Shape Type: - </text> - <combo_box - height="19" - top_delta="15" - layout="topleft" - follows="left|top" - name="Physics Shape Type Combo Ctrl" - tool_tip="Choose the physics shape type" - width="108"/> - <combo_box - height="19" - layout="topleft" - name="material" - top_pad="5" - width="150"> - <combo_box.item - label="Stone" - name="Stone" - value="Stone" /> - <combo_box.item - label="Metal" - name="Metal" - value="Metal" /> - <combo_box.item - label="Glass" - name="Glass" - value="Glass" /> - <combo_box.item - label="Wood" - name="Wood" - value="Wood" /> - <combo_box.item - label="Flesh" - name="Flesh" - value="Flesh" /> - <combo_box.item - label="Plastic" - name="Plastic" - value="Plastic" /> - <combo_box.item - label="Rubber" - name="Rubber" - value="Rubber" /> - </combo_box> - - <spinner - follows="left|top" - height="19" - increment="1" - initial_value="1" - label="Gravity" - label_width="70" - layout="topleft" - min_val="-1" - max_val="28" - name="Physics Gravity" - top_pad="10" - width="132" /> - - <spinner - follows="left|top" - height="19" - increment="0.1" - initial_value="0" - label="Friction" - label_width="70" - layout="topleft" - left_delta="0" - max_val="255" - min_val="0" - name="Physics Friction" - top_pad="4" - width="132" /> - - <spinner - follows="left|top" - height="19" - increment="0.1" - initial_value="0" - label="Density" - label_width="70" - layout="topleft" - left_delta="0" - max_val="22587" - min_val="1" - name="Physics Density" - top_pad="4" - width="132" /> - - <spinner - follows="left|top" - height="19" - increment="0.01" - initial_value="0" - label="Restitution" - label_width="70" - layout="topleft" - left_delta="0" - max_val="1" - min_val="0" - name="Physics Restitution" - top_pad="4" - width="132" /> - </panel> - <panel - border="false" - follows="all" - height="367" - label="Texture" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="toolbox_texture_tab" - name="Texture" - top_delta="0" - width="295"> - <panel.string - name="string repeats per meter"> - Repeats Per Meter - </panel.string> - <panel.string - name="string repeats per face"> - Repeats Per Face - </panel.string> - <texture_picker - can_apply_immediately="true" - default_image_name="Default" - fallback_image="locked_image.j2c" - follows="left|top" - height="80" - label="Texture" - layout="topleft" - left="10" - name="texture control" - tool_tip="Click to choose a picture" - top="8" - width="64" /> - <color_swatch - can_apply_immediately="true" - follows="left|top" - height="80" - label="Color" - layout="topleft" - left_pad="15" - name="colorswatch" - tool_tip="Click to open color picker" - top_delta="0" - width="64" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_pad="15" - name="color trans" - text_readonly_color="LabelDisabledColor" - top="6" - width="110"> - Transparency % - </text> - <spinner - decimal_digits="0" - follows="left|top" - height="19" - increment="2" - initial_value="0" - layout="topleft" - left_delta="0" - max_val="100" - name="ColorTrans" - top_pad="4" - width="80" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_delta="0" - name="glow label" - text_readonly_color="LabelDisabledColor" - top_pad="8" - width="80"> - Glow - </text> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - initial_value="0" - layout="topleft" - left_delta="0" - name="glow" - top_pad="4" - width="80" /> - <check_box - height="19" - label="Full Bright" - layout="topleft" - left_delta="-5" - name="checkbox fullbright" - top_pad="4" - width="81" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="tex gen" - text_readonly_color="LabelDisabledColor" - top_pad="5" - width="90"> - Mapping - </text> - <combo_box - height="23" - layout="topleft" - left_delta="0" - name="combobox texgen" - top_pad="4" - width="90"> - <combo_box.item - label="Default" - name="Default" - value="Default" /> - <combo_box.item - label="Planar" - name="Planar" - value="Planar" /> - </combo_box> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - name="label shininess" - left_pad="4" - text_readonly_color="LabelDisabledColor" - top_pad="-37" - width="90"> - Shininess - </text> - <combo_box - height="23" - layout="topleft" - left_delta="0" - name="combobox shininess" - top_pad="4" - width="90"> - <combo_box.item - label="None" - name="None" - value="None" /> - <combo_box.item - label="Low" - name="Low" - value="Low" /> - <combo_box.item - label="Medium" - name="Medium" - value="Medium" /> - <combo_box.item - label="High" - name="High" - value="High" /> - </combo_box> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left_pad="4" - name="label bumpiness" - text_readonly_color="LabelDisabledColor" - top_pad="-37" - width="90"> - Bumpiness - </text> - <combo_box - height="23" - layout="topleft" - left_delta="0" - name="combobox bumpiness" - top_pad="4" - width="90"> - <combo_box.item - label="None" - name="None" - value="None" /> - <combo_box.item - label="Brightness" - name="Brightness" - value="Brightness" /> - <combo_box.item - label="Darkness" - name="Darkness" - value="Darkness" /> - <combo_box.item - label="woodgrain" - name="woodgrain" - value="woodgrain" /> - <combo_box.item - label="bark" - name="bark" - value="bark" /> - <combo_box.item - label="bricks" - name="bricks" - value="bricks" /> - <combo_box.item - label="checker" - name="checker" - value="checker" /> - <combo_box.item - label="concrete" - name="concrete" - value="concrete" /> - <combo_box.item - label="crustytile" - name="crustytile" - value="crustytile" /> - <combo_box.item - label="cutstone" - name="cutstone" - value="cutstone" /> - <combo_box.item - label="discs" - name="discs" - value="discs" /> - <combo_box.item - label="gravel" - name="gravel" - value="gravel" /> - <combo_box.item - label="petridish" - name="petridish" - value="petridish" /> - <combo_box.item - label="siding" - name="siding" - value="siding" /> - <combo_box.item - label="stonetile" - name="stonetile" - value="stonetile" /> - <combo_box.item - label="stucco" - name="stucco" - value="stucco" /> - <combo_box.item - label="suction" - name="suction" - value="suction" /> - <combo_box.item - label="weave" - name="weave" - value="weave" /> - </combo_box> - <!-- - <line_editor - bevel_style="in" - border_style="line" - border_thickness="1" - follows="left|top" - height="16" - layout="topleft" - left="10" - max_length_bytes="63" - name="Home Url" - select_on_focus="true" - top="134" - width="250" /> - <check_box - height="16" - label="Media Face" - layout="topleft" - left_delta="0" - name="has media" - top_pad="6" - width="70" /> - <button - follows="left|top" - font="SansSerifSmall" - height="20" - label="Set Media Info" - label_selected="Set Media Info" - layout="topleft" - left_pad="60" - name="media info set" - top_delta="-4" - width="120" /> ---> - <check_box - follows="top|left" - height="16" - initial_value="false" - label="Align planar faces" - layout="topleft" - left="17" - name="checkbox planar align" - tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping." - top_delta="26" - width="140" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="rpt" - text_readonly_color="LabelDisabledColor" - top_pad="2" - width="140"> - Repeats / Face - </text> - <spinner - follows="left|top" - height="19" - initial_value="0" - label="Horizontal (U)" - label_width="125" - layout="topleft" - left="20" - max_val="100" - name="TexScaleU" - top_pad="5" - width="185" /> - <check_box - height="19" - label="Flip" - layout="topleft" - left_pad="5" - name="checkbox flip s" - top_delta="0" - width="70" /> - <spinner - follows="left|top" - height="19" - initial_value="0" - label="Vertical (V)" - label_width="125" - layout="topleft" - left="20" - max_val="100" - name="TexScaleV" - width="185" /> - <check_box - height="19" - label="Flip" - layout="topleft" - left_pad="5" - name="checkbox flip t" - top_delta="0" - width="70" /> - <spinner - decimal_digits="2" - follows="left|top" - height="19" - increment="1" - initial_value="0" - label="Rotation˚" - layout="topleft" - label_width="135" - left="10" - max_val="9999" - min_val="-9999" - name="TexRot" - width="195" /> - - <spinner - decimal_digits="1" - follows="left|top" - height="23" - initial_value="1" - label="Repeats / Meter" - layout="topleft" - label_width="135" - left="10" - max_val="10" - min_val="0.1" - name="rptctrl" - width="195" /> - <button - follows="left|top" - height="23" - label="Apply" - label_selected="Apply" - layout="topleft" - left_pad="5" - name="button apply" - width="75" /> - <text - type="string" - length="1" - follows="left|top" - height="10" - layout="topleft" - left="10" - name="tex offset" - text_readonly_color="LabelDisabledColor" - width="200"> - Texture Offset - </text> - <spinner - follows="left|top" - height="19" - initial_value="0" - label="Horizontal (U)" - label_width="125" - layout="topleft" - left="20" - min_val="-1" - name="TexOffsetU" - width="185" /> - <spinner - follows="left|top" - height="19" - initial_value="0" - label="Vertical (V)" - label_width="125" - layout="topleft" - left_delta="0" - min_val="-1" - name="TexOffsetV" - top_pad="1" - width="185" /> - <panel - border="false" - follows="left|top" - layout="topleft" - mouse_opaque="false" - background_visible="true" - bg_alpha_color="DkGray" - name="Add_Media" - left="0" - height="47" - width="290"> - <text - type="string" - length="1" - follows="left|top" - height="18" - layout="topleft" - left="10" - top_pad="3" - name="media_tex" - width="190"> - Media - </text> - <button - follows="top|left" - height="18" - image_selected="AddItem_Press" - image_unselected="AddItem_Off" - image_disabled="AddItem_Disabled" - layout="topleft" - left_pad="0" - name="add_media" - tab_stop="false" - top_delta="0" - tool_tip="Add Media" - width="18"> - <button.commit_callback - function="BuildTool.AddMedia"/> - </button> - <button - follows="top|left" - height="18" - image_selected="TrashItem_Press" - image_unselected="TrashItem_Off" - layout="topleft" - left_pad="5" - name="delete_media" - tool_tip="Delete this media texture" - top_delta="0" - width="18"> - <button.commit_callback - function="BuildTool.DeleteMedia"/> - </button> - <button - follows="top|left" - tool_tip="Edit this Media" - height="12" - image_disabled="Icon_Gear_Background" - image_selected="Icon_Gear_Press" - image_unselected="Icon_Gear_Foreground" - layout="topleft" - left_pad="10" - name="edit_media" - top_delta="3" - width="12"> - <button.commit_callback - function="BuildTool.EditMedia"/> - </button> - <text - follows="left|top|right" - height="9" - layout="topleft" - left="10" - use_ellipses="true" - read_only="true" - name="media_info" - width="280" /> - <web_browser - visible="false" - enabled="false" - border_visible="true" - bottom_delta="0" - follows="top|left" - left="0" - name="title_media" - width="4" - height="4" - start_url="about:blank" - decouple_texture_size="true" /> - <button - follows="right|top" - height="22" - label="Align" - label_selected="Align Media" - layout="topleft" - right="-16" - name="button align" - top_delta="-4" - tool_tip="Align media texture (must load first)" - width="80" /> - </panel> - </panel> - <panel - border="false" - follows="all" - label="Content" - layout="topleft" - left_delta="0" - mouse_opaque="false" - help_topic="toolbox_contents_tab" - name="Contents" - top_delta="0" - width="295"> - <button - follows="left|top" - height="23" - label="New Script" - label_selected="New Script" - layout="topleft" - left="10" - name="button new script" - top="10" - width="134" /> - <button - follows="left|top" - height="23" - label="Permissions" - layout="topleft" - left_pad="8" - name="button permissions" - width="134" /> - <panel_inventory_object - border="true" - border_visible="true" - bevel_style="in" - follows="left|top|right" - height="325" - layout="topleft" - left="10" - name="contents_inventory" - top="50" - width="275" /> - </panel> - </tab_container> - <panel - follows="left|top" - height="384" - layout="topleft" - left_delta="0" - name="land info panel" - top_delta="0" - width="295"> - <text - type="string" - length="1" - font="SansSerifBig" - follows="left|top" - height="19" - layout="topleft" - left="20" - name="label_parcel_info" - top="24" - width="240"> - Parcel Information - </text> - <text - type="string" - length="1" - follows="left|top" - height="19" - layout="topleft" - left="30" - name="label_area_price" - top="48" - width="150"> - Price: L$[PRICE] for [AREA] m² - </text> - <text - type="string" - length="1" - follows="left|top" - height="19" - layout="topleft" - left_delta="0" - name="label_area" - top_delta="0" - width="150"> - Area: [AREA] m² - </text> - <button - follows="left|top" - height="23" - label="About Land" - label_selected="About Land" - layout="topleft" - left_delta="0" - name="button about land" - top_pad="4" - width="125" /> - <check_box - control_name="ShowParcelOwners" - height="19" - label="Show owners" - layout="topleft" - left_delta="0" - name="checkbox show owners" - tool_tip="Colorize the parcels according to the type of owner: Green = Your land Aqua = Your group's land Red = Owned by others Yellow = For sale Purple = For auction Grey = Public" - top_pad="8" - width="205" /> - <text - type="string" - length="1" - font="SansSerifBig" - follows="left|top" - height="19" - layout="topleft" - left="20" - name="label_parcel_modify" - top="152" - width="240"> - Modify Parcel - </text> - <button - follows="left|top" - height="23" - label="Subdivide" - label_selected="Subdivide" - layout="topleft" - left="30" - name="button subdivide land" - top="172" - width="125" /> - <button - follows="left|top" - height="23" - label="Join" - label_selected="Join" - layout="topleft" - left_delta="0" - name="button join land" - top_pad="4" - width="125" /> - <text - type="string" - length="1" - font="SansSerifBig" - follows="left|top" - height="19" - layout="topleft" - left="20" - name="label_parcel_trans" - top="256" - width="240"> - Land Transactions - </text> - <button - follows="left|top" - height="23" - label="Buy Land" - label_selected="Buy Land" - layout="topleft" - left="30" - name="button buy land" - top="276" - width="125" /> - <button - follows="left|top" - height="23" - label="Abandon Land" - label_selected="Abandon Land" - layout="topleft" - left_delta="0" - name="button abandon land" - top_pad="4" - width="125" /> - </panel> -<!-- end of tabs --> -</floater> +<?xml version="1.0" encoding="utf-8" standalone="yes" ?>
+<floater
+ legacy_header_height="18"
+ follows="left|top|right"
+ height="580"
+ layout="topleft"
+ bg_opaque_image="Window_NoTitle_Foreground"
+ bg_alpha_image="Window_NoTitle_Background"
+ name="toolbox floater"
+ help_topic="toolbox_floater"
+ save_rect="true"
+ short_title="BUILD TOOLS"
+ single_instance="true"
+ save_visibility="true"
+ sound_flags="0"
+ width="295">
+ <floater.string
+ name="status_rotate">
+ Drag colored bands to rotate object
+ </floater.string>
+ <floater.string
+ name="status_scale">
+ Click and drag to stretch selected side
+ </floater.string>
+ <floater.string
+ name="status_move">
+ Drag to move, shift-drag to copy
+ </floater.string>
+ <floater.string
+ name="status_modifyland">
+ Click and hold to modify land
+ </floater.string>
+ <floater.string
+ name="status_camera">
+ Click and drag to move camera
+ </floater.string>
+ <floater.string
+ name="status_grab">
+ Drag to move, Ctrl to lift, Ctrl+Shift to rotate
+ </floater.string>
+ <floater.string
+ name="status_place">
+ Click inworld to build
+ </floater.string>
+ <floater.string
+ name="status_selectland">
+ Click and drag to select land
+ </floater.string>
+ <floater.string
+ name="grid_screen_text">
+ Screen
+ </floater.string>
+ <floater.string
+ name="grid_local_text">
+ Local
+ </floater.string>
+ <floater.string
+ name="grid_world_text">
+ World
+ </floater.string>
+ <floater.string
+ name="grid_reference_text">
+ Reference
+ </floater.string>
+ <floater.string
+ name="grid_attachment_text">
+ Attachment
+ </floater.string>
+ <button
+ follows="left|top"
+ height="25"
+ image_bottom_pad="1"
+ image_overlay="Tool_Zoom"
+ image_selected="PushButton_Selected_Press"
+ layout="topleft"
+ left="10"
+ name="button focus"
+ tool_tip="Focus"
+ width="35">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Focus" />
+ </button>
+ <button
+ follows="left|top"
+ height="25"
+ image_bottom_pad="1"
+ image_overlay="Tool_Grab"
+ image_selected="PushButton_Selected_Press"
+ layout="topleft"
+ left_pad="10"
+ name="button move"
+ tool_tip="Move"
+ width="35">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Move" />
+ </button>
+ <button
+ follows="left|top"
+ height="25"
+ image_bottom_pad="1"
+ image_overlay="Tool_Face"
+ image_selected="PushButton_Selected_Press"
+ layout="topleft"
+ left_pad="10"
+ name="button edit"
+ tool_tip="Edit"
+ width="35">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Edit" />
+ </button>
+ <button
+ follows="left|top"
+ height="25"
+ image_bottom_pad="1"
+ image_overlay="Tool_Create"
+ image_selected="PushButton_Selected_Press"
+ layout="topleft"
+ left_pad="10"
+ name="button create"
+ tool_tip="Create"
+ width="35">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Create" />
+ </button>
+ <button
+ follows="left|top"
+ height="25"
+ image_bottom_pad="1"
+ image_overlay="Tool_Dozer"
+ image_selected="PushButton_Selected_Press"
+ layout="topleft"
+ left_pad="10"
+ name="button land"
+ tool_tip="Land"
+ width="35">
+ <button.commit_callback
+ function="BuildTool.setTool"
+ parameter="Land" />
+ </button>
+ <text
+ height="30"
+ word_wrap="true"
+ use_ellipses="true"
+ type="string"
+ text_color="LabelSelectedDisabledColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="8"
+ name="text status"
+ top_pad="3"
+ width="285">
+ Drag to move, shift-drag to copy
+ </text>
+ <radio_group
+ layout="topleft"
+ left="10"
+ height="70"
+ top="59"
+ name="focus_radio_group">
+ <radio_item
+ top_pad="6"
+ label="Zoom"
+ layout="topleft"
+ name="radio zoom" />
+ <radio_item
+ top_pad="6"
+ label="Orbit (Ctrl)"
+ layout="topleft"
+ name="radio orbit" />
+ <radio_item
+ top_pad="6"
+ label="Pan (Ctrl+Shift)"
+ layout="topleft"
+ name="radio pan" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioFocus"/>
+ </radio_group>
+ <slider_bar
+ follows="left|top"
+ height="14"
+ increment="0.01"
+ initial_value="0.125"
+ layout="topleft"
+ max_val="0.5"
+ top_delta="-2"
+ left_delta="100"
+ name="slider zoom"
+ width="134">
+ <slider_bar.commit_callback
+ function="BuildTool.commitZoom"/>
+ </slider_bar>
+ <radio_group
+ left="10"
+ height="70"
+ top="59"
+ layout="topleft"
+ name="move_radio_group">
+ <radio_item
+ top_pad="6"
+ label="Move"
+ layout="topleft"
+ name="radio move" />
+ <radio_item
+ top_pad="6"
+ label="Lift (Ctrl)"
+ layout="topleft"
+ name="radio lift" />
+ <radio_item
+ top_pad="6"
+ label="Spin (Ctrl+Shift)"
+ layout="topleft"
+ name="radio spin" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioMove"/>
+ </radio_group>
+ <radio_group
+ follows="left|top"
+ left="5"
+ top="59"
+ height="70"
+ layout="topleft"
+ name="edit_radio_group">
+ <radio_item
+ label="Move"
+ layout="topleft"
+ name="radio position" />
+ <radio_item
+ top_pad="6"
+ label="Rotate (Ctrl)"
+ layout="topleft"
+ name="radio rotate" />
+ <radio_item
+ top_pad="6"
+ label="Stretch (Ctrl+Shift)"
+ layout="topleft"
+ name="radio stretch" />
+ <radio_item
+ top_pad="6"
+ label="Select Face"
+ layout="topleft"
+ name="radio select face" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioEdit"/>
+ </radio_group>
+ <check_box
+ left="5"
+ follows="left|top"
+ height="28"
+ control_name="EditLinkedParts"
+ label="Edit linked"
+ layout="topleft"
+ name="checkbox edit linked parts"
+ top_pad="-10">
+ <check_box.commit_callback
+ function="BuildTool.selectComponent"/>
+ </check_box>
+
+ <button
+ follows="left|top"
+ height="23"
+ label="Link"
+ top_pad="2"
+ layout="topleft"
+ left="5"
+ name="link_btn"
+ width="50">
+ <button.commit_callback
+ function="BuildTool.LinkObjects"/>
+ </button>
+ <button
+ follows="left|top"
+ height="23"
+ label="Unlink"
+ layout="topleft"
+ left_pad="2"
+ name="unlink_btn"
+ width="50">
+ <button.commit_callback
+ function="BuildTool.UnlinkObjects"/>
+ </button>
+ <text
+ text_color="LtGray_50"
+ follows="top|left"
+ halign="left"
+ left_pad="3"
+ name="RenderingCost"
+ tool_tip="Shows the rendering cost calculated for this object"
+ top_delta="11"
+ type="string"
+ width="100">
+ þ: [COUNT]
+ </text>
+ <check_box
+ control_name="ScaleUniform"
+ height="19"
+ label=""
+ layout="topleft"
+ left="143"
+ name="checkbox uniform"
+ top="50"
+ width="20" />
+ <text
+ height="19"
+ label="Stretch Both Sides"
+ left_delta="20"
+ name="checkbox uniform label"
+ top_delta="2"
+ width="120"
+ layout="topleft"
+ follows="top|left"
+ wrap="true">
+ Stretch Both Sides
+ </text>
+ <check_box
+ control_name="ScaleStretchTextures"
+ height="19"
+ initial_value="true"
+ label="Stretch Textures"
+ layout="topleft"
+ left="143"
+ name="checkbox stretch textures"
+ top_pad="-6"
+ follows="left|top"
+ width="134" />
+ <check_box
+ control_name="SnapEnabled"
+ height="18"
+ initial_value="true"
+ label="Snap to grid"
+ layout="topleft"
+ top_pad="0"
+ name="checkbox snap to grid"
+ width="134" />
+ <combo_box
+ height="23"
+ layout="topleft"
+ follows="left|top"
+ name="combobox grid mode"
+ tool_tip="Choose the type of grid ruler for positioning the object"
+ top_pad="0"
+ width="108">
+ <combo_box.item
+ label="World grid"
+ name="World"
+ value="World" />
+ <combo_box.item
+ label="Local grid"
+ name="Local"
+ value="Local" />
+ <combo_box.item
+ label="Reference grid"
+ name="Reference"
+ value="Reference" />
+ <combo_box.commit_callback
+ function="BuildTool.gridMode"/>
+ </combo_box>
+ <button
+ left_pad="0"
+ image_selected="ForwardArrow_Press"
+ image_unselected="ForwardArrow_Off"
+ layout="topleft"
+ follows="top|left"
+ name="Options..."
+ tool_tip="See more grid options"
+ top_pad="-22"
+ right="-10"
+ width="18"
+ height="23" >
+ <button.commit_callback
+ function="BuildTool.gridOptions"/>
+ </button>
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cube"
+ image_disabled_selected="Object_Cube"
+ image_selected="Object_Cube_Selected"
+ image_unselected="Object_Cube"
+ layout="topleft"
+ left="10"
+ name="ToolCube"
+ tool_tip="Cube"
+ top="51"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Prism"
+ image_disabled_selected="Object_Prism"
+ image_selected="Object_Prism_Selected"
+ image_unselected="Object_Prism"
+ layout="topleft"
+ left_delta="29"
+ name="ToolPrism"
+ tool_tip="Prism"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Pyramid"
+ image_disabled_selected="Object_Pyramid"
+ image_selected="Object_Pyramid_Selected"
+ image_unselected="Object_Pyramid"
+ layout="topleft"
+ left_delta="29"
+ name="ToolPyramid"
+ tool_tip="Pyramid"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tetrahedron"
+ image_disabled_selected="Object_Tetrahedron"
+ image_selected="Object_Tetrahedron_Selected"
+ image_unselected="Object_Tetrahedron"
+ layout="topleft"
+ left_delta="29"
+ name="ToolTetrahedron"
+ tool_tip="Tetrahedron"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cylinder"
+ image_disabled_selected="Object_Cylinder"
+ image_selected="Object_Cylinder_Selected"
+ image_unselected="Object_Cylinder"
+ layout="topleft"
+ left_delta="29"
+ name="ToolCylinder"
+ tool_tip="Cylinder"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Cylinder"
+ image_disabled_selected="Object_Hemi_Cylinder"
+ image_selected="Object_Hemi_Cylinder_Selected"
+ image_unselected="Object_Hemi_Cylinder"
+ layout="topleft"
+ left_delta="29"
+ name="ToolHemiCylinder"
+ tool_tip="Hemicylinder"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Cone"
+ image_disabled_selected="Object_Cone"
+ image_selected="Object_Cone_Selected"
+ image_unselected="Object_Cone"
+ layout="topleft"
+ left_delta="29"
+ name="ToolCone"
+ tool_tip="Cone"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Cone"
+ image_disabled_selected="Object_Hemi_Cone"
+ image_selected="Object_Hemi_Cone_Selected"
+ image_unselected="Object_Hemi_Cone"
+ layout="topleft"
+ left_delta="29"
+ name="ToolHemiCone"
+ tool_tip="Hemicone"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Sphere"
+ image_disabled_selected="Object_Sphere"
+ image_selected="Object_Sphere_Selected"
+ image_unselected="Object_Sphere"
+ layout="topleft"
+ left_delta="29"
+ name="ToolSphere"
+ tool_tip="Sphere"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Hemi_Sphere"
+ image_disabled_selected="Object_Hemi_Sphere"
+ image_selected="Object_Hemi_Sphere_Selected"
+ image_unselected="Object_Hemi_Sphere"
+ layout="topleft"
+ left_delta="29"
+ name="ToolHemiSphere"
+ tool_tip="Hemisphere"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Torus"
+ image_disabled_selected="Object_Torus"
+ image_selected="Object_Torus_Selected"
+ image_unselected="Object_Torus"
+ layout="topleft"
+ left="10"
+ name="ToolTorus"
+ tool_tip="Torus"
+ top="77"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tube"
+ image_disabled_selected="Object_Tube"
+ image_selected="Object_Tube_Selected"
+ image_unselected="Object_Tube"
+ layout="topleft"
+ left_delta="29"
+ name="ToolTube"
+ tool_tip="Tube"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Ring"
+ image_disabled_selected="Object_Ring"
+ image_selected="Object_Ring_Selected"
+ image_unselected="Object_Ring"
+ layout="topleft"
+ left_delta="29"
+ name="ToolRing"
+ tool_tip="Ring"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Tree"
+ image_disabled_selected="Object_Tree"
+ image_selected="Object_Tree_Selected"
+ image_unselected="Object_Tree"
+ layout="topleft"
+ left_delta="29"
+ name="ToolTree"
+ tool_tip="Tree"
+ top_delta="0"
+ width="20" />
+ <button
+ follows="left|top"
+ height="20"
+ image_disabled="Object_Grass"
+ image_disabled_selected="Object_Grass"
+ image_selected="Object_Grass_Selected"
+ image_unselected="Object_Grass"
+ image_overlay_color="Red"
+ layout="topleft"
+ left_delta="29"
+ name="ToolGrass"
+ tool_tip="Grass"
+ top_delta="0"
+ width="20" />
+ <check_box
+ control_name="CreateToolKeepSelected"
+ height="19"
+ label="Keep Tool selected"
+ layout="topleft"
+ left="4"
+ name="checkbox sticky"
+ top="101"
+ width="128" />
+ <check_box
+ control_name="CreateToolCopySelection"
+ height="19"
+ label="Copy selection"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox copy selection"
+ top_delta="15"
+ width="134" />
+ <check_box
+ control_name="CreateToolCopyCenters"
+ height="19"
+ initial_value="true"
+ label="Center Copy"
+ layout="topleft"
+ left_delta="18"
+ name="checkbox copy centers"
+ top="132"
+ width="134" />
+ <check_box
+ control_name="CreateToolCopyRotates"
+ height="19"
+ label="Rotate Copy"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox copy rotates"
+ top_delta="16"
+ width="134" />
+ <radio_group
+ height="105"
+ layout="topleft"
+ left="4"
+ name="land_radio_group"
+ top="54"
+ width="114">
+ <radio_item
+ height="19"
+ label="Select Land"
+ layout="topleft"
+ left="0"
+ name="radio select land"
+ top="-106"
+ width="134" />
+ <radio_item
+ height="19"
+ label="Flatten"
+ layout="topleft"
+ left_delta="0"
+ name="radio flatten"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Raise"
+ layout="topleft"
+ left_delta="0"
+ name="radio raise"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Lower"
+ layout="topleft"
+ left_delta="0"
+ name="radio lower"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Smooth"
+ layout="topleft"
+ left_delta="0"
+ name="radio smooth"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Roughen"
+ layout="topleft"
+ left_delta="0"
+ name="radio noise"
+ top_delta="15"
+ width="114" />
+ <radio_item
+ height="19"
+ label="Revert"
+ layout="topleft"
+ left_delta="0"
+ name="radio revert"
+ top_delta="15"
+ width="114" />
+ <radio_group.commit_callback
+ function="BuildTool.commitRadioLand"/>
+ </radio_group>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ left="135"
+ name="Bulldozer:"
+ top="57"
+ width="100">
+ Bulldozer:
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ name="Dozer Size:"
+ left="135"
+ top_pad="5"
+ width="50">
+ Size
+ </text>
+ <slider_bar
+ control_name ="LandBrushSize"
+ follows="left|top"
+ height="19"
+ initial_value="2.0"
+ layout="topleft"
+ max_val="11"
+ min_val="1"
+ left_pad="0"
+ name="slider brush size"
+ top_delta="-3"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="12"
+ layout="topleft"
+ name="Strength:"
+ left="135"
+ top_pad="5"
+ width="50">
+ Strength
+ </text>
+ <slider_bar
+ follows="left|top"
+ height="19"
+ left_pad="0"
+ initial_value="0.00"
+ layout="topleft"
+ max_val="2"
+ min_val="-1"
+ name="slider force"
+ top_delta="-3"
+ width="80" >
+ <slider_bar.commit_callback
+ function="BuildTool.LandBrushForce"/>
+ </slider_bar>
+ <button
+ follows="left|top"
+ height="23"
+ label="Apply"
+ label_selected="Apply"
+ top_pad="5"
+ layout="topleft"
+ left="135"
+ name="button apply to selection"
+ tool_tip="Modify selected land"
+ width="82">
+ <button.commit_callback
+ function="BuildTool.applyToSelection"/>
+ </button>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ height="10"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ right="-10"
+ name="obj_count"
+ top_pad="5"
+ width="143">
+ Objects: [COUNT]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ height="10"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ right="-10"
+ name="prim_count"
+ width="143">
+ Prims: [COUNT]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ height="10"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ right="-120"
+ name="linked_set_count"
+ top="144"
+ width="80">
+ Linked Sets: [COUNT]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ height="10"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ top_delta="0"
+ right="-8"
+ name="linked_set_cost"
+ tool_tip="Cost of currently selected linked sets as [prims],[physics complexity]"
+ width="80">
+ Cost: [COST] / [PHYSICS]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ top_pad="5"
+ right="-120"
+ name="object_count"
+ width="80">
+ Objects: [COUNT]
+ </text>
+ <text
+ text_color="LtGray_50"
+ type="string"
+ length="1"
+ follows="left|top"
+ halign="right"
+ layout="topleft"
+ top_delta="0"
+ right="-8"
+ name="object_cost"
+ tool_tip="Cost of currently selected objects as [prims] / [physics complexity]"
+ width="80">
+ Cost: [COST] / [PHYSICS]
+ </text>
+ <!-- <text -->
+ <!-- text_color="LtGray_50" -->
+ <!-- type="string" -->
+ <!-- length="1" -->
+ <!-- height="10" -->
+ <!-- follows="left|top" -->
+ <!-- halign="right" -->
+ <!-- layout="topleft" -->
+ <!-- right="-10" -->
+ <!-- name="obj_count" -->
+ <!-- top_pad="5" -->
+ <!-- width="143"> -->
+ <!-- Objects: [COUNT] -->
+ <!-- </text> -->
+ <!-- <text -->
+ <!-- text_color="LtGray_50" -->
+ <!-- type="string" -->
+ <!-- length="1" -->
+ <!-- follows="left|top" -->
+ <!-- halign="right" -->
+ <!-- layout="topleft" -->
+ <!-- right="-10" -->
+ <!-- name="prim_count" -->
+ <!-- width="143"> -->
+ <!-- Prims: [COUNT] -->
+ <!-- </text> -->
+ <tab_container
+ follows="left|top"
+ height="410"
+ halign="center"
+ left="0"
+ name="Object Info Tabs"
+ tab_max_width="100"
+ tab_min_width="40"
+ tab_position="top"
+ tab_height="25"
+ top="173"
+ width="295">
+
+<panel
+ border="false"
+ follows="all"
+ label="General"
+ layout="topleft"
+ mouse_opaque="false"
+ help_topic="toolbox_general_tab"
+ name="General"
+ top="16"
+ width="295">
+ <panel.string
+ name="text deed continued">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text deed">
+ Deed
+ </panel.string>
+ <panel.string
+ name="text modify info 1">
+ You can modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 2">
+ You can modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify info 3">
+ You can't modify this object
+ </panel.string>
+ <panel.string
+ name="text modify info 4">
+ You can't modify these objects
+ </panel.string>
+ <panel.string
+ name="text modify warning">
+ You must select entire object to set permissions
+ </panel.string>
+ <panel.string
+ name="Cost Default">
+ Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Total">
+ Total Price: L$
+ </panel.string>
+ <panel.string
+ name="Cost Per Unit">
+ Price Per: L$
+ </panel.string>
+ <panel.string
+ name="Cost Mixed">
+ Mixed Price
+ </panel.string>
+ <panel.string
+ name="Sale Mixed">
+ Mixed Sale
+ </panel.string>
+ <text
+ follows="left|top"
+ height="10"
+ left="10"
+ name="Name:"
+ top="5"
+ width="90">
+ Name:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ height="19"
+ left_pad="0"
+ max_length_bytes="63"
+ name="Object Name"
+ select_on_focus="true"
+ top_delta="0"
+ width="170" />
+ <text
+ follows="left|top"
+ height="10"
+ left="10"
+ name="Description:"
+ top_pad="3"
+ width="90">
+ Description:
+ </text>
+ <line_editor
+ follows="left|top|right"
+ height="19"
+ left_pad="0"
+ max_length_bytes="127"
+ name="Object Description"
+ select_on_focus="true"
+ top_delta="0"
+ width="170" />
+ <text
+ type="string"
+ left="10"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ name="Creator:"
+ top_pad="7"
+ width="90">
+ Creator:
+ </text>
+ <!-- *NOTE: Intentionally wide for long names -->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ left_pad="0"
+ height="20"
+ layout="topleft"
+ name="Creator Name"
+ top_delta="0"
+ translate="false"
+ width="190"
+ word_wrap="true"
+ use_ellipses="true">
+ TestString PleaseIgnore (please.ignore)
+ </text>
+ <text
+ type="string"
+ length="1"
+ left="10"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ name="Owner:"
+ top_pad="13"
+ width="90">
+ Owner:
+ </text>
+ <!-- *NOTE: Intentionally wide for long names -->
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ name="Owner Name"
+ left_pad="0"
+ top_delta="0"
+ translate="false"
+ width="190"
+ word_wrap="true"
+ use_ellipses="true">
+ TestString PleaseIgnore (please.ignore)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left="10"
+ height="18"
+ name="Group:"
+ top_pad="17"
+ width="75">
+ Group:
+ </text>
+ <name_box
+ follows="left|top"
+ height="18"
+ initial_value="Loading..."
+ layout="topleft"
+ left_pad="23"
+ name="Group Name Proxy"
+ width="142" />
+ <button
+ follows="top|left"
+ height="23"
+ image_overlay="Edit_Wrench"
+ layout="topleft"
+ left_pad="13"
+ name="button set group"
+ tab_stop="false"
+ tool_tip="Choose a group to share this object's permissions"
+ width="23" />
+ <check_box
+ height="19"
+ follows="left|top"
+ label="Share"
+ layout="topleft"
+ name="checkbox share with group"
+ tool_tip="Allow all members of the set group to share your modify permissions for this object. You must Deed to enable role restrictions."
+ top_pad="10"
+ left="100"
+ width="87" />
+ <button
+ follows="top|left"
+ height="23"
+ label="Deed"
+ label_selected="Deed"
+ layout="topleft"
+ name="button deed"
+ left_pad="19"
+ tool_tip="Deeding gives this item away with next owner permissions. Group shared objects can be deeded by a group officer."
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ top_pad="10"
+ left="10"
+ name="label click action"
+ width="118">
+ Click to:
+ </text>
+ <combo_box
+ follows="left|top"
+ height="23"
+ layout="topleft"
+ name="clickaction"
+ width="148"
+ left_pad="10">
+ <combo_box.item
+ label="Touch (default)"
+ name="Touch/grab(default)"
+ value="Touch" />
+ <combo_box.item
+ label="Sit on object"
+ name="Sitonobject"
+ value="Sit" />
+ <combo_box.item
+ label="Buy object"
+ name="Buyobject"
+ value="Buy" />
+ <combo_box.item
+ label="Pay object"
+ name="Payobject"
+ value="Pay" />
+ <combo_box.item
+ label="Open"
+ name="Open"
+ value="Open" />
+ <combo_box.item
+ label="Zoom"
+ name="Zoom"
+ value="Zoom" />
+ </combo_box>
+ <check_box
+ height="23"
+ label="For Sale:"
+ layout="topleft"
+ name="checkbox for sale"
+ left="7"
+ width="100" />
+<!-- NEW SALE TYPE COMBO BOX -->
+ <combo_box
+ left_pad="10"
+ layout="topleft"
+ follows="left|top"
+ allow_text_entry="false"
+ height="23"
+ initial_value="2"
+ max_chars="20"
+ mouse_opaque="true"
+ name="sale type"
+ width="168">
+ <combo_box.item
+ name="Copy"
+ label="Copy"
+ value="2" />
+ <combo_box.item
+ name="Contents"
+ label="Contents"
+ value="3" />
+ <combo_box.item
+ name="Original"
+ label="Original"
+ value="1" />
+ </combo_box>
+<!-- NEW PRICE SPINNER
+Objects are allowed to be for sale for L$0 to invoke buy UI behavior
+even though the user gets a free copy.
+-->
+ <spinner
+ follows="left|top"
+ decimal_digits="0"
+ increment="1"
+ top_pad="8"
+ left="118"
+ control_name="Edit Cost"
+ name="Edit Cost"
+ label="Price: L$"
+ label_width="65"
+ width="165"
+ min_val="0"
+ height="20"
+ max_val="999999999" />
+ <check_box
+ height="15"
+ width="110"
+ top_pad="5"
+ label="Show in search"
+ layout="topleft"
+ left="100"
+ name="search_check"
+ tool_tip="Let people see this object in search results" />
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="perms_build"
+ left="0"
+ top_pad="4"
+ height="105"
+ width="290">
+ <text
+ type="string"
+ length="1"
+ left="10"
+ top_pad="9"
+ text_color="EmphasisColor"
+ height="16"
+ follows="left|top|right"
+ layout="topleft"
+ name="perm_modify"
+ width="264">
+ You can modify this object
+ </text>
+ <text
+ type="string"
+ follows="left|top"
+ name="Anyone can:"
+ width="250"
+ left="10">
+ Anyone:
+ </text>
+ <check_box
+ height="19"
+ label="Move"
+ layout="topleft"
+ name="checkbox allow everyone move"
+ left="10"
+ width="85" />
+ <check_box
+ height="19"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox allow everyone copy"
+ width="90" />
+ <text
+ type="string"
+ follows="left|top"
+ height="19"
+ name="Next owner can:"
+ width="250"
+ left="10">
+ Next owner:
+ </text>
+ <check_box
+ follows="left|top|right"
+ label="Modify"
+ layout="topleft"
+ left="10"
+ name="checkbox next owner can modify"
+ width="85" />
+ <check_box
+ follows="left|top|right"
+ height="19"
+ label="Copy"
+ layout="topleft"
+ left_pad="0"
+ name="checkbox next owner can copy"
+ width="80" />
+ <check_box
+ follows="left|top|right"
+ height="19"
+ label="Transfer"
+ layout="topleft"
+ name="checkbox next owner can transfer"
+ left_pad="0"
+ top_delta="0"
+ tool_tip="Next owner can give away or resell this object"
+ width="100" />
+<!-- *NOTE: These "B/O/G/E/N/F fields may overlap "perm_modify" above,
+ but that's OK, this is used only for debugging. -->
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ top="9"
+ follows="left|top"
+ layout="topleft"
+ left="230"
+ name="B:"
+ height="10"
+ width="80">
+ B:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_delta="0"
+ top_pad="2"
+ name="O:"
+ height="10"
+ width="80">
+ O:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_delta="0"
+ top_pad="2"
+ name="G:"
+ height="10"
+ width="80">
+ G:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ left_delta="0"
+ top_pad="2"
+ layout="topleft"
+ name="E:"
+ height="10"
+ width="80">
+ E:
+ </text>
+ <text
+ type="string"
+ text_color="EmphasisColor"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_delta="0"
+ top_pad="2"
+ name="N:"
+ height="10"
+ width="80">
+ N:
+ </text>
+ <text
+ type="string"
+ text_color="White"
+ length="1"
+ follows="left|top"
+ layout="topleft"
+ left_delta="0"
+ top_pad="2"
+ name="F:"
+ height="10"
+ width="80">
+ F:
+ </text>
+ </panel>
+ </panel>
+ <!-- Object tab -->
+ <panel
+ border="false"
+ follows="all"
+ height="567"
+ label="Object"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_object_tab"
+ name="Object"
+ top="16"
+ width="295">
+ <check_box
+ height="19"
+ label="Locked"
+ layout="topleft"
+ name="checkbox locked"
+ tool_tip="Prevents object from being moved or deleted. Frequently useful during building to avoid unintended edits."
+ top_pad="5"
+ left="10"
+ width="123" />
+ <check_box
+ height="19"
+ label="Physical"
+ layout="topleft"
+ name="Physical Checkbox Ctrl"
+ tool_tip="Allows object to be pushed and affected by gravity"
+ top_pad="0"
+ width="123" />
+ <check_box
+ height="19"
+ label="Temporary"
+ layout="topleft"
+ name="Temporary Checkbox Ctrl"
+ tool_tip="Causes object to be deleted 1 minute after creation"
+ top_pad="0"
+ width="123" />
+ <check_box
+ height="19"
+ label="Phantom"
+ layout="topleft"
+ name="Phantom Checkbox Ctrl"
+ tool_tip="Causes object to not collide with other objects or avatars"
+ top_pad="0"
+ width="123" />
+
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label position"
+ top_pad="10"
+ width="121">
+ Position (meters)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="512"
+ min_val="-256"
+ name="Pos X"
+ text_enabled_color="1 0 0.3 .7"
+ top_pad="5"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="512"
+ min_val="-256"
+ name="Pos Y"
+ text_enabled_color="EmphasisColor"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="4096"
+ name="Pos Z"
+ text_enabled_color="0 0.8 1 .65"
+ top_pad="3"
+ width="87" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label size"
+ top_pad="6"
+ width="121">
+ Size (meters)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="64"
+ min_val="0.01"
+ name="Scale X"
+ text_enabled_color="1 1 1 1"
+ top_pad="5"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="64"
+ min_val="0.01"
+ name="Scale Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="64"
+ min_val="0.01"
+ name="Scale Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label rotation"
+ top_pad="10"
+ width="121">
+ Rotation (degrees)
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot X"
+ text_enabled_color="1 1 1 1"
+ top_pad="5"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Y"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Z"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="9999"
+ min_val="-9999"
+ name="Rot Z"
+ text_enabled_color="1 1 1 1"
+ top_pad="3"
+ width="87" />
+ <!-- <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="label basetype"
+ top="5"
+ width="150">
+ Prim Type
+ </text>-->
+ <combo_box
+ height="19"
+ layout="topleft"
+ name="comboBaseType"
+ top="6"
+ left="125"
+ width="150">
+ <combo_box.item
+ label="Box"
+ name="Box"
+ value="Box" />
+ <combo_box.item
+ label="Cylinder"
+ name="Cylinder"
+ value="Cylinder" />
+ <combo_box.item
+ label="Prism"
+ name="Prism"
+ value="Prism" />
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Torus"
+ name="Torus"
+ value="Torus" />
+ <combo_box.item
+ label="Tube"
+ name="Tube"
+ value="Tube" />
+ <combo_box.item
+ label="Ring"
+ name="Ring"
+ value="Ring" />
+ <combo_box.item
+ label="Sculpted"
+ name="Sculpted"
+ value="Sculpted" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="text cut"
+ top_pad="5"
+ width="150">
+ Path Cut (begin/end)
+ </text>
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.98"
+ name="cut begin"
+ top_pad="4"
+ width="68" />
+ <spinner
+ follows="left|top"
+ height="16"
+ increment="0.025"
+ initial_value="1"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="0.02"
+ name="cut end"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text hollow"
+ top_pad="6"
+ width="68">
+ Hollow
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="10"
+ name="text skew"
+ width="63">
+ Skew
+ </text>
+ <spinner
+ decimal_digits="1"
+ follows="left|top"
+ height="19"
+ increment="5"
+ initial_value="0"
+ layout="topleft"
+ left="125"
+ max_val="95"
+ name="Scale 1"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ layout="topleft"
+ left_pad="10"
+ max_val="0.95"
+ min_val="-0.95"
+ name="Skew"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="15"
+ layout="topleft"
+ left="125"
+ name="Hollow Shape"
+ top_pad="4"
+ width="150">
+ Hollow Shape
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="hole"
+ top_pad="-2"
+ width="150">
+ <combo_box.item
+ label="Default"
+ name="Default"
+ value="Default" />
+ <combo_box.item
+ label="Circle"
+ name="Circle"
+ value="Circle" />
+ <combo_box.item
+ label="Square"
+ name="Square"
+ value="Square" />
+ <combo_box.item
+ label="Triangle"
+ name="Triangle"
+ value="Triangle" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="text twist"
+ top_pad="5"
+ width="150">
+ Twist (begin/end)
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="9"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="180"
+ min_val="-180"
+ name="Twist Begin"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="9"
+ initial_value="0"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ max_val="180"
+ min_val="-180"
+ name="Twist End"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="scale_taper"
+ top_pad="3"
+ width="150">
+ Taper
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="scale_hole"
+ top_delta="0"
+ width="150">
+ Hole Size
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="Taper Scale X"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="-1"
+ name="Taper Scale Y"
+ top_delta="0"
+ width="68" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text topshear"
+ top_pad="3"
+ width="141">
+ Top Shear
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.5"
+ min_val="-0.5"
+ name="Shear X"
+ top_pad="4"
+ width="68" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ max_val="0.5"
+ min_val="-0.5"
+ name="Shear Y"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="advanced_cut"
+ top_pad="3"
+ width="150">
+ Profile Cut (begin/end)
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="advanced_dimple"
+ top_delta="0"
+ width="150">
+ Dimple (begin/end)
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="advanced_slice"
+ top_delta="0"
+ width="150">
+ Slice (begin/end)
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.02"
+ initial_value="0"
+ label="B"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ max_val="0.98"
+ name="Path Limit Begin"
+ top_pad="3"
+ width="68" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.02"
+ initial_value="1"
+ label="E"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="0.02"
+ name="Path Limit End"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text taper2"
+ top_pad="3"
+ width="150">
+ Taper
+ </text>
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="X"
+ label_width="10"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="Taper X"
+ top_pad="3"
+ width="68" />
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ label="Y"
+ label_width="10"
+ layout="topleft"
+ left_pad="10"
+ min_val="-1"
+ name="Taper Y"
+ top_delta="0"
+ width="68" />
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="125"
+ name="text radius delta"
+ top_pad="2"
+ width="78">
+ Radius
+ </text>
+ <text
+ visible="false"
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="78"
+ name="text revolutions"
+ width="68">
+ Revolutions
+ </text>
+ <spinner
+ visible="false"
+ follows="left|top"
+ height="19"
+ increment="0.05"
+ initial_value="0"
+ layout="topleft"
+ left="125"
+ min_val="-1"
+ name="Radius Offset"
+ top_pad="4"
+ width="68" />
+ <spinner
+ visible="false"
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ initial_value="1"
+ layout="topleft"
+ left_pad="10"
+ max_val="4"
+ min_val="1"
+ name="Revolutions"
+ top_delta="0"
+ width="68" />
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="141"
+ label="Sculpt Texture"
+ layout="topleft"
+ left="125"
+ name="sculpt texture control"
+ tool_tip="Click to choose a picture"
+ top="70"
+ visible="false"
+ width="145" />
+ <check_box
+ height="19"
+ label="Mirror"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt mirror control"
+ tool_tip="Flips sculpted prim along the X axis"
+ top_pad="8"
+ visible="false"
+ width="130" />
+ <check_box
+ height="19"
+ label="Inside-out"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt invert control"
+ tool_tip="Inverts the sculpted prims normals, making it appear inside-out"
+ top_pad="4"
+ visible="false"
+ width="121" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="label sculpt type"
+ top_pad="10"
+ visible="false"
+ width="130">
+ Stitching type
+ </text>
+ <combo_box
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="sculpt type control"
+ top_pad="4"
+ visible="false"
+ width="150">
+ <combo_box.item
+ label="(none)"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Sphere"
+ name="Sphere"
+ value="Sphere" />
+ <combo_box.item
+ label="Torus"
+ name="Torus"
+ value="Torus" />
+ <combo_box.item
+ label="Plane"
+ name="Plane"
+ value="Plane" />
+ <combo_box.item
+ label="Cylinder"
+ name="Cylinder"
+ value="Cylinder" />
+ <combo_box.item
+ label="Mesh"
+ name="Mesh"
+ value="Mesh" />
+ </combo_box>
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="367"
+ label="Features"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_features_tab"
+ name="Features"
+ top_delta="0"
+ width="295">
+ <panel.string name="None">None</panel.string>
+ <panel.string name="Prim">Prim</panel.string>
+ <panel.string name="Convex Hull">Convex Hull</panel.string>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="20"
+ layout="topleft"
+ left="10"
+ name="select_single"
+ top="5"
+ width="252"
+ word_wrap="true">
+ Select only one primitive to edit features.
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="edit_object"
+ top="5"
+ width="252">
+ Edit object features:
+ </text>
+ <check_box
+ height="19"
+ label="Flexible Path"
+ layout="topleft"
+ left="10"
+ name="Flexible1D Checkbox Ctrl"
+ tool_tip="Allows object to flex about the Z axis (Client-side only)"
+ top_pad="20"
+ width="121" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="2"
+ label="Softness"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="3"
+ name="FlexNumSections"
+ top_pad="10"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="0.3"
+ label="Gravity"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexGravity"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="2"
+ label="Drag"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexFriction"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="0"
+ label="Wind"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexWind"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.5"
+ initial_value="1"
+ label="Tension"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ name="FlexTension"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force X"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceX"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force Y"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceY"
+ top_pad="4"
+ width="128" />
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Force Z"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="10"
+ min_val="-10"
+ name="FlexForceZ"
+ top_pad="4"
+ width="128" />
+
+ <check_box
+ height="16"
+ label="Light"
+ layout="topleft"
+ left="10"
+ name="Light Checkbox Ctrl"
+ tool_tip="Causes object to emit light"
+ top_pad="15"
+ width="60" />
+ <color_swatch
+ can_apply_immediately="true"
+ color="0.5 0.5 0.5 1"
+ border.border_thickness="0"
+ follows="left|top"
+ height="50"
+ layout="topleft"
+ left_pad="10"
+ top_pad="-17"
+ name="colorswatch"
+ tool_tip="Click to open color picker"
+ width="40" />
+ <texture_picker
+ allow_no_texture="true"
+ top_delta="0"
+ can_apply_immediately="true"
+ default_image_name="Default"
+ follows="left|top"
+ height="48"
+ label=""
+ left_delta="57"
+ mouse_opaque="true"
+ name="light texture control"
+ tool_tip="Click to choose a projection image (only has effect with deferred rendering enabled)"
+ width="32" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0.5"
+ label="Intensity"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ name="Light Intensity"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.1"
+ initial_value="0.5"
+ label="FOV"
+ label_width="55"
+ left="144"
+ max_val="3"
+ min_val="0"
+ mouse_opaque="true"
+ name="Light FOV"
+ width="120" />
+ <spinner follows="left|top"
+ height="19"
+ initial_value="5"
+ label="Radius"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ max_val="20"
+ name="Light Radius"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.5"
+ initial_value="0.5"
+ label="Focus"
+ label_width="55"
+ left="144"
+ max_val="20"
+ min_val="-20"
+ mouse_opaque="true"
+ name="Light Focus"
+ width="120" />
+ <spinner follows="left|top"
+ height="19"
+ increment="0.25"
+ initial_value="1"
+ label="Falloff"
+ label_width="70"
+ layout="topleft"
+ left="10"
+ max_val="2"
+ name="Light Falloff"
+ top_pad="3"
+ width="128" />
+ <spinner bottom_delta="0"
+ decimal_digits="3"
+ follows="left|top"
+ height="16"
+ increment="0.05"
+ initial_value="1"
+ label="Ambiance"
+ label_width="55"
+ left="144"
+ max_val="1"
+ min_val="0"
+ mouse_opaque="true"
+ name="Light Ambiance"
+ width="120" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label physicsshapetype"
+ top="38"
+ width="121">
+ Physics Shape Type:
+ </text>
+ <combo_box
+ height="19"
+ top_delta="15"
+ layout="topleft"
+ follows="left|top"
+ name="Physics Shape Type Combo Ctrl"
+ tool_tip="Choose the physics shape type"
+ width="108"/>
+ <combo_box
+ height="19"
+ layout="topleft"
+ name="material"
+ top_pad="5"
+ width="150">
+ <combo_box.item
+ label="Stone"
+ name="Stone"
+ value="Stone" />
+ <combo_box.item
+ label="Metal"
+ name="Metal"
+ value="Metal" />
+ <combo_box.item
+ label="Glass"
+ name="Glass"
+ value="Glass" />
+ <combo_box.item
+ label="Wood"
+ name="Wood"
+ value="Wood" />
+ <combo_box.item
+ label="Flesh"
+ name="Flesh"
+ value="Flesh" />
+ <combo_box.item
+ label="Plastic"
+ name="Plastic"
+ value="Plastic" />
+ <combo_box.item
+ label="Rubber"
+ name="Rubber"
+ value="Rubber" />
+ </combo_box>
+
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="1"
+ label="Gravity"
+ label_width="70"
+ layout="topleft"
+ min_val="-1"
+ max_val="28"
+ name="Physics Gravity"
+ top_pad="10"
+ width="132" />
+
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.1"
+ initial_value="0"
+ label="Friction"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="255"
+ min_val="0"
+ name="Physics Friction"
+ top_pad="4"
+ width="132" />
+
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.1"
+ initial_value="0"
+ label="Density"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="22587"
+ min_val="1"
+ name="Physics Density"
+ top_pad="4"
+ width="132" />
+
+ <spinner
+ follows="left|top"
+ height="19"
+ increment="0.01"
+ initial_value="0"
+ label="Restitution"
+ label_width="70"
+ layout="topleft"
+ left_delta="0"
+ max_val="1"
+ min_val="0"
+ name="Physics Restitution"
+ top_pad="4"
+ width="132" />
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ height="367"
+ label="Texture"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_texture_tab"
+ name="Texture"
+ top_delta="0"
+ width="295">
+ <panel.string
+ name="string repeats per meter">
+ Repeats Per Meter
+ </panel.string>
+ <panel.string
+ name="string repeats per face">
+ Repeats Per Face
+ </panel.string>
+ <texture_picker
+ can_apply_immediately="true"
+ default_image_name="Default"
+ fallback_image="locked_image.j2c"
+ follows="left|top"
+ height="80"
+ label="Texture"
+ layout="topleft"
+ left="10"
+ name="texture control"
+ tool_tip="Click to choose a picture"
+ top="8"
+ width="64" />
+ <color_swatch
+ can_apply_immediately="true"
+ follows="left|top"
+ height="80"
+ label="Color"
+ layout="topleft"
+ left_pad="15"
+ name="colorswatch"
+ tool_tip="Click to open color picker"
+ top_delta="0"
+ width="64" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="15"
+ name="color trans"
+ text_readonly_color="LabelDisabledColor"
+ top="6"
+ width="110">
+ Transparency %
+ </text>
+ <spinner
+ decimal_digits="0"
+ follows="left|top"
+ height="19"
+ increment="2"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ max_val="100"
+ name="ColorTrans"
+ top_pad="4"
+ width="80" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_delta="0"
+ name="glow label"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="8"
+ width="80">
+ Glow
+ </text>
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ layout="topleft"
+ left_delta="0"
+ name="glow"
+ top_pad="4"
+ width="80" />
+ <check_box
+ height="19"
+ label="Full Bright"
+ layout="topleft"
+ left_delta="-5"
+ name="checkbox fullbright"
+ top_pad="4"
+ width="81" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="tex gen"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="5"
+ width="90">
+ Mapping
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox texgen"
+ top_pad="4"
+ width="90">
+ <combo_box.item
+ label="Default"
+ name="Default"
+ value="Default" />
+ <combo_box.item
+ label="Planar"
+ name="Planar"
+ value="Planar" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ name="label shininess"
+ left_pad="4"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="-37"
+ width="90">
+ Shininess
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox shininess"
+ top_pad="4"
+ width="90">
+ <combo_box.item
+ label="None"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Low"
+ name="Low"
+ value="Low" />
+ <combo_box.item
+ label="Medium"
+ name="Medium"
+ value="Medium" />
+ <combo_box.item
+ label="High"
+ name="High"
+ value="High" />
+ </combo_box>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left_pad="4"
+ name="label bumpiness"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="-37"
+ width="90">
+ Bumpiness
+ </text>
+ <combo_box
+ height="23"
+ layout="topleft"
+ left_delta="0"
+ name="combobox bumpiness"
+ top_pad="4"
+ width="90">
+ <combo_box.item
+ label="None"
+ name="None"
+ value="None" />
+ <combo_box.item
+ label="Brightness"
+ name="Brightness"
+ value="Brightness" />
+ <combo_box.item
+ label="Darkness"
+ name="Darkness"
+ value="Darkness" />
+ <combo_box.item
+ label="woodgrain"
+ name="woodgrain"
+ value="woodgrain" />
+ <combo_box.item
+ label="bark"
+ name="bark"
+ value="bark" />
+ <combo_box.item
+ label="bricks"
+ name="bricks"
+ value="bricks" />
+ <combo_box.item
+ label="checker"
+ name="checker"
+ value="checker" />
+ <combo_box.item
+ label="concrete"
+ name="concrete"
+ value="concrete" />
+ <combo_box.item
+ label="crustytile"
+ name="crustytile"
+ value="crustytile" />
+ <combo_box.item
+ label="cutstone"
+ name="cutstone"
+ value="cutstone" />
+ <combo_box.item
+ label="discs"
+ name="discs"
+ value="discs" />
+ <combo_box.item
+ label="gravel"
+ name="gravel"
+ value="gravel" />
+ <combo_box.item
+ label="petridish"
+ name="petridish"
+ value="petridish" />
+ <combo_box.item
+ label="siding"
+ name="siding"
+ value="siding" />
+ <combo_box.item
+ label="stonetile"
+ name="stonetile"
+ value="stonetile" />
+ <combo_box.item
+ label="stucco"
+ name="stucco"
+ value="stucco" />
+ <combo_box.item
+ label="suction"
+ name="suction"
+ value="suction" />
+ <combo_box.item
+ label="weave"
+ name="weave"
+ value="weave" />
+ </combo_box>
+ <!--
+ <line_editor
+ bevel_style="in"
+ border_style="line"
+ border_thickness="1"
+ follows="left|top"
+ height="16"
+ layout="topleft"
+ left="10"
+ max_length_bytes="63"
+ name="Home Url"
+ select_on_focus="true"
+ top="134"
+ width="250" />
+ <check_box
+ height="16"
+ label="Media Face"
+ layout="topleft"
+ left_delta="0"
+ name="has media"
+ top_pad="6"
+ width="70" />
+ <button
+ follows="left|top"
+ font="SansSerifSmall"
+ height="20"
+ label="Set Media Info"
+ label_selected="Set Media Info"
+ layout="topleft"
+ left_pad="60"
+ name="media info set"
+ top_delta="-4"
+ width="120" />
+-->
+ <check_box
+ follows="top|left"
+ height="16"
+ initial_value="false"
+ label="Align planar faces"
+ layout="topleft"
+ left="17"
+ name="checkbox planar align"
+ tool_tip="Align textures on all selected faces with the last selected face. Requires Planar texture mapping."
+ top_delta="26"
+ width="140" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="rpt"
+ text_readonly_color="LabelDisabledColor"
+ top_pad="2"
+ width="140">
+ Repeats / Face
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Horizontal (U)"
+ label_width="125"
+ layout="topleft"
+ left="20"
+ max_val="100"
+ name="TexScaleU"
+ top_pad="5"
+ width="185" />
+ <check_box
+ height="19"
+ label="Flip"
+ layout="topleft"
+ left_pad="5"
+ name="checkbox flip s"
+ top_delta="0"
+ width="70" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Vertical (V)"
+ label_width="125"
+ layout="topleft"
+ left="20"
+ max_val="100"
+ name="TexScaleV"
+ width="185" />
+ <check_box
+ height="19"
+ label="Flip"
+ layout="topleft"
+ left_pad="5"
+ name="checkbox flip t"
+ top_delta="0"
+ width="70" />
+ <spinner
+ decimal_digits="2"
+ follows="left|top"
+ height="19"
+ increment="1"
+ initial_value="0"
+ label="Rotation˚"
+ layout="topleft"
+ label_width="135"
+ left="10"
+ max_val="9999"
+ min_val="-9999"
+ name="TexRot"
+ width="195" />
+
+ <spinner
+ decimal_digits="1"
+ follows="left|top"
+ height="23"
+ initial_value="1"
+ label="Repeats / Meter"
+ layout="topleft"
+ label_width="135"
+ left="10"
+ max_val="10"
+ min_val="0.1"
+ name="rptctrl"
+ width="195" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Apply"
+ label_selected="Apply"
+ layout="topleft"
+ left_pad="5"
+ name="button apply"
+ width="75" />
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="10"
+ layout="topleft"
+ left="10"
+ name="tex offset"
+ text_readonly_color="LabelDisabledColor"
+ width="200">
+ Texture Offset
+ </text>
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Horizontal (U)"
+ label_width="125"
+ layout="topleft"
+ left="20"
+ min_val="-1"
+ name="TexOffsetU"
+ width="185" />
+ <spinner
+ follows="left|top"
+ height="19"
+ initial_value="0"
+ label="Vertical (V)"
+ label_width="125"
+ layout="topleft"
+ left_delta="0"
+ min_val="-1"
+ name="TexOffsetV"
+ top_pad="1"
+ width="185" />
+ <panel
+ border="false"
+ follows="left|top"
+ layout="topleft"
+ mouse_opaque="false"
+ background_visible="true"
+ bg_alpha_color="DkGray"
+ name="Add_Media"
+ left="0"
+ height="47"
+ width="290">
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="18"
+ layout="topleft"
+ left="10"
+ top_pad="3"
+ name="media_tex"
+ width="190">
+ Media
+ </text>
+ <button
+ follows="top|left"
+ height="18"
+ image_selected="AddItem_Press"
+ image_unselected="AddItem_Off"
+ image_disabled="AddItem_Disabled"
+ layout="topleft"
+ left_pad="0"
+ name="add_media"
+ tab_stop="false"
+ top_delta="0"
+ tool_tip="Add Media"
+ width="18">
+ <button.commit_callback
+ function="BuildTool.AddMedia"/>
+ </button>
+ <button
+ follows="top|left"
+ height="18"
+ image_selected="TrashItem_Press"
+ image_unselected="TrashItem_Off"
+ layout="topleft"
+ left_pad="5"
+ name="delete_media"
+ tool_tip="Delete this media texture"
+ top_delta="0"
+ width="18">
+ <button.commit_callback
+ function="BuildTool.DeleteMedia"/>
+ </button>
+ <button
+ follows="top|left"
+ tool_tip="Edit this Media"
+ height="12"
+ image_disabled="Icon_Gear_Background"
+ image_selected="Icon_Gear_Press"
+ image_unselected="Icon_Gear_Foreground"
+ layout="topleft"
+ left_pad="10"
+ name="edit_media"
+ top_delta="3"
+ width="12">
+ <button.commit_callback
+ function="BuildTool.EditMedia"/>
+ </button>
+ <text
+ follows="left|top|right"
+ height="9"
+ layout="topleft"
+ left="10"
+ use_ellipses="true"
+ read_only="true"
+ name="media_info"
+ width="280" />
+ <web_browser
+ visible="false"
+ enabled="false"
+ border_visible="true"
+ bottom_delta="0"
+ follows="top|left"
+ left="0"
+ name="title_media"
+ width="4"
+ height="4"
+ start_url="about:blank"
+ decouple_texture_size="true" />
+ <button
+ follows="right|top"
+ height="22"
+ label="Align"
+ label_selected="Align Media"
+ layout="topleft"
+ right="-16"
+ name="button align"
+ top_delta="-4"
+ tool_tip="Align media texture (must load first)"
+ width="80" />
+ </panel>
+ </panel>
+ <panel
+ border="false"
+ follows="all"
+ label="Content"
+ layout="topleft"
+ left_delta="0"
+ mouse_opaque="false"
+ help_topic="toolbox_contents_tab"
+ name="Contents"
+ top_delta="0"
+ width="295">
+ <button
+ follows="left|top"
+ height="23"
+ label="New Script"
+ label_selected="New Script"
+ layout="topleft"
+ left="10"
+ name="button new script"
+ top="10"
+ width="134" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Permissions"
+ layout="topleft"
+ left_pad="8"
+ name="button permissions"
+ width="134" />
+ <panel_inventory_object
+ border="true"
+ border_visible="true"
+ bevel_style="in"
+ follows="left|top|right"
+ height="325"
+ layout="topleft"
+ left="10"
+ name="contents_inventory"
+ top="50"
+ width="275" />
+ </panel>
+ </tab_container>
+ <panel
+ follows="left|top"
+ height="384"
+ layout="topleft"
+ left_delta="0"
+ name="land info panel"
+ top_delta="0"
+ width="295">
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_info"
+ top="24"
+ width="240">
+ Parcel Information
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="30"
+ name="label_area_price"
+ top="48"
+ width="150">
+ Price: L$[PRICE] for [AREA] m²
+ </text>
+ <text
+ type="string"
+ length="1"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left_delta="0"
+ name="label_area"
+ top_delta="0"
+ width="150">
+ Area: [AREA] m²
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="About Land"
+ label_selected="About Land"
+ layout="topleft"
+ left_delta="0"
+ name="button about land"
+ top_pad="4"
+ width="125" />
+ <check_box
+ control_name="ShowParcelOwners"
+ height="19"
+ label="Show owners"
+ layout="topleft"
+ left_delta="0"
+ name="checkbox show owners"
+ tool_tip="Colorize the parcels according to the type of owner: Green = Your land Aqua = Your group's land Red = Owned by others Yellow = For sale Purple = For auction Grey = Public"
+ top_pad="8"
+ width="205" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_modify"
+ top="152"
+ width="240">
+ Modify Parcel
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Subdivide"
+ label_selected="Subdivide"
+ layout="topleft"
+ left="30"
+ name="button subdivide land"
+ top="172"
+ width="125" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Join"
+ label_selected="Join"
+ layout="topleft"
+ left_delta="0"
+ name="button join land"
+ top_pad="4"
+ width="125" />
+ <text
+ type="string"
+ length="1"
+ font="SansSerifBig"
+ follows="left|top"
+ height="19"
+ layout="topleft"
+ left="20"
+ name="label_parcel_trans"
+ top="256"
+ width="240">
+ Land Transactions
+ </text>
+ <button
+ follows="left|top"
+ height="23"
+ label="Buy Land"
+ label_selected="Buy Land"
+ layout="topleft"
+ left="30"
+ name="button buy land"
+ top="276"
+ width="125" />
+ <button
+ follows="left|top"
+ height="23"
+ label="Abandon Land"
+ label_selected="Abandon Land"
+ layout="topleft"
+ left_delta="0"
+ name="button abandon land"
+ top_pad="4"
+ width="125" />
+ </panel>
+<!-- end of tabs -->
+</floater>
|