llpreview.cpp
上传用户:king477883
上传日期:2021-03-01
资源大小:9553k
文件大小:13k
源码类别:

游戏引擎

开发平台:

C++ Builder

  1. /** 
  2.  * @file llpreview.cpp
  3.  * @brief LLPreview class implementation
  4.  *
  5.  * $LicenseInfo:firstyear=2002&license=viewergpl$
  6.  * 
  7.  * Copyright (c) 2002-2010, 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 "stdenums.h"
  34. #include "llpreview.h"
  35. #include "lllineeditor.h"
  36. #include "llinventory.h"
  37. #include "llinventorymodel.h"
  38. #include "llresmgr.h"
  39. #include "lltextbox.h"
  40. #include "llfloaterreg.h"
  41. #include "llfocusmgr.h"
  42. #include "lltooldraganddrop.h"
  43. #include "llradiogroup.h"
  44. #include "llassetstorage.h"
  45. #include "llviewerassettype.h"
  46. #include "llviewerobject.h"
  47. #include "llviewerobjectlist.h"
  48. #include "lldbstrings.h"
  49. #include "llagent.h"
  50. #include "llvoavatarself.h"
  51. #include "llselectmgr.h"
  52. #include "llviewerinventory.h"
  53. #include "llviewerwindow.h"
  54. #include "lltrans.h"
  55. // Constants
  56. LLPreview::LLPreview(const LLSD& key)
  57. : LLFloater(key),
  58. mItemUUID(key.asUUID()),
  59. mObjectUUID(), // set later by setObjectID()
  60. mCopyToInvBtn( NULL ),
  61. mForceClose(FALSE),
  62. mUserResized(FALSE),
  63. mCloseAfterSave(FALSE),
  64. mAssetStatus(PREVIEW_ASSET_UNLOADED),
  65. mDirty(TRUE)
  66. {
  67. mAuxItem = new LLInventoryItem;
  68. // don't necessarily steal focus on creation -- sometimes these guys pop up without user action
  69. setAutoFocus(FALSE);
  70. gInventory.addObserver(this);
  71. refreshFromItem();
  72. }
  73. BOOL LLPreview::postBuild()
  74. {
  75. refreshFromItem();
  76. return TRUE;
  77. }
  78. LLPreview::~LLPreview()
  79. {
  80. gFocusMgr.releaseFocusIfNeeded( this ); // calls onCommit()
  81. gInventory.removeObserver(this);
  82. }
  83. void LLPreview::setObjectID(const LLUUID& object_id)
  84. {
  85. mObjectUUID = object_id;
  86. if (getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  87. {
  88. loadAsset();
  89. }
  90. }
  91. void LLPreview::setItem( LLInventoryItem* item )
  92. {
  93. mItem = item;
  94. if (mItem && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  95. {
  96. loadAsset();
  97. }
  98. }
  99. const LLInventoryItem *LLPreview::getItem() const
  100. {
  101. const LLInventoryItem *item = NULL;
  102. if (mItem.notNull())
  103. {
  104. item = mItem;
  105. }
  106. else if (mObjectUUID.isNull())
  107. {
  108. // it's an inventory item, so get the item.
  109. item = gInventory.getItem(mItemUUID);
  110. }
  111. else
  112. {
  113. // it's an object's inventory item.
  114. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  115. if(object)
  116. {
  117. item = dynamic_cast<LLInventoryItem*>(object->getInventoryObject(mItemUUID));
  118. }
  119. }
  120. return item;
  121. }
  122. // Sub-classes should override this function if they allow editing
  123. void LLPreview::onCommit()
  124. {
  125. const LLViewerInventoryItem *item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
  126. if(item)
  127. {
  128. if (!item->isComplete())
  129. {
  130. // We are attempting to save an item that was never loaded
  131. llwarns << "LLPreview::onCommit() called with mIsComplete == FALSE"
  132. << " Type: " << item->getType()
  133. << " ID: " << item->getUUID()
  134. << llendl;
  135. return;
  136. }
  137. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  138. new_item->setDescription(childGetText("desc"));
  139. std::string new_name = childGetText("name");
  140. if ( (new_item->getName() != new_name) && !new_name.empty())
  141. {
  142. new_item->rename(childGetText("name"));
  143. }
  144. if(mObjectUUID.notNull())
  145. {
  146. // must be in an object
  147. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  148. if(object)
  149. {
  150. object->updateInventory(
  151. new_item,
  152. TASK_INVENTORY_ITEM_KEY,
  153. false);
  154. }
  155. }
  156. else if(item->getPermissions().getOwner() == gAgent.getID())
  157. {
  158. new_item->updateServer(FALSE);
  159. gInventory.updateItem(new_item);
  160. gInventory.notifyObservers();
  161. // If the item is an attachment that is currently being worn,
  162. // update the object itself.
  163. if( item->getType() == LLAssetType::AT_OBJECT )
  164. {
  165. LLVOAvatarSelf* avatar = gAgent.getAvatarObject();
  166. if( avatar )
  167. {
  168. LLViewerObject* obj = avatar->getWornAttachment( item->getUUID() );
  169. if( obj )
  170. {
  171. LLSelectMgr::getInstance()->deselectAll();
  172. LLSelectMgr::getInstance()->addAsIndividual( obj, SELECT_ALL_TES, FALSE );
  173. LLSelectMgr::getInstance()->selectionSetObjectDescription( childGetText("desc") );
  174. LLSelectMgr::getInstance()->deselectAll();
  175. }
  176. }
  177. }
  178. }
  179. }
  180. }
  181. void LLPreview::changed(U32 mask)
  182. {
  183. mDirty = TRUE;
  184. }
  185. void LLPreview::setNotecardInfo(const LLUUID& notecard_inv_id, 
  186. const LLUUID& object_id)
  187. {
  188. mNotecardInventoryID = notecard_inv_id;
  189. mNotecardObjectID = object_id;
  190. }
  191. void LLPreview::draw()
  192. {
  193. LLFloater::draw();
  194. if (mDirty)
  195. {
  196. mDirty = FALSE;
  197. refreshFromItem();
  198. }
  199. }
  200. void LLPreview::refreshFromItem()
  201. {
  202. const LLInventoryItem* item = getItem();
  203. if (!item)
  204. {
  205. return;
  206. }
  207. if (hasString("Title"))
  208. {
  209. LLStringUtil::format_map_t args;
  210. args["[NAME]"] = item->getName();
  211. LLUIString title = getString("Title", args);
  212. setTitle(title.getString());
  213. }
  214. childSetText("desc",item->getDescription());
  215. BOOL can_agent_manipulate = item->getPermissions().allowModifyBy(gAgent.getID());
  216. childSetEnabled("desc",can_agent_manipulate);
  217. }
  218. // static 
  219. void LLPreview::onText(LLUICtrl*, void* userdata)
  220. {
  221. LLPreview* self = (LLPreview*) userdata;
  222. self->onCommit();
  223. }
  224. // static
  225. void LLPreview::onRadio(LLUICtrl*, void* userdata)
  226. {
  227. LLPreview* self = (LLPreview*) userdata;
  228. self->onCommit();
  229. }
  230. // static
  231. void LLPreview::hide(const LLUUID& item_uuid, BOOL no_saving /* = FALSE */ )
  232. {
  233. LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
  234. if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
  235. LLPreview* preview = dynamic_cast<LLPreview*>(floater);
  236. if (preview)
  237. {
  238. if ( no_saving )
  239. {
  240. preview->mForceClose = TRUE;
  241. }
  242. preview->closeFloater();
  243. }
  244. }
  245. // static
  246. void LLPreview::dirty(const LLUUID& item_uuid)
  247. {
  248. LLFloater* floater = LLFloaterReg::findInstance("preview", LLSD(item_uuid));
  249. if (!floater) floater = LLFloaterReg::findInstance("preview_avatar", LLSD(item_uuid));
  250. LLPreview* preview = dynamic_cast<LLPreview*>(floater);
  251. if(preview)
  252. {
  253. preview->mDirty = TRUE;
  254. }
  255. }
  256. BOOL LLPreview::handleMouseDown(S32 x, S32 y, MASK mask)
  257. {
  258. if(mClientRect.pointInRect(x, y))
  259. {
  260. // No handler needed for focus lost since this class has no
  261. // state that depends on it.
  262. bringToFront(x, y);
  263. gFocusMgr.setMouseCapture(this);
  264. S32 screen_x;
  265. S32 screen_y;
  266. localPointToScreen(x, y, &screen_x, &screen_y );
  267. LLToolDragAndDrop::getInstance()->setDragStart(screen_x, screen_y);
  268. return TRUE;
  269. }
  270. return LLFloater::handleMouseDown(x, y, mask);
  271. }
  272. BOOL LLPreview::handleMouseUp(S32 x, S32 y, MASK mask)
  273. {
  274. if(hasMouseCapture())
  275. {
  276. gFocusMgr.setMouseCapture(NULL);
  277. return TRUE;
  278. }
  279. return LLFloater::handleMouseUp(x, y, mask);
  280. }
  281. BOOL LLPreview::handleHover(S32 x, S32 y, MASK mask)
  282. {
  283. if(hasMouseCapture())
  284. {
  285. S32 screen_x;
  286. S32 screen_y;
  287. const LLInventoryItem *item = getItem();
  288. localPointToScreen(x, y, &screen_x, &screen_y );
  289. if(item
  290.    && item->getPermissions().allowCopyBy(gAgent.getID(),
  291.  gAgent.getGroupID())
  292.    && LLToolDragAndDrop::getInstance()->isOverThreshold(screen_x, screen_y))
  293. {
  294. EDragAndDropType type;
  295. type = LLViewerAssetType::lookupDragAndDropType(item->getType());
  296. LLToolDragAndDrop::ESource src = LLToolDragAndDrop::SOURCE_LIBRARY;
  297. if(!mObjectUUID.isNull())
  298. {
  299. src = LLToolDragAndDrop::SOURCE_WORLD;
  300. }
  301. else if(item->getPermissions().getOwner() == gAgent.getID())
  302. {
  303. src = LLToolDragAndDrop::SOURCE_AGENT;
  304. }
  305. LLToolDragAndDrop::getInstance()->beginDrag(type,
  306. item->getUUID(),
  307. src,
  308. mObjectUUID);
  309. return LLToolDragAndDrop::getInstance()->handleHover(x, y, mask );
  310. }
  311. }
  312. return LLFloater::handleHover(x,y,mask);
  313. }
  314. void LLPreview::onOpen(const LLSD& key)
  315. {
  316. if (!getFloaterHost() && !getHost() && getAssetStatus() == PREVIEW_ASSET_UNLOADED)
  317. {
  318. loadAsset();
  319. }
  320. }
  321. void LLPreview::setAuxItem( const LLInventoryItem* item )
  322. {
  323. if ( mAuxItem ) 
  324. mAuxItem->copyItem(item);
  325. }
  326. // static
  327. void LLPreview::onBtnCopyToInv(void* userdata)
  328. {
  329. LLPreview* self = (LLPreview*) userdata;
  330. LLInventoryItem *item = self->mAuxItem;
  331. if(item && item->getUUID().notNull())
  332. {
  333. // Copy to inventory
  334. if (self->mNotecardInventoryID.notNull())
  335. {
  336. copy_inventory_from_notecard(self->mNotecardObjectID,
  337. self->mNotecardInventoryID, item);
  338. }
  339. else
  340. {
  341. LLPointer<LLInventoryCallback> cb = NULL;
  342. copy_inventory_item(
  343. gAgent.getID(),
  344. item->getPermissions().getOwner(),
  345. item->getUUID(),
  346. LLUUID::null,
  347. std::string(),
  348. cb);
  349. }
  350. }
  351. self->closeFloater();
  352. }
  353. // static
  354. void LLPreview::onKeepBtn(void* data)
  355. {
  356. LLPreview* self = (LLPreview*)data;
  357. self->closeFloater();
  358. }
  359. // static
  360. void LLPreview::onDiscardBtn(void* data)
  361. {
  362. LLPreview* self = (LLPreview*)data;
  363. const LLInventoryItem* item = self->getItem();
  364. if (!item) return;
  365. self->mForceClose = TRUE;
  366. self->closeFloater();
  367. // Delete the item entirely
  368. /*
  369. item->removeFromServer();
  370. gInventory.deleteObject(item->getUUID());
  371. gInventory.notifyObservers();
  372. */
  373. // Move the item to the trash
  374. const LLUUID trash_id = gInventory.findCategoryUUIDForType(LLFolderType::FT_TRASH);
  375. if (item->getParentUUID() != trash_id)
  376. {
  377. LLInventoryModel::update_list_t update;
  378. LLInventoryModel::LLCategoryUpdate old_folder(item->getParentUUID(),-1);
  379. update.push_back(old_folder);
  380. LLInventoryModel::LLCategoryUpdate new_folder(trash_id, 1);
  381. update.push_back(new_folder);
  382. gInventory.accountForUpdate(update);
  383. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  384. new_item->setParent(trash_id);
  385. // no need to restamp it though it's a move into trash because
  386. // it's a brand new item already.
  387. new_item->updateParentOnServer(FALSE);
  388. gInventory.updateItem(new_item);
  389. gInventory.notifyObservers();
  390. }
  391. }
  392. void LLPreview::handleReshape(const LLRect& new_rect, bool by_user)
  393. {
  394. if(by_user 
  395. && (new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight()))
  396. {
  397. userResized();
  398. }
  399. LLFloater::handleReshape(new_rect, by_user);
  400. }
  401. //
  402. // LLMultiPreview
  403. //
  404. LLMultiPreview::LLMultiPreview()
  405. : LLMultiFloater(LLSD())
  406. {
  407. // *TODO: There should be a .xml file for this
  408. const LLRect& nextrect = LLFloaterReg::getFloaterRect("preview"); // place where the next preview should show up
  409. if (nextrect.getWidth() > 0)
  410. {
  411. setRect(nextrect);
  412. }
  413. else
  414. {
  415. // start with a rect in the top-left corner ; will get resized
  416. LLRect rect;
  417. rect.setLeftTopAndSize(0, gViewerWindow->getWindowHeightScaled(), 200, 200);
  418. setRect(rect);
  419. }
  420. setTitle(LLTrans::getString("MultiPreviewTitle"));
  421. buildTabContainer();
  422. setCanResize(TRUE);
  423. }
  424. void LLMultiPreview::onOpen(const LLSD& key)
  425. {
  426. LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
  427. if (frontmost_preview && frontmost_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
  428. {
  429. frontmost_preview->loadAsset();
  430. }
  431. LLMultiFloater::onOpen(key);
  432. }
  433. void LLMultiPreview::handleReshape(const LLRect& new_rect, bool by_user)
  434. {
  435. if(new_rect.getWidth() != getRect().getWidth() || new_rect.getHeight() != getRect().getHeight())
  436. {
  437. LLPreview* frontmost_preview = (LLPreview*)mTabContainer->getCurrentPanel();
  438. if (frontmost_preview) frontmost_preview->userResized();
  439. }
  440. LLFloater::handleReshape(new_rect, by_user);
  441. }
  442. void LLMultiPreview::tabOpen(LLFloater* opened_floater, bool from_click)
  443. {
  444. LLPreview* opened_preview = (LLPreview*)opened_floater;
  445. if (opened_preview && opened_preview->getAssetStatus() == LLPreview::PREVIEW_ASSET_UNLOADED)
  446. {
  447. opened_preview->loadAsset();
  448. }
  449. }
  450. void LLPreview::setAssetId(const LLUUID& asset_id)
  451. {
  452. const LLViewerInventoryItem* item = dynamic_cast<const LLViewerInventoryItem*>(getItem());
  453. if(NULL == item)
  454. {
  455. return;
  456. }
  457. if(mObjectUUID.isNull())
  458. {
  459. // Update avatar inventory asset_id.
  460. LLPointer<LLViewerInventoryItem> new_item = new LLViewerInventoryItem(item);
  461. new_item->setAssetUUID(asset_id);
  462. gInventory.updateItem(new_item);
  463. gInventory.notifyObservers();
  464. }
  465. else
  466. {
  467. // Update object inventory asset_id.
  468. LLViewerObject* object = gObjectList.findObject(mObjectUUID);
  469. if(NULL == object)
  470. {
  471. return;
  472. }
  473. object->updateViewerInventoryAsset(item, asset_id);
  474. }
  475. }