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 "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 // 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                 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                 // ...border
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                         // Draw the texture
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                         // Pump the texture priority
00224                         F32 pixel_area = mLoadingFullImage ? (F32)MAX_IMAGE_AREA  : (F32)(interior.getWidth() * interior.getHeight() );
00225                         mImage->addTextureStats( pixel_area );
00226 
00227                         // Don't bother decoding more than we can display, unless
00228                         // we're loading the full image.
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                                 // Don't use this feature
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                                 // Draw the progress bar.
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                                         // Downloaded bytes
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 // virtual
00291 BOOL LLPreviewTexture::canSaveAs() const
00292 {
00293         return mIsCopyable && !mLoadingFullImage && mImage.notNull() && !mImage->isMissingAsset();
00294 }
00295 
00296 
00297 // virtual
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                         // User canceled save.
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 // static
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 // It takes a while until we get height and width information.
00379 // When we receive it, reshape the window accordingly.
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         // Attempt to make the image 1:1 on screen.
00387         // If that fails, cut width by half.
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         // set text on dimensions display (should be moved out of here and into a callback of some sort)
00406         childSetTextArg("dimensions", "[WIDTH]", llformat("%d", mImage->mFullWidth));
00407         childSetTextArg("dimensions", "[HEIGHT]", llformat("%d", mImage->mFullHeight));
00408         
00409         // add space for dimensions
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) {  //mCopyToInvBtn
00419 
00420                 // add space for buttons
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                         // Try to keep whole view onscreen, don't allow partial offscreen.
00445                         gFloaterView->adjustToFitScreen(this, FALSE);
00446                 }
00447         }
00448 
00449         
00450         if (!mUserResized)
00451         {
00452                 // clamp texture size to fit within actual size of floater after attempting resize
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 }

Generated on Fri May 16 08:33:58 2008 for SecondLife by  doxygen 1.5.5