Merge branch 'stabilization/2110' into Prism/AddEditGemsButton

This commit is contained in:
nggieber
2021-11-16 15:58:14 -08:00
119 changed files with 1555 additions and 1329 deletions
@@ -12,6 +12,7 @@ import pytest
import ly_test_tools.log.log_monitor
from AWS.common import constants
from AWS.common.resource_mappings import AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY
# fixture imports
from assetpipeline.ap_fixtures.asset_processor_fixture import asset_processor
@@ -70,6 +71,41 @@ class TestAWSClientAuthWindows(object):
halt_on_unexpected=True,
)
assert result, 'Anonymous credentials fetched successfully.'
@pytest.mark.parametrize('level', ['AWS/ClientAuth'])
def test_anonymous_credentials_no_global_accountid(self,
level: str,
launcher: pytest.fixture,
resource_mappings: pytest.fixture,
workspace: pytest.fixture,
asset_processor: pytest.fixture
):
"""
Test to verify AWS Cognito Identity pool anonymous authorization.
Setup: Updates resource mapping file using existing CloudFormation stacks.
Tests: Getting credentials when no credentials are configured
Verification: Log monitor looks for success credentials log.
"""
# Remove top-level account ID from resource mappings
resource_mappings.clear_select_keys([AWS_RESOURCE_MAPPINGS_ACCOUNT_ID_KEY])
asset_processor.start()
asset_processor.wait_for_idle()
file_to_monitor = os.path.join(launcher.workspace.paths.project_log(), constants.GAME_LOG_NAME)
log_monitor = ly_test_tools.log.log_monitor.LogMonitor(launcher=launcher, log_file_path=file_to_monitor)
launcher.args = ['+LoadLevel', level]
launcher.args.extend(['-rhi=null'])
with launcher.start(launch_ap=False):
result = log_monitor.monitor_log_for_lines(
expected_lines=['(Script) - Success anonymous credentials'],
unexpected_lines=['(Script) - Fail anonymous credentials'],
halt_on_unexpected=True,
)
assert result, 'Anonymous credentials fetched successfully.'
def test_password_signin_credentials(self,
launcher: pytest.fixture,
@@ -8,42 +8,54 @@ import azlmbr.bus
import azlmbr.asset
import azlmbr.editor
import azlmbr.math
import azlmbr.legacy.general
def raise_and_stop(msg):
print (msg)
print('Starting mock asset tests')
handler = azlmbr.editor.EditorEventBusHandler()
def on_notify_editor_initialized(args):
# These tests are meant to check that the test_asset.mock source asset turned into
# a test_asset.mock_asset product asset via the Python asset builder system
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset'
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False)
if (assetId.is_valid() is False):
print(f'Mock AssetId is not valid! Got {assetId.to_string()} instead')
else:
print(f'Mock AssetId is valid!')
assetIdString = assetId.to_string()
if (assetIdString.endswith(':528cca58') is False):
print(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!')
else:
print(f'Mock AssetId has expected sub-id for {mockAssetPath}!')
print ('Mock asset exists')
# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets
def test_azmodel_product(generatedModelAssetPath):
azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0)
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False)
assetIdString = assetId.to_string()
if (assetId.is_valid()):
print(f'AssetId found for asset ({generatedModelAssetPath}) found')
else:
print(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel')
# clear up notification handler
global handler
handler.disconnect()
handler = None
print('Finished mock asset tests')
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
# These tests are meant to check that the test_asset.mock source asset turned into
# a test_asset.mock_asset product asset via the Python asset builder system
mockAssetType = azlmbr.math.Uuid_CreateString('{9274AD17-3212-4651-9F3B-7DCCB080E467}', 0)
mockAssetPath = 'gem/pythontests/pythonassetbuilder/test_asset.mock_asset'
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', mockAssetPath, mockAssetType, False)
if (assetId.is_valid() is False):
raise_and_stop(f'Mock AssetId is not valid! Got {assetId.to_string()} instead')
assetIdString = assetId.to_string()
if (assetIdString.endswith(':528cca58') is False):
raise_and_stop(f'Mock AssetId {assetIdString} has unexpected sub-id for {mockAssetPath}!')
print ('Mock asset exists')
# These tests detect if the geom_group.fbx file turns into a number of azmodel product assets
def test_azmodel_product(generatedModelAssetPath):
azModelAssetType = azlmbr.math.Uuid_CreateString('{2C7477B6-69C5-45BE-8163-BCD6A275B6D8}', 0)
assetId = azlmbr.asset.AssetCatalogRequestBus(azlmbr.bus.Broadcast, 'GetAssetIdByPath', generatedModelAssetPath, azModelAssetType, False)
assetIdString = assetId.to_string()
if (assetId.is_valid()):
print(f'AssetId found for asset ({generatedModelAssetPath}) found')
else:
raise_and_stop(f'Asset at path {generatedModelAssetPath} has unexpected asset ID ({assetIdString})!')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_z_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_y_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_positive_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_x_negative_1.azmodel')
test_azmodel_product('gem/pythontests/pythonassetbuilder/geom_group_fbx_cube_100cm_center_1.azmodel')
azlmbr.editor.EditorToolsApplicationRequestBus(azlmbr.bus.Broadcast, 'ExitNoPrompt')
handler.connect()
handler.add_callback('NotifyEditorInitialized', on_notify_editor_initialized)
@@ -0,0 +1,25 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
namespace AzToolsFramework::EmbeddedPython
{
// When using embedded Python, some platforms need to explicitly load the python library.
// For any modules that depend on 3rdParty::Python package, the AZ::Module should inherit this class.
class PythonLoader
{
public:
PythonLoader();
~PythonLoader();
private:
void* m_embeddedLibPythonHandle{ nullptr };
};
} // namespace AzToolsFramework::EmbeddedPython
@@ -47,6 +47,7 @@ set(FILES
API/EntityCompositionRequestBus.h
API/EntityCompositionNotificationBus.h
API/EditorViewportIconDisplayInterface.h
API/PythonLoader.h
API/ViewPaneOptions.h
API/ViewportEditorModeTrackerInterface.h
Application/Ticker.h
@@ -0,0 +1,20 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/PythonLoader.h>
namespace AzToolsFramework::EmbeddedPython
{
PythonLoader::PythonLoader()
{
}
PythonLoader::~PythonLoader()
{
}
}
@@ -0,0 +1,34 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <AzToolsFramework/API/PythonLoader.h>
#include <AzCore/Debug/Trace.h>
#include <dlfcn.h>
namespace AzToolsFramework::EmbeddedPython
{
PythonLoader::PythonLoader()
{
constexpr char libPythonName[] = "libpython3.7m.so.1.0";
if (m_embeddedLibPythonHandle = dlopen(libPythonName, RTLD_NOW | RTLD_GLOBAL);
m_embeddedLibPythonHandle == nullptr)
{
char* err = dlerror();
AZ_Error("PythonLoader", false, "Failed to load %s with error: %s\n", libPythonName, err ? err : "Unknown Error");
}
}
PythonLoader::~PythonLoader()
{
if (m_embeddedLibPythonHandle)
{
dlclose(m_embeddedLibPythonHandle);
}
}
} // namespace AzToolsFramework::EmbeddedPython
@@ -7,4 +7,5 @@
#
set(FILES
AzToolsFramework/API/PythonLoader_Linux.cpp
)
@@ -7,4 +7,5 @@
#
set(FILES
../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp
)
@@ -7,4 +7,5 @@
#
set(FILES
../Common/Default/AzToolsFramework/API/PythonLoader_Default.cpp
)
@@ -23,6 +23,8 @@
#include <AzCore/RTTI/BehaviorContext.h>
//////////////////////////////////////////////////////////////////////////
#include <xxhash/xxhash.h>
namespace AssetBuilderSDK
{
const char* const ErrorWindow = "Error"; //Use this window name to log error messages.
@@ -1599,4 +1601,70 @@ namespace AssetBuilderSDK
{
return m_errorsOccurred;
}
AZ::u64 GetHashFromIOStream(AZ::IO::GenericStream& readStream, AZ::IO::SizeType* bytesReadOut, int hashMsDelay)
{
constexpr AZ::u64 HashBufferSize = 1024 * 64;
char buffer[HashBufferSize];
if(readStream.IsOpen() && readStream.CanRead())
{
AZ::IO::SizeType bytesRead;
auto* state = XXH64_createState();
if(state == nullptr)
{
AZ_Assert(false, "Failed to create hash state");
return 0;
}
if (XXH64_reset(state, 0) == XXH_ERROR)
{
AZ_Assert(false, "Failed to reset hash state");
return 0;
}
do
{
// In edge cases where another process is writing to this file while this hashing is occuring and that file wasn't locked,
// the following read check can fail because it performs an end of file check, and asserts and shuts down if the read size
// was smaller than the buffer and the read is not at the end of the file. The logic used to check end of file internal to read
// will be out of date in the edge cases where another process is actively writing to this file while this hash is running.
// The stream's length ends up more accurate in this case, preventing this assert and shut down.
// One area this occurs is the navigation mesh file (mnmnavmission0.bai) that's temporarily created when exporting a level,
// the navigation system can still be writing to this file when hashing begins, causing the EoF marker to change.
AZ::IO::SizeType remainingToRead = AZStd::min(readStream.GetLength() - readStream.GetCurPos(), aznumeric_cast<AZ::IO::SizeType>(AZ_ARRAY_SIZE(buffer)));
bytesRead = readStream.Read(remainingToRead, buffer);
if(bytesReadOut)
{
*bytesReadOut += bytesRead;
}
XXH64_update(state, buffer, bytesRead);
// Used by unit tests to force the race condition mentioned above, to verify the crash fix.
if(hashMsDelay > 0)
{
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(hashMsDelay));
}
} while (bytesRead > 0);
auto hash = XXH64_digest(state);
XXH64_freeState(state);
return hash;
}
return 0;
}
AZ::u64 GetFileHash(const char* filePath, AZ::IO::SizeType* bytesReadOut, int hashMsDelay)
{
constexpr bool ErrorOnReadFailure = true;
AZ::IO::FileIOStream readStream(filePath, AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, ErrorOnReadFailure);
return GetHashFromIOStream(readStream, bytesReadOut, hashMsDelay);
}
}
@@ -910,6 +910,19 @@ namespace AssetBuilderSDK
//! There can be multiple builders running at once, so we need to filter out ones coming from other builders
AZStd::thread_id m_jobThreadId;
};
//! Get hash for a whole file
//! @filePath the path for the file
//! @bytesReadOut output the read file size in bytes
//! @hashMsDelay [Do not use except for unit test] add a delay in ms for between each block reading.
AZ::u64 GetFileHash(const char* filePath, AZ::IO::SizeType* bytesReadOut = nullptr, int hashMsDelay = 0);
//! Get hash for a generic IO stream
//! @readStream the input readable stream
//! @bytesReadOut output the read size in bytes
//! @hashMsDelay [Do not use except for unit test] add a delay in ms for between each block reading.
AZ::u64 GetHashFromIOStream(AZ::IO::GenericStream& readStream, AZ::IO::SizeType* bytesReadOut = nullptr, int hashMsDelay = 0);
} // namespace AssetBuilderSDK
namespace AZ
@@ -32,6 +32,7 @@ ly_add_target(
PUBLIC
AZ::AzFramework
AZ::AzToolsFramework
3rdParty::xxhash
)
ly_add_source_properties(
SOURCES AssetBuilderSDK/AssetBuilderSDK.cpp
@@ -1161,7 +1161,7 @@ namespace AssetUtilities
{
#ifndef AZ_TESTS_ENABLED
// Only used for unit tests, speed is critical for GetFileHash.
AZ_UNUSED(hashMsDelay);
hashMsDelay = 0;
#endif
bool useFileHashing = ShouldUseFileHashing();
@@ -1170,10 +1170,10 @@ namespace AssetUtilities
return 0;
}
AZ::u64 hash = 0;
if(!force)
{
auto* fileStateInterface = AZ::Interface<AssetProcessor::IFileStateRequests>::Get();
AZ::u64 hash = 0;
if (fileStateInterface && fileStateInterface->GetHash(filePath, &hash))
{
@@ -1181,64 +1181,8 @@ namespace AssetUtilities
}
}
char buffer[FileHashBufferSize];
constexpr bool ErrorOnReadFailure = true;
AZ::IO::FileIOStream readStream(filePath, AZ::IO::OpenMode::ModeRead | AZ::IO::OpenMode::ModeBinary, ErrorOnReadFailure);
if(readStream.IsOpen() && readStream.CanRead())
{
AZ::IO::SizeType bytesRead;
auto* state = XXH64_createState();
if(state == nullptr)
{
AZ_Assert(false, "Failed to create hash state");
return 0;
}
if (XXH64_reset(state, 0) == XXH_ERROR)
{
AZ_Assert(false, "Failed to reset hash state");
return 0;
}
do
{
// In edge cases where another process is writing to this file while this hashing is occuring and that file wasn't locked,
// the following read check can fail because it performs an end of file check, and asserts and shuts down if the read size
// was smaller than the buffer and the read is not at the end of the file. The logic used to check end of file internal to read
// will be out of date in the edge cases where another process is actively writing to this file while this hash is running.
// The stream's length ends up more accurate in this case, preventing this assert and shut down.
// One area this occurs is the navigation mesh file (mnmnavmission0.bai) that's temporarily created when exporting a level,
// the navigation system can still be writing to this file when hashing begins, causing the EoF marker to change.
AZ::IO::SizeType remainingToRead = AZStd::min(readStream.GetLength() - readStream.GetCurPos(), aznumeric_cast<AZ::IO::SizeType>(AZ_ARRAY_SIZE(buffer)));
bytesRead = readStream.Read(remainingToRead, buffer);
if(bytesReadOut)
{
*bytesReadOut += bytesRead;
}
XXH64_update(state, buffer, bytesRead);
#ifdef AZ_TESTS_ENABLED
// Used by unit tests to force the race condition mentioned above, to verify the crash fix.
if(hashMsDelay > 0)
{
AZStd::this_thread::sleep_for(AZStd::chrono::milliseconds(hashMsDelay));
}
#endif
} while (bytesRead > 0);
auto hash = XXH64_digest(state);
XXH64_freeState(state);
return hash;
}
return 0;
hash = AssetBuilderSDK::GetFileHash(filePath, bytesReadOut, hashMsDelay);
return hash;
}
AZ::u64 AdjustTimestamp(QDateTime timestamp)
@@ -363,7 +363,10 @@ namespace O3DE::ProjectManager
{
const QString selectedGemPath = m_gemModel->GetPath(modelIndex);
// Remove gem from gems to be added
const bool wasAdded = GemModel::WasPreviouslyAdded(modelIndex);
const bool wasAddedDependency = GemModel::WasPreviouslyAddedDependency(modelIndex);
// Remove gem from gems to be added to update any dependencies
GemModel::SetIsAdded(*m_gemModel, modelIndex, false);
// Unregister the gem
@@ -391,6 +394,8 @@ namespace O3DE::ProjectManager
// Select remote gem
QModelIndex remoteGemIndex = m_gemModel->FindIndexByNameString(selectedGemName);
GemModel::SetWasPreviouslyAdded(*m_gemModel, remoteGemIndex, wasAdded);
GemModel::SetWasPreviouslyAddedDependency(*m_gemModel, remoteGemIndex, wasAddedDependency);
QModelIndex proxyIndex = m_proxyModel->mapFromSource(remoteGemIndex);
m_proxyModel->GetSelectionModel()->setCurrentIndex(proxyIndex, QItemSelectionModel::ClearAndSelect);
}
@@ -523,7 +528,9 @@ namespace O3DE::ProjectManager
const QString& gemPath = GemModel::GetPath(modelIndex);
// make sure any remote gems we added were downloaded successfully
if (GemModel::GetGemOrigin(modelIndex) == GemInfo::Remote && GemModel::GetDownloadStatus(modelIndex) != GemInfo::Downloaded)
const GemInfo::DownloadStatus status = GemModel::GetDownloadStatus(modelIndex);
if (GemModel::GetGemOrigin(modelIndex) == GemInfo::Remote &&
!(status == GemInfo::Downloaded || status == GemInfo::DownloadSuccessful))
{
QMessageBox::critical(
nullptr, "Cannot add gem that isn't downloaded",
@@ -9,12 +9,14 @@
#include <ProjectBuilderController.h>
#include <ProjectBuilderWorker.h>
#include <ProjectButtonWidget.h>
#include <ProjectManagerSettings.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <QMessageBox>
#include <QDesktopServices>
#include <QUrl>
namespace O3DE::ProjectManager
{
ProjectBuilderController::ProjectBuilderController(const ProjectInfo& projectInfo, ProjectButton* projectButton, QWidget* parent)
@@ -27,6 +29,15 @@ namespace O3DE::ProjectManager
m_worker = new ProjectBuilderWorker(m_projectInfo);
m_worker->moveToThread(&m_workerThread);
auto settingsRegistry = AZ::SettingsRegistry::Get();
if (settingsRegistry)
{
// Remove key here in case Project Manager crashing while building that causes HandleResults to not be called
QString settingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName);
settingsRegistry->Remove(settingsKey.toStdString().c_str());
SaveProjectManagerSettings();
}
connect(&m_workerThread, &QThread::finished, m_worker, &ProjectBuilderWorker::deleteLater);
connect(&m_workerThread, &QThread::started, m_worker, &ProjectBuilderWorker::BuildProject);
connect(m_worker, &ProjectBuilderWorker::Done, this, &ProjectBuilderController::HandleResults);
@@ -80,6 +91,8 @@ namespace O3DE::ProjectManager
void ProjectBuilderController::HandleResults(const QString& result)
{
QString settingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName);
if (!result.isEmpty())
{
if (result.contains(tr("log")))
@@ -109,12 +122,26 @@ namespace O3DE::ProjectManager
emit NotifyBuildProject(m_projectInfo);
}
auto settingsRegistry = AZ::SettingsRegistry::Get();
if (settingsRegistry)
{
settingsRegistry->Remove(settingsKey.toStdString().c_str());
SaveProjectManagerSettings();
}
emit Done(false);
return;
}
else
{
m_projectInfo.m_buildFailed = false;
auto settingsRegistry = AZ::SettingsRegistry::Get();
if (settingsRegistry)
{
settingsRegistry->Set(settingsKey.toStdString().c_str(), true);
SaveProjectManagerSettings();
}
}
emit Done(true);
@@ -0,0 +1,54 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include "ProjectManagerSettings.h"
#include <AzCore/Settings/SettingsRegistryMergeUtils.h>
#include <AzCore/IO/ByteContainerStream.h>
#include <AzCore/Utils/Utils.h>
namespace O3DE::ProjectManager
{
void SaveProjectManagerSettings()
{
auto settingsRegistry = AZ::SettingsRegistry::Get();
AZ::SettingsRegistryMergeUtils::DumperSettings dumperSettings;
dumperSettings.m_prettifyOutput = true;
dumperSettings.m_jsonPointerPrefix = ProjectManagerKeyPrefix;
AZStd::string stringBuffer;
AZ::IO::ByteContainerStream stringStream(&stringBuffer);
if (!AZ::SettingsRegistryMergeUtils::DumpSettingsRegistryToStream(
*settingsRegistry, ProjectManagerKeyPrefix, stringStream, dumperSettings))
{
AZ_Warning("ProjectManager", false, "Could not save Project Manager settings to stream");
return;
}
AZ::IO::FixedMaxPath o3deUserPath = AZ::Utils::GetO3deManifestDirectory();
o3deUserPath /= AZ::SettingsRegistryInterface::RegistryFolder;
o3deUserPath /= "ProjectManager.setreg";
bool saved = false;
constexpr auto configurationMode =
AZ::IO::SystemFile::SF_OPEN_CREATE | AZ::IO::SystemFile::SF_OPEN_CREATE_PATH | AZ::IO::SystemFile::SF_OPEN_WRITE_ONLY;
AZ::IO::SystemFile outputFile;
if (outputFile.Open(o3deUserPath.c_str(), configurationMode))
{
saved = outputFile.Write(stringBuffer.data(), stringBuffer.size()) == stringBuffer.size();
}
AZ_Warning("ProjectManager", saved, "Unable to save Project Manager registry file to path: %s", o3deUserPath.c_str());
}
QString GetProjectBuiltSuccessfullyKey(const QString& projectName)
{
return QString("%1/Projects/%2/BuiltSuccessfully").arg(ProjectManagerKeyPrefix).arg(projectName);
}
}
@@ -0,0 +1,21 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#if !defined(Q_MOC_RUN)
#include <QString>
#endif
namespace O3DE::ProjectManager
{
static constexpr char ProjectManagerKeyPrefix[] = "/O3DE/ProjectManager";
void SaveProjectManagerSettings();
QString GetProjectBuiltSuccessfullyKey(const QString& projectName);
}
@@ -14,6 +14,7 @@
#include <ProjectUtils.h>
#include <ProjectBuilderController.h>
#include <ScreensCtrl.h>
#include <ProjectManagerSettings.h>
#include <AzQtComponents/Components/FlowLayout.h>
#include <AzCore/Platform.h>
@@ -22,6 +23,7 @@
#include <AzFramework/Process/ProcessCommon.h>
#include <AzFramework/Process/ProcessWatcher.h>
#include <AzCore/Utils/Utils.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <QVBoxLayout>
#include <QHBoxLayout>
@@ -270,17 +272,36 @@ namespace O3DE::ProjectManager
// Add any missing project buttons and restore buttons to default state
for (const ProjectInfo& project : projectsVector)
{
ProjectButton* currentButton = nullptr;
if (!m_projectButtons.contains(QDir::toNativeSeparators(project.m_path)))
{
m_projectButtons.insert(QDir::toNativeSeparators(project.m_path), CreateProjectButton(project));
currentButton = CreateProjectButton(project);
m_projectButtons.insert(QDir::toNativeSeparators(project.m_path), currentButton);
}
else
{
auto projectButtonIter = m_projectButtons.find(QDir::toNativeSeparators(project.m_path));
if (projectButtonIter != m_projectButtons.end())
{
projectButtonIter.value()->RestoreDefaultState();
m_projectsFlowLayout->addWidget(projectButtonIter.value());
currentButton = projectButtonIter.value();
currentButton->RestoreDefaultState();
m_projectsFlowLayout->addWidget(currentButton);
}
}
// Check whether project manager has successfully built the project
if (currentButton)
{
auto settingsRegistry = AZ::SettingsRegistry::Get();
bool projectBuiltSuccessfully = false;
if (settingsRegistry)
{
QString settingsKey = GetProjectBuiltSuccessfullyKey(project.m_projectName);
settingsRegistry->Get(projectBuiltSuccessfully, settingsKey.toStdString().c_str());
}
if (!projectBuiltSuccessfully)
{
currentButton->ShowBuildRequired();
}
}
}
@@ -15,6 +15,9 @@
#include <UpdateProjectCtrl.h>
#include <UpdateProjectSettingsScreen.h>
#include <ProjectUtils.h>
#include <ProjectManagerSettings.h>
#include <AzCore/Settings/SettingsRegistry.h>
#include <QDialogButtonBox>
#include <QMessageBox>
@@ -300,6 +303,21 @@ namespace O3DE::ProjectManager
}
}
if (newProjectSettings.m_projectName != m_projectInfo.m_projectName)
{
// update reg key
QString oldSettingsKey = GetProjectBuiltSuccessfullyKey(m_projectInfo.m_projectName);
QString newSettingsKey = GetProjectBuiltSuccessfullyKey(newProjectSettings.m_projectName);
auto settingsRegistry = AZ::SettingsRegistry::Get();
bool projectBuiltSuccessfully = false;
if (settingsRegistry && settingsRegistry->Get(projectBuiltSuccessfully, oldSettingsKey.toStdString().c_str()))
{
settingsRegistry->Set(newSettingsKey.toStdString().c_str(), projectBuiltSuccessfully);
SaveProjectManagerSettings();
}
}
if (!newProjectSettings.m_newPreviewImagePath.isEmpty())
{
if (!ProjectUtils::ReplaceProjectFile(
@@ -58,6 +58,8 @@ set(FILES
Source/CreateProjectCtrl.cpp
Source/UpdateProjectCtrl.h
Source/UpdateProjectCtrl.cpp
Source/ProjectManagerSettings.h
Source/ProjectManagerSettings.cpp
Source/ProjectsScreen.h
Source/ProjectsScreen.cpp
Source/ProjectSettingsScreen.h
@@ -0,0 +1,44 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#pragma once
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
namespace AWSClientAuth
{
//! Cognito Caching Credentials Provider implementation that is derived from AWS Native SDK.
//! For use with authenticated credentials.
class AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider
: public Aws::Auth::CognitoCachingCredentialsProvider
{
public:
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient = nullptr);
protected:
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome GetCredentialsFromCognito() const override;
};
//! Cognito Caching Credentials Provider implementation that is eventually derived from AWS Native SDK.
//! For use with anonymous credentials.
class AWSClientAuthCachingAnonymousCredsProvider : public AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider
{
public:
AWSClientAuthCachingAnonymousCredsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient = nullptr);
protected:
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome GetCredentialsFromCognito() const override;
};
} // namespace AWSClientAuth
@@ -9,6 +9,7 @@
#pragma once
#include <Authorization/AWSCognitoAuthorizationBus.h>
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h>
#include <Authentication/AuthenticationProviderBus.h>
#include <Credential/AWSCredentialBus.h>
@@ -51,8 +52,8 @@ namespace AWSClientAuth
std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentCognitoIdentityProvider;
std::shared_ptr<AWSClientAuthPersistentCognitoIdentityProvider> m_persistentAnonymousCognitoIdentityProvider;
std::shared_ptr<Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider> m_cognitoCachingCredentialsProvider;
std::shared_ptr<Aws::Auth::CognitoCachingAnonymousCredentialsProvider> m_cognitoCachingAnonymousCredentialsProvider;
std::shared_ptr<AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider> m_cognitoCachingCredentialsProvider;
std::shared_ptr<AWSClientAuthCachingAnonymousCredsProvider> m_cognitoCachingAnonymousCredentialsProvider;
AZStd::string m_cognitoIdentityPoolId;
AZStd::string m_formattedCognitoUserPoolId;
@@ -0,0 +1,122 @@
/*
* Copyright (c) Contributors to the Open 3D Engine Project.
* For complete copyright and license terms please see the LICENSE at the root of this distribution.
*
* SPDX-License-Identifier: Apache-2.0 OR MIT
*
*/
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <AzCore/Debug/Trace.h>
#include <aws/cognito-identity/CognitoIdentityClient.h>
#include <aws/cognito-identity/model/GetCredentialsForIdentityRequest.h>
#include <aws/cognito-identity/model/GetIdRequest.h>
#include <aws/core/utils/Outcome.h>
#include <aws/core/utils/logging/LogMacros.h>
#include <aws/identity-management/auth/CognitoCachingCredentialsProvider.h>
#include <aws/identity-management/auth/PersistentCognitoIdentityProvider.h>
namespace AWSClientAuth
{
static const char* AUTH_LOG_TAG = "AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider";
static const char* ANON_LOG_TAG = "AWSClientAuthCachingAnonymousCredsProvider";
// Modification of https://github.com/aws/aws-sdk-cpp/blob/main/aws-cpp-sdk-identity-management/source/auth/CognitoCachingCredentialsProvider.cpp#L92
// to work around account ID requirement. Account id is not required for call to succeed and is not set unless provided.
// see: https://github.com/aws/aws-sdk-cpp/issues/1448
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome FetchCredsFromCognito(
const Aws::CognitoIdentity::CognitoIdentityClient& cognitoIdentityClient,
Aws::Auth::PersistentCognitoIdentityProvider& identityRepository,
const char* logTag,
bool includeLogins)
{
auto logins = identityRepository.GetLogins();
Aws::Map<Aws::String, Aws::String> cognitoLogins;
for (auto& login : logins)
{
cognitoLogins[login.first] = login.second.accessToken;
}
if (!identityRepository.HasIdentityId())
{
auto accountId = identityRepository.GetAccountId();
auto identityPoolId = identityRepository.GetIdentityPoolId();
Aws::CognitoIdentity::Model::GetIdRequest getIdRequest;
getIdRequest.SetIdentityPoolId(identityPoolId);
if (!accountId.empty()) // new check
{
getIdRequest.SetAccountId(accountId);
AWS_LOGSTREAM_INFO(logTag, "Identity not found, requesting an id for accountId "
<< accountId << " identity pool id "
<< identityPoolId << " with logins.");
}
else
{
AWS_LOGSTREAM_INFO(
logTag, "Identity not found, requesting an id for identity pool id %s" << identityPoolId << " with logins.");
}
if (includeLogins)
{
getIdRequest.SetLogins(cognitoLogins);
}
auto getIdOutcome = cognitoIdentityClient.GetId(getIdRequest);
if (getIdOutcome.IsSuccess())
{
auto identityId = getIdOutcome.GetResult().GetIdentityId();
AWS_LOGSTREAM_INFO(logTag, "Successfully retrieved identity: " << identityId);
identityRepository.PersistIdentityId(identityId);
}
else
{
AWS_LOGSTREAM_ERROR(
logTag,
"Failed to retrieve identity. Error: " << getIdOutcome.GetError().GetExceptionName() << " "
<< getIdOutcome.GetError().GetMessage());
return Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome(getIdOutcome.GetError());
}
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityRequest getCredentialsForIdentityRequest;
getCredentialsForIdentityRequest.SetIdentityId(identityRepository.GetIdentityId());
if (includeLogins)
{
getCredentialsForIdentityRequest.SetLogins(cognitoLogins);
}
return cognitoIdentityClient.GetCredentialsForIdentity(getCredentialsForIdentityRequest);
}
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider::AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient)
: CognitoCachingCredentialsProvider(identityRepository, cognitoIdentityClient)
{
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome
AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider::GetCredentialsFromCognito() const
{
return FetchCredsFromCognito(*m_cognitoIdentityClient, *m_identityRepository, AUTH_LOG_TAG, true);
}
AWSClientAuthCachingAnonymousCredsProvider::AWSClientAuthCachingAnonymousCredsProvider(
const std::shared_ptr<Aws::Auth::PersistentCognitoIdentityProvider>& identityRepository,
const std::shared_ptr<Aws::CognitoIdentity::CognitoIdentityClient>& cognitoIdentityClient)
: AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider(identityRepository, cognitoIdentityClient)
{
}
Aws::CognitoIdentity::Model::GetCredentialsForIdentityOutcome AWSClientAuthCachingAnonymousCredsProvider::
GetCredentialsFromCognito() const
{
return FetchCredsFromCognito(*m_cognitoIdentityClient, *m_identityRepository, ANON_LOG_TAG, false);
}
} // namespace AWSClientAuth
@@ -8,6 +8,7 @@
#include <AWSClientAuthBus.h>
#include <AWSCoreBus.h>
#include <Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h>
#include <Authorization/AWSCognitoAuthorizationController.h>
#include <ResourceMapping/AWSResourceMappingBus.h>
#include <AWSClientAuthResourceMappingConstants.h>
@@ -38,10 +39,12 @@ namespace AWSClientAuth
auto identityClient = AZ::Interface<IAWSClientAuthRequests>::Get()->GetCognitoIdentityClient();
m_cognitoCachingCredentialsProvider =
std::make_shared<Aws::Auth::CognitoCachingAuthenticatedCredentialsProvider>(m_persistentCognitoIdentityProvider, identityClient);
std::make_shared<AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider>(
m_persistentCognitoIdentityProvider, identityClient);
m_cognitoCachingAnonymousCredentialsProvider =
std::make_shared<Aws::Auth::CognitoCachingAnonymousCredentialsProvider>(m_persistentAnonymousCognitoIdentityProvider, identityClient);
std::make_shared<AWSClientAuthCachingAnonymousCredsProvider>(
m_persistentAnonymousCognitoIdentityProvider, identityClient);
}
AWSCognitoAuthorizationController::~AWSCognitoAuthorizationController()
@@ -65,9 +68,13 @@ namespace AWSClientAuth
AWSCore::AWSResourceMappingRequestBus::BroadcastResult(
m_cognitoIdentityPoolId, &AWSCore::AWSResourceMappingRequests::GetResourceNameId, CognitoIdentityPoolIdResourceMappingKey);
if (m_awsAccountId.empty() || m_cognitoIdentityPoolId.empty())
if (m_awsAccountId.empty())
{
AZ_TracePrintf("AWSCognitoAuthorizationController", "AWS account id not not configured. Proceeding without it.");
}
if (m_cognitoIdentityPoolId.empty())
{
AZ_Warning("AWSCognitoAuthorizationController", !m_awsAccountId.empty(), "Missing AWS account id not configured.");
AZ_Warning("AWSCognitoAuthorizationController", !m_cognitoIdentityPoolId.empty(), "Missing Cognito Identity pool id in resource mappings.");
return false;
}
@@ -62,6 +62,14 @@ TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Success)
ASSERT_TRUE(m_mockController->m_cognitoIdentityPoolId == AWSClientAuthUnitTest::TEST_RESOURCE_NAME_ID);
}
TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Success_GetAWSAccountEmpty)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(2);
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1).WillOnce(testing::Return(""));
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultRegion()).Times(1);
ASSERT_TRUE(m_mockController->Initialize());
}
TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_WithLogins_Success)
{
AWSClientAuth::AuthenticationTokens tokens(
@@ -121,7 +129,7 @@ TEST_F(AWSCognitoAuthorizationControllerTest, MultipleCalls_UsesCacheCredentials
m_mockController->RequestAWSCredentialsAsync();
}
TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_Fail_GetIdError)
TEST_F(AWSCognitoAuthorizationControllerTest, RequestAWSCredentials_Fail_GetIdError) // fail
{
AWSClientAuth::AuthenticationTokens cognitoTokens(
AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN, AWSClientAuthUnitTest::TEST_TOKEN,
@@ -321,7 +329,7 @@ TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersisted
EXPECT_TRUE(actualCredentialsProvider == m_mockController->m_cognitoCachingAnonymousCredentialsProvider);
}
TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersistedLogins_NoAnonymousCredentials_ResultNullPtr)
TEST_F(AWSCognitoAuthorizationControllerTest, GetCredentialsProvider_NoPersistedLogins_NoAnonymousCredentials_ResultNullPtr) // fails
{
Aws::Client::AWSError<Aws::CognitoIdentity::CognitoIdentityErrors> error;
error.SetExceptionName(AWSClientAuthUnitTest::TEST_EXCEPTION);
@@ -431,11 +439,3 @@ TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Fail_GetResourceNameEmp
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1);
ASSERT_FALSE(m_mockController->Initialize());
}
TEST_F(AWSCognitoAuthorizationControllerTest, Initialize_Fail_GetAWSAccountEmpty)
{
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetResourceNameId(testing::_)).Times(1);
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultAccountId()).Times(1).WillOnce(testing::Return(""));
EXPECT_CALL(m_awsResourceMappingRequestBusMock, GetDefaultRegion()).Times(0);
ASSERT_FALSE(m_mockController->Initialize());
}
@@ -24,6 +24,7 @@ set(FILES
Include/Private/Authorization/AWSCognitoAuthorizationController.h
Include/Private/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.h
Include/Private/Authorization/AWSCognitoAuthorizationNotificationBusBehaviorHandler.h
Include/Private/Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.h
Include/Private/UserManagement/AWSCognitoUserManagementController.h
Include/Private/UserManagement/UserManagementNotificationBusBehaviorHandler.h
@@ -45,6 +46,7 @@ set(FILES
Source/Authorization/ClientAuthAWSCredentials.cpp
Source/Authorization/AWSCognitoAuthorizationController.cpp
Source/Authorization/AWSClientAuthPersistentCognitoIdentityProvider.cpp
Source/Authorization/AWSClientAuthCognitoCachingAuthenticatedCredentialsProvider.cpp
Source/UserManagement/AWSCognitoUserManagementController.cpp
)
+16
View File
@@ -65,6 +65,22 @@ them to your `setup.py` file and rerun the `pip install -r requirements.txt`
command.
## Optional Features
Optional features are activated by passing [runtime context variables](https://docs.aws.amazon.com/cdk/latest/guide/context.html). To use multiple optional features together provide one key-value pair at a time:
```
cdk synth --context key1=value1 --context key2=value2 MyStack
```
### Automatic S3 and DynamoDB Cleanup
The S3 bucket and Dynamodb created by the sample will be left behind as the CDK defaults to retaining such storage (both have default policies to retain resources on destroy). To delete
the storage resources created when using CDK destroy, use the following commands to synthesize and destroy the CDK application.
```
cdk synth -c remove_all_storage_on_destroy=true --all
cdk deploy -c remove_all_storage_on_destroy=true --all
cdk destroy --all
```
### Server Access Logging
Server access logging is enabled by default. To disable the feature, use the following commands to synthesize and deploy this CDK application.
```
+9 -1
View File
@@ -86,13 +86,21 @@ class CoreStack(core.Stack):
# Create an S3 bucket for Amazon S3 server access logging
# See https://docs.aws.amazon.com/AmazonS3/latest/dev/security-best-practices.html
if self.node.try_get_context('disable_access_log') != 'true':
# Auto cleanup bucket and data if requested
_remove_storage = self.node.try_get_context('remove_all_storage_on_destroy') == 'true'
_removal_policy = core.RemovalPolicy.DESTROY if _remove_storage else core.RemovalPolicy.RETAIN
self._server_access_logs_bucket = s3.Bucket(
self,
f'{self._project_name}-{self._feature_name}-Access-Log-Bucket',
access_control=s3.BucketAccessControl.LOG_DELIVERY_WRITE,
auto_delete_objects = _remove_storage,
block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
encryption=s3.BucketEncryption.S3_MANAGED,
access_control=s3.BucketAccessControl.LOG_DELIVERY_WRITE
removal_policy=_removal_policy
)
self._server_access_logs_bucket.grant_read(self._admin_group)
# Export access log bucket name
@@ -126,11 +126,17 @@ class ExampleResources(core.Stack):
core.Fn.import_value(f"{self._project_name}:ServerAccessLogsBucket")
)
# Auto cleanup bucket and data if requested
_remove_storage = self.node.try_get_context('remove_all_storage_on_destroy') == 'true'
_removal_policy = core.RemovalPolicy.DESTROY if _remove_storage else core.RemovalPolicy.RETAIN
example_bucket = s3.Bucket(
self,
f'{self._project_name}-{self._feature_name}-Example-S3bucket',
auto_delete_objects=_remove_storage,
block_public_access=s3.BlockPublicAccess.BLOCK_ALL,
encryption=s3.BucketEncryption.S3_MANAGED,
removal_policy=_removal_policy,
server_access_logs_bucket=
server_access_logs_bucket if server_access_logs_bucket else None,
server_access_logs_prefix=
@@ -170,6 +176,11 @@ class ExampleResources(core.Stack):
type=dynamo.AttributeType.STRING
)
)
# Auto-delete the table when requested
if self.node.try_get_context('remove_all_storage_on_destroy') == 'true':
demo_table.apply_removal_policy(core.RemovalPolicy.DESTROY)
return demo_table
def __create_outputs(self) -> None:
@@ -7,16 +7,6 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_basecolor",
"_diff",
"_color",
"_col",
"_albedo",
"_alb",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -29,16 +19,6 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_col",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"DiscardAlpha": true,
@@ -51,16 +31,6 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_col",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"DiscardAlpha": true,
@@ -73,16 +43,6 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_col",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -94,16 +54,6 @@
"UUID": "{08A95286-ADB2-41E4-96EB-DB48F4726D6A}",
"Name": "Albedo",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_col",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -7,15 +7,6 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1a",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -27,15 +18,6 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -46,15 +28,6 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -65,15 +38,6 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1a",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -84,15 +48,6 @@
"UUID": "{57ED16B1-407B-4E29-BCFC-D3BAE60F2C85}",
"Name": "AlbedoWithCoverage",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC1a",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -7,17 +7,7 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC3",
"IsPowerOf2": true,
"PixelFormat": "ASTC_4x4",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -27,18 +17,8 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -47,18 +27,8 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -67,17 +37,7 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC3",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -86,17 +46,7 @@
"UUID": "{5D9ECB52-4CD9-4CB8-80E3-10CAE5EFB8A2}",
"Name": "AlbedoWithGenericAlpha",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_diff",
"_color",
"_albedo",
"_alb",
"_basecolor",
"_bc",
"_diffuse"
],
"PixelFormat": "BC3",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -8,12 +8,6 @@
"Name": "AmbientOcclusion",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ao",
"_ambocc",
"_amb",
"_ambientocclusion"
],
"PixelFormat": "BC4"
},
"PlatformsPresets": {
@@ -22,12 +16,6 @@
"Name": "AmbientOcclusion",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ao",
"_ambocc",
"_amb",
"_ambientocclusion"
],
"MaxTextureSize": 2048,
"PixelFormat": "ASTC_4x4"
},
@@ -36,12 +24,6 @@
"Name": "AmbientOcclusion",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ao",
"_ambocc",
"_amb",
"_ambientocclusion"
],
"MaxTextureSize": 2048,
"PixelFormat": "ASTC_4x4"
},
@@ -50,12 +32,6 @@
"Name": "AmbientOcclusion",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ao",
"_ambocc",
"_amb",
"_ambientocclusion"
],
"PixelFormat": "BC4"
},
"provo": {
@@ -63,12 +39,6 @@
"Name": "AmbientOcclusion",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ao",
"_ambocc",
"_amb",
"_ambientocclusion"
],
"PixelFormat": "BC4"
}
}
@@ -8,10 +8,6 @@
"Name": "ConvolvedCubemap",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ccm",
"_convolvedcubemap"
],
"SuppressEngineReduce": true,
"PixelFormat": "R9G9B9E5",
"DiscardAlpha": true,
@@ -35,10 +31,6 @@
"Name": "ConvolvedCubemap",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ccm",
"_convolvedcubemap"
],
"SuppressEngineReduce": true,
"PixelFormat": "R9G9B9E5",
"DiscardAlpha": true,
@@ -61,10 +53,6 @@
"Name": "ConvolvedCubemap",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ccm",
"_convolvedcubemap"
],
"SuppressEngineReduce": true,
"PixelFormat": "R9G9B9E5",
"DiscardAlpha": true,
@@ -87,10 +75,6 @@
"Name": "ConvolvedCubemap",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ccm",
"_convolvedcubemap"
],
"SuppressEngineReduce": true,
"PixelFormat": "R9G9B9E5",
"DiscardAlpha": true,
@@ -113,10 +97,6 @@
"Name": "ConvolvedCubemap",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ccm",
"_convolvedcubemap"
],
"SuppressEngineReduce": true,
"PixelFormat": "R9G9B9E5",
"DiscardAlpha": true,
@@ -6,9 +6,6 @@
"DefaultPreset": {
"UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}",
"Name": "Decal_AlbedoWithOpacity",
"FileMasks": [
"_decal"
],
"PixelFormat": "BC7t",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -21,9 +18,6 @@
"android": {
"UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}",
"Name": "Decal_AlbedoWithOpacity",
"FileMasks": [
"_decal"
],
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
@@ -36,9 +30,6 @@
"ios": {
"UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}",
"Name": "Decal_AlbedoWithOpacity",
"FileMasks": [
"_decal"
],
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
@@ -51,9 +42,6 @@
"mac": {
"UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}",
"Name": "Decal_AlbedoWithOpacity",
"FileMasks": [
"_decal"
],
"PixelFormat": "BC3",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -65,9 +53,6 @@
"provo": {
"UUID": "{E06B5087-2640-49B6-B9BA-D40048162B90}",
"Name": "Decal_AlbedoWithOpacity",
"FileMasks": [
"_decal"
],
"PixelFormat": "BC7t",
"IsPowerOf2": true,
"MipMapSetting": {
@@ -8,18 +8,6 @@
"Name": "Displacement",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_displ",
"_disp",
"_dsp",
"_d",
"_dm",
"_displacement",
"_height",
"_hm",
"_ht",
"_h"
],
"PixelFormat": "BC4",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -33,18 +21,6 @@
"Name": "Displacement",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_displ",
"_disp",
"_dsp",
"_d",
"_dm",
"_displacement",
"_height",
"_hm",
"_ht",
"_h"
],
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"DiscardAlpha": true,
@@ -59,18 +35,6 @@
"Name": "Displacement",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_displ",
"_disp",
"_dsp",
"_d",
"_dm",
"_displacement",
"_height",
"_hm",
"_ht",
"_h"
],
"PixelFormat": "ASTC_4x4",
"MaxTextureSize": 2048,
"DiscardAlpha": true,
@@ -84,18 +48,6 @@
"Name": "Displacement",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_displ",
"_disp",
"_dsp",
"_d",
"_dm",
"_displacement",
"_height",
"_hm",
"_ht",
"_h"
],
"PixelFormat": "BC4",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -108,18 +60,6 @@
"Name": "Displacement",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_displ",
"_disp",
"_dsp",
"_d",
"_dm",
"_displacement",
"_height",
"_hm",
"_ht",
"_h"
],
"PixelFormat": "BC4",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -7,13 +7,6 @@
"UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}",
"Name": "Emissive",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_emissive",
"_e",
"_glow",
"_em",
"_emit"
],
"PixelFormat": "BC7",
"DiscardAlpha": true
},
@@ -22,13 +15,6 @@
"UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}",
"Name": "Emissive",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_emissive",
"_e",
"_glow",
"_em",
"_emit"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"DiscardAlpha": true
@@ -37,13 +23,6 @@
"UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}",
"Name": "Emissive",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_emissive",
"_e",
"_glow",
"_em",
"_emit"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"DiscardAlpha": true
@@ -52,13 +31,6 @@
"UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}",
"Name": "Emissive",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_emissive",
"_e",
"_glow",
"_em",
"_emit"
],
"PixelFormat": "BC7",
"DiscardAlpha": true
},
@@ -66,13 +38,6 @@
"UUID": "{07041D83-E0C3-4726-8735-CA0FE550C9A0}",
"Name": "Emissive",
"RGB_Weight": "CIEXYZ",
"FileMasks": [
"_emissive",
"_e",
"_glow",
"_em",
"_emit"
],
"PixelFormat": "BC7",
"DiscardAlpha": true
}
@@ -8,11 +8,8 @@
"Name": "Greyscale",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_mask"
],
"PixelFormat": "BC4",
"IsPowerOf2": true,
"Swizzle": "rrr1",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -23,11 +20,8 @@
"Name": "Greyscale",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_mask"
],
"PixelFormat": "ASTC_4x4",
"IsPowerOf2": true,
"Swizzle": "rrr1",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -37,11 +31,8 @@
"Name": "Greyscale",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_mask"
],
"PixelFormat": "ASTC_4x4",
"IsPowerOf2": true,
"Swizzle": "rrr1",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -51,11 +42,8 @@
"Name": "Greyscale",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_mask"
],
"PixelFormat": "BC4",
"IsPowerOf2": true,
"Swizzle": "rrr1",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -65,11 +53,8 @@
"Name": "Greyscale",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_mask"
],
"PixelFormat": "BC4",
"IsPowerOf2": true,
"Swizzle": "rrr1",
"MipMapSetting": {
"MipGenType": "Box"
}
@@ -7,9 +7,6 @@
"UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}",
"Name": "IBLDiffuse",
"Description": "The input cubemap generates an IBL diffuse output cubemap.",
"FileMasks": [
"_ibldiffusecm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -31,9 +28,6 @@
"android": {
"UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}",
"Name": "IBLDiffuse",
"FileMasks": [
"_ibldiffusecm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -54,9 +48,6 @@
"ios": {
"UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}",
"Name": "IBLDiffuse",
"FileMasks": [
"_ibldiffusecm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -77,9 +68,6 @@
"mac": {
"UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}",
"Name": "IBLDiffuse",
"FileMasks": [
"_ibldiffusecm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -100,9 +88,6 @@
"provo": {
"UUID": "{E3706342-BF21-4D9C-AE28-9670EB3EF3C5}",
"Name": "IBLDiffuse",
"FileMasks": [
"_ibldiffusecm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -8,11 +8,6 @@
"Name": "IBLGlobal",
"Description": "The input cubemap generates IBL specular and diffuse cubemaps.",
"GenerateIBLOnly": true,
"FileMasks": [
"_iblglobalcm",
"_cubemap",
"_cm"
],
"CubemapSettings": {
"GenerateIBLSpecular": true,
"IBLSpecularPreset": "IBLSpecular",
@@ -7,9 +7,6 @@
"UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}",
"Name": "IBLSkybox",
"Description": "The input cubemap generates a skybox, IBL specular, and IBL diffuse output cubemaps.",
"FileMasks": [
"_iblskyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -29,9 +26,6 @@
"android": {
"UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}",
"Name": "IBLSkybox",
"FileMasks": [
"_iblskyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -50,9 +44,6 @@
"ios": {
"UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}",
"Name": "IBLSkybox",
"FileMasks": [
"_iblskyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -71,9 +62,6 @@
"mac": {
"UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}",
"Name": "IBLSkybox",
"FileMasks": [
"_iblskyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -92,9 +80,6 @@
"provo": {
"UUID": "{E6441EAC-9843-484B-8EFC-C03B2935B48D}",
"Name": "IBLSkybox",
"FileMasks": [
"_iblskyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -7,10 +7,6 @@
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
"Name": "IBLSpecular",
"Description": "The input cubemap generates an IBL specular output cubemap.",
"FileMasks": [
"_iblspecularcm",
"_iblspecularcm256"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -34,10 +30,6 @@
"android": {
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
"Name": "IBLSpecular",
"FileMasks": [
"_iblspecularcm",
"_iblspecularcm256"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -60,10 +52,6 @@
"ios": {
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
"Name": "IBLSpecular",
"FileMasks": [
"_iblspecularcm",
"_iblspecularcm256"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -86,10 +74,6 @@
"mac": {
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
"Name": "IBLSpecular",
"FileMasks": [
"_iblspecularcm",
"_iblspecularcm256"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -112,10 +96,6 @@
"provo": {
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
"Name": "IBLSpecular",
"FileMasks": [
"_iblspecularcm",
"_iblspecularcm256"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -7,9 +7,6 @@
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
"Name": "IBLSpecularHigh",
"Description": "The input cubemap generates an IBL specular output cubemap.",
"FileMasks": [
"_iblspecularcm512"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -33,9 +30,6 @@
"android": {
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
"Name": "IBLSpecularHigh",
"FileMasks": [
"_iblspecularcm512"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -58,9 +52,6 @@
"ios": {
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
"Name": "IBLSpecularHigh",
"FileMasks": [
"_iblspecularcm512"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -83,9 +74,6 @@
"mac": {
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
"Name": "IBLSpecularHigh",
"FileMasks": [
"_iblspecularcm512"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -108,9 +96,6 @@
"provo": {
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
"Name": "IBLSpecularHigh",
"FileMasks": [
"_iblspecularcm512"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -7,9 +7,6 @@
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
"Name": "IBLSpecularLow",
"Description": "The input cubemap generates an IBL specular output cubemap.",
"FileMasks": [
"_iblspecularcm128"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -33,9 +30,6 @@
"android": {
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
"Name": "IBLSpecularLow",
"FileMasks": [
"_iblspecularcm128"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -58,9 +52,6 @@
"ios": {
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
"Name": "IBLSpecularLow",
"FileMasks": [
"_iblspecularcm128"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -83,9 +74,6 @@
"mac": {
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
"Name": "IBLSpecularLow",
"FileMasks": [
"_iblspecularcm128"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -108,9 +96,6 @@
"provo": {
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
"Name": "IBLSpecularLow",
"FileMasks": [
"_iblspecularcm128"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -7,9 +7,6 @@
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
"Name": "IBLSpecularVeryHigh",
"Description": "The input cubemap generates an IBL specular output cubemap.",
"FileMasks": [
"_iblspecularcm1024"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -33,9 +30,6 @@
"android": {
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
"Name": "IBLSpecularVeryHigh",
"FileMasks": [
"_iblspecularcm1024"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -58,9 +52,6 @@
"ios": {
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
"Name": "IBLSpecularVeryHigh",
"FileMasks": [
"_iblspecularcm1024"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -83,9 +74,6 @@
"mac": {
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
"Name": "IBLSpecularVeryHigh",
"FileMasks": [
"_iblspecularcm1024"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -108,9 +96,6 @@
"provo": {
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
"Name": "IBLSpecularVeryHigh",
"FileMasks": [
"_iblspecularcm1024"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -7,9 +7,6 @@
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
"Name": "IBLSpecularVeryLow",
"Description": "The input cubemap generates an IBL specular output cubemap.",
"FileMasks": [
"_iblspecularcm64"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -33,9 +30,6 @@
"android": {
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
"Name": "IBLSpecularVeryLow",
"FileMasks": [
"_iblspecularcm64"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -58,9 +52,6 @@
"ios": {
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
"Name": "IBLSpecularVeryLow",
"FileMasks": [
"_iblspecularcm64"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -83,9 +74,6 @@
"mac": {
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
"Name": "IBLSpecularVeryLow",
"FileMasks": [
"_iblspecularcm64"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -108,9 +96,6 @@
"provo": {
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
"Name": "IBLSpecularVeryLow",
"FileMasks": [
"_iblspecularcm64"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -0,0 +1,150 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "BuilderSettingManager",
"ClassData": {
"BuildSettings": {
"android": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"ios": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"mac": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"pc": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"linux": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"provo": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": false
}
},
"PresetsByFileMask": {
// albedo
"_basecolor": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_diff": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_diffuse": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_color": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_col": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_albedo": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_alb": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
"_bc": [ "Albedo", "AlbedoWithGenericAlpha", "AlbedoWithCoverage" ],
// normals
"_ddn": [ "Normals" ],
"_normal": [ "Normals" ],
"_normalmap": [ "Normals" ],
"_normals": [ "Normals" ],
"_norm": [ "Normals" ],
"_nor": [ "Normals" ],
"_nrm": [ "Normals" ],
"_nm": [ "Normals" ],
"_n": [ "Normals" ],
"_ddna": [ "NormalsWithSmoothness" ],
"_normala": [ "NormalsWithSmoothness" ],
"_nrma": [ "NormalsWithSmoothness" ],
"_nma": [ "NormalsWithSmoothness" ],
"_na": [ "NormalsWithSmoothness" ],
// refelctance
"_spec": [ "Reflectance" ],
"_specular": [ "Reflectance" ],
"_metallic": [ "Reflectance" ],
"_refl": [ "Reflectance" ],
"_ref": [ "Reflectance" ],
"_rf": [ "Reflectance" ],
"_gloss": [ "Reflectance" ],
"_g": [ "Reflectance" ],
"_f0": [ "Reflectance" ],
"_specf0": [ "Reflectance" ],
"_metal": [ "Reflectance" ],
"_mtl": [ "Reflectance" ],
"_m": [ "Reflectance" ],
"_mt": [ "Reflectance" ],
"_metalness": [ "Reflectance" ],
"_rough": [ "Reflectance" ],
"_roughness": [ "Reflectance" ],
// opacity
"_sss": [ "Opacity" ],
"_trans": [ "Opacity" ],
"_opac": [ "Opacity" ],
"_opacity": [ "Opacity" ],
"_o": [ "Opacity" ],
"_op": [ "Opacity" ],
"_mask": [ "Opacity", "Greyscale" ],
"_msk": [ "Opacity" ],
"_blend": [ "Opacity" ],
// AO
"_ao": [ "AmbientOcclusion" ],
"_ambocc": [ "AmbientOcclusion" ],
"_amb": [ "AmbientOcclusion" ],
"_ambientocclusion": [ "AmbientOcclusion" ],
// emissive
"_emissive": [ "Emissive" ],
"_e": [ "Emissive" ],
"_glow": [ "Emissive" ],
"_em": [ "Emissive" ],
"_emit": [ "Emissive" ],
// displacement
"_displ": [ "Emissive" ],
"_disp": [ "Emissive" ],
"_dsp": [ "Emissive" ],
"_d": [ "Emissive" ],
"_dm": [ "Emissive" ],
"_displacement": [ "Emissive" ],
"_height": [ "Emissive" ],
"_hm": [ "Emissive" ],
"_ht": [ "Emissive" ],
"_h": [ "Emissive" ],
// cubemap
"_ibldiffusecm": [ "IBLDiffuse" ],
"_iblskyboxcm": [ "IBLSkybox" ],
"_iblspecularcm": [ "IBLSpecular" ],
"_iblspecularcm128": [ "IBLSpecularLow" ],
"_iblspecularcm256": [ "IBLSpecular" ],
"_iblspecularcm512": [ "IBLSpecularHigh" ],
"_iblspecularcm1024": [ "IBLSpecularVeryHigh" ],
"_skyboxcm": [ "Skybox" ],
"_ccm": [ "ConvolvedCubemap" ],
"_convolvedcubemap": [ "ConvolvedCubemap" ],
"_iblglobalcm": [ "IBLGlobal" ],
"_cubemap": [ "IBLGlobal" ],
"_cm": [ "IBLGlobal" ],
// lut
"_lut": [ "LUT_RG8" ],
"_lutr32f": [ "LUT_R32F" ],
"_lutrgba16": [ "LUT_RGBA16" ],
"_lutrg32f": [ "LUT_RG32F" ],
"_lutrgba32f": [ "LUT_RGBA32F" ],
// layer mask
"_layers": [ "LayerMask" ],
"_rgbmask": [ "LayerMask" ],
// decal
"_decal": [ "Decal_AlbedoWithOpacity" ],
// ui
"_ui": [ "UserInterface_Lossless" ]
},
"DefaultPreset": "Albedo",
"DefaultPresetAlpha": "AlbedoWithGenericAlpha"
}
}
@@ -6,7 +6,6 @@
"DefaultPreset": {
"UUID": "{10D4D7D8-23E2-4FC5-BE6A-DA9949D2C603}",
"Name": "LUT_R32F",
"FileMasks": ["_lutr32f"],
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "R32F"
@@ -6,7 +6,6 @@
"DefaultPreset": {
"UUID": "{52470B8B-0798-4E03-B0D3-039D5141CFEC}",
"Name": "LUT_RG32F",
"FileMasks": ["_lutrg32f"],
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "R32G32F"
@@ -8,9 +8,6 @@
"Name": "LUT_RG8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lut"
],
"PixelFormat": "R8G8"
},
"PlatformsPresets": {
@@ -19,9 +16,6 @@
"Name": "LUT_RG8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lut"
],
"PixelFormat": "R8G8"
},
"ios": {
@@ -29,9 +23,6 @@
"Name": "LUT_RG8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lut"
],
"PixelFormat": "R8G8"
},
"mac": {
@@ -39,9 +30,6 @@
"Name": "LUT_RG8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lut"
],
"PixelFormat": "R8G8"
},
"provo": {
@@ -49,9 +37,6 @@
"Name": "LUT_RG8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lut"
],
"PixelFormat": "R8G8"
}
}
@@ -8,9 +8,6 @@
"Name": "LUT_RGBA16",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16"
],
"PixelFormat": "R16G16B16A16"
},
"PlatformsPresets": {
@@ -19,9 +16,6 @@
"Name": "LUT_RGBA16",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16"
],
"PixelFormat": "R16G16B16A16"
},
"ios": {
@@ -29,9 +23,6 @@
"Name": "LUT_RGBA16",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16"
],
"PixelFormat": "R16G16B16A16"
},
"osx_gl": {
@@ -39,9 +30,6 @@
"Name": "LUT_RGBA16",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16"
],
"PixelFormat": "R16G16B16A16"
},
"provo": {
@@ -49,9 +37,6 @@
"Name": "LUT_RGBA16",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16"
],
"PixelFormat": "R16G16B16A16"
}
}
@@ -8,9 +8,6 @@
"Name": "LUT_RGBA16F",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16f"
],
"PixelFormat": "R16G16B16A16F"
},
"PlatformsPresets": {
@@ -19,9 +16,6 @@
"Name": "LUT_RGBA16F",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16f"
],
"PixelFormat": "R16G16B16A16F"
},
"ios": {
@@ -29,9 +23,6 @@
"Name": "LUT_RGBA16F",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16f"
],
"PixelFormat": "R16G16B16A16F"
},
"osx_gl": {
@@ -39,9 +30,6 @@
"Name": "LUT_RGBA16F",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16f"
],
"PixelFormat": "R16G16B16A16F"
},
"provo": {
@@ -49,9 +37,6 @@
"Name": "LUT_RGBA16F",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_lutrgba16f"
],
"PixelFormat": "R16G16B16A16F"
}
}
@@ -6,7 +6,6 @@
"DefaultPreset": {
"UUID": "{AC4C49D4-2C70-425A-8DBF-E7FB2C61CF8D}",
"Name": "LUT_RGBA32F",
"FileMasks": ["_lutrgba32f"],
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "R32G32B32A32F"
@@ -8,10 +8,6 @@
"Name": "LayerMask",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_layers",
"_rgbmask"
],
"PixelFormat": "R8G8B8X8"
},
"PlatformsPresets": {
@@ -20,10 +16,6 @@
"Name": "LayerMask",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_layers",
"_rgbmask"
],
"PixelFormat": "R8G8B8X8"
},
"ios": {
@@ -31,10 +23,6 @@
"Name": "LayerMask",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_layers",
"_rgbmask"
],
"PixelFormat": "R8G8B8X8"
},
"mac": {
@@ -42,10 +30,6 @@
"Name": "LayerMask",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_layers",
"_rgbmask"
],
"PixelFormat": "R8G8B8X8"
},
"provo": {
@@ -53,10 +37,6 @@
"Name": "LayerMask",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_layers",
"_rgbmask"
],
"PixelFormat": "R8G8B8X8"
}
}
@@ -8,17 +8,6 @@
"Name": "Normals",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddn",
"_normal",
"_normalmap",
"_normals",
"_norm",
"_nor",
"_nrm",
"_nm",
"_n"
],
"PixelFormat": "BC5s",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -33,17 +22,6 @@
"Name": "Normals",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddn",
"_normal",
"_normalmap",
"_normals",
"_norm",
"_nor",
"_nrm",
"_nm",
"_n"
],
"PixelFormat": "ASTC_4x4",
"DiscardAlpha": true,
"MaxTextureSize": 1024,
@@ -58,17 +36,6 @@
"Name": "Normals",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddn",
"_normal",
"_normalmap",
"_normals",
"_norm",
"_nor",
"_nrm",
"_nm",
"_n"
],
"PixelFormat": "ASTC_4x4",
"DiscardAlpha": true,
"MaxTextureSize": 1024,
@@ -83,17 +50,6 @@
"Name": "Normals",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddn",
"_normal",
"_normalmap",
"_normals",
"_norm",
"_nor",
"_nrm",
"_nm",
"_n"
],
"PixelFormat": "BC5s",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -107,17 +63,6 @@
"Name": "Normals",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddn",
"_normal",
"_normalmap",
"_normals",
"_norm",
"_nor",
"_nrm",
"_nm",
"_n"
],
"PixelFormat": "BC5s",
"DiscardAlpha": true,
"IsPowerOf2": true,
@@ -8,13 +8,6 @@
"Name": "NormalsWithSmoothness",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddna",
"_normala",
"_nrma",
"_nma",
"_na"
],
"PixelFormat": "BC5s",
"PixelFormatAlpha": "BC4",
"IsPowerOf2": true,
@@ -30,13 +23,6 @@
"Name": "NormalsWithSmoothness",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddna",
"_normala",
"_nrma",
"_nma",
"_na"
],
"PixelFormat": "ASTC_4x4",
"PixelFormatAlpha": "ASTC_4x4",
"MaxTextureSize": 2048,
@@ -52,13 +38,6 @@
"Name": "NormalsWithSmoothness",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddna",
"_normala",
"_nrma",
"_nma",
"_na"
],
"PixelFormat": "ASTC_4x4",
"PixelFormatAlpha": "ASTC_4x4",
"MaxTextureSize": 2048,
@@ -74,13 +53,6 @@
"Name": "NormalsWithSmoothness",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddna",
"_normala",
"_nrma",
"_nma",
"_na"
],
"PixelFormat": "BC5s",
"PixelFormatAlpha": "BC4",
"IsPowerOf2": true,
@@ -95,13 +67,6 @@
"Name": "NormalsWithSmoothness",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_ddna",
"_normala",
"_nrma",
"_nma",
"_na"
],
"PixelFormat": "BC5s",
"PixelFormatAlpha": "BC4",
"IsPowerOf2": true,
@@ -8,19 +8,8 @@
"Name": "Opacity",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_sss",
"_trans",
"_opac",
"_opacity",
"_o",
"_opac",
"_op",
"_mask",
"_msk",
"_blend"
],
"PixelFormat": "BC4",
"Swizzle": "rrr1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
@@ -32,19 +21,8 @@
"Name": "Opacity",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_sss",
"_trans",
"_opac",
"_opacity",
"_o",
"_opac",
"_op",
"_mask",
"_msk",
"_blend"
],
"PixelFormat": "ASTC_4x4",
"Swizzle": "rrr1",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
@@ -56,19 +34,8 @@
"Name": "Opacity",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_sss",
"_trans",
"_opac",
"_opacity",
"_o",
"_opac",
"_op",
"_mask",
"_msk",
"_blend"
],
"PixelFormat": "ASTC_4x4",
"Swizzle": "rrr1",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
@@ -80,19 +47,8 @@
"Name": "Opacity",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_sss",
"_trans",
"_opac",
"_opacity",
"_o",
"_opac",
"_op",
"_mask",
"_msk",
"_blend"
],
"PixelFormat": "BC4",
"Swizzle": "rrr1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
@@ -103,19 +59,8 @@
"Name": "Opacity",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_sss",
"_trans",
"_opac",
"_opacity",
"_o",
"_opac",
"_op",
"_mask",
"_msk",
"_blend"
],
"PixelFormat": "BC4",
"Swizzle": "rrr1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
@@ -0,0 +1,66 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "MultiplatformPresetSettings",
"ClassData": {
"DefaultPreset": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"PlatformsPresets": {
"android": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"ios": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"mac": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"provo": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
}
}
}
}
@@ -6,9 +6,6 @@
"DefaultPreset": {
"UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}",
"Name": "Skybox",
"FileMasks": [
"_skyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -24,9 +21,6 @@
"android": {
"UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}",
"Name": "Skybox",
"FileMasks": [
"_skyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -41,9 +35,6 @@
"ios": {
"UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}",
"Name": "Skybox",
"FileMasks": [
"_skyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -58,9 +49,6 @@
"mac": {
"UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}",
"Name": "Skybox",
"FileMasks": [
"_skyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -75,9 +63,6 @@
"provo": {
"UUID": "{F359CD3B-37E6-4627-B4F6-2DFC2C0E3C1C}",
"Name": "Skybox",
"FileMasks": [
"_skyboxcm"
],
"SourceColor": "Linear",
"DestColor": "Linear",
"SuppressEngineReduce": true,
@@ -9,8 +9,7 @@
"SuppressEngineReduce": true,
"PixelFormat": "R8G8B8A8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [ "_ui" ]
"DestColor": "Linear"
},
"PlatformsPresets": {
"android": {
@@ -9,8 +9,7 @@
"SuppressEngineReduce": true,
"PixelFormat": "R8G8B8A8",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [ "_ui" ]
"DestColor": "Linear"
},
"PlatformsPresets": {
"android": {
@@ -8,6 +8,7 @@
#include "BuilderSettingManager.h"
#include <QCoreApplication>
#include <QDirIterator>
#include <QFile>
#include <QFileInfo>
@@ -17,8 +18,9 @@
#include <BuilderSettings/CubemapSettings.h>
#include <BuilderSettings/TextureSettings.h>
#include <Converters/Cubemap.h>
#include <Processing/PixelFormatInfo.h>
#include <Processing/ImageToProcess.h>
#include <Processing/PixelFormatInfo.h>
#include <Processing/Utils.h>
#include <ImageLoader/ImageLoaders.h>
#include <ImageProcessing_Traits_Platform.h>
@@ -41,13 +43,18 @@
namespace ImageProcessingAtom
{
const char* BuilderSettingManager::s_defaultConfigRelativeFolder = "Gems/Atom/Asset/ImageProcessingAtom/Config/";
const char* BuilderSettingManager::s_defaultConfigRelativeFolder = "Gems/Atom/Asset/ImageProcessingAtom/Assets/Config/";
const char* BuilderSettingManager::s_projectConfigRelativeFolder = "Config/AtomImageBuilder/";
const char* BuilderSettingManager::s_builderSettingFileName = "ImageBuilder.settings";
const char* BuilderSettingManager::s_presetFileExtension = ".preset";
const char* BuilderSettingManager::s_presetFileExtension = "preset";
const char FileMaskDelimiter = '_';
namespace
{
static constexpr const char* const LogWindow = "Image Processing";
}
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
#define AZ_RESTRICTED_PLATFORM_EXPANSION(CodeName, CODENAME, codename, PrivateName, PRIVATENAME, privatename, PublicName, PUBLICNAME, publicname, PublicAuxName1, PublicAuxName2, PublicAuxName3) \
namespace ImageProcess##PrivateName \
@@ -69,13 +76,15 @@ namespace ImageProcessingAtom
if (serialize)
{
serialize->Class<BuilderSettingManager>()
->Version(1)
->Field("AnalysisFingerprint", &BuilderSettingManager::m_analysisFingerprint)
->Version(2)
->Field("BuildSettings", &BuilderSettingManager::m_builderSettings)
->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
->Field("PresetsByFileMask", &BuilderSettingManager::m_presetFilterMap)
->Field("DefaultPreset", &BuilderSettingManager::m_defaultPreset)
->Field("DefaultPresetAlpha", &BuilderSettingManager::m_defaultPresetAlpha)
->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT);
->Field("DefaultPresetNonePOT", &BuilderSettingManager::m_defaultPresetNonePOT)
// deprecated properties
->Field("DefaultPresetsByFileMask", &BuilderSettingManager::m_defaultPresetByFileMask)
->Field("AnalysisFingerprint", &BuilderSettingManager::m_analysisFingerprint);
}
}
@@ -122,7 +131,7 @@ namespace ImageProcessingAtom
s_globalInstance.Reset();
}
const PresetSettings* BuilderSettingManager::GetPreset(const PresetName& presetName, const PlatformName& platform, AZStd::string_view* settingsFilePathOut)
const PresetSettings* BuilderSettingManager::GetPreset(const PresetName& presetName, const PlatformName& platform, AZStd::string_view* settingsFilePathOut) const
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
auto itr = m_presets.find(presetName);
@@ -137,16 +146,17 @@ namespace ImageProcessingAtom
return nullptr;
}
const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform)
const BuilderSettings* BuilderSettingManager::GetBuilderSetting(const PlatformName& platform) const
{
if (m_builderSettings.find(platform) != m_builderSettings.end())
auto itr = m_builderSettings.find(platform);
if (itr != m_builderSettings.end())
{
return &m_builderSettings[platform];
return &itr->second;
}
return nullptr;
}
const PlatformNameList BuilderSettingManager::GetPlatformList()
const PlatformNameList BuilderSettingManager::GetPlatformList() const
{
PlatformNameList platforms;
@@ -161,7 +171,7 @@ namespace ImageProcessingAtom
return platforms;
}
const AZStd::map <FileMask, AZStd::unordered_set<PresetName>>& BuilderSettingManager::GetPresetFilterMap()
const AZStd::map <FileMask, AZStd::unordered_set<PresetName>>& BuilderSettingManager::GetPresetFilterMap() const
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
return m_presetFilterMap;
@@ -188,7 +198,6 @@ namespace ImageProcessingAtom
m_presetFilterMap.clear();
m_builderSettings.clear();
m_presets.clear();
m_defaultPresetByFileMask.clear();
}
StringOutcome BuilderSettingManager::LoadConfig()
@@ -198,44 +207,53 @@ namespace ImageProcessingAtom
auto fileIoBase = AZ::IO::FileIOBase::GetInstance();
if (fileIoBase == nullptr)
{
return AZ::Failure(AZStd::string("File IO instance needs to be initialized to resolve ImageProcessing builder file aliases"));
return AZ::Failure(
AZStd::string("File IO instance needs to be initialized to resolve ImageProcessing builder file aliases"));
}
// Construct the default setting path
AZ::IO::FixedMaxPath defaultConfigFolder;
if (auto engineRoot = fileIoBase->ResolvePath("@engroot@"); engineRoot.has_value())
{
defaultConfigFolder = *engineRoot;
defaultConfigFolder /= s_defaultConfigRelativeFolder;
m_defaultConfigFolder = *engineRoot;
m_defaultConfigFolder /= s_defaultConfigRelativeFolder;
}
AZ::IO::FixedMaxPath projectConfigFolder;
if (auto sourceGameRoot = fileIoBase->ResolvePath("@projectroot@"); sourceGameRoot.has_value())
{
projectConfigFolder = *sourceGameRoot;
projectConfigFolder /= s_projectConfigRelativeFolder;
m_projectConfigFolder = *sourceGameRoot;
m_projectConfigFolder /= s_projectConfigRelativeFolder;
}
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
ClearSettings();
outcome = LoadSettings((projectConfigFolder / s_builderSettingFileName).Native());
if (!outcome.IsSuccess())
{
outcome = LoadSettings((defaultConfigFolder / s_builderSettingFileName).Native());
}
outcome = LoadSettings();
if (outcome.IsSuccess())
{
// Load presets in default folder first, then load from project folder.
// The same presets which loaded last will overwrite previous loaded one.
LoadPresets(defaultConfigFolder.Native());
LoadPresets(projectConfigFolder.Native());
LoadPresets(m_defaultConfigFolder.Native());
LoadPresets(m_projectConfigFolder.Native());
}
// Regenerate file mask mapping after all presets loaded
RegenerateMappings();
// Collect extra file masks from preset files
CollectFileMasksFromPresets();
if (QCoreApplication::instance())
{
m_fileWatcher.reset(new QFileSystemWatcher);
// track preset files
// Note, the QT signal would only works for AP but not AssetBuilder
// We use file time stamp to track preset file change in builder's CreateJob
for (auto& preset : m_presets)
{
m_fileWatcher.data()->addPath(QString(preset.second.m_presetFilePath.c_str()));
}
m_fileWatcher.data()->addPath(QString(m_defaultConfigFolder.c_str()));
m_fileWatcher.data()->addPath(QString(m_projectConfigFolder.c_str()));
QObject::connect(m_fileWatcher.data(), &QFileSystemWatcher::fileChanged, this, &BuilderSettingManager::OnFileChanged);
QObject::connect(m_fileWatcher.data(), &QFileSystemWatcher::directoryChanged, this, &BuilderSettingManager::OnFolderChanged);
}
return outcome;
@@ -243,36 +261,84 @@ namespace ImageProcessingAtom
void BuilderSettingManager::LoadPresets(AZStd::string_view presetFolder)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
QDirIterator it(presetFolder.data(), QStringList() << "*.preset", QDir::Files, QDirIterator::NoIteratorFlags);
while (it.hasNext())
{
QString filePath = it.next();
QFileInfo fileInfo = it.fileInfo();
LoadPreset(filePath.toUtf8().data());
}
}
MultiplatformPresetSettings preset;
auto result = AZ::JsonSerializationUtils::LoadObjectFromFile(preset, filePath.toUtf8().data());
if (!result.IsSuccess())
bool BuilderSettingManager::LoadPreset(const AZStd::string& filePath)
{
QFileInfo fileInfo (filePath.c_str());
if (!fileInfo.exists())
{
return false;
}
MultiplatformPresetSettings preset;
auto result = AZ::JsonSerializationUtils::LoadObjectFromFile(preset, filePath);
if (!result.IsSuccess())
{
AZ_Warning(LogWindow, false, "Failed to load preset file %s. Error: %s",
filePath.c_str(), result.GetError().c_str());
return false;
}
PresetName presetName(fileInfo.baseName().toUtf8().data());
AZ_Warning(LogWindow, presetName == preset.GetPresetName(), "Preset file name '%s' is not"
" same as preset name '%s'. Using preset file name as preset name",
filePath.c_str(), preset.GetPresetName().GetCStr());
preset.SetPresetName(presetName);
m_presets[presetName] = PresetEntry{preset, filePath.c_str(), fileInfo.lastModified()};
return true;
}
void BuilderSettingManager::ReloadPreset(const PresetName& presetName)
{
// Find the preset file from project or default config folder
AZStd::string presetFileName = AZStd::string::format("%s.%s", presetName.GetCStr(), s_presetFileExtension);
AZ::IO::FixedMaxPath filePath = m_projectConfigFolder/presetFileName;
QFileInfo fileInfo (filePath.c_str());
if (!fileInfo.exists())
{
filePath = (m_defaultConfigFolder/presetFileName).c_str();
fileInfo = QFileInfo(filePath.c_str());
}
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
//Skip the loading if the file wasn't chagned
if (fileInfo.exists())
{
if (m_presets.find(presetName) != m_presets.end())
{
AZ_Warning("Image Processing", false, "Failed to load preset file %s. Error: %s",
filePath.toUtf8().data(), result.GetError().c_str());
if (m_presets[presetName].m_lastModifiedTime == fileInfo.lastModified()
&& m_presets[presetName].m_presetFilePath == filePath.c_str())
{
return;
}
}
}
PresetName presetName(fileInfo.baseName().toUtf8().data());
// remove preset
m_presets.erase(presetName);
AZ_Warning("Image Processing", presetName == preset.GetPresetName(), "Preset file name '%s' is not"
" same as preset name '%s'. Using preset file name as preset name",
filePath.toUtf8().data(), preset.GetPresetName().GetCStr());
preset.SetPresetName(presetName);
m_presets[presetName] = PresetEntry{preset, filePath.toUtf8().data()};
if (fileInfo.exists())
{
LoadPreset(filePath.c_str());
}
}
StringOutcome BuilderSettingManager::LoadConfigFromFolder(AZStd::string_view configFolder)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
// Load builder settings
AZStd::string settingFilePath = AZStd::string::format("%.*s%s", aznumeric_cast<int>(configFolder.size()),
configFolder.data(), s_builderSettingFileName);
@@ -282,12 +348,108 @@ namespace ImageProcessingAtom
if (result.IsSuccess())
{
LoadPresets(configFolder);
RegenerateMappings();
}
return result;
}
void BuilderSettingManager::ReportDeprecatedSettings()
{
// reported deprecated attributes in image builder settings
if (!m_analysisFingerprint.empty())
{
AZ_Warning(LogWindow, false, "'AnalysisFingerprint' is deprecated and it should be removed from file [%s]", s_builderSettingFileName);
}
if (!m_defaultPresetByFileMask.empty())
{
AZ_Warning(LogWindow, false, "'DefaultPresetsByFileMask' is deprecated and it should be removed from file [%s]. Use PresetsByFileMask instead", s_builderSettingFileName);
}
}
StringOutcome BuilderSettingManager::LoadSettings()
{
// If the project image build setting file exist, it will merge image builder settings from project folder to the settings from default config folder.
bool needMerge = false;
AZStd::string projectSettingFile{ (m_projectConfigFolder / s_builderSettingFileName).Native() };
if (AZ::IO::SystemFile::Exists(projectSettingFile.c_str()))
{
needMerge = true;
}
AZ::Outcome<void, AZStd::string> outcome;
AZStd::string defaultSettingFile{ (m_defaultConfigFolder / s_builderSettingFileName).Native() };
if (needMerge)
{
auto outcome1 = AZ::JsonSerializationUtils::ReadJsonFile(defaultSettingFile);
auto outcome2 = AZ::JsonSerializationUtils::ReadJsonFile(projectSettingFile);
// return error if it failed to load default settings
if (!outcome1.IsSuccess())
{
return STRING_OUTCOME_ERROR(outcome1.GetError());
}
// if project config was loaded successfully, apply merge patch
rapidjson::Document& originDoc = outcome1.GetValue();
if (outcome2.IsSuccess())
{
const rapidjson::Document& patchDoc = outcome2.GetValue();
AZ::JsonSerializationResult::ResultCode result =
AZ::JsonSerialization::ApplyPatch(originDoc, originDoc.GetAllocator(), patchDoc, AZ::JsonMergeApproach::JsonMergePatch);
if (result.GetProcessing() == AZ::JsonSerializationResult::Processing::Completed)
{
AZStd::vector<char> outBuffer;
AZ::IO::ByteContainerStream<AZStd::vector<char>> outStream{ &outBuffer };
AZ::JsonSerializationUtils::WriteJsonStream(originDoc, outStream);
outStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
outcome = AZ::JsonSerializationUtils::LoadObjectFromStream(*this, outStream);
if (!outcome.IsSuccess())
{
return STRING_OUTCOME_ERROR(outcome.GetError());
}
ReportDeprecatedSettings();
// Generate config file fingerprint
outStream.Seek(0, AZ::IO::GenericStream::ST_SEEK_BEGIN);
AZ::u64 hash = AssetBuilderSDK::GetHashFromIOStream(outStream);
m_analysisFingerprint = AZStd::string::format("%llX", hash);
}
else
{
needMerge = false;
AZ_Warning(LogWindow, false, "Failed to fully merge data into image builder settings. Skipping project build setting file [%s]", projectSettingFile.c_str());
}
}
else
{
AZ_Warning(LogWindow, false, "Failed to load project setting file [%s]. Skipping", projectSettingFile.c_str());
}
}
if (!needMerge)
{
outcome = AZ::JsonSerializationUtils::LoadObjectFromFile(*this, defaultSettingFile);
if (!outcome.IsSuccess())
{
return STRING_OUTCOME_ERROR(outcome.GetError());
}
ReportDeprecatedSettings();
// Generate config file fingerprint
AZ::u64 hash = AssetBuilderSDK::GetFileHash(defaultSettingFile.c_str());
m_analysisFingerprint = AZStd::string::format("%llX", hash);
}
return STRING_OUTCOME_SUCCESS;
}
StringOutcome BuilderSettingManager::LoadSettings(AZStd::string_view filepath)
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
@@ -336,13 +498,13 @@ namespace ImageProcessingAtom
return m_analysisFingerprint;
}
void BuilderSettingManager::RegenerateMappings()
void BuilderSettingManager::CollectFileMasksFromPresets()
{
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
AZStd::string noFilter = AZStd::string();
m_presetFilterMap.clear();
AZStd::string extraString;
for (const auto& presetIter : m_presets)
{
@@ -357,22 +519,31 @@ namespace ImageProcessingAtom
{
if (filemask.empty() || filemask[0] != FileMaskDelimiter)
{
AZ_Warning("Image Processing", false, "File mask '%s' is invalid. It must start with '%c'.", filemask.c_str(), FileMaskDelimiter);
AZ_Warning(LogWindow, false, "File mask '%s' is invalid. It must start with '%c'.", filemask.c_str(), FileMaskDelimiter);
continue;
}
else if (filemask.size() < 2)
{
AZ_Warning("Image Processing", false, "File mask '%s' is invalid. The '%c' must be followed by at least one other character.", filemask.c_str());
AZ_Warning(LogWindow, false, "File mask '%s' is invalid. The '%c' must be followed by at least one other character.", filemask.c_str());
continue;
}
else if (filemask.find(FileMaskDelimiter, 1) != AZStd::string::npos)
{
AZ_Warning("Image Processing", false, "File mask '%s' is invalid. It must contain only a single '%c' character.", filemask.c_str(), FileMaskDelimiter);
AZ_Warning(LogWindow, false, "File mask '%s' is invalid. It must contain only a single '%c' character.", filemask.c_str(), FileMaskDelimiter);
continue;
}
extraString += (filemask + preset.m_name.GetCStr());
m_presetFilterMap[filemask].insert(preset.m_name);
}
}
if (!extraString.empty())
{
AZ::u64 hash = AZStd::hash<AZStd::string>{}(extraString);
m_analysisFingerprint += AZStd::string::format("%llX", hash);
}
}
void BuilderSettingManager::MetafilePathFromImagePath(AZStd::string_view imagePath, AZStd::string& metafilePath)
@@ -419,38 +590,15 @@ namespace ImageProcessingAtom
return m_presets.find(presetName) != m_presets.end();
}
PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr imageFromFile)
PresetName BuilderSettingManager::GetSuggestedPreset(AZStd::string_view imageFilePath) const
{
PresetName emptyPreset;
//load the image to get its size for later use
IImageObjectPtr image = imageFromFile;
//if the input image is empty we will try to load it from the path
if (imageFromFile == nullptr)
{
image = IImageObjectPtr(LoadImageFromFile(imageFilePath));
}
if (image == nullptr)
{
return emptyPreset;
}
//get file mask of this image file
AZStd::string fileMask = GetFileMask(imageFilePath);
PresetName outPreset = emptyPreset;
//check default presets for some file masks
if (m_defaultPresetByFileMask.find(fileMask) != m_defaultPresetByFileMask.end())
{
outPreset = m_defaultPresetByFileMask[fileMask];
if (!IsValidPreset(outPreset))
{
outPreset = emptyPreset;
}
}
//use the preset filter map to find
if (outPreset.IsEmpty() && !fileMask.empty())
{
@@ -461,54 +609,21 @@ namespace ImageProcessingAtom
}
}
const PresetSettings* presetInfo = nullptr;
if (!outPreset.IsEmpty())
{
presetInfo = GetPreset(outPreset);
//special case for cubemap
if (presetInfo && presetInfo->m_cubemapSetting)
{
// If it's not a latitude-longitude map or it doesn't match any cubemap layouts then reset its preset
if (!IsValidLatLongMap(image) && CubemapLayout::GetCubemapLayoutInfo(image) == nullptr)
{
outPreset = emptyPreset;
}
}
}
if (outPreset == emptyPreset)
{
if (image->GetAlphaContent() == EAlphaContent::eAlphaContent_Absent)
{
outPreset = m_defaultPreset;
}
else
{
outPreset = m_defaultPresetAlpha;
}
outPreset = m_defaultPreset;
}
//get the pixel format for selected preset
presetInfo = GetPreset(outPreset);
return outPreset;
}
if (presetInfo)
{
//valid whether image size work with pixel format
if (CPixelFormats::GetInstance().IsImageSizeValid(presetInfo->m_pixelFormat,
image->GetWidth(0), image->GetHeight(0), false))
{
return outPreset;
}
else
{
AZ_Warning("Image Processing", false, "Image dimensions are not compatible with preset '%s'. The default preset will be used.", presetInfo->m_name.GetCStr());
}
}
//uncompressed one which could be used for almost everything
return m_defaultPresetNonePOT;
AZStd::vector<AZStd::string> BuilderSettingManager::GetPossiblePresetPaths(const PresetName& presetName) const
{
AZStd::vector<AZStd::string> paths;
AZStd::string presetFile = AZStd::string::format("%s.preset", presetName.GetCStr());
paths.push_back((m_defaultConfigFolder / presetFile).c_str());
paths.push_back((m_projectConfigFolder / presetFile).c_str());
return paths;
}
bool BuilderSettingManager::DoesSupportPlatform(AZStd::string_view platformId)
@@ -526,18 +641,50 @@ namespace ImageProcessingAtom
AZStd::string filePath;
if (!AzFramework::StringFunc::Path::Join(outputFolder.data(), fileName.c_str(), filePath))
{
AZ_Warning("Image Processing", false, "Failed to construct path with folder '%.*s' and file: '%s' to save preset",
AZ_Warning(LogWindow, false, "Failed to construct path with folder '%.*s' and file: '%s' to save preset",
aznumeric_cast<int>(outputFolder.size()), outputFolder.data(), filePath.c_str());
continue;
}
auto result = AZ::JsonSerializationUtils::SaveObjectToFile(&presetEntry.m_multiPreset, filePath);
if (!result.IsSuccess())
{
AZ_Warning("Image Processing", false, "Failed to save preset '%s' to file '%s'. Error: %s",
AZ_Warning(LogWindow, false, "Failed to save preset '%s' to file '%s'. Error: %s",
presetEntry.m_multiPreset.GetDefaultPreset().m_name.GetCStr(), filePath.c_str(), result.GetError().c_str());
}
}
}
void BuilderSettingManager::OnFileChanged(const QString &path)
{
// handles preset file change
// Note: this signal only works with AP but not AssetBuilder
AZ_TracePrintf(LogWindow, "File changed %s\n", path.toUtf8().data());
QFileInfo info(path);
// skip if the file is not a preset file
// Note: for .settings file change it's handled when restart AP.
if (info.suffix() != s_presetFileExtension)
{
return;
}
ReloadPreset(PresetName(info.baseName().toUtf8().data()));
}
void BuilderSettingManager::OnFolderChanged([[maybe_unused]] const QString &path)
{
// handles new file added or removed
// Note: this signal only works with AP but not AssetBuilder
AZ_TracePrintf(LogWindow, "folder changed %s\n", path.toUtf8().data());
AZStd::lock_guard<AZStd::recursive_mutex> lock(m_presetMapLock);
m_presets.clear();
LoadPresets(m_defaultConfigFolder.Native());
LoadPresets(m_projectConfigFolder.Native());
for (auto& preset : m_presets)
{
m_fileWatcher.data()->addPath(QString(preset.second.m_presetFilePath.c_str()));
}
}
} // namespace ImageProcessingAtom
@@ -10,10 +10,15 @@
#include <BuilderSettings/ImageProcessingDefines.h>
#include <BuilderSettings/BuilderSettings.h>
#include <AzCore/std/containers/set.h>
#include <AzCore/base.h>
#include <AzCore/IO/Path/Path.h>
#include <AzCore/std/containers/set.h>
#include <Atom/ImageProcessing/ImageObject.h>
#include <QDateTime>
#include <QFileSystemWatcher>
#include <QScopedPointer>
class QSettings;
class QString;
@@ -36,6 +41,7 @@ namespace ImageProcessingAtom
* Each preset setting may have different values on different platform, but they are using same uuid.
*/
class BuilderSettingManager
: public QObject // required for using QFileSystemWatcher
{
friend class ImageProcessingTest;
@@ -49,17 +55,17 @@ namespace ImageProcessingAtom
static void DestroyInstance();
static void Reflect(AZ::ReflectContext* context);
const PresetSettings* GetPreset(const PresetName& presetName, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr);
const PresetSettings* GetPreset(const PresetName& presetName, const PlatformName& platform = "", AZStd::string_view* settingsFilePathOut = nullptr) const;
const BuilderSettings* GetBuilderSetting(const PlatformName& platform);
const BuilderSettings* GetBuilderSetting(const PlatformName& platform) const;
//! Return A list of platform supported
const PlatformNameList GetPlatformList();
const PlatformNameList GetPlatformList() const;
//! Return A map of preset settings based on their filemasks.
//! @key filemask string, empty string means no filemask
//! @value set of preset setting names supporting the specified filemask
const AZStd::map<FileMask, AZStd::unordered_set<PresetName>>& GetPresetFilterMap();
const AZStd::map<FileMask, AZStd::unordered_set<PresetName>>& GetPresetFilterMap() const;
//! Find preset name based on the preset id.
const PresetName GetPresetNameFromId(const AZ::Uuid& presetId);
@@ -68,7 +74,11 @@ namespace ImageProcessingAtom
StringOutcome LoadConfig();
//! Load configurations files from a folder which includes builder settings and presets
StringOutcome LoadConfigFromFolder(AZStd::string_view configFolder);
//! Note: this is only used for unit test. Use LoadConfig() for editor or game launcher
StringOutcome LoadConfigFromFolder(AZStd::string_view configFolder);
//! Reload preset from config folders
void ReloadPreset(const PresetName& presetName);
const AZStd::string& GetAnalysisFingerprint() const;
@@ -81,7 +91,12 @@ namespace ImageProcessingAtom
//! @param imageFilePath: Filepath string of the image file. The function may load the image from the path for better detection
//! @param image: an optional image object which can be used for preset selection if there is no match based file mask.
//! @return suggested preset name.
PresetName GetSuggestedPreset(AZStd::string_view imageFilePath, IImageObjectPtr image = nullptr);
PresetName GetSuggestedPreset(AZStd::string_view imageFilePath) const;
//! Get the possible preset config's full file paths
//! This function is only used for setting up image's source dependency if a preset file is missing
//! Otherwise, the preset's file path can be retrieved in GetPreset() function
AZStd::vector<AZStd::string> GetPossiblePresetPaths(const PresetName& presetName) const;
bool IsValidPreset(PresetName presetName) const;
@@ -105,25 +120,41 @@ namespace ImageProcessingAtom
private: // functions
AZ_DISABLE_COPY_MOVE(BuilderSettingManager);
// Write image builder setting to the file specified by filepath
StringOutcome WriteSettings(AZStd::string_view filepath);
// Load image builder settings from the file specified by filepath
StringOutcome LoadSettings(AZStd::string_view filepath);
// Load merge image builder settings (project and default)
StringOutcome LoadSettings();
// report warnings for the deprecated properties in image builder setting data
void ReportDeprecatedSettings();
// Clear Builder Settings and any cached maps/lists
void ClearSettings();
// Regenerate Builder Settings and any cached maps/lists
void RegenerateMappings();
// collect file masks
void CollectFileMasksFromPresets();
// Functions to save/load preset from a folder
void SavePresets(AZStd::string_view outputFolder);
void LoadPresets(AZStd::string_view presetFolder);
// Load a preset to m_presets and return true if success
bool LoadPreset(const AZStd::string& filePath);
// handle preset files changes
void OnFileChanged(const QString &path);
void OnFolderChanged(const QString &path);
private: // variables
struct PresetEntry
{
MultiplatformPresetSettings m_multiPreset;
AZStd::string m_presetFilePath; // Can be used for debug output
QDateTime m_lastModifiedTime;
};
// Builder settings for each platform
@@ -131,13 +162,13 @@ namespace ImageProcessingAtom
AZStd::unordered_map<PresetName, PresetEntry> m_presets;
// Cached list of presets mapped by their file masks.
// a list of presets mapped by their file masks.
// @Key file mask, use empty string to indicate all presets without filtering
// @Value set of preset names that matches the file mask
AZStd::map <FileMask, AZStd::unordered_set<PresetName>> m_presetFilterMap;
// A mutex to protect when modifying any map in this manager
AZStd::recursive_mutex m_presetMapLock;
// A mutex to protect when modifying any map in this manager
mutable AZStd::recursive_mutex m_presetMapLock;
// Default presets for certain file masks
AZStd::map <FileMask, PresetName > m_defaultPresetByFileMask;
@@ -153,5 +184,14 @@ namespace ImageProcessingAtom
// Image builder's version
AZStd::string m_analysisFingerprint;
// default config folder
AZ::IO::FixedMaxPath m_defaultConfigFolder;
// project config folder
AZ::IO::FixedMaxPath m_projectConfigFolder;
// File system watcher to detect preset file changes
QScopedPointer<QFileSystemWatcher> m_fileWatcher;
};
} // namespace ImageProcessingAtom
@@ -171,7 +171,7 @@ namespace ImageProcessingAtomEditor
if (!preset)
{
AZ_Warning("Texture Editor", false, "Cannot find preset %s! Will assign a suggested one for the texture.", presetName.GetCStr());
presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath, m_img);
presetName = BuilderSettingManager::Instance()->GetSuggestedPreset(m_fullPath);
for (auto& settingIter : m_settingsMap)
{
@@ -221,6 +221,58 @@ namespace ImageProcessingAtom
m_isShuttingDown = true;
}
PresetName GetImagePreset(const AZStd::string& filepath)
{
// first let preset from asset info
TextureSettings textureSettings;
StringOutcome output = TextureSettings::LoadTextureSetting(filepath, textureSettings);
if (!textureSettings.m_preset.IsEmpty())
{
return textureSettings.m_preset;
}
return BuilderSettingManager::Instance()->GetSuggestedPreset(filepath);
}
void HandlePresetDependency(PresetName presetName, AZStd::vector<AssetBuilderSDK::SourceFileDependency>& sourceDependencyList)
{
// Reload preset if it was changed
ImageProcessingAtom::BuilderSettingManager::Instance()->ReloadPreset(presetName);
AZStd::string_view filePath;
auto presetSettings = BuilderSettingManager::Instance()->GetPreset(presetName, /*default platform*/"", &filePath);
AssetBuilderSDK::SourceFileDependency sourceFileDependency;
sourceFileDependency.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Absolute;
// Need to watch any possibe preset paths
AZStd::vector<AZStd::string> possiblePresetPaths = BuilderSettingManager::Instance()->GetPossiblePresetPaths(presetName);
for (const auto& path:possiblePresetPaths)
{
sourceFileDependency.m_sourceFileDependencyPath = path;
sourceDependencyList.push_back(sourceFileDependency);
}
if (presetSettings)
{
// handle special case here
// Cubemap setting may reference some other presets
if (presetSettings->m_cubemapSetting)
{
if (presetSettings->m_cubemapSetting->m_generateIBLDiffuse && !presetSettings->m_cubemapSetting->m_iblDiffusePreset.IsEmpty())
{
HandlePresetDependency(presetSettings->m_cubemapSetting->m_iblDiffusePreset, sourceDependencyList);
}
if (presetSettings->m_cubemapSetting->m_generateIBLSpecular && !presetSettings->m_cubemapSetting->m_iblSpecularPreset.IsEmpty())
{
HandlePresetDependency(presetSettings->m_cubemapSetting->m_iblSpecularPreset, sourceDependencyList);
}
}
}
}
// this happens early on in the file scanning pass
// this function should consistently always create the same jobs, and should do no checking whether the job is up to date or not - just be consistent.
void ImageBuilderWorker::CreateJobs(const AssetBuilderSDK::CreateJobsRequest& request, AssetBuilderSDK::CreateJobsResponse& response)
@@ -242,13 +294,26 @@ namespace ImageProcessingAtom
if (ImageProcessingAtom::BuilderSettingManager::Instance()->DoesSupportPlatform(platformInfo.m_identifier))
{
AssetBuilderSDK::JobDescriptor descriptor;
descriptor.m_jobKey = ext + " Atom Compile";
descriptor.m_jobKey = "Image Compile: " + ext;
descriptor.SetPlatformIdentifier(platformInfo.m_identifier.c_str());
descriptor.m_critical = false;
descriptor.m_additionalFingerprintInfo = "";
response.m_createJobOutputs.push_back(descriptor);
}
}
// add source dependency for .assetinfo file
AssetBuilderSDK::SourceFileDependency sourceFileDependency;
sourceFileDependency.m_sourceDependencyType = AssetBuilderSDK::SourceFileDependency::SourceFileDependencyType::Absolute;
sourceFileDependency.m_sourceFileDependencyPath = request.m_sourceFile;
AZ::StringFunc::Path::ReplaceExtension(sourceFileDependency.m_sourceFileDependencyPath, TextureSettings::ExtensionName);
response.m_sourceFileDependencyList.push_back(sourceFileDependency);
// add source dependencies for .preset files
// Get the preset for this file
auto presetName = GetImagePreset(request.m_sourceFile);
HandlePresetDependency(presetName, response.m_sourceFileDependencyList);
response.m_result = AssetBuilderSDK::CreateJobsResultCode::Success;
return;
}
@@ -11,6 +11,7 @@
#include <Processing/ImageConvert.h>
#include <Processing/ImageAssetProducer.h>
#include <Processing/ImageFlags.h>
#include <Processing/Utils.h>
#include <Converters/FIR-Weights.h>
#include <Converters/Cubemap.h>
#include <Converters/PixelOperation.h>
@@ -229,12 +230,24 @@ namespace ImageProcessingAtom
AZStd::unique_ptr<CubemapSettings>& cubemapSettings = m_input->m_presetSetting.m_cubemapSetting;
if (cubemapSettings->m_generateIBLSpecular && !cubemapSettings->m_iblSpecularPreset.IsEmpty())
{
CreateIBLCubemap(cubemapSettings->m_iblSpecularPreset, SpecularCubemapSuffix, m_iblSpecularCubemapImage);
bool success = CreateIBLCubemap(cubemapSettings->m_iblSpecularPreset, SpecularCubemapSuffix, m_iblSpecularCubemapImage);
if (!success)
{
m_isSucceed = false;
m_isFinished = true;
break;
}
}
if (cubemapSettings->m_generateIBLDiffuse && !cubemapSettings->m_iblDiffusePreset.IsEmpty())
{
CreateIBLCubemap(cubemapSettings->m_iblDiffusePreset, DiffuseCubemapSuffix, m_iblDiffuseCubemapImage);
bool success = CreateIBLCubemap(cubemapSettings->m_iblDiffusePreset, DiffuseCubemapSuffix, m_iblDiffuseCubemapImage);
if (!success)
{
m_isSucceed = false;
m_isFinished = true;
break;
}
}
}
@@ -251,7 +264,12 @@ namespace ImageProcessingAtom
{
if (m_input->m_presetSetting.m_cubemapSetting->m_requiresConvolve)
{
FillCubemapMipmaps();
bool success = FillCubemapMipmaps();
if (!success)
{
m_isSucceed = false;
m_isFinished = true;
}
}
}
else
@@ -268,9 +286,7 @@ namespace ImageProcessingAtom
// get gloss from normal for all mipmaps and save to alpha channel
if (m_input->m_presetSetting.m_glossFromNormals)
{
bool hasAlpha = (m_alphaContent == EAlphaContent::eAlphaContent_OnlyBlack
|| m_alphaContent == EAlphaContent::eAlphaContent_OnlyBlackAndWhite
|| m_alphaContent == EAlphaContent::eAlphaContent_Greyscale);
bool hasAlpha = Utils::NeedAlphaChannel(m_alphaContent);
m_image->Get()->GlossFromNormals(hasAlpha);
// set alpha content so it won't be ignored later.
@@ -347,7 +363,11 @@ namespace ImageProcessingAtom
}
else
{
AZ_TracePrintf("Image Processing", "Image converted with preset [%s] [%s] and saved to [%s] (%d bytes) taking %f seconds\n",
[[maybe_unused]] const PixelFormatInfo* formatInfo = CPixelFormats::GetInstance().GetPixelFormatInfo(m_image->Get()->GetPixelFormat());
AZ_TracePrintf("Image Processing", "Image [%dx%d] [%s] converted with preset [%s] [%s] and saved to [%s] (%d bytes) taking %f seconds\n",
m_image->Get()->GetWidth(0), m_image->Get()->GetHeight(0),
formatInfo->szName,
m_input->m_presetSetting.m_name.GetCStr(),
m_input->m_filePath.c_str(),
m_input->m_outputFolder.c_str(), sizeTotal, m_processTime);
@@ -421,6 +441,17 @@ namespace ImageProcessingAtom
outHeight >>= 1;
outReduce++;
}
// resize to min texture size if it's smaller
if (outWidth < presetSettings->m_minTextureSize)
{
outWidth = presetSettings->m_minTextureSize;
}
if (outHeight < presetSettings->m_minTextureSize)
{
outHeight = presetSettings->m_minTextureSize;
}
}
bool ImageConvertProcess::ConvertToLinear()
@@ -647,7 +678,7 @@ namespace ImageProcessingAtom
}
else if (!CPixelFormats::GetInstance().IsImageSizeValid(dstFmt, dwWidth, dwHeight, false))
{
AZ_Warning("Image Processing", false, "Image size will be scaled for pixel format %s", CPixelFormats::GetInstance().GetPixelFormatInfo(dstFmt)->szName);
AZ_TracePrintf("Image processing", "Image size will be scaled for pixel format %s\n", CPixelFormats::GetInstance().GetPixelFormatInfo(dstFmt)->szName);
}
#if defined(AZ_TOOLS_EXPAND_FOR_RESTRICTED_PLATFORMS)
@@ -758,7 +789,7 @@ namespace ImageProcessingAtom
// in very rare user case, an old texture setting file may not have a preset. We fix it over here too.
if (textureSettings.m_preset.IsEmpty())
{
textureSettings.m_preset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilePath, srcImage);
textureSettings.m_preset = BuilderSettingManager::Instance()->GetSuggestedPreset(imageFilePath);
}
// Get preset
@@ -795,7 +826,7 @@ namespace ImageProcessingAtom
return process;
}
void ImageConvertProcess::CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage)
bool ImageConvertProcess::CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage)
{
const AZStd::string& platformId = m_input->m_platform;
AZStd::string_view filePath;
@@ -803,7 +834,7 @@ namespace ImageProcessingAtom
if (presetSettings == nullptr)
{
AZ_Error("Image Processing", false, "Couldn't find preset for IBL cubemap generation");
return;
return false;
}
// generate export file name
@@ -838,14 +869,14 @@ namespace ImageProcessingAtom
if (!imageConvertProcess)
{
AZ_Error("Image Processing", false, "Failed to create image convert process for the IBL cubemap");
return;
return false;
}
imageConvertProcess->ProcessAll();
if (!imageConvertProcess->IsSucceed())
{
AZ_Error("Image Processing", false, "Image convert process for the IBL cubemap failed");
return;
return false;
}
// append the output products to the job's product list
@@ -853,6 +884,7 @@ namespace ImageProcessingAtom
// store the output cubemap so it can be accessed by unit tests
cubemapImage = imageConvertProcess->m_image->Get();
return true;
}
bool ConvertImageFile(const AZStd::string& imageFilePath, const AZStd::string& exportDir,
@@ -160,7 +160,7 @@ namespace ImageProcessingAtom
bool FillCubemapMipmaps();
//IBL cubemap generation, this creates a separate ImageConvertProcess
void CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage);
bool CreateIBLCubemap(PresetName preset, const char* fileNameSuffix, IImageObjectPtr& cubemapImage);
//convert color space to linear with pixel format rgba32f
bool ConvertToLinear();
@@ -183,10 +183,9 @@ namespace ImageProcessingAtom
return EAlphaContent::eAlphaContent_Absent;
}
//if it's compressed format, return indeterminate. if user really want to know the content, they may convert the format to ARGB8 first
if (!CPixelFormats::GetInstance().IsPixelFormatUncompressed(m_pixelFormat))
{
AZ_Assert(false, "the function only works right with uncompressed formats. convert to uncompressed format if you get accurate result");
AZ_TracePrintf("Image processing", "GetAlphaContent() was called for compressed format\n");
return EAlphaContent::eAlphaContent_Indeterminate;
}
@@ -385,6 +385,13 @@ namespace ImageProcessingAtom
}
return true;
}
bool NeedAlphaChannel(EAlphaContent alphaContent)
{
return (alphaContent == EAlphaContent::eAlphaContent_OnlyBlack
|| alphaContent == EAlphaContent::eAlphaContent_OnlyBlackAndWhite
|| alphaContent == EAlphaContent::eAlphaContent_Greyscale);
}
}
} // namespace ImageProcessingAtom
@@ -26,5 +26,7 @@ namespace ImageProcessingAtom
IImageObjectPtr LoadImageFromImageAsset(const AZ::Data::Asset<AZ::RPI::StreamingImageAsset>& asset);
bool SaveImageToDdsFile(IImageObjectPtr image, AZStd::string_view filePath);
bool NeedAlphaChannel(EAlphaContent alphaContent);
}
}
@@ -203,7 +203,7 @@ namespace UnitTest
m_gemFolder = AZ::Test::GetEngineRootPath() + "/Gems/Atom/Asset/ImageProcessingAtom/";
m_outputFolder = m_gemFolder + AZStd::string("Code/Tests/TestAssets/temp/");
m_defaultSettingFolder = m_gemFolder + AZStd::string("Config/");
m_defaultSettingFolder = m_gemFolder + AZStd::string("Assets/Config/");
m_testFileFolder = m_gemFolder + AZStd::string("Code/Tests/TestAssets/");
InitialImageFilenames();
@@ -1,67 +0,0 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "BuilderSettingManager",
"ClassData": {
"AnalysisFingerprint": "2",
"BuildSettings": {
"android": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"ios": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"mac": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"pc": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"linux": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": true
},
"provo": {
"GlossScale": 16.0,
"GlossBias": 0.0,
"Streaming": false,
"Enable": false
}
},
"DefaultPresetsByFileMask": {
"_basecolor": "Albedo",
"_diff": "Albedo",
"_diffuse": "Albedo",
"_ddn": "Normals",
"_normal": "Normals",
"_ddna": "NormalsWithSmoothness",
"_glossness": "Reflectance",
"_spec": "Reflectance",
"_specular": "Reflectance",
"_metallic": "Reflectance",
"_refl": "Reflectance",
"_roughness": "Reflectance",
"_ibldiffusecm": "IBLDiffuse",
"_iblskyboxcm": "IBLSkybox",
"_iblspecularcm": "IBLSpecular",
"_skyboxcm": "Skybox"
},
"DefaultPreset": "Albedo",
"DefaultPresetAlpha": "AlbedoWithGenericAlpha",
"DefaultPresetNonePOT": "ReferenceImage"
}
}
@@ -1,157 +0,0 @@
{
"Type": "JsonSerialization",
"Version": 1,
"ClassName": "MultiplatformPresetSettings",
"ClassData": {
"DefaultPreset": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_spec",
"_refl",
"_ref",
"_rf",
"_gloss",
"_g",
"_f0",
"_specf0",
"_specular",
"_metal",
"_mtl",
"_m",
"_mt",
"_metalness",
"_metallic",
"_roughness",
"_rough"
],
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"PlatformsPresets": {
"android": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_spec",
"_refl",
"_ref",
"_rf",
"_gloss",
"_g",
"_f0",
"_specf0",
"_metal",
"_mtl",
"_m",
"_mt",
"_metalness",
"_metallic",
"_roughness",
"_rough"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"ios": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_spec",
"_refl",
"_ref",
"_rf",
"_gloss",
"_g",
"_f0",
"_specf0",
"_metal",
"_mtl",
"_m",
"_mt",
"_metalness",
"_metallic",
"_roughness",
"_rough"
],
"PixelFormat": "ASTC_6x6",
"MaxTextureSize": 2048,
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"mac": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_spec",
"_refl",
"_ref",
"_rf",
"_gloss",
"_g",
"_f0",
"_specf0",
"_metal",
"_mtl",
"_m",
"_mt",
"_metalness",
"_metallic",
"_roughness",
"_rough"
],
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
},
"provo": {
"UUID": "{7A3CC95E-0A0C-4CA1-8357-5712B028B77D}",
"Name": "Reflectance",
"SourceColor": "Linear",
"DestColor": "Linear",
"FileMasks": [
"_spec",
"_refl",
"_ref",
"_rf",
"_gloss",
"_g",
"_f0",
"_specf0",
"_metal",
"_mtl",
"_m",
"_mt",
"_metalness",
"_metallic",
"_roughness",
"_rough"
],
"PixelFormat": "BC1",
"IsPowerOf2": true,
"MipMapSetting": {
"MipGenType": "Box"
}
}
}
}
}
@@ -14,6 +14,7 @@
#include <Atom/RPI/Math.azsli>
#include "BicubicPcfFilters.azsli"
#include "Shadow.azsli"
#include "NormalOffsetShadows.azsli"
// ProjectedShadow calculates shadowed area projected from a light.
class ProjectedShadow
@@ -123,6 +124,7 @@ float ProjectedShadow::GetThickness(uint shadowIndex, float3 worldPosition)
ProjectedShadow shadow;
shadow.m_worldPosition = worldPosition;
shadow.m_normalVector = 0; // The normal vector is used to reduce acne, this is not an issue when using the shadowmap to determine thickness.
shadow.m_shadowIndex = shadowIndex;
shadow.SetShadowPosition();
return shadow.GetThickness();
@@ -317,8 +319,13 @@ bool ProjectedShadow::IsShadowed(float3 shadowPosition)
void ProjectedShadow::SetShadowPosition()
{
const float normalBias = ViewSrg::m_projectedShadows[m_shadowIndex].m_normalShadowBias;
const float shadowmapSize = ViewSrg::m_projectedFilterParams[m_shadowIndex].m_shadowmapSize;
const float3 shadowOffset = ComputeNormalShadowOffset(normalBias, m_normalVector, shadowmapSize);
const float4x4 depthBiasMatrix = ViewSrg::m_projectedShadows[m_shadowIndex].m_depthBiasMatrix;
float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition, 1));
float4 shadowPositionHomogeneous = mul(depthBiasMatrix, float4(m_worldPosition + shadowOffset, 1));
m_shadowPosition = shadowPositionHomogeneous.xyz / shadowPositionHomogeneous.w;
m_bias = ViewSrg::m_projectedShadows[m_shadowIndex].m_bias / shadowPositionHomogeneous.w;
@@ -86,6 +86,8 @@ namespace AZ
virtual void SetShadowsEnabled(LightHandle handle, bool enabled) = 0;
//! Sets the shadow bias
virtual void SetShadowBias(LightHandle handle, float bias) = 0;
//! Sets the normal shadow bias
virtual void SetNormalShadowBias(LightHandle handle, float bias) = 0;
//! Sets the shadowmap size (width and height) of the light.
virtual void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) = 0;
//! Specifies filter method of shadows.
@@ -74,6 +74,8 @@ namespace AZ
virtual void SetFilteringSampleCount(LightHandle handle, uint16_t count) = 0;
//! Sets the Esm exponent to use. Higher values produce a steeper falloff in the border areas between light and shadow.
virtual void SetEsmExponent(LightHandle handle, float exponent) = 0;
//! Sets the normal shadow bias. Reduces acne by biasing the shadowmap lookup along the geometric normal.
virtual void SetNormalShadowBias(LightHandle handle, float bias) = 0;
//! Sets all of the the point data for the provided LightHandle.
virtual void SetPointData(LightHandle handle, const PointLightData& data) = 0;
};
@@ -343,7 +343,6 @@ namespace AZ
m_shadowBufferNeedsUpdate = true;
m_shadowProperties.GetData(index).m_cameraConfigurations[nullptr] = {};
m_shadowProperties.GetData(index).m_cameraTransforms[nullptr] = Transform::CreateIdentity();
const LightHandle handle(index);
m_shadowingLightHandle = handle; // only the recent light has shadows.
@@ -495,20 +494,10 @@ namespace AZ
void DirectionalLightFeatureProcessor::SetCameraTransform(
LightHandle handle,
const Transform& cameraTransform,
const RPI::RenderPipelineId& renderPipelineId)
const Transform&,
const RPI::RenderPipelineId&)
{
ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex());
if (RPI::RenderPipeline* renderPipeline = GetParentScene()->GetRenderPipeline(renderPipelineId).get())
{
const RPI::View* cameraView = renderPipeline->GetDefaultView().get();
property.m_cameraTransforms[cameraView] = cameraTransform;
}
else
{
property.m_cameraTransforms[nullptr] = cameraTransform;
}
property.m_shadowmapViewNeedsUpdate = true;
}
@@ -934,17 +923,6 @@ namespace AZ
return property.m_cameraConfigurations.at(nullptr);
}
const Transform& DirectionalLightFeatureProcessor::GetCameraTransform(LightHandle handle, const RPI::View* cameraView) const
{
const ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex());
const auto findIt = property.m_cameraTransforms.find(cameraView);
if (findIt != property.m_cameraTransforms.end())
{
return findIt->second;
}
return property.m_cameraTransforms.at(nullptr);
}
void DirectionalLightFeatureProcessor::UpdateFrustums(
LightHandle handle)
{
@@ -1365,10 +1343,11 @@ namespace AZ
// If we used an AABB whose Y-direction range is from a segment,
// the depth value on the shadowmap saturated to 0 or 1,
// and we could not draw shadow correctly.
const Transform cameraTransform = cameraView->GetCameraTransform();
const Vector3 entireFrustumCenterLight =
lightTransform.GetInverseFast() * (GetCameraTransform(handle, cameraView).TransformPoint(property.m_entireFrustumCenterLocal));
lightTransform.GetInverseFast() * (cameraTransform.TransformPoint(property.m_entireFrustumCenterLocal));
const float entireCenterY = entireFrustumCenterLight.GetElement(1);
const Vector3 cameraLocationWorld = GetCameraTransform(handle, cameraView).GetTranslation();
const Vector3 cameraLocationWorld = cameraTransform.GetTranslation();
const Vector3 cameraLocationLight = lightTransformInverse * cameraLocationWorld;
// Extend light view frustum by camera depth far in order to avoid shadow lacking behind camera.
const float cameraBehindMinY = cameraLocationLight.GetElement(1) - GetCameraConfiguration(handle, cameraView).GetDepthFar();
@@ -1428,8 +1407,8 @@ namespace AZ
GetCameraConfiguration(handle, cameraView).GetDepthCenter(depthNear, depthFar),
depthFar);
const Vector3 localCenter{ 0.f, depthCenter, 0.f };
return GetCameraTransform(handle, cameraView).TransformPoint(localCenter);
const Vector3 localCenter{ 0.f, depthCenter, 0.f };
return cameraView->GetCameraTransform().TransformPoint(localCenter);
}
float DirectionalLightFeatureProcessor::GetRadius(
@@ -1483,7 +1462,7 @@ namespace AZ
const ShadowProperty& property = m_shadowProperties.GetData(handle.GetIndex());
const Vector3& boundaryCenter = GetWorldCenterPosition(handle, cameraView, depthNear, depthFar);
const CascadeShadowCameraConfiguration& cameraConfiguration = GetCameraConfiguration(handle, cameraView);
const Transform& cameraTransform = GetCameraTransform(handle, cameraView);
const Transform cameraTransform = cameraView->GetCameraTransform();
const Vector3& cameraFwd = cameraTransform.GetBasis(1);
const Vector3& cameraUp = cameraTransform.GetBasis(2);
const Vector3 cameraToBoundaryCenter = boundaryCenter - cameraTransform.GetTranslation();
@@ -134,9 +134,6 @@ namespace AZ
// Default far depth of each cascade.
AZStd::array<float, Shadow::MaxNumberOfCascades> m_defaultFarDepths;
// Transforms of camera who offers view frustum for each camera view.
AZStd::unordered_map<const RPI::View*, Transform> m_cameraTransforms;
// Configuration offers shape of the camera view frustum for each camera view.
AZStd::unordered_map<const RPI::View*, CascadeShadowCameraConfiguration> m_cameraConfigurations;
@@ -259,11 +256,6 @@ namespace AZ
//! it returns one of the fallback render pipeline ID.
const CascadeShadowCameraConfiguration& GetCameraConfiguration(LightHandle handle, const RPI::View* cameraView) const;
//! This returns the camera transform.
//! If it has not been registered for the given camera view.
//! it returns one of the fallback render pipeline ID.
const Transform& GetCameraTransform(LightHandle handle, const RPI::View* cameraView) const;
//! This update view frustum of camera.
void UpdateFrustums(LightHandle handle);
@@ -313,6 +313,11 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowBias, bias);
}
void DiskLightFeatureProcessor::SetNormalShadowBias(LightHandle handle, float bias)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetNormalShadowBias, bias);
}
void DiskLightFeatureProcessor::SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution, shadowmapSize);
@@ -51,6 +51,7 @@ namespace AZ
void SetConeAngles(LightHandle handle, float innerDegrees, float outerDegrees) override;
void SetShadowsEnabled(LightHandle handle, bool enabled) override;
void SetShadowBias(LightHandle handle, float bias) override;
void SetNormalShadowBias(LightHandle handle, float bias) override;
void SetShadowmapMaxResolution(LightHandle handle, ShadowmapSize shadowmapSize) override;
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
@@ -302,5 +302,10 @@ namespace AZ
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetEsmExponent, esmExponent);
}
void PointLightFeatureProcessor::SetNormalShadowBias(LightHandle handle, float bias)
{
SetShadowSetting(handle, &ProjectedShadowFeatureProcessor::SetNormalShadowBias, bias);
}
} // namespace Render
} // namespace AZ
@@ -52,6 +52,7 @@ namespace AZ
void SetShadowFilterMethod(LightHandle handle, ShadowFilterMethod method) override;
void SetFilteringSampleCount(LightHandle handle, uint16_t count) override;
void SetEsmExponent(LightHandle handle, float esmExponent) override;
void SetNormalShadowBias(LightHandle handle, float bias) override;
void SetPointData(LightHandle handle, const PointLightData& data) override;
const Data::Instance<RPI::Buffer> GetLightBuffer() const;
@@ -155,8 +155,9 @@ namespace AZ::Render
{
AZ_Assert(id.IsValid(), "Invalid ShadowId passed to ProjectedShadowFeatureProcessor::SetNormalShadowBias().");
ShadowProperty& shadowProperty = GetShadowPropertyFromShadowId(id);
shadowProperty.m_normalShadowBias = normalShadowBias;
ShadowData& shadowData = m_shadowData.GetElement<ShadowDataIndex>(id.GetIndex());
shadowData.m_normalShadowBias = normalShadowBias;
m_deviceBufferNeedsUpdate = true;
}
void ProjectedShadowFeatureProcessor::SetShadowmapMaxResolution(ShadowId id, ShadowmapSize size)
@@ -68,7 +68,7 @@ namespace AZ::Render
uint32_t m_filteringSampleCount = 0;
AZStd::array<float, 2> m_unprojectConstants = { {0, 0} };
float m_bias;
float m_normalShadowBias;
float m_normalShadowBias = 0;
float m_esmExponent = 87.0f;
float m_padding[3];
};
@@ -79,7 +79,6 @@ namespace AZ::Render
ProjectedShadowDescriptor m_desc;
RPI::ViewPtr m_shadowmapView;
float m_bias = 0.1f;
float m_normalShadowBias = 0.0f;
ShadowId m_shadowId;
};
@@ -163,6 +163,7 @@ _LOGGER.debug('Invoking __init__.py for {0}.'.format({_PACKAGENAME}))
# -------------------------------------------------------------------------
# -------------------------------------------------------------------------
def get_datadir() -> pathlib.Path:
"""
persistent application data.
@@ -10,9 +10,7 @@
"""Frame capture of the Displaymapper Passthrough (outputs .dds image)"""
# ------------------------------------------------------------------------
import logging as _logging
from env_bool import env_bool
# ------------------------------------------------------------------------
_MODULENAME = 'ColorGrading.capture_displaymapperpassthrough'
import ColorGrading.initialize
@@ -27,25 +25,35 @@ _LOGGER.debug('Initializing: {0}.'.format({_MODULENAME}))
import azlmbr.bus
import azlmbr.atom
default_passtree = ["Root",
# This requires the level to have the DisplayMapper component added
# and configured to 'Passthrough'
# but now we can capture the parent input
# so this is here for reference for how it previously worked
passtree_displaymapperpassthrough = ["Root",
"MainPipeline_0",
"MainPipeline",
"PostProcessPass",
"LightAdaptation",
"DisplayMapperPass",
"DisplayMapperPassthrough"]
# we can grad the parent pass input to the displaymapper directly
passtree_default = ["Root",
"MainPipeline_0",
"MainPipeline",
"PostProcessPass",
"LightAdaptation",
"DisplayMapperPass",
"DisplayMapperPassthrough"]
"DisplayMapperPass"]
default_path = "FrameCapture\DisplayMapperPassthrough.dds"
# To Do: we should try to set display mapper to passthrough,
# then back after capture?
default_path = "FrameCapture\DisplayMappeInput.dds"
# To Do: we can wrap this, to call from a PySide2 GUI
def capture(command="CapturePassAttachment",
passtree=default_passtree,
pass_type="Output",
passtree=passtree_default,
pass_type="Input",
output_path=default_path):
"""Writes frame capture into project cache"""
azlmbr.atom.FrameCaptureRequestBus(azlmbr.bus.Broadcast,
command,
passtree,
@@ -32,10 +32,7 @@ if DCCSI_GDEBUG:
DCCSI_LOGLEVEL = int(10)
# set up logger with both console and file _logging
if DCCSI_GDEBUG:
_LOGGER = initialize_logger(_PACKAGENAME, log_to_file=True, default_log_level=DCCSI_LOGLEVEL)
else:
_LOGGER = initialize_logger(_PACKAGENAME, log_to_file=False, default_log_level=DCCSI_LOGLEVEL)
_LOGGER = initialize_logger(_PACKAGENAME, log_to_file=DCCSI_GDEBUG, default_log_level=DCCSI_LOGLEVEL)
_LOGGER.debug('Initializing: {0}.'.format({_MODULENAME}))
@@ -46,7 +43,7 @@ if DCCSI_DEV_MODE:
APPDATA = get_datadir() # os APPDATA
APPDATA_WING = Path(APPDATA, f"Wing Pro {DCCSI_WING_VERSION_MAJOR}").resolve()
if APPDATA_WING.exists():
site.addsitedir(pathlib.PureWindowsPath(APPDATA_WING).as_posix())
site.addsitedir(APPDATA_WING.resolve())
import wingdbstub as debugger
try:
debugger.Ensure()
@@ -75,8 +72,7 @@ def start():
try:
_O3DE_DEV = Path(os.getenv('O3DE_DEV'))
_O3DE_DEV = _O3DE_DEV.resolve()
os.environ['O3DE_DEV'] = pathlib.PureWindowsPath(_O3DE_DEV).as_posix()
os.environ['O3DE_DEV'] = _O3DE_DEV.as_posix()
_LOGGER.debug(f'O3DE_DEV is: {_O3DE_DEV}')
except EnvironmentError as e:
_LOGGER.error('O3DE engineroot not set or found')
@@ -86,23 +82,22 @@ def start():
_TAG_LY_BUILD_PATH = os.getenv('TAG_LY_BUILD_PATH', 'build')
_DEFAULT_BIN_PATH = Path(str(_O3DE_DEV), _TAG_LY_BUILD_PATH, 'bin', 'profile')
_O3DE_BIN_PATH = Path(os.getenv('O3DE_BIN_PATH', _DEFAULT_BIN_PATH))
_O3DE_BIN_PATH = _O3DE_BIN_PATH.resolve()
os.environ['O3DE_BIN_PATH'] = pathlib.PureWindowsPath(_O3DE_BIN_PATH).as_posix()
os.environ['O3DE_BIN_PATH'] = _O3DE_BIN_PATH.as_posix()
_LOGGER.debug(f'O3DE_BIN_PATH is: {_O3DE_BIN_PATH}')
site.addsitedir(pathlib.PureWindowsPath(_O3DE_BIN_PATH).as_posix())
site.addsitedir(_O3DE_BIN_PATH.resolve())
except EnvironmentError as e:
_LOGGER.error('O3DE bin folder not set or found')
raise e
if running_editor:
_O3DE_DEV = Path(os.getenv('O3DE_DEV', Path(azlmbr.paths.engroot)))
os.environ['O3DE_DEV'] = pathlib.PureWindowsPath(_O3DE_DEV).as_posix()
os.environ['O3DE_DEV'] = _O3DE_DEV.as_posix()
_LOGGER.debug(_O3DE_DEV)
_O3DE_BIN_PATH = Path(str(_O3DE_DEV),Path(azlmbr.paths.executableFolder))
_O3DE_BIN = Path(os.getenv('O3DE_BIN', _O3DE_BIN_PATH.resolve()))
os.environ['O3DE_BIN'] = pathlib.PureWindowsPath(_O3DE_BIN).as_posix()
os.environ['O3DE_BIN'] = _O3DE_BIN_PATH.as_posix()
_LOGGER.debug(_O3DE_BIN)
@@ -34,15 +34,15 @@ SETLOCAL ENABLEDELAYEDEXPANSION
IF EXIST "%~dp0User_Env.bat" CALL %~dp0User_Env.bat
:: Initialize env
echo
echo.
echo ... calling Env_Core.bat
CALL %~dp0\Env_Core.bat
echo
echo.
echo ... calling Env_Python.bat
CALL %~dp0\Env_Python.bat
echo
echo.
echo ... calling Env_Tools.bat
CALL %~dp0\Env_Tools.bat
@@ -27,37 +27,19 @@ echo ~ O3DE Color Grading Python Env ...
echo _____________________________________________________________________
echo.
:: Python Version
:: Ideally these are set to match the O3DE python distribution
:: <O3DE>\python\runtime
IF "%DCCSI_PY_VERSION_MAJOR%"=="" (set DCCSI_PY_VERSION_MAJOR=3)
echo DCCSI_PY_VERSION_MAJOR = %DCCSI_PY_VERSION_MAJOR%
:: PY version Major
IF "%DCCSI_PY_VERSION_MINOR%"=="" (set DCCSI_PY_VERSION_MINOR=7)
echo DCCSI_PY_VERSION_MINOR = %DCCSI_PY_VERSION_MINOR%
IF "%DCCSI_PY_VERSION_RELEASE%"=="" (set DCCSI_PY_VERSION_RELEASE=10)
echo DCCSI_PY_VERSION_RELEASE = %DCCSI_PY_VERSION_RELEASE%
:: shared location for 64bit python 3.7 DEV location
:: this defines a DCCsi sandbox for lib site-packages by version
:: <O3DE>\Gems\AtomLyIntegration\TechnicalArt\DccScriptingInterface\3rdParty\Python\Lib
set DCCSI_PYTHON_PATH=%DCCSIG_PATH%\3rdParty\Python
echo DCCSI_PYTHON_PATH = %DCCSI_PYTHON_PATH%
:: add access to a Lib location that matches the py version (example: 3.7.x)
:: switch this for other python versions like maya (2.7.x)
IF "%DCCSI_PYTHON_LIB_PATH%"=="" (set DCCSI_PYTHON_LIB_PATH=%DCCSI_PYTHON_PATH%\Lib\%DCCSI_PY_VERSION_MAJOR%.x\%DCCSI_PY_VERSION_MAJOR%.%DCCSI_PY_VERSION_MINOR%.x\site-packages)
echo DCCSI_PYTHON_LIB_PATH = %DCCSI_PYTHON_LIB_PATH%
:: add to the PATH
SET PATH=%DCCSI_PYTHON_LIB_PATH%;%PATH%
:: shared location for default O3DE python location
set DCCSI_PYTHON_INSTALL=%O3DE_DEV%\Python
echo DCCSI_PYTHON_INSTALL = %DCCSI_PYTHON_INSTALL%
:: Warning, many DCC tools (like Maya) include thier own versioned python interpretter.
:: Some apps may not operate correctly if PYTHONHOME is set/propogated.
:: This is definitely the case with Maya, doing so causes Maya to not boot.
FOR /F "tokens=* USEBACKQ" %%F IN (`%DCCSI_PYTHON_INSTALL%\python.cmd %DCCSI_PYTHON_INSTALL%\get_python_path.py`) DO (SET PYTHONHOME=%%F)
echo PYTHONHOME - is now the folder containing O3DE python executable
echo PYTHONHOME = %PYTHONHOME%
SET PYTHON=%PYTHONHOME%\python.exe
:: location for O3DE python 3.7 location
set DCCSI_PY_BASE=%DCCSI_PYTHON_INSTALL%\python.cmd
echo DCCSI_PY_BASE = %DCCSI_PY_BASE%
@@ -65,10 +47,7 @@ echo DCCSI_PY_BASE = %DCCSI_PY_BASE%
:: ide and debugger plug
set DCCSI_PY_DEFAULT=%DCCSI_PY_BASE%
IF "%DCCSI_PY_REV%"=="" (set DCCSI_PY_REV=rev2)
IF "%DCCSI_PY_PLATFORM%"=="" (set DCCSI_PY_PLATFORM=windows)
set DCCSI_PY_IDE=%DCCSI_PYTHON_INSTALL%\runtime\python-%DCCSI_PY_VERSION_MAJOR%.%DCCSI_PY_VERSION_MINOR%.%DCCSI_PY_VERSION_RELEASE%-%DCCSI_PY_REV%-%DCCSI_PY_PLATFORM%\python
set DCCSI_PY_IDE=%PYTHONHOME%
echo DCCSI_PY_IDE = %DCCSI_PY_IDE%
:: Wing and other IDEs probably prefer access directly to the python.exe
@@ -91,11 +70,6 @@ SET PATH=%DCCSI_PYTHON_INSTALL%;%DCCSI_PY_IDE%;%DCCSI_PY_IDE_PACKAGES%;%DCCSI_PY
set PYTHONPATH=%DCCSIG_PATH%;%DCCSI_PYTHON_LIB_PATH%;%O3DE_BIN_PATH%;%DCCSI_COLORGRADING_SCRIPTS%;%DCCSI_FEATURECOMMON_SCRIPTS%;%PYTHONPATH%
echo PYTHONPATH = %PYTHONPATH%
:: used for debugging in WingIDE (but needs to be here)
IF "%TAG_USERNAME%"=="" (set TAG_USERNAME=NOT_SET)
echo TAG_USERNAME = %TAG_USERNAME%
IF "%TAG_USERNAME%"=="NOT_SET" (echo Add TAG_USERNAME to User_Env.bat)
:: Set flag so we don't initialize dccsi environment twice
SET O3DE_ENV_PY_INIT=1
GOTO END_OF_FILE
@@ -25,11 +25,6 @@ SET TAG_LY_BUILD_PATH=build
SET DCCSI_GDEBUG=True
SET DCCSI_DEV_MODE=True
:: set the your user name here for windows path
SET TAG_USERNAME=NOT_SET
SET DCCSI_PY_REV=rev1
SET DCCSI_PY_PLATFORM=windows
:: Set flag so we don't initialize dccsi environment twice
SET O3DE_USER_ENV_INIT=1
GOTO END_OF_FILE
@@ -9,11 +9,13 @@
#pragma once
#include <AzCore/Module/Module.h>
#include <AzToolsFramework/API/PythonLoader.h>
namespace AtomToolsFramework
{
class AtomToolsFrameworkModule
: public AZ::Module
, public AzToolsFramework::EmbeddedPython::PythonLoader
{
public:
AZ_RTTI(AtomToolsFrameworkModule, "{B58B7CA8-98C9-4DC8-8607-E094989BBBE2}", AZ::Module);
@@ -132,6 +132,13 @@ namespace AZ
//! Sets the Esm exponent. Higher values produce a steeper falloff between light and shadow.
virtual void SetEsmExponent(float exponent) = 0;
//! Reduces acne by biasing the shadowmap lookup along the geometric normal.
//! @return Returns the amount of bias to apply.
virtual float GetNormalShadowBias() const = 0;
//! Reduces acne by biasing the shadowmap lookup along the geometric normal.
//! @param normalShadowBias Sets the amount of normal shadow bias to apply.
virtual void SetNormalShadowBias(float normalShadowBias) = 0;
};
//! The EBus for requests to for setting and getting light component properties.
@@ -57,6 +57,7 @@ namespace AZ
// Shadows (only used for supported shapes)
bool m_enableShadow = false;
float m_bias = 0.1f;
float m_normalShadowBias = 0.0f;
ShadowmapSize m_shadowmapMaxSize = ShadowmapSize::Size256;
ShadowFilterMethod m_shadowFilterMethod = ShadowFilterMethod::None;
uint16_t m_filteringSampleCount = 12;

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