00001
00032 #include "llviewerprecompiledheaders.h"
00033
00034 #include "llpreviewtexture.h"
00035
00036 #include "llagent.h"
00037 #include "llbutton.h"
00038 #include "llfilepicker.h"
00039 #include "llimagetga.h"
00040 #include "llinventoryview.h"
00041 #include "llinventory.h"
00042 #include "llresmgr.h"
00043 #include "lltextbox.h"
00044 #include "lltextureview.h"
00045 #include "llui.h"
00046 #include "llviewerimage.h"
00047 #include "llviewerimagelist.h"
00048 #include "lluictrlfactory.h"
00049 #include "llviewerwindow.h"
00050 #include "lllineeditor.h"
00051
00052 const S32 PREVIEW_TEXTURE_MIN_WIDTH = 300;
00053 const S32 PREVIEW_TEXTURE_MIN_HEIGHT = 120;
00054
00055 const S32 CLIENT_RECT_VPAD = 4;
00056
00057 const F32 SECONDS_TO_SHOW_FILE_SAVED_MSG = 8.f;
00058
00059 LLPreviewTexture::LLPreviewTexture(const std::string& name,
00060 const LLRect& rect,
00061 const std::string& title,
00062 const LLUUID& item_uuid,
00063 const LLUUID& object_id,
00064 BOOL show_keep_discard)
00065 : LLPreview(name, rect, title, item_uuid, object_id, TRUE, PREVIEW_TEXTURE_MIN_WIDTH, PREVIEW_TEXTURE_MIN_HEIGHT ),
00066 mLoadingFullImage( FALSE ),
00067 mShowKeepDiscard(show_keep_discard),
00068 mCopyToInv(FALSE),
00069 mIsCopyable(FALSE),
00070 mLastHeight(0),
00071 mLastWidth(0)
00072 {
00073 const LLInventoryItem *item = getItem();
00074 if(item)
00075 {
00076 mImageID = item->getAssetUUID();
00077 const LLPermissions& perm = item->getPermissions();
00078 U32 mask = PERM_NONE;
00079 if(perm.getOwner() == gAgent.getID())
00080 {
00081 mask = perm.getMaskBase();
00082 }
00083 else if(gAgent.isInGroup(perm.getGroup()))
00084 {
00085 mask = perm.getMaskGroup();
00086 }
00087 else
00088 {
00089 mask = perm.getMaskEveryone();
00090 }
00091 if((mask & PERM_ITEM_UNRESTRICTED) == PERM_ITEM_UNRESTRICTED)
00092 {
00093 mIsCopyable = TRUE;
00094 }
00095 }
00096
00097 init();
00098
00099 setTitle(title);
00100
00101 if (!getHost())
00102 {
00103 LLRect curRect = getRect();
00104 translate(rect.mLeft - curRect.mLeft, rect.mTop - curRect.mTop);
00105 }
00106 }
00107
00108
00109
00110 LLPreviewTexture::LLPreviewTexture(
00111 const std::string& name,
00112 const LLRect& rect,
00113 const std::string& title,
00114 const LLUUID& asset_id,
00115 BOOL copy_to_inv)
00116 :
00117 LLPreview(
00118 name,
00119 rect,
00120 title,
00121 asset_id,
00122 LLUUID::null,
00123 TRUE,
00124 PREVIEW_TEXTURE_MIN_WIDTH,
00125 PREVIEW_TEXTURE_MIN_HEIGHT ),
00126 mImageID(asset_id),
00127 mLoadingFullImage( FALSE ),
00128 mShowKeepDiscard(FALSE),
00129 mCopyToInv(copy_to_inv),
00130 mIsCopyable(TRUE),
00131 mLastHeight(0),
00132 mLastWidth(0)
00133 {
00134
00135 init();
00136
00137 setTitle(title);
00138
00139 LLRect curRect = getRect();
00140 translate(curRect.mLeft - rect.mLeft, curRect.mTop - rect.mTop);
00141
00142 }
00143
00144
00145 LLPreviewTexture::~LLPreviewTexture()
00146 {
00147 if( mLoadingFullImage )
00148 {
00149 getWindow()->decBusyCount();
00150 }
00151
00152 mImage = NULL;
00153 }
00154
00155
00156 void LLPreviewTexture::init()
00157 {
00158
00159
00160 if (mCopyToInv)
00161 {
00162 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_embedded_texture.xml");
00163
00164 childSetAction("Copy To Inventory",LLPreview::onBtnCopyToInv,this);
00165 }
00166
00167 else if (mShowKeepDiscard)
00168 {
00169 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_texture_keep_discard.xml");
00170
00171 childSetAction("Keep",onKeepBtn,this);
00172 childSetAction("Discard",onDiscardBtn,this);
00173 }
00174
00175 else
00176 {
00177 LLUICtrlFactory::getInstance()->buildFloater(this,"floater_preview_texture.xml");
00178 }
00179
00180
00181 if (!mCopyToInv)
00182 {
00183 const LLInventoryItem* item = getItem();
00184
00185 if (item)
00186 {
00187 childSetCommitCallback("desc", LLPreview::onText, this);
00188 childSetText("desc", item->getDescription());
00189 childSetPrevalidate("desc", &LLLineEditor::prevalidatePrintableNotPipe);
00190 }
00191 }
00192 }
00193
00194 void LLPreviewTexture::draw()
00195 {
00196 updateDimensions();
00197
00198 LLPreview::draw();
00199
00200 if (!isMinimized())
00201 {
00202 LLGLSUIDefault gls_ui;
00203 LLGLSNoTexture gls_notex;
00204
00205 const LLRect& border = mClientRect;
00206 LLRect interior = mClientRect;
00207 interior.stretch( -PREVIEW_BORDER_WIDTH );
00208
00209
00210 gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
00211 gl_rect_2d_checkerboard( interior );
00212
00213 if ( mImage.notNull() )
00214 {
00215
00216 glColor3f( 1.f, 1.f, 1.f );
00217 gl_draw_scaled_image(interior.mLeft,
00218 interior.mBottom,
00219 interior.getWidth(),
00220 interior.getHeight(),
00221 mImage);
00222
00223
00224 F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
00225 mImage->addTextureStats( pixel_area );
00226
00227
00228
00229 if (!mLoadingFullImage)
00230 {
00231 S32 int_width = interior.getWidth();
00232 S32 int_height = interior.getHeight();
00233 mImage->setKnownDrawSize(int_width, int_height);
00234 }
00235 else
00236 {
00237
00238 mImage->setKnownDrawSize(0, 0);
00239 }
00240
00241 if( mLoadingFullImage )
00242 {
00243 LLFontGL::sSansSerif->renderUTF8("Receiving:", 0,
00244 interior.mLeft + 4,
00245 interior.mBottom + 4,
00246 LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
00247 LLFontGL::DROP_SHADOW);
00248
00249 F32 data_progress = mImage->mDownloadProgress;
00250
00251
00252 const S32 BAR_HEIGHT = 12;
00253 const S32 BAR_LEFT_PAD = 80;
00254 S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
00255 S32 bar_width = getRect().getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
00256 S32 top = interior.mBottom + 4 + BAR_HEIGHT;
00257 S32 right = left + bar_width;
00258 S32 bottom = top - BAR_HEIGHT;
00259
00260 LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
00261 LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
00262 LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
00263
00264 gl_rect_2d(left, top, right, bottom, background_color);
00265
00266 if (data_progress > 0.0f)
00267 {
00268
00269 right = left + llfloor(data_progress * (F32)bar_width);
00270 if (right > left)
00271 {
00272 gl_rect_2d(left, top, right, bottom, downloaded_color);
00273 }
00274 }
00275 }
00276 else
00277 if( !mSavedFileTimer.hasExpired() )
00278 {
00279 LLFontGL::sSansSerif->renderUTF8("File Saved", 0,
00280 interior.mLeft + 4,
00281 interior.mBottom + 4,
00282 LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
00283 LLFontGL::DROP_SHADOW);
00284 }
00285 }
00286 }
00287 }
00288
00289
00290
00291 BOOL LLPreviewTexture::canSaveAs() const
00292 {
00293 return mIsCopyable && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
00294 }
00295
00296
00297
00298 void LLPreviewTexture::saveAs()
00299 {
00300 if( !mLoadingFullImage )
00301 {
00302 LLFilePicker& file_picker = LLFilePicker::instance();
00303 if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA ) )
00304 {
00305
00306 return;
00307 }
00308 mSaveFileName = file_picker.getFirstFile();
00309 mLoadingFullImage = TRUE;
00310 getWindow()->incBusyCount();
00311 mImage->setLoadedCallback( LLPreviewTexture::onFileLoadedForSave,
00312 0,
00313 TRUE,
00314 new LLUUID( mItemUUID ) );
00315 }
00316 }
00317
00318
00319
00320 void LLPreviewTexture::onFileLoadedForSave(BOOL success,
00321 LLViewerImage *src_vi,
00322 LLImageRaw* src,
00323 LLImageRaw* aux_src,
00324 S32 discard_level,
00325 BOOL final,
00326 void* userdata)
00327 {
00328 LLUUID* item_uuid = (LLUUID*) userdata;
00329 LLPreviewTexture* self = NULL;
00330 preview_map_t::iterator found_it = LLPreview::sInstances.find(*item_uuid);
00331 if(found_it != LLPreview::sInstances.end())
00332 {
00333 self = (LLPreviewTexture*) found_it->second;
00334 }
00335
00336 if( final || !success )
00337 {
00338 delete item_uuid;
00339
00340 if( self )
00341 {
00342 self->getWindow()->decBusyCount();
00343 self->mLoadingFullImage = FALSE;
00344 }
00345 }
00346
00347 if( self && final && success )
00348 {
00349 LLPointer<LLImageTGA> image_tga = new LLImageTGA;
00350 if( !image_tga->encode( src ) )
00351 {
00352 LLStringBase<char>::format_map_t args;
00353 args["[FILE]"] = self->mSaveFileName;
00354 gViewerWindow->alertXml("CannotEncodeFile", args);
00355 }
00356 else if( !image_tga->save( self->mSaveFileName ) )
00357 {
00358 LLStringBase<char>::format_map_t args;
00359 args["[FILE]"] = self->mSaveFileName;
00360 gViewerWindow->alertXml("CannotWriteFile", args);
00361 }
00362 else
00363 {
00364 self->mSavedFileTimer.reset();
00365 self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG );
00366 }
00367
00368 self->mSaveFileName.clear();
00369 }
00370
00371 if( self && !success )
00372 {
00373 gViewerWindow->alertXml("CannotDownloadFile");
00374 }
00375 }
00376
00377
00378
00379
00380 void LLPreviewTexture::updateDimensions()
00381 {
00382 if (!mImage) return;
00383
00384 S32 image_height = llmax(1, mImage->getHeight(0));
00385 S32 image_width = llmax(1, mImage->getWidth(0));
00386
00387
00388 S32 client_width = image_width;
00389 S32 client_height = image_height;
00390 S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
00391 S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH;
00392 S32 max_client_width = gViewerWindow->getWindowWidth() - horiz_pad;
00393 S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad;
00394
00395 while ((client_width > max_client_width) ||
00396 (client_height > max_client_height ) )
00397 {
00398 client_width /= 2;
00399 client_height /= 2;
00400 }
00401
00402 S32 view_width = client_width + horiz_pad;
00403 S32 view_height = client_height + vert_pad;
00404
00405
00406 childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
00407 childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
00408
00409
00410 S32 info_height = 0;
00411 LLRect dim_rect;
00412 childGetRect("dimensions", dim_rect);
00413 S32 dim_height = dim_rect.getHeight();
00414 info_height += dim_height + CLIENT_RECT_VPAD;
00415 view_height += info_height;
00416
00417 S32 button_height = 0;
00418 if (mShowKeepDiscard || mCopyToInv) {
00419
00420
00421 view_height += BTN_HEIGHT + CLIENT_RECT_VPAD;
00422 button_height = BTN_HEIGHT + PREVIEW_PAD;
00423 }
00424
00425 view_width = llmax(view_width, getMinWidth());
00426 view_height = llmax(view_height, getMinHeight());
00427
00428 if (client_height != mLastHeight || client_width != mLastWidth)
00429 {
00430 mLastWidth = client_width;
00431 mLastHeight = client_height;
00432
00433 S32 old_top = getRect().mTop;
00434 S32 old_left = getRect().mLeft;
00435 if (getHost())
00436 {
00437 getHost()->growToFit(view_width, view_height);
00438 }
00439 else
00440 {
00441 reshape( view_width, view_height );
00442 S32 new_bottom = old_top - getRect().getHeight();
00443 setOrigin( old_left, new_bottom );
00444
00445 gFloaterView->adjustToFitScreen(this, FALSE);
00446 }
00447 }
00448
00449
00450 if (!mUserResized)
00451 {
00452
00453 client_width = llmin(client_width, getRect().getWidth() - horiz_pad);
00454 client_height = llmin(client_height, getRect().getHeight() - PREVIEW_HEADER_SIZE
00455 - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height);
00456
00457
00458 }
00459 else
00460 {
00461 client_width = getRect().getWidth() - horiz_pad;
00462 client_height = getRect().getHeight() - vert_pad;
00463 }
00464
00465 S32 max_height = getRect().getHeight() - PREVIEW_BORDER - button_height
00466 - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE;
00467 S32 max_width = getRect().getWidth() - horiz_pad;
00468
00469 client_height = llclamp(client_height, 1, max_height);
00470 client_width = llclamp(client_width, 1, max_width);
00471
00472 LLRect window_rect(0, getRect().getHeight(), getRect().getWidth(), 0);
00473 window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
00474 window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD;
00475
00476 mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
00477 }
00478
00479
00480 void LLPreviewTexture::loadAsset()
00481 {
00482 mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE);
00483 mImage->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
00484 mAssetStatus = PREVIEW_ASSET_LOADING;
00485 }
00486
00487 LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
00488 {
00489 if (mImage.notNull() && (mImage->mFullWidth * mImage->mFullHeight > 0))
00490 {
00491 mAssetStatus = PREVIEW_ASSET_LOADED;
00492 }
00493 return mAssetStatus;
00494 }