PageRenderTime 86ms CodeModel.GetById 7ms app.highlight 73ms RepoModel.GetById 1ms app.codeStats 0ms

/indra/newview/llfloatermodelwizard.cpp

https://bitbucket.org/lindenlab/viewer-beta/
C++ | 795 lines | 571 code | 152 blank | 72 comment | 90 complexity | b1204154f5c35b07908b45786cf73eca MD5 | raw file
  1/** 
  2 * @file llfloatermodelwizard.cpp
  3 * @author Leyla Farazha
  4 * @brief Implementation of the LLFloaterModelWizard class.
  5 *
  6 * $LicenseInfo:firstyear=2002&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
 29#include "llviewerprecompiledheaders.h"
 30
 31#include "llbutton.h"
 32#include "lldrawable.h"
 33#include "llcheckboxctrl.h"
 34#include "llcombobox.h"
 35#include "llfloater.h"
 36#include "llfloatermodelwizard.h"
 37#include "llfloatermodelpreview.h"
 38#include "llfloaterreg.h"
 39#include "llsliderctrl.h"
 40#include "lltoolmgr.h"
 41#include "llviewerwindow.h"
 42
 43LLFloaterModelWizard* LLFloaterModelWizard::sInstance = NULL;
 44
 45static	const std::string stateNames[]={
 46	"choose_file",
 47	"optimize",
 48	"physics",
 49	"review",
 50	"upload"};
 51
 52static void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible);
 53
 54LLFloaterModelWizard::LLFloaterModelWizard(const LLSD& key)
 55	: LLFloaterModelUploadBase(key)
 56	 ,mRecalculateGeometryBtn(NULL)
 57	 ,mRecalculatePhysicsBtn(NULL)
 58	 ,mRecalculatingPhysicsBtn(NULL)
 59	 ,mCalculateWeightsBtn(NULL)
 60	 ,mCalculatingWeightsBtn(NULL)
 61	 ,mChooseFilePreviewPanel(NULL)
 62	 ,mOptimizePreviewPanel(NULL)
 63	 ,mPhysicsPreviewPanel(NULL)
 64{
 65	mLastEnabledState = CHOOSE_FILE;
 66	sInstance = this;
 67
 68	mCommitCallbackRegistrar.add("Wizard.Choose", boost::bind(&LLFloaterModelWizard::setState, this, CHOOSE_FILE));
 69	mCommitCallbackRegistrar.add("Wizard.Optimize", boost::bind(&LLFloaterModelWizard::setState, this, OPTIMIZE));
 70	mCommitCallbackRegistrar.add("Wizard.Physics", boost::bind(&LLFloaterModelWizard::setState, this, PHYSICS));
 71	mCommitCallbackRegistrar.add("Wizard.Review", boost::bind(&LLFloaterModelWizard::setState, this, REVIEW));
 72	mCommitCallbackRegistrar.add("Wizard.Upload", boost::bind(&LLFloaterModelWizard::setState, this, UPLOAD));
 73}
 74LLFloaterModelWizard::~LLFloaterModelWizard()
 75{
 76	sInstance = NULL;
 77}
 78void LLFloaterModelWizard::setState(int state)
 79{
 80
 81	mState = state;
 82
 83	for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t)
 84	{
 85		LLView *view = getChildView(stateNames[t]+"_panel");
 86		if (view) 
 87		{
 88			view->setVisible(state == (int) t ? TRUE : FALSE);
 89		}
 90	}
 91
 92	LLView* current_preview_panel = NULL;
 93
 94	if (state == CHOOSE_FILE)
 95	{
 96		mModelPreview->mViewOption["show_physics"] = false;
 97
 98		current_preview_panel = mChooseFilePreviewPanel;
 99
100		getChildView("close")->setVisible(false);
101		getChildView("back")->setVisible(true);
102		getChildView("back")->setEnabled(false);
103		getChildView("next")->setVisible(true);
104		getChildView("upload")->setVisible(false);
105		getChildView("cancel")->setVisible(true);
106		mCalculateWeightsBtn->setVisible(false);
107		mCalculatingWeightsBtn->setVisible(false);
108	}
109
110	if (state == OPTIMIZE)
111	{
112		if (mLastEnabledState < state)
113		{			
114			mModelPreview->genLODs(-1);
115		}
116
117		mModelPreview->mViewOption["show_physics"] = false;
118
119		current_preview_panel = mOptimizePreviewPanel;
120
121		getChildView("back")->setVisible(true);
122		getChildView("back")->setEnabled(true);
123		getChildView("close")->setVisible(false);
124		getChildView("next")->setVisible(true);
125		getChildView("upload")->setVisible(false);
126		getChildView("cancel")->setVisible(true);
127		mCalculateWeightsBtn->setVisible(false);
128		mCalculatingWeightsBtn->setVisible(false);
129	}
130
131	if (state == PHYSICS)
132	{
133		if (mLastEnabledState < state)
134		{
135			mModelPreview->setPhysicsFromLOD(1);
136
137			// Trigger the recalculate physics when first entering
138			// the Physics step.
139			onClickRecalculatePhysics();
140		}
141
142		mModelPreview->mViewOption["show_physics"] = true;
143
144		current_preview_panel = mPhysicsPreviewPanel;
145
146		getChildView("next")->setVisible(false);
147		getChildView("upload")->setVisible(false);
148		getChildView("close")->setVisible(false);
149		getChildView("back")->setVisible(true);
150		getChildView("back")->setEnabled(true);
151		getChildView("cancel")->setVisible(true);
152		mCalculateWeightsBtn->setVisible(true);
153		mCalculatingWeightsBtn->setVisible(false);
154	}
155
156	if (state == REVIEW)
157	{
158		
159		mModelPreview->mViewOption["show_physics"] = false;
160
161		getChildView("close")->setVisible(false);
162		getChildView("next")->setVisible(false);
163		getChildView("back")->setVisible(true);
164		getChildView("back")->setEnabled(true);
165		getChildView("upload")->setVisible(true);
166		getChildView("cancel")->setVisible(true);
167		mCalculateWeightsBtn->setVisible(false);
168		mCalculatingWeightsBtn->setVisible(false);
169	}
170
171	if (state == UPLOAD)
172	{
173		getChildView("close")->setVisible(true);
174		getChildView("next")->setVisible(false);
175		getChildView("back")->setVisible(false);
176		getChildView("upload")->setVisible(false);
177		getChildView("cancel")->setVisible(false);
178		mCalculateWeightsBtn->setVisible(false);
179		mCalculatingWeightsBtn->setVisible(false);
180	}
181
182	if (current_preview_panel)
183	{
184		LLRect rect;
185		current_preview_panel->localRectToOtherView(current_preview_panel->getLocalRect(), &rect, this);
186
187		// Reduce the preview rect by 1 px to fit the borders
188		rect.stretch(-1);
189
190		if (rect != mPreviewRect)
191		{
192			mPreviewRect = rect;
193			mModelPreview->refresh();
194		}
195	}
196	updateButtons();
197}
198
199
200
201void LLFloaterModelWizard::updateButtons()
202{
203	if (mLastEnabledState < mState)
204	{
205		mLastEnabledState = mState;
206	}
207
208	for(size_t i=0; i<LL_ARRAY_SIZE(stateNames); ++i)
209	{
210		LLButton *button = getChild<LLButton>(stateNames[i]+"_btn");
211
212		if (i == mState)
213		{
214			button->setEnabled(TRUE);
215			button->setToggleState(TRUE);
216		}
217		else if (i <= mLastEnabledState)
218		{
219			button->setEnabled(TRUE);
220			button->setToggleState(FALSE);
221		}
222		else
223		{
224			button->setEnabled(FALSE);
225		}
226	}
227}
228
229void LLFloaterModelWizard::onClickSwitchToAdvanced()
230{
231	LLFloaterModelPreview* floater_preview = LLFloaterReg::getTypedInstance<LLFloaterModelPreview>("upload_model");
232	if (!floater_preview)
233	{
234		llwarns << "FLoater model preview not found." << llendl;
235		return;
236	}
237
238	// Open floater model preview
239	floater_preview->openFloater();
240
241	// Close the wizard
242	closeFloater();
243
244	std::string filename = getChild<LLUICtrl>("lod_file")->getValue().asString();
245	if (!filename.empty())
246	{
247		// Re-load the model to the floater model preview if it has been loaded
248		// into the wizard.
249		floater_preview->loadModel(3, filename);
250	}
251}
252
253void LLFloaterModelWizard::onClickRecalculateGeometry()
254{
255	S32 val = getChild<LLUICtrl>("accuracy_slider")->getValue().asInteger();
256
257	mModelPreview->genLODs(-1, NUM_LOD - val);
258
259	mModelPreview->refresh();
260}
261
262void LLFloaterModelWizard::onClickRecalculatePhysics()
263{
264	// Hide the "Recalculate physics" button and show the "Recalculating..."
265	// button instead.
266	swap_controls(mRecalculatePhysicsBtn, mRecalculatingPhysicsBtn, false);
267
268	executePhysicsStage("Decompose");
269}
270
271void LLFloaterModelWizard::onClickCalculateUploadFee()
272{
273	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, false);
274
275	mModelPreview->rebuildUploadData();
276
277	mUploadModelUrl.clear();
278
279	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale,
280			true, false, false, mUploadModelUrl, false, getWholeModelFeeObserverHandle());
281}
282
283void LLFloaterModelWizard::loadModel()
284{
285	 mModelPreview->mLoading = TRUE;
286	
287	(new LLMeshFilePicker(mModelPreview, 3))->getFile();
288}
289
290void LLFloaterModelWizard::onClickCancel()
291{
292	closeFloater();
293}
294
295void LLFloaterModelWizard::onClickBack()
296{
297	setState(llmax((int) CHOOSE_FILE, mState-1));
298}
299
300void LLFloaterModelWizard::onClickNext()
301{
302	setState(llmin((int) UPLOAD, mState+1));
303}
304
305bool LLFloaterModelWizard::onEnableNext()
306{
307	return true;
308}
309
310bool LLFloaterModelWizard::onEnableBack()
311{
312	return true;
313}
314
315
316//-----------------------------------------------------------------------------
317// handleMouseDown()
318//-----------------------------------------------------------------------------
319BOOL LLFloaterModelWizard::handleMouseDown(S32 x, S32 y, MASK mask)
320{
321	if (mPreviewRect.pointInRect(x, y))
322	{
323		bringToFront( x, y );
324		gFocusMgr.setMouseCapture(this);
325		gViewerWindow->hideCursor();
326		mLastMouseX = x;
327		mLastMouseY = y;
328		return TRUE;
329	}
330	
331	return LLFloater::handleMouseDown(x, y, mask);
332}
333
334//-----------------------------------------------------------------------------
335// handleMouseUp()
336//-----------------------------------------------------------------------------
337BOOL LLFloaterModelWizard::handleMouseUp(S32 x, S32 y, MASK mask)
338{
339	gFocusMgr.setMouseCapture(FALSE);
340	gViewerWindow->showCursor();
341	return LLFloater::handleMouseUp(x, y, mask);
342}
343
344//-----------------------------------------------------------------------------
345// handleHover()
346//-----------------------------------------------------------------------------
347BOOL LLFloaterModelWizard::handleHover	(S32 x, S32 y, MASK mask)
348{
349	MASK local_mask = mask & ~MASK_ALT;
350	
351	if (mModelPreview && hasMouseCapture())
352	{
353		if (local_mask == MASK_PAN)
354		{
355			// pan here
356			mModelPreview->pan((F32)(x - mLastMouseX) * -0.005f, (F32)(y - mLastMouseY) * -0.005f);
357		}
358		else if (local_mask == MASK_ORBIT)
359		{
360			F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
361			F32 pitch_radians = (F32)(y - mLastMouseY) * 0.02f;
362			
363			mModelPreview->rotate(yaw_radians, pitch_radians);
364		}
365		else 
366		{
367			
368			F32 yaw_radians = (F32)(x - mLastMouseX) * -0.01f;
369			F32 zoom_amt = (F32)(y - mLastMouseY) * 0.02f;
370			
371			mModelPreview->rotate(yaw_radians, 0.f);
372			mModelPreview->zoom(zoom_amt);
373		}
374		
375		
376		mModelPreview->refresh();
377		
378		LLUI::setMousePositionLocal(this, mLastMouseX, mLastMouseY);
379	}
380	
381	if (!mPreviewRect.pointInRect(x, y) || !mModelPreview)
382	{
383		return LLFloater::handleHover(x, y, mask);
384	}
385	else if (local_mask == MASK_ORBIT)
386	{
387		gViewerWindow->setCursor(UI_CURSOR_TOOLCAMERA);
388	}
389	else if (local_mask == MASK_PAN)
390	{
391		gViewerWindow->setCursor(UI_CURSOR_TOOLPAN);
392	}
393	else
394	{
395		gViewerWindow->setCursor(UI_CURSOR_TOOLZOOMIN);
396	}
397	
398	return TRUE;
399}
400
401//-----------------------------------------------------------------------------
402// handleScrollWheel()
403//-----------------------------------------------------------------------------
404BOOL LLFloaterModelWizard::handleScrollWheel(S32 x, S32 y, S32 clicks)
405{
406	if (mPreviewRect.pointInRect(x, y) && mModelPreview)
407	{
408		mModelPreview->zoom((F32)clicks * -0.2f);
409		mModelPreview->refresh();
410	}
411	
412	return TRUE;
413}
414
415
416void LLFloaterModelWizard::initDecompControls()
417{
418	LLSD key;
419
420	static const LLCDStageData* stage = NULL;
421	static S32 stage_count = 0;
422
423	if (!stage && LLConvexDecomposition::getInstance() != NULL)
424	{
425		stage_count = LLConvexDecomposition::getInstance()->getStages(&stage);
426	}
427
428	static const LLCDParam* param = NULL;
429	static S32 param_count = 0;
430	if (!param && LLConvexDecomposition::getInstance() != NULL)
431	{
432		param_count = LLConvexDecomposition::getInstance()->getParameters(&param);
433	}
434
435	for (S32 j = stage_count-1; j >= 0; --j)
436	{
437		gMeshRepo.mDecompThread->mStageID[stage[j].mName] = j;
438		// protected against stub by stage_count being 0 for stub above
439		LLConvexDecomposition::getInstance()->registerCallback(j, LLPhysicsDecomp::llcdCallback);
440
441		for (S32 i = 0; i < param_count; ++i)
442		{
443			if (param[i].mStage != j)
444			{
445				continue;
446			}
447
448			std::string name(param[i].mName ? param[i].mName : "");
449			std::string description(param[i].mDescription ? param[i].mDescription : "");
450
451			if (param[i].mType == LLCDParam::LLCD_FLOAT)
452			{
453				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mFloat);
454			}
455			else if (param[i].mType == LLCDParam::LLCD_INTEGER)
456			{
457				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
458			}
459			else if (param[i].mType == LLCDParam::LLCD_BOOLEAN)
460			{
461				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mBool);
462			}
463			else if (param[i].mType == LLCDParam::LLCD_ENUM)
464			{
465				mDecompParams[param[i].mName] = LLSD(param[i].mDefault.mIntOrEnumValue);
466			}
467		}
468	}
469
470	mDecompParams["Simplify Method"] = 0; // set it to retain %
471}
472
473/*virtual*/
474void LLFloaterModelWizard::onPermissionsReceived(const LLSD& result)
475{
476	std::string upload_status = result["mesh_upload_status"].asString();
477	// BAP HACK: handle "" for case that  MeshUploadFlag cap is broken.
478	mHasUploadPerm = (("" == upload_status) || ("valid" == upload_status));
479
480	getChildView("warning_label")->setVisible(!mHasUploadPerm);
481	getChildView("warning_text")->setVisible(!mHasUploadPerm);
482}
483
484/*virtual*/
485void LLFloaterModelWizard::setPermissonsErrorStatus(U32 status, const std::string& reason)
486{
487	llwarns << "LLFloaterModelWizard::setPermissonsErrorStatus(" << status << " : " << reason << ")" << llendl;
488}
489
490/*virtual*/
491void LLFloaterModelWizard::onModelPhysicsFeeReceived(const LLSD& result, std::string upload_url)
492{
493	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true);
494
495	// Enable the "Upload" buton if we have calculated the upload fee
496	// and have the permission to upload.
497	getChildView("upload")->setEnabled(mHasUploadPerm);
498
499	mUploadModelUrl = upload_url;
500
501	S32 fee = result["upload_price"].asInteger();
502	childSetTextArg("review_fee", "[FEE]", llformat("%d", fee));
503	childSetTextArg("charged_fee", "[FEE]", llformat("%d", fee));
504
505	setState(REVIEW);
506}
507
508/*virtual*/
509void LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(U32 status, const std::string& reason)
510{
511	swap_controls(mCalculateWeightsBtn, mCalculatingWeightsBtn, true);
512
513	// Disable the "Review" step if it has been previously enabled.
514	modelChangedCallback();
515
516	llwarns << "LLFloaterModelWizard::setModelPhysicsFeeErrorStatus(" << status << " : " << reason << ")" << llendl;
517
518	setState(PHYSICS);
519}
520
521/*virtual*/ 
522void LLFloaterModelWizard::onModelUploadSuccess() 
523{
524	// success!
525	setState(UPLOAD);
526}
527
528/*virtual*/
529void LLFloaterModelWizard::onModelUploadFailure()
530{
531	// Failure. Make the user recalculate fees
532	setState(PHYSICS);
533	// Disable the "Review" step if it has been previously enabled.
534	if (mLastEnabledState > PHYSICS)
535	{
536		 mLastEnabledState = PHYSICS;
537	}
538
539	updateButtons();
540}
541
542//static
543void LLFloaterModelWizard::executePhysicsStage(std::string stage_name)
544{
545	if (sInstance)
546	{
547		// Invert the slider value so that "performance" end is giving the least detailed physics,
548		// and the "accuracy" end is giving the most detailed physics
549		F64 physics_accuracy = 1 - sInstance->getChild<LLSliderCtrl>("physics_slider")->getValue().asReal();
550
551		sInstance->mDecompParams["Retain%"] = physics_accuracy;
552
553		if (!sInstance->mCurRequest.empty())
554		{
555			llinfos << "Decomposition request still pending." << llendl;
556			return;
557		}
558
559		if (sInstance->mModelPreview)
560		{
561			for (S32 i = 0; i < sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS].size(); ++i)
562			{
563				LLModel* mdl = sInstance->mModelPreview->mModel[LLModel::LOD_PHYSICS][i];
564				DecompRequest* request = new DecompRequest(stage_name, mdl);
565				if(request->isValid())
566				{
567					sInstance->mCurRequest.insert(request);
568					gMeshRepo.mDecompThread->submitRequest(request);
569				}				
570			}
571		}
572	}
573}
574
575LLFloaterModelWizard::DecompRequest::DecompRequest(const std::string& stage, LLModel* mdl)
576{
577	mStage = stage;
578	mContinue = 1;
579	mModel = mdl;
580	mDecompID = &mdl->mDecompID;
581	mParams = sInstance->mDecompParams;
582
583	//copy out positions and indices
584	assignData(mdl) ;	
585}
586
587
588S32 LLFloaterModelWizard::DecompRequest::statusCallback(const char* status, S32 p1, S32 p2)
589{
590	setStatusMessage(llformat("%s: %d/%d", status, p1, p2));
591
592	return mContinue;
593}
594
595void LLFloaterModelWizard::DecompRequest::completed()
596{ //called from the main thread
597	mModel->setConvexHullDecomposition(mHull);
598
599	if (sInstance)
600	{
601		if (sInstance->mModelPreview)
602		{
603			sInstance->mModelPreview->mDirty = true;
604			LLFloaterModelWizard::sInstance->mModelPreview->refresh();
605		}
606
607		sInstance->mCurRequest.erase(this);
608	}
609
610	if (mStage == "Decompose")
611	{
612		executePhysicsStage("Simplify");
613	}
614	else
615	{
616		// Decomp request is complete so we can enable the "Recalculate physics" button again.
617		swap_controls(sInstance->mRecalculatePhysicsBtn, sInstance->mRecalculatingPhysicsBtn, true);
618	}
619}
620
621
622BOOL LLFloaterModelWizard::postBuild()
623{
624	childSetValue("import_scale", (F32) 0.67335826);
625
626	getChild<LLUICtrl>("browse")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this));
627	//getChild<LLUICtrl>("lod_file")->setCommitCallback(boost::bind(&LLFloaterModelWizard::loadModel, this));
628	getChild<LLUICtrl>("cancel")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this));
629	getChild<LLUICtrl>("close")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCancel, this));
630	getChild<LLUICtrl>("back")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickBack, this));
631	getChild<LLUICtrl>("next")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickNext, this));
632	getChild<LLUICtrl>("preview_lod_combo")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1));
633	getChild<LLUICtrl>("preview_lod_combo2")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onPreviewLODCommit, this, _1));
634	getChild<LLUICtrl>("upload")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onUpload, this));
635	getChild<LLUICtrl>("switch_to_advanced")->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickSwitchToAdvanced, this));
636
637	mRecalculateGeometryBtn = getChild<LLButton>("recalculate_geometry_btn");
638	mRecalculateGeometryBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculateGeometry, this));
639
640	mRecalculatePhysicsBtn = getChild<LLButton>("recalculate_physics_btn");
641	mRecalculatePhysicsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickRecalculatePhysics, this));
642
643	mRecalculatingPhysicsBtn = getChild<LLButton>("recalculating_physics_btn");
644
645	mCalculateWeightsBtn = getChild<LLButton>("calculate");
646	mCalculateWeightsBtn->setCommitCallback(boost::bind(&LLFloaterModelWizard::onClickCalculateUploadFee, this));
647
648	mCalculatingWeightsBtn = getChild<LLButton>("calculating");
649
650	mChooseFilePreviewPanel = getChild<LLView>("choose_file_preview_panel");
651	mOptimizePreviewPanel = getChild<LLView>("optimize_preview_panel");
652	mPhysicsPreviewPanel = getChild<LLView>("physics_preview_panel");
653
654	LLUICtrl::EnableCallbackRegistry::ScopedRegistrar enable_registrar;
655	
656	enable_registrar.add("Next.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableNext, this));
657	enable_registrar.add("Back.OnEnable", boost::bind(&LLFloaterModelWizard::onEnableBack, this));
658	
659	mModelPreview = new LLModelPreview(512, 512, this);
660	mModelPreview->setPreviewTarget(16.f);
661	mModelPreview->setDetailsCallback(boost::bind(&LLFloaterModelWizard::setDetails, this, _1, _2, _3, _4, _5));
662	mModelPreview->setModelLoadedCallback(boost::bind(&LLFloaterModelWizard::modelLoadedCallback, this));
663	mModelPreview->setModelUpdatedCallback(boost::bind(&LLFloaterModelWizard::modelChangedCallback, this));
664	mModelPreview->mViewOption["show_textures"] = true;
665
666	center();
667
668	setState(CHOOSE_FILE);
669
670	childSetTextArg("import_dimensions", "[X]", LLStringUtil::null);
671	childSetTextArg("import_dimensions", "[Y]", LLStringUtil::null);
672	childSetTextArg("import_dimensions", "[Z]", LLStringUtil::null);
673
674	initDecompControls();
675
676	requestAgentUploadPermissions();
677
678	return TRUE;
679}
680
681
682void LLFloaterModelWizard::setDetails(F32 x, F32 y, F32 z, F32 streaming_cost, F32 physics_cost)
683{
684	// iterate through all the panels, setting the dimensions
685	for(size_t t=0; t<LL_ARRAY_SIZE(stateNames); ++t)
686	{
687		LLPanel *panel = getChild<LLPanel>(stateNames[t]+"_panel");
688		if (panel) 
689		{
690			panel->childSetText("dimension_x", llformat("%.1f", x));
691			panel->childSetText("dimension_y", llformat("%.1f", y));
692			panel->childSetText("dimension_z", llformat("%.1f", z));
693		}
694	}
695
696	childSetTextArg("review_prim_equiv", "[EQUIV]", llformat("%d", mModelPreview->mResourceCost));
697}
698
699void LLFloaterModelWizard::modelLoadedCallback()
700{
701	mLastEnabledState = CHOOSE_FILE;
702	updateButtons();
703}
704
705void LLFloaterModelWizard::modelChangedCallback()
706{
707	// Don't allow to proceed to the "Review" step if the model has changed
708	// but the new upload fee hasn't been calculated yet.
709	if (mLastEnabledState > PHYSICS)
710	{
711		 mLastEnabledState = PHYSICS;
712	}
713
714	getChildView("upload")->setEnabled(false);
715
716	updateButtons();
717}
718
719void LLFloaterModelWizard::onUpload()
720{	
721	mModelPreview->rebuildUploadData();
722	
723	gMeshRepo.uploadModel(mModelPreview->mUploadData, mModelPreview->mPreviewScale, 
724						  true, false, false, mUploadModelUrl, true,
725						  LLHandle<LLWholeModelFeeObserver>(), getWholeModelUploadObserverHandle());
726}
727
728void LLFloaterModelWizard::onPreviewLODCommit(LLUICtrl* ctrl)
729{
730	if (!mModelPreview)
731	{
732		return;
733	}
734	
735	S32 which_mode = 0;
736	
737	LLComboBox* combo = (LLComboBox*) ctrl;
738	
739	which_mode = (NUM_LOD-1)-combo->getFirstSelectedIndex(); // combo box list of lods is in reverse order
740
741	mModelPreview->setPreviewLOD(which_mode);
742}
743
744void LLFloaterModelWizard::refresh()
745{
746	if (mState == CHOOSE_FILE)
747	{
748		bool model_loaded = false;
749
750		if (mModelPreview && mModelPreview->getLoadState() == LLModelLoader::DONE)
751		{
752			model_loaded = true;
753		}
754		
755		getChildView("next")->setEnabled(model_loaded);
756	}
757}
758
759void LLFloaterModelWizard::draw()
760{
761	refresh();
762
763	LLFloater::draw();
764
765	if (mModelPreview && mState < REVIEW)
766	{
767		mModelPreview->update();
768
769		gGL.color3f(1.f, 1.f, 1.f);
770		
771		gGL.getTexUnit(0)->bind(mModelPreview);
772		
773		gGL.begin( LLRender::QUADS );
774		{
775			gGL.texCoord2f(0.f, 1.f);
776			gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mTop);
777			gGL.texCoord2f(0.f, 0.f);
778			gGL.vertex2i(mPreviewRect.mLeft, mPreviewRect.mBottom);
779			gGL.texCoord2f(1.f, 0.f);
780			gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mBottom);
781			gGL.texCoord2f(1.f, 1.f);
782			gGL.vertex2i(mPreviewRect.mRight, mPreviewRect.mTop);
783		}
784		gGL.end();
785		
786		gGL.getTexUnit(0)->unbind(LLTexUnit::TT_TEXTURE);
787	}
788}
789
790// static
791void swap_controls(LLUICtrl* first_ctrl, LLUICtrl* second_ctrl, bool first_ctr_visible)
792{
793	first_ctrl->setVisible(first_ctr_visible);
794	second_ctrl->setVisible(!first_ctr_visible);
795}