Merge branch 'development' into cleanup/SPEC-1670

This commit is contained in:
Esteban Papp
2021-07-14 14:53:59 -07:00
116 changed files with 6068 additions and 3529 deletions
-1
View File
@@ -138,7 +138,6 @@ ly_add_source_properties(
ly_add_source_properties(
SOURCES
Core/LevelEditorMenuHandler.cpp
GraphicsSettingsDialog.cpp
MainWindow.cpp
PROPERTY COMPILE_DEFINITIONS
VALUES ${LY_PAL_TOOLS_DEFINES}
+7 -41
View File
@@ -497,9 +497,15 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
// Hide Selection
editMenu.AddAction(AzToolsFramework::HideSelection);
// Unhide All
// Show All
editMenu.AddAction(AzToolsFramework::ShowAll);
// Lock Selection
editMenu.AddAction(AzToolsFramework::LockSelection);
// UnLock All
editMenu.AddAction(AzToolsFramework::UnlockAll);
/*
* The following block of code is part of the feature "Isolation Mode" and is temporarily
* disabled for 1.10 release.
@@ -552,49 +558,9 @@ void LevelEditorMenuHandler::PopulateEditMenu(ActionManager::MenuWrapper& editMe
// Global Preferences...
editorSettingsMenu.AddAction(ID_TOOLS_PREFERENCES);
// Graphics Settings...
editorSettingsMenu.AddAction(ID_GRAPHICS_SETTINGS);
// Editor Settings Manager
AddOpenViewPaneAction(editorSettingsMenu, LyViewPane::EditorSettingsManager);
// Graphics Performance
auto graphicPerformanceSubMenu = editorSettingsMenu.AddMenu(QObject::tr("Graphics Performance"));
auto pcMenu = graphicPerformanceSubMenu.AddMenu(tr("PC"));
pcMenu.AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLEHIGHSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC);
pcMenu.AddAction(ID_GAME_PC_ENABLELOWSPEC);
auto osxmetalMenu = graphicPerformanceSubMenu.AddMenu(tr("OSX Metal"));
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC);
osxmetalMenu.AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC);
auto androidMenu = graphicPerformanceSubMenu.AddMenu(tr("Android"));
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC);
androidMenu.AddAction(ID_GAME_ANDROID_ENABLELOWSPEC);
auto iosMenu = graphicPerformanceSubMenu.AddMenu(tr("iOS"));
iosMenu.AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLEHIGHSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC);
iosMenu.AddAction(ID_GAME_IOS_ENABLELOWSPEC);
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
auto publicname##Menu = graphicPerformanceSubMenu.AddMenu(tr(PublicAuxName2));\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEHIGHSPEC);\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC);\
publicname##Menu.AddAction(ID_GAME_##CODENAME##_ENABLELOWSPEC);
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
// Keyboard Customization
auto keyboardCustomizationMenu = editorSettingsMenu.AddMenu(tr("Keyboard Customization"));
keyboardCustomizationMenu.AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD);
-102
View File
@@ -111,7 +111,6 @@ AZ_POP_DISABLE_WARNING
#include "ToolBox.h"
#include "LevelInfo.h"
#include "EditorPreferencesDialog.h"
#include "GraphicsSettingsDialog.h"
#include "AnimationContext.h"
#include "GotoPositionDlg.h"
@@ -440,7 +439,6 @@ void CCryEditApp::RegisterActionHandlers()
ON_COMMAND(ID_CLEAR_REGISTRY, OnClearRegistryData)
ON_COMMAND(ID_VALIDATELEVEL, OnValidatelevel)
ON_COMMAND(ID_TOOLS_PREFERENCES, OnToolsPreferences)
ON_COMMAND(ID_GRAPHICS_SETTINGS, OnGraphicsSettings)
ON_COMMAND(ID_SWITCHCAMERA_DEFAULTCAMERA, OnSwitchToDefaultCamera)
ON_COMMAND(ID_SWITCHCAMERA_SEQUENCECAMERA, OnSwitchToSequenceCamera)
ON_COMMAND(ID_SWITCHCAMERA_SELECTEDCAMERA, OnSwitchToSelectedcamera)
@@ -453,14 +451,6 @@ void CCryEditApp::RegisterActionHandlers()
ON_COMMAND(ID_OPEN_TRACKVIEW, OnOpenTrackView)
ON_COMMAND(ID_OPEN_UICANVASEDITOR, OnOpenUICanvasEditor)
ON_COMMAND_RANGE(ID_GAME_PC_ENABLELOWSPEC, ID_GAME_PC_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_OSXMETAL_ENABLELOWSPEC, ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_ANDROID_ENABLELOWSPEC, ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
ON_COMMAND_RANGE(ID_GAME_IOS_ENABLELOWSPEC, ID_GAME_IOS_ENABLEVERYHIGHSPEC, OnChangeGameSpec)
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
ON_COMMAND_RANGE(ID_GAME_##CODENAME##_ENABLELOWSPEC, ID_GAME_##CODENAME##_ENABLEHIGHSPEC, OnChangeGameSpec)
@@ -3674,13 +3664,6 @@ void CCryEditApp::OnToolsPreferences()
dlg.exec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnGraphicsSettings()
{
GraphicsSettingsDialog dlg(MainWindow::instance());
dlg.exec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnSwitchToDefaultCamera()
{
@@ -3815,91 +3798,6 @@ void CCryEditApp::OnOpenUICanvasEditor()
QtViewPaneManager::instance()->OpenPane(LyViewPane::UiEditor);
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable)
{
if (GetIEditor()->GetEditorConfigSpec() == spec && GetIEditor()->GetEditorConfigPlatform() == platform)
{
nCheck = 1;
}
enable = spec <= GetIEditor()->GetSystem()->GetMaxConfigSpec();
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnUpdateGameSpec(QAction* action)
{
Q_ASSERT(action->isCheckable());
int nCheck = 0;
bool enable = true;
switch (action->data().toInt())
{
case ID_GAME_PC_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_PC, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID, nCheck, enable);
break;
case ID_GAME_IOS_ENABLELOWSPEC:
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEHIGHSPEC:
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_IOS, nCheck, enable);
break;
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
SetGameSpecCheck(CONFIG_VERYHIGH_SPEC, CONFIG_IOS, nCheck, enable);
break;
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
SetGameSpecCheck(CONFIG_LOW_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;\
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
SetGameSpecCheck(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;\
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
SetGameSpecCheck(CONFIG_HIGH_SPEC, CONFIG_##CODENAME, nCheck, enable);\
break;
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
}
action->setChecked(nCheck);
action->setEnabled(enable);
}
//////////////////////////////////////////////////////////////////////////
RecentFileList* CCryEditApp::GetRecentFileList()
{
-4
View File
@@ -403,7 +403,6 @@ private:
void OnClearRegistryData();
void OnValidatelevel();
void OnToolsPreferences();
void OnGraphicsSettings();
void OnSwitchToDefaultCamera();
void OnUpdateSwitchToDefaultCamera(QAction* action);
void OnSwitchToSequenceCamera();
@@ -416,9 +415,6 @@ private:
void OnOpenTrackView();
void OnOpenAudioControlsEditor();
void OnOpenUICanvasEditor();
void OnChangeGameSpec(UINT nID);
void SetGameSpecCheck(ESystemConfigSpec spec, ESystemConfigPlatform platform, int &nCheck, bool &enable);
void OnUpdateGameSpec(QAction* action);
void OnOpenQuickAccessBar();
public:
-72
View File
@@ -407,78 +407,6 @@ inline namespace Commands
}
}
//////////////////////////////////////////////////////////////////////////
void CCryEditApp::OnChangeGameSpec(UINT nID)
{
switch (nID)
{
case ID_GAME_PC_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_PC);
break;
case ID_GAME_PC_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_PC);
break;
case ID_GAME_OSXMETAL_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_OSX_METAL);
break;
case ID_GAME_ANDROID_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_ANDROID_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_ANDROID);
break;
case ID_GAME_IOS_ENABLELOWSPEC:
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEMEDIUMSPEC:
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_IOS);
break;
case ID_GAME_IOS_ENABLEVERYHIGHSPEC:
Commands::PySetConfigSpec(CONFIG_VERYHIGH_SPEC, CONFIG_IOS);
break;
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3)\
case ID_GAME_##CODENAME##_ENABLELOWSPEC:\
Commands::PySetConfigSpec(CONFIG_LOW_SPEC, CONFIG_##CODENAME);\
break;\
case ID_GAME_##CODENAME##_ENABLEMEDIUMSPEC:\
Commands::PySetConfigSpec(CONFIG_MEDIUM_SPEC, CONFIG_##CODENAME);\
break;\
case ID_GAME_##CODENAME##_ENABLEHIGHSPEC:\
Commands::PySetConfigSpec(CONFIG_HIGH_SPEC, CONFIG_##CODENAME);\
break;
AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS
#undef AZ_RESTRICTED_PLATFORM_EXPANSION
#endif
}
}
namespace AzToolsFramework
{
void CryEditPythonHandler::Reflect(AZ::ReflectContext* context)
+4 -2
View File
@@ -1896,7 +1896,7 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
{
CUndo undo("Move Camera");
AzToolsFramework::ScopedUndoBatch undo("Move Camera");
if (bMoveOnly)
{
// specify eObjectUpdateFlags_UserInput so that an undo command gets logged
@@ -1932,7 +1932,7 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
if (m_pressedKeyState != KeyPressedState::PressedInPreviousFrame)
{
CUndo undo("Move Camera");
AzToolsFramework::ScopedUndoBatch undo("Move Camera");
if (bMoveOnly)
{
AZ::TransformBus::Event(
@@ -1945,6 +1945,8 @@ void EditorViewportWidget::SetViewTM(const Matrix34& viewTM, bool bMoveOnly)
m_viewEntityId, &AZ::TransformInterface::SetWorldTM,
LYTransformToAZTransform(camMatrix));
}
AzToolsFramework::ToolsApplicationRequestBus::Broadcast(&AzToolsFramework::ToolsApplicationRequests::AddDirtyEntity, m_viewEntityId);
}
else
{
File diff suppressed because it is too large Load Diff
-284
View File
@@ -1,284 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QDialog>
#include <QTreeView>
#include <QStandardItemModel>
#include <QHeaderView>
#include <AzQtComponents/Components/Widgets/SpinBox.h>
#include <AzCore/std/containers/vector.h>
#include <AzCore/std/any.h>
#include <ISystem.h>
#endif
class QGridLayout;
class QLabel;
namespace Ui
{
class GraphicsSettingsDialog;
}
// Description:
// Status of cvar for a specifc platform and spec level
// editedValue - current setting within Graphics Settings Dialog box
// overwrittenValue - original setting from platform config file (set to originalValue if not found)
// originalValue - original settings from sys_spec config file index
struct CVarFileStatus
{
AZStd::any editedValue;
AZStd::any overwrittenValue;
AZStd::any originalValue;
CVarFileStatus(AZStd::any edit, AZStd::any over, AZStd::any orig) : editedValue(edit), overwrittenValue(over), originalValue(orig) {}
};
// Description:
// Status of specific cvar for Editor mapping
// type - CVAR_INT / CVAR_FLOAT / CVAR_STRING
// cvarGroup - source of cvar (sys_spec_particles, sys_spec_physics, etc.) or "miscellaneous" if only specified in platform config file
// fileVals = CVarFileStatus for each spec level of a specific platform
struct CVarInfo
{
int type;
AZStd::string cvarGroup;
AZStd::vector<CVarFileStatus> fileVals;
};
enum class GraphicsSettings
{
GameEffects,
Light,
ObjectDetail,
Particles,
Physics,
PostProcessing,
Quality,
Shading,
Shadows,
Sound,
Texture,
TextureResolution,
VolumetricEffects,
Water,
Miscellaneous,
numSettings
};
class GraphicsSettingsHeaderView;
class GraphicsSettingsTreeView
: public QTreeView
{
Q_OBJECT
public:
GraphicsSettingsTreeView(QWidget* parent = nullptr);
};
class GraphicsSettingsModel
: public QStandardItemModel
{
Q_OBJECT
public:
explicit GraphicsSettingsModel(QObject* parent = 0);
Qt::ItemFlags flags(const QModelIndex& index) const override;
};
class GraphicsSettingsDialog
: public QDialog,
public ILoadConfigurationEntrySink
{
Q_OBJECT
public:
explicit GraphicsSettingsDialog(QWidget* parent = nullptr);
virtual ~GraphicsSettingsDialog();
bool IsCustom(void) { return m_showCustomSpec; }
void UnloadCustomSpec(int specLevel);
// ILoadConfigurationEntrySink
void OnLoadConfigurationEntry(const char* szKey, const char* szValue, const char* szGroup) override;
public slots:
//Accept and reject
void reject() override;
void accept() override;
private slots:
//Update UIs
void PlatformChanged(const QString& platform);
bool CVarChanged(AZStd::any val, const char* cvarName, int specLevel);
void CVarChanged(int i);
void CVarChanged(double d);
void CVarChanged(const QString& s);
private:
// The struct ParameterWidget is used to store the parameter widget
// m_parameterName will be the name of the parameter the widget represent.
struct ParameterWidget
{
ParameterWidget(QWidget* widget, QString parameterName = "");
QString GetToolTip() const;
const char* PARAMETER_TOOLTIP = "The variable will update render parameter \"%1\".";
QWidget* m_widget;
QString m_parameterName;
};
struct CollapseGroup
{
QString m_groupName;
QStandardItem* m_groupRow;
QTreeView* m_treeView;
bool m_isCollapsed;
CollapseGroup(QTreeView* treeView);
void ToggleCollapsed();
};
void OpenCustomSpecDialog();
void ApplyCustomSpec(const QString& customFilePath);
bool IsCustomSpecAlreadyLoaded(const AZStd::string& filename) const;
void SetSettingsTree(int numColumns);
void SetCollapsed(const QModelIndex& index, bool flag);
enum CVarStateComparison
{
EDITED_OVERWRITTEN_COMPARE = 1,
EDITED_ORIGINAL_COMPARE = 2,
OVERWRITTEN_ORIGINAL_COMPARE = 3,
END_CVARSTATE_COMPARE,
};
bool CheckCVarStatesForDiff(AZStd::pair<AZStd::string, CVarInfo>* it, int cfgFileIndex, CVarStateComparison cmp);
// Save out settings into project-level cfg files
void SaveSystemSettings();
// Load in project-level cfg files for current platform
void LoadPlatformConfigurations();
// Build UI column for spec level of current platform
void BuildColumn(int specLevel);
// Initial UI building
void BuildUI();
// Cleaning out UI before loading new platform information
void CleanUI();
// Shows/hides custom spec option
void ShowCustomSpecOption(bool show);
// Shows/hides category labels and dropdowns
void ShowCategories(bool show);
// Warns about unsaved changes (returns true if accepted)
bool SendUnsavedChangesWarning(bool cancel);
void LoadCVarGroupDirectory(const AZStd::string& path);
/////////////////////////////////////////////
// UI help functions
// Setup collapsed buttons
void SetCollapsedLayout(const QString& groupName, QStandardItem* groupItem);
// Sets the platform entry index for the given platform
void SetPlatformEntry(ESystemConfigPlatform platform);
// Gets the platform enum given the platform name
ESystemConfigPlatform GetConfigPlatformFromName(const AZStd::string& platformName);
////////////////////////////////////////////
// Members
// Qt values
const int INPUT_MIN_WIDTH = 100;
const int INPUT_MIN_HEIGHT = 20;
const int INPUT_ROW_SPAN = 1;
const int INPUT_COLUMN_SPAN = 1;
const int CVAR_ROW_OFFSET = 2;
const int CVAR_VALUE_COLUMN_OFFSET = 1;
const int PLATFORM_LABEL_ROW = 1;
const int CVAR_LABEL_COLUMN = 1;
// Tool tips
const QString SETTINGS_FILE_PATH = "Config/spec/";
const char* CFG_FILEFILTER = "Cfg File(*.cfg);;All files(*)";
const int m_numSpecLevels = 4;
bool m_showCustomSpec;
bool m_showCategories;
GraphicsSettingsModel* m_graphicsSettingsModel;
GraphicsSettingsHeaderView* m_headerView;
int m_numColumns{ 0 };
const char* m_cvarGroupsFolder = "Config/CVarGroups";
QScopedPointer<Ui::GraphicsSettingsDialog> m_ui;
QVector<CollapseGroup*> m_uiCollapseGroup;
QVector<ParameterWidget*> m_parameterWidgets;
AZStd::string m_currentConfigFilename;
size_t m_currentSpecIndex;
// cvar name --> pair(type, CVarStatus for each file)
AZStd::unordered_map<AZStd::string, CVarInfo> m_cVarTracker;
AZStd::unordered_map<ESystemConfigPlatform, AZStd::vector<AZStd::string> > m_cfgFiles;
AZStd::vector<AZStd::pair<AZStd::string, ESystemConfigPlatform> > m_platformStrings;
struct CVarGroupInfo
{
QVector<QLabel*> m_platformLabels;
QVector<QLabel*> m_cvarLabels;
QVector<AzQtComponents::SpinBox*> m_cvarSpinBoxes;
QVector<AzQtComponents::DoubleSpinBox*> m_cvarDoubleSpinBoxes;
QVector<QLineEdit*> m_cvarLineEdits;
QVector<QToolButton*> m_specFileArea;
QVector<QWidget*> m_widgetInsertOrder;
QStandardItem* m_treeRowItem;
int m_currentRow;
};
AZStd::unordered_map<AZStd::string, CVarGroupInfo> m_cvarGroupData;
AZStd::vector<AZStd::string> m_cvarGroupOrder;
ESystemConfigPlatform m_currentPlatform;
int m_dirtyCVarCount;
};
class GraphicsSettingsHeaderView
: public QHeaderView
{
Q_OBJECT
public:
GraphicsSettingsHeaderView(GraphicsSettingsDialog* dialog, Qt::Orientation orientation, QWidget* parent = nullptr);
private:
bool event(QEvent* e) override;
void mouseMoveEvent(QMouseEvent* e) override;
void mouseReleaseEvent(QMouseEvent* e) override;
GraphicsSettingsDialog* m_dialog;
int m_index{ -1 };
};
+19 -20
View File
@@ -83,9 +83,9 @@ AZ::RPI::ViewportContextPtr LegacyViewportCameraControllerInstance::GetViewportC
}
bool LegacyViewportCameraControllerInstance::HandleMouseMove(
const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos)
int dx, int dy)
{
if (previousMousePos == currentMousePos)
if (dx == 0 && dy == 0)
{
return false;
}
@@ -105,7 +105,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
if (m_inMoveMode || m_inOrbitMode || m_inRotateMode || m_inZoomMode)
{
m_totalMouseMoveDelta += (QPoint(currentMousePos.m_x, currentMousePos.m_y)-QPoint(previousMousePos.m_x, previousMousePos.m_y)).manhattanLength();
m_totalMouseMoveDelta += AZStd::abs(dx) + AZStd::abs(dy);
}
if ((m_inRotateMode && m_inMoveMode) || m_inZoomMode)
@@ -115,7 +115,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
Vec3 ydir = m.GetColumn1().GetNormalized();
Vec3 pos = m.GetTranslation();
const float posDelta = 0.2f * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
const float posDelta = 0.2f * dy * speedScale;
pos = pos - ydir * posDelta;
m_orbitDistance = m_orbitDistance + posDelta;
m_orbitDistance = fabs(m_orbitDistance);
@@ -126,7 +126,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
}
else if (m_inRotateMode)
{
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
Ang3 angles(dy, 0, dx);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertYRotation)
{
@@ -158,7 +158,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
}
Vec3 pos = m.GetTranslation();
pos += 0.1f * xdir * (currentMousePos.m_x - previousMousePos.m_x) * speedScale + 0.1f * zdir * (previousMousePos.m_y - currentMousePos.m_y) * speedScale;
pos += 0.1f * xdir * dx * speedScale + 0.1f * zdir * dy * speedScale;
m.SetTranslation(pos);
AZ::Transform transform = viewportContext->GetCameraTransform();
@@ -168,7 +168,7 @@ bool LegacyViewportCameraControllerInstance::HandleMouseMove(
}
else if (m_inOrbitMode)
{
Ang3 angles(-currentMousePos.m_y + previousMousePos.m_y, 0, -currentMousePos.m_x + previousMousePos.m_x);
Ang3 angles(dy, 0, dx);
angles = angles * 0.002f * gSettings.cameraRotateSpeed;
if (gSettings.invertPan)
@@ -302,20 +302,19 @@ bool LegacyViewportCameraControllerInstance::HandleInputChannelEvent(const AzFra
bool shouldCaptureCursor = m_capturingCursor;
bool shouldConsumeEvent = false;
if (id == AzFramework::InputDeviceMouse::SystemCursorPosition)
if (id == AzFramework::InputDeviceMouse::Movement::X || id == AzFramework::InputDeviceMouse::Movement::Y)
{
bool result = false;
AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequestBus::Event(
GetViewportId(),
[this, &result](AzToolsFramework::ViewportInteraction::ViewportMouseCursorRequests* mouseRequests)
{
if (auto previousMousePosition = mouseRequests->PreviousViewportCursorScreenPosition();
previousMousePosition.has_value())
{
result = HandleMouseMove(mouseRequests->ViewportCursorScreenPosition(), previousMousePosition.value());
}
});
return result;
int dx = 0;
int dy = 0;
if (id == AzFramework::InputDeviceMouse::Movement::X)
{
dx = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
}
else
{
dy = -aznumeric_cast<int>(event.m_inputChannel.GetValue());
}
return HandleMouseMove(dx, dy);
}
else if (id == MouseButton::Left)
{
+1 -1
View File
@@ -69,7 +69,7 @@ namespace SandboxEditor
AZ::RPI::ViewportContextPtr GetViewportContext();
bool HandleMouseMove(const AzFramework::ScreenPoint& currentMousePos, const AzFramework::ScreenPoint& previousMousePos);
bool HandleMouseMove(int dx, int dy);
bool HandleMouseWheel(float zDelta);
bool IsKeyDown(Qt::Key key) const;
void UpdateCursorCapture(bool shouldCaptureCursor);
-44
View File
@@ -687,49 +687,6 @@ void MainWindow::InitActions()
am->AddAction(ID_FILE_PROJECT_MANAGER_SETTINGS, tr("Edit Project Settings..."));
am->AddAction(ID_FILE_PROJECT_MANAGER_NEW, tr("New Project..."));
am->AddAction(ID_FILE_PROJECT_MANAGER_OPEN, tr("Open Project..."));
am->AddAction(ID_GAME_PC_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_PC_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_OSXMETAL_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_ANDROID_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEVERYHIGHSPEC, tr("Very High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEHIGHSPEC, tr("High")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLEMEDIUMSPEC, tr("Medium")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
am->AddAction(ID_GAME_IOS_ENABLELOWSPEC, tr("Low")).SetCheckable(true)
.RegisterUpdateCallback(cryEdit, &CCryEditApp::OnUpdateGameSpec);
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#if defined(TOOLS_SUPPORT_JASPER)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, jasper)
#endif
#if defined(TOOLS_SUPPORT_PROVO)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, provo)
#endif
#if defined(TOOLS_SUPPORT_SALEM)
#include AZ_RESTRICTED_FILE_EXPLICIT(MainWindow_cpp, salem)
#endif
#endif
am->AddAction(ID_TOOLS_CUSTOMIZEKEYBOARD, tr("Customize &Keyboard..."))
.Connect(&QAction::triggered, this, &MainWindow::ShowKeyboardCustomization);
am->AddAction(ID_TOOLS_EXPORT_SHORTCUTS, tr("&Export Keyboard Settings..."))
@@ -737,7 +694,6 @@ void MainWindow::InitActions()
am->AddAction(ID_TOOLS_IMPORT_SHORTCUTS, tr("&Import Keyboard Settings..."))
.Connect(&QAction::triggered, this, &MainWindow::ImportKeyboardShortcuts);
am->AddAction(ID_TOOLS_PREFERENCES, tr("Global Preferences..."));
am->AddAction(ID_GRAPHICS_SETTINGS, tr("&Graphics Settings..."));
for (int i = ID_FILE_MRU_FIRST; i <= ID_FILE_MRU_LAST; ++i)
{
+1 -1
View File
@@ -5,7 +5,7 @@
<key>CFBundleExecutable</key>
<string>Editor</string>
<key>CFBundleIdentifier</key>
<string>com.Amazon.Lumberyard.Editor</string>
<string>org.O3DE.Editor</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleSignature</key>
@@ -46,4 +46,8 @@ ly_add_target(
AZ::AzCore
AZ::AzToolsFramework
AZ::AzQtComponents
RUNTIME_DEPENDENCIES
AZ::AzCore
AZ::AzToolsFramework
AZ::AzQtComponents
)
@@ -20,12 +20,12 @@
#include "ValidationHandler.h"
#include <AzCore/Component/ComponentApplicationBus.h>
#include <AzCore/IO/Path/Path.h>
#include "AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h"
#include <AzToolsFramework/UI/PropertyEditor/InstanceDataHierarchy.h>
#include <AzToolsFramework/UI/PropertyEditor/PropertyManagerComponent.h>
#include <AzToolsFramework/UI/PropertyEditor/ReflectedPropertyEditor.hxx>
#include <AzToolsFramework/UI/UICore/WidgetHelpers.h>
#include <Util/FileUtil.h>
#include <QMessageBox>
#include <QCloseEvent>
@@ -52,7 +52,7 @@ namespace ProjectSettingsTool
PlatformEnabled(PlatformId::Ios) ?
ProjectSettingsContainer::PlistInitVector({
ProjectSettingsContainer::PlatformAndPath
{ PlatformId::Ios, m_projectRoot + PlatformResourcesFolder(PlatformId::Ios) }
{ PlatformId::Ios, GetPlatformResource(PlatformId::Ios) }
})
:
ProjectSettingsContainer::PlistInitVector())
@@ -647,33 +647,38 @@ namespace ProjectSettingsTool
// iOS can be disabled if the plist file is missing
if (platformId == PlatformId::Ios)
{
const AZStd::string filename = m_projectRoot + PlatformResourcesFolder(platformId);
return CFileUtil::FileExists(filename.c_str());
AZStd::string plistPath = GetPlatformResource(platformId);
return !plistPath.empty();
}
return true;
}
const char* ProjectSettingsToolWindow::PlatformResourcesFolder(PlatformId platformId)
AZStd::string ProjectSettingsToolWindow::GetPlatformResource(PlatformId platformId)
{
if (platformId == PlatformId::Ios)
{
const AZStd::string firstfilename = m_projectRoot + "/Gem/Resources/Platform/iOS/Info.plist";
if (CFileUtil::FileExists(firstfilename.c_str()))
const char* searchPaths[] = {
"Resources/Platform/iOS/Info.plist",
// legacy paths
"Gem/Resources/Platform/iOS/Info.plist",
"Gem/Resources/IOSLauncher/Info.plist",
};
for (auto relPath : searchPaths)
{
return "/Gem/Resources/Platform/iOS/Info.plist";
}
else
{
const AZStd::string filename = m_projectRoot + "/Gem/Resources/IOSLauncher/Info.plist";
if (CFileUtil::FileExists(filename.c_str()))
AZ::IO::FixedMaxPath projectPlist{ m_projectRoot };
projectPlist /= relPath;
if (AZ::IO::SystemFile::Exists(projectPlist.c_str()))
{
return "/Gem/Resources/IOSLauncher/Info.plist";
return projectPlist.LexicallyNormal().String();
}
}
}
return nullptr;
return AZStd::string();
}
#include <moc_ProjectSettingsToolWindow.cpp>
@@ -137,8 +137,8 @@ namespace ProjectSettingsTool
// returns true if the platform is enabled
bool PlatformEnabled(PlatformId platformId);
// returns the resource folder
const char* PlatformResourcesFolder(PlatformId platformId);
// returns the main platform specific resource file e.g. for iOS it would be the Info.plist
AZStd::string GetPlatformResource(PlatformId platformId);
// The ui for the window
QScopedPointer<Ui::ProjectSettingsToolWidget> m_ui;
-26
View File
@@ -187,7 +187,6 @@
#define ID_SWITCHCAMERA_SEQUENCECAMERA 33701
#define ID_SWITCHCAMERA_SELECTEDCAMERA 33702
#define ID_TV_RECORD_AUTO 33703
#define ID_GRAPHICS_SETTINGS 33705
#define ID_VIEW_OPENVIEWPANE 33709
#define ID_VIEW_OPENPANE_FIRST 33712
#define ID_VIEW_OPENPANE_LAST 33811
@@ -219,10 +218,6 @@
#define ID_SPLINE_SNAP_GRID_X 33933
#define ID_SPLINE_SNAP_GRID_Y 33934
#define ID_FREEZE_TANGENTS 33935
#define ID_GAME_PC_ENABLELOWSPEC 33960
#define ID_GAME_PC_ENABLEMEDIUMSPEC 33961
#define ID_GAME_PC_ENABLEHIGHSPEC 33962
#define ID_GAME_PC_ENABLEVERYHIGHSPEC 33963
#define ID_PANEL_VEG_CREATE_SEL 33990
#define ID_TOOLS_UPDATEPROCEDURALVEGETATION 33999
#define ID_DISPLAY_GOTOPOSITION 34004
@@ -287,14 +282,6 @@
#define ID_CLEAR_REGISTRY 34470
#define ID_SOUND_STOPALLSOUNDS 34476
#define ID_AUDIO_REFRESH_AUDIO_SYSTEM 34477
#define ID_GAME_ANDROID_ENABLELOWSPEC 34490
#define ID_GAME_ANDROID_ENABLEMEDIUMSPEC 34491
#define ID_GAME_ANDROID_ENABLEHIGHSPEC 34492
#define ID_GAME_ANDROID_ENABLEVERYHIGHSPEC 34493
#define ID_GAME_IOS_ENABLELOWSPEC 34494
#define ID_GAME_IOS_ENABLEMEDIUMSPEC 34495
#define ID_GAME_IOS_ENABLEHIGHSPEC 34496
#define ID_GAME_IOS_ENABLEVERYHIGHSPEC 34497
#define ID_OPEN_AUDIO_CONTROLS_BROWSER 34580
#define ID_CREATE_GLOBAL_FG_MODULE_FROM_SELECTION 35076
#define ID_CREATE_LEVEL_FG_MODULE_FROM_SELECTION 35077
@@ -324,19 +311,6 @@
#define ID_DOCUMENTATION_FEEDBACK 36043
#define ID_OPEN_SUBSTANCE_EDITOR 36060
#define ID_IMPORT_ASSET 36069
#define ID_GAME_PROVO_ENABLELOWSPEC 34603
#define ID_GAME_PROVO_ENABLEMEDIUMSPEC 34604
#define ID_GAME_PROVO_ENABLEHIGHSPEC 34605
#define ID_GAME_OSXMETAL_ENABLELOWSPEC 34606
#define ID_GAME_OSXMETAL_ENABLEMEDIUMSPEC 34607
#define ID_GAME_OSXMETAL_ENABLEHIGHSPEC 34608
#define ID_GAME_OSXMETAL_ENABLEVERYHIGHSPEC 34609
#define ID_GAME_SALEM_ENABLELOWSPEC 34610
#define ID_GAME_SALEM_ENABLEMEDIUMSPEC 34611
#define ID_GAME_SALEM_ENABLEHIGHSPEC 34612
#define ID_GAME_JASPER_ENABLELOWSPEC 34613
#define ID_GAME_JASPER_ENABLEMEDIUMSPEC 34614
#define ID_GAME_JASPER_ENABLEHIGHSPEC 34615
#define ID_FILE_RESAVESLICES 36210
#define FIRST_QT_ACTION 50000
#define ID_VIEW_CONSOLEWINDOW 50001
@@ -1,25 +0,0 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project. For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#GraphicsSettingsDialog QHeaderView::section
{
background: #2D2D2D;
}
#GraphicsSettingsDialog QHeaderView::down-arrow
{
width: 14px;
height: 14px;
image: url(:/Gallery/Delete.svg);
}
#GraphicsSettingsDialog QHeaderView::up-arrow
{
width: 14px;
height: 14px;
image: url(:/Gallery/Delete.svg);
}
-1
View File
@@ -3,6 +3,5 @@
<file alias="Assets/Editor/Style/Editor.qss">Editor.qss</file>
<file alias="Assets/Editor/Style/EditorPreferencesDialog.qss">EditorPreferencesDialog.qss</file>
<file alias="Assets/Editor/Style/LayoutConfigDialog.qss">LayoutConfigDialog.qss</file>
<file alias="Assets/Editor/Style/GraphicsSettingsDialog.qss">GraphicsSettingsDialog.qss</file>
</qresource>
</RCC>
-3
View File
@@ -583,9 +583,6 @@ set(FILES
SettingsManager.h
SettingsManagerDialog.h
SettingsManagerDialog.ui
GraphicsSettingsDialog.h
GraphicsSettingsDialog.cpp
graphicssettingsdialog.ui
AboutDialog.cpp
ErrorReportTableModel.h
ErrorReportTableModel.cpp
-270
View File
@@ -1,270 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<ui version="4.0">
<class>GraphicsSettingsDialog</class>
<widget class="QDialog" name="GraphicsSettingsDialog">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1292</width>
<height>565</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>800</width>
<height>400</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>16777215</height>
</size>
</property>
<property name="windowTitle">
<string>Graphics Settings</string>
</property>
<layout class="QVBoxLayout" name="verticalLayout">
<item>
<widget class="QWidget" name="widget" native="true">
<layout class="QGridLayout" name="m_generalLayout">
<property name="horizontalSpacing">
<number>0</number>
</property>
<property name="verticalSpacing">
<number>6</number>
</property>
<item row="2" column="3">
<widget class="QWidget" name="m_platform" native="true">
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>0</width>
<height>20</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<layout class="QHBoxLayout" name="horizontalLayout_7">
<property name="spacing">
<number>0</number>
</property>
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
<widget class="QComboBox" name="m_platformEntry"/>
</item>
</layout>
</widget>
</item>
<item row="2" column="0">
<widget class="QPushButton" name="m_selectCustomSpecButton">
<property name="minimumSize">
<size>
<width>100</width>
<height>0</height>
</size>
</property>
<property name="maximumSize">
<size>
<width>16777215</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Add Resource</string>
</property>
</widget>
</item>
<item row="2" column="2">
<widget class="QLabel" name="m_platformLabel">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="minimumSize">
<size>
<width>60</width>
<height>20</height>
</size>
</property>
<property name="text">
<string>Platform</string>
</property>
<property name="alignment">
<set>Qt::AlignCenter</set>
</property>
</widget>
</item>
<item row="2" column="1">
<widget class="Line" name="m_lineSpacer">
<property name="minimumSize">
<size>
<width>13</width>
<height>0</height>
</size>
</property>
<property name="orientation">
<enum>Qt::Vertical</enum>
</property>
</widget>
</item>
</layout>
</widget>
</item>
<item>
<widget class="Line" name="line_2">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
<item>
<widget class="QScrollArea" name="m_scrollArea">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="widgetResizable">
<bool>true</bool>
</property>
<widget class="QWidget" name="m_scrollAreaWidgetContents">
<property name="geometry">
<rect>
<x>0</x>
<y>0</y>
<width>1272</width>
<height>452</height>
</rect>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Expanding" vsizetype="Expanding">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<layout class="QGridLayout" name="gridLayout">
<item row="0" column="0">
<widget class="GraphicsSettingsTreeView" name="m_graphicsSettingsTreeView">
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="indentation">
<number>8</number>
</property>
<attribute name="headerStretchLastSection">
<bool>false</bool>
</attribute>
</widget>
</item>
</layout>
</widget>
</widget>
</item>
<item>
<layout class="QHBoxLayout" name="m_horizontalLayout">
<item>
<spacer name="m_horizontalSpacer">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>40</width>
<height>20</height>
</size>
</property>
</spacer>
</item>
<item>
<widget class="QPushButton" name="m_applyButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="styleSheet">
<string notr="true">background-color: rgb(233, 118, 17);</string>
</property>
<property name="text">
<string>Save</string>
</property>
</widget>
</item>
<item>
<widget class="QPushButton" name="m_cancelButton">
<property name="sizePolicy">
<sizepolicy hsizetype="Fixed" vsizetype="Fixed">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="text">
<string>Cancel</string>
</property>
</widget>
</item>
</layout>
</item>
<item>
<widget class="Line" name="line">
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
</widget>
</item>
</layout>
<zorder>line</zorder>
<zorder>m_scrollArea</zorder>
<zorder>line_2</zorder>
<zorder>widget</zorder>
</widget>
<customwidgets>
<customwidget>
<class>GraphicsSettingsTreeView</class>
<extends>QTreeView</extends>
<header>GraphicsSettingsDialog.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>m_cancelButton</tabstop>
<tabstop>m_applyButton</tabstop>
<tabstop>m_scrollArea</tabstop>
</tabstops>
<resources/>
<connections/>
</ui>
@@ -116,7 +116,7 @@ namespace AZ
{
const char* uuidString = nullptr;
unsigned int uuidStringLength = 0;
if (dc.ReadArg(0, uuidString) && dc.ReadValue(1, uuidStringLength))
if (dc.ReadArg(0, uuidString) && dc.ReadArg(1, uuidStringLength))
{
dc.PushResult(Uuid(uuidString, uuidStringLength));
}
@@ -6,6 +6,7 @@
*/
#include <AzCore/Math/Vector3.h>
#include <AzCore/Serialization/Json/JsonSerializationSettings.h>
#include <AzCore/std/string/string_view.h>
#include <Tests/Serialization/Json/JsonSerializationTests.h>
@@ -43,7 +44,9 @@ namespace JsonSerializationTests
}
void CheckApplyPatchOutcome(const char* target, const char* patch,
AZ::JsonSerializationResult::Outcomes outcome, AZ::JsonSerializationResult::Processing processing)
AZ::JsonSerializationResult::Outcomes outcome,
AZ::JsonSerializationResult::Processing processing,
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
{
m_jsonDocument->Parse(target);
ASSERT_FALSE(m_jsonDocument->HasParseError());
@@ -53,12 +56,24 @@ namespace JsonSerializationTests
ASSERT_FALSE(patchDocument.HasParseError());
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(*m_jsonDocument,
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch);
m_jsonDocument->GetAllocator(), patchDocument, AZ::JsonMergeApproach::JsonPatch, settings);
EXPECT_EQ(result.GetTask(), AZ::JsonSerializationResult::Tasks::Merge);
EXPECT_EQ(result.GetOutcome(), outcome);
EXPECT_EQ(result.GetProcessing(), processing);
}
void CheckApplyPatchOutcome(
const char* target,
const char* patch,
const char* expectedPatchedResult,
AZ::JsonSerializationResult::Outcomes outcome,
AZ::JsonSerializationResult::Processing processing,
const AZ::JsonApplyPatchSettings& settings = AZ::JsonApplyPatchSettings{})
{
CheckApplyPatchOutcome(target, patch, outcome, processing, settings);
Expect_DocStrEq(expectedPatchedResult);
}
void CheckCreatePatch_Core(const char* source, AZStd::string_view patch, const char* target,
AZ::JsonMergeApproach approach)
{
@@ -262,6 +277,36 @@ namespace JsonSerializationTests
Outcomes::TypeMismatch, Processing::Halted);
}
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchWithCustomReportingCallback_ReportPartialSkip)
{
using namespace AZ::JsonSerializationResult;
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
{
using namespace AZ::JsonSerializationResult;
if (result.GetProcessing() == Processing::Halted)
{
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
}
return result;
};
AZ::JsonApplyPatchSettings applyPatchSettings;
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
CheckApplyPatchOutcome(
R"({})",
R"([
{ "op": "add", "path": "/nonexistent_key/new_member", "value": "someValue" },
{ "op": "add", "path": "/test", "value": "someValue" }
])",
R"(
{ "test": "someValue" }
)",
Outcomes::PartialSkip,
Processing::Completed,
AZStd::move(applyPatchSettings));
}
TEST_F(JsonPatchingSerializationTests, ApplyPatch_UseJsonPatchAddUnnamedMember_ReportsSuccess)
{
CheckApplyPatch(
@@ -97,6 +97,9 @@ namespace AzFramework
//! This is called when the window is deactivated from code or if the user closes the window.
virtual void OnWindowClosed() {};
//! This is called when vsync interval is changed.
virtual void OnVsyncIntervalChanged(uint32_t interval) { AZ_UNUSED(interval); };
};
using WindowNotificationBus = AZ::EBus<WindowNotifications>;
@@ -41,7 +41,7 @@ namespace AzNetworking
void TcpSocketManager::ProcessEvents(AZ::TimeMs maxBlockMs, const SocketEventCallback& readCallback, const SocketEventCallback& writeCallback)
{
if(static_cast<int32_t>(m_maxFd) <= 0 && m_socketFds.empty())
if(static_cast<int32_t>(m_maxFd) <= 0 || m_socketFds.empty())
{
// There are no available sockets to process
return;
@@ -63,6 +63,9 @@ namespace AzToolsFramework
//! Signal the Python handler to stop
virtual bool StopPython(bool silenceWarnings = false) = 0;
//! Query to determine if the Python VM has been initialized indicating an active state
virtual bool IsPythonActive() = 0;
//! Determines if the caller needs to wait for the Python VM to initialize (non-main thread only)
virtual void WaitForInitialization() {}
@@ -11,6 +11,7 @@
#include <AzFramework/Input/Buses/Notifications/InputChannelNotificationBus.h>
#include <AzFramework/Input/Buses/Requests/InputChannelRequestBus.h>
#include <AzQtComponents/Utilities/QtWindowUtilities.h>
#include <QApplication>
#include <QCursor>
@@ -187,12 +188,6 @@ namespace AzToolsFramework
bool QtEventToAzInputMapper::HandlesInputEvent(const AzFramework::InputChannel& channel) const
{
const AzFramework::InputChannelId& channelId = channel.GetInputChannelId();
if (channelId == AzFramework::InputDeviceMouse::Movement::X || channelId == AzFramework::InputDeviceMouse::Movement::Y)
{
return false;
}
// We map keyboard and mouse events from Qt, so flag all events coming from those devices
// as handled by our synthetic event system.
const AzFramework::InputDeviceId& deviceId = channel.GetInputDevice().GetInputDeviceId();
@@ -210,6 +205,22 @@ namespace AzToolsFramework
}
}
void QtEventToAzInputMapper::SetCursorCaptureEnabled(bool enabled)
{
if (m_capturingCursor != enabled)
{
m_capturingCursor = enabled;
if (m_capturingCursor)
{
qApp->setOverrideCursor(Qt::BlankCursor);
}
else
{
qApp->restoreOverrideCursor();
}
}
}
bool QtEventToAzInputMapper::eventFilter(QObject* object, QEvent* event)
{
// Abort if processing isn't enabled.
@@ -284,13 +295,25 @@ namespace AzToolsFramework
{
auto systemCursorChannel =
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::SystemCursorPosition);
auto movementXChannel =
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::X);
auto movementYChannel =
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Y);
auto mouseWheelChannel =
GetInputChannel<AzFramework::InputChannelDeltaWithSharedPosition2D>(AzFramework::InputDeviceMouse::Movement::Z);
systemCursorChannel->ProcessRawInputEvent(m_cursorPosition->m_normalizedPositionDelta.GetLength());
// Generate movement events based on the pixel delta divided by the DPI scaling factor, to calculate a rough approximation
// of cursor movement velocity.
movementXChannel->ProcessRawInputEvent(
m_cursorPosition->m_normalizedPositionDelta.GetX() * aznumeric_cast<float>(m_sourceWidget->width()) / m_sourceWidget->devicePixelRatioF());
movementYChannel->ProcessRawInputEvent(
m_cursorPosition->m_normalizedPositionDelta.GetY() * aznumeric_cast<float>(m_sourceWidget->height()) / m_sourceWidget->devicePixelRatioF());
mouseWheelChannel->ProcessRawInputEvent(0.f);
NotifyUpdateChannelIfNotIdle(systemCursorChannel, nullptr);
NotifyUpdateChannelIfNotIdle(movementXChannel, nullptr);
NotifyUpdateChannelIfNotIdle(movementYChannel, nullptr);
NotifyUpdateChannelIfNotIdle(mouseWheelChannel, nullptr);
}
@@ -318,16 +341,42 @@ namespace AzToolsFramework
}
}
AZ::Vector2 QtEventToAzInputMapper::WidgetPositionToNormalizedPosition(QPoint position)
{
const float normalizedX = aznumeric_cast<float>(position.x()) / aznumeric_cast<float>(m_sourceWidget->width());
const float normalizedY = aznumeric_cast<float>(position.y()) / aznumeric_cast<float>(m_sourceWidget->height());
return AZ::Vector2{normalizedX, normalizedY};
}
QPoint QtEventToAzInputMapper::NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition)
{
const int denormalizedX = aznumeric_cast<int>(normalizedPosition.GetX() * m_sourceWidget->width());
const int denormalizedY = aznumeric_cast<int>(normalizedPosition.GetY() * m_sourceWidget->height());
return QPoint{denormalizedX, denormalizedY};
}
void QtEventToAzInputMapper::HandleMouseMoveEvent(QMouseEvent* mouseEvent)
{
AZ::Vector2 lastCursorPosition = m_cursorPosition->m_normalizedPosition;
const QPoint mousePos = mouseEvent->pos();
const float normalizedX = aznumeric_cast<float>(mousePos.x()) / aznumeric_cast<float>(m_sourceWidget->width());
const float normalizedY = aznumeric_cast<float>(mousePos.y()) / aznumeric_cast<float>(m_sourceWidget->height());
const AZ::Vector2 normalizedPosition(normalizedX, normalizedY);
const AZ::Vector2 normalizedPosition = WidgetPositionToNormalizedPosition(mousePos);
m_cursorPosition->m_normalizedPositionDelta = normalizedPosition - m_cursorPosition->m_normalizedPosition;
m_cursorPosition->m_normalizedPosition = normalizedPosition;
ProcessPendingMouseEvents();
m_mouseChannelsNeedUpdate = true;
if (m_capturingCursor)
{
// Reset our cursor position to the previous point.
QPoint targetScreenPosition = m_sourceWidget->mapToGlobal(NormalizedPositionToWidgetPosition(lastCursorPosition));
AzQtComponents::SetCursorPos(targetScreenPosition);
// Even though we just set the cursor position, there are edge cases such as remote desktop that will leave
// the cursor position unchanged. For safety, we re-cache our last cursor position for delta generation.
QPoint actualWidgetPosition = m_sourceWidget->mapFromGlobal(QCursor::pos());
m_cursorPosition->m_normalizedPosition = WidgetPositionToNormalizedPosition(actualWidgetPosition);
}
}
void QtEventToAzInputMapper::HandleKeyEvent(QKeyEvent* keyEvent)
@@ -47,6 +47,12 @@ namespace AzToolsFramework
//! Sets whether or not this input mapper should be updating its input channels from Qt events.
void SetEnabled(bool enabled);
//! Sets whether or not the cursor should be constrained to the source widget and invisible.
//! Internally, this will reset the cursor position after each move event to ensure movement
//! events don't allow the cursor to escape. This can be used for typical camera controls
//! like a dolly or rotation, where mouse movement is important but cursor location is not.
void SetCursorCaptureEnabled(bool enabled);
// QObject overrides...
bool eventFilter(QObject* object, QEvent* event) override;
@@ -106,6 +112,11 @@ namespace AzToolsFramework
// Processes any pending mouse movement events, this allows mouse movement channels to close themselves.
void ProcessPendingMouseEvents();
// Converts a point in logical source widget space [0..m_sourceWidget->size()] to normalized [0..1] space.
AZ::Vector2 WidgetPositionToNormalizedPosition(QPoint position);
// Converts a point in normalized [0..1] space to logical source widget space [0..m_sourceWidget->size()].
QPoint NormalizedPositionToWidgetPosition(AZ::Vector2 normalizedPosition);
// Handle mouse click events.
void HandleMouseButtonEvent(QMouseEvent* mouseEvent);
// Handle mouse move events.
@@ -144,6 +155,8 @@ namespace AzToolsFramework
bool m_mouseChannelsNeedUpdate = false;
// Flags whether or not Qt events should currently be processed.
bool m_enabled = true;
// Flags whether or not the cursor is being constrained to the source widget (for invisible mouse movement).
bool m_capturingCursor = false;
// Our viewport-specific AZ devices. We control their internal input channel states.
AZStd::unique_ptr<EditorQtMouseDevice> m_mouseDevice;
@@ -172,20 +172,23 @@ namespace AzToolsFramework
PrefabDom& templateDomReference = m_prefabSystemComponentInterface->FindTemplateDom(templateId);
//apply patch to template
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
templateDomReference.GetAllocator(), providedPatch, AZ::JsonMergeApproach::JsonPatch);
AZ::JsonSerializationResult::ResultCode result =
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), providedPatch);
//trigger propagation
if (result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success)
if (result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::Success)
{
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
return true;
AZ_Error("Prefab", false, "Patch was not successfully applied.");
return false;
}
else
{
AZ_Error("Prefab", false, "Patch was not successfully applied");
return false;
AZ_Error(
"Prefab", result.GetOutcome() != AZ::JsonSerializationResult::Outcomes::PartialSkip,
"Some of the patches are not successfully applied.");
m_prefabSystemComponentInterface->SetTemplateDirtyFlag(templateId, true);
m_prefabSystemComponentInterface->PropagateTemplateChanges(templateId, instanceToExclude);
return true;
}
}
@@ -176,12 +176,17 @@ namespace AzToolsFramework
}
else
{
AZ::JsonSerializationResult::ResultCode applyPatchResult = AZ::JsonSerialization::ApplyPatch(
sourceTemplateDomCopy,
targetTemplatePrefabDom.GetAllocator(),
patchesReference->get(),
AZ::JsonMergeApproach::JsonPatch);
AZ::JsonSerializationResult::ResultCode applyPatchResult =
PrefabDomUtils::ApplyPatches(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator(), patchesReference->get());
linkedInstanceDom.CopyFrom(sourceTemplateDomCopy, targetTemplatePrefabDom.GetAllocator());
PrefabDomValueReference sourceTemplateName =
PrefabDomUtils::FindPrefabDomValue(sourceTemplateDomCopy, PrefabDomUtils::SourceName);
AZ_Assert(sourceTemplateName && sourceTemplateName->get().IsString(), "A valid source template name couldn't be found");
PrefabDomValueReference targetTemplateName =
PrefabDomUtils::FindPrefabDomValue(targetTemplatePrefabDom, PrefabDomUtils::SourceName);
AZ_Assert(targetTemplateName && targetTemplateName->get().IsString(), "A valid target template name couldn't be found");
if (applyPatchResult.GetProcessing() != AZ::JsonSerializationResult::Processing::Completed)
{
AZ_Error(
@@ -190,6 +195,14 @@ namespace AzToolsFramework
m_sourceTemplateId, m_targetTemplateId);
return false;
}
if (applyPatchResult.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip)
{
AZ_Error(
"Prefab", false,
"Link::UpdateTarget - Some of the patches couldn't be applied on the source template '%s' present under the "
"target Template '%s'.",
sourceTemplateName->get().GetString(), targetTemplateName->get().GetString());
}
}
// This is a guardrail to ensure the linked instance dom always has the LinkId value
@@ -236,6 +236,26 @@ namespace AzToolsFramework
return findInstancesResult->get();
}
AZ::JsonSerializationResult::ResultCode ApplyPatches(
PrefabDomValue& prefabDomToApplyPatchesOn, PrefabDom::AllocatorType& allocator, const PrefabDomValue& patches)
{
auto issueReportingCallback = [](AZStd::string_view, AZ::JsonSerializationResult::ResultCode result,
AZStd::string_view) -> AZ::JsonSerializationResult::ResultCode
{
using namespace AZ::JsonSerializationResult;
if (result.GetProcessing() == Processing::Halted)
{
return ResultCode(result.GetTask(), Outcomes::PartialSkip);
}
return result;
};
AZ::JsonApplyPatchSettings applyPatchSettings;
applyPatchSettings.m_reporting = AZStd::move(issueReportingCallback);
return AZ::JsonSerialization::ApplyPatch(
prefabDomToApplyPatchesOn, allocator, patches, AZ::JsonMergeApproach::JsonPatch, applyPatchSettings);
}
void PrintPrefabDomValue(
[[maybe_unused]] const AZStd::string_view printMessage,
[[maybe_unused]] const PrefabDomValue& prefabDomValue)
@@ -7,6 +7,7 @@
#pragma once
#include <AzCore/Serialization/Json/JsonSerializationResult.h>
#include <AzCore/std/optional.h>
#include <AzCore/Asset/AssetCommon.h>
#include <AzToolsFramework/Prefab/Instance/Instance.h>
@@ -122,6 +123,11 @@ namespace AzToolsFramework
*/
PrefabDomValueConstReference GetInstancesValue(const PrefabDomValue& prefabDom);
AZ::JsonSerializationResult::ResultCode ApplyPatches(
PrefabDomValue& prefabDomToApplyPatchesOn,
PrefabDom::AllocatorType& allocator,
const PrefabDomValue& patches);
/**
* Prints the contents of the given prefab DOM value to the debug output console in a readable format.
* @param printMessage The message that will be printed before printing the PrefabDomValue
@@ -261,8 +261,13 @@ namespace AzToolsFramework
instanceDom.CopyFrom(instanceDomRef->get(), instanceDom.GetAllocator());
//apply the patch to the template within the target
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(instanceDom,
instanceDom.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
AZ::JsonSerializationResult::ResultCode result = PrefabDomUtils::ApplyPatches(instanceDom, instanceDom.GetAllocator(), patch);
AZ_Error(
"Prefab",
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::PartialSkip ||
result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
"Some of the patches are not successfully applied.");
//remove the link id placed into the instance
auto linkIdIter = instanceDom.FindMember(PrefabDomUtils::LinkIdName);
@@ -22,11 +22,11 @@ namespace AzToolsFramework
/// @name Reverse URLs.
/// Used to identify common actions and override them when necessary.
//@{
static const AZ::Crc32 s_backAction = AZ_CRC("com.amazon.action.common.back", 0xd772a2af);
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.amazon.action.common.delete", 0x5731f6cb);
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.amazon.action.common.duplicate", 0x08ccf461);
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.amazon.action.common.nextComponentMode", 0xcc26094f);
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.amazon.action.common.previousComponentMode", 0x0d18ff39);
static const AZ::Crc32 s_backAction = AZ_CRC("com.o3de.action.common.back", 0xd772a2af);
static const AZ::Crc32 s_deleteAction = AZ_CRC("com.o3de.action.common.delete", 0x5731f6cb);
static const AZ::Crc32 s_duplicateAction = AZ_CRC("com.o3de.action.common.duplicate", 0x08ccf461);
static const AZ::Crc32 s_nextComponentMode = AZ_CRC("com.o3de.action.common.nextComponentMode", 0xcc26094f);
static const AZ::Crc32 s_previousComponentMode = AZ_CRC("com.o3de.action.common.previousComponentMode", 0x0d18ff39);
//@}
/// Specific Action properties to be sent to a type implementing
@@ -276,11 +276,6 @@ namespace AzToolsFramework
virtual void EndCursorCapture() = 0;
//! Gets the most recent recorded cursor position in the viewport in screen space coordinates.
virtual AzFramework::ScreenPoint ViewportCursorScreenPosition() = 0;
//! Gets the cursor position recorded prior to the most recent cursor position.
//! Note: The cursor may be captured by the viewport, in which case this may not correspond to the last result
//! from ViewportCursorScreenPosition. This method will always return the correct position to generate a mouse
//! position delta.
virtual AZStd::optional<AzFramework::ScreenPoint> PreviousViewportCursorScreenPosition() = 0;
//! Is mouse over viewport.
virtual bool IsMouseOver() const = 0;
@@ -98,7 +98,7 @@ namespace AzToolsFramework
{
}
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.amazon.action.---").
AZ::Crc32 m_uri; //!< Unique identifier for the Action. (In the form 'com.o3de.action.---").
AZStd::vector<AZStd::function<void()>> m_callbacks; //!< Callbacks associated with this Action (note: with multi-selections
//!< there will be a callback per Entity/Component).
AZStd::unique_ptr<QAction> m_action; //!< The QAction associated with the overrideWidget for all ComponentMode actions.
@@ -196,7 +196,7 @@ namespace AzToolsFramework
AZStd::vector<AzToolsFramework::ActionOverride> PlaceHolderComponentMode::PopulateActionsImpl()
{
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.amazon.action.placeholder.test");
const AZ::Crc32 placeHolderComponentModeAction = AZ_CRC_CE("com.o3de.action.placeholder.test");
return AZStd::vector<AzToolsFramework::ActionOverride>
{
@@ -96,8 +96,8 @@ namespace UnitTest
//apply the patch
PrefabDom& templateDomReference = m_prefabSystemComponent->FindTemplateDom(nestedTemplateId);
AZ::JsonSerializationResult::ResultCode result = AZ::JsonSerialization::ApplyPatch(templateDomReference,
templateDomReference.GetAllocator(), patch, AZ::JsonMergeApproach::JsonPatch);
AZ::JsonSerializationResult::ResultCode result =
PrefabDomUtils::ApplyPatches(templateDomReference, templateDomReference.GetAllocator(), patch);
AZ_Error("Prefab", result.GetOutcome() == AZ::JsonSerializationResult::Outcomes::Success,
"Patch was not successfully applied");
@@ -25,6 +25,8 @@ namespace AWSNativeSDKInit
#if defined(PLATFORM_SUPPORTS_AWS_NATIVE_SDK)
void CustomizeSDKOptions(Aws::SDKOptions& options);
void CustomizeShutdown();
void CopyCaCertBundle();
#endif
}
@@ -44,6 +46,8 @@ namespace AWSNativeSDKInit
void InitializationManager::InitAwsApi()
{
s_initManager = AZ::Environment::CreateVariable<InitializationManager>(initializationManagerTag);
Platform::CopyCaCertBundle();
}
void InitializationManager::Shutdown()
@@ -0,0 +1,89 @@
/*
* 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/PlatformDef.h>
// The AWS Native SDK AWSAllocator triggers a warning due to accessing members of std::allocator directly.
// AWSAllocator.h(70): warning C4996: 'std::allocator<T>::pointer': warning STL4010: Various members of std::allocator are deprecated in
// C++17. Use std::allocator_traits instead of accessing these members directly. You can define
// _SILENCE_CXX17_OLD_ALLOCATOR_MEMBERS_DEPRECATION_WARNING or _SILENCE_ALL_CXX17_DEPRECATION_WARNINGS to acknowledge that you have received
// this warning.
AZ_PUSH_DISABLE_WARNING(4251 4996, "-Wunknown-warning-option")
#include <aws/core/utils/memory/stl/AWSString.h>
AZ_POP_DISABLE_WARNING
#include <AzCore/Android/Utils.h>
#include <AzCore/IO/FileIO.h>
#include <AzCore/IO/SystemFile.h>
#include <AzCore/std/containers/vector.h>
namespace AWSNativeSDKInit
{
namespace Platform
{
void CopyCaCertBundle()
{
AZStd::vector<char> contents;
AZStd::string certificatePath = "@assets@/certificates/aws/cacert.pem";
AZStd::string publicStoragePath = AZ::Android::Utils::GetAppPublicStoragePath();
publicStoragePath.append("/certificates/aws/cacert.pem");
AZ::IO::FileIOBase* fileBase = AZ::IO::FileIOBase::GetInstance();
if (!fileBase->Exists(certificatePath.c_str()))
{
AZ_Error("AWSNativeSDKInit", false, "Certificate File(%s) does not exist.\n", certificatePath.c_str());
}
AZ::IO::HandleType fileHandle;
AZ::IO::Result fileResult = fileBase->Open(certificatePath.c_str(), AZ::IO::OpenMode::ModeRead, fileHandle);
if (!fileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to open certificate file with result %i\n", fileResult.GetResultCode());
}
AZ::u64 fileSize = 0;
fileBase->Size(fileHandle, fileSize);
if (fileSize == 0)
{
AZ_Error("AWSNativeSDKInit", false, "Given empty file(%s) as the certificate bundle.\n", certificatePath.c_str());
}
contents.resize(fileSize + 1);
fileResult = fileBase->Read(fileHandle, contents.data(), fileSize);
if (!fileResult)
{
AZ_Error(
"AWSNativeSDKInit", false, "Failed to read from the certificate bundle(%s) with result code(%i).\n", certificatePath.c_str(),
fileResult.GetResultCode());
}
AZ_Printf("AWSNativeSDKInit", "Certificate bundle is read successfully from %s", certificatePath.c_str());
AZ::IO::HandleType outFileHandle;
AZ::IO::Result outFileResult = fileBase->Open(publicStoragePath.c_str(), AZ::IO::OpenMode::ModeWrite, outFileHandle);
if (!outFileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to open the certificate bundle with result %i\n", fileResult.GetResultCode());
}
AZ::IO::Result writeFileResult = fileBase->Write(outFileHandle, contents.data(), fileSize);
if (!writeFileResult)
{
AZ_Error("AWSNativeSDKInit", false, "Failed to write the certificate bundle with result %i\n", writeFileResult.GetResultCode());
}
fileBase->Close(fileHandle);
fileBase->Close(outFileHandle);
AZ_Printf("AWSNativeSDKInit", "Certificate bundle successfully copied to %s", publicStoragePath.c_str());
}
} // namespace Platform
}
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
InitializeCerts_Android.cpp
)
@@ -0,0 +1,16 @@
/*
* 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
*
*/
namespace AWSNativeSDKInit
{
namespace Platform
{
void CopyCaCertBundle()
{
}
} // namespace Platform
} // namespace AWSCore
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,4 +7,5 @@
set(FILES
../Common/Default/AWSNativeSDKInit_Default.cpp
../Common/Default/InitializeCerts_Null.cpp
)
@@ -7,6 +7,8 @@
#include <AzCore/Serialization/SerializeContext.h>
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
#include <AzCore/RTTI/BehaviorContext.h>
namespace AZ
{
@@ -31,6 +33,12 @@ namespace AZ
{
serializeContext->Class<ExportingComponent, AZ::Component>()->Version(2);
}
AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context);
if (behaviorContext)
{
Events::ExportProductList::Reflect(behaviorContext);
}
}
} // namespace SceneCore
} // namespace SceneAPI
@@ -211,6 +211,7 @@ namespace AZ
AZ::SceneAPI::Containers::SceneGraph::Reflect(context);
AZ::SceneAPI::Containers::SceneManifest::Reflect(context);
AZ::SceneAPI::Containers::RuleContainer::Reflect(context);
AZ::SceneAPI::SceneCore::ExportingComponent::Reflect(context);
}
void Activate()
@@ -6,6 +6,8 @@
*/
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
#include <AzCore/RTTI/BehaviorContext.h>
#include <AzCore/std/limits.h>
namespace AZ
{
@@ -49,6 +51,45 @@ namespace AZ
return *this;
}
void ExportProductList::Reflect(ReflectContext* context)
{
if (auto* serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
{
serializeContext->Class<ExportProduct>()->Version(1);
serializeContext->Class<ExportProductList>()->Version(1);
}
if (auto* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->Class<ExportProduct>("ExportProduct")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Property("filename", BehaviorValueProperty(&ExportProduct::m_filename))
->Property("sourceId", BehaviorValueProperty(&ExportProduct::m_id))
->Property("assetType", BehaviorValueProperty(&ExportProduct::m_assetType))
->Property("productDependencies", BehaviorValueProperty(&ExportProduct::m_productDependencies))
->Property("subId",
[](ExportProduct* self) { return self->m_subId.has_value() ? self->m_subId.value() : 0; },
[](ExportProduct* self, u32 subId) { self->m_subId = AZStd::optional<u32>(subId); });
behaviorContext->Class<ExportProductList>("ExportProductList")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Method("AddProduct", [](ExportProductList& self, ExportProduct& product)
{
self.AddProduct(
product.m_filename,
product.m_id,
product.m_assetType,
product.m_lod,
product.m_subId,
product.m_dependencyFlags);
})
->Method("GetProducts", &ExportProductList::GetProducts)
->Method("AddDependencyToProduct", &ExportProductList::AddDependencyToProduct);
}
}
ExportProduct& ExportProductList::AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags)
{
@@ -14,6 +14,8 @@
namespace AZ
{
class ReflectContext;
namespace SceneAPI
{
namespace Events
@@ -24,6 +26,7 @@ namespace AZ
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
SCENE_CORE_API ExportProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
ExportProduct() = default;
ExportProduct(const ExportProduct& rhs) = default;
SCENE_CORE_API ExportProduct(ExportProduct&& rhs);
@@ -54,6 +57,8 @@ namespace AZ
class ExportProductList
{
public:
static void Reflect(ReflectContext* context);
SCENE_CORE_API ExportProduct& AddProduct(const AZStd::string& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
Data::ProductDependencyInfo::ProductDependencyFlags dependencyFlags = Data::ProductDependencyInfo::CreateFlags(Data::AssetLoadBehavior::NoLoad));
SCENE_CORE_API ExportProduct& AddProduct(AZStd::string&& filename, Uuid id, Data::AssetType assetType, AZStd::optional<u8> lod, AZStd::optional<u32> subId,
@@ -69,3 +74,9 @@ namespace AZ
} // namespace Events
} // namespace SceneAPI
} // namespace AZ
namespace AZ
{
AZ_TYPE_INFO_SPECIALIZE(SceneAPI::Events::ExportProduct, "{6054EDCB-4C04-4D96-BF26-704999FFB725}");
AZ_TYPE_INFO_SPECIALIZE(SceneAPI::Events::ExportProductList, "{1C76A51F-431B-4987-B653-CFCC940D0D0F}");
}
@@ -10,6 +10,7 @@
#include <AzCore/IO/SystemFile.h>
#include <AzCore/IO/GenericStreams.h>
#include <AzCore/Memory/SystemAllocator.h>
#include <AzCore/Utils/Utils.h>
#include <AzFramework/API/ApplicationAPI.h>
#include <AzFramework/StringFunc/StringFunc.h>
#include <SceneAPI/SceneCore/Import/ManifestImportRequestHandler.h>
@@ -75,15 +76,16 @@ namespace AZ
filename += s_extension;
filename += s_generated;
AZStd::string altManifestPath = path;
AZStd::string altManifestFolder = path;
AzFramework::ApplicationRequests::Bus::Broadcast(
&AzFramework::ApplicationRequests::Bus::Events::MakePathRootRelative,
altManifestPath);
&AzFramework::ApplicationRequests::Bus::Events::MakePathRelative,
altManifestFolder,
AZ::Utils::GetProjectPath().c_str());
AZ::StringFunc::Path::GetFolderPath(altManifestPath.c_str(), altManifestPath);
AZ::StringFunc::Path::GetFolderPath(altManifestFolder.c_str(), altManifestFolder);
AZStd::string generatedAssetInfoPath;
AZ::StringFunc::Path::Join(assetCacheRoot.c_str(), altManifestPath.c_str(), generatedAssetInfoPath);
AZ::StringFunc::Path::Join(assetCacheRoot.c_str(), altManifestFolder.c_str(), generatedAssetInfoPath);
AZ::StringFunc::Path::ConstructFull(generatedAssetInfoPath.c_str(), filename.c_str(), generatedAssetInfoPath);
if (!AZ::IO::FileIOBase::GetInstance()->Exists(generatedAssetInfoPath.c_str()))
File diff suppressed because it is too large Load Diff
@@ -25,213 +25,319 @@
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
#include <SceneAPI/SceneData/Rules/ScriptProcessorRule.h>
#include <SceneAPI/SceneCore/Utilities/Reporting.h>
#include <SceneAPI/SceneCore/Events/ExportProductList.h>
namespace AZ
namespace AZ::SceneAPI::Behaviors
{
namespace SceneAPI
class EditorPythonConsoleNotificationHandler final
: protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
{
namespace Behaviors
public:
EditorPythonConsoleNotificationHandler()
{
class EditorPythonConsoleNotificationHandler final
: protected AzToolsFramework::EditorPythonConsoleNotificationBus::Handler
BusConnect();
}
~EditorPythonConsoleNotificationHandler()
{
BusDisconnect();
}
////////////////////////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorPythonConsoleNotifications
void OnTraceMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(LogWindow, "%.*s \n", AZ_STRING_ARG(message));
}
void OnErrorMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(ErrorWindow, "[ERROR] %.*s \n", AZ_STRING_ARG(message));
}
void OnExceptionMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(ErrorWindow, "[EXCEPTION] %.*s \n", AZ_STRING_ARG(message));
}
};
using ExportProductList = AZ::SceneAPI::Events::ExportProductList;
// a event bus to signal during scene building
struct ScriptBuildingNotifications
: public AZ::EBusTraits
{
virtual AZStd::string OnUpdateManifest(Containers::Scene& scene) = 0;
virtual ExportProductList OnPrepareForExport(
const Containers::Scene& scene,
AZStd::string_view outputDirectory,
AZStd::string_view platformIdentifier,
const ExportProductList& productList) = 0;
};
using ScriptBuildingNotificationBus = AZ::EBus<ScriptBuildingNotifications>;
// a back end to handle scene builder events for a script
struct ScriptBuildingNotificationBusHandler final
: public ScriptBuildingNotificationBus::Handler
, public AZ::BehaviorEBusHandler
{
AZ_EBUS_BEHAVIOR_BINDER(
ScriptBuildingNotificationBusHandler,
"{DF2B51DE-A4D0-4139-B5D0-DF185832380D}",
AZ::SystemAllocator,
OnUpdateManifest,
OnPrepareForExport);
virtual ~ScriptBuildingNotificationBusHandler() = default;
AZStd::string OnUpdateManifest(Containers::Scene& scene) override
{
AZStd::string result;
CallResult(result, FN_OnUpdateManifest, scene);
return result;
}
ExportProductList OnPrepareForExport(
const Containers::Scene& scene,
AZStd::string_view outputDirectory,
AZStd::string_view platformIdentifier,
const ExportProductList& productList) override
{
ExportProductList result;
CallResult(result, FN_OnPrepareForExport, scene, outputDirectory, platformIdentifier, productList);
return result;
}
static void Reflect(AZ::ReflectContext* context)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
public:
EditorPythonConsoleNotificationHandler()
{
BusConnect();
}
behaviorContext->EBus<ScriptBuildingNotificationBus>("ScriptBuildingNotificationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Handler<ScriptBuildingNotificationBusHandler>()
->Event("OnUpdateManifest", &ScriptBuildingNotificationBus::Events::OnUpdateManifest)
->Event("OnPrepareForExport", &ScriptBuildingNotificationBus::Events::OnPrepareForExport);
}
}
};
~EditorPythonConsoleNotificationHandler()
{
BusDisconnect();
}
struct ScriptProcessorRuleBehavior::ExportEventHandler final
: public AZ::SceneAPI::SceneCore::ExportingComponent
{
using PreExportEventContextFunction = AZStd::function<bool(Events::PreExportEventContext&)>;
PreExportEventContextFunction m_preExportEventContextFunction;
////////////////////////////////////////////////////////////////////////////////////////////
// AzToolsFramework::EditorPythonConsoleNotifications
void OnTraceMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(LogWindow, "%.*s \n", AZ_STRING_ARG(message));
}
ExportEventHandler(PreExportEventContextFunction preExportEventContextFunction)
: m_preExportEventContextFunction(preExportEventContextFunction)
{
BindToCall(&ExportEventHandler::PrepareForExport);
AZ::SceneAPI::SceneCore::ExportingComponent::Activate();
}
void OnErrorMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(ErrorWindow, "[ERROR] %.*s \n", AZ_STRING_ARG(message));
}
~ExportEventHandler()
{
AZ::SceneAPI::SceneCore::ExportingComponent::Deactivate();
}
void OnExceptionMessage([[maybe_unused]] AZStd::string_view message) override
{
using namespace AZ::SceneAPI::Utilities;
AZ_TracePrintf(ErrorWindow, "[EXCEPTION] %.*s \n", AZ_STRING_ARG(message));
}
};
// this allows a Python script to add product assets on "scene export"
Events::ProcessingResult PrepareForExport(Events::PreExportEventContext& context)
{
return m_preExportEventContextFunction(context) ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
}
};
// a event bus to signal during scene building
struct ScriptBuildingNotifications
: public AZ::EBusTraits
void ScriptProcessorRuleBehavior::Activate()
{
Events::AssetImportRequestBus::Handler::BusConnect();
m_exportEventHandler = AZStd::make_shared<ExportEventHandler>([this](Events::PreExportEventContext& context)
{
return this->DoPrepareForExport(context);
});
}
void ScriptProcessorRuleBehavior::Deactivate()
{
m_exportEventHandler.reset();
Events::AssetImportRequestBus::Handler::BusDisconnect();
UnloadPython();
}
bool ScriptProcessorRuleBehavior::LoadPython(const AZ::SceneAPI::Containers::Scene& scene)
{
if (m_editorPythonEventsInterface && !m_scriptFilename.empty())
{
return true;
}
// get project folder
auto settingsRegistry = AZ::SettingsRegistry::Get();
AZ::IO::FixedMaxPath projectPath;
if (!settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
{
return false;
}
const AZ::SceneAPI::Containers::SceneManifest& manifest = scene.GetManifest();
auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(manifest.GetValueStorage());
for (const auto& scriptItem : view)
{
AZ::IO::FixedMaxPath scriptFilename(scriptItem.GetScriptFilename());
if (scriptFilename.empty())
{
virtual AZStd::string OnUpdateManifest(Containers::Scene& scene) = 0;
};
using ScriptBuildingNotificationBus = AZ::EBus<ScriptBuildingNotifications>;
AZ_Warning("scene", false, "Skipping an empty script filename in (%s)", scene.GetManifestFilename().c_str());
continue;
}
// a back end to handle scene builder events for a script
struct ScriptBuildingNotificationBusHandler final
: public ScriptBuildingNotificationBus::Handler
, public AZ::BehaviorEBusHandler
// check for file exist via absolute path
if (!IO::FileIOBase::GetInstance()->Exists(scriptFilename.c_str()))
{
AZ_EBUS_BEHAVIOR_BINDER(
ScriptBuildingNotificationBusHandler,
"{DF2B51DE-A4D0-4139-B5D0-DF185832380D}",
AZ::SystemAllocator,
OnUpdateManifest);
virtual ~ScriptBuildingNotificationBusHandler() = default;
AZStd::string OnUpdateManifest(Containers::Scene& scene) override
// check for script in the project folder
AZ::IO::FixedMaxPath projectScriptPath = projectPath / scriptFilename;
if (!IO::FileIOBase::GetInstance()->Exists(projectScriptPath.c_str()))
{
AZStd::string result;
CallResult(result, FN_OnUpdateManifest, scene);
return result;
AZ_Warning("scene", false, "Skipping a missing script (%s) in manifest file (%s)",
scriptFilename.c_str(),
scene.GetManifestFilename().c_str());
continue;
}
scriptFilename = AZStd::move(projectScriptPath);
}
static void Reflect(AZ::ReflectContext* context)
// lazy load the Python interface
auto editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
if (editorPythonEventsInterface->IsPythonActive() == false)
{
const bool silenceWarnings = false;
if (editorPythonEventsInterface->StartPython(silenceWarnings) == false)
{
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
{
behaviorContext->EBus<ScriptBuildingNotificationBus>("ScriptBuildingNotificationBus")
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation)
->Attribute(AZ::Script::Attributes::Module, "scene")
->Handler<ScriptBuildingNotificationBusHandler>()
->Event("OnUpdateManifest", &ScriptBuildingNotificationBus::Events::OnUpdateManifest);
}
editorPythonEventsInterface = nullptr;
}
}
// both Python and the script need to be ready
if (editorPythonEventsInterface == nullptr || scriptFilename.empty())
{
AZ_Warning("scene", false,"The scene manifest (%s) attempted to use script(%s) but Python is not enabled;"
"please add the EditorPythonBinding gem & PythonAssetBuilder gem to your project.",
scene.GetManifestFilename().c_str(), scriptFilename.c_str());
return false;
}
m_editorPythonEventsInterface = editorPythonEventsInterface;
m_scriptFilename = scriptFilename.c_str();
return true;
}
return false;
}
void ScriptProcessorRuleBehavior::UnloadPython()
{
if (m_editorPythonEventsInterface)
{
const bool silenceWarnings = true;
m_editorPythonEventsInterface->StopPython(silenceWarnings);
m_editorPythonEventsInterface = nullptr;
}
}
bool ScriptProcessorRuleBehavior::DoPrepareForExport(Events::PreExportEventContext& context)
{
using namespace AzToolsFramework;
auto executeCallback = [this, &context]()
{
// set up script's hook callback
EditorPythonRunnerRequestBus::Broadcast(&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
m_scriptFilename.c_str());
// call script's callback to allow extra products
ExportProductList extraProducts;
ScriptBuildingNotificationBus::BroadcastResult(extraProducts, &ScriptBuildingNotificationBus::Events::OnPrepareForExport,
context.GetScene(),
context.GetOutputDirectory(),
context.GetPlatformIdentifier(),
context.GetProductList()
);
// add new products
for (const auto& product : extraProducts.GetProducts())
{
context.GetProductList().AddProduct(
product.m_filename,
product.m_id,
product.m_assetType,
product.m_lod,
product.m_subId,
product.m_dependencyFlags);
}
};
if (LoadPython(context.GetScene()))
{
EditorPythonConsoleNotificationHandler logger;
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
}
return true;
}
void ScriptProcessorRuleBehavior::Reflect(ReflectContext* context)
{
ScriptBuildingNotificationBusHandler::Reflect(context);
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ScriptProcessorRuleBehavior, BehaviorComponent>()->Version(1);
}
}
Events::ProcessingResult ScriptProcessorRuleBehavior::UpdateManifest(
Containers::Scene& scene,
Events::AssetImportRequest::ManifestAction action,
[[maybe_unused]] Events::AssetImportRequest::RequestingApplication requester)
{
using namespace AzToolsFramework;
if (action != ManifestAction::Update)
{
return Events::ProcessingResult::Ignored;
}
if (LoadPython(scene))
{
AZStd::string manifestUpdate;
auto executeCallback = [this, &scene, &manifestUpdate]()
{
EditorPythonRunnerRequestBus::Broadcast(&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
m_scriptFilename.c_str());
ScriptBuildingNotificationBus::BroadcastResult(manifestUpdate, &ScriptBuildingNotificationBus::Events::OnUpdateManifest,
scene);
};
void ScriptProcessorRuleBehavior::Activate()
EditorPythonConsoleNotificationHandler logger;
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
// attempt to load the manifest string back to a JSON-scene-manifest
auto sceneManifestLoader = AZStd::make_unique<AZ::SceneAPI::Containers::SceneManifest>();
auto loadOutcome = sceneManifestLoader->LoadFromString(manifestUpdate);
if (loadOutcome.IsSuccess())
{
Events::AssetImportRequestBus::Handler::BusConnect();
scene.GetManifest().Clear();
for (size_t entryIndex = 0; entryIndex < sceneManifestLoader->GetEntryCount(); ++entryIndex)
{
scene.GetManifest().AddEntry(sceneManifestLoader->GetValue(entryIndex));
}
return Events::ProcessingResult::Success;
}
}
return Events::ProcessingResult::Ignored;
}
void ScriptProcessorRuleBehavior::Deactivate()
{
Events::AssetImportRequestBus::Handler::BusDisconnect();
if (m_editorPythonEventsInterface)
{
const bool silenceWarnings = true;
m_editorPythonEventsInterface->StopPython(silenceWarnings);
m_editorPythonEventsInterface = nullptr;
}
}
void ScriptProcessorRuleBehavior::Reflect(ReflectContext* context)
{
ScriptBuildingNotificationBusHandler::Reflect(context);
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
if (serializeContext)
{
serializeContext->Class<ScriptProcessorRuleBehavior, BehaviorComponent>()->Version(1);
}
}
Events::ProcessingResult ScriptProcessorRuleBehavior::UpdateManifest(
Containers::Scene& scene,
Events::AssetImportRequest::ManifestAction action,
[[maybe_unused]] Events::AssetImportRequest::RequestingApplication requester)
{
using namespace AzToolsFramework;
if (action != ManifestAction::Update)
{
return Events::ProcessingResult::Ignored;
}
// get project folder
auto settingsRegistry = AZ::SettingsRegistry::Get();
AZ::IO::FixedMaxPath projectPath;
if (!settingsRegistry->Get(projectPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectPath))
{
return Events::ProcessingResult::Ignored;
}
auto& sceneManifest = scene.GetManifest();
auto view = Containers::MakeDerivedFilterView<DataTypes::IScriptProcessorRule>(sceneManifest.GetValueStorage());
for (const auto& scriptItem : view)
{
AZ::IO::FixedMaxPath scriptFilename(scriptItem.GetScriptFilename());
if (scriptFilename.empty())
{
AZ_Warning("scene", false, "Skipping an empty script filename in (%s)", scene.GetManifestFilename().c_str());
continue;
}
// check for file exist via absolute path
if (!IO::FileIOBase::GetInstance()->Exists(scriptFilename.c_str()))
{
// check for script in the project folder
AZ::IO::FixedMaxPath projectScriptPath = projectPath / scriptFilename;
if (!IO::FileIOBase::GetInstance()->Exists(projectScriptPath.c_str()))
{
AZ_Warning("scene", false, "Skipping a missing script (%s) in manifest file (%s)",
scriptFilename.c_str(),
scene.GetManifestFilename().c_str());
continue;
}
scriptFilename = AZStd::move(projectScriptPath);
}
// lazy load the Python interface
if (!m_editorPythonEventsInterface)
{
m_editorPythonEventsInterface = AZ::Interface<AzToolsFramework::EditorPythonEventsInterface>::Get();
const bool silenceWarnings = true;
m_editorPythonEventsInterface->StartPython(silenceWarnings);
}
if (!m_editorPythonEventsInterface && !scriptFilename.empty())
{
AZ_Warning("scene", false,
"The scene manifest (%s) attempted to use script(%s) but Python is not enabled;"
"please add the EditorPythonBinding gem & PythonAssetBuilder gem to your project.",
scene.GetManifestFilename().c_str(), scriptFilename.c_str());
return Events::ProcessingResult::Ignored;
}
AZStd::string manifestUpdate;
auto executeCallback = [&scene, &scriptFilename, &manifestUpdate]()
{
EditorPythonRunnerRequestBus::Broadcast(
&EditorPythonRunnerRequestBus::Events::ExecuteByFilename,
scriptFilename.c_str());
ScriptBuildingNotificationBus::BroadcastResult(
manifestUpdate,
&ScriptBuildingNotificationBus::Events::OnUpdateManifest,
scene);
};
EditorPythonConsoleNotificationHandler logger;
m_editorPythonEventsInterface->ExecuteWithLock(executeCallback);
// attempt to load the manifest string back to a JSON-scene-manifest
auto sceneManifestLoader = AZStd::make_unique<AZ::SceneAPI::Containers::SceneManifest>();
auto loadOutcome = sceneManifestLoader->LoadFromString(manifestUpdate);
if (loadOutcome.IsSuccess())
{
sceneManifest.Clear();
for (size_t entryIndex = 0; entryIndex < sceneManifestLoader->GetEntryCount(); ++entryIndex)
{
sceneManifest.AddEntry(sceneManifestLoader->GetValue(entryIndex));
}
return Events::ProcessingResult::Success;
}
}
return Events::ProcessingResult::Ignored;
}
} // namespace Behaviors
} // namespace SceneAPI
} // namespace AZ
@@ -11,40 +11,56 @@
#include <AzCore/std/string/string.h>
#include <SceneAPI/SceneCore/Components/BehaviorComponent.h>
#include <SceneAPI/SceneCore/Events/AssetImportRequest.h>
#include <SceneAPI/SceneCore/Components/ExportingComponent.h>
#include <SceneAPI/SceneCore/Events/ExportEventContext.h>
namespace AzToolsFramework
{
class EditorPythonEventsInterface;
}
namespace AZ
namespace AZ::SceneAPI::Events
{
namespace SceneAPI
class PreExportEventContext;
}
namespace AZ::SceneAPI::Containers
{
class Scene;
}
namespace AZ::SceneAPI::Behaviors
{
class SCENE_DATA_CLASS ScriptProcessorRuleBehavior
: public SceneCore::BehaviorComponent
, public Events::AssetImportRequestBus::Handler
{
namespace Behaviors
{
class SCENE_DATA_CLASS ScriptProcessorRuleBehavior
: public SceneCore::BehaviorComponent
, public Events::AssetImportRequestBus::Handler
{
public:
AZ_COMPONENT(ScriptProcessorRuleBehavior, "{24054E73-1B92-43B0-AC13-174B2F0E3F66}", SceneCore::BehaviorComponent);
public:
AZ_COMPONENT(ScriptProcessorRuleBehavior, "{24054E73-1B92-43B0-AC13-174B2F0E3F66}", SceneCore::BehaviorComponent);
~ScriptProcessorRuleBehavior() override = default;
~ScriptProcessorRuleBehavior() override = default;
SCENE_DATA_API void Activate() override;
SCENE_DATA_API void Deactivate() override;
static void Reflect(ReflectContext* context);
SCENE_DATA_API void Activate() override;
SCENE_DATA_API void Deactivate() override;
static void Reflect(ReflectContext* context);
// AssetImportRequestBus::Handler
SCENE_DATA_API Events::ProcessingResult UpdateManifest(
Containers::Scene& scene,
ManifestAction action,
RequestingApplication requester) override;
// AssetImportRequestBus::Handler
SCENE_DATA_API Events::ProcessingResult UpdateManifest(
Containers::Scene& scene,
ManifestAction action,
RequestingApplication requester) override;
private:
AzToolsFramework::EditorPythonEventsInterface* m_editorPythonEventsInterface = nullptr;
};
} // namespace SceneData
} // namespace SceneAPI
} // namespace AZ
protected:
bool LoadPython(const AZ::SceneAPI::Containers::Scene& scene);
void UnloadPython();
bool DoPrepareForExport(Events::PreExportEventContext& context);
private:
AzToolsFramework::EditorPythonEventsInterface* m_editorPythonEventsInterface = nullptr;
AZStd::string m_scriptFilename;
struct ExportEventHandler;
AZStd::shared_ptr<ExportEventHandler> m_exportEventHandler;
};
} // namespace AZ::SceneAPI::Behaviors