3
0

TexturePreviewWidget.cpp 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641
  1. /*
  2. * Copyright (c) Contributors to the Open 3D Engine Project.
  3. * For complete copyright and license terms please see the LICENSE at the root of this distribution.
  4. *
  5. * SPDX-License-Identifier: Apache-2.0 OR MIT
  6. *
  7. */
  8. #include "TexturePreviewWidget.h"
  9. #include <Processing/PixelFormatInfo.h>
  10. #include <Atom/ImageProcessing/ImageObject.h>
  11. #include <AzQtComponents/Components/Widgets/PushButton.h>
  12. #include <AzQtComponents/Components/Widgets/CheckBox.h>
  13. AZ_PUSH_DISABLE_WARNING(4244 4251 4800, "-Wunknown-warning-option") // disable warnings spawned by QT
  14. #include <QCheckBox>
  15. #include <QPushButton>
  16. #include <QToolButton>
  17. #include <QLabel>
  18. #include <QPixmap>
  19. #include <QSvgWidget>
  20. #include <QSize>
  21. #include <QPoint>
  22. #include <QPainter>
  23. #include <QComboBox>
  24. #include <QColor>
  25. #include <QEvent>
  26. #include <QKeyEvent>
  27. #include <QApplicationStateChangeEvent>
  28. #include <QString>
  29. #include <QMenu>
  30. #include <QWidgetAction>
  31. #include <Source/Editor/ui_TexturePreviewWidget.h>
  32. AZ_POP_DISABLE_WARNING
  33. namespace ImageProcessingAtomEditor
  34. {
  35. using namespace ImageProcessingAtom;
  36. TexturePreviewWidget::TexturePreviewWidget(EditorTextureSetting& textureSetting, QWidget* parent /*= nullptr*/)
  37. : QWidget(parent)
  38. , m_ui(new Ui::TexturePreviewWidget)
  39. , m_textureSetting(&textureSetting)
  40. {
  41. m_ui->setupUi(this);
  42. m_platform = BuilderSettingManager::s_defaultPlatform;
  43. // For now, only provide preview for default platform
  44. m_previewConverter = AZStd::make_unique<ImageProcessingAtom::ImagePreview>(m_textureSetting->m_fullPath, &m_textureSetting->GetMultiplatformTextureSetting());
  45. m_updateTimer = new QTimer(this);
  46. connect(m_updateTimer, &QTimer::timeout, this, &TexturePreviewWidget::UpdatePreview);
  47. m_updateTimer->setSingleShot(false);
  48. m_ui->infoLayer->setAttribute(Qt::WA_NoSystemBackground);
  49. m_ui->mipLevelLabel->setAttribute(Qt::WA_NoSystemBackground);
  50. m_ui->imageSizeLabel->setAttribute(Qt::WA_NoSystemBackground);
  51. m_ui->fileSizeLabel->setAttribute(Qt::WA_NoSystemBackground);
  52. m_ui->warningIcon->load(QStringLiteral(":/warning.svg"));
  53. // Setup preview mode combo box
  54. static const QString previewModeString[] = { "RGB",
  55. "R",
  56. "G",
  57. "B",
  58. "Alpha",
  59. "RGBA" };
  60. for (int i = 0; i < (int)PreviewMode::Count; i++)
  61. {
  62. m_ui->previewComboBox->addItem(previewModeString[i]);
  63. }
  64. QSize size = m_ui->imageLabel->size();
  65. m_imageLabelSize = static_cast<float>(size.width());
  66. SetUpResolutionInfo();
  67. RefreshUI(true);
  68. QObject::connect(m_ui->previewCheckBox, &QCheckBox::clicked, this, &TexturePreviewWidget::OnTiledChanged);
  69. QObject::connect(m_ui->nextMipBtn, &QPushButton::clicked, this, &TexturePreviewWidget::OnNextMip);
  70. QObject::connect(m_ui->prevMipBtn, &QPushButton::clicked, this, &TexturePreviewWidget::OnPrevMip);
  71. QObject::connect(m_ui->previewComboBox, static_cast<void(QComboBox::*)(int)>(&QComboBox::currentIndexChanged), this, &TexturePreviewWidget::OnChangePreviewMode);
  72. // Style the Checkbox
  73. AzQtComponents::CheckBox::applyToggleSwitchStyle(m_ui->previewCheckBox);
  74. // Set up Refresh button
  75. m_alwaysRefreshAction = new QAction("Automatic update", this);
  76. m_alwaysRefreshAction->setCheckable(true);
  77. m_alwaysRefreshAction->setChecked(m_alwaysRefreshPreview);
  78. QObject::connect(m_alwaysRefreshAction, &QAction::triggered, this, &TexturePreviewWidget::OnAlwaysRefresh);
  79. m_refreshPerClickAction = new QAction("Manual update", this);
  80. m_refreshPerClickAction->setCheckable(true);
  81. m_refreshPerClickAction->setChecked(!m_alwaysRefreshPreview);
  82. QObject::connect(m_refreshPerClickAction, &QAction::triggered, this, &TexturePreviewWidget::OnRefreshPerClick);
  83. QMenu* menu = new QMenu(this);
  84. menu->addAction(m_alwaysRefreshAction);
  85. menu->addAction(m_refreshPerClickAction);
  86. m_ui->refreshBtn->setMenu(menu);
  87. QObject::connect(m_ui->refreshBtn, &QPushButton::clicked, this, &TexturePreviewWidget::OnRefreshClicked);
  88. m_alwaysRefreshIcon.addFile(QStringLiteral(":/refresh.svg"), QSize(), QIcon::Normal, QIcon::On);
  89. m_refreshPerClickIcon.addFile(QStringLiteral(":/refresh-active.svg"), QSize(), QIcon::Normal, QIcon::On);
  90. m_ui->refreshBtn->setIcon(m_alwaysRefreshIcon);
  91. m_ui->busyLabel->SetBusyIconSize(16);
  92. SetImageLabelText(QString(), false);
  93. // Tooltips
  94. m_ui->mainWidget->setToolTip(QString("Display hotkeys:\nShift - RGBA\nAlt - Alpha\nSpace - Full Resolution"));
  95. m_ui->previewComboBox->setToolTip(QString("Select the texture channel(s) to preview."));
  96. m_ui->previewCheckBox->setToolTip(QString("When enabled, a 2x2 tiled texture preview is displayed."));
  97. m_ui->refreshBtn->setToolTip(QString("Select automatic or manual preview update.\nClick on the button to refresh manually."));
  98. m_ui->prevMipBtn->setToolTip(QString("Display the previous higher level mipmap."));
  99. m_ui->nextMipBtn->setToolTip(QString("Display the next lower level mipmap."));
  100. EditorInternalNotificationBus::Handler::BusConnect();
  101. }
  102. TexturePreviewWidget::~TexturePreviewWidget()
  103. {
  104. EditorInternalNotificationBus::Handler::BusDisconnect();
  105. }
  106. void TexturePreviewWidget::resizeEvent(QResizeEvent* event)
  107. {
  108. QWidget::resizeEvent(event);
  109. QSize size = m_ui->mainWidget->size();
  110. m_ui->infoLayer->resize(size);
  111. QSize imageSize = m_ui->imageLabel->size();
  112. QPoint center = m_ui->mainWidget->rect().center();
  113. m_ui->imageLabel->move(center - QPoint(imageSize.width() / 2, imageSize.height() / 2));
  114. QSize busyLabelSize = m_ui->busyLabel->size();
  115. m_ui->busyLabel->move(center - QPoint(busyLabelSize.width() + m_ui->imageLabel->sizeHint().width() / 2, busyLabelSize.width() / 2));
  116. }
  117. void TexturePreviewWidget::SetUpResolutionInfo()
  118. {
  119. m_resolutionInfos = m_textureSetting->GetResolutionInfoForMipmap(m_platform);
  120. m_mipCount = (unsigned int)m_resolutionInfos.size();
  121. if (m_currentMipIndex > (int)m_mipCount)
  122. {
  123. m_currentMipIndex = 0;
  124. }
  125. }
  126. void TexturePreviewWidget::OnEditorSettingsChanged([[maybe_unused]] bool needRefresh, const AZStd::string& platform)
  127. {
  128. // Only update the preview if there is any change in current platform
  129. if (platform == m_platform)
  130. {
  131. SetUpResolutionInfo();
  132. RefreshUI(true);
  133. }
  134. }
  135. void TexturePreviewWidget::RefreshUI(bool fullRefresh)
  136. {
  137. m_ui->mipLevelLabel->setText(QString("Mipmap Level: %1").arg(QString::number(m_currentMipIndex)));
  138. m_ui->previewCheckBox->setCheckState(m_previewTiled ? Qt::CheckState::Checked : Qt::CheckState::Unchecked);
  139. bool hasNextMip = m_currentMipIndex < (int)m_mipCount - 1;
  140. m_ui->nextMipBtn->setVisible(hasNextMip);
  141. bool hasPrevMip = m_currentMipIndex > 0;
  142. m_ui->prevMipBtn->setVisible(hasPrevMip);
  143. RefreshWarning();
  144. if (m_currentMipIndex < m_resolutionInfos.size())
  145. {
  146. auto it = AZStd::next(m_resolutionInfos.begin(), m_currentMipIndex);
  147. QString finalResolution;
  148. if (it->arrayCount > 1)
  149. {
  150. finalResolution = QString("Resolution: %1 x %2 x %3").arg(QString::number(it->width), QString::number(it->height), QString::number(it->arrayCount));
  151. }
  152. else
  153. {
  154. finalResolution = QString("Resolution: %1 x %2").arg(QString::number(it->width), QString::number(it->height));
  155. }
  156. m_ui->imageSizeLabel->setText(finalResolution);
  157. CPixelFormats& pixelFormats = CPixelFormats::GetInstance();
  158. const PresetSettings* preset = BuilderSettingManager::Instance()->GetPreset(m_textureSetting->GetMultiplatformTextureSetting().m_preset);
  159. if (preset)
  160. {
  161. float size = static_cast<float>(pixelFormats.EvaluateImageDataSize(preset->m_pixelFormat, it->width, it->height));
  162. AZStd::string fileSizeString = EditorHelper::GetFileSizeString(static_cast<AZ::u32>(size));
  163. QString finalFileSize = QString("Size: %1").arg(fileSizeString.c_str());
  164. m_ui->fileSizeLabel->setText(finalFileSize);
  165. }
  166. if (m_alwaysRefreshPreview)
  167. {
  168. RefreshPreviewImage(fullRefresh ? RefreshMode::Convert : RefreshMode::Mip);
  169. }
  170. }
  171. else
  172. {
  173. AZ_Error("Texture Setting", false, "Cannot find mip reduce level for mip %d", m_currentMipIndex);
  174. }
  175. }
  176. void TexturePreviewWidget::OnNextMip()
  177. {
  178. if (m_currentMipIndex >= (int)m_mipCount - 1)
  179. {
  180. return;
  181. }
  182. m_currentMipIndex++;
  183. RefreshUI(false);
  184. }
  185. void TexturePreviewWidget::OnPrevMip()
  186. {
  187. if (m_currentMipIndex <= 0)
  188. {
  189. return;
  190. }
  191. m_currentMipIndex--;
  192. RefreshUI(false);
  193. }
  194. void TexturePreviewWidget::UpdatePreview()
  195. {
  196. if (!m_previewConverter->IsDone())
  197. {
  198. float progress = m_previewConverter->GetProgress();
  199. SetImageLabelText(QString("Converting for preview...Progress %1%").arg(QString::number(progress * 100, 'f', 2)));
  200. return;
  201. }
  202. m_updateTimer->stop();
  203. m_previewImageRaw = m_previewConverter->GetOutputImage();
  204. GenerateMipmap(m_currentMipIndex);
  205. GenerateChannelImage(m_previewMode);
  206. PaintPreviewImage();
  207. }
  208. void TexturePreviewWidget::OnAlwaysRefresh()
  209. {
  210. m_alwaysRefreshPreview = true;
  211. m_alwaysRefreshAction->setChecked(true);
  212. m_refreshPerClickAction->setChecked(false);
  213. m_ui->refreshBtn->setIcon(m_alwaysRefreshIcon);
  214. }
  215. void TexturePreviewWidget::OnRefreshPerClick()
  216. {
  217. m_alwaysRefreshPreview = false;
  218. m_alwaysRefreshAction->setChecked(false);
  219. m_refreshPerClickAction->setChecked(true);
  220. m_ui->refreshBtn->setIcon(m_refreshPerClickIcon);
  221. }
  222. void TexturePreviewWidget::OnRefreshClicked()
  223. {
  224. RefreshPreviewImage(RefreshMode::Convert);
  225. }
  226. void TexturePreviewWidget::GenerateMipmap(int mip)
  227. {
  228. // Clear all cached preview images
  229. for (int i = 0; i < (int)PreviewMode::Count; i++)
  230. {
  231. m_previewImages[i] = QImage();
  232. }
  233. if (m_previewImageRaw && (AZ::u32)mip < m_previewImageRaw->GetMipCount())
  234. {
  235. uint8* imageBuf;
  236. uint32 pitch;
  237. m_previewImageRaw->GetImagePointer(mip, imageBuf, pitch);
  238. const uint32 width = m_previewImageRaw->GetWidth(mip);
  239. const uint32 height = m_previewImageRaw->GetHeight(mip);
  240. m_previewImages[PreviewMode::RGBA] = QImage(imageBuf, width, height, pitch, QImage::Format_RGBA8888);
  241. }
  242. else
  243. {
  244. AZ_Error("Texture Editor", false, "Cannot generate mip preview from an invalid image.");
  245. }
  246. }
  247. void TexturePreviewWidget::GenerateChannelImage(PreviewMode channel)
  248. {
  249. // If there is no preview image generated, ignore this function
  250. if (m_previewImages[PreviewMode::RGBA].isNull())
  251. {
  252. AZ_Error("Texture Editor", false, "Cannot generate channel image from an invalid image.");
  253. return;
  254. }
  255. if (m_previewImages[channel].isNull())
  256. {
  257. // Copy the RGBA image before changing the color
  258. QImage previewImg = m_previewImages[PreviewMode::RGBA].copy();
  259. for (int x = 0; x < previewImg.width(); x++)
  260. {
  261. for (int y = 0; y < previewImg.height(); y++)
  262. {
  263. QRgb pixel = previewImg.pixel(x, y);
  264. int r = qRed(pixel);
  265. int g = qGreen(pixel);
  266. int b = qBlue(pixel);
  267. int a = qAlpha(pixel);
  268. switch (channel)
  269. {
  270. case ImageProcessingAtomEditor::RGB:
  271. pixel = qRgba(r, g, b, 255);
  272. break;
  273. case ImageProcessingAtomEditor::RRR:
  274. pixel = qRgba(r, r, r, 255);
  275. break;
  276. case ImageProcessingAtomEditor::GGG:
  277. pixel = qRgba(g, g, g, 255);
  278. break;
  279. case ImageProcessingAtomEditor::BBB:
  280. pixel = qRgba(b, b, b, 255);
  281. break;
  282. case ImageProcessingAtomEditor::Alpha:
  283. pixel = qRgba(a, a, a, 255);
  284. break;
  285. default:
  286. break;
  287. }
  288. previewImg.setPixel(x, y, pixel);
  289. }
  290. }
  291. // Cache the image in current preview mode
  292. m_previewImages[channel] = previewImg;
  293. }
  294. }
  295. void TexturePreviewWidget::RefreshPreviewImage(RefreshMode mode)
  296. {
  297. // Ignore any none-conversion refresh request when the image is being converted
  298. if (m_updateTimer->isActive() && mode != RefreshMode::Convert)
  299. {
  300. return;
  301. }
  302. switch (mode)
  303. {
  304. case RefreshMode::Convert:
  305. {
  306. // Start conversion in a AZ::Job
  307. m_previewConverter->StartConvert();
  308. // Start the timer to trigger the update function
  309. m_updateTimer->start(s_updateInterval);
  310. SetImageLabelText(QString("Converting for preview...Progress 0.01%"));
  311. }
  312. break;
  313. case RefreshMode::Mip:
  314. {
  315. GenerateMipmap(m_currentMipIndex);
  316. GenerateChannelImage(m_previewMode);
  317. PaintPreviewImage();
  318. }
  319. break;
  320. case RefreshMode::Channel:
  321. {
  322. GenerateChannelImage(m_previewMode);
  323. PaintPreviewImage();
  324. }
  325. break;
  326. default:
  327. PaintPreviewImage();
  328. break;
  329. }
  330. }
  331. void TexturePreviewWidget::PaintPreviewImage()
  332. {
  333. if (m_previewImages[m_previewMode].isNull())
  334. {
  335. SetImageLabelText(QString("Conversion failed, please check console for more information."), false);
  336. return;
  337. }
  338. SetImageLabelText(QString(), false);
  339. // Paint the image on to the image label
  340. QPixmap pixMap = QPixmap::fromImage(m_previewImages[m_previewMode]);
  341. QSize size = m_ui->imageLabel->size();
  342. QPixmap finalPix = pixMap.copy();
  343. finalPix.fill(Qt::transparent);
  344. finalPix = finalPix.scaled(size, Qt::KeepAspectRatio, Qt::SmoothTransformation);
  345. QPainter painter(&finalPix);
  346. painter.setCompositionMode(QPainter::CompositionMode_DestinationOver);
  347. QRect rect = finalPix.rect();
  348. if (m_previewTiled)
  349. {
  350. pixMap = pixMap.scaled(size / 2, Qt::KeepAspectRatio, Qt::SmoothTransformation);
  351. painter.drawTiledPixmap(rect, pixMap);
  352. }
  353. else
  354. {
  355. painter.drawPixmap(rect, pixMap);
  356. }
  357. // Recenter the image label
  358. float aspectRatio = static_cast<float>(finalPix.width()) / static_cast<float>(finalPix.height());
  359. QSize preferredSize;
  360. if (aspectRatio >= 1.0f)
  361. {
  362. preferredSize = QSize(static_cast<int>(m_imageLabelSize), static_cast<int>(m_imageLabelSize / aspectRatio));
  363. }
  364. else
  365. {
  366. preferredSize = QSize(static_cast<int>(m_imageLabelSize * aspectRatio), static_cast<int>(m_imageLabelSize));
  367. }
  368. m_ui->imageLabel->resize(preferredSize);
  369. m_ui->imageLabel->setPixmap(finalPix);
  370. QPoint center = m_ui->mainWidget->rect().center();
  371. m_ui->imageLabel->move(center - QPoint(preferredSize.width() / 2, preferredSize.height() / 2));
  372. }
  373. void TexturePreviewWidget::SetImageLabelText(const QString& text, bool busyStatus /*= true*/)
  374. {
  375. // Since setting pixmap will change the label size
  376. // Need to set back to initial size and recenter before displaying text
  377. m_ui->imageLabel->resize(QSize(static_cast<int>(m_imageLabelSize), static_cast<int>(m_imageLabelSize)));
  378. QPoint center = m_ui->mainWidget->rect().center();
  379. m_ui->imageLabel->move(center - QPoint(static_cast<int>(m_imageLabelSize / 2.0f), static_cast<int>(m_imageLabelSize / 2.0f)));
  380. m_ui->imageLabel->setText(text);
  381. // Set busy label status and position to align with the text
  382. m_ui->busyLabel->SetIsBusy(busyStatus);
  383. QSize size = m_ui->busyLabel->size();
  384. m_ui->busyLabel->move(center - QPoint(size.width() + m_ui->imageLabel->sizeHint().width() / 2, size.width() / 2));
  385. m_ui->busyLabel->setVisible(busyStatus);
  386. }
  387. void TexturePreviewWidget::RefreshWarning()
  388. {
  389. int imageWidth = m_textureSetting->m_img->GetWidth(0);
  390. int imageHeight = m_textureSetting->m_img->GetHeight(0);
  391. AZStd::list<PlatformName> stretchedPlatform;
  392. for (auto& iter: m_textureSetting->m_settingsMap)
  393. {
  394. PlatformName platform = iter.first;
  395. const PresetSettings* presetSettings = BuilderSettingManager::Instance()->GetPreset(iter.second.m_preset, platform);
  396. if (presetSettings)
  397. {
  398. EPixelFormat dstFmt = presetSettings->m_pixelFormat;
  399. if (!CPixelFormats::GetInstance().IsImageSizeValid(dstFmt, imageWidth, imageHeight, false))
  400. {
  401. stretchedPlatform.push_back(EditorHelper::ToReadablePlatformString(platform).c_str());
  402. }
  403. }
  404. }
  405. if (stretchedPlatform.size() > 0)
  406. {
  407. QString warningText = QString("The output image will be stretched on Platform:");
  408. int i = 0;
  409. for (AZStd::string platform: stretchedPlatform)
  410. {
  411. warningText += i > 0 ? ", " : " ";
  412. warningText += platform.c_str();
  413. i++;
  414. }
  415. m_ui->warningLabel->setText(warningText);
  416. m_ui->warningLabel->setVisible(true);
  417. m_ui->warningIcon->setVisible(true);
  418. }
  419. else
  420. {
  421. m_ui->warningLabel->setVisible(false);
  422. m_ui->warningIcon->setVisible(false);
  423. }
  424. }
  425. void TexturePreviewWidget::OnChangePreviewMode(int index)
  426. {
  427. if (index < (int)PreviewMode::Count)
  428. {
  429. m_previewMode = (PreviewMode)index;
  430. RefreshPreviewImage(RefreshMode::Channel);
  431. }
  432. }
  433. void TexturePreviewWidget::OnTiledChanged(bool checked)
  434. {
  435. m_previewTiled = checked;
  436. RefreshPreviewImage(RefreshMode::Repaint);
  437. }
  438. bool TexturePreviewWidget::OnQtEvent(QEvent* event)
  439. {
  440. if (event->type() == QEvent::KeyPress)
  441. {
  442. const QKeyEvent* ke = static_cast<QKeyEvent*>(event);
  443. if (ke->isAutoRepeat())
  444. {
  445. return false; //ignore repeat key event
  446. }
  447. if (ke->key() == Qt::Key_Space)
  448. {
  449. if (!m_updateTimer->isActive()) // Only popup when image is not converting
  450. {
  451. m_previewPopup.reset(new ImagePopup(m_previewImages[m_previewMode], this));
  452. m_previewPopup->installEventFilter(this);
  453. m_previewPopup->show();
  454. event->accept();
  455. return true;
  456. }
  457. }
  458. else if (ke->key() == Qt::Key_Alt)
  459. {
  460. m_previewMode = PreviewMode::Alpha;
  461. RefreshPreviewImage(RefreshMode::Channel);
  462. event->accept();
  463. return true;
  464. }
  465. else if (ke->key() == Qt::Key_Shift)
  466. {
  467. m_previewMode = PreviewMode::RGBA;
  468. RefreshPreviewImage(RefreshMode::Channel);
  469. event->accept();
  470. return true;
  471. }
  472. }
  473. else if (event->type() == QEvent::KeyRelease)
  474. {
  475. const QKeyEvent* ke = static_cast<QKeyEvent*>(event);
  476. if (ke->isAutoRepeat())
  477. {
  478. return false; //ignore repeat key event
  479. }
  480. if (ke->key() == Qt::Key_Space)
  481. {
  482. if (m_previewPopup)
  483. {
  484. m_previewPopup->hide();
  485. }
  486. event->accept();
  487. return true;
  488. }
  489. else if (ke->key() == Qt::Key_Alt)
  490. {
  491. m_previewMode = (PreviewMode)m_ui->previewComboBox->currentIndex();
  492. RefreshPreviewImage(RefreshMode::Channel);
  493. event->accept();
  494. return true;
  495. }
  496. else if (ke->key() == Qt::Key_Shift)
  497. {
  498. m_previewMode = (PreviewMode)m_ui->previewComboBox->currentIndex();
  499. RefreshPreviewImage(RefreshMode::Channel);
  500. event->accept();
  501. return true;
  502. }
  503. }
  504. else if (event->type() == QEvent::ApplicationStateChange)
  505. {
  506. const QApplicationStateChangeEvent* appEvent = static_cast<QApplicationStateChangeEvent*>(event);
  507. AZ_Warning("Texture Editor", false, "app status change %d", appEvent->applicationState());
  508. if (appEvent->applicationState() != Qt::ApplicationState::ApplicationActive)
  509. {
  510. PreviewMode currPreviewMode = (PreviewMode)m_ui->previewComboBox->currentIndex();
  511. if (m_previewMode != currPreviewMode)
  512. {
  513. m_previewMode = currPreviewMode;
  514. RefreshPreviewImage(RefreshMode::Channel);
  515. event->accept();
  516. return true;
  517. }
  518. }
  519. }
  520. else if (event->type() == QEvent::ShortcutOverride)
  521. {
  522. // since we respond to the following things, let Qt know so that shortcuts don't override us
  523. QKeyEvent* kev = static_cast<QKeyEvent*>(event);
  524. int key = kev->key() | kev->modifiers();
  525. switch (key)
  526. {
  527. case Qt::Key_Space:
  528. case Qt::Key_Alt:
  529. case Qt::Key_Shift:
  530. event->accept();
  531. return true;
  532. break;
  533. default:
  534. break;
  535. }
  536. }
  537. return false;
  538. }
  539. bool TexturePreviewWidget::eventFilter(QObject* obj, QEvent* event)
  540. {
  541. if (event->type() == QEvent::KeyRelease)
  542. {
  543. const QKeyEvent* ke = static_cast<QKeyEvent*>(event);
  544. if (ke->key() == Qt::Key_Space && !ke->isAutoRepeat())
  545. {
  546. if (m_previewPopup)
  547. {
  548. m_previewPopup->hide();
  549. }
  550. return true;
  551. }
  552. }
  553. else if (event->type() == QEvent::ApplicationStateChange)
  554. {
  555. const QApplicationStateChangeEvent* appEvent = static_cast<QApplicationStateChangeEvent*>(event);
  556. if (appEvent->applicationState() != Qt::ApplicationState::ApplicationActive)
  557. {
  558. if (m_previewPopup)
  559. {
  560. m_previewPopup->hide();
  561. }
  562. }
  563. return true;
  564. }
  565. return QWidget::eventFilter(obj, event);
  566. }
  567. }//namespace ImageProcessingAtomEditor
  568. #include <Source/Editor/moc_TexturePreviewWidget.cpp>