PageRenderTime 148ms CodeModel.GetById 40ms app.highlight 62ms RepoModel.GetById 39ms app.codeStats 0ms

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