Feature Request: Repair Uploaded by functionality

Clean up llviewertexture a bit while doing so.
Sync LLImage

Thanks to Cinder and the Alchemy Team for this buncha code.
This commit is contained in:
Lirusaito
2018-05-02 19:30:22 -04:00
parent dd49033a08
commit 1014841e2c
8 changed files with 237 additions and 330 deletions

View File

@@ -36,6 +36,7 @@
#include "llagent.h"
#include "llavataractions.h"
#include "llavatarnamecache.h"
#include "llbutton.h"
#include "llcombobox.h"
#include "statemachine/aifilepicker.h"
@@ -229,25 +230,17 @@ void LLPreviewTexture::init()
childSetText("desc", item->getDescription());
getChild<LLLineEditor>("desc")->setPrevalidate(&LLLineEditor::prevalidatePrintableNotPipe);
childSetText("uuid", getItemID().asString());
childSetText("uploader", getItemCreatorName());
childSetText("uploadtime", getItemCreationDate());
childSetText("alphanote", LLTrans::getString("LoadingData"));
}
}
childSetText("uploader", getItemCreatorName());
childSetText("uploadtime", getItemCreationDate());
childSetCommitCallback("combo_aspect_ratio", onAspectRatioCommit, this);
LLComboBox* combo = getChild<LLComboBox>("combo_aspect_ratio");
combo->setCurrentByIndex(0);
}
void LLPreviewTexture::callbackLoadAvatarName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data)
{
if (!sInstance) return;
std::ostringstream fullname;
fullname << first << " " << last;
sInstance->childSetText("uploader", fullname.str());
}
void LLPreviewTexture::draw()
{
if (mUpdateDimensions)
@@ -486,17 +479,20 @@ std::string LLPreviewTexture::getItemCreationDate()
timeToFormattedString(item->getCreationDate(), gSavedSettings.getString("TimestampFormat"), time);
return time;
}
return getString("Unknown");
const LLDate date = mImage->getUploadTime();
return date.notNull() ? date.toHTTPDateString(gSavedSettings.getString("TimestampFormat"))
: getString("Unknown");
}
std::string LLPreviewTexture::getItemCreatorName()
{
const LLViewerInventoryItem* item = getItem();
if(item)
const LLUUID& id = item ? item->getCreatorUUID() : mImage->getUploader();
if (id.notNull())
{
std::string name;
gCacheName->getFullName(item->getCreatorUUID(), name);
mCreatorKey = item->getCreatorUUID();
LLAvatarNameCache::getNSName(id, name);
mCreatorKey = id;
return name;
}
return getString("Unknown");
@@ -577,6 +573,14 @@ void LLPreviewTexture::updateDimensions()
}
// Update the width/height display every time
if (mImage->getUploader().notNull())
{
// Singu Note: This is what Alchemy does, we may need it, but it might help if it didn't load in init.
childSetText("uploader", getItemCreatorName());
childSetText("uploadtime", getItemCreationDate());
}
if (!mUserResized)
{
// clamp texture size to fit within actual size of floater after attempting resize

View File

@@ -104,7 +104,6 @@ private:
static LLPreviewTexture* sInstance;
static void onClickProfile(void* userdata);
static void callbackLoadAvatarName(const LLUUID& id, const std::string& first, const std::string& last, BOOL is_group, void* data);
// This is stored off in a member variable, because the save-as
// button and drag and drop functionality need to know.

View File

@@ -1378,70 +1378,107 @@ BOOL LLViewerFetchedTexture::createTexture(S32 usename/*= 0*/)
// mRawImage->getWidth(), mRawImage->getHeight(),mRawImage->getDataSize())
// << mID.getString() << LL_ENDL;
BOOL res = TRUE;
if (!gNoRender)
// store original size only for locally-sourced images
if (mUrl.compare(0, 7, "file://") == 0)
{
// store original size only for locally-sourced images
if (mUrl.compare(0, 7, "file://") == 0)
{
mOrigWidth = mRawImage->getWidth();
mOrigHeight = mRawImage->getHeight();
mOrigWidth = mRawImage->getWidth();
mOrigHeight = mRawImage->getHeight();
if (mBoostLevel == BOOST_PREVIEW)
{
mRawImage->biasedScaleToPowerOfTwo(1024);
}
else
{ // leave black border, do not scale image content
mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE);
}
mFullWidth = mRawImage->getWidth();
mFullHeight = mRawImage->getHeight();
setTexelsPerImage();
if (mBoostLevel == BOOST_PREVIEW)
{
mRawImage->biasedScaleToPowerOfTwo(1024);
}
else
{
mOrigWidth = mFullWidth;
mOrigHeight = mFullHeight;
}
bool size_okay = true;
U32 raw_width = mRawImage->getWidth() << mRawDiscardLevel;
U32 raw_height = mRawImage->getHeight() << mRawDiscardLevel;
if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
{
LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL;
size_okay = false;
{ // leave black border, do not scale image content
mRawImage->expandToPowerOfTwo(MAX_IMAGE_SIZE, FALSE);
}
if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight()))
{
// A non power-of-two image was uploaded (through a non standard client)
LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL;
size_okay = false;
}
if( !size_okay )
{
// An inappropriately-sized image was uploaded (through a non standard client)
// We treat these images as missing assets which causes them to
// be renderd as 'missing image' and to stop requesting data
LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL;
setIsMissingAsset();
destroyRawImage();
return FALSE;
}
//if(!(res = insertToAtlas()))
//{
res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
//resetFaceAtlas() ;
notifyAboutCreatingTexture();
//}
setActive() ;
mFullWidth = mRawImage->getWidth();
mFullHeight = mRawImage->getHeight();
setTexelsPerImage();
}
else
{
mOrigWidth = mFullWidth;
mOrigHeight = mFullHeight;
}
if (!mRawImage->mComment.empty())
{
// a is for uploader
// z is for time
// K is the whole thing (just coz)
std::string comment = mRawImage->getComment();
mComment['K'] = comment;
size_t position = 0;
size_t length = comment.length();
while (position < length)
{
std::size_t equals_position = comment.find('=', position);
if (equals_position != std::string::npos)
{
S8 type = comment.at(equals_position - 1);
position = comment.find('&', position);
if (position != std::string::npos)
{
mComment[type] = comment.substr(equals_position + 1, position - (equals_position + 1));
position++;
}
else
{
mComment[type] = comment.substr(equals_position + 1, length - (equals_position + 1));
}
}
else
{
position = equals_position;
}
}
}
bool size_okay = true;
S32 discard_level = mRawDiscardLevel;
if (mRawDiscardLevel < 0)
{
LL_DEBUGS() << "Negative raw discard level when creating image: " << mRawDiscardLevel << LL_ENDL;
discard_level = 0;
}
U32 raw_width = mRawImage->getWidth() << discard_level;
U32 raw_height = mRawImage->getHeight() << discard_level;
if( raw_width > MAX_IMAGE_SIZE || raw_height > MAX_IMAGE_SIZE )
{
LL_INFOS() << "Width or height is greater than " << MAX_IMAGE_SIZE << ": (" << raw_width << "," << raw_height << ")" << LL_ENDL;
size_okay = false;
}
if (!LLImageGL::checkSize(mRawImage->getWidth(), mRawImage->getHeight()))
{
// A non power-of-two image was uploaded (through a non standard client)
LL_INFOS() << "Non power of two width or height: (" << mRawImage->getWidth() << "," << mRawImage->getHeight() << ")" << LL_ENDL;
size_okay = false;
}
if( !size_okay )
{
// An inappropriately-sized image was uploaded (through a non standard client)
// We treat these images as missing assets which causes them to
// be renderd as 'missing image' and to stop requesting data
LL_WARNS() << "!size_ok, setting as missing" << LL_ENDL;
setIsMissingAsset();
destroyRawImage();
return FALSE;
}
res = mGLTexturep->createGLTexture(mRawDiscardLevel, mRawImage, usename, TRUE, mBoostLevel);
notifyAboutCreatingTexture();
setActive();
if (!needsToSaveRawImage())
{
@@ -2956,190 +2993,29 @@ F32 LLViewerFetchedTexture::getElapsedLastReferencedSavedRawImageTime() const
{
return sCurrentTime - mLastReferencedSavedRawImageTime ;
}
//----------------------------------------------------------------------------------------------
//atlasing
//----------------------------------------------------------------------------------------------
/*void LLViewerFetchedTexture::resetFaceAtlas()
LLUUID LLViewerFetchedTexture::getUploader()
{
//Nothing should be done here.
return (mComment.find('a') != mComment.end()) ? LLUUID(mComment['a']) : LLUUID::null;
}
//invalidate all atlas slots for this image.
void LLViewerFetchedTexture::invalidateAtlas(BOOL rebuild_geom)
LLDate LLViewerFetchedTexture::getUploadTime()
{
for(U32 i = 0 ; i < mNumFaces ; i++)
if (mComment.find('z') != mComment.end())
{
LLFace* facep = mFaceList[i] ;
facep->removeAtlas() ;
if(rebuild_geom && facep->getDrawable() && facep->getDrawable()->getSpatialGroup())
{
facep->getDrawable()->getSpatialGroup()->setState(LLSpatialGroup::GEOM_DIRTY);
}
struct tm t = {0};
sscanf(mComment['z'].c_str(), "%4d%2d%2d%2d%2d%2d",
&t.tm_year, &t.tm_mon, &t.tm_mday, &t.tm_hour, &t.tm_min, &t.tm_sec);
std::string iso_date = llformat("%d-%d-%dT%d:%d:%dZ", t.tm_year, t.tm_mon, t.tm_mday, t.tm_hour, t.tm_min, t.tm_sec);
return LLDate(iso_date);
}
return LLDate();
}
BOOL LLViewerFetchedTexture::insertToAtlas()
std::string LLViewerFetchedTexture::getComment()
{
if(!LLViewerTexture::sUseTextureAtlas)
{
return FALSE ;
}
if(getNumFaces() < 1)
{
return FALSE ;
}
if(mGLTexturep->getDiscardLevelInAtlas() > 0 && mRawDiscardLevel >= mGLTexturep->getDiscardLevelInAtlas())
{
return FALSE ;
}
if(!LLTextureAtlasManager::getInstance()->canAddToAtlas(mRawImage->getWidth(), mRawImage->getHeight(), mRawImage->getComponents(), mGLTexturep->getTexTarget()))
{
return FALSE ;
}
BOOL ret = TRUE ;//if ret is set to false, will generate a gl texture for this image.
S32 raw_w = mRawImage->getWidth() ;
S32 raw_h = mRawImage->getHeight() ;
F32 xscale = 1.0f, yscale = 1.0f ;
LLPointer<LLTextureAtlasSlot> slot_infop;
LLTextureAtlasSlot* cur_slotp ;//no need to be smart pointer.
LLSpatialGroup* groupp ;
LLFace* facep;
//if the atlas slot pointers for some faces are null, process them later.
ll_face_list_t waiting_list ;
for(U32 i = 0 ; i < mNumFaces ; i++)
{
{
facep = mFaceList[i] ;
//face can not use atlas.
if(!facep->canUseAtlas())
{
if(facep->getAtlasInfo())
{
facep->removeAtlas() ;
}
ret = FALSE ;
continue ;
}
//the atlas slot is updated
slot_infop = facep->getAtlasInfo() ;
groupp = facep->getDrawable()->getSpatialGroup() ;
if(slot_infop)
{
if(slot_infop->getSpatialGroup() != groupp)
{
if((cur_slotp = groupp->getCurUpdatingSlot(this))) //switch slot
{
facep->setAtlasInfo(cur_slotp) ;
facep->setAtlasInUse(TRUE) ;
continue ;
}
else //do not forget to update slot_infop->getSpatialGroup().
{
LLSpatialGroup* gp = slot_infop->getSpatialGroup() ;
gp->setCurUpdatingTime(gFrameCount) ;
gp->setCurUpdatingTexture(this) ;
gp->setCurUpdatingSlot(slot_infop) ;
}
}
else //same group
{
if(gFrameCount && slot_infop->getUpdatedTime() == gFrameCount)//slot is just updated
{
facep->setAtlasInUse(TRUE) ;
continue ;
}
}
}
else
{
//if the slot is null, wait to process them later.
waiting_list.push_back(facep) ;
continue ;
}
//----------
//insert to atlas
if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
{
//the texture does not qualify to add to atlas, do not bother to try for other faces.
//invalidateAtlas();
return FALSE ;
}
//update texture scale
slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
slot_infop->setTexCoordScale(xscale, yscale) ;
slot_infop->setValid() ;
slot_infop->setUpdatedTime(gFrameCount) ;
//update spatial group atlas info
groupp->setCurUpdatingTime(gFrameCount) ;
groupp->setCurUpdatingTexture(this) ;
groupp->setCurUpdatingSlot(slot_infop) ;
//make the face to switch to the atlas.
facep->setAtlasInUse(TRUE) ;
}
}
//process the waiting_list
for(ll_face_list_t::iterator iter = waiting_list.begin(); iter != waiting_list.end(); ++iter)
{
facep = (LLFace*)*iter ;
groupp = facep->getDrawable()->getSpatialGroup() ;
//check if this texture already inserted to atlas for this group
if((cur_slotp = groupp->getCurUpdatingSlot(this)))
{
facep->setAtlasInfo(cur_slotp) ;
facep->setAtlasInUse(TRUE) ;
continue ;
}
//need to reserve a slot from atlas
slot_infop = LLTextureAtlasManager::getInstance()->reserveAtlasSlot(llmax(mFullWidth, mFullHeight), getComponents(), groupp, this) ;
facep->setAtlasInfo(slot_infop) ;
groupp->setCurUpdatingTime(gFrameCount) ;
groupp->setCurUpdatingTexture(this) ;
groupp->setCurUpdatingSlot(slot_infop) ;
//slot allocation failed.
if(!slot_infop || !slot_infop->getAtlas())
{
ret = FALSE ;
facep->setAtlasInUse(FALSE) ;
continue ;
}
//insert to atlas
if(!slot_infop->getAtlas()->insertSubTexture(mGLTexturep, mRawDiscardLevel, mRawImage, slot_infop->getSlotCol(), slot_infop->getSlotRow()))
{
//the texture does not qualify to add to atlas, do not bother to try for other faces.
ret = FALSE ;
//invalidateAtlas();
break ;
}
//update texture scale
slot_infop->getAtlas()->getTexCoordScale(raw_w, raw_h, xscale, yscale) ;
slot_infop->setTexCoordScale(xscale, yscale) ;
slot_infop->setValid() ;
slot_infop->setUpdatedTime(gFrameCount) ;
//make the face to switch to the atlas.
facep->setAtlasInUse(TRUE) ;
}
return ret ;
}*/
return (mComment.find('K') != mComment.end()) ? mComment['K'] : LLStringUtil::null;
}
//----------------------------------------------------------------------------------------------
//end of LLViewerFetchedTexture

View File

@@ -413,6 +413,10 @@ public:
void forceRefetch();
/*virtual*/bool isActiveFetching(); //is actively in fetching by the fetching pipeline.
LLUUID getUploader();
LLDate getUploadTime();
std::string getComment();
protected:
/*virtual*/ void switchToCachedImage();
S32 getCurrentDiscardLevelForFetching() ;
@@ -510,6 +514,8 @@ protected:
BOOL mForSculpt ; //a flag if the texture is used as sculpt data.
BOOL mIsFetched ; //is loaded from remote or from cache, not generated locally.
std::map<S8, std::string> mComment;
public:
static LLPointer<LLViewerFetchedTexture> sMissingAssetImagep; // Texture to show for an image asset that is not in the database