Merge branch 'main' into mp_session_integ
This commit is contained in:
@@ -9,11 +9,6 @@ remove or modify any license notices. This file is distributed on an "AS IS" BAS
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
"""
|
||||
|
||||
"""
|
||||
C24064528: The File menu options function normally
|
||||
C16780778: The File menu options function normally-New view interaction Model enabled
|
||||
"""
|
||||
|
||||
import os
|
||||
import sys
|
||||
|
||||
@@ -54,7 +49,10 @@ class TestFileMenuOptions(EditorTestHelper):
|
||||
("Save",),
|
||||
("Save As",),
|
||||
("Save Level Statistics",),
|
||||
("Project Settings", "Project Settings Tool"),
|
||||
("Edit Project Settings",),
|
||||
("Edit Platform Settings",),
|
||||
("New Project",),
|
||||
("Open Project",),
|
||||
("Show Log File",),
|
||||
("Resave All Slices",),
|
||||
("Exit",),
|
||||
|
||||
@@ -15,6 +15,7 @@ import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools._internal.pytest_plugin as internal_plugin
|
||||
import editor_python_test_tools.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
@@ -40,6 +41,10 @@ class TestBasicEditorWorkflows(object):
|
||||
@pytest.mark.SUITE_main
|
||||
def test_BasicEditorWorkflows_LevelEntityComponentCRUD(self, request, editor, level, launcher_platform):
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
expected_lines = [
|
||||
"Create and load new level: True",
|
||||
"New entity creation: True",
|
||||
|
||||
@@ -7,8 +7,6 @@ distribution (the "License"). All use of this software is governed by the Licens
|
||||
or, if provided, by the license below or the license accompanying this file. Do not
|
||||
remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
|
||||
C16780783: Base Edit Menu Options (New Viewport Interaction Model)
|
||||
"""
|
||||
|
||||
import os
|
||||
@@ -17,6 +15,7 @@ import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools.environment.process_utils as process_utils
|
||||
import editor_python_test_tools.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), "EditorScripts")
|
||||
@@ -33,6 +32,7 @@ class TestMenus(object):
|
||||
def setup_teardown(self, request, workspace, project, level):
|
||||
def teardown():
|
||||
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
|
||||
process_utils.kill_processes_named("o3de", ignore_extensions=True) # Kill ProjectManager windows
|
||||
|
||||
request.addfinalizer(teardown)
|
||||
|
||||
@@ -80,8 +80,7 @@ class TestMenus(object):
|
||||
expected_lines,
|
||||
cfg_args=[level],
|
||||
run_python="--runpython",
|
||||
auto_test_mode=True,
|
||||
timeout=log_monitor_timeout,
|
||||
timeout=log_monitor_timeout
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C16780807")
|
||||
@@ -107,13 +106,13 @@ class TestMenus(object):
|
||||
"Menus_ViewMenuOptions.py",
|
||||
expected_lines,
|
||||
cfg_args=[level],
|
||||
auto_test_mode=True,
|
||||
run_python="--runpython",
|
||||
timeout=log_monitor_timeout,
|
||||
timeout=log_monitor_timeout
|
||||
)
|
||||
|
||||
@pytest.mark.test_case_id("C16780778")
|
||||
@pytest.mark.SUITE_sandbox
|
||||
@pytest.mark.xfail # LYN-4208
|
||||
def test_Menus_FileMenuOptions_Work(self, request, editor, level, launcher_platform):
|
||||
expected_lines = [
|
||||
"New Level Action triggered",
|
||||
@@ -122,7 +121,10 @@ class TestMenus(object):
|
||||
"Save Action triggered",
|
||||
"Save As Action triggered",
|
||||
"Save Level Statistics Action triggered",
|
||||
"Project Settings Tool Action triggered",
|
||||
"Edit Project Settings Action triggered",
|
||||
"Edit Platform Settings Action triggered",
|
||||
"New Project Action triggered",
|
||||
"Open Project Action triggered",
|
||||
"Show Log File Action triggered",
|
||||
"Resave All Slices Action triggered",
|
||||
"Exit Action triggered",
|
||||
@@ -135,7 +137,6 @@ class TestMenus(object):
|
||||
"Menus_FileMenuOptions.py",
|
||||
expected_lines,
|
||||
cfg_args=[level],
|
||||
auto_test_mode=True,
|
||||
run_python="--runpython",
|
||||
timeout=log_monitor_timeout,
|
||||
)
|
||||
timeout=log_monitor_timeout
|
||||
)
|
||||
|
||||
+6
@@ -16,6 +16,7 @@ import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools._internal.pytest_plugin as internal_plugin
|
||||
import editor_python_test_tools.hydra_test_utils as hydra
|
||||
from ly_remote_console.remote_console_commands import RemoteConsole as RemoteConsole
|
||||
|
||||
@@ -46,6 +47,11 @@ class TestDynamicSliceInstanceSpawner(object):
|
||||
@pytest.mark.parametrize("launcher_platform", ['windows_editor'])
|
||||
def test_DynamicSliceInstanceSpawner_DynamicSliceSpawnerWorks(self, request, editor, level, workspace, project,
|
||||
launcher_platform):
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
# Ensure temp level does not already exist
|
||||
file_system.delete([os.path.join(workspace.paths.engine_root(), project, "Levels", level)], True, True)
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import logging
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools._internal.pytest_plugin as internal_plugin
|
||||
import editor_python_test_tools.hydra_test_utils as hydra
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -40,6 +41,11 @@ class TestEmptyInstanceSpawner(object):
|
||||
@pytest.mark.SUITE_main
|
||||
@pytest.mark.dynveg_area
|
||||
def test_EmptyInstanceSpawner_EmptySpawnerWorks(self, request, editor, level, launcher_platform):
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
|
||||
+11
@@ -23,6 +23,7 @@ import pytest
|
||||
# Bail on the test if ly_test_tools doesn't exist.
|
||||
pytest.importorskip('ly_test_tools')
|
||||
import ly_test_tools.environment.file_system as file_system
|
||||
import ly_test_tools._internal.pytest_plugin as internal_plugin
|
||||
import editor_python_test_tools.hydra_test_utils as hydra
|
||||
|
||||
test_directory = os.path.join(os.path.dirname(__file__), 'EditorScripts')
|
||||
@@ -46,6 +47,11 @@ class TestGraphComponentSync(object):
|
||||
@pytest.mark.BAT
|
||||
@pytest.mark.SUITE_main
|
||||
def test_LandscapeCanvas_SlotConnections_UpdateComponentReferences(self, request, editor, level, launcher_platform):
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
@@ -122,6 +128,11 @@ class TestGraphComponentSync(object):
|
||||
"""
|
||||
Verifies a Gradient Mixer can be setup in Landscape Canvas and all references are property set.
|
||||
"""
|
||||
|
||||
# Skip test if running against Debug build
|
||||
if "debug" in internal_plugin.build_directory:
|
||||
pytest.skip("Does not execute against debug builds.")
|
||||
|
||||
cfg_args = [level]
|
||||
|
||||
expected_lines = [
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
|
||||
#include <AzFramework/IO/FileOperations.h>
|
||||
#include <AzCore/IO/FileIO.h>
|
||||
#include <AzCore/IO/Path/Path.h>
|
||||
|
||||
#ifdef WIN32
|
||||
#include <time.h>
|
||||
@@ -88,7 +89,6 @@ CLog::CLog(ISystem* pSystem)
|
||||
|
||||
m_nMainThreadId = CryGetCurrentThreadId();
|
||||
|
||||
m_logFileHandle = AZ::IO::InvalidHandle;
|
||||
#if defined(KEEP_LOG_FILE_OPEN)
|
||||
m_bFirstLine = true;
|
||||
#endif
|
||||
@@ -162,35 +162,6 @@ void CLog::RegisterConsoleVariables()
|
||||
REGISTER_COMMAND("log_flush", &LogFlushFile, 0, "Flush the log file");
|
||||
#endif
|
||||
}
|
||||
/*
|
||||
//testbed
|
||||
{
|
||||
int iSave0 = m_pLogVerbosity->GetIVal();
|
||||
int iSave1 = m_pLogFileVerbosity->GetIVal();
|
||||
|
||||
for(int i=0;i<=4;++i)
|
||||
{
|
||||
m_pLogVerbosity->Set(i);
|
||||
m_pLogFileVerbosity->Set(i);
|
||||
|
||||
LogWithType(eAlways,"CLog selftest: Verbosity=%d FileVerbosity=%d",m_pLogVerbosity->GetIVal(),m_pLogFileVerbosity->GetIVal());
|
||||
LogWithType(eAlways,"--------------");
|
||||
|
||||
LogWithType(eError,"eError");
|
||||
LogWithType(eWarning,"eWarning");
|
||||
LogWithType(eMessage,"eMessage");
|
||||
LogWithType(eInput,"eInput");
|
||||
LogWithType(eInputResponse,"eInputResponse");
|
||||
|
||||
LogWarning("LogWarning()");
|
||||
LogError("LogError()");
|
||||
LogWithType(eAlways,"--------------");
|
||||
}
|
||||
|
||||
m_pLogVerbosity->Set(iSave0);
|
||||
m_pLogFileVerbosity->Set(iSave1);
|
||||
}
|
||||
*/
|
||||
#undef DEFAULT_VERBOSITY
|
||||
}
|
||||
|
||||
@@ -210,7 +181,7 @@ CLog::~CLog()
|
||||
|
||||
UnregisterConsoleVariables();
|
||||
|
||||
CloseLogFile(true);
|
||||
CloseLogFile();
|
||||
}
|
||||
|
||||
void CLog::UnregisterConsoleVariables()
|
||||
@@ -224,31 +195,36 @@ void CLog::UnregisterConsoleVariables()
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
void CLog::CloseLogFile([[maybe_unused]] bool forceClose)
|
||||
void CLog::CloseLogFile()
|
||||
{
|
||||
if (m_logFileHandle != AZ::IO::InvalidHandle)
|
||||
{
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Close(m_logFileHandle);
|
||||
m_logFileHandle = AZ::IO::InvalidHandle;
|
||||
}
|
||||
m_logFileHandle.Close();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
AZ::IO::HandleType CLog::OpenLogFile(const char* filename, const char* mode)
|
||||
bool CLog::OpenLogFile(const char* filename, int mode)
|
||||
{
|
||||
using namespace AZ::IO;
|
||||
|
||||
AZ_Assert(m_logFileHandle == AZ::IO::InvalidHandle, "Attempt to open log file when one is already open. This would lead to a handle leak.");
|
||||
|
||||
if ((!filename) || (filename[0] == 0))
|
||||
if (m_logFileHandle.IsOpen())
|
||||
{
|
||||
return m_logFileHandle;
|
||||
// Can only AZ_Assert if a file is open, otherwise the AZ_Assert
|
||||
// would eventually lead to OpenLogFile being opened up again
|
||||
AZ_Assert(false, "Attempt to open log file when one is already open. This would lead to a handle leak.");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (filename == nullptr || filename[0] == '\0')
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// it is assumed that @log@ points at the appropriate place (so for apple, to the user profile dir)
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Open(filename, AZ::IO::GetOpenModeFromStringMode(mode), m_logFileHandle);
|
||||
AZ::IO::FileIOBase* fileSystem = AZ::IO::FileIOBase::GetDirectInstance();
|
||||
if (AZ::IO::FixedMaxPath logFilePath; fileSystem->ReplaceAlias(logFilePath, filename))
|
||||
{
|
||||
logFilePath = logFilePath.LexicallyNormal();
|
||||
m_logFileHandle.Open(logFilePath.c_str(), mode);
|
||||
}
|
||||
|
||||
if (m_logFileHandle != AZ::IO::InvalidHandle)
|
||||
if (m_logFileHandle.IsOpen())
|
||||
{
|
||||
#if defined(KEEP_LOG_FILE_OPEN)
|
||||
m_bFirstLine = true;
|
||||
@@ -257,11 +233,11 @@ AZ::IO::HandleType CLog::OpenLogFile(const char* filename, const char* mode)
|
||||
else
|
||||
{
|
||||
#if defined(LINUX) || defined(APPLE)
|
||||
syslog(LOG_NOTICE, "Failed to open log file [%s], mode [%s]", filename, mode);
|
||||
syslog(LOG_NOTICE, "Failed to open log file [%s], mode [%d]", filename, mode);
|
||||
#endif
|
||||
}
|
||||
|
||||
return m_logFileHandle;
|
||||
return m_logFileHandle.IsOpen();
|
||||
}
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
@@ -1114,12 +1090,15 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
|
||||
|
||||
if (logToFile)
|
||||
{
|
||||
if (m_logFileHandle == AZ::IO::InvalidHandle)
|
||||
if (!m_logFileHandle.IsOpen())
|
||||
{
|
||||
OpenLogFile(m_szFilename, "w+t");
|
||||
constexpr auto openMode = AZ::IO::SystemFile::OpenMode::SF_OPEN_APPEND
|
||||
| AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE
|
||||
| AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY;
|
||||
OpenLogFile(m_szFilename, openMode);
|
||||
}
|
||||
|
||||
if (m_logFileHandle != AZ::IO::InvalidHandle)
|
||||
if (m_logFileHandle.IsOpen())
|
||||
{
|
||||
#if defined(KEEP_LOG_FILE_OPEN)
|
||||
if (m_bFirstLine)
|
||||
@@ -1130,9 +1109,9 @@ void CLog::LogStringToFile(const char* szString, ELogType logType, bool bAdd, [[
|
||||
if (bAdd)
|
||||
{
|
||||
// if adding to a prior line erase the \n at the end.
|
||||
AZ::IO::FileIOBase::GetDirectInstance()->Seek(m_logFileHandle, -2, AZ::IO::SeekType::SeekFromEnd);
|
||||
m_logFileHandle.Seek(-2, AZ::IO::SystemFile::SeekMode::SF_SEEK_END);
|
||||
}
|
||||
AZ::IO::FPutS(tempString.c_str(), m_logFileHandle);
|
||||
m_logFileHandle.Write(tempString.c_str(), tempString.size());
|
||||
#if !defined(KEEP_LOG_FILE_OPEN)
|
||||
CloseLogFile();
|
||||
#endif
|
||||
@@ -1383,6 +1362,23 @@ bool CLog::SetFileName(const char* fileNameOrAbsolutePath, bool backupLogs)
|
||||
|
||||
CreateBackupFile();
|
||||
|
||||
AZ::IO::FileIOBase* fileSystem = AZ::IO::FileIOBase::GetDirectInstance();
|
||||
AZ::IO::FixedMaxPath newLogFilePath;
|
||||
if (fileSystem->ReplaceAlias(newLogFilePath, m_szFilename))
|
||||
{
|
||||
newLogFilePath = newLogFilePath.LexicallyNormal();
|
||||
}
|
||||
if (m_logFileHandle.IsOpen() && newLogFilePath != m_logFileHandle.Name())
|
||||
{
|
||||
constexpr auto openMode = AZ::IO::SystemFile::OpenMode::SF_OPEN_APPEND
|
||||
| AZ::IO::SystemFile::OpenMode::SF_OPEN_CREATE
|
||||
| AZ::IO::SystemFile::OpenMode::SF_OPEN_WRITE_ONLY;
|
||||
if(AZ::IO::SystemFile newLogFile; newLogFile.Open(m_szFilename, openMode))
|
||||
{
|
||||
m_logFileHandle = AZStd::move(newLogFile);
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -1537,9 +1533,9 @@ const char* CLog::GetModuleFilter()
|
||||
void CLog::FlushAndClose()
|
||||
{
|
||||
#if defined(KEEP_LOG_FILE_OPEN)
|
||||
if (m_logFileHandle)
|
||||
if (m_logFileHandle.IsOpen())
|
||||
{
|
||||
CloseLogFile(true);
|
||||
CloseLogFile();
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ private: // -------------------------------------------------------------------
|
||||
void LogStringToConsole(const char* szString, ELogType logType, bool bAdd) {}
|
||||
#endif // !defined(EXCLUDE_NORMAL_LOG)
|
||||
|
||||
AZ::IO::HandleType OpenLogFile(const char* filename, const char* mode);
|
||||
void CloseLogFile(bool force = false);
|
||||
bool OpenLogFile(const char* filename, int mode);
|
||||
void CloseLogFile();
|
||||
|
||||
// will format the message into m_szTemp
|
||||
void FormatMessage(const char* szCommand, ...) PRINTF_PARAMS(2, 3);
|
||||
@@ -152,15 +152,11 @@ private: // -------------------------------------------------------------------
|
||||
virtual const char* GetAssetScopeString();
|
||||
#endif
|
||||
|
||||
ISystem* m_pSystem; //
|
||||
float m_fLastLoadingUpdateTime; // for non-frequent streamingEngine update
|
||||
//char m_szTemp[MAX_TEMP_LENGTH_SIZE]; //
|
||||
char m_szFilename[MAX_FILENAME_SIZE]; // can be with path
|
||||
mutable char m_sBackupFilename[MAX_FILENAME_SIZE]; // can be with path
|
||||
AZ::IO::HandleType m_logFileHandle;
|
||||
CryStackStringT<char, 32> m_LogMode; //mode m_pLogFile has been opened with
|
||||
AZ::IO::HandleType m_errFileHandle;
|
||||
int m_nErrCount;
|
||||
ISystem* m_pSystem; //
|
||||
float m_fLastLoadingUpdateTime; // for non-frequent streamingEngine update
|
||||
char m_szFilename[MAX_FILENAME_SIZE]; // can be with path
|
||||
mutable char m_sBackupFilename[MAX_FILENAME_SIZE]; // can be with path
|
||||
AZ::IO::SystemFile m_logFileHandle;
|
||||
|
||||
bool m_backupLogs;
|
||||
|
||||
|
||||
@@ -1208,7 +1208,7 @@ bool CSystem::Init(const SSystemInitParams& startupParams)
|
||||
{
|
||||
assetPlatform = AzFramework::OSPlatformToDefaultAssetPlatform(AZ_TRAIT_OS_PLATFORM_CODENAME);
|
||||
AZ_Warning(AZ_TRACE_SYSTEM_WINDOW, false, R"(A valid asset platform is missing in "%s/assets" key in the SettingsRegistry.)""\n"
|
||||
R"(This typically done by setting he "assets" field in the bootstrap.cfg for within a .setreg file)""\n"
|
||||
R"(This typically done by setting the "assets" field within a .setreg file)""\n"
|
||||
R"(A fallback of %s will be used.)",
|
||||
AZ::SettingsRegistryMergeUtils::BootstrapSettingsRootKey,
|
||||
assetPlatform.c_str());
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace Platform
|
||||
|
||||
using FileHandleType = SystemFile::FileHandleType;
|
||||
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode);
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode);
|
||||
SystemFile::SizeType Tell(FileHandleType handle, const SystemFile* systemFile);
|
||||
bool Eof(FileHandleType handle, const SystemFile* systemFile);
|
||||
AZ::u64 ModificationTime(FileHandleType handle, const SystemFile* systemFile);
|
||||
@@ -68,9 +68,8 @@ void SystemFile::CreatePath(const char* fileName)
|
||||
}
|
||||
|
||||
SystemFile::SystemFile()
|
||||
: m_handle{ AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE }
|
||||
{
|
||||
m_fileName[0] = '\0';
|
||||
m_handle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
|
||||
}
|
||||
|
||||
SystemFile::~SystemFile()
|
||||
@@ -81,6 +80,25 @@ SystemFile::~SystemFile()
|
||||
}
|
||||
}
|
||||
|
||||
SystemFile::SystemFile(SystemFile&& other)
|
||||
: SystemFile{}
|
||||
{
|
||||
AZStd::swap(m_fileName, other.m_fileName);
|
||||
AZStd::swap(m_handle, other.m_handle);
|
||||
}
|
||||
|
||||
SystemFile& SystemFile::operator=(SystemFile&& other)
|
||||
{
|
||||
// Close the current file and take over the SystemFile handle and filename
|
||||
Close();
|
||||
m_fileName = AZStd::move(other.m_fileName);
|
||||
m_handle = AZStd::move(other.m_handle);
|
||||
other.m_fileName = {};
|
||||
other.m_handle = AZ_TRAIT_SYSTEMFILE_INVALID_HANDLE;
|
||||
|
||||
return *this;
|
||||
}
|
||||
|
||||
bool SystemFile::Open(const char* fileName, int mode, int platformFlags)
|
||||
{
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Open - %s", fileName);
|
||||
@@ -88,42 +106,42 @@ bool SystemFile::Open(const char* fileName, int mode, int platformFlags)
|
||||
|
||||
if (fileName) // If we reopen the file we are allowed to have NULL file name
|
||||
{
|
||||
if (strlen(fileName) > AZ_ARRAY_SIZE(m_fileName) - 1)
|
||||
if (strlen(fileName) > m_fileName.max_size())
|
||||
{
|
||||
EBUS_EVENT(FileIOEventBus, OnError, this, nullptr, 0);
|
||||
return false;
|
||||
}
|
||||
|
||||
// store the filename
|
||||
azsnprintf(m_fileName, AZ_ARRAY_SIZE(m_fileName), "%s", fileName);
|
||||
m_fileName = fileName;
|
||||
}
|
||||
|
||||
if (FileIOBus::HasHandlers())
|
||||
{
|
||||
bool isOpen = false;
|
||||
bool isHandled = false;
|
||||
EBUS_EVENT_RESULT(isHandled, FileIOBus, OnOpen, *this, m_fileName, mode, platformFlags, isOpen);
|
||||
EBUS_EVENT_RESULT(isHandled, FileIOBus, OnOpen, *this, m_fileName.c_str(), mode, platformFlags, isOpen);
|
||||
if (isHandled)
|
||||
{
|
||||
return isOpen;
|
||||
}
|
||||
}
|
||||
|
||||
AZ_Assert(!IsOpen(), "This file (%s) is already open!", m_fileName);
|
||||
AZ_Assert(!IsOpen(), "This file (%s) is already open!", m_fileName.c_str());
|
||||
|
||||
return PlatformOpen(mode, platformFlags);
|
||||
}
|
||||
|
||||
bool SystemFile::ReOpen(int mode, int platformFlags)
|
||||
{
|
||||
AZ_Assert(strlen(m_fileName) > 0, "Missing filename. You must call open first!");
|
||||
AZ_Assert(!m_fileName.empty(), "Missing filename. You must call open first!");
|
||||
return Open(0, mode, platformFlags);
|
||||
}
|
||||
|
||||
void SystemFile::Close()
|
||||
{
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Close - %s", m_fileName);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Close - %s", m_fileName);
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Close - %s", m_fileName.c_str());
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Close - %s", m_fileName.c_str());
|
||||
|
||||
if (FileIOBus::HasHandlers())
|
||||
{
|
||||
@@ -138,9 +156,9 @@ void SystemFile::Close()
|
||||
PlatformClose();
|
||||
}
|
||||
|
||||
void SystemFile::Seek(SizeType offset, SeekMode mode)
|
||||
void SystemFile::Seek(SeekSizeType offset, SeekMode mode)
|
||||
{
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Seek - %s:%i", m_fileName, offset);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Seek - %s:%i", m_fileName.c_str(), offset);
|
||||
|
||||
if (FileIOBus::HasHandlers())
|
||||
{
|
||||
@@ -167,15 +185,15 @@ bool SystemFile::Eof()
|
||||
|
||||
AZ::u64 SystemFile::ModificationTime()
|
||||
{
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::ModTime - %s", m_fileName);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::ModTime - %s", m_fileName.c_str());
|
||||
|
||||
return Platform::ModificationTime(m_handle, this);
|
||||
}
|
||||
|
||||
SystemFile::SizeType SystemFile::Read(SizeType byteSize, void* buffer)
|
||||
{
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Read - %s:%i", m_fileName, byteSize);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Read - %s:%i", m_fileName, byteSize);
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Read - %s:%i", m_fileName.c_str(), byteSize);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Read - %s:%i", m_fileName.c_str(), byteSize);
|
||||
|
||||
if (FileIOBus::HasHandlers())
|
||||
{
|
||||
@@ -193,8 +211,8 @@ SystemFile::SizeType SystemFile::Read(SizeType byteSize, void* buffer)
|
||||
|
||||
SystemFile::SizeType SystemFile::Write(const void* buffer, SizeType byteSize)
|
||||
{
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Write - %s:%i", m_fileName, byteSize);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Write - %s:%i", m_fileName, byteSize);
|
||||
AZ_PROFILE_INTERVAL_SCOPED(AZ::Debug::ProfileCategory::AzCore, this, "SystemFile::Write - %s:%i", m_fileName.c_str(), byteSize);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Write - %s:%i", m_fileName.c_str(), byteSize);
|
||||
|
||||
if (FileIOBus::HasHandlers())
|
||||
{
|
||||
@@ -212,14 +230,14 @@ SystemFile::SizeType SystemFile::Write(const void* buffer, SizeType byteSize)
|
||||
|
||||
void SystemFile::Flush()
|
||||
{
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Flush - %s", m_fileName);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Flush - %s", m_fileName.c_str());
|
||||
|
||||
Platform::Flush(m_handle, this);
|
||||
}
|
||||
|
||||
SystemFile::SizeType SystemFile::Length() const
|
||||
{
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Length - %s", m_fileName);
|
||||
AZ_PROFILE_SCOPE_STALL_DYNAMIC(AZ::Debug::ProfileCategory::AzCore, "SystemFile::Length - %s", m_fileName.c_str());
|
||||
|
||||
return Platform::Length(m_handle, this);
|
||||
}
|
||||
@@ -379,9 +397,9 @@ namespace
|
||||
HasPosixEnumOption(PermissionModeFlags::Write);
|
||||
|
||||
#undef HasPosixEnumOption
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
FileDescriptorRedirector::FileDescriptorRedirector(int sourceFileDescriptor)
|
||||
: m_sourceFileDescriptor(sourceFileDescriptor)
|
||||
{
|
||||
|
||||
@@ -12,10 +12,11 @@
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/base.h>
|
||||
#include <AzCore/std/function/function_fwd.h>
|
||||
#include <AzCore/std/string/string.h>
|
||||
|
||||
#include <AzCore/IO/Path/Path_fwd.h>
|
||||
#include <AzCore/IO/SystemFile_Platform.h>
|
||||
#include <AzCore/std/function/function_fwd.h>
|
||||
#include <AzCore/std/string/fixed_string.h>
|
||||
|
||||
// Establish a consistent size that works across platforms. It's actually larger than this
|
||||
// on platforms we support, but this is a good least common denominator
|
||||
@@ -51,11 +52,15 @@ namespace AZ
|
||||
};
|
||||
|
||||
using SizeType = AZ::IO::Internal::SizeType;
|
||||
using SeekSizeType = AZ::IO::Internal::SeekSizeType;
|
||||
using FileHandleType = AZ::IO::Internal::FileHandleType;
|
||||
|
||||
SystemFile();
|
||||
~SystemFile();
|
||||
|
||||
SystemFile(SystemFile&&);
|
||||
SystemFile& operator=(SystemFile&&);
|
||||
|
||||
/**
|
||||
* Opens a file.
|
||||
* \param fileName full file name including path
|
||||
@@ -69,7 +74,7 @@ namespace AZ
|
||||
/// Closes a file, if file already close it has no effect.
|
||||
void Close();
|
||||
/// Seek in current file.
|
||||
void Seek(SizeType offset, SeekMode mode);
|
||||
void Seek(SeekSizeType offset, SeekMode mode);
|
||||
/// Get the cursor position in the current file.
|
||||
SizeType Tell();
|
||||
/// Is the cursor at the end of the file?
|
||||
@@ -87,7 +92,7 @@ namespace AZ
|
||||
/// Return disc offset if possible, otherwise 0
|
||||
SizeType DiskOffset() const;
|
||||
/// Return file name or NULL if file is not open.
|
||||
AZ_FORCE_INLINE const char* Name() const { return m_fileName; }
|
||||
AZ_FORCE_INLINE const char* Name() const { return m_fileName.c_str(); }
|
||||
bool IsOpen() const;
|
||||
|
||||
/// Return native handle to the file.
|
||||
@@ -124,12 +129,12 @@ namespace AZ
|
||||
|
||||
private:
|
||||
static void CreatePath(const char * fileName);
|
||||
|
||||
|
||||
bool PlatformOpen(int mode, int platformFlags);
|
||||
void PlatformClose();
|
||||
|
||||
FileHandleType m_handle;
|
||||
char m_fileName[AZ_MAX_PATH_LEN];
|
||||
|
||||
FileHandleType m_handle;
|
||||
AZ::IO::FixedMaxPathString m_fileName;
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
@@ -641,6 +641,8 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
else
|
||||
{
|
||||
// Set the default ProjectUserPath to the <engine-root>/user directory
|
||||
registry.Set(FilePathKey_ProjectUserPath, (engineRoot / "user").LexicallyNormal().Native());
|
||||
AZ_TracePrintf("SettingsRegistryMergeUtils",
|
||||
R"(Project path isn't set in the Settings Registry at "%.*s". Project-related filepaths will not be set)" "\n",
|
||||
aznumeric_cast<int>(projectPathKey.size()), projectPathKey.data());
|
||||
|
||||
@@ -101,7 +101,7 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
|
||||
createPath = (mode & SF_OPEN_CREATE_PATH) == SF_OPEN_CREATE_PATH;
|
||||
}
|
||||
|
||||
bool isApkFile = AZ::Android::Utils::IsApkPath(m_fileName);
|
||||
bool isApkFile = AZ::Android::Utils::IsApkPath(m_fileName.c_str());
|
||||
|
||||
if (createPath)
|
||||
{
|
||||
@@ -111,19 +111,19 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
|
||||
return false;
|
||||
}
|
||||
|
||||
CreatePath(m_fileName);
|
||||
CreatePath(m_fileName.c_str());
|
||||
}
|
||||
|
||||
int errorCode = 0;
|
||||
if (isApkFile)
|
||||
{
|
||||
AZ::u64 size = 0;
|
||||
m_handle = AZ::Android::APKFileHandler::Open(m_fileName, openMode, size);
|
||||
m_handle = AZ::Android::APKFileHandler::Open(m_fileName.c_str(), openMode, size);
|
||||
errorCode = EACCES; // general error when a file can't be opened from inside the APK
|
||||
}
|
||||
else
|
||||
{
|
||||
m_handle = fopen(m_fileName, openMode);
|
||||
m_handle = fopen(m_fileName.c_str(), openMode);
|
||||
errorCode = errno;
|
||||
}
|
||||
|
||||
@@ -233,7 +233,7 @@ namespace Platform
|
||||
}
|
||||
}
|
||||
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
|
||||
{
|
||||
if (handle != PlatformSpecificInvalidHandle)
|
||||
{
|
||||
|
||||
@@ -15,6 +15,9 @@
|
||||
#include <cstdio>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <AzCore/std/typetraits/underlying_type.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -23,6 +26,7 @@ namespace AZ
|
||||
namespace Internal
|
||||
{
|
||||
using SizeType = AZ::u64;
|
||||
using SeekSizeType = AZ::s64;
|
||||
using FileHandleType = FILE*;
|
||||
}
|
||||
|
||||
@@ -37,7 +41,7 @@ namespace AZ
|
||||
#else
|
||||
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
|
||||
#endif
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
|
||||
// Note: The TRUNC flag destroys the contents of the specified file.
|
||||
|
||||
|
||||
@@ -22,9 +22,10 @@ namespace AZ
|
||||
namespace Internal
|
||||
{
|
||||
using SizeType = AZ::u64;
|
||||
using SeekSizeType = AZ::s64;
|
||||
using FileHandleType = int;
|
||||
}
|
||||
|
||||
|
||||
namespace PosixInternal
|
||||
{
|
||||
enum class OpenFlags : int
|
||||
@@ -36,7 +37,7 @@ namespace AZ
|
||||
#else
|
||||
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
|
||||
#endif
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
|
||||
// Note: The TRUNC flag destroys the contents of the specified file.
|
||||
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <AzCore/std/typetraits/underlying_type.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -21,6 +24,7 @@ namespace AZ
|
||||
namespace Internal
|
||||
{
|
||||
using SizeType = AZ::u64;
|
||||
using SeekSizeType = AZ::s64;
|
||||
using FileHandleType = int;
|
||||
}
|
||||
|
||||
@@ -35,7 +39,7 @@ namespace AZ
|
||||
#else
|
||||
Temporary = 0, // (Not applicable for this platform) Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
|
||||
#endif
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Exclusive = O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Truncate = O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
|
||||
// Note: The TRUNC flag destroys the contents of the specified file.
|
||||
|
||||
|
||||
+3
-3
@@ -86,9 +86,9 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
|
||||
|
||||
if (createPath)
|
||||
{
|
||||
CreatePath(m_fileName);
|
||||
CreatePath(m_fileName.c_str());
|
||||
}
|
||||
m_handle = open(m_fileName, desiredAccess, permissions);
|
||||
m_handle = open(m_fileName.c_str(), desiredAccess, permissions);
|
||||
|
||||
if (m_handle == PlatformSpecificInvalidHandle)
|
||||
{
|
||||
@@ -119,7 +119,7 @@ namespace Platform
|
||||
{
|
||||
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
|
||||
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
|
||||
{
|
||||
if (handle != PlatformSpecificInvalidHandle)
|
||||
{
|
||||
|
||||
@@ -209,19 +209,19 @@ bool SystemFile::PlatformOpen(int mode, int platformFlags)
|
||||
|
||||
if (createPath)
|
||||
{
|
||||
CreatePath(m_fileName);
|
||||
CreatePath(m_fileName.c_str());
|
||||
}
|
||||
|
||||
# ifdef _UNICODE
|
||||
wchar_t fileNameW[AZ_MAX_PATH_LEN];
|
||||
size_t numCharsConverted;
|
||||
m_handle = INVALID_HANDLE_VALUE;
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName, AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
if (mbstowcs_s(&numCharsConverted, fileNameW, m_fileName.c_str(), AZ_ARRAY_SIZE(fileNameW) - 1) == 0)
|
||||
{
|
||||
m_handle = CreateFileW(fileNameW, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
|
||||
}
|
||||
# else //!_UNICODE
|
||||
m_handle = CreateFile(m_fileName, dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
|
||||
m_handle = CreateFile(m_fileName.c_str(), dwDesiredAccess, dwShareMode, 0, dwCreationDisposition, dwFlagsAndAttributes, 0);
|
||||
# endif // !_UNICODE
|
||||
|
||||
if (m_handle == INVALID_HANDLE_VALUE)
|
||||
@@ -261,7 +261,7 @@ namespace Platform
|
||||
{
|
||||
using FileHandleType = AZ::IO::SystemFile::FileHandleType;
|
||||
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SizeType offset, SystemFile::SeekMode mode)
|
||||
void Seek(FileHandleType handle, const SystemFile* systemFile, SystemFile::SeekSizeType offset, SystemFile::SeekMode mode)
|
||||
{
|
||||
if (handle != PlatformSpecificInvalidHandle)
|
||||
{
|
||||
|
||||
@@ -13,6 +13,9 @@
|
||||
|
||||
#include <fcntl.h>
|
||||
#include <corecrt_io.h>
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <AzCore/std/typetraits/underlying_type.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -21,6 +24,7 @@ namespace AZ
|
||||
namespace Internal
|
||||
{
|
||||
using SizeType = AZ::u64;
|
||||
using SeekSizeType = AZ::s64;
|
||||
using FileHandleType = void*;
|
||||
}
|
||||
|
||||
@@ -31,7 +35,7 @@ namespace AZ
|
||||
Append = _O_APPEND, // Moves the file pointer to the end of the file before every write operation.
|
||||
Create = _O_CREAT, // Creates a file and opens it for writing. Has no effect if the file specified by filename exists. PermissionMode is required.
|
||||
Temporary = _O_TEMPORARY, // Applies only when used with CREAT. Creates a file as temporary; the file is deleted when the last file descriptor is closed. PermissionMode equired when CREAT is specified.
|
||||
Exclusive = _O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Exclusive = _O_EXCL, // Applies only when used with CREAT. Returns an error value if a file specified by filename exists.
|
||||
Truncate = _O_TRUNC, // Opens a file and truncates it to zero length; the file must have write permission. Cannot be specified with RDONLY.
|
||||
// Note: The TRUNC flag destroys the contents of the specified file.
|
||||
|
||||
|
||||
@@ -711,8 +711,8 @@ namespace AzFramework
|
||||
}
|
||||
}
|
||||
|
||||
AZ::IO::FixedMaxPath projectUserPath;
|
||||
if (m_settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
|
||||
if (AZ::IO::FixedMaxPath projectUserPath;
|
||||
m_settingsRegistry->Get(projectUserPath.Native(), AZ::SettingsRegistryMergeUtils::FilePathKey_ProjectUserPath))
|
||||
{
|
||||
fileIoBase->SetAlias("@user@", projectUserPath.c_str());
|
||||
AZ::IO::FixedMaxPath projectLogPath = projectUserPath / "log";
|
||||
@@ -721,6 +721,15 @@ namespace AzFramework
|
||||
|
||||
CreateUserCache(projectUserPath, *fileIoBase);
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ::IO::FixedMaxPath fallbackLogPath = GetEngineRoot();
|
||||
fallbackLogPath /= "user";
|
||||
fileIoBase->SetAlias("@user@", fallbackLogPath.c_str());
|
||||
fallbackLogPath /= "log";
|
||||
fileIoBase->SetAlias("@log@", fallbackLogPath.c_str());
|
||||
fileIoBase->CreatePath(fallbackLogPath.c_str());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+14
-11
@@ -12,17 +12,22 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
|
||||
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorBus.h>
|
||||
#include <AzToolsFramework/Manipulators/ManipulatorManager.h>
|
||||
#include <AzToolsFramework/Manipulators/PlanarManipulator.h>
|
||||
|
||||
namespace AzManipulatorTestFramework
|
||||
{
|
||||
//! Create a linear manipulator with a unit sphere bounds.
|
||||
//! Create a linear manipulator with a unit sphere bound.
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> CreateLinearManipulator(
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
|
||||
const AZ::Vector3& position = AZ::Vector3::CreateZero(),
|
||||
const float radius = 1.0f);
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position = AZ::Vector3::CreateZero(),
|
||||
float radius = 1.0f);
|
||||
|
||||
//! Create a planar manipulator with a unit sphere bound.
|
||||
AZStd::shared_ptr<AzToolsFramework::PlanarManipulator> CreatePlanarManipulator(
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position = AZ::Vector3::CreateZero(),
|
||||
float radius = 1.0f);
|
||||
|
||||
//! Create a mouse pick from the specified ray and screen point.
|
||||
AzToolsFramework::ViewportInteraction::MousePick CreateMousePick(
|
||||
@@ -34,14 +39,12 @@ namespace AzManipulatorTestFramework
|
||||
|
||||
//! Create a mouse interaction from the specified pick, buttons, interaction id and keyboard modifiers.
|
||||
AzToolsFramework::ViewportInteraction::MouseInteraction CreateMouseInteraction(
|
||||
const AzToolsFramework::ViewportInteraction::MousePick& mousePick,
|
||||
AzToolsFramework::ViewportInteraction::MouseButtons buttons,
|
||||
const AzToolsFramework::ViewportInteraction::MousePick& mousePick, AzToolsFramework::ViewportInteraction::MouseButtons buttons,
|
||||
AzToolsFramework::ViewportInteraction::InteractionId interactionId,
|
||||
AzToolsFramework::ViewportInteraction::KeyboardModifiers modifiers);
|
||||
|
||||
//! Create a mouse buttons from the specified mouse button.
|
||||
AzToolsFramework::ViewportInteraction::MouseButtons CreateMouseButtons(
|
||||
AzToolsFramework::ViewportInteraction::MouseButton button);
|
||||
AzToolsFramework::ViewportInteraction::MouseButtons CreateMouseButtons(AzToolsFramework::ViewportInteraction::MouseButton button);
|
||||
|
||||
//! Create a mouse interaction event from the specified interaction and event.
|
||||
AzToolsFramework::ViewportInteraction::MouseInteractionEvent CreateMouseInteractionEvent(
|
||||
@@ -61,5 +64,5 @@ namespace AzManipulatorTestFramework
|
||||
AzFramework::ScreenPoint GetCameraStateViewportCenter(const AzFramework::CameraState& cameraState);
|
||||
|
||||
//! Default viewport size (1080p) in 16:9 aspect ratio.
|
||||
const auto DefaultViewportSize = AZ::Vector2(1920.0f, 1080.0f);
|
||||
inline const auto DefaultViewportSize = AZ::Vector2(1920.0f, 1080.0f);
|
||||
} // namespace AzManipulatorTestFramework
|
||||
|
||||
+36
-22
@@ -14,7 +14,6 @@
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorInteractionSystemViewportSelectionRequestBus.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorTransformComponentSelectionRequestBus.h>
|
||||
|
||||
namespace AzManipulatorTestFramework
|
||||
@@ -28,22 +27,21 @@ namespace AzManipulatorTestFramework
|
||||
using MouseEvent = AzToolsFramework::ViewportInteraction::MouseEvent;
|
||||
using MousePick = AzToolsFramework::ViewportInteraction::MousePick;
|
||||
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> CreateLinearManipulator(
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
|
||||
const AZ::Vector3& position,
|
||||
const float radius)
|
||||
// create a default sphere view for a manipulator for simple intersection
|
||||
template<typename Manipulator>
|
||||
void SetupManipulatorView(
|
||||
AZStd::shared_ptr<Manipulator> manipulator, const AzToolsFramework::ManipulatorManagerId manipulatorManagerId,
|
||||
const AZ::Vector3& position, const float radius)
|
||||
{
|
||||
auto manipulator = AzToolsFramework::LinearManipulator::MakeShared(AZ::Transform::CreateIdentity());
|
||||
manipulator->SetLocalPosition(position);
|
||||
|
||||
// unit sphere view
|
||||
auto sphereView = AzToolsFramework::CreateManipulatorViewSphere(
|
||||
AZ::Colors::Red, radius,
|
||||
[](const MouseInteraction& /*mouseInteraction*/, const bool /*mouseOver*/,
|
||||
const AZ::Color& defaultColor)
|
||||
{
|
||||
return defaultColor;
|
||||
}, true);
|
||||
[]([[maybe_unused]] const MouseInteraction& mouseInteraction, [[maybe_unused]] const bool mouseOver,
|
||||
const AZ::Color& defaultColor)
|
||||
{
|
||||
return defaultColor;
|
||||
},
|
||||
true);
|
||||
|
||||
// unit sphere bound
|
||||
AzToolsFramework::Picking::BoundShapeSphere sphereBound;
|
||||
@@ -62,6 +60,26 @@ namespace AzManipulatorTestFramework
|
||||
// this would occur internally when the manipulator is drawn but we must do manually here to ensure that the
|
||||
// bounds will always be valid upon instantiation
|
||||
view->RefreshBound(manipulatorManagerId, manipulator->GetManipulatorId(), sphereBound);
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> CreateLinearManipulator(
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position, const float radius)
|
||||
{
|
||||
auto manipulator = AzToolsFramework::LinearManipulator::MakeShared(AZ::Transform::CreateIdentity());
|
||||
manipulator->SetLocalPosition(position);
|
||||
|
||||
SetupManipulatorView(manipulator, manipulatorManagerId, position, radius);
|
||||
|
||||
return manipulator;
|
||||
}
|
||||
|
||||
AZStd::shared_ptr<AzToolsFramework::PlanarManipulator> CreatePlanarManipulator(
|
||||
const AzToolsFramework::ManipulatorManagerId manipulatorManagerId, const AZ::Vector3& position, const float radius)
|
||||
{
|
||||
auto manipulator = AzToolsFramework::PlanarManipulator::MakeShared(AZ::Transform::CreateIdentity());
|
||||
manipulator->SetLocalPosition(position);
|
||||
|
||||
SetupManipulatorView(manipulator, manipulatorManagerId, position, radius);
|
||||
|
||||
return manipulator;
|
||||
}
|
||||
@@ -104,8 +122,7 @@ namespace AzManipulatorTestFramework
|
||||
return buttons;
|
||||
}
|
||||
|
||||
MouseInteractionEvent CreateMouseInteractionEvent(
|
||||
const MouseInteraction& mouseInteraction, MouseEvent event)
|
||||
MouseInteractionEvent CreateMouseInteractionEvent(const MouseInteraction& mouseInteraction, MouseEvent event)
|
||||
{
|
||||
return MouseInteractionEvent(mouseInteraction, event);
|
||||
}
|
||||
@@ -114,8 +131,7 @@ namespace AzManipulatorTestFramework
|
||||
{
|
||||
AzToolsFramework::EditorInteractionSystemViewportSelectionRequestBus::Event(
|
||||
AzToolsFramework::GetEntityContextId(),
|
||||
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions,
|
||||
event);
|
||||
&AzToolsFramework::ViewportInteraction::InternalMouseViewportRequests::InternalHandleAllMouseInteractions, event);
|
||||
}
|
||||
|
||||
AzFramework::CameraState SetCameraStatePosition(const AZ::Vector3& position, AzFramework::CameraState& cameraState)
|
||||
@@ -133,9 +149,7 @@ namespace AzManipulatorTestFramework
|
||||
|
||||
AzFramework::ScreenPoint GetCameraStateViewportCenter(const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
return {
|
||||
aznumeric_cast<int>(cameraState.m_viewportSize.GetX() / 2.f),
|
||||
aznumeric_cast<int>(cameraState.m_viewportSize.GetY() / 2.f)
|
||||
};
|
||||
return { aznumeric_cast<int>(cameraState.m_viewportSize.GetX() / 2.f),
|
||||
aznumeric_cast<int>(cameraState.m_viewportSize.GetY() / 2.f) };
|
||||
}
|
||||
} // namespace UnitTest
|
||||
} // namespace AzManipulatorTestFramework
|
||||
|
||||
@@ -10,52 +10,55 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AzManipulatorTestFrameworkTestFixtures.h"
|
||||
|
||||
#include <AzCore/std/smart_ptr/unique_ptr.h>
|
||||
#include <AzFramework/Viewport/ViewportScreen.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFramework.h>
|
||||
#include "AzManipulatorTestFrameworkTestFixtures.h"
|
||||
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzManipulatorTestFramework/AzManipulatorTestFrameworkUtils.h>
|
||||
#include <AzManipulatorTestFramework/DirectManipulatorViewportInteraction.h>
|
||||
#include <AzManipulatorTestFramework/ImmediateModeActionDispatcher.h>
|
||||
#include <AzManipulatorTestFramework/IndirectManipulatorViewportInteraction.h>
|
||||
#include <AzToolsFramework/Manipulators/LinearManipulator.h>
|
||||
#include <AzToolsFramework/Manipulators/PlanarManipulator.h>
|
||||
#include <AzToolsFramework/ViewportSelection/EditorSelectionUtil.h>
|
||||
#include <AZTestShared/Math/MathTestHelpers.h>
|
||||
|
||||
namespace UnitTest
|
||||
{
|
||||
class GridSnappingFixture
|
||||
: public ToolsApplicationFixture
|
||||
class GridSnappingFixture : public ToolsApplicationFixture
|
||||
{
|
||||
public:
|
||||
GridSnappingFixture()
|
||||
: m_viewportManipulatorInteraction(AZStd::make_unique<AzManipulatorTestFramework::DirectCallManipulatorViewportInteraction>())
|
||||
, m_actionDispatcher(AZStd::make_unique<AzManipulatorTestFramework::ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction))
|
||||
, m_linearManipulator(
|
||||
AzManipulatorTestFramework::CreateLinearManipulator(
|
||||
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
|
||||
/*position=*/AZ::Vector3(0.0f, 50.0f, 0.0f),
|
||||
/*radius=*/m_boundsRadius))
|
||||
{}
|
||||
, m_actionDispatcher(
|
||||
AZStd::make_unique<AzManipulatorTestFramework::ImmediateModeActionDispatcher>(*m_viewportManipulatorInteraction))
|
||||
{
|
||||
}
|
||||
|
||||
protected:
|
||||
void SetUpEditorFixtureImpl() override
|
||||
{
|
||||
m_cameraState = AzFramework::CreateIdentityDefaultCamera(
|
||||
AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
|
||||
m_cameraState =
|
||||
AzFramework::CreateIdentityDefaultCamera(AZ::Vector3::CreateZero(), AzManipulatorTestFramework::DefaultViewportSize);
|
||||
}
|
||||
|
||||
public:
|
||||
|
||||
const float m_boundsRadius = 1.0f;
|
||||
AZStd::unique_ptr<AzManipulatorTestFramework::ManipulatorViewportInteraction> m_viewportManipulatorInteraction;
|
||||
AZStd::unique_ptr<AzManipulatorTestFramework::ImmediateModeActionDispatcher> m_actionDispatcher;
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> m_linearManipulator;
|
||||
AzFramework::CameraState m_cameraState;
|
||||
};
|
||||
|
||||
TEST_F(GridSnappingFixture, MouseDownWithSnappingEnabledSnapsToClosestGridSize)
|
||||
{
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> linearManipulator(AzManipulatorTestFramework::CreateLinearManipulator(
|
||||
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
|
||||
/*position=*/AZ::Vector3(0.0f, 50.0f, 0.0f),
|
||||
/*radius=*/m_boundsRadius));
|
||||
|
||||
// the initial starting position of the manipulator (in front of the camera)
|
||||
const auto initialPositionWorld = m_linearManipulator->GetLocalPosition();
|
||||
const auto initialPositionWorld = linearManipulator->GetLocalPosition();
|
||||
// where the manipulator should end up (in front and to the left of the camera)
|
||||
const auto finalPositionWorld = AZ::Vector3(-10.0f, 50.0f, 0.0f);
|
||||
// perspective scale factor for manipulator distance to camera
|
||||
@@ -66,21 +69,18 @@ namespace UnitTest
|
||||
// adjusted final world position taking into account the manipulator position relative to the camera
|
||||
const auto finalPositionWorldAdjusted = finalPositionWorld - (vectorToInitialPositionWorld * scaledRadiusBound);
|
||||
// calculate the position in screen space of the initial position of the manipulator
|
||||
const auto initialPositionScreen =
|
||||
AzFramework::WorldToScreen(initialPositionWorld, m_cameraState);
|
||||
const auto initialPositionScreen = AzFramework::WorldToScreen(initialPositionWorld, m_cameraState);
|
||||
// calculate the position in screen space of the final position of the manipulator
|
||||
const auto finalPositionScreen = AzFramework::WorldToScreen(finalPositionWorldAdjusted, m_cameraState);
|
||||
|
||||
// callback to update the manipulator's current position
|
||||
m_linearManipulator->InstallMouseMoveCallback(
|
||||
[this](const AzToolsFramework::LinearManipulator::Action& action)
|
||||
{
|
||||
auto pos = action.LocalPosition();
|
||||
m_linearManipulator->SetLocalPosition(pos);
|
||||
});
|
||||
linearManipulator->InstallMouseMoveCallback(
|
||||
[this, linearManipulator](const AzToolsFramework::LinearManipulator::Action& action)
|
||||
{
|
||||
linearManipulator->SetLocalPosition(action.LocalPosition());
|
||||
});
|
||||
|
||||
m_actionDispatcher
|
||||
->EnableSnapToGrid()
|
||||
m_actionDispatcher->EnableSnapToGrid()
|
||||
->GridSize(5.0f)
|
||||
->CameraState(m_cameraState)
|
||||
->MousePosition(initialPositionScreen)
|
||||
@@ -89,7 +89,67 @@ namespace UnitTest
|
||||
->MousePosition(finalPositionScreen)
|
||||
->MouseLButtonUp()
|
||||
->ExpectManipulatorNotBeingInteracted()
|
||||
->ExpectTrue(m_linearManipulator->GetLocalPosition().IsClose(finalPositionWorld, 0.01f))
|
||||
;
|
||||
->ExpectTrue(linearManipulator->GetLocalPosition().IsClose(finalPositionWorld, 0.01f));
|
||||
}
|
||||
|
||||
template<typename Manipulator>
|
||||
void ValidateManipulatorSnappingBehavior(
|
||||
AZStd::shared_ptr<Manipulator> manipulator, AzManipulatorTestFramework::ImmediateModeActionDispatcher* actionDispatcher,
|
||||
const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
manipulator->SetLocalOrientation(AZ::Quaternion::CreateFromEulerAnglesDegrees(AZ::Vector3(180.0f, 0.0f, 135.0f)));
|
||||
|
||||
// the initial starting position of the manipulator (in front of the camera)
|
||||
const auto initialPositionWorld = manipulator->GetLocalPosition() + AZ::Vector3::CreateAxisX(0.15f);
|
||||
// where the manipulator should end up (unmoved)
|
||||
const auto finalPositionWorld = manipulator->GetLocalPosition();
|
||||
// where we should move the mouse to
|
||||
const auto attemptPositionWorld = manipulator->GetLocalPosition() + AZ::Vector3::CreateAxisX(0.35f);
|
||||
// calculate the position in screen space of the initial position of the manipulator
|
||||
const auto initialPositionScreen = AzFramework::WorldToScreen(initialPositionWorld, cameraState);
|
||||
// calculate the position in screen space of the final position of the manipulator
|
||||
const auto attemptPositionScreen = AzFramework::WorldToScreen(attemptPositionWorld, cameraState);
|
||||
|
||||
// callback to update the manipulator's current position
|
||||
manipulator->InstallMouseMoveCallback(
|
||||
[manipulator](const typename Manipulator::Action& action)
|
||||
{
|
||||
manipulator->SetLocalPosition(action.LocalPosition());
|
||||
});
|
||||
|
||||
actionDispatcher->EnableSnapToGrid()
|
||||
->GridSize(1.0f)
|
||||
->CameraState(cameraState)
|
||||
->MousePosition(initialPositionScreen)
|
||||
->MouseLButtonDown()
|
||||
->ExpectManipulatorBeingInteracted()
|
||||
->MousePosition(attemptPositionScreen)
|
||||
->MouseLButtonUp()
|
||||
->ExpectManipulatorNotBeingInteracted()
|
||||
->ExpectThat(manipulator->GetLocalPosition(), IsCloseTolerance(finalPositionWorld, 0.01f));
|
||||
}
|
||||
|
||||
TEST_F(GridSnappingFixture, MouseDownAndMoveLinearManipulatorDoesNotSnapWithMovementSmallerThanHalfGridSize)
|
||||
{
|
||||
AZStd::shared_ptr<AzToolsFramework::LinearManipulator> linearManipulator(AzManipulatorTestFramework::CreateLinearManipulator(
|
||||
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
|
||||
/*position=*/AZ::Vector3(0.0f, 10.0f, 0.0f),
|
||||
/*radius=*/m_boundsRadius));
|
||||
|
||||
linearManipulator->SetAxis(AZ::Vector3::CreateAxisY());
|
||||
|
||||
ValidateManipulatorSnappingBehavior(linearManipulator, m_actionDispatcher.get(), m_cameraState);
|
||||
}
|
||||
|
||||
TEST_F(GridSnappingFixture, MouseDownAndMovePlanarManipulatorDoesNotSnapWithMovementSmallerThanHalfGridSize)
|
||||
{
|
||||
AZStd::shared_ptr<AzToolsFramework::PlanarManipulator> planarManipulator(AzManipulatorTestFramework::CreatePlanarManipulator(
|
||||
m_viewportManipulatorInteraction->GetManipulatorManager().GetId(),
|
||||
/*position=*/AZ::Vector3(0.0f, 10.0f, 0.0f),
|
||||
/*radius=*/m_boundsRadius));
|
||||
|
||||
planarManipulator->SetAxes(AZ::Vector3::CreateAxisY(), AZ::Vector3::CreateAxisZ());
|
||||
|
||||
ValidateManipulatorSnappingBehavior(planarManipulator, m_actionDispatcher.get(), m_cameraState);
|
||||
}
|
||||
} // namespace UnitTest
|
||||
|
||||
@@ -139,7 +139,7 @@ namespace AzNetworking
|
||||
|
||||
NetworkOutputSerializer networkSerializer(buffer.GetBuffer(), buffer.GetSize());
|
||||
{
|
||||
ISerializer& serializer = networkSerializer; // To get the default typeinfo parameters in ISerializer
|
||||
ISerializer& networkISerializer = networkSerializer; // To get the default typeinfo parameters in ISerializer
|
||||
|
||||
// First, serialize out the header
|
||||
if (!header.SerializePacketFlags(networkSerializer))
|
||||
@@ -148,7 +148,7 @@ namespace AzNetworking
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!serializer.Serialize(header, "Header"))
|
||||
if (!networkISerializer.Serialize(header, "Header"))
|
||||
{
|
||||
AZLOG(NET_FragmentQueue, "Reconstructed fragmented packet failed header serialization");
|
||||
return false;
|
||||
|
||||
@@ -433,6 +433,11 @@ namespace AzToolsFramework
|
||||
return m_manipulatorSpaceWithLocalTransform.GetSpace();
|
||||
}
|
||||
|
||||
const AZ::Vector3& Manipulators::GetNonUniformScale() const
|
||||
{
|
||||
return m_manipulatorSpaceWithLocalTransform.GetNonUniformScale();
|
||||
}
|
||||
|
||||
void Manipulators::SetSpace(const AZ::Transform& worldFromLocal)
|
||||
{
|
||||
m_manipulatorSpaceWithLocalTransform.SetSpace(worldFromLocal);
|
||||
|
||||
+13
-14
@@ -192,8 +192,7 @@ namespace AzToolsFramework
|
||||
/// for each vertex associated with the translation manipulator to use with offset calculations when updating.
|
||||
template<typename Vertex>
|
||||
void InitializeVertexLookup(
|
||||
IndexedTranslationManipulator<Vertex>& translationManipulator,
|
||||
const AZ::EntityId entityId, const AZ::Vector3& snapOffset)
|
||||
IndexedTranslationManipulator<Vertex>& translationManipulator, const AZ::EntityId entityId)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
|
||||
@@ -202,7 +201,7 @@ namespace AzToolsFramework
|
||||
AZ::FixedVerticesRequestBus<Vertex>::Bind(fixedVertices, entityId);
|
||||
|
||||
translationManipulator.Process(
|
||||
[snapOffset, fixedVertices]
|
||||
[fixedVertices]
|
||||
(typename IndexedTranslationManipulator<Vertex>::VertexLookup& vertexLookup)
|
||||
{
|
||||
Vertex vertex;
|
||||
@@ -213,7 +212,7 @@ namespace AzToolsFramework
|
||||
|
||||
if (found)
|
||||
{
|
||||
vertexLookup.m_start = vertex + AZ::AdaptVertexIn<Vertex>(snapOffset);
|
||||
vertexLookup.m_start = vertex;
|
||||
vertexLookup.m_offset = Vertex::CreateZero();
|
||||
}
|
||||
});
|
||||
@@ -250,10 +249,10 @@ namespace AzToolsFramework
|
||||
|
||||
// linear manipulator callbacks
|
||||
m_translationManipulator->m_manipulator.InstallLinearManipulatorMouseDownCallback(
|
||||
[this](const LinearManipulator::Action& action)
|
||||
[this]([[maybe_unused]] const LinearManipulator::Action& action)
|
||||
{
|
||||
BeginBatchMovement();
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId(), action.m_start.m_positionSnapOffset);
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId());
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallLinearManipulatorMouseMoveCallback(
|
||||
@@ -264,17 +263,17 @@ namespace AzToolsFramework
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallLinearManipulatorMouseUpCallback(
|
||||
[this](const LinearManipulator::Action& /*action*/)
|
||||
[this]([[maybe_unused]] const LinearManipulator::Action& action)
|
||||
{
|
||||
EndBatchMovement();
|
||||
});
|
||||
|
||||
// planar manipulator callbacks
|
||||
m_translationManipulator->m_manipulator.InstallPlanarManipulatorMouseDownCallback(
|
||||
[this](const PlanarManipulator::Action& action)
|
||||
[this]([[maybe_unused]] const PlanarManipulator::Action& action)
|
||||
{
|
||||
BeginBatchMovement();
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId(), action.m_start.m_snapOffset);
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId());
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallPlanarManipulatorMouseMoveCallback(
|
||||
@@ -285,17 +284,17 @@ namespace AzToolsFramework
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallPlanarManipulatorMouseUpCallback(
|
||||
[this](const PlanarManipulator::Action& /*action*/)
|
||||
[this]([[maybe_unused]] const PlanarManipulator::Action& action)
|
||||
{
|
||||
EndBatchMovement();
|
||||
});
|
||||
|
||||
// surface manipulator callbacks
|
||||
m_translationManipulator->m_manipulator.InstallSurfaceManipulatorMouseDownCallback(
|
||||
[this](const SurfaceManipulator::Action& action)
|
||||
[this]([[maybe_unused]] const SurfaceManipulator::Action& action)
|
||||
{
|
||||
BeginBatchMovement();
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId(), action.m_start.m_snapOffset);
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId());
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallSurfaceManipulatorMouseMoveCallback(
|
||||
@@ -306,7 +305,7 @@ namespace AzToolsFramework
|
||||
});
|
||||
|
||||
m_translationManipulator->m_manipulator.InstallSurfaceManipulatorMouseUpCallback(
|
||||
[this](const SurfaceManipulator::Action& /*action*/)
|
||||
[this]([[maybe_unused]] const SurfaceManipulator::Action& action)
|
||||
{
|
||||
EndBatchMovement();
|
||||
});
|
||||
@@ -893,7 +892,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
BeginBatchMovement();
|
||||
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId(), AZ::Vector3::CreateZero());
|
||||
InitializeVertexLookup(*m_translationManipulator, GetEntityId());
|
||||
// note: AdaptVertexIn/Out is to ensure we clamp the vertex local Z position to 0 if
|
||||
// dealing with Vector2s when setting the position of the manipulator.
|
||||
const AZ::Vector3 localOffset =
|
||||
|
||||
+26
-44
@@ -23,8 +23,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
LinearManipulator::Starter CalculateLinearManipulationDataStart(
|
||||
const LinearManipulator::Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapAction& gridSnapAction, const ViewportInteraction::MouseInteraction& interaction,
|
||||
const float intersectionDistance, const AzFramework::CameraState& cameraState)
|
||||
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, const float intersectionDistance,
|
||||
const AzFramework::CameraState& cameraState)
|
||||
{
|
||||
const ManipulatorInteraction manipulatorInteraction =
|
||||
BuildManipulatorInteraction(
|
||||
@@ -50,28 +50,9 @@ namespace AzToolsFramework
|
||||
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
|
||||
localIntersectionPoint, startTransition.m_localNormal, start.m_localHitPosition);
|
||||
|
||||
const float gridSize = gridSnapAction.m_gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapAction.m_gridSnapParams.m_gridSnap;
|
||||
const float scaleRecip = manipulatorInteraction.m_scaleReciprocal;
|
||||
|
||||
// calculate position amount to snap, to align with grid
|
||||
const AZ::Vector3 positionSnapOffset = snapping && !gridSnapAction.m_localSnapping
|
||||
? CalculateSnappedOffset(localTransform.GetTranslation(), axis, gridSize * scaleRecip)
|
||||
: AZ::Vector3::CreateZero();
|
||||
|
||||
const AZ::Vector3 localScale = AZ::Vector3(localTransform.GetUniformScale());
|
||||
const AZ::Quaternion localRotation = QuaternionFromTransformNoScaling(localTransform);
|
||||
// calculate scale amount to snap, to align to round scale value
|
||||
const AZ::Vector3 scaleSnapOffset = snapping && !gridSnapAction.m_localSnapping
|
||||
? localRotation.GetInverseFull().TransformVector(CalculateSnappedOffset(
|
||||
localRotation.TransformVector(localScale), axis, gridSize * scaleRecip))
|
||||
: AZ::Vector3::CreateZero();
|
||||
|
||||
start.m_screenPosition = interaction.m_mousePick.m_screenCoordinates;
|
||||
start.m_positionSnapOffset = positionSnapOffset;
|
||||
start.m_scaleSnapOffset = scaleSnapOffset;
|
||||
start.m_localPosition = localTransform.GetTranslation() + positionSnapOffset;
|
||||
start.m_localScale = localScale + scaleSnapOffset;
|
||||
start.m_localPosition = localTransform.GetTranslation();
|
||||
start.m_localScale = AZ::Vector3(localTransform.GetUniformScale());;
|
||||
start.m_localAxis = axis;
|
||||
// sign to determine which side of the linear axis we pressed
|
||||
// (useful to know when the visual axis flips to face the camera)
|
||||
@@ -87,7 +68,7 @@ namespace AzToolsFramework
|
||||
LinearManipulator::Action CalculateLinearManipulationDataAction(
|
||||
const LinearManipulator::Fixed& fixed, const LinearManipulator::Starter& starter,
|
||||
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
|
||||
const GridSnapAction& gridSnapAction, const ViewportInteraction::MouseInteraction& interaction)
|
||||
const GridSnapParameters& gridSnapParams, const ViewportInteraction::MouseInteraction& interaction)
|
||||
{
|
||||
const ManipulatorInteraction manipulatorInteraction =
|
||||
BuildManipulatorInteraction(
|
||||
@@ -108,31 +89,34 @@ namespace AzToolsFramework
|
||||
GetCameraState(interaction.m_interactionId.m_viewportId));
|
||||
|
||||
const AZ::Vector3 axis = TransformDirectionNoScaling(localTransform, fixed.m_axis);
|
||||
// The local positions have been transformed to the reference frame of the object being manipulated. But they appear in the world
|
||||
// with non-uniform scale applied, and the object being manipulated will want to work with unscaled deltas, so we need to divide by
|
||||
// the non-uniform scale here.
|
||||
// the local positions have been transformed to the reference frame of the object being manipulated, but they appear in the world
|
||||
// with non-uniform scale applied, the object being manipulated will want to work with unscaled deltas, so we need to divide by
|
||||
// the non-uniform scale here
|
||||
const AZ::Vector3 hitDelta = (localHitPosition - start.m_localHitPosition) / nonUniformScale;
|
||||
const AZ::Vector3 unsnappedOffset = axis * axis.Dot(hitDelta);
|
||||
|
||||
const float scaleRecip = manipulatorInteraction.m_scaleReciprocal * axis.Dot(manipulatorInteraction.m_nonUniformScaleReciprocal);
|
||||
const float gridSize = gridSnapAction.m_gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapAction.m_gridSnapParams.m_gridSnap;
|
||||
const float scaleRecip =
|
||||
manipulatorInteraction.m_scaleReciprocal * fixed.m_axis.Dot(manipulatorInteraction.m_nonUniformScaleReciprocal);
|
||||
const float gridSize = gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapParams.m_gridSnap;
|
||||
|
||||
LinearManipulator::Action action;
|
||||
action.m_fixed = fixed;
|
||||
action.m_start = start;
|
||||
action.m_current.m_localPositionOffset = snapping
|
||||
? unsnappedOffset + CalculateSnappedOffset(unsnappedOffset, axis, gridSize * scaleRecip)
|
||||
? CalculateSnappedAmount(unsnappedOffset, axis, gridSize * scaleRecip)
|
||||
: unsnappedOffset;
|
||||
action.m_current.m_screenPosition = interaction.m_mousePick.m_screenCoordinates;
|
||||
action.m_viewportId = interaction.m_interactionId.m_viewportId;
|
||||
|
||||
const AZ::Quaternion localRotation = QuaternionFromTransformNoScaling(localTransform);
|
||||
const AZ::Vector3 scaledUnsnappedOffset = unsnappedOffset * startTransition.m_screenToWorldScale * NonUniformScaleReciprocal(nonUniformScale);
|
||||
const AZ::Vector3 scaledUnsnappedOffset =
|
||||
unsnappedOffset * startTransition.m_screenToWorldScale * NonUniformScaleReciprocal(nonUniformScale);
|
||||
|
||||
// how much to adjust the scale based on movement
|
||||
const AZ::Quaternion invLocalRotation = localRotation.GetInverseFull();
|
||||
action.m_current.m_localScaleOffset = snapping
|
||||
? invLocalRotation.TransformVector((scaledUnsnappedOffset + CalculateSnappedOffset(scaledUnsnappedOffset, axis, gridSize * scaleRecip)))
|
||||
? invLocalRotation.TransformVector(CalculateSnappedAmount(scaledUnsnappedOffset, axis, gridSize * scaleRecip))
|
||||
: invLocalRotation.TransformVector(scaledUnsnappedOffset);
|
||||
|
||||
// record what modifier keys are held during this action
|
||||
@@ -171,19 +155,18 @@ namespace AzToolsFramework
|
||||
const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
|
||||
{
|
||||
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
|
||||
// note: m_localTransform must not be made uniform as it may contain a local scale we want to snap
|
||||
m_starter = CalculateLinearManipulationDataStart(
|
||||
m_fixed, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction, rayIntersectionDistance,
|
||||
m_fixed, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), interaction, rayIntersectionDistance,
|
||||
GetCameraState(interaction.m_interactionId.m_viewportId));
|
||||
|
||||
if (m_onLeftMouseDownCallback)
|
||||
{
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
|
||||
m_onLeftMouseDownCallback(CalculateLinearManipulationDataAction(
|
||||
m_fixed, m_starter, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
m_fixed, m_starter, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), gridSnapParams, interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,8 +178,8 @@ namespace AzToolsFramework
|
||||
|
||||
// note: m_localTransform must not be made uniform as it may contain a local scale we want to snap
|
||||
m_onMouseMoveCallback(CalculateLinearManipulationDataAction(
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams,
|
||||
interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,8 +191,7 @@ namespace AzToolsFramework
|
||||
|
||||
// note: m_localTransform must not be made uniform as it may contain a local scale we want to snap
|
||||
m_onLeftMouseUpCallback(CalculateLinearManipulationDataAction(
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams, interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -232,8 +214,8 @@ namespace AzToolsFramework
|
||||
GridSnapSettings(mouseInteraction.m_interactionId.m_viewportId);
|
||||
|
||||
const auto action = CalculateLinearManipulationDataAction(
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, mouseInteraction.m_keyboardModifiers.Alt()), mouseInteraction);
|
||||
m_fixed, m_starter, TransformUniformScale(GetSpace()), GetNonUniformScale(), GetLocalTransform(), gridSnapParams,
|
||||
mouseInteraction);
|
||||
|
||||
// display the exact hit (ray intersection) of the mouse pick on the manipulator
|
||||
DrawTransformAxes(
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
struct GridSnapAction;
|
||||
struct GridSnapParameters;
|
||||
|
||||
/// LinearManipulator serves as a visual tool for users to modify values
|
||||
/// in one dimension on an axis defined in 3D space.
|
||||
@@ -68,8 +68,6 @@ namespace AzToolsFramework
|
||||
AZ::Vector3 m_localScale; ///< The current scale of the manipulator in local space.
|
||||
AZ::Vector3 m_localHitPosition; ///< The intersection point in local space between the ray and the manipulator when the mouse down event happens.
|
||||
AZ::Vector3 m_localAxis; ///< The axis in the local space of the manipulator itself.
|
||||
AZ::Vector3 m_positionSnapOffset; ///< The snap offset amount to ensure manipulator is aligned to the grid.
|
||||
AZ::Vector3 m_scaleSnapOffset; ///< The snap offset amount to ensure manipulator is aligned to round scale increments.
|
||||
float m_sign; ///< Used to determine which side of the axis we clicked on in case it's flipped to face the camera.
|
||||
AzFramework::ScreenPoint m_screenPosition; ///< The initial position in screen space of the manipulator.
|
||||
};
|
||||
@@ -91,7 +89,7 @@ namespace AzToolsFramework
|
||||
ViewportInteraction::KeyboardModifiers m_modifiers;
|
||||
int m_viewportId; ///< The id of the viewport this manipulator is being used in.
|
||||
AZ::Vector3 LocalScale() const { return m_start.m_localScale + m_current.m_localScaleOffset; }
|
||||
AZ::Vector3 LocalScaleOffset() const { return m_start.m_scaleSnapOffset + m_current.m_localScaleOffset; }
|
||||
AZ::Vector3 LocalScaleOffset() const { return m_current.m_localScaleOffset; }
|
||||
AZ::Vector3 LocalPosition() const { return m_start.m_localPosition + m_current.m_localPositionOffset; }
|
||||
AZ::Vector3 LocalPositionOffset() const { return m_current.m_localPositionOffset; }
|
||||
AZ::Vector2 ScreenOffset() const
|
||||
@@ -162,11 +160,11 @@ namespace AzToolsFramework
|
||||
|
||||
LinearManipulator::Starter CalculateLinearManipulationDataStart(
|
||||
const LinearManipulator::Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapAction& gridSnapAction, const ViewportInteraction::MouseInteraction& interaction,
|
||||
float intersectionDistance, const AzFramework::CameraState& cameraState);
|
||||
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, float intersectionDistance,
|
||||
const AzFramework::CameraState& cameraState);
|
||||
|
||||
LinearManipulator::Action CalculateLinearManipulationDataAction(
|
||||
const LinearManipulator::Fixed& fixed, const LinearManipulator::Starter& starter,
|
||||
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
|
||||
const GridSnapAction& gridSnapAction, const ViewportInteraction::MouseInteraction& interaction);
|
||||
const GridSnapParameters& gridSnapParams, const ViewportInteraction::MouseInteraction& interaction);
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+25
-11
@@ -42,12 +42,6 @@ namespace AzToolsFramework
|
||||
{
|
||||
}
|
||||
|
||||
GridSnapAction::GridSnapAction(const GridSnapParameters& gridSnapParameters, const bool localSnapping)
|
||||
: m_gridSnapParams(gridSnapParameters)
|
||||
, m_localSnapping(localSnapping)
|
||||
{
|
||||
}
|
||||
|
||||
ManipulatorInteraction BuildManipulatorInteraction(
|
||||
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Vector3& worldRayOrigin, const AZ::Vector3& worldRayDirection)
|
||||
@@ -57,19 +51,39 @@ namespace AzToolsFramework
|
||||
|
||||
return {localFromWorldUniform.TransformPoint(worldRayOrigin),
|
||||
TransformDirectionNoScaling(localFromWorldUniform, worldRayDirection),
|
||||
ScaleReciprocal(worldFromLocalUniform),
|
||||
NonUniformScaleReciprocal(nonUniformScale)};
|
||||
NonUniformScaleReciprocal(nonUniformScale),
|
||||
ScaleReciprocal(worldFromLocalUniform)};
|
||||
}
|
||||
|
||||
AZ::Vector3 CalculateSnappedOffset(
|
||||
const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, const float size)
|
||||
struct SnapAdjustment
|
||||
{
|
||||
float m_existingSnapDistance; //!< How far to snap up or down to align to the grid.
|
||||
float m_nextSnapDistance; //!< The snap increment (will return full signed value (grid size) when distance
|
||||
//!< moved is greater than half of the grid size in either direction).
|
||||
};
|
||||
|
||||
static SnapAdjustment CalculateSnapDistance(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, const float size)
|
||||
{
|
||||
// calculate total distance along axis
|
||||
const float axisDistance = axis.Dot(unsnappedPosition);
|
||||
// round to nearest step size
|
||||
const float snappedAxisDistance = floorf((axisDistance / size) + 0.5f) * size;
|
||||
|
||||
return { axisDistance, snappedAxisDistance };
|
||||
}
|
||||
|
||||
AZ::Vector3 CalculateSnappedOffset(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, const float size)
|
||||
{
|
||||
const auto snapAdjustment = CalculateSnapDistance(unsnappedPosition, axis, size);
|
||||
// return offset along axis to snap to step size
|
||||
return axis * (snappedAxisDistance - axisDistance);
|
||||
return axis * (snapAdjustment.m_nextSnapDistance - snapAdjustment.m_existingSnapDistance);
|
||||
}
|
||||
|
||||
AZ::Vector3 CalculateSnappedAmount(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, const float size)
|
||||
{
|
||||
const auto snapAdjustment = CalculateSnapDistance(unsnappedPosition, axis, size);
|
||||
// return offset along axis to snap to step size
|
||||
return axis * snapAdjustment.m_nextSnapDistance;
|
||||
}
|
||||
|
||||
AZ::Vector3 CalculateSnappedTerrainPosition(
|
||||
|
||||
+9
-13
@@ -31,24 +31,15 @@ namespace AzToolsFramework
|
||||
float m_gridSize;
|
||||
};
|
||||
|
||||
/// Structure to encapsulate the current grid snapping state.
|
||||
struct GridSnapAction
|
||||
{
|
||||
GridSnapAction(const GridSnapParameters& gridSnapParameters, bool localSnapping);
|
||||
|
||||
GridSnapParameters m_gridSnapParams;
|
||||
bool m_localSnapping;
|
||||
};
|
||||
|
||||
/// Structure to hold transformed incoming viewport interaction from world space to manipulator space.
|
||||
struct ManipulatorInteraction
|
||||
{
|
||||
AZ::Vector3 m_localRayOrigin; ///< The ray origin (start) in the reference from of the manipulator.
|
||||
AZ::Vector3 m_localRayDirection; ///< The ray direction in the reference from of the manipulator.
|
||||
float m_scaleReciprocal; ///< The scale reciprocal (1.0 / scale) of the transform used to move the
|
||||
///< ray from world space to local space.
|
||||
AZ::Vector3 m_nonUniformScaleReciprocal; ///< Handles inverting any non-uniform scale which was applied
|
||||
///< separately from the transform.
|
||||
float m_scaleReciprocal; ///< The scale reciprocal (1.0 / scale) of the transform used to move the
|
||||
///< ray from world space to local space.
|
||||
};
|
||||
|
||||
/// Build a ManipulatorInteraction structure from the incoming viewport interaction.
|
||||
@@ -56,11 +47,16 @@ namespace AzToolsFramework
|
||||
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Vector3& worldRayOrigin, const AZ::Vector3& worldRayDirection);
|
||||
|
||||
/// Calculate the offset along an axis to adjust a position
|
||||
/// to stay snapped to a given grid size.
|
||||
/// Calculate the offset along an axis to adjust a position to stay snapped to a given grid size.
|
||||
/// @note This is snap up or down to the nearest grid segment (e.g. 0.2 snaps to 0.0 -> delta 0.2,
|
||||
/// 0.7 snaps to 1.0 -> delta 0.3).
|
||||
AZ::Vector3 CalculateSnappedOffset(
|
||||
const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size);
|
||||
|
||||
/// Return the amount to snap from the starting position given the current grid size.
|
||||
/// @note A movement of more than half size (in either direction) will cause a snap by size.
|
||||
AZ::Vector3 CalculateSnappedAmount(const AZ::Vector3& unsnappedPosition, const AZ::Vector3& axis, float size);
|
||||
|
||||
/// For a given point on the terrain, calculate the closest xy position snapped to the grid
|
||||
/// (z position is aligned to terrain height, not snapped to z grid)
|
||||
AZ::Vector3 CalculateSnappedTerrainPosition(
|
||||
|
||||
+10
-18
@@ -59,17 +59,16 @@ namespace AzToolsFramework
|
||||
const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
|
||||
const ViewportInteraction::MouseInteraction& interaction,
|
||||
const AZStd::vector<LinearManipulator::Fixed>& fixedAxes,
|
||||
const AZStd::vector<LinearManipulator::Starter>& starterStates, const GridSnapAction& gridSnapAction)
|
||||
const AZStd::vector<LinearManipulator::Starter>& starterStates, const GridSnapParameters& gridSnapParams)
|
||||
{
|
||||
MultiLinearManipulator::Action action;
|
||||
action.m_viewportId = interaction.m_interactionId.m_viewportId;
|
||||
// build up action state for each axis
|
||||
for (size_t fixedIndex = 0; fixedIndex < fixedAxes.size(); ++fixedIndex)
|
||||
{
|
||||
action.m_actions.push_back(
|
||||
CalculateLinearManipulationDataAction(
|
||||
fixedAxes[fixedIndex], starterStates[fixedIndex], worldFromLocal, nonUniformScale, localTransform,
|
||||
gridSnapAction, interaction));
|
||||
action.m_actions.push_back(CalculateLinearManipulationDataAction(
|
||||
fixedAxes[fixedIndex], starterStates[fixedIndex], worldFromLocal, nonUniformScale, localTransform, gridSnapParams,
|
||||
interaction));
|
||||
}
|
||||
|
||||
return action;
|
||||
@@ -79,8 +78,6 @@ namespace AzToolsFramework
|
||||
const ViewportInteraction::MouseInteraction& interaction, const float rayIntersectionDistance)
|
||||
{
|
||||
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
|
||||
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
const AzFramework::CameraState cameraState = GetCameraState(interaction.m_interactionId.m_viewportId);
|
||||
|
||||
// build up initial start state for each axis
|
||||
@@ -88,20 +85,19 @@ namespace AzToolsFramework
|
||||
{
|
||||
// note: m_localTransform must not be made uniform as it may contain a local scale we want to snap
|
||||
const auto linearStart = CalculateLinearManipulationDataStart(
|
||||
fixed, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction,
|
||||
rayIntersectionDistance, cameraState);
|
||||
fixed, worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(), interaction, rayIntersectionDistance,
|
||||
cameraState);
|
||||
|
||||
m_starters.push_back(linearStart);
|
||||
}
|
||||
|
||||
if (m_onLeftMouseDownCallback)
|
||||
{
|
||||
const GridSnapAction gridSnapAction = GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt());
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
// pass action containing all linear actions for each axis to handler
|
||||
m_onLeftMouseDownCallback(BuildMultiLinearManipulatorAction(
|
||||
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
interaction, m_fixedAxes, m_starters, gridSnapAction));
|
||||
interaction, m_fixedAxes, m_starters, gridSnapParams));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -111,11 +107,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
const GridSnapAction gridSnapAction = GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt());
|
||||
|
||||
m_onMouseMoveCallback(BuildMultiLinearManipulatorAction(
|
||||
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
interaction, m_fixedAxes, m_starters, gridSnapAction));
|
||||
interaction, m_fixedAxes, m_starters, gridSnapParams));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -125,11 +119,9 @@ namespace AzToolsFramework
|
||||
{
|
||||
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
const GridSnapAction gridSnapAction = GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt());
|
||||
|
||||
m_onLeftMouseUpCallback(BuildMultiLinearManipulatorAction(
|
||||
worldFromLocalUniformScale, GetNonUniformScale(), GetLocalTransform(),
|
||||
interaction, m_fixedAxes, m_starters, gridSnapAction));
|
||||
interaction, m_fixedAxes, m_starters, gridSnapParams));
|
||||
|
||||
m_starters.clear();
|
||||
}
|
||||
|
||||
@@ -20,8 +20,6 @@
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
struct GridSnapAction;
|
||||
|
||||
//! MultiLinearManipulator serves as a visual tool for users to modify values
|
||||
//! in one or more dimensions on axes defined in 3D space.
|
||||
class MultiLinearManipulator
|
||||
|
||||
+15
-35
@@ -22,8 +22,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
PlanarManipulator::StartInternal PlanarManipulator::CalculateManipulationDataStart(
|
||||
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapAction& gridSnapAction,
|
||||
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
|
||||
const ViewportInteraction::MouseInteraction& interaction, const float intersectionDistance)
|
||||
{
|
||||
const ManipulatorInteraction manipulatorInteraction =
|
||||
@@ -31,8 +30,6 @@ namespace AzToolsFramework
|
||||
worldFromLocal, nonUniformScale, interaction.m_mousePick.m_rayOrigin, interaction.m_mousePick.m_rayDirection);
|
||||
|
||||
const AZ::Vector3 normal = TransformDirectionNoScaling(localTransform, fixed.m_normal);
|
||||
const AZ::Vector3 axis1 = TransformDirectionNoScaling(localTransform, fixed.m_axis1);
|
||||
const AZ::Vector3 axis2 = TransformDirectionNoScaling(localTransform, fixed.m_axis2);
|
||||
|
||||
// initial intersect point
|
||||
const AZ::Vector3 localIntersectionPoint =
|
||||
@@ -43,25 +40,14 @@ namespace AzToolsFramework
|
||||
manipulatorInteraction.m_localRayOrigin, manipulatorInteraction.m_localRayDirection,
|
||||
localIntersectionPoint, normal, startInternal.m_localHitPosition);
|
||||
|
||||
const float scaleRecip = manipulatorInteraction.m_scaleReciprocal;
|
||||
const float gridSize = gridSnapAction.m_gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapAction.m_gridSnapParams.m_gridSnap;
|
||||
|
||||
// calculate amount to snap to align with grid
|
||||
const AZ::Vector3 snapOffset = snapping && !gridSnapAction.m_localSnapping
|
||||
? CalculateSnappedOffset(localTransform.GetTranslation(), axis1, gridSize * scaleRecip) +
|
||||
CalculateSnappedOffset(localTransform.GetTranslation(), axis2, gridSize * scaleRecip)
|
||||
: AZ::Vector3::CreateZero();
|
||||
|
||||
startInternal.m_snapOffset = snapOffset;
|
||||
startInternal.m_localPosition = localTransform.GetTranslation() + snapOffset;
|
||||
startInternal.m_localPosition = localTransform.GetTranslation();
|
||||
|
||||
return startInternal;
|
||||
}
|
||||
|
||||
PlanarManipulator::Action PlanarManipulator::CalculateManipulationDataAction(
|
||||
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal,
|
||||
const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform, const GridSnapAction& gridSnapAction,
|
||||
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapParameters& gridSnapParams,
|
||||
const ViewportInteraction::MouseInteraction& interaction)
|
||||
{
|
||||
const ManipulatorInteraction manipulatorInteraction =
|
||||
@@ -88,20 +74,18 @@ namespace AzToolsFramework
|
||||
const AZ::Vector3 hitDelta = (localHitPosition - startInternal.m_localHitPosition) / nonUniformScale;
|
||||
const AZ::Vector3 unsnappedOffset = axis1.Dot(hitDelta) * axis1 + axis2.Dot(hitDelta) * axis2;
|
||||
|
||||
const float scaleRecip = manipulatorInteraction.m_scaleReciprocal;
|
||||
const AZ::Vector3 nonUniformScaleRecip = manipulatorInteraction.m_nonUniformScaleReciprocal;
|
||||
const float gridSize = gridSnapAction.m_gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapAction.m_gridSnapParams.m_gridSnap;
|
||||
const float scaleRecip = manipulatorInteraction.m_scaleReciprocal;
|
||||
const float gridSize = gridSnapParams.m_gridSize;
|
||||
const bool snapping = gridSnapParams.m_gridSnap;
|
||||
|
||||
Action action;
|
||||
action.m_fixed = fixed;
|
||||
action.m_start.m_localPosition = startInternal.m_localPosition;
|
||||
action.m_start.m_snapOffset = startInternal.m_snapOffset;
|
||||
action.m_start.m_localHitPosition = startInternal.m_localHitPosition;
|
||||
action.m_current.m_localOffset = snapping
|
||||
? unsnappedOffset +
|
||||
CalculateSnappedOffset(unsnappedOffset, axis1, gridSize * scaleRecip * nonUniformScaleRecip.Dot(axis1)) +
|
||||
CalculateSnappedOffset(unsnappedOffset, axis2, gridSize * scaleRecip * nonUniformScaleRecip.Dot(axis2))
|
||||
? CalculateSnappedAmount(unsnappedOffset, axis1, gridSize * scaleRecip * nonUniformScaleRecip.Dot(fixed.m_axis1)) +
|
||||
CalculateSnappedAmount(unsnappedOffset, axis2, gridSize * scaleRecip * nonUniformScaleRecip.Dot(fixed.m_axis2))
|
||||
: unsnappedOffset;
|
||||
|
||||
// record what modifier keys are held during this action
|
||||
@@ -141,18 +125,17 @@ namespace AzToolsFramework
|
||||
{
|
||||
const AZ::Transform worldFromLocalUniformScale = TransformUniformScale(GetSpace());
|
||||
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
|
||||
m_startInternal = CalculateManipulationDataStart(
|
||||
m_fixed, worldFromLocalUniformScale, GetNonUniformScale(), TransformNormalizedScale(GetLocalTransform()),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()),
|
||||
interaction, rayIntersectionDistance);
|
||||
|
||||
if (m_onLeftMouseDownCallback)
|
||||
{
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(interaction.m_interactionId.m_viewportId);
|
||||
|
||||
m_onLeftMouseDownCallback(CalculateManipulationDataAction(
|
||||
m_fixed, m_startInternal, worldFromLocalUniformScale, GetNonUniformScale(), TransformNormalizedScale(GetLocalTransform()),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
gridSnapParams, interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,8 +147,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_onMouseMoveCallback(CalculateManipulationDataAction(
|
||||
m_fixed, m_startInternal, TransformUniformScale(GetSpace()), GetNonUniformScale(),
|
||||
TransformNormalizedScale(GetLocalTransform()),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
TransformNormalizedScale(GetLocalTransform()), gridSnapParams, interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -177,8 +159,7 @@ namespace AzToolsFramework
|
||||
|
||||
m_onLeftMouseUpCallback(CalculateManipulationDataAction(
|
||||
m_fixed, m_startInternal, TransformUniformScale(GetSpace()), GetNonUniformScale(),
|
||||
TransformNormalizedScale(GetLocalTransform()),
|
||||
GridSnapAction(gridSnapParams, interaction.m_keyboardModifiers.Alt()), interaction));
|
||||
TransformNormalizedScale(GetLocalTransform()), gridSnapParams, interaction));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -195,8 +176,7 @@ namespace AzToolsFramework
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(mouseInteraction.m_interactionId.m_viewportId);
|
||||
const auto action = CalculateManipulationDataAction(
|
||||
m_fixed, m_startInternal, TransformUniformScale(GetSpace()), GetNonUniformScale(),
|
||||
TransformNormalizedScale(GetLocalTransform()),
|
||||
GridSnapAction(gridSnapParams, mouseInteraction.m_keyboardModifiers.Alt()), mouseInteraction);
|
||||
TransformNormalizedScale(GetLocalTransform()), gridSnapParams, mouseInteraction);
|
||||
|
||||
// display the exact hit (ray intersection) of the mouse pick on the manipulator
|
||||
DrawTransformAxes(
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
class ManipulatorView;
|
||||
struct GridSnapAction;
|
||||
struct GridSnapParameters;
|
||||
|
||||
/// PlanarManipulator serves as a visual tool for users to modify values
|
||||
/// in two dimension in a plane defined two non-collinear axes in 3D space.
|
||||
@@ -58,7 +58,6 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ::Vector3 m_localPosition; ///< The current position of the manipulator in local space.
|
||||
AZ::Vector3 m_localHitPosition; ///< The intersection point in local space between the ray and the manipulator when the mouse down event happens.
|
||||
AZ::Vector3 m_snapOffset; ///< The snap offset amount to ensure manipulator is aligned to the grid.
|
||||
};
|
||||
|
||||
/// The state of the manipulator during an interaction.
|
||||
@@ -120,7 +119,6 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ::Vector3 m_localPosition; ///< The starting position of the manipulator in local space.
|
||||
AZ::Vector3 m_localHitPosition; ///< The intersection point in world space between the ray and the manipulator when the mouse down event happens.
|
||||
AZ::Vector3 m_snapOffset; ///< The snap offset amount to ensure manipulator is aligned to the grid.
|
||||
};
|
||||
|
||||
Fixed m_fixed;
|
||||
@@ -134,12 +132,11 @@ namespace AzToolsFramework
|
||||
|
||||
static StartInternal CalculateManipulationDataStart(
|
||||
const Fixed& fixed, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapAction& gridSnapAction,
|
||||
const ViewportInteraction::MouseInteraction& interaction, float intersectionDistance);
|
||||
const AZ::Transform& localTransform, const ViewportInteraction::MouseInteraction& interaction, float intersectionDistance);
|
||||
|
||||
static Action CalculateManipulationDataAction(
|
||||
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal,
|
||||
const AZ::Vector3& nonUniformScale, const AZ::Transform& localTransform,
|
||||
const GridSnapAction& gridSnapAction, const ViewportInteraction::MouseInteraction& interaction);
|
||||
const Fixed& fixed, const StartInternal& startInternal, const AZ::Transform& worldFromLocal, const AZ::Vector3& nonUniformScale,
|
||||
const AZ::Transform& localTransform, const GridSnapParameters& gridSnapParams,
|
||||
const ViewportInteraction::MouseInteraction& interaction);
|
||||
};
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
@@ -174,6 +174,8 @@ namespace AzToolsFramework
|
||||
static EntityAlias GenerateEntityAlias();
|
||||
AliasPath GetAbsoluteInstanceAliasPath() const;
|
||||
|
||||
static InstanceAlias GenerateInstanceAlias();
|
||||
|
||||
protected:
|
||||
/**
|
||||
* Gets the entities owned by this instance
|
||||
@@ -190,8 +192,6 @@ namespace AzToolsFramework
|
||||
bool RegisterEntity(const AZ::EntityId& entityId, const EntityAlias& entityAlias);
|
||||
AZStd::unique_ptr<AZ::Entity> DetachEntity(const EntityAlias& entityAlias);
|
||||
|
||||
static InstanceAlias GenerateInstanceAlias();
|
||||
|
||||
// Provide access to private data members in the serializer
|
||||
friend class JsonInstanceSerializer;
|
||||
friend class InstanceEntityIdMapper;
|
||||
|
||||
+24
@@ -152,6 +152,30 @@ namespace AzToolsFramework
|
||||
Instance::EntityList newEntities;
|
||||
if (PrefabDomUtils::LoadInstanceFromPrefabDom(*instanceToUpdate, newEntities, currentTemplate.GetPrefabDom()))
|
||||
{
|
||||
// If a link was created for a nested instance before the changes were propagated,
|
||||
// then we associate it correctly here
|
||||
instanceToUpdate->GetNestedInstances([&](AZStd::unique_ptr<Instance>& nestedInstance) {
|
||||
if (nestedInstance->GetLinkId() != InvalidLinkId)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (auto linkId : currentTemplate.GetLinks())
|
||||
{
|
||||
LinkReference nestedLink = m_prefabSystemComponentInterface->FindLink(linkId);
|
||||
if (!nestedLink.has_value())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (nestedLink->get().GetInstanceName() == nestedInstance->GetInstanceAlias())
|
||||
{
|
||||
nestedInstance->SetLinkId(linkId);
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
AzToolsFramework::EditorEntityContextRequestBus::Broadcast(
|
||||
&AzToolsFramework::EditorEntityContextRequests::HandleEntitiesAdded, newEntities);
|
||||
}
|
||||
|
||||
@@ -899,16 +899,29 @@ namespace AzToolsFramework
|
||||
|
||||
if (!EntitiesBelongToSameInstance(entityIds))
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Cannot duplicate multiple "
|
||||
"entities belonging to different instances with one operation."));
|
||||
return AZ::Failure(AZStd::string("Cannot duplicate multiple entities belonging to different instances with one operation."
|
||||
"Change your selection to contain entities in the same instance."));
|
||||
}
|
||||
|
||||
// We've already verified the entities are all owned by the same instance,
|
||||
// so we can just retrieve our instance from the first entity in the list.
|
||||
InstanceOptionalReference commonEntityOwningInstance = GetOwnerInstanceByEntityId(entityIds[0]);
|
||||
AZ_Assert(
|
||||
commonEntityOwningInstance.has_value(),
|
||||
"Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided");
|
||||
AZ::EntityId firstEntityIdToDuplicate = entityIds[0];
|
||||
InstanceOptionalReference commonOwningInstance = GetOwnerInstanceByEntityId(firstEntityIdToDuplicate);
|
||||
if (!commonOwningInstance.has_value())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided."));
|
||||
}
|
||||
|
||||
// If the first entity id is a container entity id, then we need to mark its parent as the common owning instance because you
|
||||
// cannot duplicate an instance from itself.
|
||||
if (commonOwningInstance->get().GetContainerEntityId() == firstEntityIdToDuplicate)
|
||||
{
|
||||
commonOwningInstance = commonOwningInstance->get().GetParentInstance();
|
||||
}
|
||||
if (!commonOwningInstance.has_value())
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to duplicate : Couldn't get a valid owning instance for the common root entity of the entities provided."));
|
||||
}
|
||||
|
||||
// This will cull out any entities that have ancestors in the list, since we will end up duplicating
|
||||
// the full nested hierarchy with what is returned from RetrieveAndSortPrefabEntitiesAndInstances
|
||||
@@ -921,105 +934,63 @@ namespace AzToolsFramework
|
||||
{
|
||||
AZ_PROFILE_SCOPE(AZ::Debug::ProfileCategory::AzToolsFramework, "DuplicateEntitiesInInstance::UndoCaptureAndDuplicateEntities");
|
||||
|
||||
// Take a snapshot of the instance DOM before we manipulate it
|
||||
Prefab::PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonEntityOwningInstance->get());
|
||||
|
||||
AZStd::vector<AZ::Entity*> entities;
|
||||
AZStd::vector<Instance*> instances;
|
||||
|
||||
// Gather all entities/instances in the hierarchy, but don't detach them because we are duplicating not deleting.
|
||||
EntityList inputEntityList = EntityIdSetToEntityList(duplicationSet);
|
||||
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonEntityOwningInstance->get(), entities, instances);
|
||||
bool success = RetrieveAndSortPrefabEntitiesAndInstances(inputEntityList, commonOwningInstance->get(), entities, instances);
|
||||
|
||||
if (!success)
|
||||
{
|
||||
return AZ::Failure(AZStd::string("Failed to retrieve entities and instances from the given list of entity ids for duplication"));
|
||||
}
|
||||
|
||||
// Make a copy of our before instance DOM where we will add our duplicated entities
|
||||
Prefab::PrefabDom instanceDomAfter;
|
||||
// Take a snapshot of the instance DOM before we manipulate it
|
||||
PrefabDom instanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(instanceDomBefore, commonOwningInstance->get());
|
||||
|
||||
// Make a copy of our before instance DOM where we will add our duplicated entities and/or instances
|
||||
PrefabDom instanceDomAfter;
|
||||
instanceDomAfter.CopyFrom(instanceDomBefore, instanceDomAfter.GetAllocator());
|
||||
|
||||
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
|
||||
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
|
||||
EntityIdList duplicatedEntityAndInstanceIds;
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
EntityAliasOptionalReference oldAliasRef = commonEntityOwningInstance->get().GetEntityAlias(entity->GetId());
|
||||
AZ_Assert(oldAliasRef.has_value(), "No alias found for Entity in the DOM");
|
||||
EntityAlias oldAlias = oldAliasRef.value();
|
||||
// Duplicate any nested entities and instances as requested
|
||||
AZStd::unordered_map<InstanceAlias, Instance*> newInstanceAliasToOldInstanceMap;
|
||||
DuplicateNestedEntitiesInInstance(commonOwningInstance->get(),
|
||||
entities, instanceDomAfter, duplicatedEntityAndInstanceIds);
|
||||
DuplicateNestedInstancesInInstance(commonOwningInstance->get(),
|
||||
instances, instanceDomAfter, duplicatedEntityAndInstanceIds,
|
||||
newInstanceAliasToOldInstanceMap);
|
||||
|
||||
// Give this the outer allocator so that the memory reference will be valid when
|
||||
// it gets used for AddMember
|
||||
Prefab::PrefabDom entityDomBefore(&instanceDomAfter.GetAllocator());
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDomBefore, *entity);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated entity
|
||||
// so we can fixup references later
|
||||
EntityAlias newEntityAlias = Instance::GenerateEntityAlias();
|
||||
oldAliasToNewAliasMap.insert(AZStd::make_pair(oldAlias, newEntityAlias));
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
entityDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Entity DOM with its new alias as a string
|
||||
// so that we can fixup entity alias references before adding it
|
||||
// to the Entities member of our instance DOM
|
||||
QString entityDomString(buffer.GetString());
|
||||
aliasToEntityDomMap.insert(AZStd::make_pair(newEntityAlias, entityDomString));
|
||||
}
|
||||
|
||||
auto entitiesIter = instanceDomAfter.FindMember(PrefabDomUtils::EntitiesName);
|
||||
AZ_Assert(entitiesIter != instanceDomAfter.MemberEnd(), "Instance DOM missing the Entities member.");
|
||||
|
||||
// Now that all the duplicated Entity DOMs have been created, we need to iterate
|
||||
// through them and replace any previous EntityAlias references with the new ones.
|
||||
// These are more than just parent entity references for nested entities, this will
|
||||
// also cover any EntityId references that were made in the components between them.
|
||||
for (auto aliasEntityPair : aliasToEntityDomMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasEntityPair.first;
|
||||
QString newEntityDomString = aliasEntityPair.second;
|
||||
|
||||
// Replace all of the old alias references with the new ones
|
||||
// We bookend the aliases with \" and also with a / as an extra precaution to prevent
|
||||
// inadvertently replacing a matching string vs. where an actual EntityId is expected
|
||||
// This will cover both cases where an alias could be used in a normal entity vs. an instance
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newEntityDomString, aliasMapIter.first, aliasMapIter.second);
|
||||
}
|
||||
|
||||
// Create the new Entity DOM from parsing the JSON string
|
||||
Prefab::PrefabDom entityDomAfter(&instanceDomAfter.GetAllocator());
|
||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Entity DOM to the Entities member of the instance
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), newEntityAlias.length(), instanceDomAfter.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, instanceDomAfter.GetAllocator());
|
||||
}
|
||||
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity duplication");
|
||||
PrefabUndoInstance* command = aznew PrefabUndoInstance("Entity/Instance duplication");
|
||||
command->SetParent(undoBatch.GetUndoBatch());
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonEntityOwningInstance->get().GetTemplateId());
|
||||
command->RunRedo();
|
||||
command->Capture(instanceDomBefore, instanceDomAfter, commonOwningInstance->get().GetTemplateId());
|
||||
command->Redo();
|
||||
|
||||
EntityIdList duplicatedEntityIds;
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
// Create links for our duplicated instances (if any were duplicated)
|
||||
for (auto [newInstanceAlias, oldInstance] : newInstanceAliasToOldInstanceMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasMapIter.second;
|
||||
LinkId oldLinkId = oldInstance->GetLinkId();
|
||||
auto linkRef = m_prefabSystemComponentInterface->FindLink(oldLinkId);
|
||||
AZ_Assert(
|
||||
linkRef.has_value(), "Unable to find link with id '%llu' during instance duplication.",
|
||||
oldLinkId);
|
||||
|
||||
AliasPath absoluteEntityPath = commonEntityOwningInstance->get().GetAbsoluteInstanceAliasPath();
|
||||
absoluteEntityPath.Append(newEntityAlias);
|
||||
PrefabDomValueReference linkPatches = linkRef->get().GetLinkPatches();
|
||||
AZ_Assert(
|
||||
linkPatches.has_value(), "Link with id '%llu' is missing patches.",
|
||||
oldLinkId);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteEntityPath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
PrefabDom linkPatchesCopy;
|
||||
linkPatchesCopy.CopyFrom(linkPatches->get(), linkPatchesCopy.GetAllocator());
|
||||
|
||||
m_prefabSystemComponentInterface->CreateLink(
|
||||
commonOwningInstance->get().GetTemplateId(), oldInstance->GetTemplateId(), newInstanceAlias, linkPatchesCopy);
|
||||
}
|
||||
|
||||
// Select the duplicated entities
|
||||
auto selectionUndo = aznew SelectionCommand(duplicatedEntityIds, "Select Duplicated Entities");
|
||||
// Select the duplicated entities/instances
|
||||
auto selectionUndo = aznew SelectionCommand(duplicatedEntityAndInstanceIds, "Select Duplicated Entities/Instances");
|
||||
selectionUndo->SetParent(undoBatch.GetUndoBatch());
|
||||
ToolsApplicationRequestBus::Broadcast(&ToolsApplicationRequestBus::Events::RunRedoSeparately, selectionUndo);
|
||||
}
|
||||
@@ -1508,8 +1479,159 @@ namespace AzToolsFramework
|
||||
return true;
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds)
|
||||
{
|
||||
if (entities.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<EntityAlias, EntityAlias> oldAliasToNewAliasMap;
|
||||
AZStd::unordered_map<EntityAlias, QString> aliasToEntityDomMap;
|
||||
|
||||
for (AZ::Entity* entity : entities)
|
||||
{
|
||||
EntityAliasOptionalReference oldAliasRef = commonOwningInstance.GetEntityAlias(entity->GetId());
|
||||
AZ_Assert(oldAliasRef.has_value(), "No alias found for Entity in the DOM");
|
||||
EntityAlias oldAlias = oldAliasRef.value();
|
||||
|
||||
// Give this the outer allocator so that the memory reference will be valid when
|
||||
// it gets used for AddMember
|
||||
PrefabDom entityDomBefore(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
m_instanceToTemplateInterface->GenerateDomForEntity(entityDomBefore, *entity);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated entity
|
||||
// so we can fixup references later
|
||||
EntityAlias newEntityAlias = Instance::GenerateEntityAlias();
|
||||
oldAliasToNewAliasMap.emplace(oldAlias, newEntityAlias);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
entityDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Entity DOM with its new alias as a string
|
||||
// so that we can fixup entity alias references before adding it
|
||||
// to the Entities member of our instance DOM
|
||||
QString entityDomString(buffer.GetString());
|
||||
aliasToEntityDomMap.emplace(newEntityAlias, entityDomString);
|
||||
}
|
||||
|
||||
auto entitiesIter = domToAddDuplicatedEntitiesUnder.FindMember(PrefabDomUtils::EntitiesName);
|
||||
AZ_Assert(entitiesIter != domToAddDuplicatedEntitiesUnder.MemberEnd(), "Instance DOM missing the Entities member.");
|
||||
|
||||
// Now that all the duplicated Entity DOMs have been created, we need to iterate
|
||||
// through them and replace any previous EntityAlias references with the new ones.
|
||||
// These are more than just parent entity references for nested entities, this will
|
||||
// also cover any EntityId references that were made in the components between them.
|
||||
for (auto [newEntityAlias, newEntityDomString] : aliasToEntityDomMap)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
for (auto [oldAlias, newAlias] : oldAliasToNewAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newEntityDomString, oldAlias, newAlias);
|
||||
}
|
||||
|
||||
// Create the new Entity DOM from parsing the JSON string
|
||||
PrefabDom entityDomAfter(&domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entityDomAfter.Parse(newEntityDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Entity DOM to the Entities member of the instance
|
||||
rapidjson::Value aliasName(newEntityAlias.c_str(), newEntityAlias.length(), domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
entitiesIter->value.AddMember(AZStd::move(aliasName), entityDomAfter, domToAddDuplicatedEntitiesUnder.GetAllocator());
|
||||
}
|
||||
|
||||
for (auto aliasMapIter : oldAliasToNewAliasMap)
|
||||
{
|
||||
EntityAlias newEntityAlias = aliasMapIter.second;
|
||||
|
||||
AliasPath absoluteEntityPath = commonOwningInstance.GetAbsoluteInstanceAliasPath();
|
||||
absoluteEntityPath.Append(newEntityAlias);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteEntityPath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::DuplicateNestedInstancesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<Instance*>& instances, PrefabDom& domToAddDuplicatedInstancesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<InstanceAlias, Instance*>& newInstanceAliasToOldInstanceMap)
|
||||
{
|
||||
if (instances.empty())
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AZStd::unordered_map<InstanceAlias, InstanceAlias> oldInstanceAliasToNewInstanceAliasMap;
|
||||
AZStd::unordered_map<InstanceAlias, QString> aliasToInstanceDomMap;
|
||||
|
||||
for (auto instance : instances)
|
||||
{
|
||||
PrefabDom nestedInstanceDomBefore;
|
||||
m_instanceToTemplateInterface->GenerateDomForInstance(nestedInstanceDomBefore, *instance);
|
||||
|
||||
// Keep track of the old alias <-> new alias mapping for this duplicated instance
|
||||
// so we can fixup references later
|
||||
InstanceAlias oldAlias = instance->GetInstanceAlias();
|
||||
InstanceAlias newInstanceAlias = Instance::GenerateInstanceAlias();
|
||||
oldInstanceAliasToNewInstanceAliasMap.emplace(oldAlias, newInstanceAlias);
|
||||
|
||||
// Keep track of our new instance alias with the Instance it was duplicated from,
|
||||
// so that after all instances are duplicated, we can go back and create links for them
|
||||
newInstanceAliasToOldInstanceMap.emplace(newInstanceAlias, instance);
|
||||
|
||||
rapidjson::StringBuffer buffer;
|
||||
rapidjson::Writer<rapidjson::StringBuffer> writer(buffer);
|
||||
nestedInstanceDomBefore.Accept(writer);
|
||||
|
||||
// Store our duplicated Instance DOM with its new alias as a string
|
||||
// so that we can fixup instance alias references before adding it
|
||||
// to the Instances member of our instance DOM
|
||||
QString instanceDomString(buffer.GetString());
|
||||
aliasToInstanceDomMap.emplace(newInstanceAlias, instanceDomString);
|
||||
}
|
||||
|
||||
auto instancesIter = domToAddDuplicatedInstancesUnder.FindMember(PrefabDomUtils::InstancesName);
|
||||
AZ_Assert(instancesIter != domToAddDuplicatedInstancesUnder.MemberEnd(), "Instance DOM missing the Instances member.");
|
||||
|
||||
// Now that all the duplicated Instance DOMs have been created, we need to iterate
|
||||
// through them and replace any previous InstanceAlias references with the new ones.
|
||||
for (auto [newInstanceAlias, newInstanceDomString]: aliasToInstanceDomMap)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
for (auto [oldAlias, newAlias] : oldInstanceAliasToNewInstanceAliasMap)
|
||||
{
|
||||
ReplaceOldAliases(newInstanceDomString, oldAlias, newAlias);
|
||||
}
|
||||
|
||||
// Create the new Instance DOM from parsing the JSON string
|
||||
PrefabDom nestedInstanceDomAfter(&domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
nestedInstanceDomAfter.Parse(newInstanceDomString.toUtf8().constData());
|
||||
|
||||
// Add the new Instance DOM to the Instances member of the instance
|
||||
rapidjson::Value aliasName(newInstanceAlias.c_str(), newInstanceAlias.length(), domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
instancesIter->value.AddMember(AZStd::move(aliasName), nestedInstanceDomAfter, domToAddDuplicatedInstancesUnder.GetAllocator());
|
||||
}
|
||||
|
||||
for (auto aliasMapIter : oldInstanceAliasToNewInstanceAliasMap)
|
||||
{
|
||||
InstanceAlias newInstanceAlias = aliasMapIter.second;
|
||||
|
||||
AliasPath absoluteInstancePath = commonOwningInstance.GetAbsoluteInstanceAliasPath();
|
||||
absoluteInstancePath.Append(newInstanceAlias);
|
||||
|
||||
AZ::EntityId newEntityId = InstanceEntityIdMapper::GenerateEntityIdForAliasPath(absoluteInstancePath);
|
||||
duplicatedEntityIds.push_back(newEntityId);
|
||||
}
|
||||
}
|
||||
|
||||
void PrefabPublicHandler::ReplaceOldAliases(QString& stringToReplace, AZStd::string_view oldAlias, AZStd::string_view newAlias)
|
||||
{
|
||||
// Replace all of the old alias references with the new ones
|
||||
// We bookend the aliases with \" and also with a / as an extra precaution to prevent
|
||||
// inadvertently replacing a matching string vs. where an actual EntityId is expected
|
||||
// This will cover both cases where an alias could be used in a normal entity vs. an instance
|
||||
QString oldAliasQuotes = QString("\"%1\"").arg(oldAlias.data());
|
||||
QString newAliasQuotes = QString("\"%1\"").arg(newAlias.data());
|
||||
|
||||
|
||||
@@ -73,6 +73,33 @@ namespace AzToolsFramework
|
||||
|
||||
InstanceOptionalReference GetOwnerInstanceByEntityId(AZ::EntityId entityId) const;
|
||||
bool EntitiesBelongToSameInstance(const EntityIdList& entityIds) const;
|
||||
|
||||
/**
|
||||
* Duplicate a list of entities owned by a common owning instance by directly
|
||||
* copying/modifying their entries in the instance DOM
|
||||
*
|
||||
* \param commonOwningInstance The common owning instance of all the entities being duplicated.
|
||||
* \param entities The list of Entities that will be duplicated.
|
||||
* \param domToAddDuplicatedEntitiesUnder The DOM of the common owning instance where the duplicated
|
||||
* entity DOM values will be added to.
|
||||
* \param duplicatedEntityIds A list of EntityIds corresponding to the entities that were duplicated.
|
||||
*/
|
||||
void DuplicateNestedEntitiesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<AZ::Entity*>& entities, PrefabDom& domToAddDuplicatedEntitiesUnder,
|
||||
EntityIdList& duplicatedEntityIds);
|
||||
/**
|
||||
* Duplicate a list of instances owned by a common owning instance by directly
|
||||
* copying/modifying their entries in the instance DOM
|
||||
*
|
||||
* \param commonOwningInstance The common owning instance of all the instances being duplicated.
|
||||
* \param entities The list of Instances that will be duplicated.
|
||||
* \param domToAddDuplicatedInstancesUnder The DOM of the common owning instance where the duplicated
|
||||
* instance DOM values will be added to.
|
||||
* \param duplicatedEntityIds A list of EntityIds corresponding to the instances that were duplicated.
|
||||
*/
|
||||
void DuplicateNestedInstancesInInstance(Instance& commonOwningInstance,
|
||||
const AZStd::vector<Instance*>& instances, PrefabDom& domToAddDuplicatedInstancesUnder,
|
||||
EntityIdList& duplicatedEntityIds, AZStd::unordered_map<InstanceAlias, Instance*>& newInstanceAliasToOldInstanceMap);
|
||||
|
||||
/**
|
||||
* Applies the correct transform changes to the container entity based on the parent and child entities provided, and returns an appropriate patch.
|
||||
|
||||
+28
-20
@@ -37,13 +37,13 @@ namespace AzToolsFramework
|
||||
axisLength, AzFramework::ViewportColors::XAxisColor, AzFramework::ViewportColors::YAxisColor,
|
||||
AzFramework::ViewportColors::ZAxisColor);
|
||||
|
||||
auto mouseDownCallback = [this](const LinearManipulator::Action& action) {
|
||||
auto mouseDownCallback = [this]([[maybe_unused]] const LinearManipulator::Action& action)
|
||||
{
|
||||
AZ::Vector3 nonUniformScale = AZ::Vector3::CreateOne();
|
||||
|
||||
AZ::NonUniformScaleRequestBus::EventResult(
|
||||
nonUniformScale, m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::GetScale);
|
||||
|
||||
m_initialScale = nonUniformScale + action.m_start.m_scaleSnapOffset;
|
||||
m_initialScale = nonUniformScale;
|
||||
|
||||
AZ::NonUniformScaleRequestBus::Event(
|
||||
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale, m_initialScale);
|
||||
@@ -51,29 +51,37 @@ namespace AzToolsFramework
|
||||
|
||||
m_manipulators->InstallAxisLeftMouseDownCallback(mouseDownCallback);
|
||||
|
||||
m_manipulators->InstallAxisMouseMoveCallback([this](const LinearManipulator::Action& action) {
|
||||
const AZ::Vector3 scaleMultiplier =
|
||||
(AZ::Vector3::CreateOne() + ((action.LocalScaleOffset() * action.m_start.m_sign) / m_initialScale));
|
||||
m_manipulators->InstallAxisMouseMoveCallback(
|
||||
[this](const LinearManipulator::Action& action)
|
||||
{
|
||||
const AZ::Vector3 scaleMultiplier =
|
||||
(AZ::Vector3::CreateOne() + ((action.LocalScaleOffset() * action.m_start.m_sign) / m_initialScale));
|
||||
|
||||
AZ::NonUniformScaleRequestBus::Event(
|
||||
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale,
|
||||
(scaleMultiplier * m_initialScale).GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)));
|
||||
});
|
||||
AZ::NonUniformScaleRequestBus::Event(
|
||||
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale,
|
||||
(scaleMultiplier * m_initialScale)
|
||||
.GetClamp(AZ::Vector3(AZ::MinTransformScale), AZ::Vector3(AZ::MaxTransformScale)));
|
||||
});
|
||||
|
||||
m_manipulators->InstallUniformLeftMouseDownCallback(mouseDownCallback);
|
||||
|
||||
m_manipulators->InstallUniformMouseMoveCallback([this](const LinearManipulator::Action& action) {
|
||||
const auto sumVectorElements = [](const AZ::Vector3& vec) { return vec.GetX() + vec.GetY() + vec.GetZ(); };
|
||||
m_manipulators->InstallUniformMouseMoveCallback(
|
||||
[this](const LinearManipulator::Action& action)
|
||||
{
|
||||
const auto sumVectorElements = [](const AZ::Vector3& vec)
|
||||
{
|
||||
return vec.GetX() + vec.GetY() + vec.GetZ();
|
||||
};
|
||||
|
||||
const float minScaleMultiplier = AZ::MinTransformScale / m_initialScale.GetMinElement();
|
||||
const float maxScaleMultiplier = AZ::MaxTransformScale / m_initialScale.GetMaxElement();
|
||||
const float scaleMultiplier = AZ::GetClamp(
|
||||
1.0f + sumVectorElements(action.m_start.m_sign * action.LocalScaleOffset() / m_initialScale), minScaleMultiplier,
|
||||
maxScaleMultiplier);
|
||||
const float minScaleMultiplier = AZ::MinTransformScale / m_initialScale.GetMinElement();
|
||||
const float maxScaleMultiplier = AZ::MaxTransformScale / m_initialScale.GetMaxElement();
|
||||
const float scaleMultiplier = AZ::GetClamp(
|
||||
1.0f + sumVectorElements(action.m_start.m_sign * action.LocalScaleOffset() / m_initialScale), minScaleMultiplier,
|
||||
maxScaleMultiplier);
|
||||
|
||||
AZ::NonUniformScaleRequestBus::Event(
|
||||
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale, scaleMultiplier * m_initialScale);
|
||||
});
|
||||
AZ::NonUniformScaleRequestBus::Event(
|
||||
m_entityComponentIdPair.GetEntityId(), &AZ::NonUniformScaleRequests::SetScale, scaleMultiplier * m_initialScale);
|
||||
});
|
||||
}
|
||||
|
||||
NonUniformScaleComponentMode::~NonUniformScaleComponentMode()
|
||||
|
||||
+14
-25
@@ -423,15 +423,14 @@ namespace AzToolsFramework
|
||||
}
|
||||
}
|
||||
|
||||
static void InitializeTranslationLookup(
|
||||
EntityIdManipulators& entityIdManipulators, const AZ::Vector3& snapOffset)
|
||||
static void InitializeTranslationLookup(EntityIdManipulators& entityIdManipulators)
|
||||
{
|
||||
AZ_PROFILE_FUNCTION(AZ::Debug::ProfileCategory::AzToolsFramework);
|
||||
|
||||
for (auto& entityIdLookup : entityIdManipulators.m_lookups)
|
||||
{
|
||||
entityIdLookup.second.m_initial =
|
||||
AZ::Transform::CreateTranslation(GetWorldTranslation(entityIdLookup.first) + snapOffset);
|
||||
AZ::Transform::CreateTranslation(GetWorldTranslation(entityIdLookup.first));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -820,7 +819,7 @@ namespace AzToolsFramework
|
||||
// moving with ctrl - setting override
|
||||
pivotOverrideFrame.m_translationOverride =
|
||||
entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
|
||||
InitializeTranslationLookup(entityIdManipulators, -action.LocalPositionOffset());
|
||||
InitializeTranslationLookup(entityIdManipulators);
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1277,12 +1276,12 @@ namespace AzToolsFramework
|
||||
|
||||
// linear
|
||||
translationManipulators->InstallLinearManipulatorMouseDownCallback(
|
||||
[this, manipulatorEntityIds](const LinearManipulator::Action& action) mutable
|
||||
[this, manipulatorEntityIds]([[maybe_unused]] const LinearManipulator::Action& action) mutable
|
||||
{
|
||||
// important to sort entityIds based on hierarchy order when updating transforms
|
||||
BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds);
|
||||
|
||||
InitializeTranslationLookup(m_entityIdManipulators, action.m_start.m_positionSnapOffset);
|
||||
InitializeTranslationLookup(m_entityIdManipulators);
|
||||
|
||||
m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
|
||||
m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(
|
||||
@@ -1302,19 +1301,19 @@ namespace AzToolsFramework
|
||||
});
|
||||
|
||||
translationManipulators->InstallLinearManipulatorMouseUpCallback(
|
||||
[this](const LinearManipulator::Action& /*action*/) mutable
|
||||
[this]([[maybe_unused]] const LinearManipulator::Action& action) mutable
|
||||
{
|
||||
EndRecordManipulatorCommand();
|
||||
});
|
||||
|
||||
// planar
|
||||
translationManipulators->InstallPlanarManipulatorMouseDownCallback(
|
||||
[this, manipulatorEntityIds](const PlanarManipulator::Action& action)
|
||||
[this, manipulatorEntityIds]([[maybe_unused]] const PlanarManipulator::Action& action)
|
||||
{
|
||||
// important to sort entityIds based on hierarchy order when updating transforms
|
||||
BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds);
|
||||
|
||||
InitializeTranslationLookup(m_entityIdManipulators, action.m_start.m_snapOffset);
|
||||
InitializeTranslationLookup(m_entityIdManipulators);
|
||||
|
||||
m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
|
||||
m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(
|
||||
@@ -1340,11 +1339,11 @@ namespace AzToolsFramework
|
||||
|
||||
// surface
|
||||
translationManipulators->InstallSurfaceManipulatorMouseDownCallback(
|
||||
[this, manipulatorEntityIds](const SurfaceManipulator::Action& action)
|
||||
[this, manipulatorEntityIds]([[maybe_unused]] const SurfaceManipulator::Action& action)
|
||||
{
|
||||
BuildSortedEntityIdVectorFromEntityIdMap(m_entityIdManipulators.m_lookups, manipulatorEntityIds->m_entityIds);
|
||||
|
||||
InitializeTranslationLookup(m_entityIdManipulators, action.m_start.m_snapOffset);
|
||||
InitializeTranslationLookup(m_entityIdManipulators);
|
||||
|
||||
m_axisPreview.m_translation = m_entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
|
||||
m_axisPreview.m_orientation = QuaternionFromTransformNoScaling(
|
||||
@@ -3326,26 +3325,16 @@ namespace AzToolsFramework
|
||||
}
|
||||
|
||||
static void DrawManipulatorGrid(
|
||||
AzFramework::DebugDisplayRequests& debugDisplay, const EntityIdManipulators& entityIdManipulators,
|
||||
const float gridSize, const float localSnapping)
|
||||
AzFramework::DebugDisplayRequests& debugDisplay, const EntityIdManipulators& entityIdManipulators, const float gridSize)
|
||||
{
|
||||
const AZ::Matrix3x3 orientation =
|
||||
AZ::Matrix3x3::CreateFromTransform(entityIdManipulators.m_manipulators->GetLocalTransform());
|
||||
|
||||
const AZ::Vector3 unsnappedTranslation =
|
||||
const AZ::Vector3 translation =
|
||||
entityIdManipulators.m_manipulators->GetLocalTransform().GetTranslation();
|
||||
|
||||
// calculate the offset to snap by to align the manipulator to the grid
|
||||
// note: only perform this if we are not snapping in local space
|
||||
const AZ::Vector3 snappedOffset = !localSnapping
|
||||
? CalculateSnappedOffset(unsnappedTranslation, orientation.GetBasisX(), gridSize) +
|
||||
CalculateSnappedOffset(unsnappedTranslation, orientation.GetBasisY(), gridSize)
|
||||
: AZ::Vector3::CreateZero();
|
||||
|
||||
const AZ::Vector3 snappedTranslation = unsnappedTranslation + snappedOffset;
|
||||
|
||||
DrawSnappingGrid(
|
||||
debugDisplay, AZ::Transform::CreateFromMatrix3x3AndTranslation(orientation, snappedTranslation),
|
||||
debugDisplay, AZ::Transform::CreateFromMatrix3x3AndTranslation(orientation, translation),
|
||||
gridSize);
|
||||
}
|
||||
|
||||
@@ -3484,7 +3473,7 @@ namespace AzToolsFramework
|
||||
const GridSnapParameters gridSnapParams = GridSnapSettings(viewportInfo.m_viewportId);
|
||||
if (gridSnapParams.m_gridSnap && m_entityIdManipulators.m_manipulators)
|
||||
{
|
||||
DrawManipulatorGrid(debugDisplay, m_entityIdManipulators, gridSnapParams.m_gridSize, modifiers.Alt());
|
||||
DrawManipulatorGrid(debugDisplay, m_entityIdManipulators, gridSnapParams.m_gridSize);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,10 +118,10 @@ void CVarMenu::AddUniqueCVarsItem(QString displayName,
|
||||
// Otherwise we could have just used the action's currently checked
|
||||
// state and updated the CVar's value only
|
||||
bool cVarOn = (cVar->GetFVal() == availableCVar.m_onValue);
|
||||
bool checked = !cVarOn;
|
||||
SetCVar(cVar, checked ? availableCVar.m_onValue : availableCVar.m_offValue);
|
||||
action->setChecked(checked);
|
||||
if (checked)
|
||||
bool cVarChecked = !cVarOn;
|
||||
SetCVar(cVar, cVarChecked ? availableCVar.m_onValue : availableCVar.m_offValue);
|
||||
action->setChecked(cVarChecked);
|
||||
if (cVarChecked)
|
||||
{
|
||||
// Set the rest of the CVars in the group to their off values
|
||||
SetCVarsToOffValue(availableCVars, availableCVar);
|
||||
@@ -132,9 +132,9 @@ void CVarMenu::AddUniqueCVarsItem(QString displayName,
|
||||
|
||||
// Initialize the action's checked state based on its associated CVar's current value
|
||||
ICVar* cVar = gEnv->pConsole->GetCVar(availableCVar.m_cVarName.toUtf8().data());
|
||||
bool checked = (cVar && cVar->GetFVal() == availableCVar.m_onValue);
|
||||
action->setChecked(checked);
|
||||
if (checked)
|
||||
bool cVarChecked = (cVar && cVar->GetFVal() == availableCVar.m_onValue);
|
||||
action->setChecked(cVarChecked);
|
||||
if (cVarChecked)
|
||||
{
|
||||
// Set the rest of the CVars in the group to their off values
|
||||
SetCVarsToOffValue(availableCVars, availableCVar);
|
||||
|
||||
@@ -2281,6 +2281,14 @@ int CCryEditApp::IdleProcessing(bool bBackgroundUpdate)
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Ensure we don't get called re-entrantly
|
||||
// This can occur when a nested Qt event loop fires (e.g. by way of a modal dialog calling exec)
|
||||
if (m_idleProcessingRunning)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
QScopedValueRollback<bool> guard(m_idleProcessingRunning, true);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
// Call the update function of the engine
|
||||
////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -335,6 +335,8 @@ private:
|
||||
// If this flag is set, the next OnIdle() will update, even if the app is in the background, and then
|
||||
// this flag will be reset.
|
||||
bool m_bForceProcessIdle = false;
|
||||
// This is set while IdleProcessing is running to prevent re-entrancy
|
||||
bool m_idleProcessingRunning = false;
|
||||
// Keep the editor alive, even if no focus is set
|
||||
bool m_bKeepEditorActive = false;
|
||||
// Currently creating a new level
|
||||
|
||||
@@ -2887,9 +2887,12 @@ void EditorViewportWidget::UpdateCameraFromViewportContext()
|
||||
AZ::Matrix3x4 matrix;
|
||||
matrix.SetBasisAndTranslation(cameraState.m_side, cameraState.m_forward, cameraState.m_up, cameraState.m_position);
|
||||
auto m = AZMatrix3x4ToLYMatrix3x4(matrix);
|
||||
|
||||
m_updatingCameraPosition = true;
|
||||
SetViewTM(m);
|
||||
SetFOV(cameraState.m_fovOrZoom);
|
||||
m_Camera.SetZRange(cameraState.m_nearClip, cameraState.m_farClip);
|
||||
m_updatingCameraPosition = false;
|
||||
}
|
||||
|
||||
void EditorViewportWidget::SetAsActiveViewport()
|
||||
|
||||
@@ -205,10 +205,10 @@ CTrackViewAnimNode::CTrackViewAnimNode(IAnimSequence* pSequence, IAnimNode* anim
|
||||
for (int i = 0; i < nodeCount; ++i)
|
||||
{
|
||||
IAnimNode* node = pSequence->GetNode(i);
|
||||
IAnimNode* pParentNode = node->GetParent();
|
||||
IAnimNode* pNodeParentNode = node->GetParent();
|
||||
|
||||
// If our node is the parent, then the current node is a child of it
|
||||
if (animNode == pParentNode)
|
||||
if (animNode == pNodeParentNode)
|
||||
{
|
||||
CTrackViewAnimNodeFactory animNodeFactory;
|
||||
CTrackViewAnimNode* pNewTVAnimNode = animNodeFactory.BuildAnimNode(pSequence, node, this);
|
||||
|
||||
@@ -68,12 +68,12 @@ CTrackViewTrack::CTrackViewTrack(IAnimTrack* pTrack, CTrackViewAnimNode* pTrackA
|
||||
{
|
||||
// Search for child tracks
|
||||
const unsigned int subTrackCount = m_pAnimTrack->GetSubTrackCount();
|
||||
for (unsigned int subTrackIndex = 0; subTrackIndex < subTrackCount; ++subTrackIndex)
|
||||
for (unsigned int subTrackI = 0; subTrackI < subTrackCount; ++subTrackI)
|
||||
{
|
||||
IAnimTrack* pSubTrack = m_pAnimTrack->GetSubTrack(subTrackIndex);
|
||||
IAnimTrack* pSubTrack = m_pAnimTrack->GetSubTrack(subTrackI);
|
||||
|
||||
CTrackViewTrackFactory trackFactory;
|
||||
CTrackViewTrack* pNewTVTrack = trackFactory.BuildTrack(pSubTrack, pTrackAnimNode, this, true, subTrackIndex);
|
||||
CTrackViewTrack* pNewTVTrack = trackFactory.BuildTrack(pSubTrack, pTrackAnimNode, this, true, subTrackI);
|
||||
m_childNodes.push_back(std::unique_ptr<CTrackViewNode>(pNewTVTrack));
|
||||
}
|
||||
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
*/
|
||||
|
||||
#include <ProjectButtonWidget.h>
|
||||
|
||||
#include <AzQtComponents/Utilities/DesktopUtilities.h>
|
||||
|
||||
#include <QVBoxLayout>
|
||||
#include <QHBoxLayout>
|
||||
@@ -81,18 +81,24 @@ namespace O3DE::ProjectManager
|
||||
m_projectImageLabel = new LabelButton(this);
|
||||
m_projectImageLabel->setFixedSize(s_projectImageWidth, s_projectImageHeight);
|
||||
m_projectImageLabel->setAlignment(Qt::AlignHCenter | Qt::AlignVCenter);
|
||||
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); });
|
||||
vLayout->addWidget(m_projectImageLabel);
|
||||
|
||||
m_projectImageLabel->setPixmap(
|
||||
QPixmap(m_projectInfo.m_imagePath).scaled(m_projectImageLabel->size(), Qt::KeepAspectRatioByExpanding));
|
||||
|
||||
QMenu* newProjectMenu = new QMenu(this);
|
||||
m_editProjectAction = newProjectMenu->addAction(tr("Edit Project Settings..."));
|
||||
newProjectMenu->addSeparator();
|
||||
m_copyProjectAction = newProjectMenu->addAction(tr("Duplicate"));
|
||||
newProjectMenu->addSeparator();
|
||||
m_removeProjectAction = newProjectMenu->addAction(tr("Remove from O3DE"));
|
||||
m_deleteProjectAction = newProjectMenu->addAction(tr("Delete this Project"));
|
||||
QMenu* menu = new QMenu(this);
|
||||
menu->addAction(tr("Edit Project Settings..."), this, [this]() { emit EditProject(m_projectInfo.m_path); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Open Project folder..."), this, [this]()
|
||||
{
|
||||
AzQtComponents::ShowFileOnDesktop(m_projectInfo.m_path);
|
||||
});
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Duplicate"), this, [this]() { emit CopyProject(m_projectInfo.m_path); });
|
||||
menu->addSeparator();
|
||||
menu->addAction(tr("Remove from O3DE"), this, [this]() { emit RemoveProject(m_projectInfo.m_path); });
|
||||
menu->addAction(tr("Delete this Project"), this, [this]() { emit DeleteProject(m_projectInfo.m_path); });
|
||||
|
||||
QFrame* footer = new QFrame(this);
|
||||
QHBoxLayout* hLayout = new QHBoxLayout();
|
||||
@@ -104,17 +110,11 @@ namespace O3DE::ProjectManager
|
||||
|
||||
QPushButton* projectMenuButton = new QPushButton(this);
|
||||
projectMenuButton->setObjectName("projectMenuButton");
|
||||
projectMenuButton->setMenu(newProjectMenu);
|
||||
projectMenuButton->setMenu(menu);
|
||||
hLayout->addWidget(projectMenuButton);
|
||||
}
|
||||
|
||||
vLayout->addWidget(footer);
|
||||
|
||||
connect(m_projectImageLabel, &LabelButton::triggered, [this]() { emit OpenProject(m_projectInfo.m_path); });
|
||||
connect(m_editProjectAction, &QAction::triggered, [this]() { emit EditProject(m_projectInfo.m_path); });
|
||||
connect(m_copyProjectAction, &QAction::triggered, [this]() { emit CopyProject(m_projectInfo.m_path); });
|
||||
connect(m_removeProjectAction, &QAction::triggered, [this]() { emit RemoveProject(m_projectInfo.m_path); });
|
||||
connect(m_deleteProjectAction, &QAction::triggered, [this]() { emit DeleteProject(m_projectInfo.m_path); });
|
||||
}
|
||||
|
||||
void ProjectButton::SetButtonEnabled(bool enabled)
|
||||
|
||||
@@ -71,9 +71,5 @@ namespace O3DE::ProjectManager
|
||||
|
||||
ProjectInfo m_projectInfo;
|
||||
LabelButton* m_projectImageLabel;
|
||||
QAction* m_editProjectAction;
|
||||
QAction* m_copyProjectAction;
|
||||
QAction* m_removeProjectAction;
|
||||
QAction* m_deleteProjectAction;
|
||||
};
|
||||
} // namespace O3DE::ProjectManager
|
||||
|
||||
@@ -294,7 +294,8 @@ namespace O3DE::ProjectManager
|
||||
RegisterThisEngine();
|
||||
|
||||
return result == 0 && !PyErr_Occurred();
|
||||
} catch ([[maybe_unused]] const std::exception& e)
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
AZ_Warning("ProjectManagerWindow", false, "Py_Initialize() failed with %s", e.what());
|
||||
return false;
|
||||
@@ -320,25 +321,25 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = true; // already registered is considered successful
|
||||
bool pythonResult = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
{
|
||||
// check current engine path against all other registered engines
|
||||
// to see if we are already registered
|
||||
auto allEngines = m_manifest.attr("get_engines")();
|
||||
if (pybind11::isinstance<pybind11::list>(allEngines))
|
||||
for (auto engine : allEngines)
|
||||
{
|
||||
for (auto engine : allEngines)
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
AZ::IO::FixedMaxPath enginePath(Py_To_String(engine["path"]));
|
||||
if (enginePath.Compare(m_enginePath) == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
auto result = m_register.attr("register")(m_enginePath.c_str());
|
||||
registrationResult = (result.cast<int>() == 0);
|
||||
});
|
||||
|
||||
bool finalResult = (registrationResult && pythonResult);
|
||||
AZ_Assert(finalResult, "Registration of this engine failed!");
|
||||
@@ -378,12 +379,12 @@ namespace O3DE::ProjectManager
|
||||
auto o3deData = m_manifest.attr("load_o3de_manifest")();
|
||||
if (pybind11::isinstance<pybind11::dict>(o3deData))
|
||||
{
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_path = Py_To_String(enginePath);
|
||||
engineInfo.m_defaultGemsFolder = Py_To_String(o3deData["default_gems_folder"]);
|
||||
engineInfo.m_defaultProjectsFolder = Py_To_String(o3deData["default_projects_folder"]);
|
||||
engineInfo.m_defaultRestrictedFolder = Py_To_String(o3deData["default_restricted_folder"]);
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String_Optional(o3deData,"third_party_path","");
|
||||
engineInfo.m_defaultTemplatesFolder = Py_To_String(o3deData["default_templates_folder"]);
|
||||
engineInfo.m_thirdPartyPath = Py_To_String(o3deData["default_third_party_folder"]);
|
||||
}
|
||||
|
||||
auto engineData = m_manifest.attr("get_engine_json_data")(pybind11::none(), enginePath);
|
||||
@@ -391,8 +392,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
try
|
||||
{
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData,"O3DEVersion","0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData,"engine_name","O3DE");
|
||||
engineInfo.m_version = Py_To_String_Optional(engineData, "O3DEVersion", "0.0.0.0");
|
||||
engineInfo.m_name = Py_To_String_Optional(engineData, "engine_name", "O3DE");
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -416,44 +417,32 @@ namespace O3DE::ProjectManager
|
||||
bool PythonBindings::SetEngineInfo(const EngineInfo& engineInfo)
|
||||
{
|
||||
bool result = ExecuteWithLock([&] {
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str enginePath = engineInfo.m_path.toStdString();
|
||||
pybind11::str defaultProjectsFolder = engineInfo.m_defaultProjectsFolder.toStdString();
|
||||
pybind11::str defaultGemsFolder = engineInfo.m_defaultGemsFolder.toStdString();
|
||||
pybind11::str defaultTemplatesFolder = engineInfo.m_defaultTemplatesFolder.toStdString();
|
||||
pybind11::str defaultThirdPartyFolder = engineInfo.m_thirdPartyPath.toStdString();
|
||||
|
||||
auto registrationResult = m_register.attr("register")(
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
enginePath, // engine_path
|
||||
pybind11::none(), // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
defaultProjectsFolder,
|
||||
defaultGemsFolder,
|
||||
defaultTemplatesFolder
|
||||
defaultTemplatesFolder,
|
||||
pybind11::none(), // default_restricted_folder
|
||||
defaultThirdPartyFolder
|
||||
);
|
||||
|
||||
if (registrationResult.cast<int>() != 0)
|
||||
{
|
||||
result = false;
|
||||
}
|
||||
|
||||
auto manifest = m_manifest.attr("load_o3de_manifest")();
|
||||
if (pybind11::isinstance<pybind11::dict>(manifest))
|
||||
{
|
||||
try
|
||||
{
|
||||
manifest["third_party_path"] = engineInfo.m_thirdPartyPath.toStdString();
|
||||
m_manifest.attr("save_o3de_manifest")(manifest);
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
AZ_Warning("PythonBindings", false, "Failed to set third party path.");
|
||||
}
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return result;
|
||||
@@ -477,12 +466,12 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
for (auto path : m_manifest.attr("get_engine_gems")())
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -497,13 +486,13 @@ namespace O3DE::ProjectManager
|
||||
QVector<GemInfo> gems;
|
||||
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
for (auto path : m_manifest.attr("get_all_gems")(pyProjectPath))
|
||||
{
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
gems.push_back(GemInfoFromPath(path));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -518,12 +507,12 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the path to the cmake file that lists the enabled gems.
|
||||
pybind11::str enabledGemsFilename;
|
||||
auto result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
{
|
||||
const pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
enabledGemsFilename = m_cmake.attr("get_enabled_gem_cmake_file")(
|
||||
pybind11::none(), // project_name
|
||||
pyProjectPath); // project_path
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -532,13 +521,13 @@ namespace O3DE::ProjectManager
|
||||
// Retrieve the actual list of names from the cmake file.
|
||||
QVector<AZStd::string> gemNames;
|
||||
result = ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
const auto pyGemNames = m_cmake.attr("get_enabled_gems")(enabledGemsFilename);
|
||||
for (auto gemName : pyGemNames)
|
||||
{
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
gemNames.push_back(Py_To_String(gemName));
|
||||
}
|
||||
});
|
||||
if (!result.IsSuccess())
|
||||
{
|
||||
return AZ::Failure<AZStd::string>(result.GetError().c_str());
|
||||
@@ -552,13 +541,13 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(pybind11::none(), projectPath);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -568,30 +557,31 @@ namespace O3DE::ProjectManager
|
||||
bool registrationResult = false;
|
||||
bool result = ExecuteWithLock(
|
||||
[&]
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
{
|
||||
pybind11::str projectPath = path.toStdString();
|
||||
auto pythonRegistrationResult = m_register.attr("register")(
|
||||
pybind11::none(), // engine_path
|
||||
projectPath, // project_path
|
||||
pybind11::none(), // gem_path
|
||||
pybind11::none(), // external_subdir_path
|
||||
pybind11::none(), // template_path
|
||||
pybind11::none(), // restricted_path
|
||||
pybind11::none(), // repo_uri
|
||||
pybind11::none(), // default_engines_folder
|
||||
pybind11::none(), // default_projects_folder
|
||||
pybind11::none(), // default_gems_folder
|
||||
pybind11::none(), // default_templates_folder
|
||||
pybind11::none(), // default_restricted_folder
|
||||
pybind11::none(), // default_third_party_folder
|
||||
pybind11::none(), // external_subdir_engine_path
|
||||
pybind11::none(), // external_subdir_project_path
|
||||
true, // remove
|
||||
false // force
|
||||
);
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
// Returns an exit code so boolify it then invert result
|
||||
registrationResult = !pythonRegistrationResult.cast<bool>();
|
||||
});
|
||||
|
||||
return result && registrationResult;
|
||||
}
|
||||
@@ -649,12 +639,12 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
// required
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
gemInfo.m_name = Py_To_String(data["gem_name"]);
|
||||
|
||||
// optional
|
||||
gemInfo.m_displayName = Py_To_String_Optional(data, "DisplayName", gemInfo.m_name);
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
gemInfo.m_summary = Py_To_String_Optional(data, "Summary", "");
|
||||
gemInfo.m_version = Py_To_String_Optional(data, "Version", "");
|
||||
|
||||
if (data.contains("Tags"))
|
||||
{
|
||||
@@ -685,7 +675,7 @@ namespace O3DE::ProjectManager
|
||||
try
|
||||
{
|
||||
projectInfo.m_projectName = Py_To_String(projectData["project_name"]);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData,"display_name", projectInfo.m_projectName);
|
||||
projectInfo.m_displayName = Py_To_String_Optional(projectData, "display_name", projectInfo.m_projectName);
|
||||
}
|
||||
catch ([[maybe_unused]] const std::exception& e)
|
||||
{
|
||||
@@ -727,33 +717,33 @@ namespace O3DE::ProjectManager
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::AddGemToProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_enableGemProject.attr("enable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
AZ::Outcome<void, AZStd::string> PythonBindings::RemoveGemFromProject(const QString& gemPath, const QString& projectPath)
|
||||
{
|
||||
return ExecuteWithLockErrorHandling([&]
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
{
|
||||
pybind11::str pyGemPath = gemPath.toStdString();
|
||||
pybind11::str pyProjectPath = projectPath.toStdString();
|
||||
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
m_disableGemProject.attr("disable_gem_in_project")(
|
||||
pybind11::none(), // gem name not needed as path is provided
|
||||
pyGemPath,
|
||||
pybind11::none(), // project name not needed as path is provided
|
||||
pyProjectPath
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
bool PythonBindings::UpdateProject([[maybe_unused]] const ProjectInfo& projectInfo)
|
||||
@@ -773,8 +763,8 @@ namespace O3DE::ProjectManager
|
||||
{
|
||||
// required
|
||||
templateInfo.m_displayName = Py_To_String(data["display_name"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
templateInfo.m_name = Py_To_String(data["template_name"]);
|
||||
templateInfo.m_summary = Py_To_String(data["summary"]);
|
||||
|
||||
// optional
|
||||
if (data.contains("canonical_tags"))
|
||||
@@ -806,7 +796,7 @@ namespace O3DE::ProjectManager
|
||||
QVector<ProjectTemplateInfo> templates;
|
||||
|
||||
bool result = ExecuteWithLock([&] {
|
||||
for (auto path : m_manifest.attr("get_project_templates")())
|
||||
for (auto path : m_manifest.attr("get_templates_for_project_creation")())
|
||||
{
|
||||
templates.push_back(ProjectTemplateInfoFromPath(path));
|
||||
}
|
||||
|
||||
@@ -70,6 +70,52 @@ namespace LUAEditor
|
||||
, m_bIsModified(false)
|
||||
, m_bIsBeingSaved(false)
|
||||
, m_PresetLineAtOpen(1){}
|
||||
|
||||
// Copy constructor does not copy over open file handle
|
||||
DocumentInfo(const DocumentInfo& other)
|
||||
: m_assetId(other.m_assetId)
|
||||
, m_scriptAsset(other.m_scriptAsset)
|
||||
, m_assetName(other.m_assetName)
|
||||
, m_displayName(other.m_displayName)
|
||||
, m_lastKnownModTime(other.m_lastKnownModTime)
|
||||
, m_sourceControlInfo(other.m_sourceControlInfo)
|
||||
, m_bSourceControl_Ready(other.m_bSourceControl_Ready)
|
||||
, m_bSourceControl_BusyGettingStats(other.m_bSourceControl_BusyGettingStats)
|
||||
, m_bSourceControl_BusyRequestingEdit(other.m_bSourceControl_BusyRequestingEdit)
|
||||
, m_bSourceControl_CanWrite(other.m_bSourceControl_CanWrite)
|
||||
, m_bSourceControl_CanCheckOut(other.m_bSourceControl_CanCheckOut)
|
||||
, m_bDataIsLoaded(other.m_bDataIsLoaded)
|
||||
, m_bDataIsWritten(other.m_bDataIsWritten)
|
||||
, m_bCloseAfterSave(other.m_bCloseAfterSave)
|
||||
, m_bUntitledDocument(other.m_bUntitledDocument)
|
||||
, m_bIsModified(other.m_bIsModified)
|
||||
, m_bIsBeingSaved(other.m_bIsBeingSaved)
|
||||
, m_PresetLineAtOpen(other.m_PresetLineAtOpen)
|
||||
{}
|
||||
|
||||
DocumentInfo& operator=(const DocumentInfo& other)
|
||||
{
|
||||
m_assetId = other.m_assetId;
|
||||
m_scriptAsset = other.m_scriptAsset;
|
||||
m_assetName = other.m_assetName;
|
||||
m_displayName = other.m_displayName;
|
||||
m_lastKnownModTime = other.m_lastKnownModTime;
|
||||
m_sourceControlInfo = other.m_sourceControlInfo;
|
||||
m_bSourceControl_Ready = other.m_bSourceControl_Ready;
|
||||
m_bSourceControl_BusyGettingStats = other.m_bSourceControl_BusyGettingStats;
|
||||
m_bSourceControl_BusyRequestingEdit = other.m_bSourceControl_BusyRequestingEdit;
|
||||
m_bSourceControl_CanWrite = other.m_bSourceControl_CanWrite;
|
||||
m_bSourceControl_CanCheckOut = other.m_bSourceControl_CanCheckOut;
|
||||
m_bDataIsLoaded = other.m_bDataIsLoaded;
|
||||
m_bDataIsWritten = other.m_bDataIsWritten;
|
||||
m_bCloseAfterSave = other.m_bCloseAfterSave;
|
||||
m_bUntitledDocument = other.m_bUntitledDocument;
|
||||
m_bIsModified = other.m_bIsModified;
|
||||
m_bIsBeingSaved = other.m_bIsBeingSaved;
|
||||
m_PresetLineAtOpen = other.m_PresetLineAtOpen;
|
||||
|
||||
return *this;
|
||||
}
|
||||
};
|
||||
|
||||
class ContextInterface
|
||||
|
||||
@@ -8,7 +8,8 @@
|
||||
"Name": "IBLSpecular",
|
||||
"Description": "The input cubemap generates an IBL specular output cubemap.",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -34,7 +35,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -59,7 +61,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -84,7 +87,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
@@ -109,7 +113,8 @@
|
||||
"UUID": "{908DA68C-97FB-4C4A-97BC-5A55F30F14FA}",
|
||||
"Name": "IBLSpecular",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm"
|
||||
"_iblspecularcm",
|
||||
"_iblspecularcm256"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"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,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{B66395E1-8D0E-4159-989B-FC2B9F091B75}",
|
||||
"Name": "IBLSpecularHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm512"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 512,
|
||||
"MaxTextureSize": 512,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"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,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{7273ACAE-6E34-487C-AF71-99423A6E1CB0}",
|
||||
"Name": "IBLSpecularLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm128"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 128,
|
||||
"MaxTextureSize": 128,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"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,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{5CD1AFA6-915B-4716-893C-A5B1F4074C22}",
|
||||
"Name": "IBLSpecularVeryHigh",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm1024"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 1024,
|
||||
"MaxTextureSize": 1024,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,135 @@
|
||||
{
|
||||
"Type": "JsonSerialization",
|
||||
"Version": 1,
|
||||
"ClassName": "MultiplatformPresetSettings",
|
||||
"ClassData": {
|
||||
"DefaultPreset": {
|
||||
"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,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"PlatformsPresets": {
|
||||
"android": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"ios": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"mac": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
},
|
||||
"provo": {
|
||||
"UUID": "{8293C236-D3E8-4352-8B18-C2E82EEE6547}",
|
||||
"Name": "IBLSpecularVeryLow",
|
||||
"FileMasks": [
|
||||
"_iblspecularcm64"
|
||||
],
|
||||
"SourceColor": "Linear",
|
||||
"DestColor": "Linear",
|
||||
"SuppressEngineReduce": true,
|
||||
"PixelFormat": "R9G9B9E5",
|
||||
"DiscardAlpha": true,
|
||||
"MinTextureSize": 64,
|
||||
"MaxTextureSize": 64,
|
||||
"IsPowerOf2": true,
|
||||
"CubemapSettings": {
|
||||
"Filter": "GGX",
|
||||
"MipAngle": 7.0,
|
||||
"MipSlope": 2.299999952316284,
|
||||
"EdgeFixup": -431602080.0,
|
||||
"SubId": 2000
|
||||
},
|
||||
"MipMapSetting": {
|
||||
"MipGenType": "Box"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,3 @@
|
||||
version https://git-lfs.github.com/spec/v1
|
||||
oid sha256:a476e99b55cf2a76fef6775c5a57dad29f8ffcb942c625bab04c89051a72a560
|
||||
size 62626
|
||||
oid sha256:838830c99f344f5b68e5e85c9bc52751350caf48e662c9c2b767ab77039bbd8f
|
||||
size 103472
|
||||
|
||||
@@ -177,4 +177,5 @@ namespace AZ
|
||||
} // namespace Render
|
||||
|
||||
AZ_TYPE_INFO_SPECIALIZE(Render::DisplayMapperOperationType, "{41CA80B1-9E0D-41FB-A235-9638D2A905A5}");
|
||||
AZ_TYPE_INFO_SPECIALIZE(Render::OutputDeviceTransformType, "{B94085B7-C0D4-466A-A791-188A4559EC8D}");
|
||||
} // namespace AZ
|
||||
|
||||
+5
-3
@@ -12,11 +12,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
#include <Atom/RPI.Reflect/Pass/PassAsset.h>
|
||||
#include <Atom/RPI.Reflect/Pass/PassData.h>
|
||||
#include <Atom/RPI.Reflect/System/AnyAsset.h>
|
||||
#include <AzCore/Asset/AssetCommon.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -33,6 +35,7 @@ namespace AZ
|
||||
AZ_TYPE_INFO(AcesParameterOverrides, "{3EE8C0D4-3792-46C0-B91C-B89A81C36B91}");
|
||||
static void Reflect(ReflectContext* context);
|
||||
|
||||
// Load preconfigured preset for specific ODT mode defined by m_preset
|
||||
void LoadPreset();
|
||||
|
||||
// When enabled allows parameter overrides for ACES configuration
|
||||
@@ -98,6 +101,5 @@ namespace AZ
|
||||
|
||||
DisplayMapperConfigurationDescriptor m_config;
|
||||
};
|
||||
|
||||
} // namespace RPI
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
@@ -311,14 +311,9 @@ namespace AZ
|
||||
{
|
||||
auto tileBufferResolution = GetTileDataBufferResolution();
|
||||
|
||||
// generate a UUID for the buffer name to keep it unique when there are multiple render pipelines
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadWrite;
|
||||
desc.m_bufferName = AZStd::string::format("LightList_%s", uuidString.c_str());
|
||||
desc.m_bufferName = "LightList";
|
||||
desc.m_elementSize = sizeof(uint32_t);
|
||||
desc.m_byteCount = tileBufferResolution.m_width * tileBufferResolution.m_height * 256 * sizeof(uint32_t);
|
||||
m_lightList = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
|
||||
@@ -118,14 +118,9 @@ namespace AZ
|
||||
|
||||
void LightCullingRemap::CreateRemappedLightListBuffer()
|
||||
{
|
||||
// generate a UUID for the buffer name to keep it unique when there are multiple render pipelines
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadWrite;
|
||||
desc.m_bufferName = AZStd::string::format("LightListRemapped_%s", uuidString.c_str());
|
||||
desc.m_bufferName = "LightListRemapped";
|
||||
desc.m_elementSize = RHI::GetFormatSize(LightListRemappedFormat);
|
||||
desc.m_byteCount = m_tileDim.m_width * m_tileDim.m_height * NumBins * MaxLightsPerTile * desc.m_elementSize;
|
||||
m_lightListRemapped = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
|
||||
+27
-1
@@ -23,6 +23,15 @@ namespace AZ
|
||||
{
|
||||
if (auto serializeContext = azrtti_cast<AZ::SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Enum<OutputDeviceTransformType>()
|
||||
->Version(0)
|
||||
->Value("48Nits", OutputDeviceTransformType::OutputDeviceTransformType_48Nits)
|
||||
->Value("1000Nits", OutputDeviceTransformType::OutputDeviceTransformType_1000Nits)
|
||||
->Value("2000Nits", OutputDeviceTransformType::OutputDeviceTransformType_2000Nits)
|
||||
->Value("4000Nits", OutputDeviceTransformType::OutputDeviceTransformType_4000Nits)
|
||||
->Value("NumOutputDeviceTransformTypes", OutputDeviceTransformType::NumOutputDeviceTransformTypes)
|
||||
;
|
||||
|
||||
serializeContext->Class<AcesParameterOverrides>()
|
||||
->Version(0)
|
||||
->Field("OverrideDefaults", &AcesParameterOverrides::m_overrideDefaults)
|
||||
@@ -38,6 +47,22 @@ namespace AZ
|
||||
->Field("SurroundGamma", &AcesParameterOverrides::m_surroundGamma)
|
||||
->Field("Gamma", &AcesParameterOverrides::m_gamma);
|
||||
}
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<AcesParameterOverrides>("AcesParameterOverrides")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "render")
|
||||
->Attribute(AZ::Script::Attributes::Module, "render")
|
||||
->Constructor()
|
||||
->Method("LoadPreset", &AcesParameterOverrides::LoadPreset)
|
||||
->Property("overrideDefaults", BehaviorValueProperty(&AcesParameterOverrides::m_overrideDefaults))
|
||||
->Property("preset", BehaviorValueProperty(&AcesParameterOverrides::m_preset))
|
||||
->Property("alterSurround", BehaviorValueProperty(&AcesParameterOverrides::m_alterSurround))
|
||||
->Property("applyDesaturation", BehaviorValueProperty(&AcesParameterOverrides::m_applyDesaturation))
|
||||
->Property("applyCATD60toD65", BehaviorValueProperty(&AcesParameterOverrides::m_applyCATD60toD65))
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void AcesParameterOverrides::LoadPreset()
|
||||
@@ -71,11 +96,12 @@ namespace AZ
|
||||
;
|
||||
|
||||
serializeContext->Class<DisplayMapperConfigurationDescriptor>()
|
||||
->Version(1)
|
||||
->Version(2)
|
||||
->Field("Name", &DisplayMapperConfigurationDescriptor::m_name)
|
||||
->Field("OperationType", &DisplayMapperConfigurationDescriptor::m_operationType)
|
||||
->Field("LdrGradingLutEnabled", &DisplayMapperConfigurationDescriptor::m_ldrGradingLutEnabled)
|
||||
->Field("LdrColorGradingLut", &DisplayMapperConfigurationDescriptor::m_ldrColorGradingLut)
|
||||
->Field("AcesParameterOverrides", &DisplayMapperConfigurationDescriptor::m_acesParameterOverrides)
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ namespace AZ
|
||||
desc.m_elementFormat = filters.front()->GetElementFormat();
|
||||
desc.m_byteCount = totalElementCount * elementSize;
|
||||
desc.m_bufferData = data.data();
|
||||
desc.m_isUniqueName = true;
|
||||
|
||||
auto buffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
|
||||
|
||||
+2
-9
@@ -100,16 +100,9 @@ namespace AZ
|
||||
|
||||
bool ExposureControlSettings::InitCommonBuffer()
|
||||
{
|
||||
// generate a UUID for the buffer name to keep it unique
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
AZStd::string bufferName = AZStd::string::format("%s_%s", ExposureControlBufferBaseName, uuidString.c_str());
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::Constant;
|
||||
desc.m_bufferName = bufferName;
|
||||
desc.m_bufferName = ExposureControlBufferName;
|
||||
desc.m_byteCount = sizeof(ShaderParameters);
|
||||
desc.m_elementSize = sizeof(ShaderParameters);
|
||||
|
||||
@@ -117,7 +110,7 @@ namespace AZ
|
||||
|
||||
if (!m_buffer)
|
||||
{
|
||||
AZ_Assert(false, "Failed to create the RPI::Buffer[%s] which is used for the exposure control feature.", bufferName.c_str());
|
||||
AZ_Assert(false, "Failed to create the RPI::Buffer[%s] which is used for the exposure control feature.", desc.m_bufferName.c_str());
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -28,8 +28,8 @@ namespace AZ
|
||||
{
|
||||
class PostProcessSettings;
|
||||
|
||||
// Base name of the buffer used for the exposure control feature. Usually distinct identifier will be added to this name for each exposure control settings.
|
||||
static const char* const ExposureControlBufferBaseName = "ExposureControlBuffer";
|
||||
// Name of the buffer used for the exposure control feature
|
||||
static const char* const ExposureControlBufferName = "ExposureControlBuffer";
|
||||
|
||||
// The post process sub-settings class for the exposure control feature
|
||||
class ExposureControlSettings final
|
||||
|
||||
+1
-2
@@ -47,9 +47,8 @@ namespace AZ
|
||||
m_getDepthPass = static_cast<DepthOfFieldWriteFocusDepthFromGpuPass*>(pass.get());
|
||||
|
||||
// Create buffer for read back focus depth. We append static counter to avoid name conflicts.
|
||||
AZStd::string bufferName = AZStd::string::format("DepthOfFieldReadBackAutoFocusDepthBuffer_%d", s_bufferInstance++);
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_bufferName = bufferName;
|
||||
desc.m_bufferName = "DepthOfFieldReadBackAutoFocusDepthBuffer";
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadWrite;
|
||||
desc.m_byteCount = sizeof(float);
|
||||
desc.m_elementSize = aznumeric_cast<uint32_t>(desc.m_byteCount);
|
||||
|
||||
@@ -71,6 +71,7 @@ namespace AZ
|
||||
desc.m_bufferName = bufferName;
|
||||
desc.m_byteCount = sizeof(ShaderParameters);
|
||||
desc.m_elementSize = sizeof(ShaderParameters);
|
||||
desc.m_isUniqueName = true;
|
||||
|
||||
m_buffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
}
|
||||
|
||||
@@ -34,7 +34,7 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
static const char* const EyeAdaptationBufferBaseName = "EyeAdaptationBuffer";
|
||||
static const char* const EyeAdaptationBufferName = "EyeAdaptationBuffer";
|
||||
|
||||
RPI::Ptr<EyeAdaptationPass> EyeAdaptationPass::Create(const RPI::PassDescriptor& descriptor)
|
||||
{
|
||||
@@ -49,12 +49,10 @@ namespace AZ
|
||||
|
||||
void EyeAdaptationPass::InitBuffer()
|
||||
{
|
||||
AZStd::string bufferName = AZStd::string::format("%s_%p", EyeAdaptationBufferBaseName, this);
|
||||
|
||||
ExposureCalculationData defaultData;
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadWrite;
|
||||
desc.m_bufferName = bufferName;
|
||||
desc.m_bufferName = EyeAdaptationBufferName;
|
||||
desc.m_byteCount = sizeof(ExposureCalculationData);
|
||||
desc.m_elementSize = aznumeric_cast<uint32_t>(desc.m_byteCount);
|
||||
desc.m_bufferData = &defaultData;
|
||||
|
||||
+1
-6
@@ -62,14 +62,9 @@ namespace AZ
|
||||
|
||||
void LuminanceHistogramGeneratorPass::CreateHistogramBuffer()
|
||||
{
|
||||
// generate a UUID for the buffer name to keep it unique when there are multiple render pipelines
|
||||
AZ::Uuid uuid = AZ::Uuid::CreateRandom();
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadWrite;
|
||||
desc.m_bufferName = AZStd::string::format("LuminanceHistogramBuffer_%s", uuidString.c_str());
|
||||
desc.m_bufferName = "LuminanceHistogramBuffer";
|
||||
desc.m_elementSize = sizeof(uint32_t);
|
||||
desc.m_byteCount = NumHistogramBins * sizeof(uint32_t);
|
||||
desc.m_elementFormat = RHI::Format::R32_UINT;
|
||||
|
||||
@@ -210,12 +210,10 @@ namespace AZ
|
||||
|
||||
if (m_meshInfoBuffer == nullptr)
|
||||
{
|
||||
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
|
||||
|
||||
// allocate the MeshInfo structured buffer
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = AZStd::string::format("RayTracingMeshInfo_%s", uuidString.c_str());
|
||||
desc.m_bufferName = "RayTracingMeshInfo";
|
||||
desc.m_byteCount = newMeshByteCount;
|
||||
desc.m_elementSize = sizeof(MeshInfo);
|
||||
m_meshInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
@@ -283,12 +281,10 @@ namespace AZ
|
||||
|
||||
if (m_materialInfoBuffer == nullptr)
|
||||
{
|
||||
AZStd::string uuidString = AZ::Uuid::CreateRandom().ToString<AZStd::string>();
|
||||
|
||||
// allocate the MaterialInfo structured buffer
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = AZStd::string::format("RayTracingMaterialInfo_%s", uuidString.c_str());
|
||||
desc.m_bufferName = "RayTracingMaterialInfo";
|
||||
desc.m_byteCount = newMaterialByteCount;
|
||||
desc.m_elementSize = sizeof(MaterialInfo);
|
||||
m_materialInfoBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
|
||||
@@ -193,7 +193,7 @@ namespace AZ
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::Constant;
|
||||
desc.m_bufferName = AZStd::string::format("SkyboxBuffer_%p", this);
|
||||
desc.m_bufferName = "SkyboxBuffer";
|
||||
desc.m_byteCount = byteCount;
|
||||
desc.m_elementSize = byteCount;
|
||||
desc.m_bufferData = &m_physicalSkyData;
|
||||
|
||||
+3
-3
@@ -89,13 +89,13 @@ namespace AZ
|
||||
// Create the transform buffer, grow by powers of two
|
||||
RPI::CommonBufferDescriptor desc2;
|
||||
desc2.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc2.m_bufferName = AZStd::string::format("'m_objectToWorldBuffer_%" PRIXPTR, reinterpret_cast<uintptr_t>(this));
|
||||
desc2.m_bufferName = "m_objectToWorldBuffer";
|
||||
desc2.m_byteCount = byteCount;
|
||||
desc2.m_elementSize = elementSize;
|
||||
|
||||
m_objectToWorldBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc2);
|
||||
|
||||
desc2.m_bufferName = AZStd::string::format("'m_objectToWorldHistoryBuffer_%p", this);
|
||||
desc2.m_bufferName = "m_objectToWorldHistoryBuffer";
|
||||
m_objectToWorldHistoryBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc2);
|
||||
}
|
||||
else
|
||||
@@ -119,7 +119,7 @@ namespace AZ
|
||||
// Create the normal buffer, grow by powers of two
|
||||
RPI::CommonBufferDescriptor desc2;
|
||||
desc2.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc2.m_bufferName = AZStd::string::format("'m_objectToWorldInverseTransposeBuffer_%" PRIXPTR, reinterpret_cast<uintptr_t>(this));
|
||||
desc2.m_bufferName = "m_objectToWorldInverseTransposeBuffer";
|
||||
desc2.m_byteCount = byteCount;
|
||||
desc2.m_elementSize = elementSize;
|
||||
|
||||
|
||||
@@ -40,13 +40,11 @@ namespace AZ
|
||||
|
||||
if (m_bufferIndex.IsValid())
|
||||
{
|
||||
AZStd::string bufferName = AZStd::string::format("%s_%" PRIXPTR, descriptor.m_bufferName.c_str(), reinterpret_cast<uintptr_t>(this));
|
||||
|
||||
uint32_t byteCount = RHI::NextPowerOfTwo(GetMax<uint32_t>(BufferMinSize, m_elementCount * m_elementSize));
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = bufferName;
|
||||
desc.m_bufferName = descriptor.m_bufferName;
|
||||
desc.m_byteCount = byteCount;
|
||||
desc.m_elementSize = descriptor.m_elementSize;
|
||||
|
||||
|
||||
@@ -261,8 +261,8 @@ namespace AZ
|
||||
if (vulkanDescriptor.m_constantDataPool && constantDataSize)
|
||||
{
|
||||
m_constantDataBuffer = Buffer::Create();
|
||||
const RHI::BufferDescriptor descriptor(RHI::BufferBindFlags::Constant, constantDataSize);
|
||||
RHI::BufferInitRequest request(*m_constantDataBuffer, descriptor);
|
||||
const RHI::BufferDescriptor bufferDescriptor(RHI::BufferBindFlags::Constant, constantDataSize);
|
||||
RHI::BufferInitRequest request(*m_constantDataBuffer, bufferDescriptor);
|
||||
RHI::ResultCode rhiResult = vulkanDescriptor.m_constantDataPool->InitBuffer(request);
|
||||
if (rhiResult != RHI::ResultCode::Success)
|
||||
{
|
||||
|
||||
@@ -112,6 +112,8 @@ namespace AZ
|
||||
AZStd::mutex m_pendingUploadMutex;
|
||||
|
||||
RHI::BufferViewDescriptor m_bufferViewDescriptor;
|
||||
|
||||
RHI::AttachmentId m_attachmentId;
|
||||
};
|
||||
|
||||
template <class structureType>
|
||||
|
||||
@@ -35,7 +35,7 @@ namespace AZ
|
||||
// BufferSystemInterface overrides...
|
||||
RHI::Ptr<RHI::BufferPool> GetCommonBufferPool(CommonBufferPoolType poolType) override;
|
||||
Data::Instance<Buffer> CreateBufferFromCommonPool(const CommonBufferDescriptor& descriptor) override;
|
||||
Data::Instance<Buffer> FindCommonBuffer(AZStd::string_view bufferName) override;
|
||||
Data::Instance<Buffer> FindCommonBuffer(AZStd::string_view uniqueBufferName) override;
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
@@ -53,6 +53,9 @@ namespace AZ
|
||||
RHI::Format m_elementFormat = RHI::Format::Unknown; //<! [optional] If it's specified with a valid format, the size of this format will be used instead of m_elementSize
|
||||
AZ::u64 m_byteCount = 0;
|
||||
const void* m_bufferData = nullptr; //<! [optional] Initial data content of this buffer. This data buffer size needs to be same as m_bufferSizeInbytes
|
||||
//! Set to true if you want this buffer to be discoverable by BufferSystemInterface::FindCommonBuffer using m_bufferName.
|
||||
//! Note that create buffer may fail if there is a buffer with the same name.
|
||||
bool m_isUniqueName = false;
|
||||
};
|
||||
|
||||
class BufferSystemInterface
|
||||
@@ -78,7 +81,7 @@ namespace AZ
|
||||
virtual Data::Instance<Buffer> CreateBufferFromCommonPool(const CommonBufferDescriptor& descriptor) = 0;
|
||||
|
||||
//! Find a buffer by name. The buffer has to be created by CreateBufferFromCommonPool function
|
||||
virtual Data::Instance<Buffer> FindCommonBuffer(AZStd::string_view bufferName) = 0;
|
||||
virtual Data::Instance<Buffer> FindCommonBuffer(AZStd::string_view uniqueBufferName) = 0;
|
||||
};
|
||||
} // namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -60,11 +60,15 @@ namespace AZ
|
||||
const Data::Asset<ResourcePoolAsset>& GetPoolAsset() const;
|
||||
|
||||
CommonBufferPoolType GetCommonPoolType() const;
|
||||
|
||||
const AZStd::string& GetName() const;
|
||||
|
||||
private:
|
||||
// Called by asset creators to assign the asset to a ready state.
|
||||
void SetReady();
|
||||
|
||||
AZStd::string m_name;
|
||||
|
||||
AZStd::vector<uint8_t> m_buffer;
|
||||
|
||||
RHI::BufferDescriptor m_bufferDescriptor;
|
||||
|
||||
@@ -114,7 +114,7 @@ namespace AZ
|
||||
if (auto* serialize = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serialize->Class<ModelAssetBuilderComponent, SceneAPI::SceneCore::ExportingComponent>()
|
||||
->Version(26); // [ATOM-14992]
|
||||
->Version(27); // [ATOM-15658]
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -14,9 +14,11 @@
|
||||
#include <Atom/RPI.Reflect/Model/MorphTargetDelta.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Utilities/Filters.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Utilities/SceneGraphUtilities.h>
|
||||
#include <SceneAPI/SceneCore/Utilities/SceneGraphSelector.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/FilterIterator.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/PairIterator.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphDownwardsIterator.h>
|
||||
#include <SceneAPI/SceneCore/Containers/Views/SceneGraphChildIterator.h>
|
||||
|
||||
#include <AzToolsFramework/API/EditorAssetSystemAPI.h>
|
||||
#include <AzCore/Asset/AssetManagerBus.h>
|
||||
@@ -27,62 +29,42 @@ namespace AZ::RPI
|
||||
|
||||
AZStd::unordered_map<AZStd::string, MorphTargetExporter::SourceBlendShapeInfo> MorphTargetExporter::GetBlendShapeInfos(
|
||||
const Containers::Scene& scene,
|
||||
const AZStd::optional<AZStd::string>& filterMeshName) const
|
||||
const MeshData* meshData) const
|
||||
{
|
||||
const Containers::SceneGraph& sceneGraph = scene.GetGraph();
|
||||
const auto contentStorage = sceneGraph.GetContentStorage();
|
||||
const auto nameStorage = sceneGraph.GetNameStorage();
|
||||
|
||||
const auto foundBaseMeshIter = AZStd::find_if(sceneGraph.GetContentStorage().cbegin(), sceneGraph.GetContentStorage().cend(), [meshData](const auto& nodeData)
|
||||
{
|
||||
return nodeData.get() == meshData;
|
||||
});
|
||||
if (foundBaseMeshIter == sceneGraph.GetContentStorage().cend())
|
||||
{
|
||||
return {};
|
||||
}
|
||||
|
||||
const auto baseMeshNodeIndex = sceneGraph.ConvertToNodeIndex(foundBaseMeshIter);
|
||||
|
||||
const auto childBlendShapeDatas = Containers::MakeDerivedFilterView<DataTypes::IBlendShapeData>(
|
||||
Containers::Views::MakeSceneGraphChildView(sceneGraph, baseMeshNodeIndex, sceneGraph.GetContentStorage().cbegin(), true)
|
||||
);
|
||||
|
||||
AZStd::unordered_map<AZStd::string, SourceBlendShapeInfo> result;
|
||||
|
||||
const auto keyValueView = Containers::Views::MakePairView(nameStorage, contentStorage);
|
||||
const auto filteredView = Containers::Views::MakeFilterView(keyValueView, Containers::DerivedTypeFilter<DataTypes::IBlendShapeData>());
|
||||
for (const auto& [name, object] : filteredView)
|
||||
for (auto it = childBlendShapeDatas.cbegin(); it != childBlendShapeDatas.cend(); ++it)
|
||||
{
|
||||
const Containers::SceneGraph::NodeIndex sceneNodeIndex = sceneGraph.Find(name.GetPath());
|
||||
const Containers::SceneGraph::NodeIndex blendShapeNodeIndex = sceneGraph.ConvertToNodeIndex(it.GetBaseIterator().GetBaseIterator().GetHierarchyIterator());
|
||||
|
||||
AZStd::set<AZ::Crc32> types;
|
||||
Events::GraphMetaInfoBus::Broadcast(&Events::GraphMetaInfo::GetVirtualTypes, types, scene, sceneNodeIndex);
|
||||
if (types.find(Events::GraphMetaInfo::GetIgnoreVirtualType()) == types.end())
|
||||
Events::GraphMetaInfoBus::Broadcast(&Events::GraphMetaInfo::GetVirtualTypes, types, scene, blendShapeNodeIndex);
|
||||
if (!types.contains(Events::GraphMetaInfo::GetIgnoreVirtualType()))
|
||||
{
|
||||
const char* sceneNodePath = name.GetPath();
|
||||
const Containers::SceneGraph::NodeIndex nodeIndex = sceneGraph.Find(sceneNodePath);
|
||||
if (nodeIndex.IsValid())
|
||||
{
|
||||
const AZStd::string meshNodeName = SourceBlendShapeInfo::GetMeshNodeName(sceneGraph, nodeIndex);
|
||||
if (!filterMeshName.has_value() ||
|
||||
(filterMeshName.has_value() && filterMeshName.value() == meshNodeName))
|
||||
{
|
||||
const AZStd::string blendShapeName = sceneGraph.GetNodeName(nodeIndex).GetName();
|
||||
SourceBlendShapeInfo& blendShapeInfo = result[blendShapeName];
|
||||
blendShapeInfo.m_sceneNodeIndices.push_back(nodeIndex);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
AZ_Warning(ModelAssetBuilderComponent::s_builderName, false, "Cannot retrieve scene graph index for blend shape node with path %s.", sceneNodePath);
|
||||
}
|
||||
const AZStd::string blendShapeName{sceneGraph.GetNodeName(blendShapeNodeIndex).GetName(), sceneGraph.GetNodeName(blendShapeNodeIndex).GetNameLength()};
|
||||
result[blendShapeName].m_sceneNodeIndices.emplace_back(blendShapeNodeIndex);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
AZStd::string MorphTargetExporter::SourceBlendShapeInfo::GetMeshNodeName(const Containers::SceneGraph& sceneGraph,
|
||||
const Containers::SceneGraph::NodeIndex& sceneNodeIndex)
|
||||
{
|
||||
const auto* blendShapeData =
|
||||
azrtti_cast<const DataTypes::IBlendShapeData*>(sceneGraph.GetNodeContent(sceneNodeIndex).get());
|
||||
AZ_Assert(blendShapeData, "Cannot get mesh node name from scene node. Node is expected to be a blend shape.");
|
||||
if (blendShapeData)
|
||||
{
|
||||
Containers::SceneGraph::NodeIndex morphMeshParentIndex = sceneGraph.GetNodeParent(sceneNodeIndex);
|
||||
return sceneGraph.GetNodeName(morphMeshParentIndex).GetName();
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void MorphTargetExporter::ProduceMorphTargets(const Containers::Scene& scene,
|
||||
uint32_t vertexOffset,
|
||||
const ModelAssetBuilderComponent::SourceMeshContent& sourceMesh,
|
||||
@@ -92,9 +74,14 @@ namespace AZ::RPI
|
||||
{
|
||||
const Containers::SceneGraph& sceneGraph = scene.GetGraph();
|
||||
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const auto baseMeshIt = AZStd::find(sceneGraph.GetContentStorage().cbegin(), sceneGraph.GetContentStorage().cend(), sourceMesh.m_meshData);
|
||||
const Containers::SceneGraph::NodeIndex baseMeshIndex = sceneGraph.ConvertToNodeIndex(baseMeshIt);
|
||||
const AZStd::string_view baseMeshName{sceneGraph.GetNodeName(baseMeshIndex).GetName(), sceneGraph.GetNodeName(baseMeshIndex).GetNameLength()};
|
||||
#endif
|
||||
|
||||
// Get the blend shapes for the given mesh
|
||||
const AZStd::string_view meshName = sourceMesh.m_name.GetStringView();
|
||||
AZStd::unordered_map<AZStd::string, SourceBlendShapeInfo> blendShapeInfos = GetBlendShapeInfos(scene, meshName);
|
||||
AZStd::unordered_map<AZStd::string, SourceBlendShapeInfo> blendShapeInfos = GetBlendShapeInfos(scene, sourceMesh.m_meshData.get());
|
||||
|
||||
for (const auto& iter : blendShapeInfos)
|
||||
{
|
||||
@@ -109,12 +96,12 @@ namespace AZ::RPI
|
||||
{
|
||||
#if defined(AZ_ENABLE_TRACING)
|
||||
const Containers::SceneGraph::NodeIndex morphMeshParentIndex = sceneGraph.GetNodeParent(sceneNodeIndex);
|
||||
const char* meshNodeName = sceneGraph.GetNodeName(morphMeshParentIndex).GetName();
|
||||
const AZStd::string_view sourceMeshName{sceneGraph.GetNodeName(morphMeshParentIndex).GetName(), sceneGraph.GetNodeName(morphMeshParentIndex).GetNameLength()};
|
||||
#endif
|
||||
|
||||
AZ_Assert(AZ::StringFunc::Equal(sourceMesh.m_name.GetCStr(), meshNodeName, /*bCaseSensitive=*/true),
|
||||
"Scene graph mesh node (%s) has a different name than the product mesh (%s).",
|
||||
meshNodeName, sourceMesh.m_name.GetCStr());
|
||||
AZ_Assert(AZ::StringFunc::Equal(baseMeshName, sourceMeshName, /*bCaseSensitive=*/true),
|
||||
"Scene graph mesh node (%.*s) has a different name than the product mesh (%.*s).",
|
||||
AZ_STRING_ARG(sourceMeshName), AZ_STRING_ARG(baseMeshName));
|
||||
|
||||
const DataTypes::MatrixType globalTransform = Utilities::BuildWorldTransform(sceneGraph, sceneNodeIndex);
|
||||
BuildMorphTargetMesh(vertexOffset, sourceMesh, productMesh, metaAssetCreator, blendShapeName, blendShapeData, globalTransform, coordSysConverter, scene.GetSourceFilename());
|
||||
|
||||
@@ -39,12 +39,9 @@ namespace AZ
|
||||
struct SourceBlendShapeInfo
|
||||
{
|
||||
AZStd::vector<AZ::SceneAPI::Containers::SceneGraph::NodeIndex> m_sceneNodeIndices;
|
||||
|
||||
static AZStd::string GetMeshNodeName(const AZ::SceneAPI::Containers::SceneGraph& sceneGraph,
|
||||
const AZ::SceneAPI::Containers::SceneGraph::NodeIndex& sceneNodeIndex);
|
||||
};
|
||||
//! Retrieve all scene graph nodes per blend shape for all available blend shapes.
|
||||
AZStd::unordered_map<AZStd::string, SourceBlendShapeInfo> GetBlendShapeInfos(const AZ::SceneAPI::Containers::Scene& scene, const AZStd::optional<AZStd::string>& filterMeshName = AZStd::nullopt) const;
|
||||
AZStd::unordered_map<AZStd::string, SourceBlendShapeInfo> GetBlendShapeInfos(const AZ::SceneAPI::Containers::Scene& scene, const MeshData* meshData) const;
|
||||
|
||||
//! Calculate position delta tolerance that is used to indicate whether a given vertex is part of the sparse set of morphed vertices
|
||||
//! or if it will be skipped and optimized out due to a hardly visible or no movement at all.
|
||||
|
||||
@@ -32,10 +32,6 @@ namespace AZ
|
||||
auto buffer = Data::InstanceDatabase<Buffer>::Instance().FindOrCreate(
|
||||
Data::InstanceId::CreateFromAssetId(bufferAsset.GetId()),
|
||||
bufferAsset);
|
||||
if (buffer && buffer->m_rhiBuffer)
|
||||
{
|
||||
buffer->m_rhiBuffer->SetName(Name(bufferAsset.GetHint()));
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
@@ -170,6 +166,16 @@ namespace AZ
|
||||
return resultCode;
|
||||
}
|
||||
}
|
||||
|
||||
m_rhiBuffer->SetName(Name(bufferAsset.GetName()));
|
||||
|
||||
// Only generate buffer's attachment id if the buffer is writable
|
||||
if (RHI::CheckBitsAny(m_rhiBuffer->GetDescriptor().m_bindFlags,
|
||||
RHI::BufferBindFlags::ShaderWrite | RHI::BufferBindFlags::CopyWrite | RHI::BufferBindFlags::DynamicInputAssembly))
|
||||
{
|
||||
// attachment id = bufferName_bufferInstanceId
|
||||
m_attachmentId = Name(bufferAsset.GetName() + "_" + bufferAsset.GetId().m_guid.ToString<AZStd::string>(false, false));
|
||||
}
|
||||
|
||||
return RHI::ResultCode::Success;
|
||||
}
|
||||
@@ -312,7 +318,8 @@ namespace AZ
|
||||
|
||||
const RHI::AttachmentId& Buffer::GetAttachmentId() const
|
||||
{
|
||||
return m_rhiBuffer->GetName();
|
||||
AZ_Assert(!m_attachmentId.GetStringView().empty(), "Read-only buffer doesn't need attachment id");
|
||||
return m_attachmentId;
|
||||
}
|
||||
|
||||
const RHI::BufferViewDescriptor& Buffer::GetBufferViewDescriptor() const
|
||||
|
||||
@@ -152,15 +152,22 @@ namespace AZ
|
||||
}
|
||||
|
||||
Data::Instance<Buffer> BufferSystem::CreateBufferFromCommonPool(const CommonBufferDescriptor& descriptor)
|
||||
{
|
||||
Uuid bufferId = Uuid::CreateName(descriptor.m_bufferName.c_str());
|
||||
|
||||
// Report error if there is a buffer with same name.
|
||||
// Note: this shouldn't return the existing buffer because users are expecting a newly created buffer.
|
||||
if (Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId(bufferId)))
|
||||
{
|
||||
Uuid bufferId;
|
||||
if (descriptor.m_isUniqueName)
|
||||
{
|
||||
AZ_Error("BufferSystem", false, "Buffer with same name '%s' already exist", descriptor.m_bufferName.c_str());
|
||||
return nullptr;
|
||||
bufferId = Uuid::CreateName(descriptor.m_bufferName.c_str());
|
||||
// Report error if there is a buffer with same name.
|
||||
// Note: this shouldn't return the existing buffer because users are expecting a newly created buffer.
|
||||
if (Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId(bufferId)))
|
||||
{
|
||||
AZ_Error("BufferSystem", false, "Buffer with same name '%s' already exist", descriptor.m_bufferName.c_str());
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bufferId = Uuid::CreateRandom();
|
||||
}
|
||||
|
||||
RHI::Ptr<RHI::BufferPool> bufferPool = GetCommonBufferPool(descriptor.m_poolType);
|
||||
@@ -207,9 +214,9 @@ namespace AZ
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Data::Instance<Buffer> BufferSystem::FindCommonBuffer(AZStd::string_view bufferName)
|
||||
Data::Instance<Buffer> BufferSystem::FindCommonBuffer(AZStd::string_view uniqueBufferName)
|
||||
{
|
||||
Uuid bufferId = Uuid::CreateName(bufferName.data());
|
||||
Uuid bufferId = Uuid::CreateName(uniqueBufferName.data());
|
||||
return Data::InstanceDatabase<Buffer>::Instance().Find(Data::InstanceId(bufferId));
|
||||
}
|
||||
} // namespace RPI
|
||||
|
||||
@@ -30,7 +30,7 @@ namespace AZ
|
||||
// Create the ring buffer from common pool
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::DynamicInputAssembly;
|
||||
desc.m_bufferName = AZStd::string::format("DyanmicBufferRing_%p", this);
|
||||
desc.m_bufferName = "DyanmicBufferRing";
|
||||
desc.m_elementSize = 1;
|
||||
desc.m_byteCount = ringBufferSize;
|
||||
m_ringBuffer = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
|
||||
@@ -30,7 +30,8 @@ namespace AZ
|
||||
if (auto* serializeContext = azrtti_cast<SerializeContext*>(context))
|
||||
{
|
||||
serializeContext->Class<BufferAsset>()
|
||||
->Version(1)
|
||||
->Version(2)
|
||||
->Field("Name", &BufferAsset::m_name)
|
||||
->Field("Buffer", &BufferAsset::m_buffer)
|
||||
->Field("BufferDescriptor", &BufferAsset::m_bufferDescriptor)
|
||||
->Field("BufferViewDescriptor", &BufferAsset::m_bufferViewDescriptor)
|
||||
@@ -80,5 +81,10 @@ namespace AZ
|
||||
{
|
||||
return m_poolType;
|
||||
}
|
||||
|
||||
const AZStd::string& BufferAsset::GetName() const
|
||||
{
|
||||
return m_name;
|
||||
}
|
||||
} //namespace RPI
|
||||
} // namespace AZ
|
||||
|
||||
@@ -152,7 +152,10 @@ namespace AZ
|
||||
|
||||
void BufferAssetCreator::SetBufferName(AZStd::string_view name)
|
||||
{
|
||||
m_asset.SetHint(name);
|
||||
if (ValidateIsReady())
|
||||
{
|
||||
m_asset->m_name = name;
|
||||
}
|
||||
}
|
||||
|
||||
bool BufferAssetCreator::Clone(const Data::Asset<BufferAsset>& sourceAsset, Data::Asset<BufferAsset>& clonedResult, Data::AssetId& inOutLastCreatedAssetId)
|
||||
|
||||
@@ -474,6 +474,7 @@ namespace UnitTest
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = "Buffer1";
|
||||
desc.m_byteCount = bufferInfo.m_bufferDescriptor.m_byteCount;
|
||||
desc.m_isUniqueName = true;
|
||||
|
||||
Data::Instance<RPI::Buffer> bufferInst = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
// buffer created
|
||||
@@ -488,8 +489,33 @@ namespace UnitTest
|
||||
EXPECT_EQ(bufferFound2.get(), nullptr);
|
||||
}
|
||||
|
||||
// Failed if creates a buffer with duplicated name with existing buffer
|
||||
TEST_F(BufferTests, BufferSystem_CreateDuplicatedNamedBuffer_Fail)
|
||||
// Failed if creates a buffe which has a same name with existing buffer
|
||||
// and has m_isUniqueName is enabled
|
||||
TEST_F(BufferTests, BufferSystem_CreateDuplicatedNamedBufferEnableUniqueName_Fail)
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
ExpectedBuffer bufferInfo = CreateValidBuffer();
|
||||
|
||||
RPI::CommonBufferDescriptor desc;
|
||||
desc.m_poolType = RPI::CommonBufferPoolType::ReadOnly;
|
||||
desc.m_bufferName = "Buffer1";
|
||||
desc.m_byteCount = bufferInfo.m_bufferDescriptor.m_byteCount;
|
||||
desc.m_isUniqueName = true;
|
||||
|
||||
Data::Instance<RPI::Buffer> bufferInst = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
// buffer created
|
||||
EXPECT_NE(bufferInst.get(), nullptr);
|
||||
|
||||
AZ_TEST_START_ASSERTTEST;
|
||||
Data::Instance<RPI::Buffer> bufferInst2 = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
AZ_TEST_STOP_ASSERTTEST(1);
|
||||
// buffer NOT created
|
||||
EXPECT_EQ(bufferInst2.get(), nullptr);
|
||||
}
|
||||
|
||||
// create a buffer which has a same name with existing buffer
|
||||
TEST_F(BufferTests, BufferSystem_CreateDuplicatedNamedBuffers_Success)
|
||||
{
|
||||
using namespace AZ;
|
||||
|
||||
@@ -503,12 +529,10 @@ namespace UnitTest
|
||||
Data::Instance<RPI::Buffer> bufferInst = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
// buffer created
|
||||
EXPECT_NE(bufferInst.get(), nullptr);
|
||||
|
||||
AZ_TEST_START_ASSERTTEST;
|
||||
|
||||
Data::Instance<RPI::Buffer> bufferInst2 = RPI::BufferSystemInterface::Get()->CreateBufferFromCommonPool(desc);
|
||||
AZ_TEST_STOP_ASSERTTEST(1);
|
||||
// buffer NOT created
|
||||
EXPECT_EQ(bufferInst2.get(), nullptr);
|
||||
// buffer created
|
||||
EXPECT_NE(bufferInst2.get(), nullptr);
|
||||
}
|
||||
|
||||
// Buffer instance creation unit tests
|
||||
|
||||
+2
-2
@@ -510,9 +510,9 @@ namespace ShaderManagementConsole
|
||||
AZStd::vector<AZ::Uuid> documentIdsToClose;
|
||||
documentIdsToClose.reserve(m_tabWidget->count());
|
||||
const AZ::Uuid documentIdToKeepOpen = GetDocumentIdFromTab(tabIndex);
|
||||
for (int tabIndex = 0; tabIndex < m_tabWidget->count(); ++tabIndex)
|
||||
for (int tabI = 0; tabI < m_tabWidget->count(); ++tabI)
|
||||
{
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabIndex);
|
||||
const AZ::Uuid documentId = GetDocumentIdFromTab(tabI);
|
||||
if (documentId != documentIdToKeepOpen)
|
||||
{
|
||||
documentIdsToClose.push_back(documentId);
|
||||
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* All or portions of this file Copyright (c) Amazon.com, Inc. or its affiliates or
|
||||
* its licensors.
|
||||
*
|
||||
* For complete copyright and license terms please see the LICENSE at the root of this
|
||||
* distribution (the "License"). All use of this software is governed by the License,
|
||||
* or, if provided, by the license below or the license accompanying this file. Do not
|
||||
* remove or modify any license notices. This file is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
*
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
#include <AzCore/Component/ComponentBus.h>
|
||||
#include <Atom/Feature/Material/MaterialAssignment.h>
|
||||
#include <ACES/Aces.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
struct AcesParameterOverrides;
|
||||
|
||||
//! DisplayMapperComponentRequests provides an interface to request operations on a DisplayMapperComponent
|
||||
class DisplayMapperComponentRequests
|
||||
: public ComponentBus
|
||||
{
|
||||
public:
|
||||
AZ_RTTI(AZ::Render::DisplayMapperComponentRequests, "{9E2E8AF5-1176-44B4-A461-E09867753349}");
|
||||
|
||||
/// Overrides the default AZ::EBusTraits handler policy to allow one listener only.
|
||||
static const EBusHandlerPolicy HandlerPolicy = EBusHandlerPolicy::Single;
|
||||
|
||||
//! Load preconfigured preset for specific ODT mode
|
||||
virtual void LoadPreset(OutputDeviceTransformType preset) = 0;
|
||||
//! Set display mapper type
|
||||
virtual void SetDisplayMapperOperationType(DisplayMapperOperationType displayMapperOperationType) = 0;
|
||||
//! Get display mapper type
|
||||
virtual DisplayMapperOperationType GetDisplayMapperOperationType() const = 0;
|
||||
//! Set ACES parameter overrides for ACES mapping, display mapper must be set to Aces to see the difference
|
||||
virtual void SetAcesParameterOverrides(const AcesParameterOverrides& parameterOverrides) = 0;
|
||||
//! Get ACES parameter overrides
|
||||
virtual const AcesParameterOverrides& GetAcesParameterOverrides() const = 0;
|
||||
|
||||
// Enable or disable ACES parameter overrides
|
||||
virtual void SetOverrideAcesParameters(bool value) = 0;
|
||||
// Check if ACES parameters are overriding default preset values
|
||||
virtual bool GetOverrideAcesParameters() const = 0;
|
||||
|
||||
// Set gamma adjustment to compensate for dim surround
|
||||
virtual void SetAlterSurround(bool value) = 0;
|
||||
// Get gamma adjustment to compensate for dim surround
|
||||
virtual bool GetAlterSurround() const = 0;
|
||||
|
||||
// Set desaturation to compensate for luminance difference
|
||||
virtual void SetApplyDesaturation(bool value) = 0;
|
||||
// Get desaturation to compensate for luminance difference
|
||||
virtual bool GetApplyDesaturation() const = 0;
|
||||
|
||||
// Set color appearance transform (CAT) from ACES white point to assumed observer adapted white point
|
||||
virtual void SetApplyCATD60toD65(bool value) = 0;
|
||||
// Get color appearance transform (CAT) from ACES white point to assumed observer adapted white point
|
||||
virtual bool GetApplyCATD60toD65() const = 0;
|
||||
|
||||
// Set reference black luminance value
|
||||
virtual void SetCinemaLimitsBlack(float value) = 0;
|
||||
// Get reference black luminance value
|
||||
virtual float GetCinemaLimitsBlack() const = 0;
|
||||
|
||||
// Set reference white luminance value
|
||||
virtual void SetCinemaLimitsWhite(float value) = 0;
|
||||
// Get reference white luminance value
|
||||
virtual float GetCinemaLimitsWhite() const = 0;
|
||||
|
||||
// Set min luminance value
|
||||
virtual void SetMinPoint(float value) = 0;
|
||||
// Get min luminance value
|
||||
virtual float GetMinPoint() const = 0;
|
||||
|
||||
// Set mid luminance value
|
||||
virtual void SetMidPoint(float value) = 0;
|
||||
// Get mid luminance value
|
||||
virtual float GetMidPoint() const = 0;
|
||||
|
||||
// Set max luminance value
|
||||
virtual void SetMaxPoint(float value) = 0;
|
||||
// Get max luminance value
|
||||
virtual float GetMaxPoint() const = 0;
|
||||
|
||||
// Set gamma adjustment value
|
||||
virtual void SetSurroundGamma(float value) = 0;
|
||||
// Get gamma adjustment value
|
||||
virtual float GetSurroundGamma() const = 0;
|
||||
|
||||
// Set optional gamma value that is applied as basic gamma curve OETF
|
||||
virtual void SetGamma(float value) = 0;
|
||||
// Get optional gamma value that is applied as basic gamma curve OETF
|
||||
virtual float GetGamma() const = 0;
|
||||
};
|
||||
using DisplayMapperComponentRequestBus = EBus<DisplayMapperComponentRequests>;
|
||||
|
||||
//! DisplayMapperComponent can send out notifications on the DisplayMapperComponentNotifications
|
||||
class DisplayMapperComponentNotifications : public ComponentBus
|
||||
{
|
||||
public:
|
||||
//! Notifies that display mapper type changed
|
||||
virtual void OnDisplayMapperOperationTypeUpdated([[maybe_unused]] const DisplayMapperOperationType& displayMapperOperationType)
|
||||
{
|
||||
}
|
||||
|
||||
//! Notifies that ACES parameter overrides changed
|
||||
virtual void OnAcesParameterOverridesUpdated([[maybe_unused]] const AcesParameterOverrides& acesParameterOverrides)
|
||||
{
|
||||
}
|
||||
};
|
||||
using DisplayMapperComponentNotificationBus = EBus<DisplayMapperComponentNotifications>;
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
@@ -54,13 +54,14 @@ namespace AZ
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &GridComponentConfig::m_gridSize, "Grid Size", "Grid width and depth")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Min, GridComponentController::MinGridSize)
|
||||
->Attribute(AZ::Edit::Attributes::Max, GridComponentController::MaxGridSize)
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " m")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &GridComponentConfig::m_primarySpacing, "Primary Grid Spacing", "Amount of space between grid lines")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.01f)
|
||||
->Attribute(AZ::Edit::Attributes::Min, GridComponentController::MinSpacing)
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " m")
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &GridComponentConfig::m_secondarySpacing, "Secondary Grid Spacing", "Amount of space between sub-grid lines")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.01f)
|
||||
->Attribute(AZ::Edit::Attributes::Min, GridComponentController::MinSpacing)
|
||||
->Attribute(AZ::Edit::Attributes::Suffix, " m")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &GridComponentConfig::m_axisColor, "Axis Color", "Color of the grid axis")
|
||||
->DataElement(AZ::Edit::UIHandlers::Color, &GridComponentConfig::m_primaryColor, "Primary Color", "Color of the primary grid lines")
|
||||
|
||||
@@ -115,7 +115,7 @@ namespace AZ
|
||||
|
||||
void GridComponentController::SetSize(float gridSize)
|
||||
{
|
||||
m_configuration.m_gridSize = gridSize;
|
||||
m_configuration.m_gridSize = AZStd::clamp(gridSize, MinGridSize, MaxGridSize);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace AZ
|
||||
|
||||
void GridComponentController::SetPrimarySpacing(float gridPrimarySpacing)
|
||||
{
|
||||
m_configuration.m_primarySpacing = gridPrimarySpacing;
|
||||
m_configuration.m_primarySpacing = AZStd::max(gridPrimarySpacing, MinSpacing);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
@@ -137,7 +137,7 @@ namespace AZ
|
||||
|
||||
void GridComponentController::SetSecondarySpacing(float gridSecondarySpacing)
|
||||
{
|
||||
m_configuration.m_secondarySpacing = gridSecondarySpacing;
|
||||
m_configuration.m_secondarySpacing = AZStd::max(gridSecondarySpacing, MinSpacing);
|
||||
m_dirty = true;
|
||||
}
|
||||
|
||||
|
||||
@@ -46,6 +46,10 @@ namespace AZ
|
||||
void SetConfiguration(const GridComponentConfig& config);
|
||||
const GridComponentConfig& GetConfiguration() const;
|
||||
|
||||
static constexpr float MinGridSize = 0.0f;
|
||||
static constexpr float MaxGridSize = 1000000.0f;
|
||||
static constexpr float MinSpacing = 0.01f;
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY(GridComponentController);
|
||||
|
||||
|
||||
-1
@@ -39,6 +39,5 @@ namespace AZ
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace Render
|
||||
} // namespace AZ
|
||||
|
||||
+282
@@ -10,6 +10,8 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "AtomLyIntegration/CommonFeatures/CoreLights/AreaLightBus.h"
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
|
||||
#include <Atom/RPI.Public/Scene.h>
|
||||
@@ -32,6 +34,69 @@ namespace AZ
|
||||
->Version(0)
|
||||
->Field("Configuration", &DisplayMapperComponentController::m_configuration);
|
||||
}
|
||||
|
||||
if (AZ::BehaviorContext* behaviorContext = azrtti_cast<AZ::BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->EBus<DisplayMapperComponentRequestBus>("DisplayMapperComponentRequestBus")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Common)
|
||||
->Attribute(AZ::Script::Attributes::Category, "render")
|
||||
->Attribute(AZ::Script::Attributes::Module, "render")
|
||||
// LoadPreset
|
||||
->Event("LoadPreset", &DisplayMapperComponentRequestBus::Events::LoadPreset)
|
||||
// DisplayMapperOperationType
|
||||
->Event("SetDisplayMapperOperationType", &DisplayMapperComponentRequestBus::Events::SetDisplayMapperOperationType)
|
||||
->Event("GetDisplayMapperOperationType", &DisplayMapperComponentRequestBus::Events::GetDisplayMapperOperationType)
|
||||
->VirtualProperty("DisplayMapperOperationType", "GetDisplayMapperOperationType", "SetDisplayMapperOperationType")
|
||||
// AcesParameterOverrides
|
||||
->Event("SetAcesParameterOverrides", &DisplayMapperComponentRequestBus::Events::SetAcesParameterOverrides)
|
||||
->Event("GetAcesParameterOverrides", &DisplayMapperComponentRequestBus::Events::GetAcesParameterOverrides)
|
||||
->VirtualProperty("AcesParameterOverrides", "GetAcesParameterOverrides", "SetAcesParameterOverrides")
|
||||
// OverrideAcesParameters
|
||||
->Event("SetOverrideAcesParameters", &DisplayMapperComponentRequestBus::Events::SetOverrideAcesParameters)
|
||||
->Event("GetOverrideAcesParameters", &DisplayMapperComponentRequestBus::Events::GetOverrideAcesParameters)
|
||||
->VirtualProperty("OverrideAcesParameters", "GetOverrideAcesParameters", "SetOverrideAcesParameters")
|
||||
// AlterSurround
|
||||
->Event("SetAlterSurround", &DisplayMapperComponentRequestBus::Events::SetAlterSurround)
|
||||
->Event("GetAlterSurround", &DisplayMapperComponentRequestBus::Events::GetAlterSurround)
|
||||
->VirtualProperty("AlterSurround", "GetAlterSurround", "SetAlterSurround")
|
||||
// ApplyDesaturation
|
||||
->Event("SetApplyDesaturation", &DisplayMapperComponentRequestBus::Events::SetApplyDesaturation)
|
||||
->Event("GetApplyDesaturation", &DisplayMapperComponentRequestBus::Events::GetApplyDesaturation)
|
||||
->VirtualProperty("ApplyDesaturation", "GetApplyDesaturation", "SetApplyDesaturation")
|
||||
// ApplyCATD60toD65
|
||||
->Event("SetApplyCATD60toD65", &DisplayMapperComponentRequestBus::Events::SetApplyCATD60toD65)
|
||||
->Event("GetApplyCATD60toD65", &DisplayMapperComponentRequestBus::Events::GetApplyCATD60toD65)
|
||||
->VirtualProperty("ApplyCATD60toD65", "GetApplyCATD60toD65", "SetApplyCATD60toD65")
|
||||
// CinemaLimitsBlack
|
||||
->Event("SetCinemaLimitsBlack", &DisplayMapperComponentRequestBus::Events::SetCinemaLimitsBlack)
|
||||
->Event("GetCinemaLimitsBlack", &DisplayMapperComponentRequestBus::Events::GetCinemaLimitsBlack)
|
||||
->VirtualProperty("CinemaLimitsBlack", "GetCinemaLimitsBlack", "SetCinemaLimitsBlack")
|
||||
// CinemaLimitsWhite
|
||||
->Event("SetCinemaLimitsWhite", &DisplayMapperComponentRequestBus::Events::SetCinemaLimitsWhite)
|
||||
->Event("GetCinemaLimitsWhite", &DisplayMapperComponentRequestBus::Events::GetCinemaLimitsWhite)
|
||||
->VirtualProperty("CinemaLimitsWhite", "GetCinemaLimitsWhite", "SetCinemaLimitsWhite")
|
||||
// MinPoint
|
||||
->Event("SetMinPoint", &DisplayMapperComponentRequestBus::Events::SetMinPoint)
|
||||
->Event("GetMinPoint", &DisplayMapperComponentRequestBus::Events::GetMinPoint)
|
||||
->VirtualProperty("MinPoint", "GetMinPoint", "SetMinPoint")
|
||||
// MidPoint
|
||||
->Event("SetMidPoint", &DisplayMapperComponentRequestBus::Events::SetMidPoint)
|
||||
->Event("GetMidPoint", &DisplayMapperComponentRequestBus::Events::GetMidPoint)
|
||||
->VirtualProperty("MidPoint", "GetMidPoint", "SetMidPoint")
|
||||
// MaxPoint
|
||||
->Event("SetMaxPoint", &DisplayMapperComponentRequestBus::Events::SetMaxPoint)
|
||||
->Event("GetMaxPoint", &DisplayMapperComponentRequestBus::Events::GetMaxPoint)
|
||||
->VirtualProperty("MaxPoint", "GetMaxPoint", "SetMaxPoint")
|
||||
// SurroundGamma
|
||||
->Event("SetSurroundGamma", &DisplayMapperComponentRequestBus::Events::SetSurroundGamma)
|
||||
->Event("GetSurroundGamma", &DisplayMapperComponentRequestBus::Events::GetSurroundGamma)
|
||||
->VirtualProperty("SurroundGamma", "GetSurroundGamma", "SetSurroundGamma")
|
||||
// Gamma
|
||||
->Event("SetGamma", &DisplayMapperComponentRequestBus::Events::SetGamma)
|
||||
->Event("GetGamma", &DisplayMapperComponentRequestBus::Events::GetGamma)
|
||||
->VirtualProperty("Gamma", "GetGamma", "SetGamma")
|
||||
;
|
||||
}
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::GetProvidedServices(AZ::ComponentDescriptor::DependencyArrayType& provided)
|
||||
@@ -57,10 +122,14 @@ namespace AZ
|
||||
void DisplayMapperComponentController::Activate(EntityId entityId)
|
||||
{
|
||||
m_entityId = entityId;
|
||||
|
||||
DisplayMapperComponentRequestBus::Handler::BusConnect(m_entityId);
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::Deactivate()
|
||||
{
|
||||
DisplayMapperComponentRequestBus::Handler::BusDisconnect(m_entityId);
|
||||
|
||||
m_postProcessInterface = nullptr;
|
||||
m_entityId.SetInvalid();
|
||||
}
|
||||
@@ -76,6 +145,219 @@ namespace AZ
|
||||
return m_configuration;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::LoadPreset(OutputDeviceTransformType preset)
|
||||
{
|
||||
AcesParameterOverrides propertyOverrides;
|
||||
propertyOverrides.m_preset = preset;
|
||||
propertyOverrides.m_overrideDefaults = true;
|
||||
propertyOverrides.LoadPreset();
|
||||
SetAcesParameterOverrides(propertyOverrides);
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetDisplayMapperOperationType(DisplayMapperOperationType displayMapperOperationType)
|
||||
{
|
||||
if (m_configuration.m_displayMapperOperation != displayMapperOperationType)
|
||||
{
|
||||
m_configuration.m_displayMapperOperation = displayMapperOperationType;
|
||||
OnConfigChanged();
|
||||
DisplayMapperComponentNotificationBus::Broadcast(
|
||||
&DisplayMapperComponentNotificationBus::Handler::OnDisplayMapperOperationTypeUpdated,
|
||||
m_configuration.m_displayMapperOperation);
|
||||
}
|
||||
}
|
||||
|
||||
DisplayMapperOperationType DisplayMapperComponentController::GetDisplayMapperOperationType() const
|
||||
{
|
||||
return m_configuration.m_displayMapperOperation;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetAcesParameterOverrides(const AcesParameterOverrides& parameterOverrides)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides = parameterOverrides;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
DisplayMapperComponentNotificationBus::Broadcast(
|
||||
&DisplayMapperComponentNotificationBus::Handler::OnAcesParameterOverridesUpdated,
|
||||
m_configuration.m_acesParameterOverrides);
|
||||
}
|
||||
|
||||
const AcesParameterOverrides& DisplayMapperComponentController::GetAcesParameterOverrides() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetOverrideAcesParameters(bool value)
|
||||
{
|
||||
if (m_configuration.m_acesParameterOverrides.m_overrideDefaults == value)
|
||||
{
|
||||
return; // prevents flickering when set via TrackView
|
||||
}
|
||||
m_configuration.m_acesParameterOverrides.m_overrideDefaults = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayMapperComponentController::GetOverrideAcesParameters() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_overrideDefaults;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetAlterSurround(bool value)
|
||||
{
|
||||
if (m_configuration.m_acesParameterOverrides.m_alterSurround != value)
|
||||
{
|
||||
return; // prevents flickering when set via TrackView
|
||||
}
|
||||
m_configuration.m_acesParameterOverrides.m_alterSurround = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayMapperComponentController::GetAlterSurround() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_alterSurround;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetApplyDesaturation(bool value)
|
||||
{
|
||||
if (m_configuration.m_acesParameterOverrides.m_applyDesaturation != value)
|
||||
{
|
||||
return; // prevents flickering when set via TrackView
|
||||
}
|
||||
m_configuration.m_acesParameterOverrides.m_applyDesaturation = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayMapperComponentController::GetApplyDesaturation() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_applyDesaturation;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetApplyCATD60toD65(bool value)
|
||||
{
|
||||
if (m_configuration.m_acesParameterOverrides.m_applyCATD60toD65 != value)
|
||||
{
|
||||
return; // prevents flickering when set via TrackView
|
||||
}
|
||||
m_configuration.m_acesParameterOverrides.m_applyCATD60toD65 = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
bool DisplayMapperComponentController::GetApplyCATD60toD65() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_applyCATD60toD65;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetCinemaLimitsBlack(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_cinemaLimitsBlack = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetCinemaLimitsBlack() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_cinemaLimitsBlack;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetCinemaLimitsWhite(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_cinemaLimitsWhite = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetCinemaLimitsWhite() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_cinemaLimitsWhite;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetMinPoint(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_minPoint = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetMinPoint() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_minPoint;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetMidPoint(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_midPoint = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetMidPoint() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_midPoint;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetMaxPoint(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_maxPoint = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetMaxPoint() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_maxPoint;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetSurroundGamma(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_surroundGamma = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetSurroundGamma() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_surroundGamma;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::SetGamma(float value)
|
||||
{
|
||||
m_configuration.m_acesParameterOverrides.m_gamma = value;
|
||||
if (m_configuration.m_displayMapperOperation == DisplayMapperOperationType::Aces)
|
||||
{
|
||||
OnConfigChanged();
|
||||
}
|
||||
}
|
||||
|
||||
float DisplayMapperComponentController::GetGamma() const
|
||||
{
|
||||
return m_configuration.m_acesParameterOverrides.m_gamma;
|
||||
}
|
||||
|
||||
void DisplayMapperComponentController::OnConfigChanged()
|
||||
{
|
||||
// Register the configuration with the AcesDisplayMapperFeatureProcessor for this scene.
|
||||
|
||||
+34
@@ -12,10 +12,12 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
|
||||
#include <AzCore/Component/Component.h>
|
||||
#include <AzCore/Component/TransformBus.h>
|
||||
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h>
|
||||
#include <AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentBus.h>
|
||||
|
||||
#include <Atom/Feature/PostProcess/PostProcessSettingsInterface.h>
|
||||
#include <Atom/Feature/PostProcess/PostProcessFeatureProcessorInterface.h>
|
||||
@@ -24,7 +26,10 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
struct AcesParameterOverrides;
|
||||
|
||||
class DisplayMapperComponentController final
|
||||
: DisplayMapperComponentRequestBus::Handler
|
||||
{
|
||||
public:
|
||||
friend class EditorDisplayMapperComponent;
|
||||
@@ -43,6 +48,35 @@ namespace AZ
|
||||
void SetConfiguration(const DisplayMapperComponentConfig& config);
|
||||
const DisplayMapperComponentConfig& GetConfiguration() const;
|
||||
|
||||
//! DisplayMapperComponentRequestBus::Handler overrides...
|
||||
void LoadPreset(OutputDeviceTransformType preset) override;
|
||||
void SetDisplayMapperOperationType(DisplayMapperOperationType displayMapperOperationType) override;
|
||||
DisplayMapperOperationType GetDisplayMapperOperationType() const override;
|
||||
void SetAcesParameterOverrides(const AcesParameterOverrides& parameterOverrides) override;
|
||||
const AcesParameterOverrides& GetAcesParameterOverrides() const override;
|
||||
void SetOverrideAcesParameters(bool value) override;
|
||||
bool GetOverrideAcesParameters() const override;
|
||||
void SetAlterSurround(bool value) override;
|
||||
bool GetAlterSurround() const override;
|
||||
void SetApplyDesaturation(bool value) override;
|
||||
bool GetApplyDesaturation() const override;
|
||||
void SetApplyCATD60toD65(bool value) override;
|
||||
bool GetApplyCATD60toD65() const override;
|
||||
void SetCinemaLimitsBlack(float value) override;
|
||||
float GetCinemaLimitsBlack() const override;
|
||||
void SetCinemaLimitsWhite(float value) override;
|
||||
float GetCinemaLimitsWhite() const override;
|
||||
void SetMinPoint(float value) override;
|
||||
float GetMinPoint() const override;
|
||||
void SetMidPoint(float value) override;
|
||||
float GetMidPoint() const override;
|
||||
void SetMaxPoint(float value) override;
|
||||
float GetMaxPoint() const override;
|
||||
void SetSurroundGamma(float value) override;
|
||||
float GetSurroundGamma() const override;
|
||||
void SetGamma(float value) override;
|
||||
float GetGamma() const override;
|
||||
|
||||
private:
|
||||
AZ_DISABLE_COPY(DisplayMapperComponentController);
|
||||
|
||||
|
||||
+53
-17
@@ -10,10 +10,9 @@
|
||||
*
|
||||
*/
|
||||
|
||||
#include "Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h"
|
||||
|
||||
#include <AzCore/RTTI/BehaviorContext.h>
|
||||
#include <PostProcess/DisplayMapper/EditorDisplayMapperComponent.h>
|
||||
#include <Atom/Feature/ACES/AcesDisplayMapperFeatureProcessor.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -54,54 +53,89 @@ namespace AZ
|
||||
->ClassElement(AZ::Edit::ClassElements::EditorData, "")
|
||||
->Attribute(AZ::Edit::Attributes::AutoExpand, true)
|
||||
|
||||
// m_overrideDefaults
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &AcesParameterOverrides::m_overrideDefaults, "Override Defaults",
|
||||
"When enabled allows parameter overrides for ACES configuration")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_alterSurround
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &AcesParameterOverrides::m_alterSurround, "Alter Surround",
|
||||
"Apply gamma adjustment to compensate for dim surround")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_applyDesaturation
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &AcesParameterOverrides::m_applyDesaturation, "Alter Desaturation",
|
||||
"Apply desaturation to compensate for luminance difference")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_applyCATD60toD65
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::CheckBox, &AcesParameterOverrides::m_applyCATD60toD65, "Alter CAT D60 to D65",
|
||||
"Apply Color appearance transform (CAT) from ACES white point to assumed observer adapted white point")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
|
||||
// m_cinemaLimitsBlack
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Default, &AcesParameterOverrides::m_cinemaLimitsBlack,
|
||||
Edit::UIHandlers::Slider, &AcesParameterOverrides::m_cinemaLimitsBlack,
|
||||
"Cinema Limit (black)",
|
||||
"Reference black luminance value")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.02f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, &AcesParameterOverrides::m_cinemaLimitsWhite)
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.005f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_cinemaLimitsWhite
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Default, &AcesParameterOverrides::m_cinemaLimitsWhite,
|
||||
Edit::UIHandlers::Slider, &AcesParameterOverrides::m_cinemaLimitsWhite,
|
||||
"Cinema Limit (white)",
|
||||
"Reference white luminance value")
|
||||
->Attribute(AZ::Edit::Attributes::Min, &AcesParameterOverrides::m_cinemaLimitsBlack)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 4000.f)
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.005f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_minPoint
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Vector2, &AcesParameterOverrides::m_minPoint, "Min Point (luminance)",
|
||||
Edit::UIHandlers::Slider, &AcesParameterOverrides::m_minPoint, "Min Point (luminance)",
|
||||
"Linear extension below this")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.002f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, &AcesParameterOverrides::m_midPoint)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues)
|
||||
|
||||
// m_midPoint
|
||||
->DataElement(Edit::UIHandlers::Slider, &AcesParameterOverrides::m_midPoint,
|
||||
"Mid Point (luminance)", "Middle gray")
|
||||
->Attribute(AZ::Edit::Attributes::Min, &AcesParameterOverrides::m_minPoint)
|
||||
->Attribute(AZ::Edit::Attributes::Max, &AcesParameterOverrides::m_maxPoint)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues)
|
||||
|
||||
// m_maxPoint
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Vector2, &AcesParameterOverrides::m_midPoint, "Mid Point (luminance)",
|
||||
"Middle gray")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->DataElement(
|
||||
Edit::UIHandlers::Vector2, &AcesParameterOverrides::m_maxPoint, "Max Point (luminance)",
|
||||
Edit::UIHandlers::Slider, &AcesParameterOverrides::m_maxPoint, "Max Point (luminance)",
|
||||
"Linear extension above this")
|
||||
->Attribute(AZ::Edit::Attributes::Min, &AcesParameterOverrides::m_midPoint)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 4000.f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::AttributesAndValues)
|
||||
|
||||
// m_surroundGamma
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Slider, &AcesParameterOverrides::m_surroundGamma, "Surround Gamma",
|
||||
"Gamma adjustment to be applied to compensate for the condition of the viewing environment")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.6f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 1.2f)
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.005f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// m_gamma
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AcesParameterOverrides::m_surroundGamma, "Surround Gamma",
|
||||
"Gamma adjustment to be applied to compensate for the condition of the viewing environment")
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
->DataElement(
|
||||
AZ::Edit::UIHandlers::Default, &AcesParameterOverrides::m_gamma, "Gamma",
|
||||
AZ::Edit::UIHandlers::Slider, &AcesParameterOverrides::m_gamma, "Gamma",
|
||||
"Optional gamma value that is applied as basic gamma curve OETF")
|
||||
->Attribute(AZ::Edit::Attributes::Min, 0.2f)
|
||||
->Attribute(AZ::Edit::Attributes::Max, 4.0f)
|
||||
->Attribute(AZ::Edit::Attributes::Step, 0.005f)
|
||||
->Attribute(Edit::Attributes::ChangeNotify, Edit::PropertyRefreshLevels::ValuesOnly)
|
||||
|
||||
// Load preset group
|
||||
@@ -145,6 +179,8 @@ namespace AZ
|
||||
|
||||
if (auto behaviorContext = azrtti_cast<BehaviorContext*>(context))
|
||||
{
|
||||
behaviorContext->Class<EditorDisplayMapperComponent>()->RequestBus("DisplayMapperComponentRequestBus");
|
||||
|
||||
behaviorContext->ConstantProperty("EditorDisplayMapperComponentTypeId", BehaviorConstant(Uuid(EditorDisplayMapperComponentTypeId)))
|
||||
->Attribute(AZ::Script::Attributes::Module, "render")
|
||||
->Attribute(AZ::Script::Attributes::Scope, AZ::Script::Attributes::ScopeFlags::Automation);
|
||||
|
||||
+19
-1
@@ -39,6 +39,7 @@ namespace AZ
|
||||
serializeContext->Class<EditorReflectionProbeComponent, BaseClass>()
|
||||
->Version(2, ConvertToEditorRenderComponentAdapter<1>)
|
||||
->Field("useBakedCubemap", &EditorReflectionProbeComponent::m_useBakedCubemap)
|
||||
->Field("bakedCubeMapQualityLevel", &EditorReflectionProbeComponent::m_bakedCubeMapQualityLevel)
|
||||
->Field("bakedCubeMapRelativePath", &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath)
|
||||
->Field("authoredCubeMapAsset", &EditorReflectionProbeComponent::m_authoredCubeMapAsset)
|
||||
;
|
||||
@@ -67,6 +68,13 @@ namespace AZ
|
||||
->DataElement(AZ::Edit::UIHandlers::Default, &EditorReflectionProbeComponent::m_useBakedCubemap, "Use Baked Cubemap", "Selects between a cubemap that captures the environment at location in the scene or a preauthored cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::ChangeValidate, &EditorReflectionProbeComponent::OnUseBakedCubemapValidate)
|
||||
->Attribute(AZ::Edit::Attributes::ChangeNotify, &EditorReflectionProbeComponent::OnUseBakedCubemapChanged)
|
||||
->DataElement(AZ::Edit::UIHandlers::ComboBox, &EditorReflectionProbeComponent::m_bakedCubeMapQualityLevel, "Baked Cubemap Quality", "Resolution of the baked cubemap")
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::VeryLow, "Very Low")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::Low, "Low")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::Medium, "Medium")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::High, "High")
|
||||
->EnumAttribute(BakedCubeMapQualityLevel::VeryHigh, "Very High")
|
||||
->DataElement(AZ::Edit::UIHandlers::MultiLineEdit, &EditorReflectionProbeComponent::m_bakedCubeMapRelativePath, "Baked Cubemap Path", "Baked Cubemap Path")
|
||||
->Attribute(AZ::Edit::Attributes::ReadOnly, true)
|
||||
->Attribute(AZ::Edit::Attributes::Visibility, &EditorReflectionProbeComponent::GetBakedCubemapVisibilitySetting)
|
||||
@@ -332,6 +340,12 @@ namespace AZ
|
||||
// clear it to force the generation of a new filename
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
|
||||
// if the quality level changed we need to generate a new filename
|
||||
if (m_controller.m_configuration.m_bakedCubeMapQualityLevel != m_bakedCubeMapQualityLevel)
|
||||
{
|
||||
cubeMapRelativePath.clear();
|
||||
}
|
||||
}
|
||||
|
||||
// build a new cubemap path if necessary
|
||||
@@ -345,7 +359,10 @@ namespace AZ
|
||||
AZStd::string uuidString;
|
||||
uuid.ToString(uuidString);
|
||||
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + "_iblspecularcm.dds";
|
||||
// determine the filemask suffix from the cubemap quality level setting
|
||||
AZStd::string fileSuffix = BakedCubeMapFileSuffixes[aznumeric_cast<uint32_t>(m_bakedCubeMapQualityLevel)];
|
||||
|
||||
cubeMapRelativePath = "ReflectionProbes/" + entity->GetName() + "_" + uuidString + fileSuffix;
|
||||
|
||||
// replace any invalid filename characters
|
||||
auto invalidCharacters = [](char letter)
|
||||
@@ -384,6 +401,7 @@ namespace AZ
|
||||
// save the relative source path in the configuration
|
||||
AzToolsFramework::ScopedUndoBatch undoBatch("Cubemap path changed.");
|
||||
m_controller.m_configuration.m_bakedCubeMapRelativePath = cubeMapRelativePath;
|
||||
m_controller.m_configuration.m_bakedCubeMapQualityLevel = m_bakedCubeMapQualityLevel;
|
||||
SetDirty();
|
||||
|
||||
// update UI cubemap path display
|
||||
|
||||
+1
@@ -77,6 +77,7 @@ namespace AZ
|
||||
// UI settings
|
||||
// the user can select between a baked cubemap or an authored cubemap asset
|
||||
bool m_useBakedCubemap = true;
|
||||
BakedCubeMapQualityLevel m_bakedCubeMapQualityLevel = BakedCubeMapQualityLevel::Medium;
|
||||
AZStd::string m_bakedCubeMapRelativePath;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedCubeMapAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_authoredCubeMapAsset;
|
||||
|
||||
+1
@@ -46,6 +46,7 @@ namespace AZ
|
||||
->Field("InnerLength", &ReflectionProbeComponentConfig::m_innerLength)
|
||||
->Field("InnerWidth", &ReflectionProbeComponentConfig::m_innerWidth)
|
||||
->Field("UseBakedCubemap", &ReflectionProbeComponentConfig::m_useBakedCubemap)
|
||||
->Field("BakedCubemapQualityLevel", &ReflectionProbeComponentConfig::m_bakedCubeMapQualityLevel)
|
||||
->Field("BakedCubeMapRelativePath", &ReflectionProbeComponentConfig::m_bakedCubeMapRelativePath)
|
||||
->Field("BakedCubeMapAsset", &ReflectionProbeComponentConfig::m_bakedCubeMapAsset)
|
||||
->Field("AuthoredCubeMapAsset", &ReflectionProbeComponentConfig::m_authoredCubeMapAsset)
|
||||
|
||||
+24
@@ -24,6 +24,29 @@ namespace AZ
|
||||
{
|
||||
namespace Render
|
||||
{
|
||||
enum class BakedCubeMapQualityLevel : uint32_t
|
||||
{
|
||||
VeryLow, // 64
|
||||
Low, // 128
|
||||
Medium, // 256
|
||||
High, // 512
|
||||
VeryHigh, // 1024
|
||||
|
||||
Count
|
||||
};
|
||||
|
||||
static const char* BakedCubeMapFileSuffixes[] =
|
||||
{
|
||||
"_iblspecularcm64.dds",
|
||||
"_iblspecularcm128.dds",
|
||||
"_iblspecularcm256.dds",
|
||||
"_iblspecularcm512.dds",
|
||||
"_iblspecularcm1024.dds"
|
||||
};
|
||||
|
||||
static_assert(AZ_ARRAY_SIZE(BakedCubeMapFileSuffixes) == aznumeric_cast<uint32_t>(BakedCubeMapQualityLevel::Count),
|
||||
"BakedCubeMapFileSuffixes must have the same number of entries as BakedCubeMapQualityLevel");
|
||||
|
||||
class ReflectionProbeComponentConfig final
|
||||
: public AZ::ComponentConfig
|
||||
{
|
||||
@@ -43,6 +66,7 @@ namespace AZ
|
||||
bool m_showVisualization = true;
|
||||
bool m_useBakedCubemap = true;
|
||||
|
||||
BakedCubeMapQualityLevel m_bakedCubeMapQualityLevel = BakedCubeMapQualityLevel::Medium;
|
||||
AZStd::string m_bakedCubeMapRelativePath;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_bakedCubeMapAsset;
|
||||
Data::Asset<RPI::StreamingImageAsset> m_authoredCubeMapAsset;
|
||||
|
||||
+1
@@ -36,6 +36,7 @@ set(FILES
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/Bloom/BloomComponentConfig.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/DepthOfField/DepthOfFieldBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/DepthOfField/DepthOfFieldComponentConfig.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentBus.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConfig.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/DisplayMapper/DisplayMapperComponentConstants.h
|
||||
Include/AtomLyIntegration/CommonFeatures/PostProcess/ExposureControl/ExposureControlBus.h
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user