phoenix-firestorm/indra/newview/llthumbnailctrl.cpp

239 lines
7.1 KiB
C++

/**
* @file llthumbnailctrl.cpp
* @brief LLThumbnailCtrl base class
*
* $LicenseInfo:firstyear=2023&license=viewerlgpl$
* Second Life Viewer Source Code
* Copyright (C) 2023, Linden Research, Inc.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation;
* version 2.1 of the License only.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*
* Linden Research, Inc., 945 Battery Street, San Francisco, CA 94111 USA
* $/LicenseInfo$
*/
#include "llviewerprecompiledheaders.h"
#include "llthumbnailctrl.h"
#include "linden_common.h"
#include "llagent.h"
#include "lluictrlfactory.h"
#include "lluuid.h"
#include "lltrans.h"
#include "llviewborder.h"
#include "llviewertexture.h"
#include "llviewertexturelist.h"
#include "llwindow.h"
static LLDefaultChildRegistry::Register<LLThumbnailCtrl> r("thumbnail");
LLThumbnailCtrl::Params::Params()
: border("border")
, border_color("border_color")
, fallback_image("fallback_image")
, image_name("image_name")
, border_visible("show_visible", false)
, interactable("interactable", false)
, show_loading("show_loading", true)
{}
LLThumbnailCtrl::LLThumbnailCtrl(const LLThumbnailCtrl::Params& p)
: LLUICtrl(p)
, mBorderColor(p.border_color())
, mBorderVisible(p.border_visible())
, mFallbackImagep(p.fallback_image)
, mInteractable(p.interactable())
, mShowLoadingPlaceholder(p.show_loading())
, mPriority(LLGLTexture::BOOST_PREVIEW)
{
mLoadingPlaceholderString = LLTrans::getString("texture_loading");
LLRect border_rect = getLocalRect();
LLViewBorder::Params vbparams(p.border);
vbparams.name("border");
vbparams.rect(border_rect);
mBorder = LLUICtrlFactory::create<LLViewBorder> (vbparams);
addChild(mBorder);
if (p.image_name.isProvided())
{
setValue(p.image_name());
}
}
LLThumbnailCtrl::~LLThumbnailCtrl()
{
mTexturep = nullptr;
mImagep = nullptr;
mFallbackImagep = nullptr;
}
void LLThumbnailCtrl::draw()
{
LLRect draw_rect = getLocalRect();
if (mBorderVisible)
{
mBorder->setKeyboardFocusHighlight(hasFocus());
gl_rect_2d( draw_rect, mBorderColor.get(), FALSE );
draw_rect.stretch( -1 );
}
// If we're in a focused floater, don't apply the floater's alpha to the texture.
const F32 alpha = getTransparencyType() == TT_ACTIVE ? 1.0f : getCurrentTransparency();
if( mTexturep )
{
if( mTexturep->getComponents() == 4 )
{
gl_rect_2d_checkerboard( draw_rect, alpha );
}
gl_draw_scaled_image( draw_rect.mLeft, draw_rect.mBottom, draw_rect.getWidth(), draw_rect.getHeight(), mTexturep, UI_VERTEX_COLOR % alpha);
mTexturep->setKnownDrawSize(draw_rect.getWidth(), draw_rect.getHeight());
}
else if( mImagep.notNull() )
{
mImagep->draw(draw_rect, UI_VERTEX_COLOR % alpha );
}
else if (mFallbackImagep.notNull())
{
if (draw_rect.getWidth() > mFallbackImagep->getWidth()
&& draw_rect.getHeight() > mFallbackImagep->getHeight())
{
S32 img_width = mFallbackImagep->getWidth();
S32 img_height = mFallbackImagep->getHeight();
S32 rect_width = draw_rect.getWidth();
S32 rect_height = draw_rect.getHeight();
LLRect fallback_rect;
fallback_rect.mLeft = draw_rect.mLeft + (rect_width - img_width) / 2;
fallback_rect.mRight = fallback_rect.mLeft + img_width;
fallback_rect.mBottom = draw_rect.mBottom + (rect_height - img_height) / 2;
fallback_rect.mTop = fallback_rect.mBottom + img_height;
mFallbackImagep->draw(fallback_rect, UI_VERTEX_COLOR % alpha);
}
else
{
mFallbackImagep->draw(draw_rect, UI_VERTEX_COLOR % alpha);
}
}
else
{
gl_rect_2d( draw_rect, LLColor4::grey % alpha, TRUE );
// Draw X
gl_draw_x( draw_rect, LLColor4::black );
}
// Show "Loading..." string on the top left corner while this texture is loading.
// Using the discard level, do not show the string if the texture is almost but not
// fully loaded.
if (mTexturep.notNull()
&& mShowLoadingPlaceholder
&& !mTexturep->isFullyLoaded())
{
U32 v_offset = 25;
LLFontGL* font = LLFontGL::getFontSansSerif();
// Don't show as loaded if the texture is almost fully loaded (i.e. discard1) unless god
if ((mTexturep->getDiscardLevel() > 1) || gAgent.isGodlike())
{
font->renderUTF8(
mLoadingPlaceholderString,
0,
llfloor(draw_rect.mLeft+3),
llfloor(draw_rect.mTop-v_offset),
LLColor4::white,
LLFontGL::LEFT,
LLFontGL::BASELINE,
LLFontGL::DROP_SHADOW);
}
}
LLUICtrl::draw();
}
void LLThumbnailCtrl::clearTexture()
{
mImageAssetID = LLUUID::null;
mTexturep = nullptr;
mImagep = nullptr;
}
// virtual
// value might be a string or a UUID
void LLThumbnailCtrl::setValue(const LLSD& value)
{
LLSD tvalue(value);
if (value.isString() && LLUUID::validate(value.asString()))
{
//RN: support UUIDs masquerading as strings
tvalue = LLSD(LLUUID(value.asString()));
}
LLUICtrl::setValue(tvalue);
mImageAssetID = LLUUID::null;
mTexturep = nullptr;
mImagep = nullptr;
if (tvalue.isUUID())
{
mImageAssetID = tvalue.asUUID();
if (mImageAssetID.notNull())
{
// Should it support baked textures?
mTexturep = LLViewerTextureManager::getFetchedTexture(mImageAssetID, FTT_DEFAULT, MIPMAP_YES, LLGLTexture::BOOST_NONE, LLViewerTexture::LOD_TEXTURE);
mTexturep->setBoostLevel(mPriority);
mTexturep->forceToSaveRawImage(0);
S32 desired_draw_width = mTexturep->getWidth();
S32 desired_draw_height = mTexturep->getHeight();
mTexturep->setKnownDrawSize(desired_draw_width, desired_draw_height);
}
}
else if (tvalue.isString())
{
mImagep = LLUI::getUIImage(tvalue.asString(), LLGLTexture::BOOST_UI);
if (mImagep)
{
LLViewerFetchedTexture* texture = dynamic_cast<LLViewerFetchedTexture*>(mImagep->getImage().get());
if(texture)
{
mImageAssetID = texture->getID();
}
}
}
}
BOOL LLThumbnailCtrl::handleHover(S32 x, S32 y, MASK mask)
{
if (mInteractable && getEnabled())
{
getWindow()->setCursor(UI_CURSOR_HAND);
return TRUE;
}
return LLUICtrl::handleHover(x, y, mask);
}