diff options
Diffstat (limited to 'indra/newview/llpanelobject.cpp')
-rw-r--r-- | indra/newview/llpanelobject.cpp | 4666 |
1 files changed, 2333 insertions, 2333 deletions
diff --git a/indra/newview/llpanelobject.cpp b/indra/newview/llpanelobject.cpp index b06f41b920..1dcb7c414c 100644 --- a/indra/newview/llpanelobject.cpp +++ b/indra/newview/llpanelobject.cpp @@ -1,2333 +1,2333 @@ -/** - * @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 "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 "llcalc.h" -#include "llcheckboxctrl.h" -#include "llcolorswatch.h" -#include "llcombobox.h" -#include "llfocusmgr.h" -#include "llmanipscale.h" -#include "llmenubutton.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 -}; - -const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters - -//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 - mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn"); - 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 - mMenuClipboardSize = getChild<LLMenuButton>("clipboard_size_btn"); - 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 - mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn"); - 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); - - mMenuClipboardParams = getChild<LLMenuButton>("clipboard_obj_params_btn"); - - // 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); - mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER); - 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), - mSelectedType(MI_BOX), - mSculptTextureRevert(LLUUID::null), - mSculptTypeRevert(0), - mHasClipboardPos(false), - mHasClipboardSize(false), - mHasClipboardRot(false), - mSizeChanged(false) -{ - mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2)); - mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2)); -} - - -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; - } - } - } - - LLCalc* calcp = LLCalc::getInstance(); - - 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(); - calcp->clearAllVariables(); - return; - } - - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME )) - && (selected_count == 1); - - bool enable_move; - bool enable_modify; - - LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); - - bool enable_scale = enable_modify; - bool enable_rotate = enable_move; // already accounts for a case of children, which needs permModify() as well - - LLVector3 vec; - if (enable_move) - { - vec = objectp->getPositionEdit(); - mCtrlPosX->set( vec.mV[VX] ); - mCtrlPosY->set( vec.mV[VY] ); - mCtrlPosZ->set( vec.mV[VZ] ); - calcp->setVar(LLCalc::X_POS, vec.mV[VX]); - calcp->setVar(LLCalc::Y_POS, vec.mV[VY]); - calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]); - } - else - { - mCtrlPosX->clear(); - mCtrlPosY->clear(); - mCtrlPosZ->clear(); - calcp->clearVar(LLCalc::X_POS); - calcp->clearVar(LLCalc::Y_POS); - calcp->clearVar(LLCalc::Z_POS); - } - - mMenuClipboardPos->setEnabled(enable_move); - 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] ); - calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]); - calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]); - calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]); - } - else - { - mCtrlScaleX->clear(); - mCtrlScaleY->clear(); - mCtrlScaleZ->clear(); - calcp->setVar(LLCalc::X_SCALE, 0.f); - calcp->setVar(LLCalc::Y_SCALE, 0.f); - calcp->setVar(LLCalc::Z_SCALE, 0.f); - } - - mMenuClipboardSize->setEnabled(enable_scale); - 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(ll_round(mCurEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f); - mCurEulerDegrees.mV[VY] = fmod(ll_round(mCurEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f); - mCurEulerDegrees.mV[VZ] = fmod(ll_round(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] ); - calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]); - calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]); - calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]); - } - else - { - mCtrlRotX->clear(); - mCtrlRotY->clear(); - mCtrlRotZ->clear(); - calcp->clearVar(LLCalc::X_ROT); - calcp->clearVar(LLCalc::Y_ROT); - calcp->clearVar(LLCalc::Z_ROT); - } - - mMenuClipboardRot->setEnabled(enable_rotate); - mLabelRotation->setEnabled( enable_rotate ); - mCtrlRotX->setEnabled( enable_rotate ); - mCtrlRotY->setEnabled( enable_rotate ); - mCtrlRotZ->setEnabled( enable_rotate ); - - LLUUID owner_id; - std::string owner_name; - 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(); - - bool is_flexible = volobjp && volobjp->isFlexible(); - bool is_permanent = root_objectp->flagObjectPermanent(); - bool is_permanent_enforced = root_objectp->isPermanentEnforced(); - bool is_character = root_objectp->flagCharacter(); - llassert(!is_permanent || !is_character); // should never have a permanent object that is also a character - - // Lock checkbox - only modifiable if you own the object. - bool self_owned = (gAgent.getID() == owner_id); - mCheckLock->setEnabled( roots_selected > 0 && self_owned && !is_permanent_enforced); - - // 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); - } - } - - // Physics checkbox - mIsPhysical = root_objectp->flagUsePhysics(); - llassert(!is_permanent || !mIsPhysical); // should never have a permanent object that is also physical - - mCheckPhysics->set( mIsPhysical ); - mCheckPhysics->setEnabled( roots_selected>0 - && (editable || gAgent.isGodlike()) - && !is_flexible && !is_permanent); - - mIsTemporary = root_objectp->flagTemporaryOnRez(); - llassert(!is_permanent || !mIsTemporary); // should never has a permanent object that is also temporary - - mCheckTemporary->set( mIsTemporary ); - mCheckTemporary->setEnabled( roots_selected>0 && editable && !is_permanent); - - mIsPhantom = root_objectp->flagPhantom(); - bool is_volume_detect = root_objectp->flagVolumeDetect(); - llassert(!is_character || !mIsPhantom); // should never have a character that is also a phantom - mCheckPhantom->set( mIsPhantom ); - mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible && !is_permanent_enforced && !is_character && !is_volume_detect); - - //---------------------------------------------------------------------------- - - 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() && !root_objectp->isPermanentEnforced(); - - // 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 - { - LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL; - 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 = 100.f * volume_params.getHollow(); - mSpinHollow->set( hollow ); - calcp->setVar(LLCalc::HOLLOW, 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 ); - calcp->setVar(LLCalc::CUT_BEGIN, cut_begin); - calcp->setVar(LLCalc::CUT_END, cut_end); - calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin); - calcp->setVar(LLCalc::PATH_END, 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 ); - calcp->setVar(LLCalc::TWIST_END, twist); - calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin); - - // Shear - F32 shear_x = volume_params.getShearX(); - F32 shear_y = volume_params.getShearY(); - mSpinShearX->set( shear_x ); - mSpinShearY->set( shear_y ); - calcp->setVar(LLCalc::X_SHEAR, shear_x); - calcp->setVar(LLCalc::Y_SHEAR, shear_y); - - // Taper - F32 taper_x = volume_params.getTaperX(); - F32 taper_y = volume_params.getTaperY(); - mSpinTaperX->set( taper_x ); - mSpinTaperY->set( taper_y ); - calcp->setVar(LLCalc::X_TAPER, taper_x); - calcp->setVar(LLCalc::Y_TAPER, 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); - calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset); - - // Revolutions - F32 revolutions = volume_params.getRevolutions(); - mSpinRevolutions->set( revolutions ); - calcp->setVar(LLCalc::REVOLUTIONS, 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 ); - calcp->setVar(LLCalc::SKEW, 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 ); - calcp->setVar(LLCalc::X_HOLE, scale_x); - calcp->setVar(LLCalc::Y_HOLE, 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 && single_volume) - { - 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); - - // Torus' Hole Size is Box/Cyl/Prism's Taper - calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x); - calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y); - - // Box/Cyl/Prism have no hole size - calcp->setVar(LLCalc::X_HOLE, 0.f); - calcp->setVar(LLCalc::Y_HOLE, 0.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 ); - mMenuClipboardParams->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); - mMenuClipboardParams->setEnabled(!isMesh); - - if (mCtrlSculptType) - { - if (sculpt_stitching == LL_SCULPT_TYPE_NONE) - { - // since 'None' is no longer an option in the combo box - // use 'Plane' as an equivalent sculpt type - mCtrlSculptType->setSelectedByValue(LLSD(LL_SCULPT_TYPE_PLANE), true); - } - else - { - mCtrlSculptType->setSelectedByValue(LLSD(sculpt_stitching), true); - } - 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; - - LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL; - } - else - { - LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL; - } -} - -void LLPanelObject::sendIsTemporary() -{ - bool value = mCheckTemporary->get(); - if( mIsTemporary != value ) - { - LLSelectMgr::getInstance()->selectionUpdateTemporary(value); - mIsTemporary = value; - - LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL; - } - else - { - LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL; - } -} - - -void LLPanelObject::sendIsPhantom() -{ - bool value = mCheckPhantom->get(); - if( mIsPhantom != value ) - { - LLSelectMgr::getInstance()->selectionUpdatePhantom(value); - mIsPhantom = value; - - LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL; - } - else - { - LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL; - } -} - -// 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: - LL_WARNS("FloaterTools") << "Unknown base type " << selected_type - << " in getVolumeParams()" << LL_ENDL; - // 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] = ll_round(new_rot.mV[VX], OBJECT_ROTATION_PRECISION); - new_rot.mV[VY] = ll_round(new_rot.mV[VY], OBJECT_ROTATION_PRECISION); - new_rot.mV[VZ] = ll_round(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(); - } - - // To include avatars into movements and rotation - // If false, all children are selected anyway - move avatar - // If true, not all children are selected - save positions - bool individual_selection = gSavedSettings.getBOOL("EditLinkedParts"); - std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ; - std::vector<LLQuaternion> child_rotations; - if (mObject->isRootEdit() && individual_selection) - { - 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() && individual_selection) - { - 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 || (mSizeChanged && !btn_down)) - { - // scale changed by more than 1/2 millimeter - mSizeChanged = btn_down; - - // 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); -// LL_INFOS() << "scale sent" << LL_ENDL; - } - else - { -// LL_INFOS() << "scale not changed" << LL_ENDL; - } -} - - -void LLPanelObject::sendPosition(bool btn_down) -{ - if (mObject.isNull()) return; - - LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); - LLViewerRegion* regionp = mObject->getRegion(); - - if (!regionp) return; - - if (!mObject->isAttachment()) - { - // 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 ( 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); - } - } - else - { - if (newpos.length() > MAX_ATTACHMENT_DIST) - { - newpos.clampLength(MAX_ATTACHMENT_DIST); - mCtrlPosX->set(newpos.mV[VX]); - mCtrlPosY->set(newpos.mV[VY]); - mCtrlPosZ->set(newpos.mV[VZ]); - } - } - - // 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); - bool is_valid_pos = true; - if (mObject->isAttachment()) - { - LLVector3 delta_pos = mObject->getPositionEdit() - newpos; - LLVector3d attachment_pos = regionp->getPosGlobalFromRegion(mObject->getPositionRegion() + delta_pos); - is_valid_pos = LLWorld::getInstance()->positionRegionValidGlobal(attachment_pos); - } - else - { - is_valid_pos = LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global); - } - - if (is_valid_pos) - { - // 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, 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; - LLUUID sculpt_id = LLUUID::null; - - if (mCtrlSculptTexture) - { - sculpt_id = mCtrlSculptTexture->getImageAssetID(); - } - - U8 sculpt_type = 0; - - if (mCtrlSculptType) - { - sculpt_type |= mCtrlSculptType->getValue().asInteger(); - } - - bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH; - - if (mCtrlSculptMirror) - { - mCtrlSculptMirror->setEnabled(enabled); - } - - if (mCtrlSculptInvert) - { - mCtrlSculptInvert->setEnabled(enabled); - } - - if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get())) - { - sculpt_type |= LL_SCULPT_FLAG_MIRROR; - } - - if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get())) - { - sculpt_type |= LL_SCULPT_FLAG_INVERT; - } - - sculpt_params.setSculptTexture(sculpt_id, 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; - } - - 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); -} - - -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 ); - - // 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("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(); -} - -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; - - if(mSculptTextureRevert == LLUUID::null) - { - mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE); - } - mTextureCtrl->setImageAssetID(mSculptTextureRevert); - - sendSculpt(); -} - -// static -void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata) -{ - LLPanelObject* self = (LLPanelObject*) userdata; - - self->sendSculpt(); -} - -void LLPanelObject::menuDoToSelected(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - // paste - if (command == "psr_paste") - { - onPastePos(); - onPasteSize(); - onPasteRot(); - } - else if (command == "pos_paste") - { - onPastePos(); - } - else if (command == "size_paste") - { - onPasteSize(); - } - else if (command == "rot_paste") - { - onPasteRot(); - } - else if (command == "params_paste") - { - onPasteParams(); - } - // copy - else if (command == "psr_copy") - { - onCopyPos(); - onCopySize(); - onCopyRot(); - } - else if (command == "pos_copy") - { - onCopyPos(); - } - else if (command == "size_copy") - { - onCopySize(); - } - else if (command == "rot_copy") - { - onCopyRot(); - } - else if (command == "params_copy") - { - onCopyParams(); - } -} - -bool LLPanelObject::menuEnableItem(const LLSD& userdata) -{ - std::string command = userdata.asString(); - - // paste options - if (command == "psr_paste") - { - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) - && (selected_count == 1); - - if (!single_volume) - { - return false; - } - - bool enable_move; - bool enable_modify; - - LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); - - return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot; - } - else if (command == "pos_paste") - { - // assumes that menu won't be active if there is no move permission - return mHasClipboardPos; - } - else if (command == "size_paste") - { - return mHasClipboardSize; - } - else if (command == "rot_paste") - { - return mHasClipboardRot; - } - else if (command == "params_paste") - { - return mClipboardParams.isMap() && (mClipboardParams.size() != 0); - } - // copy options - else if (command == "psr_copy") - { - S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount(); - bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME)) - && (selected_count == 1); - - if (!single_volume) - { - return false; - } - - bool enable_move; - bool enable_modify; - - LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify); - - // since we forbid seeing values we also should forbid copying them - return enable_move && enable_modify; - } - return false; -} - -void LLPanelObject::onCopyPos() -{ - mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get()); - - std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]); - LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - - mHasClipboardPos = true; -} - -void LLPanelObject::onCopySize() -{ - mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get()); - - std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]); - LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - - mHasClipboardSize = true; -} - -void LLPanelObject::onCopyRot() -{ - mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get()); - - std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]); - LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec)); - - mHasClipboardRot = true; -} - -void LLPanelObject::onPastePos() -{ - if (!mHasClipboardPos) return; - if (mObject.isNull()) return; - - LLViewerRegion* regionp = mObject->getRegion(); - if (!regionp) return; - - - // Clamp pos on non-attachments, just keep the prims within the region - if (!mObject->isAttachment()) - { - F32 max_width = regionp->getWidth(); // meters - mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, max_width); - mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width); - //height will get properly clamped by sendPosition - } - else - { - mClipboardPos.clampLength(MAX_ATTACHMENT_DIST); - } - - mCtrlPosX->set( mClipboardPos.mV[VX] ); - mCtrlPosY->set( mClipboardPos.mV[VY] ); - mCtrlPosZ->set( mClipboardPos.mV[VZ] ); - - sendPosition(false); -} - -void LLPanelObject::onPasteSize() -{ - if (!mHasClipboardSize) return; - - mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); - mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); - mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE); - - mCtrlScaleX->set(mClipboardSize.mV[VX]); - mCtrlScaleY->set(mClipboardSize.mV[VY]); - mCtrlScaleZ->set(mClipboardSize.mV[VZ]); - - sendScale(false); -} - -void LLPanelObject::onPasteRot() -{ - if (!mHasClipboardRot) return; - - mCtrlRotX->set(mClipboardRot.mV[VX]); - mCtrlRotY->set(mClipboardRot.mV[VY]); - mCtrlRotZ->set(mClipboardRot.mV[VZ]); - - sendRotation(false); -} - -void LLPanelObject::onCopyParams() -{ - LLViewerObject* objectp = mObject; - if (!objectp || objectp->isMesh()) - { - return; - } - - mClipboardParams.clear(); - - // Parametrics - LLVolumeParams params; - getVolumeParams(params); - mClipboardParams["volume_params"] = params.asLLSD(); - - // Sculpted Prim - if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT)) - { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - - LLUUID texture_id = sculpt_params->getSculptTexture(); - if (get_can_copy_texture(texture_id)) - { - LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL; - mClipboardParams["sculpt"]["id"] = texture_id; - } - else - { - mClipboardParams["sculpt"]["id"] = LLUUID(SCULPT_DEFAULT_TEXTURE); - } - - mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType(); - } -} - -void LLPanelObject::onPasteParams() -{ - LLViewerObject* objectp = mObject; - if (!objectp) - { - return; - } - - // Sculpted Prim - if (mClipboardParams.has("sculpt")) - { - LLSculptParams sculpt_params; - LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID(); - U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger(); - sculpt_params.setSculptTexture(sculpt_id, sculpt_type); - objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, true); - } - else - { - LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT); - if (sculpt_params) - { - objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true); - } - } - - // volume params - // make sure updateVolume() won't affect flexible - if (mClipboardParams.has("volume_params")) - { - LLVolumeParams params; - params.fromLLSD(mClipboardParams["volume_params"]); - LLVOVolume *volobjp = (LLVOVolume *)objectp; - if (volobjp->isFlexible()) - { - if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE) - { - params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE); - } - } - else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE) - { - params.getPathParams().setCurveType(LL_PCODE_PATH_LINE); - } - - objectp->updateVolume(params); - } -} +/**
+ * @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 "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 "llcalc.h"
+#include "llcheckboxctrl.h"
+#include "llcolorswatch.h"
+#include "llcombobox.h"
+#include "llfocusmgr.h"
+#include "llmanipscale.h"
+#include "llmenubutton.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
+};
+
+const F32 MAX_ATTACHMENT_DIST = 3.5f; // meters
+
+//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
+ mMenuClipboardPos = getChild<LLMenuButton>("clipboard_pos_btn");
+ 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
+ mMenuClipboardSize = getChild<LLMenuButton>("clipboard_size_btn");
+ 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
+ mMenuClipboardRot = getChild<LLMenuButton>("clipboard_rot_btn");
+ 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);
+
+ mMenuClipboardParams = getChild<LLMenuButton>("clipboard_obj_params_btn");
+
+ // 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(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);
+ mCtrlSculptTexture->setDnDFilterPermMask(PERM_COPY | PERM_TRANSFER);
+ 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),
+ mSelectedType(MI_BOX),
+ mSculptTextureRevert(LLUUID::null),
+ mSculptTypeRevert(0),
+ mHasClipboardPos(false),
+ mHasClipboardSize(false),
+ mHasClipboardRot(false),
+ mSizeChanged(false)
+{
+ mCommitCallbackRegistrar.add("PanelObject.menuDoToSelected", boost::bind(&LLPanelObject::menuDoToSelected, this, _2));
+ mEnableCallbackRegistrar.add("PanelObject.menuEnable", boost::bind(&LLPanelObject::menuEnableItem, this, _2));
+}
+
+
+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;
+ }
+ }
+ }
+
+ LLCalc* calcp = LLCalc::getInstance();
+
+ 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();
+ calcp->clearAllVariables();
+ return;
+ }
+
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ))
+ && (selected_count == 1);
+
+ bool enable_move;
+ bool enable_modify;
+
+ LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
+
+ bool enable_scale = enable_modify;
+ bool enable_rotate = enable_move; // already accounts for a case of children, which needs permModify() as well
+
+ LLVector3 vec;
+ if (enable_move)
+ {
+ vec = objectp->getPositionEdit();
+ mCtrlPosX->set( vec.mV[VX] );
+ mCtrlPosY->set( vec.mV[VY] );
+ mCtrlPosZ->set( vec.mV[VZ] );
+ calcp->setVar(LLCalc::X_POS, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_POS, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]);
+ }
+ else
+ {
+ mCtrlPosX->clear();
+ mCtrlPosY->clear();
+ mCtrlPosZ->clear();
+ calcp->clearVar(LLCalc::X_POS);
+ calcp->clearVar(LLCalc::Y_POS);
+ calcp->clearVar(LLCalc::Z_POS);
+ }
+
+ mMenuClipboardPos->setEnabled(enable_move);
+ 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] );
+ calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]);
+ calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]);
+ calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]);
+ }
+ else
+ {
+ mCtrlScaleX->clear();
+ mCtrlScaleY->clear();
+ mCtrlScaleZ->clear();
+ calcp->setVar(LLCalc::X_SCALE, 0.f);
+ calcp->setVar(LLCalc::Y_SCALE, 0.f);
+ calcp->setVar(LLCalc::Z_SCALE, 0.f);
+ }
+
+ mMenuClipboardSize->setEnabled(enable_scale);
+ 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(ll_round(mCurEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mCurEulerDegrees.mV[VY] = fmod(ll_round(mCurEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
+ mCurEulerDegrees.mV[VZ] = fmod(ll_round(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] );
+ calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]);
+ calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]);
+ calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]);
+ }
+ else
+ {
+ mCtrlRotX->clear();
+ mCtrlRotY->clear();
+ mCtrlRotZ->clear();
+ calcp->clearVar(LLCalc::X_ROT);
+ calcp->clearVar(LLCalc::Y_ROT);
+ calcp->clearVar(LLCalc::Z_ROT);
+ }
+
+ mMenuClipboardRot->setEnabled(enable_rotate);
+ mLabelRotation->setEnabled( enable_rotate );
+ mCtrlRotX->setEnabled( enable_rotate );
+ mCtrlRotY->setEnabled( enable_rotate );
+ mCtrlRotZ->setEnabled( enable_rotate );
+
+ LLUUID owner_id;
+ std::string owner_name;
+ 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();
+
+ bool is_flexible = volobjp && volobjp->isFlexible();
+ bool is_permanent = root_objectp->flagObjectPermanent();
+ bool is_permanent_enforced = root_objectp->isPermanentEnforced();
+ bool is_character = root_objectp->flagCharacter();
+ llassert(!is_permanent || !is_character); // should never have a permanent object that is also a character
+
+ // Lock checkbox - only modifiable if you own the object.
+ bool self_owned = (gAgent.getID() == owner_id);
+ mCheckLock->setEnabled( roots_selected > 0 && self_owned && !is_permanent_enforced);
+
+ // 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);
+ }
+ }
+
+ // Physics checkbox
+ mIsPhysical = root_objectp->flagUsePhysics();
+ llassert(!is_permanent || !mIsPhysical); // should never have a permanent object that is also physical
+
+ mCheckPhysics->set( mIsPhysical );
+ mCheckPhysics->setEnabled( roots_selected>0
+ && (editable || gAgent.isGodlike())
+ && !is_flexible && !is_permanent);
+
+ mIsTemporary = root_objectp->flagTemporaryOnRez();
+ llassert(!is_permanent || !mIsTemporary); // should never has a permanent object that is also temporary
+
+ mCheckTemporary->set( mIsTemporary );
+ mCheckTemporary->setEnabled( roots_selected>0 && editable && !is_permanent);
+
+ mIsPhantom = root_objectp->flagPhantom();
+ bool is_volume_detect = root_objectp->flagVolumeDetect();
+ llassert(!is_character || !mIsPhantom); // should never have a character that is also a phantom
+ mCheckPhantom->set( mIsPhantom );
+ mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible && !is_permanent_enforced && !is_character && !is_volume_detect);
+
+ //----------------------------------------------------------------------------
+
+ 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() && !root_objectp->isPermanentEnforced();
+
+ // 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
+ {
+ LL_INFOS("FloaterTools") << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << LL_ENDL;
+ 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 = 100.f * volume_params.getHollow();
+ mSpinHollow->set( hollow );
+ calcp->setVar(LLCalc::HOLLOW, 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 );
+ calcp->setVar(LLCalc::CUT_BEGIN, cut_begin);
+ calcp->setVar(LLCalc::CUT_END, cut_end);
+ calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin);
+ calcp->setVar(LLCalc::PATH_END, 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 );
+ calcp->setVar(LLCalc::TWIST_END, twist);
+ calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin);
+
+ // Shear
+ F32 shear_x = volume_params.getShearX();
+ F32 shear_y = volume_params.getShearY();
+ mSpinShearX->set( shear_x );
+ mSpinShearY->set( shear_y );
+ calcp->setVar(LLCalc::X_SHEAR, shear_x);
+ calcp->setVar(LLCalc::Y_SHEAR, shear_y);
+
+ // Taper
+ F32 taper_x = volume_params.getTaperX();
+ F32 taper_y = volume_params.getTaperY();
+ mSpinTaperX->set( taper_x );
+ mSpinTaperY->set( taper_y );
+ calcp->setVar(LLCalc::X_TAPER, taper_x);
+ calcp->setVar(LLCalc::Y_TAPER, 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);
+ calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset);
+
+ // Revolutions
+ F32 revolutions = volume_params.getRevolutions();
+ mSpinRevolutions->set( revolutions );
+ calcp->setVar(LLCalc::REVOLUTIONS, 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 );
+ calcp->setVar(LLCalc::SKEW, 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 );
+ calcp->setVar(LLCalc::X_HOLE, scale_x);
+ calcp->setVar(LLCalc::Y_HOLE, 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 && single_volume)
+ {
+ 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);
+
+ // Torus' Hole Size is Box/Cyl/Prism's Taper
+ calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x);
+ calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y);
+
+ // Box/Cyl/Prism have no hole size
+ calcp->setVar(LLCalc::X_HOLE, 0.f);
+ calcp->setVar(LLCalc::Y_HOLE, 0.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 );
+ mMenuClipboardParams->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);
+ mMenuClipboardParams->setEnabled(!isMesh);
+
+ if (mCtrlSculptType)
+ {
+ if (sculpt_stitching == LL_SCULPT_TYPE_NONE)
+ {
+ // since 'None' is no longer an option in the combo box
+ // use 'Plane' as an equivalent sculpt type
+ mCtrlSculptType->setSelectedByValue(LLSD(LL_SCULPT_TYPE_PLANE), true);
+ }
+ else
+ {
+ mCtrlSculptType->setSelectedByValue(LLSD(sculpt_stitching), true);
+ }
+ 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;
+
+ LL_INFOS("FloaterTools") << "update physics sent" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("FloaterTools") << "update physics not changed" << LL_ENDL;
+ }
+}
+
+void LLPanelObject::sendIsTemporary()
+{
+ bool value = mCheckTemporary->get();
+ if( mIsTemporary != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdateTemporary(value);
+ mIsTemporary = value;
+
+ LL_INFOS("FloaterTools") << "update temporary sent" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("FloaterTools") << "update temporary not changed" << LL_ENDL;
+ }
+}
+
+
+void LLPanelObject::sendIsPhantom()
+{
+ bool value = mCheckPhantom->get();
+ if( mIsPhantom != value )
+ {
+ LLSelectMgr::getInstance()->selectionUpdatePhantom(value);
+ mIsPhantom = value;
+
+ LL_INFOS("FloaterTools") << "update phantom sent" << LL_ENDL;
+ }
+ else
+ {
+ LL_INFOS("FloaterTools") << "update phantom not changed" << LL_ENDL;
+ }
+}
+
+// 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:
+ LL_WARNS("FloaterTools") << "Unknown base type " << selected_type
+ << " in getVolumeParams()" << LL_ENDL;
+ // 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] = ll_round(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VY] = ll_round(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
+ new_rot.mV[VZ] = ll_round(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();
+ }
+
+ // To include avatars into movements and rotation
+ // If false, all children are selected anyway - move avatar
+ // If true, not all children are selected - save positions
+ bool individual_selection = gSavedSettings.getBOOL("EditLinkedParts");
+ std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ;
+ std::vector<LLQuaternion> child_rotations;
+ if (mObject->isRootEdit() && individual_selection)
+ {
+ 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() && individual_selection)
+ {
+ 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 || (mSizeChanged && !btn_down))
+ {
+ // scale changed by more than 1/2 millimeter
+ mSizeChanged = btn_down;
+
+ // 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);
+// LL_INFOS() << "scale sent" << LL_ENDL;
+ }
+ else
+ {
+// LL_INFOS() << "scale not changed" << LL_ENDL;
+ }
+}
+
+
+void LLPanelObject::sendPosition(bool btn_down)
+{
+ if (mObject.isNull()) return;
+
+ LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
+ LLViewerRegion* regionp = mObject->getRegion();
+
+ if (!regionp) return;
+
+ if (!mObject->isAttachment())
+ {
+ // 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 ( 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);
+ }
+ }
+ else
+ {
+ if (newpos.length() > MAX_ATTACHMENT_DIST)
+ {
+ newpos.clampLength(MAX_ATTACHMENT_DIST);
+ mCtrlPosX->set(newpos.mV[VX]);
+ mCtrlPosY->set(newpos.mV[VY]);
+ mCtrlPosZ->set(newpos.mV[VZ]);
+ }
+ }
+
+ // 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);
+ bool is_valid_pos = true;
+ if (mObject->isAttachment())
+ {
+ LLVector3 delta_pos = mObject->getPositionEdit() - newpos;
+ LLVector3d attachment_pos = regionp->getPosGlobalFromRegion(mObject->getPositionRegion() + delta_pos);
+ is_valid_pos = LLWorld::getInstance()->positionRegionValidGlobal(attachment_pos);
+ }
+ else
+ {
+ is_valid_pos = LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global);
+ }
+
+ if (is_valid_pos)
+ {
+ // 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, 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;
+ LLUUID sculpt_id = LLUUID::null;
+
+ if (mCtrlSculptTexture)
+ {
+ sculpt_id = mCtrlSculptTexture->getImageAssetID();
+ }
+
+ U8 sculpt_type = 0;
+
+ if (mCtrlSculptType)
+ {
+ sculpt_type |= mCtrlSculptType->getValue().asInteger();
+ }
+
+ bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
+
+ if (mCtrlSculptMirror)
+ {
+ mCtrlSculptMirror->setEnabled(enabled);
+ }
+
+ if (mCtrlSculptInvert)
+ {
+ mCtrlSculptInvert->setEnabled(enabled);
+ }
+
+ if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get()))
+ {
+ sculpt_type |= LL_SCULPT_FLAG_MIRROR;
+ }
+
+ if ((mCtrlSculptInvert) && (mCtrlSculptInvert->get()))
+ {
+ sculpt_type |= LL_SCULPT_FLAG_INVERT;
+ }
+
+ sculpt_params.setSculptTexture(sculpt_id, 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;
+ }
+
+ 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);
+}
+
+
+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 );
+
+ // 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("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();
+}
+
+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;
+
+ if(mSculptTextureRevert == LLUUID::null)
+ {
+ mSculptTextureRevert = SCULPT_DEFAULT_TEXTURE;
+ }
+ mTextureCtrl->setImageAssetID(mSculptTextureRevert);
+
+ sendSculpt();
+}
+
+// static
+void LLPanelObject::onCommitSculptType(LLUICtrl *ctrl, void* userdata)
+{
+ LLPanelObject* self = (LLPanelObject*) userdata;
+
+ self->sendSculpt();
+}
+
+void LLPanelObject::menuDoToSelected(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+
+ // paste
+ if (command == "psr_paste")
+ {
+ onPastePos();
+ onPasteSize();
+ onPasteRot();
+ }
+ else if (command == "pos_paste")
+ {
+ onPastePos();
+ }
+ else if (command == "size_paste")
+ {
+ onPasteSize();
+ }
+ else if (command == "rot_paste")
+ {
+ onPasteRot();
+ }
+ else if (command == "params_paste")
+ {
+ onPasteParams();
+ }
+ // copy
+ else if (command == "psr_copy")
+ {
+ onCopyPos();
+ onCopySize();
+ onCopyRot();
+ }
+ else if (command == "pos_copy")
+ {
+ onCopyPos();
+ }
+ else if (command == "size_copy")
+ {
+ onCopySize();
+ }
+ else if (command == "rot_copy")
+ {
+ onCopyRot();
+ }
+ else if (command == "params_copy")
+ {
+ onCopyParams();
+ }
+}
+
+bool LLPanelObject::menuEnableItem(const LLSD& userdata)
+{
+ std::string command = userdata.asString();
+
+ // paste options
+ if (command == "psr_paste")
+ {
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME))
+ && (selected_count == 1);
+
+ if (!single_volume)
+ {
+ return false;
+ }
+
+ bool enable_move;
+ bool enable_modify;
+
+ LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
+
+ return enable_move && enable_modify && mHasClipboardPos && mHasClipboardSize && mHasClipboardRot;
+ }
+ else if (command == "pos_paste")
+ {
+ // assumes that menu won't be active if there is no move permission
+ return mHasClipboardPos;
+ }
+ else if (command == "size_paste")
+ {
+ return mHasClipboardSize;
+ }
+ else if (command == "rot_paste")
+ {
+ return mHasClipboardRot;
+ }
+ else if (command == "params_paste")
+ {
+ return mClipboardParams.isMap() && (mClipboardParams.size() != 0);
+ }
+ // copy options
+ else if (command == "psr_copy")
+ {
+ S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
+ bool single_volume = (LLSelectMgr::getInstance()->selectionAllPCode(LL_PCODE_VOLUME))
+ && (selected_count == 1);
+
+ if (!single_volume)
+ {
+ return false;
+ }
+
+ bool enable_move;
+ bool enable_modify;
+
+ LLSelectMgr::getInstance()->selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
+
+ // since we forbid seeing values we also should forbid copying them
+ return enable_move && enable_modify;
+ }
+ return false;
+}
+
+void LLPanelObject::onCopyPos()
+{
+ mClipboardPos = LLVector3(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
+
+ std::string stringVec = llformat("<%g, %g, %g>", mClipboardPos.mV[VX], mClipboardPos.mV[VY], mClipboardPos.mV[VZ]);
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
+
+ mHasClipboardPos = true;
+}
+
+void LLPanelObject::onCopySize()
+{
+ mClipboardSize = LLVector3(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
+
+ std::string stringVec = llformat("<%g, %g, %g>", mClipboardSize.mV[VX], mClipboardSize.mV[VY], mClipboardSize.mV[VZ]);
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
+
+ mHasClipboardSize = true;
+}
+
+void LLPanelObject::onCopyRot()
+{
+ mClipboardRot = LLVector3(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
+
+ std::string stringVec = llformat("<%g, %g, %g>", mClipboardRot.mV[VX], mClipboardRot.mV[VY], mClipboardRot.mV[VZ]);
+ LLView::getWindow()->copyTextToClipboard(utf8str_to_wstring(stringVec));
+
+ mHasClipboardRot = true;
+}
+
+void LLPanelObject::onPastePos()
+{
+ if (!mHasClipboardPos) return;
+ if (mObject.isNull()) return;
+
+ LLViewerRegion* regionp = mObject->getRegion();
+ if (!regionp) return;
+
+
+ // Clamp pos on non-attachments, just keep the prims within the region
+ if (!mObject->isAttachment())
+ {
+ F32 max_width = regionp->getWidth(); // meters
+ mClipboardPos.mV[VX] = llclamp(mClipboardPos.mV[VX], 0.f, max_width);
+ mClipboardPos.mV[VY] = llclamp(mClipboardPos.mV[VY], 0.f, max_width);
+ //height will get properly clamped by sendPosition
+ }
+ else
+ {
+ mClipboardPos.clampLength(MAX_ATTACHMENT_DIST);
+ }
+
+ mCtrlPosX->set( mClipboardPos.mV[VX] );
+ mCtrlPosY->set( mClipboardPos.mV[VY] );
+ mCtrlPosZ->set( mClipboardPos.mV[VZ] );
+
+ sendPosition(false);
+}
+
+void LLPanelObject::onPasteSize()
+{
+ if (!mHasClipboardSize) return;
+
+ mClipboardSize.mV[VX] = llclamp(mClipboardSize.mV[VX], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
+ mClipboardSize.mV[VY] = llclamp(mClipboardSize.mV[VY], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
+ mClipboardSize.mV[VZ] = llclamp(mClipboardSize.mV[VZ], MIN_PRIM_SCALE, DEFAULT_MAX_PRIM_SCALE);
+
+ mCtrlScaleX->set(mClipboardSize.mV[VX]);
+ mCtrlScaleY->set(mClipboardSize.mV[VY]);
+ mCtrlScaleZ->set(mClipboardSize.mV[VZ]);
+
+ sendScale(false);
+}
+
+void LLPanelObject::onPasteRot()
+{
+ if (!mHasClipboardRot) return;
+
+ mCtrlRotX->set(mClipboardRot.mV[VX]);
+ mCtrlRotY->set(mClipboardRot.mV[VY]);
+ mCtrlRotZ->set(mClipboardRot.mV[VZ]);
+
+ sendRotation(false);
+}
+
+void LLPanelObject::onCopyParams()
+{
+ LLViewerObject* objectp = mObject;
+ if (!objectp || objectp->isMesh())
+ {
+ return;
+ }
+
+ mClipboardParams.clear();
+
+ // Parametrics
+ LLVolumeParams params;
+ getVolumeParams(params);
+ mClipboardParams["volume_params"] = params.asLLSD();
+
+ // Sculpted Prim
+ if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+
+ LLUUID texture_id = sculpt_params->getSculptTexture();
+ if (get_can_copy_texture(texture_id))
+ {
+ LL_DEBUGS("FloaterTools") << "Recording texture" << LL_ENDL;
+ mClipboardParams["sculpt"]["id"] = texture_id;
+ }
+ else
+ {
+ mClipboardParams["sculpt"]["id"] = SCULPT_DEFAULT_TEXTURE;
+ }
+
+ mClipboardParams["sculpt"]["type"] = sculpt_params->getSculptType();
+ }
+}
+
+void LLPanelObject::onPasteParams()
+{
+ LLViewerObject* objectp = mObject;
+ if (!objectp)
+ {
+ return;
+ }
+
+ // Sculpted Prim
+ if (mClipboardParams.has("sculpt"))
+ {
+ LLSculptParams sculpt_params;
+ LLUUID sculpt_id = mClipboardParams["sculpt"]["id"].asUUID();
+ U8 sculpt_type = (U8)mClipboardParams["sculpt"]["type"].asInteger();
+ sculpt_params.setSculptTexture(sculpt_id, sculpt_type);
+ objectp->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params, true);
+ }
+ else
+ {
+ LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
+ if (sculpt_params)
+ {
+ objectp->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, false, true);
+ }
+ }
+
+ // volume params
+ // make sure updateVolume() won't affect flexible
+ if (mClipboardParams.has("volume_params"))
+ {
+ LLVolumeParams params;
+ params.fromLLSD(mClipboardParams["volume_params"]);
+ LLVOVolume *volobjp = (LLVOVolume *)objectp;
+ if (volobjp->isFlexible())
+ {
+ if (params.getPathParams().getCurveType() == LL_PCODE_PATH_LINE)
+ {
+ params.getPathParams().setCurveType(LL_PCODE_PATH_FLEXIBLE);
+ }
+ }
+ else if (params.getPathParams().getCurveType() == LL_PCODE_PATH_FLEXIBLE)
+ {
+ params.getPathParams().setCurveType(LL_PCODE_PATH_LINE);
+ }
+
+ objectp->updateVolume(params);
+ }
+}
|