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 "llvieweruictrlfactory.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 gUICtrlFactory->buildFloater(this,"floater_preview_embedded_texture.xml");
00163
00164 childSetAction("Copy To Inventory",LLPreview::onBtnCopyToInv,this);
00165 }
00166
00167 else if (mShowKeepDiscard)
00168 {
00169 gUICtrlFactory->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 gUICtrlFactory->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 if( getVisible() )
00197 {
00198 updateAspectRatio();
00199
00200 LLPreview::draw();
00201
00202 if (!mMinimized)
00203 {
00204 LLGLSUIDefault gls_ui;
00205 LLGLSNoTexture gls_notex;
00206
00207 const LLRect& border = mClientRect;
00208 LLRect interior = mClientRect;
00209 interior.stretch( -PREVIEW_BORDER_WIDTH );
00210
00211
00212 gl_rect_2d( border, LLColor4(0.f, 0.f, 0.f, 1.f));
00213 gl_rect_2d_checkerboard( interior );
00214
00215 if ( mImage.notNull() )
00216 {
00217 LLGLSTexture gls_no_texture;
00218
00219 glColor3f( 1.f, 1.f, 1.f );
00220 gl_draw_scaled_image(interior.mLeft,
00221 interior.mBottom,
00222 interior.getWidth(),
00223 interior.getHeight(),
00224 mImage);
00225
00226
00227 F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA : (F32)(interior.getWidth() * interior.getHeight() );
00228 mImage->addTextureStats( pixel_area );
00229
00230
00231
00232 if (!mLoadingFullImage)
00233 {
00234 S32 int_width = interior.getWidth();
00235 S32 int_height = interior.getHeight();
00236 mImage->setKnownDrawSize(int_width, int_height);
00237 }
00238 else
00239 {
00240
00241 mImage->setKnownDrawSize(0, 0);
00242 }
00243
00244 if( mLoadingFullImage )
00245 {
00246 LLFontGL::sSansSerif->renderUTF8("Receiving:", 0,
00247 interior.mLeft + 4,
00248 interior.mBottom + 4,
00249 LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
00250 LLFontGL::DROP_SHADOW);
00251
00252 F32 data_progress = mImage->mDownloadProgress;
00253
00254
00255 const S32 BAR_HEIGHT = 12;
00256 const S32 BAR_LEFT_PAD = 80;
00257 S32 left = interior.mLeft + 4 + BAR_LEFT_PAD;
00258 S32 bar_width = mRect.getWidth() - left - RESIZE_HANDLE_WIDTH - 2;
00259 S32 top = interior.mBottom + 4 + BAR_HEIGHT;
00260 S32 right = left + bar_width;
00261 S32 bottom = top - BAR_HEIGHT;
00262
00263 LLColor4 background_color(0.f, 0.f, 0.f, 0.75f);
00264 LLColor4 decoded_color(0.f, 1.f, 0.f, 1.0f);
00265 LLColor4 downloaded_color(0.f, 0.5f, 0.f, 1.0f);
00266
00267 gl_rect_2d(left, top, right, bottom, background_color);
00268
00269 if (data_progress > 0.0f)
00270 {
00271
00272 right = left + llfloor(data_progress * (F32)bar_width);
00273 if (right > left)
00274 {
00275 gl_rect_2d(left, top, right, bottom, downloaded_color);
00276 }
00277 }
00278 }
00279 else
00280 if( !mSavedFileTimer.hasExpired() )
00281 {
00282 LLFontGL::sSansSerif->renderUTF8("File Saved", 0,
00283 interior.mLeft + 4,
00284 interior.mBottom + 4,
00285 LLColor4::white, LLFontGL::LEFT, LLFontGL::BOTTOM,
00286 LLFontGL::DROP_SHADOW);
00287 }
00288 }
00289 }
00290 }
00291 }
00292
00293
00294
00295 BOOL LLPreviewTexture::canSaveAs()
00296 {
00297 return mIsCopyable && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
00298 }
00299
00300
00301
00302 void LLPreviewTexture::saveAs()
00303 {
00304 if( !mLoadingFullImage )
00305 {
00306 LLFilePicker& file_picker = LLFilePicker::instance();
00307 if( !file_picker.getSaveFile( LLFilePicker::FFSAVE_TGA ) )
00308 {
00309
00310 return;
00311 }
00312 mSaveFileName = file_picker.getFirstFile();
00313 mLoadingFullImage = TRUE;
00314 getWindow()->incBusyCount();
00315 mImage->setLoadedCallback( LLPreviewTexture::onFileLoadedForSave,
00316 0,
00317 TRUE,
00318 new LLUUID( mItemUUID ) );
00319 }
00320 }
00321
00322
00323
00324 void LLPreviewTexture::onFileLoadedForSave(BOOL success,
00325 LLViewerImage *src_vi,
00326 LLImageRaw* src,
00327 LLImageRaw* aux_src,
00328 S32 discard_level,
00329 BOOL final,
00330 void* userdata)
00331 {
00332 LLUUID* item_uuid = (LLUUID*) userdata;
00333 LLPreviewTexture* self = NULL;
00334 preview_map_t::iterator found_it = LLPreview::sInstances.find(*item_uuid);
00335 if(found_it != LLPreview::sInstances.end())
00336 {
00337 self = (LLPreviewTexture*) found_it->second;
00338 }
00339
00340 if( final || !success )
00341 {
00342 delete item_uuid;
00343
00344 if( self )
00345 {
00346 self->getWindow()->decBusyCount();
00347 self->mLoadingFullImage = FALSE;
00348 }
00349 }
00350
00351 if( self && final && success )
00352 {
00353 LLPointer<LLImageTGA> image_tga = new LLImageTGA;
00354 if( !image_tga->encode( src ) )
00355 {
00356 LLStringBase<char>::format_map_t args;
00357 args["[FILE]"] = self->mSaveFileName;
00358 gViewerWindow->alertXml("CannotEncodeFile", args);
00359 }
00360 else if( !image_tga->save( self->mSaveFileName ) )
00361 {
00362 LLStringBase<char>::format_map_t args;
00363 args["[FILE]"] = self->mSaveFileName;
00364 gViewerWindow->alertXml("CannotWriteFile", args);
00365 }
00366 else
00367 {
00368 self->mSavedFileTimer.reset();
00369 self->mSavedFileTimer.setTimerExpirySec( SECONDS_TO_SHOW_FILE_SAVED_MSG );
00370 }
00371
00372 self->mSaveFileName.clear();
00373 }
00374
00375 if( self && !success )
00376 {
00377 gViewerWindow->alertXml("CannotDownloadFile");
00378 }
00379 }
00380
00381
00382
00383
00384 void LLPreviewTexture::updateAspectRatio()
00385 {
00386 if (!mImage) return;
00387
00388 S32 image_height = llmax(1, mImage->getHeight(0));
00389 S32 image_width = llmax(1, mImage->getWidth(0));
00390
00391
00392 S32 client_width = image_width;
00393 S32 horiz_pad = 2 * (LLPANEL_BORDER_WIDTH + PREVIEW_PAD) + PREVIEW_RESIZE_HANDLE_SIZE;
00394 S32 vert_pad = PREVIEW_HEADER_SIZE + 2 * CLIENT_RECT_VPAD + LLPANEL_BORDER_WIDTH;
00395 S32 screen_width = gViewerWindow->getWindowWidth();
00396 S32 max_client_width = screen_width - horiz_pad;
00397 S32 max_client_height = gViewerWindow->getWindowHeight() - vert_pad;
00398 F32 inv_aspect_ratio = (F32) image_height / (F32) image_width;
00399
00400 while ((client_width > max_client_width) || ( llround(client_width * inv_aspect_ratio) > max_client_height ) )
00401 {
00402 client_width /= 2;
00403 }
00404
00405 S32 view_width = client_width + horiz_pad;
00406
00407
00408 S32 client_height = llround(client_width * inv_aspect_ratio);
00409 S32 view_height = client_height + vert_pad;
00410
00411
00412
00413 childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
00414 childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
00415
00416
00417 S32 info_height = 0;
00418 LLRect dim_rect;
00419 childGetRect("dimensions", dim_rect);
00420 S32 dim_height = dim_rect.getHeight();
00421 info_height += dim_height + CLIENT_RECT_VPAD;
00422 view_height += info_height;
00423
00424 S32 button_height = 0;
00425 if (mShowKeepDiscard || mCopyToInv) {
00426
00427
00428 view_height += BTN_HEIGHT + CLIENT_RECT_VPAD;
00429 button_height = BTN_HEIGHT + PREVIEW_PAD;
00430 }
00431
00432 if (client_height != mLastHeight || client_width != mLastWidth)
00433 {
00434 mLastWidth = client_width;
00435 mLastHeight = client_height;
00436
00437 S32 old_top = mRect.mTop;
00438 S32 old_left = mRect.mLeft;
00439 if (getHost())
00440 {
00441 getHost()->growToFit(view_width, view_height);
00442 }
00443 else
00444 {
00445 reshape( view_width, view_height );
00446 S32 new_bottom = old_top - mRect.getHeight();
00447 setOrigin( old_left, new_bottom );
00448
00449 gFloaterView->adjustToFitScreen(this, FALSE);
00450 }
00451 }
00452
00453
00454 if (!mUserResized)
00455 {
00456
00457 client_width = llmin(client_width, mRect.getWidth() - horiz_pad);
00458 client_height = llmin(client_height, mRect.getHeight() - PREVIEW_HEADER_SIZE
00459 - (2 * CLIENT_RECT_VPAD) - LLPANEL_BORDER_WIDTH - info_height);
00460
00461
00462 }
00463 else
00464 {
00465 client_width = mRect.getWidth() - horiz_pad;
00466 client_height = llround(client_width * inv_aspect_ratio);
00467 }
00468
00469
00470 S32 max_height = mRect.getHeight() - PREVIEW_BORDER - button_height
00471 - CLIENT_RECT_VPAD - info_height - CLIENT_RECT_VPAD - PREVIEW_HEADER_SIZE;
00472 max_height = llmax(max_height, 1);
00473
00474 if (client_height > max_height)
00475 {
00476 F32 aspect_ratio = (F32) image_width / (F32) image_height;
00477 client_height = max_height;
00478 client_width = llround(client_height * aspect_ratio);
00479 }
00480
00481 LLRect window_rect(0, mRect.getHeight(), mRect.getWidth(), 0);
00482 window_rect.mTop -= (PREVIEW_HEADER_SIZE + CLIENT_RECT_VPAD);
00483 window_rect.mBottom += PREVIEW_BORDER + button_height + CLIENT_RECT_VPAD + info_height + CLIENT_RECT_VPAD;
00484
00485
00486 mClientRect.setLeftTopAndSize(window_rect.getCenterX() - (client_width / 2), window_rect.mTop, client_width, client_height);
00487 }
00488
00489
00490 void LLPreviewTexture::loadAsset()
00491 {
00492 mImage = gImageList.getImage(mImageID, MIPMAP_TRUE, FALSE);
00493 mImage->setBoostLevel(LLViewerImage::BOOST_PREVIEW);
00494 mAssetStatus = PREVIEW_ASSET_LOADING;
00495 }
00496
00497 LLPreview::EAssetStatus LLPreviewTexture::getAssetStatus()
00498 {
00499 if (mImage.notNull() && (mImage->mFullWidth * mImage->mFullHeight > 0))
00500 {
00501 mAssetStatus = PREVIEW_ASSET_LOADED;
00502 }
00503 return mAssetStatus;
00504 }