Merge branch 'stabilization/2106' into cpack/stabilization/2106
This commit is contained in:
@@ -175,4 +175,11 @@ namespace AZ::Utils
|
||||
path /= ".o3de";
|
||||
return path.Native();
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPathString GetO3deLogsDirectory()
|
||||
{
|
||||
AZ::IO::FixedMaxPath path = GetO3deManifestDirectory();
|
||||
path /= "Logs";
|
||||
return path.Native();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -97,6 +97,9 @@ namespace AZ
|
||||
//! Retrieves the full path where the manifest file lives, i.e. "<userhome>/.o3de/o3de_manifest.json"
|
||||
AZ::IO::FixedMaxPathString GetEngineManifestPath();
|
||||
|
||||
//! Retrieves the full directory to the O3DE logs directory, i.e. "<userhome>/.o3de/Logs"
|
||||
AZ::IO::FixedMaxPathString GetO3deLogsDirectory();
|
||||
|
||||
//! Retrieves the App root path to use on the current platform
|
||||
//! If the optional is not engaged the AppRootPath should be calculated based
|
||||
//! on the location of the bootstrap.cfg file
|
||||
|
||||
@@ -2891,7 +2891,7 @@ void CCryEditApp::OpenProjectManager(const AZStd::string& screen)
|
||||
{
|
||||
// provide the current project path for in case we want to update the project
|
||||
AZ::IO::FixedMaxPathString projectPath = AZ::Utils::GetProjectPath();
|
||||
const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project_path %s", screen.c_str(), projectPath.c_str());
|
||||
const AZStd::string commandLineOptions = AZStd::string::format(" --screen %s --project-path %s", screen.c_str(), projectPath.c_str());
|
||||
bool launchSuccess = AzFramework::ProjectManager::LaunchProjectManager(commandLineOptions);
|
||||
if (!launchSuccess)
|
||||
{
|
||||
|
||||
@@ -514,18 +514,28 @@ void EditorViewportWidget::Update()
|
||||
// Disable rendering to avoid recursion into Update()
|
||||
PushDisableRendering();
|
||||
|
||||
|
||||
//get debug display interface for the viewport
|
||||
AzFramework::DebugDisplayRequestBus::BusPtr debugDisplayBus;
|
||||
AzFramework::DebugDisplayRequestBus::Bind(debugDisplayBus, GetViewportId());
|
||||
AZ_Assert(debugDisplayBus, "Invalid DebugDisplayRequestBus.");
|
||||
|
||||
AzFramework::DebugDisplayRequests* debugDisplay =
|
||||
AzFramework::DebugDisplayRequestBus::FindFirstHandler(debugDisplayBus);
|
||||
|
||||
|
||||
// draw debug visualizations
|
||||
if (m_debugDisplay)
|
||||
if (debugDisplay)
|
||||
{
|
||||
const AZ::u32 prevState = m_debugDisplay->GetState();
|
||||
m_debugDisplay->SetState(
|
||||
const AZ::u32 prevState = debugDisplay->GetState();
|
||||
debugDisplay->SetState(
|
||||
e_Mode3D | e_AlphaBlended | e_FillModeSolid | e_CullModeBack | e_DepthWriteOn | e_DepthTestOn);
|
||||
|
||||
AzFramework::EntityDebugDisplayEventBus::Broadcast(
|
||||
&AzFramework::EntityDebugDisplayEvents::DisplayEntityViewport,
|
||||
AzFramework::ViewportInfo{ GetViewportId() }, *m_debugDisplay);
|
||||
AzFramework::ViewportInfo{ GetViewportId() }, *debugDisplay);
|
||||
|
||||
m_debugDisplay->SetState(prevState);
|
||||
debugDisplay->SetState(prevState);
|
||||
}
|
||||
|
||||
QtViewport::Update();
|
||||
|
||||
@@ -20,12 +20,11 @@ if (NOT python_package_name)
|
||||
message(WARNING "Python was not found in the package assocation list. Did someone call ly_associate_package(xxxxxxx Python) ?")
|
||||
endif()
|
||||
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAME ProjectManager.Static STATIC
|
||||
NAMESPACE AZ
|
||||
AUTOMOC
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_files.cmake
|
||||
@@ -47,6 +46,60 @@ ly_add_target(
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzToolsFramework
|
||||
AZ::AzQtComponents
|
||||
)
|
||||
)
|
||||
|
||||
ly_add_target(
|
||||
NAME ProjectManager APPLICATION
|
||||
OUTPUT_NAME o3de
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_app_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzCore
|
||||
AZ::AzFramework
|
||||
AZ::AzQtComponents
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
if(PAL_TRAIT_BUILD_TESTS_SUPPORTED)
|
||||
ly_add_target(
|
||||
NAME ProjectManager.Tests EXECUTABLE
|
||||
NAMESPACE AZ
|
||||
AUTORCC
|
||||
FILES_CMAKE
|
||||
project_manager_tests_files.cmake
|
||||
Platform/${PAL_PLATFORM_NAME}/PAL_${PAL_PLATFORM_NAME_LOWERCASE}_tests_files.cmake
|
||||
INCLUDE_DIRECTORIES
|
||||
PRIVATE
|
||||
Source
|
||||
Platform/${PAL_PLATFORM_NAME}
|
||||
BUILD_DEPENDENCIES
|
||||
PRIVATE
|
||||
3rdParty::Qt::Core
|
||||
3rdParty::Qt::Concurrent
|
||||
3rdParty::Qt::Widgets
|
||||
3rdParty::Python
|
||||
3rdParty::pybind11
|
||||
AZ::AzTest
|
||||
AZ::AzFramework
|
||||
AZ::AzFrameworkTestShared
|
||||
AZ::ProjectManager.Static
|
||||
)
|
||||
|
||||
ly_add_googletest(
|
||||
NAME AZ::ProjectManager.Tests
|
||||
TEST_COMMAND $<TARGET_FILE:AZ::ProjectManager.Tests> --unittest
|
||||
)
|
||||
|
||||
endif()
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Linux.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS true
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include <ProjectManager_Test_Traits_Linux.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Mac.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include <ProjectManager_Test_Traits_Mac.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
ProjectManager_Test_Traits_Platform.h
|
||||
ProjectManager_Test_Traits_Windows.h
|
||||
)
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include <ProjectManager_Test_Traits_Windows.h>
|
||||
@@ -0,0 +1,15 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#define AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS false
|
||||
@@ -7,6 +7,11 @@ QMainWindow {
|
||||
margin:0;
|
||||
}
|
||||
|
||||
#ScreensCtrl {
|
||||
min-width:1200px;
|
||||
min-height:800px;
|
||||
}
|
||||
|
||||
QPushButton:focus {
|
||||
outline: none;
|
||||
border:1px solid #1e70eb;
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
/*
|
||||
* 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 <Application.h>
|
||||
#include <ProjectUtils.h>
|
||||
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/Utils/Utils.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzFramework/Logging/LoggingComponent.h>
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzQtComponents/Components/WindowDecorationWrapper.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QDir>
|
||||
#include <QMessageBox>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
Application::~Application()
|
||||
{
|
||||
TearDown();
|
||||
}
|
||||
|
||||
bool Application::Init(bool interactive)
|
||||
{
|
||||
constexpr const char* applicationName { "O3DE" };
|
||||
|
||||
QApplication::setOrganizationName(applicationName);
|
||||
QApplication::setOrganizationDomain("o3de.org");
|
||||
|
||||
QCoreApplication::setApplicationName(applicationName);
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
|
||||
// Use the LogComponent for non-dev logging log
|
||||
RegisterComponentDescriptor(AzFramework::LogComponent::CreateDescriptor());
|
||||
|
||||
// set the log alias to .o3de/Logs instead of the default user/logs
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
|
||||
// DevWriteStorage is where the event log is written during development
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::FilePathKey_DevWriteStorage, path.LexicallyNormal().Native());
|
||||
|
||||
// Save event logs to .o3de/Logs/eventlogger/EventLogO3DE.azsl
|
||||
m_settingsRegistry->Set(AZ::SettingsRegistryMergeUtils::BuildTargetNameKey, applicationName);
|
||||
|
||||
Start(AzFramework::Application::Descriptor());
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
|
||||
QLocale::setDefault(QLocale(QLocale::English, QLocale::UnitedStates));
|
||||
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
// Create the actual Qt Application - this needs to happen before using QMessageBox
|
||||
m_app.reset(new QApplication(*GetArgC(), *GetArgV()));
|
||||
|
||||
if(!InitLog(applicationName))
|
||||
{
|
||||
AZ_Warning("ProjectManager", false, "Failed to init logging");
|
||||
}
|
||||
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(GetEngineRoot());
|
||||
if (!m_pythonBindings || !m_pythonBindings->PythonStarted())
|
||||
{
|
||||
if (interactive)
|
||||
{
|
||||
QMessageBox::critical(nullptr, QObject::tr("Failed to start Python"),
|
||||
QObject::tr("This tool requires an O3DE engine with a Python runtime, "
|
||||
"but either Python is missing or mis-configured. Please rename "
|
||||
"your python/runtime folder to python/runtime_bak, then run "
|
||||
"python/get_python.bat to restore the Python runtime folder."));
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
const AZ::CommandLine* commandLine = GetCommandLine();
|
||||
AZ_Assert(commandLine, "Failed to get command line");
|
||||
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects;
|
||||
if (size_t screenSwitchCount = commandLine->GetNumSwitchValues("screen"); screenSwitchCount > 0)
|
||||
{
|
||||
QString screenOption = commandLine->GetSwitchValue("screen", screenSwitchCount - 1).c_str();
|
||||
ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption);
|
||||
if (screen != ProjectManagerScreen::Invalid)
|
||||
{
|
||||
startScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath;
|
||||
if (size_t projectSwitchCount = commandLine->GetNumSwitchValues("project-path"); projectSwitchCount > 0)
|
||||
{
|
||||
projectPath = commandLine->GetSwitchValue("project-path", projectSwitchCount - 1).c_str();
|
||||
}
|
||||
|
||||
m_mainWindow.reset(new ProjectManagerWindow(nullptr, projectPath, startScreen));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Application::InitLog(const char* logName)
|
||||
{
|
||||
if (!m_entity)
|
||||
{
|
||||
// override the log alias to the O3de Logs directory instead of the default project user/Logs folder
|
||||
AZ::IO::FixedMaxPath path = AZ::Utils::GetO3deLogsDirectory();
|
||||
AZ::IO::FileIOBase* fileIO = AZ::IO::FileIOBase::GetInstance();
|
||||
AZ_Assert(fileIO, "Failed to get FileIOBase instance");
|
||||
|
||||
fileIO->SetAlias("@log@", path.LexicallyNormal().Native().c_str());
|
||||
|
||||
// this entity exists because we need a home for LogComponent
|
||||
// and cannot use the system entity because we need to be able to call SetLogFileBaseName
|
||||
// so the log will be named O3DE.log
|
||||
m_entity = aznew AZ::Entity("Application Entity");
|
||||
if (m_entity)
|
||||
{
|
||||
AzFramework::LogComponent* logger = aznew AzFramework::LogComponent();
|
||||
AZ_Assert(logger, "Failed to create LogComponent");
|
||||
logger->SetLogFileBaseName(logName);
|
||||
m_entity->AddComponent(logger);
|
||||
m_entity->Init();
|
||||
m_entity->Activate();
|
||||
}
|
||||
}
|
||||
|
||||
return m_entity != nullptr;
|
||||
}
|
||||
|
||||
void Application::TearDown()
|
||||
{
|
||||
if (m_entity)
|
||||
{
|
||||
m_entity->Deactivate();
|
||||
delete m_entity;
|
||||
m_entity = nullptr;
|
||||
}
|
||||
|
||||
m_pythonBindings.reset();
|
||||
m_mainWindow.reset();
|
||||
m_app.reset();
|
||||
}
|
||||
|
||||
bool Application::Run()
|
||||
{
|
||||
// Set up the Style Manager
|
||||
AzQtComponents::StyleManager styleManager(qApp);
|
||||
styleManager.initialize(qApp, GetEngineRoot());
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
AZ::IO::FixedMaxPath engineRoot(GetEngineRoot());
|
||||
QDir rootDir(engineRoot.c_str());
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRoot);
|
||||
|
||||
// set stylesheet after creating the main window or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(m_mainWindow.data(), QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// the decoration wrapper is intended to remember window positioning and sizing
|
||||
auto wrapper = new AzQtComponents::WindowDecorationWrapper();
|
||||
wrapper->setGuest(m_mainWindow.data());
|
||||
wrapper->show();
|
||||
m_mainWindow->show();
|
||||
|
||||
qApp->setQuitOnLastWindowClosed(true);
|
||||
|
||||
// Run the application
|
||||
return qApp->exec();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* 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 <AzFramework/Application/Application.h>
|
||||
#include <QCoreApplication>
|
||||
#include <PythonBindings.h>
|
||||
#include <ProjectManagerWindow.h>
|
||||
#endif
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
class Entity;
|
||||
}
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class Application
|
||||
: public AzFramework::Application
|
||||
{
|
||||
public:
|
||||
using AzFramework::Application::Application;
|
||||
virtual ~Application();
|
||||
|
||||
bool Init(bool interactive = true);
|
||||
bool Run();
|
||||
void TearDown();
|
||||
|
||||
private:
|
||||
bool InitLog(const char* logName);
|
||||
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
QSharedPointer<QCoreApplication> m_app;
|
||||
QSharedPointer<ProjectManagerWindow> m_mainWindow;
|
||||
|
||||
AZ::Entity* m_entity = nullptr;
|
||||
};
|
||||
}
|
||||
@@ -25,7 +25,7 @@ namespace O3DE::ProjectManager
|
||||
EngineSettingsScreen::EngineSettingsScreen(QWidget* parent)
|
||||
: ScreenWidget(parent)
|
||||
{
|
||||
auto* layout = new QVBoxLayout(this);
|
||||
auto* layout = new QVBoxLayout();
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
|
||||
setObjectName("engineSettingsScreen");
|
||||
|
||||
@@ -82,6 +82,8 @@ namespace O3DE::ProjectManager
|
||||
|
||||
m_headerWidget->ReinitForProject();
|
||||
|
||||
connect(m_gemModel, &GemModel::dataChanged, m_filterWidget, &GemFilterWidget::ResetGemStatusFilter);
|
||||
|
||||
// Select the first entry after everything got correctly sized
|
||||
QTimer::singleShot(200, [=]{
|
||||
QModelIndex firstModelIndex = m_gemListView->model()->index(0,0);
|
||||
|
||||
@@ -26,6 +26,7 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton,
|
||||
bool collapsed,
|
||||
int defaultShowCount,
|
||||
QWidget* parent)
|
||||
: QWidget(parent)
|
||||
@@ -40,6 +41,7 @@ namespace O3DE::ProjectManager
|
||||
QHBoxLayout* collapseLayout = new QHBoxLayout();
|
||||
m_collapseButton = new QPushButton();
|
||||
m_collapseButton->setCheckable(true);
|
||||
m_collapseButton->setChecked(collapsed);
|
||||
m_collapseButton->setFlat(true);
|
||||
m_collapseButton->setFocusPolicy(Qt::NoFocus);
|
||||
m_collapseButton->setFixedWidth(s_collapseButtonSize);
|
||||
@@ -178,6 +180,11 @@ namespace O3DE::ProjectManager
|
||||
return m_buttonGroup;
|
||||
}
|
||||
|
||||
bool FilterCategoryWidget::IsCollapsed()
|
||||
{
|
||||
return m_collapseButton->isChecked();
|
||||
}
|
||||
|
||||
GemFilterWidget::GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent)
|
||||
: QScrollArea(parent)
|
||||
, m_filterProxyModel(filterProxyModel)
|
||||
@@ -193,20 +200,106 @@ namespace O3DE::ProjectManager
|
||||
QWidget* mainWidget = new QWidget();
|
||||
setWidget(mainWidget);
|
||||
|
||||
m_mainLayout = new QVBoxLayout();
|
||||
m_mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(m_mainLayout);
|
||||
QVBoxLayout* mainLayout = new QVBoxLayout();
|
||||
mainLayout->setAlignment(Qt::AlignTop);
|
||||
mainWidget->setLayout(mainLayout);
|
||||
|
||||
QLabel* filterByLabel = new QLabel("Filter by");
|
||||
filterByLabel->setStyleSheet("font-size: 16px;");
|
||||
m_mainLayout->addWidget(filterByLabel);
|
||||
mainLayout->addWidget(filterByLabel);
|
||||
|
||||
QWidget* filterSection = new QWidget(this);
|
||||
mainLayout->addWidget(filterSection);
|
||||
|
||||
m_filterLayout = new QVBoxLayout();
|
||||
m_filterLayout->setAlignment(Qt::AlignTop);
|
||||
m_filterLayout->setContentsMargins(0, 0, 0, 0);
|
||||
filterSection->setLayout(m_filterLayout);
|
||||
|
||||
ResetGemStatusFilter();
|
||||
AddGemOriginFilter();
|
||||
AddTypeFilter();
|
||||
AddPlatformFilter();
|
||||
AddFeatureFilter();
|
||||
}
|
||||
|
||||
void GemFilterWidget::ResetGemStatusFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
QVector<int> elementCounts;
|
||||
const int totalGems = m_gemModel->rowCount();
|
||||
const int selectedGemTotal = m_gemModel->TotalAddedGems();
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Unselected));
|
||||
elementCounts.push_back(totalGems - selectedGemTotal);
|
||||
|
||||
elementNames.push_back(GemSortFilterProxyModel::GetGemStatusString(GemSortFilterProxyModel::GemStatus::Selected));
|
||||
elementCounts.push_back(selectedGemTotal);
|
||||
|
||||
bool wasCollapsed = false;
|
||||
if (m_statusFilter)
|
||||
{
|
||||
wasCollapsed = m_statusFilter->IsCollapsed();
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget =
|
||||
new FilterCategoryWidget("Status", elementNames, elementCounts, /*showAllLessButton=*/false, /*collapsed*/wasCollapsed);
|
||||
if (m_statusFilter)
|
||||
{
|
||||
m_filterLayout->replaceWidget(m_statusFilter, filterWidget);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
}
|
||||
|
||||
m_statusFilter->deleteLater();
|
||||
m_statusFilter = filterWidget;
|
||||
|
||||
const GemSortFilterProxyModel::GemStatus currentFilterState = m_filterProxyModel->GetGemStatus();
|
||||
const QList<QAbstractButton*> buttons = m_statusFilter->GetButtonGroup()->buttons();
|
||||
for (int statusFilterIndex = 0; statusFilterIndex < buttons.size(); ++statusFilterIndex)
|
||||
{
|
||||
const GemSortFilterProxyModel::GemStatus gemStatus = static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex);
|
||||
QAbstractButton* button = buttons[statusFilterIndex];
|
||||
|
||||
if (static_cast<GemSortFilterProxyModel::GemStatus>(statusFilterIndex) == currentFilterState)
|
||||
{
|
||||
button->setChecked(true);
|
||||
}
|
||||
|
||||
connect(
|
||||
button, &QAbstractButton::toggled, this,
|
||||
[=](bool checked)
|
||||
{
|
||||
GemSortFilterProxyModel::GemStatus filterStatus = m_filterProxyModel->GetGemStatus();
|
||||
if (checked)
|
||||
{
|
||||
if (filterStatus == GemSortFilterProxyModel::GemStatus::NoFilter)
|
||||
{
|
||||
filterStatus = gemStatus;
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (filterStatus != gemStatus)
|
||||
{
|
||||
filterStatus = static_cast<GemSortFilterProxyModel::GemStatus>(!gemStatus);
|
||||
}
|
||||
else
|
||||
{
|
||||
filterStatus = GemSortFilterProxyModel::GemStatus::NoFilter;
|
||||
}
|
||||
}
|
||||
m_filterProxyModel->SetGemStatus(filterStatus);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
void GemFilterWidget::AddGemOriginFilter()
|
||||
{
|
||||
QVector<QString> elementNames;
|
||||
@@ -233,7 +326,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Provider", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -283,7 +376,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Type", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -333,7 +426,7 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Supported Platforms", elementNames, elementCounts, /*showAllLessButton=*/false);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
@@ -388,8 +481,8 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
|
||||
FilterCategoryWidget* filterWidget = new FilterCategoryWidget("Features", elementNames, elementCounts,
|
||||
/*showAllLessButton=*/true, /*defaultShowCount=*/5);
|
||||
m_mainLayout->addWidget(filterWidget);
|
||||
/*showAllLessButton=*/true, false, /*defaultShowCount=*/5);
|
||||
m_filterLayout->addWidget(filterWidget);
|
||||
|
||||
const QList<QAbstractButton*> buttons = filterWidget->GetButtonGroup()->buttons();
|
||||
for (int i = 0; i < buttons.size(); ++i)
|
||||
|
||||
@@ -37,11 +37,14 @@ namespace O3DE::ProjectManager
|
||||
const QVector<QString>& elementNames,
|
||||
const QVector<int>& elementCounts,
|
||||
bool showAllLessButton = true,
|
||||
bool collapsed = false,
|
||||
int defaultShowCount = 4,
|
||||
QWidget* parent = nullptr);
|
||||
|
||||
QButtonGroup* GetButtonGroup();
|
||||
|
||||
bool IsCollapsed();
|
||||
|
||||
private:
|
||||
void UpdateCollapseState();
|
||||
void UpdateSeeMoreLess();
|
||||
@@ -66,14 +69,18 @@ namespace O3DE::ProjectManager
|
||||
explicit GemFilterWidget(GemSortFilterProxyModel* filterProxyModel, QWidget* parent = nullptr);
|
||||
~GemFilterWidget() = default;
|
||||
|
||||
public slots:
|
||||
void ResetGemStatusFilter();
|
||||
|
||||
private:
|
||||
void AddGemOriginFilter();
|
||||
void AddTypeFilter();
|
||||
void AddPlatformFilter();
|
||||
void AddFeatureFilter();
|
||||
|
||||
QVBoxLayout* m_mainLayout = nullptr;
|
||||
QVBoxLayout* m_filterLayout = nullptr;
|
||||
GemModel* m_gemModel = nullptr;
|
||||
GemSortFilterProxyModel* m_filterProxyModel = nullptr;
|
||||
FilterCategoryWidget* m_statusFilter = nullptr;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -204,7 +204,6 @@ namespace O3DE::ProjectManager
|
||||
painter->save();
|
||||
const QRect buttonRect = CalcButtonRect(contentRect);
|
||||
QPoint circleCenter;
|
||||
QString buttonText;
|
||||
|
||||
const bool isAdded = GemModel::IsAdded(modelIndex);
|
||||
if (isAdded)
|
||||
@@ -213,34 +212,15 @@ namespace O3DE::ProjectManager
|
||||
painter->setPen(m_buttonEnabledColor);
|
||||
|
||||
circleCenter = buttonRect.center() + QPoint(buttonRect.width() / 2 - s_buttonBorderRadius + 1, 1);
|
||||
buttonText = "Added";
|
||||
}
|
||||
else
|
||||
{
|
||||
circleCenter = buttonRect.center() + QPoint(-buttonRect.width() / 2 + s_buttonBorderRadius, 1);
|
||||
buttonText = "Get";
|
||||
}
|
||||
|
||||
// Rounded rect
|
||||
painter->drawRoundedRect(buttonRect, s_buttonBorderRadius, s_buttonBorderRadius);
|
||||
|
||||
// Text
|
||||
QFont font;
|
||||
QRect textRect = GetTextRect(font, buttonText, s_buttonFontSize);
|
||||
if (isAdded)
|
||||
{
|
||||
textRect = QRect(buttonRect.left(), buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
|
||||
}
|
||||
else
|
||||
{
|
||||
textRect = QRect(buttonRect.left() + s_buttonCircleRadius * 2.0, buttonRect.top(), buttonRect.width() - s_buttonCircleRadius * 2.0, buttonRect.height());
|
||||
}
|
||||
|
||||
font.setPixelSize(s_buttonFontSize);
|
||||
painter->setFont(font);
|
||||
painter->setPen(m_textColor);
|
||||
painter->drawText(textRect, Qt::AlignCenter, buttonText);
|
||||
|
||||
// Circle
|
||||
painter->setBrush(m_textColor);
|
||||
painter->drawEllipse(circleCenter, s_buttonCircleRadius, s_buttonCircleRadius);
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
#include <QStandardItemModel>
|
||||
#include <QLabel>
|
||||
#include <QVBoxLayout>
|
||||
#include <QSpacerItem>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
@@ -74,6 +75,15 @@ namespace O3DE::ProjectManager
|
||||
gemSummaryLabel->setStyleSheet("font-size: 12px;");
|
||||
columnHeaderLayout->addWidget(gemSummaryLabel);
|
||||
|
||||
QSpacerItem* horizontalSpacer = new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Minimum);
|
||||
columnHeaderLayout->addSpacerItem(horizontalSpacer);
|
||||
|
||||
QLabel* gemSelectedLabel = new QLabel(tr("Selected"));
|
||||
gemSelectedLabel->setStyleSheet("font-size: 12px;");
|
||||
columnHeaderLayout->addWidget(gemSelectedLabel);
|
||||
|
||||
columnHeaderLayout->addSpacing(60);
|
||||
|
||||
vLayout->addLayout(columnHeaderLayout);
|
||||
}
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -235,4 +235,19 @@ namespace O3DE::ProjectManager
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
int GemModel::TotalAddedGems() const
|
||||
{
|
||||
int result = 0;
|
||||
for (int row = 0; row < rowCount(); ++row)
|
||||
{
|
||||
const QModelIndex modelIndex = index(row, 0);
|
||||
if (IsAdded(modelIndex))
|
||||
{
|
||||
++result;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -63,6 +63,8 @@ namespace O3DE::ProjectManager
|
||||
QVector<QModelIndex> GatherGemsToBeAdded() const;
|
||||
QVector<QModelIndex> GatherGemsToBeRemoved() const;
|
||||
|
||||
int TotalAddedGems() const;
|
||||
|
||||
private:
|
||||
enum UserRole
|
||||
{
|
||||
|
||||
@@ -37,6 +37,16 @@ namespace O3DE::ProjectManager
|
||||
return false;
|
||||
}
|
||||
|
||||
// Gem status
|
||||
if (m_gemStatusFilter != GemStatus::NoFilter)
|
||||
{
|
||||
const GemStatus sourceGemStatus = static_cast<GemStatus>(GemModel::IsAdded(sourceIndex));
|
||||
if (m_gemStatusFilter != sourceGemStatus)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Gem origins
|
||||
if (m_gemOriginFilter)
|
||||
{
|
||||
@@ -125,6 +135,19 @@ namespace O3DE::ProjectManager
|
||||
return true;
|
||||
}
|
||||
|
||||
QString GemSortFilterProxyModel::GetGemStatusString(GemStatus status)
|
||||
{
|
||||
switch (status)
|
||||
{
|
||||
case Unselected:
|
||||
return "Unselected";
|
||||
case Selected:
|
||||
return "Selected";
|
||||
default:
|
||||
return "<Unknown Gem Status>";
|
||||
}
|
||||
}
|
||||
|
||||
void GemSortFilterProxyModel::InvalidateFilter()
|
||||
{
|
||||
invalidate();
|
||||
|
||||
@@ -29,8 +29,17 @@ namespace O3DE::ProjectManager
|
||||
Q_OBJECT // AUTOMOC
|
||||
|
||||
public:
|
||||
enum GemStatus
|
||||
{
|
||||
NoFilter = -1,
|
||||
Unselected,
|
||||
Selected
|
||||
};
|
||||
|
||||
GemSortFilterProxyModel(GemModel* sourceModel, QObject* parent = nullptr);
|
||||
|
||||
static QString GetGemStatusString(GemStatus status);
|
||||
|
||||
bool filterAcceptsRow(int sourceRow, const QModelIndex& sourceParent) const override;
|
||||
|
||||
GemModel* GetSourceModel() const { return m_sourceModel; }
|
||||
@@ -38,6 +47,9 @@ namespace O3DE::ProjectManager
|
||||
|
||||
void SetSearchString(const QString& searchString) { m_searchString = searchString; InvalidateFilter(); }
|
||||
|
||||
GemStatus GetGemStatus() const { return m_gemStatusFilter; }
|
||||
void SetGemStatus(GemStatus gemStatus) { m_gemStatusFilter = gemStatus; InvalidateFilter(); }
|
||||
|
||||
GemInfo::GemOrigins GetGemOrigins() const { return m_gemOriginFilter; }
|
||||
void SetGemOrigins(const GemInfo::GemOrigins& gemOrigins) { m_gemOriginFilter = gemOrigins; InvalidateFilter(); }
|
||||
|
||||
@@ -61,6 +73,7 @@ namespace O3DE::ProjectManager
|
||||
AzQtComponents::SelectionProxyModel* m_selectionProxyModel = nullptr;
|
||||
|
||||
QString m_searchString;
|
||||
GemStatus m_gemStatusFilter = GemStatus::NoFilter;
|
||||
GemInfo::GemOrigins m_gemOriginFilter = {};
|
||||
GemInfo::Platforms m_platformFilter = {};
|
||||
GemInfo::Types m_typeFilter = {};
|
||||
|
||||
@@ -33,7 +33,7 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
setObjectName("labelButton");
|
||||
|
||||
QVBoxLayout* vLayout = new QVBoxLayout(this);
|
||||
QVBoxLayout* vLayout = new QVBoxLayout();
|
||||
vLayout->setContentsMargins(0, 0, 0, 0);
|
||||
vLayout->setSpacing(5);
|
||||
|
||||
|
||||
@@ -13,21 +13,11 @@
|
||||
#include <ProjectManagerWindow.h>
|
||||
#include <ScreensCtrl.h>
|
||||
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
#include <AzFramework/Application/Application.h>
|
||||
|
||||
#include <QDir>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen)
|
||||
ProjectManagerWindow::ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath, ProjectManagerScreen startScreen)
|
||||
: QMainWindow(parent)
|
||||
{
|
||||
m_pythonBindings = AZStd::make_unique<PythonBindings>(engineRootPath);
|
||||
|
||||
setWindowTitle(tr("O3DE Project Manager"));
|
||||
|
||||
ScreensCtrl* screensCtrl = new ScreensCtrl();
|
||||
@@ -44,15 +34,6 @@ namespace O3DE::ProjectManager
|
||||
|
||||
setCentralWidget(screensCtrl);
|
||||
|
||||
// setup stylesheets and hot reloading
|
||||
QDir rootDir = QString::fromUtf8(engineRootPath.Native().data(), aznumeric_cast<int>(engineRootPath.Native().size()));
|
||||
const auto pathOnDisk = rootDir.absoluteFilePath("Code/Tools/ProjectManager/Resources");
|
||||
const auto qrcPath = QStringLiteral(":/ProjectManager/style");
|
||||
AzQtComponents::StyleManager::addSearchPaths("style", pathOnDisk, qrcPath, engineRootPath);
|
||||
|
||||
// set stylesheet after creating the screens or their styles won't get updated
|
||||
AzQtComponents::StyleManager::setStyleSheet(this, QStringLiteral("style:ProjectManager.qss"));
|
||||
|
||||
// always push the projects screen first so we have something to come back to
|
||||
if (startScreen != ProjectManagerScreen::Projects)
|
||||
{
|
||||
@@ -66,10 +47,4 @@ namespace O3DE::ProjectManager
|
||||
emit screensCtrl->NotifyCurrentProject(path);
|
||||
}
|
||||
}
|
||||
|
||||
ProjectManagerWindow::~ProjectManagerWindow()
|
||||
{
|
||||
m_pythonBindings.reset();
|
||||
}
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
|
||||
#if !defined(Q_MOC_RUN)
|
||||
#include <QMainWindow>
|
||||
#include <PythonBindings.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <ScreenDefs.h>
|
||||
#endif
|
||||
|
||||
@@ -25,12 +25,8 @@ namespace O3DE::ProjectManager
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& engineRootPath, const AZ::IO::PathView& projectPath,
|
||||
explicit ProjectManagerWindow(QWidget* parent, const AZ::IO::PathView& projectPath,
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects);
|
||||
~ProjectManagerWindow();
|
||||
|
||||
private:
|
||||
AZStd::unique_ptr<PythonBindings> m_pythonBindings;
|
||||
};
|
||||
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -37,7 +37,7 @@ namespace O3DE::ProjectManager
|
||||
// if we don't set this in a frame (just use a sub-layout) all the content will align incorrectly horizontally
|
||||
QFrame* projectSettingsFrame = new QFrame(this);
|
||||
projectSettingsFrame->setObjectName("projectSettings");
|
||||
m_verticalLayout = new QVBoxLayout(this);
|
||||
m_verticalLayout = new QVBoxLayout();
|
||||
|
||||
// you cannot remove content margins in qss
|
||||
m_verticalLayout->setContentsMargins(0, 0, 0, 0);
|
||||
|
||||
@@ -85,7 +85,7 @@ namespace O3DE::ProjectManager
|
||||
QFrame* frame = new QFrame(this);
|
||||
frame->setObjectName("firstTimeContent");
|
||||
{
|
||||
QVBoxLayout* layout = new QVBoxLayout(this);
|
||||
QVBoxLayout* layout = new QVBoxLayout();
|
||||
layout->setContentsMargins(0, 0, 0, 0);
|
||||
layout->setAlignment(Qt::AlignTop);
|
||||
frame->setLayout(layout);
|
||||
@@ -100,7 +100,7 @@ namespace O3DE::ProjectManager
|
||||
"available by downloading our sample project."));
|
||||
layout->addWidget(introLabel);
|
||||
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout(this);
|
||||
QHBoxLayout* buttonLayout = new QHBoxLayout();
|
||||
buttonLayout->setAlignment(Qt::AlignLeft);
|
||||
buttonLayout->setSpacing(s_spacerSize);
|
||||
|
||||
|
||||
@@ -226,7 +226,7 @@ namespace O3DE::ProjectManager
|
||||
PythonBindings::PythonBindings(const AZ::IO::PathView& enginePath)
|
||||
: m_enginePath(enginePath)
|
||||
{
|
||||
StartPython();
|
||||
m_pythonStarted = StartPython();
|
||||
}
|
||||
|
||||
PythonBindings::~PythonBindings()
|
||||
@@ -234,6 +234,11 @@ namespace O3DE::ProjectManager
|
||||
StopPython();
|
||||
}
|
||||
|
||||
bool PythonBindings::PythonStarted()
|
||||
{
|
||||
return m_pythonStarted && Py_IsInitialized();
|
||||
}
|
||||
|
||||
bool PythonBindings::StartPython()
|
||||
{
|
||||
if (Py_IsInitialized())
|
||||
@@ -246,7 +251,7 @@ namespace O3DE::ProjectManager
|
||||
AZStd::string pyBasePath = Platform::GetPythonHomePath(PY_PACKAGE, m_enginePath.c_str());
|
||||
if (!AZ::IO::SystemFile::Exists(pyBasePath.c_str()))
|
||||
{
|
||||
AZ_Assert(false, "Python home path must exist. path:%s", pyBasePath.c_str());
|
||||
AZ_Error("python", false, "Python home path does not exist: %s", pyBasePath.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -351,6 +356,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::ExecuteWithLockErrorHandling(AZStd::function<void()> executionCallback)
|
||||
{
|
||||
if (!Py_IsInitialized())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>("Python is not initialized");
|
||||
}
|
||||
|
||||
AZStd::lock_guard<decltype(m_lock)> lock(m_lock);
|
||||
pybind11::gil_scoped_release release;
|
||||
pybind11::gil_scoped_acquire acquire;
|
||||
|
||||
@@ -34,6 +34,8 @@ namespace O3DE::ProjectManager
|
||||
~PythonBindings() override;
|
||||
|
||||
// PythonBindings overrides
|
||||
bool PythonStarted() override;
|
||||
|
||||
// Engine
|
||||
AZ::Outcome<EngineInfo> GetEngineInfo() override;
|
||||
bool SetEngineInfo(const EngineInfo& engineInfo) override;
|
||||
@@ -70,6 +72,8 @@ namespace O3DE::ProjectManager
|
||||
bool StopPython();
|
||||
|
||||
|
||||
bool m_pythonStarted = false;
|
||||
|
||||
AZ::IO::FixedMaxPath m_enginePath;
|
||||
pybind11::handle m_engineTemplate;
|
||||
AZStd::recursive_mutex m_lock;
|
||||
|
||||
@@ -34,6 +34,12 @@ namespace O3DE::ProjectManager
|
||||
IPythonBindings() = default;
|
||||
virtual ~IPythonBindings() = default;
|
||||
|
||||
/**
|
||||
* Get whether Python was started or not. All Python functionality will fail if Python
|
||||
* failed to start.
|
||||
* @return true if Python was started successfully, false on failure
|
||||
*/
|
||||
virtual bool PythonStarted() = 0;
|
||||
|
||||
// Engine
|
||||
|
||||
|
||||
@@ -189,11 +189,13 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
if (m_stack->currentIndex() == ScreenOrder::Gems)
|
||||
{
|
||||
m_header->setSubTitle(QString(tr("Configure Gems for \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_nextButton->setText(tr("Confirm"));
|
||||
m_header->setTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_header->setSubTitle(QString(tr("Configure Gems")));
|
||||
m_nextButton->setText(tr("Finalize"));
|
||||
}
|
||||
else
|
||||
{
|
||||
m_header->setTitle("");
|
||||
m_header->setSubTitle(QString(tr("Edit Project Settings: \"%1\"")).arg(m_projectInfo.m_projectName));
|
||||
m_nextButton->setText(tr("Save"));
|
||||
}
|
||||
|
||||
@@ -10,85 +10,26 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include <AzQtComponents/Utilities/HandleDpiAwareness.h>
|
||||
#include <AzQtComponents/Components/StyleManager.h>
|
||||
#include <AzCore/Component/ComponentApplication.h>
|
||||
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
#include <AzFramework/CommandLine/CommandLine.h>
|
||||
|
||||
#include <ProjectManagerWindow.h>
|
||||
#include <ProjectUtils.h>
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCoreApplication>
|
||||
#include <QGuiApplication>
|
||||
|
||||
using namespace O3DE::ProjectManager;
|
||||
#include <AzQtComponents/Utilities/QtPluginPaths.h>
|
||||
#include <Application.h>
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
QApplication::setOrganizationName("O3DE");
|
||||
QApplication::setOrganizationDomain("o3de.org");
|
||||
QCoreApplication::setApplicationName("ProjectManager");
|
||||
QCoreApplication::setApplicationVersion("1.0");
|
||||
|
||||
QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
|
||||
QCoreApplication::setAttribute(Qt::AA_UseHighDpiPixmaps);
|
||||
QCoreApplication::setAttribute(Qt::AA_DontCreateNativeWidgetSiblings);
|
||||
QGuiApplication::setHighDpiScaleFactorRoundingPolicy(Qt::HighDpiScaleFactorRoundingPolicy::PassThrough);
|
||||
AzQtComponents::Utilities::HandleDpiAwareness(AzQtComponents::Utilities::SystemDpiAware);
|
||||
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Create();
|
||||
int runSuccess = 0;
|
||||
|
||||
// Call before using any Qt, or the app may not be able to locate Qt libs
|
||||
AzQtComponents::PrepareQtPaths();
|
||||
|
||||
O3DE::ProjectManager::Application application(&argc, &argv);
|
||||
if (!application.Init())
|
||||
{
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// Need to use settings registry to get EngineRootFolder
|
||||
AZ::IO::FixedMaxPath engineRootPath;
|
||||
{
|
||||
AZ::ComponentApplication componentApplication;
|
||||
auto settingsRegistry = AZ::SettingsRegistry::Get();
|
||||
settingsRegistry->Get(engineRootPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_EngineRootFolder);
|
||||
}
|
||||
|
||||
AzQtComponents::StyleManager styleManager(&app);
|
||||
styleManager.initialize(&app, engineRootPath);
|
||||
|
||||
// Get the initial start screen if one is provided via command line
|
||||
constexpr char optionPrefix[] = "--";
|
||||
AZ::CommandLine commandLine(optionPrefix);
|
||||
commandLine.Parse(argc, argv);
|
||||
|
||||
ProjectManagerScreen startScreen = ProjectManagerScreen::Projects;
|
||||
if(commandLine.HasSwitch("screen"))
|
||||
{
|
||||
QString screenOption = commandLine.GetSwitchValue("screen", 0).c_str();
|
||||
ProjectManagerScreen screen = ProjectUtils::GetProjectManagerScreen(screenOption);
|
||||
if (screen != ProjectManagerScreen::Invalid)
|
||||
{
|
||||
startScreen = screen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectPath;
|
||||
if (commandLine.HasSwitch("project-path"))
|
||||
{
|
||||
projectPath = commandLine.GetSwitchValue("project-path", 0).c_str();
|
||||
}
|
||||
|
||||
ProjectManagerWindow window(nullptr, engineRootPath, projectPath, startScreen);
|
||||
window.show();
|
||||
|
||||
// somethings is preventing us from moving the window to the center of the
|
||||
// primary screen - likely an Az style or component helper
|
||||
constexpr int width = 1200;
|
||||
constexpr int height = 800;
|
||||
window.resize(width, height);
|
||||
|
||||
runSuccess = app.exec();
|
||||
AZ_Error("ProjectManager", false, "Failed to initialize");
|
||||
runSuccess = 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
runSuccess = application.Run() ? 0 : 1;
|
||||
}
|
||||
AZ::AllocatorInstance<AZ::SystemAllocator>::Destroy();
|
||||
|
||||
return runSuccess;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Resources/ProjectManager.rc
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
Source/main.cpp
|
||||
)
|
||||
@@ -1,4 +1,5 @@
|
||||
#
|
||||
#
|
||||
# All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
# its licensors.
|
||||
#
|
||||
@@ -10,10 +11,8 @@
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Resources/ProjectManager.rc
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
Source/main.cpp
|
||||
Source/Application.h
|
||||
Source/Application.cpp
|
||||
Source/ScreenDefs.h
|
||||
Source/ScreenFactory.h
|
||||
Source/ScreenFactory.cpp
|
||||
|
||||
@@ -0,0 +1,17 @@
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
set(FILES
|
||||
Resources/ProjectManager.qrc
|
||||
Resources/ProjectManager.qss
|
||||
tests/ApplicationTests.cpp
|
||||
tests/main.cpp
|
||||
)
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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 <AzCore/UnitTest/TestTypes.h>
|
||||
#include <AzCore/std/smart_ptr/make_shared.h>
|
||||
#include <Application.h>
|
||||
#include <ProjectManager_Test_Traits_Platform.h>
|
||||
|
||||
namespace O3DE::ProjectManager
|
||||
{
|
||||
class ProjectManagerApplicationTests
|
||||
: public ::UnitTest::ScopedAllocatorSetupFixture
|
||||
{
|
||||
public:
|
||||
|
||||
ProjectManagerApplicationTests()
|
||||
{
|
||||
m_application = AZStd::make_unique<ProjectManager::Application>();
|
||||
}
|
||||
|
||||
~ProjectManagerApplicationTests()
|
||||
{
|
||||
m_application.reset();
|
||||
}
|
||||
|
||||
AZStd::unique_ptr<ProjectManager::Application> m_application;
|
||||
};
|
||||
|
||||
#if AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS
|
||||
TEST_F(ProjectManagerApplicationTests, DISABLED_Application_Init_Succeeds)
|
||||
#else
|
||||
TEST_F(ProjectManagerApplicationTests, Application_Init_Succeeds)
|
||||
#endif // !AZ_TRAIT_DISABLE_FAILED_PROJECT_MANAGER_TESTS
|
||||
{
|
||||
// we don't want to interact with actual GUI or display it
|
||||
EXPECT_TRUE(m_application->Init(/*interactive=*/false));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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 <AzTest/AzTest.h>
|
||||
|
||||
DECLARE_AZ_UNIT_TEST_MAIN();
|
||||
|
||||
int runDefaultRunner(int argc, char* argv[])
|
||||
{
|
||||
INVOKE_AZ_UNIT_TEST_MAIN(nullptr)
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (argc == 1)
|
||||
{
|
||||
// if no parameters are provided, add the --unittests parameter
|
||||
constexpr int defaultArgc = 2;
|
||||
char unittest_arg[] = "--unittests"; // Conversion from string literal to char* is not allowed per ISO C++11
|
||||
char* defaultArgv[defaultArgc] = { argv[0], unittest_arg };
|
||||
return runDefaultRunner(defaultArgc, defaultArgv);
|
||||
}
|
||||
INVOKE_AZ_UNIT_TEST_MAIN(nullptr);
|
||||
return 0;
|
||||
}
|
||||
@@ -46,22 +46,69 @@ namespace AZ
|
||||
serializeContext->Class<AssImpTransformImporter, SceneCore::LoadingComponent>()->Version(1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void GetAllBones(const aiScene* scene, AZStd::unordered_map<AZStd::string, const aiBone*>& boneLookup)
|
||||
{
|
||||
for (unsigned meshIndex = 0; meshIndex < scene->mNumMeshes; ++meshIndex)
|
||||
{
|
||||
const aiMesh* mesh = scene->mMeshes[meshIndex];
|
||||
|
||||
for (unsigned boneIndex = 0; boneIndex < mesh->mNumBones; ++boneIndex)
|
||||
{
|
||||
const aiBone* bone = mesh->mBones[boneIndex];
|
||||
|
||||
boneLookup[bone->mName.C_Str()] = bone;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Events::ProcessingResult AssImpTransformImporter::ImportTransform(AssImpSceneNodeAppendedContext& context)
|
||||
{
|
||||
AZ_TraceContext("Importer", "transform");
|
||||
const aiNode* currentNode = context.m_sourceNode.GetAssImpNode();
|
||||
const aiScene* scene = context.m_sourceScene.GetAssImpScene();
|
||||
|
||||
|
||||
if (currentNode == scene->mRootNode || IsPivotNode(currentNode->mName))
|
||||
{
|
||||
return Events::ProcessingResult::Ignored;
|
||||
}
|
||||
|
||||
aiMatrix4x4 combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
AZStd::unordered_map<AZStd::string, const aiBone*> boneLookup;
|
||||
GetAllBones(scene, boneLookup);
|
||||
|
||||
auto boneIterator = boneLookup.find(currentNode->mName.C_Str());
|
||||
const bool isBone = boneIterator != boneLookup.end();
|
||||
|
||||
aiMatrix4x4 combinedTransform;
|
||||
|
||||
if (isBone)
|
||||
{
|
||||
auto parentNode = currentNode->mParent;
|
||||
|
||||
aiMatrix4x4 offsetMatrix = boneIterator->second->mOffsetMatrix;
|
||||
aiMatrix4x4 parentOffset {};
|
||||
|
||||
auto parentBoneIterator = boneLookup.find(parentNode->mName.C_Str());
|
||||
|
||||
if (parentNode && parentBoneIterator != boneLookup.end())
|
||||
{
|
||||
const auto& parentBone = parentBoneIterator->second;
|
||||
|
||||
parentOffset = parentBone->mOffsetMatrix;
|
||||
}
|
||||
|
||||
auto inverseOffset = offsetMatrix;
|
||||
inverseOffset.Inverse();
|
||||
|
||||
combinedTransform = parentOffset * inverseOffset;
|
||||
}
|
||||
else
|
||||
{
|
||||
combinedTransform = GetConcatenatedLocalTransform(currentNode);
|
||||
}
|
||||
|
||||
DataTypes::MatrixType localTransform = AssImpSDKWrapper::AssImpTypeConverter::ToTransform(combinedTransform);
|
||||
|
||||
|
||||
context.m_sourceSceneSystem.SwapTransformForUpAxis(localTransform);
|
||||
context.m_sourceSceneSystem.ConvertUnit(localTransform);
|
||||
|
||||
@@ -105,9 +152,7 @@ namespace AZ
|
||||
}
|
||||
else
|
||||
{
|
||||
bool addedData = context.m_scene.GetGraph().SetContent(
|
||||
context.m_currentGraphPosition,
|
||||
transformData);
|
||||
bool addedData = context.m_scene.GetGraph().SetContent(context.m_currentGraphPosition, transformData);
|
||||
|
||||
AZ_Error(SceneAPI::Utilities::ErrorWindow, addedData, "Failed to add node data");
|
||||
return addedData ? Events::ProcessingResult::Success : Events::ProcessingResult::Failure;
|
||||
|
||||
@@ -69,13 +69,14 @@ namespace AZ
|
||||
// aiProcess_JoinIdenticalVertices is not enabled because O3DE has a mesh optimizer that also does this,
|
||||
// this flag is disabled to keep AssImp output similar to FBX SDK to reduce downstream bugs for the initial AssImp release.
|
||||
// There's currently a minimum of properties and flags set to maximize compatibility with the existing node graph.
|
||||
|
||||
// aiProcess_LimitBoneWeights is not enabled because it will remove bones which are not associated with a mesh.
|
||||
// This results in the loss of the offset matrix data for nodes without a mesh which is required for the Transform Importer.
|
||||
m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_PRESERVE_PIVOTS, false);
|
||||
m_importer.SetPropertyBool(AI_CONFIG_IMPORT_FBX_OPTIMIZE_EMPTY_ANIMATION_CURVES, false);
|
||||
m_sceneFileName = fileName;
|
||||
m_assImpScene = m_importer.ReadFile(fileName,
|
||||
aiProcess_Triangulate //Triangulates all faces of all meshes
|
||||
| aiProcess_LimitBoneWeights //Limits the number of bones that can affect a vertex to a maximum value
|
||||
//dropping the least important and re-normalizing
|
||||
| aiProcess_GenNormals); //Generate normals for meshes
|
||||
|
||||
#if AZ_TRAIT_COMPILER_SUPPORT_CSIGNAL
|
||||
|
||||
@@ -24,9 +24,9 @@
|
||||
},
|
||||
"ImageDescriptor": {
|
||||
"Format": "R16G16B16A16_FLOAT",
|
||||
"MipLevels": "8",
|
||||
"SharedQueueMask": "Graphics"
|
||||
}
|
||||
},
|
||||
"GenerateFullMipChain": true
|
||||
}
|
||||
],
|
||||
"Connections": [
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"ClassData": {
|
||||
"PassTemplate": {
|
||||
"Name": "ReflectionScreenSpaceCompositePassTemplate",
|
||||
"PassClass": "FullScreenTriangle",
|
||||
"PassClass": "ReflectionScreenSpaceCompositePass",
|
||||
"Slots": [
|
||||
{
|
||||
"Name": "TraceInput",
|
||||
|
||||
+4
-6
@@ -37,6 +37,9 @@ ShaderResourceGroup PassSrg : SRG_PerPass
|
||||
AddressV = Clamp;
|
||||
AddressW = Clamp;
|
||||
};
|
||||
|
||||
// the max roughness mip level for sampling the previous frame image
|
||||
uint m_maxMipLevel;
|
||||
}
|
||||
|
||||
#include <Atom/RPI/ShaderResourceGroups/DefaultDrawSrg.azsli>
|
||||
@@ -69,10 +72,6 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
float4 positionWS = mul(ViewSrg::m_viewProjectionInverseMatrix, projectedPos);
|
||||
positionWS /= positionWS.w;
|
||||
|
||||
//float4 positionVS = mul(ViewSrg::m_projectionMatrixInverse, projectedPos);
|
||||
//positionVS /= positionVS.w;
|
||||
//float4 positionWS = mul(ViewSrg::m_viewMatrixInverse, positionVS);
|
||||
|
||||
// compute ray from camera to surface position
|
||||
float3 cameraToPositionWS = normalize(positionWS.xyz - ViewSrg::m_worldPosition);
|
||||
|
||||
@@ -103,8 +102,7 @@ PSOutput MainPS(VSOutput IN, in uint sampleIndex : SV_SampleIndex)
|
||||
// compute the roughness mip to use in the previous frame image
|
||||
// remap the roughness mip into a lower range to more closely match the material roughness values
|
||||
const float MaxRoughness = 0.5f;
|
||||
const float MaxRoughnessMip = 7;
|
||||
float mip = saturate(roughness / MaxRoughness) * MaxRoughnessMip;
|
||||
float mip = saturate(roughness / MaxRoughness) * PassSrg::m_maxMipLevel;
|
||||
|
||||
// sample reflection value from the roughness mip
|
||||
float4 reflectionColor = float4(PassSrg::m_previousFrame.SampleLevel(PassSrg::LinearSampler, tracePrevUV, mip).rgb, 1.0f);
|
||||
|
||||
@@ -103,6 +103,7 @@
|
||||
#include <DiffuseGlobalIllumination/DiffuseGlobalIlluminationFeatureProcessor.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h>
|
||||
#include <ReflectionScreenSpace/ReflectionCopyFrameBufferPass.h>
|
||||
#include <OcclusionCullingPlane/OcclusionCullingPlaneFeatureProcessor.h>
|
||||
|
||||
@@ -283,6 +284,7 @@ namespace AZ
|
||||
// Add Reflection passes
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurPass"), &Render::ReflectionScreenSpaceBlurPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceBlurChildPass"), &Render::ReflectionScreenSpaceBlurChildPass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionScreenSpaceCompositePass"), &Render::ReflectionScreenSpaceCompositePass::Create);
|
||||
passSystem->AddPassCreator(Name("ReflectionCopyFrameBufferPass"), &Render::ReflectionCopyFrameBufferPass::Create);
|
||||
|
||||
// Add RayTracing pas
|
||||
|
||||
+3
@@ -37,6 +37,9 @@ namespace AZ
|
||||
//! to store the previous frame image
|
||||
Data::Instance<RPI::AttachmentImage>& GetFrameBufferImageAttachment() { return m_frameBufferImageAttachment; }
|
||||
|
||||
//! Returns the number of mip levels in the blur
|
||||
uint32_t GetNumBlurMips() const { return m_numBlurMips; }
|
||||
|
||||
private:
|
||||
explicit ReflectionScreenSpaceBlurPass(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
|
||||
+58
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* 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 "ReflectionScreenSpaceCompositePass.h"
|
||||
#include "ReflectionScreenSpaceBlurPass.h"
|
||||
#include <Atom/RPI.Public/Pass/PassSystemInterface.h>
|
||||
#include <Atom/RPI.Public/Pass/PassFilter.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
RPI::Ptr<ReflectionScreenSpaceCompositePass> ReflectionScreenSpaceCompositePass::Create(const RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
RPI::Ptr<ReflectionScreenSpaceCompositePass> pass = aznew ReflectionScreenSpaceCompositePass(descriptor);
|
||||
return AZStd::move(pass);
|
||||
}
|
||||
|
||||
ReflectionScreenSpaceCompositePass::ReflectionScreenSpaceCompositePass(const RPI::PassDescriptor& descriptor)
|
||||
: RPI::FullscreenTrianglePass(descriptor)
|
||||
{
|
||||
}
|
||||
|
||||
void ReflectionScreenSpaceCompositePass::CompileResources([[maybe_unused]] const RHI::FrameGraphCompileContext& context)
|
||||
{
|
||||
if (!m_shaderResourceGroup)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
RPI::PassHierarchyFilter passFilter(AZ::Name("ReflectionScreenSpaceBlurPass"));
|
||||
const AZStd::vector<RPI::Pass*>& passes = RPI::PassSystemInterface::Get()->FindPasses(passFilter);
|
||||
if (!passes.empty())
|
||||
{
|
||||
Render::ReflectionScreenSpaceBlurPass* blurPass = azrtti_cast<ReflectionScreenSpaceBlurPass*>(passes.front());
|
||||
|
||||
// compute the max mip level based on the available mips in the previous frame image, and capping it
|
||||
// to stay within a range that has reasonable data
|
||||
const uint32_t MaxNumRoughnessMips = 8;
|
||||
uint32_t maxMipLevel = AZStd::min(MaxNumRoughnessMips, blurPass->GetNumBlurMips()) - 1;
|
||||
|
||||
auto constantIndex = m_shaderResourceGroup->FindShaderInputConstantIndex(Name("m_maxMipLevel"));
|
||||
m_shaderResourceGroup->SetConstant(constantIndex, maxMipLevel);
|
||||
}
|
||||
|
||||
FullscreenTrianglePass::CompileResources(context);
|
||||
}
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
+43
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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
|
||||
|
||||
#include <Atom/RPI.Public/Pass/Pass.h>
|
||||
#include <Atom/RPI.Public/Pass/FullscreenTrianglePass.h>
|
||||
#include <Atom/RPI.Public/Shader/ShaderResourceGroup.h>
|
||||
#include <Atom/RPI.Public/Shader/Shader.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
//! This pass composites the screenspace reflection trace onto the reflection buffer.
|
||||
class ReflectionScreenSpaceCompositePass
|
||||
: public RPI::FullscreenTrianglePass
|
||||
{
|
||||
AZ_RPI_PASS(ReflectionScreenSpaceCompositePass);
|
||||
|
||||
public:
|
||||
AZ_RTTI(Render::ReflectionScreenSpaceCompositePass, "{88739CC9-C3F1-413A-A527-9916C697D93A}", FullscreenTrianglePass);
|
||||
AZ_CLASS_ALLOCATOR(Render::ReflectionScreenSpaceCompositePass, SystemAllocator, 0);
|
||||
|
||||
//! Creates a new pass without a PassTemplate
|
||||
static RPI::Ptr<ReflectionScreenSpaceCompositePass> Create(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
private:
|
||||
explicit ReflectionScreenSpaceCompositePass(const RPI::PassDescriptor& descriptor);
|
||||
|
||||
// Pass Overrides...
|
||||
void CompileResources(const RHI::FrameGraphCompileContext& context) override;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
@@ -629,6 +629,11 @@ namespace AZ
|
||||
|
||||
Data::Asset<RPI::ModelLodAsset> lodAsset;
|
||||
modelLodCreator.End(lodAsset);
|
||||
if (!lodAsset.IsReady())
|
||||
{
|
||||
// [GFX TODO] During mesh reload the modelLodCreator could report errors and result in the lodAsset not ready.
|
||||
return nullptr;
|
||||
}
|
||||
modelCreator.AddLodAsset(AZStd::move(lodAsset));
|
||||
|
||||
lodIndex++;
|
||||
|
||||
@@ -267,6 +267,8 @@ set(FILES
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurPass.h
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceBlurChildPass.h
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionScreenSpaceCompositePass.h
|
||||
Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.cpp
|
||||
Source/ReflectionScreenSpace/ReflectionCopyFrameBufferPass.h
|
||||
Source/ScreenSpace/DeferredFogSettings.cpp
|
||||
|
||||
@@ -57,6 +57,20 @@ namespace AZ
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Prints a generic message at the appropriate indent level.
|
||||
template<typename ... Args>
|
||||
static void Printf([[maybe_unused]] const char* format, [[maybe_unused]] Args... args)
|
||||
{
|
||||
#ifdef AZ_ENABLE_SHADER_RELOAD_DEBUG_TRACKER
|
||||
if (IsEnabled())
|
||||
{
|
||||
const AZStd::string message = AZStd::string::format(format, args...);
|
||||
|
||||
AZ_TracePrintf("ShaderReloadDebug", "%*s %s \n", s_indent, "", message.c_str());
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
//! Use this utility to call BeginSection(), and automatically call EndSection() when the object goes out of scope.
|
||||
class ScopedSection final
|
||||
|
||||
@@ -97,6 +97,7 @@ namespace AZ
|
||||
ShaderReloadNotificationBus::MultiHandler::BusDisconnect();
|
||||
for (auto& shaderItem : m_shaderCollection)
|
||||
{
|
||||
ShaderReloadDebugTracker::Printf("(Material has ShaderAsset %p)", shaderItem.GetShaderAsset().Get());
|
||||
ShaderReloadNotificationBus::MultiHandler::BusConnect(shaderItem.GetShaderAsset().GetId());
|
||||
}
|
||||
|
||||
@@ -226,7 +227,7 @@ namespace AZ
|
||||
// AssetBus overrides...
|
||||
void Material::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnAssetReloaded %s", asset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
Data::Asset<MaterialAsset> newMaterialAsset = { asset.GetAs<MaterialAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
|
||||
@@ -241,7 +242,7 @@ namespace AZ
|
||||
// MaterialReloadNotificationBus overrides...
|
||||
void Material::OnMaterialAssetReinitialized(const Data::Asset<MaterialAsset>& materialAsset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnMaterialAssetReinitialized %s", materialAsset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnMaterialAssetReinitialized %s", this, materialAsset.GetHint().c_str());
|
||||
OnAssetReloaded(materialAsset);
|
||||
}
|
||||
|
||||
@@ -249,7 +250,7 @@ namespace AZ
|
||||
// ShaderReloadNotificationBus overrides...
|
||||
void Material::OnShaderReinitialized([[maybe_unused]] const Shader& shader)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderReinitialized %s", shader.GetAsset().GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderReinitialized %s", this, shader.GetAsset().GetHint().c_str());
|
||||
// Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with
|
||||
// just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be
|
||||
// updated to correctly handle the reload, so it's safer to just reinitialize the whole material.
|
||||
@@ -260,7 +261,7 @@ namespace AZ
|
||||
{
|
||||
// TODO: I think we should make Shader handle OnShaderAssetReinitialized and treat it just like the shader reloaded.
|
||||
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderAssetReinitialized %s", shaderAsset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderAssetReinitialized %s", this, shaderAsset.GetHint().c_str());
|
||||
// Note that it might not be strictly necessary to reinitialize the entire material, we might be able to get away with
|
||||
// just bumping the m_currentChangeId or some other minor updates. But it's pretty hard to know what exactly needs to be
|
||||
// updated to correctly handle the reload, so it's safer to just reinitialize the whole material.
|
||||
@@ -269,7 +270,7 @@ namespace AZ
|
||||
|
||||
void Material::OnShaderVariantReinitialized(const Shader& shader, const ShaderVariantId& /*shaderVariantId*/, ShaderVariantStableId shaderVariantStableId)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Material::OnShaderVariantReinitialized %s variant %u", shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Material::OnShaderVariantReinitialized %s variant %u", this, shader.GetAsset().GetHint().c_str(), shaderVariantStableId.GetIndex());
|
||||
|
||||
// Note that it would be better to check the shaderVariantId to see if that variant is relevant to this particular material before reinitializing it.
|
||||
// There could be hundreds or even thousands of variants for a shader, but only one of those variants will be used by any given material. So we could
|
||||
|
||||
@@ -132,7 +132,7 @@ namespace AZ
|
||||
// AssetBus overrides
|
||||
void Shader::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("Shader::OnAssetReloaded %s", asset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->Shader::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
if (asset->GetId() == m_asset->GetId())
|
||||
{
|
||||
|
||||
@@ -119,7 +119,7 @@ namespace AZ
|
||||
|
||||
void MaterialAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialAsset::OnAssetReloaded %s", asset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
Data::Asset<MaterialTypeAsset> newMaterialTypeAsset = { asset.GetAs<MaterialTypeAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
|
||||
|
||||
@@ -130,7 +130,7 @@ namespace AZ
|
||||
|
||||
void MaterialTypeAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("MaterialTypeAsset::OnAssetReloaded %s", asset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->MaterialTypeAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
// The order of asset reloads is non-deterministic. If the MaterialTypeAsset reloads before these
|
||||
// dependency assets, this will make sure the MaterialTypeAsset gets the latest ones when they reload.
|
||||
|
||||
@@ -381,7 +381,7 @@ namespace AZ
|
||||
// AssetBus overrides...
|
||||
void ShaderAsset::OnAssetReloaded(Data::Asset<Data::AssetData> asset)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnAssetReloaded %s", asset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnAssetReloaded %s", this, asset.GetHint().c_str());
|
||||
|
||||
Data::Asset<ShaderVariantAsset> shaderVariantAsset = { asset.GetAs<ShaderVariantAsset>(), AZ::Data::AssetLoadBehavior::PreLoad };
|
||||
AZ_Assert(shaderVariantAsset->GetStableId() == RootShaderVariantStableId,
|
||||
@@ -396,7 +396,7 @@ namespace AZ
|
||||
/// ShaderVariantFinderNotificationBus overrides
|
||||
void ShaderAsset::OnShaderVariantTreeAssetReady(Data::Asset<ShaderVariantTreeAsset> shaderVariantTreeAsset, bool isError)
|
||||
{
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("ShaderAsset::OnShaderVariantTreeAssetReady %s", shaderVariantTreeAsset.GetHint().c_str());
|
||||
ShaderReloadDebugTracker::ScopedSection reloadSection("{%p}->ShaderAsset::OnShaderVariantTreeAssetReady %s", this, shaderVariantTreeAsset.GetHint().c_str());
|
||||
|
||||
AZStd::unique_lock<decltype(m_variantTreeMutex)> lock(m_variantTreeMutex);
|
||||
if (isError)
|
||||
|
||||
+7
-3
@@ -14,13 +14,14 @@
|
||||
},
|
||||
"clearCoat": {
|
||||
"enable": true,
|
||||
"normalMap": "EngineAssets/Textures/perlinNoiseNormal_ddn.tif"
|
||||
"normalMap": "EngineAssets/Textures/perlinNoiseNormal_ddn.tif",
|
||||
"normalStrength": 0.10000000149011612
|
||||
},
|
||||
"general": {
|
||||
"applySpecularAA": true
|
||||
},
|
||||
"metallic": {
|
||||
"factor": 0.5
|
||||
"factor": 0.10000000149011612
|
||||
},
|
||||
"normal": {
|
||||
"factor": 0.05000000074505806,
|
||||
@@ -31,6 +32,9 @@
|
||||
},
|
||||
"roughness": {
|
||||
"factor": 0.0
|
||||
},
|
||||
"specularF0": {
|
||||
"enableMultiScatterCompensation": true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -8,7 +8,7 @@
|
||||
"Gem"
|
||||
],
|
||||
"user_tags": [
|
||||
"AtomConent"
|
||||
"AtomContent"
|
||||
],
|
||||
"icon_path": "preview.png"
|
||||
}
|
||||
|
||||
+4
-4
@@ -112,13 +112,13 @@ namespace AZ
|
||||
->DataElement(Edit::UIHandlers::Default, &AreaLightComponentConfig::m_enableShutters, "Enable shutters", "Restrict the light to a specific beam angle depending on shape.")
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::ShuttersMustBeEnabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_innerShutterAngleDegrees, "Inner angle", "The inner angle of the shutters where the light beam begins to be occluded.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 180.0f)
|
||||
->Attribute(Edit::Attributes::Min, 0.5f)
|
||||
->Attribute(Edit::Attributes::Max, 90.0f)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled)
|
||||
->DataElement(Edit::UIHandlers::Slider, &AreaLightComponentConfig::m_outerShutterAngleDegrees, "Outer angle", "The outer angle of the shutters where the light beam is completely occluded.")
|
||||
->Attribute(Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(Edit::Attributes::Max, 180.0f)
|
||||
->Attribute(Edit::Attributes::Min, 0.5f)
|
||||
->Attribute(Edit::Attributes::Max, 90.0f)
|
||||
->Attribute(Edit::Attributes::Visibility, &AreaLightComponentConfig::SupportsShutters)
|
||||
->Attribute(Edit::Attributes::ReadOnly, &AreaLightComponentConfig::ShuttersDisabled)
|
||||
|
||||
|
||||
@@ -311,7 +311,8 @@ namespace AZ
|
||||
Data::Asset<RPI::ModelAsset> modelAsset = actor->GetMeshAsset();
|
||||
if (!modelAsset.IsReady())
|
||||
{
|
||||
AZ_Error("CreateSkinnedMeshInputFromActor", false, "Attempting to create skinned mesh input buffers for an actor that doesn't have a loaded model.");
|
||||
AZ_Warning("CreateSkinnedMeshInputFromActor", false, "Check if the actor has a mesh added. Right click the source file in the asset browser, click edit settings, "
|
||||
"and navigate to the Meshes tab. Add a mesh if it's missing.");
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
|
||||
@@ -456,9 +456,8 @@ namespace AZ
|
||||
void AtomActorInstance::Create()
|
||||
{
|
||||
Destroy();
|
||||
|
||||
m_skinnedMeshInputBuffers = GetRenderActor()->FindOrCreateSkinnedMeshInputBuffers();
|
||||
AZ_Error("AtomActorInstance", m_skinnedMeshInputBuffers, "Failed to get SkinnedMeshInputBuffers from Actor.");
|
||||
AZ_Warning("AtomActorInstance", m_skinnedMeshInputBuffers, "Failed to create SkinnedMeshInputBuffers from Actor. It is likely that this actor doesn't have any meshes");
|
||||
if (m_skinnedMeshInputBuffers)
|
||||
{
|
||||
m_boneTransforms = CreateBoneTransformBufferFromActorInstance(m_actorInstance, GetSkinningMethod());
|
||||
|
||||
@@ -69,10 +69,16 @@ proj.launch-config = {loc('../../SDK/Atom/Scripts/Python/DCC_Materials/maya_mate
|
||||
loc('../../azpy/__init__.py'): ('custom',
|
||||
(u'',
|
||||
'launch-oobMrvXFf1SwtYBg')),
|
||||
loc('../../azpy/constants.py'): ('custom',
|
||||
(u'',
|
||||
'launch-GeaM41WYMGA1sEfm')),
|
||||
loc('../../azpy/env_base.py'): ('project',
|
||||
(u'',
|
||||
'launch-GeaM41WYMGA1sEfm')),
|
||||
loc('../../azpy/maya/callbacks/node_message_callback_handler.py'): ('c'\
|
||||
'ustom',
|
||||
(u'',
|
||||
'launch-GeaM41WYMGA1sEfm')),
|
||||
loc('../../config.py'): ('custom',
|
||||
(u'',
|
||||
'launch-GeaM41WYMGA1sEfm'))}
|
||||
|
||||
@@ -165,12 +165,14 @@ def get_current_project():
|
||||
bootstrap_box = None
|
||||
|
||||
try:
|
||||
bootstrap_box = Box.from_json(filename=PATH_USER_O3DE_BOOTSTRAP,
|
||||
bootstrap_box = Box.from_json(filename=str(Path(PATH_USER_O3DE_BOOTSTRAP).resolve()),
|
||||
encoding="utf-8",
|
||||
errors="strict",
|
||||
object_pairs_hook=OrderedDict)
|
||||
except FileExistsError as e:
|
||||
_LOGGER.error('File does not exist: {}'.format(PATH_USER_O3DE_BOOTSTRAP))
|
||||
except Exception as e:
|
||||
# this file runs in py2.7 for Maya 2020, FileExistsError is not defined
|
||||
_LOGGER.error('FileExistsError: {}'.format(PATH_USER_O3DE_BOOTSTRAP))
|
||||
_LOGGER.error('exception is: {}'.format(e))
|
||||
|
||||
if bootstrap_box:
|
||||
# this seems fairly hard coded - what if the data changes?
|
||||
|
||||
@@ -226,7 +226,18 @@ TAG_DEFAULT_PY = str('Launch_pyBASE.bat')
|
||||
FILENAME_DEFAULT_CONFIG = str('DCCSI_config.json')
|
||||
|
||||
# new o3de related paths
|
||||
PATH_USER_O3DE = str('{home}\\{o3de}').format(home=expanduser("~"),
|
||||
# os.path.expanduser("~") returns different values in py2.7 vs 3
|
||||
PATH_USER_HOME = expanduser("~")
|
||||
_LOGGER.debug('user home: {}'.format(PATH_USER_HOME))
|
||||
|
||||
# special case, make sure didn't return <user>\documents
|
||||
parts = os.path.split(PATH_USER_HOME)
|
||||
|
||||
if str(parts[1].lower()) == 'documents':
|
||||
PATH_USER_HOME = parts[0]
|
||||
_LOGGER.debug('user home CORRECTED: {}'.format(PATH_USER_HOME))
|
||||
|
||||
PATH_USER_O3DE = str('{home}\\{o3de}').format(home=PATH_USER_HOME,
|
||||
o3de=TAG_O3DE_FOLDER)
|
||||
PATH_USER_O3DE_REGISTRY = str('{0}\\Registry').format(PATH_USER_O3DE)
|
||||
PATH_USER_O3DE_BOOTSTRAP = str('{reg}\\{file}').format(reg=PATH_USER_O3DE_REGISTRY,
|
||||
|
||||
Reference in New Issue
Block a user