Merge branch 'development' into Atom/guthadam/atomtools_refactor_main
This commit is contained in:
@@ -630,7 +630,7 @@ void EditorViewportWidget::OnEditorNotifyEvent(EEditorNotifyEvent event)
|
||||
|
||||
if (m_renderViewport)
|
||||
{
|
||||
m_renderViewport->GetControllerList()->SetEnabled(true);
|
||||
m_renderViewport->SetInputProcessingEnabled(true);
|
||||
}
|
||||
break;
|
||||
|
||||
@@ -2697,8 +2697,7 @@ void EditorViewportWidget::RestoreViewportAfterGameMode()
|
||||
QString(
|
||||
tr("When leaving \" Game Mode \" the engine will automatically restore your camera position to the default position before you "
|
||||
"had entered Game mode.<br/><br/><small>If you dislike this setting you can always change this anytime in the global "
|
||||
"preferences.</small><br/><br/>"))
|
||||
.arg(EditorPreferencesGeneralRestoreViewportCameraSettingName);
|
||||
"preferences.</small><br/><br/>"));
|
||||
QString restoreOnExitGameModePopupDisabledRegKey("Editor/AutoHide/ViewportCameraRestoreOnExitGameMode");
|
||||
|
||||
// Read the popup disabled registry value
|
||||
|
||||
@@ -1452,7 +1452,7 @@ void SandboxIntegrationManager::ContextMenu_NewEntity()
|
||||
if (view)
|
||||
{
|
||||
const QPoint viewPoint(m_contextMenuViewPoint.GetX(), m_contextMenuViewPoint.GetY());
|
||||
worldPosition = LYVec3ToAZVec3(view->SnapToGrid(view->ViewToWorld(viewPoint)));
|
||||
worldPosition = view->GetHitLocation(viewPoint);
|
||||
}
|
||||
|
||||
CreateNewEntityAtPosition(worldPosition);
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include <QMouseEvent>
|
||||
|
||||
OutlinerTreeView::OutlinerTreeView(QWidget* pParent)
|
||||
: QTreeView(pParent)
|
||||
: AzQtComponents::StyledTreeView(pParent)
|
||||
, m_queuedMouseEvent(nullptr)
|
||||
, m_draggingUnselectedItem(false)
|
||||
{
|
||||
@@ -135,16 +135,12 @@ void OutlinerTreeView::startDrag(Qt::DropActions supportedActions)
|
||||
|
||||
if (!selectionModel()->isSelected(index))
|
||||
{
|
||||
startCustomDrag({ index }, supportedActions);
|
||||
StartCustomDrag({ index }, supportedActions);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectionModel()->selectedIndexes().empty())
|
||||
{
|
||||
startCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
|
||||
return;
|
||||
}
|
||||
StyledTreeView::startDrag(supportedActions);
|
||||
}
|
||||
|
||||
void OutlinerTreeView::dragMoveEvent(QDragMoveEvent* event)
|
||||
@@ -336,14 +332,14 @@ void OutlinerTreeView::processQueuedMousePressedEvent(QMouseEvent* event)
|
||||
QTreeView::mousePressEvent(&mousePressedEvent);
|
||||
}
|
||||
|
||||
void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
void OutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
{
|
||||
m_draggingUnselectedItem = true;
|
||||
|
||||
//sort by container entity depth and order in hierarchy for proper drag image and drop order
|
||||
QModelIndexList indexListSorted = indexList;
|
||||
AZStd::unordered_map<AZ::EntityId, AZStd::list<AZ::u64>> locations;
|
||||
for (auto index : indexListSorted)
|
||||
for (const auto& index : indexListSorted)
|
||||
{
|
||||
AZ::EntityId entityId(index.data(OutlinerListModel::EntityIdRole).value<AZ::u64>());
|
||||
AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]);
|
||||
@@ -356,74 +352,7 @@ void OutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::Dro
|
||||
return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end());
|
||||
});
|
||||
|
||||
//get the data for the unselected item(s)
|
||||
QMimeData* mimeData = model()->mimeData(indexListSorted);
|
||||
if (mimeData)
|
||||
{
|
||||
//initiate drag/drop for the item
|
||||
QDrag* drag = new QDrag(this);
|
||||
drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted)));
|
||||
drag->setMimeData(mimeData);
|
||||
Qt::DropAction defDropAction = Qt::IgnoreAction;
|
||||
if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction()))
|
||||
{
|
||||
defDropAction = defaultDropAction();
|
||||
}
|
||||
else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
|
||||
{
|
||||
defDropAction = Qt::CopyAction;
|
||||
}
|
||||
drag->exec(supportedActions, defDropAction);
|
||||
}
|
||||
}
|
||||
|
||||
QImage OutlinerTreeView::createDragImage(const QModelIndexList& indexList)
|
||||
{
|
||||
//generate a drag image of the item icon and text, normally done internally, and inaccessible
|
||||
QRect rect(0, 0, 0, 0);
|
||||
for (auto index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QRect itemRect = visualRect(index);
|
||||
rect.setHeight(rect.height() + itemRect.height());
|
||||
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
|
||||
}
|
||||
|
||||
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QPainter dragPainter(&dragImage);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
dragPainter.setOpacity(0.35f);
|
||||
dragPainter.fillRect(rect, QColor("#222222"));
|
||||
dragPainter.setOpacity(1.0f);
|
||||
|
||||
int imageY = 0;
|
||||
for (auto index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRect itemRect = visualRect(index);
|
||||
dragPainter.drawPixmap(QPoint(0, imageY),
|
||||
model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
|
||||
dragPainter.setPen(
|
||||
model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
|
||||
dragPainter.setFont(
|
||||
font());
|
||||
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
|
||||
model()->data(index, Qt::DisplayRole).value<QString>());
|
||||
imageY += itemRect.height();
|
||||
}
|
||||
|
||||
dragPainter.end();
|
||||
return dragImage;
|
||||
StyledTreeView::StartCustomDrag(indexListSorted, supportedActions);
|
||||
}
|
||||
|
||||
#include <UI/Outliner/moc_OutlinerTreeView.cpp>
|
||||
|
||||
@@ -15,7 +15,8 @@
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QEvent>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/TreeView.h>
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
@@ -31,7 +32,7 @@ class OutlinerTreeViewModel;
|
||||
//! allow for dragging and dropping of entities from the outliner into the property editor
|
||||
//! of other entities. If the selection updates instantly, this would never be possible.
|
||||
class OutlinerTreeView
|
||||
: public QTreeView
|
||||
: public AzQtComponents::StyledTreeView
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -66,9 +67,7 @@ private:
|
||||
|
||||
void processQueuedMousePressedEvent(QMouseEvent* event);
|
||||
|
||||
void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
|
||||
|
||||
QImage createDragImage(const QModelIndexList& indexList);
|
||||
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
|
||||
|
||||
void DrawLayerUI(QPainter* painter, const QRect& rect, const QModelIndex& index) const;
|
||||
|
||||
|
||||
+24
-18
@@ -46,24 +46,7 @@ void QtViewport::BuildDragDropContext(AzQtComponents::ViewportDragContext& conte
|
||||
|
||||
PreWidgetRendering(); // required so that the current render cam is set.
|
||||
|
||||
Vec3 pos = Vec3(ZERO);
|
||||
HitContext hit;
|
||||
if (HitTest(pt, hit))
|
||||
{
|
||||
pos = hit.raySrc + hit.rayDir * hit.dist;
|
||||
pos = SnapToGrid(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hitTerrain;
|
||||
pos = ViewToWorld(pt, &hitTerrain);
|
||||
if (hitTerrain)
|
||||
{
|
||||
pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y);
|
||||
}
|
||||
pos = SnapToGrid(pos);
|
||||
}
|
||||
context.m_hitLocation = AZ::Vector3(pos.x, pos.y, pos.z);
|
||||
context.m_hitLocation = GetHitLocation(pt);
|
||||
|
||||
PostWidgetRendering();
|
||||
}
|
||||
@@ -1154,6 +1137,29 @@ bool QtViewport::HitTest(const QPoint& point, HitContext& hitInfo)
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Vector3 QtViewport::GetHitLocation(const QPoint& point)
|
||||
{
|
||||
Vec3 pos = Vec3(ZERO);
|
||||
HitContext hit;
|
||||
if (HitTest(point, hit))
|
||||
{
|
||||
pos = hit.raySrc + hit.rayDir * hit.dist;
|
||||
pos = SnapToGrid(pos);
|
||||
}
|
||||
else
|
||||
{
|
||||
bool hitTerrain;
|
||||
pos = ViewToWorld(point, &hitTerrain);
|
||||
if (hitTerrain)
|
||||
{
|
||||
pos.z = GetIEditor()->GetTerrainElevation(pos.x, pos.y);
|
||||
}
|
||||
pos = SnapToGrid(pos);
|
||||
}
|
||||
|
||||
return AZ::Vector3(pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void QtViewport::SetZoomFactor(float fZoomFactor)
|
||||
{
|
||||
|
||||
@@ -201,6 +201,7 @@ public:
|
||||
|
||||
//! Performs hit testing of 2d point in view to find which object hit.
|
||||
virtual bool HitTest(const QPoint& point, HitContext& hitInfo) = 0;
|
||||
virtual AZ::Vector3 GetHitLocation(const QPoint& point) = 0;
|
||||
|
||||
virtual void MakeConstructionPlane(int axis) = 0;
|
||||
|
||||
@@ -436,6 +437,7 @@ public:
|
||||
|
||||
//! Performs hit testing of 2d point in view to find which object hit.
|
||||
bool HitTest(const QPoint& point, HitContext& hitInfo) override;
|
||||
AZ::Vector3 GetHitLocation(const QPoint& point) override;
|
||||
|
||||
//! Do 2D hit testing of line in world space.
|
||||
// pToCameraDistance is an optional output parameter in which distance from the camera to the line is returned.
|
||||
|
||||
@@ -10,6 +10,17 @@
|
||||
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
|
||||
void OnVsyncIntervalChanged(uint32_t const& interval)
|
||||
{
|
||||
AzFramework::WindowNotificationBus::Broadcast(
|
||||
&AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged, AZ::GetClamp(interval, 0u, 4u));
|
||||
}
|
||||
|
||||
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
|
||||
// The value of the vsync interval is constrained between 0 and 4
|
||||
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
|
||||
AZ_CVAR(uint32_t, vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
|
||||
|
||||
namespace AzFramework
|
||||
{
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -122,6 +133,16 @@ namespace AzFramework
|
||||
return m_pimpl->GetDpiScaleFactor();
|
||||
}
|
||||
|
||||
uint32_t NativeWindow::GetDisplayRefreshRate() const
|
||||
{
|
||||
return m_pimpl->GetDisplayRefreshRate();
|
||||
}
|
||||
|
||||
uint32_t NativeWindow::GetSyncInterval() const
|
||||
{
|
||||
return vsync_interval;
|
||||
}
|
||||
|
||||
/*static*/ bool NativeWindow::GetFullScreenStateOfDefaultWindow()
|
||||
{
|
||||
NativeWindowHandle defaultWindowHandle = nullptr;
|
||||
@@ -240,4 +261,10 @@ namespace AzFramework
|
||||
return 1.0f;
|
||||
}
|
||||
|
||||
uint32_t NativeWindow::Implementation::GetDisplayRefreshRate() const
|
||||
{
|
||||
// Default to 60
|
||||
return 60;
|
||||
}
|
||||
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -130,6 +130,8 @@ namespace AzFramework
|
||||
bool CanToggleFullScreenState() const override;
|
||||
void ToggleFullScreenState() override;
|
||||
float GetDpiScaleFactor() const override;
|
||||
uint32_t GetSyncInterval() const override;
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
|
||||
//! Get the full screen state of the default window.
|
||||
//! \return True if the default window is currently in full screen, false otherwise.
|
||||
@@ -172,6 +174,7 @@ namespace AzFramework
|
||||
virtual void SetFullScreenState(bool fullScreenState);
|
||||
virtual bool CanToggleFullScreenState() const;
|
||||
virtual float GetDpiScaleFactor() const;
|
||||
virtual uint32_t GetDisplayRefreshRate() const;
|
||||
|
||||
protected:
|
||||
uint32_t m_width = 0;
|
||||
|
||||
@@ -74,6 +74,12 @@ namespace AzFramework
|
||||
//! to a "standard" value of 96, the default for Windows in a DPI unaware setting. This can
|
||||
//! be used to scale user interface elements to ensure legibility on high density displays.
|
||||
virtual float GetDpiScaleFactor() const = 0;
|
||||
|
||||
//! Returns the sync interval which tells the drivers the number of v-blanks to synchronize with
|
||||
virtual uint32_t GetSyncInterval() const = 0;
|
||||
|
||||
//! Returns the refresh rate of the main display
|
||||
virtual uint32_t GetDisplayRefreshRate() const = 0;
|
||||
};
|
||||
using WindowRequestBus = AZ::EBus<WindowRequests>;
|
||||
|
||||
@@ -101,6 +107,9 @@ namespace AzFramework
|
||||
|
||||
//! This is called when vsync interval is changed.
|
||||
virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); };
|
||||
|
||||
//! This is called if the main display's refresh rate changes
|
||||
virtual void OnRefreshRateChanged([[maybe_unused]] uint32_t refreshRate) {}
|
||||
};
|
||||
using WindowNotificationBus = AZ::EBus<WindowNotifications>;
|
||||
|
||||
|
||||
+6
-1
@@ -25,7 +25,7 @@ namespace AzFramework
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks) override;
|
||||
NativeWindowHandle GetWindowHandle() const override;
|
||||
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
private:
|
||||
ANativeWindow* m_nativeWindow = nullptr;
|
||||
};
|
||||
@@ -55,4 +55,9 @@ namespace AzFramework
|
||||
return reinterpret_cast<NativeWindowHandle>(m_nativeWindow);
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Android::GetDisplayRefreshRate() const
|
||||
{
|
||||
// Using 60 for now until proper support is added
|
||||
return 60;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -23,6 +23,7 @@ namespace AzFramework
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks) override;
|
||||
NativeWindowHandle GetWindowHandle() const override;
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
};
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
@@ -44,4 +45,9 @@ namespace AzFramework
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Linux::GetDisplayRefreshRate() const
|
||||
{
|
||||
//Using 60 for now until proper support is added
|
||||
return 60;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
@@ -34,12 +34,14 @@ namespace AzFramework
|
||||
bool GetFullScreenState() const override;
|
||||
void SetFullScreenState(bool fullScreenState) override;
|
||||
bool CanToggleFullScreenState() const override { return true; }
|
||||
uint32_t GetMainDisplayRefreshRate() const;
|
||||
|
||||
private:
|
||||
static NSWindowStyleMask ConvertToNSWindowStyleMask(const WindowStyleMasks& styleMasks);
|
||||
|
||||
NSWindow* m_nativeWindow;
|
||||
NSString* m_windowTitle;
|
||||
uint32_t m_mainDisplayRefreshRate = 0;
|
||||
};
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
@@ -76,6 +78,17 @@ namespace AzFramework
|
||||
// Make the window active
|
||||
[m_nativeWindow makeKeyAndOrderFront:nil];
|
||||
m_nativeWindow.title = m_windowTitle;
|
||||
|
||||
CGDirectDisplayID display = CGMainDisplayID();
|
||||
CGDisplayModeRef currentMode = CGDisplayCopyDisplayMode(display);
|
||||
m_mainDisplayRefreshRate = CGDisplayModeGetRefreshRate(currentMode);
|
||||
|
||||
// Assume 60hz if 0 is returned.
|
||||
// This can happen on OSX. In future we can hopefully use maximumFramesPerSecond which wont have this issue
|
||||
if (m_mainDisplayRefreshRate == 0)
|
||||
{
|
||||
m_mainDisplayRefreshRate = 60;
|
||||
}
|
||||
}
|
||||
|
||||
NativeWindowHandle NativeWindowImpl_Darwin::GetWindowHandle() const
|
||||
@@ -128,4 +141,9 @@ namespace AzFramework
|
||||
const NSWindowStyleMask defaultMask = NSWindowStyleMaskResizable | NSWindowStyleMaskTitled | NSWindowStyleMaskClosable | NSWindowStyleMaskMiniaturizable;
|
||||
return nativeMask ? nativeMask : defaultMask;
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Darwin::GetMainDisplayRefreshRate() const
|
||||
{
|
||||
return m_mainDisplayRefreshRate;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
+3
-1
@@ -117,9 +117,11 @@ namespace AzFramework
|
||||
, m_hasFocus(false)
|
||||
, m_hasTextEntryStarted(false)
|
||||
{
|
||||
static const char* s_keyboardCountEnvironmentVarName = "InputDeviceKeyboardInstanceCount";
|
||||
s_instanceCount = AZ::Environment::FindVariable<int>(s_keyboardCountEnvironmentVarName);
|
||||
if (!s_instanceCount)
|
||||
{
|
||||
s_instanceCount = AZ::Environment::CreateVariable<int>("InputDeviceKeyboardInstanceCount", 1);
|
||||
s_instanceCount = AZ::Environment::CreateVariable<int>(s_keyboardCountEnvironmentVarName, 1);
|
||||
|
||||
// Register for raw keyboard input
|
||||
RAWINPUTDEVICE rawInputDevice;
|
||||
|
||||
+3
-1
@@ -138,9 +138,11 @@ namespace AzFramework
|
||||
{
|
||||
memset(&m_lastClientRect, 0, sizeof(m_lastClientRect));
|
||||
|
||||
static const char* s_mouseCountEnvironmentVarName = "InputDeviceMouseInstanceCount";
|
||||
s_instanceCount = AZ::Environment::FindVariable<int>(s_mouseCountEnvironmentVarName);
|
||||
if (!s_instanceCount)
|
||||
{
|
||||
s_instanceCount = AZ::Environment::CreateVariable<int>("InputDeviceMouseInstanceCount", 1);
|
||||
s_instanceCount = AZ::Environment::CreateVariable<int>(s_mouseCountEnvironmentVarName, 1);
|
||||
|
||||
// Register for raw mouse input
|
||||
RAWINPUTDEVICE rawInputDevice;
|
||||
|
||||
+20
@@ -37,6 +37,7 @@ namespace AzFramework
|
||||
void SetFullScreenState(bool fullScreenState) override;
|
||||
bool CanToggleFullScreenState() const override { return true; }
|
||||
float GetDpiScaleFactor() const override;
|
||||
uint32_t GetDisplayRefreshRate() const override;
|
||||
|
||||
private:
|
||||
static DWORD ConvertToWin32WindowStyleMask(const WindowStyleMasks& styleMasks);
|
||||
@@ -56,6 +57,7 @@ namespace AzFramework
|
||||
|
||||
using GetDpiForWindowType = UINT(HWND hwnd);
|
||||
GetDpiForWindowType* m_getDpiFunction = nullptr;
|
||||
uint32_t m_mainDisplayRefreshRate = 0;
|
||||
};
|
||||
|
||||
const wchar_t* NativeWindowImpl_Win32::s_defaultClassName = L"O3DEWin32Class";
|
||||
@@ -144,6 +146,10 @@ namespace AzFramework
|
||||
{
|
||||
SetWindowLongPtr(m_win32Handle, GWLP_USERDATA, reinterpret_cast<LONG_PTR>(this));
|
||||
}
|
||||
|
||||
DEVMODE DisplayConfig;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig);
|
||||
m_mainDisplayRefreshRate = DisplayConfig.dmDisplayFrequency;
|
||||
}
|
||||
|
||||
void NativeWindowImpl_Win32::Activate()
|
||||
@@ -263,6 +269,15 @@ namespace AzFramework
|
||||
WindowNotificationBus::Event(nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnDpiScaleFactorChanged, newScaleFactor);
|
||||
break;
|
||||
}
|
||||
case WM_WINDOWPOSCHANGED:
|
||||
{
|
||||
DEVMODE DisplayConfig;
|
||||
EnumDisplaySettings(NULL, ENUM_CURRENT_SETTINGS, &DisplayConfig);
|
||||
uint32_t refreshRate = DisplayConfig.dmDisplayFrequency;
|
||||
WindowNotificationBus::Event(
|
||||
nativeWindowImpl->GetWindowHandle(), &WindowNotificationBus::Events::OnRefreshRateChanged, refreshRate);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
return DefWindowProc(hWnd, message, wParam, lParam);
|
||||
break;
|
||||
@@ -367,6 +382,11 @@ namespace AzFramework
|
||||
return aznumeric_cast<float>(dotsPerInch) / aznumeric_cast<float>(defaultDotsPerInch);
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Win32::GetDisplayRefreshRate() const
|
||||
{
|
||||
return m_mainDisplayRefreshRate;
|
||||
}
|
||||
|
||||
void NativeWindowImpl_Win32::EnterBorderlessWindowFullScreen()
|
||||
{
|
||||
if (m_isInBorderlessWindowFullScreenState)
|
||||
|
||||
@@ -27,9 +27,11 @@ namespace AzFramework
|
||||
const WindowGeometry& geometry,
|
||||
const WindowStyleMasks& styleMasks) override;
|
||||
NativeWindowHandle GetWindowHandle() const override;
|
||||
|
||||
uint32_t GetMainDisplayRefreshRate() const;
|
||||
|
||||
private:
|
||||
UIWindow* m_nativeWindow;
|
||||
uint32_t m_mainDisplayRefreshRate = 0;
|
||||
};
|
||||
|
||||
NativeWindow::Implementation* NativeWindow::Implementation::Create()
|
||||
@@ -56,6 +58,7 @@ namespace AzFramework
|
||||
|
||||
m_width = geometry.m_width;
|
||||
m_height = geometry.m_height;
|
||||
m_mainDisplayRefreshRate = [[UIScreen mainScreen] maximumFramesPerSecond];
|
||||
}
|
||||
|
||||
NativeWindowHandle NativeWindowImpl_Ios::GetWindowHandle() const
|
||||
@@ -63,5 +66,9 @@ namespace AzFramework
|
||||
return m_nativeWindow;
|
||||
}
|
||||
|
||||
uint32_t NativeWindowImpl_Ios::GetMainDisplayRefreshRate() const
|
||||
{
|
||||
return m_mainDisplayRefreshRate;
|
||||
}
|
||||
} // namespace AzFramework
|
||||
|
||||
|
||||
@@ -8,10 +8,13 @@
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/TreeView.h>
|
||||
|
||||
#include <QDrag>
|
||||
#include <QEvent>
|
||||
#include <QSettings>
|
||||
#include <QPainter>
|
||||
|
||||
#include <AzCore/std/algorithm.h>
|
||||
|
||||
#include <AzQtComponents/Components/Style.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/ConfigHelpers.h>
|
||||
@@ -252,5 +255,109 @@ namespace AzQtComponents
|
||||
return qobject_cast<QTreeView*>(widget) && !qobject_cast<TableView*>(widget);
|
||||
}
|
||||
|
||||
StyledTreeView::StyledTreeView(QWidget* parent)
|
||||
: QTreeView(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void StyledTreeView::startDrag(Qt::DropActions supportedActions)
|
||||
{
|
||||
if (!selectionModel()->selectedIndexes().empty())
|
||||
{
|
||||
StartCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
|
||||
}
|
||||
}
|
||||
|
||||
void StyledTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
{
|
||||
StartCustomDragInternal(this, indexList, supportedActions);
|
||||
}
|
||||
|
||||
void StyledTreeView::StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
{
|
||||
QMimeData* mimeData = itemView->model()->mimeData(indexList);
|
||||
if (mimeData)
|
||||
{
|
||||
QDrag* drag = new QDrag(itemView);
|
||||
drag->setPixmap(QPixmap::fromImage(CreateDragImage(itemView, indexList)));
|
||||
drag->setMimeData(mimeData);
|
||||
|
||||
Qt::DropAction defDropAction = Qt::IgnoreAction;
|
||||
if (itemView->defaultDropAction() != Qt::IgnoreAction && (supportedActions & itemView->defaultDropAction()))
|
||||
{
|
||||
defDropAction = itemView->defaultDropAction();
|
||||
}
|
||||
else if (supportedActions & Qt::CopyAction && itemView->dragDropMode() != QAbstractItemView::InternalMove)
|
||||
{
|
||||
defDropAction = Qt::CopyAction;
|
||||
}
|
||||
|
||||
drag->exec(supportedActions, defDropAction);
|
||||
}
|
||||
}
|
||||
|
||||
QImage StyledTreeView::CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList)
|
||||
{
|
||||
// Generate a drag image of the item icon and text, normally done internally, and inaccessible
|
||||
QRect rect(0, 0, 0, 0);
|
||||
for (const auto& index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRect itemRect = itemView->visualRect(index);
|
||||
rect.setHeight(rect.height() + itemRect.height());
|
||||
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
|
||||
}
|
||||
|
||||
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QPainter dragPainter(&dragImage);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
dragPainter.setOpacity(0.35f);
|
||||
dragPainter.fillRect(rect, QColor("#222222"));
|
||||
dragPainter.setOpacity(1.0f);
|
||||
|
||||
int imageY = 0;
|
||||
for (const auto& index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRect itemRect = itemView->visualRect(index);
|
||||
dragPainter.drawPixmap(QPoint(0, imageY),
|
||||
itemView->model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
|
||||
dragPainter.setPen(
|
||||
itemView->model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
|
||||
dragPainter.setFont(
|
||||
itemView->font());
|
||||
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
|
||||
itemView->model()->data(index, Qt::DisplayRole).value<QString>());
|
||||
imageY += itemRect.height();
|
||||
}
|
||||
|
||||
dragPainter.end();
|
||||
return dragImage;
|
||||
}
|
||||
|
||||
StyledTreeWidget::StyledTreeWidget(QWidget* parent)
|
||||
: QTreeWidget(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void StyledTreeWidget::startDrag(Qt::DropActions supportedActions)
|
||||
{
|
||||
if (!selectionModel()->selectedIndexes().empty())
|
||||
{
|
||||
StyledTreeView::StartCustomDragInternal(this, selectionModel()->selectedIndexes(), supportedActions);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace AzQtComponents
|
||||
#include <Components/Widgets/moc_TreeView.cpp>
|
||||
|
||||
@@ -9,8 +9,11 @@
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
#include <AzQtComponents/AzQtComponentsAPI.h>
|
||||
#include <AzQtComponents/Components/Widgets/TableView.h>
|
||||
|
||||
#include <QTreeWidget>
|
||||
#endif
|
||||
|
||||
namespace AzQtComponents
|
||||
@@ -68,4 +71,46 @@ namespace AzQtComponents
|
||||
void updateEditorGeometry(QWidget* editor, const QStyleOptionViewItem& option, const QModelIndex& index) const override;
|
||||
};
|
||||
|
||||
//! For most of the custom QTreeView styling, we override in AzQtComponents::Style class,
|
||||
//! but there are some cases (e.g. drag/drop) that can only be overriden by an actual
|
||||
//! subclass of the QTreeView
|
||||
class AZ_QT_COMPONENTS_API StyledTreeView
|
||||
: public QTreeView
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(StyledTreeView, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit StyledTreeView(QWidget* parent = nullptr);
|
||||
|
||||
//! NOTE: QTreeWidget derives from QTreeView, but because we need a custom dervied class
|
||||
//! of QTreeView, then we can't inherit our custom drag methods in our custom derived
|
||||
//! class of QTreeWidget, so these functions are made static so they can be shared
|
||||
static void StartCustomDragInternal(QAbstractItemView* itemView, const QModelIndexList& indexList, Qt::DropActions supportedActions);
|
||||
static QImage CreateDragImage(QAbstractItemView* itemView, const QModelIndexList& indexList);
|
||||
|
||||
protected:
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
|
||||
virtual void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
|
||||
};
|
||||
|
||||
//! For most of the custom QTreeWidget styling, we override in AzQtComponents::Style class,
|
||||
//! but there are some cases (e.g. drag/drop) that can only be overriden by an actual
|
||||
//! subclass of the QTreeWidget.
|
||||
class AZ_QT_COMPONENTS_API StyledTreeWidget
|
||||
: public QTreeWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
AZ_CLASS_ALLOCATOR(StyledTreeWidget, AZ::SystemAllocator, 0);
|
||||
|
||||
explicit StyledTreeWidget(QWidget* parent = nullptr);
|
||||
|
||||
protected:
|
||||
void startDrag(Qt::DropActions supportedActions) override;
|
||||
};
|
||||
|
||||
} // namespace AzQtComponents
|
||||
|
||||
+6
-78
@@ -27,7 +27,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
EntityOutlinerTreeView::EntityOutlinerTreeView(QWidget* pParent)
|
||||
: QTreeView(pParent)
|
||||
: AzQtComponents::StyledTreeView(pParent)
|
||||
, m_queuedMouseEvent(nullptr)
|
||||
, m_draggingUnselectedItem(false)
|
||||
{
|
||||
@@ -144,16 +144,12 @@ namespace AzToolsFramework
|
||||
|
||||
if (!selectionModel()->isSelected(index))
|
||||
{
|
||||
startCustomDrag({ index }, supportedActions);
|
||||
StartCustomDrag({ index }, supportedActions);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectionModel()->selectedIndexes().empty())
|
||||
{
|
||||
startCustomDrag(selectionModel()->selectedIndexes(), supportedActions);
|
||||
return;
|
||||
}
|
||||
StyledTreeView::startDrag(supportedActions);
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::dragMoveEvent(QDragMoveEvent* event)
|
||||
@@ -243,14 +239,14 @@ namespace AzToolsFramework
|
||||
QTreeView::mousePressEvent(&mousePressedEvent);
|
||||
}
|
||||
|
||||
void EntityOutlinerTreeView::startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
void EntityOutlinerTreeView::StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions)
|
||||
{
|
||||
m_draggingUnselectedItem = true;
|
||||
|
||||
//sort by container entity depth and order in hierarchy for proper drag image and drop order
|
||||
QModelIndexList indexListSorted = indexList;
|
||||
AZStd::unordered_map<AZ::EntityId, AZStd::list<AZ::u64>> locations;
|
||||
for (auto index : indexListSorted)
|
||||
for (const auto& index : indexListSorted)
|
||||
{
|
||||
AZ::EntityId entityId(index.data(EntityOutlinerListModel::EntityIdRole).value<AZ::u64>());
|
||||
AzToolsFramework::GetEntityLocationInHierarchy(entityId, locations[entityId]);
|
||||
@@ -263,76 +259,8 @@ namespace AzToolsFramework
|
||||
return AZStd::lexicographical_compare(locationsE1.begin(), locationsE1.end(), locationsE2.begin(), locationsE2.end());
|
||||
});
|
||||
|
||||
//get the data for the unselected item(s)
|
||||
QMimeData* mimeData = model()->mimeData(indexListSorted);
|
||||
if (mimeData)
|
||||
{
|
||||
//initiate drag/drop for the item
|
||||
QDrag* drag = new QDrag(this);
|
||||
drag->setPixmap(QPixmap::fromImage(createDragImage(indexListSorted)));
|
||||
drag->setMimeData(mimeData);
|
||||
Qt::DropAction defDropAction = Qt::IgnoreAction;
|
||||
if (defaultDropAction() != Qt::IgnoreAction && (supportedActions & defaultDropAction()))
|
||||
{
|
||||
defDropAction = defaultDropAction();
|
||||
}
|
||||
else if (supportedActions & Qt::CopyAction && dragDropMode() != QAbstractItemView::InternalMove)
|
||||
{
|
||||
defDropAction = Qt::CopyAction;
|
||||
}
|
||||
drag->exec(supportedActions, defDropAction);
|
||||
}
|
||||
StyledTreeView::StartCustomDrag(indexListSorted, supportedActions);
|
||||
}
|
||||
|
||||
QImage EntityOutlinerTreeView::createDragImage(const QModelIndexList& indexList)
|
||||
{
|
||||
//generate a drag image of the item icon and text, normally done internally, and inaccessible
|
||||
QRect rect(0, 0, 0, 0);
|
||||
for (auto index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
QRect itemRect = visualRect(index);
|
||||
rect.setHeight(rect.height() + itemRect.height());
|
||||
rect.setWidth(AZStd::GetMax(rect.width(), itemRect.width()));
|
||||
}
|
||||
|
||||
QImage dragImage(rect.size(), QImage::Format_ARGB32_Premultiplied);
|
||||
|
||||
QPainter dragPainter(&dragImage);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_Source);
|
||||
dragPainter.fillRect(dragImage.rect(), Qt::transparent);
|
||||
dragPainter.setCompositionMode(QPainter::CompositionMode_SourceOver);
|
||||
dragPainter.setOpacity(0.35f);
|
||||
dragPainter.fillRect(rect, QColor("#222222"));
|
||||
dragPainter.setOpacity(1.0f);
|
||||
|
||||
int imageY = 0;
|
||||
for (auto index : indexList)
|
||||
{
|
||||
if (index.column() != 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
QRect itemRect = visualRect(index);
|
||||
dragPainter.drawPixmap(QPoint(0, imageY),
|
||||
model()->data(index, Qt::DecorationRole).value<QIcon>().pixmap(QSize(16, 16)));
|
||||
dragPainter.setPen(
|
||||
model()->data(index, Qt::ForegroundRole).value<QBrush>().color());
|
||||
dragPainter.setFont(
|
||||
font());
|
||||
dragPainter.drawText(QRect(20, imageY, rect.width() - 20, rect.height()),
|
||||
model()->data(index, Qt::DisplayRole).value<QString>());
|
||||
imageY += itemRect.height();
|
||||
}
|
||||
|
||||
dragPainter.end();
|
||||
return dragImage;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#include <UI/Outliner/moc_EntityOutlinerTreeView.cpp>
|
||||
|
||||
+4
-5
@@ -14,7 +14,8 @@
|
||||
|
||||
#include <QBasicTimer>
|
||||
#include <QEvent>
|
||||
#include <QTreeView>
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/TreeView.h>
|
||||
#endif
|
||||
|
||||
#pragma once
|
||||
@@ -33,7 +34,7 @@ namespace AzToolsFramework
|
||||
//! allow for dragging and dropping of entities from the outliner into the property editor
|
||||
//! of other entities. If the selection updates instantly, this would never be possible.
|
||||
class EntityOutlinerTreeView
|
||||
: public QTreeView
|
||||
: public AzQtComponents::StyledTreeView
|
||||
{
|
||||
Q_OBJECT;
|
||||
public:
|
||||
@@ -68,9 +69,7 @@ namespace AzToolsFramework
|
||||
|
||||
void processQueuedMousePressedEvent(QMouseEvent* event);
|
||||
|
||||
void startCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions);
|
||||
|
||||
QImage createDragImage(const QModelIndexList& indexList);
|
||||
void StartCustomDrag(const QModelIndexList& indexList, Qt::DropActions supportedActions) override;
|
||||
|
||||
void PaintBranchBackground(QPainter* painter, const QRect& rect, const QModelIndex& index) const;
|
||||
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace GridMate
|
||||
{
|
||||
|
||||
@@ -7,6 +7,7 @@
|
||||
*/
|
||||
|
||||
#include <unistd.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
namespace GridMate
|
||||
{
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <O3DEApplication_Mac.h>
|
||||
#include <../Common/Apple/Launcher_Apple.h>
|
||||
#include <../Common/UnixLike/Launcher_UnixLike.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
|
||||
#if AZ_TESTS_ENABLED
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
|
||||
#include <CryCommon/CryLibrary.h>
|
||||
#include <AzCore/Math/Vector2.h>
|
||||
#include <AzCore/Memory/SystemAllocator.h>
|
||||
|
||||
int APIENTRY WinMain([[maybe_unused]] HINSTANCE hInstance, [[maybe_unused]] HINSTANCE hPrevInstance, [[maybe_unused]] LPSTR lpCmdLine, [[maybe_unused]] int nCmdShow)
|
||||
{
|
||||
|
||||
@@ -226,6 +226,21 @@ typedef uint64 __uint64;
|
||||
|
||||
#define _PTRDIFF_T_DEFINED 1
|
||||
|
||||
typedef union _LARGE_INTEGER
|
||||
{
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
};
|
||||
struct
|
||||
{
|
||||
DWORD LowPart;
|
||||
LONG HighPart;
|
||||
} u;
|
||||
long long QuadPart;
|
||||
} LARGE_INTEGER;
|
||||
|
||||
#define _A_RDONLY (0x01) /* Read only file */
|
||||
#define _A_HIDDEN (0x02) /* Hidden file */
|
||||
#define _A_SUBDIR (0x10) /* Subdirectory */
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <AzCore/PlatformDef.h>
|
||||
#include <AzCore/PlatformIncl.h>
|
||||
#include <AzCore/Module/Environment.h>
|
||||
|
||||
#define INJECT_ENVIRONMENT_FUNCTION "InjectEnvironment"
|
||||
|
||||
@@ -26,4 +26,6 @@
|
||||
|
||||
typedef uint64_t threadID;
|
||||
|
||||
#define VK_CONTROL 0
|
||||
|
||||
#endif // CRYINCLUDE_CRYCOMMON_MACSPECIFIC_H
|
||||
|
||||
@@ -121,12 +121,6 @@ namespace AzTestRunner
|
||||
{
|
||||
const char* cwd = AzTestRunner::get_current_working_directory();
|
||||
std::cout << "cwd = " << cwd << std::endl;
|
||||
|
||||
for (int i = 0; i < argc; i++)
|
||||
{
|
||||
std::cout << "arg[" << i << "] " << argv[i] << std::endl;
|
||||
}
|
||||
|
||||
std::cout << "LIB: " << lib << std::endl;
|
||||
}
|
||||
|
||||
@@ -227,6 +221,12 @@ namespace AzTestRunner
|
||||
testMainFunction.reset();
|
||||
}
|
||||
|
||||
// Construct a retry command if the test fails
|
||||
if (result != 0)
|
||||
{
|
||||
std::cout << "Retry command: " << std::endl << argv[0] << " " << lib << " " << symbol << std::endl;
|
||||
}
|
||||
|
||||
// unload and reset the module here, because it needs to release resources that were used / activated in
|
||||
// system allocator / etc.
|
||||
module.reset();
|
||||
|
||||
@@ -39,7 +39,7 @@ namespace O3DE::ProjectManager
|
||||
NewProjectSettingsScreen::NewProjectSettingsScreen(QWidget* parent)
|
||||
: ProjectSettingsScreen(parent)
|
||||
{
|
||||
const QString defaultName{ "NewProject" };
|
||||
const QString defaultName = GetDefaultProjectName();
|
||||
const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + defaultName);
|
||||
|
||||
m_projectName->lineEdit()->setText(defaultName);
|
||||
@@ -162,6 +162,17 @@ namespace O3DE::ProjectManager
|
||||
return defaultPath;
|
||||
}
|
||||
|
||||
QString NewProjectSettingsScreen::GetDefaultProjectName()
|
||||
{
|
||||
return "NewProject";
|
||||
}
|
||||
|
||||
QString NewProjectSettingsScreen::GetProjectAutoPath()
|
||||
{
|
||||
const QString projectName = m_projectName->lineEdit()->text();
|
||||
return QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + projectName);
|
||||
}
|
||||
|
||||
ProjectManagerScreen NewProjectSettingsScreen::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::NewProjectSettings;
|
||||
@@ -260,4 +271,22 @@ namespace O3DE::ProjectManager
|
||||
m_projectTemplateButtonGroup->blockSignals(false);
|
||||
}
|
||||
}
|
||||
void NewProjectSettingsScreen::OnProjectNameUpdated()
|
||||
{
|
||||
if (ValidateProjectName() && !m_userChangedProjectPath)
|
||||
{
|
||||
m_projectPath->setText(GetProjectAutoPath());
|
||||
}
|
||||
}
|
||||
|
||||
void NewProjectSettingsScreen::OnProjectPathUpdated()
|
||||
{
|
||||
const QString defaultPath = QDir::toNativeSeparators(GetDefaultProjectPath() + "/" + GetDefaultProjectName());
|
||||
const QString autoPath = GetProjectAutoPath();
|
||||
const QString path = m_projectPath->lineEdit()->text();
|
||||
m_userChangedProjectPath = path != defaultPath && path != autoPath;
|
||||
|
||||
ValidateProjectPath();
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -40,8 +40,14 @@ namespace O3DE::ProjectManager
|
||||
signals:
|
||||
void OnTemplateSelectionChanged(int oldIndex, int newIndex);
|
||||
|
||||
protected:
|
||||
void OnProjectNameUpdated() override;
|
||||
void OnProjectPathUpdated() override;
|
||||
|
||||
private:
|
||||
QString GetDefaultProjectName();
|
||||
QString GetDefaultProjectPath();
|
||||
QString GetProjectAutoPath();
|
||||
QFrame* CreateTemplateDetails(int margin);
|
||||
void UpdateTemplateDetails(const ProjectTemplateInfo& templateInfo);
|
||||
|
||||
@@ -51,6 +57,7 @@ namespace O3DE::ProjectManager
|
||||
TagContainerWidget* m_templateIncludedGems;
|
||||
QVector<ProjectTemplateInfo> m_templates;
|
||||
int m_selectedTemplateIndex = -1;
|
||||
bool m_userChangedProjectPath = false;
|
||||
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_templateDetailsContentMargin = 20;
|
||||
|
||||
@@ -40,12 +40,11 @@ namespace O3DE::ProjectManager
|
||||
m_verticalLayout->setAlignment(Qt::AlignTop);
|
||||
|
||||
m_projectName = new FormLineEditWidget(tr("Project name"), "", this);
|
||||
connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::ValidateProjectName);
|
||||
connect(m_projectName->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectNameUpdated);
|
||||
m_verticalLayout->addWidget(m_projectName);
|
||||
|
||||
m_projectPath = new FormFolderBrowseEditWidget(tr("Project Location"), "", this);
|
||||
m_projectPath->lineEdit()->setReadOnly(true);
|
||||
connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::Validate);
|
||||
connect(m_projectPath->lineEdit(), &QLineEdit::textChanged, this, &ProjectSettingsScreen::OnProjectPathUpdated);
|
||||
m_verticalLayout->addWidget(m_projectPath);
|
||||
|
||||
projectSettingsFrame->setLayout(m_verticalLayout);
|
||||
@@ -110,28 +109,36 @@ namespace O3DE::ProjectManager
|
||||
m_projectName->setErrorLabelVisible(!projectNameIsValid);
|
||||
return projectNameIsValid;
|
||||
}
|
||||
|
||||
bool ProjectSettingsScreen::ValidateProjectPath()
|
||||
{
|
||||
bool projectPathIsValid = true;
|
||||
if (m_projectPath->lineEdit()->text().isEmpty())
|
||||
QDir path(m_projectPath->lineEdit()->text());
|
||||
if (!path.isAbsolute())
|
||||
{
|
||||
projectPathIsValid = false;
|
||||
m_projectPath->setErrorLabelText(tr("Please provide a valid location."));
|
||||
m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location."));
|
||||
}
|
||||
else
|
||||
else if (path.exists() && !path.isEmpty())
|
||||
{
|
||||
QDir path(m_projectPath->lineEdit()->text());
|
||||
if (path.exists() && !path.isEmpty())
|
||||
{
|
||||
projectPathIsValid = false;
|
||||
m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location."));
|
||||
}
|
||||
projectPathIsValid = false;
|
||||
m_projectPath->setErrorLabelText(tr("This folder exists and isn't empty. Please choose a different location."));
|
||||
}
|
||||
|
||||
m_projectPath->setErrorLabelVisible(!projectPathIsValid);
|
||||
return projectPathIsValid;
|
||||
}
|
||||
|
||||
void ProjectSettingsScreen::OnProjectNameUpdated()
|
||||
{
|
||||
ValidateProjectName();
|
||||
}
|
||||
|
||||
void ProjectSettingsScreen::OnProjectPathUpdated()
|
||||
{
|
||||
Validate();
|
||||
}
|
||||
|
||||
bool ProjectSettingsScreen::Validate()
|
||||
{
|
||||
return ValidateProjectName() && ValidateProjectPath();
|
||||
|
||||
@@ -33,10 +33,13 @@ namespace O3DE::ProjectManager
|
||||
virtual bool Validate();
|
||||
|
||||
protected slots:
|
||||
virtual bool ValidateProjectName();
|
||||
virtual bool ValidateProjectPath();
|
||||
virtual void OnProjectNameUpdated();
|
||||
virtual void OnProjectPathUpdated();
|
||||
|
||||
protected:
|
||||
bool ValidateProjectName();
|
||||
virtual bool ValidateProjectPath();
|
||||
|
||||
QString GetDefaultProjectPath();
|
||||
|
||||
QHBoxLayout* m_horizontalLayout;
|
||||
|
||||
@@ -108,10 +108,11 @@ namespace O3DE::ProjectManager
|
||||
bool UpdateProjectSettingsScreen::ValidateProjectPath()
|
||||
{
|
||||
bool projectPathIsValid = true;
|
||||
if (m_projectPath->lineEdit()->text().isEmpty())
|
||||
QDir path(m_projectPath->lineEdit()->text());
|
||||
if (!path.isAbsolute())
|
||||
{
|
||||
projectPathIsValid = false;
|
||||
m_projectPath->setErrorLabelText(tr("Please provide a valid location."));
|
||||
m_projectPath->setErrorLabelText(tr("Please provide an absolute path for the project location."));
|
||||
}
|
||||
|
||||
m_projectPath->setErrorLabelVisible(!projectPathIsValid);
|
||||
|
||||
+1
-1
@@ -230,7 +230,7 @@ namespace TestImpact
|
||||
processInFlight.m_process = LaunchProcess(AZStd::move(processInfo));
|
||||
processInFlight.m_startTime = createTime;
|
||||
}
|
||||
catch (ProcessException& e)
|
||||
catch ([[maybe_unused]] ProcessException& e)
|
||||
{
|
||||
AZ_Warning("ProcessScheduler", false, e.what());
|
||||
createResult = LaunchResult::Failure;
|
||||
|
||||
+1
-1
@@ -169,7 +169,7 @@ namespace TestImpact
|
||||
WriteFileContents<TestEngineException>(SerializeTestEnumeration(enumeration.value()), jobInfo->GetCache()->m_file);
|
||||
}
|
||||
}
|
||||
catch (const Exception& e)
|
||||
catch ([[maybe_unused]] const Exception& e)
|
||||
{
|
||||
AZ_Warning("Enumerate", false, e.what());
|
||||
enumerations[jobId] = AZStd::nullopt;
|
||||
|
||||
@@ -105,6 +105,8 @@ class ViewEditController(QObject):
|
||||
|
||||
def _create_new_config_file(self) -> None:
|
||||
configuration: Configuration = self._configuration_manager.configuration
|
||||
self._set_default_region(configuration)
|
||||
|
||||
try:
|
||||
new_config_file_path: str = file_utils.join_path(
|
||||
configuration.config_directory, constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME)
|
||||
@@ -117,6 +119,15 @@ class ViewEditController(QObject):
|
||||
|
||||
self._rescan_config_directory()
|
||||
|
||||
def _set_default_region(self, configuration: Configuration):
|
||||
default_region = configuration.region
|
||||
if not default_region or default_region == 'aws-global':
|
||||
self.set_notification_frame_text_sender.emit(
|
||||
notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE)
|
||||
logger.warning(notification_label_text.VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE)
|
||||
|
||||
configuration.region = constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION
|
||||
|
||||
def _delete_table_row(self) -> None:
|
||||
indices: List[QModelIndex] = self._table_view.selectedIndexes()
|
||||
self._proxy_model.remove_resources(indices)
|
||||
|
||||
@@ -24,6 +24,7 @@ AWS_RESOURCE_REGIONS: List[str] = ["us-east-2", "us-east-1", "us-west-1", "us-we
|
||||
# Default client&server config file name
|
||||
RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX: str = "_aws_resource_mappings.json"
|
||||
RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME: str = "default" + RESOURCE_MAPPING_CONFIG_FILE_NAME_SUFFIX
|
||||
RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION: str = "us-east-1"
|
||||
|
||||
# View related constants
|
||||
SEARCH_TYPED_RESOURCES_VERSION: str = "Import AWS Resources"
|
||||
|
||||
@@ -5,6 +5,8 @@ For complete copyright and license terms please see the LICENSE at the root of t
|
||||
SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
"""
|
||||
|
||||
from model import constants
|
||||
|
||||
NOTIFICATION_LOADING_MESSAGE: str = "Loading..."
|
||||
|
||||
ERROR_PAGE_OK_TEXT: str = "OK"
|
||||
@@ -21,6 +23,12 @@ VIEW_EDIT_PAGE_RESCAN_TEXT: str = "Rescan"
|
||||
VIEW_EDIT_PAGE_CONFIG_FILES_PLACEHOLDER_TEXT: str = "Found {} config files"
|
||||
VIEW_EDIT_PAGE_SEARCH_PLACEHOLDER_TEXT: str = "Search by Key Name, Type, Name/ID, Account ID or Region"
|
||||
VIEW_EDIT_PAGE_IMPORT_RESOURCES_PLACEHOLDER_TEXT: str = "Import Additional Resources"
|
||||
VIEW_EDIT_PAGE_CREATE_NEW_CONFIG_FILE_NO_DEFAULT_REGION_MESSAGE: str = \
|
||||
f"Resource mapping file {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_NAME} is created"\
|
||||
f" with {constants.RESOURCE_MAPPING_DEFAULT_CONFIG_FILE_REGION} as the default region. "\
|
||||
f"See <a href=\"https://docs.o3de.org/docs/user-guide/gems/reference/aws/aws-core/configuring-credentials/\">"\
|
||||
f"<span style=\"color:#4A90E2;\">documentation</span></a> "\
|
||||
f"for configuring the AWS credentials and default region."
|
||||
|
||||
VIEW_EDIT_PAGE_SELECT_CONFIG_FILE_MESSAGE: str = "Please select the Config file you would like to view and modify..."
|
||||
VIEW_EDIT_PAGE_NO_CONFIG_FILE_FOUND_MESSAGE: str = \
|
||||
|
||||
+2
-1
@@ -482,6 +482,7 @@ class TestViewEditController(TestCase):
|
||||
mock_json_utils.create_empty_resource_mapping_file.assert_called_once()
|
||||
mock_file_utils.find_files_with_suffix_under_directory.assert_called_once()
|
||||
self._mocked_view_edit_page.set_config_files.assert_called_with(expected_config_files)
|
||||
self._test_view_edit_controller.set_notification_frame_text_sender.emit.assert_called_once()
|
||||
|
||||
@patch("controller.view_edit_controller.file_utils")
|
||||
@patch("controller.view_edit_controller.json_utils")
|
||||
@@ -496,7 +497,7 @@ class TestViewEditController(TestCase):
|
||||
mock_file_utils.join_path.assert_called_once()
|
||||
mock_json_utils.create_empty_resource_mapping_file.assert_called_once()
|
||||
mock_file_utils.find_files_with_suffix_under_directory.assert_not_called()
|
||||
self._test_view_edit_controller.set_notification_frame_text_sender.emit.assert_called_once()
|
||||
assert len(self._test_view_edit_controller.set_notification_frame_text_sender.emit.mock_calls) == 2
|
||||
|
||||
@patch("controller.view_edit_controller.file_utils")
|
||||
def test_page_rescan_button_post_notification_when_find_files_throw_exception(
|
||||
|
||||
@@ -42,4 +42,4 @@ namespace AWSGameLift
|
||||
};
|
||||
}// namespace AWSGameLift
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Client, AWSGameLift::AWSGameLiftClientModule)
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Clients, AWSGameLift::AWSGameLiftClientModule)
|
||||
|
||||
@@ -42,4 +42,4 @@ namespace AWSGameLift
|
||||
};
|
||||
}// namespace AWSGameLift
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Server, AWSGameLift::AWSGameLiftServerModule)
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_AWSGameLift_Servers, AWSGameLift::AWSGameLiftServerModule)
|
||||
|
||||
@@ -125,7 +125,6 @@ namespace AZ
|
||||
Format GetNearestSupportedFormat(Format requestedFormat, FormatCapabilities requestedCapabilities) const;
|
||||
|
||||
//! Small API to support getting supported/working swapchain formats for a window.
|
||||
//! [GFX TODO]ATOM-1125] [RHI] Device::GetValidSwapChainImageFormats()
|
||||
//! Returns the set of supported formats for swapchain images.
|
||||
virtual AZStd::vector<Format> GetValidSwapChainImageFormats(const WindowHandle& windowHandle) const;
|
||||
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace Aftermath
|
||||
#if defined(USE_NSIGHT_AFTERMATH)
|
||||
AZStd::vector<GFSDK_Aftermath_ContextHandle> cntxtHandles = static_cast<GpuCrashTracker*>(crashTracker)->GetContextHandles();
|
||||
GFSDK_Aftermath_ContextData* outContextData = new GFSDK_Aftermath_ContextData[cntxtHandles.size()];
|
||||
GFSDK_Aftermath_Result result = GFSDK_Aftermath_GetData(cntxtHandles.size(), cntxtHandles.data(), outContextData);
|
||||
GFSDK_Aftermath_Result result = GFSDK_Aftermath_GetData(static_cast<uint32_t>(cntxtHandles.size()), cntxtHandles.data(), outContextData);
|
||||
AssertOnError(result);
|
||||
for (int i = 0; i < cntxtHandles.size(); i++)
|
||||
{
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Metal
|
||||
|
||||
@@ -5,6 +5,8 @@
|
||||
* SPDX-License-Identifier: Apache-2.0 OR MIT
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Metal
|
||||
|
||||
@@ -77,7 +77,6 @@ namespace AZ
|
||||
|
||||
m_samplerCache = [[NSCache alloc]init];
|
||||
[m_samplerCache setName:@"SamplerCache"];
|
||||
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
#include <Atom/RHI/CpuProfiler.h>
|
||||
#include <RHI/Device.h>
|
||||
#include <RHI/Image.h>
|
||||
@@ -74,21 +75,16 @@ namespace AZ
|
||||
AddSubView();
|
||||
}
|
||||
|
||||
m_refreshRate = Platform::GetRefreshRate();
|
||||
|
||||
//Assume 60hz if 0 is returned.
|
||||
//Internal OSX displays have 'flexible' refresh rates, with a max of 60Hz - but report 0hz
|
||||
if (m_refreshRate < 0.1f)
|
||||
{
|
||||
m_refreshRate = 60.0f;
|
||||
}
|
||||
|
||||
m_drawables.resize(descriptor.m_dimensions.m_imageCount);
|
||||
|
||||
if (nativeDimensions)
|
||||
{
|
||||
*nativeDimensions = descriptor.m_dimensions;
|
||||
}
|
||||
|
||||
AzFramework::WindowRequestBus::EventResult(
|
||||
m_refreshRate, m_nativeWindow, &AzFramework::WindowRequestBus::Events::GetDisplayRefreshRate);
|
||||
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
|
||||
@@ -160,7 +156,10 @@ namespace AZ
|
||||
const uint32_t currentImageIndex = GetCurrentImageIndex();
|
||||
|
||||
//Preset the drawable
|
||||
Platform::PresentInternal(m_mtlCommandBuffer, m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval, m_refreshRate);
|
||||
Platform::PresentInternal(
|
||||
m_mtlCommandBuffer,
|
||||
m_drawables[currentImageIndex], GetDescriptor().m_verticalSyncInterval,
|
||||
m_refreshRate);
|
||||
|
||||
[m_drawables[currentImageIndex] release];
|
||||
m_drawables[currentImageIndex] = nil;
|
||||
|
||||
@@ -53,7 +53,7 @@ namespace AZ
|
||||
id<MTLDevice> m_mtlDevice = nil;
|
||||
NativeWindowType* m_nativeWindow = nullptr;
|
||||
AZStd::vector<id<CAMetalDrawable>> m_drawables;
|
||||
float m_refreshRate = 0.0f;
|
||||
uint32_t m_refreshRate = 0;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -117,6 +117,35 @@ namespace AZ
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::MultiSampleReadOnly2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_4_BIT;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::MultiSampleReadOnly2D)].m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)] = {};
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_name = "NULL_DESCRIPTOR_GENERAL_ARRAY_2D";
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_usageFlagBits =VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_arrayLayers = 1;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_imageCreateFlagBits = VkImageCreateFlagBits(0);
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralArray2D)].m_dimension = imageDimension;
|
||||
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)] = m_imageNullDescriptor.m_images[static_cast<uint32_t>(NullDescriptorManager::ImageTypes::GeneralArray2D)];
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_name = "NULL_DESCRIPTOR_READONLY_ARRAY_2D";
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_format = VK_FORMAT_R8G8B8A8_SRGB;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_usageFlagBits = VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT);
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_arrayLayers = 1;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_imageCreateFlagBits = VkImageCreateFlagBits(0);
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::ReadOnlyArray2D)].m_dimension = imageDimension;
|
||||
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)] = m_imageNullDescriptor.m_images[static_cast<uint32_t>(NullDescriptorManager::ImageTypes::General2D)];
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_name = "NULL_DESCRIPTOR_STORAGE_ARRAY_2D";
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_sampleCountFlag = VK_SAMPLE_COUNT_1_BIT;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_format = VK_FORMAT_R32G32B32A32_UINT;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_usageFlagBits = VkImageUsageFlagBits(VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_STORAGE_BIT);
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_arrayLayers = 1;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_layout = VK_IMAGE_LAYOUT_GENERAL;
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::StorageArray2D)].m_dimension = 256;
|
||||
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralCube)] = m_imageNullDescriptor.m_images[static_cast<uint32_t>(NullDescriptorManager::ImageTypes::General2D)];
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralCube)].m_name = "NULL_DESCRIPTOR_GENERAL_CUBE";
|
||||
m_imageNullDescriptor.m_images[static_cast<uint32_t>(ImageTypes::GeneralCube)].m_arrayLayers = 6;
|
||||
@@ -243,6 +272,10 @@ namespace AZ
|
||||
{
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_3D;
|
||||
}
|
||||
else if (imageIndex >= static_cast<uint32_t>(ImageTypes::GeneralArray2D) && imageIndex <= static_cast<uint32_t>(ImageTypes::StorageArray2D))
|
||||
{
|
||||
imageViewCreateInfo.viewType = VK_IMAGE_VIEW_TYPE_2D_ARRAY;
|
||||
}
|
||||
|
||||
result = vkCreateImageView(device.GetNativeDevice(), &imageViewCreateInfo, nullptr, &m_imageNullDescriptor.m_images[imageIndex].m_view);
|
||||
RETURN_RESULT_IF_UNSUCCESSFUL(ConvertResult(result));
|
||||
@@ -366,7 +399,7 @@ namespace AZ
|
||||
|
||||
VkDescriptorImageInfo NullDescriptorManager::GetDescriptorImageInfo(RHI::ShaderInputImageType imageType, bool storageImage)
|
||||
{
|
||||
if (imageType == RHI::ShaderInputImageType::Image2D || imageType == RHI::ShaderInputImageType::Image2DArray)
|
||||
if (imageType == RHI::ShaderInputImageType::Image2D)
|
||||
{
|
||||
if (storageImage)
|
||||
{
|
||||
@@ -377,6 +410,17 @@ namespace AZ
|
||||
return GetImage(ImageTypes::ReadOnly2D);
|
||||
}
|
||||
}
|
||||
else if (imageType == RHI::ShaderInputImageType::Image2DArray)
|
||||
{
|
||||
if (storageImage)
|
||||
{
|
||||
return GetImage(ImageTypes::StorageArray2D);
|
||||
}
|
||||
else
|
||||
{
|
||||
return GetImage(ImageTypes::ReadOnlyArray2D);
|
||||
}
|
||||
}
|
||||
else if (imageType == RHI::ShaderInputImageType::Image2DMultisample)
|
||||
{
|
||||
if (storageImage)
|
||||
|
||||
@@ -30,6 +30,11 @@ namespace AZ
|
||||
MultiSampleGeneral2D,
|
||||
MultiSampleReadOnly2D,
|
||||
|
||||
// 2d image arrays
|
||||
GeneralArray2D,
|
||||
ReadOnlyArray2D,
|
||||
StorageArray2D,
|
||||
|
||||
// cube images
|
||||
GeneralCube,
|
||||
ReadOnlyCube,
|
||||
|
||||
@@ -17,19 +17,6 @@
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Math/MathUtils.h>
|
||||
|
||||
|
||||
void OnVsyncIntervalChanged(uint32_t const& interval)
|
||||
{
|
||||
AzFramework::WindowNotificationBus::Broadcast(
|
||||
&AzFramework::WindowNotificationBus::Events::OnVsyncIntervalChanged,
|
||||
AZ::GetClamp(interval, 0u, 4u));
|
||||
}
|
||||
|
||||
// NOTE: On change, broadcasts the new requested vsync interval to all windows.
|
||||
// The value of the vsync interval is constrained between 0 and 4
|
||||
// Vsync intervals greater than 1 are not currently supported on the Vulkan RHI (see #2061 for discussion)
|
||||
AZ_CVAR(uint32_t, rpi_vsync_interval, 1, OnVsyncIntervalChanged, AZ::ConsoleFunctorFlags::Null, "Set swapchain vsync interval");
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace RPI
|
||||
@@ -158,9 +145,13 @@ namespace AZ
|
||||
|
||||
const RHI::WindowHandle windowHandle = RHI::WindowHandle(reinterpret_cast<uintptr_t>(m_windowHandle));
|
||||
|
||||
uint32_t syncInterval = 1;
|
||||
AzFramework::WindowRequestBus::EventResult(
|
||||
syncInterval, m_windowHandle, &AzFramework::WindowRequestBus::Events::GetSyncInterval);
|
||||
|
||||
RHI::SwapChainDescriptor descriptor;
|
||||
descriptor.m_window = windowHandle;
|
||||
descriptor.m_verticalSyncInterval = rpi_vsync_interval;
|
||||
descriptor.m_verticalSyncInterval = syncInterval;
|
||||
descriptor.m_dimensions.m_imageWidth = width;
|
||||
descriptor.m_dimensions.m_imageHeight = height;
|
||||
descriptor.m_dimensions.m_imageCount = 3;
|
||||
|
||||
+2
@@ -121,6 +121,8 @@ namespace AtomToolsFramework
|
||||
bool CanToggleFullScreenState() const override;
|
||||
void ToggleFullScreenState() override;
|
||||
float GetDpiScaleFactor() const override;
|
||||
uint32_t GetSyncInterval() const override;
|
||||
uint32_t GetDisplayRefreshRate() const;
|
||||
|
||||
protected:
|
||||
// AzFramework::InputChannelEventListener ...
|
||||
|
||||
@@ -465,4 +465,14 @@ namespace AtomToolsFramework
|
||||
{
|
||||
return aznumeric_cast<float>(devicePixelRatioF());
|
||||
}
|
||||
|
||||
uint32_t RenderViewportWidget::GetDisplayRefreshRate() const
|
||||
{
|
||||
return 60;
|
||||
}
|
||||
|
||||
uint32_t RenderViewportWidget::GetSyncInterval() const
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
} //namespace AtomToolsFramework
|
||||
|
||||
+1
-1
@@ -28,7 +28,7 @@ namespace EMStudio
|
||||
setWindowTitle("Notification");
|
||||
|
||||
// window, no border, no focus, stays on top
|
||||
setWindowFlags(Qt::Popup | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus);
|
||||
setWindowFlags(Qt::Window | Qt::FramelessWindowHint | Qt::WindowDoesNotAcceptFocus | Qt::WindowStaysOnTopHint);
|
||||
|
||||
// enable the translucent background
|
||||
setAttribute(Qt::WA_TranslucentBackground);
|
||||
|
||||
@@ -90,6 +90,11 @@ namespace EditorPythonBindings
|
||||
PythonSymbolEventBus::Handler::BusConnect();
|
||||
EditorPythonBindingsNotificationBus::Handler::BusConnect();
|
||||
AZ::Interface<AzToolsFramework::EditorPythonConsoleInterface>::Register(this);
|
||||
|
||||
if (PythonSymbolEventBus::GetTotalNumOfEventHandlers() > 1)
|
||||
{
|
||||
OnPostInitialize();
|
||||
}
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::Deactivate()
|
||||
@@ -111,6 +116,7 @@ namespace EditorPythonBindings
|
||||
m_basePath = pythonSymbolsPath;
|
||||
}
|
||||
EditorPythonBindingsNotificationBus::Handler::BusDisconnect();
|
||||
PythonSymbolEventBus::ExecuteQueuedEvents();
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::WriteMethod(AZ::IO::HandleType handle, AZStd::string_view methodName, const AZ::BehaviorMethod& behaviorMethod, const AZ::BehaviorClass* behaviorClass)
|
||||
@@ -206,12 +212,12 @@ namespace EditorPythonBindings
|
||||
AZ::IO::FileIOBase::GetInstance()->Write(handle, buffer.c_str(), buffer.size());
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass)
|
||||
void PythonLogSymbolsComponent::LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass)
|
||||
{
|
||||
LogClassWithName(moduleName, behaviorClass, behaviorClass->m_name.c_str());
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className)
|
||||
void PythonLogSymbolsComponent::LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className)
|
||||
{
|
||||
Internal::FileHandle fileHandle(OpenModuleAt(moduleName));
|
||||
if (fileHandle.IsValid())
|
||||
@@ -255,7 +261,11 @@ namespace EditorPythonBindings
|
||||
}
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod)
|
||||
void PythonLogSymbolsComponent::LogClassMethod(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string globalMethodName,
|
||||
const AZ::BehaviorClass* behaviorClass,
|
||||
const AZ::BehaviorMethod* behaviorMethod)
|
||||
{
|
||||
AZ_UNUSED(behaviorClass);
|
||||
Internal::FileHandle fileHandle(OpenModuleAt(moduleName));
|
||||
@@ -265,7 +275,7 @@ namespace EditorPythonBindings
|
||||
}
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus)
|
||||
void PythonLogSymbolsComponent::LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus)
|
||||
{
|
||||
if (behaviorEBus->m_events.empty())
|
||||
{
|
||||
@@ -404,7 +414,7 @@ namespace EditorPythonBindings
|
||||
}
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod)
|
||||
void PythonLogSymbolsComponent::LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod)
|
||||
{
|
||||
Internal::FileHandle fileHandle(OpenModuleAt(moduleName));
|
||||
if (fileHandle.IsValid())
|
||||
@@ -428,7 +438,10 @@ namespace EditorPythonBindings
|
||||
}
|
||||
}
|
||||
|
||||
void PythonLogSymbolsComponent::LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty)
|
||||
void PythonLogSymbolsComponent::LogGlobalProperty(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string propertyName,
|
||||
const AZ::BehaviorProperty* behaviorProperty)
|
||||
{
|
||||
if (!behaviorProperty->m_getter || !behaviorProperty->m_getter->GetResult())
|
||||
{
|
||||
|
||||
@@ -51,12 +51,19 @@ namespace EditorPythonBindings
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// PythonSymbolEventBus::Handler
|
||||
void LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass) override;
|
||||
void LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className) override;
|
||||
void LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod) override;
|
||||
void LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus) override;
|
||||
void LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) override;
|
||||
void LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) override;
|
||||
void LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass) override;
|
||||
void LogClassWithName(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass, const AZStd::string className) override;
|
||||
void LogClassMethod(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string globalMethodName,
|
||||
const AZ::BehaviorClass* behaviorClass,
|
||||
const AZ::BehaviorMethod* behaviorMethod) override;
|
||||
void LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus) override;
|
||||
void LogGlobalMethod(const AZStd::string moduleName, const AZStd::string methodName, const AZ::BehaviorMethod* behaviorMethod) override;
|
||||
void LogGlobalProperty(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string propertyName,
|
||||
const AZ::BehaviorProperty* behaviorProperty) override;
|
||||
void Finalize() override;
|
||||
AZStd::string FetchPythonTypeName(const AZ::BehaviorParameter& param) override;
|
||||
|
||||
|
||||
@@ -394,7 +394,7 @@ namespace EditorPythonBindings
|
||||
|
||||
// log the bus symbol
|
||||
AZStd::string subModuleName = pybind11::cast<AZStd::string>(thisBusModule.attr("__name__"));
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogBus, subModuleName, ebusName, behaviorEBus);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogBus, subModuleName, ebusName, behaviorEBus);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -756,7 +756,7 @@ namespace EditorPythonBindings
|
||||
}
|
||||
|
||||
AZStd::string subModuleName = pybind11::cast<AZStd::string>(subModule.attr("__name__"));
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClassMethod, subModuleName, globalMethodName, behaviorClass, behaviorMethod);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClassMethod, subModuleName, globalMethodName, behaviorClass, behaviorMethod);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -782,7 +782,7 @@ namespace EditorPythonBindings
|
||||
pybind11::setattr(subModule, constantPropertyName.c_str(), constantValue);
|
||||
|
||||
AZStd::string subModuleName = pybind11::cast<AZStd::string>(subModule.attr("__name__"));
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, constantPropertyName, behaviorProperty);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, constantPropertyName, behaviorProperty);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -809,11 +809,11 @@ namespace EditorPythonBindings
|
||||
{
|
||||
return ConstructPythonProxyObjectByTypename(behaviorClassName, pythonArgs);
|
||||
});
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClassWithName, subModuleName, behaviorClass, properSyntax);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClassWithName, subModuleName, behaviorClass, properSyntax);
|
||||
}
|
||||
else
|
||||
{
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogClass, subModuleName, behaviorClass);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogClass, subModuleName, behaviorClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -153,7 +153,7 @@ namespace EditorPythonBindings
|
||||
StaticPropertyHolderMapEntry& entry = iter->second;
|
||||
entry.second->AddProperty(propertyName, behaviorProperty);
|
||||
}
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, scopeName, propertyName, behaviorProperty);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, scopeName, propertyName, behaviorProperty);
|
||||
}
|
||||
|
||||
pybind11::module DetermineScope(pybind11::module scope, const AZStd::string& fullName)
|
||||
@@ -302,7 +302,7 @@ namespace EditorPythonBindings
|
||||
|
||||
// log global method symbol
|
||||
AZStd::string subModuleName = pybind11::cast<AZStd::string>(targetModule.attr("__name__"));
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalMethod, subModuleName, methodName, behaviorMethod);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalMethod, subModuleName, methodName, behaviorMethod);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -325,7 +325,7 @@ namespace EditorPythonBindings
|
||||
|
||||
// log global property symbol
|
||||
AZStd::string subModuleName = pybind11::cast<AZStd::string>(globalsModule.attr("__name__"));
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, propertyName, behaviorProperty);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::LogGlobalProperty, subModuleName, propertyName, behaviorProperty);
|
||||
|
||||
if (behaviorProperty->m_getter && behaviorProperty->m_setter)
|
||||
{
|
||||
@@ -377,7 +377,7 @@ namespace EditorPythonBindings
|
||||
PythonProxyBusManagement::CreateSubmodule(parentModule);
|
||||
Internal::RegisterPaths(parentModule);
|
||||
|
||||
PythonSymbolEventBus::Broadcast(&PythonSymbolEventBus::Events::Finalize);
|
||||
PythonSymbolEventBus::QueueBroadcast(&PythonSymbolEventBus::Events::Finalize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,14 @@
|
||||
|
||||
#include <AzCore/EBus/EBus.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class BehaviorClass;
|
||||
class BehaviorMethod;
|
||||
class BehaviorEBus;
|
||||
class BehaviorProperty;
|
||||
}
|
||||
|
||||
namespace EditorPythonBindings
|
||||
{
|
||||
//! An interface to track exported Python symbols
|
||||
@@ -16,23 +24,39 @@ namespace EditorPythonBindings
|
||||
: public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
// the symbols will be written out in the future
|
||||
static const bool EnableEventQueue = true;
|
||||
|
||||
//! logs a behavior class type
|
||||
virtual void LogClass(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass) = 0;
|
||||
virtual void LogClass(const AZStd::string moduleName, const AZ::BehaviorClass* behaviorClass) = 0;
|
||||
|
||||
//! logs a behavior class type with an override to its name
|
||||
virtual void LogClassWithName(AZStd::string_view moduleName, AZ::BehaviorClass* behaviorClass, AZStd::string_view className) = 0;
|
||||
virtual void LogClassWithName(
|
||||
const AZStd::string moduleName,
|
||||
const AZ::BehaviorClass* behaviorClass,
|
||||
const AZStd::string className) = 0;
|
||||
|
||||
//! logs a static class method with a specified global method name
|
||||
virtual void LogClassMethod(AZStd::string_view moduleName, AZStd::string_view globalMethodName, AZ::BehaviorClass* behaviorClass, AZ::BehaviorMethod* behaviorMethod) = 0;
|
||||
virtual void LogClassMethod(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string globalMethodName,
|
||||
const AZ::BehaviorClass* behaviorClass,
|
||||
const AZ::BehaviorMethod* behaviorMethod) = 0;
|
||||
|
||||
//! logs a behavior bus with a specified bus name
|
||||
virtual void LogBus(AZStd::string_view moduleName, AZStd::string_view busName, AZ::BehaviorEBus* behaviorEBus) = 0;
|
||||
virtual void LogBus(const AZStd::string moduleName, const AZStd::string busName, const AZ::BehaviorEBus* behaviorEBus) = 0;
|
||||
|
||||
//! logs a global method from the behavior context registry with a specified method name
|
||||
virtual void LogGlobalMethod(AZStd::string_view moduleName, AZStd::string_view methodName, AZ::BehaviorMethod* behaviorMethod) = 0;
|
||||
virtual void LogGlobalMethod(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string methodName,
|
||||
const AZ::BehaviorMethod* behaviorMethod) = 0;
|
||||
|
||||
//! logs a global property, enum, or constant from the behavior context registry with a specified property name
|
||||
virtual void LogGlobalProperty(AZStd::string_view moduleName, AZStd::string_view propertyName, AZ::BehaviorProperty* behaviorProperty) = 0;
|
||||
virtual void LogGlobalProperty(
|
||||
const AZStd::string moduleName,
|
||||
const AZStd::string propertyName,
|
||||
const AZ::BehaviorProperty* behaviorProperty) = 0;
|
||||
|
||||
//! signals the end of the logging of symbols
|
||||
virtual void Finalize() = 0;
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include <EditorPythonBindings/EditorPythonBindingsBus.h>
|
||||
|
||||
#include <Source/PythonCommon.h>
|
||||
#include <Source/PythonSymbolsBus.h>
|
||||
#include <pybind11/pybind11.h>
|
||||
#include <pybind11/embed.h>
|
||||
#include <pybind11/eval.h>
|
||||
@@ -25,6 +26,7 @@
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/std/string/conversions.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
|
||||
@@ -39,7 +41,7 @@
|
||||
|
||||
namespace Platform
|
||||
{
|
||||
// Implemented in each different platform's implentation files, as it differs per platform.
|
||||
// Implemented in each different platform's implementation files, as it differs per platform.
|
||||
bool InsertPythonBinaryLibraryPaths(AZStd::unordered_set<AZStd::string>& paths, const char* pythonPackage, const char* engineRoot);
|
||||
AZStd::string GetPythonHomePath(const char* pythonPackage, const char* engineRoot);
|
||||
}
|
||||
@@ -225,6 +227,37 @@ namespace RedirectOutput
|
||||
|
||||
namespace EditorPythonBindings
|
||||
{
|
||||
// A stand in bus to capture the log symbol queue events
|
||||
// so that when/if the PythonLogSymbolsComponent becomes
|
||||
// active it can write out the python symbols to disk
|
||||
class PythonSystemComponent::SymbolLogHelper final
|
||||
: public PythonSymbolEventBus::Handler
|
||||
{
|
||||
public:
|
||||
SymbolLogHelper()
|
||||
{
|
||||
PythonSymbolEventBus::Handler::BusConnect();
|
||||
}
|
||||
|
||||
~SymbolLogHelper()
|
||||
{
|
||||
PythonSymbolEventBus::ExecuteQueuedEvents();
|
||||
PythonSymbolEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
void LogClass(const AZStd::string, const AZ::BehaviorClass*) override {}
|
||||
void LogClassWithName(const AZStd::string, const AZ::BehaviorClass*, const AZStd::string) override {}
|
||||
void LogClassMethod(
|
||||
const AZStd::string,
|
||||
const AZStd::string,
|
||||
const AZ::BehaviorClass*,
|
||||
const AZ::BehaviorMethod*) override {}
|
||||
void LogBus(const AZStd::string, const AZStd::string, const AZ::BehaviorEBus*) override {}
|
||||
void LogGlobalMethod(const AZStd::string, const AZStd::string, const AZ::BehaviorMethod*) override {}
|
||||
void LogGlobalProperty(const AZStd::string, const AZStd::string, const AZ::BehaviorProperty*) override {}
|
||||
void Finalize() override {}
|
||||
};
|
||||
|
||||
void PythonSystemComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (AZ::SerializeContext* serialize = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
@@ -471,8 +504,6 @@ namespace EditorPythonBindings
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
bool PythonSystemComponent::StartPythonInterpreter(const PythonPathStack& pythonPathStack)
|
||||
{
|
||||
AZStd::unordered_set<AZStd::string> pyPackageSites(pythonPathStack.begin(), pythonPathStack.end());
|
||||
@@ -520,6 +551,11 @@ namespace EditorPythonBindings
|
||||
AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
|
||||
pybind11::gil_scoped_acquire acquire;
|
||||
|
||||
if (EditorPythonBindings::PythonSymbolEventBus::GetTotalNumOfEventHandlers() == 0)
|
||||
{
|
||||
m_symbolLogHelper = AZStd::make_shared<PythonSystemComponent::SymbolLogHelper>();
|
||||
}
|
||||
|
||||
// print Python version using AZ logging
|
||||
const int verRet = PyRun_SimpleStringFlags("import sys \nprint (sys.version) \n", nullptr);
|
||||
AZ_Error("python", verRet == 0, "Error trying to fetch the version number in Python!");
|
||||
|
||||
@@ -59,10 +59,13 @@ namespace EditorPythonBindings
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
class SymbolLogHelper;
|
||||
|
||||
// handle multiple Python initializers and threads
|
||||
AZStd::atomic_int m_initalizeWaiterCount {0};
|
||||
AZStd::semaphore m_initalizeWaiter;
|
||||
AZStd::recursive_mutex m_lock;
|
||||
AZStd::shared_ptr<SymbolLogHelper> m_symbolLogHelper;
|
||||
|
||||
enum class Result
|
||||
{
|
||||
|
||||
@@ -1482,7 +1482,7 @@ bool CUiAnimViewAnimNode::PasteNodesFromClipboard(QWidget* context)
|
||||
const bool bLightAnimationSetActive = GetSequence()->GetFlags() & IUiAnimSequence::eSeqFlags_LightAnimationSet;
|
||||
|
||||
const unsigned int numNodes = animNodesRoot->getChildCount();
|
||||
for (int i = 0; i < numNodes; ++i)
|
||||
for (unsigned int i = 0; i < numNodes; ++i)
|
||||
{
|
||||
XmlNodeRef xmlNode = animNodesRoot->getChild(i);
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
#include <QDragEnterEvent>
|
||||
|
||||
HierarchyWidget::HierarchyWidget(EditorWindow* editorWindow)
|
||||
: QTreeWidget()
|
||||
: AzQtComponents::StyledTreeWidget()
|
||||
, m_isDeleting(false)
|
||||
, m_editorWindow(editorWindow)
|
||||
, m_entityItemMap()
|
||||
@@ -391,7 +391,7 @@ void HierarchyWidget::startDrag(Qt::DropActions supportedActions)
|
||||
// Remember the current selection so that we can revert back to it when the items are dragged back into the hierarchy
|
||||
m_dragSelection = selectedItems();
|
||||
|
||||
QTreeView::startDrag(supportedActions);
|
||||
AzQtComponents::StyledTreeWidget::startDrag(supportedActions);
|
||||
}
|
||||
|
||||
void HierarchyWidget::dragEnterEvent(QDragEnterEvent* event)
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "EditorCommon.h"
|
||||
|
||||
#include <AzQtComponents/Components/Widgets/TreeView.h>
|
||||
|
||||
#include <AzToolsFramework/API/ToolsApplicationAPI.h>
|
||||
#include <AzToolsFramework/ToolsMessaging/EntityHighlightBus.h>
|
||||
|
||||
@@ -19,7 +21,7 @@
|
||||
class QMimeData;
|
||||
|
||||
class HierarchyWidget
|
||||
: public QTreeWidget
|
||||
: public AzQtComponents::StyledTreeWidget
|
||||
, private AzToolsFramework::EditorPickModeNotificationBus::Handler
|
||||
, private AzToolsFramework::EntityHighlightMessages::Bus::Handler
|
||||
{
|
||||
|
||||
@@ -28,4 +28,4 @@ namespace Multiplayer
|
||||
}
|
||||
}
|
||||
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Imgui, Multiplayer::MultiplayerDebugModule);
|
||||
AZ_DECLARE_MODULE_CLASS(Gem_Multiplayer_Debug, Multiplayer::MultiplayerDebugModule);
|
||||
|
||||
@@ -322,11 +322,9 @@ namespace ScriptCanvasEditor
|
||||
return;
|
||||
}
|
||||
|
||||
auto& variableOverrides = parseOutcome.GetValue();
|
||||
|
||||
if (!m_variableOverrides.IsEmpty())
|
||||
{
|
||||
variableOverrides.CopyPreviousOverriddenValues(m_variableOverrides);
|
||||
parseOutcome.GetValue().CopyPreviousOverriddenValues(m_variableOverrides);
|
||||
}
|
||||
|
||||
m_variableOverrides = parseOutcome.TakeValue();
|
||||
@@ -351,8 +349,7 @@ namespace ScriptCanvasEditor
|
||||
}
|
||||
|
||||
auto runtimeComponent = gameEntity->CreateComponent<ScriptCanvas::RuntimeComponent>();
|
||||
auto runtimeOverrides = ConvertToRuntime(m_variableOverrides);
|
||||
runtimeComponent->SetRuntimeDataOverrides(runtimeOverrides);
|
||||
runtimeComponent->TakeRuntimeDataOverrides(ConvertToRuntime(m_variableOverrides));
|
||||
}
|
||||
|
||||
void EditorScriptCanvasComponent::OnCatalogAssetAdded(const AZ::Data::AssetId& assetId)
|
||||
@@ -518,8 +515,8 @@ namespace ScriptCanvasEditor
|
||||
[[maybe_unused]] AZ::Entity* scriptCanvasEntity = assetData->GetScriptCanvasEntity();
|
||||
AZ_Assert(scriptCanvasEntity, "This graph must have a valid entity");
|
||||
BuildGameEntityData();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
UpdateName();
|
||||
AzToolsFramework::ToolsApplicationNotificationBus::Broadcast(&AzToolsFramework::ToolsApplicationEvents::InvalidatePropertyDisplay, AzToolsFramework::Refresh_EntireTree_NewContent);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -283,7 +283,7 @@ namespace ScriptCanvasEditor
|
||||
loadResult.m_runtimeAsset.Get()->GetData().m_debugMap = luaAssetResult.m_debugMap;
|
||||
loadResult.m_runtimeComponent = loadResult.m_entity->CreateComponent<ScriptCanvas::RuntimeComponent>();
|
||||
CopyAssetEntityIdsToOverrides(runtimeDataOverrides);
|
||||
loadResult.m_runtimeComponent->SetRuntimeDataOverrides(runtimeDataOverrides);
|
||||
loadResult.m_runtimeComponent->TakeRuntimeDataOverrides(AZStd::move(runtimeDataOverrides));
|
||||
Execution::Context::InitializeActivationData(loadResult.m_runtimeAsset->GetData());
|
||||
Execution::InitializeInterpretedStatics(loadResult.m_runtimeAsset->GetData());
|
||||
}
|
||||
|
||||
@@ -311,7 +311,7 @@ namespace ScriptCanvasEditor
|
||||
{
|
||||
if (AZStd::wildcard_match("*.scriptcanvas", fullSourceFileName))
|
||||
{
|
||||
return AzToolsFramework::AssetBrowser::SourceFileDetails("Icons/AssetBrowser/ScriptCanvas_16.png");
|
||||
return AzToolsFramework::AssetBrowser::SourceFileDetails("Editor/Icons/AssetBrowser/ScriptCanvas_16.png");
|
||||
}
|
||||
|
||||
// not one of our types.
|
||||
|
||||
@@ -80,12 +80,11 @@ namespace ScriptCanvasEditor
|
||||
GraphCanvas::NodePaletteTreeItem* variablesRoot = root->CreateChildNode<LocalVariablesListNodePaletteTreeItem>("Variables");
|
||||
root->RegisterCategoryNode(variablesRoot, "Variables");
|
||||
|
||||
// We always want to keep these around as place holders
|
||||
GraphCanvas::NodePaletteTreeItem* customEventRoot = root->GetCategoryNode("Script Events");
|
||||
customEventRoot->SetAllowPruneOnEmpty(false);
|
||||
customEventRoot->SetAllowPruneOnEmpty(true);
|
||||
|
||||
GraphCanvas::NodePaletteTreeItem* globalFunctionRoot = root->GetCategoryNode("User Functions");
|
||||
globalFunctionRoot->SetAllowPruneOnEmpty(false);
|
||||
globalFunctionRoot->SetAllowPruneOnEmpty(true);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,7 @@
|
||||
namespace AZ
|
||||
{
|
||||
class ReflectContext;
|
||||
class DatumSerializer;
|
||||
}
|
||||
|
||||
namespace ScriptCanvas
|
||||
@@ -33,6 +34,8 @@ namespace ScriptCanvas
|
||||
/// in the editor, regardless of their actual ScriptCanvas or BehaviorContext type.
|
||||
class Datum final
|
||||
{
|
||||
friend class AZ::DatumSerializer;
|
||||
|
||||
public:
|
||||
AZ_TYPE_INFO(Datum, "{8B836FC0-98A8-4A81-8651-35C7CA125451}");
|
||||
AZ_CLASS_ALLOCATOR(Datum, AZ::SystemAllocator, 0);
|
||||
|
||||
@@ -509,7 +509,8 @@ namespace ScriptCanvas
|
||||
|
||||
bool SubgraphInterface::HasAnyFunctionality() const
|
||||
{
|
||||
return IsActiveDefaultObject() || HasPublicFunctionality();
|
||||
// \todo restore default object addition when ndoes can define an variable, as well
|
||||
return /*IsActiveDefaultObject() || */ HasPublicFunctionality();
|
||||
}
|
||||
|
||||
bool SubgraphInterface::HasBranches() const
|
||||
|
||||
@@ -93,9 +93,9 @@ namespace ScriptCanvas
|
||||
return m_runtimeOverrides;
|
||||
}
|
||||
|
||||
void RuntimeComponent::SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData)
|
||||
void RuntimeComponent::TakeRuntimeDataOverrides(RuntimeDataOverrides&& overrideData)
|
||||
{
|
||||
m_runtimeOverrides = overrideData;
|
||||
m_runtimeOverrides = AZStd::move(overrideData);
|
||||
m_runtimeOverrides.EnforcePreloadBehavior();
|
||||
}
|
||||
|
||||
|
||||
@@ -54,7 +54,7 @@ namespace ScriptCanvas
|
||||
|
||||
const RuntimeDataOverrides& GetRuntimeDataOverrides() const;
|
||||
|
||||
void SetRuntimeDataOverrides(const RuntimeDataOverrides& overrideData);
|
||||
void TakeRuntimeDataOverrides(RuntimeDataOverrides&& overrideData);
|
||||
|
||||
protected:
|
||||
static void GetIncompatibleServices(AZ::ComponentDescriptor::DependencyArrayType& incompatible)
|
||||
|
||||
+3
-3
@@ -10,17 +10,17 @@
|
||||
Category="Nodeables"
|
||||
GeneratePropertyFriend="True"
|
||||
Namespace="ScriptCanvas"
|
||||
Description="Repeats the output signal the given number of times using the specified delay to space the signals out">
|
||||
Description="Repeats the output signal the given number of times using the specified delay to space the signals out.">
|
||||
|
||||
|
||||
<!-- Input tag is for an execution input that has optional data (parameters) -->
|
||||
<Input Name="Start" Description="">
|
||||
<Parameter Name="Repetitions" Type="Data::NumberType" DefaultValue="0.0" Description="How many times to repeat."/>
|
||||
<Parameter Name="Interval" Type="Data::NumberType" DefaultValue="0.0" Description="The Interval between repetitions."/>
|
||||
<Parameter Name="Interval" Type="Data::NumberType" DefaultValue="0.0" Description="The Interval between repetitions. If zero, all repititions execute immediately, before On Start"/>
|
||||
</Input>
|
||||
|
||||
<Output Name="Complete" Description="Signaled upon node exit"/>
|
||||
<Output Name="Action" Description="Signaled every repeition"/>
|
||||
<Output Name="Action" Description="Signaled every repetition"/>
|
||||
|
||||
<PropertyInterface Property="m_timeUnitsInterface" Name="Units" Type="Input" Description="Units to represent the time in."/>
|
||||
|
||||
|
||||
@@ -0,0 +1,178 @@
|
||||
/*
|
||||
* 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 <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <ScriptCanvas/Asset/RuntimeAsset.h>
|
||||
#include <ScriptCanvas/Serialization/DatumSerializer.h>
|
||||
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(DatumSerializer, SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result DatumSerializer::Load
|
||||
( void* outputValue
|
||||
, [[maybe_unused]] const Uuid& outputValueTypeId
|
||||
, const rapidjson::Value& inputValue
|
||||
, JsonDeserializerContext& context)
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
AZ_Assert(outputValueTypeId == azrtti_typeid<Datum>(), "DatumSerializer Load against output typeID that was not Datum");
|
||||
AZ_Assert(outputValue, "DatumSerializer Load against null output");
|
||||
|
||||
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
|
||||
auto outputDatum = reinterpret_cast<Datum*>(outputValue);
|
||||
|
||||
bool isOverloadedStorage = false;
|
||||
AZ_Assert(azrtti_typeid<decltype(outputDatum->m_isOverloadedStorage)>() == azrtti_typeid<decltype(isOverloadedStorage)>()
|
||||
, "overloaded storage type changed and won't load properly");
|
||||
result.Combine(ContinueLoadingFromJsonObjectField
|
||||
( &isOverloadedStorage
|
||||
, azrtti_typeid<decltype(outputDatum->m_isOverloadedStorage)>()
|
||||
, inputValue
|
||||
, "isOverloadedStorage"
|
||||
, context));
|
||||
|
||||
ScriptCanvas::Data::Type scType;
|
||||
AZ_Assert(azrtti_typeid<decltype(outputDatum->m_type)>() == azrtti_typeid<decltype(scType)>()
|
||||
, "ScriptCanvas::Data::Type type changed and won't load properly");
|
||||
result.Combine(ContinueLoadingFromJsonObjectField
|
||||
( &scType
|
||||
, azrtti_typeid<decltype(outputDatum->m_type)>()
|
||||
, inputValue
|
||||
, "scriptCanvasType"
|
||||
, context));
|
||||
|
||||
AZStd::any storage;
|
||||
{ // datum storage begin
|
||||
AZ::Uuid typeId = AZ::Uuid::CreateNull();
|
||||
|
||||
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
|
||||
if (typeIdMember == inputValue.MemberEnd())
|
||||
{
|
||||
return context.Report
|
||||
( JSR::Tasks::ReadField
|
||||
, JSR::Outcomes::Missing
|
||||
, AZStd::string::format("DatumSerializer::Load failed to load the %s member"
|
||||
, JsonSerialization::TypeIdFieldIdentifier));
|
||||
}
|
||||
|
||||
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
|
||||
if (typeId.IsNull())
|
||||
{
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic
|
||||
, "DatumSerializer::Load failed to load the AZ TypeId of the value");
|
||||
}
|
||||
|
||||
storage = context.GetSerializeContext()->CreateAny(typeId);
|
||||
if (storage.empty() || storage.type() != typeId)
|
||||
{
|
||||
return context.Report(result, "DatumSerializer::Load failed to load a value matched the reported AZ TypeId. "
|
||||
"The C++ declaration may have been deleted or changed.");
|
||||
}
|
||||
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&storage), typeId, inputValue, "value", context));
|
||||
} // datum storage end
|
||||
|
||||
AZStd::string label;
|
||||
AZ_Assert(azrtti_typeid<decltype(outputDatum->m_datumLabel)>() == azrtti_typeid<decltype(label)>()
|
||||
, "m_datumLabel type changed and won't load properly");
|
||||
result.Combine(ContinueLoadingFromJsonObjectField
|
||||
( &label
|
||||
, azrtti_typeid<decltype(outputDatum->m_datumLabel)>()
|
||||
, inputValue
|
||||
, "label"
|
||||
, context));
|
||||
|
||||
Datum copy(scType, Datum::eOriginality::Original, AZStd::any_cast<void>(&storage), scType.GetAZType());
|
||||
copy.SetLabel(label);
|
||||
*outputDatum = copy;
|
||||
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "DatumSerializer Load finished loading Datum"
|
||||
: "DatumSerializer Load failed to load Datum");
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result DatumSerializer::Store
|
||||
( rapidjson::Value& outputValue
|
||||
, const void* inputValue
|
||||
, const void* defaultValue
|
||||
, [[maybe_unused]] const Uuid& valueTypeId
|
||||
, JsonSerializerContext& context)
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
AZ_Assert(valueTypeId == azrtti_typeid<Datum>(), "DatumSerializer Store against value typeID that was not Datum");
|
||||
AZ_Assert(inputValue, "DatumSerializer Store against null inputValue pointer ");
|
||||
|
||||
auto inputScriptDataPtr = reinterpret_cast<const Datum*>(inputValue);
|
||||
auto defaultScriptDataPtr = reinterpret_cast<const Datum*>(defaultValue);
|
||||
|
||||
if (defaultScriptDataPtr)
|
||||
{
|
||||
if (*inputScriptDataPtr == *defaultScriptDataPtr)
|
||||
{
|
||||
return context.Report
|
||||
( JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "DatumSerializer Store used defaults for Datum");
|
||||
}
|
||||
}
|
||||
|
||||
JSR::ResultCode result(JSR::Tasks::WriteValue);
|
||||
outputValue.SetObject();
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField
|
||||
( outputValue
|
||||
, "isOverloadedStorage"
|
||||
, &inputScriptDataPtr->m_isOverloadedStorage
|
||||
, defaultScriptDataPtr ? &defaultScriptDataPtr->m_isOverloadedStorage : nullptr
|
||||
, azrtti_typeid<decltype(inputScriptDataPtr->m_isOverloadedStorage)>()
|
||||
, context));
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField
|
||||
( outputValue
|
||||
, "scriptCanvasType"
|
||||
, &inputScriptDataPtr->GetType()
|
||||
, defaultScriptDataPtr ? &defaultScriptDataPtr->GetType() : nullptr
|
||||
, azrtti_typeid<decltype(inputScriptDataPtr->GetType())>()
|
||||
, context));
|
||||
|
||||
{ // datum storage begin
|
||||
{
|
||||
rapidjson::Value typeValue;
|
||||
result.Combine(StoreTypeId(typeValue, inputScriptDataPtr->GetType().GetAZType(), context));
|
||||
outputValue.AddMember
|
||||
( rapidjson::StringRef(JsonSerialization::TypeIdFieldIdentifier)
|
||||
, AZStd::move(typeValue)
|
||||
, context.GetJsonAllocator());
|
||||
}
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField
|
||||
( outputValue
|
||||
, "value"
|
||||
, inputScriptDataPtr->GetAsDanger()
|
||||
, defaultScriptDataPtr ? defaultScriptDataPtr->GetAsDanger() : nullptr
|
||||
, inputScriptDataPtr->GetType().GetAZType()
|
||||
, context));
|
||||
} // datum storage end
|
||||
|
||||
result.Combine(ContinueStoringToJsonObjectField
|
||||
( outputValue
|
||||
, "label"
|
||||
, &inputScriptDataPtr->m_datumLabel
|
||||
, defaultScriptDataPtr ? &defaultScriptDataPtr->m_datumLabel : nullptr
|
||||
, azrtti_typeid<decltype(inputScriptDataPtr->m_datumLabel)>()
|
||||
, context));
|
||||
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "DatumSerializer Store finished saving Datum"
|
||||
: "DatumSerializer Store failed to save Datum");
|
||||
}
|
||||
|
||||
}
|
||||
+2
-2
@@ -14,11 +14,11 @@
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class ScriptUserDataSerializer
|
||||
class DatumSerializer
|
||||
: public BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(ScriptUserDataSerializer, "{7E5FC193-8CDB-4251-A68B-F337027381DF}", BaseJsonSerializer);
|
||||
AZ_RTTI(DatumSerializer, "{FBEBF833-465F-49F4-AFB1-CC9D3B25C16C}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
private:
|
||||
+14
-14
@@ -8,15 +8,15 @@
|
||||
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <ScriptCanvas/Asset/RuntimeAsset.h>
|
||||
#include <ScriptCanvas/Serialization/ScriptUserDataSerializer.h>
|
||||
#include <ScriptCanvas/Serialization/RuntimeVariableSerializer.h>
|
||||
|
||||
using namespace ScriptCanvas;
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
AZ_CLASS_ALLOCATOR_IMPL(ScriptUserDataSerializer, SystemAllocator, 0);
|
||||
AZ_CLASS_ALLOCATOR_IMPL(RuntimeVariableSerializer, SystemAllocator, 0);
|
||||
|
||||
JsonSerializationResult::Result ScriptUserDataSerializer::Load
|
||||
JsonSerializationResult::Result RuntimeVariableSerializer::Load
|
||||
( void* outputValue
|
||||
, [[maybe_unused]] const Uuid& outputValueTypeId
|
||||
, const rapidjson::Value& inputValue
|
||||
@@ -24,8 +24,8 @@ namespace AZ
|
||||
{
|
||||
namespace JSR = JsonSerializationResult;
|
||||
|
||||
AZ_Assert(outputValueTypeId == azrtti_typeid<RuntimeVariable>(), "ScriptUserDataSerializer Load against output typeID that was not RuntimeVariable");
|
||||
AZ_Assert(outputValue, "ScriptUserDataSerializer Load against null output");
|
||||
AZ_Assert(outputValueTypeId == azrtti_typeid<RuntimeVariable>(), "RuntimeVariableSerializer Load against output typeID that was not RuntimeVariable");
|
||||
AZ_Assert(outputValue, "RuntimeVariableSerializer Load against null output");
|
||||
|
||||
auto outputVariable = reinterpret_cast<RuntimeVariable*>(outputValue);
|
||||
JsonSerializationResult::ResultCode result(JSR::Tasks::ReadField);
|
||||
@@ -34,28 +34,28 @@ namespace AZ
|
||||
auto typeIdMember = inputValue.FindMember(JsonSerialization::TypeIdFieldIdentifier);
|
||||
if (typeIdMember == inputValue.MemberEnd())
|
||||
{
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("ScriptUserDataSerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier));
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Missing, AZStd::string::format("RuntimeVariableSerializer::Load failed to load the %s member", JsonSerialization::TypeIdFieldIdentifier));
|
||||
}
|
||||
|
||||
result.Combine(LoadTypeId(typeId, typeIdMember->value, context));
|
||||
if (typeId.IsNull())
|
||||
{
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "ScriptUserDataSerializer::Load failed to load the AZ TypeId of the value");
|
||||
return context.Report(JSR::Tasks::ReadField, JSR::Outcomes::Catastrophic, "RuntimeVariableSerializer::Load failed to load the AZ TypeId of the value");
|
||||
}
|
||||
|
||||
outputVariable->value = context.GetSerializeContext()->CreateAny(typeId);
|
||||
if (outputVariable->value.empty() || outputVariable->value.type() != typeId)
|
||||
{
|
||||
return context.Report(result, "ScriptUserDataSerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed.");
|
||||
return context.Report(result, "RuntimeVariableSerializer::Load failed to load a value matched the reported AZ TypeId. The C++ declaration may have been deleted or changed.");
|
||||
}
|
||||
|
||||
result.Combine(ContinueLoadingFromJsonObjectField(AZStd::any_cast<void>(&outputVariable->value), typeId, inputValue, "value", context));
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "ScriptUserDataSerializer Load finished loading RuntimeVariable"
|
||||
: "ScriptUserDataSerializer Load failed to load RuntimeVariable");
|
||||
? "RuntimeVariableSerializer Load finished loading RuntimeVariable"
|
||||
: "RuntimeVariableSerializer Load failed to load RuntimeVariable");
|
||||
}
|
||||
|
||||
JsonSerializationResult::Result ScriptUserDataSerializer::Store
|
||||
JsonSerializationResult::Result RuntimeVariableSerializer::Store
|
||||
( rapidjson::Value& outputValue
|
||||
, const void* inputValue
|
||||
, const void* defaultValue
|
||||
@@ -79,7 +79,7 @@ namespace AZ
|
||||
|
||||
if (inputDatum == defaultDatum)
|
||||
{
|
||||
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "ScriptUserDataSerializer Store used defaults for RuntimeVariable");
|
||||
return context.Report(JSR::Tasks::WriteValue, JSR::Outcomes::DefaultsUsed, "RuntimeVariableSerializer Store used defaults for RuntimeVariable");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -95,8 +95,8 @@ namespace AZ
|
||||
result.Combine(ContinueStoringToJsonObjectField(outputValue, "value", AZStd::any_cast<void>(inputAnyPtr), AZStd::any_cast<void>(defaultAnyPtr), inputAnyPtr->type(), context));
|
||||
|
||||
return context.Report(result, result.GetProcessing() != JSR::Processing::Halted
|
||||
? "ScriptUserDataSerializer Store finished saving RuntimeVariable"
|
||||
: "ScriptUserDataSerializer Store failed to save RuntimeVariable");
|
||||
? "RuntimeVariableSerializer Store finished saving RuntimeVariable"
|
||||
: "RuntimeVariableSerializer Store failed to save RuntimeVariable");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* 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
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Memory/Memory.h>
|
||||
#include <AzCore/Serialization/Json/BaseJsonSerializer.h>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class RuntimeVariableSerializer
|
||||
: public BaseJsonSerializer
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(RuntimeVariableSerializer, "{7E5FC193-8CDB-4251-A68B-F337027381DF}", BaseJsonSerializer);
|
||||
AZ_CLASS_ALLOCATOR_DECL;
|
||||
|
||||
private:
|
||||
JsonSerializationResult::Result Load
|
||||
( void* outputValue
|
||||
, const Uuid& outputValueTypeId
|
||||
, const rapidjson::Value& inputValue
|
||||
, JsonDeserializerContext& context) override;
|
||||
|
||||
JsonSerializationResult::Result Store
|
||||
( rapidjson::Value& outputValue
|
||||
, const void* inputValue
|
||||
, const void* defaultValue
|
||||
, const Uuid& valueTypeId, JsonSerializerContext& context) override;
|
||||
};
|
||||
}
|
||||
@@ -23,7 +23,8 @@
|
||||
#include <ScriptCanvas/Execution/ExecutionPerformanceTimer.h>
|
||||
#include <ScriptCanvas/Execution/Interpreted/ExecutionInterpretedAPI.h>
|
||||
#include <ScriptCanvas/Execution/RuntimeComponent.h>
|
||||
#include <ScriptCanvas/Serialization/ScriptUserDataSerializer.h>
|
||||
#include <ScriptCanvas/Serialization/RuntimeVariableSerializer.h>
|
||||
#include <ScriptCanvas/Serialization/DatumSerializer.h>
|
||||
#include <ScriptCanvas/SystemComponent.h>
|
||||
#include <ScriptCanvas/Variable/GraphVariableManagerComponent.h>
|
||||
|
||||
@@ -87,8 +88,13 @@ namespace ScriptCanvas
|
||||
|
||||
if (AZ::JsonRegistrationContext* jsonContext = azrtti_cast<AZ::JsonRegistrationContext*>(context))
|
||||
{
|
||||
jsonContext->Serializer<AZ::ScriptUserDataSerializer>()
|
||||
->HandlesType<RuntimeVariable>();
|
||||
jsonContext->Serializer<AZ::RuntimeVariableSerializer>()
|
||||
->HandlesType<RuntimeVariable>()
|
||||
;
|
||||
|
||||
jsonContext->Serializer<AZ::DatumSerializer>()
|
||||
->HandlesType<Datum>()
|
||||
;
|
||||
}
|
||||
|
||||
#if defined(SC_EXECUTION_TRACE_ENABLED)
|
||||
|
||||
@@ -539,8 +539,10 @@ set(FILES
|
||||
Include/ScriptCanvas/Profiler/Aggregator.cpp
|
||||
Include/ScriptCanvas/Profiler/DrillerEvents.h
|
||||
Include/ScriptCanvas/Profiler/DrillerEvents.cpp
|
||||
Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.h
|
||||
Include/ScriptCanvas/Serialization/ScriptUserDataSerializer.cpp
|
||||
Include/ScriptCanvas/Serialization/DatumSerializer.h
|
||||
Include/ScriptCanvas/Serialization/DatumSerializer.cpp
|
||||
Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.h
|
||||
Include/ScriptCanvas/Serialization/RuntimeVariableSerializer.cpp
|
||||
Include/ScriptCanvas/Data/DataTrait.cpp
|
||||
Include/ScriptCanvas/Data/DataTrait.h
|
||||
Include/ScriptCanvas/Data/PropertyTraits.cpp
|
||||
|
||||
@@ -89,7 +89,7 @@
|
||||
"CONFIGURATION": "profile",
|
||||
"SCRIPT_PATH": "scripts/build/TestImpactAnalysis/tiaf_driver.py",
|
||||
"SCRIPT_PARAMETERS":
|
||||
"--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --suite=main --test-failure-policy=continue"
|
||||
"--config=\"!OUTPUT_DIRECTORY!/bin/TestImpactFramework/profile/Persistent/tiaf.json\" --src-branch=!BRANCH_NAME! --dst-branch=!CHANGE_TARGET! --commit=!CHANGE_ID! --s3-bucket=!TEST_IMPACT_S3_BUCKET! --mars-index-prefix=jonawals --s3-top-level-dir=!REPOSITORY_NAME! --build-number=!BUILD_NUMBER! --suite=main --test-failure-policy=continue"
|
||||
}
|
||||
},
|
||||
"debug_vs2019": {
|
||||
|
||||
@@ -14,6 +14,7 @@ import pathlib
|
||||
class Repo:
|
||||
def __init__(self, repo_path: str):
|
||||
self._repo = git.Repo(repo_path)
|
||||
self._remote_url = self._repo.remotes[0].config_reader.get("url")
|
||||
|
||||
# Returns the current branch
|
||||
@property
|
||||
@@ -21,6 +22,11 @@ class Repo:
|
||||
branch = self._repo.active_branch
|
||||
return branch.name
|
||||
|
||||
# Returns the remote URL
|
||||
@property
|
||||
def remote_url(self):
|
||||
return self._remote_url
|
||||
|
||||
def create_diff_file(self, src_commit_hash: str, dst_commit_hash: str, output_path: pathlib.Path, multi_branch: bool):
|
||||
"""
|
||||
Attempts to create a diff from the src and dst commits and write to the specified output file.
|
||||
|
||||
@@ -14,6 +14,7 @@ from tiaf_logger import get_logger
|
||||
logger = get_logger(__file__)
|
||||
|
||||
MARS_JOB_KEY = "job"
|
||||
BUILD_NUMBER_KEY = "build_number"
|
||||
SRC_COMMIT_KEY = "src_commit"
|
||||
DST_COMMIT_KEY = "dst_commit"
|
||||
COMMIT_DISTANCE_KEY = "commit_distance"
|
||||
@@ -175,12 +176,14 @@ def get_duration_in_seconds(duration_in_milliseconds: int):
|
||||
|
||||
return duration_in_milliseconds * 0.001
|
||||
|
||||
def generate_mars_job(tiaf_result, driver_args):
|
||||
def generate_mars_job(tiaf_result, driver_args, build_number: int):
|
||||
"""
|
||||
Generates a MARS job document using the job meta-data used to drive the TIAF sequence.
|
||||
|
||||
@param tiaf_result: The result object generated by the TIAF script.
|
||||
@param driver_args: The arguments specified to the driver script.
|
||||
@param tiaf_result: The result object generated by the TIAF script.
|
||||
@param driver_args: The arguments specified to the driver script.
|
||||
@param driver_args: The arguments specified to the driver script.
|
||||
@param build_number: The build number this job corresponds to.
|
||||
@return: The MARS job document with the job meta-data.
|
||||
"""
|
||||
|
||||
@@ -203,6 +206,7 @@ def generate_mars_job(tiaf_result, driver_args):
|
||||
]}
|
||||
|
||||
mars_job[DRIVER_ARGS_KEY] = driver_args
|
||||
mars_job[BUILD_NUMBER_KEY] = build_number
|
||||
return mars_job
|
||||
|
||||
def generate_test_run_list(test_runs):
|
||||
@@ -418,7 +422,7 @@ def generate_mars_test_targets(sequence_report: dict, mars_job: dict, t0_timesta
|
||||
|
||||
return mars_test_targets
|
||||
|
||||
def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_args: list):
|
||||
def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_args: list, build_number: int):
|
||||
"""
|
||||
Transforms the TIAF result into the appropriate MARS documents and transmits them to MARS.
|
||||
|
||||
@@ -434,7 +438,7 @@ def transmit_report_to_mars(mars_index_prefix: str, tiaf_result: dict, driver_ar
|
||||
t0_timestamp = datetime.datetime.now().timestamp()
|
||||
|
||||
# Generate and transmit the MARS job document
|
||||
mars_job = generate_mars_job(tiaf_result, driver_args)
|
||||
mars_job = generate_mars_job(tiaf_result, driver_args, build_number)
|
||||
filebeat.send_event(mars_job, f"{mars_index_prefix}.tiaf.job")
|
||||
|
||||
if tiaf_result[REPORT_KEY]:
|
||||
|
||||
@@ -161,7 +161,7 @@ class TestImpact:
|
||||
result["change_list"] = self._change_list
|
||||
return result
|
||||
|
||||
def run(self, commit: str, src_branch: str, dst_branch: str, s3_bucket: str, suite: str, test_failure_policy: str, safe_mode: bool, test_timeout: int, global_timeout: int):
|
||||
def run(self, commit: str, src_branch: str, dst_branch: str, s3_bucket: str, s3_top_level_dir: str, suite: str, test_failure_policy: str, safe_mode: bool, test_timeout: int, global_timeout: int):
|
||||
"""
|
||||
Determins the type of sequence to run based on the commit, source branch and test branch before running the
|
||||
sequence with the specified values.
|
||||
@@ -170,6 +170,7 @@ class TestImpact:
|
||||
@param src_branch: If not equal to dst_branch, the branch that is being built.
|
||||
@param dst_branch: If not equal to src_branch, the destination branch for the PR being built.
|
||||
@param s3_bucket: Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used.
|
||||
@param s3_top_level_dir: Top level directory to use in the S3 bucket.
|
||||
@param suite: Test suite to run.
|
||||
@param test_failure_policy: Test failure policy for regular and test impact sequences (ignored when seeding).
|
||||
@param safe_mode: Flag to run impact analysis tests in safe mode (ignored when seeding).
|
||||
@@ -218,7 +219,7 @@ class TestImpact:
|
||||
try:
|
||||
# Persistent storage location
|
||||
if s3_bucket:
|
||||
persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, self._source_of_truth_branch)
|
||||
persistent_storage = PersistentStorageS3(self._config, suite, s3_bucket, s3_top_level_dir, self._source_of_truth_branch)
|
||||
else:
|
||||
persistent_storage = PersistentStorageLocal(self._config, suite)
|
||||
except SystemError as e:
|
||||
@@ -226,14 +227,20 @@ class TestImpact:
|
||||
persistent_storage = None
|
||||
|
||||
if persistent_storage:
|
||||
# Flag to signify whether or not this is a re-run (multiple runs of the same commit)
|
||||
# Right now, we don't fully support re-runs but in the future we will have an extra subfolder for each commit hash with the
|
||||
# last run hash that was used for the first run for the commit so we can retreive the same reference point for building the
|
||||
# change list to ensure each subsequent run is using the same data but for the time being, just perform a regular run
|
||||
is_rerun = False
|
||||
if persistent_storage.has_historic_data:
|
||||
logger.info("Historic data found.")
|
||||
self._src_commit = persistent_storage.last_commit_hash
|
||||
|
||||
# Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of of the environment
|
||||
# Perform some basic sanity checks on the commit hashes to ensure confidence in the integrity of the environment
|
||||
if self._src_commit == self._dst_commit:
|
||||
logger.error(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying the integrity of the historic data is compromised.")
|
||||
logger.info(f"Source commit '{self._src_commit}' and destination commit '{self._dst_commit}', implying this is a re-run. A regular sequence will instead be performed.")
|
||||
persistent_storage = None
|
||||
is_rerun = True
|
||||
else:
|
||||
self._attempt_to_generate_change_list()
|
||||
else:
|
||||
@@ -261,7 +268,7 @@ class TestImpact:
|
||||
args.append(f"--changelist={self._change_list_path}")
|
||||
logger.info(f"Change list is set to '{self._change_list_path}'.")
|
||||
else:
|
||||
if self._is_source_of_truth_branch:
|
||||
if self._is_source_of_truth_branch and not is_rerun:
|
||||
# Use seed sequence (instrumented all tests) for coverage updating branches so we can generate the coverage bed for future sequences
|
||||
sequence_type = "seed"
|
||||
# We always continue after test failures when seeding to ensure we capture the coverage for all test targets
|
||||
|
||||
@@ -11,6 +11,7 @@ import mars_utils
|
||||
import sys
|
||||
import pathlib
|
||||
import traceback
|
||||
import re
|
||||
from tiaf import TestImpact
|
||||
from tiaf_logger import get_logger
|
||||
|
||||
@@ -66,13 +67,20 @@ def parse_args():
|
||||
required=True
|
||||
)
|
||||
|
||||
# S3 bucket
|
||||
# S3 bucket name
|
||||
parser.add_argument(
|
||||
'--s3-bucket',
|
||||
help="Location of S3 bucket to use for persistent storage, otherwise local disk storage will be used",
|
||||
required=False
|
||||
)
|
||||
|
||||
# S3 bucket top level directory
|
||||
parser.add_argument(
|
||||
'--s3-top-level-dir',
|
||||
help="The top level directory to use in the S3 bucket",
|
||||
required=False
|
||||
)
|
||||
|
||||
# MARS index prefix
|
||||
parser.add_argument(
|
||||
'--mars-index-prefix',
|
||||
@@ -80,6 +88,13 @@ def parse_args():
|
||||
required=False
|
||||
)
|
||||
|
||||
# Build number
|
||||
parser.add_argument(
|
||||
'--build-number',
|
||||
help="The build number this run of TIAF corresponds to",
|
||||
required=True
|
||||
)
|
||||
|
||||
# Test suite
|
||||
parser.add_argument(
|
||||
'--suite',
|
||||
@@ -127,12 +142,19 @@ if __name__ == "__main__":
|
||||
|
||||
try:
|
||||
args = parse_args()
|
||||
|
||||
s3_top_level_dir = None
|
||||
if args.s3_top_level_dir:
|
||||
s3_top_level_dir = args.s3_top_level_dir
|
||||
else:
|
||||
s3_top_level_dir = "tiaf"
|
||||
|
||||
tiaf = TestImpact(args.config)
|
||||
tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout)
|
||||
tiaf_result = tiaf.run(args.commit, args.src_branch, args.dst_branch, args.s3_bucket, s3_top_level_dir, args.suite, args.test_failure_policy, args.safe_mode, args.test_timeout, args.global_timeout)
|
||||
|
||||
if args.mars_index_prefix:
|
||||
logger.info("Transmitting report to MARS...")
|
||||
mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv)
|
||||
mars_utils.transmit_report_to_mars(args.mars_index_prefix, tiaf_result, sys.argv, args.build_number)
|
||||
|
||||
logger.info("Complete!")
|
||||
# Non-gating will be removed from this script and handled at the job level in SPEC-7413
|
||||
|
||||
@@ -106,7 +106,7 @@ class PersistentStorage(ABC):
|
||||
|
||||
historic_data_json = self._pack_historic_data(last_commit_hash)
|
||||
if historic_data_json:
|
||||
logger.info(f"Attempting to store historic data with new last commit hash '{self._last_commit_hash}'...")
|
||||
logger.info(f"Attempting to store historic data with new last commit hash '{last_commit_hash}'...")
|
||||
self._store_historic_data(historic_data_json)
|
||||
logger.info("The historic data was successfully stored.")
|
||||
|
||||
|
||||
@@ -18,7 +18,7 @@ logger = get_logger(__file__)
|
||||
|
||||
# Implementation of s3 bucket persistent storage
|
||||
class PersistentStorageS3(PersistentStorage):
|
||||
def __init__(self, config: dict, suite: str, s3_bucket: str, branch: str):
|
||||
def __init__(self, config: dict, suite: str, s3_bucket: str, root_dir: str, branch: str):
|
||||
"""
|
||||
Initializes the persistent storage with the specified s3 bucket.
|
||||
|
||||
@@ -36,8 +36,8 @@ class PersistentStorageS3(PersistentStorage):
|
||||
# historic_data.json.zip is the file containing the coverage and meta-data of the last TIAF sequence run
|
||||
historic_data_file = f"historic_data.{object_extension}"
|
||||
|
||||
# The location of the data is in the form <branch>/<config> so the build config of each branch gets its own historic data
|
||||
self._dir = f'{branch}/{config["meta"]["build_config"]}'
|
||||
# The location of the data is in the form <root_dir>/<branch>/<config> so the build config of each branch gets its own historic data
|
||||
self._dir = f'{root_dir}/{branch}/{config["meta"]["build_config"]}'
|
||||
self._historic_data_key = f'{self._dir}/{historic_data_file}'
|
||||
|
||||
logger.info(f"Attempting to retrieve historic data for branch '{branch}' at location '{self._historic_data_key}' on bucket '{s3_bucket}'...")
|
||||
|
||||
Reference in New Issue
Block a user