Merge branch 'development' into issues/3202

Signed-off-by: Esteban Papp <81431996+amznestebanpapp@users.noreply.github.com>
This commit is contained in:
Esteban Papp
2021-09-01 15:19:32 -07:00
360 changed files with 29993 additions and 30472 deletions
@@ -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);
+25 -6
View File
@@ -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();
@@ -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);
+2 -2
View File
@@ -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;
@@ -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
@@ -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;
@@ -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);
@@ -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
@@ -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();
@@ -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;
@@ -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/>
@@ -53,7 +53,6 @@ namespace AzToolsFramework
// AssetBrowserComponentNotificationBus
void OnAssetBrowserComponentReady() override;
//////////////////////////////////////////////////////////////////////////
Q_SIGNALS:
void selectionChangedSignal(const QItemSelection& selected, const QItemSelection& deselected);
void ClearStringFilter();
@@ -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();
}
}