Merge branch 'development' into Atom/santorac/RemixableMaterialTypes4_Layering

Signed-off-by: santorac <55155825+santorac@users.noreply.github.com>
This commit is contained in:
santorac
2022-02-01 12:24:14 -08:00
467 changed files with 29360 additions and 6960 deletions
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa
size 41127
oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
size 1232
@@ -62,15 +62,16 @@ def Multiplayer_AutoComponent_RPC():
Report.critical_result(TestSuccessFailTuples.find_network_player, player_id.IsValid())
# 4) Check the editor logs for expected and unexpected log output
# Authority->Autonomous RPC
PLAYERID_RPC_WAIT_TIME_SECONDS = 1.0 # The player id is sent from the server as soon as the player script is spawned. 1 second should be more than enough time to send/receive that RPC.
helper.succeed_if_log_line_found('EditorServer', 'Script: AutoComponent_RPC: Sending client PlayerNumber 1', section_tracer.prints, PLAYERID_RPC_WAIT_TIME_SECONDS)
helper.succeed_if_log_line_found('Script', "AutoComponent_RPC: I'm Player #1", section_tracer.prints, PLAYERID_RPC_WAIT_TIME_SECONDS)
# Uncomment once editor game-play mode supports level entities with net-binding
#PLAYFX_RPC_WAIT_TIME_SECONDS = 1.1 # The server will send an RPC to play an fx on the client every second.
#helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity Activated on entity: NetLevelEntity", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
#helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity: Authority sending RPC to play some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
#helper.succeed_if_log_line_found('Script', "AutoComponent_RPC_NetLevelEntity: I'm a client playing some superficial fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
# Authority->Client RPC
PLAYFX_RPC_WAIT_TIME_SECONDS = 1.1 # The server will send an RPC to play an fx on the client every second.
helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity Activated on entity: NetLevelEntity", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
helper.succeed_if_log_line_found('EditorServer', "Script: AutoComponent_RPC_NetLevelEntity: Authority sending RPC to play some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
helper.succeed_if_log_line_found('Script', "AutoComponent_RPC_NetLevelEntity: I'm a client playing some fx.", section_tracer.prints, PLAYFX_RPC_WAIT_TIME_SECONDS)
# Exit game mode
@@ -93,7 +93,7 @@ def Terrain_World_ConfigurationWorks():
# 5) Set the base Terrain World values
world_bounds_max = azmath.Vector3(1100.0, 1100.0, 1100.0)
world_bounds_min = azmath.Vector3(10.0, 10.0, 10.0)
height_query_resolution = azmath.Vector2(1.0, 1.0)
height_query_resolution = 1.0
hydra.set_component_property_value(terrain_world_component, "Configuration|World Bounds (Max)", world_bounds_max)
hydra.set_component_property_value(terrain_world_component, "Configuration|World Bounds (Min)", world_bounds_min)
hydra.set_component_property_value(terrain_world_component, "Configuration|Height Query Resolution (m)", height_query_resolution)
@@ -148,7 +148,7 @@ def Terrain_World_ConfigurationWorks():
# 13) Check height value is the expected one when query resolution is changed
testpoint = terrain.TerrainDataRequestBus(bus.Broadcast, 'GetHeightFromFloats', 10.5, 10.5, CLAMP)
height_query_resolution = azmath.Vector2(0.5, 0.5)
height_query_resolution = 0.5
hydra.set_component_property_value(terrain_world_component, "Configuration|Height Query Resolution (m)", height_query_resolution)
general.idle_wait_frames(1)
testpoint2 = terrain.TerrainDataRequestBus(bus.Broadcast, 'GetHeightFromFloats', 10.5, 10.5, CLAMP)
@@ -165,4 +165,3 @@ if __name__ == "__main__":
from editor_python_test_tools.utils import Report
Report.start_test(Terrain_World_ConfigurationWorks)
@@ -38,7 +38,7 @@ def Menus_FileMenuOptions_Work():
("Save As",),
("Save Level Statistics",),
("Edit Project Settings",),
#("Edit Platform Settings",), Temporarily disabled due to https://github.com/o3de/o3de/issues/6604
("Edit Platform Settings",),
("New Project",),
("Open Project",),
("Show Log File",),
+3
View File
@@ -0,0 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
size 1232
+2 -2
View File
@@ -1,3 +1,3 @@
version https://git-lfs.github.com/spec/v1
oid sha256:6d6204c6730e5675791765ca194e9b1cbec282208e280507de830afc2805e5fa
size 41127
oid sha256:de0e6e480ece5b423222f4feacf56553d73713fe9afea8bbc9a2660a3cd54ec7
size 1232
@@ -568,22 +568,10 @@
"$type": "EditorScriptCanvasComponent",
"Id": 14750978061505735417,
"m_name": "GlobalGameData",
"m_assetHolder": {
"m_asset": {
"assetId": {
"guid": "{B16589A0-EA01-56BC-8141-91A3967FB95F}"
},
"assetHint": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas"
}
},
"runtimeDataIsValid": true,
"runtimeDataOverrides": {
"source": {
"assetId": {
"guid": "{B16589A0-EA01-56BC-8141-91A3967FB95F}"
},
"assetHint": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas"
}
"sourceHandle": {
"id": "{B16589A0-EA01-56BC-8141-91A3967FB95F}",
"path": "levels/multiplayer/autocomponent_rpc/globalgamedata.scriptcanvas"
}
},
"Component_[16436925042043744033]": {
@@ -636,6 +624,13 @@
"$type": "SelectionComponent",
"Id": 12302672911455629152
},
"Component_[12517591696100736853]": {
"$type": "GenericComponentWrapper",
"Id": 12517591696100736853,
"m_template": {
"$type": "AutomatedTesting::NetworkTestLevelEntityComponent"
}
},
"Component_[14169903623243423134]": {
"$type": "EditorVisibilityComponent",
"Id": 14169903623243423134
@@ -644,13 +639,6 @@
"$type": "EditorInspectorComponent",
"Id": 14607413934411389854
},
"Component_[15396284312416541768]": {
"$type": "GenericComponentWrapper",
"Id": 15396284312416541768,
"m_template": {
"$type": "Multiplayer::LocalPredictionPlayerInputComponent"
}
},
"Component_[15494977028055234270]": {
"$type": "EditorDisabledCompositionComponent",
"Id": 15494977028055234270
@@ -682,22 +670,10 @@
"$type": "EditorScriptCanvasComponent",
"Id": 7256163899440301540,
"m_name": "AutoComponent_RPC_NetLevelEntity",
"m_assetHolder": {
"m_asset": {
"assetId": {
"guid": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}"
},
"assetHint": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas"
}
},
"runtimeDataIsValid": true,
"runtimeDataOverrides": {
"source": {
"assetId": {
"guid": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}"
},
"assetHint": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas"
}
"sourceHandle": {
"id": "{1D517006-AC01-5ECA-AE66-0E007871F0CD}",
"path": "levels/multiplayer/autocomponent_rpc/autocomponent_rpc_netlevelentity.scriptcanvas"
}
},
"Component_[731336627222243355]": {
@@ -730,13 +706,6 @@
"$type": "NetBindComponent"
}
},
"Component_[9816897251206708579]": {
"$type": "GenericComponentWrapper",
"Id": 9816897251206708579,
"m_template": {
"$type": "AutomatedTesting::NetworkTestPlayerComponent"
}
},
"Component_[9880860858035405475]": {
"$type": "EditorOnlyEntityComponent",
"Id": 9880860858035405475
File diff suppressed because it is too large Load Diff
+11 -1
View File
@@ -42,6 +42,16 @@
"RayTracingAccelerationStructurePass"
]
},
{
"Name": "TerrainDetailTextureComputePass",
"TemplateName": "TerrainDetailTextureComputePassTemplate",
"Enabled": false
},
{
"Name": "TerrainMacroTextureComputePass",
"TemplateName": "TerrainMacroTextureComputePassTemplate",
"Enabled": false
},
{
"Name": "DepthPrePass",
"TemplateName": "DepthMSAAParentTemplate",
@@ -215,7 +225,7 @@
// Note: The following two lines represent the choice of rendering pipeline for the hair.
// You can either choose to use PPLL or ShortCut and accordingly change the flag
// 'm_usePPLLRenderTechnique' in the class 'HairFeatureProcessor.cpp'
// "TemplateName": "HairParentPassTemplate",
// "TemplateName": "HairParentPassTemplate",
"TemplateName": "HairParentShortCutPassTemplate",
"Enabled": true,
"Connections": [
@@ -78,10 +78,7 @@
<enum>Qt::ClickFocus</enum>
</property>
<property name="toolTip">
<string extracomment="Collapse All"/>
</property>
<property name="toolTipDuration">
<number>3</number>
<string extracomment="Collapse All">Collapse All</string>
</property>
<property name="text">
<string/>
-369
View File
@@ -1,369 +0,0 @@
/*
* 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>
-88
View File
@@ -1,88 +0,0 @@
/*
* 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.
#ifndef CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H
#define CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H
#pragma once
#if !defined(Q_MOC_RUN)
#include "Controls/ImageHistogramCtrl.h"
#include <QLabel>
#include <QTimer>
#endif
//////////////////////////////////////////////////////////////////////////
class CBitmapToolTip
: public QWidget
{
Q_OBJECT
// Construction
public:
enum EShowMode
{
ESHOW_RGB = 0,
ESHOW_ALPHA,
ESHOW_RGBA,
ESHOW_RGB_ALPHA,
ESHOW_RGBE
};
CBitmapToolTip(QWidget* parent = nullptr);
virtual ~CBitmapToolTip();
bool Create(const RECT& rect);
// Attributes
public:
// Operations
public:
void RefreshViewmode();
bool LoadImage(const QString& imageFilename);
void SetTool(QWidget* pWnd, const QRect& rect);
// Generated message map functions
protected:
void OnTimer();
void keyPressEvent(QKeyEvent* event) override;
void keyReleaseEvent(QKeyEvent* event) override;
void showEvent(QShowEvent* event) override;
void hideEvent(QHideEvent* event) override;
private:
void GetShowMode(EShowMode& showMode, bool& showInOriginalSize) const;
const char* GetShowModeDescription(EShowMode showMode, bool showInOriginalSize) const;
QLabel* m_staticBitmap;
QLabel* m_staticText;
QString m_filename;
bool m_bShowHistogram;
EShowMode m_eShowMode;
bool m_bShowFullsize;
bool m_bHasAlpha;
bool m_bIsLimitedHDR;
CImageHistogramCtrl* m_rgbaHistogram;
CImageHistogramCtrl* m_alphaChannelHistogram;
int m_nTimer;
QWidget* m_hToolWnd;
QRect m_toolRect;
QTimer m_timer;
};
#endif // CRYINCLUDE_EDITOR_CONTROLS_BITMAPTOOLTIP_H
@@ -1,172 +0,0 @@
/*
* 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
*
*/
#include "EditorDefs.h"
#include "QBitmapPreviewDialog.h"
#include <Controls/ui_QBitmapPreviewDialog.h>
#include <QApplication>
#include <QDesktopWidget>
#include <QPainter>
#include <QScreen>
void QBitmapPreviewDialog::ImageData::setRgba8888(const void* buffer, const int& w, const int& h)
{
const unsigned long bytes = w * h * 4;
m_buffer.resize(bytes);
memcpy(m_buffer.data(), buffer, bytes);
m_image = QImage((uchar*)m_buffer.constData(), w, h, QImage::Format::Format_RGBA8888);
}
static void fillChecker(int w, int h, unsigned int* dst)
{
for (int y = 0; y < h; y++)
{
for (int x = 0; x < w; x++)
{
dst[y * w + x] = 0xFF000000 | (((x >> 2) + (y >> 2)) % 2 == 0 ? 0x007F7F7F : 0x00000000);
}
}
}
QBitmapPreviewDialog::QBitmapPreviewDialog(QWidget* parent)
: QWidget(parent)
, ui(new Ui::QBitmapTooltip)
{
ui->setupUi(this);
setAttribute(Qt::WA_TranslucentBackground);
setAttribute(Qt::WA_ShowWithoutActivating);
// Clear label text
ui->m_placeholderBitmap->setText("");
ui->m_placeholderHistogram->setText("");
ui->m_bitmapSize->setProperty("tableRow", "Odd");
ui->m_Mips->setProperty("tableRow", "Even");
ui->m_Mean->setProperty("tableRow", "Odd");
ui->m_StdDev->setProperty("tableRow", "Even");
ui->m_Median->setProperty("tableRow", "Odd");
ui->m_labelForBitmapSize->setProperty("tooltipLabel", "content");
ui->m_labelForMean->setProperty("tooltipLabel", "content");
ui->m_labelForMedian->setProperty("tooltipLabel", "content");
ui->m_labelForMips->setProperty("tooltipLabel", "content");
ui->m_labelForStdDev->setProperty("tooltipLabel", "content");
ui->m_vBitmapSize->setProperty("tooltipLabel", "content");
ui->m_vMean->setProperty("tooltipLabel", "content");
ui->m_vMedian->setProperty("tooltipLabel", "content");
ui->m_vMips->setProperty("tooltipLabel", "content");
ui->m_vStdDev->setProperty("tooltipLabel", "content");
// Initialize placeholder images
const int w = 64;
const int h = 64;
QByteArray buffer;
buffer.resize(w * h * 4);
unsigned int* dst = (unsigned int*)buffer.data();
fillChecker(w, h, dst);
m_checker.setRgba8888(buffer.constData(), w, h);
m_initialSize = window()->window()->geometry().size();
}
QBitmapPreviewDialog::~QBitmapPreviewDialog()
{
delete ui;
}
void QBitmapPreviewDialog::setImageRgba8888(const void* buffer, const int& w, const int& h, [[maybe_unused]] const QString& info)
{
m_imageMain.setRgba8888(buffer, w, h);
}
QRect QBitmapPreviewDialog::getHistogramArea()
{
return QRect(ui->m_placeholderHistogram->pos(), ui->m_placeholderHistogram->size());
}
void QBitmapPreviewDialog::setFullSize(const bool& fullSize)
{
if (fullSize)
{
QSize desktop = QApplication::screenAt(ui->m_placeholderBitmap->pos())->availableGeometry().size();
QSize image = m_imageMain.m_image.size();
QPoint location = mapToGlobal(ui->m_placeholderBitmap->pos());
QSize finalSize;
finalSize.setWidth((image.width() < (desktop.width() - location.x())) ? image.width() : (desktop.width() - location.x()));
finalSize.setHeight((image.height() < (desktop.height() - location.y())) ? image.height() : (desktop.height() - location.y()));
float scale = (finalSize.width() < finalSize.height()) ? finalSize.width() / float(m_imageMain.m_image.width()) : finalSize.height() / float(m_imageMain.m_image.height());
ui->m_placeholderBitmap->setFixedSize(scale * m_imageMain.m_image.size());
}
else
{
ui->m_placeholderBitmap->setFixedSize(256, 256);
}
adjustSize();
update();
}
void QBitmapPreviewDialog::paintEvent(QPaintEvent* e)
{
QWidget::paintEvent(e);
QRect rect(ui->m_placeholderBitmap->pos(), ui->m_placeholderBitmap->size());
drawImageData(rect, m_imageMain);
}
void QBitmapPreviewDialog::drawImageData(const QRect& rect, const ImageData& imgData)
{
// Draw the
QPainter p(this);
p.drawImage(rect.topLeft(), m_checker.m_image.scaled(rect.size()));
p.drawImage(rect.topLeft(), imgData.m_image.scaled(rect.size()));
// Draw border
QPen pen;
pen.setColor(QColor(0, 0, 0));
p.drawRect(rect.top(), rect.left(), rect.width() - 1, rect.height());
}
void QBitmapPreviewDialog::setSize(QString _value)
{
ui->m_vBitmapSize->setText(_value);
}
void QBitmapPreviewDialog::setMips(QString _value)
{
ui->m_vMips->setText(_value);
}
void QBitmapPreviewDialog::setMean(QString _value)
{
ui->m_vMean->setText(_value);
}
void QBitmapPreviewDialog::setMedian(QString _value)
{
ui->m_vMedian->setText(_value);
}
void QBitmapPreviewDialog::setStdDev(QString _value)
{
ui->m_vStdDev->setText(_value);
}
QSize QBitmapPreviewDialog::GetCurrentBitmapSize()
{
return ui->m_placeholderBitmap->size();
}
QSize QBitmapPreviewDialog::GetOriginalImageSize()
{
return m_imageMain.m_image.size();
}
#include <Controls/moc_QBitmapPreviewDialog.cpp>
@@ -1,64 +0,0 @@
/*
* 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
*
*/
#ifndef QBITMAPPREVIEWDIALOG_H
#define QBITMAPPREVIEWDIALOG_H
#if !defined(Q_MOC_RUN)
#include <QWidget>
#include <QPixmap>
#include <QImage>
#endif
class QLabel;
namespace Ui {
class QBitmapTooltip;
}
class QBitmapPreviewDialog
: public QWidget
{
Q_OBJECT
struct ImageData
{
QByteArray m_buffer;
QImage m_image;
void setRgba8888(const void* buffer, const int& w, const int& h);
};
public:
explicit QBitmapPreviewDialog(QWidget* parent = 0);
virtual ~QBitmapPreviewDialog();
QSize GetCurrentBitmapSize();
QSize GetOriginalImageSize();
protected:
void setImageRgba8888(const void* buffer, const int& w, const int& h, const QString& info);
void setSize(QString _value);
void setMips(QString _value);
void setMean(QString _value);
void setMedian(QString _value);
void setStdDev(QString _value);
QRect getHistogramArea();
void setFullSize(const bool& fullSize);
void paintEvent(QPaintEvent* e) override;
private:
void drawImageData(const QRect& rect, const ImageData& imgData);
protected:
Ui::QBitmapTooltip* ui;
QSize m_initialSize;
ImageData m_checker;
ImageData m_imageMain;
};
#endif // QBITMAPPREVIEWDIALOG_H
@@ -1,390 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>QBitmapTooltip</class>
<widget class="QWidget" name="QBitmapTooltip">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>256</width>
<height>510</height>
</rect>
</property>
<property name="minimumSize">
<size>
<width>256</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Form</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_placeholderBitmap">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>256</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="autoFillBackground">
<bool>false</bool>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string>Bitmap Area</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
<property name="wordWrap">
<bool>false</bool>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_placeholderHistogram">
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>128</height>
</size>
</property>
<property name="frameShape">
<enum>QFrame::NoFrame</enum>
</property>
<property name="frameShadow">
<enum>QFrame::Sunken</enum>
</property>
<property name="text">
<string>Histogram Area</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item>
<widget class="QWidget" name="m_bitmapSize" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_labelForBitmapSize">
<property name="text">
<string>Size:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_vBitmapSize">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Size Value</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_Mips" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_2">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_labelForMips">
<property name="text">
<string>DXT5 Mips:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_vMips">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Size Value</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_Mean" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_3">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_labelForMean">
<property name="text">
<string>Mean:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_vMean">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Size Value</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_StdDev" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_5">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_labelForStdDev">
<property name="text">
<string>StdDev:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_vStdDev">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Size Value</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="QWidget" name="m_Median" native="true">
<property name="minimumSize">
<size>
<width>0</width>
<height>24</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>24</height>
</size>
</property>
<property name="styleSheet">
<string notr="true"/>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_4">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QLabel" name="m_labelForMedian">
<property name="text">
<string>Median:</string>
</property>
</widget>
</item>
<item>
<widget class="QLabel" name="m_vMedian">
<property name="layoutDirection">
<enum>Qt::RightToLeft</enum>
</property>
<property name="text">
<string>Size Value</string>
</property>
<property name="alignment">
<set>Qt::AlignRight|Qt::AlignTrailing|Qt::AlignVCenter</set>
</property>
</widget>
</item>
</layout>
</widget>
</item>
</layout>
</widget>
<resources/>
<connections/>
</ui>
@@ -1,528 +0,0 @@
/*
* 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
*
*/
#include "EditorDefs.h"
#include "QBitmapPreviewDialogImp.h"
// Cry
#include <ITexture.h>
// EditorCore
#include <Util/Image.h>
#include <Include/IImageUtil.h>
// QT
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...'
#include <QEvent>
#include <QKeyEvent>
#include <QPainter>
#include <QPainterPath>
#include <qmath.h>
AZ_POP_DISABLE_WARNING
#include <Controls/ui_QBitmapPreviewDialog.h>
static const int kDefaultWidth = 256;
static const int kDefaultHeight = 256;
QBitmapPreviewDialogImp::QBitmapPreviewDialogImp(QWidget* parent)
: QBitmapPreviewDialog(parent)
, m_image(new CImageEx())
, m_showOriginalSize(false)
, m_showMode(ESHOW_RGB)
, m_histrogramMode(eHistogramMode_OverlappedRGB)
{
setMouseTracking(true);
setImage("");
ui->m_placeholderBitmap->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
ui->m_placeholderHistogram->setStyleSheet("background-color: rgba(0, 0, 0, 0);");
ui->m_labelForBitmapSize->setProperty("tooltipLabel", "Content");
ui->m_labelForMean->setProperty("tooltipLabel", "Content");
ui->m_labelForMedian->setProperty("tooltipLabel", "Content");
ui->m_labelForMips->setProperty("tooltipLabel", "Content");
ui->m_labelForStdDev->setProperty("tooltipLabel", "Content");
ui->m_vBitmapSize->setProperty("tooltipLabel", "Content");
ui->m_vMean->setProperty("tooltipLabel", "Content");
ui->m_vMedian->setProperty("tooltipLabel", "Content");
ui->m_vMips->setProperty("tooltipLabel", "Content");
ui->m_vStdDev->setProperty("tooltipLabel", "Content");
setUIStyleMode(EUISTYLE_IMAGE_ONLY);
}
QBitmapPreviewDialogImp::~QBitmapPreviewDialogImp()
{
SAFE_DELETE(m_image);
}
void QBitmapPreviewDialogImp::setImage(const QString path)
{
if (path.isEmpty()
|| m_path == path
|| !GetIEditor()->GetImageUtil()->LoadImage(path.toUtf8().data(), *m_image))
{
return;
}
m_showOriginalSize = isSizeSmallerThanDefault();
m_path = path;
refreshData();
}
void QBitmapPreviewDialogImp::setShowMode(EShowMode mode)
{
if (mode == ESHOW_NumModes)
{
return;
}
m_showMode = mode;
refreshData();
update();
}
void QBitmapPreviewDialogImp::toggleShowMode()
{
m_showMode = (EShowMode)(((int)m_showMode + 1) % ESHOW_NumModes);
refreshData();
update();
}
void QBitmapPreviewDialogImp::setUIStyleMode(EUIStyle mode)
{
if (mode >= EUISTYLE_NumModes)
{
return;
}
m_uiStyle = mode;
if (m_uiStyle == EUISTYLE_IMAGE_ONLY)
{
ui->m_placeholderHistogram->hide();
ui->m_labelForBitmapSize->hide();
ui->m_labelForMean->hide();
ui->m_labelForMedian->hide();
ui->m_labelForMips->hide();
ui->m_labelForStdDev->hide();
ui->m_vBitmapSize->hide();
ui->m_vMean->hide();
ui->m_vMedian->hide();
ui->m_vMips->hide();
ui->m_vStdDev->hide();
}
else
{
ui->m_placeholderHistogram->show();
ui->m_labelForBitmapSize->show();
ui->m_labelForMean->show();
ui->m_labelForMedian->show();
ui->m_labelForMips->show();
ui->m_labelForStdDev->show();
ui->m_vBitmapSize->show();
ui->m_vMean->show();
ui->m_vMedian->show();
ui->m_vMips->show();
ui->m_vStdDev->show();
}
}
const QBitmapPreviewDialogImp::EShowMode& QBitmapPreviewDialogImp::getShowMode() const
{
return m_showMode;
}
void QBitmapPreviewDialogImp::setHistogramMode(EHistogramMode mode)
{
if (mode == eHistogramMode_NumModes)
{
return;
}
m_histrogramMode = mode;
}
void QBitmapPreviewDialogImp::toggleHistrogramMode()
{
m_histrogramMode = (EHistogramMode)(((int)m_histrogramMode + 1) % eHistogramMode_NumModes);
update();
}
const QBitmapPreviewDialogImp::EHistogramMode& QBitmapPreviewDialogImp::getHistogramMode() const
{
return m_histrogramMode;
}
void QBitmapPreviewDialogImp::toggleOriginalSize()
{
m_showOriginalSize = !m_showOriginalSize;
refreshData();
update();
}
bool QBitmapPreviewDialogImp::isSizeSmallerThanDefault()
{
return m_image->GetWidth() < kDefaultWidth && m_image->GetHeight() < kDefaultHeight;
}
void QBitmapPreviewDialogImp::setOriginalSize(bool value)
{
m_showOriginalSize = value;
refreshData();
update();
}
const char* QBitmapPreviewDialogImp::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 "";
}
const char* getHistrogramModeStr(QBitmapPreviewDialogImp::EHistogramMode mode, bool shortName)
{
switch (mode)
{
case QBitmapPreviewDialogImp::eHistogramMode_Luminosity:
return shortName ? "Lum" : "Luminosity";
case QBitmapPreviewDialogImp::eHistogramMode_OverlappedRGB:
return shortName ? "Overlap" : "Overlapped RGBA";
case QBitmapPreviewDialogImp::eHistogramMode_SplitRGB:
return shortName ? "R|G|B" : "Split RGB";
case QBitmapPreviewDialogImp::eHistogramMode_RedChannel:
return shortName ? "Red" : "Red Channel";
case QBitmapPreviewDialogImp::eHistogramMode_GreenChannel:
return shortName ? "Green" : "Green Channel";
case QBitmapPreviewDialogImp::eHistogramMode_BlueChannel:
return shortName ? "Blue" : "Blue Channel";
case QBitmapPreviewDialogImp::eHistogramMode_AlphaChannel:
return shortName ? "Alpha" : "Alpha Channel";
default:
break;
}
return "";
}
void QBitmapPreviewDialogImp::refreshData()
{
// Check if we have some usefull data loaded
if (m_image->GetWidth() * m_image->GetHeight() == 0)
{
return;
}
int w = m_image->GetWidth();
int h = m_image->GetHeight();
int multiplier = (m_showMode == ESHOW_RGB_ALPHA ? 2 : 1);
int originalW = w * multiplier;
int originalH = h;
if (!m_showOriginalSize || (w == 0))
{
w = kDefaultWidth;
}
if (!m_showOriginalSize || (h == 0))
{
h = kDefaultHeight;
}
w *= multiplier;
CImageEx scaledImage;
if (m_showOriginalSize && (originalW < w))
{
w = originalW;
}
if (m_showOriginalSize && (originalH < h))
{
h = originalH;
}
scaledImage.Allocate(w, h);
if (m_showMode == ESHOW_RGB_ALPHA)
{
GetIEditor()->GetImageUtil()->ScaleToDoubleFit(*m_image, scaledImage);
}
else
{
GetIEditor()->GetImageUtil()->ScaleToFit(*m_image, scaledImage);
}
if (m_showMode == ESHOW_RGB || m_showMode == ESHOW_RGBE)
{
scaledImage.FillAlpha();
}
else if (m_showMode == ESHOW_ALPHA)
{
for (int h2 = 0; h2 < scaledImage.GetHeight(); h2++)
{
for (int w2 = 0; w2 < scaledImage.GetWidth(); w2++)
{
int a = scaledImage.ValueAt(w2, h2) >> 24;
scaledImage.ValueAt(w2, h2) = RGB(a, a, a) | (a << 24);
}
}
}
else if (m_showMode == ESHOW_RGB_ALPHA)
{
int halfWidth = scaledImage.GetWidth() / 2;
for (int h2 = 0; h2 < scaledImage.GetHeight(); h2++)
{
for (int w2 = 0; w2 < halfWidth; w2++)
{
int r = GetRValue(scaledImage.ValueAt(w2, h2));
int g = GetGValue(scaledImage.ValueAt(w2, h2));
int b = GetBValue(scaledImage.ValueAt(w2, h2));
int a = scaledImage.ValueAt(w2, h2) >> 24;
scaledImage.ValueAt(w2, h2) = RGB(r, g, b) | (a << 24);
scaledImage.ValueAt(w2 + halfWidth, h2) = RGB(a, a, a) | (a << 24);
}
}
}
setImageRgba8888(scaledImage.GetData(), w, h, "");
setSize(QString().asprintf("%d x %d", m_image->GetWidth(), m_image->GetHeight()));
setMips(QString().asprintf("%d", m_image->GetNumberOfMipMaps()));
setFullSize(m_showOriginalSize);
// Compute histogram
m_histogram.ComputeHistogram((BYTE*)scaledImage.GetData(), w, h, CImageHistogram::eImageFormat_32BPP_RGBA);
}
void QBitmapPreviewDialogImp::paintEvent(QPaintEvent* e)
{
QBitmapPreviewDialog::paintEvent(e);
//if showing original size hide other information so it's easier to see
if (m_showOriginalSize)
{
return;
}
if (m_uiStyle == EUISTYLE_IMAGE_ONLY)
{
return;
}
QPainter p(this);
QPen pen;
QPainterPath path[4];
// Fill background color
QRect histogramRect = getHistogramArea();
p.fillRect(histogramRect, QColor(255, 255, 255));
// Draw borders
pen.setColor(QColor(0, 0, 0));
p.setPen(pen);
p.drawRect(histogramRect);
// Draw histogram
QVector<int> drawChannels;
switch (m_histrogramMode)
{
case eHistogramMode_Luminosity:
drawChannels.push_back(3);
break;
case eHistogramMode_SplitRGB:
drawChannels.push_back(0);
drawChannels.push_back(1);
drawChannels.push_back(2);
break;
case eHistogramMode_OverlappedRGB:
drawChannels.push_back(0);
drawChannels.push_back(1);
drawChannels.push_back(2);
break;
case eHistogramMode_RedChannel:
drawChannels.push_back(0);
break;
case eHistogramMode_GreenChannel:
drawChannels.push_back(1);
break;
case eHistogramMode_BlueChannel:
drawChannels.push_back(2);
break;
case eHistogramMode_AlphaChannel:
drawChannels.push_back(3);
break;
}
int graphWidth = qMax(histogramRect.width(), 1);
int graphHeight = qMax(histogramRect.height() - 2, 0);
int graphBottom = histogramRect.bottom() + 1;
int currX[4] = {0, 0, 0, 0};
int prevX[4] = {0, 0, 0, 0};
float scale = 0.0f;
static const int numSubGraphs = 3;
const int subGraph = qCeil(graphWidth / numSubGraphs);
// Fill background for Split RGB histogram
if (m_histrogramMode == eHistogramMode_SplitRGB)
{
const static QColor backgroundColor[numSubGraphs] =
{
QColor(255, 220, 220),
QColor(220, 255, 220),
QColor(220, 220, 255)
};
for (int i = 0; i < numSubGraphs; i++)
{
p.fillRect(histogramRect.left() + subGraph * i,
histogramRect.top(),
subGraph + (i == numSubGraphs - 1 ? 1 : 0),
histogramRect.height(), backgroundColor[i]);
}
}
int lastHeight[CImageHistogram::kNumChannels] = { INT_MAX, INT_MAX, INT_MAX, INT_MAX };
for (int x = 0; x < graphWidth; ++x)
{
for (int j = 0; j < drawChannels.size(); j++)
{
const int c = drawChannels[j];
int& curr_x = currX[c];
int& prev_x = prevX[c];
int& last_height = lastHeight[c];
QPainterPath& curr_path = path[c];
curr_x = histogramRect.left() + x + 1;
int i = static_cast<int>(((float)x / (graphWidth - 1)) * (CImageHistogram::kNumColorLevels - 1));
if (m_histrogramMode == eHistogramMode_SplitRGB)
{
// Filter out to area which we are interested
const int k = x / subGraph;
if (k != c)
{
continue;
}
i = qCeil((i - (subGraph * c)) * numSubGraphs);
i = qMin(i, CImageHistogram::kNumColorLevels - 1);
i = qMax(i, 0);
}
if (m_histrogramMode == eHistogramMode_Luminosity)
{
scale = (float)m_histogram.m_lumCount[i] / m_histogram.m_maxLumCount;
}
else if (m_histogram.m_maxCount[c])
{
scale = (float)m_histogram.m_count[c][i] / m_histogram.m_maxCount[c];
}
int height = static_cast<int>(graphBottom - graphHeight * scale);
if (last_height == INT_MAX)
{
last_height = height;
}
curr_path.moveTo(prev_x, last_height);
curr_path.lineTo(curr_x, height);
last_height = height;
if (prev_x == INT_MAX)
{
prev_x = curr_x;
}
prev_x = curr_x;
}
}
static const QColor kChannelColor[4] =
{
QColor(255, 0, 0),
QColor(0, 255, 0),
QColor(0, 0, 255),
QColor(120, 120, 120)
};
for (int i = 0; i < drawChannels.size(); i++)
{
const int c = drawChannels[i];
pen.setColor(kChannelColor[c]);
p.setPen(pen);
p.drawPath(path[c]);
}
// Update histogram info
{
float mean = 0, stdDev = 0, median = 0;
switch (m_histrogramMode)
{
case eHistogramMode_Luminosity:
case eHistogramMode_SplitRGB:
case eHistogramMode_OverlappedRGB:
mean = m_histogram.m_meanAvg;
stdDev = m_histogram.m_stdDevAvg;
median = m_histogram.m_medianAvg;
break;
case eHistogramMode_RedChannel:
mean = m_histogram.m_mean[0];
stdDev = m_histogram.m_stdDev[0];
median = m_histogram.m_median[0];
break;
case eHistogramMode_GreenChannel:
mean = m_histogram.m_mean[1];
stdDev = m_histogram.m_stdDev[1];
median = m_histogram.m_median[1];
break;
case eHistogramMode_BlueChannel:
mean = m_histogram.m_mean[2];
stdDev = m_histogram.m_stdDev[2];
median = m_histogram.m_median[2];
break;
case eHistogramMode_AlphaChannel:
mean = m_histogram.m_mean[3];
stdDev = m_histogram.m_stdDev[3];
median = m_histogram.m_median[3];
break;
}
QString val;
val.setNum(mean);
setMean(val);
val.setNum(stdDev);
setStdDev(val);
val.setNum(median);
setMedian(val);
}
}
#include <Controls/moc_QBitmapPreviewDialogImp.cpp>
@@ -1,89 +0,0 @@
/*
* 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
*
*/
#ifndef QBITMAPPREVIEWDIALOG_IMP_H
#define QBITMAPPREVIEWDIALOG_IMP_H
#if !defined(Q_MOC_RUN)
#include "QBitmapPreviewDialog.h"
#include <Util/ImageHistogram.h>
#endif
class CImageEx;
class QBitmapPreviewDialogImp
: public QBitmapPreviewDialog
{
Q_OBJECT;
public:
enum EUIStyle
{
EUISTYLE_IMAGE_ONLY,
EUISTYLE_IMAGE_HISTOGRAM,
EUISTYLE_NumModes
};
enum EShowMode
{
ESHOW_RGB = 0,
ESHOW_ALPHA,
ESHOW_RGBA,
ESHOW_RGB_ALPHA,
ESHOW_RGBE,
ESHOW_NumModes,
};
enum EHistogramMode
{
eHistogramMode_Luminosity,
eHistogramMode_OverlappedRGB,
eHistogramMode_SplitRGB,
eHistogramMode_RedChannel,
eHistogramMode_GreenChannel,
eHistogramMode_BlueChannel,
eHistogramMode_AlphaChannel,
eHistogramMode_NumModes,
};
explicit QBitmapPreviewDialogImp(QWidget* parent = 0);
virtual ~QBitmapPreviewDialogImp();
void setImage(const QString path);
void setShowMode(EShowMode mode);
void toggleShowMode();
void setUIStyleMode(EUIStyle mode);
const EShowMode& getShowMode() const;
void setHistogramMode(EHistogramMode mode);
void toggleHistrogramMode();
const EHistogramMode& getHistogramMode() const;
void setOriginalSize(bool value);
void toggleOriginalSize();
bool isSizeSmallerThanDefault();
void paintEvent(QPaintEvent* e) override;
protected:
void refreshData();
private:
const char* GetShowModeDescription(EShowMode eShowMode, bool bShowInOriginalSize) const;
private:
CImageEx* m_image;
QString m_path;
CImageHistogram m_histogram;
bool m_showOriginalSize;
EShowMode m_showMode;
EHistogramMode m_histrogramMode;
EUIStyle m_uiStyle;
};
#endif // QBITMAPPREVIEWDIALOG_IMP_H
-642
View File
@@ -1,642 +0,0 @@
/*
* 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
*
*/
#include "EditorDefs.h"
#include <Controls/QToolTipWidget.h>
#include "QBitmapPreviewDialogImp.h"
#include "qcoreapplication.h"
#include "qguiapplication.h"
#include "qapplication.h"
#include <QDesktopWidget>
#include <QPainter>
#include <QtGlobal>
#include <qgraphicseffect.h>
void QToolTipWidget::RebuildLayout()
{
if (m_title != nullptr)
{
m_title->hide();
}
if (m_content != nullptr)
{
m_content->hide();
}
if (m_specialContent != nullptr)
{
m_specialContent->hide();
}
//empty layout
while (m_layout->count() > 0)
{
m_layout->takeAt(0);
}
qDeleteAll(m_currentShortcuts);
m_currentShortcuts.clear();
if (m_includeTextureShortcuts)
{
m_currentShortcuts.append(new QLabel(tr("Alt - Alpha"), this));
m_currentShortcuts.back()->setProperty("tooltipLabel", "Shortcut");
m_currentShortcuts.append(new QLabel(tr("Shift - RGBA"), this));
m_currentShortcuts.back()->setProperty("tooltipLabel", "Shortcut");
}
if (m_title != nullptr && !m_title->text().isEmpty())
{
m_layout->addWidget(m_title);
m_title->show();
}
for (QLabel* var : m_currentShortcuts)
{
if (var != nullptr)
{
m_layout->addWidget(var);
var->show();
}
}
if (m_specialContent != nullptr)
{
m_layout->addWidget(m_specialContent);
m_specialContent->show();
}
if (m_content != nullptr && !m_content->text().isEmpty())
{
m_layout->addWidget(m_content);
m_content->show();
}
m_background->adjustSize();
adjustSize();
}
void QToolTipWidget::Hide()
{
m_currentShortcuts.clear();
hide();
}
void QToolTipWidget::Show(QPoint pos, ArrowDirection dir)
{
if (!IsValid())
{
return;
}
m_arrow->m_direction = dir;
pos = AdjustTipPosByArrowSize(pos, dir);
m_normalPos = pos;
move(pos);
RebuildLayout();
show();
m_arrow->show();
}
void QToolTipWidget::Display(QRect targetRect, ArrowDirection preferredArrowDir)
{
if (!IsValid())
{
return;
}
KeepTipOnScreen(targetRect, preferredArrowDir);
RebuildLayout();
show();
m_arrow->show();
}
void QToolTipWidget::TryDisplay(QPoint mousePos, const QRect& rect, [[maybe_unused]] ArrowDirection preferredArrowDir)
{
if (rect.contains(mousePos))
{
Display(rect, QToolTipWidget::ArrowDirection::ARROW_RIGHT);
}
else
{
hide();
}
}
void QToolTipWidget::TryDisplay(QPoint mousePos, const QWidget* widget, ArrowDirection preferredArrowDir)
{
const QRect rect(widget->mapToGlobal(QPoint(0,0)), widget->size());
TryDisplay(mousePos, rect, preferredArrowDir);
}
void QToolTipWidget::SetTitle(QString title)
{
if (!title.isEmpty())
{
m_title->setText(title);
}
m_title->setProperty("tooltipLabel", "Title");
setWindowTitle("ToolTip - " + title);
}
void QToolTipWidget::SetContent(QString content)
{
m_content->setWordWrap(true);
m_content->setProperty("tooltipLabel", "Content");
//line-height is not supported via stylesheet so we use the html rich-text subset in QT for it.
m_content->setText(QString("<span style=\"line-height: 14px;\">%1</span>").arg(content));
}
void QToolTipWidget::AppendContent(QString content)
{
m_content->setText(m_content->text() + "\n\n" + content);
update();
RebuildLayout();
m_content->update();
m_content->repaint();
}
QToolTipWidget::QToolTipWidget(QWidget* parent)
: QWidget(parent)
{
m_background = new QWidget(this);
m_background->setProperty("tooltip", "Background");
m_background->stackUnder(this);
m_title = new QLabel(this);
m_currentShortcuts = QVector<QLabel*>();
m_content = new QLabel(this);
m_specialContent = nullptr;
setWindowTitle("ToolTip");
setObjectName("ToolTip");
m_layout = new QVBoxLayout(this);
m_normalPos = QPoint(0, 0);
m_arrow = new QArrow(m_background);
setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint);
m_arrow->setWindowFlags(Qt::ToolTip | Qt::FramelessWindowHint);
m_arrow->setAttribute(Qt::WA_TranslucentBackground, true);
m_background->setLayout(m_layout);
m_arrow->setObjectName("ToolTipArrow");
m_background->setObjectName("ToolTipBackground");
//we need a drop shadow for the background
QGraphicsDropShadowEffect* dropShadow = new QGraphicsDropShadowEffect(this);
dropShadow->setBlurRadius(m_shadowRadius);
dropShadow->setColor(Qt::black);
dropShadow->setOffset(0);
dropShadow->setEnabled(true);
m_background->setGraphicsEffect(dropShadow);
//we need a second drop shadow effect for the arrow
dropShadow = new QGraphicsDropShadowEffect(m_arrow);
dropShadow->setBlurRadius(m_shadowRadius);
dropShadow->setColor(Qt::black);
dropShadow->setOffset(0);
dropShadow->setEnabled(true);
m_arrow->setGraphicsEffect(dropShadow);
}
QToolTipWidget::~QToolTipWidget()
{
}
void QToolTipWidget::AddSpecialContent(QString type, QString dataStream)
{
if (type.isEmpty())
{
m_includeTextureShortcuts = false;
if (m_specialContent != nullptr)
{
delete m_specialContent;
m_specialContent = nullptr;
}
return;
}
if (type == "TEXTURE")
{
if (m_specialContent == nullptr)
{
QCoreApplication::instance()->installEventFilter(this); //grab the event filter while displaying the advanced texture tooltip
m_specialContent = new QBitmapPreviewDialogImp(this);
}
QString path(dataStream);
qobject_cast<QBitmapPreviewDialogImp*>(m_specialContent)->setImage(path);
// set default showmode to RGB
qobject_cast<QBitmapPreviewDialogImp*>(m_specialContent)->setShowMode(QBitmapPreviewDialogImp::EShowMode::ESHOW_RGB);
QString dir = (path.split("/").count() > path.split("\\").count()) ? path.split("/").back() : path.split("\\").back();
SetTitle(dir);
//always use default size but not image size
qobject_cast<QBitmapPreviewDialogImp*>(m_specialContent)->setOriginalSize(false);
m_includeTextureShortcuts = true;
}
else if (type == "ADD TO CONTENT")
{
AppendContent(dataStream);
m_includeTextureShortcuts = false;
if (m_specialContent != nullptr)
{
delete m_specialContent;
m_specialContent = nullptr;
}
}
else if (type == "REPLACE TITLE")
{
SetTitle(dataStream);
m_includeTextureShortcuts = false;
if (m_specialContent != nullptr)
{
delete m_specialContent;
m_specialContent = nullptr;
}
}
else if (type == "REPLACE CONTENT")
{
SetContent(dataStream);
m_includeTextureShortcuts = false;
if (m_specialContent != nullptr)
{
delete m_specialContent;
m_specialContent = nullptr;
}
}
else
{
m_includeTextureShortcuts = false;
if (m_specialContent != nullptr)
{
delete m_specialContent;
m_specialContent = nullptr;
}
return;
}
m_special = type;
}
bool QToolTipWidget::eventFilter(QObject* obj, QEvent* event)
{
if (event->type() == QEvent::KeyPress)
{
if (m_special == "TEXTURE" && m_specialContent != nullptr)
{
const QKeyEvent* ke = static_cast<QKeyEvent*>(event);
Qt::KeyboardModifiers mods = ke->modifiers();
if (mods & Qt::KeyboardModifier::AltModifier)
{
((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_ALPHA);
}
else if (mods & Qt::KeyboardModifier::ShiftModifier && !(mods & Qt::KeyboardModifier::ControlModifier))
{
((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_RGBA);
}
}
}
if (event->type() == QEvent::KeyRelease)
{
if (m_special == "TEXTURE" && m_specialContent != nullptr)
{
const QKeyEvent* ke = static_cast<QKeyEvent*>(event);
Qt::KeyboardModifiers mods = ke->modifiers();
if (!(mods& Qt::KeyboardModifier::AltModifier) && !(mods & Qt::KeyboardModifier::ShiftModifier))
{
((QBitmapPreviewDialogImp*)m_specialContent)->setShowMode(QBitmapPreviewDialogImp::ESHOW_RGB);
}
}
}
return QWidget::eventFilter(obj, event);
}
void QToolTipWidget::hideEvent(QHideEvent* event)
{
QWidget::hideEvent(event);
m_arrow->hide();
}
void QToolTipWidget::UpdateOptionalData(QString optionalData)
{
AddSpecialContent(m_special, optionalData);
}
QPoint QToolTipWidget::AdjustTipPosByArrowSize(QPoint pos, ArrowDirection dir)
{
switch (dir)
{
case QToolTipWidget::ArrowDirection::ARROW_UP:
{
m_arrow->move(pos);
pos.setY(pos.y() + 10);
m_arrow->setFixedSize(20, 10);
pos -= QPoint(m_shadowRadius, m_shadowRadius);
break;
}
case QToolTipWidget::ArrowDirection::ARROW_LEFT:
{
m_arrow->move(pos);
pos.setX(pos.x() + 10);
m_arrow->setFixedSize(10, 20);
pos -= QPoint(m_shadowRadius, m_shadowRadius);
break;
}
case QToolTipWidget::ArrowDirection::ARROW_RIGHT:
{
pos.setX(pos.x() - 10);
m_arrow->move(QPoint(pos.x() + width(), pos.y()));
m_arrow->setFixedSize(10, 20);
pos -= QPoint(-m_shadowRadius, m_shadowRadius);
break;
}
case QToolTipWidget::ArrowDirection::ARROW_DOWN:
{
pos.setY(pos.y() - 10);
m_arrow->move(QPoint(pos.x(), pos.y() + height()));
m_arrow->setFixedSize(20, 10);
pos -= QPoint(m_shadowRadius, -m_shadowRadius);
break;
}
default:
m_arrow->move(-10, -10);
break;
}
return pos;
}
bool QToolTipWidget::IsValid()
{
if (m_title->text().isEmpty() ||
(m_content->text().isEmpty() && m_specialContent == nullptr))
{
return false;
}
return true;
}
void QToolTipWidget::KeepTipOnScreen(QRect targetRect, ArrowDirection preferredArrowDir)
{
QRect desktop = QApplication::desktop()->availableGeometry(this);
if (this->isHidden())
{
setAttribute(Qt::WA_DontShowOnScreen, true);
Show(QPoint(0, 0), preferredArrowDir);
hide();
setAttribute(Qt::WA_DontShowOnScreen, false);
}
//else assume the size is right
//calculate initial rect
QRect tipRect = QRect(0, 0, 0, 0);
switch (preferredArrowDir)
{
case QToolTipWidget::ArrowDirection::ARROW_UP:
{
//tip is below the widget with a left alignment
tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.bottomLeft(), preferredArrowDir));
break;
}
case QToolTipWidget::ArrowDirection::ARROW_LEFT:
{
//tip is on the right with the top being even
tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), preferredArrowDir));
break;
}
case QToolTipWidget::ArrowDirection::ARROW_RIGHT:
{
//tip is on the left with the top being even
tipRect.setY(targetRect.top());
tipRect.setX(targetRect.left() - width());
tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), preferredArrowDir));
break;
}
case QToolTipWidget::ArrowDirection::ARROW_DOWN:
{
//tip is above the widget with a left alignment
tipRect.setX(targetRect.left());
tipRect.setY(targetRect.top() - height());
tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), preferredArrowDir));
break;
}
default:
{
//tip is on the right with the top being even
preferredArrowDir = QToolTipWidget::ArrowDirection::ARROW_LEFT;
tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), QToolTipWidget::ArrowDirection::ARROW_LEFT));
break;
}
}
tipRect.setSize(size());
//FixPositioning
if (preferredArrowDir == ArrowDirection::ARROW_LEFT || preferredArrowDir == ArrowDirection::ARROW_RIGHT)
{
if (tipRect.left() <= desktop.left())
{
m_arrow->m_direction = ArrowDirection::ARROW_LEFT;
tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.topRight(), m_arrow->m_direction));
}
else if (tipRect.right() >= desktop.right())
{
m_arrow->m_direction = ArrowDirection::ARROW_RIGHT;
tipRect.setLeft(targetRect.left() - width());
tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), m_arrow->m_direction));
}
}
else if (preferredArrowDir == ArrowDirection::ARROW_UP || preferredArrowDir == ArrowDirection::ARROW_DOWN)
{
if (tipRect.top() <= desktop.top())
{
m_arrow->m_direction = ArrowDirection::ARROW_UP;
tipRect.setTopLeft(AdjustTipPosByArrowSize(targetRect.bottomLeft(), m_arrow->m_direction));
}
else if (tipRect.bottom() >= desktop.bottom())
{
m_arrow->m_direction = ArrowDirection::ARROW_DOWN;
tipRect.setY(targetRect.top() - height());
tipRect.setTopLeft(AdjustTipPosByArrowSize(tipRect.topLeft(), m_arrow->m_direction));
}
}
//Nudge tip without arrow
if (preferredArrowDir == ArrowDirection::ARROW_UP || preferredArrowDir == ArrowDirection::ARROW_DOWN)
{
if (tipRect.left() <= desktop.left())
{
tipRect.setLeft(desktop.left());
}
else if (tipRect.right() >= desktop.right())
{
tipRect.setLeft(desktop.right() - width());
}
}
else if (preferredArrowDir == ArrowDirection::ARROW_RIGHT || preferredArrowDir == ArrowDirection::ARROW_LEFT)
{
if (tipRect.top() <= desktop.top())
{
tipRect.setTop(desktop.top());
}
else if (tipRect.bottom() >= desktop.bottom())
{
tipRect.setTop(desktop.bottom() - height());
}
}
m_normalPos = tipRect.topLeft();
move(m_normalPos);
}
QPolygonF QToolTipWidget::QArrow::CreateArrow()
{
QVector<QPointF> vertex;
//3 points in triangle
vertex.reserve(3);
//all magic number below are given in order to draw smooth transitions between tooltip and arrow
if (m_direction == ArrowDirection::ARROW_UP)
{
vertex.push_back(QPointF(10, 1));
vertex.push_back(QPointF(19, 10));
vertex.push_back(QPointF(0, 10));
}
else if (m_direction == ArrowDirection::ARROW_RIGHT)
{
vertex.push_back(QPointF(9, 10));
vertex.push_back(QPointF(0, 19));
vertex.push_back(QPointF(0, 1));
}
else if (m_direction == ArrowDirection::ARROW_LEFT)
{
vertex.push_back(QPointF(1, 10));
vertex.push_back(QPointF(10, 19));
vertex.push_back(QPointF(10, 0));
}
else //ArrowDirection::ARROW_DOWN
{
vertex.push_back(QPointF(10, 10));
vertex.push_back(QPointF(19, 0));
vertex.push_back(QPointF(0, 0));
}
return QPolygonF(vertex);
}
void QToolTipWidget::QArrow::paintEvent([[maybe_unused]] QPaintEvent* event)
{
QColor color(255, 255, 255, 255);
QPainter painter(this);
painter.fillRect(rect(), Qt::transparent); //force transparency
painter.setRenderHint(QPainter::Antialiasing, false);
painter.setBrush(color);
painter.setPen(Qt::NoPen);
painter.drawPolygon(CreateArrow());
//painter.setRenderHint(QPainter::Antialiasing, false);
}
QToolTipWrapper::QToolTipWrapper(QWidget* parent)
: QObject(parent)
{
}
void QToolTipWrapper::SetTitle(QString title)
{
m_title = title;
}
void QToolTipWrapper::SetContent(QString content)
{
AddSpecialContent("REPLACE CONTENT", content);
}
void QToolTipWrapper::AppendContent(QString content)
{
AddSpecialContent("ADD TO CONTENT", content);
}
void QToolTipWrapper::AddSpecialContent(QString type, QString dataStream)
{
if (type == "REPLACE CONTENT")
{
m_contentOperations.clear();
}
m_contentOperations.push_back({type, dataStream});
}
void QToolTipWrapper::UpdateOptionalData(QString optionalData)
{
m_contentOperations.push_back({"UPDATE OPTIONAL", optionalData});
}
void QToolTipWrapper::Display(QRect targetRect, QToolTipWidget::ArrowDirection preferredArrowDir)
{
GetOrCreateToolTip()->Display(targetRect, preferredArrowDir);
}
void QToolTipWrapper::TryDisplay(QPoint mousePos, const QWidget * widget, QToolTipWidget::ArrowDirection preferredArrowDir)
{
GetOrCreateToolTip()->TryDisplay(mousePos, widget, preferredArrowDir);
}
void QToolTipWrapper::TryDisplay(QPoint mousePos, const QRect & widget, QToolTipWidget::ArrowDirection preferredArrowDir)
{
GetOrCreateToolTip()->TryDisplay(mousePos, widget, preferredArrowDir);
}
void QToolTipWrapper::hide()
{
DestroyToolTip();
}
void QToolTipWrapper::show()
{
GetOrCreateToolTip()->show();
}
bool QToolTipWrapper::isVisible() const
{
return m_actualTooltip && m_actualTooltip->isVisible();
}
void QToolTipWrapper::update()
{
if (m_actualTooltip)
{
m_actualTooltip->update();
}
}
void QToolTipWrapper::ReplayContentOperations(QToolTipWidget* tooltipWidget)
{
tooltipWidget->SetTitle(m_title);
for (const auto& operation : m_contentOperations)
{
if (operation.first == "UPDATE OPTIONAL")
{
tooltipWidget->UpdateOptionalData(operation.second);
}
else
{
tooltipWidget->AddSpecialContent(operation.first, operation.second);
}
}
}
QToolTipWidget * QToolTipWrapper::GetOrCreateToolTip()
{
if (!m_actualTooltip)
{
QToolTipWidget* tooltipWidget = new QToolTipWidget(static_cast<QWidget*>(parent()));
tooltipWidget->setAttribute(Qt::WA_DeleteOnClose);
ReplayContentOperations(tooltipWidget);
m_actualTooltip = tooltipWidget;
}
return m_actualTooltip.data();
}
void QToolTipWrapper::DestroyToolTip()
{
if (m_actualTooltip)
{
m_actualTooltip->deleteLater();
}
}
-148
View File
@@ -1,148 +0,0 @@
/*
* 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
*
*/
#ifndef QToolTipWidget_h__
#define QToolTipWidget_h__
#include "EditorCoreAPI.h"
#include <QPointer>
#include <QWidget>
#include <QLabel>
#include <QString>
#include <QMap>
#include <QMapIterator>
#include <QVector>
#include <QVBoxLayout>
#include <memory>
class IQToolTip
{
public:
virtual void SetTitle(QString title) = 0;
virtual void SetContent(QString content) = 0;
virtual void AppendContent(QString content) = 0;
virtual void AddSpecialContent(QString type, QString dataStream) = 0;
virtual void UpdateOptionalData(QString optionalData) = 0;
};
class EDITOR_CORE_API QToolTipWidget
: public QWidget
, public IQToolTip
{
public:
enum class ArrowDirection
{
ARROW_UP,
ARROW_LEFT,
ARROW_RIGHT,
ARROW_DOWN
};
class QArrow
: public QWidget
{
public:
ArrowDirection m_direction;
QPoint m_pos;
QArrow(QWidget* parent)
: QWidget(parent){ setWindowFlags(Qt::ToolTip); }
virtual ~QArrow(){}
QPolygonF CreateArrow();
virtual void paintEvent(QPaintEvent*) override;
};
QToolTipWidget(QWidget* parent);
~QToolTipWidget();
void SetTitle(QString title) override;
void SetContent(QString content) override;
void AppendContent(QString content) override;
void AddSpecialContent(QString type, QString dataStream) override;
void UpdateOptionalData(QString optionalData) override;
void Display(QRect targetRect, ArrowDirection preferredArrowDir);
//! Displays the tooltip on the given widget, only if the mouse is over it.
void TryDisplay(QPoint mousePos, const QWidget* widget, ArrowDirection preferredArrowDir);
//! Displays the tooltip on the given rect, only if the mouse is over it.
void TryDisplay(QPoint mousePos, const QRect& widget, ArrowDirection preferredArrowDir);
void Hide();
protected:
void Show(QPoint pos, ArrowDirection dir);
bool IsValid();
void KeepTipOnScreen(QRect targetRect, ArrowDirection preferredArrowDir);
QPoint AdjustTipPosByArrowSize(QPoint pos, ArrowDirection dir);
virtual bool eventFilter(QObject* obj, QEvent* event) override;
void RebuildLayout();
virtual void hideEvent(QHideEvent*) override;
QLabel* m_title;
AZ_PUSH_DISABLE_DLL_EXPORT_MEMBER_WARNING
QVector<QLabel*> m_currentShortcuts;
AZ_POP_DISABLE_DLL_EXPORT_MEMBER_WARNING
//can be anything from QLabel to QBitMapPreviewDialog
//must allow movement, and show/hide calls
QLabel* m_content;
QWidget* m_specialContent;
QWidget* m_background;
QVBoxLayout* m_layout;
QString m_special;
QPoint m_normalPos;
QArrow* m_arrow;
const int m_shadowRadius = 5;
bool m_includeTextureShortcuts; //added since Qt does not support modifier only shortcuts
};
// HACK: The EditorUI_QT classes all were keeping persistent references to QToolTipWidgets around
// This led to many, many top-level widget creations, which led to many platform-side window allocations
// which led to crashes in Qt5.15. As this is legacy code, this is a drop-in replacement that only
// allocates the actual QToolTipWidget (and thus platform window) while the tooltip is visible
class EDITOR_CORE_API QToolTipWrapper
: public QObject
, public IQToolTip
{
public:
QToolTipWrapper(QWidget* parent);
void SetTitle(QString title) override;
void SetContent(QString content) override;
void AppendContent(QString content) override;
void AddSpecialContent(QString type, QString dataStream) override;
void UpdateOptionalData(QString optionalData) override;
void Display(QRect targetRect, QToolTipWidget::ArrowDirection preferredArrowDir);
void TryDisplay(QPoint mousePos, const QWidget* widget, QToolTipWidget::ArrowDirection preferredArrowDir);
void TryDisplay(QPoint mousePos, const QRect& widget, QToolTipWidget::ArrowDirection preferredArrowDir);
void hide();
void show();
bool isVisible() const;
void update();
void repaint(){update();} //Things really shouldn't be calling repaint on these...
void Hide(){hide();}
void close(){hide();}
private:
void ReplayContentOperations(QToolTipWidget* tooltipWidget);
QToolTipWidget* GetOrCreateToolTip();
void DestroyToolTip();
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // conditional expression is constant, needs to have dll-interface to be used by clients of class 'AzQtComponents::FilteredSearchWidget'
QPointer<QToolTipWidget> m_actualTooltip;
AZ_POP_DISABLE_WARNING
QString m_title;
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // conditional expression is constant, needs to have dll-interface to be used by clients of class 'AzQtComponents::FilteredSearchWidget'
QVector<QPair<QString, QString>> m_contentOperations;
AZ_POP_DISABLE_WARNING
};
#endif // QToolTipWidget_h__
@@ -10,7 +10,6 @@
// Editor
#include "PropertyCtrl.h"
#include "PropertyResourceCtrl.h"
#include "PropertyGenericCtrl.h"
#include "PropertyMiscCtrl.h"
#include "PropertyMotionCtrl.h"
@@ -21,7 +20,6 @@ void RegisterReflectedVarHandlers()
if (!registered)
{
registered = true;
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew FileResourceSelectorWidgetHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequencePropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew SequenceIdPropertyHandler());
EBUS_EVENT(AzToolsFramework::PropertyTypeRegistrationMessages::Bus, RegisterPropertyType, aznew LocalStringPropertyHandler());
@@ -1,383 +0,0 @@
/*
* 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
*
*/
#include "EditorDefs.h"
#include "PropertyResourceCtrl.h"
// Qt
#include <QHBoxLayout>
#include <QLineEdit>
// AzToolsFramework
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyAudioCtrl.h>
// Editor
#include "Controls/QToolTipWidget.h"
#include "Controls/BitmapToolTip.h"
BrowseButton::BrowseButton(PropertyType type, QWidget* parent /*= nullptr*/)
: QToolButton(parent)
, m_propertyType(type)
{
setAutoRaise(true);
setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/browse-edit.svg")));
connect(this, &QAbstractButton::clicked, this, &BrowseButton::OnClicked);
}
void BrowseButton::SetPathAndEmit(const QString& path)
{
//only emit if path changes. Old property control
if (path != m_path)
{
m_path = path;
emit PathChanged(m_path);
}
}
class FileBrowseButton
: public BrowseButton
{
public:
AZ_CLASS_ALLOCATOR(FileBrowseButton, AZ::SystemAllocator, 0);
FileBrowseButton(PropertyType type, QWidget* pParent = nullptr)
: BrowseButton(type, pParent)
{
setToolTip("Browse...");
}
private:
void OnClicked() override
{
QString tempValue("");
if (!m_path.isEmpty() && !Path::GetExt(m_path).isEmpty())
{
tempValue = m_path;
}
AssetSelectionModel selection;
if (m_propertyType == ePropertyTexture)
{
// Filters for texture.
selection = AssetSelectionModel::AssetGroupSelection("Texture");
}
else
{
return;
}
AzToolsFramework::EditorRequests::Bus::Broadcast(&AzToolsFramework::EditorRequests::BrowseForAssets, selection);
if (selection.IsValid())
{
QString newPath = Path::FullPathToGamePath(selection.GetResult()->GetFullPath().c_str()).c_str();
switch (m_propertyType)
{
case ePropertyTexture:
newPath.replace("\\\\", "/");
if (newPath.size() > MAX_PATH)
{
newPath.resize(MAX_PATH);
}
}
SetPathAndEmit(newPath);
}
}
};
class AudioControlSelectorButton
: public BrowseButton
{
public:
AZ_CLASS_ALLOCATOR(AudioControlSelectorButton, AZ::SystemAllocator, 0);
AudioControlSelectorButton(PropertyType type, QWidget* pParent = nullptr)
: BrowseButton(type, pParent)
{
setToolTip(tr("Select Audio Control"));
}
private:
void OnClicked() override
{
AZStd::string resourceResult;
auto ConvertLegacyAudioPropertyType = [](const PropertyType type) -> AzToolsFramework::AudioPropertyType
{
switch (type)
{
case ePropertyAudioTrigger:
return AzToolsFramework::AudioPropertyType::Trigger;
case ePropertyAudioRTPC:
return AzToolsFramework::AudioPropertyType::Rtpc;
case ePropertyAudioSwitch:
return AzToolsFramework::AudioPropertyType::Switch;
case ePropertyAudioSwitchState:
return AzToolsFramework::AudioPropertyType::SwitchState;
case ePropertyAudioEnvironment:
return AzToolsFramework::AudioPropertyType::Environment;
case ePropertyAudioPreloadRequest:
return AzToolsFramework::AudioPropertyType::Preload;
default:
return AzToolsFramework::AudioPropertyType::NumTypes;
}
};
auto propType = ConvertLegacyAudioPropertyType(m_propertyType);
if (propType != AzToolsFramework::AudioPropertyType::NumTypes)
{
AzToolsFramework::AudioControlSelectorRequestBus::EventResult(
resourceResult, propType, &AzToolsFramework::AudioControlSelectorRequestBus::Events::SelectResource,
AZStd::string_view{ m_path.toUtf8().constData() });
SetPathAndEmit(QString{ resourceResult.c_str() });
}
}
};
class TextureEditButton
: public BrowseButton
{
public:
AZ_CLASS_ALLOCATOR(TextureEditButton, AZ::SystemAllocator, 0);
TextureEditButton(QWidget* pParent = nullptr)
: BrowseButton(ePropertyTexture, pParent)
{
setIcon(QIcon(QStringLiteral(":/stylesheet/img/UI20/open-in-internal-app.svg")));
setToolTip(tr("Launch default editor"));
}
private:
void OnClicked() override
{
CFileUtil::EditTextureFile(m_path.toUtf8().data(), true);
}
};
FileResourceSelectorWidget::FileResourceSelectorWidget(QWidget* pParent /*= nullptr*/)
: QWidget(pParent)
, m_propertyType(ePropertyInvalid)
, m_tooltip(nullptr)
{
m_pathEdit = new QLineEdit;
m_mainLayout = new QHBoxLayout(this);
m_mainLayout->addWidget(m_pathEdit, 1);
m_mainLayout->setContentsMargins(0, 0, 0, 0);
// KDAB just ported the MFC texture preview tooltip, but looks like Amazon added their own. Not sure which to use.
// To switch to Amazon QToolTipWidget, remove FileResourceSelectorWidget::event and m_previewTooltip
#ifdef USE_QTOOLTIPWIDGET
m_tooltip = new QToolTipWidget(this);
installEventFilter(this);
#endif
connect(m_pathEdit, &QLineEdit::editingFinished, this, [this]() { OnPathChanged(m_pathEdit->text()); });
}
bool FileResourceSelectorWidget::eventFilter([[maybe_unused]] QObject* obj, QEvent* event)
{
if (m_propertyType == ePropertyTexture)
{
if (event->type() == QEvent::ToolTip)
{
QHelpEvent* e = (QHelpEvent*)event;
m_tooltip->AddSpecialContent("TEXTURE", m_path);
m_tooltip->TryDisplay(e->globalPos(), m_pathEdit, QToolTipWidget::ArrowDirection::ARROW_RIGHT);
return true;
}
if (event->type() == QEvent::Leave)
{
m_tooltip->hide();
}
}
return false;
}
void FileResourceSelectorWidget::SetPropertyType(PropertyType type)
{
if (m_propertyType == type)
{
return;
}
//if the property type changed for some reason, delete all the existing widgets
if (!m_buttons.isEmpty())
{
qDeleteAll(m_buttons.begin(), m_buttons.end());
m_buttons.clear();
}
m_previewToolTip.reset();
m_propertyType = type;
switch (type)
{
case ePropertyTexture:
AddButton(new FileBrowseButton(type));
AddButton(new TextureEditButton);
m_previewToolTip.reset(new CBitmapToolTip);
break;
case ePropertyAudioTrigger:
case ePropertyAudioSwitch:
case ePropertyAudioSwitchState:
case ePropertyAudioRTPC:
case ePropertyAudioEnvironment:
case ePropertyAudioPreloadRequest:
AddButton(new AudioControlSelectorButton(type));
break;
default:
break;
}
m_mainLayout->invalidate();
}
void FileResourceSelectorWidget::AddButton(BrowseButton* button)
{
m_mainLayout->addWidget(button);
m_buttons.push_back(button);
connect(button, &BrowseButton::PathChanged, this, &FileResourceSelectorWidget::OnPathChanged);
}
void FileResourceSelectorWidget::OnPathChanged(const QString& path)
{
bool changed = SetPath(path);
if (changed)
{
emit PathChanged(m_path);
}
}
bool FileResourceSelectorWidget::SetPath(const QString& path)
{
bool changed = false;
const QString newPath = path.toLower();
if (m_path != newPath)
{
m_path = newPath;
UpdateWidgets();
changed = true;
}
return changed;
}
void FileResourceSelectorWidget::UpdateWidgets()
{
m_pathEdit->setText(m_path);
foreach(BrowseButton * button, m_buttons)
{
button->SetPath(m_path);
}
if (m_previewToolTip)
{
m_previewToolTip->SetTool(this, rect());
}
}
QString FileResourceSelectorWidget::GetPath() const
{
return m_path;
}
QWidget* FileResourceSelectorWidget::GetLastInTabOrder()
{
return m_buttons.empty() ? nullptr : m_buttons.last();
}
QWidget* FileResourceSelectorWidget::GetFirstInTabOrder()
{
return m_buttons.empty() ? nullptr : m_buttons.first();
}
void FileResourceSelectorWidget::UpdateTabOrder()
{
if (m_buttons.count() >= 2)
{
for (int i = 0; i < m_buttons.count() - 1; ++i)
{
setTabOrder(m_buttons[i], m_buttons[i + 1]);
}
}
}
bool FileResourceSelectorWidget::event(QEvent* event)
{
if (event->type() == QEvent::ToolTip && m_previewToolTip && !m_previewToolTip->isVisible())
{
if (!m_path.isEmpty())
{
m_previewToolTip->LoadImage(m_path);
m_previewToolTip->setVisible(true);
}
event->accept();
return true;
}
if (event->type() == QEvent::Resize && m_previewToolTip)
{
m_previewToolTip->SetTool(this, rect());
}
return QWidget::event(event);
}
QWidget* FileResourceSelectorWidgetHandler::CreateGUI(QWidget* pParent)
{
FileResourceSelectorWidget* newCtrl = aznew FileResourceSelectorWidget(pParent);
connect(newCtrl, &FileResourceSelectorWidget::PathChanged, newCtrl, [newCtrl]()
{
EBUS_EVENT(AzToolsFramework::PropertyEditorGUIMessages::Bus, RequestWrite, newCtrl);
});
return newCtrl;
}
void FileResourceSelectorWidgetHandler::ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName)
{
Q_UNUSED(GUI);
Q_UNUSED(attrib);
Q_UNUSED(attrValue);
Q_UNUSED(debugName);
}
void FileResourceSelectorWidgetHandler::WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node)
{
Q_UNUSED(index);
Q_UNUSED(node);
CReflectedVarResource val = instance;
val.m_propertyType = GUI->GetPropertyType();
val.m_path = GUI->GetPath().toUtf8().data();
instance = static_cast<property_t>(val);
}
bool FileResourceSelectorWidgetHandler::ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node)
{
Q_UNUSED(index);
Q_UNUSED(node);
CReflectedVarResource val = instance;
GUI->SetPropertyType(val.m_propertyType);
GUI->SetPath(val.m_path.c_str());
return false;
}
#include <Controls/ReflectedPropertyControl/moc_PropertyResourceCtrl.cpp>
@@ -1,118 +0,0 @@
/*
* 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
*
*/
#ifndef CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
#define CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
#pragma once
#if !defined(Q_MOC_RUN)
#include <AzCore/base.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyEditorAPI.h>
#include "ReflectedVar.h"
#include "Util/VariablePropertyType.h"
#include <QWidget>
#include <QtWidgets/QToolButton>
#include <QtCore/QVector>
#endif
class QLineEdit;
class QHBoxLayout;
class CBitmapToolTip;
class QToolTipWidget;
class BrowseButton
: public QToolButton
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(BrowseButton, AZ::SystemAllocator, 0);
BrowseButton(PropertyType type, QWidget* parent = nullptr);
void SetPath(const QString& path) { m_path = path; }
QString GetPath() const { return m_path; }
PropertyType GetPropertyType() const {return m_propertyType; }
signals:
void PathChanged(const QString& path);
protected:
void SetPathAndEmit(const QString& path);
virtual void OnClicked() = 0;
PropertyType m_propertyType;
QString m_path;
};
class FileResourceSelectorWidget
: public QWidget
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(FileResourceSelectorWidget, AZ::SystemAllocator, 0);
FileResourceSelectorWidget(QWidget* pParent = nullptr);
bool SetPath(const QString& path);
QString GetPath() const;
void SetPropertyType(PropertyType type);
PropertyType GetPropertyType() const { return m_propertyType; }
QWidget* GetFirstInTabOrder();
QWidget* GetLastInTabOrder();
void UpdateTabOrder();
bool eventFilter(QObject* obj, QEvent* event) override;
signals:
void PathChanged(const QString& path);
protected:
bool event(QEvent* event) override;
private:
void OnAssignClicked();
void OnMaterialClicked();
void UpdateWidgets();
void AddButton(BrowseButton* button);
void OnPathChanged(const QString& path);
private:
QLineEdit* m_pathEdit;
PropertyType m_propertyType;
QString m_path;
QHBoxLayout* m_mainLayout;
QVector<BrowseButton*> m_buttons;
QScopedPointer<CBitmapToolTip> m_previewToolTip;
QToolTipWidget* m_tooltip;
};
class FileResourceSelectorWidgetHandler
: QObject
, public AzToolsFramework::PropertyHandler < CReflectedVarResource, FileResourceSelectorWidget >
{
Q_OBJECT
public:
AZ_CLASS_ALLOCATOR(FileResourceSelectorWidgetHandler, AZ::SystemAllocator, 0);
virtual AZ::u32 GetHandlerName(void) const override { return AZ_CRC("Resource", 0xbc91f416); }
virtual bool IsDefaultHandler() const override { return true; }
virtual QWidget* GetFirstInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetFirstInTabOrder(); }
virtual QWidget* GetLastInTabOrder(FileResourceSelectorWidget* widget) override { return widget->GetLastInTabOrder(); }
virtual void UpdateWidgetInternalTabbing(FileResourceSelectorWidget* widget) override { widget->UpdateTabOrder(); }
virtual QWidget* CreateGUI(QWidget* pParent) override;
virtual void ConsumeAttribute(FileResourceSelectorWidget* GUI, AZ::u32 attrib, AzToolsFramework::PropertyAttributeReader* attrValue, const char* debugName) override;
virtual void WriteGUIValuesIntoProperty(size_t index, FileResourceSelectorWidget* GUI, property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
virtual bool ReadValuesIntoGUI(size_t index, FileResourceSelectorWidget* GUI, const property_t& instance, AzToolsFramework::InstanceDataNode* node) override;
};
#endif // CRYINCLUDE_EDITOR_UTILS_PROPERTYRESOURCECTRL_H
@@ -70,12 +70,6 @@ void ReflectedVarInit::setupReflection(AZ::SerializeContext* serializeContext)
AZ::EditContext* ec = serializeContext->GetEditContext();
if (ec)
{
ec->Class< CReflectedVarResource >("VarResource", "Resource")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarResource::varName)
->Attribute(AZ::Edit::Attributes::DescriptionTextOverride, &CReflectedVarResource::description)
;
ec->Class< CReflectedVarUser >("VarUser", "")
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
->Attribute(AZ::Edit::Attributes::NameLabelOverride, &CReflectedVarUser::varName)
-1
View File
@@ -13,7 +13,6 @@
#include <QMap>
#include <QTranslator>
#include <QSet>
#include "IEventLoopHook.h"
#include <unordered_map>
#include <AzCore/PlatformDef.h>
-28
View File
@@ -1828,34 +1828,6 @@ bool CCryEditApp::InitInstance()
return true;
}
void CCryEditApp::RegisterEventLoopHook(IEventLoopHook* pHook)
{
pHook->pNextHook = m_pEventLoopHook;
m_pEventLoopHook = pHook;
}
void CCryEditApp::UnregisterEventLoopHook(IEventLoopHook* pHookToRemove)
{
IEventLoopHook* pPrevious = nullptr;
for (IEventLoopHook* pHook = m_pEventLoopHook; pHook != nullptr; pHook = pHook->pNextHook)
{
if (pHook == pHookToRemove)
{
if (pPrevious)
{
pPrevious->pNextHook = pHookToRemove->pNextHook;
}
else
{
m_pEventLoopHook = pHookToRemove->pNextHook;
}
pHookToRemove->pNextHook = nullptr;
return;
}
}
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::LoadFile(QString fileName)
{
-4
View File
@@ -30,7 +30,6 @@ class CConsoleDialog;
struct mg_connection;
struct mg_request_info;
struct mg_context;
struct IEventLoopHook;
class QAction;
class MainWindow;
class QSharedMemory;
@@ -153,8 +152,6 @@ public:
int IdleProcessing(bool bBackground);
bool IsWindowInForeground();
void RunInitPythonScript(CEditCommandLineInfo& cmdInfo);
void RegisterEventLoopHook(IEventLoopHook* pHook);
void UnregisterEventLoopHook(IEventLoopHook* pHook);
void DisableIdleProcessing() override;
void EnableIdleProcessing() override;
@@ -344,7 +341,6 @@ private:
QString m_lastOpenLevelPath;
CQuickAccessBar* m_pQuickAccessBar = nullptr;
IEventLoopHook* m_pEventLoopHook = nullptr;
QString m_rootEnginePath;
int m_disableIdleProcessingCounter = 0; //!< Counts requests to disable idle processing. When non-zero, idle processing will be disabled.
+1 -1
View File
@@ -101,7 +101,7 @@ void CEditorPreferencesPage_AWS::SaveSettingsRegistryFile()
return;
}
[[maybe_unused]] bool saved{};
[[maybe_unused]] bool saved = false;
constexpr auto configurationMode =
AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
if (AZ::IO::SystemFile outputFile; outputFile.Open(resolvedPath.data(), configurationMode))
+1
View File
@@ -586,6 +586,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
break;
case eNotify_OnEndLoad:
case eNotify_OnEndCreate:
UpdateScene();
SetDefaultCamera();
break;
+2 -2
View File
@@ -317,8 +317,8 @@ void CGameExporter::ExportLevelInfo(const QString& path)
root->setAttr("Name", levelName.toUtf8().data());
auto terrain = AzFramework::Terrain::TerrainDataRequestBus::FindFirstHandler();
const AZ::Aabb terrainAabb = terrain ? terrain->GetTerrainAabb() : AZ::Aabb::CreateFromPoint(AZ::Vector3::CreateZero());
const AZ::Vector2 terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : AZ::Vector2::CreateOne();
const int compiledHeightmapSize = static_cast<int>(terrainAabb.GetXExtent() / terrainGridResolution.GetX());
const float terrainGridResolution = terrain ? terrain->GetTerrainHeightQueryResolution() : 1.0f;
const int compiledHeightmapSize = static_cast<int>(terrainAabb.GetXExtent() / terrainGridResolution);
root->setAttr("HeightmapSize", compiledHeightmapSize);
//////////////////////////////////////////////////////////////////////////
-6
View File
@@ -66,7 +66,6 @@ class IAWSResourceManager;
struct ISystem;
struct IRenderer;
struct AABB;
struct IEventLoopHook;
struct IErrorReport; // Vladimir@conffx
struct IFileUtil; // Vladimir@conffx
struct IEditorLog; // Vladimir@conffx
@@ -509,11 +508,6 @@ struct IEditor
virtual void SetActiveView(CViewport* viewport) = 0;
virtual struct IEditorFileMonitor* GetFileMonitor() = 0;
// These are needed for Qt integration:
virtual void RegisterEventLoopHook(IEventLoopHook* pHook) = 0;
virtual void UnregisterEventLoopHook(IEventLoopHook* pHook) = 0;
// ^^^
//! QMimeData is used by the Qt clipboard.
//! IMPORTANT: Any QMimeData allocated for the clipboard will be deleted
//! when the editor exists. If a QMimeData is allocated by a different
-10
View File
@@ -789,16 +789,6 @@ IEditorFileMonitor* CEditorImpl::GetFileMonitor()
return m_pEditorFileMonitor.get();
}
void CEditorImpl::RegisterEventLoopHook(IEventLoopHook* pHook)
{
CCryEditApp::instance()->RegisterEventLoopHook(pHook);
}
void CEditorImpl::UnregisterEventLoopHook(IEventLoopHook* pHook)
{
CCryEditApp::instance()->UnregisterEventLoopHook(pHook);
}
float CEditorImpl::GetTerrainElevation(float x, float y)
{
float terrainElevation = AzFramework::Terrain::TerrainDataRequests::GetDefaultTerrainHeight();
-2
View File
@@ -155,8 +155,6 @@ public:
CMusicManager* GetMusicManager() override { return m_pMusicManager; };
IEditorFileMonitor* GetFileMonitor() override;
void RegisterEventLoopHook(IEventLoopHook* pHook) override;
void UnregisterEventLoopHook(IEventLoopHook* pHook) override;
IIconManager* GetIconManager() override;
float GetTerrainElevation(float x, float y) override;
Editor::EditorQtApplication* GetEditorQtApplication() override { return m_QtApplication; }
@@ -135,9 +135,6 @@ struct IClassDesc
//////////////////////////////////////////////////////////////////////////
};
struct IViewPaneClass;
struct CRYEDIT_API IEditorClassFactory
{
public:
@@ -149,7 +146,6 @@ public:
virtual IClassDesc* FindClass(const char* pClassName) const = 0;
//! Find class in the factory by class id
virtual IClassDesc* FindClass(const GUID& rClassID) const = 0;
virtual IViewPaneClass* FindViewPaneClassByTitle(const char* pPaneTitle) const = 0;
virtual void UnregisterClass(const char* pClassName) = 0;
virtual void UnregisterClass(const GUID& rClassID) = 0;
//! Get classes that matching specific requirements.
-24
View File
@@ -1,24 +0,0 @@
/*
* 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
*
*/
#ifndef CRYINCLUDE_EDITOR_INCLUDE_IEVENTLOOPHOOK_H
#define CRYINCLUDE_EDITOR_INCLUDE_IEVENTLOOPHOOK_H
#pragma once
struct IEventLoopHook
{
IEventLoopHook* pNextHook;
IEventLoopHook()
: pNextHook(0) {}
virtual bool PrePumpMessage() { return false; }
};
#endif // CRYINCLUDE_EDITOR_INCLUDE_IEVENTLOOPHOOK_H
-74
View File
@@ -1,74 +0,0 @@
/*
* 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
*
*/
#ifndef CRYINCLUDE_EDITOR_INCLUDE_IVIEWPANE_H
#define CRYINCLUDE_EDITOR_INCLUDE_IVIEWPANE_H
#pragma once
#include "IEditorClassFactory.h"
#include <QSize>
class QWidget;
class QRect;
struct IViewPaneClass
: public IClassDesc
{
DEFINE_UUID(0x7E13EC7C, 0xF621, 0x4aeb, 0xB6, 0x42, 0x67, 0xD7, 0x8E, 0xD4, 0x68, 0xF8)
enum EDockingDirection
{
DOCK_TOP,
DOCK_LEFT,
DOCK_RIGHT,
DOCK_BOTTOM,
DOCK_FLOAT,
};
virtual ~IViewPaneClass() = default;
// Return text for view pane title.
virtual QString GetPaneTitle() = 0;
// Return the string resource ID for the title's text.
virtual unsigned int GetPaneTitleID() const = 0;
// Return preferable initial docking position for pane.
virtual EDockingDirection GetDockingDirection() = 0;
// Initial pane size.
virtual QRect GetPaneRect() = 0;
// Get Minimal view size
virtual QSize GetMinSize() { return QSize(0, 0); }
// Return true if only one pane at a time of time view class can be created.
virtual bool SinglePane() = 0;
// Return true if the view window wants to get ID_IDLE_UPDATE commands.
virtual bool WantIdleUpdate() = 0;
//////////////////////////////////////////////////////////////////////////
// IUnknown
//////////////////////////////////////////////////////////////////////////
HRESULT STDMETHODCALLTYPE QueryInterface(const IID& riid, void** ppvObj)
{
if (riid == __az_uuidof(IViewPaneClass))
{
*ppvObj = this;
return S_OK;
}
return E_NOINTERFACE;
}
//////////////////////////////////////////////////////////////////////////
};
#endif // CRYINCLUDE_EDITOR_INCLUDE_IVIEWPANE_H
-2
View File
@@ -97,8 +97,6 @@ public:
MOCK_METHOD0(GetActiveView, class CViewport* ());
MOCK_METHOD1(SetActiveView, void(CViewport*));
MOCK_METHOD0(GetFileMonitor, struct IEditorFileMonitor* ());
MOCK_METHOD1(RegisterEventLoopHook, void(IEventLoopHook* ));
MOCK_METHOD1(UnregisterEventLoopHook, void(IEventLoopHook* ));
MOCK_CONST_METHOD0(CreateQMimeData, QMimeData* ());
MOCK_CONST_METHOD1(DestroyQMimeData, void(QMimeData*));
MOCK_METHOD0(GetLevelIndependentFileMan, class CLevelIndependentFileMan* ());
-2
View File
@@ -499,14 +499,12 @@ void CEntityObject::AdjustLightProperties(CVarBlockPtr& properties, const char*
pAreaLight->SetHumanName("PlanarLight");
}
bool bCastShadowLegacy = false; // Backward compatibility for existing shadow casting lights
if (IVariable* pCastShadowVarLegacy = FindVariableInSubBlock(properties, pSubBlockVar, "bCastShadow"))
{
pCastShadowVarLegacy->SetFlags(pCastShadowVarLegacy->GetFlags() | IVariable::UI_INVISIBLE);
const QString zeroPrefix("0");
if (!pCastShadowVarLegacy->GetDisplayValue().startsWith(zeroPrefix))
{
bCastShadowLegacy = true;
pCastShadowVarLegacy->SetDisplayValue(zeroPrefix);
}
}
-20
View File
@@ -11,9 +11,6 @@
#include "Plugin.h"
// Editor
#include "Include/IViewPane.h"
#include <QMessageBox>
CClassFactory* CClassFactory::s_pInstance = nullptr;
@@ -149,23 +146,6 @@ IClassDesc* CClassFactory::FindClass(const GUID& rClassID) const
return pClassDesc;
}
IViewPaneClass* CClassFactory::FindViewPaneClassByTitle(const char* pPaneTitle) const
{
for (size_t i = 0; i < m_classes.size(); i++)
{
IViewPaneClass* viewPane = nullptr;
IClassDesc* desc = m_classes[i];
if (SUCCEEDED(desc->QueryInterface(__az_uuidof(IViewPaneClass), (void**)&viewPane)))
{
if (QString::compare(viewPane->GetPaneTitle(), pPaneTitle) == 0)
{
return viewPane;
}
}
}
return nullptr;
}
void CClassFactory::UnregisterClass(const char* pClassName)
{
IClassDesc* pClassDesc = FindClass(pClassName);
-8
View File
@@ -32,8 +32,6 @@ public:
IClassDesc* FindClass(const char* className) const;
//! Find class in the factory by class ID
IClassDesc* FindClass(const GUID& rClassID) const;
//! Find View Pane Class in the factory by pane title
IViewPaneClass* FindViewPaneClassByTitle(const char* pPaneTitle) const;
void UnregisterClass(const char* pClassName);
void UnregisterClass(const GUID& rClassID);
//! Get classes matching specific requirements ordered alphabetically by name.
@@ -96,10 +94,4 @@ public:
#define REGISTER_CLASS_DESC(ClassDesc) \
CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new ClassDesc);
#define REGISTER_QT_CLASS_DESC(ClassDesc, name, category) \
CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new CQtViewClass<ClassDesc>(name, category));
#define REGISTER_QT_CLASS_DESC_SYSTEM_ID(ClassDesc, name, category, systemid) \
CAutoRegisterClassHelper g_AutoRegHelper##ClassDesc(new CQtViewClass<ClassDesc>(name, category, systemid));
#endif // CRYINCLUDE_EDITOR_PLUGIN_H
@@ -209,12 +209,10 @@ namespace ProjectSettingsTool
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::PackageName))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::AndroidPackageName)
->Attribute(Attributes::LinkedProperty, Identfiers::IosBundleIdentifer)
->DataElement(Handlers::LinkedLineEdit, &AndroidSettings::m_versionName, "Version Name", "Human readable version number. Used to set the \"android: versionName\" tag in the AndroidManifest.xml and ultimately what will be displayed in the App Store.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::AndroidVersionName)
->Attribute(Attributes::LinkedProperty, Identfiers::IosVersionName)
->DataElement(AZ::Edit::UIHandlers::Default, &AndroidSettings::m_versionNumber, "Version Number", "Internal application version number. Used to set the \"android:versionCode\" tag in the AndroidManifest.xml.")
->Attribute(AZ::Edit::Attributes::Min, 1)
->Attribute(AZ::Edit::Attributes::Max, Validators::maxAndroidVersion)
@@ -37,19 +37,15 @@ namespace ProjectSettingsTool
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_projectName, "Project Name", "The name of the project.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProjectName)
->Attribute(Attributes::LinkedProperty, Identfiers::IosBundleName)
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_productName, "Product Name", "The project's user facing name.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IsNotEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProductName)
->Attribute(Attributes::LinkedProperty, Identfiers::IosDisplayName)
->DataElement(Handlers::LinkedLineEdit, &BaseSettings::m_executableName, "Executable Name", "The project launcher's name.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ExecutableName)
->Attribute(Attributes::LinkedProperty, Identfiers::IosExecutableName)
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_projectPath, "Project Path", "The project root folder path .")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileNameOrEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::ProductName)
->Attribute(Attributes::LinkedProperty, Identfiers::ExecutableName)
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_projectOutputFolder, "Output Folder", "The folder the packed project will be exported to.")
->DataElement(Handlers::QValidatedLineEdit, &BaseSettings::m_codeFolder, "Code Folder (legacy)", "A legacy setting specifing the folder for this project's code.")
;
@@ -262,27 +262,22 @@ namespace ProjectSettingsTool
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
->Attribute(AZ::Edit::Attributes::Visibility, AZ::Edit::PropertyVisibility::ShowChildrenOnly)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleName, "Bundle Name", "The name of the bundle.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSFileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosBundleName)
->Attribute(Attributes::LinkedProperty, Identfiers::ProjectName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleDisplayName, "Display Name", "The user visible name of the bundle.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IsNotEmpty))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosDisplayName)
->Attribute(Attributes::LinkedProperty, Identfiers::ProductName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_executableName, "Executable Name", "Name of the bundle's executable file.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::FileName))
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSFileName))
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosExecutableName)
->Attribute(Attributes::LinkedProperty, Identfiers::ExecutableName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_bundleIdentifier, "Bundle Identifier", "Uniquely identifies the bundle. Should be in reverse-DNS format.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::PackageName))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosBundleIdentifer)
->Attribute(Attributes::LinkedProperty, Identfiers::AndroidPackageName)
->DataElement(Handlers::LinkedLineEdit, &IosSettings::m_versionName, "Version Name", "The release version number string for the app. Displayed in the app store.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->Attribute(Attributes::LinkOptional, true)
->Attribute(Attributes::PropertyIdentfier, Identfiers::IosVersionName)
->Attribute(Attributes::LinkedProperty, Identfiers::AndroidVersionName)
->DataElement(Handlers::QValidatedLineEdit, &IosSettings::m_versionNumber, "Version Number", "The build version number string for the bundle.")
->Attribute(Attributes::FuncValidator, ConvertFunctorToVoid(&Validators::IOSVersionNumber))
->DataElement(AZ::Edit::UIHandlers::ComboBox, &IosSettings::m_developmentRegion, "Development Region", "The default language and region for the app.")
@@ -22,7 +22,6 @@ namespace ProjectSettingsTool
static const AZ::Crc32 Obfuscated = AZ_CRC("ObfuscatedText");
// Used as a tooltip and for distinguising linked properties
static const AZ::Crc32 PropertyIdentfier = AZ_CRC("PropertyIdentfier");
static const AZ::Crc32 LinkedProperty = AZ_CRC("LinkedProperty");
static const AZ::Crc32 DefaultPath = AZ_CRC("DefaultPath");
static const AZ::Crc32 DefaultImagePreview = AZ_CRC("DefaultImagePreview");
static const AZ::Crc32 ObfuscatedText = AZ_CRC("ObfuscatedText");
@@ -225,25 +225,6 @@ namespace ProjectSettingsTool
}
}
}
else if (attrib == Attributes::LinkedProperty)
{
AZStd::string linked;
if (attrValue->Read<AZStd::string>(linked))
{
auto result = m_ctrlToIdentAndLink.find(GUI);
if (result != m_ctrlToIdentAndLink.end())
{
result->second.linkedIdentifier = linked;
}
else
{
m_ctrlToIdentAndLink.insert(AZStd::pair<PropertyLinkedCtrl*, IdentAndLink>(GUI, IdentAndLink{ "", linked }));
m_ctrlInitOrder.push_back(GUI);
}
GUI->SetLinkTooltip(linked.data());
}
}
else
{
GUI->ConsumeAttribute(attrib, attrValue, debugName);
@@ -106,6 +106,11 @@ namespace ProjectSettingsTool
return RegularExpressionValidator("[\\w,-]+", name);
}
// Returns true if valid iOS file or directory name
RetType IOSFileName(const QString& name)
{
return RegularExpressionValidator("[\\w,-.]+", name);
}
RetType FileNameOrEmpty(const QString& name)
{
if (IsNotEmpty(name).first == QValidator::Acceptable)
@@ -24,6 +24,8 @@ namespace ProjectSettingsTool
// Returns true if valid cross platform file or directory name
FunctorValidator::ReturnType FileName(const QString& name);
// Returns true if valid iOS file or directory name
FunctorValidator::ReturnType IOSFileName(const QString& name);
// Returns true if valid cross platform file or directory name or empty
FunctorValidator::ReturnType FileNameOrEmpty(const QString& name);
// Returns true if string isn't empty
-40
View File
@@ -13,7 +13,6 @@
#include "IEditor.h"
#include "Include/IEditorClassFactory.h"
#include "Include/IViewPane.h"
#include "Include/ObjectEvent.h"
#include "Objects/ClassDesc.h"
@@ -107,43 +106,4 @@ public:
}
};
template<class TWidget>
class CQtViewClass
: public IViewPaneClass
{
public:
const char* m_name;
const char* m_category;
ESystemClassID m_classId;
CQtViewClass(const char* name, const char* category, ESystemClassID classId = ESYSTEM_CLASS_VIEWPANE)
: m_name(name)
, m_category(category)
, m_classId(classId)
{
}
ESystemClassID SystemClassID() override { return m_classId; };
static const GUID& GetClassID()
{
return TWidget::GetClassID();
}
const GUID& ClassID() override
{
return GetClassID();
}
QString ClassName() override { return m_name; };
QString Category() override { return m_category; };
QObject* CreateQObject() const override { return new TWidget(); };
QString GetPaneTitle() override { return m_name; };
unsigned int GetPaneTitleID() const override { return 0; };
EDockingDirection GetDockingDirection() override { return DOCK_FLOAT; };
QRect GetPaneRect() override { return {}; /* KDAB_TODO: ;m_sizeOptions.m_paneRect; */};
bool SinglePane() override { return false; };
bool WantIdleUpdate() override { return true; };
QSize GetMinSize() override { return {}; /*return m_sizeOptions.m_minSize;*/ }
};
#endif // CRYINCLUDE_EDITORCOMMON_QTVIEWPANE_H
-8
View File
@@ -269,14 +269,6 @@ bool RegisterQtViewPaneWithName([[maybe_unused]] IEditor* editor, const QString&
return true;
}
template<class TWidget>
void UnregisterQtViewPane()
{
// always close any views that the pane is responsible for before you remove it!
GetIEditor()->CloseView(CQtViewClass<TWidget>::GetClassID());
GetIEditor()->GetClassFactory()->UnregisterClass(CQtViewClass<TWidget>::GetClassID());
}
template<typename TWidget>
TWidget* FindViewPane(const QString& name)
{
+1 -1
View File
@@ -1084,7 +1084,7 @@ void SEditorSettings::SaveSettingsRegistryFile()
return;
}
[[maybe_unused]] bool saved{};
[[maybe_unused]] bool saved = false;
constexpr auto configurationMode = AZ::IO::SystemFile::SF_OPEN_CREATE
| AZ::IO::SystemFile::SF_OPEN_CREATE_PATH
| AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
@@ -143,5 +143,3 @@ void C2DBezierKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& se
}
}
}
REGISTER_QT_CLASS_DESC(C2DBezierKeyUIControls, "TrackView.KeyUI.2DBezier", "TrackViewKeyUI");
@@ -220,5 +220,3 @@ void CAssetBlendKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle&
}
}
}
REGISTER_QT_CLASS_DESC(CAssetBlendKeyUIControls, "TrackView.KeyUI.AssetBlends", "TrackViewKeyUI");
@@ -143,5 +143,3 @@ void CCaptureKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
REGISTER_QT_CLASS_DESC(CCaptureKeyUIControls, "TrackView.KeyUI.Capture", "TrackViewKeyUI");
@@ -169,5 +169,3 @@ void CCommentKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
REGISTER_QT_CLASS_DESC(CCommentKeyUIControls, "TrackView.KeyUI.Comment", "TrackViewKeyUI");
@@ -118,5 +118,3 @@ void CConsoleKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& sel
}
}
}
REGISTER_QT_CLASS_DESC(CConsoleKeyUIControls, "TrackView.KeyUI.Console", "TrackViewKeyUI");
@@ -149,5 +149,3 @@ void CEventKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& selec
}
}
}
REGISTER_QT_CLASS_DESC(CEventKeyUIControls, "TrackView.KeyUI.Event", "TrackViewKeyUI");
@@ -121,5 +121,3 @@ void CGotoKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& select
}
}
}
REGISTER_QT_CLASS_DESC(CGotoKeyUIControls, "TrackView.KeyUI.Goto", "TrackViewKeyUI");
@@ -167,5 +167,3 @@ void CScreenFaderKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle&
}
}
}
REGISTER_QT_CLASS_DESC(CScreenFaderKeyUIControls, "TrackView.KeyUI.ScreenFader", "TrackViewKeyUI");
@@ -269,5 +269,3 @@ void CSelectKeyUIControls::ResetCameraEntries()
OnCameraAdded(cameraComponentEntities.values[i]);
}
}
REGISTER_QT_CLASS_DESC(CSelectKeyUIControls, "TrackView.KeyUI.Select", "TrackViewKeyUI");
@@ -215,5 +215,3 @@ void CSequenceKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& se
}
}
}
REGISTER_QT_CLASS_DESC(CSequenceKeyUIControls, "TrackView.KeyUI.Sequence", "TrackViewKeyUI");
@@ -127,5 +127,3 @@ void CSoundKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& selec
}
}
}
REGISTER_QT_CLASS_DESC(CSoundKeyUIControls, "TrackView.KeyUI.Sound", "TrackViewKeyUI");
@@ -122,5 +122,3 @@ void CTimeRangeKeyUIControls::OnUIChange(IVariable* pVar, CTrackViewKeyBundle& s
}
}
}
REGISTER_QT_CLASS_DESC(CTimeRangeKeyUIControls, "TrackView.KeyUI.TimeRange", "TrackViewKeyUI");
@@ -235,5 +235,3 @@ void CTrackEventKeyUIControls::BuildEventDropDown(QString& curEvent, const QStri
}
}
}
REGISTER_QT_CLASS_DESC(CTrackEventKeyUIControls, "TrackView.KeyUI.TrackEvent", "TrackViewKeyUI");
-1
View File
@@ -17,7 +17,6 @@
#include "Cry_Geo.h"
#include "Viewport.h"
#include "Include/IViewPane.h"
#include "QtViewPaneManager.h"
// forward declaration.
class CLayoutWnd;
-7
View File
@@ -22,13 +22,6 @@ set(FILES
Controls/ReflectedPropertyControl/ReflectedVar.h
Controls/ReflectedPropertyControl/ReflectedVarWrapper.cpp
Controls/ReflectedPropertyControl/ReflectedVarWrapper.h
Controls/QBitmapPreviewDialog.cpp
Controls/QBitmapPreviewDialog.h
Controls/QBitmapPreviewDialog.ui
Controls/QBitmapPreviewDialogImp.cpp
Controls/QBitmapPreviewDialogImp.h
Controls/QToolTipWidget.h
Controls/QToolTipWidget.cpp
UsedResources.cpp
LyViewPaneNames.h
QtViewPaneManager.cpp
-6
View File
@@ -270,7 +270,6 @@ set(FILES
Include/ICommandManager.h
Include/IDisplayViewport.h
Include/IEditorClassFactory.h
Include/IEventLoopHook.h
Include/IExportManager.h
Include/IGizmoManager.h
Include/IIconManager.h
@@ -281,7 +280,6 @@ set(FILES
Include/IPreferencesPage.h
Include/ISourceControl.h
Include/ITransformManipulator.h
Include/IViewPane.h
Include/ObjectEvent.h
Util/AffineParts.cpp
Objects/BaseObject.cpp
@@ -315,8 +313,6 @@ set(FILES
AssetEditor/AssetEditorWindow.ui
Commands/CommandManager.cpp
Commands/CommandManager.h
Controls/BitmapToolTip.cpp
Controls/BitmapToolTip.h
Controls/ConsoleSCB.cpp
Controls/ConsoleSCB.h
Controls/ConsoleSCB.ui
@@ -338,8 +334,6 @@ set(FILES
Controls/ReflectedPropertyControl/PropertyMiscCtrl.h
Controls/ReflectedPropertyControl/PropertyMotionCtrl.cpp
Controls/ReflectedPropertyControl/PropertyMotionCtrl.h
Controls/ReflectedPropertyControl/PropertyResourceCtrl.cpp
Controls/ReflectedPropertyControl/PropertyResourceCtrl.h
Controls/ReflectedPropertyControl/PropertyCtrl.cpp
Controls/ReflectedPropertyControl/PropertyCtrl.h
MainStatusBar.cpp
@@ -92,6 +92,12 @@ namespace AZ::Data
result.Combine(resultHint);
}
if (SerializedAssetTracker* assetTracker = context.GetMetadata().Find<SerializedAssetTracker>();
assetTracker != nullptr && result.GetProcessing() == JSR::Processing::Completed)
{
assetTracker->AddAsset(*instance);
}
return context.Report(result,
result.GetProcessing() == JSR::Processing::Completed ? "Successfully stored Asset<T>." : "Failed to store Asset<T>.");
}
@@ -67,8 +67,7 @@ namespace AZ::Debug
Profiler() = default;
virtual ~Profiler() = default;
// support for the extra macro args (e.g. format strings) will come in a later PR
virtual void BeginRegion(const Budget* budget, const char* eventName) = 0;
virtual void BeginRegion(const Budget* budget, const char* eventName, size_t eventNameArgCount, ...) = 0;
virtual void EndRegion(const Budget* budget) = 0;
};
@@ -76,12 +75,11 @@ namespace AZ::Debug
{
public:
template<typename... T>
static void BeginRegion([[maybe_unused]] Budget* budget, [[maybe_unused]] const char* eventName, [[maybe_unused]] T const&... args);
static void EndRegion([[maybe_unused]] Budget* budget);
static void BeginRegion(Budget* budget, const char* eventName, T const&... args);
static void EndRegion(Budget* budget);
template<typename... T>
ProfileScope(Budget* budget, char const* eventName, T const&... args);
ProfileScope(Budget* budget, const char* eventName, T const&... args);
~ProfileScope();
@@ -31,10 +31,10 @@ namespace AZ::Debug
if (auto profiler = AZ::Interface<Profiler>::Get(); profiler)
{
profiler->BeginRegion(budget, eventName);
profiler->BeginRegion(budget, eventName, sizeof...(T), args...);
}
}
#endif // #if !defined(_RELEASE)
#endif // !defined(_RELEASE)
}
inline void ProfileScope::EndRegion([[maybe_unused]] Budget* budget)
@@ -55,7 +55,7 @@ namespace AZ::Debug
}
template<typename... T>
ProfileScope::ProfileScope(Budget* budget, char const* eventName, T const&... args)
ProfileScope::ProfileScope(Budget* budget, const char* eventName, T const&... args)
: m_budget{ budget }
{
BeginRegion(budget, eventName, args...);
@@ -203,7 +203,7 @@ namespace AZ
JsonSerializationResult::Result JsonMapSerializer::LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context)
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap)
{
namespace JSR = JsonSerializationResult;
@@ -231,8 +231,30 @@ namespace AZ
return context.Report(keyResult, "Failed to read key for associative container.");
}
void* valueAddress = nullptr;
bool keyExists = false;
// For multimaps, we append values to keys instead updating them.
// This is to ensure legacy multimap serialization support.
if (!isMultiMap)
{
auto associativeContainer = container->GetAssociativeContainerInterface();
void* existingKeyValuePair = associativeContainer->GetElementByKey(outputValue, keyElement, keyAddress);
if (existingKeyValuePair)
{
valueAddress = pairContainer->GetElementByIndex(existingKeyValuePair, pairElement, 1);
expectedSize--;
keyExists = true;
}
}
// If the key doesn't exist or it's a multimap, we're adding the new element we reserved above.
if (!keyExists)
{
valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
}
// Load value
void* valueAddress = pairContainer->GetElementByIndex(address, pairElement, 1);
AZ_Assert(valueAddress, "Element reserved for associative container, but unable to retrieve address of the value.");
ContinuationFlags valueLoadFlags = ContinuationFlags::LoadAsNewInstance;
if (valueElement->m_flags & SerializeContext::ClassElement::Flags::FLG_POINTER)
@@ -257,7 +279,18 @@ namespace AZ
}
else
{
container->StoreElement(outputValue, address);
// Even if the key exists, calling StoreElement will not replace the existing key
// and will free the temporary address as expected. Checking if the key already
// exists and skipping the call to StoreElement if it does, makes the intent more
// clear. The end result is the same either way.
if (!keyExists)
{
container->StoreElement(outputValue, address);
}
else
{
container->FreeReservedElement(outputValue, address, context.GetSerializeContext());
}
if (container->Size(outputValue) != expectedSize)
{
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Unavailable,
@@ -430,7 +463,7 @@ namespace AZ
JsonSerializationResult::Result JsonUnorderedMultiMapSerializer::LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context)
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, [[maybe_unused]] bool isMultiMap)
{
namespace JSR = JsonSerializationResult;
@@ -440,7 +473,7 @@ namespace AZ
for (auto& entry : value.GetArray())
{
result.Combine(JsonMapSerializer::LoadElement(outputValue, container, pairElement, pairContainer,
keyElement, valueElement, key, entry, context));
keyElement, valueElement, key, entry, context, true));
if (result.GetProcessing() == JSR::Processing::Halted)
{
return context.Report(result, "Unable to process the key or all values in multi-map.");
@@ -451,7 +484,7 @@ namespace AZ
else if (IsExplicitDefault(value))
{
return JsonMapSerializer::LoadElement(outputValue, container, pairElement, pairContainer,
keyElement, valueElement, key, value, context);
keyElement, valueElement, key, value, context, true);
}
else
{
@@ -32,7 +32,7 @@ namespace AZ
virtual JsonSerializationResult::Result LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context);
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap = false);
virtual JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
const Uuid& valueTypeId, JsonSerializerContext& context, bool sortResult);
@@ -62,7 +62,7 @@ namespace AZ
JsonSerializationResult::Result LoadElement(void* outputValue, SerializeContext::IDataContainer* container,
const SerializeContext::ClassElement* pairElement, SerializeContext::IDataContainer* pairContainer,
const SerializeContext::ClassElement* keyElement, const SerializeContext::ClassElement* valueElement,
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context) override;
const rapidjson::Value& key, const rapidjson::Value& value, JsonDeserializerContext& context, bool isMultiMap = false) override;
using JsonMapSerializer::Store;
JsonSerializationResult::Result Store(rapidjson::Value& outputValue, const void* inputValue, const void* defaultValue,
@@ -36,5 +36,12 @@ namespace AZStd
{
pthread_setname_np(tId, name);
}
uint8_t GetDefaultThreadPriority()
{
// pthread priority is an integer between >=1 and <=99 (although only range 1<=>32 is guaranteed)
// Don't use a scheduling policy value (e.g. SCHED_OTHER or SCHED_FIFO) here.
return 1;
}
}
}
@@ -35,7 +35,7 @@ namespace AZStd
void SetThreadPriority(int priority, pthread_attr_t& attr)
{
if (priority == -1)
if (priority <= -1)
{
pthread_attr_setinheritsched(&attr, PTHREAD_INHERIT_SCHED);
}
@@ -59,5 +59,18 @@ namespace AZStd
thread_policy_set(mach_thread, THREAD_AFFINITY_POLICY, (thread_policy_t)& policyData, 1);
}
}
//////////////////////////////////////////////////////////////////////////////////
// Apple pthread -> NSThread quality of service level map
// QOS class name | min pthread priority | max pthread priority | comment
// QOS_CLASS_USER_INTERACTIVE | 38 | 47 | Per-frame work
// QOS_CLASS_USER_INITIATED | 32 | 37 | Asynchronous / Cross frame work
// QOS_CLASS_DEFAULT | 21 | 31 | Streaming / Multiple frames deadline
// QOS_CLASS_UTILITY | 5 | 20 | Background asset download
// QOS_CLASS_BACKGROUN | 0 | 4 | Will be prevented from using whole core.
uint8_t GetDefaultThreadPriority()
{
return 10;
}
}
}
@@ -21,6 +21,7 @@ namespace AZStd
void PreCreateSetThreadAffinity(int cpuId, pthread_attr_t& attr);
void SetThreadPriority(int priority, pthread_attr_t& attr);
void PostCreateThread(pthread_t tId, const char * name, int cpuId);
uint8_t GetDefaultThreadPriority();
}
namespace Internal
@@ -60,12 +61,13 @@ namespace AZStd
}
else
{
priority = SCHED_OTHER;
priority = Platform::GetDefaultThreadPriority();
}
if (desc->m_name)
{
name = desc->m_name;
}
ti->m_name = name;
cpuId = desc->m_cpuId;
pthread_attr_setdetachstate(&attr, desc->m_isJoinable ? PTHREAD_CREATE_JOINABLE : PTHREAD_CREATE_DETACHED);
@@ -55,5 +55,12 @@ namespace AZStd
{
pthread_setname_np(tId, name);
}
uint8_t GetDefaultThreadPriority()
{
// pthread priority is an integer between >=1 and <=99 (although only range 1<=>32 is guaranteed)
// Don't use a scheduling policy value (e.g. SCHED_OTHER or SCHED_FIFO) here.
return 1;
}
}
}
@@ -475,7 +475,7 @@ namespace JsonSerializationTests
EXPECT_STRCASEEQ("value_42", worldKey->second.m_value.c_str());
}
TEST_F(JsonMapSerializerTests, Load_DuplicateKey_EntryIgnored)
TEST_F(JsonMapSerializerTests, Load_DuplicateKey_EntryUpdated)
{
using namespace AZ::JsonSerializationResult;
@@ -489,12 +489,12 @@ namespace JsonSerializationTests
StringMap values;
ResultCode result = m_unorderedMapSerializer.Load(&values, azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext);
EXPECT_EQ(Processing::PartialAlter, result.GetProcessing());
EXPECT_EQ(Outcomes::Unavailable, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
EXPECT_EQ(Outcomes::Success, result.GetOutcome());
auto entry = values.find("Hello");
ASSERT_NE(values.end(), entry);
EXPECT_STRCASEEQ("World", entry->second.c_str());
EXPECT_EQ("Other", entry->second);
}
TEST_F(JsonMapSerializerTests, Load_DuplicateMultiKey_LoadEverything)
@@ -536,8 +536,8 @@ namespace JsonSerializationTests
ResultCode result = m_unorderedMapSerializer.Load(&values,
azrtti_typeid(&values), *m_jsonDocument, *m_jsonDeserializationContext);
EXPECT_EQ(Processing::Altered, result.GetProcessing());
EXPECT_EQ(Outcomes::Unavailable, result.GetOutcome());
EXPECT_EQ(Processing::Completed, result.GetProcessing());
EXPECT_EQ(Outcomes::Success, result.GetOutcome());
auto entry = values.find("Hello");
ASSERT_NE(values.end(), entry);
+32 -32
View File
@@ -447,13 +447,13 @@ namespace UnitTest
{
x -= 1;
});
// a <-- Root
// / \
// b c
// \ /
// d
/*
a <-- Root
/ \
b c
\ /
d
*/
a.Precedes(b, c);
d.Follows(b, c);
@@ -522,20 +522,20 @@ namespace UnitTest
{
x -= 1;
});
// NOTE: The ideal way to express this topology is without the wait on the subgraph
// at task g, but this is more an illustrative test. Better is to express the entire
// graph in a single larger graph.
// a <-- Root
// / \
// b c - f
// \ \ \
// \ e - g
// \ /
// \ /
// \ /
// d
/*
NOTE: The ideal way to express this topology is without the wait on the subgraph
at task g, but this is more an illustrative test. Better is to express the entire
graph in a single larger graph.
a <-- Root
/ \
b c - f
\ \ \
\ e - g
\ /
\ /
\ /
d
*/
a.Precedes(b);
a.Precedes(c);
b.Precedes(d);
@@ -593,17 +593,17 @@ namespace UnitTest
{
x += 0b1000;
});
// a <-- Root
// / \
// b c - f
// \ \ \
// \ e - g
// \ /
// \ /
// \ /
// d
/*
a <-- Root
/ \
b c - f
\ \ \
\ e - g
\ /
\ /
\ /
d
*/
a.Precedes(b, c);
b.Precedes(d);
c.Precedes(e, f);
@@ -378,7 +378,7 @@ namespace Physics
m_cachedNativeHeightfield = cachedNativeHeightfield;
}
AZ::Vector2 HeightfieldShapeConfiguration::GetGridResolution() const
const AZ::Vector2& HeightfieldShapeConfiguration::GetGridResolution() const
{
return m_gridResolution;
}
@@ -221,7 +221,7 @@ namespace Physics
const void* GetCachedNativeHeightfield() const;
void* GetCachedNativeHeightfield();
void SetCachedNativeHeightfield(void* cachedNativeHeightfield);
AZ::Vector2 GetGridResolution() const;
const AZ::Vector2& GetGridResolution() const;
void SetGridResolution(const AZ::Vector2& gridSpacing);
int32_t GetNumColumns() const;
void SetNumColumns(int32_t numColumns);
@@ -235,7 +235,7 @@ namespace Physics
void SetMaxHeightBounds(float maxBounds);
private:
//! The number of meters between each heightfield sample.
//! The number of meters between each heightfield sample in x and y.
AZ::Vector2 m_gridResolution{ 1.0f };
//! The number of columns in the heightfield sample grid.
int32_t m_numColumns{ 0 };
@@ -50,8 +50,8 @@ namespace AzFramework
static AZ::Vector3 GetDefaultTerrainNormal() { return AZ::Vector3::CreateAxisZ(); }
// System-level queries to understand world size and resolution
virtual AZ::Vector2 GetTerrainHeightQueryResolution() const = 0;
virtual void SetTerrainHeightQueryResolution(AZ::Vector2 queryResolution) = 0;
virtual float GetTerrainHeightQueryResolution() const = 0;
virtual void SetTerrainHeightQueryResolution(float queryResolution) = 0;
virtual AZ::Aabb GetTerrainAabb() const = 0;
virtual void SetTerrainAabb(const AZ::Aabb& worldBounds) = 0;
@@ -49,8 +49,8 @@ namespace UnitTest
AzFramework::Terrain::TerrainDataRequestBus::Handler::BusDisconnect();
}
MOCK_CONST_METHOD0(GetTerrainHeightQueryResolution, AZ::Vector2());
MOCK_METHOD1(SetTerrainHeightQueryResolution, void(AZ::Vector2));
MOCK_CONST_METHOD0(GetTerrainHeightQueryResolution, float());
MOCK_METHOD1(SetTerrainHeightQueryResolution, void(float));
MOCK_CONST_METHOD0(GetTerrainAabb, AZ::Aabb());
MOCK_METHOD1(SetTerrainAabb, void(const AZ::Aabb&));
MOCK_CONST_METHOD3(GetHeight, float(const AZ::Vector3&, Sampler, bool*));
@@ -47,8 +47,6 @@ namespace AzManipulatorTestFramework
virtual void UpdateVisibility() = 0;
//! Sets if sticky select is enabled or not.
virtual void SetStickySelect(bool enabled) = 0;
//! Gets default Editor Camera Position.
virtual AZ::Vector3 DefaultEditorCameraPosition() const = 0;
//! Sets if icons are visible in the viewport.
virtual void SetIconsVisible(bool visible) = 0;
//! Sets if helpers are visible in the viewport.
@@ -10,6 +10,7 @@
#include <AzFramework/Visibility/EntityVisibilityQuery.h>
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
#include <AzToolsFramework/UnitTest/AzToolsFrameworkTestHelpers.h>
namespace AzFramework
{
@@ -22,7 +23,7 @@ namespace AzManipulatorTestFramework
class ViewportInteraction
: public ViewportInteractionInterface
, public AzToolsFramework::ViewportInteraction::ViewportInteractionRequestBus::Handler
, public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
, public UnitTest::ViewportSettingsTestImpl
, private AzToolsFramework::ViewportInteraction::EditorEntityViewportInteractionRequestBus::Handler
{
public:
@@ -50,19 +51,6 @@ namespace AzManipulatorTestFramework
const AzFramework::ScreenPoint& screenPosition) override;
float DeviceScalingFactor() override;
// ViewportSettingsRequestBus overrides ...
bool GridSnappingEnabled() const override;
float GridSize() const override;
bool ShowGrid() const override;
bool AngleSnappingEnabled() const override;
float AngleStep() const override;
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
// EditorEntityViewportInteractionRequestBus overrides ...
void FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntities) override;
@@ -72,12 +60,5 @@ namespace AzManipulatorTestFramework
AzFramework::EntityVisibilityQuery m_entityVisibilityQuery;
AZStd::shared_ptr<AzFramework::DebugDisplayRequests> m_debugDisplayRequests;
AzFramework::CameraState m_cameraState;
float m_gridSize = 1.0f;
float m_angularStep = 0.0f;
bool m_gridSnapping = false;
bool m_angularSnapping = false;
bool m_stickySelect = true;
bool m_iconsVisible = true;
bool m_helpersVisible = true;
};
} // namespace AzManipulatorTestFramework
@@ -37,46 +37,6 @@ namespace AzManipulatorTestFramework
return m_cameraState;
}
bool ViewportInteraction::GridSnappingEnabled() const
{
return m_gridSnapping;
}
float ViewportInteraction::GridSize() const
{
return m_gridSize;
}
bool ViewportInteraction::ShowGrid() const
{
return false;
}
bool ViewportInteraction::AngleSnappingEnabled() const
{
return m_angularSnapping;
}
float ViewportInteraction::AngleStep() const
{
return m_angularStep;
}
float ViewportInteraction::ManipulatorLineBoundWidth() const
{
return 0.1f;
}
float ViewportInteraction::ManipulatorCircleBoundWidth() const
{
return 0.1f;
}
bool ViewportInteraction::StickySelectEnabled() const
{
return m_stickySelect;
}
void ViewportInteraction::FindVisibleEntities(AZStd::vector<AZ::EntityId>& visibleEntitiesOut)
{
visibleEntitiesOut.assign(m_entityVisibilityQuery.Begin(), m_entityVisibilityQuery.End());
@@ -127,11 +87,6 @@ namespace AzManipulatorTestFramework
m_helpersVisible = visible;
}
AZ::Vector3 ViewportInteraction::DefaultEditorCameraPosition() const
{
return {};
}
void ViewportInteraction::SetGridSize(float size)
{
m_gridSize = size;
@@ -162,14 +117,4 @@ namespace AzManipulatorTestFramework
{
return 1.0f;
}
bool ViewportInteraction::IconsVisible() const
{
return m_iconsVisible;
}
bool ViewportInteraction::HelpersVisible() const
{
return m_helpersVisible;
}
} // namespace AzManipulatorTestFramework
@@ -28,7 +28,7 @@ namespace AzToolsFramework
{
namespace Internal
{
AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer,
static AZ::JsonSerializationResult::ResultCode JsonIssueReporter(AZStd::string& scratchBuffer,
AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result, AZStd::string_view path)
{
namespace JSR = AZ::JsonSerializationResult;
@@ -48,6 +48,66 @@ namespace AzToolsFramework
return result;
}
static bool StoreInstanceInPrefabDom(
const Instance& instance,
PrefabDom& prefabDom,
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>* referencedAssets,
StoreFlags flags)
{
InstanceEntityIdMapper entityIdMapper;
entityIdMapper.SetStoringInstance(instance);
// Need to store the id mapper as both its type and its base type
// Metadata is found by type id and we need access to both types at different levels (Instance, EntityId)
AZ::JsonSerializerSettings settings;
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
settings.m_metadata.Add(&entityIdMapper);
if (referencedAssets)
{
settings.m_metadata.Add(AZ::Data::SerializedAssetTracker{});
}
if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
{
settings.m_keepDefaults = true;
}
if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None)
{
settings.m_metadata.Create<LinkIdMetadata>();
}
AZStd::string scratchBuffer;
auto issueReportingCallback = [&scratchBuffer](
AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
{
return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
};
settings.m_reporting = AZStd::move(issueReportingCallback);
AZ::JsonSerializationResult::ResultCode result =
AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
{
AZ_Error(
"Prefab", false,
"Failed to serialize prefab instance with source path %s. "
"Unable to proceed.",
instance.GetTemplateSourcePath().c_str());
return false;
}
if (referencedAssets)
{
*referencedAssets = AZStd::move(settings.m_metadata.Find<AZ::Data::SerializedAssetTracker>()->GetTrackedAssets());
}
return true;
}
}
PrefabDomValueReference FindPrefabDomValue(PrefabDomValue& parentValue, const char* valueName)
@@ -74,49 +134,16 @@ namespace AzToolsFramework
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags)
{
InstanceEntityIdMapper entityIdMapper;
entityIdMapper.SetStoringInstance(instance);
return Internal::StoreInstanceInPrefabDom(instance, prefabDom, nullptr, flags);
}
// Need to store the id mapper as both its type and its base type
// Meta data is found by type id and we need access to both types at different levels (Instance, EntityId)
AZ::JsonSerializerSettings settings;
settings.m_metadata.Add(static_cast<AZ::JsonEntityIdSerializer::JsonEntityIdMapper*>(&entityIdMapper));
settings.m_metadata.Add(&entityIdMapper);
if ((flags & StoreFlags::StripDefaultValues) != StoreFlags::StripDefaultValues)
{
settings.m_keepDefaults = true;
}
if ((flags & StoreFlags::StoreLinkIds) != StoreFlags::None)
{
settings.m_metadata.Create<LinkIdMetadata>();
}
AZStd::string scratchBuffer;
auto issueReportingCallback = [&scratchBuffer]
(AZStd::string_view message, AZ::JsonSerializationResult::ResultCode result,
AZStd::string_view path) -> AZ::JsonSerializationResult::ResultCode
{
return Internal::JsonIssueReporter(scratchBuffer, message, result, path);
};
settings.m_reporting = AZStd::move(issueReportingCallback);
AZ::JsonSerializationResult::ResultCode result =
AZ::JsonSerialization::Store(prefabDom, prefabDom.GetAllocator(), instance, settings);
if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Halted)
{
AZ_Error("Prefab", false,
"Failed to serialize prefab instance with source path %s. "
"Unable to proceed.",
instance.GetTemplateSourcePath().c_str());
return false;
}
return true;
bool StoreInstanceInPrefabDom(
const Instance& instance,
PrefabDom& prefabDom,
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets,
StoreFlags flags)
{
return Internal::StoreInstanceInPrefabDom(instance, prefabDom, &referencedAssets, flags);
}
bool StoreEntityInPrefabDomFormat(const AZ::Entity& entity, Instance& owningInstance, PrefabDom& prefabDom, StoreFlags flags)
@@ -57,14 +57,28 @@ namespace AzToolsFramework
AZ_DEFINE_ENUM_BITWISE_OPERATORS(StoreFlags);
/**
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates
* @param instance The instance to store
* @param prefabDom The prefabDom that will be used to store the Instance data
* @param flags Controls behavior such as whether to store default values
* @return bool on whether the operation succeeded
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates.
* @param instance The instance to store.
* @param prefabDom The prefabDom that will be used to store the Instance data.
* @param flags Controls behavior such as whether to store default values.
* @return bool on whether the operation succeeded.
*/
bool StoreInstanceInPrefabDom(const Instance& instance, PrefabDom& prefabDom, StoreFlags flags = StoreFlags::None);
/**
* Stores a valid Prefab Instance within a Prefab Dom. Useful for generating Templates.
* @param instance The instance to store.
* @param prefabDom The prefabDom that will be used to store the Instance data.
* @param referencedAssets Collect a list of the assets that are referenced during storing.
* @param flags Controls behavior such as whether to store default values.
* @return bool on whether the operation succeeded.
*/
bool StoreInstanceInPrefabDom(
const Instance& instance,
PrefabDom& prefabDom,
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets,
StoreFlags flags = StoreFlags::None);
/**
* Stores a valid entity in Prefab Dom format.
* @param entity The entity to store
@@ -6,12 +6,14 @@
*
*/
#include <AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h>
#include <AzCore/Asset/AssetManager.h>
#include <AzCore/Asset/AssetManagerBus.h>
#include <AzCore/Asset/AssetSerializer.h>
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzToolsFramework/Prefab/PrefabLoader.h>
#include <AzToolsFramework/Prefab/PrefabSystemComponentInterface.h>
#include <AzToolsFramework/Prefab/Spawnable/InMemorySpawnableAssetContainer.h>
#include <AzToolsFramework/Prefab/Spawnable/PrefabConverterStackProfileNames.h>
namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -161,13 +163,10 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
{
return AZ::Failure(AZStd::string::format("Failed to produce the target spawnable '%.*s'.", AZ_STRING_ARG(spawnableName)));
}
if (loadReferencedAssets)
{
for (auto& product : context.GetProcessedObjects())
{
LoadReferencedAssets(product.GetReferencedAssets());
}
LoadReferencedAssets(spawnableAssetData);
}
auto& spawnableAssetDataAdded = m_spawnableAssets.emplace(spawnableName, spawnableAssetData).first->second;
@@ -213,63 +212,87 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return m_spawnableAssets;
}
void InMemorySpawnableAssetContainer::LoadReferencedAssets(AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets)
void InMemorySpawnableAssetContainer::LoadReferencedAssets(SpawnableAssetData& spawnable)
{
// Start our loads on all assets by calling GetAsset from the AssetManager
for (AZ::Data::Asset<AZ::Data::AssetData>& asset : referencedAssets)
// Get the referenced assets directly from the product. This is done for two reasons:
// 1. Avoids calls to the Asset Manager for assets that are already loaded.
// 2. Gets the exact asset to load to avoid issues with assets that don't reload.
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>*> blockingAssets;
AZ::SerializeContext* sc = nullptr;
AZ::ComponentApplicationBus::BroadcastResult(sc, &AZ::ComponentApplicationBus::Events::GetSerializeContext);
AZ_Assert(sc, "Unable to locate Serialize Context while resolving asset references in the in-memory spawnable asset container.");
for (AZ::Data::Asset<AZ::Data::AssetData>& asset : spawnable.m_assets)
{
if (!asset.GetId().IsValid())
auto callback = [&blockingAssets](
void* object, const AZ::SerializeContext::ClassData* classData,
[[maybe_unused]]const AZ::SerializeContext::ClassElement* elementData) -> bool
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
if (classData->m_typeId == AZ::GetAssetClassId())
{
auto asset = reinterpret_cast<AZ::Data::Asset<AZ::Data::AssetData>*>(object);
const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
if (!asset->GetId().IsValid())
{
AZ_Error(
"Prefab", false,
"Invalid asset found referenced in scene while entering game mode. The asset was stored in an instance of %s.",
classData->m_name);
return false;
}
if (loadBehavior == AZ::Data::AssetLoadBehavior::NoLoad)
{
continue;
}
if (asset->GetStatus() != AZ::Data::AssetData::AssetStatus::NotLoaded)
{
// Already loaded so no need to do anything.
return false;
}
AZ::Data::AssetId assetId = asset.GetId();
AZ::Data::AssetType assetType = asset.GetType();
const AZ::Data::AssetLoadBehavior loadBehavior = asset->GetAutoLoadBehavior();
if (loadBehavior == AZ::Data::AssetLoadBehavior::NoLoad)
{
return false;
}
asset = AZ::Data::AssetManager::Instance().GetAsset(assetId, assetType, loadBehavior);
if (loadBehavior == AZ::Data::AssetLoadBehavior::PreLoad)
{
// Only assets that are preloaded need to be waited on.
blockingAssets.push_back(asset);
}
if (!asset->QueueLoad())
{
AZ_Error(
"Prefab", false, "Failed to queue asset '%s' (%s) of type '%s' for loading while entering game mode.",
asset->GetHint().c_str(), asset->GetId().ToString<AZStd::fixed_string<AZ::Uuid::MaxStringBuffer>>().c_str(),
asset->GetType().ToString<AZStd::fixed_string<AZ::Uuid::MaxStringBuffer>>().c_str());
return false;
}
if (!asset.GetId().IsValid())
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
return false;
}
return true;
};
AZ::SerializeContext::EnumerateInstanceCallContext enumerationContext(
callback, nullptr, sc, AZ::SerializeContext::ENUM_ACCESS_FOR_READ, nullptr);
sc->EnumerateInstance(&enumerationContext, asset.GetData(), asset.GetType(), nullptr, nullptr);
}
// For all Preload assets we block until they're ready
// We do this as a separate pass so that we don't interrupt queuing up all other asset loads
for (AZ::Data::Asset<AZ::Data::AssetData>& asset : referencedAssets)
for (AZ::Data::Asset<AZ::Data::AssetData>* asset : blockingAssets)
{
if (!asset.GetId().IsValid())
asset->BlockUntilLoadComplete();
if (asset->IsError())
{
AZ_Error("Prefab", false, "Invalid asset found referenced in scene while entering game mode");
continue;
}
const AZ::Data::AssetLoadBehavior loadBehavior = asset.GetAutoLoadBehavior();
if (loadBehavior != AZ::Data::AssetLoadBehavior::PreLoad)
{
continue;
}
asset.BlockUntilLoadComplete();
if (asset.IsError())
{
AZ_Error("Prefab", false, "Asset with id %s failed to preload while entering game mode",
asset.GetId().ToString<AZStd::string>().c_str());
AZ_Error(
"Prefab", false, "Asset '%s' (%s) of type '%s' failed to preload while entering game mode", asset->GetHint().c_str(),
asset->GetId().ToString<AZStd::fixed_string<AZ::Uuid::MaxStringBuffer>>().c_str(),
asset->GetType().ToString<AZStd::fixed_string<AZ::Uuid::MaxStringBuffer>>().c_str());
continue;
}
}
}
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -21,7 +21,6 @@ namespace AzToolsFramework::Prefab
namespace AzToolsFramework::Prefab::PrefabConversionUtils
{
class InMemorySpawnableAssetContainer
{
public:
@@ -58,8 +57,8 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
const SpawnableAssets& GetAllInMemorySpawnableAssets() const;
private:
void LoadReferencedAssets(AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& referencedAssets);
void LoadReferencedAssets(SpawnableAssetData& spawnable);
SpawnableAssets m_spawnableAssets;
PrefabConversionUtils::PrefabConversionPipeline m_converter;
AZStd::string_view m_stockProfile;
@@ -53,21 +53,14 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
const PrefabDom& PrefabDocument::GetDom() const
{
if (m_isDirty)
{
m_isDirty = !PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
}
RefreshPrefabDom();
return m_dom;
}
PrefabDom&& PrefabDocument::TakeDom()
{
if (m_isDirty)
{
[[maybe_unused]] bool storedSuccessfully = PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom);
AZ_Assert(storedSuccessfully, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
m_isDirty = false;
}
RefreshPrefabDom();
// After the PrefabDom is moved an empty PrefabDom is left behind. This should be reflected in the Instance,
// so reset it so it's empty as well.
m_instance->Reset();
@@ -126,11 +119,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& PrefabDocument::GetReferencedAssets()
{
RefreshPrefabDom();
return m_referencedAssets;
}
const AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>>& PrefabDocument::GetReferencedAssets() const
{
RefreshPrefabDom();
return m_referencedAssets;
}
@@ -158,4 +153,20 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
return false;
}
}
void PrefabDocument::RefreshPrefabDom() const
{
if (m_isDirty)
{
m_referencedAssets.clear();
if (PrefabDomUtils::StoreInstanceInPrefabDom(*m_instance, m_dom, m_referencedAssets))
{
m_isDirty = false;
}
else
{
AZ_Assert(false, "Failed to store Instance '%s' to PrefabDom.", m_name.c_str());
}
}
}
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -58,11 +58,13 @@ namespace AzToolsFramework::Prefab::PrefabConversionUtils
private:
bool ConstructInstanceFromPrefabDom(const PrefabDom& prefab);
// Marked const so this function can be called from other const functions. It will only operate on mutable variables.
void RefreshPrefabDom() const;
mutable PrefabDom m_dom;
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> m_instance;
AZStd::string m_name;
AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> m_referencedAssets;
mutable AZStd::vector<AZ::Data::Asset<AZ::Data::AssetData>> m_referencedAssets;
mutable bool m_isDirty{ false };
};
} // namespace AzToolsFramework::Prefab::PrefabConversionUtils
@@ -80,7 +80,6 @@ namespace AzToolsFramework
EntityOutlinerListModel::EntityOutlinerListModel(QObject* parent)
: QAbstractItemModel(parent)
, m_entitySelectQueue()
, m_entityExpandQueue()
, m_entityChangeQueue()
, m_entityChangeQueued(false)
, m_entityLayoutQueued(false)
@@ -1275,7 +1274,6 @@ namespace AzToolsFramework
void EntityOutlinerListModel::QueueEntityToExpand(AZ::EntityId entityId, bool expand)
{
m_entityExpansionState[entityId] = expand;
m_entityExpandQueue.insert(entityId);
QueueEntityUpdate(entityId);
}
@@ -1300,16 +1298,7 @@ namespace AzToolsFramework
{
return;
}
{
AZ_PROFILE_SCOPE(Editor, "EntityOutlinerListModel::ProcessEntityUpdates:ExpandQueue");
for (auto entityId : m_entityExpandQueue)
{
emit ExpandEntity(entityId, IsExpanded(entityId));
};
m_entityExpandQueue.clear();
}
{
AZ_PROFILE_SCOPE(Editor, "EntityOutlinerListModel::ProcessEntityUpdates:SelectQueue");
for (auto entityId : m_entitySelectQueue)
@@ -156,7 +156,6 @@ namespace AzToolsFramework
void ProcessEntityUpdates();
Q_SIGNALS:
void ExpandEntity(const AZ::EntityId& entityId, bool expand);
void SelectEntity(const AZ::EntityId& entityId, bool select);
void EnableSelectionUpdates(bool enable);
void ResetFilter();
@@ -190,7 +189,6 @@ namespace AzToolsFramework
void QueueEntityToExpand(AZ::EntityId entityId, bool expand);
void ProcessEntityInfoResetEnd();
AZStd::unordered_set<AZ::EntityId> m_entitySelectQueue;
AZStd::unordered_set<AZ::EntityId> m_entityExpandQueue;
AZStd::unordered_set<AZ::EntityId> m_entityChangeQueue;
bool m_entityChangeQueued;
bool m_entityLayoutQueued;
@@ -81,6 +81,61 @@ namespace AzToolsFramework
update();
}
void EntityOutlinerTreeView::dataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight, const QVector<int>& roles)
{
AzQtComponents::StyledTreeView::dataChanged(topLeft, bottomRight, roles);
if (topLeft.isValid() && topLeft.parent() == bottomRight.parent() && topLeft.row() <= bottomRight.row() &&
topLeft.column() <= bottomRight.column())
{
for (int i = topLeft.row(); i <= bottomRight.row(); i++)
{
auto modelRow = topLeft.sibling(i, EntityOutlinerListModel::ColumnName);
if (modelRow.isValid())
{
checkExpandedState(modelRow);
}
}
}
}
void EntityOutlinerTreeView::rowsInserted(const QModelIndex& parent, int start, int end)
{
if (parent.isValid())
{
for (int i = start; i <= end; i++)
{
auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, parent);
if (modelRow.isValid())
{
checkExpandedState(modelRow);
recursiveCheckExpandedStates(modelRow);
}
}
}
AzQtComponents::StyledTreeView::rowsInserted(parent, start, end);
}
void EntityOutlinerTreeView::recursiveCheckExpandedStates(const QModelIndex& current)
{
const int rowCount = model()->rowCount(current);
for (int i = 0; i < rowCount; i++)
{
auto modelRow = model()->index(i, EntityOutlinerListModel::ColumnName, current);
if (modelRow.isValid())
{
checkExpandedState(modelRow);
recursiveCheckExpandedStates(modelRow);
}
}
}
void EntityOutlinerTreeView::checkExpandedState(const QModelIndex& current)
{
const bool expandState = current.data(EntityOutlinerListModel::ExpandedRole).template value<bool>();
setExpanded(current, expandState);
}
void EntityOutlinerTreeView::mousePressEvent(QMouseEvent* event)
{
//postponing normal mouse pressed logic until mouse is released or dragged
@@ -51,6 +51,10 @@ namespace AzToolsFramework
Q_SIGNALS:
void ItemDropped();
protected Q_SLOTS:
void dataChanged(const QModelIndex &topLeft, const QModelIndex &bottomRight, const QVector<int> &roles = QVector<int>()) override;
void rowsInserted(const QModelIndex &parent, int start, int end) override;
protected:
// Qt overrides
void mousePressEvent(QMouseEvent* event) override;
@@ -75,6 +79,8 @@ namespace AzToolsFramework
void ClearQueuedMouseEvent();
void processQueuedMousePressedEvent(QMouseEvent* event);
void recursiveCheckExpandedStates(const QModelIndex& parent);
void checkExpandedState(const QModelIndex& current);
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
@@ -224,7 +224,6 @@ namespace AzToolsFramework
connect(m_gui->m_objectTree, &QTreeView::expanded, this, &EntityOutlinerWidget::OnTreeItemExpanded);
connect(m_gui->m_objectTree, &QTreeView::collapsed, this, &EntityOutlinerWidget::OnTreeItemCollapsed);
connect(m_gui->m_objectTree, &EntityOutlinerTreeView::ItemDropped, this, &EntityOutlinerWidget::OnDropEvent);
connect(m_listModel, &EntityOutlinerListModel::ExpandEntity, this, &EntityOutlinerWidget::OnExpandEntity);
connect(m_listModel, &EntityOutlinerListModel::SelectEntity, this, &EntityOutlinerWidget::OnSelectEntity);
connect(m_listModel, &EntityOutlinerListModel::EnableSelectionUpdates, this, &EntityOutlinerWidget::OnEnableSelectionUpdates);
connect(m_listModel, &EntityOutlinerListModel::ResetFilter, this, &EntityOutlinerWidget::ClearFilter);
@@ -972,10 +971,6 @@ namespace AzToolsFramework
m_listModel->OnEntityCollapsed(entityId);
}
void EntityOutlinerWidget::OnExpandEntity(const AZ::EntityId& entityId, bool expand)
{
m_gui->m_objectTree->setExpanded(GetIndexFromEntityId(entityId), expand);
}
void EntityOutlinerWidget::OnSelectEntity(const AZ::EntityId& entityId, bool selected)
{
@@ -155,7 +155,6 @@ namespace AzToolsFramework
void OnTreeItemDoubleClicked(const QModelIndex& index);
void OnTreeItemExpanded(const QModelIndex& index);
void OnTreeItemCollapsed(const QModelIndex& index);
void OnExpandEntity(const AZ::EntityId& entityId, bool expand);
void OnSelectEntity(const AZ::EntityId& entityId, bool selected);
void OnEnableSelectionUpdates(bool enable);
void OnDropEvent();
@@ -306,41 +306,37 @@ namespace AzToolsFramework
{
// Only show the close icon if the prefab is expanded.
// This allows the prefab container to be opened if it was collapsed during propagation.
if (!isExpanded)
if (isExpanded)
{
return;
}
// Use the same color as the background.
QColor backgroundColor = m_backgroundColor;
if (isSelected)
{
backgroundColor = m_backgroundSelectedColor;
}
else if (isHovered)
{
backgroundColor = m_backgroundHoverColor;
}
// Use the same color as the background.
QColor backgroundColor = m_backgroundColor;
if (isSelected)
{
backgroundColor = m_backgroundSelectedColor;
}
else if (isHovered)
{
backgroundColor = m_backgroundHoverColor;
}
// Paint a rect to cover up the expander.
QRect rect = QRect(0, 0, 16, 16);
rect.translate(option.rect.topLeft() + offset);
painter->fillRect(rect, backgroundColor);
// Paint a rect to cover up the expander.
QRect rect = QRect(0, 0, 16, 16);
rect.translate(option.rect.topLeft() + offset);
painter->fillRect(rect, backgroundColor);
// Paint the icon.
QIcon closeIcon = QIcon(m_prefabEditCloseIconPath);
painter->drawPixmap(option.rect.topLeft() + offset, closeIcon.pixmap(iconSize));
// Paint the icon.
QIcon closeIcon = QIcon(m_prefabEditCloseIconPath);
painter->drawPixmap(option.rect.topLeft() + offset, closeIcon.pixmap(iconSize));
}
}
else
{
// Only show the edit icon on hover.
if (!isHovered)
if (isHovered)
{
return;
QIcon openIcon = QIcon(m_prefabEditOpenIconPath);
painter->drawPixmap(option.rect.topLeft() + offset, openIcon.pixmap(iconSize));
}
QIcon openIcon = QIcon(m_prefabEditOpenIconPath);
painter->drawPixmap(option.rect.topLeft() + offset, openIcon.pixmap(iconSize));
}
painter->restore();
@@ -122,7 +122,7 @@ namespace AzToolsFramework
EditorInteractionSystemViewportSelectionRequestBus::Event(
GetEntityContextId(), &EditorInteractionSystemViewportSelection::SetHandler,
[](const EditorVisibleEntityDataCache* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
[](const EditorVisibleEntityDataCacheInterface* entityDataCache, ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
return AZStd::make_unique<EditorPickEntitySelection>(entityDataCache, viewportEditorModeTracker);
});
@@ -90,6 +90,61 @@ namespace UnitTest
return AZStd::string(keyText.toUtf8().data());
}
bool ViewportSettingsTestImpl::GridSnappingEnabled() const
{
return m_gridSnapping;
}
float ViewportSettingsTestImpl::GridSize() const
{
return m_gridSize;
}
bool ViewportSettingsTestImpl::ShowGrid() const
{
return false;
}
bool ViewportSettingsTestImpl::AngleSnappingEnabled() const
{
return m_angularSnapping;
}
float ViewportSettingsTestImpl::AngleStep() const
{
return m_angularStep;
}
float ViewportSettingsTestImpl::ManipulatorLineBoundWidth() const
{
return 0.1f;
}
float ViewportSettingsTestImpl::ManipulatorCircleBoundWidth() const
{
return 0.1f;
}
bool ViewportSettingsTestImpl::StickySelectEnabled() const
{
return m_stickySelect;
}
bool ViewportSettingsTestImpl::IconsVisible() const
{
return m_iconsVisible;
}
bool ViewportSettingsTestImpl::HelpersVisible() const
{
return m_helpersVisible;
}
AZ::Vector3 ViewportSettingsTestImpl::DefaultEditorCameraPosition() const
{
return {};
}
bool TestWidget::eventFilter(QObject* watched, QEvent* event)
{
AZ_UNUSED(watched);
@@ -91,6 +91,43 @@ namespace UnitTest
/// @param modifiers Optional keyboard modifiers to include during the wheel events, defaults to Qt::NoModifier
AZStd::string QtKeyToAzString(Qt::Key key, Qt::KeyboardModifiers modifiers = Qt::NoModifier);
//! Test implementation of the ViewportSettingsRequestBus.
//! @note Can be used to customize viewport settings during test execution.
class ViewportSettingsTestImpl : public AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler
{
public:
void Connect(const AzFramework::ViewportId viewportId)
{
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusConnect(viewportId);
}
void Disconnect()
{
AzToolsFramework::ViewportInteraction::ViewportSettingsRequestBus::Handler::BusDisconnect();
}
// ViewportSettingsRequestBus overrides ...
bool GridSnappingEnabled() const override;
float GridSize() const override;
bool ShowGrid() const override;
bool AngleSnappingEnabled() const override;
float AngleStep() const override;
float ManipulatorLineBoundWidth() const override;
float ManipulatorCircleBoundWidth() const override;
bool StickySelectEnabled() const override;
AZ::Vector3 DefaultEditorCameraPosition() const override;
bool IconsVisible() const override;
bool HelpersVisible() const override;
float m_gridSize = 1.0f;
float m_angularStep = 0.0f;
bool m_gridSnapping = false;
bool m_angularSnapping = false;
bool m_stickySelect = true;
bool m_iconsVisible = true;
bool m_helpersVisible = true;
};
/// Test widget to store QActions generated by EditorTransformComponentSelection.
class TestWidget : public QWidget
{
@@ -207,7 +244,7 @@ namespace UnitTest
m_editorActions.Connect();
const auto viewportHandlerBuilder =
[this](const AzToolsFramework::EditorVisibleEntityDataCache* entityDataCache,
[this](const AzToolsFramework::EditorVisibleEntityDataCacheInterface* entityDataCache,
[[maybe_unused]] AzToolsFramework::ViewportEditorModeTrackerInterface* viewportEditorModeTracker)
{
// create the default viewport (handles ComponentMode)

Some files were not shown because too many files have changed in this diff Show More