llpanelobject.cpp 60 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280
  1. /**
  2. * @file llpanelobject.cpp
  3. * @brief Object editing (position, scale, etc.) in the tools floater
  4. *
  5. * $LicenseInfo:firstyear=2001&license=viewergpl$
  6. *
  7. * Copyright (c) 2001-2009, Linden Research, Inc.
  8. *
  9. * Second Life Viewer Source Code
  10. * The source code in this file ("Source Code") is provided by Linden Lab
  11. * to you under the terms of the GNU General Public License, version 2.0
  12. * ("GPL"), unless you have obtained a separate licensing agreement
  13. * ("Other License"), formally executed by you and Linden Lab. Terms of
  14. * the GPL can be found in doc/GPL-license.txt in this distribution, or
  15. * online at http://secondlifegrid.net/programs/open_source/licensing/gplv2
  16. *
  17. * There are special exceptions to the terms and conditions of the GPL as
  18. * it is applied to this Source Code. View the full text of the exception
  19. * in the file doc/FLOSS-exception.txt in this software distribution, or
  20. * online at
  21. * http://secondlifegrid.net/programs/open_source/licensing/flossexception
  22. *
  23. * By copying, modifying or distributing this software, you acknowledge
  24. * that you have read and understood your obligations described above,
  25. * and agree to abide by those obligations.
  26. *
  27. * ALL LINDEN LAB SOURCE CODE IS PROVIDED "AS IS." LINDEN LAB MAKES NO
  28. * WARRANTIES, EXPRESS, IMPLIED OR OTHERWISE, REGARDING ITS ACCURACY,
  29. * COMPLETENESS OR PERFORMANCE.
  30. * $/LicenseInfo$
  31. */
  32. #include "llviewerprecompiledheaders.h"
  33. #include "llpanelobject.h"
  34. #include "llbutton.h"
  35. #include "llcheckboxctrl.h"
  36. #include "llcombobox.h"
  37. #include "lleconomy.h"
  38. #include "llnotifications.h"
  39. #include "llpermissionsflags.h"
  40. #include "llspinctrl.h"
  41. #include "lltextbox.h"
  42. #include "lluictrlfactory.h"
  43. #include "llagent.h"
  44. #include "llcolorswatch.h"
  45. #include "lldrawpool.h"
  46. #include "llfirstuse.h"
  47. #include "llmanipscale.h"
  48. #include "llpipeline.h"
  49. #include "hbpreprocessor.h" // For HBPreprocessor::evaluate()
  50. #include "llpreviewscript.h"
  51. #include "llselectmgr.h"
  52. #include "lltexturectrl.h"
  53. #include "lltool.h"
  54. #include "lltoolcomp.h"
  55. #include "lltoolmgr.h"
  56. #include "llviewercontrol.h"
  57. #include "llviewerobject.h"
  58. #include "llviewerregion.h"
  59. #include "llviewerwindow.h" // For LLPickInfo
  60. //MK
  61. #include "mkrlinterface.h"
  62. #include "llvoavatarself.h"
  63. //mk
  64. #include "llvovolume.h"
  65. #include "llworld.h"
  66. // Static variables for the object clipboard
  67. bool LLPanelObject::sSavedSizeValid = false;
  68. bool LLPanelObject::sSavedPosValid = false;
  69. bool LLPanelObject::sSavedRotValid = false;
  70. bool LLPanelObject::sSavedShapeValid = false;
  71. LLVector3 LLPanelObject::sSavedSize;
  72. LLVector3 LLPanelObject::sSavedPos;
  73. LLVector3 LLPanelObject::sSavedRot;
  74. LLVolumeParams LLPanelObject::sSavedShape;
  75. // Constants
  76. enum
  77. {
  78. MI_BOX,
  79. MI_CYLINDER,
  80. MI_PRISM,
  81. MI_SPHERE,
  82. MI_TORUS,
  83. MI_TUBE,
  84. MI_RING,
  85. MI_SCULPT,
  86. MI_NONE,
  87. MI_VOLUME_COUNT
  88. };
  89. enum
  90. {
  91. MI_HOLE_SAME,
  92. MI_HOLE_CIRCLE,
  93. MI_HOLE_SQUARE,
  94. MI_HOLE_TRIANGLE,
  95. MI_HOLE_COUNT
  96. };
  97. static std::string preprocess_math(const std::string& text)
  98. {
  99. std::string result = text;
  100. if (!HBPreprocessor::evaluate(result))
  101. {
  102. gNotifications.add("InvalidMathExpression");
  103. return text;
  104. }
  105. return result;
  106. }
  107. LLPanelObject::LLPanelObject(const std::string& name)
  108. : LLPanel(name),
  109. mIsTemporary(false),
  110. mIsPhantom(false),
  111. mSizeChanged(false),
  112. mSelectedType(MI_BOX),
  113. mSculptTextureRevert(LLUUID::null),
  114. mSculptTypeRevert(0)
  115. {
  116. }
  117. //virtual
  118. bool LLPanelObject::postBuild()
  119. {
  120. setMouseOpaque(false);
  121. mLabelSelectSingle = getChild<LLTextBox>("select_single");
  122. mLabelEditObject = getChild<LLTextBox>("edit_object");
  123. mButtonCopy = getChild<LLButton>("copy");
  124. mButtonCopy->setClickedCallback(onClickCopy, this);
  125. mButtonPaste = getChild<LLButton>("paste");
  126. mButtonPaste->setClickedCallback(onClickPaste, this);
  127. // Lock checkbox
  128. mCheckLock = getChild<LLCheckBoxCtrl>("checkbox locked");
  129. mCheckLock->setCommitCallback(onCommitLock);
  130. mCheckLock->setCallbackUserData(this);
  131. // Temporary checkbox
  132. mCheckTemporary = getChild<LLCheckBoxCtrl>("Temporary Checkbox Ctrl");
  133. mCheckTemporary->setCommitCallback(onCommitTemporary);
  134. mCheckTemporary->setCallbackUserData(this);
  135. // Phantom checkbox
  136. mCheckPhantom = getChild<LLCheckBoxCtrl>("Phantom Checkbox Ctrl");
  137. mCheckPhantom->setCommitCallback(onCommitPhantom);
  138. mCheckPhantom->setCallbackUserData(this);
  139. // Position
  140. mLabelPosition = getChild<LLTextBox>("label position");
  141. mCtrlPosX = getChild<LLSpinCtrl>("Pos X");
  142. mCtrlPosX->setCommitCallback(onCommitPosition);
  143. mCtrlPosX->setCallbackUserData(this);
  144. mCtrlPosX->setPrevalidate(LLLineEditor::prevalidateASCII);
  145. mCtrlPosX->setPreProcessCallback(preprocess_math);
  146. mCtrlPosY = getChild<LLSpinCtrl>("Pos Y");
  147. mCtrlPosY->setCommitCallback(onCommitPosition);
  148. mCtrlPosY->setCallbackUserData(this);
  149. mCtrlPosY->setPrevalidate(LLLineEditor::prevalidateASCII);
  150. mCtrlPosY->setPreProcessCallback(preprocess_math);
  151. mCtrlPosZ = getChild<LLSpinCtrl>("Pos Z");
  152. mCtrlPosZ->setCommitCallback(onCommitPosition);
  153. mCtrlPosZ->setCallbackUserData(this);
  154. mCtrlPosZ->setPrevalidate(LLLineEditor::prevalidateASCII);
  155. mCtrlPosZ->setPreProcessCallback(preprocess_math);
  156. mCheckCopyPos = getChild<LLCheckBoxCtrl>("paste_position");
  157. mCheckCopyPos->setCommitCallback(onCommitCopyPaste);
  158. mCheckCopyPos->setCallbackUserData(this);
  159. // Scale
  160. mLabelSize = getChild<LLTextBox>("label size");
  161. mCtrlScaleX = getChild<LLSpinCtrl>("Scale X");
  162. mCtrlScaleX->setCommitCallback(onCommitScale);
  163. mCtrlScaleX->setCallbackUserData(this);
  164. mCtrlScaleX->setPrevalidate(LLLineEditor::prevalidateASCII);
  165. mCtrlScaleX->setPreProcessCallback(preprocess_math);
  166. mCtrlScaleY = getChild<LLSpinCtrl>("Scale Y");
  167. mCtrlScaleY->setCommitCallback(onCommitScale);
  168. mCtrlScaleY->setCallbackUserData(this);
  169. mCtrlScaleY->setPrevalidate(LLLineEditor::prevalidateASCII);
  170. mCtrlScaleY->setPreProcessCallback(preprocess_math);
  171. mCtrlScaleZ = getChild<LLSpinCtrl>("Scale Z");
  172. mCtrlScaleZ->setCommitCallback(onCommitScale);
  173. mCtrlScaleZ->setCallbackUserData(this);
  174. mCtrlScaleZ->setPrevalidate(LLLineEditor::prevalidateASCII);
  175. mCtrlScaleZ->setPreProcessCallback(preprocess_math);
  176. mCheckCopySize = getChild<LLCheckBoxCtrl>("paste_size");
  177. mCheckCopySize->setCommitCallback(onCommitCopyPaste);
  178. mCheckCopySize->setCallbackUserData(this);
  179. // Rotation
  180. mLabelRotation = getChild<LLTextBox>("label rotation");
  181. mCtrlRotX = getChild<LLSpinCtrl>("Rot X");
  182. mCtrlRotX->setCommitCallback(onCommitRotation);
  183. mCtrlRotX->setCallbackUserData(this);
  184. mCtrlRotX->setPrevalidate(LLLineEditor::prevalidateASCII);
  185. mCtrlRotX->setPreProcessCallback(preprocess_math);
  186. mCtrlRotY = getChild<LLSpinCtrl>("Rot Y");
  187. mCtrlRotY->setCommitCallback(onCommitRotation);
  188. mCtrlRotY->setCallbackUserData(this);
  189. mCtrlRotY->setPrevalidate(LLLineEditor::prevalidateASCII);
  190. mCtrlRotY->setPreProcessCallback(preprocess_math);
  191. mCtrlRotZ = getChild<LLSpinCtrl>("Rot Z");
  192. mCtrlRotZ->setCommitCallback(onCommitRotation);
  193. mCtrlRotZ->setCallbackUserData(this);
  194. mCtrlRotZ->setPrevalidate(LLLineEditor::prevalidateASCII);
  195. mCtrlRotZ->setPreProcessCallback(preprocess_math);
  196. mCheckCopyRot = getChild<LLCheckBoxCtrl>("paste_rotation");
  197. mCheckCopyRot->setCommitCallback(onCommitCopyPaste);
  198. mCheckCopyRot->setCallbackUserData(this);
  199. mCheckCopyShape = getChild<LLCheckBoxCtrl>("paste_shape");
  200. mCheckCopyShape->setCommitCallback(onCommitCopyPaste);
  201. mCheckCopyShape->setCallbackUserData(this);
  202. // Base Type
  203. mLabelBaseType = getChild<LLTextBox>("label basetype");
  204. mComboBaseType = getChild<LLComboBox>("comboBaseType");
  205. mComboBaseType->setCommitCallback(onCommitParametric);
  206. mComboBaseType->setCallbackUserData(this);
  207. // Cut
  208. mLabelCut = getChild<LLTextBox>("text cut");
  209. mSpinCutBegin = getChild<LLSpinCtrl>("cut begin");
  210. mSpinCutBegin->setCommitCallback(onCommitParametric);
  211. mSpinCutBegin->setCallbackUserData(this);
  212. mSpinCutEnd = getChild<LLSpinCtrl>("cut end");
  213. mSpinCutEnd->setCommitCallback(onCommitParametric);
  214. mSpinCutEnd->setCallbackUserData(this);
  215. // Hollow / Skew
  216. mLabelHollow = getChild<LLTextBox>("text hollow");
  217. mLabelSkew = getChild<LLTextBox>("text skew");
  218. mSpinHollow = getChild<LLSpinCtrl>("Scale 1");
  219. mSpinHollow->setCommitCallback(onCommitParametric);
  220. mSpinHollow->setCallbackUserData(this);
  221. mSpinSkew = getChild<LLSpinCtrl>("Skew");
  222. mSpinSkew->setCommitCallback(onCommitParametric);
  223. mSpinSkew->setCallbackUserData(this);
  224. mLabelHollowShape = getChild<LLTextBox>("Hollow Shape");
  225. // Hole Type
  226. mComboHoleType = getChild<LLComboBox>("hole");
  227. mComboHoleType->setCommitCallback(onCommitParametric);
  228. mComboHoleType->setCallbackUserData(this);
  229. // Twist
  230. mLabelTwist = getChild<LLTextBox>("text twist");
  231. mSpinTwistBegin = getChild<LLSpinCtrl>("Twist Begin");
  232. mSpinTwistBegin->setCommitCallback(onCommitParametric);
  233. mSpinTwistBegin->setCallbackUserData(this);
  234. mSpinTwist = getChild<LLSpinCtrl>("Twist End");
  235. mSpinTwist->setCommitCallback(onCommitParametric);
  236. mSpinTwist->setCallbackUserData(this);
  237. // Scale
  238. mLabelScaleHole = getChild<LLTextBox>("scale_hole");
  239. mLabelScaleTaper = getChild<LLTextBox>("scale_taper");
  240. mSpinScaleX = getChild<LLSpinCtrl>("Taper Scale X");
  241. mSpinScaleX->setCommitCallback(onCommitParametric);
  242. mSpinScaleX->setCallbackUserData(this);
  243. mSpinScaleY = getChild<LLSpinCtrl>("Taper Scale Y");
  244. mSpinScaleY->setCommitCallback(onCommitParametric);
  245. mSpinScaleY->setCallbackUserData(this);
  246. // Shear
  247. mLabelShear = getChild<LLTextBox>("text topshear");
  248. mSpinShearX = getChild<LLSpinCtrl>("Shear X");
  249. mSpinShearX->setCommitCallback(onCommitParametric);
  250. mSpinShearX->setCallbackUserData(this);
  251. mSpinShearY = getChild<LLSpinCtrl>("Shear Y");
  252. mSpinShearY->setCommitCallback(onCommitParametric);
  253. mSpinShearY->setCallbackUserData(this);
  254. // Path / Profile
  255. mLabelAdvancedCut = getChild<LLTextBox>("advanced_cut");
  256. mLabelAdvancedDimple = getChild<LLTextBox>("advanced_dimple");
  257. mLabelAdvancedSlice = getChild<LLTextBox>("advanced_slice");
  258. mCtrlPathBegin = getChild<LLSpinCtrl>("Path Limit Begin");
  259. mCtrlPathBegin->setCommitCallback(onCommitParametric);
  260. mCtrlPathBegin->setCallbackUserData(this);
  261. mCtrlPathEnd = getChild<LLSpinCtrl>("Path Limit End");
  262. mCtrlPathEnd->setCommitCallback(onCommitParametric);
  263. mCtrlPathEnd->setCallbackUserData(this);
  264. // Taper
  265. mLabelTaper = getChild<LLTextBox>("text taper2");
  266. mSpinTaperX = getChild<LLSpinCtrl>("Taper X");
  267. mSpinTaperX->setCommitCallback(onCommitParametric);
  268. mSpinTaperX->setCallbackUserData(this);
  269. mSpinTaperY = getChild<LLSpinCtrl>("Taper Y");
  270. mSpinTaperY->setCommitCallback(onCommitParametric);
  271. mSpinTaperY->setCallbackUserData(this);
  272. // Radius Offset / Revolutions
  273. mLabelRadiusOffset = getChild<LLTextBox>("text radius delta");
  274. mLabelRevolutions = getChild<LLTextBox>("text revolutions");
  275. mSpinRadiusOffset = getChild<LLSpinCtrl>("Radius Offset");
  276. mSpinRadiusOffset->setCommitCallback(onCommitParametric);
  277. mSpinRadiusOffset->setCallbackUserData(this);
  278. mSpinRevolutions = getChild<LLSpinCtrl>("Revolutions");
  279. mSpinRevolutions->setCommitCallback(onCommitParametric);
  280. mSpinRevolutions->setCallbackUserData(this);
  281. // Sculpt
  282. mCtrlSculptTexture = getChild<LLTextureCtrl>("sculpt texture control");
  283. mCtrlSculptTexture->setDefaultImageAssetID(LLUUID(SCULPT_DEFAULT_TEXTURE));
  284. mCtrlSculptTexture->setCommitCallback(LLPanelObject::onCommitSculpt);
  285. mCtrlSculptTexture->setOnCancelCallback(LLPanelObject::onCancelSculpt);
  286. mCtrlSculptTexture->setOnSelectCallback(LLPanelObject::onSelectSculpt);
  287. mCtrlSculptTexture->setDropCallback(LLPanelObject::onDropSculpt);
  288. mCtrlSculptTexture->setCallbackUserData(this);
  289. // Don't allow (no copy) or (no transfer) textures to be selected during
  290. // immediate mode
  291. mCtrlSculptTexture->setImmediateFilterPermMask(PERM_COPY | PERM_TRANSFER);
  292. // Allow any texture to be used during non-immediate mode.
  293. mCtrlSculptTexture->setNonImmediateFilterPermMask(PERM_NONE);
  294. LLAggregatePermissions perms;
  295. if (gSelectMgr.selectGetAggregateTexturePermissions(perms))
  296. {
  297. bool can_copy =
  298. perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_EMPTY ||
  299. perms.getValue(PERM_COPY) == LLAggregatePermissions::AP_ALL;
  300. bool can_transfer =
  301. perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_EMPTY ||
  302. perms.getValue(PERM_TRANSFER) == LLAggregatePermissions::AP_ALL;
  303. mCtrlSculptTexture->setCanApplyImmediately(can_copy && can_transfer);
  304. }
  305. else
  306. {
  307. mCtrlSculptTexture->setCanApplyImmediately(false);
  308. }
  309. mLabelSculptType = getChild<LLTextBox>("label sculpt type");
  310. mCtrlSculptType = getChild<LLComboBox>("sculpt type control");
  311. mCtrlSculptType->setCommitCallback(onCommitSculptType);
  312. mCtrlSculptType->setCallbackUserData(this);
  313. mCtrlSculptMirror = getChild<LLCheckBoxCtrl>("sculpt mirror control");
  314. mCtrlSculptMirror->setCommitCallback(onCommitSculptType);
  315. mCtrlSculptMirror->setCallbackUserData(this);
  316. mCtrlSculptInvert = getChild<LLCheckBoxCtrl>("sculpt invert control");
  317. mCtrlSculptInvert->setCommitCallback(onCommitSculptType);
  318. mCtrlSculptInvert->setCallbackUserData(this);
  319. // Start with everyone disabled
  320. clearCtrls();
  321. return true;
  322. }
  323. void LLPanelObject::getState()
  324. {
  325. LLObjectSelectionHandle selection = gSelectMgr.getSelection();
  326. LLViewerObject* objectp = selection->getFirstRootObject();
  327. LLViewerObject* root_objectp = objectp;
  328. if (!objectp)
  329. {
  330. objectp = selection->getFirstObject();
  331. // *FIXME: should not we just keep the child ?
  332. if (objectp)
  333. {
  334. LLViewerObject* parentp = objectp->getRootEdit();
  335. if (parentp)
  336. {
  337. root_objectp = parentp;
  338. }
  339. else
  340. {
  341. root_objectp = objectp;
  342. }
  343. }
  344. }
  345. LLVOVolume* volobjp = NULL;
  346. if (objectp && objectp->getPCode() == LL_PCODE_VOLUME)
  347. {
  348. volobjp = (LLVOVolume*)objectp;
  349. }
  350. if (!objectp)
  351. {
  352. // Forfeit focus
  353. if (gFocusMgr.childHasKeyboardFocus(this))
  354. {
  355. gFocusMgr.setKeyboardFocus(NULL);
  356. }
  357. // Disable all text input fields
  358. clearCtrls();
  359. return;
  360. }
  361. static LLCachedControl<bool> debug_edited(gSavedSettings,
  362. "DebugEditedObject");
  363. if (debug_edited)
  364. {
  365. LLViewerObject::setDebugObjectId(objectp->getID());
  366. }
  367. static LLCachedControl<bool> edit_linked_parts(gSavedSettings,
  368. "EditLinkedParts");
  369. bool enable_move, enable_modify;
  370. gSelectMgr.selectGetEditMoveLinksetPermissions(enable_move, enable_modify);
  371. bool enable_scale = enable_modify;
  372. // Already accounts for children case, which needs permModify() as well:
  373. bool enable_rotate = enable_move;
  374. S32 selected_count = selection->getObjectCount();
  375. bool single_volume = selected_count == 1 &&
  376. gSelectMgr.selectionAllPCode(LL_PCODE_VOLUME);
  377. if (selection->getRootObjectCount() > 1)
  378. {
  379. enable_move = false;
  380. enable_scale = false;
  381. enable_rotate = false;
  382. }
  383. //MK
  384. // Cannot edit objects that we are sitting on, when sit-restricted
  385. if (gRLenabled &&
  386. (gRLInterface.mSittpMax < EXTREMUM || gRLInterface.mContainsUnsit) &&
  387. isAgentAvatarValid() && gAgentAvatarp->mIsSitting &&
  388. objectp->getRootEdit()->isAgentSeat())
  389. {
  390. enable_move = enable_scale = enable_rotate = false;
  391. }
  392. //mk
  393. bool is_attachment = objectp->isAttachment();
  394. if (is_attachment && (enable_move || enable_rotate) &&
  395. gSelectMgr.getGridMode() != 0)
  396. {
  397. // Position and rotation for attachments are always in given mode 0, so
  398. // disable the position and rotation spinners when another mode is in
  399. // force.
  400. enable_move = enable_rotate = false;
  401. }
  402. LLVector3 vec;
  403. if (enable_move)
  404. {
  405. if (is_attachment)
  406. {
  407. // Attachments Z (relative to avatar joint) can be negative !
  408. mCtrlPosZ->setMinValue(-mCtrlPosZ->getMaxValue());
  409. }
  410. else
  411. {
  412. // Normal objects cannot have a negative altitude
  413. mCtrlPosZ->setMinValue(0.f);
  414. }
  415. vec = objectp->getPositionEdit();
  416. mCtrlPosX->set(vec.mV[VX]);
  417. mCtrlPosY->set(vec.mV[VY]);
  418. mCtrlPosZ->set(vec.mV[VZ]);
  419. }
  420. else
  421. {
  422. mCtrlPosX->clear();
  423. mCtrlPosY->clear();
  424. mCtrlPosZ->clear();
  425. }
  426. mLabelPosition->setEnabled(enable_move);
  427. mCtrlPosX->setEnabled(enable_move);
  428. mCtrlPosY->setEnabled(enable_move);
  429. mCtrlPosZ->setEnabled(enable_move);
  430. mCheckCopyPos->setEnabled(enable_move);
  431. if (enable_scale)
  432. {
  433. vec = objectp->getScale();
  434. mCtrlScaleX->set(vec.mV[VX]);
  435. mCtrlScaleY->set(vec.mV[VY]);
  436. mCtrlScaleZ->set(vec.mV[VZ]);
  437. }
  438. else
  439. {
  440. mCtrlScaleX->clear();
  441. mCtrlScaleY->clear();
  442. mCtrlScaleZ->clear();
  443. }
  444. mLabelSize->setEnabled(enable_scale);
  445. mCtrlScaleX->setEnabled(enable_scale);
  446. mCtrlScaleY->setEnabled(enable_scale);
  447. mCtrlScaleZ->setEnabled(enable_scale);
  448. mCheckCopySize->setEnabled(enable_scale);
  449. LLQuaternion object_rot = objectp->getRotationEdit();
  450. object_rot.getEulerAngles(&(mCurEulerDegrees.mV[VX]),
  451. &(mCurEulerDegrees.mV[VY]),
  452. &(mCurEulerDegrees.mV[VZ]));
  453. mCurEulerDegrees *= RAD_TO_DEG;
  454. mCurEulerDegrees.mV[VX] = fmod(ll_round(mCurEulerDegrees.mV[VX],
  455. OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
  456. mCurEulerDegrees.mV[VY] = fmod(ll_round(mCurEulerDegrees.mV[VY],
  457. OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
  458. mCurEulerDegrees.mV[VZ] = fmod(ll_round(mCurEulerDegrees.mV[VZ],
  459. OBJECT_ROTATION_PRECISION) + 360.f, 360.f);
  460. if (enable_rotate)
  461. {
  462. mCtrlRotX->set(mCurEulerDegrees.mV[VX]);
  463. mCtrlRotY->set(mCurEulerDegrees.mV[VY]);
  464. mCtrlRotZ->set(mCurEulerDegrees.mV[VZ]);
  465. }
  466. else
  467. {
  468. mCtrlRotX->clear();
  469. mCtrlRotY->clear();
  470. mCtrlRotZ->clear();
  471. }
  472. mLabelRotation->setEnabled(enable_rotate);
  473. mCtrlRotX->setEnabled(enable_rotate);
  474. mCtrlRotY->setEnabled(enable_rotate);
  475. mCtrlRotZ->setEnabled(enable_rotate);
  476. mCheckCopyRot->setEnabled(enable_rotate);
  477. LLUUID owner_id;
  478. std::string owner_name;
  479. gSelectMgr.selectGetOwner(owner_id, owner_name);
  480. // BUG ? Check for all objects being editable ?
  481. S32 roots_selected = selection->getRootObjectCount();
  482. bool editable = root_objectp->permModify();
  483. // Select Single Message
  484. mLabelSelectSingle->setVisible(false);
  485. mLabelEditObject->setVisible(false);
  486. if (!editable || single_volume || selected_count <= 1)
  487. {
  488. mLabelEditObject->setVisible(true);
  489. mLabelEditObject->setEnabled(true);
  490. mCheckCopyShape->setVisible(true);
  491. }
  492. else
  493. {
  494. mLabelSelectSingle->setVisible(true);
  495. mLabelSelectSingle->setEnabled(true);
  496. mCheckCopyShape->setVisible(false);
  497. }
  498. bool is_permanent = root_objectp->flagObjectPermanent();
  499. bool is_permanent_enforced = root_objectp->isPermanentEnforced();
  500. bool is_character = root_objectp->flagCharacter();
  501. // Should never have a permanent object that is also a character
  502. if (is_permanent && is_character)
  503. {
  504. // *TODO: Pop up a one-time warning with object details
  505. llwarns << "PATHFINDING BUG: editing a Permanent object that is also a Character !"
  506. << llendl;
  507. }
  508. // Lock checkbox - only modifiable if you own the object.
  509. bool self_owned = (gAgentID == owner_id);
  510. mCheckLock->setEnabled(roots_selected > 0 && self_owned &&
  511. !is_permanent_enforced);
  512. // More lock and debit checkbox - get the values
  513. U32 owner_mask_on;
  514. U32 owner_mask_off;
  515. bool valid = gSelectMgr.selectGetPerm(PERM_OWNER,
  516. &owner_mask_on, &owner_mask_off);
  517. if (valid)
  518. {
  519. if (owner_mask_on & PERM_MOVE)
  520. {
  521. // Owner can move, so not locked
  522. mCheckLock->set(false);
  523. mCheckLock->setTentative(false);
  524. }
  525. else if (owner_mask_off & PERM_MOVE)
  526. {
  527. // Owner can't move, so locked
  528. mCheckLock->set(true);
  529. mCheckLock->setTentative(false);
  530. }
  531. else
  532. {
  533. // Some locked, some not locked
  534. mCheckLock->set(false);
  535. mCheckLock->setTentative(true);
  536. }
  537. }
  538. bool is_flexible = volobjp && volobjp->isFlexible();
  539. mIsTemporary = root_objectp->flagTemporaryOnRez();
  540. if (is_permanent && mIsTemporary)
  541. {
  542. // *TODO: Pop up a one-time warning with object details
  543. llwarns << "PATHFINDING BUG: editing a Permanent object that is also Temporary !"
  544. << llendl;
  545. }
  546. mCheckTemporary->set(mIsTemporary);
  547. mCheckTemporary->setEnabled(roots_selected > 0 && editable &&
  548. !is_permanent);
  549. mIsPhantom = root_objectp->flagPhantom();
  550. if (is_character && mIsPhantom)
  551. {
  552. // *TODO: Pop up a one-time warning with object details
  553. llwarns << "PATHFINDING BUG: editing a Character object that is also Phantom !"
  554. << llendl;
  555. }
  556. bool is_volume_detect = root_objectp->flagVolumeDetect();
  557. mCheckPhantom->set(mIsPhantom);
  558. mCheckPhantom->setEnabled(roots_selected > 0 && editable && !is_flexible &&
  559. !is_permanent_enforced && !is_character &&
  560. !is_volume_detect);
  561. S32 selected_item = MI_BOX;
  562. S32 selected_hole = MI_HOLE_SAME;
  563. bool enabled = false;
  564. bool hole_enabled = false;
  565. F32 scale_x = 1.f, scale_y = 1.f;
  566. if (!objectp || !objectp->getVolume() || !editable || !single_volume)
  567. {
  568. // Clear out all geometry fields.
  569. mComboBaseType->clear();
  570. mSpinHollow->clear();
  571. mSpinCutBegin->clear();
  572. mSpinCutEnd->clear();
  573. mCtrlPathBegin->clear();
  574. mCtrlPathEnd->clear();
  575. mSpinScaleX->clear();
  576. mSpinScaleY->clear();
  577. mSpinTwist->clear();
  578. mSpinTwistBegin->clear();
  579. mComboHoleType->clear();
  580. mSpinShearX->clear();
  581. mSpinShearY->clear();
  582. mSpinTaperX->clear();
  583. mSpinTaperY->clear();
  584. mSpinRadiusOffset->clear();
  585. mSpinRevolutions->clear();
  586. mSpinSkew->clear();
  587. mSelectedType = MI_NONE;
  588. }
  589. else
  590. {
  591. // Only allowed to change these parameters for objects that you have
  592. // permissions on AND are not attachments.
  593. enabled = root_objectp->permModify() &&
  594. !root_objectp->isPermanentEnforced();
  595. // Volume type
  596. const LLVolumeParams& volume_params =
  597. objectp->getVolume()->getParams();
  598. U8 path = volume_params.getPathParams().getCurveType();
  599. U8 profile_and_hole = volume_params.getProfileParams().getCurveType();
  600. U8 profile = profile_and_hole & LL_PCODE_PROFILE_MASK;
  601. U8 hole = profile_and_hole & LL_PCODE_HOLE_MASK;
  602. // Scale goes first so we can differentiate between a sphere and a
  603. // torus, which have the same profile and path types.
  604. // Scale
  605. scale_x = volume_params.getRatioX();
  606. scale_y = volume_params.getRatioY();
  607. bool linear_path = (path == LL_PCODE_PATH_LINE ||
  608. path == LL_PCODE_PATH_FLEXIBLE);
  609. if (linear_path && profile == LL_PCODE_PROFILE_CIRCLE)
  610. {
  611. selected_item = MI_CYLINDER;
  612. }
  613. else if (linear_path && profile == LL_PCODE_PROFILE_SQUARE)
  614. {
  615. selected_item = MI_BOX;
  616. }
  617. else if (linear_path && profile == LL_PCODE_PROFILE_ISOTRI)
  618. {
  619. selected_item = MI_PRISM;
  620. }
  621. else if (linear_path && profile == LL_PCODE_PROFILE_EQUALTRI)
  622. {
  623. selected_item = MI_PRISM;
  624. }
  625. else if (linear_path && profile == LL_PCODE_PROFILE_RIGHTTRI)
  626. {
  627. selected_item = MI_PRISM;
  628. }
  629. else if (path == LL_PCODE_PATH_FLEXIBLE) // shouldn't happen
  630. {
  631. selected_item = MI_CYLINDER; // reasonable default
  632. }
  633. else if (path == LL_PCODE_PATH_CIRCLE &&
  634. profile == LL_PCODE_PROFILE_CIRCLE && scale_y > 0.75f)
  635. {
  636. selected_item = MI_SPHERE;
  637. }
  638. else if (path == LL_PCODE_PATH_CIRCLE &&
  639. profile == LL_PCODE_PROFILE_CIRCLE && scale_y <= 0.75f)
  640. {
  641. selected_item = MI_TORUS;
  642. }
  643. else if (path == LL_PCODE_PATH_CIRCLE &&
  644. profile == LL_PCODE_PROFILE_CIRCLE_HALF)
  645. {
  646. selected_item = MI_SPHERE;
  647. }
  648. else if (path == LL_PCODE_PATH_CIRCLE2 &&
  649. profile == LL_PCODE_PROFILE_CIRCLE)
  650. {
  651. // Spirals are not supported. Make it into a sphere. JC
  652. selected_item = MI_SPHERE;
  653. }
  654. else if (path == LL_PCODE_PATH_CIRCLE &&
  655. profile == LL_PCODE_PROFILE_EQUALTRI)
  656. {
  657. selected_item = MI_RING;
  658. }
  659. else if (path == LL_PCODE_PATH_CIRCLE &&
  660. profile == LL_PCODE_PROFILE_SQUARE && scale_y <= 0.75f)
  661. {
  662. selected_item = MI_TUBE;
  663. }
  664. else
  665. {
  666. llwarns << "Unknown path " << (S32)path << " - profile "
  667. << (S32)profile << " in getState()" << llendl;
  668. selected_item = MI_BOX;
  669. }
  670. if (objectp->getParameterEntryInUse(LLNetworkData::PARAMS_SCULPT))
  671. {
  672. selected_item = MI_SCULPT;
  673. LLFirstUse::useSculptedPrim();
  674. }
  675. mComboBaseType->setCurrentByIndex(selected_item);
  676. mSelectedType = selected_item;
  677. // Grab S path
  678. F32 begin_s = volume_params.getBeginS();
  679. F32 end_s = volume_params.getEndS();
  680. // Compute cut and advanced cut from S and T
  681. F32 begin_t = volume_params.getBeginT();
  682. F32 end_t = volume_params.getEndT();
  683. // Hollowness
  684. F32 hollow = volume_params.getHollow();
  685. mSpinHollow->set(100.f * hollow);
  686. // All hollow objects allow a shape to be selected.
  687. if (hollow > 0.f)
  688. {
  689. switch (hole)
  690. {
  691. case LL_PCODE_HOLE_CIRCLE:
  692. selected_hole = MI_HOLE_CIRCLE;
  693. break;
  694. case LL_PCODE_HOLE_SQUARE:
  695. selected_hole = MI_HOLE_SQUARE;
  696. break;
  697. case LL_PCODE_HOLE_TRIANGLE:
  698. selected_hole = MI_HOLE_TRIANGLE;
  699. break;
  700. case LL_PCODE_HOLE_SAME:
  701. default:
  702. selected_hole = MI_HOLE_SAME;
  703. }
  704. mComboHoleType->setCurrentByIndex(selected_hole);
  705. hole_enabled = enabled;
  706. }
  707. else
  708. {
  709. mComboHoleType->setCurrentByIndex(MI_HOLE_SAME);
  710. hole_enabled = false;
  711. }
  712. // Cut interpretation varies based on base object type
  713. F32 cut_begin, cut_end, adv_cut_begin, adv_cut_end;
  714. if (selected_item == MI_SPHERE || selected_item == MI_TORUS ||
  715. selected_item == MI_TUBE || selected_item == MI_RING)
  716. {
  717. cut_begin = begin_t;
  718. cut_end = end_t;
  719. adv_cut_begin = begin_s;
  720. adv_cut_end = end_s;
  721. }
  722. else
  723. {
  724. cut_begin = begin_s;
  725. cut_end = end_s;
  726. adv_cut_begin = begin_t;
  727. adv_cut_end = end_t;
  728. }
  729. mSpinCutBegin->set(cut_begin);
  730. mSpinCutEnd->set(cut_end);
  731. mCtrlPathBegin->set(adv_cut_begin);
  732. mCtrlPathEnd->set(adv_cut_end);
  733. // Twist
  734. F32 twist = volume_params.getTwistEnd();
  735. F32 twist_begin = volume_params.getTwistBegin();
  736. // Check the path type for conversion.
  737. if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
  738. {
  739. twist *= OBJECT_TWIST_LINEAR_MAX;
  740. twist_begin *= OBJECT_TWIST_LINEAR_MAX;
  741. }
  742. else
  743. {
  744. twist *= OBJECT_TWIST_MAX;
  745. twist_begin *= OBJECT_TWIST_MAX;
  746. }
  747. mSpinTwist->set(twist);
  748. mSpinTwistBegin->set(twist_begin);
  749. // Shear
  750. F32 shear_x = volume_params.getShearX();
  751. F32 shear_y = volume_params.getShearY();
  752. mSpinShearX->set(shear_x);
  753. mSpinShearY->set(shear_y);
  754. // Taper
  755. F32 taper_x = volume_params.getTaperX();
  756. F32 taper_y = volume_params.getTaperY();
  757. mSpinTaperX->set(taper_x);
  758. mSpinTaperY->set(taper_y);
  759. // Radius offset.
  760. F32 radius_offset = volume_params.getRadiusOffset();
  761. // Limit radius offset, based on taper and hole size y.
  762. F32 radius_mag = fabs(radius_offset);
  763. F32 hole_y_mag = fabs(scale_y);
  764. F32 taper_y_mag = fabs(taper_y);
  765. // Check to see if the taper effects us.
  766. if ((radius_offset > 0.f && taper_y < 0.f) ||
  767. (radius_offset < 0.f && taper_y > 0.f))
  768. {
  769. // The taper does not help increase the radius offset range.
  770. taper_y_mag = 0.f;
  771. }
  772. F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) /
  773. (1.f - hole_y_mag);
  774. // Enforce the maximum magnitude.
  775. if (radius_mag > max_radius_mag)
  776. {
  777. // Check radius offset sign.
  778. if (radius_offset < 0.f)
  779. {
  780. radius_offset = -max_radius_mag;
  781. }
  782. else
  783. {
  784. radius_offset = max_radius_mag;
  785. }
  786. }
  787. mSpinRadiusOffset->set(radius_offset);
  788. // Revolutions
  789. F32 revolutions = volume_params.getRevolutions();
  790. mSpinRevolutions->set(revolutions);
  791. // Skew
  792. F32 skew = volume_params.getSkew();
  793. // Limit skew, based on revolutions hole size x.
  794. F32 skew_mag = fabs(skew);
  795. F32 min_skew_mag = 1.f - 1.f / (revolutions * scale_x + 1.f);
  796. // Discontinuity; A revolution of 1 allows skews below 0.5.
  797. if (fabsf(revolutions - 1.f) < 0.001f)
  798. {
  799. min_skew_mag = 0.f;
  800. }
  801. // Clip skew.
  802. if (skew_mag < min_skew_mag)
  803. {
  804. // Check skew sign.
  805. if (skew < 0.f)
  806. {
  807. skew = -min_skew_mag;
  808. }
  809. else
  810. {
  811. skew = min_skew_mag;
  812. }
  813. }
  814. mSpinSkew->set(skew);
  815. }
  816. // Compute control visibility, label names, and twist range.
  817. // Start with defaults.
  818. bool cut_visible = true;
  819. bool hollow_visible = true;
  820. bool top_size_x_visible = true;
  821. bool top_size_y_visible = true;
  822. bool top_shear_x_visible = true;
  823. bool top_shear_y_visible = true;
  824. bool twist_visible = true;
  825. bool advanced_cut_visible = false;
  826. bool taper_visible = false;
  827. bool skew_visible = false;
  828. bool radius_offset_visible = false;
  829. bool revolutions_visible = false;
  830. bool sculpt_texture_visible = false;
  831. F32 twist_min = OBJECT_TWIST_LINEAR_MIN;
  832. F32 twist_max = OBJECT_TWIST_LINEAR_MAX;
  833. F32 twist_inc = OBJECT_TWIST_LINEAR_INC;
  834. bool advanced_is_dimple = false;
  835. bool advanced_is_slice = false;
  836. bool size_is_hole = false;
  837. // Tune based on overall volume type
  838. switch (selected_item)
  839. {
  840. case MI_SPHERE:
  841. top_size_x_visible = false;
  842. top_size_y_visible = false;
  843. top_shear_x_visible = false;
  844. top_shear_y_visible = false;
  845. //twist_visible = false;
  846. advanced_cut_visible = true;
  847. advanced_is_dimple = true;
  848. twist_min = OBJECT_TWIST_MIN;
  849. twist_max = OBJECT_TWIST_MAX;
  850. twist_inc = OBJECT_TWIST_INC;
  851. break;
  852. case MI_TORUS:
  853. case MI_TUBE:
  854. case MI_RING:
  855. //top_size_x_visible = false;
  856. //top_size_y_visible = false;
  857. size_is_hole = true;
  858. skew_visible = true;
  859. advanced_cut_visible = true;
  860. taper_visible = true;
  861. radius_offset_visible = true;
  862. revolutions_visible = true;
  863. twist_min = OBJECT_TWIST_MIN;
  864. twist_max = OBJECT_TWIST_MAX;
  865. twist_inc = OBJECT_TWIST_INC;
  866. break;
  867. case MI_SCULPT:
  868. cut_visible = false;
  869. hollow_visible = false;
  870. twist_visible = false;
  871. top_size_x_visible = false;
  872. top_size_y_visible = false;
  873. top_shear_x_visible = false;
  874. top_shear_y_visible = false;
  875. skew_visible = false;
  876. advanced_cut_visible = false;
  877. taper_visible = false;
  878. radius_offset_visible = false;
  879. revolutions_visible = false;
  880. sculpt_texture_visible = true;
  881. break;
  882. case MI_BOX:
  883. advanced_cut_visible = true;
  884. advanced_is_slice = true;
  885. break;
  886. case MI_CYLINDER:
  887. advanced_cut_visible = true;
  888. advanced_is_slice = true;
  889. break;
  890. case MI_PRISM:
  891. advanced_cut_visible = true;
  892. advanced_is_slice = true;
  893. break;
  894. default:
  895. break;
  896. }
  897. // Check if we need to change top size/hole size params.
  898. switch (selected_item)
  899. {
  900. case MI_SPHERE:
  901. case MI_TORUS:
  902. case MI_TUBE:
  903. case MI_RING:
  904. mSpinScaleX->set(scale_x);
  905. mSpinScaleY->set(scale_y);
  906. mSpinScaleX->setMinValue(OBJECT_MIN_HOLE_SIZE);
  907. mSpinScaleX->setMaxValue(OBJECT_MAX_HOLE_SIZE_X);
  908. mSpinScaleY->setMinValue(OBJECT_MIN_HOLE_SIZE);
  909. mSpinScaleY->setMaxValue(OBJECT_MAX_HOLE_SIZE_Y);
  910. break;
  911. default:
  912. if (editable && single_volume)
  913. {
  914. mSpinScaleX->set(1.f - scale_x);
  915. mSpinScaleY->set(1.f - scale_y);
  916. mSpinScaleX->setMinValue(-1.f);
  917. mSpinScaleX->setMaxValue(1.f);
  918. mSpinScaleY->setMinValue(-1.f);
  919. mSpinScaleY->setMaxValue(1.f);
  920. }
  921. }
  922. // Check if we need to limit the hollow based on the hole type.
  923. if (selected_hole == MI_HOLE_SQUARE &&
  924. (selected_item == MI_CYLINDER || selected_item == MI_TORUS ||
  925. selected_item == MI_PRISM || selected_item == MI_RING ||
  926. selected_item == MI_SPHERE))
  927. {
  928. mSpinHollow->setMinValue(OBJECT_HOLLOW_MIN * 100.f);
  929. mSpinHollow->setMaxValue(OBJECT_HOLLOW_MAX_SQUARE * 100.f);
  930. }
  931. else
  932. {
  933. mSpinHollow->setMinValue(OBJECT_HOLLOW_MIN * 100.f);
  934. mSpinHollow->setMaxValue(OBJECT_HOLLOW_MAX * 100.f);
  935. }
  936. // Update field enablement
  937. mLabelBaseType->setEnabled(enabled);
  938. mComboBaseType->setEnabled(enabled);
  939. mLabelCut->setEnabled(enabled);
  940. mSpinCutBegin->setEnabled(enabled);
  941. mSpinCutEnd->setEnabled(enabled);
  942. mLabelHollow->setEnabled(enabled);
  943. mSpinHollow->setEnabled(enabled);
  944. mLabelHollowShape->setEnabled(hole_enabled);
  945. mComboHoleType->setEnabled(hole_enabled);
  946. mLabelTwist->setEnabled(enabled);
  947. mSpinTwist->setEnabled(enabled);
  948. mSpinTwistBegin->setEnabled(enabled);
  949. mLabelSkew->setEnabled(enabled);
  950. mSpinSkew->setEnabled(enabled);
  951. mLabelScaleHole->setVisible(false);
  952. mLabelScaleTaper->setVisible(false);
  953. if (top_size_x_visible || top_size_y_visible)
  954. {
  955. if (size_is_hole)
  956. {
  957. mLabelScaleHole->setVisible(true);
  958. mLabelScaleHole->setEnabled(enabled);
  959. }
  960. else
  961. {
  962. mLabelScaleTaper->setVisible(true);
  963. mLabelScaleTaper->setEnabled(enabled);
  964. }
  965. }
  966. mSpinScaleX->setEnabled(enabled);
  967. mSpinScaleY->setEnabled(enabled);
  968. mLabelShear->setEnabled(enabled);
  969. mSpinShearX->setEnabled(enabled);
  970. mSpinShearY->setEnabled(enabled);
  971. mLabelAdvancedCut->setVisible(false);
  972. mLabelAdvancedDimple->setVisible(false);
  973. mLabelAdvancedSlice->setVisible(false);
  974. if (advanced_cut_visible)
  975. {
  976. if (advanced_is_dimple)
  977. {
  978. mLabelAdvancedDimple->setVisible(true);
  979. mLabelAdvancedDimple->setEnabled(enabled);
  980. }
  981. else if (advanced_is_slice)
  982. {
  983. mLabelAdvancedSlice->setVisible(true);
  984. mLabelAdvancedSlice->setEnabled(enabled);
  985. }
  986. else
  987. {
  988. mLabelAdvancedCut->setVisible(true);
  989. mLabelAdvancedCut->setEnabled(enabled);
  990. }
  991. }
  992. mCtrlPathBegin->setEnabled(enabled);
  993. mCtrlPathEnd->setEnabled(enabled);
  994. mLabelTaper->setEnabled(enabled);
  995. mSpinTaperX->setEnabled(enabled);
  996. mSpinTaperY->setEnabled(enabled);
  997. mLabelRadiusOffset->setEnabled(enabled);
  998. mSpinRadiusOffset->setEnabled(enabled);
  999. mLabelRevolutions->setEnabled(enabled);
  1000. mSpinRevolutions->setEnabled(enabled);
  1001. mCheckCopyShape->setEnabled(enabled && mCheckCopyShape->getVisible());
  1002. // Update field visibility
  1003. mLabelCut->setVisible(cut_visible);
  1004. mSpinCutBegin->setVisible(cut_visible);
  1005. mSpinCutEnd->setVisible(cut_visible);
  1006. mLabelHollow->setVisible(hollow_visible);
  1007. mSpinHollow->setVisible(hollow_visible);
  1008. mLabelHollowShape->setVisible(hollow_visible);
  1009. mComboHoleType->setVisible(hollow_visible);
  1010. mLabelTwist->setVisible(twist_visible);
  1011. mSpinTwist->setVisible(twist_visible);
  1012. mSpinTwistBegin->setVisible(twist_visible);
  1013. mSpinTwist->setMinValue(twist_min);
  1014. mSpinTwist->setMaxValue(twist_max);
  1015. mSpinTwist->setIncrement(twist_inc);
  1016. mSpinTwistBegin->setMinValue(twist_min);
  1017. mSpinTwistBegin->setMaxValue(twist_max);
  1018. mSpinTwistBegin->setIncrement(twist_inc);
  1019. mSpinScaleX->setVisible(top_size_x_visible);
  1020. mSpinScaleY->setVisible(top_size_y_visible);
  1021. mLabelSkew->setVisible(skew_visible);
  1022. mSpinSkew->setVisible(skew_visible);
  1023. mLabelShear->setVisible(top_shear_x_visible || top_shear_y_visible);
  1024. mSpinShearX->setVisible(top_shear_x_visible);
  1025. mSpinShearY->setVisible(top_shear_y_visible);
  1026. mCtrlPathBegin->setVisible(advanced_cut_visible);
  1027. mCtrlPathEnd->setVisible(advanced_cut_visible);
  1028. mLabelTaper->setVisible(taper_visible);
  1029. mSpinTaperX->setVisible(taper_visible);
  1030. mSpinTaperY->setVisible(taper_visible);
  1031. mLabelRadiusOffset->setVisible(radius_offset_visible);
  1032. mSpinRadiusOffset->setVisible(radius_offset_visible);
  1033. mLabelRevolutions->setVisible(revolutions_visible);
  1034. mSpinRevolutions->setVisible(revolutions_visible);
  1035. // sculpt texture and parameters
  1036. bool is_mesh = false;
  1037. if (selected_item == MI_SCULPT)
  1038. {
  1039. LLUUID id;
  1040. const LLSculptParams* sculpt_params = objectp->getSculptParams();
  1041. if (sculpt_params)
  1042. {
  1043. // If we have a legal sculpt param block for this object:
  1044. if (mObject != objectp)
  1045. {
  1046. // We have just selected a new object, so save for undo
  1047. mSculptTextureRevert = sculpt_params->getSculptTexture();
  1048. mSculptTypeRevert = sculpt_params->getSculptType();
  1049. }
  1050. U8 sculpt_type = sculpt_params->getSculptType();
  1051. U8 sculpt_stitching = sculpt_type & LL_SCULPT_TYPE_MASK;
  1052. bool sculpt_invert = sculpt_type & LL_SCULPT_FLAG_INVERT;
  1053. bool sculpt_mirror = sculpt_type & LL_SCULPT_FLAG_MIRROR;
  1054. is_mesh = (sculpt_stitching == LL_SCULPT_TYPE_MESH);
  1055. mCtrlSculptTexture->setTentative(false);
  1056. mCtrlSculptTexture->setEnabled(editable && !is_mesh);
  1057. mCtrlSculptTexture->setImageAssetID(editable ? sculpt_params->getSculptTexture()
  1058. : LLUUID::null);
  1059. mComboBaseType->setEnabled(!is_mesh);
  1060. mCtrlSculptType->setCurrentByIndex(sculpt_stitching);
  1061. mCtrlSculptType->setEnabled(editable && !is_mesh);
  1062. mCtrlSculptMirror->set(sculpt_mirror);
  1063. mCtrlSculptMirror->setEnabled(editable && !is_mesh);
  1064. mCtrlSculptInvert->set(sculpt_invert);
  1065. mCtrlSculptInvert->setEnabled(editable && !is_mesh);
  1066. mLabelSculptType->setEnabled(!is_mesh);
  1067. }
  1068. }
  1069. else
  1070. {
  1071. mSculptTextureRevert.setNull();
  1072. }
  1073. mLabelSculptType->setVisible(sculpt_texture_visible && !is_mesh);
  1074. mCtrlSculptType->setVisible(sculpt_texture_visible && !is_mesh);
  1075. mCtrlSculptMirror->setVisible(sculpt_texture_visible && !is_mesh);
  1076. mCtrlSculptInvert->setVisible(sculpt_texture_visible && !is_mesh);
  1077. mCtrlSculptTexture->setVisible(sculpt_texture_visible && !is_mesh);
  1078. if (selected_item == MI_SCULPT)
  1079. {
  1080. mCheckCopyShape->setVisible(false);
  1081. }
  1082. setCopyPasteState();
  1083. mObject = objectp;
  1084. mRootObject = root_objectp;
  1085. }
  1086. void LLPanelObject::setCopyPasteState()
  1087. {
  1088. bool shape_enabled = mCheckCopyShape->getVisible() &&
  1089. mCheckCopyShape->getEnabled();
  1090. bool size_enabled = mCheckCopySize->getVisible() &&
  1091. mCheckCopySize->getEnabled();
  1092. bool pos_enabled = mCheckCopyPos->getVisible() &&
  1093. mCheckCopyPos->getEnabled();
  1094. bool rot_enabled = mCheckCopyRot->getVisible() &&
  1095. mCheckCopyRot->getEnabled();
  1096. mButtonCopy->setEnabled(shape_enabled || size_enabled ||
  1097. pos_enabled || rot_enabled);
  1098. bool shape_checked = shape_enabled && mCheckCopyShape->get();
  1099. bool size_checked = size_enabled && mCheckCopySize->get();
  1100. bool pos_checked = pos_enabled && mCheckCopyPos->get();
  1101. bool rot_checked = rot_enabled && mCheckCopyRot->get();
  1102. bool can_paste = (shape_checked && sSavedShapeValid) ||
  1103. (size_checked && sSavedSizeValid) ||
  1104. (pos_checked && sSavedPosValid) ||
  1105. (rot_checked && sSavedRotValid);
  1106. if (!sSavedShapeValid && shape_checked) can_paste = false;
  1107. if (!sSavedSizeValid && size_checked) can_paste = false;
  1108. if (!sSavedPosValid && pos_checked) can_paste = false;
  1109. if (!sSavedRotValid && rot_checked) can_paste = false;
  1110. mButtonPaste->setEnabled(can_paste);
  1111. }
  1112. void LLPanelObject::sendIsTemporary()
  1113. {
  1114. bool value = mCheckTemporary->get();
  1115. if (mIsTemporary != value)
  1116. {
  1117. gSelectMgr.selectionUpdateTemporary(value);
  1118. mIsTemporary = value;
  1119. llinfos << "Update temporary state sent" << llendl;
  1120. }
  1121. }
  1122. void LLPanelObject::sendIsPhantom()
  1123. {
  1124. bool value = mCheckPhantom->get();
  1125. if (mIsPhantom != value)
  1126. {
  1127. gSelectMgr.selectionUpdatePhantom(value);
  1128. mIsPhantom = value;
  1129. llinfos << "Update phantom sent" << llendl;
  1130. }
  1131. }
  1132. //static
  1133. void LLPanelObject::onCommitParametric(LLUICtrl* ctrl, void* userdata)
  1134. {
  1135. LLPanelObject* self = (LLPanelObject*)userdata;
  1136. if (!self) return;
  1137. if (self->mObject.isNull())
  1138. {
  1139. return;
  1140. }
  1141. if (self->mObject->getPCode() != LL_PCODE_VOLUME)
  1142. {
  1143. // Do not allow modification of non-volume objects.
  1144. return;
  1145. }
  1146. LLVolume *volume = self->mObject->getVolume();
  1147. if (!volume)
  1148. {
  1149. return;
  1150. }
  1151. LLVolumeParams volume_params;
  1152. self->getVolumeParams(volume_params);
  1153. // Set sculpting
  1154. S32 selected_type = self->mComboBaseType->getCurrentIndex();
  1155. if (selected_type == MI_SCULPT)
  1156. {
  1157. self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT,
  1158. true, true);
  1159. const LLSculptParams* sculpt_params = self->mObject->getSculptParams();
  1160. if (sculpt_params)
  1161. {
  1162. volume_params.setSculptID(sculpt_params->getSculptTexture(),
  1163. sculpt_params->getSculptType());
  1164. }
  1165. }
  1166. else
  1167. {
  1168. const LLSculptParams* sculpt_params = self->mObject->getSculptParams();
  1169. if (sculpt_params)
  1170. {
  1171. self->mObject->setParameterEntryInUse(LLNetworkData::PARAMS_SCULPT,
  1172. false, true);
  1173. }
  1174. }
  1175. // Update the volume, if necessary.
  1176. self->mObject->updateVolume(volume_params);
  1177. // This was added to make sure thate when changes are made, the UI adjusts
  1178. // to present valid options. *FIX: only some changes, ie, hollow or
  1179. // primitive type changes, require a refresh.
  1180. self->refresh();
  1181. }
  1182. void LLPanelObject::getVolumeParams(LLVolumeParams& volume_params)
  1183. {
  1184. // Figure out what type of volume to make
  1185. S32 was_selected_type = mSelectedType;
  1186. S32 selected_type = mComboBaseType->getCurrentIndex();
  1187. U8 profile;
  1188. U8 path;
  1189. switch (selected_type)
  1190. {
  1191. case MI_CYLINDER:
  1192. profile = LL_PCODE_PROFILE_CIRCLE;
  1193. path = LL_PCODE_PATH_LINE;
  1194. break;
  1195. case MI_BOX:
  1196. profile = LL_PCODE_PROFILE_SQUARE;
  1197. path = LL_PCODE_PATH_LINE;
  1198. break;
  1199. case MI_PRISM:
  1200. profile = LL_PCODE_PROFILE_EQUALTRI;
  1201. path = LL_PCODE_PATH_LINE;
  1202. break;
  1203. case MI_SPHERE:
  1204. profile = LL_PCODE_PROFILE_CIRCLE_HALF;
  1205. path = LL_PCODE_PATH_CIRCLE;
  1206. break;
  1207. case MI_TORUS:
  1208. profile = LL_PCODE_PROFILE_CIRCLE;
  1209. path = LL_PCODE_PATH_CIRCLE;
  1210. break;
  1211. case MI_TUBE:
  1212. profile = LL_PCODE_PROFILE_SQUARE;
  1213. path = LL_PCODE_PATH_CIRCLE;
  1214. break;
  1215. case MI_RING:
  1216. profile = LL_PCODE_PROFILE_EQUALTRI;
  1217. path = LL_PCODE_PATH_CIRCLE;
  1218. break;
  1219. case MI_SCULPT:
  1220. profile = LL_PCODE_PROFILE_CIRCLE;
  1221. path = LL_PCODE_PATH_CIRCLE;
  1222. break;
  1223. default:
  1224. llwarns << "Unknown base type " << selected_type
  1225. << " in getVolumeParams()" << llendl;
  1226. // assume a box
  1227. selected_type = MI_BOX;
  1228. profile = LL_PCODE_PROFILE_SQUARE;
  1229. path = LL_PCODE_PATH_LINE;
  1230. break;
  1231. }
  1232. if (path == LL_PCODE_PATH_LINE)
  1233. {
  1234. LLVOVolume* volobjp = (LLVOVolume*)((LLViewerObject*)mObject);
  1235. if (volobjp && volobjp->isFlexible())
  1236. {
  1237. path = LL_PCODE_PATH_FLEXIBLE;
  1238. }
  1239. }
  1240. S32 selected_hole = mComboHoleType->getCurrentIndex();
  1241. U8 hole;
  1242. switch (selected_hole)
  1243. {
  1244. case MI_HOLE_CIRCLE:
  1245. hole = LL_PCODE_HOLE_CIRCLE;
  1246. break;
  1247. case MI_HOLE_SQUARE:
  1248. hole = LL_PCODE_HOLE_SQUARE;
  1249. break;
  1250. case MI_HOLE_TRIANGLE:
  1251. hole = LL_PCODE_HOLE_TRIANGLE;
  1252. break;
  1253. case MI_HOLE_SAME:
  1254. default:
  1255. hole = LL_PCODE_HOLE_SAME;
  1256. break;
  1257. }
  1258. volume_params.setType(profile | hole, path);
  1259. mSelectedType = selected_type;
  1260. // Compute cut start/end
  1261. F32 cut_begin = mSpinCutBegin->get();
  1262. F32 cut_end = mSpinCutEnd->get();
  1263. // Make sure at least OBJECT_CUT_INC of the object survives
  1264. if (cut_begin > cut_end - OBJECT_MIN_CUT_INC)
  1265. {
  1266. cut_begin = cut_end - OBJECT_MIN_CUT_INC;
  1267. mSpinCutBegin->set(cut_begin);
  1268. }
  1269. F32 adv_cut_begin = mCtrlPathBegin->get();
  1270. F32 adv_cut_end = mCtrlPathEnd->get();
  1271. // Make sure at least OBJECT_CUT_INC of the object survives
  1272. if (adv_cut_begin > adv_cut_end - OBJECT_MIN_CUT_INC)
  1273. {
  1274. adv_cut_begin = adv_cut_end - OBJECT_MIN_CUT_INC;
  1275. mCtrlPathBegin->set(adv_cut_begin);
  1276. }
  1277. F32 begin_s, end_s;
  1278. F32 begin_t, end_t;
  1279. if (selected_type == MI_SPHERE || selected_type == MI_TORUS ||
  1280. selected_type == MI_TUBE || selected_type == MI_RING)
  1281. {
  1282. begin_s = adv_cut_begin;
  1283. end_s = adv_cut_end;
  1284. begin_t = cut_begin;
  1285. end_t = cut_end;
  1286. }
  1287. else
  1288. {
  1289. begin_s = cut_begin;
  1290. end_s = cut_end;
  1291. begin_t = adv_cut_begin;
  1292. end_t = adv_cut_end;
  1293. }
  1294. volume_params.setBeginAndEndS(begin_s, end_s);
  1295. volume_params.setBeginAndEndT(begin_t, end_t);
  1296. // Hollowness
  1297. F32 hollow = mSpinHollow->get() / 100.f;
  1298. if (hollow > 0.7f && selected_hole == MI_HOLE_SQUARE &&
  1299. (selected_type == MI_CYLINDER || selected_type == MI_TORUS ||
  1300. selected_type == MI_PRISM || selected_type == MI_RING ||
  1301. selected_type == MI_SPHERE))
  1302. {
  1303. hollow = 0.7f;
  1304. }
  1305. volume_params.setHollow(hollow);
  1306. // Twist Begin,End
  1307. F32 twist_begin = mSpinTwistBegin->get();
  1308. F32 twist = mSpinTwist->get();
  1309. // Check the path type for twist conversion.
  1310. if (path == LL_PCODE_PATH_LINE || path == LL_PCODE_PATH_FLEXIBLE)
  1311. {
  1312. constexpr F32 linear_factor = 1.f / OBJECT_TWIST_LINEAR_MAX;
  1313. twist_begin *= linear_factor;
  1314. twist *= linear_factor;
  1315. }
  1316. else
  1317. {
  1318. constexpr F32 factor = 1.f / OBJECT_TWIST_MAX;
  1319. twist_begin *= factor;
  1320. twist *= factor;
  1321. }
  1322. volume_params.setTwistBegin(twist_begin);
  1323. volume_params.setTwistEnd(twist);
  1324. // Scale X,Y
  1325. F32 scale_x = mSpinScaleX->get();
  1326. F32 scale_y = mSpinScaleY->get();
  1327. if (was_selected_type == MI_BOX || was_selected_type == MI_CYLINDER ||
  1328. was_selected_type == MI_PRISM)
  1329. {
  1330. scale_x = 1.f - scale_x;
  1331. scale_y = 1.f - scale_y;
  1332. }
  1333. // Skew
  1334. F32 skew = mSpinSkew->get();
  1335. // Taper X,Y
  1336. F32 taper_x = mSpinTaperX->get();
  1337. F32 taper_y = mSpinTaperY->get();
  1338. // Radius offset
  1339. F32 radius_offset = mSpinRadiusOffset->get();
  1340. // Revolutions
  1341. F32 revolutions = mSpinRevolutions->get();
  1342. if (selected_type == MI_SPHERE)
  1343. {
  1344. // Snap values to valid sphere parameters.
  1345. scale_x = 1.f;
  1346. scale_y = 1.f;
  1347. skew = 0.f;
  1348. taper_x = 0.f;
  1349. taper_y = 0.f;
  1350. radius_offset = 0.f;
  1351. revolutions = 1.f;
  1352. }
  1353. else if (selected_type == MI_TORUS || selected_type == MI_TUBE ||
  1354. selected_type == MI_RING)
  1355. {
  1356. scale_x = llclamp(scale_x, OBJECT_MIN_HOLE_SIZE, OBJECT_MAX_HOLE_SIZE_X);
  1357. scale_y = llclamp(scale_y, OBJECT_MIN_HOLE_SIZE, OBJECT_MAX_HOLE_SIZE_Y);
  1358. // Limit radius offset, based on taper and hole size y.
  1359. F32 radius_mag = fabs(radius_offset);
  1360. F32 hole_y_mag = fabs(scale_y);
  1361. F32 taper_y_mag = fabs(taper_y);
  1362. // Check to see if the taper effects us.
  1363. if ((radius_offset > 0.f && taper_y < 0.f) ||
  1364. (radius_offset < 0.f && taper_y > 0.f))
  1365. {
  1366. // The taper does not help increase the radius offset range.
  1367. taper_y_mag = 0.f;
  1368. }
  1369. F32 max_radius_mag = 1.f - hole_y_mag * (1.f - taper_y_mag) /
  1370. (1.f - hole_y_mag);
  1371. // Enforce the maximum magnitude.
  1372. if (radius_mag > max_radius_mag)
  1373. {
  1374. // Check radius offset sign.
  1375. if (radius_offset < 0.f)
  1376. {
  1377. radius_offset = -max_radius_mag;
  1378. }
  1379. else
  1380. {
  1381. radius_offset = max_radius_mag;
  1382. }
  1383. }
  1384. // Check the skew value against the revolutions.
  1385. F32 skew_mag= fabs(skew);
  1386. F32 min_skew_mag = 1.f - 1.f / (revolutions * scale_x + 1.f);
  1387. // Discontinuity; A revolution of 1 allows skews below 0.5.
  1388. if (fabsf(revolutions - 1.f) < 0.001f)
  1389. {
  1390. min_skew_mag = 0.f;
  1391. }
  1392. // Clip skew.
  1393. if (skew_mag < min_skew_mag)
  1394. {
  1395. // Check skew sign.
  1396. if (skew < 0.f)
  1397. {
  1398. skew = -min_skew_mag;
  1399. }
  1400. else
  1401. {
  1402. skew = min_skew_mag;
  1403. }
  1404. }
  1405. }
  1406. volume_params.setRatio(scale_x, scale_y);
  1407. volume_params.setSkew(skew);
  1408. volume_params.setTaper(taper_x, taper_y);
  1409. volume_params.setRadiusOffset(radius_offset);
  1410. volume_params.setRevolutions(revolutions);
  1411. // Shear X,Y
  1412. F32 shear_x = mSpinShearX->get();
  1413. F32 shear_y = mSpinShearY->get();
  1414. volume_params.setShear(shear_x, shear_y);
  1415. if (selected_type == MI_SCULPT)
  1416. {
  1417. volume_params.setSculptID(LLUUID::null, 0);
  1418. volume_params.setBeginAndEndT(0.f, 1.f);
  1419. volume_params.setBeginAndEndS(0.f, 1.f);
  1420. volume_params.setHollow(0.f);
  1421. volume_params.setTwistBegin(0.f);
  1422. volume_params.setTwistEnd(0.f);
  1423. volume_params.setRatio(1.f, 0.5f);
  1424. volume_params.setShear(0.f, 0.f);
  1425. volume_params.setTaper(0.f, 0.f);
  1426. volume_params.setRevolutions(1.f);
  1427. volume_params.setRadiusOffset(0.f);
  1428. volume_params.setSkew(0.f);
  1429. }
  1430. }
  1431. // *FIXME: make it work with multiple objects
  1432. void LLPanelObject::sendRotation(bool btn_down)
  1433. {
  1434. if (mObject.isNull()) return;
  1435. LLVector3 new_rot(mCtrlRotX->get(), mCtrlRotY->get(), mCtrlRotZ->get());
  1436. new_rot.mV[VX] = ll_round(new_rot.mV[VX], OBJECT_ROTATION_PRECISION);
  1437. new_rot.mV[VY] = ll_round(new_rot.mV[VY], OBJECT_ROTATION_PRECISION);
  1438. new_rot.mV[VZ] = ll_round(new_rot.mV[VZ], OBJECT_ROTATION_PRECISION);
  1439. // Note: must compare before conversion to radians
  1440. LLVector3 delta = new_rot - mCurEulerDegrees;
  1441. if (delta.length() >= 0.00001f)
  1442. {
  1443. mCurEulerDegrees = new_rot;
  1444. new_rot *= DEG_TO_RAD;
  1445. LLQuaternion rotation;
  1446. rotation.setEulerAngles(new_rot.mV[VX], new_rot.mV[VY],
  1447. new_rot.mV[VZ]);
  1448. if (mRootObject != mObject)
  1449. {
  1450. rotation = rotation * ~mRootObject->getRotationRegion();
  1451. }
  1452. // To include avatars into movements and rotation.
  1453. // If false, all children are selected anyway, so move avatar.
  1454. // If true, not all children are selected: save positions.
  1455. static LLCachedControl<bool> edit_linked_parts(gSavedSettings,
  1456. "EditLinkedParts");
  1457. std::vector<LLVector3>& child_positions =
  1458. mObject->mUnselectedChildrenPositions;
  1459. std::vector<LLQuaternion> child_rotations;
  1460. if (mObject->isRootEdit() && edit_linked_parts)
  1461. {
  1462. mObject->saveUnselectedChildrenRotation(child_rotations);
  1463. mObject->saveUnselectedChildrenPosition(child_positions);
  1464. }
  1465. mObject->setRotation(rotation);
  1466. LLManip::rebuild(mObject);
  1467. // For individually selected roots, we need to counterrotate all the
  1468. // children
  1469. if (mObject->isRootEdit() && edit_linked_parts)
  1470. {
  1471. mObject->resetChildrenRotationAndPosition(child_rotations,
  1472. child_positions);
  1473. }
  1474. if (!btn_down)
  1475. {
  1476. child_positions.clear();
  1477. gSelectMgr.sendMultipleUpdate(UPD_ROTATION | UPD_POSITION);
  1478. }
  1479. }
  1480. }
  1481. // *FIXME: make it work with multiple objects
  1482. void LLPanelObject::sendScale(bool btn_down)
  1483. {
  1484. if (mObject.isNull()) return;
  1485. LLVector3 newscale(mCtrlScaleX->get(), mCtrlScaleY->get(),
  1486. mCtrlScaleZ->get());
  1487. LLVector3 delta = newscale - mObject->getScale();
  1488. if (delta.length() >= 0.00001f || (mSizeChanged && !btn_down))
  1489. {
  1490. // Scale changed by more than 1/2 millimeter
  1491. mSizeChanged = btn_down;
  1492. // Check to see if we are not scaling the textures (in which case the
  1493. // tex coords need to be recomputed)
  1494. bool dont_stretch_textures = !LLManipScale::getStretchTextures();
  1495. if (dont_stretch_textures)
  1496. {
  1497. gSelectMgr.saveSelectedObjectTransform(SELECT_ACTION_TYPE_SCALE);
  1498. }
  1499. mObject->setScale(newscale, true);
  1500. if (!btn_down)
  1501. {
  1502. gSelectMgr.sendMultipleUpdate(UPD_SCALE | UPD_POSITION);
  1503. }
  1504. gSelectMgr.adjustTexturesByScale(true, !dont_stretch_textures);
  1505. }
  1506. }
  1507. void LLPanelObject::sendPosition(bool btn_down)
  1508. {
  1509. if (mObject.isNull()) return;
  1510. LLVector3 newpos(mCtrlPosX->get(), mCtrlPosY->get(), mCtrlPosZ->get());
  1511. LLViewerRegion* regionp = mObject->getRegion();
  1512. bool is_attachment = mObject->isAttachment();
  1513. if (is_attachment)
  1514. {
  1515. if (newpos.length() > MAX_ATTACHMENT_DIST)
  1516. {
  1517. newpos.clampLength(MAX_ATTACHMENT_DIST);
  1518. mCtrlPosX->set(newpos.mV[VX]);
  1519. mCtrlPosY->set(newpos.mV[VY]);
  1520. mCtrlPosZ->set(newpos.mV[VZ]);
  1521. }
  1522. }
  1523. else
  1524. {
  1525. // Clamp the Z height
  1526. const F32 height = newpos.mV[VZ];
  1527. const F32 min_height = gWorld.getMinAllowedZ(mObject);
  1528. constexpr F32 max_height = MAX_OBJECT_Z;
  1529. if (height < min_height)
  1530. {
  1531. newpos.mV[VZ] = min_height;
  1532. mCtrlPosZ->set(min_height);
  1533. }
  1534. else if (height > max_height)
  1535. {
  1536. newpos.mV[VZ] = max_height;
  1537. mCtrlPosZ->set(max_height);
  1538. }
  1539. // Grass is always drawn on the ground, so clamp its position to the
  1540. // ground
  1541. if (mObject->getPCode() == LL_PCODE_LEGACY_GRASS)
  1542. {
  1543. mCtrlPosZ->set(gWorld.resolveLandHeightAgent(newpos) + 1.f);
  1544. }
  1545. }
  1546. // Make sure new position is in a valid region, so the object would not get
  1547. // dumped by the simulator.
  1548. LLVector3d new_pos_global = regionp->getPosGlobalFromRegion(newpos);
  1549. bool is_valid_pos;
  1550. if (is_attachment)
  1551. {
  1552. LLVector3 delta_pos = mObject->getPositionEdit() - newpos;
  1553. LLVector3d attachment_pos =
  1554. regionp->getPosGlobalFromRegion(mObject->getPositionRegion() +
  1555. delta_pos);
  1556. is_valid_pos = gWorld.positionRegionValidGlobal(attachment_pos);
  1557. }
  1558. else
  1559. {
  1560. is_valid_pos = gWorld.positionRegionValidGlobal(new_pos_global);
  1561. }
  1562. if (is_valid_pos)
  1563. {
  1564. // Send only if the position is changed, that is, the delta vector is
  1565. // not zero
  1566. LLVector3d old_pos_global = mObject->getPositionGlobal();
  1567. LLVector3d delta = new_pos_global - old_pos_global;
  1568. // Moved more than 1/2 millimeter
  1569. if (delta.length() >= 0.00001f)
  1570. {
  1571. if (mRootObject != mObject)
  1572. {
  1573. newpos = newpos - mRootObject->getPositionRegion();
  1574. newpos = newpos * ~mRootObject->getRotationRegion();
  1575. mObject->setPositionParent(newpos);
  1576. }
  1577. else
  1578. {
  1579. mObject->setPositionEdit(newpos);
  1580. }
  1581. LLManip::rebuild(mObject);
  1582. // For individually selected roots, we need to counter-translate
  1583. // all unselected children
  1584. if (mObject->isRootEdit())
  1585. {
  1586. // Only offset by parent's translation
  1587. mObject->resetChildrenPosition(LLVector3(-delta), true, true);
  1588. }
  1589. if (!btn_down)
  1590. {
  1591. gSelectMgr.sendMultipleUpdate(UPD_POSITION);
  1592. }
  1593. gSelectMgr.updateSelectionCenter();
  1594. }
  1595. }
  1596. else
  1597. {
  1598. // Move failed, so we update the UI with the correct values
  1599. LLVector3 vec = mRootObject->getPositionRegion();
  1600. mCtrlPosX->set(vec.mV[VX]);
  1601. mCtrlPosY->set(vec.mV[VY]);
  1602. mCtrlPosZ->set(vec.mV[VZ]);
  1603. }
  1604. }
  1605. void LLPanelObject::sendSculpt()
  1606. {
  1607. if (mObject.isNull())
  1608. {
  1609. return;
  1610. }
  1611. const LLUUID& sculpt_id = mCtrlSculptTexture->getImageAssetID();
  1612. U8 sculpt_type = 0;
  1613. sculpt_type |= mCtrlSculptType->getCurrentIndex();
  1614. bool enabled = sculpt_type != LL_SCULPT_TYPE_MESH;
  1615. mCtrlSculptMirror->setEnabled(enabled);
  1616. if (mCtrlSculptMirror->get())
  1617. {
  1618. sculpt_type |= LL_SCULPT_FLAG_MIRROR;
  1619. }
  1620. mCtrlSculptInvert->setEnabled(enabled);
  1621. if (mCtrlSculptInvert->get())
  1622. {
  1623. sculpt_type |= LL_SCULPT_FLAG_INVERT;
  1624. }
  1625. LLSculptParams sculpt_params;
  1626. sculpt_params.setSculptTexture(sculpt_id, sculpt_type);
  1627. mObject->setParameterEntry(LLNetworkData::PARAMS_SCULPT, sculpt_params,
  1628. true);
  1629. }
  1630. //virtual
  1631. void LLPanelObject::refresh()
  1632. {
  1633. getState();
  1634. if (mObject.notNull() && mObject->isDead())
  1635. {
  1636. mObject = NULL;
  1637. }
  1638. if (mRootObject.notNull() && mRootObject->isDead())
  1639. {
  1640. mRootObject = NULL;
  1641. }
  1642. if (mObject)
  1643. {
  1644. bool is_flora = LLPickInfo::isFlora(mObject);
  1645. F32 max_scale = LLManipScale::maxPrimScale(is_flora);
  1646. mCtrlScaleX->setMaxValue(max_scale);
  1647. mCtrlScaleY->setMaxValue(max_scale);
  1648. mCtrlScaleZ->setMaxValue(max_scale);
  1649. F32 min_scale = LLManipScale::minPrimScale(is_flora);
  1650. mCtrlScaleX->setMinValue(min_scale);
  1651. mCtrlScaleY->setMinValue(min_scale);
  1652. mCtrlScaleZ->setMinValue(min_scale);
  1653. }
  1654. }
  1655. //virtual
  1656. void LLPanelObject::draw()
  1657. {
  1658. static const LLColor4 white(1.f, 1.f, 1.f, 1.f);
  1659. static const LLColor4 red(1.f, 0.25f, 0.f, 1.f);
  1660. static const LLColor4 green(0.f, 1.f, 0.f, 1.f);
  1661. static const LLColor4 blue(0.f, 0.5f, 1.f, 1.f);
  1662. // Tune the colors of the labels
  1663. LLTool* tool = gToolMgr.getCurrentTool();
  1664. if (tool == &gToolCompTranslate)
  1665. {
  1666. mCtrlPosX->setLabelColor(red);
  1667. mCtrlPosY->setLabelColor(green);
  1668. mCtrlPosZ->setLabelColor(blue);
  1669. mCtrlScaleX->setLabelColor(white);
  1670. mCtrlScaleY->setLabelColor(white);
  1671. mCtrlScaleZ->setLabelColor(white);
  1672. mCtrlRotX->setLabelColor(white);
  1673. mCtrlRotY->setLabelColor(white);
  1674. mCtrlRotZ->setLabelColor(white);
  1675. }
  1676. else if (tool == &gToolCompScale)
  1677. {
  1678. mCtrlPosX->setLabelColor(white);
  1679. mCtrlPosY->setLabelColor(white);
  1680. mCtrlPosZ->setLabelColor(white);
  1681. mCtrlScaleX->setLabelColor(red);
  1682. mCtrlScaleY->setLabelColor(green);
  1683. mCtrlScaleZ->setLabelColor(blue);
  1684. mCtrlRotX->setLabelColor(white);
  1685. mCtrlRotY->setLabelColor(white);
  1686. mCtrlRotZ->setLabelColor(white);
  1687. }
  1688. else if (tool == &gToolCompRotate)
  1689. {
  1690. mCtrlPosX->setLabelColor(white);
  1691. mCtrlPosY->setLabelColor(white);
  1692. mCtrlPosZ->setLabelColor(white);
  1693. mCtrlScaleX->setLabelColor(white);
  1694. mCtrlScaleY->setLabelColor(white);
  1695. mCtrlScaleZ->setLabelColor(white);
  1696. mCtrlRotX->setLabelColor(red);
  1697. mCtrlRotY->setLabelColor(green);
  1698. mCtrlRotZ->setLabelColor(blue);
  1699. }
  1700. else
  1701. {
  1702. mCtrlPosX->setLabelColor(white);
  1703. mCtrlPosY->setLabelColor(white);
  1704. mCtrlPosZ->setLabelColor(white);
  1705. mCtrlScaleX->setLabelColor(white);
  1706. mCtrlScaleY->setLabelColor(white);
  1707. mCtrlScaleZ->setLabelColor(white);
  1708. mCtrlRotX->setLabelColor(white);
  1709. mCtrlRotY->setLabelColor(white);
  1710. mCtrlRotZ->setLabelColor(white);
  1711. }
  1712. LLPanel::draw();
  1713. }
  1714. //virtual
  1715. void LLPanelObject::clearCtrls()
  1716. {
  1717. LLPanel::clearCtrls();
  1718. mCheckLock->set(false);
  1719. mCheckLock->setEnabled(false);
  1720. mCheckTemporary->set(false);
  1721. mCheckTemporary->setEnabled(false);
  1722. mCheckPhantom->set(false);
  1723. mCheckPhantom->setEnabled(false);
  1724. // Disable text labels
  1725. mLabelPosition->setEnabled(false);
  1726. mLabelSize->setEnabled(false);
  1727. mLabelRotation->setEnabled(false);
  1728. mLabelBaseType->setEnabled(false);
  1729. mLabelCut->setEnabled(false);
  1730. mLabelHollow->setEnabled(false);
  1731. mLabelHollowShape->setEnabled(false);
  1732. mLabelTwist->setEnabled(false);
  1733. mLabelSkew->setEnabled(false);
  1734. mLabelShear->setEnabled(false);
  1735. mLabelScaleTaper->setEnabled(false);
  1736. mLabelRadiusOffset->setEnabled(false);
  1737. mLabelRevolutions->setEnabled(false);
  1738. mLabelSelectSingle->setVisible(false);
  1739. mLabelEditObject->setVisible(true);
  1740. mLabelEditObject->setEnabled(false);
  1741. mLabelScaleHole->setEnabled(false);
  1742. mLabelScaleTaper->setEnabled(false);
  1743. mLabelAdvancedCut->setEnabled(false);
  1744. mLabelAdvancedDimple->setEnabled(false);
  1745. mLabelAdvancedSlice->setVisible(false);
  1746. }
  1747. //static
  1748. void LLPanelObject::onCommitLock(LLUICtrl* ctrl, void* userdata)
  1749. {
  1750. // Checkbox will have toggled itself
  1751. LLPanelObject* self = (LLPanelObject*)userdata;
  1752. if (!self || self->mRootObject.isNull())
  1753. {
  1754. return;
  1755. }
  1756. bool new_state = self->mCheckLock->get();
  1757. gSelectMgr.selectionSetObjectPermissions(PERM_OWNER, !new_state,
  1758. PERM_MOVE | PERM_MODIFY);
  1759. }
  1760. //static
  1761. void LLPanelObject::onCommitPosition(LLUICtrl* ctrl, void* userdata)
  1762. {
  1763. LLPanelObject* self = (LLPanelObject*)userdata;
  1764. if (self && ctrl)
  1765. {
  1766. bool btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown();
  1767. self->sendPosition(btn_down);
  1768. }
  1769. }
  1770. //static
  1771. void LLPanelObject::onCommitScale(LLUICtrl* ctrl, void* userdata)
  1772. {
  1773. LLPanelObject* self = (LLPanelObject*)userdata;
  1774. if (self && ctrl)
  1775. {
  1776. bool btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown();
  1777. self->sendScale(btn_down);
  1778. }
  1779. }
  1780. //static
  1781. void LLPanelObject::onCommitRotation(LLUICtrl* ctrl, void* userdata)
  1782. {
  1783. LLPanelObject* self = (LLPanelObject*)userdata;
  1784. if (self && ctrl)
  1785. {
  1786. bool btn_down = ((LLSpinCtrl*)ctrl)->isMouseHeldDown();
  1787. self->sendRotation(btn_down);
  1788. }
  1789. }
  1790. //static
  1791. void LLPanelObject::onCommitTemporary(LLUICtrl* ctrl, void* userdata)
  1792. {
  1793. LLPanelObject* self = (LLPanelObject*)userdata;
  1794. if (self)
  1795. {
  1796. self->sendIsTemporary();
  1797. }
  1798. }
  1799. //static
  1800. void LLPanelObject::onCommitPhantom(LLUICtrl* ctrl, void* userdata)
  1801. {
  1802. LLPanelObject* self = (LLPanelObject*)userdata;
  1803. if (self)
  1804. {
  1805. self->sendIsPhantom();
  1806. }
  1807. }
  1808. //static
  1809. void LLPanelObject::onSelectSculpt(LLUICtrl* ctrl, void* userdata)
  1810. {
  1811. LLPanelObject* self = (LLPanelObject*)userdata;
  1812. if (self)
  1813. {
  1814. self->mSculptTextureRevert =
  1815. self->mCtrlSculptTexture->getImageAssetID();
  1816. self->sendSculpt();
  1817. }
  1818. }
  1819. //static
  1820. void LLPanelObject::onCommitSculpt(LLUICtrl* ctrl, void* userdata)
  1821. {
  1822. LLPanelObject* self = (LLPanelObject*)userdata;
  1823. if (self)
  1824. {
  1825. self->sendSculpt();
  1826. }
  1827. }
  1828. //static
  1829. bool LLPanelObject::onDropSculpt(LLUICtrl*, LLInventoryItem* item,
  1830. void* userdata)
  1831. {
  1832. LLPanelObject* self = (LLPanelObject*)userdata;
  1833. if (self)
  1834. {
  1835. LLUUID asset = item->getAssetUUID();
  1836. self->mCtrlSculptTexture->setImageAssetID(asset);
  1837. self->mSculptTextureRevert = asset;
  1838. }
  1839. return true;
  1840. }
  1841. //static
  1842. void LLPanelObject::onCancelSculpt(LLUICtrl* ctrl, void* userdata)
  1843. {
  1844. LLPanelObject* self = (LLPanelObject*)userdata;
  1845. if (self)
  1846. {
  1847. if (self->mSculptTextureRevert.isNull())
  1848. {
  1849. self->mSculptTextureRevert = LLUUID(SCULPT_DEFAULT_TEXTURE);
  1850. }
  1851. self->mCtrlSculptTexture->setImageAssetID(self->mSculptTextureRevert);
  1852. self->sendSculpt();
  1853. }
  1854. }
  1855. //static
  1856. void LLPanelObject::onCommitSculptType(LLUICtrl* ctrl, void* userdata)
  1857. {
  1858. LLPanelObject* self = (LLPanelObject*)userdata;
  1859. if (self)
  1860. {
  1861. self->sendSculpt();
  1862. }
  1863. }
  1864. //static
  1865. void LLPanelObject::onCommitCopyPaste(LLUICtrl* ctrl, void* userdata)
  1866. {
  1867. LLPanelObject* self = (LLPanelObject*)userdata;
  1868. if (self)
  1869. {
  1870. self->setCopyPasteState();
  1871. }
  1872. }
  1873. //static
  1874. void LLPanelObject::onClickCopy(void* userdata)
  1875. {
  1876. LLPanelObject* self = (LLPanelObject*)userdata;
  1877. if (!self) return;
  1878. if (self->mCheckCopySize->getVisible() &&
  1879. self->mCheckCopySize->getEnabled())
  1880. {
  1881. self->sSavedSize = LLVector3(self->mCtrlScaleX->get(),
  1882. self->mCtrlScaleY->get(),
  1883. self->mCtrlScaleZ->get());
  1884. sSavedSizeValid = true;
  1885. }
  1886. else
  1887. {
  1888. sSavedSizeValid = false;
  1889. }
  1890. if (self->mCheckCopyPos->getVisible() && self->mCheckCopyPos->getEnabled())
  1891. {
  1892. self->sSavedPos = LLVector3(self->mCtrlPosX->get(),
  1893. self->mCtrlPosY->get(),
  1894. self->mCtrlPosZ->get());
  1895. sSavedPosValid = true;
  1896. }
  1897. else
  1898. {
  1899. sSavedPosValid = false;
  1900. }
  1901. if (self->mCheckCopyRot->getVisible() && self->mCheckCopyRot->getEnabled())
  1902. {
  1903. self->sSavedRot = LLVector3(self->mCtrlRotX->get(),
  1904. self->mCtrlRotY->get(),
  1905. self->mCtrlRotZ->get());
  1906. sSavedRotValid = true;
  1907. }
  1908. else
  1909. {
  1910. sSavedRotValid = false;
  1911. }
  1912. if (self->mCheckCopyShape->getVisible() &&
  1913. self->mCheckCopyShape->getEnabled())
  1914. {
  1915. self->getVolumeParams(sSavedShape);
  1916. sSavedShapeValid = true;
  1917. }
  1918. else
  1919. {
  1920. sSavedShapeValid = false;
  1921. }
  1922. self->setCopyPasteState();
  1923. }
  1924. //static
  1925. void LLPanelObject::onClickPaste(void* userdata)
  1926. {
  1927. LLPanelObject* self = (LLPanelObject*)userdata;
  1928. if (!self) return;
  1929. if (sSavedSizeValid && self->mCheckCopySize->getVisible() &&
  1930. self->mCheckCopySize->getEnabled() && self->mCheckCopySize->get())
  1931. {
  1932. self->mCtrlScaleX->set(sSavedSize.mV[VX]);
  1933. self->mCtrlScaleY->set(sSavedSize.mV[VY]);
  1934. self->mCtrlScaleZ->set(sSavedSize.mV[VZ]);
  1935. self->sendScale(false);
  1936. }
  1937. if (sSavedPosValid && self->mCheckCopyPos->getVisible() &&
  1938. self->mCheckCopyPos->getEnabled() && self->mCheckCopyPos->get())
  1939. {
  1940. LLVector3 newpos = sSavedPos;
  1941. if (self->mObject->isAttachment() &&
  1942. newpos.length() > MAX_ATTACHMENT_DIST)
  1943. {
  1944. newpos.clampLength(MAX_ATTACHMENT_DIST);
  1945. llwarns << "Clamping pasted position " << sSavedPos
  1946. << " to fit attachment distance limit. New position is: "
  1947. << newpos << llendl;
  1948. }
  1949. self->mCtrlPosX->set(newpos.mV[VX]);
  1950. self->mCtrlPosY->set(newpos.mV[VY]);
  1951. self->mCtrlPosZ->set(newpos.mV[VZ]);
  1952. self->sendPosition(false);
  1953. }
  1954. if (sSavedRotValid && self->mCheckCopyRot->getVisible() &&
  1955. self->mCheckCopyRot->getEnabled() && self->mCheckCopyRot->get())
  1956. {
  1957. self->mCtrlRotX->set(sSavedRot.mV[VX]);
  1958. self->mCtrlRotY->set(sSavedRot.mV[VY]);
  1959. self->mCtrlRotZ->set(sSavedRot.mV[VZ]);
  1960. self->sendRotation(false);
  1961. }
  1962. if (sSavedShapeValid && self->mCheckCopyShape->getVisible() &&
  1963. self->mCheckCopyShape->getEnabled() && self->mCheckCopyShape->get())
  1964. {
  1965. self->mObject->updateVolume(sSavedShape);
  1966. }
  1967. }