/indra/newview/llfloaterauction.cpp

https://bitbucket.org/lindenlab/viewer-beta/ · C++ · 565 lines · 403 code · 97 blank · 65 comment · 30 complexity · 9085da106af1bca8d421921da89aae36 MD5 · raw file

  1. /**
  2. * @file llfloaterauction.cpp
  3. * @author James Cook, Ian Wilkes
  4. * @brief Implementation of the auction floater.
  5. *
  6. * $LicenseInfo:firstyear=2004&license=viewerlgpl$
  7. * Second Life Viewer Source Code
  8. * Copyright (C) 2010, Linden Research, Inc.
  9. *
  10. * This library is free software; you can redistribute it and/or
  11. * modify it under the terms of the GNU Lesser General Public
  12. * License as published by the Free Software Foundation;
  13. * version 2.1 of the License only.
  14. *
  15. * This library is distributed in the hope that it will be useful,
  16. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  17. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  18. * Lesser General Public License for more details.
  19. *
  20. * You should have received a copy of the GNU Lesser General Public
  21. * License along with this library; if not, write to the Free Software
  22. * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
  23. *
  24. * Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
  25. * $/LicenseInfo$
  26. */
  27. #include "llviewerprecompiledheaders.h"
  28. #include "llfloaterauction.h"
  29. #include "llgl.h"
  30. #include "llimagej2c.h"
  31. #include "llimagetga.h"
  32. #include "llparcel.h"
  33. #include "llvfile.h"
  34. #include "llvfs.h"
  35. #include "llwindow.h"
  36. #include "message.h"
  37. #include "llagent.h"
  38. #include "llcombobox.h"
  39. #include "llestateinfomodel.h"
  40. #include "llmimetypes.h"
  41. #include "llnotifications.h"
  42. #include "llnotificationsutil.h"
  43. #include "llsavedsettingsglue.h"
  44. #include "llviewertexturelist.h"
  45. #include "llviewerparcelmgr.h"
  46. #include "llviewerregion.h"
  47. #include "lluictrlfactory.h"
  48. #include "llviewerwindow.h"
  49. #include "llviewerdisplay.h"
  50. #include "llviewercontrol.h"
  51. #include "llui.h"
  52. #include "llrender.h"
  53. #include "llsdutil.h"
  54. #include "llsdutil_math.h"
  55. #include "lltrans.h"
  56. ///----------------------------------------------------------------------------
  57. /// Local function declarations, constants, enums, and typedefs
  58. ///----------------------------------------------------------------------------
  59. void auction_j2c_upload_done(const LLUUID& asset_id,
  60. void* user_data, S32 status, LLExtStat ext_status);
  61. void auction_tga_upload_done(const LLUUID& asset_id,
  62. void* user_data, S32 status, LLExtStat ext_status);
  63. ///----------------------------------------------------------------------------
  64. /// Class llfloaterauction
  65. ///----------------------------------------------------------------------------
  66. // Default constructor
  67. LLFloaterAuction::LLFloaterAuction(const LLSD& key)
  68. : LLFloater(key),
  69. mParcelID(-1)
  70. {
  71. mCommitCallbackRegistrar.add("ClickSnapshot", boost::bind(&LLFloaterAuction::onClickSnapshot, this));
  72. mCommitCallbackRegistrar.add("ClickSellToAnyone", boost::bind(&LLFloaterAuction::onClickSellToAnyone, this));
  73. mCommitCallbackRegistrar.add("ClickStartAuction", boost::bind(&LLFloaterAuction::onClickStartAuction, this));
  74. mCommitCallbackRegistrar.add("ClickResetParcel", boost::bind(&LLFloaterAuction::onClickResetParcel, this));
  75. }
  76. // Destroys the object
  77. LLFloaterAuction::~LLFloaterAuction()
  78. {
  79. }
  80. BOOL LLFloaterAuction::postBuild()
  81. {
  82. return TRUE;
  83. }
  84. void LLFloaterAuction::onOpen(const LLSD& key)
  85. {
  86. initialize();
  87. }
  88. void LLFloaterAuction::initialize()
  89. {
  90. mParcelUpdateCapUrl.clear();
  91. mParcelp = LLViewerParcelMgr::getInstance()->getParcelSelection();
  92. LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
  93. LLParcel* parcelp = mParcelp->getParcel();
  94. if(parcelp && region && !parcelp->getForSale())
  95. {
  96. mParcelHost = region->getHost();
  97. mParcelID = parcelp->getLocalID();
  98. mParcelUpdateCapUrl = region->getCapability("ParcelPropertiesUpdate");
  99. getChild<LLUICtrl>("parcel_text")->setValue(parcelp->getName());
  100. getChildView("snapshot_btn")->setEnabled(TRUE);
  101. getChildView("reset_parcel_btn")->setEnabled(TRUE);
  102. getChildView("start_auction_btn")->setEnabled(TRUE);
  103. U32 estate_id = LLEstateInfoModel::instance().getID();
  104. // Only enable "Sell to Anyone" on Teen grid or if we don't know the ID yet
  105. getChildView("sell_to_anyone_btn")->setEnabled(estate_id == ESTATE_TEEN || estate_id == 0);
  106. }
  107. else
  108. {
  109. mParcelHost.invalidate();
  110. if(parcelp && parcelp->getForSale())
  111. {
  112. getChild<LLUICtrl>("parcel_text")->setValue(getString("already for sale"));
  113. }
  114. else
  115. {
  116. getChild<LLUICtrl>("parcel_text")->setValue(LLStringUtil::null);
  117. }
  118. mParcelID = -1;
  119. getChildView("snapshot_btn")->setEnabled(false);
  120. getChildView("reset_parcel_btn")->setEnabled(false);
  121. getChildView("sell_to_anyone_btn")->setEnabled(false);
  122. getChildView("start_auction_btn")->setEnabled(false);
  123. }
  124. mImageID.setNull();
  125. mImage = NULL;
  126. }
  127. void LLFloaterAuction::draw()
  128. {
  129. LLFloater::draw();
  130. if(!isMinimized() && mImage.notNull())
  131. {
  132. LLView* snapshot_icon = findChildView("snapshot_icon");
  133. if (snapshot_icon)
  134. {
  135. LLRect rect = snapshot_icon->getRect();
  136. {
  137. gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
  138. gl_rect_2d(rect, LLColor4(0.f, 0.f, 0.f, 1.f));
  139. rect.stretch(-1);
  140. }
  141. {
  142. LLGLSUIDefault gls_ui;
  143. gGL.color3f(1.f, 1.f, 1.f);
  144. gl_draw_scaled_image(rect.mLeft,
  145. rect.mBottom,
  146. rect.getWidth(),
  147. rect.getHeight(),
  148. mImage);
  149. }
  150. }
  151. }
  152. }
  153. // static
  154. void LLFloaterAuction::onClickSnapshot(void* data)
  155. {
  156. LLFloaterAuction* self = (LLFloaterAuction*)(data);
  157. LLPointer<LLImageRaw> raw = new LLImageRaw;
  158. gForceRenderLandFence = self->getChild<LLUICtrl>("fence_check")->getValue().asBoolean();
  159. BOOL success = gViewerWindow->rawSnapshot(raw,
  160. gViewerWindow->getWindowWidthScaled(),
  161. gViewerWindow->getWindowHeightScaled(),
  162. TRUE, FALSE,
  163. FALSE, FALSE);
  164. gForceRenderLandFence = FALSE;
  165. if (success)
  166. {
  167. self->mTransactionID.generate();
  168. self->mImageID = self->mTransactionID.makeAssetID(gAgent.getSecureSessionID());
  169. if(!gSavedSettings.getBOOL("QuietSnapshotsToDisk"))
  170. {
  171. gViewerWindow->playSnapshotAnimAndSound();
  172. }
  173. llinfos << "Writing TGA..." << llendl;
  174. LLPointer<LLImageTGA> tga = new LLImageTGA;
  175. tga->encode(raw);
  176. LLVFile::writeFile(tga->getData(), tga->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_IMAGE_TGA);
  177. raw->biasedScaleToPowerOfTwo(LLViewerTexture::MAX_IMAGE_SIZE_DEFAULT);
  178. llinfos << "Writing J2C..." << llendl;
  179. LLPointer<LLImageJ2C> j2c = new LLImageJ2C;
  180. j2c->encode(raw, 0.0f);
  181. LLVFile::writeFile(j2c->getData(), j2c->getDataSize(), gVFS, self->mImageID, LLAssetType::AT_TEXTURE);
  182. self->mImage = LLViewerTextureManager::getLocalTexture((LLImageRaw*)raw, FALSE);
  183. gGL.getTexUnit(0)->bind(self->mImage);
  184. self->mImage->setAddressMode(LLTexUnit::TAM_CLAMP);
  185. }
  186. else
  187. {
  188. llwarns << "Unable to take snapshot" << llendl;
  189. }
  190. }
  191. // static
  192. void LLFloaterAuction::onClickStartAuction(void* data)
  193. {
  194. LLFloaterAuction* self = (LLFloaterAuction*)(data);
  195. if(self->mImageID.notNull())
  196. {
  197. LLSD parcel_name = self->getChild<LLUICtrl>("parcel_text")->getValue();
  198. // create the asset
  199. std::string* name = new std::string(parcel_name.asString());
  200. gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_IMAGE_TGA,
  201. &auction_tga_upload_done,
  202. (void*)name,
  203. FALSE);
  204. self->getWindow()->incBusyCount();
  205. std::string* j2c_name = new std::string(parcel_name.asString());
  206. gAssetStorage->storeAssetData(self->mTransactionID, LLAssetType::AT_TEXTURE,
  207. &auction_j2c_upload_done,
  208. (void*)j2c_name,
  209. FALSE);
  210. self->getWindow()->incBusyCount();
  211. LLNotificationsUtil::add("UploadingAuctionSnapshot");
  212. }
  213. LLMessageSystem* msg = gMessageSystem;
  214. msg->newMessage("ViewerStartAuction");
  215. msg->nextBlock("AgentData");
  216. msg->addUUID("AgentID", gAgent.getID());
  217. msg->addUUID("SessionID", gAgent.getSessionID());
  218. msg->nextBlock("ParcelData");
  219. msg->addS32("LocalID", self->mParcelID);
  220. msg->addUUID("SnapshotID", self->mImageID);
  221. msg->sendReliable(self->mParcelHost);
  222. // clean up floater, and get out
  223. self->cleanupAndClose();
  224. }
  225. void LLFloaterAuction::cleanupAndClose()
  226. {
  227. mImageID.setNull();
  228. mImage = NULL;
  229. mParcelID = -1;
  230. mParcelHost.invalidate();
  231. closeFloater();
  232. }
  233. // static glue
  234. void LLFloaterAuction::onClickResetParcel(void* data)
  235. {
  236. LLFloaterAuction* self = (LLFloaterAuction*)(data);
  237. if (self)
  238. {
  239. self->doResetParcel();
  240. }
  241. }
  242. // Reset all the values for the parcel in preparation for a sale
  243. void LLFloaterAuction::doResetParcel()
  244. {
  245. LLParcel* parcelp = mParcelp->getParcel();
  246. LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
  247. if (parcelp
  248. && region
  249. && !mParcelUpdateCapUrl.empty())
  250. {
  251. LLSD body;
  252. std::string empty;
  253. // request new properties update from simulator
  254. U32 message_flags = 0x01;
  255. body["flags"] = ll_sd_from_U32(message_flags);
  256. // Set all the default parcel properties for auction
  257. body["local_id"] = parcelp->getLocalID();
  258. U32 parcel_flags = PF_ALLOW_LANDMARK |
  259. PF_ALLOW_FLY |
  260. PF_CREATE_GROUP_OBJECTS |
  261. PF_ALLOW_ALL_OBJECT_ENTRY |
  262. PF_ALLOW_GROUP_OBJECT_ENTRY |
  263. PF_ALLOW_GROUP_SCRIPTS |
  264. PF_RESTRICT_PUSHOBJECT |
  265. PF_SOUND_LOCAL |
  266. PF_ALLOW_VOICE_CHAT |
  267. PF_USE_ESTATE_VOICE_CHAN;
  268. body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
  269. // Build a parcel name like "Ahern (128,128) PG 4032m"
  270. std::ostringstream parcel_name;
  271. LLVector3 center_point( parcelp->getCenterpoint() );
  272. center_point.snap(0); // Get rid of fractions
  273. parcel_name << region->getName()
  274. << " ("
  275. << (S32) center_point.mV[VX]
  276. << ","
  277. << (S32) center_point.mV[VY]
  278. << ") "
  279. << region->getSimAccessString()
  280. << " "
  281. << parcelp->getArea()
  282. << "m";
  283. std::string new_name(parcel_name.str().c_str());
  284. body["name"] = new_name;
  285. getChild<LLUICtrl>("parcel_text")->setValue(new_name); // Set name in dialog as well, since it won't get updated otherwise
  286. body["sale_price"] = (S32) 0;
  287. body["description"] = empty;
  288. body["music_url"] = empty;
  289. body["media_url"] = empty;
  290. body["media_desc"] = empty;
  291. body["media_type"] = LLMIMETypes::getDefaultMimeType();
  292. body["media_width"] = (S32) 0;
  293. body["media_height"] = (S32) 0;
  294. body["auto_scale"] = (S32) 0;
  295. body["media_loop"] = (S32) 0;
  296. body["obscure_media"] = (S32) 0; // OBSOLETE - no longer used
  297. body["obscure_music"] = (S32) 0; // OBSOLETE - no longer used
  298. body["media_id"] = LLUUID::null;
  299. body["group_id"] = MAINTENANCE_GROUP_ID; // Use maintenance group
  300. body["pass_price"] = (S32) 10; // Defaults to $10
  301. body["pass_hours"] = 0.0f;
  302. body["category"] = (U8) LLParcel::C_NONE;
  303. body["auth_buyer_id"] = LLUUID::null;
  304. body["snapshot_id"] = LLUUID::null;
  305. body["user_location"] = ll_sd_from_vector3( LLVector3::zero );
  306. body["user_look_at"] = ll_sd_from_vector3( LLVector3::zero );
  307. body["landing_type"] = (U8) LLParcel::L_DIRECT;
  308. llinfos << "Sending parcel update to reset for auction via capability to: "
  309. << mParcelUpdateCapUrl << llendl;
  310. LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
  311. // Send a message to clear the object return time
  312. LLMessageSystem *msg = gMessageSystem;
  313. msg->newMessageFast(_PREHASH_ParcelSetOtherCleanTime);
  314. msg->nextBlockFast(_PREHASH_AgentData);
  315. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID());
  316. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID());
  317. msg->nextBlockFast(_PREHASH_ParcelData);
  318. msg->addS32Fast(_PREHASH_LocalID, parcelp->getLocalID());
  319. msg->addS32Fast(_PREHASH_OtherCleanTime, 5); // 5 minute object auto-return
  320. msg->sendReliable(region->getHost());
  321. // Clear the access lists
  322. clearParcelAccessLists(parcelp, region);
  323. }
  324. }
  325. void LLFloaterAuction::clearParcelAccessLists(LLParcel* parcel, LLViewerRegion* region)
  326. {
  327. if (!region || !parcel) return;
  328. LLUUID transactionUUID;
  329. transactionUUID.generate();
  330. LLMessageSystem* msg = gMessageSystem;
  331. // Clear access list
  332. // parcel->mAccessList.clear();
  333. msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
  334. msg->nextBlockFast(_PREHASH_AgentData);
  335. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  336. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  337. msg->nextBlockFast(_PREHASH_Data);
  338. msg->addU32Fast(_PREHASH_Flags, AL_ACCESS);
  339. msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
  340. msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
  341. msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
  342. msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
  343. // pack an empty block since there will be no data
  344. msg->nextBlockFast(_PREHASH_List);
  345. msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
  346. msg->addS32Fast(_PREHASH_Time, 0 );
  347. msg->addU32Fast(_PREHASH_Flags, 0 );
  348. msg->sendReliable( region->getHost() );
  349. // Send message for empty ban list
  350. //parcel->mBanList.clear();
  351. msg->newMessageFast(_PREHASH_ParcelAccessListUpdate);
  352. msg->nextBlockFast(_PREHASH_AgentData);
  353. msg->addUUIDFast(_PREHASH_AgentID, gAgent.getID() );
  354. msg->addUUIDFast(_PREHASH_SessionID, gAgent.getSessionID() );
  355. msg->nextBlockFast(_PREHASH_Data);
  356. msg->addU32Fast(_PREHASH_Flags, AL_BAN);
  357. msg->addS32(_PREHASH_LocalID, parcel->getLocalID() );
  358. msg->addUUIDFast(_PREHASH_TransactionID, transactionUUID);
  359. msg->addS32Fast(_PREHASH_SequenceID, 1); // sequence_id
  360. msg->addS32Fast(_PREHASH_Sections, 0); // num_sections
  361. // pack an empty block since there will be no data
  362. msg->nextBlockFast(_PREHASH_List);
  363. msg->addUUIDFast(_PREHASH_ID, LLUUID::null );
  364. msg->addS32Fast(_PREHASH_Time, 0 );
  365. msg->addU32Fast(_PREHASH_Flags, 0 );
  366. msg->sendReliable( region->getHost() );
  367. }
  368. // static - 'Sell to Anyone' clicked, throw up a confirmation dialog
  369. void LLFloaterAuction::onClickSellToAnyone(void* data)
  370. {
  371. LLFloaterAuction* self = (LLFloaterAuction*)(data);
  372. if (self)
  373. {
  374. LLParcel* parcelp = self->mParcelp->getParcel();
  375. // Do a confirmation
  376. S32 sale_price = parcelp->getArea(); // Selling for L$1 per meter
  377. S32 area = parcelp->getArea();
  378. LLSD args;
  379. args["LAND_SIZE"] = llformat("%d", area);
  380. args["SALE_PRICE"] = llformat("%d", sale_price);
  381. args["NAME"] = LLTrans::getString("Anyone");
  382. LLNotification::Params params("ConfirmLandSaleChange"); // Re-use existing dialog
  383. params.substitutions(args)
  384. .functor.function(boost::bind(&LLFloaterAuction::onSellToAnyoneConfirmed, self, _1, _2));
  385. params.name("ConfirmLandSaleToAnyoneChange");
  386. // ask away
  387. LLNotifications::instance().add(params);
  388. }
  389. }
  390. // Sell confirmation clicked
  391. bool LLFloaterAuction::onSellToAnyoneConfirmed(const LLSD& notification, const LLSD& response)
  392. {
  393. S32 option = LLNotificationsUtil::getSelectedOption(notification, response);
  394. if (option == 0)
  395. {
  396. doSellToAnyone();
  397. }
  398. return false;
  399. }
  400. // Reset all the values for the parcel in preparation for a sale
  401. void LLFloaterAuction::doSellToAnyone()
  402. {
  403. LLParcel* parcelp = mParcelp->getParcel();
  404. LLViewerRegion* region = LLViewerParcelMgr::getInstance()->getSelectionRegion();
  405. if (parcelp
  406. && region
  407. && !mParcelUpdateCapUrl.empty())
  408. {
  409. LLSD body;
  410. std::string empty;
  411. // request new properties update from simulator
  412. U32 message_flags = 0x01;
  413. body["flags"] = ll_sd_from_U32(message_flags);
  414. // Set all the default parcel properties for auction
  415. body["local_id"] = parcelp->getLocalID();
  416. // Set 'for sale' flag
  417. U32 parcel_flags = parcelp->getParcelFlags() | PF_FOR_SALE;
  418. // Ensure objects not included
  419. parcel_flags &= ~PF_FOR_SALE_OBJECTS;
  420. body["parcel_flags"] = ll_sd_from_U32(parcel_flags);
  421. body["sale_price"] = parcelp->getArea(); // Sell for L$1 per square meter
  422. body["auth_buyer_id"] = LLUUID::null; // To anyone
  423. llinfos << "Sending parcel update to sell to anyone for L$1 via capability to: "
  424. << mParcelUpdateCapUrl << llendl;
  425. LLHTTPClient::post(mParcelUpdateCapUrl, body, new LLHTTPClient::Responder());
  426. // clean up floater, and get out
  427. cleanupAndClose();
  428. }
  429. }
  430. ///----------------------------------------------------------------------------
  431. /// Local function definitions
  432. ///----------------------------------------------------------------------------
  433. void auction_tga_upload_done(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
  434. {
  435. std::string* name = (std::string*)(user_data);
  436. llinfos << "Upload of asset '" << *name << "' " << asset_id
  437. << " returned " << status << llendl;
  438. delete name;
  439. gViewerWindow->getWindow()->decBusyCount();
  440. if (0 == status)
  441. {
  442. LLNotificationsUtil::add("UploadWebSnapshotDone");
  443. }
  444. else
  445. {
  446. LLSD args;
  447. args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
  448. LLNotificationsUtil::add("UploadAuctionSnapshotFail", args);
  449. }
  450. }
  451. void auction_j2c_upload_done(const LLUUID& asset_id, void* user_data, S32 status, LLExtStat ext_status) // StoreAssetData callback (fixed)
  452. {
  453. std::string* name = (std::string*)(user_data);
  454. llinfos << "Upload of asset '" << *name << "' " << asset_id
  455. << " returned " << status << llendl;
  456. delete name;
  457. gViewerWindow->getWindow()->decBusyCount();
  458. if (0 == status)
  459. {
  460. LLNotificationsUtil::add("UploadSnapshotDone");
  461. }
  462. else
  463. {
  464. LLSD args;
  465. args["REASON"] = std::string(LLAssetStorage::getErrorString(status));
  466. LLNotificationsUtil::add("UploadAuctionSnapshotFail", args);
  467. }
  468. }