leocad/common/lc_thumbnailmanager.cpp
2024-11-14 12:45:34 -08:00

154 lines
4.3 KiB
C++

#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);
const char* IconName = nullptr;
if (Info->GetSynthInfo())
IconName = ":/resources/part_flexible.png";
else if (Info->GetTrainTrackInfo())
IconName = ":/resources/part_traintrack.png";
if (IconName)
{
QPainter Painter(&Image);
QImage Icon = QImage(IconName);
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);
}