diff options
| author | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2022-03-30 18:32:42 +0300 | 
|---|---|---|
| committer | Andrey Kleshchev <andreykproductengine@lindenlab.com> | 2022-03-30 18:35:47 +0300 | 
| commit | 8f6d149fadf635f6698e2e68aa4f48db13eff648 (patch) | |
| tree | a86adf0a7c38c4d0ced579ed364187a26af7f9d9 | |
| parent | cd61dbe6eea8d9a7e4bdb594179bafc24a504146 (diff) | |
SL-16937 New Profile capability, image uploader for testing
This commit is mostly to simplify cap testing for server side. Plan is to remove LLLocalBitmap and draw texture more directly instead
| -rw-r--r-- | indra/newview/lllocalbitmaps.cpp | 60 | ||||
| -rw-r--r-- | indra/newview/lllocalbitmaps.h | 1 | ||||
| -rw-r--r-- | indra/newview/llpanelprofile.cpp | 141 | ||||
| -rw-r--r-- | indra/newview/llpanelprofile.h | 10 | ||||
| -rw-r--r-- | indra/newview/skins/default/xui/en/panel_profile_secondlife.xml | 17 | 
5 files changed, 165 insertions, 64 deletions
| diff --git a/indra/newview/lllocalbitmaps.cpp b/indra/newview/lllocalbitmaps.cpp index 5a17332fde..de8db69e19 100644 --- a/indra/newview/lllocalbitmaps.cpp +++ b/indra/newview/lllocalbitmaps.cpp @@ -919,6 +919,36 @@ LLLocalBitmapMgr::~LLLocalBitmapMgr()      mBitmapList.clear();  } +LLUUID LLLocalBitmapMgr::addUnit(const std::string &filename) +{ +    if (!checkTextureDimensions(filename)) +    { +        return LLUUID::null; +    } + +    LLLocalBitmap* unit = new LLLocalBitmap(filename); + +    if (unit->getValid()) +    { +        mBitmapList.push_back(unit); +        return unit->getTrackingID(); +    } +    else +    { +        LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" +            << "Filename: " << filename << LL_ENDL; + +        LLSD notif_args; +        notif_args["FNAME"] = filename; +        LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); + +        delete unit; +        unit = NULL; +    } + +    return LLUUID::null; +} +  bool LLLocalBitmapMgr::addUnit()  {  	bool add_successful = false; @@ -931,32 +961,10 @@ bool LLLocalBitmapMgr::addUnit()  		std::string filename = picker.getFirstFile();  		while(!filename.empty())  		{ -			if(!checkTextureDimensions(filename)) -			{ -				filename = picker.getNextFile(); -				continue; -			} - -			LLLocalBitmap* unit = new LLLocalBitmap(filename); - -			if (unit->getValid()) -			{ -				mBitmapList.push_back(unit); -				add_successful = true; -			} -			else -			{ -				LL_WARNS() << "Attempted to add invalid or unreadable image file, attempt cancelled.\n" -					    << "Filename: " << filename << LL_ENDL; - -				LLSD notif_args; -				notif_args["FNAME"] = filename; -				LLNotificationsUtil::add("LocalBitmapsVerifyFail", notif_args); - -				delete unit; -				unit = NULL; -			} - +            if (addUnit(filename).notNull()) +            { +                add_successful = true; +            }  			filename = picker.getNextFile();  		} diff --git a/indra/newview/lllocalbitmaps.h b/indra/newview/lllocalbitmaps.h index d5ee7efdc6..c29f3f62f6 100644 --- a/indra/newview/lllocalbitmaps.h +++ b/indra/newview/lllocalbitmaps.h @@ -116,6 +116,7 @@ class LLLocalBitmapMgr : public LLSingleton<LLLocalBitmapMgr>  	~LLLocalBitmapMgr();  public:  	bool         addUnit(); +    LLUUID       addUnit(const std::string &filename);  	void         delUnit(LLUUID tracking_id);  	bool 		checkTextureDimensions(std::string filename); diff --git a/indra/newview/llpanelprofile.cpp b/indra/newview/llpanelprofile.cpp index 156d2671f4..c19688191b 100644 --- a/indra/newview/llpanelprofile.cpp +++ b/indra/newview/llpanelprofile.cpp @@ -58,6 +58,7 @@  #include "llcallingcard.h"  #include "llcommandhandler.h"  #include "llfloaterreg.h" +#include "llfilepicker.h"  #include "llfirstuse.h"  #include "llgroupactions.h"  #include "llmutelist.h" @@ -68,6 +69,7 @@  #include "lltrans.h"  #include "llviewercontrol.h"  #include "llviewermenu.h" //is_agent_mappable +#include "llviewermenufile.h"  #include "llviewertexturelist.h"  #include "llvoiceclient.h"  #include "llweb.h" @@ -324,17 +326,20 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s      if (!status)      {          LL_WARNS("AvatarProperties") << "Failed to get uploader cap " << status.toString() << LL_ENDL; +        LLFile::remove(path_to_image);          return;      }      if (!result.has("uploader"))      {          LL_WARNS("AvatarProperties") << "Failed to get uploader cap, response contains no data." << LL_ENDL; +        LLFile::remove(path_to_image);          return;      }      std::string uploader_cap = result["uploader"].asString();      if (uploader_cap.empty())      {          LL_WARNS("AvatarProperties") << "Failed to get uploader cap, cap invalid." << LL_ENDL; +        LLFile::remove(path_to_image);          return;      } @@ -350,6 +355,7 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s          if (!instream.is_open())          {              LL_WARNS("AvatarProperties") << "Failed to open file " << path_to_image << LL_ENDL; +            LLFile::remove(path_to_image);              return;          }          length = instream.tellg(); @@ -367,6 +373,7 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s      if (!status)      {          LL_WARNS("AvatarProperties") << "Failed to upload image " << status.toString() << LL_ENDL; +        LLFile::remove(path_to_image);          return;      } @@ -380,6 +387,7 @@ void post_profile_image_coro(std::string cap_url, EProfileImageType type, std::s          {              LL_WARNS("AvatarProperties") << "Failed to upload image " << result << LL_ENDL;          } +        LLFile::remove(path_to_image);          return;      } @@ -575,6 +583,8 @@ LLPanelProfileSecondLife::~LLPanelProfileSecondLife()      {          mAvatarNameCacheConnection.disconnect();      } + +    clearUploadProfileImagePath();  }  BOOL LLPanelProfileSecondLife::postBuild() @@ -582,7 +592,7 @@ BOOL LLPanelProfileSecondLife::postBuild()      mStatusText             = getChild<LLTextBox>("status");      mGroupList              = getChild<LLGroupList>("group_list");      mShowInSearchCheckbox   = getChild<LLCheckBoxCtrl>("show_in_search_checkbox"); -    mSecondLifePic          = getChild<LLTextureCtrl>("2nd_life_pic"); +    mSecondLifePic          = getChild<LLIconCtrl>("2nd_life_pic");      mSecondLifePicLayout    = getChild<LLPanel>("image_stack");      mDescriptionEdit        = getChild<LLTextBase>("sl_description_edit");      mTeleportButton         = getChild<LLButton>("teleport"); @@ -610,7 +620,7 @@ BOOL LLPanelProfileSecondLife::postBuild()      mUnblockButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onClickToggleBlock, this));      mGroupInviteButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onGroupInvite,this));      mDisplayNameButton->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onClickSetName, this)); -    mSecondLifePic->setCommitCallback(boost::bind(&LLPanelProfileSecondLife::onCommitTexture, this)); +    mSecondLifePic->setMouseUpCallback(boost::bind(&LLPanelProfileSecondLife::onPickTexture, this));      LLUICtrl::CommitCallbackRegistry::ScopedRegistrar commit;      commit.add("Profile.CopyName", [this](LLUICtrl*, const LLSD& userdata) { onCommitMenu(userdata); }); @@ -650,8 +660,6 @@ void LLPanelProfileSecondLife::onOpen(const LLSD& key)      mGroupList->setShowNone(!own_profile);      mGiveInvPanel->setVisible(!own_profile); -    mSecondLifePic->setOpenTexPreview(!own_profile); -      if (own_profile && !getEmbedded())      {          // Group list control cannot toggle ForAgent loading @@ -693,10 +701,11 @@ void LLPanelProfileSecondLife::apply(LLAvatarData* data)          LLSD params = LLSDMap();          // we have an image, check if it is local. Server won't recognize local ids. -        if (data->image_id != mSecondLifePic->getImageAssetID() -            && !LLLocalBitmapMgr::getInstance()->isLocal(mSecondLifePic->getImageAssetID())) +        if (data->image_id != mImageAssetId +            && mImageFile.empty() +            && !LLLocalBitmapMgr::getInstance()->isLocal(mImageAssetId))          { -            params["sl_image_id"] = mSecondLifePic->getImageAssetID(); +            params["sl_image_id"] = mImageAssetId;          }          if (data->about_text != mDescriptionEdit->getValue().asString())          { @@ -721,12 +730,19 @@ void LLPanelProfileSecondLife::apply(LLAvatarData* data)          }          // Only if image is local -        if (data->image_id != mSecondLifePic->getImageAssetID() -            && LLLocalBitmapMgr::getInstance()->isLocal(mSecondLifePic->getImageAssetID())) +        if (!mImageFile.empty())          { -            // todo: temporary file, connect to UI -            std::string file_path = gDirUtilp->findSkinnedFilename("textures", "icons/Default_Outfit_Photo.png"); -            launch_profile_image_coro(PROFILE_IMAGE_SL, file_path); +            std::string cap_url = gAgent.getRegionCapability(PROFILE_IMAGE_UPLOAD_CAP); +            if (!cap_url.empty()) +            { +                LLCoros::instance().launch("postAgentUserImageCoro", +                    boost::bind(post_profile_image_coro, cap_url, PROFILE_IMAGE_SL, mImageFile)); +                mImageFile.clear(); // coro should do the deleting +            } +            else +            { +                LL_WARNS("AvatarProperties") << "Failed to upload profile image of type " << (S32)PROFILE_IMAGE_SL << ", no cap found" << LL_ENDL; +            }          }      }  } @@ -773,7 +789,7 @@ void LLPanelProfileSecondLife::resetData()      getChild<LLUICtrl>("partner_text")->setValue(LLStringUtil::null);      // Set default image and 1:1 dimensions for it -    mSecondLifePic->setValue(mSecondLifePic->getDefaultImageAssetID()); +    mSecondLifePic->setValue("Generic_Person_Large");      LLRect imageRect = mSecondLifePicLayout->getRect();      mSecondLifePicLayout->reshape(imageRect.getHeight(), imageRect.getHeight()); @@ -782,6 +798,7 @@ void LLPanelProfileSecondLife::resetData()      mCopyMenuButton->setVisible(FALSE);      mGroups.clear();      mGroupList->setGroups(mGroups); +    clearUploadProfileImagePath();  }  void LLPanelProfileSecondLife::processProfileProperties(const LLAvatarData* avatar_data) @@ -845,6 +862,37 @@ void LLPanelProfileSecondLife::onAvatarNameCache(const LLUUID& agent_id, const L      mCopyMenuButton->setVisible(TRUE);  } +void LLPanelProfileSecondLife::setUploadProfileImagePath(const std::string &path, const std::string &orig_path) +{ +    clearUploadProfileImagePath(); +    // todo: display this in floater, +    // LLIconCtrl can't show a path, only by id or name, so may be draw directly or add as a local bitmap? +    // LLLocalBitmap* unit = new LLLocalBitmap(path); + +    // assign a local texture to view in viewer +    // Todo: remove LLLocalBitmap and just draw texture instead +    // orig_path was used instead of path, since LLLocalBitmapMgr does not support j2c +    LLUUID tracking_id = LLLocalBitmapMgr::getInstance()->addUnit(orig_path); +    if (tracking_id.isNull()) +    { +        // todo: error handling +        return; +    } + +    mImageFile = path; +    mImageAssetId = LLLocalBitmapMgr::getInstance()->getWorldID(tracking_id); +    mSecondLifePic->setValue(mImageAssetId); +} + +void LLPanelProfileSecondLife::clearUploadProfileImagePath() +{ +    if (!mImageFile.empty()) +    { +        LLFile::remove(mImageFile); //todo: supress errors, may be not need to remove if it becomes a LLLocalBitmap +    } +    mImageFile.clear(); +} +  void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)  {      // Refresh avatar id in cache with new info to prevent re-requests @@ -862,7 +910,8 @@ void LLPanelProfileSecondLife::fillCommonData(const LLAvatarData* avatar_data)      std::string register_date = getString("RegisterDateFormat", args);      getChild<LLUICtrl>("register_date")->setValue(register_date );      mDescriptionEdit->setValue(avatar_data->about_text); -    mSecondLifePic->setValue(avatar_data->image_id); +    mImageAssetId = avatar_data->image_id; +    mSecondLifePic->setValue(mImageAssetId);      //Don't bother about boost level, picker will set it      LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(avatar_data->image_id); @@ -1119,23 +1168,63 @@ void LLPanelProfileSecondLife::onClickSetName()      LLFirstUse::setDisplayName(false);  } -void LLPanelProfileSecondLife::onCommitTexture() + + +class LLProfileImagePicker : public LLFilePickerThread  { -    LLViewerFetchedTexture* imagep = LLViewerTextureManager::getFetchedTexture(mSecondLifePic->getImageAssetID()); -    if (imagep->getFullHeight()) +public: +    LLProfileImagePicker(LLHandle<LLPanel> *handle); +    ~LLProfileImagePicker(); +    virtual void notify(const std::vector<std::string>& filenames); + +private: +    LLHandle<LLPanel> *mHandle; +}; + +LLProfileImagePicker::LLProfileImagePicker(LLHandle<LLPanel> *handle) +    : LLFilePickerThread(LLFilePicker::FFLOAD_IMAGE), +    mHandle(handle) +{ +} + +LLProfileImagePicker::~LLProfileImagePicker() +{ +    delete mHandle; +} + +void LLProfileImagePicker::notify(const std::vector<std::string>& filenames) +{ +    /*if (LLAppViewer::instance()->quitRequested())      { -        onImageLoaded(true, imagep); +        return; +    }*/ +    if (mHandle->isDead()) +    { +        return;      } -    else +    std::string file_path = filenames[0]; +    if (file_path.empty())      { -        imagep->setLoadedCallback(onImageLoaded, -            MAX_DISCARD_LEVEL, -            FALSE, -            FALSE, -            new LLHandle<LLPanel>(getHandle()), -            NULL, -            FALSE); +        return; +    } + +    // generate a temp texture file for coroutine +    std::string temp_file = gDirUtilp->getTempFilename(); +    U32 codec = LLImageBase::getCodecFromExtension(gDirUtilp->getExtension(file_path)); +    const S32 MAX_DIM = 256; +    if (!LLViewerTextureList::createUploadFile(file_path, temp_file, codec, MAX_DIM)) +    { +        // todo: error handling +        return;      } + +    LLPanelProfileSecondLife* panel = static_cast<LLPanelProfileSecondLife*>(mHandle->get()); +    panel->setUploadProfileImagePath(temp_file, file_path); +} + +void LLPanelProfileSecondLife::onPickTexture() +{ +    (new LLProfileImagePicker(new LLHandle<LLPanel>(getHandle())))->getFile();  }  void LLPanelProfileSecondLife::onCommitMenu(const LLSD& userdata) diff --git a/indra/newview/llpanelprofile.h b/indra/newview/llpanelprofile.h index e87de9f96f..9aab8a087c 100644 --- a/indra/newview/llpanelprofile.h +++ b/indra/newview/llpanelprofile.h @@ -46,6 +46,7 @@  class LLAvatarName;  class LLCheckBoxCtrl; +class LLIconCtrl;  class LLTabContainer;  class LLTextBox;  class LLTextureCtrl; @@ -102,6 +103,9 @@ public:  	void onAvatarNameCache(const LLUUID& agent_id, const LLAvatarName& av_name); +    void setUploadProfileImagePath(const std::string &path, const std::string &orig_path); +    void clearUploadProfileImagePath(); +      friend void request_avatar_properties_coro(std::string cap_url, LLUUID agent_id);  protected: @@ -178,7 +182,7 @@ protected:  private:      /*virtual*/ void updateButtons();  	void onClickSetName(); -	void onCommitTexture(); +	void onPickTexture();  	void onCommitMenu(const LLSD& userdata);  	void onAvatarNameCacheSetName(const LLUUID& id, const LLAvatarName& av_name); @@ -190,7 +194,7 @@ private:  	LLTextBox*			mStatusText;  	LLGroupList*		mGroupList;  	LLCheckBoxCtrl*		mShowInSearchCheckbox; -	LLTextureCtrl*		mSecondLifePic; +    LLIconCtrl*			mSecondLifePic;  	LLPanel*			mSecondLifePicLayout;  	LLTextBase*			mDescriptionEdit;  	LLButton*			mTeleportButton; @@ -207,6 +211,8 @@ private:  	LLPanel*			mGiveInvPanel;  	bool				mVoiceStatus; +    std::string mImageFile; +    LLUUID mImageAssetId;  	boost::signals2::connection	mAvatarNameCacheConnection;  }; diff --git a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml index 816b0b8f5c..d8d2749a2b 100644 --- a/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml +++ b/indra/newview/skins/default/xui/en/panel_profile_secondlife.xml @@ -177,19 +177,16 @@           auto_resize="false"           user_resize="false"          > -            <!-- 23 pixels (BTN_HEIGHT_SMALL) are reserved by label field of texture and shouldn't be visible--> -            <texture_picker + +            <icon               name="2nd_life_pic" +             image_name="Generic_Person_Large" +             layout="topleft" +             follows="all"               top="0"               left="0" -             right="-1" -             height="180" -             follows="all" -             layout="topleft" -             allow_no_texture="true" -             default_image_name="None" -             fallback_image="Generic_Person_Large" -             /> +             width="157" +             height="157"/>          </layout_panel>          <layout_panel           name="label_stack" | 
