PageRenderTime 1427ms CodeModel.GetById 201ms app.highlight 1028ms RepoModel.GetById 180ms app.codeStats 1ms

/indra/newview/llpanelobject.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 2039 lines | 1549 code | 302 blank | 188 comment | 293 complexity | cd2ae1e4d4efb992cabd5fecf6e2c075 MD5 | raw file

Large files files are truncated, but you can click here to view the full file

   1/** 
   2 * @file llpanelobject.cpp
   3 * @brief Object editing (position, scale, etc.) in the tools floater
   4 *
   5 * $LicenseInfo:firstyear=2001&license=viewerlgpl$
   6 * Second Life Viewer Source Code
   7 * Copyright (C) 2010, Linden Research, Inc.
   8 * 
   9 * This library is free software; you can redistribute it and/or
  10 * modify it under the terms of the GNU Lesser General Public
  11 * License as published by the Free Software Foundation;
  12 * version 2.1 of the License only.
  13 * 
  14 * This library is distributed in the hope that it will be useful,
  15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  17 * Lesser General Public License for more details.
  18 * 
  19 * You should have received a copy of the GNU Lesser General Public
  20 * License along with this library; if not, write to the Free Software
  21 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  22 * 
  23 * Linden Research, Inc., 945 Battery Street, San Francisco, CA  94111  USA
  24 * $/LicenseInfo$
  25 */
  26
  27#include "llviewerprecompiledheaders.h"
  28
  29// file include
  30#include "llpanelobject.h"
  31
  32// linden library includes
  33#include "lleconomy.h"
  34#include "llerror.h"
  35#include "llfontgl.h"
  36#include "llpermissionsflags.h"
  37#include "llstring.h"
  38#include "llvolume.h"
  39#include "m3math.h"
  40
  41// project includes
  42#include "llagent.h"
  43#include "llbutton.h"
  44#include "llcalc.h"
  45#include "llcheckboxctrl.h"
  46#include "llcolorswatch.h"
  47#include "llcombobox.h"
  48#include "llfocusmgr.h"
  49#include "llmanipscale.h"
  50#include "llpreviewscript.h"
  51#include "llresmgr.h"
  52#include "llselectmgr.h"
  53#include "llspinctrl.h"
  54#include "lltexturectrl.h"
  55#include "lltextbox.h"
  56#include "lltool.h"
  57#include "lltoolcomp.h"
  58#include "lltoolmgr.h"
  59#include "llui.h"
  60#include "llviewerobject.h"
  61#include "llviewerregion.h"
  62#include "llviewerwindow.h"
  63#include "llvovolume.h"
  64#include "llworld.h"
  65#include "pipeline.h"
  66#include "llviewercontrol.h"
  67#include "lluictrlfactory.h"
  68//#include "llfirstuse.h"
  69
  70#include "lldrawpool.h"
  71
  72//
  73// Constants
  74//
  75enum {
  76	MI_BOX,
  77	MI_CYLINDER,
  78	MI_PRISM,
  79	MI_SPHERE,
  80	MI_TORUS,
  81	MI_TUBE,
  82	MI_RING,
  83	MI_SCULPT,
  84	MI_NONE,
  85	MI_VOLUME_COUNT
  86};
  87
  88enum {
  89	MI_HOLE_SAME,
  90	MI_HOLE_CIRCLE,
  91	MI_HOLE_SQUARE,
  92	MI_HOLE_TRIANGLE,
  93	MI_HOLE_COUNT
  94};
  95
  96//static const std::string LEGACY_FULLBRIGHT_DESC =LLTrans::getString("Fullbright");
  97
  98BOOL	LLPanelObject::postBuild()
  99{
 100	setMouseOpaque(FALSE);
 101	
 102	//--------------------------------------------------------
 103	// Top
 104	//--------------------------------------------------------
 105	
 106	// Lock checkbox
 107	mCheckLock = getChild<LLCheckBoxCtrl>("checkbox locked");
 108	childSetCommitCallback("checkbox locked",onCommitLock,this);
 109
 110	// Physical checkbox
 111	mCheckPhysics = getChild<LLCheckBoxCtrl>("Physical Checkbox Ctrl");
 112	childSetCommitCallback("Physical Checkbox Ctrl",onCommitPhysics,this);
 113
 114	// Temporary checkbox
 115	mCheckTemporary = getChild<LLCheckBoxCtrl>("Temporary Checkbox Ctrl");
 116	childSetCommitCallback("Temporary Checkbox Ctrl",onCommitTemporary,this);
 117
 118	// Phantom checkbox
 119	mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl");
 120	childSetCommitCallback("Phantom Checkbox Ctrl",onCommitPhantom,this);
 121       
 122
 123	// Position
 124	mLabelPosition = getChild<LLTextBox>("label position");
 125	mCtrlPosX = getChild<LLSpinCtrl>("Pos X");
 126	childSetCommitCallback("Pos X",onCommitPosition,this);
 127	mCtrlPosY = getChild<LLSpinCtrl>("Pos Y");
 128	childSetCommitCallback("Pos Y",onCommitPosition,this);
 129	mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z");
 130	childSetCommitCallback("Pos Z",onCommitPosition,this);
 131
 132	// Scale
 133	mLabelSize = getChild<LLTextBox>("label size");
 134	mCtrlScaleX = getChild<LLSpinCtrl>("Scale X");
 135	childSetCommitCallback("Scale X",onCommitScale,this);
 136
 137	// Scale Y
 138	mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y");
 139	childSetCommitCallback("Scale Y",onCommitScale,this);
 140
 141	// Scale Z
 142	mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z");
 143	childSetCommitCallback("Scale Z",onCommitScale,this);
 144
 145	// Rotation
 146	mLabelRotation = getChild<LLTextBox>("label rotation");
 147	mCtrlRotX = getChild<LLSpinCtrl>("Rot X");
 148	childSetCommitCallback("Rot X",onCommitRotation,this);
 149	mCtrlRotY = getChild<LLSpinCtrl>("Rot Y");
 150	childSetCommitCallback("Rot Y",onCommitRotation,this);
 151	mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z");
 152	childSetCommitCallback("Rot Z",onCommitRotation,this);
 153
 154	//--------------------------------------------------------
 155		
 156	// Base Type
 157	mComboBaseType = getChild<LLComboBox>("comboBaseType");
 158	childSetCommitCallback("comboBaseType",onCommitParametric,this);
 159
 160	// Cut
 161	mLabelCut = getChild<LLTextBox>("text cut");
 162	mSpinCutBegin = getChild<LLSpinCtrl>("cut begin");
 163	childSetCommitCallback("cut begin",onCommitParametric,this);
 164	mSpinCutBegin->setValidateBeforeCommit( precommitValidate );
 165	mSpinCutEnd = getChild<LLSpinCtrl>("cut end");
 166	childSetCommitCallback("cut end",onCommitParametric,this);
 167	mSpinCutEnd->setValidateBeforeCommit( &precommitValidate );
 168
 169	// Hollow / Skew
 170	mLabelHollow = getChild<LLTextBox>("text hollow");
 171	mLabelSkew = getChild<LLTextBox>("text skew");
 172	mSpinHollow = getChild<LLSpinCtrl>("Scale 1");
 173	childSetCommitCallback("Scale 1",onCommitParametric,this);
 174	mSpinHollow->setValidateBeforeCommit( &precommitValidate );
 175	mSpinSkew = getChild<LLSpinCtrl>("Skew");
 176	childSetCommitCallback("Skew",onCommitParametric,this);
 177	mSpinSkew->setValidateBeforeCommit( &precommitValidate );
 178	mLabelHoleType = getChild<LLTextBox>("Hollow Shape");
 179
 180	// Hole Type
 181	mComboHoleType = getChild<LLComboBox>("hole");
 182	childSetCommitCallback("hole",onCommitParametric,this);
 183
 184	// Twist
 185	mLabelTwist = getChild<LLTextBox>("text twist");
 186	mSpinTwistBegin = getChild<LLSpinCtrl>("Twist Begin");
 187	childSetCommitCallback("Twist Begin",onCommitParametric,this);
 188	mSpinTwistBegin->setValidateBeforeCommit( precommitValidate );
 189	mSpinTwist = getChild<LLSpinCtrl>("Twist End");
 190	childSetCommitCallback("Twist End",onCommitParametric,this);
 191	mSpinTwist->setValidateBeforeCommit( &precommitValidate );
 192
 193	// Scale
 194	mSpinScaleX = getChild<LLSpinCtrl>("Taper Scale X");
 195	childSetCommitCallback("Taper Scale X",onCommitParametric,this);
 196	mSpinScaleX->setValidateBeforeCommit( &precommitValidate );
 197	mSpinScaleY = getChild<LLSpinCtrl>("Taper Scale Y");
 198	childSetCommitCallback("Taper Scale Y",onCommitParametric,this);
 199	mSpinScaleY->setValidateBeforeCommit( &precommitValidate );
 200
 201	// Shear
 202	mLabelShear = getChild<LLTextBox>("text topshear");
 203	mSpinShearX = getChild<LLSpinCtrl>("Shear X");
 204	childSetCommitCallback("Shear X",onCommitParametric,this);
 205	mSpinShearX->setValidateBeforeCommit( &precommitValidate );
 206	mSpinShearY = getChild<LLSpinCtrl>("Shear Y");
 207	childSetCommitCallback("Shear Y",onCommitParametric,this);
 208	mSpinShearY->setValidateBeforeCommit( &precommitValidate );
 209
 210	// Path / Profile
 211	mCtrlPathBegin = getChild<LLSpinCtrl>("Path Limit Begin");
 212	childSetCommitCallback("Path Limit Begin",onCommitParametric,this);
 213	mCtrlPathBegin->setValidateBeforeCommit( &precommitValidate );
 214	mCtrlPathEnd = getChild<LLSpinCtrl>("Path Limit End");
 215	childSetCommitCallback("Path Limit End",onCommitParametric,this);
 216	mCtrlPathEnd->setValidateBeforeCommit( &precommitValidate );
 217
 218	// Taper
 219	mLabelTaper = getChild<LLTextBox>("text taper2");
 220	mSpinTaperX = getChild<LLSpinCtrl>("Taper X");
 221	childSetCommitCallback("Taper X",onCommitParametric,this);
 222	mSpinTaperX->setValidateBeforeCommit( precommitValidate );
 223	mSpinTaperY = getChild<LLSpinCtrl>("Taper Y");
 224	childSetCommitCallback("Taper Y",onCommitParametric,this);
 225	mSpinTaperY->setValidateBeforeCommit( precommitValidate );
 226	
 227	// Radius Offset / Revolutions
 228	mLabelRadiusOffset = getChild<LLTextBox>("text radius delta");
 229	mLabelRevolutions = getChild<LLTextBox>("text revolutions");
 230	mSpinRadiusOffset = getChild<LLSpinCtrl>("Radius Offset");
 231	childSetCommitCallback("Radius Offset",onCommitParametric,this);
 232	mSpinRadiusOffset->setValidateBeforeCommit( &precommitValidate );
 233	mSpinRevolutions = getChild<LLSpinCtrl>("Revolutions");
 234	childSetCommitCallback("Revolutions",onCommitParametric,this);
 235	mSpinRevolutions->setValidateBeforeCommit( &precommitValidate );
 236
 237	// Sculpt
 238	mCtrlSculptTexture = getChild<LLTextureCtrl>("sculpt texture control");
 239	if (mCtrlSculptTexture)
 240	{
 241		mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE));
 242		mCtrlSculptTexture->setCommitCallback( boost::bind(&LLPanelObject::onCommitSculpt, this, _2 ));
 243		mCtrlSculptTexture->setOnCancelCallback( boost::bind(&LLPanelObject::onCancelSculpt, this, _2 ));
 244		mCtrlSculptTexture->setOnSelectCallback( boost::bind(&LLPanelObject::onSelectSculpt, this, _2 ));
 245		mCtrlSculptTexture->setDropCallback( boost::bind(&LLPanelObject::onDropSculpt, this, _2 ));
 246		// Don't allow (no copy) or (no transfer) textures to be selected during immediate mode
 247		mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
 248		// Allow any texture to be used during non-immediate mode.
 249		mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE);
 250		LLAggregatePermissions texture_perms;
 251		if (LLSelectMgr::getInstance()->selectGetAggregateTexturePermissions(texture_perms))
 252		{
 253			BOOL can_copy =
 254				texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY ||
 255				texture_perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL;
 256			BOOL can_transfer =
 257				texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY ||
 258				texture_perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL;
 259			mCtrlSculptTexture->setCanApplyImmediately(can_copy && can_transfer);
 260		}
 261		else
 262		{
 263			mCtrlSculptTexture->setCanApplyImmediately(FALSE);
 264		}
 265	}
 266
 267	mLabelSculptType = getChild<LLTextBox>("label sculpt type");
 268	mCtrlSculptType = getChild<LLComboBox>("sculpt type control");
 269	childSetCommitCallback("sculpt type control", onCommitSculptType, this);
 270	mCtrlSculptMirror = getChild<LLCheckBoxCtrl>("sculpt mirror control");
 271	childSetCommitCallback("sculpt mirror control", onCommitSculptType, this);
 272	mCtrlSculptInvert = getChild<LLCheckBoxCtrl>("sculpt invert control");
 273	childSetCommitCallback("sculpt invert control", onCommitSculptType, this);
 274	
 275	// Start with everyone disabled
 276	clearCtrls();
 277
 278	return TRUE;
 279}
 280
 281LLPanelObject::LLPanelObject()
 282:	LLPanel(),
 283	mIsPhysical(FALSE),
 284	mIsTemporary(FALSE),
 285	mIsPhantom(FALSE),
 286	mCastShadows(TRUE),
 287	mSelectedType(MI_BOX),
 288	mSculptTextureRevert(LLUUID::null),
 289	mSculptTypeRevert(0)
 290{
 291}
 292
 293
 294LLPanelObject::~LLPanelObject()
 295{
 296	// Children all cleaned up by default view destructor.
 297}
 298
 299void LLPanelObject::getState( )
 300{
 301	LLViewerObject* objectp = LLSelectMgr::getInstance()->getSelection()->getFirstRootObject();
 302	LLViewerObject* root_objectp = objectp;
 303	if(!objectp)
 304	{
 305		objectp = LLSelectMgr::getInstance()->getSelection()->getFirstObject();
 306		// *FIX: shouldn't we just keep the child?
 307		if (objectp)
 308		{
 309			LLViewerObject* parentp = objectp->getRootEdit();
 310
 311			if (parentp)
 312			{
 313				root_objectp = parentp;
 314			}
 315			else
 316			{
 317				root_objectp = objectp;
 318			}
 319		}
 320	}
 321
 322	LLCalc* calcp = LLCalc::getInstance();
 323
 324	LLVOVolume *volobjp = NULL;
 325	if ( objectp && (objectp->getPCode() == LL_PCODE_VOLUME))
 326	{
 327		volobjp = (LLVOVolume *)objectp;
 328	}
 329
 330	if( !objectp )
 331	{
 332		//forfeit focus
 333		if (gFocusMgr.childHasKeyboardFocus(this))
 334		{
 335			gFocusMgr.setKeyboardFocus(NULL);
 336		}
 337
 338		// Disable all text input fields
 339		clearCtrls();
 340		calcp->clearAllVariables();
 341		return;
 342	}
 343
 344	// can move or rotate only linked group with move permissions, or sub-object with move and modify perms
 345	BOOL enable_move	= objectp->permMove() && !objectp->isAttachment() && (objectp->permModify() || !gSavedSettings.getBOOL("EditLinkedParts"));
 346	BOOL enable_scale	= objectp->permMove() && objectp->permModify();
 347	BOOL enable_rotate	= objectp->permMove() && ( (objectp->permModify() && !objectp->isAttachment()) || !gSavedSettings.getBOOL("EditLinkedParts"));
 348
 349	S32 selected_count = LLSelectMgr::getInstance()->getSelection()->getObjectCount();
 350	BOOL single_volume = (LLSelectMgr::getInstance()->selectionAllPCode( LL_PCODE_VOLUME ))
 351						 && (selected_count == 1);
 352
 353	if (LLSelectMgr::getInstance()->getSelection()->getRootObjectCount() > 1)
 354	{
 355		enable_move = FALSE;
 356		enable_scale = FALSE;
 357		enable_rotate = FALSE;
 358	}
 359
 360	LLVector3 vec;
 361	if (enable_move)
 362	{
 363		vec = objectp->getPositionEdit();
 364		mCtrlPosX->set( vec.mV[VX] );
 365		mCtrlPosY->set( vec.mV[VY] );
 366		mCtrlPosZ->set( vec.mV[VZ] );
 367		calcp->setVar(LLCalc::X_POS, vec.mV[VX]);
 368		calcp->setVar(LLCalc::Y_POS, vec.mV[VY]);
 369		calcp->setVar(LLCalc::Z_POS, vec.mV[VZ]);
 370	}
 371	else
 372	{
 373		mCtrlPosX->clear();
 374		mCtrlPosY->clear();
 375		mCtrlPosZ->clear();
 376		calcp->clearVar(LLCalc::X_POS);
 377		calcp->clearVar(LLCalc::Y_POS);
 378		calcp->clearVar(LLCalc::Z_POS);
 379	}
 380
 381
 382	mLabelPosition->setEnabled( enable_move );
 383	mCtrlPosX->setEnabled(enable_move);
 384	mCtrlPosY->setEnabled(enable_move);
 385	mCtrlPosZ->setEnabled(enable_move);
 386
 387	if (enable_scale)
 388	{
 389		vec = objectp->getScale();
 390		mCtrlScaleX->set( vec.mV[VX] );
 391		mCtrlScaleY->set( vec.mV[VY] );
 392		mCtrlScaleZ->set( vec.mV[VZ] );
 393		calcp->setVar(LLCalc::X_SCALE, vec.mV[VX]);
 394		calcp->setVar(LLCalc::Y_SCALE, vec.mV[VY]);
 395		calcp->setVar(LLCalc::Z_SCALE, vec.mV[VZ]);
 396	}
 397	else
 398	{
 399		mCtrlScaleX->clear();
 400		mCtrlScaleY->clear();
 401		mCtrlScaleZ->clear();
 402		calcp->setVar(LLCalc::X_SCALE, 0.f);
 403		calcp->setVar(LLCalc::Y_SCALE, 0.f);
 404		calcp->setVar(LLCalc::Z_SCALE, 0.f);
 405	}
 406
 407	mLabelSize->setEnabled( enable_scale );
 408	mCtrlScaleX->setEnabled( enable_scale );
 409	mCtrlScaleY->setEnabled( enable_scale );
 410	mCtrlScaleZ->setEnabled( enable_scale );
 411
 412	LLQuaternion object_rot = objectp->getRotationEdit();
 413	object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]), &(mCurEulerDegrees.mV[VY]), &(mCurEulerDegrees.mV[VZ]));
 414	mCurEulerDegrees *= RAD_TO_DEG;
 415	mCurEulerDegrees.mV[VX] = fmod(llround(mCurEulerDegrees.mV[VX], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
 416	mCurEulerDegrees.mV[VY] = fmod(llround(mCurEulerDegrees.mV[VY], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
 417	mCurEulerDegrees.mV[VZ] = fmod(llround(mCurEulerDegrees.mV[VZ], OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
 418
 419	if (enable_rotate)
 420	{
 421		mCtrlRotX->set( mCurEulerDegrees.mV[VX] );
 422		mCtrlRotY->set( mCurEulerDegrees.mV[VY] );
 423		mCtrlRotZ->set( mCurEulerDegrees.mV[VZ] );
 424		calcp->setVar(LLCalc::X_ROT, mCurEulerDegrees.mV[VX]);
 425		calcp->setVar(LLCalc::Y_ROT, mCurEulerDegrees.mV[VY]);
 426		calcp->setVar(LLCalc::Z_ROT, mCurEulerDegrees.mV[VZ]);
 427	}
 428	else
 429	{
 430		mCtrlRotX->clear();
 431		mCtrlRotY->clear();
 432		mCtrlRotZ->clear();
 433		calcp->clearVar(LLCalc::X_ROT);
 434		calcp->clearVar(LLCalc::Y_ROT);
 435		calcp->clearVar(LLCalc::Z_ROT);
 436	}
 437
 438	mLabelRotation->setEnabled( enable_rotate );
 439	mCtrlRotX->setEnabled( enable_rotate );
 440	mCtrlRotY->setEnabled( enable_rotate );
 441	mCtrlRotZ->setEnabled( enable_rotate );
 442
 443	BOOL owners_identical;
 444	LLUUID owner_id;
 445	std::string owner_name;
 446	owners_identical = LLSelectMgr::getInstance()->selectGetOwner(owner_id, owner_name);
 447
 448	// BUG? Check for all objects being editable?
 449	S32 roots_selected = LLSelectMgr::getInstance()->getSelection()->getRootObjectCount();
 450	BOOL editable = root_objectp->permModify();
 451
 452	// Select Single Message
 453	getChildView("select_single")->setVisible( FALSE);
 454	getChildView("edit_object")->setVisible( FALSE);
 455	if (!editable || single_volume || selected_count <= 1)
 456	{
 457		getChildView("edit_object")->setVisible( TRUE);
 458		getChildView("edit_object")->setEnabled(TRUE);
 459	}
 460	else
 461	{
 462		getChildView("select_single")->setVisible( TRUE);
 463		getChildView("select_single")->setEnabled(TRUE);
 464	}
 465	// Lock checkbox - only modifiable if you own the object.
 466	BOOL self_owned = (gAgent.getID() == owner_id);
 467	mCheckLock->setEnabled( roots_selected > 0 && self_owned );
 468
 469	// More lock and debit checkbox - get the values
 470	BOOL valid;
 471	U32 owner_mask_on;
 472	U32 owner_mask_off;
 473	valid = LLSelectMgr::getInstance()->selectGetPerm(PERM_OWNER, &owner_mask_on, &owner_mask_off);
 474
 475	if(valid)
 476	{
 477		if(owner_mask_on & PERM_MOVE)
 478		{
 479			// owner can move, so not locked
 480			mCheckLock->set(FALSE);
 481			mCheckLock->setTentative(FALSE);
 482		}
 483		else if(owner_mask_off & PERM_MOVE)
 484		{
 485			// owner can't move, so locked
 486			mCheckLock->set(TRUE);
 487			mCheckLock->setTentative(FALSE);
 488		}
 489		else
 490		{
 491			// some locked, some not locked
 492			mCheckLock->set(FALSE);
 493			mCheckLock->setTentative(TRUE);
 494		}
 495	}
 496
 497	BOOL is_flexible = volobjp && volobjp->isFlexible();
 498
 499	// Physics checkbox
 500	mIsPhysical = root_objectp->usePhysics();
 501	mCheckPhysics->set( mIsPhysical );
 502	mCheckPhysics->setEnabled( roots_selected>0 
 503								&& (editable || gAgent.isGodlike()) 
 504								&& !is_flexible);
 505
 506	mIsTemporary = root_objectp->flagTemporaryOnRez();
 507	mCheckTemporary->set( mIsTemporary );
 508	mCheckTemporary->setEnabled( roots_selected>0 && editable );
 509
 510	mIsPhantom = root_objectp->flagPhantom();
 511	mCheckPhantom->set( mIsPhantom );
 512	mCheckPhantom->setEnabled( roots_selected>0 && editable && !is_flexible );
 513
 514       
 515#if 0 // 1.9.2
 516	mCastShadows = root_objectp->flagCastShadows();
 517	mCheckCastShadows->set( mCastShadows );
 518	mCheckCastShadows->setEnabled( roots_selected==1 && editable );
 519#endif
 520	
 521	//----------------------------------------------------------------------------
 522
 523	S32 selected_item	= MI_BOX;
 524	S32	selected_hole	= MI_HOLE_SAME;
 525	BOOL enabled = FALSE;
 526	BOOL hole_enabled = FALSE;
 527	F32 scale_x=1.f, scale_y=1.f;
 528	BOOL isMesh = FALSE;
 529	
 530	if( !objectp || !objectp->getVolume() || !editable || !single_volume)
 531	{
 532		// Clear out all geometry fields.
 533		mComboBaseType->clear();
 534		mSpinHollow->clear();
 535		mSpinCutBegin->clear();
 536		mSpinCutEnd->clear();
 537		mCtrlPathBegin->clear();
 538		mCtrlPathEnd->clear();
 539		mSpinScaleX->clear();
 540		mSpinScaleY->clear();
 541		mSpinTwist->clear();
 542		mSpinTwistBegin->clear();
 543		mComboHoleType->clear();
 544		mSpinShearX->clear();
 545		mSpinShearY->clear();
 546		mSpinTaperX->clear();
 547		mSpinTaperY->clear();
 548		mSpinRadiusOffset->clear();
 549		mSpinRevolutions->clear();
 550		mSpinSkew->clear();
 551		
 552		mSelectedType = MI_NONE;
 553	}
 554	else
 555	{
 556		// Only allowed to change these parameters for objects
 557		// that you have permissions on AND are not attachments.
 558		enabled = root_objectp->permModify();
 559		
 560		// Volume type
 561		const LLVolumeParams &volume_params = objectp->getVolume()->getParams();
 562		U8 path = volume_params.getPathParams().getCurveType();
 563		U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
 564		U8 profile	= profile_and_hole & LL_PCODE_PROFILE_MASK;
 565		U8 hole		= profile_and_hole & LL_PCODE_HOLE_MASK;
 566		
 567		// Scale goes first so we can differentiate between a sphere and a torus,
 568		// which have the same profile and path types.
 569
 570		// Scale
 571		scale_x = volume_params.getRatioX();
 572		scale_y = volume_params.getRatioY();
 573
 574		BOOL linear_path = (path == LL_PCODE_PATH_LINE) || (path == LL_PCODE_PATH_FLEXIBLE);
 575		if ( linear_path && profile == LL_PCODE_PROFILE_CIRCLE )
 576		{
 577			selected_item = MI_CYLINDER;
 578		}
 579		else if ( linear_path && profile == LL_PCODE_PROFILE_SQUARE )
 580		{
 581			selected_item = MI_BOX;
 582		}
 583		else if ( linear_path && profile == LL_PCODE_PROFILE_ISOTRI )
 584		{
 585			selected_item = MI_PRISM;
 586		}
 587		else if ( linear_path && profile == LL_PCODE_PROFILE_EQUALTRI )
 588		{
 589			selected_item = MI_PRISM;
 590		}
 591		else if ( linear_path && profile == LL_PCODE_PROFILE_RIGHTTRI )
 592		{
 593			selected_item = MI_PRISM;
 594		}
 595		else if (path == LL_PCODE_PATH_FLEXIBLE) // shouldn't happen
 596		{
 597			selected_item = MI_CYLINDER; // reasonable default
 598		}
 599		else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y > 0.75f)
 600		{
 601			selected_item = MI_SPHERE;
 602		}
 603		else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE && scale_y <= 0.75f)
 604		{
 605			selected_item = MI_TORUS;
 606		}
 607		else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_CIRCLE_HALF)
 608		{
 609			selected_item = MI_SPHERE;
 610		}
 611		else if ( path == LL_PCODE_PATH_CIRCLE2 && profile == LL_PCODE_PROFILE_CIRCLE )
 612		{
 613			// Spirals aren't supported.  Make it into a sphere.  JC
 614			selected_item = MI_SPHERE;
 615		}
 616		else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_EQUALTRI )
 617		{
 618			selected_item = MI_RING;
 619		}
 620		else if ( path == LL_PCODE_PATH_CIRCLE && profile == LL_PCODE_PROFILE_SQUARE && scale_y <= 0.75f)
 621		{
 622			selected_item = MI_TUBE;
 623		}
 624		else
 625		{
 626			llinfos << "Unknown path " << (S32) path << " profile " << (S32) profile << " in getState" << llendl;
 627			selected_item = MI_BOX;
 628		}
 629
 630
 631		if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
 632		{
 633			selected_item = MI_SCULPT;
 634			//LLFirstUse::useSculptedPrim();
 635		}
 636
 637		
 638		mComboBaseType	->setCurrentByIndex( selected_item );
 639		mSelectedType = selected_item;
 640		
 641		// Grab S path
 642		F32 begin_s	= volume_params.getBeginS();
 643		F32 end_s	= volume_params.getEndS();
 644
 645		// Compute cut and advanced cut from S and T
 646		F32 begin_t = volume_params.getBeginT();
 647		F32 end_t	= volume_params.getEndT();
 648
 649		// Hollowness
 650		F32 hollow = 100.f * volume_params.getHollow();
 651		mSpinHollow->set( hollow );
 652		calcp->setVar(LLCalc::HOLLOW, hollow);
 653		// All hollow objects allow a shape to be selected.
 654		if (hollow > 0.f)
 655		{
 656			switch (hole)
 657			{
 658			case LL_PCODE_HOLE_CIRCLE:
 659				selected_hole = MI_HOLE_CIRCLE;
 660				break;
 661			case LL_PCODE_HOLE_SQUARE:
 662				selected_hole = MI_HOLE_SQUARE;
 663				break;
 664			case LL_PCODE_HOLE_TRIANGLE:
 665				selected_hole = MI_HOLE_TRIANGLE;
 666				break;
 667			case LL_PCODE_HOLE_SAME:
 668			default:
 669				selected_hole = MI_HOLE_SAME;
 670				break;
 671			}
 672			mComboHoleType->setCurrentByIndex( selected_hole );
 673			hole_enabled = enabled;
 674		}
 675		else
 676		{
 677			mComboHoleType->setCurrentByIndex( MI_HOLE_SAME );
 678			hole_enabled = FALSE;
 679		}
 680
 681		// Cut interpretation varies based on base object type
 682		F32 cut_begin, cut_end, adv_cut_begin, adv_cut_end;
 683
 684		if ( selected_item == MI_SPHERE || selected_item == MI_TORUS || 
 685			 selected_item == MI_TUBE   || selected_item == MI_RING )
 686		{
 687			cut_begin		= begin_t;
 688			cut_end			= end_t;
 689			adv_cut_begin	= begin_s;
 690			adv_cut_end		= end_s;
 691		}
 692		else
 693		{
 694			cut_begin       = begin_s;
 695			cut_end         = end_s;
 696			adv_cut_begin   = begin_t;
 697			adv_cut_end     = end_t;
 698		}
 699
 700		mSpinCutBegin	->set( cut_begin );
 701		mSpinCutEnd		->set( cut_end );
 702		mCtrlPathBegin	->set( adv_cut_begin );
 703		mCtrlPathEnd	->set( adv_cut_end );
 704		calcp->setVar(LLCalc::CUT_BEGIN, cut_begin);
 705		calcp->setVar(LLCalc::CUT_END, cut_end);
 706		calcp->setVar(LLCalc::PATH_BEGIN, adv_cut_begin);
 707		calcp->setVar(LLCalc::PATH_END, adv_cut_end);
 708
 709		// Twist
 710		F32 twist		= volume_params.getTwist();
 711		F32 twist_begin = volume_params.getTwistBegin();
 712		// Check the path type for conversion.
 713		if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
 714		{
 715			twist		*= OBJECT_TWIST_LINEAR_MAX;
 716			twist_begin	*= OBJECT_TWIST_LINEAR_MAX;
 717		}
 718		else
 719		{
 720			twist		*= OBJECT_TWIST_MAX;
 721			twist_begin	*= OBJECT_TWIST_MAX;
 722		}
 723
 724		mSpinTwist		->set( twist );
 725		mSpinTwistBegin	->set( twist_begin );
 726		calcp->setVar(LLCalc::TWIST_END, twist);
 727		calcp->setVar(LLCalc::TWIST_BEGIN, twist_begin);
 728
 729		// Shear
 730		F32 shear_x = volume_params.getShearX();
 731		F32 shear_y = volume_params.getShearY();
 732		mSpinShearX->set( shear_x );
 733		mSpinShearY->set( shear_y );
 734		calcp->setVar(LLCalc::X_SHEAR, shear_x);
 735		calcp->setVar(LLCalc::Y_SHEAR, shear_y);
 736
 737		// Taper
 738		F32 taper_x	= volume_params.getTaperX();
 739		F32 taper_y = volume_params.getTaperY();
 740		mSpinTaperX->set( taper_x );
 741		mSpinTaperY->set( taper_y );
 742		calcp->setVar(LLCalc::X_TAPER, taper_x);
 743		calcp->setVar(LLCalc::Y_TAPER, taper_y);
 744
 745		// Radius offset.
 746		F32 radius_offset = volume_params.getRadiusOffset();
 747		// Limit radius offset, based on taper and hole size y.
 748		F32 radius_mag = fabs(radius_offset);
 749		F32 hole_y_mag = fabs(scale_y);
 750		F32 taper_y_mag  = fabs(taper_y);
 751		// Check to see if the taper effects us.
 752		if ( (radius_offset > 0.f && taper_y < 0.f) ||
 753			 (radius_offset < 0.f && taper_y > 0.f) )
 754		{
 755			// The taper does not help increase the radius offset range.
 756			taper_y_mag = 0.f;
 757		}
 758		F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag);
 759		// Enforce the maximum magnitude.
 760		if (radius_mag > max_radius_mag)
 761		{
 762			// Check radius offset sign.
 763			if (radius_offset < 0.f)
 764			{
 765				radius_offset = -max_radius_mag;
 766			}
 767			else
 768			{
 769				radius_offset = max_radius_mag;
 770			}
 771		}
 772		mSpinRadiusOffset->set( radius_offset);
 773		calcp->setVar(LLCalc::RADIUS_OFFSET, radius_offset);
 774
 775		// Revolutions
 776		F32 revolutions = volume_params.getRevolutions();
 777		mSpinRevolutions->set( revolutions );
 778		calcp->setVar(LLCalc::REVOLUTIONS, revolutions);
 779		
 780		// Skew
 781		F32 skew	= volume_params.getSkew();
 782		// Limit skew, based on revolutions hole size x.
 783		F32 skew_mag= fabs(skew);
 784		F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f);
 785		// Discontinuity; A revolution of 1 allows skews below 0.5.
 786		if ( fabs(revolutions - 1.0f) < 0.001)
 787			min_skew_mag = 0.0f;
 788
 789		// Clip skew.
 790		if (skew_mag < min_skew_mag)
 791		{
 792			// Check skew sign.
 793			if (skew < 0.0f)
 794			{
 795				skew = -min_skew_mag;
 796			}
 797			else 
 798			{
 799				skew = min_skew_mag;
 800			}
 801		}
 802		mSpinSkew->set( skew );
 803		calcp->setVar(LLCalc::SKEW, skew);
 804	}
 805	
 806	// Compute control visibility, label names, and twist range.
 807	// Start with defaults.
 808	BOOL cut_visible                = TRUE;
 809	BOOL hollow_visible             = TRUE;
 810	BOOL top_size_x_visible			= TRUE;
 811	BOOL top_size_y_visible			= TRUE;
 812	BOOL top_shear_x_visible		= TRUE;
 813	BOOL top_shear_y_visible		= TRUE;
 814	BOOL twist_visible				= TRUE;
 815	BOOL advanced_cut_visible		= FALSE;
 816	BOOL taper_visible				= FALSE;
 817	BOOL skew_visible				= FALSE;
 818	BOOL radius_offset_visible		= FALSE;
 819	BOOL revolutions_visible		= FALSE;
 820	BOOL sculpt_texture_visible     = FALSE;
 821	F32	 twist_min					= OBJECT_TWIST_LINEAR_MIN;
 822	F32	 twist_max					= OBJECT_TWIST_LINEAR_MAX;
 823	F32	 twist_inc					= OBJECT_TWIST_LINEAR_INC;
 824
 825	BOOL advanced_is_dimple = FALSE;
 826	BOOL advanced_is_slice = FALSE;
 827	BOOL size_is_hole = FALSE;
 828
 829	// Tune based on overall volume type
 830	switch (selected_item)
 831	{
 832	case MI_SPHERE:
 833		top_size_x_visible		= FALSE;
 834		top_size_y_visible		= FALSE;
 835		top_shear_x_visible		= FALSE;
 836		top_shear_y_visible		= FALSE;
 837		//twist_visible			= FALSE;
 838		advanced_cut_visible	= TRUE;
 839		advanced_is_dimple		= TRUE;
 840		twist_min				= OBJECT_TWIST_MIN;
 841		twist_max				= OBJECT_TWIST_MAX;
 842		twist_inc				= OBJECT_TWIST_INC;
 843		break;
 844
 845	case MI_TORUS:
 846	case MI_TUBE:	
 847	case MI_RING:
 848		//top_size_x_visible		= FALSE;
 849		//top_size_y_visible		= FALSE;
 850	  	size_is_hole 			= TRUE;
 851		skew_visible			= TRUE;
 852		advanced_cut_visible	= TRUE;
 853		taper_visible			= TRUE;
 854		radius_offset_visible	= TRUE;
 855		revolutions_visible		= TRUE;
 856		twist_min				= OBJECT_TWIST_MIN;
 857		twist_max				= OBJECT_TWIST_MAX;
 858		twist_inc				= OBJECT_TWIST_INC;
 859
 860		break;
 861
 862	case MI_SCULPT:
 863		cut_visible             = FALSE;
 864		hollow_visible          = FALSE;
 865		twist_visible           = FALSE;
 866		top_size_x_visible      = FALSE;
 867		top_size_y_visible      = FALSE;
 868		top_shear_x_visible     = FALSE;
 869		top_shear_y_visible     = FALSE;
 870		skew_visible            = FALSE;
 871		advanced_cut_visible    = FALSE;
 872		taper_visible           = FALSE;
 873		radius_offset_visible   = FALSE;
 874		revolutions_visible     = FALSE;
 875		sculpt_texture_visible  = TRUE;
 876
 877		break;
 878		
 879	case MI_BOX:
 880		advanced_cut_visible	= TRUE;
 881		advanced_is_slice		= TRUE;
 882		break;
 883
 884	case MI_CYLINDER:
 885		advanced_cut_visible	= TRUE;
 886		advanced_is_slice		= TRUE;
 887		break;
 888
 889	case MI_PRISM:
 890		advanced_cut_visible	= TRUE;
 891		advanced_is_slice		= TRUE;
 892		break;
 893
 894	default:
 895		break;
 896	}
 897
 898	// Check if we need to change top size/hole size params.
 899	switch (selected_item)
 900	{
 901	case MI_SPHERE:
 902	case MI_TORUS:
 903	case MI_TUBE:
 904	case MI_RING:
 905		mSpinScaleX->set( scale_x );
 906		mSpinScaleY->set( scale_y );
 907		calcp->setVar(LLCalc::X_HOLE, scale_x);
 908		calcp->setVar(LLCalc::Y_HOLE, scale_y);
 909		mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);
 910		mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);
 911		mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE);
 912		mSpinScaleY->setMaxValue(OBJECT_MAX_HOLE_SIZE_Y);
 913		break;
 914	default:
 915		if (editable)
 916		{
 917			mSpinScaleX->set( 1.f - scale_x );
 918			mSpinScaleY->set( 1.f - scale_y );
 919			mSpinScaleX->setMinValue(-1.f);
 920			mSpinScaleX->setMaxValue(1.f);
 921			mSpinScaleY->setMinValue(-1.f);
 922			mSpinScaleY->setMaxValue(1.f);
 923
 924			// Torus' Hole Size is Box/Cyl/Prism's Taper
 925			calcp->setVar(LLCalc::X_TAPER, 1.f - scale_x);
 926			calcp->setVar(LLCalc::Y_TAPER, 1.f - scale_y);
 927
 928			// Box/Cyl/Prism have no hole size
 929			calcp->setVar(LLCalc::X_HOLE, 0.f);
 930			calcp->setVar(LLCalc::Y_HOLE, 0.f);
 931		}
 932		break;
 933	}
 934
 935	// Check if we need to limit the hollow based on the hole type.
 936	if (  selected_hole == MI_HOLE_SQUARE && 
 937		  ( selected_item == MI_CYLINDER || selected_item == MI_TORUS ||
 938		    selected_item == MI_PRISM    || selected_item == MI_RING  ||
 939			selected_item == MI_SPHERE ) )
 940	{
 941		mSpinHollow->setMinValue(0.f);
 942		mSpinHollow->setMaxValue(70.f);
 943	}
 944	else 
 945	{
 946		mSpinHollow->setMinValue(0.f);
 947		mSpinHollow->setMaxValue(95.f);
 948	}
 949
 950	// Update field enablement
 951	mComboBaseType	->setEnabled( enabled );
 952
 953	mLabelCut		->setEnabled( enabled );
 954	mSpinCutBegin	->setEnabled( enabled );
 955	mSpinCutEnd		->setEnabled( enabled );
 956
 957	mLabelHollow	->setEnabled( enabled );
 958	mSpinHollow		->setEnabled( enabled );
 959	mLabelHoleType	->setEnabled( hole_enabled );
 960	mComboHoleType	->setEnabled( hole_enabled );
 961
 962	mLabelTwist		->setEnabled( enabled );
 963	mSpinTwist		->setEnabled( enabled );
 964	mSpinTwistBegin	->setEnabled( enabled );
 965
 966	mLabelSkew		->setEnabled( enabled );
 967	mSpinSkew		->setEnabled( enabled );
 968
 969	getChildView("scale_hole")->setVisible( FALSE);
 970	getChildView("scale_taper")->setVisible( FALSE);
 971	if (top_size_x_visible || top_size_y_visible)
 972	{
 973		if (size_is_hole)
 974		{
 975			getChildView("scale_hole")->setVisible( TRUE);
 976			getChildView("scale_hole")->setEnabled(enabled);
 977		}
 978		else
 979		{
 980			getChildView("scale_taper")->setVisible( TRUE);
 981			getChildView("scale_taper")->setEnabled(enabled);
 982		}
 983	}
 984	
 985	mSpinScaleX		->setEnabled( enabled );
 986	mSpinScaleY		->setEnabled( enabled );
 987
 988	mLabelShear		->setEnabled( enabled );
 989	mSpinShearX		->setEnabled( enabled );
 990	mSpinShearY		->setEnabled( enabled );
 991
 992	getChildView("advanced_cut")->setVisible( FALSE);
 993	getChildView("advanced_dimple")->setVisible( FALSE);
 994	getChildView("advanced_slice")->setVisible( FALSE);
 995
 996	if (advanced_cut_visible)
 997	{
 998		if (advanced_is_dimple)
 999		{
1000			getChildView("advanced_dimple")->setVisible( TRUE);
1001			getChildView("advanced_dimple")->setEnabled(enabled);
1002		}
1003
1004		else if (advanced_is_slice)
1005		{
1006			getChildView("advanced_slice")->setVisible( TRUE);
1007			getChildView("advanced_slice")->setEnabled(enabled);
1008		}
1009		else
1010		{
1011			getChildView("advanced_cut")->setVisible( TRUE);
1012			getChildView("advanced_cut")->setEnabled(enabled);
1013		}
1014	}
1015	
1016	mCtrlPathBegin	->setEnabled( enabled );
1017	mCtrlPathEnd	->setEnabled( enabled );
1018
1019	mLabelTaper		->setEnabled( enabled );
1020	mSpinTaperX		->setEnabled( enabled );
1021	mSpinTaperY		->setEnabled( enabled );
1022
1023	mLabelRadiusOffset->setEnabled( enabled );
1024	mSpinRadiusOffset ->setEnabled( enabled );
1025
1026	mLabelRevolutions->setEnabled( enabled );
1027	mSpinRevolutions ->setEnabled( enabled );
1028
1029	// Update field visibility
1030	mLabelCut		->setVisible( cut_visible );
1031	mSpinCutBegin	->setVisible( cut_visible );
1032	mSpinCutEnd		->setVisible( cut_visible ); 
1033
1034	mLabelHollow	->setVisible( hollow_visible );
1035	mSpinHollow		->setVisible( hollow_visible );
1036	mLabelHoleType	->setVisible( hollow_visible );
1037	mComboHoleType	->setVisible( hollow_visible );
1038	
1039	mLabelTwist		->setVisible( twist_visible );
1040	mSpinTwist		->setVisible( twist_visible );
1041	mSpinTwistBegin	->setVisible( twist_visible );
1042	mSpinTwist		->setMinValue(  twist_min );
1043	mSpinTwist		->setMaxValue(  twist_max );
1044	mSpinTwist		->setIncrement( twist_inc );
1045	mSpinTwistBegin	->setMinValue(  twist_min );
1046	mSpinTwistBegin	->setMaxValue(  twist_max );
1047	mSpinTwistBegin	->setIncrement( twist_inc );
1048
1049	mSpinScaleX		->setVisible( top_size_x_visible );
1050	mSpinScaleY		->setVisible( top_size_y_visible );
1051
1052	mLabelSkew		->setVisible( skew_visible );
1053	mSpinSkew		->setVisible( skew_visible );
1054
1055	mLabelShear		->setVisible( top_shear_x_visible || top_shear_y_visible );
1056	mSpinShearX		->setVisible( top_shear_x_visible );
1057	mSpinShearY		->setVisible( top_shear_y_visible );
1058
1059	mCtrlPathBegin	->setVisible( advanced_cut_visible );
1060	mCtrlPathEnd	->setVisible( advanced_cut_visible );
1061
1062	mLabelTaper		->setVisible( taper_visible );
1063	mSpinTaperX		->setVisible( taper_visible );
1064	mSpinTaperY		->setVisible( taper_visible );
1065
1066	mLabelRadiusOffset->setVisible( radius_offset_visible );
1067	mSpinRadiusOffset ->setVisible( radius_offset_visible );
1068
1069	mLabelRevolutions->setVisible( revolutions_visible );
1070	mSpinRevolutions ->setVisible( revolutions_visible );
1071
1072	mCtrlSculptTexture->setVisible(sculpt_texture_visible);
1073	mLabelSculptType->setVisible(sculpt_texture_visible);
1074	mCtrlSculptType->setVisible(sculpt_texture_visible);
1075
1076
1077	// sculpt texture
1078	if (selected_item == MI_SCULPT)
1079	{
1080
1081
1082		LLUUID id;
1083		LLSculptParams *sculpt_params = (LLSculptParams *)objectp->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
1084
1085		
1086		if (sculpt_params) // if we have a legal sculpt param block for this object:
1087		{
1088			if (mObject != objectp)  // we've just selected a new object, so save for undo
1089			{
1090				mSculptTextureRevert = sculpt_params->getSculptTexture();
1091				mSculptTypeRevert    = sculpt_params->getSculptType();
1092			}
1093		
1094			U8 sculpt_type = sculpt_params->getSculptType();
1095			U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
1096			BOOL sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
1097			BOOL sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
1098			isMesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
1099
1100			LLTextureCtrl*  mTextureCtrl = getChild<LLTextureCtrl>("sculpt texture control");
1101			if(mTextureCtrl)
1102			{
1103				mTextureCtrl->setTentative(FALSE);
1104				mTextureCtrl->setEnabled(editable && !isMesh);
1105				if (editable)
1106					mTextureCtrl->setImageAssetID(sculpt_params->getSculptTexture());
1107				else
1108					mTextureCtrl->setImageAssetID(LLUUID::null);
1109			}
1110
1111			mComboBaseType->setEnabled(!isMesh);
1112			
1113			if (mCtrlSculptType)
1114			{
1115				if (sculpt_stitching == LL_SCULPT_TYPE_NONE)
1116				{
1117					// since 'None' is no longer an option in the combo box
1118					// use 'Plane' as an equivalent sculpt type
1119					mCtrlSculptType->setSelectedByValue(LLSD(LL_SCULPT_TYPE_PLANE), true);
1120				}
1121				else
1122				{
1123					mCtrlSculptType->setSelectedByValue(LLSD(sculpt_stitching), true);
1124				}
1125				mCtrlSculptType->setEnabled(editable && !isMesh);
1126			}
1127
1128			if (mCtrlSculptMirror)
1129			{
1130				mCtrlSculptMirror->set(sculpt_mirror);
1131				mCtrlSculptMirror->setEnabled(editable && !isMesh);
1132			}
1133
1134			if (mCtrlSculptInvert)
1135			{
1136				mCtrlSculptInvert->set(sculpt_invert);
1137				mCtrlSculptInvert->setEnabled(editable);
1138			}
1139
1140			if (mLabelSculptType)
1141			{
1142				mLabelSculptType->setEnabled(TRUE);
1143			}
1144			
1145		}
1146	}
1147	else
1148	{
1149		mSculptTextureRevert = LLUUID::null;		
1150	}
1151
1152	mCtrlSculptMirror->setVisible(sculpt_texture_visible && !isMesh);
1153	mCtrlSculptInvert->setVisible(sculpt_texture_visible && !isMesh);
1154
1155	//----------------------------------------------------------------------------
1156
1157	mObject = objectp;
1158	mRootObject = root_objectp;
1159}
1160
1161// static
1162bool LLPanelObject::precommitValidate( const LLSD& data )
1163{
1164	// TODO: Richard will fill this in later.  
1165	return TRUE; // FALSE means that validation failed and new value should not be commited.
1166}
1167
1168void LLPanelObject::sendIsPhysical()
1169{
1170	BOOL value = mCheckPhysics->get();
1171	if( mIsPhysical != value )
1172	{
1173		LLSelectMgr::getInstance()->selectionUpdatePhysics(value);
1174		mIsPhysical = value;
1175
1176		llinfos << "update physics sent" << llendl;
1177	}
1178	else
1179	{
1180		llinfos << "update physics not changed" << llendl;
1181	}
1182}
1183
1184void LLPanelObject::sendIsTemporary()
1185{
1186	BOOL value = mCheckTemporary->get();
1187	if( mIsTemporary != value )
1188	{
1189		LLSelectMgr::getInstance()->selectionUpdateTemporary(value);
1190		mIsTemporary = value;
1191
1192		llinfos << "update temporary sent" << llendl;
1193	}
1194	else
1195	{
1196		llinfos << "update temporary not changed" << llendl;
1197	}
1198}
1199
1200
1201void LLPanelObject::sendIsPhantom()
1202{
1203	BOOL value = mCheckPhantom->get();
1204	if( mIsPhantom != value )
1205	{
1206		LLSelectMgr::getInstance()->selectionUpdatePhantom(value);
1207		mIsPhantom = value;
1208
1209		llinfos << "update phantom sent" << llendl;
1210	}
1211	else
1212	{
1213		llinfos << "update phantom not changed" << llendl;
1214	}
1215}
1216
1217void LLPanelObject::sendCastShadows()
1218{
1219	BOOL value = mCheckCastShadows->get();
1220	if( mCastShadows != value )
1221	{
1222		LLSelectMgr::getInstance()->selectionUpdateCastShadows(value);
1223		mCastShadows = value;
1224
1225		llinfos << "update cast shadows sent" << llendl;
1226	}
1227	else
1228	{
1229		llinfos << "update cast shadows not changed" << llendl;
1230	}
1231}
1232
1233// static
1234void LLPanelObject::onCommitParametric( LLUICtrl* ctrl, void* userdata )
1235{
1236	LLPanelObject* self = (LLPanelObject*) userdata;
1237
1238	if (self->mObject.isNull())
1239	{
1240		return;
1241	}
1242
1243	if (self->mObject->getPCode() != LL_PCODE_VOLUME)
1244	{
1245		// Don't allow modification of non-volume objects.
1246		return;
1247	}
1248
1249	LLVolume *volume = self->mObject->getVolume();
1250	if (!volume)
1251	{
1252		return;
1253	}
1254
1255	LLVolumeParams volume_params;
1256	self->getVolumeParams(volume_params);
1257	
1258
1259	
1260	// set sculpting
1261	S32 selected_type = self->mComboBaseType->getCurrentIndex();
1262
1263	if (selected_type == MI_SCULPT)
1264	{
1265		self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, TRUE, TRUE);
1266		LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
1267		if (sculpt_params)
1268			volume_params.setSculptID(sculpt_params->getSculptTexture(), sculpt_params->getSculptType());
1269	}
1270	else
1271	{
1272		LLSculptParams *sculpt_params = (LLSculptParams *)self->mObject->getParameterEntry(LLNetworkData::PARAMS_SCULPT);
1273		if (sculpt_params)
1274			self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT, FALSE, TRUE);
1275	}
1276
1277	// Update the volume, if necessary.
1278	self->mObject->updateVolume(volume_params);
1279
1280
1281	// This was added to make sure thate when changes are made, the UI
1282	// adjusts to present valid options.
1283	// *FIX: only some changes, ie, hollow or primitive type changes,
1284	// require a refresh.
1285	self->refresh();
1286
1287}
1288
1289void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params)
1290{
1291	// Figure out what type of volume to make
1292	S32 was_selected_type = mSelectedType;
1293	S32 selected_type = mComboBaseType->getCurrentIndex();
1294	U8 profile;
1295	U8 path;
1296	switch ( selected_type )
1297	{
1298	case MI_CYLINDER:
1299		profile = LL_PCODE_PROFILE_CIRCLE;
1300		path = LL_PCODE_PATH_LINE;
1301		break;
1302
1303	case MI_BOX:
1304		profile = LL_PCODE_PROFILE_SQUARE;
1305		path = LL_PCODE_PATH_LINE;
1306		break;
1307
1308	case MI_PRISM:
1309		profile = LL_PCODE_PROFILE_EQUALTRI;
1310		path = LL_PCODE_PATH_LINE;
1311		break;
1312
1313	case MI_SPHERE:
1314		profile = LL_PCODE_PROFILE_CIRCLE_HALF;
1315		path = LL_PCODE_PATH_CIRCLE;
1316		break;
1317
1318	case MI_TORUS:
1319		profile = LL_PCODE_PROFILE_CIRCLE;
1320		path = LL_PCODE_PATH_CIRCLE;
1321		break;
1322
1323	case MI_TUBE:
1324		profile = LL_PCODE_PROFILE_SQUARE;
1325		path = LL_PCODE_PATH_CIRCLE;
1326		break;
1327
1328	case MI_RING:
1329		profile = LL_PCODE_PROFILE_EQUALTRI;
1330		path = LL_PCODE_PATH_CIRCLE;
1331		break;
1332
1333	case MI_SCULPT:
1334		profile = LL_PCODE_PROFILE_CIRCLE;
1335		path = LL_PCODE_PATH_CIRCLE;
1336		break;
1337		
1338	default:
1339		llwarns << "Unknown base type " << selected_type 
1340			<< " in getVolumeParams()" << llendl;
1341		// assume a box
1342		selected_type = MI_BOX;
1343		profile = LL_PCODE_PROFILE_SQUARE;
1344		path = LL_PCODE_PATH_LINE;
1345		break;
1346	}
1347
1348
1349	if (path == LL_PCODE_PATH_LINE)
1350	{
1351		LLVOVolume *volobjp = (LLVOVolume *)(LLViewerObject*)(mObject);
1352		if (volobjp->isFlexible())
1353		{
1354			path = LL_PCODE_PATH_FLEXIBLE;
1355		}
1356	}
1357	
1358	S32 selected_hole = mComboHoleType->getCurrentIndex();
1359	U8 hole;
1360	switch (selected_hole)
1361	{
1362	case MI_HOLE_CIRCLE: 
1363		hole = LL_PCODE_HOLE_CIRCLE;
1364		break;
1365	case MI_HOLE_SQUARE:
1366		hole = LL_PCODE_HOLE_SQUARE;
1367		break;
1368	case MI_HOLE_TRIANGLE:
1369		hole = LL_PCODE_HOLE_TRIANGLE;
1370		break;
1371	case MI_HOLE_SAME:
1372	default:
1373		hole = LL_PCODE_HOLE_SAME;
1374		break;
1375	}
1376
1377	volume_params.setType(profile | hole, path);
1378	mSelectedType = selected_type;
1379	
1380	// Compute cut start/end
1381	F32 cut_begin	= mSpinCutBegin->get();
1382	F32 cut_end		= mSpinCutEnd->get();
1383
1384	// Make sure at least OBJECT_CUT_INC of the object survives
1385	if (cut_begin > cut_end - OBJECT_MIN_CUT_INC)
1386	{
1387		cut_begin = cut_end - OBJECT_MIN_CUT_INC;
1388		mSpinCutBegin->set(cut_begin);
1389	}
1390
1391	F32 adv_cut_begin	= mCtrlPathBegin->get();
1392	F32 adv_cut_end		= mCtrlPathEnd->get();
1393
1394	// Make sure at least OBJECT_CUT_INC of the object survives
1395	if (adv_cut_begin > adv_cut_end - OBJECT_MIN_CUT_INC)
1396	{
1397		adv_cut_begin = adv_cut_end - OBJECT_MIN_CUT_INC;
1398		mCtrlPathBegin->set(adv_cut_begin);
1399	}
1400
1401	F32 begin_s, end_s;
1402	F32 begin_t, end_t;
1403
1404	if (selected_type == MI_SPHERE || selected_type == MI_TORUS || 
1405		selected_type == MI_TUBE   || selected_type == MI_RING)
1406	{
1407		begin_s = adv_cut_begin;
1408		end_s	= adv_cut_end;
1409
1410		begin_t = cut_begin;
1411		end_t	= cut_end;
1412	}
1413	else
1414	{
1415		begin_s = cut_begin;
1416		end_s	= cut_end;
1417
1418		begin_t = adv_cut_begin;
1419		end_t	= adv_cut_end;
1420	}
1421
1422	volume_params.setBeginAndEndS(begin_s, end_s);
1423	volume_params.setBeginAndEndT(begin_t, end_t);
1424
1425	// Hollowness
1426	F32 hollow = mSpinHollow->get() / 100.f;
1427
1428	if (  selected_hole == MI_HOLE_SQUARE && 
1429		( selected_type == MI_CYLINDER || selected_type == MI_TORUS ||
1430		  selected_type == MI_PRISM    || selected_type == MI_RING  ||
1431		  selected_type == MI_SPHERE ) )
1432	{
1433		if (hollow > 0.7f) hollow = 0.7f;
1434	}
1435
1436	volume_params.setHollow( hollow );
1437
1438	// Twist Begin,End
1439	F32 twist_begin = mSpinTwistBegin->get();
1440	F32 twist		= mSpinTwist->get();
1441	// Check the path type for twist conversion.
1442	if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
1443	{
1444		twist_begin	/= OBJECT_TWIST_LINEAR_MAX;
1445		twist		/= OBJECT_TWIST_LINEAR_MAX;
1446	}
1447	else
1448	{
1449		twist_begin	/= OBJECT_TWIST_MAX;
1450		twist		/= OBJECT_TWIST_MAX;
1451	}
1452
1453	volume_params.setTwistBegin(twist_begin);
1454	volume_params.setTwist(twist);
1455
1456	// Scale X,Y
1457	F32 scale_x = mSpinScaleX->get();
1458	F32 scale_y = mSpinScaleY->get();
1459	if ( was_selected_type == MI_BOX || was_selected_type == MI_CYLINDER || was_selected_type == MI_PRISM)
1460	{
1461		scale_x = 1.f - scale_x;
1462		scale_y = 1.f - scale_y;
1463	}
1464	
1465	// Skew
1466	F32 skew = mSpinSkew->get();
1467
1468	// Taper X,Y
1469	F32 taper_x = mSpinTaperX->get();
1470	F32 taper_y = mSpinTaperY->get();
1471
1472	// Radius offset
1473	F32 radius_offset = mSpinRadiusOffset->get();
1474
1475	// Revolutions
1476	F32 revolutions	  = mSpinRevolutions->get();
1477
1478	if ( selected_type == MI_SPHERE )
1479	{
1480		// Snap values to valid sphere parameters.
1481		scale_x			= 1.0f;
1482		scale_y			= 1.0f;
1483		skew			= 0.0f;
1484		taper_x			= 0.0f;
1485		taper_y			= 0.0f;
1486		radius_offset	= 0.0f;
1487		revolutions		= 1.0f;
1488	}
1489	else if ( selected_type == MI_TORUS || selected_type == MI_TUBE ||
1490			  selected_type == MI_RING )
1491	{
1492		scale_x = llclamp(
1493			scale_x,
1494			OBJECT_MIN_HOLE_SIZE,
1495			OBJECT_MAX_HOLE_SIZE_X);
1496		scale_y = llclamp(
1497			scale_y,
1498			OBJECT_MIN_HOLE_SIZE,
1499			OBJECT_MAX_HOLE_SIZE_Y);
1500
1501		// Limit radius offset, based on taper and hole size y.
1502		F32 radius_mag = fabs(radius_offset);
1503		F32 hole_y_mag = fabs(scale_y);
1504		F32 taper_y_mag  = fabs(taper_y);
1505		// Check to see if the taper effects us.
1506		if ( (radius_offset > 0.f && taper_y < 0.f) ||
1507			 (radius_offset < 0.f && taper_y > 0.f) )
1508		{
1509			// The taper does not help increase the radius offset range.
1510			taper_y_mag = 0.f;
1511		}
1512		F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) / (1.f - hole_y_mag);
1513		// Enforce the maximum magnitude.
1514		if (radius_mag > max_radius_mag)
1515		{
1516			// Check radius offset sign.
1517			if (radius_offset < 0.f)
1518			{
1519				radius_offset = -max_radius_mag;
1520			}
1521			else
1522			{
1523				radius_offset = max_radius_mag;
1524			}
1525		}
1526			
1527		// Check the skew value against the revolutions.
1528		F32 skew_mag= fabs(skew);
1529		F32 min_skew_mag = 1.0f - 1.0f / (revolutions * scale_x + 1.0f);
1530		// Discontinuity; A revolution of 1 allows skews below 0.5.
1531		if ( fabs(revolutions - 1.0f) < 0.001)
1532			min_skew_mag = 0.0f;
1533
1534		// Clip skew.
1535		if (skew_mag < min_skew_mag)
1536		{
1537			// Check skew sign.
1538			if (skew < 0.0f)
1539			{
1540				skew = -min_skew_mag;
1541			}
1542			else 
1543			{
1544				skew = min_skew_mag;
1545			}
1546		}
1547	}
1548
1549	volume_params.setRatio( scale_x, scale_y );
1550	volume_params.setSkew(skew);
1551	volume_params.setTaper( taper_x, taper_y );
1552	volume_params.setRadiusOffset(radius_offset);
1553	volume_params.setRevolutions(revolutions);
1554
1555	// Shear X,Y
1556	F32 shear_x = mSpinShearX->get();
1557	F32 shear_y = mSpinShearY->get();
1558	volume_params.setShear( shear_x, shear_y );
1559
1560	if (selected_type == MI_SCULPT)
1561	{
1562		volume_params.setSculptID(LLUUID::null, 0);
1563		volume_params.setBeginAndEndT   (0, 1);
1564		volume_params.setBeginAndEndS   (0, 1);
1565		volume_params.setHollow         (0);
1566		volume_params.setTwistBegin     (0);
1567		volume_params.setTwistEnd       (0);
1568		volume_params.setRatio          (1, 0.5);
1569		volume_params.setShear          (0, 0);
1570		volume_params.setTaper          (0, 0);
1571		volume_params.setRevolutions    (1);
1572		volume_params.setRadiusOffset   (0);
1573		volume_params.setSkew           (0);
1574	}
1575
1576}
1577
1578// BUG: Make work with multiple objects
1579void LLPanelObject::sendRotation(BOOL btn_down)
1580{
1581	if (mObject.isNull()) return;
1582
1583	LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
1584	new_rot.mV[VX] = llround(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
1585	new_rot.mV[VY] = llround(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
1586	new_rot.mV[VZ] = llround(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION);
1587
1588	// Note: must compare before conversion to radians
1589	LLVector3 delta = new_rot - mCurEulerDegrees;
1590
1591	if (delta.magVec() >= 0.0005f)
1592	{
1593		mCurEulerDegrees = new_rot;
1594		new_rot *= DEG_TO_RAD;
1595
1596		LLQuaternion rotation;
1597		rotation.setQuat(new_rot.mV[VX], new_rot.mV[VY], new_rot.mV[VZ]);
1598
1599		if (mRootObject != mObject)
1600		{
1601			rotation = rotation * ~mRootObject->getRotationRegion();
1602		}
1603		std::vector<LLVector3>& child_positions = mObject->mUnselectedChildrenPositions ;
1604		std::vector<LLQuaternion> child_rotations;
1605		if (mObject->isRootEdit())
1606		{
1607			mObject->saveUnselectedChildrenRotation(child_rotations) ;
1608			mObject->saveUnselectedChildrenPosition(child_positions) ;			
1609		}
1610
1611		mObject->setRotation(rotation);
1612		LLManip::rebuild(mObject) ;
1613
1614		// for individually selected roots, we need to counterrotate all the children
1615		if (mObject->isRootEdit())
1616		{			
1617			mObject->resetChildrenRotationAndPosition(child_rotations, child_positions) ;			
1618		}
1619
1620		if(!btn_down)
1621		{
1622			child_positions.clear() ;
1623			LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
1624		}
1625	}
1626}
1627
1628
1629// BUG: Make work with multiple objects
1630void LLPanelObject::sendScale(BOOL btn_down)
1631{
1632	if (mObject.isNull()) return;
1633
1634	LLVector3 newscale(mCtrlScaleX->get(), mCtrlScaleY->get(), mCtrlScaleZ->get());
1635
1636	LLVector3 delta = newscale - mObject->getScale();
1637	if (delta.magVec() >= 0.0005f)
1638	{
1639		// scale changed by more than 1/2 millimeter
1640
1641		// check to see if we aren't scaling the textures
1642		// (in which case the tex coord's need to be recomputed)
1643		BOOL dont_stretch_textures = !LLManipScale::getStretchTextures();
1644		if (dont_stretch_textures)
1645		{
1646			LLSelectMgr::getInstance()->saveSelectedObjectTransform(SELECT_ACTION_TYPE_SCALE);
1647		}
1648
1649		mObject->setScale(newscale, TRUE);
1650
1651		if(!btn_down)
1652		{
1653			LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_SCALE | UPD_POSITION);
1654		}
1655
1656		LLSelectMgr::getInstance()->adjustTexturesByScale(TRUE, !dont_stretch_textures);
1657//		llinfos << "scale sent" << llendl;
1658	}
1659	else
1660	{
1661//		llinfos << "scale not changed" << llendl;
1662	}
1663}
1664
1665
1666void LLPanelObject::sendPosition(BOOL btn_down)
1667{	
1668	if (mObject.isNull()) return;
1669
1670	LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
1671	LLViewerRegion* regionp = mObject->getRegion();
1672
1673	// Clamp the Z height
1674	const F32 height = newpos.mV[VZ];
1675	const F32 min_height = LLWorld::getInstance()->getMinAllowedZ(mObject, mObject->getPositionGlobal());
1676	const F32 max_height = LLWorld::getInstance()->getRegionMaxHeight();
1677
1678	if (!mObject->isAttachment())
1679	{
1680		if ( height < min_height)
1681		{
1682			newpos.mV[VZ] = min_height;
1683			mCtrlPosZ->set( min_height );
1684		}
1685		else if ( height > max_height )
1686		{
1687			newpos.mV[VZ] = max_height;
1688			mCtrlPosZ->set( max_height );
1689		}
1690
1691		// Grass is always drawn on the ground, so clamp its position to the ground
1692		if (mObject->getPCode() == LL_PCODE_LEGACY_GRASS)
1693		{
1694			mCtrlPosZ->set(LLWorld::getInstance()->resolveLandHeightAgent(newpos) + 1.f);
1695		}
1696	}
1697
1698	// Make sure new position is in a valid region, so the object
1699	// won't get dumped by the simulator.
1700	LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos);
1701
1702	if ( LLWorld::getInstance()->positionRegionValidGlobal(new_pos_global) )
1703	{
1704		// send only if the position is changed, that is, the delta vector is not zero
1705		LLVector3d old_pos_global = mObject->getPositionGlobal();
1706		LLVector3d delta = new_pos_global - old_pos_global;
1707		// moved more than 1/2 millimeter
1708		if (delta.magVec() >= 0.0005f)
1709		{			
1710			if (mRootObject != mObject)
1711			{
1712				newpos = newpos - mRootObject->getPositionRegion();
1713				newpos = newpos * ~mRootObject->getRotationRegion();
1714				mObject->setPositionParent(newpos);
1715			}
1716			else
1717			{
1718				mObject->setPositionEdit(newpos);
1719			}			
1720			
1721			LLManip::rebuild(mObject) ;
1722
1723			// for individually selected roots, we need to counter-translate all unselected children
1724			if (mObject->isRootEdit())
1725			{								
1726				// only offset by parent's translation
1727				mObject->resetChildrenPosition(LLVector3(-delta), TRUE) ;				
1728			}
1729
1730			if(!btn_down)
1731			{
1732				LLSelectMgr::getInstance()->sendMultipleUpdate(UPD_POSITION);
1733			}
1734
1735			LLSelectMgr::getInstance()->updateSelectionCenter();
1736		}
1737	}
1738	else
1739	{
1740		// move failed, so we update the UI with the correct values
1741		LLVector3 vec = mRootObject->getPositionRegion();
1742		mCtrlPosX->set(vec.mV[VX]);
1743		mCtrlPosY->set(vec.mV[VY]);
1744		mCtrlPosZ->set(vec.mV[VZ]);
1745	}
1746}
1747
1748void LLPanelObject::sendSculpt()
1749{
1750	if (mObject.isNull())
1751		return;
1752	
1753	LLSculptParams sculpt_params;
1754
1755	if (mCtrlSculptTexture)
1756		sculpt_params.setSculptTexture(mCtrlSculptTexture->getImageAssetID());
1757
1758	U8 sculpt_type = 0;
1759	
1760	if (mCtrlSculptType)
1761		sculpt_type |= mCtrlSculptType->getValue().asInteger();
1762
1763	bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
1764
1765	if (mCtrlSculptMirror)
1766	{
1767		mCtrlSculptMirror->setEnabled(enabled ? TRUE : FALSE);
1768	}
1769	if (mCtrlSculptInvert)
1770	{
1771		mCtrlSculptInvert->setEnabled(enabled ? TRUE : FALSE);
1772	}
1773	
1774	if ((mCtrlSculptMirror) && (mCtrlSculptMirror->get()))
1775	

Large files files are truncated, but you can click here to view the full file