Merge branch 'development' into issues/3202
Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
@@ -25,6 +25,7 @@
|
||||
#include <AzCore/std/containers/unordered_set.h>
|
||||
#include <AzCore/Module/Environment.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
#include <AzCore/std/chrono/chrono.h>
|
||||
|
||||
namespace AZ
|
||||
{
|
||||
@@ -33,6 +34,7 @@ namespace AZ
|
||||
namespace Platform
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
bool AttachDebugger();
|
||||
bool IsDebuggerPresent();
|
||||
void HandleExceptions(bool isEnabled);
|
||||
void DebugBreak();
|
||||
@@ -141,6 +143,42 @@ namespace AZ
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
Trace::AttachDebugger()
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
return Platform::AttachDebugger();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
Trace::WaitForDebugger(float timeoutSeconds/*=-1.f*/)
|
||||
{
|
||||
#if defined(AZ_ENABLE_DEBUG_TOOLS)
|
||||
using AZStd::chrono::system_clock;
|
||||
using AZStd::chrono::time_point;
|
||||
using AZStd::chrono::milliseconds;
|
||||
|
||||
milliseconds timeoutMs = milliseconds(aznumeric_cast<long long>(timeoutSeconds * 1000));
|
||||
system_clock clock;
|
||||
time_point start = clock.now();
|
||||
auto hasTimedOut = [&clock, start, timeoutMs]()
|
||||
{
|
||||
return timeoutMs.count() >= 0 && (clock.now() - start) >= timeoutMs;
|
||||
};
|
||||
|
||||
while (!AZ::Debug::Trace::IsDebuggerPresent() && !hasTimedOut())
|
||||
{
|
||||
AZStd::this_thread::sleep_for(milliseconds(1));
|
||||
}
|
||||
return AZ::Debug::Trace::IsDebuggerPresent();
|
||||
#else
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
//=========================================================================
|
||||
// HandleExceptions
|
||||
// [8/3/2009]
|
||||
|
||||
@@ -49,6 +49,8 @@ namespace AZ
|
||||
*/
|
||||
static const char* GetDefaultSystemWindow();
|
||||
static bool IsDebuggerPresent();
|
||||
static bool AttachDebugger();
|
||||
static bool WaitForDebugger(float timeoutSeconds = -1.f);
|
||||
|
||||
/// True or false if we want to handle system exceptions.
|
||||
static void HandleExceptions(bool isEnabled);
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
#include <AzCore/std/containers/array.h>
|
||||
#include <AzCore/std/string/wildcard.h>
|
||||
#include <AzCore/Casting/numeric_cast.h>
|
||||
#include <AzCore/AzCore_Traits_Platform.h>
|
||||
|
||||
// extern instantiations of Path templates to prevent implicit instantiations
|
||||
namespace AZ::IO
|
||||
@@ -92,11 +93,23 @@ namespace AZ::IO::Internal
|
||||
constexpr auto ConsumeRootName(InputIt entryBeginIter, InputIt entryEndIter, const char preferredSeparator)
|
||||
-> AZStd::enable_if_t<AZStd::Internal::is_forward_iterator_v<InputIt>, InputIt>
|
||||
{
|
||||
if (preferredSeparator == '/')
|
||||
if (preferredSeparator == PosixPathSeparator)
|
||||
{
|
||||
// If the preferred separator is forward slash the parser is in posix path
|
||||
// parsing mode, which doesn't have a root name
|
||||
// parsing mode, which doesn't have a root name,
|
||||
// unless we're on a posix platform that uses a custom path root separator
|
||||
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
|
||||
const AZStd::string_view path{ entryBeginIter, entryEndIter };
|
||||
const auto positionOfPathSeparator = path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR);
|
||||
if (positionOfPathSeparator == AZStd::string_view::npos)
|
||||
{
|
||||
return entryBeginIter;
|
||||
}
|
||||
const AZStd::string_view rootName{ path.substr(0, positionOfPathSeparator + 1) };
|
||||
return AZStd::next(entryBeginIter, rootName.size());
|
||||
#else
|
||||
return entryBeginIter;
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -185,13 +198,18 @@ namespace AZ::IO::Internal
|
||||
template <typename InputIt, typename EndIt, typename = AZStd::enable_if_t<AZStd::Internal::is_input_iterator_v<InputIt>>>
|
||||
static constexpr bool IsAbsolute(InputIt first, EndIt last, const char preferredSeparator)
|
||||
{
|
||||
size_t pathSize = AZStd::distance(first, last);
|
||||
|
||||
// If the preferred separator is a forward slash
|
||||
// than an absolute path is simply one that starts with a forward slash
|
||||
if (preferredSeparator == '/')
|
||||
// than an absolute path is simply one that starts with a forward slash,
|
||||
// unless we're on a posix platform that uses a custom path root separator
|
||||
if (preferredSeparator == PosixPathSeparator)
|
||||
{
|
||||
#if defined(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR)
|
||||
const AZStd::string_view path{ first, last };
|
||||
return path.find(AZ_TRAIT_CUSTOM_PATH_ROOT_SEPARATOR) != AZStd::string_view::npos;
|
||||
#else
|
||||
const size_t pathSize = AZStd::distance(first, last);
|
||||
return pathSize > 0 && IsSeparator(*first);
|
||||
#endif
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -199,6 +217,7 @@ namespace AZ::IO::Internal
|
||||
{
|
||||
// If a windows path ends starts with C:foo it is a root relative path
|
||||
// A path is absolute root absolute on windows if it starts with <drive_letter><colon><path_separator>
|
||||
const size_t pathSize = AZStd::distance(first, last);
|
||||
return pathSize > 2 && Internal::IsSeparator(*AZStd::next(first, 2));
|
||||
}
|
||||
|
||||
|
||||
@@ -550,7 +550,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
registry.Set(FilePathKey_ProjectUserPath, projectUserPath.Native());
|
||||
|
||||
// Set the user directory with the provided path or using project/user as default
|
||||
// Set the log directory with the provided path or using project/user/log as default
|
||||
auto projectLogPathKey = FixedValueString::format("%s/project_log_path", BootstrapSettingsRootKey);
|
||||
AZ::IO::FixedMaxPath projectLogPath;
|
||||
if (!registry.Get(projectLogPath.Native(), projectLogPathKey))
|
||||
@@ -640,7 +640,7 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
}
|
||||
|
||||
#if !AZ_TRAIT_OS_IS_HOST_OS_PLATFORM
|
||||
// Setup the cache and user paths when to platform specific locations when running on non-host platforms
|
||||
// Setup the cache, user, and log paths to platform specific locations when running on non-host platforms
|
||||
path = engineRoot;
|
||||
if (AZStd::optional<AZ::IO::FixedMaxPathString> nonHostCacheRoot = Utils::GetDefaultAppRootPath();
|
||||
nonHostCacheRoot)
|
||||
@@ -656,13 +656,16 @@ namespace AZ::SettingsRegistryMergeUtils
|
||||
if (AZStd::optional<AZ::IO::FixedMaxPathString> devWriteStorage = Utils::GetDevWriteStoragePath();
|
||||
devWriteStorage)
|
||||
{
|
||||
registry.Set(FilePathKey_DevWriteStorage, *devWriteStorage);
|
||||
registry.Set(FilePathKey_ProjectUserPath, *devWriteStorage);
|
||||
const AZ::IO::FixedMaxPath devWriteStoragePath(*devWriteStorage);
|
||||
registry.Set(FilePathKey_DevWriteStorage, devWriteStoragePath.LexicallyNormal().Native());
|
||||
registry.Set(FilePathKey_ProjectUserPath, (devWriteStoragePath / "user").LexicallyNormal().Native());
|
||||
registry.Set(FilePathKey_ProjectLogPath, (devWriteStoragePath / "user/log").LexicallyNormal().Native());
|
||||
}
|
||||
else
|
||||
{
|
||||
registry.Set(FilePathKey_DevWriteStorage, path.LexicallyNormal().Native());
|
||||
registry.Set(FilePathKey_ProjectUserPath, (path / "user").LexicallyNormal().Native());
|
||||
registry.Set(FilePathKey_ProjectLogPath, (path / "user/log").LexicallyNormal().Native());
|
||||
}
|
||||
#endif // AZ_TRAIT_OS_IS_HOST_OS_PLATFORM
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <AzCore/std/typetraits/is_member_pointer.h>
|
||||
#include <AzCore/std/typetraits/is_const.h>
|
||||
#include <AzCore/std/typetraits/remove_cvref.h>
|
||||
#include <AzCore/std/typetraits/is_volatile.h>
|
||||
#include <AzCore/std/createdestroy.h>
|
||||
|
||||
#define AZSTD_FUNCTION_TARGET_FIX(x)
|
||||
@@ -591,8 +592,8 @@ namespace AZStd
|
||||
|
||||
Internal::function_util::function_buffer type_result;
|
||||
type_result.type.type = aztypeid(Functor);
|
||||
type_result.type.const_qualified = is_const<Functor>::value;
|
||||
type_result.type.volatile_qualified = is_volatile<Functor>::value;
|
||||
type_result.type.const_qualified = AZStd::is_const<Functor>::value;
|
||||
type_result.type.volatile_qualified = AZStd::is_volatile<Functor>::value;
|
||||
vtable->manager(functor, type_result, Internal::function_util::check_functor_type_tag);
|
||||
return static_cast<Functor*>(type_result.obj_ptr);
|
||||
}
|
||||
@@ -608,7 +609,7 @@ namespace AZStd
|
||||
Internal::function_util::function_buffer type_result;
|
||||
type_result.type.type = aztypeid(Functor);
|
||||
type_result.type.const_qualified = true;
|
||||
type_result.type.volatile_qualified = is_volatile<Functor>::value;
|
||||
type_result.type.volatile_qualified = AZStd::is_volatile<Functor>::value;
|
||||
vtable->manager(functor, type_result, Internal::function_util::check_functor_type_tag);
|
||||
// GCC 2.95.3 gets the CV qualifiers wrong here, so we
|
||||
// can't do the static_cast that we should do.
|
||||
|
||||
@@ -359,7 +359,7 @@ namespace AZStd
|
||||
{
|
||||
functor.obj_ref.obj_ptr = (void*)&f.get();
|
||||
functor.obj_ref.is_const_qualified = is_const<FunctionObj>::value;
|
||||
functor.obj_ref.is_volatile_qualified = is_volatile<FunctionObj>::value;
|
||||
functor.obj_ref.is_volatile_qualified = AZStd::is_volatile<FunctionObj>::value;
|
||||
return true;
|
||||
}
|
||||
else
|
||||
|
||||
@@ -70,11 +70,11 @@ namespace AZStd
|
||||
bool try_acquire_until(const chrono::time_point<Clock, Duration>& abs_time)
|
||||
{
|
||||
auto timeNow = chrono::system_clock::now();
|
||||
if (timeNow >= absTime)
|
||||
if (timeNow >= abs_time)
|
||||
{
|
||||
return false; // we timed out already!
|
||||
}
|
||||
auto deltaTime = absTime - timeNow;
|
||||
auto deltaTime = abs_time - timeNow;
|
||||
auto timeToTry = chrono::duration_cast<chrono::milliseconds>(deltaTime);
|
||||
return (WaitForSingleObject(m_event, aznumeric_cast<DWORD>(timeToTry.count())) == AZ_WAIT_OBJECT_0);
|
||||
}
|
||||
|
||||
@@ -56,6 +56,13 @@ namespace AZ
|
||||
return ((info.kp_proc.p_flag & P_TRACED) != 0);
|
||||
}
|
||||
|
||||
bool AttachDebugger()
|
||||
{
|
||||
// Not supported yet
|
||||
AZ_Assert(false, "AttachDebugger() is not supported for Mac platform yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandleExceptions(bool)
|
||||
{}
|
||||
|
||||
|
||||
@@ -60,6 +60,13 @@ namespace AZ
|
||||
return s_debuggerDetected;
|
||||
}
|
||||
|
||||
bool AttachDebugger()
|
||||
{
|
||||
// Not supported yet
|
||||
AZ_Assert(false, "AttachDebugger() is not supported for Unix platform yet");
|
||||
return false;
|
||||
}
|
||||
|
||||
void HandleExceptions(bool)
|
||||
{}
|
||||
|
||||
|
||||
@@ -49,6 +49,45 @@ namespace AZ
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachDebugger()
|
||||
{
|
||||
if (IsDebuggerPresent())
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Launch vsjitdebugger.exe, this app is always present in System32 folder
|
||||
// with an installation of any version of visual studio.
|
||||
// It will open a debugging dialog asking the user what debugger to use
|
||||
|
||||
STARTUPINFOW startupInfo = {0};
|
||||
startupInfo.cb = sizeof(startupInfo);
|
||||
PROCESS_INFORMATION processInfo = {0};
|
||||
|
||||
wchar_t cmdline[MAX_PATH];
|
||||
swprintf_s(cmdline, L"vsjitdebugger.exe -p %li", ::GetCurrentProcessId());
|
||||
bool success = ::CreateProcessW(
|
||||
NULL, // No module name (use command line)
|
||||
cmdline, // Command line
|
||||
NULL, // Process handle not inheritable
|
||||
NULL, // Thread handle not inheritable
|
||||
FALSE, // No handle inheritance
|
||||
0, // No creation flags
|
||||
NULL, // Use parent's environment block
|
||||
NULL, // Use parent's starting directory
|
||||
&startupInfo, // Pointer to STARTUPINFO structure
|
||||
&processInfo); // Pointer to PROCESS_INFORMATION structure
|
||||
|
||||
if (success)
|
||||
{
|
||||
::WaitForSingleObject(processInfo.hProcess, INFINITE);
|
||||
::CloseHandle(processInfo.hProcess);
|
||||
::CloseHandle(processInfo.hThread);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void DebugBreak()
|
||||
{
|
||||
__debugbreak();
|
||||
|
||||
+2
-2
@@ -198,7 +198,7 @@ namespace AZStd
|
||||
AZ_FORCE_INLINE cv_status condition_variable_any::wait_for(Lock& lock, const chrono::duration<Rep, Period>& rel_time)
|
||||
{
|
||||
chrono::milliseconds toWait = rel_time;
|
||||
EnterCriticalSection(&m_mutex);
|
||||
EnterCriticalSection(AZ_STD_MUTEX_CAST(m_mutex));
|
||||
lock.unlock();
|
||||
|
||||
// We need to make sure we use CriticalSection based mutex.
|
||||
@@ -217,7 +217,7 @@ namespace AZStd
|
||||
returnCode = cv_status::timeout;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&m_mutex);
|
||||
LeaveCriticalSection(AZ_STD_MUTEX_CAST(m_mutex));
|
||||
lock.lock();
|
||||
return returnCode;
|
||||
}
|
||||
|
||||
@@ -480,7 +480,9 @@ namespace UnitTest
|
||||
TEST_F(AnyTest, Any_CopyAssignSelfEmpty_IsEmpty)
|
||||
{
|
||||
any a;
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
a = a;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
EXPECT_TRUE(a.empty());
|
||||
}
|
||||
|
||||
@@ -491,7 +493,9 @@ namespace UnitTest
|
||||
any a((TypeParam(1)));
|
||||
EXPECT_EQ(TypeParam::s_count, 1);
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
a = a;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
EXPECT_EQ(TypeParam::s_count, 1);
|
||||
EXPECT_EQ(any_cast<const TypeParam&>(a).val(), 1);
|
||||
|
||||
@@ -285,7 +285,9 @@ namespace UnitTest
|
||||
|
||||
// Invocation and self-assignment
|
||||
global_int = 0;
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
v1 = v1;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
v1();
|
||||
AZ_TEST_ASSERT(global_int == 3);
|
||||
|
||||
@@ -294,7 +296,9 @@ namespace UnitTest
|
||||
|
||||
// Invocation and self-assignment
|
||||
global_int = 0;
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
v1 = (v1);
|
||||
AZ_POP_DISABLE_WARNING
|
||||
v1();
|
||||
AZ_TEST_ASSERT(global_int == 5);
|
||||
|
||||
|
||||
@@ -2100,8 +2100,8 @@ namespace UnitTest
|
||||
typename TypeParam::ContainerType container;
|
||||
container.emplace(-2352);
|
||||
container.emplace(3534);
|
||||
container.emplace(1535408957);
|
||||
container.emplace(3310556522);
|
||||
container.emplace(535408957);
|
||||
container.emplace(1310556522);
|
||||
container.emplace(55546193);
|
||||
container.emplace(1582);
|
||||
|
||||
|
||||
@@ -1805,8 +1805,8 @@ namespace UnitTest
|
||||
typename TypeParam::ContainerType container;
|
||||
container.emplace(-2352);
|
||||
container.emplace(3534);
|
||||
container.emplace(1535408957);
|
||||
container.emplace(3310556522);
|
||||
container.emplace(535408957);
|
||||
container.emplace(1310556522);
|
||||
container.emplace(55546193);
|
||||
container.emplace(1582);
|
||||
|
||||
|
||||
@@ -920,7 +920,9 @@ namespace UnitTest
|
||||
|
||||
AZStd::shared_ptr<incomplete> p1;
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
p1 = p1;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
EXPECT_EQ(p1, p1);
|
||||
EXPECT_FALSE(p1);
|
||||
@@ -950,7 +952,9 @@ namespace UnitTest
|
||||
{
|
||||
AZStd::shared_ptr<void> p1;
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
p1 = p1;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
EXPECT_EQ(p1, p1);
|
||||
EXPECT_FALSE(p1);
|
||||
@@ -996,7 +1000,9 @@ namespace UnitTest
|
||||
using X = SharedPtr::test::X;
|
||||
AZStd::shared_ptr<X> p1;
|
||||
|
||||
AZ_PUSH_DISABLE_WARNING(, "-Wself-assign-overloaded")
|
||||
p1 = p1;
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
EXPECT_EQ(p1, p1);
|
||||
EXPECT_FALSE(p1);
|
||||
|
||||
@@ -72,11 +72,8 @@ namespace AzFramework
|
||||
/// Retrieves the app root path for the application.
|
||||
virtual const char* GetAppRoot() const { return nullptr; }
|
||||
|
||||
#pragma push_macro("GetCommandLine")
|
||||
#undef GetCommandLine
|
||||
/// Get the Command Line arguments passed in.
|
||||
virtual const CommandLine* GetCommandLine() { return nullptr; }
|
||||
#pragma pop_macro("GetCommandLine")
|
||||
|
||||
/// Get the Command Line arguments passed in. (Avoids collisions with platform specific macros.)
|
||||
virtual const CommandLine* GetApplicationCommandLine() { return nullptr; }
|
||||
|
||||
@@ -707,6 +707,7 @@ namespace AZ
|
||||
resolvedPathLen += postAliasView.size();
|
||||
// Null-Terminated the resolved path
|
||||
resolvedPath[resolvedPathLen] = '\0';
|
||||
|
||||
// If the path started with one of the "asset cache" path aliases, lowercase the path
|
||||
const char* assetAliasPath = GetAlias("@assets@");
|
||||
const char* rootAliasPath = GetAlias("@root@");
|
||||
@@ -714,10 +715,13 @@ namespace AZ
|
||||
const bool lowercasePath = (assetAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, assetAliasPath)) ||
|
||||
(rootAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, rootAliasPath)) ||
|
||||
(projectPlatformCacheAliasPath != nullptr && AZ::StringFunc::StartsWith(resolvedPath, projectPlatformCacheAliasPath));
|
||||
|
||||
if (lowercasePath)
|
||||
{
|
||||
AZStd::to_lower(resolvedPath, resolvedPath + resolvedPathLen);
|
||||
// Lowercase only the relative part after the replaced alias.
|
||||
AZStd::to_lower(resolvedPath + aliasValue.size(), resolvedPath + resolvedPathLen);
|
||||
}
|
||||
|
||||
// Replace any backslashes with posix slashes
|
||||
AZStd::replace(resolvedPath, resolvedPath + resolvedPathLen, AZ::IO::WindowsPathSeparator, AZ::IO::PosixPathSeparator);
|
||||
return true;
|
||||
|
||||
+3
-3
@@ -31,10 +31,10 @@ namespace AzToolsFramework
|
||||
AssetBrowserFilterModel::AssetBrowserFilterModel(QObject* parent)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
m_showColumn.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName));
|
||||
m_shownColumns.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::DisplayName));
|
||||
if (ed_useNewAssetBrowserTableView)
|
||||
{
|
||||
m_showColumn.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::Path));
|
||||
m_shownColumns.insert(aznumeric_cast<int>(AssetBrowserEntry::Column::Path));
|
||||
}
|
||||
m_collator.setNumericMode(true);
|
||||
AssetBrowserComponentNotificationBus::Handler::BusConnect();
|
||||
@@ -96,7 +96,7 @@ namespace AzToolsFramework
|
||||
bool AssetBrowserFilterModel::filterAcceptsColumn(int source_column, const QModelIndex&) const
|
||||
{
|
||||
//if the column is in the set we want to show it
|
||||
return m_showColumn.find(source_column) != m_showColumn.end();
|
||||
return m_shownColumns.find(source_column) != m_shownColumns.end();
|
||||
}
|
||||
|
||||
bool AssetBrowserFilterModel::lessThan(const QModelIndex& source_left, const QModelIndex& source_right) const
|
||||
|
||||
+6
-4
@@ -27,6 +27,8 @@ namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
{
|
||||
using ShownColumnsSet = AZStd::fixed_unordered_set<int, 3, aznumeric_cast<int>(AssetBrowserEntry::Column::Count)>;
|
||||
|
||||
class AssetBrowserFilterModel
|
||||
: public QSortFilterProxyModel
|
||||
, public AssetBrowserComponentNotificationBus::Handler
|
||||
@@ -61,11 +63,11 @@ namespace AzToolsFramework
|
||||
void filterUpdatedSlot();
|
||||
|
||||
protected:
|
||||
//set for filtering columns
|
||||
//if the column is in the set the column is not filtered and is shown
|
||||
AZStd::fixed_unordered_set<int, 3, aznumeric_cast<int>(AssetBrowserEntry::Column::Count)> m_showColumn;
|
||||
// Set for filtering columns
|
||||
// If the column is in the set the column is not filtered and is shown
|
||||
ShownColumnsSet m_shownColumns;
|
||||
bool m_alreadyRecomputingFilters = false;
|
||||
//asset source name match filter
|
||||
//Asset source name match filter
|
||||
FilterConstType m_filter;
|
||||
AZ_PUSH_DISABLE_WARNING(4251, "-Wunknown-warning-option") // 4251: class '...' needs to have dll-interface to be used by clients of class '...'
|
||||
QWeakPointer<const StringFilter> m_stringFilter;
|
||||
|
||||
+53
-30
@@ -16,7 +16,6 @@ namespace AzToolsFramework
|
||||
AssetBrowserTableModel::AssetBrowserTableModel(QObject* parent /* = nullptr */)
|
||||
: QSortFilterProxyModel(parent)
|
||||
{
|
||||
setDynamicSortFilter(false);
|
||||
}
|
||||
|
||||
void AssetBrowserTableModel::setSourceModel(QAbstractItemModel* sourceModel)
|
||||
@@ -25,19 +24,47 @@ namespace AzToolsFramework
|
||||
AZ_Assert(
|
||||
m_filterModel,
|
||||
"Error in AssetBrowserTableModel initialization, class expects source model to be an AssetBrowserFilterModel.");
|
||||
connect(sourceModel, &QAbstractItemModel::rowsInserted, this, &AssetBrowserTableModel::UpdateTableModelMaps);
|
||||
connect(sourceModel, &QAbstractItemModel::rowsRemoved, this, &AssetBrowserTableModel::UpdateTableModelMaps);
|
||||
connect(sourceModel, &QAbstractItemModel::modelAboutToBeReset, this, &AssetBrowserTableModel::beginResetModel);
|
||||
connect(
|
||||
sourceModel, &QAbstractItemModel::modelReset, this,
|
||||
[this]()
|
||||
{
|
||||
{
|
||||
QSignalBlocker sb(this);
|
||||
UpdateTableModelMaps();
|
||||
}
|
||||
endResetModel();
|
||||
});
|
||||
connect(sourceModel, &QAbstractItemModel::layoutChanged, this, &AssetBrowserTableModel::UpdateTableModelMaps);
|
||||
connect(sourceModel, &QAbstractItemModel::dataChanged, this, &AssetBrowserTableModel::SourceDataChanged);
|
||||
|
||||
|
||||
QSortFilterProxyModel::setSourceModel(sourceModel);
|
||||
}
|
||||
|
||||
QModelIndex AssetBrowserTableModel::mapToSource(const QModelIndex& proxyIndex) const
|
||||
{
|
||||
Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() == this);
|
||||
if (!proxyIndex.isValid())
|
||||
Q_ASSERT(!proxyIndex.isValid() || proxyIndex.model() != this);
|
||||
if (!proxyIndex.isValid() || !m_indexMap.contains(proxyIndex.row()))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
return m_indexMap[proxyIndex.row()];
|
||||
}
|
||||
|
||||
QModelIndex AssetBrowserTableModel::mapFromSource(const QModelIndex& sourceIndex) const
|
||||
{
|
||||
Q_ASSERT(!sourceIndex.isValid() || sourceIndex.model() == sourceModel());
|
||||
if (!sourceIndex.isValid() || !m_rowMap.contains(sourceIndex))
|
||||
{
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
return createIndex(m_rowMap[sourceIndex], sourceIndex.column());
|
||||
}
|
||||
|
||||
QVariant AssetBrowserTableModel::headerData(int section, Qt::Orientation orientation, int role) const
|
||||
{
|
||||
if (role == Qt::DisplayRole && orientation == Qt::Horizontal)
|
||||
@@ -49,20 +76,8 @@ namespace AzToolsFramework
|
||||
|
||||
QVariant AssetBrowserTableModel::data(const QModelIndex& index, int role) const
|
||||
{
|
||||
auto sourceIndex = mapToSource(index);
|
||||
if (!sourceIndex.isValid())
|
||||
{
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
AssetBrowserEntry* entry = GetAssetEntry(sourceIndex);
|
||||
if (entry == nullptr)
|
||||
{
|
||||
AZ_Assert(false, "AssetBrowserTableModel - QModelIndex does not reference an AssetEntry. Source model is not valid.");
|
||||
return QVariant();
|
||||
}
|
||||
|
||||
return sourceIndex.data(role);
|
||||
Q_ASSERT(index.isValid() && index.model() == this);
|
||||
return sourceModel()->data(mapToSource(index), role);
|
||||
}
|
||||
|
||||
QModelIndex AssetBrowserTableModel::parent([[maybe_unused]] const QModelIndex& child) const
|
||||
@@ -76,14 +91,28 @@ namespace AzToolsFramework
|
||||
return QModelIndex();
|
||||
}
|
||||
|
||||
void AssetBrowserTableModel::SourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight)
|
||||
{
|
||||
for (int row = topLeft.row(); row <= bottomRight.row(); ++row)
|
||||
{
|
||||
if (!m_indexMap.contains(row))
|
||||
{
|
||||
UpdateTableModelMaps();
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
QModelIndex AssetBrowserTableModel::index(int row, int column, const QModelIndex& parent) const
|
||||
{
|
||||
Q_ASSERT(!parent.isValid());
|
||||
|
||||
return parent.isValid() ? QModelIndex() : createIndex(row, column, m_indexMap[row].internalPointer());
|
||||
}
|
||||
|
||||
int AssetBrowserTableModel::rowCount(const QModelIndex& parent) const
|
||||
{
|
||||
return !parent.isValid() ? m_indexMap.size() : 0;
|
||||
return !parent.isValid() ? m_indexMap.size() : sourceModel()->rowCount(parent);
|
||||
}
|
||||
|
||||
int AssetBrowserTableModel::BuildTableModelMap(
|
||||
@@ -102,14 +131,12 @@ namespace AzToolsFramework
|
||||
{
|
||||
QModelIndex index = model->index(currentRow, 0, parent);
|
||||
AssetBrowserEntry* entry = GetAssetEntry(m_filterModel->mapToSource(index));
|
||||
// We only want to see the source assets.
|
||||
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source)
|
||||
// We only want to see source and product assets.
|
||||
if (entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Source ||
|
||||
entry->GetEntryType() == AssetBrowserEntry::AssetEntryType::Product)
|
||||
{
|
||||
beginInsertRows(parent, row, row);
|
||||
m_indexMap[row] = index;
|
||||
endInsertRows();
|
||||
|
||||
Q_EMIT dataChanged(index, index);
|
||||
m_rowMap[index] = row;
|
||||
++row;
|
||||
++m_displayedItemsCounter;
|
||||
}
|
||||
@@ -143,12 +170,8 @@ namespace AzToolsFramework
|
||||
void AssetBrowserTableModel::UpdateTableModelMaps()
|
||||
{
|
||||
emit layoutAboutToBeChanged();
|
||||
if (!m_indexMap.isEmpty())
|
||||
{
|
||||
beginRemoveRows(m_indexMap.first(), m_indexMap.first().row(), m_indexMap.last().row());
|
||||
m_indexMap.clear();
|
||||
endRemoveRows();
|
||||
}
|
||||
m_indexMap.clear();
|
||||
m_rowMap.clear();
|
||||
|
||||
AzToolsFramework::EditorSettingsAPIBus::BroadcastResult(
|
||||
m_numberOfItemsDisplayed, &AzToolsFramework::EditorSettingsAPIBus::Handler::GetMaxNumberOfItemsShownInSearchView);
|
||||
|
||||
+8
-5
@@ -21,8 +21,7 @@ namespace AzToolsFramework
|
||||
class AssetBrowserFilterModel;
|
||||
class AssetBrowserEntry;
|
||||
|
||||
class AssetBrowserTableModel
|
||||
: public QSortFilterProxyModel
|
||||
class AssetBrowserTableModel : public QSortFilterProxyModel
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
@@ -30,12 +29,11 @@ namespace AzToolsFramework
|
||||
AZ_CLASS_ALLOCATOR(AssetBrowserTableModel, AZ::SystemAllocator, 0);
|
||||
explicit AssetBrowserTableModel(QObject* parent = nullptr);
|
||||
|
||||
void UpdateTableModelMaps();
|
||||
|
||||
////////////////////////////////////////////////////////////////////
|
||||
// QSortFilterProxyModel
|
||||
void setSourceModel(QAbstractItemModel* sourceModel) override;
|
||||
QModelIndex mapToSource(const QModelIndex& proxyIndex) const override;
|
||||
QModelIndex mapFromSource(const QModelIndex &sourceIndex) const override;
|
||||
QModelIndex index(int row, int column, const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant data(const QModelIndex& index, int role = Qt::DisplayRole) const override;
|
||||
QModelIndex parent(const QModelIndex& child) const override;
|
||||
@@ -45,16 +43,21 @@ namespace AzToolsFramework
|
||||
int rowCount(const QModelIndex& parent = QModelIndex()) const override;
|
||||
QVariant headerData(int section, Qt::Orientation orientation, int role /* = Qt::DisplayRole */) const override;
|
||||
////////////////////////////////////////////////////////////////////
|
||||
|
||||
private:
|
||||
AssetBrowserEntry* GetAssetEntry(QModelIndex index) const;
|
||||
int BuildTableModelMap(const QAbstractItemModel* model, const QModelIndex& parent = QModelIndex(), int row = 0);
|
||||
|
||||
public slots:
|
||||
void UpdateTableModelMaps();
|
||||
|
||||
private slots:
|
||||
void SourceDataChanged(const QModelIndex& topLeft, const QModelIndex& bottomRight);
|
||||
private:
|
||||
int m_numberOfItemsDisplayed = 50;
|
||||
int m_displayedItemsCounter = 0;
|
||||
QPointer<AssetBrowserFilterModel> m_filterModel;
|
||||
QMap<int, QModelIndex> m_indexMap;
|
||||
QMap<QModelIndex, int> m_rowMap;
|
||||
};
|
||||
} // namespace AssetBrowser
|
||||
} // namespace AzToolsFramework
|
||||
|
||||
+65
-2
@@ -9,9 +9,11 @@
|
||||
#include <AzCore/UserSettings/UserSettings.h>
|
||||
|
||||
#include <AzQtComponents/Components/DockBar.h>
|
||||
#include <AzCore/Console/IConsole.h>
|
||||
|
||||
#include <AzToolsFramework/AssetBrowser/Views/AssetBrowserTreeView.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserFilterModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserTableModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserModel.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetBrowserBus.h>
|
||||
#include <AzToolsFramework/AssetBrowser/AssetSelectionModel.h>
|
||||
@@ -26,6 +28,11 @@ AZ_PUSH_DISABLE_WARNING(4251 4244, "-Wunknown-warning-option") // disable warnin
|
||||
#include <QTimer>
|
||||
AZ_POP_DISABLE_WARNING
|
||||
|
||||
AZ_CVAR(
|
||||
bool, ed_hideAssetPickerPathColumn, false, nullptr, AZ::ConsoleFunctorFlags::Null,
|
||||
"Hide AssetPicker path column for a clearer view.");
|
||||
AZ_CVAR_EXTERNED(bool, ed_useNewAssetBrowserTableView);
|
||||
|
||||
namespace AzToolsFramework
|
||||
{
|
||||
namespace AssetBrowser
|
||||
@@ -34,6 +41,7 @@ namespace AzToolsFramework
|
||||
: QDialog(parent)
|
||||
, m_ui(new Ui::AssetPickerDialogClass())
|
||||
, m_filterModel(new AssetBrowserFilterModel(parent))
|
||||
, m_tableModel(new AssetBrowserTableModel(parent))
|
||||
, m_selection(selection)
|
||||
, m_hasFilter(false)
|
||||
{
|
||||
@@ -97,6 +105,56 @@ namespace AzToolsFramework
|
||||
|
||||
m_persistentState = AZ::UserSettings::CreateFind<AzToolsFramework::QWidgetSavedState>(AZ::Crc32(("AssetBrowserTreeView_Dialog_" + name).toUtf8().data()), AZ::UserSettings::CT_GLOBAL);
|
||||
|
||||
m_ui->m_assetBrowserTableViewWidget->setVisible(false);
|
||||
if (ed_useNewAssetBrowserTableView)
|
||||
{
|
||||
m_ui->m_assetBrowserTreeViewWidget->setVisible(false);
|
||||
m_ui->m_assetBrowserTableViewWidget->setVisible(true);
|
||||
m_tableModel->setSourceModel(m_filterModel.get());
|
||||
m_ui->m_assetBrowserTableViewWidget->setModel(m_tableModel.get());
|
||||
|
||||
m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_" + name);
|
||||
m_ui->m_assetBrowserTableViewWidget->setDragEnabled(false);
|
||||
m_ui->m_assetBrowserTableViewWidget->setSelectionMode(
|
||||
selection.GetMultiselect() ? QAbstractItemView::SelectionMode::ExtendedSelection
|
||||
: QAbstractItemView::SelectionMode::SingleSelection);
|
||||
|
||||
if (ed_hideAssetPickerPathColumn)
|
||||
{
|
||||
m_ui->m_assetBrowserTableViewWidget->hideColumn(1);
|
||||
}
|
||||
|
||||
// if the current selection is invalid, disable the Ok button
|
||||
m_ui->m_buttonBox->button(QDialogButtonBox::Ok)->setEnabled(EvaluateSelection());
|
||||
|
||||
connect(
|
||||
m_filterModel.data(), &AssetBrowserFilterModel::filterChanged, this,
|
||||
[this]()
|
||||
{
|
||||
m_tableModel->UpdateTableModelMaps();
|
||||
});
|
||||
|
||||
connect(
|
||||
m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::selectionChangedSignal, this,
|
||||
[this](const QItemSelection&, const QItemSelection&)
|
||||
{
|
||||
AssetPickerDialog::SelectionChangedSlot();
|
||||
});
|
||||
|
||||
connect(m_ui->m_assetBrowserTableViewWidget, &QAbstractItemView::doubleClicked, this, &AssetPickerDialog::DoubleClickedSlot);
|
||||
|
||||
connect(
|
||||
m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearStringFilter, m_ui->m_searchWidget,
|
||||
&SearchWidget::ClearStringFilter);
|
||||
|
||||
connect(
|
||||
m_ui->m_assetBrowserTableViewWidget, &AssetBrowserTableView::ClearTypeFilter, m_ui->m_searchWidget,
|
||||
&SearchWidget::ClearTypeFilter);
|
||||
|
||||
m_ui->m_assetBrowserTableViewWidget->SetName("AssetBrowserTableView_main");
|
||||
m_tableModel->UpdateTableModelMaps();
|
||||
}
|
||||
|
||||
QTimer::singleShot(0, this, &AssetPickerDialog::RestoreState);
|
||||
SelectionChangedSlot();
|
||||
}
|
||||
@@ -134,6 +192,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
m_ui->m_assetBrowserTreeViewWidget->expandAll();
|
||||
});
|
||||
m_tableModel->UpdateTableModelMaps();
|
||||
}
|
||||
|
||||
if (m_hasFilter && !hasFilter)
|
||||
@@ -166,7 +225,8 @@ namespace AzToolsFramework
|
||||
|
||||
bool AssetPickerDialog::EvaluateSelection() const
|
||||
{
|
||||
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
|
||||
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible() ? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()
|
||||
: m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets();
|
||||
// exactly one item must be selected, even if multi-select option is disabled, still good practice to check
|
||||
if (selectedAssets.empty())
|
||||
{
|
||||
@@ -197,7 +257,10 @@ namespace AzToolsFramework
|
||||
|
||||
void AssetPickerDialog::UpdatePreview() const
|
||||
{
|
||||
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets();
|
||||
auto selectedAssets = m_ui->m_assetBrowserTreeViewWidget->isVisible()
|
||||
? m_ui->m_assetBrowserTreeViewWidget->GetSelectedAssets()
|
||||
: m_ui->m_assetBrowserTableViewWidget->GetSelectedAssets();
|
||||
;
|
||||
if (selectedAssets.size() != 1)
|
||||
{
|
||||
m_ui->m_previewerFrame->Clear();
|
||||
|
||||
+2
@@ -33,6 +33,7 @@ namespace AzToolsFramework
|
||||
{
|
||||
class ProductAssetBrowserEntry;
|
||||
class AssetBrowserFilterModel;
|
||||
class AssetBrowserTableModel;
|
||||
class AssetBrowserModel;
|
||||
class AssetSelectionModel;
|
||||
|
||||
@@ -69,6 +70,7 @@ namespace AzToolsFramework
|
||||
QScopedPointer<Ui::AssetPickerDialogClass> m_ui;
|
||||
AssetBrowserModel* m_assetBrowserModel = nullptr;
|
||||
QScopedPointer<AssetBrowserFilterModel> m_filterModel;
|
||||
QScopedPointer<AssetBrowserTableModel> m_tableModel;
|
||||
AssetSelectionModel& m_selection;
|
||||
bool m_hasFilter;
|
||||
AZStd::unique_ptr<TreeViewState> m_filterStateSaver;
|
||||
|
||||
+8
@@ -142,6 +142,9 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item>
|
||||
<widget class="AzToolsFramework::AssetBrowser::AssetBrowserTableView" name="m_assetBrowserTableViewWidget"/>
|
||||
</item>
|
||||
</layout>
|
||||
</widget>
|
||||
<widget class="QWidget" name="verticalLayoutWidget">
|
||||
@@ -197,6 +200,11 @@
|
||||
<header>AzToolsFramework/AssetBrowser/Previewer/PreviewerFrame.h</header>
|
||||
<container>1</container>
|
||||
</customwidget>
|
||||
<customwidget>
|
||||
<class>AzToolsFramework::AssetBrowser::AssetBrowserTableView</class>
|
||||
<extends>QTableView</extends>
|
||||
<header>AzToolsFramework/AssetBrowser/Views/AssetBrowserTableView.h</header>
|
||||
</customwidget>
|
||||
</customwidgets>
|
||||
<resources/>
|
||||
<connections/>
|
||||
|
||||
-1
@@ -53,7 +53,6 @@ namespace AzToolsFramework
|
||||
// AssetBrowserComponentNotificationBus
|
||||
void OnAssetBrowserComponentReady() override;
|
||||
//////////////////////////////////////////////////////////////////////////
|
||||
|
||||
Q_SIGNALS:
|
||||
void selectionChangedSignal(const QItemSelection& selected, const QItemSelection& deselected);
|
||||
void ClearStringFilter();
|
||||
|
||||
+1
@@ -65,6 +65,7 @@ namespace AzToolsFramework
|
||||
AddedScanTimeSecondsSinceEpochField = 29,
|
||||
ChangedSortFunctionFromQSortToStdStableSort = 30,
|
||||
RemoveOutputPrefixFromScanFolders,
|
||||
AddedSourceIndexForSourceDependencyTable,
|
||||
//Add all new versions before this
|
||||
DatabaseVersionCount,
|
||||
LatestVersion = DatabaseVersionCount - 1
|
||||
|
||||
@@ -43,7 +43,6 @@ AzToolsFramework--EntityOutlinerCheckBox
|
||||
padding: 0;
|
||||
padding-right: 2px;
|
||||
line-height: 0px;
|
||||
font-size: 0px;
|
||||
margin: 0px;
|
||||
max-height: 20px;
|
||||
max-width: 18px;
|
||||
@@ -59,7 +58,6 @@ AzToolsFramework--EntityOutlinerCheckBox::indicator
|
||||
spacing: 0px;
|
||||
padding: 0px;
|
||||
line-height: 0px;
|
||||
font-size: 0px;
|
||||
margin: 3px 0 0 0;
|
||||
max-width: 18px;
|
||||
width: 18px;
|
||||
|
||||
@@ -99,5 +99,6 @@ namespace AzToolsFramework
|
||||
|
||||
// Draw border at the bottom
|
||||
painter->drawLine(rect.bottomLeft(), rect.bottomRight());
|
||||
painter->restore();
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user