mirror of
https://github.com/leozide/leocad
synced 2025-01-18 22:26:44 +01:00
Added thumbnail manager.
This commit is contained in:
parent
7451d336f7
commit
f06a231816
8 changed files with 307 additions and 192 deletions
|
@ -1,5 +1,6 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_thumbnailmanager.h"
|
||||
#include "lc_zipfile.h"
|
||||
#include "lc_file.h"
|
||||
#include "pieceinf.h"
|
||||
|
@ -33,6 +34,7 @@ lcPiecesLibrary::lcPiecesLibrary()
|
|||
: mLoadMutex(QMutex::Recursive)
|
||||
#endif
|
||||
{
|
||||
mThumbnailManager = std::unique_ptr<lcThumbnailManager>(new lcThumbnailManager(this));
|
||||
QStringList cachePathList = QStandardPaths::standardLocations(QStandardPaths::CacheLocation);
|
||||
mCachePath = cachePathList.first();
|
||||
|
||||
|
@ -49,6 +51,7 @@ lcPiecesLibrary::lcPiecesLibrary()
|
|||
|
||||
lcPiecesLibrary::~lcPiecesLibrary()
|
||||
{
|
||||
mThumbnailManager.reset();
|
||||
mLoadMutex.lock();
|
||||
mLoadQueue.clear();
|
||||
mLoadMutex.unlock();
|
||||
|
|
|
@ -7,6 +7,7 @@
|
|||
class PieceInfo;
|
||||
class lcZipFile;
|
||||
class lcLibraryMeshData;
|
||||
class lcThumbnailManager;
|
||||
|
||||
enum class lcStudStyle
|
||||
{
|
||||
|
@ -126,6 +127,11 @@ public:
|
|||
lcPiecesLibrary& operator=(const lcPiecesLibrary&) = delete;
|
||||
lcPiecesLibrary& operator=(lcPiecesLibrary&&) = delete;
|
||||
|
||||
lcThumbnailManager* GetThumbnailManager() const
|
||||
{
|
||||
return mThumbnailManager.get();
|
||||
}
|
||||
|
||||
bool Load(const QString& LibraryPath, bool ShowProgress);
|
||||
void LoadColors();
|
||||
void Unload();
|
||||
|
@ -234,6 +240,7 @@ protected:
|
|||
lcStudStyle mStudStyle;
|
||||
bool mStudCylinderColorEnabled;
|
||||
|
||||
std::unique_ptr<lcThumbnailManager> mThumbnailManager;
|
||||
QString mCachePath;
|
||||
qint64 mArchiveCheckSum[4];
|
||||
std::unique_ptr<lcZipFile> mZipFiles[static_cast<int>(lcZipFileType::Count)];
|
||||
|
|
|
@ -1341,7 +1341,7 @@ void lcMainWindow::SetShadingMode(lcShadingMode ShadingMode)
|
|||
lcView::UpdateAllViews();
|
||||
|
||||
if (mPartSelectionWidget)
|
||||
mPartSelectionWidget->Redraw();
|
||||
mPartSelectionWidget->UpdateThumbnails();
|
||||
}
|
||||
|
||||
void lcMainWindow::SetSelectionMode(lcSelectionMode SelectionMode)
|
||||
|
|
|
@ -5,12 +5,9 @@
|
|||
#include "lc_application.h"
|
||||
#include "lc_mainwindow.h"
|
||||
#include "lc_library.h"
|
||||
#include "lc_model.h"
|
||||
#include "lc_thumbnailmanager.h"
|
||||
#include "project.h"
|
||||
#include "pieceinf.h"
|
||||
#include "camera.h"
|
||||
#include "lc_scene.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_glextensions.h"
|
||||
#include "lc_category.h"
|
||||
|
||||
|
@ -18,7 +15,7 @@ Q_DECLARE_METATYPE(QList<int>)
|
|||
|
||||
void lcPartSelectionItemDelegate::paint(QPainter* Painter, const QStyleOptionViewItem& Option, const QModelIndex& Index) const
|
||||
{
|
||||
mListModel->RequestPreview(Index.row());
|
||||
mListModel->RequestThumbnail(Index.row());
|
||||
QStyledItemDelegate::paint(Painter, Option, Index);
|
||||
}
|
||||
|
||||
|
@ -60,38 +57,19 @@ lcPartSelectionListModel::lcPartSelectionListModel(QObject* Parent)
|
|||
mColorLocked = true;
|
||||
}
|
||||
|
||||
connect(lcGetPiecesLibrary(), &lcPiecesLibrary::PartLoaded, this, &lcPartSelectionListModel::PartLoaded);
|
||||
connect(lcGetPiecesLibrary()->GetThumbnailManager(), &lcThumbnailManager::ThumbnailReady, this, &lcPartSelectionListModel::ThumbnailReady);
|
||||
}
|
||||
|
||||
lcPartSelectionListModel::~lcPartSelectionListModel()
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
mView.reset();
|
||||
mModel.reset();
|
||||
ReleaseThumbnails();
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::ClearRequests()
|
||||
void lcPartSelectionListModel::UpdateThumbnails()
|
||||
{
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
|
||||
for (int RequestIdx : mRequestedPreviews)
|
||||
{
|
||||
PieceInfo* Info = mParts[RequestIdx].first;
|
||||
Library->ReleasePieceInfo(Info);
|
||||
}
|
||||
|
||||
mRequestedPreviews.clear();
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::Redraw()
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
|
||||
mParts[PartIdx].second = QPixmap();
|
||||
ReleaseThumbnails();
|
||||
|
||||
endResetModel();
|
||||
|
||||
|
@ -103,8 +81,9 @@ void lcPartSelectionListModel::SetColorIndex(int ColorIndex)
|
|||
if (mColorLocked || ColorIndex == mColorIndex)
|
||||
return;
|
||||
|
||||
UpdateThumbnails();
|
||||
|
||||
mColorIndex = ColorIndex;
|
||||
Redraw();
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::ToggleColorLocked()
|
||||
|
@ -125,10 +104,10 @@ void lcPartSelectionListModel::ToggleListMode()
|
|||
|
||||
void lcPartSelectionListModel::SetCategory(int CategoryIndex)
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
ReleaseThumbnails();
|
||||
|
||||
lcPiecesLibrary* Library = lcGetPiecesLibrary();
|
||||
std::vector<PieceInfo*> SingleParts, GroupedParts;
|
||||
|
||||
|
@ -160,8 +139,8 @@ void lcPartSelectionListModel::SetCategory(int CategoryIndex)
|
|||
|
||||
mParts.resize(SingleParts.size());
|
||||
|
||||
for (size_t PartIdx = 0; PartIdx < SingleParts.size(); PartIdx++)
|
||||
mParts[PartIdx] = std::pair<PieceInfo*, QPixmap>(SingleParts[PartIdx], QPixmap());
|
||||
for (size_t PartIndex = 0; PartIndex < SingleParts.size(); PartIndex++)
|
||||
mParts[PartIndex].Info = SingleParts[PartIndex];
|
||||
|
||||
endResetModel();
|
||||
|
||||
|
@ -170,10 +149,9 @@ void lcPartSelectionListModel::SetCategory(int CategoryIndex)
|
|||
|
||||
void lcPartSelectionListModel::SetModelsCategory()
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
ReleaseThumbnails();
|
||||
mParts.clear();
|
||||
|
||||
const std::vector<std::unique_ptr<lcModel>>& Models = lcGetActiveProject()->GetModels();
|
||||
|
@ -181,11 +159,11 @@ void lcPartSelectionListModel::SetModelsCategory()
|
|||
|
||||
for (const std::unique_ptr<lcModel>& Model : Models)
|
||||
if (!Model->IncludesModel(ActiveModel))
|
||||
mParts.emplace_back(std::pair<PieceInfo*, QPixmap>(Model->GetPieceInfo(), QPixmap()));
|
||||
mParts.emplace_back().Info = Model->GetPieceInfo();
|
||||
|
||||
auto lcPartSortFunc = [](const std::pair<PieceInfo*, QPixmap>& a, const std::pair<PieceInfo*, QPixmap>& b)
|
||||
auto lcPartSortFunc = [](const lcPartSelectionListModelEntry& a, const lcPartSelectionListModelEntry& b)
|
||||
{
|
||||
return strcmp(a.first->m_strDescription, b.first->m_strDescription) < 0;
|
||||
return strcmp(a.Info->m_strDescription, b.Info->m_strDescription) < 0;
|
||||
};
|
||||
|
||||
std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
|
||||
|
@ -197,10 +175,9 @@ void lcPartSelectionListModel::SetModelsCategory()
|
|||
|
||||
void lcPartSelectionListModel::SetPaletteCategory(int SetIndex)
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
ReleaseThumbnails();
|
||||
mParts.clear();
|
||||
|
||||
lcPartSelectionWidget* PartSelectionWidget = mListView->GetPartSelectionWidget();
|
||||
|
@ -216,8 +193,8 @@ void lcPartSelectionListModel::SetPaletteCategory(int SetIndex)
|
|||
|
||||
mParts.reserve(PartsList.size());
|
||||
|
||||
for (PieceInfo* Favorite : PartsList)
|
||||
mParts.emplace_back(std::pair<PieceInfo*, QPixmap>(Favorite, QPixmap()));
|
||||
for (PieceInfo* Info : PartsList)
|
||||
mParts.emplace_back().Info = Info;
|
||||
|
||||
endResetModel();
|
||||
|
||||
|
@ -226,10 +203,9 @@ void lcPartSelectionListModel::SetPaletteCategory(int SetIndex)
|
|||
|
||||
void lcPartSelectionListModel::SetCurrentModelCategory()
|
||||
{
|
||||
ClearRequests();
|
||||
|
||||
beginResetModel();
|
||||
|
||||
ReleaseThumbnails();
|
||||
mParts.clear();
|
||||
|
||||
lcModel* ActiveModel = gMainWindow->GetActiveModel();
|
||||
|
@ -239,11 +215,11 @@ void lcPartSelectionListModel::SetCurrentModelCategory()
|
|||
ActiveModel->GetPartsList(gDefaultColor, true, true, PartsList);
|
||||
|
||||
for (const auto& PartIt : PartsList)
|
||||
mParts.emplace_back(std::pair<PieceInfo*, QPixmap>((PieceInfo*)PartIt.first, QPixmap()));
|
||||
mParts.emplace_back().Info = (PieceInfo*)PartIt.first;
|
||||
|
||||
auto lcPartSortFunc = [](const std::pair<PieceInfo*, QPixmap>& a, const std::pair<PieceInfo*, QPixmap>& b)
|
||||
auto lcPartSortFunc = [](const lcPartSelectionListModelEntry& a, const lcPartSelectionListModelEntry& b)
|
||||
{
|
||||
return strcmp(a.first->m_strDescription, b.first->m_strDescription) < 0;
|
||||
return strcmp(a.Info->m_strDescription, b.Info->m_strDescription) < 0;
|
||||
};
|
||||
|
||||
std::sort(mParts.begin(), mParts.end(), lcPartSortFunc);
|
||||
|
@ -259,7 +235,7 @@ void lcPartSelectionListModel::SetFilter(const QString& Filter)
|
|||
|
||||
for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
|
||||
{
|
||||
PieceInfo* Info = mParts[PartIdx].first;
|
||||
PieceInfo* Info = mParts[PartIdx].Info;
|
||||
bool Visible;
|
||||
|
||||
if (!mShowDecoratedParts && Info->IsPatterned() && !Info->IsProjectPiece())
|
||||
|
@ -307,7 +283,7 @@ QVariant lcPartSelectionListModel::data(const QModelIndex& Index, int Role) cons
|
|||
|
||||
if (Index.isValid() && InfoIndex < mParts.size())
|
||||
{
|
||||
PieceInfo* Info = mParts[InfoIndex].first;
|
||||
PieceInfo* Info = mParts[InfoIndex].Info;
|
||||
|
||||
switch (Role)
|
||||
{
|
||||
|
@ -320,8 +296,8 @@ QVariant lcPartSelectionListModel::data(const QModelIndex& Index, int Role) cons
|
|||
return QVariant(QString("%1 (%2)").arg(QString::fromLatin1(Info->m_strDescription), QString::fromLatin1(Info->mFileName)));
|
||||
|
||||
case Qt::DecorationRole:
|
||||
if (!mParts[InfoIndex].second.isNull() && mIconSize)
|
||||
return QVariant(mParts[InfoIndex].second);
|
||||
if (mIconSize && !mParts[InfoIndex].Pixmap.isNull())
|
||||
return QVariant(mParts[InfoIndex].Pixmap);
|
||||
else
|
||||
return QVariant(QColor(0, 0, 0, 0));
|
||||
|
||||
|
@ -351,119 +327,51 @@ Qt::ItemFlags lcPartSelectionListModel::flags(const QModelIndex& Index) const
|
|||
return DefaultFlags;
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::RequestPreview(int InfoIndex)
|
||||
void lcPartSelectionListModel::ReleaseThumbnails()
|
||||
{
|
||||
if (!mIconSize || !mParts[InfoIndex].second.isNull())
|
||||
return;
|
||||
lcThumbnailManager* ThumbnailManager = lcGetPiecesLibrary()->GetThumbnailManager();
|
||||
|
||||
if (std::find(mRequestedPreviews.begin(), mRequestedPreviews.end(), InfoIndex) != mRequestedPreviews.end())
|
||||
return;
|
||||
|
||||
PieceInfo* Info = mParts[InfoIndex].first;
|
||||
lcGetPiecesLibrary()->LoadPieceInfo(Info, false, false);
|
||||
|
||||
if (Info->mState == lcPieceInfoState::Loaded)
|
||||
DrawPreview(InfoIndex);
|
||||
else
|
||||
mRequestedPreviews.push_back(InfoIndex);
|
||||
for (lcPartSelectionListModelEntry& Part : mParts)
|
||||
{
|
||||
ThumbnailManager->ReleaseThumbnail(Part.ThumbnailId);
|
||||
Part.ThumbnailId = lcPartThumbnailId::Invalid;
|
||||
Part.Pixmap = QPixmap();
|
||||
}
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::PartLoaded(PieceInfo* Info)
|
||||
void lcPartSelectionListModel::RequestThumbnail(int PartIndex)
|
||||
{
|
||||
for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
|
||||
if (!mIconSize || !mParts[PartIndex].Pixmap.isNull() || mParts[PartIndex].ThumbnailId != lcPartThumbnailId::Invalid)
|
||||
return;
|
||||
|
||||
PieceInfo* Info = mParts[PartIndex].Info;
|
||||
auto [ThumbnailId, Thumbnail] = lcGetPiecesLibrary()->GetThumbnailManager()->RequestThumbnail(Info, mColorIndex, mIconSize);
|
||||
|
||||
mParts[PartIndex].ThumbnailId = ThumbnailId;
|
||||
|
||||
if (!Thumbnail.isNull())
|
||||
{
|
||||
if (mParts[PartIdx].first == Info)
|
||||
mParts[PartIndex].Pixmap = Thumbnail;
|
||||
|
||||
emit dataChanged(index(PartIndex, 0), index(PartIndex, 0), { Qt::DecorationRole });
|
||||
}
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::ThumbnailReady(lcPartThumbnailId ThumbnailId, QPixmap Pixmap)
|
||||
{
|
||||
for (int PartIndex = 0; PartIndex < static_cast<int>(mParts.size()); PartIndex++)
|
||||
{
|
||||
if (mParts[PartIndex].ThumbnailId == ThumbnailId)
|
||||
{
|
||||
auto PreviewIt = std::find(mRequestedPreviews.begin(), mRequestedPreviews.end(), static_cast<int>(PartIdx));
|
||||
if (PreviewIt != mRequestedPreviews.end())
|
||||
{
|
||||
mRequestedPreviews.erase(PreviewIt);
|
||||
DrawPreview((int)PartIdx);
|
||||
}
|
||||
mParts[PartIndex].Pixmap = Pixmap;
|
||||
|
||||
emit dataChanged(index(PartIndex, 0), index(PartIndex, 0), { Qt::DecorationRole });
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::DrawPreview(int InfoIndex)
|
||||
{
|
||||
const int Width = mIconSize * 2;
|
||||
const int Height = mIconSize * 2;
|
||||
|
||||
if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height))
|
||||
mView.reset();
|
||||
|
||||
if (!mView)
|
||||
{
|
||||
if (!mModel)
|
||||
mModel = std::unique_ptr<lcModel>(new lcModel(QString(), nullptr, true));
|
||||
mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, mModel.get()));
|
||||
|
||||
mView->SetOffscreenContext();
|
||||
mView->MakeCurrent();
|
||||
mView->SetSize(Width, Height);
|
||||
|
||||
if (!mView->BeginRenderToImage(Width, Height))
|
||||
{
|
||||
mView.reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mView->MakeCurrent();
|
||||
mView->BindRenderFramebuffer();
|
||||
|
||||
const uint BackgroundColor = mListView->palette().color(QPalette::Base).rgba();
|
||||
mView->SetBackgroundColorOverride(LC_RGBA(qRed(BackgroundColor), qGreen(BackgroundColor), qBlue(BackgroundColor), 0));
|
||||
|
||||
PieceInfo* Info = mParts[InfoIndex].first;
|
||||
mModel->SetPreviewPieceInfo(Info, mColorIndex);
|
||||
|
||||
const lcVector3 Center = (Info->GetBoundingBox().Min + Info->GetBoundingBox().Max) / 2.0f;
|
||||
const lcVector3 Position = Center + lcVector3(100.0f, -100.0f, 75.0f);
|
||||
|
||||
mView->GetCamera()->SetViewpoint(Position, Center, lcVector3(0, 0, 1));
|
||||
mView->GetCamera()->m_fovy = 20.0f;
|
||||
mView->ZoomExtents();
|
||||
|
||||
mView->OnDraw();
|
||||
|
||||
mView->UnbindRenderFramebuffer();
|
||||
|
||||
QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
if (Info->GetSynthInfo())
|
||||
{
|
||||
QPainter Painter(&Image);
|
||||
QImage Icon = QImage(":/resources/flexible.png");
|
||||
uchar* ImageBits = Icon.bits();
|
||||
QRgb TextColor = mListView->palette().color(QPalette::WindowText).rgba();
|
||||
int Red = qRed(TextColor);
|
||||
int Green = qGreen(TextColor);
|
||||
int Blue = qBlue(TextColor);
|
||||
|
||||
for (int y = 0; y < Icon.height(); y++)
|
||||
{
|
||||
for (int x = 0; x < Icon.width(); x++)
|
||||
{
|
||||
QRgb& Pixel = ((QRgb*)ImageBits)[x];
|
||||
Pixel = qRgba(Red, Green, Blue, qAlpha(Pixel));
|
||||
}
|
||||
|
||||
ImageBits += Icon.bytesPerLine();
|
||||
}
|
||||
|
||||
Painter.drawImage(QPoint(0, 0), Icon);
|
||||
Painter.end();
|
||||
}
|
||||
|
||||
mParts[InfoIndex].second = QPixmap::fromImage(Image).scaled(mIconSize, mIconSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
lcGetPiecesLibrary()->ReleasePieceInfo(Info);
|
||||
|
||||
emit dataChanged(index(InfoIndex, 0), index(InfoIndex, 0), QVector<int>() << Qt::DecorationRole);
|
||||
}
|
||||
|
||||
void lcPartSelectionListModel::SetShowDecoratedParts(bool Show)
|
||||
{
|
||||
if (Show == mShowDecoratedParts)
|
||||
|
@ -493,8 +401,7 @@ void lcPartSelectionListModel::SetIconSize(int Size)
|
|||
|
||||
beginResetModel();
|
||||
|
||||
for (size_t PartIdx = 0; PartIdx < mParts.size(); PartIdx++)
|
||||
mParts[PartIdx].second = QPixmap();
|
||||
ReleaseThumbnails();
|
||||
|
||||
endResetModel();
|
||||
|
||||
|
@ -1036,9 +943,9 @@ void lcPartSelectionWidget::EditPartPalettes()
|
|||
UpdateCategories();
|
||||
}
|
||||
|
||||
void lcPartSelectionWidget::Redraw()
|
||||
void lcPartSelectionWidget::UpdateThumbnails()
|
||||
{
|
||||
mPartsWidget->GetListModel()->Redraw();
|
||||
mPartsWidget->GetListModel()->UpdateThumbnails();
|
||||
}
|
||||
|
||||
void lcPartSelectionWidget::SetDefaultPart()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
#pragma once
|
||||
|
||||
#include "lc_context.h"
|
||||
#include "lc_thumbnailmanager.h"
|
||||
|
||||
class lcPartSelectionListModel;
|
||||
class lcPartSelectionListView;
|
||||
|
@ -45,6 +45,13 @@ protected:
|
|||
lcPartSelectionListModel* mListModel;
|
||||
};
|
||||
|
||||
struct lcPartSelectionListModelEntry
|
||||
{
|
||||
PieceInfo* Info = nullptr;
|
||||
QPixmap Pixmap;
|
||||
lcPartThumbnailId ThumbnailId = lcPartThumbnailId::Invalid;
|
||||
};
|
||||
|
||||
class lcPartSelectionListModel : public QAbstractListModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
@ -60,12 +67,12 @@ public:
|
|||
|
||||
PieceInfo* GetPieceInfo(const QModelIndex& Index) const
|
||||
{
|
||||
return Index.isValid() ? mParts[Index.row()].first : nullptr;
|
||||
return Index.isValid() ? mParts[Index.row()].Info : nullptr;
|
||||
}
|
||||
|
||||
PieceInfo* GetPieceInfo(int Row) const
|
||||
{
|
||||
return mParts[Row].first;
|
||||
return mParts[Row].Info;
|
||||
}
|
||||
|
||||
bool GetShowDecoratedParts() const
|
||||
|
@ -103,7 +110,7 @@ public:
|
|||
return mListMode;
|
||||
}
|
||||
|
||||
void Redraw();
|
||||
void UpdateThumbnails();
|
||||
void SetColorIndex(int ColorIndex);
|
||||
void ToggleColorLocked();
|
||||
void ToggleListMode();
|
||||
|
@ -112,22 +119,20 @@ public:
|
|||
void SetPaletteCategory(int SetIndex);
|
||||
void SetCurrentModelCategory();
|
||||
void SetFilter(const QString& Filter);
|
||||
void RequestPreview(int InfoIndex);
|
||||
void RequestThumbnail(int PartIndex);
|
||||
void SetShowDecoratedParts(bool Show);
|
||||
void SetShowPartAliases(bool Show);
|
||||
void SetIconSize(int Size);
|
||||
void SetShowPartNames(bool Show);
|
||||
|
||||
protected slots:
|
||||
void PartLoaded(PieceInfo* Info);
|
||||
void ThumbnailReady(lcPartThumbnailId ThumbnailId, QPixmap Pixmap);
|
||||
|
||||
protected:
|
||||
void ClearRequests();
|
||||
void DrawPreview(int InfoIndex);
|
||||
void ReleaseThumbnails();
|
||||
|
||||
lcPartSelectionListView* mListView;
|
||||
std::vector<std::pair<PieceInfo*, QPixmap>> mParts;
|
||||
std::vector<int> mRequestedPreviews;
|
||||
std::vector<lcPartSelectionListModelEntry> mParts;
|
||||
int mIconSize;
|
||||
bool mColorLocked;
|
||||
int mColorIndex;
|
||||
|
@ -136,8 +141,6 @@ protected:
|
|||
bool mShowDecoratedParts;
|
||||
bool mShowPartAliases;
|
||||
QByteArray mFilter;
|
||||
std::unique_ptr<lcView> mView;
|
||||
std::unique_ptr<lcModel> mModel;
|
||||
};
|
||||
|
||||
class lcPartSelectionListView : public QListView
|
||||
|
@ -205,7 +208,7 @@ class lcPartSelectionWidget : public QWidget
|
|||
public:
|
||||
lcPartSelectionWidget(QWidget* Parent);
|
||||
|
||||
void Redraw();
|
||||
void UpdateThumbnails();
|
||||
void SetDefaultPart();
|
||||
void UpdateModels();
|
||||
void UpdateCategories();
|
||||
|
|
148
common/lc_thumbnailmanager.cpp
Normal file
148
common/lc_thumbnailmanager.cpp
Normal file
|
@ -0,0 +1,148 @@
|
|||
#include "lc_global.h"
|
||||
#include "lc_thumbnailmanager.h"
|
||||
#include "lc_library.h"
|
||||
#include "pieceinf.h"
|
||||
#include "lc_view.h"
|
||||
#include "lc_model.h"
|
||||
#include "camera.h"
|
||||
|
||||
lcThumbnailManager::lcThumbnailManager(lcPiecesLibrary* Library)
|
||||
: QObject(Library), mLibrary(Library)
|
||||
{
|
||||
connect(mLibrary, &lcPiecesLibrary::PartLoaded, this, &lcThumbnailManager::PartLoaded);
|
||||
}
|
||||
|
||||
lcThumbnailManager::~lcThumbnailManager()
|
||||
{
|
||||
for (auto &[ThumbnailId, Thumbnail] : mThumbnails)
|
||||
if (Thumbnail.Pixmap.isNull())
|
||||
mLibrary->ReleasePieceInfo(Thumbnail.Info);
|
||||
}
|
||||
|
||||
std::pair<lcPartThumbnailId, QPixmap> lcThumbnailManager::RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size)
|
||||
{
|
||||
for (auto &[ThumbnailId, Thumbnail] : mThumbnails)
|
||||
if (Thumbnail.Info == Info && Thumbnail.ColorIndex == ColorIndex && Thumbnail.Size == Size)
|
||||
return { ThumbnailId, Thumbnail.Pixmap };
|
||||
|
||||
lcPartThumbnailId ThumbnailId = static_cast<lcPartThumbnailId>(mNextThumbnailId++);
|
||||
lcPartThumbnail& Thumbnail = mThumbnails[ThumbnailId];
|
||||
|
||||
Thumbnail.Info = Info;
|
||||
Thumbnail.ColorIndex = ColorIndex;
|
||||
Thumbnail.Size = Size;
|
||||
Thumbnail.ReferenceCount = 1;
|
||||
|
||||
mLibrary->LoadPieceInfo(Info, false, false);
|
||||
|
||||
if (Info->mState == lcPieceInfoState::Loaded)
|
||||
DrawThumbnail(ThumbnailId, Thumbnail);
|
||||
|
||||
return { ThumbnailId, Thumbnail.Pixmap };
|
||||
}
|
||||
|
||||
void lcThumbnailManager::ReleaseThumbnail(lcPartThumbnailId ThumbnailId)
|
||||
{
|
||||
auto ThumbnailIt = mThumbnails.find(ThumbnailId);
|
||||
|
||||
if (ThumbnailIt == mThumbnails.end())
|
||||
return;
|
||||
|
||||
lcPartThumbnail& Thumbnail = ThumbnailIt->second;
|
||||
|
||||
Thumbnail.ReferenceCount--;
|
||||
|
||||
if (Thumbnail.ReferenceCount == 0)
|
||||
{
|
||||
if (Thumbnail.Pixmap.isNull())
|
||||
mLibrary->ReleasePieceInfo(Thumbnail.Info);
|
||||
|
||||
mThumbnails.erase(ThumbnailIt);
|
||||
}
|
||||
}
|
||||
|
||||
void lcThumbnailManager::PartLoaded(PieceInfo* Info)
|
||||
{
|
||||
for (auto& [ThumbnailId, Thumbnail] : mThumbnails)
|
||||
if (Thumbnail.Info == Info && Thumbnail.Pixmap.isNull())
|
||||
DrawThumbnail(ThumbnailId, Thumbnail);
|
||||
}
|
||||
|
||||
void lcThumbnailManager::DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThumbnail& Thumbnail)
|
||||
{
|
||||
const int Width = Thumbnail.Size * 2;
|
||||
const int Height = Thumbnail.Size * 2;
|
||||
|
||||
if (mView && (mView->GetWidth() != Width || mView->GetHeight() != Height))
|
||||
mView.reset();
|
||||
|
||||
if (!mView)
|
||||
{
|
||||
if (!mModel)
|
||||
mModel = std::unique_ptr<lcModel>(new lcModel(QString(), nullptr, true));
|
||||
mView = std::unique_ptr<lcView>(new lcView(lcViewType::PartsList, mModel.get()));
|
||||
|
||||
mView->SetOffscreenContext();
|
||||
mView->MakeCurrent();
|
||||
mView->SetSize(Width, Height);
|
||||
|
||||
if (!mView->BeginRenderToImage(Width, Height))
|
||||
{
|
||||
mView.reset();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mView->MakeCurrent();
|
||||
mView->BindRenderFramebuffer();
|
||||
|
||||
const uint BackgroundColor = QApplication::palette().color(QPalette::Base).rgba();
|
||||
mView->SetBackgroundColorOverride(LC_RGBA(qRed(BackgroundColor), qGreen(BackgroundColor), qBlue(BackgroundColor), 0));
|
||||
|
||||
PieceInfo* Info = Thumbnail.Info;
|
||||
mModel->SetPreviewPieceInfo(Info, Thumbnail.ColorIndex);
|
||||
|
||||
const lcVector3 Center = (Info->GetBoundingBox().Min + Info->GetBoundingBox().Max) / 2.0f;
|
||||
const lcVector3 Position = Center + lcVector3(100.0f, -100.0f, 75.0f);
|
||||
|
||||
mView->GetCamera()->SetViewpoint(Position, Center, lcVector3(0, 0, 1));
|
||||
mView->GetCamera()->m_fovy = 20.0f;
|
||||
mView->ZoomExtents();
|
||||
|
||||
mView->OnDraw();
|
||||
|
||||
mView->UnbindRenderFramebuffer();
|
||||
|
||||
QImage Image = mView->GetRenderFramebufferImage().convertToFormat(QImage::Format_ARGB32);
|
||||
|
||||
if (Info->GetSynthInfo())
|
||||
{
|
||||
QPainter Painter(&Image);
|
||||
QImage Icon = QImage(":/resources/flexible.png");
|
||||
uchar* ImageBits = Icon.bits();
|
||||
QRgb TextColor = QApplication::palette().color(QPalette::WindowText).rgba();
|
||||
int Red = qRed(TextColor);
|
||||
int Green = qGreen(TextColor);
|
||||
int Blue = qBlue(TextColor);
|
||||
|
||||
for (int y = 0; y < Icon.height(); y++)
|
||||
{
|
||||
for (int x = 0; x < Icon.width(); x++)
|
||||
{
|
||||
QRgb& Pixel = ((QRgb*)ImageBits)[x];
|
||||
Pixel = qRgba(Red, Green, Blue, qAlpha(Pixel));
|
||||
}
|
||||
|
||||
ImageBits += Icon.bytesPerLine();
|
||||
}
|
||||
|
||||
Painter.drawImage(QPoint(0, 0), Icon);
|
||||
Painter.end();
|
||||
}
|
||||
|
||||
Thumbnail.Pixmap = QPixmap::fromImage(Image).scaled(Thumbnail.Size, Thumbnail.Size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
|
||||
|
||||
mLibrary->ReleasePieceInfo(Info);
|
||||
|
||||
emit ThumbnailReady(ThumbnailId, Thumbnail.Pixmap);
|
||||
}
|
45
common/lc_thumbnailmanager.h
Normal file
45
common/lc_thumbnailmanager.h
Normal file
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
|
||||
class lcPiecesLibrary;
|
||||
|
||||
struct lcPartThumbnail
|
||||
{
|
||||
QPixmap Pixmap;
|
||||
PieceInfo* Info;
|
||||
int ColorIndex;
|
||||
int Size;
|
||||
int ReferenceCount;
|
||||
};
|
||||
|
||||
enum class lcPartThumbnailId : uint64_t
|
||||
{
|
||||
Invalid = 0
|
||||
};
|
||||
|
||||
class lcThumbnailManager : public QObject
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
lcThumbnailManager(lcPiecesLibrary* Library);
|
||||
~lcThumbnailManager();
|
||||
|
||||
std::pair<lcPartThumbnailId, QPixmap> RequestThumbnail(PieceInfo* Info, int ColorIndex, int Size);
|
||||
void ReleaseThumbnail(lcPartThumbnailId ThumbnailId);
|
||||
|
||||
signals:
|
||||
void ThumbnailReady(lcPartThumbnailId ThumbnailId, QPixmap Pixmap);
|
||||
|
||||
protected slots:
|
||||
void PartLoaded(PieceInfo* Info);
|
||||
|
||||
protected:
|
||||
void DrawThumbnail(lcPartThumbnailId ThumbnailId, lcPartThumbnail& Thumbnail);
|
||||
|
||||
lcPiecesLibrary* mLibrary = nullptr;
|
||||
std::map<lcPartThumbnailId, lcPartThumbnail> mThumbnails;
|
||||
int mNextThumbnailId = 1;
|
||||
|
||||
std::unique_ptr<lcView> mView;
|
||||
std::unique_ptr<lcModel> mModel;
|
||||
};
|
46
leocad.pro
46
leocad.pro
|
@ -165,13 +165,16 @@ macx {
|
|||
}
|
||||
|
||||
SOURCES += \
|
||||
common/texfont.cpp \
|
||||
common/project.cpp \
|
||||
common/pieceinf.cpp \
|
||||
common/piece.cpp \
|
||||
common/object.cpp \
|
||||
common/minifig.cpp \
|
||||
common/camera.cpp \
|
||||
common/group.cpp \
|
||||
common/image.cpp \
|
||||
common/light.cpp \
|
||||
common/minifig.cpp \
|
||||
common/object.cpp \
|
||||
common/piece.cpp \
|
||||
common/pieceinf.cpp \
|
||||
common/project.cpp \
|
||||
common/texfont.cpp \
|
||||
common/lc_aboutdialog.cpp \
|
||||
common/lc_application.cpp \
|
||||
common/lc_arraydialog.cpp \
|
||||
|
@ -204,6 +207,7 @@ SOURCES += \
|
|||
common/lc_modellistdialog.cpp \
|
||||
common/lc_objectproperty.cpp \
|
||||
common/lc_pagesetupdialog.cpp \
|
||||
common/lc_partpalettedialog.cpp \
|
||||
common/lc_partselectionwidget.cpp \
|
||||
common/lc_previewwidget.cpp \
|
||||
common/lc_profile.cpp \
|
||||
|
@ -213,15 +217,13 @@ SOURCES += \
|
|||
common/lc_stringcache.cpp \
|
||||
common/lc_synth.cpp \
|
||||
common/lc_texture.cpp \
|
||||
common/lc_thumbnailmanager.cpp \
|
||||
common/lc_timelinewidget.cpp \
|
||||
common/lc_view.cpp \
|
||||
common/lc_viewmanipulator.cpp \
|
||||
common/lc_viewsphere.cpp \
|
||||
common/lc_viewwidget.cpp \
|
||||
common/lc_zipfile.cpp \
|
||||
common/image.cpp \
|
||||
common/group.cpp \
|
||||
common/camera.cpp \
|
||||
qt/system.cpp \
|
||||
qt/qtmain.cpp \
|
||||
qt/lc_qeditgroupsdialog.cpp \
|
||||
|
@ -233,16 +235,18 @@ SOURCES += \
|
|||
qt/lc_qupdatedialog.cpp \
|
||||
qt/lc_qutils.cpp \
|
||||
qt/lc_renderdialog.cpp \
|
||||
qt/lc_setsdatabasedialog.cpp \
|
||||
common/lc_partpalettedialog.cpp
|
||||
qt/lc_setsdatabasedialog.cpp
|
||||
HEADERS += \
|
||||
common/texfont.h \
|
||||
common/project.h \
|
||||
common/pieceinf.h \
|
||||
common/piece.h \
|
||||
common/object.h \
|
||||
common/minifig.h \
|
||||
common/camera.h \
|
||||
common/group.h \
|
||||
common/image.h \
|
||||
common/light.h \
|
||||
common/minifig.h \
|
||||
common/object.h \
|
||||
common/piece.h \
|
||||
common/pieceinf.h \
|
||||
common/project.h \
|
||||
common/texfont.h \
|
||||
common/lc_aboutdialog.h \
|
||||
common/lc_application.h \
|
||||
common/lc_arraydialog.h \
|
||||
|
@ -277,6 +281,7 @@ HEADERS += \
|
|||
common/lc_modellistdialog.h \
|
||||
common/lc_objectproperty.h \
|
||||
common/lc_pagesetupdialog.h \
|
||||
common/lc_partselectionwidget.h \
|
||||
common/lc_previewwidget.h \
|
||||
common/lc_profile.h \
|
||||
common/lc_propertieswidget.h \
|
||||
|
@ -285,16 +290,13 @@ HEADERS += \
|
|||
common/lc_stringcache.h \
|
||||
common/lc_synth.h \
|
||||
common/lc_texture.h \
|
||||
common/lc_thumbnailmanager.h \
|
||||
common/lc_timelinewidget.h \
|
||||
common/lc_view.h \
|
||||
common/lc_viewmanipulator.h \
|
||||
common/lc_viewsphere.h \
|
||||
common/lc_viewwidget.h \
|
||||
common/lc_zipfile.h \
|
||||
common/lc_partselectionwidget.h \
|
||||
common/lc_timelinewidget.h \
|
||||
common/image.h \
|
||||
common/group.h \
|
||||
common/camera.h \
|
||||
qt/lc_qeditgroupsdialog.h \
|
||||
qt/lc_qselectdialog.h \
|
||||
qt/lc_qpropertiesdialog.h \
|
||||
|
|
Loading…
Reference in a new issue