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