llpreviewtexture.cpp

Go to the documentation of this file.
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 // Note: uses asset_id as a dummy item id.
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                         // ...border
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                                 // Draw the texture
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                                 // Pump the texture priority
00227                                 F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA  : (F32)(interior.getWidth() * interior.getHeight() );
00228                                 mImage->addTextureStats( pixel_area );
00229 
00230                                 // Don't bother decoding more than we can display, unless
00231                                 // we're loading the full image.
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                                         // Don't use this feature
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                                         // Draw the progress bar.
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                                                 // Downloaded bytes
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 // virtual
00295 BOOL LLPreviewTexture::canSaveAs()
00296 {
00297         return mIsCopyable && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
00298 }
00299 
00300 
00301 // virtual
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                         // User canceled save.
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 // static
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 // It takes a while until we get height and width information.
00383 // When we receive it, reshape the window accordingly.
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         // Attempt to make the image 1:1 on screen.
00391         // If that fails, cut width by half.
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         // Adjust the height based on the width computed above.
00408         S32 client_height = llround(client_width * inv_aspect_ratio);
00409         S32 view_height = client_height + vert_pad;
00410 
00411         
00412         // set text on dimensions display (should be moved out of here and into a callback of some sort)
00413         childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
00414         childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
00415         
00416         // add space for dimensions
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) {  //mCopyToInvBtn
00426 
00427                 // add space for buttons
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                         // Try to keep whole view onscreen, don't allow partial offscreen.
00449                         gFloaterView->adjustToFitScreen(this, FALSE);
00450                 }
00451         }
00452 
00453         
00454         if (!mUserResized)
00455         {
00456                 // clamp texture size to fit within actual size of floater after attempting resize
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         // try to keep aspect ratio when hosted, as hosting view can resize without user input
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 }

Generated on Thu Jul 1 06:09:02 2010 for Second Life Viewer by  doxygen 1.4.7