You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
370 lines
10 KiB
C++
370 lines
10 KiB
C++
/*
|
|
* Copyright (c) Contributors to the Open 3D Engine Project.
|
|
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
|
|
*
|
|
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
|
*
|
|
*/
|
|
|
|
|
|
// Description : Tooltip that displays bitmap.
|
|
|
|
|
|
#include "EditorDefs.h"
|
|
|
|
#include "BitmapToolTip.h"
|
|
|
|
// Qt
|
|
#include <QVBoxLayout>
|
|
|
|
// Editor
|
|
#include "Util/Image.h"
|
|
#include "Util/ImageUtil.h"
|
|
|
|
|
|
static const int STATIC_TEXT_C_HEIGHT = 42;
|
|
static const int HISTOGRAM_C_HEIGHT = 130;
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// CBitmapToolTip
|
|
CBitmapToolTip::CBitmapToolTip(QWidget* parent)
|
|
: QWidget(parent, Qt::ToolTip)
|
|
, m_staticBitmap(new QLabel(this))
|
|
, m_staticText(new QLabel(this))
|
|
, m_rgbaHistogram(new CImageHistogramCtrl(this))
|
|
, m_alphaChannelHistogram(new CImageHistogramCtrl(this))
|
|
{
|
|
m_nTimer = 0;
|
|
m_hToolWnd = nullptr;
|
|
m_bShowHistogram = true;
|
|
m_bShowFullsize = false;
|
|
m_eShowMode = ESHOW_RGB;
|
|
|
|
connect(&m_timer, &QTimer::timeout, this, &CBitmapToolTip::OnTimer);
|
|
|
|
auto* layout = new QVBoxLayout(this);
|
|
layout->setSizeConstraint(QLayout::SetFixedSize);
|
|
|
|
layout->addWidget(m_staticBitmap);
|
|
layout->addWidget(m_staticText);
|
|
|
|
auto* histogramLayout = new QHBoxLayout();
|
|
histogramLayout->addWidget(m_rgbaHistogram);
|
|
histogramLayout->addWidget(m_alphaChannelHistogram);
|
|
m_alphaChannelHistogram->setVisible(false);
|
|
|
|
layout->addLayout(histogramLayout);
|
|
|
|
setLayout(layout);
|
|
}
|
|
|
|
CBitmapToolTip::~CBitmapToolTip()
|
|
{
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CBitmapToolTip::GetShowMode(EShowMode& eShowMode, bool& bShowInOriginalSize) const
|
|
{
|
|
bShowInOriginalSize = CheckVirtualKey(Qt::Key_Space);
|
|
eShowMode = ESHOW_RGB;
|
|
|
|
if (m_bHasAlpha)
|
|
{
|
|
if (CheckVirtualKey(Qt::Key_Control))
|
|
{
|
|
eShowMode = ESHOW_RGB_ALPHA;
|
|
}
|
|
else if (CheckVirtualKey(Qt::Key_Alt))
|
|
{
|
|
eShowMode = ESHOW_ALPHA;
|
|
}
|
|
else if (CheckVirtualKey(Qt::Key_Shift))
|
|
{
|
|
eShowMode = ESHOW_RGBA;
|
|
}
|
|
}
|
|
else if (m_bIsLimitedHDR)
|
|
{
|
|
if (CheckVirtualKey(Qt::Key_Shift))
|
|
{
|
|
eShowMode = ESHOW_RGBE;
|
|
}
|
|
}
|
|
}
|
|
|
|
const char* CBitmapToolTip::GetShowModeDescription(EShowMode eShowMode, [[maybe_unused]] bool bShowInOriginalSize) const
|
|
{
|
|
switch (eShowMode)
|
|
{
|
|
case ESHOW_RGB:
|
|
return "RGB";
|
|
case ESHOW_RGB_ALPHA:
|
|
return "RGB+A";
|
|
case ESHOW_ALPHA:
|
|
return "Alpha";
|
|
case ESHOW_RGBA:
|
|
return "RGBA";
|
|
case ESHOW_RGBE:
|
|
return "RGBExp";
|
|
}
|
|
|
|
return "";
|
|
}
|
|
|
|
void CBitmapToolTip::RefreshViewmode()
|
|
{
|
|
LoadImage(m_filename);
|
|
|
|
if (m_eShowMode == ESHOW_RGB_ALPHA || m_eShowMode == ESHOW_RGBA)
|
|
{
|
|
m_rgbaHistogram->setVisible(true);
|
|
m_alphaChannelHistogram->setVisible(true);
|
|
}
|
|
else if (m_eShowMode == ESHOW_ALPHA)
|
|
{
|
|
m_rgbaHistogram->setVisible(false);
|
|
m_alphaChannelHistogram->setVisible(true);
|
|
}
|
|
else
|
|
{
|
|
m_rgbaHistogram->setVisible(true);
|
|
m_alphaChannelHistogram->setVisible(false);
|
|
}
|
|
}
|
|
|
|
bool CBitmapToolTip::LoadImage(const QString& imageFilename)
|
|
{
|
|
EShowMode eShowMode = ESHOW_RGB;
|
|
const char* pShowModeDescription = "RGB";
|
|
bool bShowInOriginalSize = false;
|
|
|
|
GetShowMode(eShowMode, bShowInOriginalSize);
|
|
pShowModeDescription = GetShowModeDescription(eShowMode, bShowInOriginalSize);
|
|
|
|
QString convertedFileName = Path::GamePathToFullPath(Path::ReplaceExtension(imageFilename, ".dds"));
|
|
|
|
// We need to check against both the image filename and the converted filename as it is possible that the
|
|
// converted file existed but failed to load previously and we reverted to loading the source asset.
|
|
bool alreadyLoadedImage = ((m_filename == convertedFileName) || (m_filename == imageFilename));
|
|
if (alreadyLoadedImage && (m_eShowMode == eShowMode) && (m_bShowFullsize == bShowInOriginalSize))
|
|
{
|
|
return true;
|
|
}
|
|
|
|
CCryFile fileCheck;
|
|
if (!fileCheck.Open(convertedFileName.toUtf8().data(), "rb"))
|
|
{
|
|
// if we didn't find it, then default back to just using what we can find (if any)
|
|
convertedFileName = imageFilename;
|
|
}
|
|
else
|
|
{
|
|
fileCheck.Close();
|
|
}
|
|
|
|
m_eShowMode = eShowMode;
|
|
m_bShowFullsize = bShowInOriginalSize;
|
|
|
|
CImageEx image;
|
|
image.SetHistogramEqualization(CheckVirtualKey(Qt::Key_Shift));
|
|
bool loadedRequestedAsset = true;
|
|
if (!CImageUtil::LoadImage(convertedFileName, image))
|
|
{
|
|
//Failed to load the requested asset, let's try loading the source asset if available.
|
|
loadedRequestedAsset = false;
|
|
if (!CImageUtil::LoadImage(imageFilename, image))
|
|
{
|
|
m_staticBitmap->clear();
|
|
return false;
|
|
}
|
|
}
|
|
|
|
QString imginfo;
|
|
|
|
m_filename = loadedRequestedAsset ? convertedFileName : imageFilename;
|
|
m_bHasAlpha = image.HasAlphaChannel();
|
|
m_bIsLimitedHDR = image.IsLimitedHDR();
|
|
|
|
GetShowMode(eShowMode, bShowInOriginalSize);
|
|
pShowModeDescription = GetShowModeDescription(eShowMode, bShowInOriginalSize);
|
|
|
|
if (m_bHasAlpha)
|
|
{
|
|
imginfo = tr("%1x%2 %3\nShowing %4 (ALT=Alpha, SHIFT=RGBA, CTRL=RGB+A, SPACE=see in original size)");
|
|
}
|
|
else if (m_bIsLimitedHDR)
|
|
{
|
|
imginfo = tr("%1x%2 %3\nShowing %4 (SHIFT=see hist.-equalized, SPACE=see in original size)");
|
|
}
|
|
else
|
|
{
|
|
imginfo = tr("%1x%2 %3\nShowing %4 (SPACE=see in original size)");
|
|
}
|
|
|
|
imginfo = imginfo.arg(image.GetWidth()).arg(image.GetHeight()).arg(image.GetFormatDescription()).arg(pShowModeDescription);
|
|
|
|
m_staticText->setText(imginfo);
|
|
|
|
int w = image.GetWidth();
|
|
int h = image.GetHeight();
|
|
int multiplier = (m_eShowMode == ESHOW_RGB_ALPHA ? 2 : 1);
|
|
int originalW = w * multiplier;
|
|
int originalH = h;
|
|
|
|
if (!bShowInOriginalSize || (w == 0))
|
|
{
|
|
w = 256;
|
|
}
|
|
if (!bShowInOriginalSize || (h == 0))
|
|
{
|
|
h = 256;
|
|
}
|
|
|
|
w *= multiplier;
|
|
|
|
resize(w + 4, h + 4 + STATIC_TEXT_C_HEIGHT + HISTOGRAM_C_HEIGHT);
|
|
setVisible(true);
|
|
|
|
CImageEx scaledImage;
|
|
|
|
if (bShowInOriginalSize && (originalW < w))
|
|
{
|
|
w = originalW;
|
|
}
|
|
if (bShowInOriginalSize && (originalH < h))
|
|
{
|
|
h = originalH;
|
|
}
|
|
|
|
scaledImage.Allocate(w, h);
|
|
|
|
if (m_eShowMode == ESHOW_RGB_ALPHA)
|
|
{
|
|
CImageUtil::ScaleToDoubleFit(image, scaledImage);
|
|
}
|
|
else
|
|
{
|
|
CImageUtil::ScaleToFit(image, scaledImage);
|
|
}
|
|
|
|
if (m_eShowMode == ESHOW_RGB || m_eShowMode == ESHOW_RGBE)
|
|
{
|
|
scaledImage.SwapRedAndBlue();
|
|
scaledImage.FillAlpha();
|
|
}
|
|
else if (m_eShowMode == ESHOW_ALPHA)
|
|
{
|
|
for (int hh = 0; hh < scaledImage.GetHeight(); hh++)
|
|
{
|
|
for (int ww = 0; ww < scaledImage.GetWidth(); ww++)
|
|
{
|
|
int a = scaledImage.ValueAt(ww, hh) >> 24;
|
|
scaledImage.ValueAt(ww, hh) = RGB(a, a, a);
|
|
}
|
|
}
|
|
}
|
|
else if (m_eShowMode == ESHOW_RGB_ALPHA)
|
|
{
|
|
int halfWidth = scaledImage.GetWidth() / 2;
|
|
for (int hh = 0; hh < scaledImage.GetHeight(); hh++)
|
|
{
|
|
for (int ww = 0; ww < halfWidth; ww++)
|
|
{
|
|
int r = GetRValue(scaledImage.ValueAt(ww, hh));
|
|
int g = GetGValue(scaledImage.ValueAt(ww, hh));
|
|
int b = GetBValue(scaledImage.ValueAt(ww, hh));
|
|
int a = scaledImage.ValueAt(ww, hh) >> 24;
|
|
scaledImage.ValueAt(ww, hh) = RGB(b, g, r);
|
|
scaledImage.ValueAt(ww + halfWidth, hh) = RGB(a, a, a);
|
|
}
|
|
}
|
|
}
|
|
else //if (m_showMode == ESHOW_RGBA)
|
|
{
|
|
scaledImage.SwapRedAndBlue();
|
|
}
|
|
|
|
QImage qImage(scaledImage.GetWidth(), scaledImage.GetHeight(), QImage::Format_RGB32);
|
|
memcpy(qImage.bits(), scaledImage.GetData(), qImage.sizeInBytes());
|
|
m_staticBitmap->setPixmap(QPixmap::fromImage(qImage));
|
|
|
|
if (m_bShowHistogram && scaledImage.GetData())
|
|
{
|
|
m_rgbaHistogram->ComputeHistogram(image, CImageHistogram::eImageFormat_32BPP_BGRA);
|
|
m_rgbaHistogram->setDrawMode(EHistogramDrawMode::OverlappedRGB);
|
|
|
|
m_alphaChannelHistogram->histogramDisplay()->CopyComputedDataFrom(m_rgbaHistogram->histogramDisplay());
|
|
m_alphaChannelHistogram->setDrawMode(EHistogramDrawMode::AlphaChannel);
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void CBitmapToolTip::OnTimer()
|
|
{
|
|
/*
|
|
if (IsWindowVisible())
|
|
{
|
|
if (m_bHaveAnythingToRender)
|
|
Invalidate();
|
|
}
|
|
*/
|
|
if (m_hToolWnd)
|
|
{
|
|
QRect toolRc(m_toolRect);
|
|
QRect rc = geometry();
|
|
QPoint cursorPos = QCursor::pos();
|
|
toolRc.moveTopLeft(m_hToolWnd->mapToGlobal(toolRc.topLeft()));
|
|
if (!toolRc.contains(cursorPos) && !rc.contains(cursorPos))
|
|
{
|
|
setVisible(false);
|
|
}
|
|
else
|
|
{
|
|
RefreshViewmode();
|
|
}
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CBitmapToolTip::showEvent([[maybe_unused]] QShowEvent* event)
|
|
{
|
|
QPoint cursorPos = QCursor::pos();
|
|
move(cursorPos);
|
|
m_timer.start(500);
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CBitmapToolTip::hideEvent([[maybe_unused]] QHideEvent* event)
|
|
{
|
|
m_timer.stop();
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
|
|
void CBitmapToolTip::keyPressEvent(QKeyEvent* event)
|
|
{
|
|
if (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift)
|
|
{
|
|
RefreshViewmode();
|
|
}
|
|
}
|
|
|
|
void CBitmapToolTip::keyReleaseEvent(QKeyEvent* event)
|
|
{
|
|
if (event->key() == Qt::Key_Control || event->key() == Qt::Key_Alt || event->key() == Qt::Key_Shift)
|
|
{
|
|
RefreshViewmode();
|
|
}
|
|
}
|
|
|
|
//////////////////////////////////////////////////////////////////////////
|
|
void CBitmapToolTip::SetTool(QWidget* pWnd, const QRect& rect)
|
|
{
|
|
assert(pWnd);
|
|
m_hToolWnd = pWnd;
|
|
m_toolRect = rect;
|
|
}
|
|
|
|
#include <Controls/moc_BitmapToolTip.cpp>
|