Merge branch 'main' into transform-float-scale
This commit is contained in:
@@ -26,19 +26,23 @@ TEST_DIRECTORY = os.path.join(os.path.dirname(__file__), "atom_hydra_scripts")
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
@pytest.mark.parametrize("level", ["auto_test"])
|
||||
class TestAtomEditorComponentsMain(object):
|
||||
"""Holds tests for Atom components."""
|
||||
|
||||
@pytest.mark.test_case_id(
|
||||
"C32078130", # Display Mapper
|
||||
"C32078129", # Light
|
||||
"C32078131", # Radius Weight Modifier
|
||||
"C32078127", # PostFX Layer
|
||||
"C32078125", # Physical Sky
|
||||
"C32078115", # Global Skylight (IBL)
|
||||
"C32078121", # Exposure Control
|
||||
"C32078120", # Directional Light
|
||||
"C32078119", # DepthOfField
|
||||
"C32078118") # Decal (Atom)
|
||||
def test_AtomEditorComponents_AddedToEntity(self, request, editor, level, workspace, project, launcher_platform):
|
||||
"""
|
||||
Please review the hydra script run by this test for more specific test info.
|
||||
Tests the following Atom components and verifies all "expected_lines" appear in Editor.log:
|
||||
1. Display Mapper
|
||||
2. Light
|
||||
3. Radius Weight Modifier
|
||||
4. PostFX Layer
|
||||
5. Physical Sky
|
||||
6. Global Skylight (IBL)
|
||||
7. Exposure Control
|
||||
8. Directional Light
|
||||
9. DepthOfField
|
||||
10. Decal (Atom)
|
||||
"""
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
|
||||
+12
-1
@@ -81,9 +81,20 @@ namespace AzToolsFramework
|
||||
|
||||
m_ui->m_assetBrowserTreeViewWidget->SetName("AssetBrowserTreeView_" + name);
|
||||
|
||||
bool selectedAsset = false;
|
||||
|
||||
for (auto& assetId : selection.GetSelectedAssetIds())
|
||||
{
|
||||
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
|
||||
if (assetId.IsValid())
|
||||
{
|
||||
selectedAsset = true;
|
||||
m_ui->m_assetBrowserTreeViewWidget->SelectProduct(assetId);
|
||||
}
|
||||
}
|
||||
|
||||
if (!selectedAsset)
|
||||
{
|
||||
m_ui->m_assetBrowserTreeViewWidget->SelectFolder(selection.GetDefaultDirectory());
|
||||
}
|
||||
|
||||
setWindowTitle(tr("Pick %1").arg(m_selection.GetTitle()));
|
||||
|
||||
@@ -93,6 +93,16 @@ namespace AzToolsFramework
|
||||
m_selectedAssetIds.push_back(selectedAssetId);
|
||||
}
|
||||
|
||||
void AssetSelectionModel::SetDefaultDirectory(AZStd::string_view defaultDirectory)
|
||||
{
|
||||
m_defaultDirectory = defaultDirectory;
|
||||
}
|
||||
|
||||
AZStd::string_view AssetSelectionModel::GetDefaultDirectory() const
|
||||
{
|
||||
return m_defaultDirectory;
|
||||
}
|
||||
|
||||
AZStd::vector<const AssetBrowserEntry*>& AssetSelectionModel::GetResults()
|
||||
{
|
||||
return m_results;
|
||||
|
||||
@@ -47,6 +47,9 @@ namespace AzToolsFramework
|
||||
const AZStd::vector<AZ::Data::AssetId>& GetSelectedAssetIds() const;
|
||||
void SetSelectedAssetIds(const AZStd::vector<AZ::Data::AssetId>& selectedAssetIds);
|
||||
void SetSelectedAssetId(const AZ::Data::AssetId& selectedAssetId);
|
||||
|
||||
void SetDefaultDirectory(AZStd::string_view defaultDirectory);
|
||||
AZStd::string_view GetDefaultDirectory() const;
|
||||
|
||||
AZStd::vector<const AssetBrowserEntry*>& GetResults();
|
||||
const AssetBrowserEntry* GetResult();
|
||||
@@ -72,6 +75,7 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::vector<AZ::Data::AssetId> m_selectedAssetIds;
|
||||
AZStd::vector<const AssetBrowserEntry*> m_results;
|
||||
AZStd::string m_defaultDirectory;
|
||||
|
||||
QString m_title;
|
||||
};
|
||||
|
||||
+45
-18
@@ -14,6 +14,7 @@
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
#include <AzCore/Math/Crc.h>
|
||||
#include <AzCore/std/containers/vector.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
|
||||
@@ -270,7 +271,20 @@ namespace AzToolsFramework
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex)
|
||||
void AssetBrowserTreeView::SelectFolder(AZStd::string_view folderPath)
|
||||
{
|
||||
if (folderPath.size() == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::vector<AZStd::string> entries;
|
||||
AZ::StringFunc::Tokenize(folderPath, entries, "/");
|
||||
|
||||
SelectEntry(QModelIndex(), entries, 0, true);
|
||||
}
|
||||
|
||||
bool AssetBrowserTreeView::SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entries, const uint32_t entryPathIndex, bool useDisplayName)
|
||||
{
|
||||
if (entries.empty())
|
||||
{
|
||||
@@ -285,30 +299,43 @@ namespace AzToolsFramework
|
||||
auto rowIdx = model()->index(idx, 0, idxParent);
|
||||
auto rowEntry = GetEntryFromIndex<AssetBrowserEntry>(rowIdx);
|
||||
|
||||
// Check if this entry name matches the query
|
||||
if (rowEntry && AzFramework::StringFunc::Equal(entry.c_str(), rowEntry->GetName().c_str(), true))
|
||||
if (rowEntry)
|
||||
{
|
||||
// Final entry found - set it as the selected element
|
||||
if (entryPathIndex == entries.size() - 1)
|
||||
{
|
||||
selectionModel()->clear();
|
||||
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
|
||||
setCurrentIndex(rowIdx);
|
||||
return true;
|
||||
}
|
||||
// Check if this entry name matches the query
|
||||
AZStd::string_view compareName = useDisplayName ? (const char*)(rowEntry->GetDisplayName().toUtf8()) : rowEntry->GetName().c_str();
|
||||
|
||||
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
|
||||
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
|
||||
if (AzFramework::StringFunc::Equal(entry.c_str(), compareName, true))
|
||||
{
|
||||
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset Browser (otherwise, early out)
|
||||
if (SelectEntry(rowIdx, entries, entryPathIndex + 1))
|
||||
// Final entry found - set it as the selected element
|
||||
if (entryPathIndex == entries.size() - 1)
|
||||
{
|
||||
expand(rowIdx);
|
||||
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
|
||||
{
|
||||
// Expand the item itself if it is a folder
|
||||
expand(rowIdx);
|
||||
}
|
||||
|
||||
selectionModel()->clear();
|
||||
selectionModel()->select(rowIdx, QItemSelectionModel::Select);
|
||||
setCurrentIndex(rowIdx);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// If this isn't the final entry, it needs to be a folder for the path to be valid (otherwise, early out)
|
||||
if (rowEntry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Folder)
|
||||
{
|
||||
// Folder found - if the final entry is found, expand this folder so the final entry is viewable in the Asset
|
||||
// Browser (otherwise, early out)
|
||||
if (SelectEntry(rowIdx, entries, entryPathIndex + 1, useDisplayName))
|
||||
{
|
||||
expand(rowIdx);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+4
-1
@@ -60,6 +60,8 @@ namespace AzToolsFramework
|
||||
|
||||
AZStd::vector<AssetBrowserEntry*> GetSelectedAssets() const;
|
||||
|
||||
void SelectFolder(AZStd::string_view folderPath);
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
// AssetBrowserViewRequestBus
|
||||
void SelectProduct(AZ::Data::AssetId assetID) override;
|
||||
@@ -67,6 +69,7 @@ namespace AzToolsFramework
|
||||
void ClearFilter() override;
|
||||
|
||||
void Update() override;
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -105,7 +108,7 @@ namespace AzToolsFramework
|
||||
QString m_name;
|
||||
|
||||
bool SelectProduct(const QModelIndex& idxParent, AZ::Data::AssetId assetID);
|
||||
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0);
|
||||
bool SelectEntry(const QModelIndex& idxParent, const AZStd::vector<AZStd::string>& entryPathTokens, const uint32_t entryPathIndex = 0, bool useDisplayName = false);
|
||||
|
||||
//! Grab one entry from the source thumbnail list and update it
|
||||
void UpdateSCThumbnails();
|
||||
|
||||
+18
@@ -769,6 +769,14 @@ namespace AzToolsFramework
|
||||
// Request the AssetBrowser Dialog and set a type filter
|
||||
AssetSelectionModel selection = GetAssetSelectionModel();
|
||||
selection.SetSelectedAssetId(m_selectedAssetID);
|
||||
|
||||
AZStd::string defaultDirectory;
|
||||
if (m_defaultDirectoryCallback)
|
||||
{
|
||||
m_defaultDirectoryCallback->Invoke(m_editNotifyTarget, defaultDirectory);
|
||||
selection.SetDefaultDirectory(defaultDirectory);
|
||||
}
|
||||
|
||||
AssetBrowserComponentRequestBus::Broadcast(&AssetBrowserComponentRequests::PickAssets, selection, parentWidget());
|
||||
if (selection.IsValid())
|
||||
{
|
||||
@@ -1080,6 +1088,11 @@ namespace AzToolsFramework
|
||||
m_editNotifyCallback = editNotifyCallback;
|
||||
}
|
||||
|
||||
void PropertyAssetCtrl::SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback)
|
||||
{
|
||||
m_defaultDirectoryCallback = callback;
|
||||
}
|
||||
|
||||
void PropertyAssetCtrl::SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback)
|
||||
{
|
||||
m_clearNotifyCallback = clearNotifyCallback;
|
||||
@@ -1214,6 +1227,11 @@ namespace AzToolsFramework
|
||||
GUI->SetTitle(title.c_str());
|
||||
}
|
||||
}
|
||||
else if (attrib == AZ_CRC_CE("DefaultStartingDirectoryCallback"))
|
||||
{
|
||||
// This is assumed to be an Asset Browser path to a specific folder to be used as a default by the asset picker if provided
|
||||
GUI->SetDefaultDirectoryCallback(azdynamic_cast<PropertyAssetCtrl::DefaultDirectoryCallbackType*>(attrValue->GetAttribute()));
|
||||
}
|
||||
else if (attrib == AZ_CRC("EditCallback", 0xb74f2ee1))
|
||||
{
|
||||
PropertyAssetCtrl::EditCallbackType* func = azdynamic_cast<PropertyAssetCtrl::EditCallbackType*>(attrValue->GetAttribute());
|
||||
|
||||
+3
@@ -68,6 +68,7 @@ namespace AzToolsFramework
|
||||
// This is meant to be used with the "EditCallback" Attribute
|
||||
using EditCallbackType = AZ::Edit::AttributeFunction<void(const AZ::Data::AssetId&, const AZ::Data::AssetType&)>;
|
||||
using ClearCallbackType = AZ::Edit::AttributeFunction<void()>;
|
||||
using DefaultDirectoryCallbackType = AZ::Edit::AttributeFunction<void(AZStd::string&)>;
|
||||
|
||||
PropertyAssetCtrl(QWidget *pParent = NULL, QString optionalValidDragDropExtensions = QString());
|
||||
virtual ~PropertyAssetCtrl();
|
||||
@@ -119,6 +120,7 @@ namespace AzToolsFramework
|
||||
EditCallbackType* m_editNotifyCallback = nullptr;
|
||||
ClearCallbackType* m_clearNotifyCallback = nullptr;
|
||||
QString m_optionalValidDragDropExtensions;
|
||||
DefaultDirectoryCallbackType* m_defaultDirectoryCallback = nullptr;
|
||||
|
||||
//! The number of characters after which the autocompleter dropdown will be shown.
|
||||
// Prevents showing too many options.
|
||||
@@ -196,6 +198,7 @@ namespace AzToolsFramework
|
||||
void SetEditNotifyTarget(void* editNotifyTarget);
|
||||
void SetEditNotifyCallback(EditCallbackType* editNotifyCallback); // This is meant to be used with the "EditCallback" Attribute
|
||||
void SetClearNotifyCallback(ClearCallbackType* clearNotifyCallback); // This is meant to be used with the "ClearNotify" Attribute
|
||||
void SetDefaultDirectoryCallback(DefaultDirectoryCallbackType* callback); // This is meant to be used with the "DefaultStartingDirectoryCallback" Attribute
|
||||
void SetEditButtonEnabled(bool enabled);
|
||||
void SetEditButtonVisible(bool visible);
|
||||
void SetEditButtonIcon(const QIcon& icon);
|
||||
|
||||
@@ -58,13 +58,11 @@
|
||||
#include "LevelFileDialog.h"
|
||||
#include "StatObjBus.h"
|
||||
|
||||
// LmbrCentral
|
||||
#include <ModernViewportCameraController.h>
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <Atom/RPI.Public/ViewportContextBus.h>
|
||||
#include <LmbrCentral/Rendering/EditorLightComponentBus.h> // for LmbrCentral::EditorLightComponentRequestBus
|
||||
|
||||
|
||||
// LmbrCentral
|
||||
#include <LmbrCentral/Rendering/EditorLightComponentBus.h> // for LmbrCentral::EditorLightComponentRequestBus
|
||||
|
||||
//#define PROFILE_LOADING_WITH_VTUNE
|
||||
|
||||
|
||||
@@ -53,6 +53,7 @@
|
||||
|
||||
// AtomToolsFramework
|
||||
#include <AtomToolsFramework/Viewport/RenderViewportWidget.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
|
||||
|
||||
// CryCommon
|
||||
#include <CryCommon/HMDBus.h>
|
||||
@@ -75,7 +76,6 @@
|
||||
#include "EditorPreferencesPageGeneral.h"
|
||||
#include "ViewportManipulatorController.h"
|
||||
#include "LegacyViewportCameraController.h"
|
||||
#include "ModernViewportCameraController.h"
|
||||
#include "EditorViewportSettings.h"
|
||||
|
||||
#include "ViewPane.h"
|
||||
@@ -1220,7 +1220,7 @@ void EditorViewportWidget::SetViewportId(int id)
|
||||
{
|
||||
AzFramework::ReloadCameraKeyBindings();
|
||||
|
||||
auto controller = AZStd::make_shared<SandboxEditor::ModernViewportCameraController>();
|
||||
auto controller = AZStd::make_shared<AtomToolsFramework::ModularViewportCameraController>();
|
||||
controller->SetCameraListBuilderCallback([](AzFramework::Cameras& cameras)
|
||||
{
|
||||
auto firstPersonRotateCamera = AZStd::make_shared<AzFramework::RotateCameraInput>(AzFramework::CameraFreeLookButton);
|
||||
|
||||
@@ -823,9 +823,6 @@ set(FILES
|
||||
ViewportManipulatorController.h
|
||||
LegacyViewportCameraController.cpp
|
||||
LegacyViewportCameraController.h
|
||||
ModernViewportCameraController.cpp
|
||||
ModernViewportCameraController.h
|
||||
ModernViewportCameraControllerRequestBus.h
|
||||
RenderViewport.cpp
|
||||
RenderViewport.h
|
||||
TopRendererWnd.cpp
|
||||
|
||||
@@ -38,6 +38,7 @@ ly_add_target(
|
||||
Gem::LmbrCentral
|
||||
AZ::AtomCore
|
||||
Gem::Atom_RPI.Public
|
||||
Gem::AtomToolsFramework.Static
|
||||
)
|
||||
|
||||
ly_add_dependencies(Editor ComponentEntityEditorPlugin)
|
||||
|
||||
@@ -66,8 +66,8 @@
|
||||
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <Atom/RPI.Public/ViewportContextBus.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h>
|
||||
|
||||
#include <ModernViewportCameraControllerRequestBus.h>
|
||||
|
||||
#include "Objects/ComponentEntityObject.h"
|
||||
#include "ISourceControl.h"
|
||||
@@ -1736,9 +1736,9 @@ void SandboxIntegrationManager::GoToEntitiesInViewports(const AzToolsFramework::
|
||||
const AZ::Transform nextCameraTransform =
|
||||
AZ::Transform::CreateLookAt(aabb.GetCenter() - (forward * distanceToTarget), aabb.GetCenter());
|
||||
|
||||
SandboxEditor::ModernViewportCameraControllerRequestBus::Event(
|
||||
viewportContext->GetId(), &SandboxEditor::ModernViewportCameraControllerRequestBus::Events::InterpolateToTransform,
|
||||
nextCameraTransform);
|
||||
AtomToolsFramework::ModularViewportCameraControllerRequestBus::Event(
|
||||
viewportContext->GetId(),
|
||||
&AtomToolsFramework::ModularViewportCameraControllerRequestBus::Events::InterpolateToTransform, nextCameraTransform);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -224,7 +224,7 @@ void RCcontrollerTest_Simple::SubmitJob()
|
||||
|
||||
// This is a regresssion test to ensure the rccontroller can handle multiple jobs for the same file being completed before
|
||||
// the APM has a chance to send OnFinishedProcesssingJob events
|
||||
TEST_F(RCcontrollerTest_Simple, SameJobIsCompletedMultipleTimes_CompletesWithoutError)
|
||||
TEST_F(RCcontrollerTest_Simple, DISABLED_SameJobIsCompletedMultipleTimes_CompletesWithoutError)
|
||||
{
|
||||
using namespace AssetProcessor;
|
||||
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:f82f22df64b93d4bec91e56b60efa3d5ce2915ce388a2dc627f1ab720678e3d5
|
||||
size 334987
|
||||
@@ -11,6 +11,9 @@
|
||||
<file>iOS.svg</file>
|
||||
<file>Linux.svg</file>
|
||||
<file>macOS.svg</file>
|
||||
<file>DefaultProjectImage.png</file>
|
||||
<file>ArrowDownLine.svg</file>
|
||||
<file>ArrowUpLine.svg</file>
|
||||
<file>Backgrounds/FirstTimeBackgroundImage.jpg</file>
|
||||
</qresource>
|
||||
</RCC>
|
||||
|
||||
+18
-12
@@ -10,7 +10,7 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ProjectSettingsCtrl.h>
|
||||
#include <CreateProjectCtrl.h>
|
||||
#include <ScreensCtrl.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
@@ -22,7 +22,7 @@
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectSettingsCtrl::ProjectSettingsCtrl(QWidget* parent)
|
||||
CreateProjectCtrl::CreateProjectCtrl(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
@@ -34,11 +34,11 @@ namespace O3DE::ProjectManager
|
||||
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
|
||||
vLayout->addWidget(backNextButtons);
|
||||
|
||||
m_backButton = backNextButtons->addButton("Back", QDialogButtonBox::RejectRole);
|
||||
m_nextButton = backNextButtons->addButton("Next", QDialogButtonBox::ApplyRole);
|
||||
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
|
||||
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
|
||||
|
||||
connect(m_backButton, &QPushButton::pressed, this, &ProjectSettingsCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::pressed, this, &ProjectSettingsCtrl::HandleNextButton);
|
||||
connect(m_backButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::pressed, this, &CreateProjectCtrl::HandleNextButton);
|
||||
|
||||
m_screensOrder =
|
||||
{
|
||||
@@ -47,15 +47,16 @@ namespace O3DE::ProjectManager
|
||||
};
|
||||
m_screensCtrl->BuildScreens(m_screensOrder);
|
||||
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::NewProjectSettings, false);
|
||||
|
||||
UpdateNextButtonText();
|
||||
}
|
||||
|
||||
ProjectManagerScreen ProjectSettingsCtrl::GetScreenEnum()
|
||||
ProjectManagerScreen CreateProjectCtrl::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::NewProjectSettingsCore;
|
||||
return ProjectManagerScreen::CreateProject;
|
||||
}
|
||||
|
||||
void ProjectSettingsCtrl::HandleBackButton()
|
||||
void CreateProjectCtrl::HandleBackButton()
|
||||
{
|
||||
if (!m_screensCtrl->GotoPreviousScreen())
|
||||
{
|
||||
@@ -66,7 +67,7 @@ namespace O3DE::ProjectManager
|
||||
UpdateNextButtonText();
|
||||
}
|
||||
}
|
||||
void ProjectSettingsCtrl::HandleNextButton()
|
||||
void CreateProjectCtrl::HandleNextButton()
|
||||
{
|
||||
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
|
||||
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
|
||||
@@ -116,9 +117,14 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
}
|
||||
|
||||
void ProjectSettingsCtrl::UpdateNextButtonText()
|
||||
void CreateProjectCtrl::UpdateNextButtonText()
|
||||
{
|
||||
m_nextButton->setText(m_screensCtrl->GetCurrentScreen()->GetNextButtonText());
|
||||
QString nextButtonText = tr("Next");
|
||||
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
|
||||
{
|
||||
nextButtonText = tr("Create Project");
|
||||
}
|
||||
m_nextButton->setText(nextButtonText);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
+3
-3
@@ -21,12 +21,12 @@
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectSettingsCtrl
|
||||
class CreateProjectCtrl
|
||||
: public ScreenWidget
|
||||
{
|
||||
public:
|
||||
explicit ProjectSettingsCtrl(QWidget* parent = nullptr);
|
||||
~ProjectSettingsCtrl() = default;
|
||||
explicit CreateProjectCtrl(QWidget* parent = nullptr);
|
||||
~CreateProjectCtrl() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
protected slots:
|
||||
@@ -21,13 +21,6 @@
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_buttonSpacing = 30;
|
||||
inline constexpr static int s_iconSize = 24;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_boxButtonWidth = 210;
|
||||
inline constexpr static int s_boxButtonHeight = 280;
|
||||
|
||||
FirstTimeUseScreen::FirstTimeUseScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
@@ -79,8 +72,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void FirstTimeUseScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void FirstTimeUseScreen::HandleAddProjectButton()
|
||||
{
|
||||
|
||||
@@ -37,6 +37,13 @@ namespace O3DE::ProjectManager
|
||||
|
||||
QPushButton* m_createProjectButton;
|
||||
QPushButton* m_addProjectButton;
|
||||
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_buttonSpacing = 30;
|
||||
inline constexpr static int s_iconSize = 24;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_boxButtonWidth = 210;
|
||||
inline constexpr static int s_boxButtonHeight = 280;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -170,9 +170,4 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
return ProjectManagerScreen::GemCatalog;
|
||||
}
|
||||
|
||||
QString GemCatalogScreen::GetNextButtonText()
|
||||
{
|
||||
return "Create Project";
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace O3DE::ProjectManager
|
||||
explicit GemCatalogScreen(QWidget* parent = nullptr);
|
||||
~GemCatalogScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
QString GetNextButtonText() override;
|
||||
|
||||
private:
|
||||
QVector<GemInfo> GenerateTestData();
|
||||
|
||||
@@ -96,11 +96,6 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::NewProjectSettings;
|
||||
}
|
||||
|
||||
QString NewProjectSettingsScreen::GetNextButtonText()
|
||||
{
|
||||
return tr("Next");
|
||||
}
|
||||
|
||||
void NewProjectSettingsScreen::HandleBrowseButton()
|
||||
{
|
||||
QString defaultPath = m_projectPathLineEdit->text();
|
||||
|
||||
@@ -28,7 +28,6 @@ namespace O3DE::ProjectManager
|
||||
explicit NewProjectSettingsScreen(QWidget* parent = nullptr);
|
||||
~NewProjectSettingsScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
QString GetNextButtonText() override;
|
||||
|
||||
ProjectInfo GetProjectInfo();
|
||||
QString GetProjectTemplatePath();
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ProjectButtonWidget.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QResizeEvent>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QPixmap>
|
||||
#include <QMenu>
|
||||
#include <QSpacerItem>
|
||||
|
||||
//#define SHOW_ALL_PROJECT_ACTIONS
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
inline constexpr static int s_projectImageWidth = 210;
|
||||
inline constexpr static int s_projectImageHeight = 280;
|
||||
|
||||
LabelButton::LabelButton(QWidget* parent)
|
||||
: QLabel(parent)
|
||||
{
|
||||
}
|
||||
|
||||
void LabelButton::mousePressEvent([[maybe_unused]] QMouseEvent* event)
|
||||
{
|
||||
emit triggered();
|
||||
}
|
||||
|
||||
ProjectButton::ProjectButton(const QString& projectName, QWidget* parent)
|
||||
: QFrame(parent)
|
||||
, m_projectName(projectName)
|
||||
, m_projectImagePath(":/Resources/DefaultProjectImage.png")
|
||||
{
|
||||
Setup();
|
||||
}
|
||||
|
||||
ProjectButton::ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent)
|
||||
: QFrame(parent)
|
||||
, m_projectName(projectName)
|
||||
, m_projectImagePath(projectImage)
|
||||
{
|
||||
Setup();
|
||||
}
|
||||
|
||||
void ProjectButton::Setup()
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setSpacing(0);
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
setLayout(vLayout);
|
||||
|
||||
m_projectImageLabel = new LabelButton(this);
|
||||
m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight);
|
||||
vLayout->addWidget(m_projectImageLabel);
|
||||
|
||||
m_projectImageLabel->setPixmap(QPixmap(m_projectImagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
|
||||
|
||||
QMenu* newProjectMenu = new QMenu(this);
|
||||
m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings..."));
|
||||
|
||||
#ifdef SHOW_ALL_PROJECT_ACTIONS
|
||||
m_editProjectGemsAction = newProjectMenu->addAction(tr("Cutomize Gems..."));
|
||||
newProjectMenu->addSeparator();
|
||||
m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate"));
|
||||
newProjectMenu->addSeparator();
|
||||
m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE"));
|
||||
m_deleteProjectAction = newProjectMenu->addAction(tr("Delete the Project"));
|
||||
#endif
|
||||
|
||||
m_projectSettingsMenuButton = new QPushButton(this);
|
||||
m_projectSettingsMenuButton->setText(m_projectName);
|
||||
m_projectSettingsMenuButton->setMenu(newProjectMenu);
|
||||
m_projectSettingsMenuButton->setFocusPolicy(Qt::FocusPolicy::NoFocus);
|
||||
m_projectSettingsMenuButton->setStyleSheet("font-size: 14px; text-align:left;");
|
||||
vLayout->addWidget(m_projectSettingsMenuButton);
|
||||
|
||||
setFixedSize(s_projectImageWidth, s_projectImageHeight + m_projectSettingsMenuButton->height());
|
||||
|
||||
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectName); });
|
||||
connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectName); });
|
||||
|
||||
#ifdef SHOW_ALL_PROJECT_ACTIONS
|
||||
connect(m_editProjectGemsAction, &QAction::triggered, [this]() { emit EditProjectGems(m_projectName); });
|
||||
connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectName); });
|
||||
connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectName); });
|
||||
connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectName); });
|
||||
#endif
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,73 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QFrame>
|
||||
#include <QLabel>
|
||||
#endif
|
||||
|
||||
QT_FORWARD_DECLARE_CLASS(QPixmap)
|
||||
QT_FORWARD_DECLARE_CLASS(QPushButton)
|
||||
QT_FORWARD_DECLARE_CLASS(QAction)
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class LabelButton
|
||||
: public QLabel
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit LabelButton(QWidget* parent = nullptr);
|
||||
~LabelButton() = default;
|
||||
|
||||
signals:
|
||||
void triggered();
|
||||
|
||||
public slots:
|
||||
void mousePressEvent(QMouseEvent* event) override;
|
||||
};
|
||||
|
||||
class ProjectButton
|
||||
: public QFrame
|
||||
{
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
explicit ProjectButton(const QString& projectName, QWidget* parent = nullptr);
|
||||
explicit ProjectButton(const QString& projectName, const QString& projectImage, QWidget* parent = nullptr);
|
||||
~ProjectButton() = default;
|
||||
|
||||
signals:
|
||||
void OpenProject(const QString& projectName);
|
||||
void EditProject(const QString& projectName);
|
||||
void EditProjectGems(const QString& projectName);
|
||||
void CopyProject(const QString& projectName);
|
||||
void RemoveProject(const QString& projectName);
|
||||
void DeleteProject(const QString& projectName);
|
||||
|
||||
private:
|
||||
void Setup();
|
||||
|
||||
QString m_projectName;
|
||||
QString m_projectImagePath;
|
||||
LabelButton* m_projectImageLabel;
|
||||
QPushButton* m_projectSettingsMenuButton;
|
||||
QAction* m_editProjectAction;
|
||||
QAction* m_editProjectGemsAction;
|
||||
QAction* m_copyProjectAction;
|
||||
QAction* m_removeProjectAction;
|
||||
QAction* m_deleteProjectAction;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -50,9 +50,9 @@ namespace O3DE::ProjectManager
|
||||
QVector<ProjectManagerScreen> screenEnums =
|
||||
{
|
||||
ProjectManagerScreen::FirstTimeUse,
|
||||
ProjectManagerScreen::NewProjectSettingsCore,
|
||||
ProjectManagerScreen::CreateProject,
|
||||
ProjectManagerScreen::ProjectsHome,
|
||||
ProjectManagerScreen::ProjectSettings,
|
||||
ProjectManagerScreen::UpdateProject,
|
||||
ProjectManagerScreen::EngineSettings
|
||||
};
|
||||
m_screensCtrl->BuildScreens(screenEnums);
|
||||
|
||||
@@ -30,6 +30,23 @@ namespace O3DE::ProjectManager
|
||||
return ProjectManagerScreen::ProjectSettings;
|
||||
}
|
||||
|
||||
ProjectInfo ProjectSettingsScreen::GetProjectInfo()
|
||||
{
|
||||
// Impl pending next PR
|
||||
return ProjectInfo();
|
||||
}
|
||||
|
||||
void ProjectSettingsScreen::SetProjectInfo()
|
||||
{
|
||||
// Impl pending next PR
|
||||
}
|
||||
|
||||
bool ProjectSettingsScreen::Validate()
|
||||
{
|
||||
// Impl pending next PR
|
||||
return true;
|
||||
}
|
||||
|
||||
void ProjectSettingsScreen::HandleGemsButton()
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <ScreenWidget.h>
|
||||
#include <ProjectInfo.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
@@ -30,6 +31,11 @@ namespace O3DE::ProjectManager
|
||||
~ProjectSettingsScreen() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
ProjectInfo GetProjectInfo();
|
||||
void SetProjectInfo();
|
||||
|
||||
bool Validate();
|
||||
|
||||
protected slots:
|
||||
void HandleGemsButton();
|
||||
|
||||
|
||||
@@ -12,21 +12,103 @@
|
||||
|
||||
#include <ProjectsHomeScreen.h>
|
||||
|
||||
#include <Source/ui_ProjectsHomeScreen.h>
|
||||
|
||||
#include <ProjectButtonWidget.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
#include <QGridLayout>
|
||||
#include <QLabel>
|
||||
#include <QPushButton>
|
||||
#include <QMenu>
|
||||
#include <QListView>
|
||||
#include <QSpacerItem>
|
||||
#include <QListWidget>
|
||||
#include <QListWidgetItem>
|
||||
#include <QFileInfo>
|
||||
#include <QScrollArea>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectsHomeScreen::ProjectsHomeScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
, m_ui(new Ui::ProjectsHomeClass())
|
||||
{
|
||||
m_ui->setupUi(this);
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
vLayout->setContentsMargins(s_contentMargins, s_contentMargins, s_contentMargins, s_contentMargins);
|
||||
|
||||
connect(m_ui->newProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleNewProjectButton);
|
||||
connect(m_ui->addProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleAddProjectButton);
|
||||
connect(m_ui->editProjectButton, &QPushButton::pressed, this, &ProjectsHomeScreen::HandleEditProjectButton);
|
||||
QHBoxLayout* topLayout = new QHBoxLayout();
|
||||
|
||||
QLabel* titleLabel = new QLabel(this);
|
||||
titleLabel->setText("My Projects");
|
||||
titleLabel->setStyleSheet("font-size: 24px");
|
||||
topLayout->addWidget(titleLabel);
|
||||
|
||||
QSpacerItem* topSpacer = new QSpacerItem(s_spacerSize, s_spacerSize, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
topLayout->addItem(topSpacer);
|
||||
|
||||
QMenu* newProjectMenu = new QMenu(this);
|
||||
m_createNewProjectAction = newProjectMenu->addAction("Create New Project");
|
||||
m_addExistingProjectAction = newProjectMenu->addAction("Add Existing Project");
|
||||
|
||||
QPushButton* newProjectMenuButton = new QPushButton(this);
|
||||
newProjectMenuButton->setText("New Project...");
|
||||
newProjectMenuButton->setMenu(newProjectMenu);
|
||||
newProjectMenuButton->setFixedWidth(s_newProjectButtonWidth);
|
||||
newProjectMenuButton->setStyleSheet("font-size: 14px;");
|
||||
topLayout->addWidget(newProjectMenuButton);
|
||||
|
||||
vLayout->addLayout(topLayout);
|
||||
|
||||
// Get all projects and create a horizontal scrolling list of them
|
||||
auto projectsResult = PythonBindingsInterface::Get()->GetProjects();
|
||||
if (projectsResult.IsSuccess() && !projectsResult.GetValue().isEmpty())
|
||||
{
|
||||
QScrollArea* projectsScrollArea = new QScrollArea(this);
|
||||
QWidget* scrollWidget = new QWidget();
|
||||
QGridLayout* projectGridLayout = new QGridLayout();
|
||||
scrollWidget->setLayout(projectGridLayout);
|
||||
projectsScrollArea->setWidget(scrollWidget);
|
||||
projectsScrollArea->setWidgetResizable(true);
|
||||
|
||||
int gridIndex = 0;
|
||||
for (auto project : projectsResult.GetValue())
|
||||
{
|
||||
ProjectButton* projectButton;
|
||||
QString projectPreviewPath = project.m_path + m_projectPreviewImagePath;
|
||||
QFileInfo doesPreviewExist(projectPreviewPath);
|
||||
if (doesPreviewExist.exists() && doesPreviewExist.isFile())
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, projectPreviewPath, this);
|
||||
}
|
||||
else
|
||||
{
|
||||
projectButton = new ProjectButton(project.m_projectName, this);
|
||||
}
|
||||
|
||||
// Create rows of projects buttons s_projectButtonRowCount buttons wide
|
||||
projectGridLayout->addWidget(projectButton, gridIndex / s_projectButtonRowCount, gridIndex % s_projectButtonRowCount);
|
||||
|
||||
connect(projectButton, &ProjectButton::OpenProject, this, &ProjectsHomeScreen::HandleOpenProject);
|
||||
connect(projectButton, &ProjectButton::EditProject, this, &ProjectsHomeScreen::HandleEditProject);
|
||||
|
||||
#ifdef SHOW_ALL_PROJECT_ACTIONS
|
||||
connect(projectButton, &ProjectButton::EditProjectGems, this, &ProjectsHomeScreen::HandleEditProjectGems);
|
||||
connect(projectButton, &ProjectButton::CopyProject, this, &ProjectsHomeScreen::HandleCopyProject);
|
||||
connect(projectButton, &ProjectButton::RemoveProject, this, &ProjectsHomeScreen::HandleRemoveProject);
|
||||
connect(projectButton, &ProjectButton::DeleteProject, this, &ProjectsHomeScreen::HandleDeleteProject);
|
||||
#endif
|
||||
++gridIndex;
|
||||
}
|
||||
|
||||
vLayout->addWidget(projectsScrollArea);
|
||||
}
|
||||
|
||||
// Using border-image allows for scaling options background-image does not support
|
||||
setStyleSheet("O3DE--ProjectManager--ScreenWidget { border-image: url(:/Backgrounds/FirstTimeBackgroundImage.jpg) repeat repeat; }");
|
||||
|
||||
connect(m_createNewProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleNewProjectButton);
|
||||
connect(m_addExistingProjectAction, &QAction::triggered, this, &ProjectsHomeScreen::HandleAddProjectButton);
|
||||
}
|
||||
|
||||
ProjectManagerScreen ProjectsHomeScreen::GetScreenEnum()
|
||||
@@ -36,16 +118,41 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void ProjectsHomeScreen::HandleNewProjectButton()
|
||||
{
|
||||
emit ResetScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::NewProjectSettingsCore);
|
||||
emit ResetScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::CreateProject);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleAddProjectButton()
|
||||
{
|
||||
// Do nothing for now
|
||||
}
|
||||
void ProjectsHomeScreen::HandleEditProjectButton()
|
||||
void ProjectsHomeScreen::HandleOpenProject(const QString& projectPath)
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectSettings);
|
||||
// Open the editor with this project open
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleEditProject(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ResetScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::UpdateProject);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleEditProjectGems(const QString& projectPath)
|
||||
{
|
||||
emit NotifyCurrentProject(projectPath);
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::GemCatalog);
|
||||
}
|
||||
void ProjectsHomeScreen::HandleCopyProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Open file dialog and choose location for copied project then register copy with O3DE
|
||||
}
|
||||
void ProjectsHomeScreen::HandleRemoveProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Unregister Project from O3DE
|
||||
}
|
||||
void ProjectsHomeScreen::HandleDeleteProject([[maybe_unused]] const QString& projectPath)
|
||||
{
|
||||
// Remove project from 03DE and delete from disk
|
||||
ProjectsHomeScreen::HandleRemoveProject(projectPath);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -15,11 +15,6 @@
|
||||
#include <ScreenWidget.h>
|
||||
#endif
|
||||
|
||||
namespace Ui
|
||||
{
|
||||
class ProjectsHomeClass;
|
||||
}
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectsHomeScreen
|
||||
@@ -34,10 +29,23 @@ namespace O3DE::ProjectManager
|
||||
protected slots:
|
||||
void HandleNewProjectButton();
|
||||
void HandleAddProjectButton();
|
||||
void HandleEditProjectButton();
|
||||
void HandleOpenProject(const QString& projectPath);
|
||||
void HandleEditProject(const QString& projectPath);
|
||||
void HandleEditProjectGems(const QString& projectPath);
|
||||
void HandleCopyProject(const QString& projectPath);
|
||||
void HandleRemoveProject(const QString& projectPath);
|
||||
void HandleDeleteProject(const QString& projectPath);
|
||||
|
||||
private:
|
||||
QScopedPointer<Ui::ProjectsHomeClass> m_ui;
|
||||
QAction* m_createNewProjectAction;
|
||||
QAction* m_addExistingProjectAction;
|
||||
|
||||
const QString m_projectPreviewImagePath = "/preview.png";
|
||||
inline constexpr static int s_contentMargins = 80;
|
||||
inline constexpr static int s_spacerSize = 20;
|
||||
inline constexpr static int s_projectButtonRowCount = 4;
|
||||
inline constexpr static int s_newProjectButtonWidth = 156;
|
||||
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -1,137 +0,0 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<ui version="4.0">
|
||||
<class>ProjectsHomeClass</class>
|
||||
<widget class="QWidget" name="ProjectsHomeClass">
|
||||
<property name="geometry">
|
||||
<rect>
|
||||
<x>0</x>
|
||||
<y>0</y>
|
||||
<width>826</width>
|
||||
<height>585</height>
|
||||
</rect>
|
||||
</property>
|
||||
<property name="windowTitle">
|
||||
<string>Form</string>
|
||||
</property>
|
||||
<layout class="QVBoxLayout" name="verticalLayout">
|
||||
<item>
|
||||
<widget class="QLabel" name="label">
|
||||
<property name="text">
|
||||
<string>My Projects</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<layout class="QHBoxLayout" name="horizontalLayout">
|
||||
<item>
|
||||
<widget class="QPushButton" name="currentProjectButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="newProjectButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/ProjectManager.qrc">
|
||||
<normaloff>:/Add.svg</normaloff>:/Add.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QPushButton" name="addProjectButton">
|
||||
<property name="sizePolicy">
|
||||
<sizepolicy hsizetype="MinimumExpanding" vsizetype="MinimumExpanding">
|
||||
<horstretch>0</horstretch>
|
||||
<verstretch>0</verstretch>
|
||||
</sizepolicy>
|
||||
</property>
|
||||
<property name="text">
|
||||
<string/>
|
||||
</property>
|
||||
<property name="icon">
|
||||
<iconset resource="../Resources/ProjectManager.qrc">
|
||||
<normaloff>:/Select_Folder.svg</normaloff>:/Select_Folder.svg</iconset>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="horizontalSpacer_2">
|
||||
<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>
|
||||
<spacer name="horizontalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Horizontal</enum>
|
||||
</property>
|
||||
<property name="sizeType">
|
||||
<enum>QSizePolicy::Expanding</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>40</width>
|
||||
<height>20</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QToolButton" name="editProjectButton">
|
||||
<property name="text">
|
||||
<string>Edit Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="QLabel" name="label_2">
|
||||
<property name="text">
|
||||
<string>Open a Project</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<spacer name="verticalSpacer">
|
||||
<property name="orientation">
|
||||
<enum>Qt::Vertical</enum>
|
||||
</property>
|
||||
<property name="sizeHint" stdset="0">
|
||||
<size>
|
||||
<width>20</width>
|
||||
<height>40</height>
|
||||
</size>
|
||||
</property>
|
||||
</spacer>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<resources>
|
||||
<include location="../Resources/ProjectManager.qrc"/>
|
||||
</resources>
|
||||
<connections/>
|
||||
</ui>
|
||||
@@ -540,7 +540,8 @@ namespace O3DE::ProjectManager
|
||||
ProjectInfo PythonBindings::ProjectInfoFromPath(pybind11::handle path)
|
||||
{
|
||||
ProjectInfo projectInfo;
|
||||
projectInfo.m_path = Py_To_String(path);
|
||||
projectInfo.m_path = Py_To_String(path);
|
||||
projectInfo.m_isNew = false;
|
||||
|
||||
auto projectData = m_registration.attr("get_project_data")(pybind11::none(), path);
|
||||
if (pybind11::isinstance<pybind11::dict>(projectData))
|
||||
|
||||
@@ -18,10 +18,11 @@ namespace O3DE::ProjectManager
|
||||
Invalid = -1,
|
||||
Empty,
|
||||
FirstTimeUse,
|
||||
NewProjectSettingsCore,
|
||||
CreateProject,
|
||||
NewProjectSettings,
|
||||
GemCatalog,
|
||||
ProjectsHome,
|
||||
UpdateProject,
|
||||
ProjectSettings,
|
||||
EngineSettings
|
||||
};
|
||||
|
||||
@@ -12,7 +12,8 @@
|
||||
#include <ScreenFactory.h>
|
||||
|
||||
#include <FirstTimeUseScreen.h>
|
||||
#include <ProjectSettingsCtrl.h>
|
||||
#include <CreateProjectCtrl.h>
|
||||
#include <UpdateProjectCtrl.h>
|
||||
#include <NewProjectSettingsScreen.h>
|
||||
#include <GemCatalog/GemCatalogScreen.h>
|
||||
#include <ProjectsHomeScreen.h>
|
||||
@@ -30,8 +31,8 @@ namespace O3DE::ProjectManager
|
||||
case (ProjectManagerScreen::FirstTimeUse):
|
||||
newScreen = new FirstTimeUseScreen(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::NewProjectSettingsCore):
|
||||
newScreen = new ProjectSettingsCtrl(parent);
|
||||
case (ProjectManagerScreen::CreateProject):
|
||||
newScreen = new CreateProjectCtrl(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::NewProjectSettings):
|
||||
newScreen = new NewProjectSettingsScreen(parent);
|
||||
@@ -42,6 +43,9 @@ namespace O3DE::ProjectManager
|
||||
case (ProjectManagerScreen::ProjectsHome):
|
||||
newScreen = new ProjectsHomeScreen(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::UpdateProject):
|
||||
newScreen = new UpdateProjectCtrl(parent);
|
||||
break;
|
||||
case (ProjectManagerScreen::ProjectSettings):
|
||||
newScreen = new ProjectSettingsScreen(parent);
|
||||
break;
|
||||
|
||||
@@ -41,15 +41,12 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
return true;
|
||||
}
|
||||
virtual QString GetNextButtonText()
|
||||
{
|
||||
return "Next";
|
||||
}
|
||||
|
||||
signals:
|
||||
void ChangeScreenRequest(ProjectManagerScreen screen);
|
||||
void GotoPreviousScreenRequest();
|
||||
void ResetScreenRequest(ProjectManagerScreen screen);
|
||||
void NotifyCurrentProject(const QString& projectPath);
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -117,6 +117,7 @@ namespace O3DE::ProjectManager
|
||||
connect(newScreen, &ScreenWidget::ChangeScreenRequest, this, &ScreensCtrl::ChangeToScreen);
|
||||
connect(newScreen, &ScreenWidget::GotoPreviousScreenRequest, this, &ScreensCtrl::GotoPreviousScreen);
|
||||
connect(newScreen, &ScreenWidget::ResetScreenRequest, this, &ScreensCtrl::ResetScreen);
|
||||
connect(newScreen, &ScreenWidget::NotifyCurrentProject, this, &ScreensCtrl::NotifyCurrentProject);
|
||||
}
|
||||
|
||||
void ScreensCtrl::ResetAllScreens()
|
||||
|
||||
@@ -35,6 +35,9 @@ namespace O3DE::ProjectManager
|
||||
ScreenWidget* FindScreen(ProjectManagerScreen screen);
|
||||
ScreenWidget* GetCurrentScreen();
|
||||
|
||||
signals:
|
||||
void NotifyCurrentProject(const QString& projectPath);
|
||||
|
||||
public slots:
|
||||
bool ChangeToScreen(ProjectManagerScreen screen);
|
||||
bool ForceChangeToScreen(ProjectManagerScreen screen, bool addVisit = true);
|
||||
|
||||
@@ -0,0 +1,139 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <UpdateProjectCtrl.h>
|
||||
#include <ScreensCtrl.h>
|
||||
#include <PythonBindingsInterface.h>
|
||||
#include <ProjectSettingsScreen.h>
|
||||
|
||||
#include <QDialogButtonBox>
|
||||
#include <QVBoxLayout>
|
||||
#include <QPushButton>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
UpdateProjectCtrl::UpdateProjectCtrl(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
setLayout(vLayout);
|
||||
|
||||
m_screensCtrl = new ScreensCtrl();
|
||||
vLayout->addWidget(m_screensCtrl);
|
||||
|
||||
QDialogButtonBox* backNextButtons = new QDialogButtonBox();
|
||||
vLayout->addWidget(backNextButtons);
|
||||
|
||||
m_backButton = backNextButtons->addButton(tr("Back"), QDialogButtonBox::RejectRole);
|
||||
m_nextButton = backNextButtons->addButton(tr("Next"), QDialogButtonBox::ApplyRole);
|
||||
|
||||
connect(m_backButton, &QPushButton::pressed, this, &UpdateProjectCtrl::HandleBackButton);
|
||||
connect(m_nextButton, &QPushButton::pressed, this, &UpdateProjectCtrl::HandleNextButton);
|
||||
connect(reinterpret_cast<ScreensCtrl*>(parent), &ScreensCtrl::NotifyCurrentProject, this, &UpdateProjectCtrl::UpdateCurrentProject);
|
||||
|
||||
m_screensOrder =
|
||||
{
|
||||
ProjectManagerScreen::ProjectSettings,
|
||||
ProjectManagerScreen::GemCatalog
|
||||
};
|
||||
m_screensCtrl->BuildScreens(m_screensOrder);
|
||||
m_screensCtrl->ForceChangeToScreen(ProjectManagerScreen::ProjectSettings, false);
|
||||
|
||||
UpdateNextButtonText();
|
||||
|
||||
}
|
||||
|
||||
ProjectManagerScreen UpdateProjectCtrl::GetScreenEnum()
|
||||
{
|
||||
return ProjectManagerScreen::UpdateProject;
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::HandleBackButton()
|
||||
{
|
||||
if (!m_screensCtrl->GotoPreviousScreen())
|
||||
{
|
||||
emit GotoPreviousScreenRequest();
|
||||
}
|
||||
else
|
||||
{
|
||||
UpdateNextButtonText();
|
||||
}
|
||||
}
|
||||
void UpdateProjectCtrl::HandleNextButton()
|
||||
{
|
||||
ScreenWidget* currentScreen = m_screensCtrl->GetCurrentScreen();
|
||||
ProjectManagerScreen screenEnum = currentScreen->GetScreenEnum();
|
||||
auto screenOrderIter = m_screensOrder.begin();
|
||||
for (; screenOrderIter != m_screensOrder.end(); ++screenOrderIter)
|
||||
{
|
||||
if (*screenOrderIter == screenEnum)
|
||||
{
|
||||
++screenOrderIter;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (screenEnum == ProjectManagerScreen::ProjectSettings)
|
||||
{
|
||||
auto projectScreen = reinterpret_cast<ProjectSettingsScreen*>(currentScreen);
|
||||
if (projectScreen)
|
||||
{
|
||||
if (!projectScreen->Validate())
|
||||
{
|
||||
QMessageBox::critical(this, tr("Invalid project settings"), tr("Invalid project settings"));
|
||||
return;
|
||||
}
|
||||
|
||||
m_projectInfo = projectScreen->GetProjectInfo();
|
||||
}
|
||||
}
|
||||
|
||||
if (screenOrderIter != m_screensOrder.end())
|
||||
{
|
||||
m_screensCtrl->ChangeToScreen(*screenOrderIter);
|
||||
UpdateNextButtonText();
|
||||
}
|
||||
else
|
||||
{
|
||||
auto result = PythonBindingsInterface::Get()->UpdateProject(m_projectInfo);
|
||||
if (result)
|
||||
{
|
||||
emit ChangeScreenRequest(ProjectManagerScreen::ProjectsHome);
|
||||
}
|
||||
else
|
||||
{
|
||||
QMessageBox::critical(this, tr("Project update failed"), tr("Failed to update project."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::UpdateCurrentProject(const QString& projectPath)
|
||||
{
|
||||
auto projectResult = PythonBindingsInterface::Get()->GetProject(projectPath);
|
||||
if (projectResult.IsSuccess())
|
||||
{
|
||||
m_projectInfo = projectResult.GetValue();
|
||||
}
|
||||
}
|
||||
|
||||
void UpdateProjectCtrl::UpdateNextButtonText()
|
||||
{
|
||||
QString nextButtonText = tr("Continue");
|
||||
if (m_screensCtrl->GetCurrentScreen()->GetScreenEnum() == ProjectManagerScreen::GemCatalog)
|
||||
{
|
||||
nextButtonText = tr("Update Project");
|
||||
}
|
||||
m_nextButton->setText(nextButtonText);
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include "ProjectInfo.h"
|
||||
#include <ScreenWidget.h>
|
||||
#include <ScreensCtrl.h>
|
||||
#include <QPushButton>
|
||||
#endif
|
||||
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class UpdateProjectCtrl
|
||||
: public ScreenWidget
|
||||
{
|
||||
public:
|
||||
explicit UpdateProjectCtrl(QWidget* parent = nullptr);
|
||||
~UpdateProjectCtrl() = default;
|
||||
ProjectManagerScreen GetScreenEnum() override;
|
||||
|
||||
|
||||
protected slots:
|
||||
void HandleBackButton();
|
||||
void HandleNextButton();
|
||||
void UpdateCurrentProject(const QString& projectPath);
|
||||
|
||||
private:
|
||||
void UpdateNextButtonText();
|
||||
|
||||
ScreensCtrl* m_screensCtrl;
|
||||
QPushButton* m_backButton;
|
||||
QPushButton* m_nextButton;
|
||||
QVector<ProjectManagerScreen> m_screensOrder;
|
||||
|
||||
ProjectInfo m_projectInfo;
|
||||
|
||||
ProjectManagerScreen m_screenEnum;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
@@ -41,16 +41,19 @@ set(FILES
|
||||
Source/ProjectInfo.cpp
|
||||
Source/NewProjectSettingsScreen.h
|
||||
Source/NewProjectSettingsScreen.cpp
|
||||
Source/ProjectSettingsCtrl.h
|
||||
Source/ProjectSettingsCtrl.cpp
|
||||
Source/CreateProjectCtrl.h
|
||||
Source/CreateProjectCtrl.cpp
|
||||
Source/UpdateProjectCtrl.h
|
||||
Source/UpdateProjectCtrl.cpp
|
||||
Source/ProjectsHomeScreen.h
|
||||
Source/ProjectsHomeScreen.cpp
|
||||
Source/ProjectsHomeScreen.ui
|
||||
Source/ProjectSettingsScreen.h
|
||||
Source/ProjectSettingsScreen.cpp
|
||||
Source/ProjectSettingsScreen.ui
|
||||
Source/EngineSettingsScreen.h
|
||||
Source/EngineSettingsScreen.cpp
|
||||
Source/ProjectButtonWidget.h
|
||||
Source/ProjectButtonWidget.cpp
|
||||
Source/LinkWidget.h
|
||||
Source/LinkWidget.cpp
|
||||
Source/TagWidget.h
|
||||
|
||||
@@ -41,6 +41,18 @@ namespace AZ
|
||||
static AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler* g_fbxImporter = nullptr;
|
||||
static AZStd::vector<AZ::ComponentDescriptor*> g_componentDescriptors;
|
||||
|
||||
void Initialize()
|
||||
{
|
||||
// Currently it's still needed to explicitly create an instance of this instead of letting
|
||||
// it be a normal component. This is because ResourceCompilerScene needs to return
|
||||
// the list of available extensions before it can start the application.
|
||||
if (!g_fbxImporter)
|
||||
{
|
||||
g_fbxImporter = aznew AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler();
|
||||
g_fbxImporter->Activate();
|
||||
}
|
||||
}
|
||||
|
||||
void Reflect(AZ::SerializeContext* /*context*/)
|
||||
{
|
||||
// Descriptor registration is done in Reflect instead of Initialize because the ResourceCompilerScene initializes the libraries before
|
||||
@@ -52,7 +64,6 @@ namespace AZ
|
||||
{
|
||||
// Global importer and behavior
|
||||
g_componentDescriptors.push_back(FbxSceneBuilder::FbxImporter::CreateDescriptor());
|
||||
g_componentDescriptors.push_back(FbxSceneImporter::FbxImportRequestHandler::CreateDescriptor());
|
||||
|
||||
// Node and attribute importers
|
||||
g_componentDescriptors.push_back(AssImpBitangentStreamImporter::CreateDescriptor());
|
||||
@@ -114,11 +125,7 @@ namespace AZ
|
||||
extern "C" AZ_DLL_EXPORT void InitializeDynamicModule(void* env)
|
||||
{
|
||||
AZ::Environment::Attach(static_cast<AZ::EnvironmentInstance>(env));
|
||||
if (!AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter)
|
||||
{
|
||||
AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter = aznew AZ::SceneAPI::FbxSceneImporter::FbxImportRequestHandler();
|
||||
AZ::SceneAPI::FbxSceneBuilder::g_fbxImporter->Activate();
|
||||
}
|
||||
AZ::SceneAPI::FbxSceneBuilder::Initialize();
|
||||
}
|
||||
extern "C" AZ_DLL_EXPORT void Reflect(AZ::SerializeContext* context)
|
||||
{
|
||||
|
||||
@@ -10,16 +10,12 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AssetProcessor/AssetBuilderSDK/AssetBuilderSDK/AssetBuilderSDK.h>
|
||||
#include <AzCore/Serialization/EditContextConstants.inl>
|
||||
#include <AzCore/Serialization/SerializeContext.h>
|
||||
#include <AzCore/Serialization/Json/JsonSerialization.h>
|
||||
#include <AzCore/Settings/SettingsRegistry.h>
|
||||
#include <AzCore/StringFunc/StringFunc.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.h>
|
||||
#include <AzFramework/StringFunc/StringFunc.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Scene.h>
|
||||
#include <SceneAPI/SceneCore/Events/CallProcessorBus.h>
|
||||
#include <SceneAPI/SceneCore/Events/ImportEventContext.h>
|
||||
#include <SceneAPI/FbxSceneBuilder/FbxImportRequestHandler.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -27,23 +23,10 @@ namespace AZ
|
||||
{
|
||||
namespace FbxSceneImporter
|
||||
{
|
||||
void SceneImporterSettings::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context); serializeContext)
|
||||
{
|
||||
serializeContext->Class<SceneImporterSettings>()
|
||||
->Version(1)
|
||||
->Field("SupportedFileTypeExtensions", &SceneImporterSettings::m_supportedFileTypeExtensions);
|
||||
}
|
||||
}
|
||||
const char* FbxImportRequestHandler::s_extension = ".fbx";
|
||||
|
||||
void FbxImportRequestHandler::Activate()
|
||||
{
|
||||
if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
settingsRegistry->GetObject(m_settings, "/O3DE/SceneAPI/AssetImporter");
|
||||
}
|
||||
|
||||
BusConnect();
|
||||
}
|
||||
|
||||
@@ -54,38 +37,21 @@ namespace AZ
|
||||
|
||||
void FbxImportRequestHandler::Reflect(ReflectContext* context)
|
||||
{
|
||||
SceneImporterSettings::Reflect(context);
|
||||
|
||||
SerializeContext* serializeContext = azrtti_cast<SerializeContext*>(context);
|
||||
if (serializeContext)
|
||||
{
|
||||
serializeContext->Class<FbxImportRequestHandler, AZ::Component>()->Version(1)->Attribute(
|
||||
AZ::Edit::Attributes::SystemComponentTags,
|
||||
AZStd::vector<AZ::Crc32>({AssetBuilderSDK::ComponentTags::AssetBuilder}));
|
||||
|
||||
serializeContext->Class<FbxImportRequestHandler, SceneCore::BehaviorComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
void FbxImportRequestHandler::GetSupportedFileExtensions(AZStd::unordered_set<AZStd::string>& extensions)
|
||||
{
|
||||
// It's unlikely an empty file extension list is intentional,
|
||||
// so if it's empty, try reloading it from the registry.
|
||||
if (m_settings.m_supportedFileTypeExtensions.empty())
|
||||
{
|
||||
if (auto* settingsRegistry = AZ::SettingsRegistry::Get())
|
||||
{
|
||||
settingsRegistry->GetObject(m_settings, "/O3DE/SceneAPI/AssetImporter");
|
||||
}
|
||||
}
|
||||
extensions.insert(m_settings.m_supportedFileTypeExtensions.begin(), m_settings.m_supportedFileTypeExtensions.end());
|
||||
extensions.insert(s_extension);
|
||||
}
|
||||
|
||||
Events::LoadingResult FbxImportRequestHandler::LoadAsset(Containers::Scene& scene, const AZStd::string& path, const Uuid& guid, [[maybe_unused]] RequestingApplication requester)
|
||||
{
|
||||
AZStd::string extension;
|
||||
StringFunc::Path::GetExtension(path.c_str(), extension);
|
||||
|
||||
if (!m_settings.m_supportedFileTypeExtensions.contains(extension))
|
||||
if (!AzFramework::StringFunc::Path::IsExtension(path.c_str(), s_extension))
|
||||
{
|
||||
return Events::LoadingResult::Ignored;
|
||||
}
|
||||
@@ -107,11 +73,6 @@ namespace AZ
|
||||
return Events::LoadingResult::AssetFailure;
|
||||
}
|
||||
}
|
||||
|
||||
void FbxImportRequestHandler::GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided)
|
||||
{
|
||||
provided.emplace_back(AZ_CRC_CE("AssetImportRequestHandler"));
|
||||
}
|
||||
} // namespace Import
|
||||
} // namespace SceneAPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -21,21 +21,12 @@ namespace AZ
|
||||
{
|
||||
namespace FbxSceneImporter
|
||||
{
|
||||
struct SceneImporterSettings
|
||||
{
|
||||
AZ_TYPE_INFO(SceneImporterSettings, "{8BB6C7AD-BF99-44DC-9DA1-E7AD3F03DC10}");
|
||||
|
||||
static void Reflect(AZ::ReflectContext* context);
|
||||
|
||||
AZStd::unordered_set<AZStd::string> m_supportedFileTypeExtensions;
|
||||
};
|
||||
|
||||
class FbxImportRequestHandler
|
||||
: public AZ::Component
|
||||
: public SceneCore::BehaviorComponent
|
||||
, public Events::AssetImportRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
AZ_COMPONENT(FbxImportRequestHandler, "{9F4B189C-0A96-4F44-A5F0-E087FF1561F8}");
|
||||
AZ_COMPONENT(FbxImportRequestHandler, "{9F4B189C-0A96-4F44-A5F0-E087FF1561F8}", SceneCore::BehaviorComponent);
|
||||
|
||||
~FbxImportRequestHandler() override = default;
|
||||
|
||||
@@ -47,13 +38,8 @@ namespace AZ
|
||||
Events::LoadingResult LoadAsset(Containers::Scene& scene, const AZStd::string& path, const Uuid& guid,
|
||||
RequestingApplication requester) override;
|
||||
|
||||
static void GetProvidedServices(ComponentDescriptor::DependencyArrayType& provided);
|
||||
|
||||
private:
|
||||
|
||||
SceneImporterSettings m_settings;
|
||||
|
||||
static constexpr const char* SettingsFilename = "AssetImporterSettings.json";
|
||||
static const char* s_extension;
|
||||
};
|
||||
} // namespace FbxSceneImporter
|
||||
} // namespace SceneAPI
|
||||
|
||||
@@ -97,6 +97,11 @@ namespace AZ
|
||||
return m_configFilePath.c_str();
|
||||
}
|
||||
|
||||
void Application::QueryApplicationType(AZ::ApplicationTypeQuery& appType) const
|
||||
{
|
||||
appType.m_maskValue = AZ::ApplicationTypeQuery::Masks::Tool;
|
||||
}
|
||||
|
||||
void Application::SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations)
|
||||
{
|
||||
AZ::ComponentApplication::SetSettingsRegistrySpecializations(specializations);
|
||||
|
||||
@@ -28,6 +28,7 @@ namespace AZ
|
||||
|
||||
const char* GetConfigFilePath() const;
|
||||
AZ::ComponentTypeList GetRequiredSystemComponents() const override;
|
||||
void QueryApplicationType(AZ::ApplicationTypeQuery& appType) const override;
|
||||
|
||||
protected:
|
||||
void SetSettingsRegistrySpecializations(AZ::SettingsRegistryInterface::Specializations& specializations) override;
|
||||
|
||||
@@ -25,8 +25,11 @@
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzFramework/Archive/IArchive.h>
|
||||
#include <AzFramework/Asset/AssetSystemBus.h>
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabDomUtils.h>
|
||||
#include <AzToolsFramework/Prefab/EditorPrefabComponent.h>
|
||||
#include <AzToolsFramework/Prefab/PrefabPublicInterface.h>
|
||||
#include <AzToolsFramework/Entity/EditorEntityContextBus.h>
|
||||
#include <AzToolsFramework/Entity/PrefabEditorEntityOwnershipInterface.h>
|
||||
#include <AzToolsFramework/ToolsComponents/TransformComponent.h>
|
||||
@@ -36,7 +39,6 @@
|
||||
|
||||
// SliceConverter reads in a slice file (saved in an ObjectStream format), instantiates it, creates a prefab out of the data,
|
||||
// and saves the prefab in a JSON format. This can be used for one-time migrations of slices or slice-based levels to prefabs.
|
||||
// This converter is still in an early state. It can convert trivial slices, but it cannot handle nested slices yet.
|
||||
//
|
||||
// If the slice contains legacy data, it will print out warnings / errors about the data that couldn't be serialized.
|
||||
// The prefab will be generated without that data.
|
||||
@@ -70,6 +72,20 @@ namespace AZ
|
||||
AZ_Error("Convert-Slice", false, "No json registration context found.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Connect to the Asset Processor so that we can get the correct source path to any nested slice references.
|
||||
if (!ConnectToAssetProcessor())
|
||||
{
|
||||
AZ_Error("Convert-Slice", false, " Failed to connect to the Asset Processor.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the asset catalog so that we can find any nested assets successfully. We also need to tick the tick bus
|
||||
// so that the OnCatalogLoaded event gets processed now, instead of during application shutdown.
|
||||
AZ::Data::AssetCatalogRequestBus::Broadcast(
|
||||
&AZ::Data::AssetCatalogRequestBus::Events::LoadCatalog, "@assets@/assetcatalog.xml");
|
||||
application.Tick();
|
||||
|
||||
AZStd::string logggingScratchBuffer;
|
||||
SetupLogging(logggingScratchBuffer, convertSettings.m_reporting, *commandLine);
|
||||
|
||||
@@ -80,83 +96,90 @@ namespace AZ
|
||||
verifySettings.m_serializeContext = application.GetSerializeContext();
|
||||
SetupLogging(logggingScratchBuffer, verifySettings.m_reporting, *commandLine);
|
||||
|
||||
auto archiveInterface = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
|
||||
// Find the Prefab System Component for use in creating and saving the prefab
|
||||
AZ::Entity* systemEntity = application.FindEntity(AZ::SystemEntityId);
|
||||
AZ_Assert(systemEntity != nullptr, "System entity doesn't exist.");
|
||||
auto prefabSystemComponent = systemEntity->FindComponent<AzToolsFramework::Prefab::PrefabSystemComponent>();
|
||||
AZ_Assert(prefabSystemComponent != nullptr, "Prefab System component doesn't exist");
|
||||
|
||||
bool result = true;
|
||||
rapidjson::StringBuffer scratchBuffer;
|
||||
|
||||
// Loop through the list of requested files and convert them.
|
||||
AZStd::vector<AZStd::string> fileList = Utilities::ReadFileListFromCommandLine(application, "files");
|
||||
for (AZStd::string& filePath : fileList)
|
||||
{
|
||||
bool packOpened = false;
|
||||
|
||||
AZ::IO::Path outputPath = filePath;
|
||||
outputPath.ReplaceExtension("prefab");
|
||||
|
||||
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
|
||||
AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str());
|
||||
|
||||
AZ::IO::Path inputPath = filePath;
|
||||
auto fileExtension = inputPath.Extension();
|
||||
if (fileExtension == ".ly")
|
||||
{
|
||||
// Special case: for level files, we need to open the .ly zip file and convert the levelentities.editor_xml file
|
||||
// inside of it. All the other files can be ignored as they are deprecated legacy system files that are no longer
|
||||
// loaded with prefab-based levels.
|
||||
packOpened = archiveInterface->OpenPack(filePath);
|
||||
inputPath.ReplaceFilename("levelentities.editor_xml");
|
||||
AZ_Warning("Convert-Slice", packOpened, " '%s' could not be opened as a pack file.\n", filePath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning(
|
||||
"Convert-Slice", (fileExtension == ".slice"),
|
||||
" Warning: Only .ly and .slice files are supported, conversion of '%.*s' may not work.\n",
|
||||
AZ_STRING_ARG(fileExtension.Native()));
|
||||
}
|
||||
|
||||
auto callback = [prefabSystemComponent, &outputPath, isDryRun]
|
||||
(void* classPtr, const Uuid& classId, [[maybe_unused]] SerializeContext* context)
|
||||
{
|
||||
if (classId != azrtti_typeid<AZ::Entity>())
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Entity* rootEntity = reinterpret_cast<AZ::Entity*>(classPtr);
|
||||
return ConvertSliceFile(prefabSystemComponent, outputPath, isDryRun, rootEntity);
|
||||
};
|
||||
|
||||
if (!Utilities::InspectSerializedFile(inputPath.c_str(), convertSettings.m_serializeContext, callback))
|
||||
{
|
||||
AZ_Warning("Convert-Slice", false, "Failed to load '%s'. File may not contain an object stream.", inputPath.c_str());
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (packOpened)
|
||||
{
|
||||
[[maybe_unused]] bool closeResult = archiveInterface->ClosePack(filePath);
|
||||
AZ_Warning("Convert-Slice", closeResult, "Failed to close '%s'.", filePath.c_str());
|
||||
}
|
||||
|
||||
AZ_Printf("Convert-Slice", "Finished converting '%s' to '%s'\n", filePath.c_str(), outputPath.c_str());
|
||||
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
|
||||
bool convertResult = ConvertSliceFile(convertSettings.m_serializeContext, filePath, isDryRun);
|
||||
result = result && convertResult;
|
||||
}
|
||||
|
||||
DisconnectFromAssetProcessor();
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SliceConverter::ConvertSliceFile(
|
||||
AzToolsFramework::Prefab::PrefabSystemComponent* prefabSystemComponent, AZ::IO::PathView outputPath, bool isDryRun,
|
||||
AZ::Entity* rootEntity)
|
||||
AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun)
|
||||
{
|
||||
bool result = true;
|
||||
bool packOpened = false;
|
||||
|
||||
auto archiveInterface = AZ::Interface<AZ::IO::IArchive>::Get();
|
||||
|
||||
AZ::IO::Path outputPath = slicePath;
|
||||
outputPath.ReplaceExtension("prefab");
|
||||
|
||||
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
|
||||
AZ_Printf("Convert-Slice", "Converting '%s' to '%s'\n", slicePath.c_str(), outputPath.c_str());
|
||||
|
||||
AZ::IO::Path inputPath = slicePath;
|
||||
auto fileExtension = inputPath.Extension();
|
||||
if (fileExtension == ".ly")
|
||||
{
|
||||
// Special case: for level files, we need to open the .ly zip file and convert the levelentities.editor_xml file
|
||||
// inside of it. All the other files can be ignored as they are deprecated legacy system files that are no longer
|
||||
// loaded with prefab-based levels.
|
||||
packOpened = archiveInterface->OpenPack(slicePath);
|
||||
inputPath.ReplaceFilename("levelentities.editor_xml");
|
||||
AZ_Warning("Convert-Slice", packOpened, " '%s' could not be opened as a pack file.\n", slicePath.c_str());
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning(
|
||||
"Convert-Slice", (fileExtension == ".slice"),
|
||||
" Warning: Only .ly and .slice files are supported, conversion of '%.*s' may not work.\n",
|
||||
AZ_STRING_ARG(fileExtension.Native()));
|
||||
}
|
||||
|
||||
auto callback = [&outputPath, isDryRun](void* classPtr, const Uuid& classId, SerializeContext* context)
|
||||
{
|
||||
if (classId != azrtti_typeid<AZ::Entity>())
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " File not converted: Slice root is not an entity.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ::Entity* rootEntity = reinterpret_cast<AZ::Entity*>(classPtr);
|
||||
return ConvertSliceToPrefab(context, outputPath, isDryRun, rootEntity);
|
||||
};
|
||||
|
||||
// Read in the slice file and call the callback on completion to convert the read-in slice to a prefab.
|
||||
if (!Utilities::InspectSerializedFile(inputPath.c_str(), serializeContext, callback))
|
||||
{
|
||||
AZ_Warning("Convert-Slice", false, "Failed to load '%s'. File may not contain an object stream.", inputPath.c_str());
|
||||
result = false;
|
||||
}
|
||||
|
||||
if (packOpened)
|
||||
{
|
||||
[[maybe_unused]] bool closeResult = archiveInterface->ClosePack(slicePath);
|
||||
AZ_Warning("Convert-Slice", closeResult, "Failed to close '%s'.", slicePath.c_str());
|
||||
}
|
||||
|
||||
AZ_Printf("Convert-Slice", "Finished converting '%s' to '%s'\n", slicePath.c_str(), outputPath.c_str());
|
||||
AZ_Printf("Convert-Slice", "------------------------------------------------------------------------------------------\n");
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
bool SliceConverter::ConvertSliceToPrefab(
|
||||
AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity)
|
||||
{
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
// Find the slice from the root entity.
|
||||
SliceComponent* sliceComponent = AZ::EntityUtils::FindFirstDerivedComponent<SliceComponent>(rootEntity);
|
||||
if (sliceComponent == nullptr)
|
||||
@@ -167,44 +190,21 @@ namespace AZ
|
||||
|
||||
// Get all of the entities from the slice.
|
||||
SliceComponent::EntityList sliceEntities = sliceComponent->GetNewEntities();
|
||||
if (sliceEntities.empty())
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " File not converted: Slice entities could not be retrieved.\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
AZ_Warning("Convert-Slice", sliceComponent->GetSlices().empty(), " Slice depends on other slices, this conversion will lose data.\n");
|
||||
AZ_Printf("Convert-Slice", " Slice contains %zu entities.\n", sliceEntities.size());
|
||||
|
||||
// Create the Prefab with the entities from the slice
|
||||
AZStd::unique_ptr<AzToolsFramework::Prefab::Instance> sourceInstance(
|
||||
prefabSystemComponent->CreatePrefab(sliceEntities, {}, outputPath));
|
||||
prefabSystemComponentInterface->CreatePrefab(sliceEntities, {}, outputPath));
|
||||
|
||||
// Dispatch events here, because prefab creation might trigger asset loads in rare circumstances.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
|
||||
// Set up the Prefab container entity to be a proper Editor entity. (This logic is normally triggered
|
||||
// via an EditorRequests EBus in CreatePrefab, but the subsystem that listens for it isn't present in this tool.)
|
||||
// Fix up the container entity to have the proper components and fix up the slice entities to have the proper hierarchy
|
||||
// with the container as the top-most parent.
|
||||
AzToolsFramework::Prefab::EntityOptionalReference container = sourceInstance->GetContainerEntity();
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, container->get());
|
||||
container->get().AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent());
|
||||
|
||||
// Reparent any root-level slice entities to the container entity.
|
||||
for (auto entity : sliceEntities)
|
||||
{
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
if (!transformComponent->GetParentId().IsValid())
|
||||
{
|
||||
transformComponent->SetParent(container->get().GetId());
|
||||
}
|
||||
}
|
||||
}
|
||||
FixPrefabEntities(container->get(), sliceEntities);
|
||||
|
||||
auto templateId = sourceInstance->GetTemplateId();
|
||||
|
||||
if (templateId == AzToolsFramework::Prefab::InvalidTemplateId)
|
||||
{
|
||||
AZ_Printf("Convert-Slice", " Path error. Path could be invalid, or the prefab may not be loaded in this level.\n");
|
||||
@@ -219,14 +219,27 @@ namespace AZ
|
||||
AZ_Printf("Convert-Slice", " Failed to convert prefab instance data to a PrefabDom.\n");
|
||||
return false;
|
||||
}
|
||||
prefabSystemComponent->UpdatePrefabTemplate(templateId, prefabDom);
|
||||
prefabSystemComponentInterface->UpdatePrefabTemplate(templateId, prefabDom);
|
||||
|
||||
// Dispatch events here, because prefab serialization might trigger asset loads in rare circumstances.
|
||||
AZ::Data::AssetManager::Instance().DispatchEvents();
|
||||
|
||||
// If this slice has nested slices, we need to loop through those, convert them to prefabs as well, and
|
||||
// set up the new nesting relationships correctly.
|
||||
const SliceComponent::SliceList& sliceList = sliceComponent->GetSlices();
|
||||
AZ_Printf("Convert-Slice", " Slice contains %zu nested slices.\n", sliceList.size());
|
||||
if (!sliceList.empty())
|
||||
{
|
||||
bool nestedSliceResult = ConvertNestedSlices(sliceComponent, sourceInstance.get(), serializeContext, isDryRun);
|
||||
if (!nestedSliceResult)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (isDryRun)
|
||||
{
|
||||
PrintPrefab(prefabDom, sourceInstance->GetTemplateSourcePath());
|
||||
PrintPrefab(templateId);
|
||||
return true;
|
||||
}
|
||||
else
|
||||
@@ -235,8 +248,187 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
void SliceConverter::PrintPrefab(const AzToolsFramework::Prefab::PrefabDom& prefabDom, const AZ::IO::Path& templatePath)
|
||||
void SliceConverter::FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities)
|
||||
{
|
||||
// Set up the Prefab container entity to be a proper Editor entity. (This logic is normally triggered
|
||||
// via an EditorRequests EBus in CreatePrefab, but the subsystem that listens for it isn't present in this tool.)
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequestBus::Events::AddRequiredComponents, containerEntity);
|
||||
containerEntity.AddComponent(aznew AzToolsFramework::Prefab::EditorPrefabComponent());
|
||||
|
||||
// Reparent any root-level slice entities to the container entity.
|
||||
for (auto entity : sliceEntities)
|
||||
{
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
entity->FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
if (!transformComponent->GetParentId().IsValid())
|
||||
{
|
||||
transformComponent->SetParent(containerEntity.GetId());
|
||||
transformComponent->UpdateCachedWorldTransform();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool SliceConverter::ConvertNestedSlices(
|
||||
SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance,
|
||||
AZ::SerializeContext* serializeContext, bool isDryRun)
|
||||
{
|
||||
const SliceComponent::SliceList& sliceList = sliceComponent->GetSlices();
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
for (auto& slice : sliceList)
|
||||
{
|
||||
// Get the nested slice asset
|
||||
auto sliceAsset = slice.GetSliceAsset();
|
||||
sliceAsset.QueueLoad();
|
||||
sliceAsset.BlockUntilLoadComplete();
|
||||
|
||||
// The slice list gives us asset IDs, and we need to get to the source path. So first we get the asset path from the ID,
|
||||
// then we get the source path from the asset path.
|
||||
|
||||
AZStd::string processedAssetPath;
|
||||
AZ::Data::AssetCatalogRequestBus::BroadcastResult(
|
||||
processedAssetPath, &AZ::Data::AssetCatalogRequests::GetAssetPathById, sliceAsset.GetId());
|
||||
|
||||
AZStd::string assetPath;
|
||||
AzToolsFramework::AssetSystemRequestBus::Broadcast(
|
||||
&AzToolsFramework::AssetSystemRequestBus::Events::GetFullSourcePathFromRelativeProductPath,
|
||||
processedAssetPath, assetPath);
|
||||
if (assetPath.empty())
|
||||
{
|
||||
AZ_Warning("Convert-Slice", false,
|
||||
" Source path for nested slice '%s' could not be found, slice not converted.", processedAssetPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Now, convert the nested slice to a prefab.
|
||||
bool nestedSliceResult = ConvertSliceFile(serializeContext, assetPath, isDryRun);
|
||||
if (!nestedSliceResult)
|
||||
{
|
||||
AZ_Warning("Convert-Slice", nestedSliceResult, " Nested slice '%s' could not be converted.", assetPath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Load the prefab template for the newly-created nested prefab.
|
||||
// To get the template, we need to take our absolute slice path and turn it into a project-relative prefab path.
|
||||
AZ::IO::Path nestedPrefabPath = assetPath;
|
||||
nestedPrefabPath.ReplaceExtension("prefab");
|
||||
|
||||
auto prefabLoaderInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabLoaderInterface>::Get();
|
||||
nestedPrefabPath = prefabLoaderInterface->GetRelativePathToProject(nestedPrefabPath);
|
||||
|
||||
AzToolsFramework::Prefab::TemplateId nestedTemplateId =
|
||||
prefabSystemComponentInterface->GetTemplateIdFromFilePath(nestedPrefabPath);
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate =
|
||||
prefabSystemComponentInterface->FindTemplate(nestedTemplateId);
|
||||
|
||||
// For each slice instance of the nested slice, convert it to a nested prefab instance instead.
|
||||
|
||||
auto instances = slice.GetInstances();
|
||||
AZ_Printf(
|
||||
"Convert-Slice", " Attaching %zu instances of nested slice '%s'.\n", instances.size(),
|
||||
nestedPrefabPath.Native().c_str());
|
||||
|
||||
for (auto& instance : instances)
|
||||
{
|
||||
bool instanceConvertResult = ConvertSliceInstance(instance, sliceAsset, nestedTemplate, sourceInstance);
|
||||
if (!instanceConvertResult)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SliceConverter::ConvertSliceInstance(
|
||||
[[maybe_unused]] AZ::SliceComponent::SliceInstance& instance,
|
||||
[[maybe_unused]] AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate,
|
||||
AzToolsFramework::Prefab::Instance* topLevelInstance)
|
||||
{
|
||||
auto instanceToTemplateInterface = AZ::Interface<AzToolsFramework::Prefab::InstanceToTemplateInterface>::Get();
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
// Create a new unmodified prefab Instance for the nested slice instance.
|
||||
auto nestedInstance = AZStd::make_unique<AzToolsFramework::Prefab::Instance>();
|
||||
AzToolsFramework::Prefab::Instance::EntityList newEntities;
|
||||
if (!AzToolsFramework::Prefab::PrefabDomUtils::LoadInstanceFromPrefabDom(
|
||||
*nestedInstance, newEntities, nestedTemplate->get().GetPrefabDom()))
|
||||
{
|
||||
AZ_Error(
|
||||
"Convert-Slice", false, " Failed to load and instantiate nested Prefab Template '%s'.",
|
||||
nestedTemplate->get().GetFilePath().c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
// Get the DOM for the unmodified nested instance. This will be used later below for generating the correct patch
|
||||
// to the top-level template DOM.
|
||||
AzToolsFramework::Prefab::PrefabDom unmodifiedNestedInstanceDom;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(unmodifiedNestedInstanceDom, *(nestedInstance.get()));
|
||||
|
||||
// Currently, DataPatch conversions for nested slices aren't implemented, so all nested slice overrides will
|
||||
// be lost.
|
||||
AZ_Warning(
|
||||
"Convert-Slice", false, " Nested slice instances will lose all of their override data during conversion.",
|
||||
nestedTemplate->get().GetFilePath().c_str());
|
||||
|
||||
// Set the container entity of the nested prefab to have the top-level prefab as the parent.
|
||||
// Once DataPatch conversions are supported, this will need to change to nest the prefab under the appropriate entity
|
||||
// within the level.
|
||||
auto containerEntity = nestedInstance->GetContainerEntity();
|
||||
AzToolsFramework::Components::TransformComponent* transformComponent =
|
||||
containerEntity->get().FindComponent<AzToolsFramework::Components::TransformComponent>();
|
||||
if (transformComponent)
|
||||
{
|
||||
transformComponent->SetParent(topLevelInstance->GetContainerEntityId());
|
||||
transformComponent->UpdateCachedWorldTransform();
|
||||
}
|
||||
|
||||
// Add the nested instance itself to the top-level prefab. To do this, we need to add it to our top-level instance,
|
||||
// create a patch out of it, and patch the top-level prefab template.
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomBefore;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomBefore, *topLevelInstance);
|
||||
|
||||
AzToolsFramework::Prefab::Instance& addedInstance = topLevelInstance->AddInstance(AZStd::move(nestedInstance));
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom topLevelInstanceDomAfter;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(topLevelInstanceDomAfter, *topLevelInstance);
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom addedInstancePatch;
|
||||
instanceToTemplateInterface->GeneratePatch(addedInstancePatch, topLevelInstanceDomBefore, topLevelInstanceDomAfter);
|
||||
instanceToTemplateInterface->PatchTemplate(addedInstancePatch, topLevelInstance->GetTemplateId());
|
||||
|
||||
// Get the DOM for the modified nested instance. Now that the data has been fixed up, and the instance has been added
|
||||
// to the top-level instance, we've got all the changes we need to generate the correct patch.
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom modifiedNestedInstanceDom;
|
||||
instanceToTemplateInterface->GenerateDomForInstance(modifiedNestedInstanceDom, addedInstance);
|
||||
|
||||
AzToolsFramework::Prefab::PrefabDom linkPatch;
|
||||
instanceToTemplateInterface->GeneratePatch(linkPatch, unmodifiedNestedInstanceDom, modifiedNestedInstanceDom);
|
||||
|
||||
prefabSystemComponentInterface->CreateLink(
|
||||
topLevelInstance->GetTemplateId(), addedInstance.GetTemplateId(), addedInstance.GetInstanceAlias(), linkPatch,
|
||||
AzToolsFramework::Prefab::InvalidLinkId);
|
||||
prefabSystemComponentInterface->PropagateTemplateChanges(topLevelInstance->GetTemplateId());
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void SliceConverter::PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId)
|
||||
{
|
||||
auto prefabSystemComponentInterface = AZ::Interface<AzToolsFramework::Prefab::PrefabSystemComponentInterface>::Get();
|
||||
|
||||
auto prefabTemplate = prefabSystemComponentInterface->FindTemplate(templateId);
|
||||
auto& prefabDom = prefabTemplate->get().GetPrefabDom();
|
||||
const AZ::IO::Path& templatePath = prefabTemplate->get().GetFilePath();
|
||||
|
||||
rapidjson::StringBuffer prefabBuffer;
|
||||
rapidjson::PrettyWriter<rapidjson::StringBuffer> writer(prefabBuffer);
|
||||
prefabDom.Accept(writer);
|
||||
@@ -260,5 +452,41 @@ namespace AZ
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SliceConverter::ConnectToAssetProcessor()
|
||||
{
|
||||
AzFramework::AssetSystem::ConnectionSettings connectionSettings;
|
||||
AzFramework::AssetSystem::ReadConnectionSettingsFromSettingsRegistry(connectionSettings);
|
||||
|
||||
connectionSettings.m_launchAssetProcessorOnFailedConnection = true;
|
||||
connectionSettings.m_connectionDirection =
|
||||
AzFramework::AssetSystem::ConnectionSettings::ConnectionDirection::ConnectToAssetProcessor;
|
||||
connectionSettings.m_connectionIdentifier = AzFramework::AssetSystem::ConnectionIdentifiers::Editor;
|
||||
connectionSettings.m_loggingCallback = [](AZStd::string_view logData)
|
||||
{
|
||||
AZ_Printf("Convert-Slice", "%.*s\n", AZ_STRING_ARG(logData));
|
||||
};
|
||||
|
||||
bool connectedToAssetProcessor = false;
|
||||
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(
|
||||
connectedToAssetProcessor, &AzFramework::AssetSystemRequestBus::Events::EstablishAssetProcessorConnection,
|
||||
connectionSettings);
|
||||
|
||||
return connectedToAssetProcessor;
|
||||
}
|
||||
|
||||
void SliceConverter::DisconnectFromAssetProcessor()
|
||||
{
|
||||
AzFramework::AssetSystemRequestBus::Broadcast(
|
||||
&AzFramework::AssetSystem::AssetSystemRequests::StartDisconnectingAssetProcessor);
|
||||
|
||||
// Wait for the disconnect to finish.
|
||||
bool disconnected = false;
|
||||
AzFramework::AssetSystemRequestBus::BroadcastResult(disconnected,
|
||||
&AzFramework::AssetSystem::AssetSystemRequests::WaitUntilAssetProcessorDisconnected, AZStd::chrono::seconds(30));
|
||||
|
||||
AZ_Error("Convert-Slice", disconnected, "Asset Processor failed to disconnect successfully.");
|
||||
}
|
||||
|
||||
} // namespace SerializeContextTools
|
||||
} // namespace AZ
|
||||
|
||||
@@ -42,11 +42,20 @@ namespace AZ
|
||||
static bool ConvertSliceFiles(Application& application);
|
||||
|
||||
private:
|
||||
static bool ConnectToAssetProcessor();
|
||||
static void DisconnectFromAssetProcessor();
|
||||
|
||||
static bool ConvertSliceFile(AzToolsFramework::Prefab::PrefabSystemComponent* prefabSystemComponent,
|
||||
AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity);
|
||||
|
||||
static void PrintPrefab(const AzToolsFramework::Prefab::PrefabDom& prefabDom, const AZ::IO::Path& templatePath);
|
||||
static bool ConvertSliceFile(AZ::SerializeContext* serializeContext, const AZStd::string& slicePath, bool isDryRun);
|
||||
static bool ConvertSliceToPrefab(
|
||||
AZ::SerializeContext* serializeContext, AZ::IO::PathView outputPath, bool isDryRun, AZ::Entity* rootEntity);
|
||||
static void FixPrefabEntities(AZ::Entity& containerEntity, SliceComponent::EntityList& sliceEntities);
|
||||
static bool ConvertNestedSlices(
|
||||
SliceComponent* sliceComponent, AzToolsFramework::Prefab::Instance* sourceInstance,
|
||||
AZ::SerializeContext* serializeContext, bool isDryRun);
|
||||
static bool SliceConverter::ConvertSliceInstance(
|
||||
AZ::SliceComponent::SliceInstance& instance, AZ::Data::Asset<AZ::SliceAsset>& sliceAsset,
|
||||
AzToolsFramework::Prefab::TemplateReference nestedTemplate, AzToolsFramework::Prefab::Instance* topLevelInstance);
|
||||
static void PrintPrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
static bool SavePrefab(AzToolsFramework::Prefab::TemplateId templateId);
|
||||
};
|
||||
} // namespace SerializeContextTools
|
||||
|
||||
+8
-9
@@ -12,17 +12,16 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <ModernViewportCameraControllerRequestBus.h>
|
||||
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h>
|
||||
#include <AzFramework/Entity/EntityDebugDisplayBus.h>
|
||||
#include <AzFramework/Viewport/CameraInput.h>
|
||||
#include <AzFramework/Viewport/MultiViewportController.h>
|
||||
|
||||
namespace SandboxEditor
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
class ModernViewportCameraControllerInstance;
|
||||
class ModernViewportCameraController
|
||||
class ModularViewportCameraController
|
||||
: public AzFramework::MultiViewportController<
|
||||
ModernViewportCameraControllerInstance, AzFramework::ViewportControllerPriority::DispatchToAllPriorities>
|
||||
{
|
||||
@@ -39,19 +38,19 @@ namespace SandboxEditor
|
||||
};
|
||||
|
||||
class ModernViewportCameraControllerInstance final
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModernViewportCameraController>,
|
||||
public ModernViewportCameraControllerRequestBus::Handler,
|
||||
: public AzFramework::MultiViewportControllerInstanceInterface<ModularViewportCameraController>,
|
||||
public ModularViewportCameraControllerRequestBus::Handler,
|
||||
private AzFramework::ViewportDebugDisplayEventBus::Handler
|
||||
{
|
||||
public:
|
||||
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModernViewportCameraController* controller);
|
||||
explicit ModernViewportCameraControllerInstance(AzFramework::ViewportId viewportId, ModularViewportCameraController* controller);
|
||||
~ModernViewportCameraControllerInstance() override;
|
||||
|
||||
// MultiViewportControllerInstanceInterface overrides ...
|
||||
bool HandleInputChannelEvent(const AzFramework::ViewportControllerInputEvent& event) override;
|
||||
void UpdateViewport(const AzFramework::ViewportControllerUpdateEvent& event) override;
|
||||
|
||||
// ModernViewportCameraControllerRequestBus overrides ...
|
||||
// ModularViewportCameraControllerRequestBus overrides ...
|
||||
void InterpolateToTransform(const AZ::Transform& worldFromLocal) override;
|
||||
|
||||
private:
|
||||
@@ -76,4 +75,4 @@ namespace SandboxEditor
|
||||
|
||||
AZ::RPI::ViewportContext::MatrixChangedEvent::Handler m_cameraViewMatrixChangeHandler;
|
||||
};
|
||||
} // namespace SandboxEditor
|
||||
} // namespace AtomToolsFramework
|
||||
+5
-5
@@ -20,11 +20,11 @@ namespace AZ
|
||||
class Transform;
|
||||
}
|
||||
|
||||
namespace SandboxEditor
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
//! Provides an interface to control the modern viewport camera controller from the Editor.
|
||||
//! @note The bus is addressed by viewport id.
|
||||
class ModernViewportCameraControllerRequests : public AZ::EBusTraits
|
||||
class ModularViewportCameraControllerRequests : public AZ::EBusTraits
|
||||
{
|
||||
public:
|
||||
using BusIdType = AzFramework::ViewportId;
|
||||
@@ -35,8 +35,8 @@ namespace SandboxEditor
|
||||
virtual void InterpolateToTransform(const AZ::Transform& worldFromLocal) = 0;
|
||||
|
||||
protected:
|
||||
~ModernViewportCameraControllerRequests() = default;
|
||||
~ModularViewportCameraControllerRequests() = default;
|
||||
};
|
||||
|
||||
using ModernViewportCameraControllerRequestBus = AZ::EBus<ModernViewportCameraControllerRequests>;
|
||||
} // namespace SandboxEditor
|
||||
using ModularViewportCameraControllerRequestBus = AZ::EBus<ModularViewportCameraControllerRequests>;
|
||||
} // namespace AtomToolsFramework
|
||||
+9
-10
@@ -10,10 +10,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ModernViewportCameraController.h"
|
||||
|
||||
#include <Atom/RPI.Public/ViewportContext.h>
|
||||
#include <Atom/RPI.Public/ViewportContextBus.h>
|
||||
#include <AtomToolsFramework/Viewport/ModularViewportCameraController.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/Interface/Interface.h>
|
||||
#include <AzFramework/Input/Devices/Keyboard/InputDeviceKeyboard.h>
|
||||
@@ -23,7 +22,7 @@
|
||||
#include <AzFramework/Windowing/WindowBus.h>
|
||||
#include <AzToolsFramework/Viewport/ViewportMessages.h>
|
||||
|
||||
namespace SandboxEditor
|
||||
namespace AtomToolsFramework
|
||||
{
|
||||
// debug
|
||||
void DrawPreviewAxis(AzFramework::DebugDisplayRequests& display, const AZ::Transform& transform, const float axisLength)
|
||||
@@ -53,12 +52,12 @@ namespace SandboxEditor
|
||||
return viewportContext;
|
||||
}
|
||||
|
||||
void ModernViewportCameraController::SetCameraListBuilderCallback(const CameraListBuilder& builder)
|
||||
void ModularViewportCameraController::SetCameraListBuilderCallback(const CameraListBuilder& builder)
|
||||
{
|
||||
m_cameraListBuilder = builder;
|
||||
}
|
||||
|
||||
void ModernViewportCameraController::SetupCameras(AzFramework::Cameras& cameras)
|
||||
void ModularViewportCameraController::SetupCameras(AzFramework::Cameras& cameras)
|
||||
{
|
||||
if (m_cameraListBuilder)
|
||||
{
|
||||
@@ -67,8 +66,8 @@ namespace SandboxEditor
|
||||
}
|
||||
|
||||
ModernViewportCameraControllerInstance::ModernViewportCameraControllerInstance(
|
||||
const AzFramework::ViewportId viewportId, ModernViewportCameraController* controller)
|
||||
: MultiViewportControllerInstanceInterface<ModernViewportCameraController>(viewportId, controller)
|
||||
const AzFramework::ViewportId viewportId, ModularViewportCameraController* controller)
|
||||
: MultiViewportControllerInstanceInterface<ModularViewportCameraController>(viewportId, controller)
|
||||
{
|
||||
controller->SetupCameras(m_cameraSystem.m_cameras);
|
||||
|
||||
@@ -88,12 +87,12 @@ namespace SandboxEditor
|
||||
}
|
||||
|
||||
AzFramework::ViewportDebugDisplayEventBus::Handler::BusConnect(AzToolsFramework::GetEntityContextId());
|
||||
ModernViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
|
||||
ModularViewportCameraControllerRequestBus::Handler::BusConnect(viewportId);
|
||||
}
|
||||
|
||||
ModernViewportCameraControllerInstance::~ModernViewportCameraControllerInstance()
|
||||
{
|
||||
ModernViewportCameraControllerRequestBus::Handler::BusDisconnect();
|
||||
ModularViewportCameraControllerRequestBus::Handler::BusDisconnect();
|
||||
AzFramework::ViewportDebugDisplayEventBus::Handler::BusDisconnect();
|
||||
}
|
||||
|
||||
@@ -182,4 +181,4 @@ namespace SandboxEditor
|
||||
m_transformStart = m_camera.Transform();
|
||||
m_transformEnd = worldFromLocal;
|
||||
}
|
||||
} // namespace SandboxEditor
|
||||
} // namespace AtomToolsFramework
|
||||
@@ -24,6 +24,8 @@ set(FILES
|
||||
Include/AtomToolsFramework/Util/MaterialPropertyUtil.h
|
||||
Include/AtomToolsFramework/Util/Util.h
|
||||
Include/AtomToolsFramework/Viewport/RenderViewportWidget.h
|
||||
Include/AtomToolsFramework/Viewport/ModularViewportCameraController.h
|
||||
Include/AtomToolsFramework/Viewport/ModularViewportCameraControllerRequestBus.h
|
||||
Source/Communication/LocalServer.cpp
|
||||
Source/Communication/LocalSocket.cpp
|
||||
Source/Debug/TraceRecorder.cpp
|
||||
@@ -38,4 +40,5 @@ set(FILES
|
||||
Source/Util/MaterialPropertyUtil.cpp
|
||||
Source/Util/Util.cpp
|
||||
Source/Viewport/RenderViewportWidget.cpp
|
||||
Source/Viewport/ModularViewportCameraController.cpp
|
||||
)
|
||||
|
||||
@@ -72,11 +72,6 @@ namespace SceneBuilder
|
||||
m_sceneBuilder.BusDisconnect();
|
||||
}
|
||||
|
||||
void BuilderPluginComponent::GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required)
|
||||
{
|
||||
required.emplace_back(AZ_CRC_CE("AssetImportRequestHandler"));
|
||||
}
|
||||
|
||||
void BuilderPluginComponent::Reflect(AZ::ReflectContext* context)
|
||||
{
|
||||
AZ::SerializeContext* serializeContext = azrtti_cast<AZ::SerializeContext*>(context);
|
||||
@@ -86,4 +81,5 @@ namespace SceneBuilder
|
||||
->Attribute(AZ::Edit::Attributes::SystemComponentTags, AZStd::vector<AZ::Crc32>({ AssetBuilderSDK::ComponentTags::AssetBuilder }));
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace SceneBuilder
|
||||
|
||||
@@ -32,8 +32,6 @@ namespace SceneBuilder
|
||||
void Activate() override;
|
||||
void Deactivate() override;
|
||||
|
||||
static void GetRequiredServices(AZ::ComponentDescriptor::DependencyArrayType& required);
|
||||
|
||||
private:
|
||||
SceneBuilderWorker m_sceneBuilder;
|
||||
};
|
||||
|
||||
@@ -118,6 +118,8 @@ namespace SurfaceData
|
||||
|
||||
void EditorSurfaceDataSystemComponent::Deactivate()
|
||||
{
|
||||
m_surfaceTagNameAssets.clear();
|
||||
|
||||
AzFramework::AssetCatalogEventBus::Handler::BusDisconnect();
|
||||
AzToolsFramework::Components::EditorComponentBase::Deactivate();
|
||||
SurfaceDataTagProviderRequestBus::Handler::BusDisconnect();
|
||||
|
||||
@@ -9,6 +9,18 @@
|
||||
},
|
||||
"PythonAssetBuilder.Editor": {
|
||||
"AutoLoad": false
|
||||
},
|
||||
"AWSCore.Editor": {
|
||||
"AutoLoad": false
|
||||
},
|
||||
"AWSClientAuth": {
|
||||
"AutoLoad": false
|
||||
},
|
||||
"AWSClientAuth.Editor": {
|
||||
"AutoLoad": false
|
||||
},
|
||||
"AWSMetrics": {
|
||||
"AutoLoad": false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
{
|
||||
"O3DE":
|
||||
{
|
||||
"SceneAPI":
|
||||
{
|
||||
"AssetImporter":
|
||||
{
|
||||
"SupportedFileTypeExtensions":
|
||||
[
|
||||
".fbx",
|
||||
".stl"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,15 +29,15 @@ string(TOLOWER ${PROJECT_NAME} _project_name_lower)
|
||||
set(CPACK_PACKAGE_FILE_NAME "${_project_name_lower}_${LY_VERSION_STRING}_installer")
|
||||
|
||||
set(DEFAULT_LICENSE_NAME "Apache-2.0")
|
||||
set(DEFAULT_LICENSE_FILE "${CMAKE_SOURCE_DIR}/LICENSE.txt")
|
||||
set(DEFAULT_LICENSE_FILE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE.txt")
|
||||
|
||||
set(CPACK_RESOURCE_FILE_LICENSE ${DEFAULT_LICENSE_FILE})
|
||||
set(CPACK_LICENSE_URL ${LY_INSTALLER_LICENSE_URL})
|
||||
|
||||
set(CPACK_PACKAGE_INSTALL_DIRECTORY "${CPACK_PACKAGE_VENDOR}/${CPACK_PACKAGE_VERSION}")
|
||||
|
||||
# CMAKE_SOURCE_DIR doesn't equate to anything during execution of pre/post build scripts
|
||||
set(CPACK_SOURCE_DIR ${CMAKE_SOURCE_DIR}/cmake)
|
||||
# neither of the SOURCE_DIR variables equate to anything during execution of pre/post build scripts
|
||||
set(CPACK_SOURCE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
|
||||
|
||||
# attempt to apply platform specific settings
|
||||
ly_get_absolute_pal_filename(pal_dir ${CPACK_SOURCE_DIR}/Platform/${PAL_HOST_PLATFORM_NAME})
|
||||
|
||||
Reference in New Issue
Block a user